From 085e86a026d362c27f38c7e8ebc1ca3dee2c576d Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Tue, 11 Aug 2026 16:20:58 +0200 Subject: [PATCH 1/2] docs: make CipherBox the identity-token issuer in the blueprint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A login has two authentications and the blueprint conflated them: unlocking the Core Kit, and authenticating the derived key to the API. The second was decided by #28 D5. The first was not, and v2 built it as Web3Auth hosted OAuth in the client wiring. Records CipherBox as the issuer, passwordless email as the API's own, and the wallet method as a first-class first login on web. It is absent on desktop because that webview reaches no wallet. States the sharing boundary at credential collection rather than at the bearer token, and names the one login step that is genuinely native on desktop: Google collection cannot run in the webview, so the callback is served from a loopback listener. The account model is untouched — the Core Kit yields the same key whichever provider vouched. Entire-Checkpoint: c84ee372d3ce --- blueprint/api.md | 14 +++++++++++++- blueprint/desktop.md | 12 ++++++++++++ blueprint/web-client.md | 14 ++++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/blueprint/api.md b/blueprint/api.md index 01e056f10..c323b1fa4 100644 --- a/blueprint/api.md +++ b/blueprint/api.md @@ -37,7 +37,19 @@ What left the API relative to v1 — with the design that removed it: ## Identity and auth - Account = the Web3Auth-derived secp256k1 **identity key**; challenge-signature - login; SIWE wallet login stays as a secondary auth method (feature-set decision FSM1/cipher-box-next#5). + login. **CipherBox issues the identity token the Core Kit consumes** (FSM1/cipher-box-next#5 as + amended by ADR 0008): each verified method mints a CipherBox JWT, and the Core Kit + logs in against a CipherBox custom verifier over the API's own JWKS. The account + model is unchanged by this — the Core Kit yields the same key whichever provider + vouched. +- **Method set**: Google, passwordless email, and wallet. Passwordless email is + CipherBox's own — the API issues and verifies the code and owns its delivery. + Wallet is a **first-class first login on web only**: a SIWE signature the API + verifies mints the same JWT as any other method, so it reaches the same derived + key. It is absent on desktop because that webview reaches no wallet, which is a + platform property rather than a deferred feature (ADR 0008). +- Google's OAuth client ID is the **provider's**, distinct from the Web3Auth project + client ID. The two are not interchangeable. - Short-lived access JWT + rotating refresh token (HTTP-only cookie on web, OS keychain on desktop). Staging-gated test-login endpoint for e2e. - Tables: `users` (keyed by `publicKey`; carries quota-limit override and BYO flag), diff --git a/blueprint/desktop.md b/blueprint/desktop.md index 8cd962641..d96a86a7d 100644 --- a/blueprint/desktop.md +++ b/blueprint/desktop.md @@ -250,6 +250,18 @@ navigation (FSM1/cipher-box-next#33 D2): the shell's only credential duty is hosting the keychain seam. Dev-key mode survives: a debug flag feeds the staging test-login path through the same facade, keychain bypassed — the headless agent/e2e seam. +- **The orchestration is the web client's** (ADR 0008 D3): the shell imports the + same host-agnostic login package and supplies its own credential collector. It + does **not** take `packages/client` — the worker, leadership and Service Worker + machinery has no place here. +- **Google collection is native, not in-webview.** Google Identity Services does + not run in this webview, and the manual OAuth2 flow it falls back to needs a + `redirect_uri` a packaged Tauri origin cannot satisfy — `tauri://localhost` is + refused as a non-`http(s)` scheme. The shell therefore serves the callback from + a loopback listener on a pre-registered port. This is the one login step that + is genuinely native (ADR 0008). +- **No wallet method here.** The webview reaches no wallet, so the method is + absent rather than offered and unable to complete (ADR 0008 D2). - **Tray** renders the event stream: the staleness ladder maps to `Synced / Reconciling / Stale / Offline`, dead-letters to the parked-writes state (edge-triggered notifications, v1's anti-spam watermark kept), trust diff --git a/blueprint/web-client.md b/blueprint/web-client.md index d3878ed11..fc1e9925b 100644 --- a/blueprint/web-client.md +++ b/blueprint/web-client.md @@ -197,8 +197,18 @@ all living in `packages/client` and running inside the engine worker realm: entry. - **The engine owns the token lifecycle** (FSM1/cipher-box-next#28 D5): challenge-signature login through its API client; access JWT in engine memory; refresh cookie rides - the Http seam. SIWE stays secondary — wagmi collects the wallet signature - on the UI thread and the facade forwards it (engine.md). + the Http seam. This is a distinct authentication from unlocking the Core Kit, + and only the latter involves an identity provider (ADR 0008). +- **The login orchestration is shared, the credential collection is not** + (ADR 0008 D3). One host-agnostic package sequences provider credential → API + exchange → Core Kit login → secret export → `start(secret)`; both hosts import + it and inject their own collector. On web that collector is the Google popup + and wagmi; desktop's is its own (desktop.md). The boundary is credential + collection, not the bearer token — v1 drew it at the token and the two hosts + drifted. +- **Wallet is a first login here** (ADR 0008 D2): wagmi collects the signature on + the UI thread, the API verifies it and mints the identity token, and the Core + Kit login proceeds as for any other method. Web only. - **Cold start**: facade `start(secret)` → vault-pointer resolve, floor cold-seed, root adoption (the engine's non-circular cold-start sequence) → first snapshot event. The UI shows exactly two cold-start states: an From 2de3c3a4c41b44237fa885de1a3eab9d0dbfd438 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Tue, 11 Aug 2026 17:38:44 +0200 Subject: [PATCH 2/2] docs: link the ADR 0008 citations to the decision corpus blueprint/core.md and blueprint/engine.md already cite ADRs as links to cipher-box-next/decisions. These cited it as plain text. Links the first mention in each file, which is where a reader looks for the path. Entire-Checkpoint: 8198883d1ef2 --- blueprint/api.md | 2 +- blueprint/desktop.md | 2 +- blueprint/web-client.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blueprint/api.md b/blueprint/api.md index c323b1fa4..3a0e7c59a 100644 --- a/blueprint/api.md +++ b/blueprint/api.md @@ -38,7 +38,7 @@ What left the API relative to v1 — with the design that removed it: - Account = the Web3Auth-derived secp256k1 **identity key**; challenge-signature login. **CipherBox issues the identity token the Core Kit consumes** (FSM1/cipher-box-next#5 as - amended by ADR 0008): each verified method mints a CipherBox JWT, and the Core Kit + amended by [ADR 0008](https://github.com/FSM1/cipher-box-next/blob/main/decisions/0008-cipherbox-issues-the-identity-token.md)): each verified method mints a CipherBox JWT, and the Core Kit logs in against a CipherBox custom verifier over the API's own JWKS. The account model is unchanged by this — the Core Kit yields the same key whichever provider vouched. diff --git a/blueprint/desktop.md b/blueprint/desktop.md index d96a86a7d..de36b8139 100644 --- a/blueprint/desktop.md +++ b/blueprint/desktop.md @@ -250,7 +250,7 @@ navigation (FSM1/cipher-box-next#33 D2): the shell's only credential duty is hosting the keychain seam. Dev-key mode survives: a debug flag feeds the staging test-login path through the same facade, keychain bypassed — the headless agent/e2e seam. -- **The orchestration is the web client's** (ADR 0008 D3): the shell imports the +- **The orchestration is the web client's** ([ADR 0008](https://github.com/FSM1/cipher-box-next/blob/main/decisions/0008-cipherbox-issues-the-identity-token.md) D3): the shell imports the same host-agnostic login package and supplies its own credential collector. It does **not** take `packages/client` — the worker, leadership and Service Worker machinery has no place here. diff --git a/blueprint/web-client.md b/blueprint/web-client.md index fc1e9925b..6450aae32 100644 --- a/blueprint/web-client.md +++ b/blueprint/web-client.md @@ -198,7 +198,7 @@ all living in `packages/client` and running inside the engine worker realm: - **The engine owns the token lifecycle** (FSM1/cipher-box-next#28 D5): challenge-signature login through its API client; access JWT in engine memory; refresh cookie rides the Http seam. This is a distinct authentication from unlocking the Core Kit, - and only the latter involves an identity provider (ADR 0008). + and only the latter involves an identity provider ([ADR 0008](https://github.com/FSM1/cipher-box-next/blob/main/decisions/0008-cipherbox-issues-the-identity-token.md)). - **The login orchestration is shared, the credential collection is not** (ADR 0008 D3). One host-agnostic package sequences provider credential → API exchange → Core Kit login → secret export → `start(secret)`; both hosts import