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>
114 lines
4.7 KiB
Markdown
114 lines
4.7 KiB
Markdown
# Testing against the saltire LTI platform emulator
|
|
|
|
[saltire](https://saltire.lti.app) 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):
|
|
|
|
```json
|
|
{
|
|
"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.
|