Skip to content

feat(assets): cold-device asset metadata reconstruction (Asset-B5)#97

Merged
th3-br41n merged 1 commit into
mainfrom
feat/asset-b5-restore
Jul 3, 2026
Merged

feat(assets): cold-device asset metadata reconstruction (Asset-B5)#97
th3-br41n merged 1 commit into
mainfrom
feat/asset-b5-restore

Conversation

@th3-br41n

Copy link
Copy Markdown
Contributor

Asset-B5 — restore integration. Stacked on #93.

After a cold restore (10.14) the Y.Docs come back but every asset was invisible: no assets row → the FK forbids the asset_refs row → serve-on-miss can't find an owning entity → permanent 404. This closes that gap per data/70's lazy-fetch design — metadata reconstructs eagerly, bytes stay lazy.

How

  1. Manifest kind (advisory, validated; absent/unknown → upload; pre-B5 manifests parse unchanged) so the reconstructed row + ref role are faithful.
  2. AssetStore.registerSynced — mints assets + asset_deks rows from the manifest + the B1 entity-wrap-recovered DEK, re-sealed under this vault's master key. content_hash starts as the empty sentinel: it's a local-only plaintext hash a cold device cannot know; transport integrity is the chunk AEAD under the recovered DEK.
  3. restoreBlob backfill — first materialise length-checks against the row and backfills the hash (write-once via SQL guard); every later restore verifies as before.
  4. listAssetManifests ydoc-worker op + reconstructAssetMetadata orchestration (per-pair fail-safe, tallied) wired into runRestore after backfill, before reindex. Contained — can never fail a restore.

Security notes

  • A hostile manifest can only produce bytes that open under the DEK recovered from the entity's own wrap — same trust as entity content. Unknown kind degrades, never rejects; id-mismatched manifests are skipped.
  • No wrap recoverable (unshared entity) → row is NOT minted, ref is NOT bound (test-pinned).

Tests

+25: parser kind cases · registerSynced/idempotence · sentinel backfill + write-once + length refusal · reconstruction unit tally paths · worker list op · end-to-end cold restore with real crypto (owner upload → cold reconstruct → lazy materialise → hash backfill → local round-trip). 993 green across the touched suites; tsc clean.

🤖 Generated with Claude Code

Base automatically changed from feat/asset-b4-lifecycle to main July 3, 2026 22:17
Restore integration: after the 10.14 Y.Doc backfill, reconstruct the local
assets + asset_deks + asset_refs rows from each restored entity's synced
chunk manifests, so serve-on-miss can lazily materialise bytes on access
(the true cold-first-fetch case B4 deferred — no assets row meant the FK
forbade the ref and the serve path couldn't find an owner).

- manifest carries a validated advisory `kind` (absent/unknown → upload;
  pre-B5 manifests parse unchanged)
- AssetStore.registerSynced: rows from manifest + entity-wrap-recovered DEK
  (sealed under THIS vault's master key), content_hash sentinel, marked bound
- restoreBlob backfills the sentinel hash on first materialise (length-
  checked; SQL guard makes the backfill write-once) — integrity anchor for a
  synced asset is the chunk AEAD under the recovered DEK
- ydoc worker: listAssetManifests (all pairs on an entity doc)
- reconstructAssetMetadata orchestration (per-pair fail-safe tally), wired
  into runRestore before the search reindex, contained

Tests: +25 (parser kind, registerSynced/backfill, reconstruction unit,
worker list op, cold-restore end-to-end with real crypto). 993 green across
assets/entities/sync/workers/storage; tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@th3-br41n th3-br41n force-pushed the feat/asset-b5-restore branch from 64b0704 to d87ccaf Compare July 3, 2026 22:19
@th3-br41n th3-br41n merged commit 89496a1 into main Jul 3, 2026
3 checks passed
@th3-br41n th3-br41n deleted the feat/asset-b5-restore branch July 3, 2026 22:20
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