soul.demarkus.io:6309/adr/0004-edge-semantics-rel-convention.md
soul.demarkus.io:6309/debt/architecture-quality-3a-3b.md draft reader meta

Architecture quality tracks 3a and 3b

Part of Code Debt & Improvements; every section below moved here verbatim.

Resolved 2026-09-20 on chore/architecture-quality (PR 489)

Closed by the architecture quality plan; details in its Status section.

  • findVersions and VerifyChain bypass resolve(): both now go through Store.containDoc, along with CurrentVersionResult, VersionFilePath, ImportDoc, exportArchived and write (P2, P3, P4, P21).
  • Self conflict on mark_publish: the client no longer resends a write after its request was sent, and merge.Candidate treats a head equal to the submitted body at expected plus one as success (C3, C4). mark_append and archive surface ErrOutcomeUnknown and do not reconcile yet.
  • Behavioral tests missing for two of three gate sites: one gateIdentity now serves all sign in paths, with a device callback denial test and a unit table (B2, B9).
  • Refresh path does not re-gate on hd: it now does, against stored claims, and answers invalid_grant (B3). A user removed at the IdP still holds a valid refresh token until TTL; that needs a design decision.

Still open from the same ledger: Claims mutation surface (B8), rel diagnostics (C25), the kind smoke gate.

Resolved 2026-09-20, second pass on chore/architecture-quality (PR 489)

Details in the architecture quality plan Status section.

  • Claims mutation surface: gateWrite and meInstall canonicalize a copy; a race test pins it (B8).
  • Rejected rel- metadata skipped without a diagnostic: graph.RelEdges returns the rejected values with reasons, the crawl summary counts them, the federation crawler logs them, and ADR 0004 now says "skipped with a diagnostic" (C25).
  • parseVersionPath and version shaped directories: /api/v2 under a directory /api now resolves as a path (S8). The filepath.Split portability note above still stands, though native Windows is out of scope.

New debt from the same pass:

  • graphstore.ObserveDocument drops RejectedRels; explore has no place to show them yet.
  • The promoted knowledge copy of ADR 0004 is behind docs/adr/0004; promote when ready.
  • store.ImportDoc and the flat layout migration write versions without fsync, unlike write (P12 remainder).
  • The read view is still held while the response is written; the new write deadline bounds it (S1 remainder, with S27).
  • World manager still opens worlds under its lock and closes runtimes without a deadline (S16 remainder).

Still open from the earlier ledger: the kind smoke AllowDomains stage.

Resolved 2026-09-20, third pass on chore/architecture-quality (PR 489)

  • handleVersions accesses versions[0] without length guard: closed. VERSIONS renders through render.VersionsResponse, which reports current: 0 for an empty history.
  • Hand written wire fixtures in consumer tests (B4, B5, B29, C34): closed. LIST, LOOKUP and VERSIONS fakes come from protocol/render, the per verb goldens in protocol/wiretest are emitted by storetest and matched by both backends, and the MCP and broker suites share client/fetchtest.

New debt from the same pass:

  • The lint ratchet exempts client/fetchtest/ from the revive argument limit, because the fake mirrors fetch client signatures with six and seven positional arguments. Remove the exemption when 3c gives fetch request structs (C20, B23).
  • Rejection conformance (quota, policy) runs on the bucket backend only; the file backend enforces neither until policy moves to a decorator above the store (S15, 3b). No conformance case for a request timeout until the backend contract takes a context (S11).

Resolved 2026-09-21, track 3a on chore/architecture-quality (PR 489)

Details in the architecture quality plan Status section and ADR 0014.

  • Store.Write returns shared metadata map reference: closed earlier by reading metadata back from stored bytes; the nil versus empty rule is now stated on storefmt.Document.Metadata and ApplyOKFTypeDefault always copies (P22).
  • findVersions and VerifyChain path derivation: one Store.locate helper (P17).

New debt from the same pass:

  • Tests of pure stored format functions still sit in protocol/store/store_test.go; move them to protocol/storefmt with the P13 split.
  • tools/internal/token writes the tokens file and server/internal/auth reads it, with no producer and consumer fixture between them.
  • storefmt.SetArchived is exported only for fixtures in two modules.

Resolved 2026-09-21, track 3b start on chore/architecture-quality (PR 489)

Details in ADR 0015.

  • No conformance case for a request timeout: closed. The contract takes a context and CanceledContext runs on both backends (S11).
  • Dead Catalog.Put and Remove: removed from the contract, both backends and the handler (S10).

New debt from the same pass:

  • bucketstore's internal per operation readView still stores a context; the contract view does not.
  • bucketstore tests keep the old one shot method names as helpers in oneshot_test.go; port them to backendtest.Direct when read_test.go is split (S33).

Resolved 2026-09-21, track 3b continued (PR 489)

  • Handler Logger nil fallback: closed. Constructors refuse a nil logger; the knowledge server was opening bucketstores without one.
  • Read auth split between handler and auth package: closed, TokenStore.AuthorizeRead (S14).
  • LIST loads the whole directory per page: closed, windowed ListEntries (S17).

Resolved 2026-09-21, S15 (PR 489)

  • Enforcement is a phase flag inside Open: closed. Policy is a decorator above the store (ADR 0016); bucketstore has no requirePolicy.
  • Rejection conformance runs on the bucket backend only: closed for policy; the file backend has no quota.

Open: the file server does not wrap its store with writepolicy.Enforce. Whether a file world that holds a policy document should enforce it is a product decision.

Resolved 2026-09-21, track 3b finish on chore/aq-3b-finish

Recorded in ADR 0017; detail in the plan's Status section.

  • "ReadOnly is enforced at the request layer only": closed. bucketstore.Options.ReadOnly refuses every mutation with backend.ErrReadOnly; the seeding exception in worlds.go is gone. The genesis skip stays in the server because genesis happens before a Store exists.

  • "Handler Logger nil fallback": fully closed. handler.New(Config) refuses a nil logger or store, so a bare literal can no longer panic at the first log line.

  • "The per-world Bootstrap flag is now one and a half ideas": still open. Genesis no longer depends on it, so it means only "no seed, policy not required". Retiring it collides with the broker's create only memory policy seed and the strictly parsed worlds fragment; waiting on a decision.

  • Update, same day: "The per-world Bootstrap flag is now one and a half ideas" is closed in behavior. The flag no longer changes the open; it remains a deprecated key for one release. New entry: two writers for a provisioned world's policy (server seed at version one, broker's at version two, told apart by publishpolicy.SeedAgent). A single writer, with the broker passing the policy body through the worlds fragment, would be simpler but needs a config field and chart changes.

trail
  1. soul.demarkus.io:6309 graph: 0004-edge-semantics-rel-convention
  2. architecture-quality-3a-3b