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).
This commit is contained in:
1 parent
9bbe6f3ad9
commit
abf8c5ae9c
18 files changed
+1137
-336
No files matched your search
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03
|
||||
last_updated: 2026-10-03 (pin-token renewal contract pinned per ADR-010 §4)
|
||||
---
|
||||
|
||||
# Ops surface (alkcall-backed network operations)
|
||||
@@ -96,8 +96,11 @@ the server. The hand-over contract:
|
||||
|
||||
1. the put lands pinned (ADR-005) — the entry cannot be swept while
|
||||
the handler holds the pin;
|
||||
2. the `blobs/put` response returns a **pin token** (opaque handle);
|
||||
the putter can later confirm its registration landed by observing
|
||||
2. the `blobs/put` response returns a **pin token** (opaque handle —
|
||||
minted by the ops layer over the pin row the put committed; the
|
||||
token↔(key, owner) mapping is ops-layer state, not durable state —
|
||||
the durable state is the pin row itself, ADR-010 §4); the putter
|
||||
can later confirm its registration landed by observing
|
||||
the digest present via `blobs/have`;
|
||||
3. the embedder's registered liveness source is the *actual* root of
|
||||
record: the contract on the embedder (documented on the ops module)
|
||||
@@ -112,6 +115,32 @@ the server. The hand-over contract:
|
||||
conversion on the server side (token → registered liveness source)
|
||||
is the mechanism the embedder plugs its registry into.
|
||||
|
||||
**Token renewal (ADR-010 §4 — the fleet-TTL race, resolved): the
|
||||
token *is* the pin — there is no second pin state.** The server-side
|
||||
handler's in-process `Pin` guard drops when the `blobs/put` response
|
||||
completes (if it never dropped, the TTL machinery would be dead on
|
||||
the ops path — the pin row's expiry, not the guard's presence, is the
|
||||
fleet liveness signal). Under fleet
|
||||
engines the put's pin is an expiry-carrying row (ADR-008: TTL 60 s
|
||||
default, renewed every TTL/3). The remote putter holding a token is
|
||||
the row's owner and renews by the ops it already speaks: a
|
||||
`blobs/have` probe **presenting the token alongside the digest** (the
|
||||
handler verifies the token maps to the digest's pin row and calls the
|
||||
crate-internal `pin_renew` via the ops module's store-core access —
|
||||
the ops module is in-crate and crosses the seam by construction, the
|
||||
same way the put handler holds the `Pin` guard; `has` itself remains
|
||||
a pure existence probe per ADR-008 — renewal is a token-authenticated
|
||||
act on the pin row, not a `has` semantic), or a re-put of the same
|
||||
digest (CAS dedup renews the row). **A putter may pause past the
|
||||
TTL/3 mark (20 s at the default TTL) only if it renews before expiry;
|
||||
a putter pausing past TTL lets the row expire** — the sweeper reaps
|
||||
it (ADR-008) and delete-then-recover (ADR-005) is the backstop: the
|
||||
putter re-offers the digest; CAS makes the re-put idempotent. The
|
||||
race resolves to a re-put, never to silent loss. For non-fleet
|
||||
(`local`-engine) serving nodes the token is the in-process guard —
|
||||
nothing expires; the process-crash case is ADR-005's in-flight-put
|
||||
loss with the same backstop.
|
||||
|
||||
Placement of the op *registration* (which embedders wire where they
|
||||
want them exposed) matches the alkgit ops pattern (its
|
||||
`git/repo/*` call ops): the module exports spec/handler pairs; the
|
||||
@@ -143,10 +172,11 @@ handlers call `put`; both honor pins and delete windows. There is no
|
||||
ops-internal path around the store facade (ADR-001 §Consequences —
|
||||
this is what makes "re-homing the ops surface later loses nothing"
|
||||
true). One fleet topology additionally rides this module: **re-routing
|
||||
(ADR-008)** — a fleet whose nodes do not share fs media routes
|
||||
(ADR-008)** — a fleet whose nodes do not share large-tier media routes
|
||||
large-blob access through a single storage node via these ops, with
|
||||
client nodes' fs tiers serving only node-private content. The module
|
||||
supports this shape without change; no fleet-specific op exists.
|
||||
client nodes' constructors in kv-only mode (ADR-011 §4) for pool
|
||||
content. The module supports this shape without change; no
|
||||
fleet-specific op exists.
|
||||
|
||||
## Design Decisions
|
||||
|
||||
@@ -154,7 +184,9 @@ supports this shape without change; no fleet-specific op exists.
|
||||
|---|---|---|
|
||||
| [001](decisions/001-substrate-posture-and-ops-placement.md) | Substrate posture & placement | alkcall-backed, feature-gated ops module; conformance-not-deviation rationale |
|
||||
| [006](decisions/006-verification-posture-and-transfer-encoding.md) | Verification | verified-fetch via carried digests; no chunk trees |
|
||||
| [008](decisions/008-trait-size-probe-fleet-gc-and-fs-engines.md) | Fleet re-routing topology | non-shared-media fleets route large-blob access through a storage node via these ops; no new ops |
|
||||
| [008](decisions/008-trait-size-probe-fleet-gc-and-large-engines.md) | Fleet re-routing topology | non-shared-media fleets route large-blob access through a storage node via these ops; no new ops |
|
||||
| [010](decisions/010-backend-io-seams-and-fleet-state-home.md) | Pin-token renewal | the token is the pin; renewal rides have/re-put; TTL expiry falls to delete-then-recover |
|
||||
| [011](decisions/011-vocabulary-tiers-engines-and-fleet-state.md) | Vocabulary + modes | instance/node/fleet split; kv-only mode named (the re-routing posture's client shape) |
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
Reference in new issue
Block a user