1
0
Files
coldcall_lti/docs/SALTIRE.md
Benjamin Mako Hill c4cb3307fa Update README and saltire docs to current behavior
The README now documents the daily workflow (working date, live mode
vs printed lists, regenerate semantics, full day-editor editability),
describes cycle mode's rolling rotation accurately, repairs the
custom-parameters section, and points to the saltire testing guide,
which gains resume-after-a-break instructions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 19:16:54 -07:00

4.7 KiB

Testing against the saltire LTI platform emulator

saltire is the ceLTIc project's hosted LTI test harness. Its Platform Emulator impersonates an LMS: it performs the real OIDC handshake, signs a real id_token, and answers NRPS requests, which makes it the way to exercise the app's actual launch path without a Canvas Developer Key. This setup was first run and verified on 2026-08-01 (launch, role routing for both Instructor and Learner, and a live NRPS roster sync all worked).

Local side

The app must be served over HTTPS, because real LTI session cookies are Secure; SameSite=None. A self-signed certificate is fine — you accept it once in the browser:

# one-time: tool keypair and TLS cert (all live in instance/, gitignored)
openssl genrsa -out instance/private.key 4096
openssl rsa -in instance/private.key -pubout -out instance/public.key
openssl req -x509 -newkey rsa:2048 -keyout instance/tls-key.pem \
    -out instance/tls-cert.pem -days 30 -nodes -subj "/CN=localhost"

# run
.venv/bin/python -m flask --app coldcall_lti run --port 5443 \
    --cert instance/tls-cert.pem --key instance/tls-key.pem

Then open https://localhost:5443/healthz once and click through the certificate warning (Advanced → Proceed).

instance/lti_config.json describes the saltire platform to the app. The working shape (fill the session id — see the caveat below):

{
  "https://saltire.lti.app/platform": [
    {
      "default": true,
      "client_id": "saltire.lti.app",
      "auth_login_url": "https://saltire.lti.app/platform/auth",
      "auth_token_url": "https://saltire.lti.app/platform/token/<SESSION>",
      "key_set_url": "https://saltire.lti.app/platform/jwks/<SESSION>",
      "private_key_file": "private.key",
      "public_key_file": "public.key",
      "deployment_ids": ["<DEPLOYMENT-ID-FROM-SALTIRE>"]
    }
  ]
}

saltire side

On https://saltire.lti.app → Test Platform → Security Model:

  1. Set LTI version to 1.3.0. The Platform Details panel then shows the issuer, client id, deployment id, and the auth/token/jwks URLs — copy these into instance/lti_config.json.
  2. Set Message URL to https://localhost:5443/lti/launch.
  3. Under Tool Details: Initiate login URL https://localhost:5443/lti/login; Redirection URI(s) https://localhost:5443/lti/launch; clear the tool's public keyset URL (saltire's server cannot reach localhost) and instead paste the contents of instance/public.key into the tool Public key box.
  4. Save, then Connect launches the tool. The default saltire user carries the Instructor role and lands on the instructor page, with the fake "Telecommunications 101" roster synced via NRPS. To test the student experience, change the role under User to http://purl.imsglobal.org/vocab/lis/v2/membership#Learner, save, and Connect again — you land on /me.

Picking the test setup back up

With the configuration saved under a saltire account (sign in, then Save), resuming a test session is short:

  1. Start the local server (the keys and TLS cert in instance/ are already there):

    COLDCALL_SECRET_KEY=saltire-test .venv/bin/python -m flask \
        --app coldcall_lti run --port 5443 \
        --cert instance/tls-cert.pem --key instance/tls-key.pem
    
  2. If the browser has forgotten the self-signed certificate, open https://localhost:5443/healthz and click through the warning again.

  3. Sign in at https://saltire.lti.app → Test Platform, confirm the saved configuration loaded (Security Model should show LTI 1.3 and the localhost URLs), and press Connect.

  4. If the launch fails at JWT validation or roster sync, compare the token/jwks URLs shown in Platform Details against instance/lti_config.json — the session id may have changed; copy the new values in. Everything else should be stable.

To test as a student instead of the instructor, change the role under User to .../membership#Learner, Save, and Connect; switch back to #Instructor the same way.

Caveats

  • The token and jwks URLs embed a saltire session id (the /token/s...//jwks/s... suffix). Anonymous saltire sessions get a new id eventually, which breaks lti_config.json until you update it. To keep a stable setup, use saltire's Save menu to store the configuration under a saltire account and reconnect from there.
  • saltire sometimes raises native browser dialogs (e.g. "save your changes first" flows); nothing about that affects the tool under test.
  • The cookie-check interstitial (cookies_allowed_js_check.html) is part of the app and required: pylti1p3's Flask adapter expects the application to supply that template when enable_check_cookies() is used.