The ADR-008 pg-lo admission POC ran in a standalone crate (/workspace/alkblobs-pglo-poc): PgLoBackend over the ADR-003/008 trait contract (including size), 10/10 exact-count sweep-outcome contract tests, clippy/fmt clean; dockerized postgres:16-alpine on :15432, POC #5 driver stack (tokio-postgres + deadpool) via SQL lo_* functions, no new dependency. Gate verdict: passed, with named deltas. - Performance: durable put 60-65 MB/s at >=1 MiB, within 1.5x of — and below 1 MiB beating — durable local fs on this fsync-slow disk; cached gets 70-180 MB/s single-stream, ~0.7 GB/s aggregate over 16 readers (20-50x behind page-cache fs — the honest named delta) - Contract: companion table is the list()/size()/CAS authority (never the catalogs); stage-then-commit; GC-participating lo_unlink delete - Handles: the tx-scoped descriptor is real but pool-compatible via descriptorless lo_get(oid, off, len) windows — window gets keep handle-acquire p99 at 1-6 ms under readers <= pool; held descriptor is the fallback posture - Vacuum: pg_largeobject pages churn-reused, never returned; tracked by autovacuum; rel-size monitoring named as an ops requirement - Crash/orphan: LO creation is transactional — kill/terminate mid-write-tx leaves zero orphan pages; the only orphan class is a committed LO bypassing the companion table (planted, reaped by the ~7 ms/oid sweep; committed content survives byte-exact) - Harness lessons: lo_lseek is int4 — the 64 variants are the >2 GiB discipline; shared-table parallel tests are unsound (per-test CREATE DATABASE isolation) Docs: new poc-pglo-findings.md; poc-pglo-spec.md status passed; register OQ-BL-06 #7 marked passed; ADR-008 pg-lo bullet updated (duplicate bullet removed) + backends-and-dispatch/open-questions cross-references. Verification: cargo test --release (10 passed), clippy -D warnings, fmt --check in /workspace/alkblobs-pglo-poc.
263 lines
13 KiB
Markdown
263 lines
13 KiB
Markdown
---
|
|
status: draft
|
|
last_updated: 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. 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 fs-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](overview.md), [gc-and-namespaces.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](overview.md), [backends-and-dispatch.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](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](decisions/007-two-kv-engines-sqlite-and-postgres.md)).
|
|
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](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](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](decisions/001-substrate-posture-and-ops-placement.md)
|
|
(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](decisions/003-backend-contract-and-dispatch.md).
|
|
- **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](decisions/002-canonical-hash-and-key-encoding.md).
|
|
- **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](decisions/006-verification-posture-and-transfer-encoding.md).
|
|
- **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](decisions/005-pooled-cas-and-gc-mechanism.md).
|
|
- **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 fs-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 fs-tier engine + POC #7 (`docs/research/poc-pglo-spec.md`)
|
|
as its admission evidence — sequenced work, per the deferral-policy
|
|
header's third category. An earlier draft of that OQ parked on
|
|
"alkgit's architecture process names the topology" — rendered moot the
|
|
same day by the REQ-2 fact; recorded here because the audit trail of
|
|
*why not parked* is part of this document's job.
|
|
|
|
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). |