Skip to content

Commit 93aeb8f

Browse files
johnzillaclaude
andcommitted
chore: pre-bump cleanup — stop printing test counts, fix design-doc status, drop dead param
Three small items ahead of a version bump. 1. Test-count drift (3rd recurrence): removed the hardcoded "335 / 347" from CLAUDE.md and FAQ.md (actual had already fallen to 329 / 341 after the v1.1-surface test deletions). Counts rot within days of every change, so the process fix is to stop writing them in prose — added a CLAUDE.md guardrail ("Do not hardcode test counts in prose … run the command"). 2. Design-doc status header was actively wrong (still said "pre-implementation / not shipped / crypto deps are test-only dev-deps"). Flipped docs/design/derived-key-addressing.md to IMPLEMENTED — shipped through Phase 3c (PROTOCOL_VERSION 2, crate 1.2.0-alpha.1; parent-key surface removed in 8be2567), deps are main dependencies, code+tests are source of truth. Marked §13 phases 3/4/5 DONE with pointers. 3. Removed the vestigial `_audit_detail` param from render_receipts_table — the multi-row branch is gone; run_receipts always renders one receipt in audit form. (Not addressed, by design: OuterRecord still carries cleartext pubkey/recipient, so a DHT scanner that finds a share packet recovers the edge — accepted tradeoff; THREAT-MODEL §1 is accurate, and the receipt enumeration path is closed.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8be2567 commit 93aeb8f

4 files changed

Lines changed: 26 additions & 18 deletions

File tree

CLAUDE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Build / test / lint commands:
1111
```bash
1212
cargo build --release # release binary: ./target/release/cipherpost
1313
cargo test # unit + doc tests (no DHT-touching tests)
14-
cargo test --features mock # + MockTransport integration tests (335 tests; 347 with --all-features)
14+
cargo test --features mock # + MockTransport integration tests (--all-features adds feature-gated suites)
1515
cargo nextest run --all-features # CI's runner (nextest); doctests run separately via `cargo test --doc`
1616
cargo fmt --check # CI-enforced
1717
cargo clippy -- -D warnings # CI-enforced
@@ -21,6 +21,8 @@ cargo deny check # CI-enforced supply-chain policy
2121

2222
CI runs all of the above plus `lychee` link-check across `SPEC.md`, `THREAT-MODEL.md`, `SECURITY.md`, and `README.md`. The binary is a plain `fn main()` — there is no `tokio` dependency at the cipherpost layer (uses `pkarr::ClientBlocking`).
2323

24+
**Do not hardcode test counts in prose** (CLAUDE.md, FAQ, READMEs). They rot within days of every change and have been wrong three times; run the command for the current number instead of writing it down.
25+
2426
**MSRV: rust 1.88** (matched by `rust-toolchain.toml` and `.github/workflows/ci.yml`). Bumped from 1.85 at v1.1 close to resolve RUSTSEC-2026-0009 (`time 0.3.41``0.3.47` DoS-via-stack-exhaustion fix), which required rustc 1.88. Cipherpost is a binary CLI — MSRV constraints from downstream library consumers do not apply.
2527

2628
**Pre-push hook.** Every clone runs the full CI gauntlet locally before a push reaches GitHub via `bash scripts/setup-hooks.sh` (one-time per clone). The hook lives at `.githooks/pre-push` and mirrors `.github/workflows/ci.yml` job-for-job. GitHub Actions minutes are not free; this hook keeps them spent only on green builds. Escape hatches: `git push --no-verify` for the whole hook, or `CIPHERPOST_SKIP_NEXTEST=1 git push` for individual gates.

FAQ.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ Simply copy `~/.cipherpost/secret_key` to a secure location (encrypted USB, pass
156156

157157
<summary>Is Cipherpost production-ready?</summary>
158158

159-
As of v1.1 (shipped 2026-04-26), the full PRD v1 scope ships: the core protocol, all four typed payload variants (`GenericSecret`, `X509Cert`, `PgpKey`, `SshKey`), `--pin` and `--burn` encryption modes, and non-interactive automation. The repo is now at crate `1.2.0-alpha` with **v2 derived-key addressing** (`PROTOCOL_VERSION = 2`), which publishes each share and receipt under its own key and lifts the v1.1 one-record-per-key ceiling (see the packet-budget question above). 335 tests pass under `cargo nextest run --features mock` (347 under `--all-features`); the full PRD v1 requirement set is validated across v1.0 + v1.1.
159+
As of v1.1 (shipped 2026-04-26), the full PRD v1 scope ships: the core protocol, all four typed payload variants (`GenericSecret`, `X509Cert`, `PgpKey`, `SshKey`), `--pin` and `--burn` encryption modes, and non-interactive automation. The repo is now at crate `1.2.0-alpha` with **v2 derived-key addressing** (`PROTOCOL_VERSION = 2`), which publishes each share and receipt under its own key and lifts the v1.1 one-record-per-key ceiling (see the packet-budget question above). The test suite passes under `cargo nextest run --features mock` (and `--all-features`); the full PRD v1 requirement set is validated across v1.0 + v1.1.
160160

161161
Larger payloads shipped **experimentally** in v2-alpha (the off-by-default `large-payload` feature, `--self`-only — the crate is now `1.2.0-alpha.1`); full cross-identity large payloads, signed receipts for large pickup, key import, multiple identities, and destruction attestation remain deferred. The v1 core is suitable for careful use. The v1.1.0 cross-identity round trip has been validated against real Mainline DHT — both via a manual CLI demo and the automated regression test, both passing on the same network with no mocks involved. Evidence is checked in at [`RELEASE-EVIDENCE-v1.1.0.md`](./RELEASE-EVIDENCE-v1.1.0.md). Future releases automatically re-run the same gate via the tag-push workflow at [`.github/workflows/release-acceptance.yml`](./.github/workflows/release-acceptance.yml), so each public version publishes its own real-DHT evidence next to the tag.
162162

docs/design/derived-key-addressing.md

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
# Design: Derived-key packet addressing (lift the one-record-per-key ceiling)
22

3-
> **Status: DESIGN / pre-implementation — FEASIBILITY SPIKE PASSED + COMMITTED.**
4-
> Not shipped. The spike (§14) is committed as two `#[ignore]`'d tests in
5-
> `tests/derived_key_spike.rs` (reproducible via `cargo test --test
6-
> derived_key_spike -- --ignored`), carrying **byte-exact golden vectors**. Its
7-
> crypto deps (`ed25519-dalek` `hazmat`+`digest`, `curve25519-dalek`, `bytes`)
8-
> are **test-only dev-deps**, so the shipped binary stays hazmat-free until Phase 1
9-
> wires derivation into `src/`. Nothing lands in production until the schema (§8)
10-
> is signed off and Phase 1 begins. Touches signed bytes and key derivation.
3+
> **Status: IMPLEMENTED — shipped through Phase 3c (`PROTOCOL_VERSION = 2`, crate
4+
> `1.2.0-alpha.1`); the v1.1 parent-key transport surface was removed in commit
5+
> `8be2567`.** All phases in §13 are DONE. This doc is the design reference for the
6+
> v2 wire format, but where it and the repo could drift, **code + tests are the
7+
> source of truth**`src/derive.rs`, `src/transport.rs::build_derived_signed_packet`,
8+
> SPEC.md §3.8 / §3.4 / §8.4. The crypto deps (`ed25519-dalek` `hazmat`+`digest`,
9+
> `curve25519-dalek`, `bytes`) are now **main dependencies**; the shipped binary uses
10+
> `hazmat::raw_sign` only in `transport::build_derived_signed_packet` (self-verified
11+
> before use). The spike (§14) remains committed in `tests/derived_key_spike.rs` with
12+
> its byte-exact golden vectors.
1113
1214
## 1. Problem
1315

@@ -261,10 +263,17 @@ behind a feature/flag during rollout so v1.1 stays buildable for comparison.
261263
`build_derived_signed_packet`, self-verified before use). No flow wiring yet.
262264
3. **Flow wiring** — shares publish under `derive(sender_pub, share_ref)`;
263265
receipts under `derive(recipient_pub, share_ref)`; lift the one-per-key limits
264-
(re-enable self-receipts, multi-receipt). PROTOCOL_VERSION → 2.
265-
4. **Receipt schema** — apply §8 once; regenerate fixtures + SPEC §8 vector.
266+
(re-enable self-receipts, multi-receipt). PROTOCOL_VERSION → 2. **DONE**
267+
`src/flow.rs` run_send/run_receive/run_receipts on derived keys; parent-binding
268+
check; self-receipts re-enabled (D-SEQ-06); `receipts` requires `--share-ref`.
269+
4. **Receipt schema** — apply §8 once; regenerate fixtures + SPEC §8 vector. **DONE**
270+
(Phase 3c) — slim receipt `{accepted_at, ciphertext_hash, cleartext_hash,
271+
protocol_version, share_ref, signature}`; `verify_receipt` takes `recipient_pub`
272+
as context; `receipt_signable.bin` (263 B) + SPEC §8.2 regenerated.
266273
5. **Docs + real-DHT validation** — SPEC/THREAT-MODEL/README/CLAUDE.md; extend the
267-
manual `real_dht_e2e` harness with a derived-key round trip.
274+
manual `real_dht_e2e` harness with a derived-key round trip. **DONE** — SPEC (incl.
275+
§3.8 + §8.4 vector), THREAT-MODEL, README, FAQ, CLAUDE.md aligned to v2;
276+
`tests/real_dht_e2e.rs` ported to a derived-key round trip (commit `8be2567`).
268277

269278
## 14. Feasibility spike spec (do first)
270279

src/flow.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ pub fn run_receipts(
11971197
.map_err(|e| Error::Config(format!("json encode: {e}")))?;
11981198
println!("{out}");
11991199
} else {
1200-
render_receipts_table(&valid, true)?; // single-receipt audit-detail view
1200+
render_receipts_table(&valid)?; // single-receipt audit-detail view
12011201
}
12021202
Ok(())
12031203
}
@@ -1206,10 +1206,7 @@ pub fn run_receipts(
12061206
/// by share_ref, so there is no multi-row/enumeration form. The recipient pubkey
12071207
/// is the `--from` argument (context), not a receipt field; `purpose` is not
12081208
/// published (bound via cleartext_hash); no `nonce` (v2 slim schema).
1209-
fn render_receipts_table(
1210-
receipts: &[crate::receipt::Receipt],
1211-
_audit_detail: bool,
1212-
) -> Result<(), Error> {
1209+
fn render_receipts_table(receipts: &[crate::receipt::Receipt]) -> Result<(), Error> {
12131210
let r = &receipts[0];
12141211
println!("share_ref: {}", r.share_ref);
12151212
// format_unix_as_iso_utc already appends " UTC"; no extra suffix needed.

0 commit comments

Comments
 (0)