Token persistence via sys.save #6

Closed
opened 2026-08-19 06:49:30 +00:00 by yuris · 1 comment
Owner

Identity/token from InitialConnection should persist across sessions; reuse on next connect via Authorization header.

  • Save {identity, token} with sys.save after InitialConnection
  • Load + pass as Authorization: Bearer on connect
  • Handle server rejecting stale token (reconnect fresh)
Identity/token from InitialConnection should persist across sessions; reuse on next connect via Authorization header. - [ ] Save {identity, token} with sys.save after InitialConnection - [ ] Load + pass as Authorization: Bearer on connect - [ ] Handle server rejecting stale token (reconnect fresh)
Author
Owner

Closed in 7c0fac9 — identity survives an app restart

Conformance runs the headless client twice; the second run has no token in its environment and must still come back as the same player:

run 1: SMOKE: identity 0xc200643de0aa4839f2b4b5bfcfe4db34dca62e09a2adcf3d82a6074833a44163
run 2: SMOKE: identity 0xc200643de0aa4839f2b4b5bfcfe4db34dca62e09a2adcf3d82a6074833a44163
[conformance] PASS (identity persisted across a process restart)

The script fails if the two identities differ, so this cannot silently rot.

What landed

  • connection.lua takes an injectable storage = { load, save } and writes through it when IdentityToken arrives. Pure and unit tested with a fake table — no engine required.
  • init.lua defaults storage to sys.save/sys.load via stdb.sys_storage(name), keyed under the app's save directory.
  • Token precedence: live token (reconnect) → explicit opts.token → persisted token. So a caller can always override, and a reconnect never regresses to a stale stored value.
  • storage = false opts out entirely for callers who want to own credential handling.

Why this matters beyond convenience

Identity is the player in SpacetimeDB — rows keyed by caller_identity are that player's data. Without persistence every relaunch orphans whatever the player owned. This closes that hole with no login flow and no account system.

Bonus observation

Run 2 needed two backoff attempts (1s, then 2s) because the server took longer to come back, which exercised the doubling path end to end for free.

Related: #5 (reconnect, closed) — together these mean a client keeps its identity across both a dropped socket and a full restart.

## Closed in 7c0fac9 — identity survives an app restart Conformance runs the headless client twice; the second run has **no token in its environment** and must still come back as the same player: ``` run 1: SMOKE: identity 0xc200643de0aa4839f2b4b5bfcfe4db34dca62e09a2adcf3d82a6074833a44163 run 2: SMOKE: identity 0xc200643de0aa4839f2b4b5bfcfe4db34dca62e09a2adcf3d82a6074833a44163 [conformance] PASS (identity persisted across a process restart) ``` The script fails if the two identities differ, so this cannot silently rot. ### What landed - `connection.lua` takes an injectable `storage = { load, save }` and writes through it when `IdentityToken` arrives. Pure and unit tested with a fake table — no engine required. - `init.lua` defaults storage to `sys.save`/`sys.load` via `stdb.sys_storage(name)`, keyed under the app's save directory. - Token precedence: live token (reconnect) → explicit `opts.token` → persisted token. So a caller can always override, and a reconnect never regresses to a stale stored value. - `storage = false` opts out entirely for callers who want to own credential handling. ### Why this matters beyond convenience Identity *is* the player in SpacetimeDB — rows keyed by `caller_identity` are that player's data. Without persistence every relaunch orphans whatever the player owned. This closes that hole with no login flow and no account system. ### Bonus observation Run 2 needed two backoff attempts (1s, then 2s) because the server took longer to come back, which exercised the doubling path end to end for free. Related: #5 (reconnect, closed) — together these mean a client keeps its identity across both a dropped socket and a full restart.
yuris closed this issue 2026-08-19 08:49:47 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
yuris/spacetimedb-defold#6
No description provided.