Deduplicate stored upload files and retain adoption bytes until their Root is durable

This commit is contained in:
2026-11-09 16:31:31 +08:00
parent a626e6c300
commit 902e30a65b
10 changed files with 167 additions and 18 deletions
+39
View File
@@ -209,3 +209,42 @@ NodeNext type check excludes DOM libraries. A separate peer consumer renders a
registered component, verifies its command context, and checks typed NodeProps and
EdgeProps with the declared peers. Browser tests still execute the compiled ESM
storage and Worker artifacts independently of Next.js/TypeScript stripping.
Workspace asset depot and file storage:
`createWorkspaceRuntime` owns one depot when `StoragePort.assetDepot` is provided.
`await engine.adoptResource(id, (resource, tx) => { ... }, {signal})` obtains fresh
server permission, verifies the original bytes, and runs a synchronous editor
transaction. The callback uses the existing `resource.id` / canonical `resource.src`
in a newly allocated element; it also receives server dimensions in `resource.asset`.
The project stores a `SharedAssetBinding`, not a second upload. Binding, document,
history, ledger, shared bytes and pins cross the same durable barrier. The returned
local `Result` does not imply durability or backend completion. Async or failed
callbacks leave no partial binding. The Foundry authority requires the matching
permission-checked asset metadata endpoint; cached metadata is not an authorization.
Bindings use recovery envelope 13 (including partial loading v6); readers retain
formats 1–12 and reject unknown future formats. A reopened binding can display
shared local bytes, and undo/redo reuse the asset without uploading again. The
workspace closes projects before its depot; retiring the identity fences late work.
The browser adapter uses IndexedDB version 4. After a proven stored-upload cut, a
project's `files` row holds an opaque pointer to digest-addressed `asset-bytes`.
Unconfirmed uploads and import source files keep their original Blob rows. Use
`readFile` / `scanFiles`; direct assumptions that every raw files-store row is a
Blob are invalid. Logical reads preserve the original local MIME, even if the
server detected another MIME. Existing v3 databases upgrade without dropping
checkpoints or original files and promote on a subsequent matching Root commit
(or an idempotent reindex). Older DB readers reject v4. Blob URLs and already
returned Blob objects live independently of a later persistent eviction; actual
disk reclamation remains the browser's responsibility.
Resource identities retain immutable metadata after byte eviction. Complete,
revision-matched durable manifests from every project in the workspace protect
closed editors; missing/stale/opaque coverage prevents shared deletion. Distinct
resource IDs may own the same digest; the shared byte row disappears only when
its last live identity is retired. An older Root cannot release temporary bytes
that belong to a newer adoption revision. Collection is explicit and local; this
preview does not enable background deletion on Foundry or claim the full retention,
permission-race and product acceptance matrix is finished.