Skip to content

feat(05): Folder System - IPNS metadata, folder hierarchy, and operations#39

Merged
FSM1 merged 26 commits into
mainfrom
feat/phase-5-folder-system
Jan 21, 2026
Merged

feat(05): Folder System - IPNS metadata, folder hierarchy, and operations#39
FSM1 merged 26 commits into
mainfrom
feat/phase-5-folder-system

Conversation

@FSM1

@FSM1 FSM1 commented Jan 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add backend IPNS module with delegated routing relay (POST /ipns/publish)
  • Extend @cipherbox/crypto with IPNS record creation and folder metadata encryption
  • Create frontend vault/folder Zustand stores and IPNS publishing service
  • Implement complete folder CRUD operations (create, delete, rename, move)

What's Included

Backend (apps/api)

  • IpnsModule with POST /ipns/publish endpoint
  • FolderIpns entity for tracking IPNS names/CIDs (TEE republishing)
  • Delegated routing client with exponential backoff retry

Crypto Package (packages/crypto)

  • IPNS record creation using ipns npm package with libp2p integration
  • IPNS name derivation from Ed25519 public keys
  • Folder metadata types (FolderMetadata, FolderEntry, FileEntry)
  • AES-256-GCM encryption/decryption for folder metadata
  • 24 new tests for IPNS and folder operations

Frontend (apps/web)

  • useVaultStore - memory-only key management with zeroing
  • useFolderStore - folder tree state management
  • ipns.service.ts - local IPNS signing with backend relay
  • folder.service.ts - complete CRUD operations
  • useFolder hook - React integration with loading/error state

Requirements Completed

  • FOLD-01: User can create folders ✓
  • FOLD-02: User can delete folders (recursive) ✓
  • FOLD-03: User can nest folders up to 20 levels deep ✓
  • FOLD-04: User can rename folders ✓
  • FOLD-05: User can move folders between parent folders ✓
  • FOLD-06: Each folder has its own IPNS keypair ✓
  • FILE-04: User can rename files ✓
  • FILE-05: User can move files between folders ✓
  • API-05: Backend relays pre-signed IPNS records ✓

Test plan

  • Backend: IPNS publish endpoint accepts valid records
  • Crypto: IPNS record creation tests pass (13 tests)
  • Crypto: Folder metadata encryption tests pass (11 tests)
  • Frontend: Folder creation with depth limit enforcement
  • Frontend: Recursive folder deletion with file unpinning
  • Frontend: Move operations prevent circular references

🤖 Generated with Claude Code

FSM1 and others added 25 commits January 21, 2026 04:19
Phase 05: Folder System
- Implementation decisions documented
- Phase boundary established
Phase 05: Folder System
- Standard stack: ipns, @libp2p/crypto, @libp2p/peer-id packages
- Architecture: client-signed IPNS with delegated routing API relay
- Folder metadata encryption patterns documented
- Pitfalls: Ed25519 key format, sequence numbers, TTL vs lifetime
- Code examples for IPNS record creation and publishing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 05-03: Add depth check in createFolder (FOLD-03)
- 05-03: Add getDepth helper to exports
- 05-03: Document VaultStore auth flow integration
- 05-04: Add deleteFile function to Task 1
- 05-04: Add depth validation in handleCreate hook
- 05-04: Update must_haves to include file deletion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add FolderIpns entity with unique (userId, ipnsName) constraint
- Track ipnsName, latestCid, sequenceNumber for each folder
- Store ECIES-wrapped IPNS keys for TEE republishing
- Add PublishIpnsDto with validation decorators
- Add PublishIpnsResponseDto for publish response
- Add ipns, @libp2p/crypto, @libp2p/peer-id, multiformats dependencies
- createIpnsRecord: converts @noble/ed25519 keys to libp2p format
- deriveIpnsName: derives k51... IPNS name from Ed25519 public key
- marshalIpnsRecord/unmarshalIpnsRecord: protobuf serialization wrappers
- publishRecord() validates base64, relays to delegated-ipfs.dev
- Exponential backoff retry on rate limits and network errors
- upsertFolderIpns() tracks folder IPNS names and CIDs
- getFolderIpns() and getAllFolderIpns() for TEE republishing
- Configurable DELEGATED_ROUTING_URL env var
- FolderMetadata, FolderEntry, FileEntry types per RESEARCH.md spec
- EncryptedFolderMetadata for storage format
- encryptFolderMetadata: AES-256-GCM encryption with random IV
- decryptFolderMetadata: restores metadata from encrypted form
…ient

- Add IpnsController with POST /ipns/publish endpoint
- Add IpnsModule with proper exports for future VaultModule integration
- Register IpnsModule and FolderIpns entity in app.module.ts
- Update generate-openapi.ts with IpnsController and IpnsService
- Regenerate OpenAPI spec and web API client
Tasks completed: 3/3
- Create FolderIpns entity and DTOs
- Create IpnsService with delegated routing
- Create IpnsController and IpnsModule

SUMMARY: .planning/phases/05-folder-system/05-01-SUMMARY.md
- IPNS record tests: createIpnsRecord, deriveIpnsName, marshal/unmarshal
- Folder metadata tests: encrypt/decrypt round-trip, security tests
- Tests verify compatibility with IPFS network expectations
- All 132 tests passing
Tasks completed: 3/3
- Task 1: Add IPNS dependencies and create record functions
- Task 2: Create folder metadata types and encryption
- Task 3: Add tests for IPNS record and folder metadata

SUMMARY: .planning/phases/05-folder-system/05-02-SUMMARY.md
- Add useVaultStore Zustand store for decrypted vault keys
- Store rootFolderKey (AES-256) for folder encryption
- Store rootIpnsKeypair (Ed25519) for IPNS signing
- Store rootIpnsName derived from keypair
- Implement memory-zeroing on clearVaultKeys (MEDIUM-02 security)
- Document integration flow with auth.store.ts
- Add createAndPublishIpnsRecord for local signing and backend relay
- Sign IPNS records locally with Ed25519 private key
- Marshal and base64-encode records for API transport
- Integrate with @cipherbox/crypto createIpnsRecord and marshalIpnsRecord
- Add resolveIpnsRecord stub (Phase 7 implementation)
- Create services/index.ts barrel export
- Add useFolderStore Zustand store for folder tree state
- Export FolderNode type for folder representation
- Track current folder, breadcrumbs, pending publishes
- Implement memory-zeroing on clearFolders (MEDIUM-02 security)

- Add folder.service.ts with CRUD operations
- getDepth: calculate folder depth from root
- createFolder: generate IPNS keypair, folder key, ECIES wrap
- loadFolder: stub for Phase 05-04 implementation
- updateFolderMetadata: encrypt metadata, upload, publish IPNS
- Enforce FOLD-03 max depth of 20 in createFolder

- Update services/index.ts barrel export
Tasks completed: 3/3
- Create vault store for key management
- Create IPNS service for record publishing
- Create folder store and service

SUMMARY: .planning/phases/05-folder-system/05-03-SUMMARY.md
- Add renameFolder: updates folder name in parent metadata and publishes IPNS
- Add deleteFolder: recursively collects CIDs, removes from parent, unpins
- Add deleteFileFromFolder: removes file from parent metadata and unpins
- Add folder.store removeFolder: clears folder keys and removes from state
- Add folder.store updateFolderName: updates folder name in local state
- Name collision check on rename with descriptive error
- Add moveFolder: add-before-remove pattern, depth limit check, self-move prevention
- Add moveFile: add-before-remove pattern, name collision check
- Add renameFile: updates file name in parent metadata with collision check
- Add calculateSubtreeDepth: computes max depth for move validation (FOLD-03)
- Add isDescendantOf: prevents moving folder into itself or descendants
- Add useFolder hook with createFolder, renameItem, moveItem, deleteItem
- Each operation manages loading/error state
- Depth limit validation (FOLD-03) on folder creation
- Uses add-before-remove pattern for move operations
- Updates local folder store state after operations
- Add hooks barrel export file (hooks/index.ts)
Tasks completed: 3/3
- Task 1: Implement folder rename and delete operations
- Task 2: Implement move operations for files and folders
- Task 3: Create useFolder hook for UI integration

SUMMARY: .planning/phases/05-folder-system/05-04-SUMMARY.md
Phase 5 verified:
- 4/4 plans executed
- 6/6 success criteria verified
- 9 requirements marked complete (FOLD-01 through FOLD-06, FILE-04, FILE-05, API-05)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CRITICAL:
- Add ValidationPipe to API main.ts to enable DTO validation

HIGH:
- Clear vault/folder stores on logout to zero crypto keys from memory
- Clear all stores on token refresh failure
- Add @nestjs/throttler rate limiting to IPNS publish endpoint

MEDIUM:
- Clear intermediate private key material after use in create-record.ts
- Add sequence number validation (non-negative) in create-record.ts
- Add runtime type validation for decrypted folder metadata
- Use chunked base64 encoding for large folder metadata
- Strengthen DTO validation (ipnsName, metadataCid, encryptedIpnsPrivateKey)
- Sanitize error messages in ipns.service.ts to avoid leaking internals

Documentation:
- Add security review report (.planning/security/REVIEW-2026-01-21-phase5.md)
- Document LOW severity issues for future work

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ThrottlerModule to OpenAPI generator module (required by IpnsController)
- Add comprehensive unit tests for IpnsService (24 tests, 100% coverage)
- Regenerate OpenAPI spec with proper module dependencies

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

codecov Bot commented Jan 21, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@FSM1 FSM1 merged commit 8793004 into main Jan 21, 2026
4 checks passed
@FSM1 FSM1 deleted the feat/phase-5-folder-system branch January 27, 2026 03:26
This was referenced Mar 23, 2026
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.

1 participant