Files
alkblobs/tasks/ops-json-ops.md
T
glm-5.3-flash 5144b6a733 feat(ops): the JSON control plane — stat, have (+ the renewal form), and the internal delete (wave 7)
- stat_pair/have_pair/delete_pair exported as spec/handler pairs the
  embedder assembles (OpsContext-bound); input/output + typed error
  schemas per alkcall ADR-016 with namespace-as-resource ACL, the read
  action on stat/have, closed-by-default (OQ-09) verified by test
- stat rides Store::stat (the miss answering the typed BLOB_MISSING,
  never {len: null}); the non-token have is the pure has probe with
  index-corresponded present[]; delete is Visibility::Internal —
  external discovery NOT_FOUND, the operator authority context carried
  as the registration-time composition authority (not namespace-gated),
  GC_REFUSED/BLOB_MISSING typed, fail-fast
- the have renewal form rides the foundation's OpsContext::renew: the
  one-digest arity enforced at the schema (if/then) and as the typed
  INVALID_RENEWAL_FORM; digests wire-form hex via the key layer's
  ingress (INVALID_DIGEST); the fleet arms tested against the harness
  server (env-driven, skipping cleanly server-less): the live row
  renews with the expiry observed moving, the expired row answers
  present: false with the expiry frozen (no renewal), the foreign
  token is the validity-domain refusal, and mint_custodial refuses
  under fleet

Gates: cargo test (default 73/19/3), cargo test --features ops
(92/19/3), cargo test --all-features against the harness server
(246/125/4), clippy -D warnings across default/ops/all-features plus
the pg-pure checks, cargo fmt --check, cargo doc --no-deps clean.
2026-10-13 00:31:25 +00:00

11 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
ops-json-ops the JSON control plane — blobs/stat, blobs/have (+ the token-renewal form), blobs/delete completed
ops-foundation
ops-call-harness
moderate medium component implementation
wave-7
ops
json
acl
tokens

Description

The three JSON control ops (ops-surface.md §Op family), each exported as a spec/handler pair the embedder assembles — riding alkcall's OperationSpec + JSON Schema validation (alkcall ADR-016) and its ACL machinery at op entry (convention 6: this module never re-implements an authorization check):

  • blobs/stat {namespace, digest} → {len} — Query; the read action; the handler calls Store::stat (the fall-through general rule, ADR-012 §6.1); a miss is the typed missing-error schema (not a {len: null}).
  • blobs/have {namespace, digests[], token?} → {present[]} — Query; read-gated (an existence probe over arbitrary digests is a discovery surface — gated exactly like fetch, not public); present[] corresponds to digests[] by index; content never traverses this op (hashes only). The renewal form (ADR-012 §2): when token is present, exactly one digest accompanies it — the handler verifies the token maps to that digest's pin row (the foundation's token layer), calls the crate-internal pin_renew(key, owner) via the foundation's store-core access, and answers present[] as usual; an expired or foreign row answers present: false and no renewal occurs — the putter's backstop is re-put. Without token, the pure existence probe (ADR-008's has discipline) over the facade's has. The non-fleet renewal form: the token is the held guard's handle — the probe answers present from the custody (nothing expires; ADR-012 §2's generalization); the custody/conversion lifecycle is the foundation's.
  • blobs/delete {namespace, digests[]} — Mutation; Visibility::Internal, evaluated under the internal authority context per alkcall ADR-017 (internal calls switch authority context, never skip ACL): requires the embedder's operator/admin authority context, not a namespace grant; the namespace field exists for audit/triage scoping, not gating. The handler calls Store::delete (the arbitration-then-delete path; a GcRefuse refusal surfaces as the typed error schema). External discovery of an Internal op returns NOT_FOUND (alkcall ADR-017's visibility discipline).
  • The ACL mapping (ops-surface.md §ACL mapping; OQ-09's resolution): namespace = resource — resource_type: "blob-namespace", resource_id_path selecting the payload's namespace field; stat/have = the read action; unlisted namespaces deny by default (closed-by-default: no ACL entry ⇒ no read, no write — a grant per namespace is the deferred cost, deliberately paid over accidental exposure).
  • Schemas (alkcall ADR-016): input/output JSON Schema per op + typed error schemas; the namespace field's syntax (non-empty UTF-8 string, embedder-validated — the minting of namespaces is the embedder's act); the digest wire form is hex (the canonical digest hex — the same form blobs/put's response returns; parsed via the key layer's hex ingress, malformed → the typed invalid error, rejects-never-guesses).
  • Tests through the harness (ops-call-harness): stat round-trip
    • the miss shape; have's index correspondence (present/absent mixed); the renewal form's three answers (live row renews → present: true; expired row → present: false, no renewal; foreign token → present: false); delete under the internal authority context (an external caller gets NOT_FOUND; an internal operator-context call deletes); the closed-by-default ACL matrix (an unlisted namespace denies read; a granted identity reads).

Acceptance Criteria

  • Three spec/handler pairs exported (stat, have, delete); input/ output schemas + typed error schemas per alkcall ADR-016
  • The ACL mapping: namespace-as-resource with the resource_id_path; the read action on stat/have; closed-by-default verified by test (unlisted namespace denies)
  • delete: Visibility::Internal, the internal-authority-context requirement (not namespace-gated), external discovery NOT_FOUND
  • have's renewal form: one digest + token; verify-mapping → pin_renew; expired/foreign → present: false with no renewal; the non-fleet form answers from the held custody
  • The handlers touch only the store facade + the foundation's crate-internal renewal access (no backend side-door — the ADR-001 §4 rule)
  • Harness tests green; cargo test (default) green; cargo test --features ops green; clippy/fmt green on both shapes; cargo doc --no-deps clean

References

  • docs/architecture/ops-surface.md (§Op family — the three JSON ops; §ACL mapping)
  • docs/architecture/decisions/001-substrate-posture-and-ops-placement.md §2/§4
  • docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §2 (the have payload shape + the renewal form's three-step handler duty)
  • docs/architecture/decisions/008-trait-size-probe-fleet-gc-and-large-engines.md (the has discipline the non-token form preserves)
  • docs/architecture/open-questions.md OQ-09 (closed-by-default, the risk-asymmetry rationale)
  • alkcall (upstream checkout): ADR-016 (operation error schemas), ADR-017 (the privilege model — internal switches context, never skips ACL), src/registry/spec.rs (AccessControl, resource_id_path)
  • tasks/ops-foundation.md (the token layer + the renewal access the have handler rides), tasks/ops-call-harness.md (the harness)

Notes

Landed in src/ops.rs (the ops module's "JSON control plane" section, appended to the foundation's substrate) + src/lib.rs re-exports (stat_pair/have_pair/delete_pair and the four domain codes BLOB_MISSING/INVALID_DIGEST/INVALID_RENEWAL_FORM/ GC_REFUSED). Each export is pub fn X_pair(ctx: Arc<OpsContext>) -> (OperationSpec, Handler) — the embedder assembles; the harness's assembly (extended: assemble_registrations now carries the registration-side composition authority and scoped composition env, ADR-017/019 — the pair-level assemble shape is unchanged).

Schemas (alkcall ADR-016): input/output JSON Schema per op — the namespace field's syntax enforced at the schema (minLength: 1, the non-empty-UTF-8 rule); the digest wire form hex with the canonical pattern (^[0-9a-f]{40}$|^[0-9a-f]{64}$, the key layer's lowercase-only ingress also enforced at the handlers — rejects-never-guesses). The have schema carries the renewal form's arity as if/then (token ⇒ digests minItems/maxItems 1) — verified live at the wire (INVALID_INPUT on the two-digest+token shape) — and re-enforced at the handler (INVALID_RENEWAL_FORM, the typed error for non-registry dispatch paths, exercised by direct handler invocation). Typed error schemas: BLOB_MISSING (stat's miss — details {digest}; a {len: null} was never an option), INVALID_DIGEST (the ingress), INVALID_RENEWAL_FORM (have's arity), GC_REFUSED (delete's Error::GcRefuse).

The ACL mapping (OQ-09's resolution, verified by test): namespace-as-resource — resource_type: "blob-namespace", resource_id_path: "$.namespace", the read action on stat/have; closed-by-default proven on the wire (an unlisted namespace denies the granted identity's probe; a granted namespace reads; the anonymous call answers the authentication required gate). delete: Visibility::Internal, AccessControl left un-gated (not namespace-gated — the field is audit/triage scoping), the operator-admin authority context realized as the composition authority the embedder declares at registration (the pair exports it authority-agnostic); external discovery is the registry's NOT_FOUND (tested); the internal path proven through a composant op (blobs/compose-delete test stub, scoped env → delete) whose grantless caller composes — the check ran against the declared operator authority, the namespace grant not the gate. GcRefuse and Missing surface as the typed errors (fail-fast; no atomic multi- delete was specced — the preceding digests' deletions stand, and the doc says so).

The renewal form (ADR-012 §2's three-step duty, riding the foundation's OpsContext::renew — no new store access, no backend side-door): the non-fleet arms answer from custody (renew → present: true; unknown/foreign/mismatched → present: false, never an error; the malformed-token ingress maps to the unknown-token answer); the fleet arms ran against the harness server (env-driven ALKBLOBS_PG_HOST/..., skipping cleanly server-less — the fleet column's SKIP posture adapted in-crate): the live row renews with the row's expiry observed moving (the independent gc_pins instrument), the expired row answers present: false with the expiry frozen at the last renewal (no renewal occurred — the never-resurrect discipline), and the peer mint's foreign token answers present: false the same way (the validity domain = the minting node). The foundation's noted mint_custodial-refused-under- fleet arm is asserted in the same test. The put-side arms (mint the token from a wire-carried put) ride the put's handler (ops-put).

Summary

Completed 2026-10-13 (wave 7). The JSON control plane's three spec/handler pairs landed in src/ops.rs under feature ops: blobs/stat (Query/read — Store::stat, the miss as the typed BLOB_MISSING), blobs/have (Query/read — the pure existence probe over Store::has with index-corresponded present[], engine failures folding to present: false, and the token-renewal form riding OpsContext::renew with the one-digest arity enforced at the schema (if/then) and the handler), and blobs/delete (Mutation/Visibility::Internal — external discovery NOT_FOUND; the operator authority context via the registration-time composition authority; not namespace-gated; Store::delete with GC_REFUSED/ BLOB_MISSING as the typed errors, fail-fast). ACL: namespace-as- resource, the read action, closed-by-default (verified by test); digests wire-form hex parsed via the key layer's ingress (rejects-never-guesses); domain error codes BLOB_MISSING/ INVALID_DIGEST/INVALID_RENEWAL_FORM/GC_REFUSED declared per op with their details schemas. Five harness tests added (stat round-trip/miss/ingress, have's index correspondence + closed-by- default matrix, the renewal form's arms incl. the arity gate at both the wire and the handler, delete's NOT_FOUND + internal composition

  • refusal arms) plus one fleet harness-server test (the three renewal answers with the row-expiry instrument; the foreign token; the custodial-mint refusal under fleet) — env-driven, skipping cleanly server-less (SKIP posture). Gates green: cargo test (default 73/19/3), cargo test --features ops (92/19/3), cargo test --all-features against the harness server (246/125/4 — one pre-existing fleet-timing row flaked once under full-suite load and passed on the isolated + full reruns, untouched by this task's diff: the fleet column reads no ops code), clippy --all-targets -- -D warnings on the default/ops/all-features shapes plus the pg-pure checks, cargo fmt --check, cargo doc --no-deps clean on the default and ops builds.