improvement(files): cache stream binding meta, tighten file cache-control, prune dead persist path (#6149)

* improvement(files): cache stream binding meta, tighten file cache-control, prune dead persist path

- Cache the agent-stream ProseMirror↔Yjs binding metadata per session and reuse it
  across streamed frames instead of rebuilding it (O(doc)) every frame; matches how
  y-tiptap's own binding maintains the mapping in place. Safe because the shadow doc
  only ever sees the agent's own reconciles.
- Default createFileResponse to a private, no-cache policy so auth-gated bytes are never
  stored in a shared cache; genuinely-public serve routes opt into public caching
  explicitly.
- Serve content-addressed (key=) embedded images with an immutable private cache to
  avoid re-downloading them on every doc re-open; fileId= embeds and public shares keep
  revalidating (the underlying key can change / a share can be revoked).
- Drop the dead conflict.version field from the collab-doc persist result and remove the
  wasted getWorkspaceFile re-read on the conflict path (the relay treats missing and
  conflict identically and never read version).
- Decorate-sort the files/folders lists (compute each sort key once) and index the
  move-menu subtree build (O(N) vs O(N^2)); ordering is preserved exactly.

* fix(files): serve inline images with no-cache so deletion/authorization is enforced per request

Embedded images are authenticated content whose backing file can be deleted or have its
access revoked at any time. Both key= and fileId= embeds serve
private, no-cache, must-revalidate, so every request re-runs the server-side
deletion/authorization check instead of serving a possibly-stale image from cache.
This commit is contained in:
Waleed
2026-07-31 20:09:45 -07:00
committed by GitHub
parent 10bfb5d139
commit 06506bbd38
13 changed files with 166 additions and 85 deletions
+3 -3
View File
@@ -77,13 +77,13 @@ export async function fetchFileDocMerge(
* Result of a persist attempt (mirrors the app's `persistFileDoc` contract):
* - `persisted` — written; `version` is the new durable version the relay records as synced.
* - `missing` — the file is gone.
* - `conflict` — the file changed out-of-band since `expectedVersion`; NOT written. `version` is the
* current durable version the relay adopts as its new If-Match to re-persist the current live stream.
* - `conflict` — the file changed out-of-band since `expectedVersion`; NOT written. The relay leaves the
* durable content authoritative and reads nothing off this result beyond the status.
*/
export type PersistResult =
| { status: 'persisted'; version: number }
| { status: 'missing' }
| { status: 'conflict'; version: number }
| { status: 'conflict' }
| { status: 'deferred' }
/**
@@ -338,7 +338,6 @@ describe('setupWorkspaceFileDocHandlers', () => {
// authoritative; a later flush projects the converged stream once the merge lands.
mockFetchFileDocPersist.mockResolvedValue({
status: 'conflict',
version: 999,
})
const { io } = createIo()
const { handlers } = setup('socket-1', io)