feat: make first-user bootstrap atomic (TIN-2821) - #41
feat: make first-user bootstrap atomic (TIN-2821)#41Jess Sullivan (Jesssullivan) wants to merge 4 commits into
Conversation
|
Review gate: preserve this PR as the canonical design, but keep it draft until the following are repaired and re-reviewed:
The competing local implementation will not replace this PR: it regresses browser-state custody, lost-response recovery, and immutable session identity. A clean follow-up worktree based on this exact head is repairing only the gaps above. |
|
RBAC/invitation interoperability review confirms this PR should stay focused on atomic bootstrap. The separate RBAC worktree preserves the intended model: management rank is a strict order, while specialist capabilities remain intentionally non-monotone. It is not release-ready yet. Blocking follow-ons, in order:
Claim boundary: current RBAC work is source-contract review only, not merge, release, registry promotion, downstream adoption, or live correctness. |
|
Follow-up hardening is now on the PR head as signed commit Evidence before push:
Claim boundary remains unchanged: source-only draft at package version 0.7.1; no release, adapter rollout, or live two-replica canary. |
|
Review follow-up
Boundary unchanged: this remains a source-only draft. The file lock is single-host/cooperative-filesystem authority; PostgreSQL and Redis remain blocked on TIN-2828/TIN-2829. Do not merge, tag, release, promote, adopt, or touch mothership runtime state from this PR. |
Scope\n\n- Add a tenant-scoped atomic first-user bootstrap claim/finalize/receipt protocol.\n- Keep inert claims authority-free and make exact finalization replay idempotent.\n- Move password hashes, raw TOTP material, backup codes, and prepared finalization into server-side attempt custody.\n- Make session identity immutable so existing sessions cannot be rebound to the claimed actor.\n- Add reusable storage and attempt-store conformance suites for built-in and external adapters.\n- Update the file, memory, fixed-tenant, MVP, and operator documentation surfaces.\n\n## Security properties\n\n- Browser state is only a version plus a 192-bit opaque attempt id.\n- Completion never returns backup codes; one-time disclosure occurs during initiation.\n- TOTP ciphertext is round-trip decrypted and timing-safe compared before finalization.\n- Prepared attempts expire, reject stale profile snapshots, freeze after preparation, and permit replacement after expiry.\n- Finalized bootstrap actors, factors, and backup-code authority cannot be independently deleted.\n\n## Hard gates\n\nSOURCE-ONLY DRAFT. DO NOT MERGE, TAG, RELEASE, PROMOTE, OR ADOPT YET.\n\nThe unreleased 0.8 interface is intentionally breaking. Current PostgreSQL and Redis adapter releases do not implement the mandatory atomic methods or durable attempt-store contract. Merge/release/adoption remain blocked on:\n\n- TIN-2828: PostgreSQL implementation plus conformance.\n- TIN-2829: Redis implementation plus conformance.\n- Release metadata and registry promotion for a coordinated 0.8 wave.\n- Mothership adoption and an attended first-user canary.\n- TIN-2822 RBAC convergence after this source contract is staged.\n\ntinyland.dev #731 remains held. This PR does not mutate runtime state, SOPS, CI secrets, tags, registry packages, or deployments.\n\n## Verification\n\n- pnpm typecheck\n- focused bootstrap/storage suite: 76/76\n- pnpm build\n- pnpm check:release-metadata\n- pnpm check:invitation-authority\n- pnpm check:package (passes; existing sideEffects suggestion only)\n- Bazel //:test and //:typecheck with a 60-second Vitest case timeout: passed\n- git diff --check\n- independent adversarial review: no remaining source-draft blockers\n\nThe default host-constrained full suite previously reached 446/449 with only three unchanged bcrypt cases hitting their 30-second timeout; the isolated password suite passed 20/20, and the final Bazel run passed with the explicit timeout above.\n\nTracks TIN-2821. It does not close the ticket because adapter adoption, release, and attended runtime proof remain outstanding.