docs(plans): implementation plan — wave-based decomposition; wave 1 decomposed into tasks/
- docs/plans/implementation.md: the meta plan (alkstore pattern) — nine waves, dependency logic, decided points, review gates. Scope authority: v0.1.0 ships the full surface (all five engines, fleet GC, ops). - Wave 1 decomposed: scaffold-crate-features, core-error-model, core-hashing-keys, core-trait-and-types, suite-scaffold, review-wave-1 (the one-way-door gate). - Waves 2-9 shaped in the plan; each decomposes after the prior wave's review gate. Verification: cargo test / clippy -D warnings / fmt --check green (docs-only change).
This commit is contained in:
1 parent
6f6ab19b8e
commit
8a2df4fa57
7 files changed
+829
No files matched your search
@@ -0,0 +1,92 @@
|
||||
---
|
||||
id: core-hashing-keys
|
||||
name: Hashing & keys — the canonical derivation and the one-way-door encoding
|
||||
status: pending
|
||||
depends_on: [core-error-model]
|
||||
scope: narrow
|
||||
risk: medium
|
||||
impact: project
|
||||
level: implementation
|
||||
tags: [wave-1, keys]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Implement the content-address layer (`src/keys.rs` or `keys/` +
|
||||
`hashing`, one module per file per convention) per ADR-002 and
|
||||
hashing-and-keys.md. This is the crate's declared one-way door — key
|
||||
bytes persist in backend rows and filenames with no migration story —
|
||||
so the encoding is implemented exactly to the ADR text and reviewed
|
||||
line-by-line at the wave gate.
|
||||
|
||||
- **`Digest`** — algorithm + digest pair. Algorithm enum with exactly
|
||||
two members: `GitBlobSha256` (canonical), `GitBlobSha1` (tolerated
|
||||
legacy). BLAKE3 is absent from the crate entirely (ADR-002 §Decision
|
||||
class 3).
|
||||
- **Canonical derivation**: `H("blob <len>\0" + content)` — SHA-256
|
||||
canonical, SHA-1 same derivation. The preamble is the algorithm's
|
||||
domain separation, not a special case (ADR-002 §The preamble as
|
||||
abstraction). Known-length derivation is the primary constructor;
|
||||
the unknown-length path's derivation-over-staged-bytes restart is
|
||||
wave 2 facade logic, not here.
|
||||
- **Interop constructor**: `from_git_oid_hex` shape (POC #1 finding 4)
|
||||
— a pre-computed pair from an external git oid, both algorithms.
|
||||
- **`Key`** — the typed wrapper; `as_bytes()` / `from_bytes()` are the
|
||||
only conversions across the backend boundary. Physical encoding per
|
||||
ADR-002: `1 algorithm byte + digest bytes` — `0x01` =
|
||||
git-blob-sha-256 (32-byte digest; total 33), `0x02` = git-blob-sha-1
|
||||
(20-byte digest; total 21). `0x00` is reserved and never assigned.
|
||||
- **Validation**: truncated keys and unknown algorithm bytes are
|
||||
rejects (`Error::KeyInvalid`), never guesses (the POC's
|
||||
length-checking test is the standard).
|
||||
- **Sort stability**: fixed-length enum-tagged keys sort in total
|
||||
order (required for the sweep's live-set diffs) — asserted by test.
|
||||
- **Registry constants**: the algorithm bytes are the ADR-002
|
||||
registry; new algorithms require a new ADR (doc comment states
|
||||
this).
|
||||
- **Interop test (the load-bearing test)**: byte-exact derivation
|
||||
against the `git hash-object` CLI for both algorithms (POC #1
|
||||
findings 4/5's standard — validated against git, not just hardcoded
|
||||
vectors), plus the external-oid round-trip: `from_git_oid_hex` →
|
||||
`as_bytes` → `from_bytes` → equal, and tagged-key coexistence of
|
||||
both algorithms in one flat collection.
|
||||
- **Named design point for the review gate**: oid hex parsing policy —
|
||||
git oids are lowercase hex; pin lowercase-only acceptance (reject
|
||||
uppercase as malformed) or case-insensitive acceptance, with the
|
||||
choice recorded. Lean lowercase-only (git's own output is always
|
||||
lowercase; strictness at the boundary matches rejects-never-guesses)
|
||||
unless implementation finds a concrete interop reason otherwise.
|
||||
- Deps: `sha2`, `sha1` (RustCrypto), `hex` — added to the manifest by
|
||||
this task.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `Digest`/`Key`/algorithm enum per ADR-002; encoding byte-exact
|
||||
(33/21 total lengths; 0x01/0x02 tags; 0x00 rejected)
|
||||
- [ ] Canonical derivation matches `git hash-object` byte-exact for
|
||||
both algorithms (CLI-driven test, both a small and a multi-KiB
|
||||
content case)
|
||||
- [ ] `from_git_oid_hex` round-trips external oids into pool keys
|
||||
- [ ] Rejects: truncated keys, unknown algorithm bytes (incl. 0x00,
|
||||
0xFF), wrong digest lengths → `Error::KeyInvalid`, never guesses
|
||||
- [ ] Total-order sort stability asserted (mixed-algorithm collection
|
||||
sorts deterministically)
|
||||
- [ ] Doc comments carry the one-way-door warning and the registry
|
||||
note (new algorithm = new ADR)
|
||||
- [ ] `cargo test`, `cargo clippy --all-targets -- -D warnings`,
|
||||
`cargo fmt --check` green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/hashing-and-keys.md
|
||||
- docs/architecture/decisions/002-canonical-hash-and-key-encoding.md
|
||||
- docs/research/poc-trait-dispatch-findings.md findings 4/5
|
||||
- AGENTS.md convention 5 (the one-way door)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Reference in new issue
Block a user