From 5d3d94414bf7dfcc83ca765822b436167914fdae Mon Sep 17 00:00:00 2001 From: bigbes Date: Wed, 22 Jul 2026 14:04:53 +0300 Subject: [PATCH] docs: pin URL grammar, document addressing, and the attachment gap The read plane specified both that /~user/space/path.md renders and that .md returns raw source, which cannot both hold for one URL. Extensions are format selectors, so a document's own address carries none. Adds the addressing rule for documents whose id is absent or duplicated, which skip-validation makes reachable on the approved branch. A duplicated id resolves to neither document: picking one silently would aim links and search results at a document nobody chose, with no visible sign. Records that cross-space id resolution cannot live in the read layer, since an archive is one space at one revision; the global hop needs the registry and therefore belongs in service/. Promotes attachments from a hypothetical to a measured gap: the git layer walks and accepts .md only, so embeds have nothing to resolve against. --- docs/DESIGN.md | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index 21039d0250446f81887d0f258057385c290d75f3..127b3d3052f3cd9f790a89604a101a6cdc5b2f21 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -161,6 +161,23 @@ tags: [storage, review] resolve by ID, comment anchors reference IDs, and bots pin to IDs. The service enforces **global** ID uniqueness via a registry table. +**Addressing when `id:` is absent or duplicated.** Because +`--push-option=skip-validation` exists, both states are reachable on the approved +branch, and the read plane still has to name such a document. The rule, mirroring +what the merge already does: + +- valid and unique in its space → the document is addressed by its ID; +- absent or malformed → addressed by its path minus the extension; +- **duplicated → the ID resolves to neither document.** Refusing to guess is the + only safe option: silently picking one would make links and search results + point at a document the author did not mean, and the ambiguity is invisible. + +**Cross-space ID resolution belongs to `service/`, not the read layer.** A +rendered archive is one space at one revision, so `[[SPEC-0007]]` can only be +resolved space-locally there. The global hop needs the `document_id` registry, +which means the link resolver is layered: `doc/` resolves within the space and +reports misses; `service/` resolves the misses against the registry. + **"Approved" is a property of the branch, not of the frontmatter.** A document reachable from the approved ref is approved; that is the whole definition. Had `approved` stayed in the `status` enum, either the approved branch would @@ -326,8 +343,14 @@ a volume question, not an architectural one (see the reuse inventory). ### 1. Read plane (anonymous-capable, cached) -`GET /~user/space/path.md` renders. Content negotiation gives `.md` raw, -`.json` metadata+body, `?rev=` pinned to an immutable revision. +`GET /~user/space/specs/0007-storage` renders. Content negotiation gives +`.md` raw, `.json` metadata+body, `?rev=` pinned to an immutable revision. + +**URL grammar, pinned.** An earlier draft wrote both "`GET /~user/space/path.md` +renders" and "`.md` gives raw" — which cannot both be true of one URL. The +extension is a *format selector*, so the document's own address carries **no** +extension: `/~user/space/specs/0007-storage` renders, `+ .md` is raw source, +`+ .json` is metadata plus body. **Reads default to the approved revision**, with a visible "draft is 3 changes ahead" affordance. This is the plane bots consume; it must be boring and @@ -1143,10 +1166,14 @@ degrading, which is the point of listing them. mangles whichever language it was not chosen for. Options: detect language at index time and write to `ru`/`en` fields, querying both; or accept degraded stemming on the minority language. -- **Attachments and binaries.** Diagrams and images in specs mean binary blobs in - git: no useful diff, unbounded repo growth, and a size-cap decision. Mermaid in - fenced blocks stays text and diffs properly — possibly worth *preferring* by - convention over checked-in images. +- **Attachments and binaries — now a concrete gap, not a hypothetical.** The + Space section says a space holds "markdown documents, plus attachments", but + the git layer enumerates and accepts **`.md` only**, so `![[diagram.png]]` has + nothing to resolve against and renders as visibly missing. Closing it needs a + `WalkBlobs`-shaped addition to `gitx` plus an asset index in `doc/`. Deliberately + not faked: an invented href would be worse than an honest missing link. The + cheaper answer may be to **prefer Mermaid in fenced blocks by convention** — + it stays text, diffs properly, and needs none of the above. - **Agent token distribution.** How a Claude Code session actually acquires a scoped token — long-lived value in the environment, or minted per session. Per-session is better for provenance and revocation but needs an issuing flow.