Add the gateway backend for the wallet onboarding flow so each browser
session carries its OWN bus identity instead of sharing the single
operator client.
- POST /api/session (session.go): the browser hands its full wallet
keypair (unlocked from the local encrypted key, over TLS) and the
gateway spins up a dedicated bus client that acts AS that user. The
private key lives only in process memory for the life of the session
and is dropped on logout/shutdown. identityFromHex enforces the exact
key sizes (sign_pub 32, sign_priv 64, kex_pub 32, kex_priv 32) that
match cs.Identity on the Go side.
- POST /api/register (register.go): unauthenticated onboarding gated by
a one-shot invite token. Validates the two PUBLIC key halves, then
either consumes a configured --mock-tokens invite (local testing) or
proxies to the bus POST /register (--register-url, bus >= 0.12.0). The
handle/role come from the invite, never from the client.
- server.go: sessions move from a token->time map to a sessionStore of
per-user *session records; auth() now resolves the session and passes
its gateway to each handler. The legacy operator passphrase login
(POST /api/login) is kept, bound to the shared operator gateway.
- main.go: build a busTemplate config that wallet sessions clone with
their own Identity; wire --register-url / --mock-tokens.
- webgw_test.go: identity-size validation, hex-key validation, mock
token parsing, and single-use register (201 then 409) using a fixed
browser-derived wallet vector.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>