Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8f66c42
docs(12.3.1): create phase plan for pre-wipe identity cleanup
FSM1 Feb 14, 2026
73ea664
fix(12.3.1): revise plans based on checker feedback
FSM1 Feb 14, 2026
8a61855
fix(12.3.1): revise plans based on checker feedback
FSM1 Feb 14, 2026
2716dad
feat(12.3.1-02): add generic hashIdentifier and widen identifier_display
FSM1 Feb 14, 2026
3424f8f
feat(12.3.1-01): deterministic vault IPNS derivation and EncryptedVau…
FSM1 Feb 14, 2026
b37fbff
test(12.3.1-01): vault IPNS derivation tests and updated vault tests
FSM1 Feb 14, 2026
a7d31bf
feat(12.3.1-02): hash all auth identifiers and remove cross-method au…
FSM1 Feb 14, 2026
bcf2293
docs(12.3.1-01): complete deterministic vault IPNS plan
FSM1 Feb 14, 2026
dab2382
test(12.3.1-02): update tests for hashed identifiers and independent …
FSM1 Feb 14, 2026
e6bbb94
docs(12.3.1-02): complete SHA-256 hashed identifiers plan
FSM1 Feb 14, 2026
07caf1b
feat(12.3.1-03): remove rootIpnsPublicKey from vault schema, service,…
FSM1 Feb 14, 2026
da2bc83
feat(12.3.1-03): wire deterministic IPNS derivation into frontend vau…
FSM1 Feb 14, 2026
6032c59
docs(12.3.1-04): complete downstream rootIpnsPublicKey cleanup plan
FSM1 Feb 14, 2026
4980b97
fix(12.3.1-03): complete rootIpnsPublicKey removal from API source files
FSM1 Feb 14, 2026
b0ffa96
docs(12.3.1-03): complete vault IPNS wiring plan
FSM1 Feb 14, 2026
f15c096
docs(12.3.1): complete pre-wipe identity cleanup phase
FSM1 Feb 14, 2026
a44151d
fix(12.3.1): normalize email in JWT, add e2e dep, fix coverage
FSM1 Feb 14, 2026
310d22b
refactor(12.3.1): normalize Google email, deduplicate wallet user cre…
FSM1 Feb 14, 2026
e930b9f
feat(12.3.1): truncate email in identifierDisplay for privacy
FSM1 Feb 14, 2026
29dc4d1
fix(12.3.1): address CodeRabbit review — identifier guards, hash cent…
FSM1 Feb 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions .planning/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ See `.planning/archive/m1-ROADMAP.md` for full M1 phase details and plan lists.
- [ ] **Phase 12.1: AES-CTR Streaming Encryption** - AES-256-CTR for media files with byte-range decryption and in-browser playback (INSERTED)
- [x] **Phase 12.2: Encrypted Device Registry** - Encrypted device metadata on IPFS for cross-device infrastructure (INSERTED)
- [x] **Phase 12.3: SIWE + Unified Identity** - Wallet login via SIWE, multi-auth linking, ADR-001 cleanup (INSERTED)
- [ ] **Phase 12.3.1: Pre-Wipe Identity Cleanup** - Deterministic IPNS derivation, hashed identifiers, remove auto-linking (INSERTED)
- [x] **Phase 12.3.1: Pre-Wipe Identity Cleanup** - Deterministic IPNS derivation, hashed identifiers, remove auto-linking (INSERTED)
- [ ] **Phase 12.4: MFA + Cross-Device Approval** - MFA enrollment, recovery phrase, factor management, device approval flow (INSERTED)
- [ ] **Phase 13: File Versioning** - Automatic version retention with history view and restore
- [ ] **Phase 14: User-to-User Sharing** - Read-only folder sharing with ECIES key re-wrapping
Expand Down Expand Up @@ -180,11 +180,16 @@ Plans:
2. All auth method identifiers are stored as SHA-256 hashes: Google uses SHA-256(google_sub), email uses SHA-256(normalized_email), wallet uses SHA-256(checksummed_address)
3. Each auth method (google, email, wallet) is an independent identity — no cross-method email auto-linking; users link methods explicitly via Settings
4. Self-sovereign recovery path works: recovery phrase → privateKey → derive vault IPNS key → resolve IPNS → decrypt vault metadata
5. TEE republishing updated to use deterministically derived IPNS keys
5. TEE republishing continues to work — ipns.service.ts has no rootIpnsPublicKey dependency (passive compatibility, verified by grep)

**Plans:** 4 plans

Plans:

- [ ] TBD (run `/gsd:plan-phase 12.3.1` to break down)
- [x] 12.3.1-01-PLAN.md — Crypto: deterministic vault IPNS keypair derivation (HKDF) + updated initializeVault/encryptVaultKeys/decryptVaultKeys + EncryptedVaultKeys type cleanup + tests
- [x] 12.3.1-02-PLAN.md — Backend: SHA-256 hashed identifiers for all auth methods + remove cross-method auto-linking
- [x] 12.3.1-03-PLAN.md — Backend vault schema + frontend vault init for deterministic IPNS + API client regen
- [x] 12.3.1-04-PLAN.md — Codebase-wide cleanup: desktop Rust, E2E helpers, controller spec rootIpnsPublicKey removal

### Phase 12.4: MFA + Cross-Device Approval (INSERTED)

Expand Down Expand Up @@ -308,7 +313,7 @@ Parallel phases:
| 12.1 AES-CTR Streaming | M2 | 0/TBD | Not started | - |
| 12.2 Device Registry | M2 | 3/3 | Complete | 2026-02-13 |
| 12.3 SIWE + Identity | M2 | 4/4 | Complete | 2026-02-14 |
| 12.3.1 Identity Cleanup | M2 | 0/TBD | Not started | - |
| 12.3.1 Identity Cleanup | M2 | 4/4 | Complete | 2026-02-14 |
| 13. File Versioning | M2 | 0/TBD | Not started | - |
| 14. User-to-User Sharing | M2 | 0/TBD | Not started | - |
| 15. Link Sharing + Search | M2 | 0/TBD | Not started | - |
Expand Down
98 changes: 53 additions & 45 deletions .planning/STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,38 @@
See: .planning/PROJECT.md (updated 2026-02-11)

**Core value:** Zero-knowledge privacy - files encrypted client-side, server never sees plaintext
**Current focus:** Milestone 2 -- Phase 12.3 complete (SIWE + Unified Identity)
**Current focus:** Milestone 2 -- Phase 12.3.1 complete (Pre-Wipe Identity Cleanup)

## Current Position

Phase: 12.3 (SIWE + Unified Identity)
Phase: 12.3.1 (Pre-Wipe Identity Cleanup)
Plan: 4 of 4 planned
Status: Phase complete
Last activity: 2026-02-14 -- Completed 12.3-04-PLAN.md (Link/Unlink Methods + Settings UI)
Last activity: 2026-02-14 -- Completed 12.3.1-04-PLAN.md (Downstream rootIpnsPublicKey Cleanup)

Progress: [##############......] 68% (M1 complete, M2 Phase 12 complete, Phase 12.2 complete, Phase 12.3 complete)
Progress: [###############.....] 73% (M1 complete, M2 Phase 12 complete, Phase 12.2 complete, Phase 12.3 complete, Phase 12.3.1 complete)

## Performance Metrics

**Velocity:**

- Total plans completed: 85
- Average duration: 4.7 min
- Total execution time: 7.13 hours
- Total plans completed: 89
- Average duration: 4.9 min
- Total execution time: 7.7 hours

**By Phase (M1 summary):**

| Phase | Plans | Total | Avg/Plan |
| -------------- | ----- | ------- | -------- |
| M1 (17 phases) | 72/72 | 5.6 hrs | 4.7 min |
| M2 Phase 12 | 5/5 | 45 min | 9.0 min |
| M2 Phase 12.2 | 3/3 | 10 min | 3.3 min |
| M2 Phase 12.3 | 4/4 | 39 min | 9.8 min |
| Phase | Plans | Total | Avg/Plan |
| --------------- | ----- | ------- | -------- |
| M1 (17 phases) | 72/72 | 5.6 hrs | 4.7 min |
| M2 Phase 12 | 5/5 | 45 min | 9.0 min |
| M2 Phase 12.2 | 3/3 | 10 min | 3.3 min |
| M2 Phase 12.3 | 4/4 | 39 min | 9.8 min |
| M2 Phase 12.3.1 | 4/4 | 38 min | 9.5 min |

**Recent Trend:**

- Last 5 plans: 3m, 16m, 9m, 7m, 7m
- Last 5 plans: 10m, 4m, 10m, 18m, 6m
- Trend: Stable

Updated after each plan completion.
Expand All @@ -47,34 +48,41 @@ Updated after each plan completion.
Decisions are logged in PROJECT.md Key Decisions table.
Recent decisions affecting current work:

| Decision | Phase | Rationale |
| -------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| Replace PnP Modal SDK with MPC Core Kit | Phase 12 | Full MFA control, custom UX, programmatic factor mgmt |
| CipherBox as identity provider (sub=userId) | Phase 12 | Enables multi-auth linking, less data to Web3Auth |
| Identity trilemma: chose (wallet-only + unified) w/ SPOF | Phase 12 | No mandatory email; SPOF mitigated by key export+IPFS |
| Phase 12 split into 12, 12.2, 12.3, 12.4 | Phase 12 | Foundation->device registry->SIWE->MFA dependency chain |
| Core Kit WEB3AUTH_NETWORK uses DEVNET/MAINNET keys | 12-02 | Different from PnP SDK's SAPPHIRE_DEVNET/SAPPHIRE_MAINNET |
| CipherBox JWT for backend auth (not coreKit.signatures) | 12-04 | Core Kit signatures are session tokens, not verifiable JWTs. Pass CipherBox-issued JWT with loginType 'corekit' |
| importTssKey via localStorage one-time read-and-delete | 12-05 | PnP migration key consumed once then removed |
| E2E uses CipherBox login UI directly (no modal iframe) | 12-05 | Simpler, more reliable than Web3Auth modal automation |
| jose library for identity JWTs (not @nestjs/jwt) | 12-01 | Separate signing keys (RS256) and audience from internal |
| Cross-auth-method email linking | 12-01 | Same email across Google/email auth -> same user account |
| ECIES re-wrapping for sharing (not proxy re-encryption) | Research | Same wrapKey() function, server sees only ciphertexts |
| Versioning = stop unpinning old CIDs + metadata extension | Research | Nearly free on IPFS, no new crypto needed |
| Read-only sharing only (no multi-writer IPNS) | Research | Unsolved problem, deferred to v3 |
| minisearch + idb for client-side search | Research | ~8KB total, TypeScript-native, zero server interaction |
| Wallet addr: SHA-256 hash + truncated display (no encrypt) | 12.3-01 | Simpler than hash+encrypted; full plaintext never stored |
| Auth types: email_passwordless->email, external_wallet->wallet | 12.3-01 | Clean method-based naming for simplified auth type system |
| derivationVersion removed (ADR-001 clean break) | 12.3-01 | DB will be wiped, no migration needed, clean Core Kit-only schema |
| Web3AuthVerifierService decoupled from auth.service | 12.3-02 | No longer injected; all login/link flows use CipherBox JWT verification |
| LinkMethodDto uses auth method types directly | 12.3-02 | google/email/wallet instead of routing through social/external_wallet loginType |
| Vault export derivationInfo simplified to derivationMethod | 12.3-02 | Always 'web3auth' for Core Kit users; no derivationVersion needed |
| connectAsync for wallet SIWE flow (not useEffect-based) | 12.3-03 | Simpler async flow; avoids address-watching complexity |
| Disconnect wagmi after SIWE verification | 12.3-03 | No persistent wallet connection needed; Core Kit handles ongoing auth |
| vaultKeypair naming for auth store keypair | 12.3-03 | Clear purpose naming; replaces misleading ADR-001 derivedKeypair |
| Reuse login components in link mode (settings) | 12.3-04 | GoogleLoginButton/EmailLoginForm reused via callback props; no separate link components |
| Multiple wallets allowed per account | 12.3-04 | Wallet always shows as available to link; CONTEXT.md requirement |
| Cross-account collision via TypeORM Not() | 12.3-04 | Check same identifier with different userId before allowing link |
| Decision | Phase | Rationale |
| ---------------------------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------- |
| Replace PnP Modal SDK with MPC Core Kit | Phase 12 | Full MFA control, custom UX, programmatic factor mgmt |
| CipherBox as identity provider (sub=userId) | Phase 12 | Enables multi-auth linking, less data to Web3Auth |
| Identity trilemma: chose (wallet-only + unified) w/ SPOF | Phase 12 | No mandatory email; SPOF mitigated by key export+IPFS |
| Phase 12 split into 12, 12.2, 12.3, 12.4 | Phase 12 | Foundation->device registry->SIWE->MFA dependency chain |
| Core Kit WEB3AUTH_NETWORK uses DEVNET/MAINNET keys | 12-02 | Different from PnP SDK's SAPPHIRE_DEVNET/SAPPHIRE_MAINNET |
| CipherBox JWT for backend auth (not coreKit.signatures) | 12-04 | Core Kit signatures are session tokens, not verifiable JWTs. Pass CipherBox-issued JWT with loginType 'corekit' |
| importTssKey via localStorage one-time read-and-delete | 12-05 | PnP migration key consumed once then removed |
| E2E uses CipherBox login UI directly (no modal iframe) | 12-05 | Simpler, more reliable than Web3Auth modal automation |
| jose library for identity JWTs (not @nestjs/jwt) | 12-01 | Separate signing keys (RS256) and audience from internal |
| Cross-auth-method email linking | 12-01 | Same email across Google/email auth -> same user account |
| ECIES re-wrapping for sharing (not proxy re-encryption) | Research | Same wrapKey() function, server sees only ciphertexts |
| Versioning = stop unpinning old CIDs + metadata extension | Research | Nearly free on IPFS, no new crypto needed |
| Read-only sharing only (no multi-writer IPNS) | Research | Unsolved problem, deferred to v3 |
| minisearch + idb for client-side search | Research | ~8KB total, TypeScript-native, zero server interaction |
| Wallet addr: SHA-256 hash + truncated display (no encrypt) | 12.3-01 | Simpler than hash+encrypted; full plaintext never stored |
| Auth types: email_passwordless->email, external_wallet->wallet | 12.3-01 | Clean method-based naming for simplified auth type system |
| derivationVersion removed (ADR-001 clean break) | 12.3-01 | DB will be wiped, no migration needed, clean Core Kit-only schema |
| Web3AuthVerifierService decoupled from auth.service | 12.3-02 | No longer injected; all login/link flows use CipherBox JWT verification |
| LinkMethodDto uses auth method types directly | 12.3-02 | google/email/wallet instead of routing through social/external_wallet loginType |
| Vault export derivationInfo simplified to derivationMethod | 12.3-02 | Always 'web3auth' for Core Kit users; no derivationVersion needed |
| connectAsync for wallet SIWE flow (not useEffect-based) | 12.3-03 | Simpler async flow; avoids address-watching complexity |
| Disconnect wagmi after SIWE verification | 12.3-03 | No persistent wallet connection needed; Core Kit handles ongoing auth |
| vaultKeypair naming for auth store keypair | 12.3-03 | Clear purpose naming; replaces misleading ADR-001 derivedKeypair |
| Reuse login components in link mode (settings) | 12.3-04 | GoogleLoginButton/EmailLoginForm reused via callback props; no separate link components |
| Multiple wallets allowed per account | 12.3-04 | Wallet always shows as available to link; CONTEXT.md requirement |
| Cross-account collision via TypeORM Not() | 12.3-04 | Check same identifier with different userId before allowing link |
| Vault IPNS: same salt, different HKDF info for domain separation | 12.3.1-01 | HKDF info is primary domain separator; "cipherbox-vault-ipns-v1" vs registry's info |
| rootIpnsPublicKey removed from EncryptedVaultKeys | 12.3.1-01 | Derivable from private key; reduces stored data, eliminates inconsistency |
| Google login hashes sub (not email) for identifierHash | 12.3.1-02 | Sub is immutable Google user ID; email can change. Privacy-preserving lookup. |
| Cross-method email auto-linking removed | 12.3.1-02 | Each auth method is independent; users link explicitly via Settings, not auto-linked by email match |
| identifier column stores hash for all auth types | 12.3.1-02 | identifier=identifierHash for consistency; identifierDisplay holds human-readable value |
| rootIpnsPublicKey removed from vault entity/DTO/API/frontend | 12.3.1-03 | Derivable from privateKey via HKDF; reduces schema, eliminates inconsistency |
| Plan 04 work completed by Plan 03 broader scope | 12.3.1-04 | Desktop Rust, E2E helpers, controller spec changes committed in Plan 03 execution |

### Pending Todos

Expand Down Expand Up @@ -130,11 +138,11 @@ Recent decisions affecting current work:
## Session Continuity

Last session: 2026-02-14
Stopped at: Completed 12.3-04-PLAN.md (Link/Unlink Methods + Settings UI)
Stopped at: Completed 12.3.1-04-PLAN.md (Downstream rootIpnsPublicKey Cleanup) -- Phase 12.3.1 complete
Resume file: None
Next: Phase 12.3.1 (Pre-Wipe Identity Cleanup) -- ready to plan
Next: Phase 12.4 (MFA + Cross-Device Approval) -- needs research phase first

---

_State initialized: 2026-01-20_
_Last updated: 2026-02-14 after completing Phase 12.3 Plan 04 (Phase 12.3 complete)_
_Last updated: 2026-02-14 after completing Phase 12.3.1 Plan 04 (Downstream rootIpnsPublicKey Cleanup)_
Loading
Loading