Skip to content

feat(api): share item-name backfill endpoint#505

Merged
FSM1 merged 7 commits into
mainfrom
feat/share-itemname-lazy-backfill
Jun 17, 2026
Merged

feat(api): share item-name backfill endpoint#505
FSM1 merged 7 commits into
mainfrom
feat/share-itemname-lazy-backfill

Conversation

@FSM1

@FSM1 FSM1 commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the last open item from Phase 48 (REQ-4): encrypting share itemName at rest now works for legacy shares too.

Phase 48 added at-rest itemNameEncrypted on share create paths, but left a gap — there was no update endpoint accepting itemNameEncrypted, so the web client's lazy backfill (decision A2) could re-wrap a legacy plaintext itemName for the recipient but had nowhere to persist it (void itemNameEncrypted). This PR adds that endpoint and wires the backfill through it.

The server stays zero-knowledge: it never encrypts, only persists client-supplied ciphertext.

Changes

feat(api): share item-name backfill endpoint

  • New PATCH /shares/:shareId/item-name — sharer-only; stores the client-supplied ECIES ciphertext as-is (mirrors the existing PATCH /shares/:shareId/encrypted-key pattern).
  • New UpdateItemNameDto (even-length hex, MaxLength 2500) + SharesService.updateShareItemName (load → 404 → sharer-only 403 → persist).
  • Regenerated the typed API client (@cipherbox/api-client) → sharesControllerUpdateShareItemName.
  • Web: backfillSentShareItemNames now persists via the new endpoint, and the backfill pass is re-enabled in fetchAllSentShares (best-effort, idempotent via shouldBackfill, fire-and-forget so list loads never block).

docs(planning): bookkeeping

  • Backfilled the 5 missing Phase 47 SUMMARY.md files (Phase 47 shipped via #494 but its summaries were never written, which tripped a false-positive resume gate).
  • Added 48-VERIFICATION.md and advanced STATE.md — milestone v1.1 now 33/33 phases, 146/146 plans.

Requirements Addressed

  • REQ-4 (Phase 48) — encrypt share itemName at rest, now complete for legacy rows.

Verification

  • API: apps/api shares suites — 171 passed (added 3 service + 3 controller specs for the new endpoint).
  • Web: share suites — 48 passed; tsc --noEmit clean; eslint clean.
  • pnpm api:generate — generated client + openapi.json regenerated and committed (satisfies the check-api-client.sh pre-commit gate).
  • E2E (two-party): tests/web-e2e/tests/share-itemname-backfill.spec.ts — seeds a legacy share (plaintext itemName, NULL itemNameEncrypted), triggers the owner-side backfill via a file upload, then asserts the persisted itemNameEncrypted is valid ciphertext (null → hex ≠ plaintext, longer than plaintext), the recipient still displays the correct name, and the backfill is idempotent. All 7 steps pass against the local full stack (~52s). Runs in CI via web-e2e.yml (playwright test, unfiltered) on main-push or when dispatched against the branch.
  • Residual (out of harness): a literal raw-bytea Postgres read to byte-prove "server never saw plaintext" — web-e2e has no DB client, so the spec's GET /shares/sent hex-≠-plaintext assertion is the in-harness proxy. Closeable later by adding a pg util.

Key Decisions

  • Dedicated single-field PATCH endpoint, matching the existing /encrypted-key, /permission, /hide convention (no generic bulk-update endpoint exists).
  • Lazy client-side backfill (decision A2) rather than a server migration — the server is zero-knowledge and cannot encrypt; only the sharer holds the recipient pubkey to re-wrap.
  • Sequential fire-and-forget backfill (not parallel) to stay within the API throttler; steady-state cost is ~zero via the shouldBackfill idempotence short-circuit.

Summary by CodeRabbit

  • New Features
    • Added a new PATCH /shares/:shareId/item-name endpoint to persist encrypted share item names (ciphertext) for legacy shares.
  • Bug Fixes
    • Re-enabled lazy backfill for legacy shares and made it run asynchronously so share list loading doesn’t block.
    • Fixed the SDK self-bootstrap regression affecting shared folder/metadata behavior.
  • Tests
    • Added an end-to-end Playwright test covering item-name backfill, validation, and idempotency.
  • Chores
    • Marked Phase 47 and Phase 48 as shipped and updated tracked milestone status.
    • Updated release versions for API, web, and SDK packages.

FSM1 and others added 3 commits June 17, 2026 15:24
… shares

Phase 48 REQ-4 left a gap: itemNameEncrypted was only accepted on share
CREATE paths, so the web lazy-backfill (decision A2) could re-wrap legacy
plaintext itemName but had nowhere to persist it. Add PATCH
/shares/:shareId/item-name (sharer-only, stores client ciphertext as-is,
server never encrypts), regenerate the typed client, and wire+re-enable
backfillSentShareItemNames in the web share service.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: b886f47dabf9
Phase 47 shipped via PR #494 but its 5 SUMMARY.md files were never written,
tripping a false-positive resume-incomplete gate. Reconstruct them from the
plans and merged source. Add the missing 48-VERIFICATION.md (3.5/4; REQ-4
legacy backfill now resolved by the item-name endpoint).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: e0c3a8080f74
Advance STATE.md now that phase 48 has all summaries + verification and
the REQ-4 itemName backfill gap is resolved. 33/33 phases, 146/146 plans.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: 027e67269db2
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4f5d0223-4fed-4aa8-b4a3-97c090b9d8be

📥 Commits

Reviewing files that changed from the base of the PR and between 1be1910 and dbd65ac.

📒 Files selected for processing (2)
  • apps/web/src/services/share.service.ts
  • tests/web-e2e/tests/share-itemname-backfill.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/services/share.service.ts

Walkthrough

Adds a new PATCH /shares/:shareId/item-name API endpoint backed by UpdateItemNameDto, SharesService.updateShareItemName, and a matching controller handler that enforces sharer-only authorization. The web share.service.ts backfill function is wired to call this endpoint and re-enabled fire-and-forget during sent-share pagination. A comprehensive E2E test verifies legacy share seed, plaintext fallback, backfill trigger, ciphertext persistence, and idempotency. Planning documentation includes five Phase 47 summaries, a Phase 48 verification report, and version bumps.

Changes

itemNameEncrypted Backfill API and Web Integration

Layer / File(s) Summary
DTO and service contract for itemNameEncrypted persistence
apps/api/src/shares/dto/update-item-name.dto.ts, apps/api/src/shares/dto/index.ts, apps/api/src/shares/shares.service.ts, apps/api/src/shares/shares.service.spec.ts
UpdateItemNameDto enforces even-length hex validation and 2500-byte max length; SharesService.updateShareItemName loads the share, checks sharer identity, hex-decodes the payload to a Buffer, and persists it; service tests cover success, missing share, and unauthorized caller flows.
PATCH /shares/:shareId/item-name controller endpoint
apps/api/src/shares/shares.controller.ts, apps/api/src/shares/shares.controller.spec.ts
New PATCH /:shareId/item-name route in SharesController returns 204 No Content with Swagger documentation; imports UpdateItemNameDto and delegates to sharesService.updateShareItemName; controller tests verify service invocation and error propagation for missing shares and non-sharers.
Web share service backfill invocation
apps/web/src/services/share.service.ts
sharesControllerUpdateShareItemName is imported and called inside backfillSentShareItemNames for legacy plaintext-only shares, replacing the prior no-op stub; fetchAllSentShares re-enables the fire-and-forget backfill pass with warning logging on failure.
E2E backfill scenario and ciphertext verification
tests/web-e2e/tests/share-itemname-backfill.spec.ts
Playwright test seeds a legacy share without ciphertext, confirms plaintext fallback render, triggers backfill via file upload, polls until ciphertext persists, validates hex encoding and ciphertext ≠ plaintext hex, verifies recipient-side visibility, and confirms idempotency on second trigger.
Phase 47 plan summaries, Phase 48 verification report, and version tracking
.planning/STATE.md, .planning/phases/47-sdk-folder-state-publish-consolidation/47-*-SUMMARY.md, .planning/phases/48-sdk-self-bootstrap-regression-fix-and-shared-folder-metadata/48-VERIFICATION.md, release-please-config.json
STATE.md counters advanced to 100% with Phase 48 marked COMPLETE; five Phase 47 plan summaries (01–05) are backfilled describing CAS unification, shared-write cleanup, SDK client file-ops, web hook routing, and folder store projection; Phase 48 verification marks REQ-1/2/3 achieved and REQ-4 gap now closed; release-as versions bumped for apps/api (0.40.0), apps/web (0.44.0), packages/api-client (0.40.0), and packages/sdk (0.35.1).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • FSM1/cipher-box#183: Introduced the original shares controller/service infrastructure that the new updateShareItemName method and PATCH /shares/:shareId/item-name endpoint extend.
  • FSM1/cipher-box#500: The main PR's new PATCH endpoint and re-enabled backfillSentShareItemNames directly complete the itemNameEncrypted-at-rest lazy backfill gap and Phase 48 requirements from that prior work.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(api): share item-name backfill endpoint' directly describes the main change: a new PATCH endpoint for persisting encrypted itemName on legacy shares, which is the core functional addition in this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/share-itemname-lazy-backfill

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@FSM1 FSM1 changed the title feat: share item-name backfill endpoint (Phase 48 REQ-4 gap) feat(api): share item-name backfill endpoint Jun 17, 2026
@github-actions github-actions Bot added release:api:feat Minor version bump (new feature) for api release:web:feat Minor version bump (new feature) for web release:sdk-core:fix Patch version bump (bug fix) for sdk-core release:sdk:fix Patch version bump (bug fix) for sdk release:cipherbox-fuse:fix Patch version bump (bug fix) for cipherbox-fuse release:cipherbox-sdk:fix Patch version bump (bug fix) for cipherbox-sdk release:desktop:fix Patch version bump (bug fix) for desktop release:tee-worker:fix Patch version bump (bug fix) for tee-worker labels Jun 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Release Preview

Package Bump Label Source
api minor release:api:feat Direct (feat commit)
cipherbox-fuse patch release:cipherbox-fuse:fix Cascade (api minor)
cipherbox-sdk patch release:cipherbox-sdk:fix Cascade (api minor)
desktop minor release:desktop:fix Cascade (api minor)
sdk patch release:sdk:fix Cascade (api minor)
sdk-core patch release:sdk-core:fix Cascade (api minor)
tee-worker patch release:tee-worker:fix Cascade (sdk-core patch)
web minor release:web:feat Direct (feat commit)

Cascade Details

  • api minor -> sdk-core patch (direct dependency)
  • api minor -> sdk patch (direct dependency)
  • api minor -> cipherbox-fuse patch (direct dependency)
  • api minor -> cipherbox-sdk patch (direct dependency)
  • api minor -> desktop patch (direct dependency)
  • sdk-core patch -> tee-worker patch (direct dependency)

github-actions Bot and others added 2 commits June 17, 2026 13:26
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: f7d244dcc682
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.92%. Comparing base (5646b60) to head (dbd65ac).

Files with missing lines Patch % Lines
apps/api/src/shares/shares.controller.ts 60.00% 0 Missing and 2 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #505      +/-   ##
==========================================
+ Coverage   63.90%   63.92%   +0.02%     
==========================================
  Files         141      141              
  Lines       10863    10875      +12     
  Branches     1205     1209       +4     
==========================================
+ Hits         6942     6952      +10     
  Misses       3678     3678              
- Partials      243      245       +2     
Flag Coverage Δ
api 84.71% <83.33%> (-0.01%) ⬇️
api-client 84.71% <83.33%> (-0.01%) ⬇️
core 84.71% <83.33%> (-0.01%) ⬇️
crypto 84.71% <83.33%> (-0.01%) ⬇️
sdk 84.71% <83.33%> (-0.01%) ⬇️
sdk-core 84.71% <83.33%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
apps/api/src/shares/shares.service.ts 93.60% <100.00%> (+0.37%) ⬆️
apps/api/src/shares/shares.controller.ts 61.53% <60.00%> (-0.11%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/services/share.service.ts (1)

199-210: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clear transient plaintext bytes after wrapping the item name.

Line 204 creates plaintext bytes (TextEncoder().encode(share.itemName)) but they are never zeroed after use, leaving sensitive metadata in memory longer than necessary.

Proposed fix
-      const wrapped = await wrapKey(new TextEncoder().encode(share.itemName), recipientPubKey);
-      const itemNameEncrypted = bytesToHex(wrapped);
-
-      // Persist the re-wrapped ciphertext for this legacy row. Only the sharer
-      // may update it; the server stores the ciphertext as-is.
-      await sharesControllerUpdateShareItemName(share.shareId, { itemNameEncrypted });
-      backfilled += 1;
+      const plaintextNameBytes = new TextEncoder().encode(share.itemName);
+      let wrapped: Uint8Array | null = null;
+      try {
+        wrapped = await wrapKey(plaintextNameBytes, recipientPubKey);
+        const itemNameEncrypted = bytesToHex(wrapped);
+
+        // Persist the re-wrapped ciphertext for this legacy row. Only the sharer
+        // may update it; the server stores the ciphertext as-is.
+        await sharesControllerUpdateShareItemName(share.shareId, { itemNameEncrypted });
+        backfilled += 1;
+      } finally {
+        plaintextNameBytes.fill(0);
+        wrapped?.fill(0);
+      }

As per coding guidelines, TypeScript crypto paths must clear sensitive data from memory after use.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/services/share.service.ts` around lines 199 - 210, The plaintext
bytes created by TextEncoder().encode(share.itemName) are not being cleared from
memory after the wrapKey call completes, leaving sensitive metadata exposed.
Store the result of new TextEncoder().encode(share.itemName) in a variable
before passing it to wrapKey, then after the wrapKey call returns and
itemNameEncrypted is set, explicitly zero out the plaintext bytes variable by
calling .fill(0) on it to clear the sensitive data from memory. This ensures the
item name plaintext does not remain in memory longer than necessary.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/web/src/services/share.service.ts`:
- Around line 199-210: The plaintext bytes created by
TextEncoder().encode(share.itemName) are not being cleared from memory after the
wrapKey call completes, leaving sensitive metadata exposed. Store the result of
new TextEncoder().encode(share.itemName) in a variable before passing it to
wrapKey, then after the wrapKey call returns and itemNameEncrypted is set,
explicitly zero out the plaintext bytes variable by calling .fill(0) on it to
clear the sensitive data from memory. This ensures the item name plaintext does
not remain in memory longer than necessary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ab2b2e0a-d434-47b9-ac4e-b78c61531c16

📥 Commits

Reviewing files that changed from the base of the PR and between 5646b60 and 1be1910.

⛔ Files ignored due to path filters (131)
  • packages/api-client/openapi.json is excluded by !packages/api-client/**
  • packages/api-client/src/generated/auth/auth.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/device-approval/device-approval.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/health/health.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/identity/identity.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/invites/invites.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/ipfs/ipfs.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/ipns/ipns.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/root/root.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/share-invites/share-invites.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/shares/shares.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/tee/tee.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/generated/vault/vault.ts is excluded by !**/generated/**, !**/generated/**, !packages/api-client/**
  • packages/api-client/src/models/addShareKeysDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/authMethodResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/authMethodResponseDtoType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/batchPublishIpnsDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/batchPublishIpnsResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/batchUnenrollIpnsDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/batchUnenrollIpnsResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/childKeyDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/childKeyDtoKeyType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/claimChildKeyDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/claimChildKeyDtoKeyType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/claimInviteDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/claimInviteResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/connectionTestRequestDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/connectionTestResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/connectionTestResponseDtoProtocol.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createApprovalDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createInviteDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createInviteDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createShareDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createShareDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createShareDtoPermission.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createShareResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createShareResponseDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/createShareResponseDtoPermission.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/deleteAccountDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/deleteAccountResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/desktopRefreshDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/deviceApprovalControllerCreateRequest201.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/deviceApprovalControllerGetPending200Item.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/deviceApprovalControllerGetStatus200.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/deviceApprovalControllerGetStatus200Status.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/googleLoginDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/googleLoginDtoIntent.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/healthControllerCheck200.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/healthControllerCheck200Details.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/healthControllerCheck200DetailsDatabase.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/healthControllerCheck200Error.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/healthControllerCheck200Info.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/healthControllerCheck200InfoDatabase.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/identityControllerGetJwks200.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/identityControllerGetJwks200KeysItem.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/identityControllerGetWalletNonce200.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/identityTokenResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/index.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/initVaultDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteChildKeyDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteChildKeyDtoKeyType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteDataResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteDataResponseDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteDataResponseDtoStatus.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteResponseDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteResponseDtoStatus.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteStatusResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/inviteStatusResponseDtoStatus.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/ipfsControllerUploadBody.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/ipnsControllerResolveRecordParams.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/linkMethodDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/linkMethodDtoLoginType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/loginDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/loginDtoLoginType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/loginResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/logoutResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/lookupUserResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/paginatedReceivedSharesDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/paginatedSentSharesDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/pendingRotationResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/pendingRotationResponseDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/publishIpnsDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/publishIpnsEntryDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/publishIpnsEntryDtoRecordType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/publishIpnsResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/quotaResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/receivedShareResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/receivedShareResponseDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/receivedShareResponseDtoPermission.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/registerCidDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/registerCidResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/resolveIpnsResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/respondApprovalDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/respondApprovalDtoAction.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sendOtpDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sendOtpResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sentShareResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sentShareResponseDtoItemType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sentShareResponseDtoPermission.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/setByoStatusDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/setByoStatusResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/shareInvitesControllerListInvitesParams.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/shareKeyEntryDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/shareKeyEntryDtoKeyType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/shareKeyResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/shareKeyResponseDtoKeyType.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sharesControllerGetReceivedSharesParams.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sharesControllerGetSentSharesParams.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/sharesControllerLookupUserParams.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/teeKeysDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/testLoginDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/testLoginResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/tokenResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/unlinkMethodDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/unlinkMethodResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/unpinDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/unpinResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/updateEncryptedKeyDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/updateItemNameDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/updatePermissionDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/updatePermissionDtoPermission.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/uploadResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/vaultConfigResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/vaultExportDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/vaultResponseDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/vaultResponseDtoTeeKeys.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/verifyOtpDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/verifyOtpDtoIntent.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/walletVerifyDto.ts is excluded by !packages/api-client/**
  • packages/api-client/src/models/walletVerifyDtoIntent.ts is excluded by !packages/api-client/**
📒 Files selected for processing (15)
  • .planning/STATE.md
  • .planning/phases/47-sdk-folder-state-publish-consolidation/47-01-SUMMARY.md
  • .planning/phases/47-sdk-folder-state-publish-consolidation/47-02-SUMMARY.md
  • .planning/phases/47-sdk-folder-state-publish-consolidation/47-03-SUMMARY.md
  • .planning/phases/47-sdk-folder-state-publish-consolidation/47-04-SUMMARY.md
  • .planning/phases/47-sdk-folder-state-publish-consolidation/47-05-SUMMARY.md
  • .planning/phases/48-sdk-self-bootstrap-regression-fix-and-shared-folder-metadata/48-VERIFICATION.md
  • apps/api/src/shares/dto/index.ts
  • apps/api/src/shares/dto/update-item-name.dto.ts
  • apps/api/src/shares/shares.controller.spec.ts
  • apps/api/src/shares/shares.controller.ts
  • apps/api/src/shares/shares.service.spec.ts
  • apps/api/src/shares/shares.service.ts
  • apps/web/src/services/share.service.ts
  • release-please-config.json

FSM1 and others added 2 commits June 17, 2026 16:15
Two-party spec for Phase 48 REQ-4: seed a legacy share (plaintext itemName,
NULL itemNameEncrypted) via POST /shares with the field omitted, trigger the
owner-side backfill by uploading a file, then assert the ciphertext is persisted
at rest (null -> valid hex != plaintext, longer than plaintext), the recipient
still sees the correct name, and the backfill is idempotent. All 7 steps pass
against the local full stack.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: ffdbce177943
Address CodeRabbit review on PR #505: backfillSentShareItemNames encoded the
plaintext display name into a Uint8Array that was never zeroed. Wrap the
wrap+persist in try/finally and fill(0) the plaintext bytes (and the ciphertext
buffer) after use, per the project crypto rule to clear sensitive data from
memory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: c68bbeb847dd
@FSM1

FSM1 commented Jun 17, 2026

Copy link
Copy Markdown
Owner Author

Addressed the CodeRabbit review finding in dbd65ac59:

  • apps/web/src/services/share.service.ts (backfillSentShareItemNames) — the transient plaintext itemName bytes from TextEncoder().encode() were not zeroed after wrapping. Wrapped the wrap+persist in try/finally and fill(0) the plaintext buffer (and the ciphertext buffer) after use, per the project rule to clear sensitive data from memory.

Verified: tsc --noEmit clean, eslint clean, web share suites 48/48 pass. Behavior-preserving, so the new e2e (share-itemname-backfill.spec.ts) is unaffected.

This was CodeRabbit's only actionable item (the rest of the review was file-list/info); it was an 'outside diff range' comment with no resolvable inline thread.

@FSM1 FSM1 merged commit 63638b5 into main Jun 17, 2026
28 checks passed
@FSM1 FSM1 deleted the feat/share-itemname-lazy-backfill branch June 17, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:api:feat Minor version bump (new feature) for api release:cipherbox-fuse:fix Patch version bump (bug fix) for cipherbox-fuse release:cipherbox-sdk:fix Patch version bump (bug fix) for cipherbox-sdk release:desktop:fix Patch version bump (bug fix) for desktop release:sdk:fix Patch version bump (bug fix) for sdk release:sdk-core:fix Patch version bump (bug fix) for sdk-core release:tee-worker:fix Patch version bump (bug fix) for tee-worker release:web:feat Minor version bump (new feature) for web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant