From a7d266debb3a18a7f12fdb170b56c15e005a18a1 Mon Sep 17 00:00:00 2001 From: Edouard Vanbelle Date: Sun, 30 Aug 2026 22:43:41 +0200 Subject: [PATCH] docs(plan): sketch the satellite-table diagram in step 12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The security boundary is a shape before it is a rule: DERIVED hangs off content, ATTACHED hangs off the file, and two arrows starting from different places carries the argument faster than the paragraph explaining it. Sketched inline rather than left as "add a diagram", so whoever writes the page inherits the structure — including the parts a diagram is uniquely good at showing: that both tables point into the same artifact space (hence why one cannot be folded into the other with a kind column), and that DERIVED.blob_hash is optional where ATTACHED.blob_hash is not. Co-Authored-By: Claude Opus 5 (1M context) --- docs/plan/derived-blobs.md | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/plan/derived-blobs.md b/docs/plan/derived-blobs.md index 3b9e63e3..62e7647d 100644 --- a/docs/plan/derived-blobs.md +++ b/docs/plan/derived-blobs.md @@ -1621,6 +1621,48 @@ hardcoded SQL). New sources bolt on independently. `data_loss`). Anything joining on `blob_hash` must decide which of the two it wants. + * **A diagram**, because the security boundary is a shape before it + is a rule — two arrows starting from different places is the + whole argument, and it lands faster than any paragraph: + + ```mermaid + erDiagram + FILES ||--o{ ATTACHED : "file_id — per FILE" + FILES }o--|| BLOBS : "blob_hash (content)" + BLOBS ||--o{ DERIVED : "source_hash — per CONTENT" + DERIVED }o--o| ARTIFACT : "blob_hash (NULL = negative)" + ATTACHED }o--|| ARTIFACT : "blob_hash" + + FILES { + uuid id + text blob_hash + } + DERIVED { + text source_hash PK + text kind PK + text variant PK + text blob_hash "NULL = not worth deriving" + text content_type "NULL iff blob_hash NULL" + } + ATTACHED { + uuid file_id PK + text kind PK + text variant PK + text blob_hash + uuid uploaded_by "no FK; nil = imported" + } + ARTIFACT { + text hash PK + } + ``` + + What a reader should take from it: `DERIVED` hangs off **content**, + so two files with identical bytes reach the same row — good for a + render, catastrophic for an upload. `ATTACHED` hangs off the + **file**, so those rows are duplicated on copy and never shared. + Both point at the same artifact space, which is why one table + could not simply be folded into the other with a `kind` column. + Home: `docs/architecture/`, alongside `backend-storage.md`, which already documents the blob layer these sit on top of. Operator- facing rather than end-user, so schema and SQL are appropriate