Files
alkblobs/docs/architecture/open-questions.md
T
glm-5.3-flash abf8c5ae9c docs(architecture): ADR-010/011 — I/O seams, GC-state home, vocabulary; pre-decomposition consistency round
ADR-010 (new): the Backend trait's I/O seams pinned before any code —
'get' returns a crate-internal read cursor (kv engines materialize;
'local' pread loop; pg-lo lo_get windows), 'put' has two named forms
(whole-value kv / staged-put large); GC state is store-core-owned via
a crate-internal contract-tested engine-state seam on the SQL-backed
engines (backends never learn liveness — ADR-005 verbatim); the store
core holds the joint entry+pin transaction (corrects ADR-009 §2's
ownership statement); kv-tier fleet-validity rule added (mirror of
ADR-008 §3); ops pin-token TTL race resolved (the token IS the pin;
renewal rides have/re-put; pause-past-TTL falls to delete-then-recover);
feature graph pinned (pg-lo does not imply postgres).

ADR-011 (new): vocabulary pinned — tier (contract, exactly two) vs
engine (concrete impl, exactly five); store instance / node / fleet
split (fleet = pool-sharing, not node count — fixes requirements.md's
self-contradiction with REQ-2); mem demoted from 'backend'/'testing
tier' to the kv tier's third engine (contract-reference engine);
fs tier renamed 'large' including the feature name (last free moment
before code exists); constructor modes pinned (dual-tier default,
kv-only, mem-only) plus the composite fleet-validity predicate.

Consistency round across all specs and ADR-003/004/007/008/009: stale
pg-lo passages resolved per ADR-009's supersession; ADR-008 owner
'node id' → store-instance id; threshold wording corrected (conservative
edge, not midpoint, of the 128-256 KiB crossover zone); SweepReport
shape specced; mem classification unified; 008/009 ADR files renamed to
match the tier rename; README deferral-policy recap aligned (third
category = decided-but-sequenced work, not a parking kind); POC crate
list completed.

Verification: two independent architecture review rounds (the first
found 4 criticals — unpinned trait I/O shapes, missing fleet-state
seam, node/fleet self-contradiction, pin-token/TTL conflict — all
resolved; final round: zero criticals); all markdown links resolve;
ADR tables complete (11 ADRs).
2026-10-03 05:55:20 +00:00

13 KiB

status, last_updated
status last_updated
draft 2026-10-03

Open Questions

Centralized tracker. Theme sections hold OQs; cross-theme status lives in the Deferred/Blocked index below.

Deferral policy (the Schrödinger's-code rule). A decision this crate needs before shipping may not be deferred on a dependency that is itself waiting for this crate to exist. alkgit is paused mid-Phase-1 to build this core; alkfs is pending that shared base. "Deciding input: what alkgit wires first" never collapses into an input, so it is not one. Two kinds of parked question remain legitimate:

  • deferred(scope) — the deciding fact exists independently of this crate (e.g., alkfs Phase 0 outcomes); the crate proceeds on its own ADRs meanwhile.
  • externally-owned questions — questions about how a consumer maps onto this crate, which are not decisions this crate needs before shipping and are not this document's to decide; they are carried here for visibility, owned by the consumer's own process, and collapse when that consumer acts (including on an API of this crate that will exist by then — that is acceptable only because the question gates no decision here; it would be Schrödinger's code if it gated one).

Invalid for either kind: a blocker that is a decision this crate must make before shipping. (A third category — decided-but-sequenced work — is not a parked kind at all; see below.) Phase 0's residual list was swept under this rule: every residual either resolved into an ADR (the evidence was already in hand) or re-owned as below.

The line between the two kinds (added 2026-10-03, after the pg-lo round): deferring on a consumer's design decision is valid — the deciding fact is obtainable independently of this crate (OQ-07, OQ-08). Deferring on a consumer's deployment of this crate is invalid — that fact is created by this crate (OQ-10's original framing, OQ-09's original framing). And a third thing is neither: decided-but-sequenced work. Once a question resolves to a decision (the pg-lo engine is the named large-tier candidate under REQ-2/ADR-008), what remains is the evidence pipeline the decision's own admission gate requires (POC #7) — a task with an owner, not a parked question, and not a hedge. A decision is not "unmade" because its verification is pending; deferral policy applies to decisions, not to work.

Index of active OQs: OQ-07, OQ-08 (externally-owned, carried for visibility). OQ-09 and OQ-10 are resolved (recorded below). Promoted Phase 0 questions OQ-BL-01..06 are recorded here with their resolutions for traceability.


Theme: consumer integration

OQ-07: How alkgit's object-storage seam consumes alkblobs

  • Origin: overview.md, gc-and-namespaces.md
  • Status: externally-owned (alkgit) — carried here for visibility; not a decision this crate must make before shipping
  • Priority: high (it is why this crate exists) — but not a blocker: alkblobs builds by its own ADRs; this question maps the consumer on.
  • Owner: alkgit (external)
  • Question: how do alkgit's reviewed GitRefs/GitPackGen/GitPackIngest traits (its backend.md, ADR-018) sit over alkblobs — gix-odb-over-pool, alkblobs-behind-those-traits, or a mixed composition (e.g. refs in the pool, pack generation still gix)? Which tier serves the loose tier; does packfile serving (ADR-005) get wanted at all?
  • Resolution: owned by alkgit's architecture process; it is answerable on paper against this document tree (backend.md + these ADRs) whenever alkgit's process acts, and gates nothing here. This crate's obligations toward it are already fixed: git-oid addressing (ADR-002), liveness seam (ADR-005), serving surface (ADR-006/store-api).
  • Cross-references: OQ-08, ADR-002, ADR-005, ADR-006

OQ-08: alkfs requirement intake

  • Origin: overview.md, backends-and-dispatch.md
  • Status: externally-owned (alkfs) — carried here for visibility; alkfs Phase 0 has not run
  • Priority: medium (alkfs Phase 0 pending; nothing here blocks on it)
  • Owner: alkfs (external)
  • Question: what does alkfs's Phase 0 name as requirements on the shared base — durability tiers, sync/replication seams the store does not expose, manifest-layer shapes beyond ADR-004's boundary (e.g. the appfile write-session shape as a consumer concern)?
  • Resolution: owned by alkfs's Phase 0 (independently obtainable — it needs no alkblobs artifact). The store's posture toward an unknown consumer is deliberately permissive: open trait + addresses + liveness seams (ADR-003/004/005) without baking an alkfs shape in.
  • Cross-references: OQ-07, ADR-004

OQ-10: Postgres as the second shipped kv engine

  • Origin: docs/research/poc-postgres-kv-findings.md, poc-redb-kv-findings.md, backends-and-dispatch.md
  • Status: resolved — by ADR-007 (2026-10-02)
  • Resolution: the kv tier ships two engines — sqlite (default) and postgres (feature postgres, default-off) — behind one Backend trait; engine selection is a per-node constructor parameter (ADR-007). The evidence base was already complete (POC #3 A4's sqlite solo curves; POC #5 B1-B6's pg concurrency scale-out and posture deltas; POC #6 C1-C6 ruling out redb at a durability-tier mismatch) — all deciding facts were in hand, and the only thing the prior framing left outstanding was this crate's own build sequence, which is implementation sequencing, not an open architecture question.
  • Why this is not Schrödinger's code (recorded because the question was once framed as an externally-owned standing offer): the proposed trigger — "a replicator-shaped deployment materializes" — is a fact only this crate could create (a deployment running alkblobs capable of pg cannot pre-exist the pg engine), so gating on it was circular hedging, the exact corollary the README names and the precedent OQ-09 resolved on. The topology-not-throughput decision rule and the measured curves stand on evidence in hand; the deployment is where the costs named by the ADR (POC-derived posture defaults) get verified — a deferred cost in the ADR-006 pattern, not a gating input.
  • Reopen condition (not a parked question): a third engine is the ADR-003/007 substitution door — a new ADR with its own measured evidence and sweep-safety proof. "Some future deployment might want it" does not open it.
  • Cross-references: OQ-07, ADR-003, ADR-004, ADR-007, POC #3, POC #5, POC #6

Theme: ops surface

OQ-09: Default visibility of namespaces in network ops

  • Origin: ops-surface.md
  • Status: resolved
  • Resolution: closed-by-default (deny-unlisted namespaces: no ACL entry ⇒ no read, no write). The deciding fact for this is not a future deployment (one that can only exist once the ops module ships is not a deciding input — Schrödinger's-code rule); it is the risk asymmetry on evidence in hand: an open-by-default store accidentally exposes content and the exposure is discovered only after the fact, while a closed-by-default store's failure mode — a legit access attempt denied until a grant exists — is loud, cheap, and recoverable at grant time. A conservative default is chosen by reasoning from the failure modes, not measured against a deployment. This is a made decision with a deferred cost (an embedder wanting public read pays one explicit grant), not an unmade decision.
  • Reopen condition (not a parked question): a concrete use case names why a namespace needs open read as a default — that is a new requirement naming a new decision (the same shape ADR-006 gives the chunk-tree question: deferred cost, re-entry at a new ADR if ever named). "Some future embedder might exist" does not open it.
  • Cross-references: ADR-001, ops-surface.md

Theme: promoted Phase 0 register (resolutions recorded)

OQ-BL-01: Crate scope — store-only, or store + ops surface?

  • Origin: docs/research/phase-0.md
  • Status: resolved
  • Resolution: store-only core; ops surface exists as a feature-gated alkcall-backed module (placement decided, not hedged — Schrödinger's-code rule applied: no waiting on paused consumers). Full rationale: ADR-001 (family-pattern conformance record; placement; no-store-layer-wire invariant).
  • Cross-references: ADR-001; OQ-09 (its one former residual policy line, now resolved closed-by-default)

OQ-BL-02: Multi-backend dispatch

  • Origin: docs/research/phase-0.md
  • Status: resolved
  • Resolution: lean Backend contract + two shipped backends + pure-function size routing (pre-threshold buffering for unknown-length puts); migration eliminated by construction; per-namespace backend config rejected. Full rationale: ADR-003.
  • Cross-references: ADR-003, ADR-004

OQ-BL-03: Hash abstraction

  • Origin: docs/research/phase-0.md
  • Status: resolved
  • Resolution: canonical git-blob-sha-256; git-blob-sha-1 tolerated; BLAKE3 excluded from the crate. Key bytes: algorithm-in-key, fixed-length enum-tagged, tag byte dropped. The declared wire-format ADR. Full rationale: ADR-002.
  • Cross-references: ADR-002, ADR-006

OQ-BL-04: Verification and chunking

  • Origin: docs/research/phase-0.md
  • Status: resolved
  • Resolution: whole-blob verification; range reads carry out-of-band slice digests; chunk-tree/CDC encodings excluded by scoping (not deferred — the transfer-encoding consumer cannot be waited on; re-entry is a new decision at a new layer if ever named). Full rationale: ADR-006.
  • Cross-references: ADR-006, ADR-001

OQ-BL-05: Pooling and GC

  • Origin: docs/research/phase-0.md
  • Status: resolved
  • Resolution: one pooled CAS; flat bytes + logical namespaces; store persists no root table; mark-and-sweep with three liveness sources (registered sources / RAII + batch pins / protect callback with abort); delete windows close the sweep-vs-put race; explicit sweep, embedder-owned cadence; packfile serving rides large-blob range reads if ever wanted. Full rationale: ADR-005.
  • Cross-references: ADR-005, ADR-003

OQ-BL-06: POC register

  • Origin: docs/research/phase-0.md
  • Status: resolved (complete: #1, #3 passed; #2 absorbed; #4 covered in miniature, concurrency half specified as architecture in ADR-005; post-convergence additions #5 postgres and #6 redb passed and fed ADR-007; #7 pg-lo passed 2026-10-03 — poc-pglo-findings.md, spec poc-pglo-spec.md, requested by REQ-2/ADR-008)
  • Resolution: register complete and extended post-convergence; Phase 0 ended; evidence trail in docs/research/. The register's canonical numbering lives in phase-0.md OQ-BL-06.
  • Cross-references: all ADRs above

Parked index (deciding fact / owner — externally-owned rows are not blockers)

OQ Status Deciding fact / owner
OQ-07 externally-owned alkgit's architecture process (answerable on paper anytime; gates nothing here)
OQ-08 externally-owned alkfs Phase 0 intake

OQ-09 was deferred(scope) on the first embedded ops deployment — a deciding fact that could only exist once the ops module ships, i.e. a wait that never collapses. It resolved to closed-by-default (see its entry above); its tracker task is deleted.

OQ-10 was briefly recorded as an externally-owned "standing offer" on a deployment trigger — the same invalid shape, caught at review: the trigger was a fact only this crate could create. It resolved to ADR-007 (two kv engines; see its entry above).

The pg-lo large-engine question (raised in the ADR-008 review round, 2026-10-03) never became a parked question: REQ-2 made the multi-instance-with-large-blobs topology a standing requirement (requirements.md — a planning fact predating all POCs), so there was nothing to defer on. It resolved to ADR-008 naming pg-lo as the candidate large-tier engine + POC #7 (docs/research/poc-pglo-spec.md) as its admission evidence — sequenced work, per the deferral-policy header's third category. That work completed the same day: POC #7 passed (docs/research/poc-pglo-findings.md, gate verdict passed with named deltas) and ADR-009 shipped the engine. An earlier draft of that OQ parked on "alkgit's architecture process names the topology" — rendered moot by the REQ-2 fact before it was even written; recorded here because the audit trail of why not parked is part of this document's job, and because it is the worked example of the header's third category (decided → sequenced → completed).

OQ-07/OQ-08 are owned by other repos' processes and are not alkblobs tracker tasks (their outcome arrives through their owners, not through any artifact this repo creates).