Skip to content

Theseus site-pairing QR (layer 2) ​

Approved: 17 September 2026 (#152)

An unlocked Theseus phone stores HTTPS origin + write-scoped field token from a QR minted on Mobile Access. This is not the Nav mobile key, not a Keryx ntfy subscribe token, and not safecall-ops (T4).

Layer 1 (Wantok unlock) stays in front. The unlock screen has no site QR scanner. Its only scanner reads the RTLS test QR, which opens the restricted tester mode and never a site pairing.

Payload ​

Type safecall.theseus.pair.v1:

json
{
  "type": "safecall.theseus.pair.v1",
  "origin": "https://customer.example",
  "field_token": "th_…",
  "token_id": "<uuid>",
  "created_at": "2026-09-17T00:00:00.000Z"
}
FieldRule
originHTTPS origin of the SafeCall box the phone will call. Reject http.
field_tokenOpaque th_ secret. Never server_mobile_api_key. Shown once at mint.
token_idUUID. Used to revoke.
created_atISO-8601 mint time

SQLite stores SHA-256 of the token (token_hash) plus token_id. The raw secret is not kept after mint. Soft revoke sets revoked_at.

HTTP ​

MethodPathAuth
POST/api/v1/theseus/qrAdmin JWT (guard_auth + admin)
DELETE/api/v1/theseus/qr/token/:token_idguard_admin
GET/api/v1/theseus/sessionAuthorization: Bearer th_… (not JWT)

GET /theseus/session is a pairing probe only: 200 if the hash matches and revoked_at is null; 401 otherwise. No snapshot, no writes.

Mint origin comes from the request Origin header (must be HTTPS). Lab HTTP admin UIs cannot mint; the phone must call HTTPS.

In the app ​

Pairing is the app's sign-in. The start screen shows Scan site QR to sign in when no pairing is stored, and the origin, the session state, Switch site and Sign out when one is. Sign out only forgets the pairing on the phone; it does not call the revoke route.

Scanner ​

Theseus parses v1 and hard-rejects:

  • Nav { url, mobile_key }
  • Keryx safecall.keryx.ntfy.v2

No ntfy topics. No safecall-ops. Tokens live on the customer SQLite, not the NAS — no operator-actions row.

Web ​

Mobile Access shows a third, full-width Theseus card under Keryx / Nav, with its own canvas #theseus-qr-canvas.