docs: decide CipherBox issues the Core Kit identity token - #64
Merged
Conversation
A CipherBox login has two authentications and the blueprint conflates them: unlocking the Core Kit, and authenticating the derived key to the API. #28 D5 governs the second and is correct. The first was never decided — v2 built it as Web3Auth hosted OAuth in the client wiring, where v1 had CipherBox issue a JWT against a custom verifier. The account model cannot tell them apart, because the Core Kit yields the same key whichever provider vouched. So making CipherBox the issuer again costs nothing in the account model and returns two things: a wallet that can start a session, and passwordless email the API owns. Amends #5 so the wallet method is first-class on web. It stays absent on desktop because that webview reaches no wallet — v1 wrote that path and never wired it. Draws the sharing boundary at credential collection rather than at the bearer token, which is where v1 drew it and where it drifted.
This was referenced Aug 11, 2026
Owner
Author
|
Marked Accepted — not implemented in That umbrella is decomposed into six sub-issues with dependency edges: FSM1/cipher-box#1256 (the Google client-ID split, independent of this ADR and ready now), FSM1/cipher-box#1257 (the API issues the identity token), FSM1/cipher-box#1258 (API-owned passwordless email), FSM1/cipher-box#1259 (extract the shared login package), FSM1/cipher-box#1260 (wallet as a first login), and FSM1/cipher-box#1261 (a desktop frontend that can log in). The blueprint statement of this decision is FSM1/cipher-box#1255, held as a draft so it does not land ahead of the decision it records — it can go ready once this merges. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this decides
A CipherBox login has two authentications, and the blueprint conflates them:
#28 D5 governs (2) and is correct as written. (1) was never decided. v2 built it as Web3Auth's hosted OAuth, in the client wiring; v1 had CipherBox mint a JWT against a custom verifier.
The account model cannot distinguish them, because the Core Kit yields the same key whichever provider vouched — so
blueprint/api.md's "Account = the Web3Auth-derived secp256k1 identity key" holds under both, and the issuer was chosen by accident rather than by decision.Three decisions follow:
Nothing about the account model, challenge-signature login, the engine-held token lifecycle, or the
CredentialStoresplit changes.Why now
Hand UAT on a local stack found all three login methods down, for three different reasons — one of which (Google answering
401 invalid_client, because the Web3Auth project client ID is passed where the provider's belongs) is a plain defect that holds regardless of this ADR.Evidence it rests on
apps/webagainst ~2,400 inapps/desktop, implementing the same flows twice. The shared boundary sat atgetAccessToken, so everything producing a token was per-host by construction.MAINNETvsDEVNETfor the same environment, a device-factor recovery branch on one host only,viem/siweagainst a hand-concatenated EIP-4361 string, and an email-OTP failure where the JS half read a compile-time API URL and the Rust half a runtime one.redirect_uri, and a packaged Tauri origin istauri://localhost, which Google rejects.loginWithWalletand never wired it.Cost to be honest about
apps/desktop/frontendis a 43-line static HTML file with no bundler, no TypeScript and no dependencies, and the shell links no engine. D3 needs a desktop JS app to exist first. That is new build configuration, not a refactor, and it is the largest single cost here.Rejected, with reasons in the ADR
Moving the orchestration into the engine — attractive, since the engine is shared by construction and already performs challenge-signature login, SIWE challenge/login/link, refresh and logout. It fails on two counts: the Core Kit is a JS SDK owning DOM and redirect flows, so the engine would need a callback seam against
SeamSet's completeness gate; and under D1 the API exchange precedes the login secret, so the engine would need a command surface that works unstarted.Implemented by FSM1/cipher-box#1253, which will decompose into linked issues per layer.