Skip to content

security-remediation: gateway/SDK/witness-network hardening + productization#396

Merged
bordumb merged 11 commits into
mainfrom
security-remediation
Jul 20, 2026
Merged

security-remediation: gateway/SDK/witness-network hardening + productization#396
bordumb merged 11 commits into
mainfrom
security-remediation

Conversation

@bordumb

@bordumb bordumb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Security-remediation epics 1–7: gateway enforcement & spend-log audit quality, published verifier SDK (anchors, freshness, version honesty), witness-network productization, identity/CLI first-run + error corpus, paste-integrity CI lint, error-docs completeness lint.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
83b90ee3 ❌ Failed No signature found
94952de2 ❌ Failed No signature found
e8c6a359 ❌ Failed No signature found
c1a7f2a7 ❌ Failed No signature found
176c0060 ❌ Failed No signature found
aa09c639 ❌ Failed No signature found

Result: ❌ 0/6 commits verified


How to fix

Commit 83b90ee3 has no Auths signature (no Auths-Id/Auths-Device trailer).

1. Install auths

macOS: brew install auths
Linux: Download from releases

2. One-time setup (creates your identity and configures Git)

auths init

3. Sign this branch and push

auths sign origin/main..HEAD
git push --force-with-lease

For CI to verify the signer, commit an identity bundle:

auths id export-bundle --alias main --output .auths/ci-bundle.json --max-age-secs 31536000

Quickstart →

bordumb and others added 7 commits July 20, 2026 16:53
…quality

Wire the three unenforced bounds and make each audit verdict state what it proved.

- 1.1 wrap --ttl now threaded into `id agent add --expires-in` (chain.rs, proxy.rs,
      main.rs, replay.rs) so TTL is anchored as an expiry seal the verifier already
      enforces (AgentExpired). Previously parsed + printed in the banner, enforced nowhere.
- 1.2 verify-spend cross-checks the signed `Auths-Settle-Ref`; new counterparty-mismatch
      verdict + a verified `counterparty` field on the report (audit.rs, evidence types + schema).
- 1.3 truncated/rolled-back log no longer audits bare `consistent` — `self-consistent`
      with an explicit head-pin/completeness caveat.
- 1.4 portable `--json` verdict object + MCP error `data` payload for live refusals.
- 1.5 MISSING/REORDERED/DUPLICATE distinguished; positional record index.
- 1.6 receipt display fields not vouched-for unless signed.
- 1.7 fs.read read-family tool mapping (gate.rs).
- 1.8 budget boundary rule (`>` vs `>=`) surfaced in --budget help.
- 1.9 revocation KEL re-resolve (close the session cache window).
- 1.10 deterministic/announced spend-log path.
- 1.11 metered-0c / empty log no longer reads as a clean audit.
- 1.12 malformed-log voice: corrupt vs tampered distinguished.
- 1.13 wrap keychain-alias idempotency.
- 1.14 doubled verdict-word fix (main.rs).
- 1.15 KEEP+LOCK regression tests: amount tamper caught, exact-token scope incl.
      Cyrillic/prefix/suffix/`../` near-misses, signature binding, TOCTOU race.

Tests: new tests/e2e/test_mcp_gate_bounds.py (+ helpers/mcp_downstream.py);
extended test_mcp_spend_log_audit.py and test_receipts_threat_model.py.

Spec: product-findings/remediation/EPIC-1.md. Not locally built — GitHub CI is the gate.
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
…ness, version honesty

Make the embedded witness anchor a real gate and report the assurance tier, so a
relying party never launders a signed claim into a witnessed fact.

- Embedded anchor is now a GATE (auths-evidence): a bad / foreign-witness /
  threshold-unmet / duplicated / removed-when-witness-claimed anchor fails the WHOLE
  document with a named check; an AnchorSummary (tier, witnesses, threshold, failed
  check) rides every verdict. verify_embedded_anchor no longer returns Ok on absence.
- Freshness is a first-class verdict field against an injected clock: a future as_of
  is rejected; fresh|unknown|stale; the strict policy denies offline-Unknown for a
  witness-tier claim. anchor:null / live / stale are legibly distinguishable.
- Head binding: head_bound is true only when a verified anchor cosigns the head; the
  monotonicity rule is documented as load-bearing only at the witness tier.
- napi verdict shape (packages/auths-node) surfaces anchor / freshness / headBound and
  the AnchorInvalid -> {status, failedCheck} arm; cumulativeCents documented as a signed
  claim, witnessed only at a non-stale witness anchor (market display gate is separate).
  version() now reads the real package version (version.workspace = true).
- Call sites updated for the new signatures: packages/auths-node and packages/auths-python
  evidence bindings (clock + opts + new verdict fields).
- Tests: anchor-forgery + freshness + head-binding battery
  (auths-evidence/tests/cases/attestation.rs; auths-anchor test-support builders in
  finalize.rs/lib.rs), a freshness 24h-boundary lock, and napi verdict-shape + version
  contract tests.

Release remains a user step: bump workspace version 0.1.12 -> 0.1.13, rebuild the committed
.node, and push v0.1.13 so publish-node.yml ships it. A registry-backed anchor e2e is
deferred (needs a live witness lab, unbuildable under the CI-is-the-gate policy).

Spec: product-findings/remediation/EPIC-2.md. Not locally built — GitHub CI is the gate.
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
Make the witness node refuse to serve unsynced, give operators a working conformance +
onboarding path, and give a duplicity victim something portable to run.

- Registry-mount readiness (witness-node): build_state probes the registry with a sentinel
  and refuses to bind on an unsynced/absent registry instead of 422-ing every submission;
  PartyResolveError split into RegistryUnavailable (503, operator) vs IdentityNotInRegistry
  (422, stranger), classified structurally — no libgit2/registry path leak. The anchor
  router is lifted into anchor_role.rs so it is testable via oneshot.
- deploy/witness compose defaults WITNESS_REGISTRY (${..:-./registry}) so `docker compose
  up` no longer dies at paste time; README documents the registry-sync prerequisite.
- .gitignore re-includes .cargo/config.toml and the alias ships, so `cargo xtask` works
  from a fresh clone (the alias file was previously gitignored).
- `auths anchor verify <proof>` wraps DuplicityProof::verify (exit 0 proven / non-zero on
  tamper) — the portable, offline duplicity-proof check a victim or regulator can run.
- Equivocation is durably recorded (<data_dir>/duplicity/<seed>.json) and re-served at
  GET /v1/duplicity/{seed}; auths-monitor pushes AUTHS_ALERT_WEBHOOK on duplicity and
  withholding (tracing unchanged when unset) — the proof no longer goes only to the cheater.
- Exact replay (AlreadyAnchored -> 200 no-op) distinguished from a true rollback
  (IndexRollback -> 422); the seed param is shape-validated to one named 400 (no "Odd number
  of digits"); conformance echoes the certified node's witness_did and creates --emit dirs.
- release.yml builds + stages the witness-node binary (previously shipped in no artifact).
- Tests: HTTP-level anchor.rs (readiness 503-not-422, 409 duplicity, rollback, seed
  validation), DuplicityProof::verify round-trip + tamper, e2e test_anchor_duplicity.py
  (offline CLI verify + tamper, withholding webhook, readiness refusal).

Note: on this machine .cargo/config.toml is force-added past a global gitignore; the repo
.gitignore fix works on CI/fresh clones. A live-node submission e2e is deferred (no shipped
anchor-submit tool) — guarantees are locked at the protocol/service/HTTP level instead.
Spec: product-findings/remediation/EPIC-3.md. Not locally built — GitHub CI is the gate.

Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
Fix headless identity first-run and make the error corpus lookup-able.

- Headless init no longer hangs: keychain backend selection is TTY/interactivity-aware
  (auths-core keychain + init/gather) — a non-interactive run auto-selects the file backend
  (or fails fast naming the backend env var) instead of blocking forever on a Touch-ID prompt.
- One state-root resolver: init/sign and verify/doctor now resolve the same registry root
  (factories/mod, verify_commit, unified_verify, doctor), so a freshly-signed commit verifies
  instead of "Device KEL could not be resolved" against a different root.
- CI passphrase generator (ci/types) satisfies its own policy (the encryption validator) — the
  documented CI path no longer fails on its own generated passphrase.
- Errors point somewhere real: the renderer + error_lookup route to the working offline
  `auths error show <CODE>` (and accept a bare `E4203`) instead of the 404 docs URL.
- Error-corpus honesty: retired pre-KEL SSH/allowed-signers advice rewritten to the KEL-native
  flow (commit_error); a missing key alias reports "no such alias", not "keychain unavailable"
  (signing service/workflow); the untyped "Device KEL could not be resolved" and the bare
  AUTHS-E0031 are registered/typed; the gateway error namespace aligned (mcp-server).
- gen_error_docs parses rustfmt-wrapped multi-line suggestion arms so every code carries its
  next step; a new xtask check_error_codes lint fails CI if any emitted AUTHS-E code is
  unregistered or lacks a suggestion.
- Tests: identity-lifecycle + git-signing e2e (headless-init-no-hang, sign->verify passes,
  isolated via AUTHS_REPO + file keychain); the CI passphrase satisfies the validator; every
  registered code round-trips through `auths error show`.

Spec: product-findings/remediation/EPIC-4.md. Not locally built — GitHub CI is the gate.
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
Kill the FINDING-000 class at the source: a new `cargo xtask check-paste-integrity --path <dir>`
scans, in one binary runnable against any of the three repos, every fenced shell block
(bash/sh/console/shell/zsh in .md/.mdx/.mdoc) and every copyable site string (`copy="..."`,
<Prompt>/<BashLines> in .ts/.tsx, HTML-entity-decoded first) and fails CI on: an <...> angle
placeholder in a copyable command, a bare $VAR with no matching export/assignment in the block,
or a leading `$ ` prompt glyph. A block opts out with a `paste-integrity: illustrative` marker.

Mirrors the existing check_*.rs style (walkdir + regex_lite, per-violation lines, bail on any
hit); wired into xtask main.rs as `check-paste-integrity`. Unit battery locks the placeholder-
flagged and paste-clean-passes cases plus the buyer-integration-pane positive control.

Spec: product-findings/remediation/EPIC-6.md. Not locally built — GitHub CI is the gate.
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
A new `cargo xtask check-error-docs-published` guards drift between the error registry and the
generated docs/errors/ pages: every registered AUTHS-E code must have a docs/errors/AUTHS-E<code>.md
page, and every page must map to a registered code (no orphans). Enumerates codes via the same
registry path check_error_codes uses; distinct from that lint (registration + suggestion coverage).
Self-contained to the auths repo — the docs.auths.dev publish of the corpus is a separate step.
Wired into xtask main.rs; unit battery covers missing-page, orphan-page, and complete-set-passes.
Passes against the current tree (373 codes / 373 pages).

Note: this is only the auths-side lint for epic 7. The auths-docs content rewrites (publish-receipts
artifact, anchor-page version banners, error-page publish, freshness window, witness key/URL, etc.)
are deferred — see product-findings/remediation/EPIC-7.md, to be applied after the witness-network
docs reorganization lands.

Spec: product-findings/remediation/EPIC-7.md. Not locally built — GitHub CI is the gate.
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
- gate ShellBlock::copy with #[cfg(test)] (used only by tests; dead in a
  plain build under -D warnings, breaking the schema + tree-sitter jobs)
- collapse nested ifs into let-chains (clippy::collapsible_if) in
  check_anchor_discipline, check_constant_time, gen_error_docs
- add the Acceptance::AlreadyAnchored arm to the accept.rs duplicity test
  (non-exhaustive match E0004 after the idempotent-replay variant landed)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
@bordumb
bordumb force-pushed the security-remediation branch from 83b90ee to c7f1889 Compare July 20, 2026 15:54
@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
c7f18894 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
91104409 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c0a59a21 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
29a128a6 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
497b33ee ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc78a185 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
3073bc5b ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp

Result: ✅ 7/7 commits verified

The AST-walking lint checkers nest tree-sitter node guards deliberately;
collapsing them into let-chains reads worse. Added to the existing
tooling-lint allow block, alongside print_stdout/unwrap_used/etc. Clears
the remaining collapsible_if failures across check_curve_agnostic,
check_rfc6979, check_verify_path_completeness, gen_docs, gen_error_docs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
bc7083cf ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c7f18894 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
91104409 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c0a59a21 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
29a128a6 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
497b33ee ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc78a185 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
3073bc5b ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp

Result: ✅ 8/8 commits verified

…lockfile

- auths-receipts api/error.rs: map the new EvidenceError::AnchorInvalid
  {code, detail} to a 422 (E0004 non-exhaustive match; the variant landed
  with embedded-anchor verification)
- registry.rs error suggestions: reference real flags — pairing relay is
  `auths device pair --registry <url>` (no --mode); replace the
  non-existent `auths verify --trust` with `auths trust pin` guidance
  (command-drift lint)
- packages/auths-python/Cargo.lock: add auths-anchor + the auths-evidence
  → auths-anchor edge the pre-commit hook regenerates

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
fab78d24 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc7083cf ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c7f18894 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
91104409 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c0a59a21 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
29a128a6 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
497b33ee ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc78a185 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
3073bc5b ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp

Result: ✅ 9/9 commits verified

The command-drift fix belonged in the AuthsErrorInfo::suggestion() impls,
not the generated registry.rs — editing only the generated file left the
error docs out of date (gen-error-docs --check). Fix the source so
regeneration is a no-op AND won't reintroduce the bad flags:
- auths-core PairingError (QrCodeFailed, MdnsError): relay via
  `auths device pair --registry <url>`
- auths-sdk auth TofuRequiresInteraction: `auths trust pin` guidance

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
fd9ce449 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
fab78d24 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc7083cf ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c7f18894 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
91104409 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c0a59a21 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
29a128a6 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
497b33ee ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc78a185 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
3073bc5b ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp

Result: ✅ 10/10 commits verified

- cargo fmt wrapped the longer Some("...") suggestion lines (fmt --check --all)
- docs/errors/AUTHS-E3202/E3205/E5554.md: sync the generated per-code docs
  to the new source suggestions (gen-error-docs --check)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
@github-actions

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
a75b7a4e ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
fd9ce449 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
fab78d24 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc7083cf ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c7f18894 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
91104409 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
c0a59a21 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
29a128a6 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
497b33ee ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
bc78a185 ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
3073bc5b ✅ Verified Signed by did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp

Result: ✅ 11/11 commits verified

@bordumb
bordumb merged commit 43daae6 into main Jul 20, 2026
24 of 26 checks passed
@bordumb
bordumb deleted the security-remediation branch July 20, 2026 16:44
bordumb pushed a commit that referenced this pull request Jul 20, 2026
test_unsigned_commit_advice_is_kel_native has been red since #396: it asserts
`auths verify` gives KEL-native advice for an UNSIGNED commit, but make_commit
runs a bare `git commit` — and the init_identity fixture (`auths init --profile
developer`) configures global commit signing plus a commit-trailer hook, so the
commit is signed and verify reports it verified instead of advising.

Give make_commit a `sign` flag; with sign=False it ignores global/system git
config (neither commit.gpgsign nor the hooks path apply) and passes
--no-gpg-sign, producing a genuinely bare commit. Pre-existing failure,
unrelated to this branch's changes — folded in so CI goes green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13
bordumb added a commit that referenced this pull request Jul 20, 2026
* witness-node: sync-registry subcommand (fetch refs/auths/*)

The anchor role resolves party keys from the tree at refs/auths/registry,
but a plain `git clone` fetches only refs/heads/* — so an operator who
cloned the registry still 422s every submission (this is the RT-2 root
cause: auths-w1's /data/registry has no refs/auths/registry).

Add `witness-node sync-registry --from <url> --registry <dir>`: init the
dir, force-fetch +refs/auths/*:refs/auths/*, and confirm the result is
resolvable (registry_ready) before returning. HTTPS in-process via git2's
own transport (the workspace git2 is transportless; opt in here as
packages/auths-node does). Mirrors the SDK's fetch_registry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

* xtask: generate the verdict contract manifest + drift gate

Verdict strings are defined once, in a code() method per emitting enum, but
downstream consumers hardcode copies — so a rename silently breaks them (a
consistent → self-consistent rename broke the @auths-dev/mcp release gate).

Add `xtask gen-contracts`: scan each enum's inherent code() for the kebab
literals it emits and write them, namespaced by emitter, to
schemas/contracts-v1.json. Gate it in CI with the same generate-then-
`git diff --exit-code` idiom the JSON schemas use, so a rename becomes a
visible, must-commit change. Unit tests assert the extraction against source
(they run in CI where I can compile).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

* sdk(node): ship the verdict manifest in conformance/verdicts.json

Extend sync-conformance to copy schemas/contracts-v1.json into the package's
conformance/ dir (alongside statuses.json), so a JS/TS consumer can pin every
verdict string to the exact contract the installed SDK version was built from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

* deny: allow git2 in auths-witness-node (registry sync)

The witness reads party keys from refs/auths/*, which it now fetches with
git2 (A1). auths-witness-node is a server/adapter binary — exactly the
storage/adapter layer the git2 ban already permits — so add it to the
wrappers allowlist.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

* xtask: gen-contracts skips comment lines in code() bodies

The audit code() has a `// "self-consistent" …` note above the arm; the
scanner pulled the literal out of the comment too, emitting a phantom
duplicate. Skip comment-only lines (no code, no real brace scope), and add a
per-family uniqueness assertion so a future leak fails the unit test, not just
the CI diff.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

* deploy(witness): sync the registry with refs/auths/*, not git clone

The RT-2 root cause: every deploy path told operators to populate the party
registry with `git clone`, which brings only refs/heads/* — so the refs/auths/*
KELs the anchor role resolves keys from never arrived, and every submission
422'd. Point all four paths (Compose, README bare-metal, Helm, Terraform) at
the new `witness-node sync-registry` command, run before/alongside serve.

Also fix stale/broken serve flags that never matched the binary:
- Helm + Terraform passed `--anchor-store` (no such flag) and omitted
  --data-dir/--registry/--witness-name; correct them and add a registry
  init container (Helm) / pre-serve sync (Terraform).
- Terraform ran the anchor store on `--tmpfs /data` — an amnesiac witness that
  co-signs a fork after any restart. Move it to a durable host dir.
- Compose mounted the registry :ro, which blocks the in-place sync; make it
  writable (serve only reads it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

* test(witness): match compose registry mount by var, not :ro

The registry mount is now read-write so the in-place sync can populate it; the
compose-default test located the line by the literal `:/registry:ro`, so
dropping :ro made it fail to find the line. Match on ${WITNESS_REGISTRY}
instead and assert the /registry mount target explicitly — the test's real
subject (a `:-` default, never `:?`) is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

* test(e2e): make the unsigned-commit test commit genuinely unsigned

test_unsigned_commit_advice_is_kel_native has been red since #396: it asserts
`auths verify` gives KEL-native advice for an UNSIGNED commit, but make_commit
runs a bare `git commit` — and the init_identity fixture (`auths init --profile
developer`) configures global commit signing plus a commit-trailer hook, so the
commit is signed and verify reports it verified instead of advising.

Give make_commit a `sign` flag; with sign=False it ignores global/system git
config (neither commit.gpgsign nor the hooks path apply) and passes
--no-gpg-sign, producing a genuinely bare commit. Pre-existing failure,
unrelated to this branch's changes — folded in so CI goes green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Auths-Scope: sign_commit
Auths-Id: did:keri:EB5cPHY0t-ejNC_rUzPS1dclTvd6kG-R9mQzjozCuGgd
Auths-Device: did:keri:EO1cBsYoV5izKvdIL6TstN5TOQl1hYN3WnhtAOh1lwAp
Auths-Anchor-Seq: 13

---------

Co-authored-by: claude-release <claude@auths.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant