Skip to content

Added PoC spec and implementation#3

Merged
FSM1 merged 3 commits into
mainfrom
add-poc-spec
Jan 17, 2026
Merged

Added PoC spec and implementation#3
FSM1 merged 3 commits into
mainfrom
add-poc-spec

Conversation

@FSM1

@FSM1 FSM1 commented Jan 17, 2026

Copy link
Copy Markdown
Owner

No description provided.

@FSM1 FSM1 self-assigned this Jan 17, 2026
@FSM1 FSM1 requested a review from Copilot January 17, 2026 03:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds a Proof of Concept (PoC) console harness to validate CipherBox's cryptographic and IPFS/IPNS architecture before building the full Web UI and backend. The PoC is a single-user Node.js test harness that performs end-to-end file system operations using local IPFS, demonstrating encryption, IPNS publishing, and proper teardown.

Changes:

  • Added complete PoC implementation with file/folder operations, encryption, and IPNS management
  • Updated all documentation files to version 1.8.0 with PoC specifications and flows
  • Added TypeScript configuration, dependencies, and environment setup for the PoC

Reviewed changes

Copilot reviewed 17 out of 19 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
poc/src/index.ts Main PoC harness implementation with crypto operations, IPFS interactions, and test flows
poc/package.json Dependencies and scripts for the PoC project
poc/tsconfig.json TypeScript configuration for ES2022 with strict mode
poc/yarn.lock Auto-generated lockfile with IPFS, crypto, and tooling dependencies
poc/README.md Documentation explaining PoC setup, requirements, and usage
poc/.env.example Environment variable template for IPFS, Pinata, and test configuration
poc/scripts/gen-private-key.ts Utility script to generate test private keys
poc/state/state.json Persisted vault state from a PoC run
Documentation/*.md Version bumps to 1.8.0 and addition of PoC specifications across all docs
README.md Added PoC focus section explaining validation approach
.gitignore Added patterns for dist, node_modules, and .env files
.vscode/extensions.json Added Mermaid extension recommendation
.github/copilot-instructions.md Version update to 1.8.0
.claude/claude.md Version update to 1.8.0

Comment thread poc/src/index.ts Outdated
Comment thread poc/src/index.ts Outdated
FSM1 and others added 2 commits January 17, 2026 05:04
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@FSM1 FSM1 merged commit 65a2b32 into main Jan 17, 2026
@FSM1 FSM1 deleted the add-poc-spec branch January 17, 2026 04:05
FSM1 added a commit that referenced this pull request Feb 2, 2026
ENVIRONMENTS.md:
- Rename section title to "Environment-Specific IPNS Key Derivation"
- Replace "environment salt" terminology with "environment context" throughout
- Remove unused VITE_WEB3AUTH_NETWORK env var (network derived from VITE_ENVIRONMENT)
- Add URL schemes to environment variable reference table

REVIEW-2026-01-25-environments.md:
- Update findings #1, #3, #4 status to "Addressed" with dates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
FSM1 added a commit that referenced this pull request Feb 2, 2026
…ion (#49)

* docs: add comprehensive environment architecture for multi-env isolation

Addresses the Web3Auth key isolation problem where all environments
sharing the same project leads to IPNS sequence number conflicts.

Documents four environments (local, CI, staging, production) with:
- Environment-specific Ed25519 key derivation salt approach
- Docker Compose configurations for offline/online IPFS modes
- Web3Auth network switching (Devnet vs Mainnet)
- Complete env var reference and implementation checklist

* docs: add TEE infrastructure analysis to environment architecture

Extends ENVIRONMENTS.md with detailed TEE layer implications:

- Local/CI: TEE disabled, IPNS can expire, user resets to clean slate
- Staging: TEE active with Phala testnet, needs DHT cleanup strategy
  for orphaned records when Web3Auth testnet IDs become unstable
- Production: Full TEE with monitoring, alerting thresholds, and
  incident runbooks for IPNS staleness detection

Includes:
- TEE environment matrix and configuration per environment
- Staging cleanup job interface for orphaned IPNS records
- Production monitoring requirements (staleness, error rates, latency)
- Implementation checklist for TEE infrastructure rollout
- Incident response runbook for IPNS staleness

* docs: add security review for environment architecture

Security review of ENVIRONMENTS.md found:
- 2 Medium: HKDF parameter naming, random vs derived key migration
- 2 Low: Cross-env data accessibility, mock service /reset endpoint
- 3 Info: TEE epoch design, Web3Auth shared identity, JWT placeholder

Overall assessment: APPROVED WITH CONCERNS
Core cryptographic approach is sound, needs clarification before impl.

* docs: address CodeRabbit review comments

- Clarify HKDF salt vs info usage to match RFC 5869 best practices
- Add security warning about cross-environment CID leakage risks
- Add safety note for /reset endpoint (local/CI only)
- Add language tags to fenced code blocks (bash, text)
- Add blank lines around alerting thresholds table (MD058)
- Replace absolute paths with repo-relative paths

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: address Copilot and additional CodeRabbit comments

ENVIRONMENTS.md:
- Rename section title to "Environment-Specific IPNS Key Derivation"
- Replace "environment salt" terminology with "environment context" throughout
- Remove unused VITE_WEB3AUTH_NETWORK env var (network derived from VITE_ENVIRONMENT)
- Add URL schemes to environment variable reference table

REVIEW-2026-01-25-environments.md:
- Update findings #1, #3, #4 status to "Addressed" with dates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: address CodeRabbit review comments for TEE architecture

- Add comprehensive TEE Key Encryption Architecture section:
  - Document threat model and security goals
  - Add encryption flow diagram (client -> API -> TEE)
  - Specify ECIES over secp256k1 as encryption primitive
  - Document TEE public key distribution with attestation
  - Define key epoch rotation scheme with 1-week grace period
  - Add epoch validation logic and error handling
  - Document forward secrecy considerations

- Update security review findings:
  - Mark TEE epoch rotation finding (#5) as addressed
  - Add comprehensive private key security test cases:
    - Test that private keys are never logged
    - Test that keys are not stored in localStorage/sessionStorage
    - Test that only encrypted keys are sent to TEE
    - Test IPNS signature verification prevents forgery

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
FSM1 added a commit that referenced this pull request May 25, 2026
- Scope Tauri events per attempt via port-specific event names (review #1)
- Validate POST requests with server-generated nonce (review #2)
- Use absolute deadline instead of per-connection timeout (review #3)
- Use actual popup counter value for cleanup (review #4)
- Fail fast when all preferred ports are taken (review #6)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 172d4ce72f72
FSM1 added a commit that referenced this pull request May 25, 2026
…#459)

* fix(desktop): use localhost callback server for Google OAuth in Tauri

Google OAuth rejects custom URI schemes like `tauri://localhost` which
is what `window.location.origin` resolves to in production Tauri builds.
This caused Error 400: invalid_request when attempting Google login.

Replace the localStorage-polling approach with a temporary localhost HTTP
server (Rust-side) that receives the OAuth redirect, extracts the id_token
from the URL fragment via an injected callback page, and emits it back to
the main webview via a Tauri event.

- Add `start_oauth_server` Tauri command with preferred port selection
  (14200-14202) and random fallback
- Rewrite `getGoogleCredential()` to use the callback server + Tauri
  event listener instead of localStorage polling
- Add `core:event:default` permission for Tauri event API access
- Content-Length-aware HTTP body reading for reliable POST parsing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 51734dbce9b4

* chore(release): set release targets for PR #459

* fix(desktop): address PR review comments on OAuth callback server

- Scope Tauri events per attempt via port-specific event names (review #1)
- Validate POST requests with server-generated nonce (review #2)
- Use absolute deadline instead of per-connection timeout (review #3)
- Use actual popup counter value for cleanup (review #4)
- Fail fast when all preferred ports are taken (review #6)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 172d4ce72f72

* docs: implement temporary localhost HTTP server for Google OAuth callback in Tauri

Entire-Checkpoint: ac0f39da9ff3

* fix(desktop): address second round of PR review comments

- Update JSDoc to reflect fixed-port strategy (no dynamic/loopback)
- Validate OAuth state before handling errors (prevents DoS via crafted error)
- Loop-read TCP until headers are complete before parsing Content-Length
- Update debug doc to match current implementation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 72dff9156bda

* fix(desktop): address CodeRabbit review on OAuth callback server

- Move cleanup() after state validation to prevent promise hang on mismatch
- Use OsRng (CSPRNG) instead of thread_rng for nonce generation
- Remove Access-Control-Allow-Origin: * from GET responses (prevents
  local pages from fetching callback HTML to steal the nonce)
- Close OAuth popup windows on server timeout
- Gate callback HTML serving to /callback path only (404 for others)
- Remove stale review-cycle comment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 60247aaac75c

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
FSM1 added a commit that referenced this pull request Jun 29, 2026
The Phase-64 moveItem destination re-seal (FLAG-63-U2) looked up the moved
child in updatedDest by childId (a UUID handle), but SealedChildRef carries
no id (NODE-03) — it is keyed by ipnsName. The lookup always missed and threw
"moved child <id> not found in dest after link rewrite", breaking the active
client-extended.test.ts > moveItem CI test (the Test job).

Use the movedRef that sdkCore.moveItem() already returns, locate the real
entry in updatedDest by movedRef.ipnsName, and resolve the child IPNS by
ipnsName. Strengthen the unit test to mock the IPNS resolve/fetch + seal/unseal
and assert the published dest entry carries the re-sealed key (CodeRabbit #2
fixed, #3 addressed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUSYqMyCLbNGDLcn1cp1eh
Entire-Checkpoint: db39705f39f0
FSM1 added a commit that referenced this pull request Jun 29, 2026
…crash-safe resume (#582)

* docs(64): capture phase context

Entire-Checkpoint: e93088839ad6

* docs(state): record phase 64 context session

Entire-Checkpoint: 500072385b16

* docs(64): research — rotation soundness seam fills and D-02/D-06/D-07 hardening

Entire-Checkpoint: e21e9fa3c13d

* docs(64): add validation strategy and pattern map

Entire-Checkpoint: 7fdbefa471e2

* docs(64): create rotation-soundness phase plans

Entire-Checkpoint: a7f5d10d27cf

* docs(64): pin no-double-bump per-node convergence guard in plan 64-07

Entire-Checkpoint: 1e8ed6c455d4

* docs(64): resolve research open questions and fill validation map

Entire-Checkpoint: cc92facc65bc

* docs(64): record planning completion and roadmap wave annotations

Entire-Checkpoint: d727bfa43d77

* test(64-01): add failing tests for nodeId/nodeGeneration required fields

- RED: 'throws when nodeId not provided' fails (function resolves, no guard yet)
- RED: 'throws when nodeGeneration not provided' fails (function resolves, no guard yet)
- Behavioral round-trip tests pass to document correct identity-preservation behavior
- Uses real sealNode/unsealNode; mocks only IPFS/IPNS I/O layers

Entire-Checkpoint: 3615bef8dac1

* feat(64-01): make nodeId/nodeGeneration required on updateFolderMetadataAndPublish

- Remove ?? crypto.randomUUID() and ?? 0 fallbacks (D-06 fix)
- Add required nodeId: string and nodeGeneration: number to params type
- Add runtime guards with descriptive error messages (AAD-stability enforcement)
- Add nodeId/nodeGeneration as required fields on FolderState (sdk/types.ts)
- Update existing folder.test.ts calls to supply the required fields
- GREEN: all 5 registration.test.ts tests pass

Entire-Checkpoint: 84bea983f14c

* feat(64-01): thread nodeId/nodeGeneration through all six client.ts CRUD call sites

- Add nodeId/nodeGeneration optional params to registerFolder (D-06 bridge)
- Set nodeId/nodeGeneration in loadFolder from result.metadata.id/.generation
- Pass folder.nodeId/folder.nodeGeneration to all six updateFolderMetadataAndPublish
  call sites: renameItem, moveItem (src+dst), deleteItem, uploadFile, uploadFiles
- Fix FolderState test fixtures in 7 test files (Rule 1: caused by required fields)

Entire-Checkpoint: 177ccaf415e2

* test(64-01): add AEAD round-trip spec for moveItem dest-parent re-seal (FLAG-63-U2)

Entire-Checkpoint: 1f1ced14e87c

* feat(64-01): re-seal moved child readKey under dest parent readKey in moveItem (FLAG-63-U2)

- Import sealChildReadKey, unsealChildReadKey, PublishedNode from @cipherbox/core
- After sdkCore.moveItem() link rewrite, resolve child IPNS to get plaintext id/kind
- Unseal movedRef.readKeySealed under source parent folderKey
- Re-seal under dest parent folderKey using unchanged id/kind/generation
- Zero recovered childReadKey (engine-derived, terminal-owned — D-09)
- Do NOT zero sourceFolder.folderKey or destFolder.folderKey (caller-owned)

Entire-Checkpoint: 8d37fe2fc8c8

* docs(64-01): complete nodeId/nodeGeneration required + moveItem re-seal plan

Entire-Checkpoint: 9721d0ffb633

* test(64-02): add failing three-way merge tests for SealedChildRef

Entire-Checkpoint: 6cf80e49e9b2

* feat(64-02): implement mergeChildren three-way merge for SealedChildRef

- Union by ipnsName: local inserted first, remote overwrites on conflict
- Remote wins on conflict so concurrent adds are never silently dropped
- Intentional delete: base entry absent from both local and remote is pruned
- One-sided delete: entry kept when at least one side still holds it
- Pure structural merge: no crypto, no mutation of sealed bytes
- Return type changed from never to SealedChildRef[]

Entire-Checkpoint: 70a7d11743f2

* docs(64-02): complete mergeChildren three-way merge plan

Entire-Checkpoint: 6d39de02c928

* test(64-03): add failing content-key rotation tests

- RED: mintFileKeyOnRotate assigns fresh 32-byte fileKey distinct from old key
- RED: mintFileKeyOnRotate is no-op for folder nodes (no content field added)
- RED: rotateOne sealNode integration — sealNode receives new fileKey after mint

Entire-Checkpoint: 9b10bf0c5309

* feat(64-03): mint fresh fileKey on file rotation

- Fill mintFileKeyOnRotate seam (ROT-03/CRIT-1): mint fileKey' = generateRandomBytes(32)
  and assign to node.content.fileKey when content present; folder nodes are no-op
- Import generateRandomBytes from @cipherbox/crypto for cryptographic randomness
- Remove obsolete 'mintFileKeyOnRotate throws phase 64' tests from Phase-63 seam suite
- Green: all 19 engine tests pass; old readKey/fileKey holder cannot decrypt next version

Entire-Checkpoint: 503247cc33ff

* docs(64-03): complete mintFileKeyOnRotate seam fill plan

Entire-Checkpoint: 95e1a7552608

* fix(64-01): typecheck-clean the D-06 test files

Entire-Checkpoint: 9003f3740525

* test(64-04): RED tests for D-01 fail-closed publish and nodeKeySource

- Assert rotateOne throws when nodeIpnsPrivateKey is absent
- Assert publishWithCas not called with all-zero placeholder key
- Assert BFS threads nodeKeySource key to child publishWithCas
- Assert BFS throws when nodeKeySource returns undefined for a child
- Add nodeKeySource? to RotationParams type (type-only seam, no threading yet)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUSYqMyCLbNGDLcn1cp1eh
Entire-Checkpoint: 068bec968119

* feat(64-04): D-01 fail-closed publish guard and nodeKeySource BFS threading

- Add runtime guard in rotateOne: throws when nodeIpnsPrivateKey absent
- Remove PLACEHOLDER_WRITE_KEY fallback from publishWithCas ipnsPrivateKey arg
- Destructure nodeKeySource from RotationParams in rotateReadFromNode
- Thread nodeKeySource keys to child and grandchild BFS queue items
- Update all existing rotateOne tests to supply nodeIpnsPrivateKey
- Update all rotateReadFromNode tests with children to supply rootIpnsPrivateKey
  and nodeKeySource; add unsealChildReadKey mock where missing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUSYqMyCLbNGDLcn1cp1eh
Entire-Checkpoint: 5144d4bc942a

* test(64-04): RED tests for D-02 parent re-seal and D-09 batched parent publish

- Assert sealChildReadKey called with parent new readKey' for child re-seal
- Assert publishWithCas called 3 times for root->child walk
- Assert sealChildReadKey total call count is 3 for root->child walk

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUSYqMyCLbNGDLcn1cp1eh
Entire-Checkpoint: 412974d990b3

* feat(64-04): D-02 parent-link re-seal and D-09 batched parent publish

- Add newSequenceNumber to RotateOneDone; capture publishWithCas return in rotateOne
- Add ParentTrackingState and parentTracking Map to rotateReadFromNode BFS walker
- After each child rotates, call sealChildReadKey with parent's NEW readKey' (D-02 fix)
- Update parent's mutable SealedChildRef copy with re-sealed key and new generation
- Call updateFolderMetadataAndPublish once when all children done (D-09 batched publish)
- Add childPubId/childPubKind to BFS queue items for AAD binding in D-02 re-seal
- Import updateFolderMetadataAndPublish from folder/registration
- Fix TypeScript tuple destructuring in sealChildReadKey mock assertion

Entire-Checkpoint: 91655dc8a1c4

* docs(64-04): complete plan 04 summary

Entire-Checkpoint: d29b43cfd1a3

* test(64-05): add failing inner-grant re-mint tests

- 4 RED tests for reMintGrantsRootedAt (ROT-04/HIGH-3/D-04)
- Test 1: non-revoked grant → wrapKey + updateGrantFn; deleteGrantFn not called
- Test 2: revoked grant → deleteGrantFn only; wrapKey + updateGrantFn not called
- Test 3: mixed set → exactly one update and one delete with correct shareIds
- Test 4: no callbacks supplied → clean no-op (no throw)
- Extend reMintGrantsRootedAt signature with optional GrantRemintCallbacks param
- Add GrantRemintCallbacks type (D-04 transport seam)
- Add grantCallbacks field to RotateOneParams for call-site threading

Entire-Checkpoint: ef5d06556ecc

* feat(64-05): re-mint readDescriptorRef for rooted grants

- Fill reMintGrantsRootedAt body (ROT-04/HIGH-3/D-04)
- Add wrapKey import from @cipherbox/crypto for ECIES descriptor minting
- Add local bytesToBase64 helper for readDescriptorRef encoding
- Enumerate grants via queryGrantsFn; delete revoked, re-mint non-revoked
- Never zero newReadKey (caller is terminal owner per D-09)
- Add grantCallbacks field to RotateOneParams; thread through call site
- Update engine.test.ts seam test to reflect filled reMintGrantsRootedAt

Entire-Checkpoint: 2f84097cb689

* docs(64-05): complete plan 05 summary

Entire-Checkpoint: cd15a6063aa9

* test(64-06): add failing CAS-409 concurrent-add tests

Entire-Checkpoint: 30192904c769

* feat(64-06): merge concurrent child adds on rotation CAS-409

- Implement mergeConcurrentChildren: unseal base+remote under old readKey,
  three-way merge via mergeChildren, re-seal merged result under readKeyPrime
- Wire async merge callback in rotateOne publishWithCas for ROT-05/HIGH-4
- Update cas.ts merge type to accept async callback (Promise union); wrap
  call site with await Promise.resolve() for backward-compat sync callers
- Add mergeChildren import from folder/merge in engine.ts
- Remove old Phase-63 throw stub from rotateOne merge callback
- Remove mergeConcurrentChildren direct-call seam test (now tested indirectly
  through rotateOne 64-06 integration tests)
- Fix vi.clearAllMocks() -> vi.resetAllMocks() in 64-06 and D-02 beforeEach
  blocks to drain mockResolvedValueOnce queue between tests (Rule 1: prevents
  leftover Once-values from failing RED tests contaminating D-02/D-09 tests)

Entire-Checkpoint: 1917175ac7cb

* docs(64-06): complete plan 06 summary and state

Entire-Checkpoint: 7e9f7f2c3a63

* test(64-07): add failing tests for verifySubtreeClean resume and convergence guard

- Replace old throws-phase-64 test with 5 new ROT-06 tests (Tests 1-5)
- Test 1/2: verifySubtreeClean { isDirty, frontier } return shape (BFS dirty-edge)
- Test 3: resume guard with dirty child triggers D-09 re-publish not short-circuit
- Test 4: clean resume marks complete and persists (passes in RED too, regression gate)
- Test 5: fresh-job no-double-bump convergence guard skips child already at baseline+1
- Update verifySubtreeClean signature to accept rootIpnsName, rootReadKey, ctx

Entire-Checkpoint: 51f009ac09cf

* feat(64-07): fill verifySubtreeClean and rewrite resume guard with convergence guard

- Implement verifySubtreeClean: BFS read-only pass comparing SealedChildRef.generation
  (parent mirror) vs childPub.generation (plaintext) to rebuild dirty-edge frontier
- Rewrite resume guard: call verifySubtreeClean before marking complete (Pitfall 5);
  dirty resume seeds BFS queue from frontier instead of short-circuiting to complete
- Add enqueuedGeneration field to BFS queue items (parent mirror at enqueue time)
- Add convergence guard before each rotateOne in BFS: skip if current published
  generation exceeds enqueued baseline (ROT-06 no-double-bump); still handle D-09

Entire-Checkpoint: 4749801642b4

* test(64-07): add failing tests for D-07 ordering terminal persist and queue-key zeroization

- Test 1: reMintGrantsRootedAt throws → nodeId must NOT be in completedNodeIds (D-07)
- Test 2: terminal status=complete must be persisted via persistCallback (terminal persist)
- Test 3: queue-derived child nodeReadKey must be zeroed after grandchildren enqueued;
  rootReadKey must NOT be zeroed (regression gate — caller is terminal owner per D-09)

Entire-Checkpoint: 6d7dbbd5806f

* feat(64-07): fix D-07 ordering terminal persist and queue-key zeroization

- Move completedNodeIds.add(nodeId) to AFTER reMintGrantsRootedAt succeeds (D-07):
  a failed re-mint no longer silently skips the node on resume
- Add persistCallback call at terminal status=complete (Pitfall 5: advisory job
  record must be persisted at completion so the resumable walk gate is accurate)
- Zero item.nodeReadKey after grandchildren enqueued (D-09 queue-key ownership):
  engine-derived BFS readKeys are zeroed once their consumers are enqueued;
  caller-supplied rootReadKey is never zeroed (caller is terminal owner)

Entire-Checkpoint: 1dd05f2fedc4

* docs(64-07): complete verifySubtreeClean and D-07 ordering plan

Entire-Checkpoint: 086888ac926c

* test(64-08): add rotation crash-safety E2E suite (TEST-01 phase gate)

- Task 1: depth-2 tree (root→subfolder→file) happy-path rotation; all nodes
  advance to gen=1; post-rotation read-chain navigation under new keys proves
  multi-level D-02 re-seal; pre-rotation grant returns behind-retry
- Task 2: crash at final persistCallback (call 4, after all D-09s complete);
  fresh resume with seeded completedNodeIds and readKeyPrime converges with
  isDirty=false, no double-bump, zero getRandomValues calls on resume
- Task 3: concurrent IPNS write to parent between root commit and D-09
  batched republish forces CAS-409; mergeChildren (ROT-05/HIGH-4) absorbs
  the conflict and the concurrently-added child survives in the final parent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUSYqMyCLbNGDLcn1cp1eh
Entire-Checkpoint: c7801eb52d88

* docs(64-08): complete rotation crash-safety suite plan

Entire-Checkpoint: e69fa8406d74

* docs(64): capture deferred rotation-soundness todos (HIGH-4 merge, fresh-record resume)

Entire-Checkpoint: 7ed06cb1ff18

* docs(64): add verification and security audit

Entire-Checkpoint: 36441ac5f1c9

* docs(64): fix stale Phase-63 seam comments in rotation engine

Entire-Checkpoint: 4b277c878d83

* fix(64): apply low-risk CodeRabbit findings and capture deferred ones

Entire-Checkpoint: 1226147f936f

* fix(64): resolve moveItem re-seal by ipnsName not childId

The Phase-64 moveItem destination re-seal (FLAG-63-U2) looked up the moved
child in updatedDest by childId (a UUID handle), but SealedChildRef carries
no id (NODE-03) — it is keyed by ipnsName. The lookup always missed and threw
"moved child <id> not found in dest after link rewrite", breaking the active
client-extended.test.ts > moveItem CI test (the Test job).

Use the movedRef that sdkCore.moveItem() already returns, locate the real
entry in updatedDest by movedRef.ipnsName, and resolve the child IPNS by
ipnsName. Strengthen the unit test to mock the IPNS resolve/fetch + seal/unseal
and assert the published dest entry carries the re-sealed key (CodeRabbit #2
fixed, #3 addressed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUSYqMyCLbNGDLcn1cp1eh
Entire-Checkpoint: db39705f39f0

* fix(64): harden rotation D-01/D-09 guards from PR review

Apply the low-risk quick-win findings from the CodeRabbit + greptile PR reviews;
defer the heavy rotation-soundness rework (RR-01 merge re-enqueue, recursive
verifySubtreeClean, convergence-skip re-seal) to its existing Phase 66/68 todos.

- D-09: mintFileKeyOnRotate now zeroes the pre-rotation node.content.fileKey
  before overwriting (safe — node is a fresh unsealNode output, engine-owned).
- D-01: rotateOne's fail-closed guard rejects malformed/all-zero/wrong-length
  IPNS keys, not just undefined (keys are the 32-byte Ed25519 seed).
- D-01: dirty-resume root republish fails closed when rootIpnsPrivateKey is
  missing, before seeding parentTracking (no more parentIpnsPrivateKey! leaking
  undefined into updateFolderMetadataAndPublish).
- Test fixtures (helpers.setupFolder, client.test, client-move-reencrypt.test)
  seed stable non-empty nodeId placeholders per the folder publish contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUSYqMyCLbNGDLcn1cp1eh
Entire-Checkpoint: c85e68fa1b12

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants