The hash registry extends per ADR-018: bytes 0x03/0x04 (git-object sha-1/sha-256), preimage-identity hashing over git's loose-object form as the stored preimage — the digest byte-identical to git's oid, every kind included. Re-derived from poc-o-git-objects, ADR-stamped, not merged. - Registry + Algorithm members after the blob members (total order rides the registry bytes, 0x02 < 0x03 < 0x04); the derivation arms (derive's len parameter inert for the family — documented, test-pinned); the BlobHasher no-preamble arms (finish pinned equal to derive); from_git_oid_hex's contract pinned blob-family-only. - keys.rs: the extended physical layout round-trips in total order; rejects-never-guesses unchanged (0x05 is the unknown-tag example). - put path: put_git_object(algorithm, len, stream) public — family members only (KeyInvalid otherwise), known-length only, the inherited Verification/Io mappings — via put_known_as; the unknown-length drivers take their derivation from callers. - fleet threading (ADR-018 §7): every hasher site derivation-parameterized (put_known_as; fleet_put_pglo_known/ _unknown); put_git_object under a fleet declaration lands through the joint entry+pin tx / pg-lo consolidation / pin-first staged forms — pinned by two env-driven tests with exact-count sweep outcomes (kv joint form byte-exact + dedup row-alone; consolidation form with LO pages landing and dying exactly). - git_interop: the family tests green against the real git CLI (tree/commit/tag byte-exact, dedup, the blob-tag negative, the sha-256 sibling), the seam guard (blob algorithms reject), the preimage-length stat assertion; in-module empty-tree known-answer vectors. - Conformance: the INV-1/2/6 reference rows gain family legs (round-trip incl. the staged form, dedup-by-oid, the stored-preimage stat semantic); backlog pins + README inventory updated. - kind-decision delta (ADR-018 §2): behavior unchanged, texts honest — the ops module doc's digest-wire-form paragraph, digest_ingress's doc, the specs' headers. - fuzz: the key_encoding generator + shared battery extended to the four-member registry (family keys, known-answer vectors, the len inertness pin, 0x05 as the invalid tag); committed corpus regenerated per policy (0x03 was an invalid-tag seed — 117 rewritten, 67 added); idempotent after landing. Verification: cargo test (default, 153+54+7+2), cargo test --all-features server-less (skip-clean) and against the live pglo-poc harness (336+125+7+3), cargo clippy --all-targets both feature variants (-D warnings), cargo fmt --check, cargo doc --no-deps, Cargo test --manifest-path fuzz/shared/Cargo.toml (the corpus-replay gate). Task: tasks/c1-git-object-family-impl.md (status completed, notes + summary recorded).
12 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| c1-git-object-family-impl | C-1 (implementation half) — the git-object family lands: registry, derivation, put path, fleet threading, interop tests | completed |
|
broad | medium | project | implementation |
|
Description
Review-002 C-1's implementation half, per ADR-018 (the prior task's
record — read it first; where the prototype and the ADR disagree, the
ADR wins). Re-implement from the prototype branch poc-o-git-objects
(f0b045c) — re-derive, don't merge:
- Registry + Algorithm (src/hashing.rs): bytes
0x03/0x04, theGitObjectSha1/GitObjectSha256members, the preimage-identity derivation arms (derive's no-preamble arms — thelenparameter is ignored for the family), theBlobHasherno-preamble arms (the known-length path's one-pass form feeds no preamble — the loose-object header is inside the stored preimage). - Key decode/order (src/keys.rs): the new tags decode
round-trip; total order follows the registry bytes (0x02 < 0x03 <
0x04); rejects-never-guesses unchanged (unknown/truncated are
KeyInvalid). - The put path (src/store/put.rs):
put_git_object(algorithm, len, stream)public per ADR-018's pinned shape, via the derivation-parameterized internalput_known_as(the canonical blob put routes the preamble hasher; the family put routes the plain hasher; everything after hasher construction is pin-before-publish identical). Known-length only; the family members only (KeyInvalidotherwise); kv-only over-threshold rejection inherited. - Interop tests (tests/git_interop.rs): the branch's family tests
— byte-exact against real
git hash-object -t(tree/commit/tag round-trips), dedup, the negative (the same oid unreachable through the blob tags — no cross-family collision), the empty-tree known-answer vectors (sha14b825dc6…, the sha-256 sibling), the sha-256 sibling CLI-validated.
Plus what the branch deliberately skipped (review-002's not-carried list — the merge-time work):
- Fleet threading. The fleet/non-fleet hasher sites still
hardcode the canonical blob derivation (representative anchor:
src/store/fleet.rs:786 —
Key::derive(content, …)in the fleet put path; src/local.rs:899 is the non-fleet large-tier site). The derivation must thread through the fleet put path uniformly: a fleet-declared store'sput_git_objectlands through the joint entry+pin tx with pin-before-publish ordering intact, and the fleet hasher sites are derivation-parameterized, not family-branching copies. Mechanical per the POC, but it is the merge-time work. - The ops-surface delta per ADR-018's kind decision (likely docs-only — the digest ingress staying blob-family — but whatever the ADR decided lands here: the ingress, the section doc, the specs' wire-form text).
- The
statsemantic per the ADR: the stored value is the loose form, sostat's code may need no change — but the docs and the conformance rows must state the preimage-length semantic explicitly (a deliberate difference from the blob family, not an accident).
Fuzz consistency: the key_encoding target's surface
(Key::from_bytes / Digest::from_git_oid_hex / the registry /
derive) gains the new tags — the committed seeds regenerate per the
corpus policy if the target's input shape changes
(python3 fuzz/gen_fuzz_seeds.py; a no-op diff on the committed set
is the expected outcome unless the seeds encode the registry
constants — check, and record either way).
Acceptance Criteria
- The family lands per ADR-018: registry bytes, Algorithm
members, derivation + hasher arms, key decode/order,
put_git_objectpublic with the ADR's pinned shape - Fleet threading: the fleet hasher sites derivation-parameterized;
put_git_objectunder a fleet declaration lands through the joint entry+pin tx (exact-count fleet sweep outcome test) - tests/git_interop.rs family tests green against the git CLI (tree/commit/tag, dedup, the blob-tag negative, empty-tree vectors, the sha-256 sibling)
- The
statsemantic documented per the ADR; conformance rows extended (the family's round-trip/dedup/verification rows) - The ops surface matches ADR-018's kind decision (code or docs, as decided)
- The fuzz
key_encodingtarget/seeds consistent with the extended registry (disposition recorded) - Gates green: the full AGENTS block —
cargo test(default),cargo test --all-featuresserver-less and against the live pg harness (ALKBLOBS_PG_HOST=localhost,ALKBLOBS_PG_PORT=15432,ALKBLOBS_PG_USER=postgres,ALKBLOBS_PG_PASSWORD=poc,ALKBLOBS_PG_DB=blobs— thepglo-poccontainer; server-less runs skip cleanly), both clippy variants,cargo fmt --check,cargo doc --no-deps, the fuzz corpus-replay gate (cargo test --manifest-path fuzz/shared/Cargo.toml)
References
- tasks/c1-adr-git-object-family.md (the ADR — this task's contract)
- docs/reviews/002-first-consumer-review.md (C-1)
- branch
poc-o-git-objects(f0b045c) — the working reference - docs/architecture/decisions/002-canonical-hash-and-key-encoding.md; hashing-and-keys.md; store-api.md; ops-surface.md (as amended)
- src/hashing.rs; src/keys.rs; src/store/put.rs; src/store/fleet.rs:786; src/local.rs:899; tests/git_interop.rs
- fuzz/README.md (the corpus policy); fuzz/gen_fuzz_seeds.py
Notes
- Re-derive landed per ADR-018 (no merge of
poc-o-git-objects): the registry/derivation shape tracks the prototype byte-for-byte, the docs are ADR-018-stamped (the prototype's "POC-O prototype, not an ADR" markers replaced), and the five prototype-uncarried decisions landed per the ADR's §Deviations. - Fleet threading (deviation 1): every hasher site is
derivation-parameterized, not family-branching —
put_known→put_known_as(algorithm, …)(src/store/put.rs);fleet_put_pglo_known(algorithm, …)(the pg-lo consolidation tx's hasher); the unknown-length drivers (put_unknown,fleet_put_pglo_unknown) take the derivation from their callers, whose single caller passes the canonical blob derivation (blob-family by construction — ADR-018 §Decision 6 rejected the family's unknown-length arm).put_git_objectunder a fleet declaration routes: kv tier → the joint entry+pin tx (fleet_put_kv), pg-lo → the one-tx consolidation form, local shared-media → pin-first/publish-second. Two new env-driven tests in src/store/fleet.rs pin the family forms end to end:fleet_kv_put_git_object_lands_through_the_joint_tx(byte-exact joint landing, the empty-tree oid under tag0x03, the dedup re-put's row-alone form, and the exact-count sweep outcome — held pins protect (0/0/0), the expired shape stages (1/0/0) then deletes exactly once (1/0) across the executor sweep) andfleet_pglo_put_git_object_lands_through_the_consolidation_tx(over-threshold loose form through the one-tx consolidation, LO pages land and die exactly, the stat semantic on the LO medium, the same exact-count sweep outcome). - The kind-decision delta (deviation 2): behavior unchanged,
texts honest —
Digest::from_git_oid_hex's contract doc pins the blob family (the physical-encoding path for family-explicit construction named), the ops module doc's digest-wire-form paragraph states the blob-family scoping (S-5: schema gate and ingress agree by construction),digest_ingress's doc carries the posture; ops-surface.md's header noted. The wire schema, ingress, and put cross-check are byte-for-byte unchanged. - The stat-semantic record (deviation 3): no code change (the
stored value is uniformly the returned length) — store-api.md's
per-family semantic stands; the conformance rows pin it (see
below), and the
put_git_objectdoc states it. - Fuzz-seed disposition (deviation 4): the committed seeds did
encode the registry constant (
0x03in the invalid-tag battery of bothfuzz/gen_fuzz_seeds.pyand the shared replay) — regeneration was expected and done. The generator now derives valid0x03/0x04family keys (loose-form oids), loops all four algorithms for truncation/over-long forms, battery-tests tag/digest-width mismatches per family member, and retires0x03-as-invalid in favor of0x05; 117 committed seeds rewritten, 67 added. The shared replay battery gains the family keys, the family known-answer vectors (the empty-tree oids), the derive-leninertness boundary pin, and the registry sweep's width-mapping-by-family fix. Regeneration is idempotent after landing (a replay-only diff). - The derive-
lenquirk (deviation 5): documented inAlgorithm::derive's contract and pinned bygit_object_derive_len_parameter_is_inert(src/hashing.rs — everylenincl.u64::MAXequals the plain hash). - Conformance rows extended in place (the INV-1/2/6 reference rows gained family legs rather than new rows — the columns inherit via the shared row bodies, INV-7's uniformity mechanism): INV-1 round-trips both family members (sub-threshold and, against the dual-tier columns, staged forms alike), INV-2 pins the family re-put's CAS dedup through sweep outcomes, INV-6 pins the stored-preimage stat semantic as a deliberate per-family property. Backlog pins and the README inventory updated. The fleet-tier family coverage is the two env-driven store-core tests above (the conformance columns run non-fleet factories by design).
- Interop tests: the prototype's two family tests landed
(CLI-validated tree/commit/tag byte-exactness incl. the sha-256
sibling; the facade round-trip with the blob-tag negative), plus a
new seam-guard test (
put_git_object_rejects_blob_algorithms— the ADR's pinnedError::KeyInvalidmapping) and the stat-semantic assertion folded into the round-trip test.
Summary
The git-object derivation family landed per ADR-018 — review-002 C-1
complete. src/hashing.rs: registry bytes 0x03/0x04
(GIT_OBJECT_SHA1/GIT_OBJECT_SHA256), the Algorithm family
members after the blob members (total order rides the registry bytes),
the preimage-identity derivation arms (derive ignores len for the
family — documented and test-pinned), the BlobHasher no-preamble
arms (finish pinned equal to derive), from_git_oid_hex's contract
pinned blob-family-only. src/keys.rs: the extended physical layout,
family keys round-trip in total order, rejects-never-guesses unchanged
(0x05 is the unknown-tag example now). src/store/put.rs:
put_git_object(algorithm, len, stream) public per the ADR's pinned
shape (family members only, key-invalid otherwise; known-length only;
the inherited Verification/Io error mapping), via the
derivation-parameterized put_known_as; the unknown-length drivers
take their derivation from callers. src/store/fleet.rs: the pg-lo
known/unknown drivers derivation-parameterized; put_git_object
under a fleet declaration lands through the kv joint entry+pin tx /
pg-lo one-tx consolidation / local pin-first-publish-second forms,
pinned by two env-driven tests with exact-count sweep outcomes.
tests/git_interop.rs: the family tests green against the real git CLI
(tree/commit/tag byte-exact, dedup, the blob-tag negative, the
empty-tree vectors, the sha-256 sibling CLI-validated). Conformance:
INV-1/2/6 rows extended with family legs (round-trip incl. the staged
form, dedup-by-oid, the stored-preimage stat semantic), backlog/README
updated. Ops-surface texts honest (behavior unchanged). Fuzz: the
key_encoding generator and shared battery extended to the four-member
registry; the committed corpus regenerated per policy (0x03 was an
invalid-tag seed — a no-op was not the expected outcome). Gates green:
default cargo test (153+54+7+2), cargo test --all-features
server-less and against the live pglo-poc harness (336+125+7+3),
both clippy variants, cargo fmt --check, cargo doc --no-deps, and
the fuzz corpus-replay gate.