Skip to content

Dev keri compliant devices#230

Merged
bordumb merged 102 commits into
mainfrom
dev-keriCompliantDevices
Jun 6, 2026
Merged

Dev keri compliant devices#230
bordumb merged 102 commits into
mainfrom
dev-keriCompliantDevices

Conversation

@bordumb

@bordumb bordumb commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

No description provided.

bordumb added 30 commits June 1, 2026 01:42
…10,11,12)

A.1 remove in-body dt (timestamps via external slice in validate_kel_with_policy)
A.2 sign over finalized event bytes (serialize_for_signing no longer clears d/i)
A.4 threshold satisfiability (Threshold::validate_satisfiable; typed nt over commitments; fix weighted-collapse)
A.6 P-256 verkey CESR 1AAJ transferable / 1AAI non-transferable (KeriPublicKey::P256{key,transferable})
A.8 seal-shape: delete SealType, add EventLocation seal, gate MerkleRoot/RegistrarBacker behind seal-extensions, strict deser
A.9 basic-derivation inception i must equal k[0]
A.10 rotation backer-delta validation (br subset prior; ba not duplicating survivor)
A.11 reject legacy short version strings
A.12 non-transferable != abandoned at inception
Two edits from the Epic A batch were dropped by editor string-mismatches:
- events.rs lost `use std::fmt;` (needed by KeriSequence Display) during A.8
- validate.rs A.10 used ValidationError::InvalidBackerDelta without defining it
auths-keri --all-features now builds; 155 lib tests pass (default + seal-extensions).
Prevent silent ECDSA-DER / digest drift from minor bumps. Versions match
Cargo.lock exactly (no lock churn). rand/rand_core left multi-version (intentional).
KELs are stored as Git objects; an automatic git gc that prunes an
unreferenced object is silent identity loss. GitRepo::init now sets
gc.auto=0 and gc.pruneExpire=never. Test init_disables_gc.
A rotation whose c[] flips the registrar-backer role (RB<->NRB) while a
prior backer survives is now rejected with ValidationError::BackerRoleFlip.
RB and NRB carry different backer-list semantics, so a partial br/ba delta
across a role change would leave a survivor governed by semantics it was
never admitted under. A role flip must rebuild b[] (cut every prior backer);
an empty c[] inherits the role and cannot flip.

Adds the backer_role() resolver, the BackerRoleFlip validation error, and a
rotation_rejects_silent_backer_role_flip test. Also drops an unnecessary
mut on the adjacent backer-delta test.

DID (DelegateIsDelegator) honoring in validate_delegation is intentionally
deferred: it is a non-standard, never-consumed trait whose seal-waiver
semantics need a spec decision before implementation.
…ectors

SPEC.md is the normative wire-format/validation specification for the KERI
substrate: emitted field sets per event type (icp/rot/ixn/dip/drt), CESR
derivation codes (Ed25519 D/B, P-256 1AAJ/1AAI), thresholds, config traits,
seals, and the rct receipt shape. Every rule is marked ENFORCED or PENDING
with the task that will land it, so closed findings cannot silently regress.
Records the two resolved-but-divergent points honestly: the pre-rotation
commitment domain (raw bytes today; CESR-qualified qb64 is the resolved
target, pending) and dual-index signatures (pending).

interop_vectors.rs executes the SPEC field-set table for all five event
types — exact field set, documented order, no legacy dt/x — and round-trips
the three finalizable types. This is the structural, cross-type complement
to the icp-only keripy_interop checks and the oracle that the H.3 KERIox
cross-impl gate will build on.
… wire format

Updates the two required-reading architecture docs to match the substrate as
it actually serializes and verifies today:

- Event tables: drop the in-body signature field 'x' (signatures are
  externalized as CESR attachments) and the implied in-body timestamp; add
  the config-traits field 'c'; fix the rotation table to show backer deltas
  'br'/'ba' instead of a full 'b' list.
- SAID/signing: SAID is computed with 'd'/'i' placeholder-filled (not
  cleared), and signatures are over the finalized event bytes, not a cleared
  skeleton.
- Seals: replace the application-level '{d,type}' seal model with the real
  structural KERI seal variants (Digest, SourceEvent, KeyEvent,
  EventLocation, LatestEstablishment), noting the seal-extensions gate.
- Key encoding: document the resolved P-256 verkey codes 1AAJ (transferable)
  / 1AAI (non-transferable) alongside Ed25519 D/B, everywhere a lone 1AAI
  previously implied it was the only P-256 code.

Points readers to SPEC.md as the normative source. No code changes.
WitnessAgreement::submit_event collapsed a weighted bt via
bt.simple_value().unwrap_or(0), so a weighted backer threshold became 0 and
the event was accepted immediately with zero receipts. The tracker now keeps
the designated backer list (b[] order) and the typed Threshold, maps each
receipted backer AID to its b[] index, and decides quorum with
Threshold::is_satisfied over those indices — mirroring the typed pre-rotation
check. A receipt from a non-designated backer contributes no index.

submit_event now takes the backer AID slice instead of a bare count. Adds the
weighted_bt_requires_quorum regression test (two of three 1/2-weighted backers
required); existing simple-threshold tests updated to pass the backer list.
WitnessAgreement has no callers outside this module, so the signature change
is contained.
Audit-only deliverable: records consumers and build/CLI impact for
auths-infra-rekor, auths-scim, auths-radicle, auths-mobile-ffi. Nothing
deleted or gated.

Corrects a stale spec claim: auths-infra-rekor client.rs is NOT stubbed —
build_dsse and parse_entry_response are implemented (real DSSE envelope +
inclusion-proof/checkpoint parsing, 0 todo markers). It is an unconditional
auths-cli dependency behind 'auths artifact sign --log sigstore-rekor';
deleting it breaks the default build. The open item is the live Rekor demo
(H.6), not the code.

scim/radicle have no workspace consumers (radicle is under active WIP);
keep both, revisit post-launch (H.5). mobile-ffi A.5 reroute is deferred —
its lib.rs carries the user's CanonicalDid WIP, so the dedup can't be cleanly
applied yet.
Every remaining task in epics B-H is blocked on one of: the in-flight
DeviceDID->CanonicalDid refactor (entangles ~20 tasks across auths-id/sdk/cli/
verifier/core), six design decisions (A.3 serde-default, A.7 commitment domain,
A.13-DID semantics, C m/n default, B dual-index gating, A.5 keep/quarantine),
or external infra (D.5 witness, H.3 KERIox CI, H.6 Rekor demo, H.5 issue
filing). Documents the decision options + recommendation for each so the
remaining work can be unblocked quickly. No code change.
…G.1)

verify_with_capability on a single attestation only checked capability
presence; a standalone delegated attestation got no scope-down. Adds
verify_delegated_with_capability: when delegated_by.is_some() it enforces
capability-subset, expiry-within-parent, and delegator-not-revoked against the
caller-resolved delegator, and FAILS CLOSED (DelegatorUnresolved) if the
delegator isn't supplied. Core check is the pub(crate) enforce_delegation_scope
helper. Additive method — existing verify_with_capability signature unchanged,
so FFI/WASM bindings are untouched (the FFI error map has a catch-all).

New AttestationError variants CapabilityEscalation / DelegationOutlivesParent /
DelegatorRevoked / DelegatorUnresolved (E2019-E2022). Tests: escalation,
outliving-parent, revoked-delegator, within-scope, and fail-closed-without-
delegator — all green; clippy --all-features clean.
…gence (D.6)

New tests/cases/witness_flows.rs drives the witness pieces together as a
validator would: a 2-of-3 WitnessAgreement quorum accepting an event; a
recovery rotation superseding a first-seen interaction (and an interaction
failing to displace it); two diverging local views converging on the same
recovery rotation; and a SignedReceipt round-tripping through the Git-trailer
encoding with the typed t='rct' surviving (D.4). 4 tests, clippy clean.
Replaces the stale unblock list (the refactor it described is now committed)
with a context-free pickup doc: orientation + commit/signing mechanics + gates,
the FINAL spec-compliant decisions (A.3 require-d, A.7 qb64 commitment, A.13
remove DID, C.4 configurable-default-not-hardcoded + platform floor, B
code-directed parser + diverging-index dual sigs, A.5 reroute), a dependency
DAG, per-task gotchas (D.1 signing-domain, E.1 sync-bridge + clippy-sync,
F.1/F.4 key-material handling, A.14 churn), the still-blocked infra/user items,
and a done log. Builds straight from this + the .flow specs.
Captures: interop/proofs are validation layered after the build, with two
fold-ins so a fresh session doesn't redo work — A.16 fixtures come FROM keripy
(so A.16 doubles as A.7's interop proof), and B's target fixture is a
keripy-generated key-removal rotation written FIRST (implement against the
reference's bytes, not prose). Plus the early P-256/keripy support probe and
the layered-after ladder (proptest invariants incl. low-s malleability, the
H.3 cross-impl gate, optional TLA+ duplicity model). Notes which expert
questions collapse into tests vs the two that genuinely remain.
Proves cesride 0.6 produces byte-identical CESR primitives to keripy: the
Ed25519 verkey qb64 (DAAB... CESR alignment, not naive D+base64) and the
Blake3-256 digest over the verkey's qb64b. This is the foundation for aligning
our wire encoding (currently a naive base64 scheme behind the default build)
to keripy via CesrV1Codec, so KEL events become byte-interoperable.

Discovered via the keripy interop harness: our naive 'D'+base64 verkey
(DAAEC...) and naive SAID encoding diverge from keripy's CESR qb64 — our event
SAIDs do not match keripy. Routing through CesrV1Codec (this test confirms it
matches keripy) is the fix.
keripy interop validation revealed our wire encoding is naive base64, not
CESR qb64 alignment — keripy rejects our events (our SAID EEpOF... != keripy
EBKTh...; our verkey DAAEC... != keripy DAAB...). User chose Option A (align to
keripy). Documents the proven fix (route through CesrV1Codec; cesride 0.6 ==
keripy 1.3.4, pinned in commit 9354fba) and the one-atomic-commit re-foundation:
un-gate the codec, switch keys.rs/said.rs/crypto.rs + ~29 naive format! sites to
cesride, regenerate ~41 fixtures + icp.bin from keripy, gate on the keripy
subprocess test. A.7/A.16 collapse into this wave; it blocks B/C interop.
…o_qb64 (Wave 0)

First safe increment of the CESR-encoding alignment (Option A). Adds the
always-available cesr_encode module (encode_verkey/decode_verkey/
encode_blake3_digest/verkey_code) wrapping cesride, plus KeriPublicKey::to_qb64.
These produce keripy-1.3.4-identical qb64 (DAAB... alignment, not naive
D+base64), pinned by cesr_encode::tests::encode_decode_matches_keripy. cesride
is non-optional so these are in the default build, unlike the feature-gated
codec module. No behavior flip yet — the event/key/digest paths still use the
naive scheme; swapping them onto these helpers + regenerating fixtures is the
next step.
…ommitment (Wave 0, part 1)

Type-driven step toward CESR alignment: change `compute_next_commitment(&[u8])`
and `verify_commitment(&[u8], _)` to take `&KeriPublicKey`, so the curve travels
WITH the key instead of being re-supplied (or guessed) at 40 call sites. This is
the durable fix — a 'key without a curve' is now unrepresentable at the boundary;
the next part flips the internals to hash the cesride qb64 with no further
call-site churn because the curve is already in hand.

VALUE-PRESERVING: the internals still hash the raw verkey bytes, so every
commitment/SAID value is unchanged — 892 tests pass, no fixture regen.

Bridges added so call sites pass what they already hold: KeriPublicKey::ed25519
/ ::from_verkey_bytes(bytes, curve), and GeneratedKeypair::verkey() (parses its
cesr_encoded). The sdk rotation path now USES its previously-ignored
`new_next_curve` param; the verify path uses ParsedKey's TypedSeed curve.

Clippy --all-targets --all-features -D warnings clean; packages clippy clean.
…Wave 0, part 2a)

Flip compute_said and compute_next_commitment from naive 'E'+base64url to the
cesride CESR digest encoding. Our event SAIDs now match keripy 1.3.4 byte-for-
byte: the KERIPY_INTEROP=1 subprocess test (keripy parses our icp and recomputes
its SAID) goes FAIL->PASS — previously our SAID EEpOF... != keripy EBKTh...

compute_next_commitment hashes the verkey's CESR qb64 (keripy:
Diger(ser=verfer.qb64b)); the Part-1 typing makes the curve available so this is
a pure internal change. 1458 tests across keri/id/sdk/storage/core/verifier pass
unchanged — they compute SAIDs rather than hardcoding them, so the value change
is non-breaking. Verkey (k[]) encoding alignment is the remaining follow-up.
Records the actual progress: cesride==keripy proven (9354fba), always-on
encoders (74dcf5b), Part 1 typing (6efef5b), Part 2a digests — SAID byte-interop
with keripy PROVEN, FAIL->PASS (2ad5cd0). Details the remaining Part 2b (verkey
k[] encoding: parse + 30 encode sites + auths-crypto key_ops, atomic, then
fixtures) with exact files, the reusable Part-1 bridges, and the gate. Corrects
the earlier 'one atomic ~100-site commit' framing — splitting into typing ->
digest -> verkey kept each green/committable, and the digest flip was
non-breaking because tests compute SAIDs.
… 2b)

Flip every verkey encode/decode from naive base64 to cesride qb64 so k[] is
byte-interoperable with keripy — keripy can now decode our verkeys for signature
checks, not just our SAIDs. Atomic (parse + all encoders together; cesride
silently mis-decodes naive, so there is no safe fallback).

- KeriPublicKey::parse routes through cesride decode_verkey + matter-code mapping
  (Ed25519 / ECDSA_256r1 / ECDSA_256r1N; B / Ed25519N -> UnsupportedKeyType);
  naive decode_base64url deleted.
- All naive verkey encoders flipped to KeriPublicKey::{to_qb64,from_verkey_bytes}
  / cesr_encode::encode_verkey — including several hidden multi-line production
  encoders the single-line grep missed: inception.rs (x3, both create_keri_identity
  entry points), rotate.rs (x2), rotation::parse_next_key, storage identity_adapter.
  cesride added to auths-crypto for cesr_encoded_pubkey.
- rotate.rs now carries typed KeriPublicKey for current keys instead of a hardcoded
  "D", fixing a latent length-guess bug (a P-256 added device would have been
  mis-encoded as Ed25519).
- Broken-by-flip unit asserts (wrong-length / unknown-prefix) updated to the new
  cesride error variant (DecodeError). No fixture regen needed: all-zero verkey
  literals coincide across schemes and icp.bin round-trips unchanged.
- SPEC.md 3.1/3.2 + conformance table updated (A.7 ENFORCED); decisions doc 1.6
  marks Wave 0 (CESR alignment, Option A) complete.

Gates: workspace nextest 2499/2499 (macOS gate: --features test-utils,witness-client);
KERIPY_INTEROP=1 subprocess interop test green (runs keripy 1.3.4); verifier wasm32
green; clippy --all-targets --all-features -D warnings clean on the touched crates.
The curve-agnostic AST lint forbids curve-specific names in production code
outside auths-crypto. auths-test-utils re-exported seeded_p256_keypair, leaking
the curve token a layer up. Drop the re-export; the one consumer (auths-id
attestation golden test) imports it directly from auths_crypto::testing, where
curve-specific helpers belong.

No behavior change. check-curve-agnostic: 0 violations (was 1).
A KERI event must carry its self-addressing identifier; deserialization now
rejects an event with `d` omitted or empty.

- Drop `#[serde(default)]` from `d` on the 5 event structs (icp/rot/ixn/dip/drt)
  so a *missing* `d` fails to parse.
- Give `Said`/`Prefix` a custom `Deserialize` that rejects the empty string (the
  derived impl silently accepted `""`); this also strictly rejects empty
  `i`/`p`/`n[]` on the wire. `Default`/`new_unchecked` (internal placeholders,
  including the SAID-compute placeholder) bypass it, so finalization is unchanged.
- Tests: new wire_requires_d cases (missing/empty `d` rejected; finalized icp
  round-trips); message round-trip helpers now use non-empty placeholder SAIDs.
`ConfigTrait::DelegateIsDelegator` (serde "DID") is a non-standard KERI config
trait whose intended semantics waive the delegation seal. It is never consumed —
`validate_delegation` fail-closes on the anchoring seal regardless — so a dormant
trait that relaxes delegation authorization is a bypass risk if ever honored.
Pre-launch, zero users: delete it.

- Remove the variant and its `#[serde(rename = "DID")]`; update the config-trait
  round-trip test to `["EO","DND","RB","NRB"]`.
- `validate_delegation` / `backer_role` unchanged (no seal waiver added; the
  latter already uses a catch-all match arm).
- Drop `DID` from SPEC.md (the `c` field list, the §5 trait table + paragraph,
  and the conformance table) and from schemas/keri-icp-v1.json.
…(Wave 2, B step 0)

Oracle for Epic B: a 3->2 key-removal rot with two 2A (Ed25519_Big) dual-index
sigers (index/ondex 0/1 and 1/2), authored by keripy and pinned to CESR v1
counters (-AAC) to match auths' serialize_attachment. gen_rot_remove.py records
provenance (not run in CI). The fixtures dir is excluded from the whitespace
pre-commit hooks so the byte-exact bytes are never reformatted.
A rotation signature must bind to both the new-key index and the prior next-key
commitment it reveals. Add prior_index: Option<u32> with
#[serde(default, skip_serializing_if = "Option::is_none")] so single-index sigs
serialize byte-identically (no key emitted when None). None keeps the single-index
code A (ondex == index); Some(j) will drive the dual-index 2A code (B.2). Updated
all 24 construction sites with prior_index: None.
…3, F-33)

parse_attachment no longer assumes a fixed 88-char siger. It reads each siger's
CESR hard code, looks up its full width and ondex size via a private sizage table
(mirroring cesride indexer/tables.rs, whose sizage is pub(crate)), and consumes
exactly that many chars — so a group may mix single-index A (88) and dual-index
2A (92), or curves. prior_index is set from the siger's ondex only for dual-index
codes (os > 0); single-index codes (ondex == index) stay None.

Tests (vs the committed keripy fixture): parses_keripy_rot_remove_attachment
[(0,Some(1)),(1,Some(2))]; mixed_curve_attachment_parses (A + 2A boundaries).
bordumb added 12 commits June 5, 2026 01:35
…ring-join roundtrip

- generate_inmemory_keypair now derives the 32-byte private key curve-aware via
  TypedSignerKey::from_pkcs8 (P-256 scalar or Ed25519 seed), replacing the
  Ed25519-only extract_seed_bytes that rejected the default P-256 curve. Adds a
  regression test covering both curves.
- xfail (non-strict) test_pairing_roundtrip / test_pairing_with_scoped_capabilities
  referencing #219: every pairing-join client (CLI, SDK relay client,
  both bindings) calls the removed `by-code` route while the daemon serves `/lookup`
  (HMAC). The tracking issue frames the by-code-vs-HMAC route decision; the tests
  stay as tripwires that flip to XPASS when the route is reconciled.
Demonstration tests proving the witness-gate behavior the ACDC/TEL plan rests on:
- establishment events (icp/rot/drt) are witness-quorum-gated + fail closed
  (existing e2e), and detect_duplicity catches ixn-level forks;
- but interaction events are NOT quorum-gated ("ixn never gates", validate.rs) —
  so a TEL-anchoring ixn (vcp/iss/rev) reaches Accepted with no receipts of its own.

Finding drives Epic F: F.5 (with F.4 anchoring) must itself quorum-check the
vcp/iss/rev anchoring ixns via KAWA (lifecycle-scoped Option A), so witnessed
issuance + revocation compose under RequireWitnesses. Epic-D witnessing confirmed
usable (no core-gate change needed).
…(keripy byte-interop, both curves)

Holder-bindable Acdc {v,d,i,ri,s,a} in auths-keri: ACDC10JSON protocol tag
(compute_said parameterized via a Protocol enum; all KEL SAIDs unchanged),
most-compact SAID, an authored+SAID'd pinned JSON-Schema-2020-12 capability doc,
and keripy 1.3.4 byte-equal fixtures for P-256 and Ed25519. Honest forward-compat:
top-level `e` is additive layout; selective disclosure (u/A) is a SAID-breaking v2.
…validation (keripy byte-interop)

vcp/iss/rev event types in auths-keri tel.rs (backerless NB), strict insertion-order
SAID via the F.1 Protocol-parameterized engine, validate_tel chain validation
(p back-link + monotonic seq), typed TelError, and keripy 1.3.4 byte-equal fixtures
for both curves. Event shapes derived from keripy output (the byte oracle).
…azy vcp)

Persist TEL events and ACDC blobs and anchor vcp/iss/rev to the issuer KEL
atomically. Extend the RegistryBackend with append_tel_event/visit_tel_events/
store_credential (documented atomicity justification: ACDC blob + TEL event +
KEL ixn must land in one commit, mirroring the attestation write-batch
exception). New auths-id/keri/credential_registry.rs: anchor_tel_event reuses
the staged single-author ixn path (author_root_anchor_ixn refactored into
stage_root_anchor_ixn), ensure_registry lazily incepts an idempotent backerless
vcp per issuer, kt>=2 issuer rejected with a typed error. Implemented for Git
and Fake backends; CESR Salt_128 nonce encoder added to auths-keri.
…cycle witness-quorum

verify_credential(acdc, issuer_kel, tel_events, receipts, schema, policy, now)
in auths-verifier: pure replay (no git/network/clock-of-its-own) reporting facts.
Recompute d/a.d, validate a against the embedded pinned capability schema,
confirm iss is KEL-anchored and signed by the signing-time key (rotation after
issue stays valid), and order TEL revocation by KEL anchor position. Implements
the lifecycle witness-quorum decision: under RequireWitnesses, Valid requires
vcp+iss anchoring-ixn quorum and no quorum-reaching rev at/before the
presentation position; under Warn under-quorum is a non-fatal TOFS warning and a
seen rev revokes. KAWA WitnessAgreement runs over the given receipts against the
in-force backer set at each anchor position; detect_duplicity flags issuer-KEL
forks in both modes. WitnessQuorumNotMet names which lifecycle anchor missed.
WASM-clean; both curves; 12 named TDD tests pass.
…y + CLI

New auths-sdk domains/credentials orchestrating F.3 storage + F.5 verification:
issue (issuee-KEL guard, lazy registry, issuer-sign over wire bytes, iss anchor,
kt>=2 typed error), revoke (idempotent rev anchor), list (issued minus revoked),
and verify — the resolution + freshness layer the pure verifier can't be: it
resolves the issuer KEL + TEL and collects witness receipts for every lifecycle
anchor (establishment events + vcp/iss/rev ixns) to the witnessed tip, hands
them to the pure verify_credential, and owns the freshness verdict
(StaleOrUnresolvable, fail-closed) with the resolved as-of attached. CredentialError
is thiserror with AuthsErrorInfo codes. Thin 'auths credential issue|revoke|list|
verify' CLI (--require-witnesses maps to the policy; clock only at the boundary);
routes solely through auths-sdk re-exports so the SDK boundary check stays clean.
8 named TDD tests pass; both curves.
… (no bearer tokens)

Credentials are not bearer tokens: credential-derived authority is honored only
on proof of current control of the subject AID (a.i) by KEL replay plus a fresh
presentation signature. auths-verifier presentation.rs (pure, WASM-safe):
verify_presentation chains F.5's verify_credential, then enforces audience,
nonce/TTL, and the holder signature against the subject KEL's current
(signing-time) key — curve-agnostic, never length-dispatched. Interactive
challenge-response is the v1 default: an SDK-held ChallengeSession issues a fresh
32-byte nonce (ephemeral per-session state, not a global cache) bound to one
(audience, credential-SAID) and consumed once; the subject signs
(cred-SAID || audience || nonce). Non-interactive path binds (audience, purpose,
short-TTL) via injected now, with the within-TTL same-audience replay residual
documented honestly. PresentationVerdict distinguishes HolderNotCurrentKey /
WrongAudience / NonceMismatchOrConsumed / Expired / SubjectKelInvalid /
CredentialNotValid. Delegated subjects supported via a subject_delegator_kel
input (empty fails closed). Both curves; full IPEX deferred. 7 named TDD tests.
…licy bridge

Close the bearer hole at the policy seam: a policy EvalContext can be built only
from a holder-verified presentation (F.8), never a raw ACDC. context_from_credential
in auths-id/policy takes a PresentationVerdict and yields an authority-bearing
context only for Valid; every other variant fails closed (PolicyBridgeError::
NoHolderProof) so caps/role can never flow into a decision from possession alone.
Surface the grant facts on PresentationVerdict::Valid {issuer,subject,caps,role,
expires_at} — populated post-proof inside verify_presentation from the verified
acdc.a + the inner CredentialVerdict, leaving F.5 untouched. Reconcile the two
caps sources via a documented CapsSource precedence rule: the agentscope: seal is
commit-time advisory (offline fast path), the ACDC is authoritative for
credential-grade decisions (ADR text in F.7). Capability round-trips losslessly
legacy agentscope/attestation -> ACDC a JSON -> CanonicalCapability::parse.
Reader migration is F.10, write-path removal is F.11. 4 named TDD tests.
…f attestations

Make every authority/grant reader stop consulting Attestation.{capabilities,role}
so the fields can be deleted cleanly (F.11). Single authority source going
forward: ACDC credential (credential-grade, via the F.6 holder-proof
context_from_credential bridge), agentscope scope-seal (commit-time advisory
fast path, kept), and the KEL scope-seal (org membership role, Epic E).

Removed dead legacy: the whole auths-core/src/policy module (authorize_org_action,
authorize_device, Decision/Action — no callers outside its own tests); the
verifier capability-gate API verify_with_capability / verify_chain_with_capability
/ verify_delegated_with_capability / enforce_delegation_scope caps-subset (+ FFI
exports on both bindings + their tests); org_member attestation caps helpers.
Neutralized: context_from_attestation drops caps/role reads (keeps identity facts;
caps/role now come only via context_from_credential — fail-closed otherwise);
list_org_members/MemberView source role/caps from the KEL scope-seal path, not the
attestation; org find_admin matches by device key + not-revoked (no caps read);
deprecated auths-radicle verify drops its attestation-cap check.

The live capability gates on 'auths artifact verify' (sign_release) and
'auths device verify-attestation --require-capability' are removed (authenticity
verification kept); the credential-grade capability check is now 'auths credential
verify'. Re-introducing an ACDC-sourced capability gate for artifact/device
verification is tracked in #220 (needs an issuer flow). Attestation
fields stay signed/tamper-proof until F.11 removes them.

Cargo.lock: add p256 (auths-verifier F.5 test dep).
@bordumb bordumb self-assigned this Jun 6, 2026
@vercel

vercel Bot commented Jun 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
auths Error Error Jun 6, 2026 2:23am

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
f23ab54b ❌ Failed Signature from non-allowed signer
71f6d26a ❌ Failed Signature from non-allowed signer
4d6e41a0 ❌ Failed No signature found
71777e2d ❌ Failed No signature found
47e3d48b ❌ Failed No signature found
6ea1f3a3 ❌ Failed No signature found
d7caaca8 ❌ Failed No signature found
5accc2ff ❌ Failed No signature found
2a6ec1ab ❌ Failed No signature found
f8c4cf06 ❌ Failed No signature found
9e7ff8e4 ❌ Failed No signature found
cd81d759 ❌ Failed No signature found
162a2200 ❌ Failed No signature found
d85f28d8 ❌ Failed No signature found
27652589 ❌ Failed No signature found
ef45e130 ❌ Failed No signature found
49ecf397 ❌ Failed No signature found
5348612e ❌ Failed No signature found
3de69cd2 ❌ Failed No signature found
c0645467 ❌ Failed No signature found
d9ab31a1 ❌ Failed No signature found
2a766391 ❌ Failed No signature found
5b120cad ❌ Failed No signature found
3035a4af ❌ Failed No signature found
b03ebcb0 ❌ Failed No signature found
8ae752f8 ❌ Failed No signature found
54dff176 ❌ Failed No signature found
6073acb8 ❌ Failed No signature found
59dc5b6a ❌ Failed No signature found
a123298f ❌ Failed No signature found
f0fa1373 ❌ Failed Signature from non-allowed signer
30ace9fd ❌ Failed Signature from non-allowed signer
0aee6436 ❌ Failed No signature found
3ac81ee5 ❌ Failed No signature found
1715c4be ❌ Failed No signature found
d9e9eec5 ❌ Failed No signature found
16259215 ❌ Failed No signature found
c0282186 ❌ Failed No signature found
e7ae53b7 ❌ Failed No signature found
fb1a25bc ❌ Failed No signature found
49587126 ❌ Failed No signature found
2b77ad7d ❌ Failed No signature found
fa261689 ❌ Failed No signature found
83718e5a ❌ Failed No signature found
a5c85a50 ❌ Failed No signature found
1f462ab0 ❌ Failed No signature found
84185870 ❌ Failed No signature found
6050c6c1 ❌ Failed No signature found
549f09ea ❌ Failed No signature found
39d2df30 ❌ Failed No signature found
389de257 ❌ Failed No signature found
170002dd ❌ Failed No signature found
ddb50f98 ❌ Failed No signature found
bb3797ce ❌ Failed No signature found
03852ba4 ❌ Failed No signature found
a1d03524 ❌ Failed No signature found
69f3133f ❌ Failed No signature found
9e6acdff ❌ Failed No signature found
a960d317 ❌ Failed No signature found
f2ccc683 ❌ Failed No signature found
eecbb45e ❌ Failed No signature found
b5f83e0f ❌ Failed No signature found
3f38ddcf ❌ Failed No signature found
723a2324 ❌ Failed No signature found
432dc69e ❌ Failed No signature found
ad919616 ❌ Failed No signature found
a55301b9 ❌ Failed No signature found
9b07f82a ❌ Failed No signature found
b52659af ❌ Failed No signature found
f2d0f7bb ❌ Failed No signature found
8a01f873 ❌ Failed No signature found
405d47f1 ❌ Failed No signature found
fe658ea6 ❌ Failed No signature found
d29862c0 ❌ Failed Signature from non-allowed signer
8fe1d2ab ❌ Failed No signature found
2ad5cd08 ❌ Failed No signature found
6efef5b6 ❌ Failed No signature found
74dcf5bd ❌ Failed No signature found
3dc28a68 ❌ Failed No signature found
9354fba1 ❌ Failed No signature found
f985f6eb ❌ Failed No signature found
508524e5 ❌ Failed No signature found
ad4ae53d ❌ Failed No signature found
5b44f0e5 ❌ Failed No signature found
54a1bc2a ❌ Failed No signature found
aa471f05 ❌ Failed No signature found
68576842 ❌ Failed No signature found
5ac8a434 ❌ Failed No signature found
224af930 ❌ Failed No signature found
3d0a0fd0 ❌ Failed No signature found
0f9c011b ❌ Failed No signature found
ec750122 ❌ Failed No signature found
16cce1f1 ❌ Failed No signature found
79ffea0e ❌ Failed No signature found
45e96b31 ❌ Failed No signature found
adea55fd ❌ Failed No signature found

Result: ❌ 0/96 commits verified


How to fix

Commit f23ab54b is not signed. To sign future commits:

1. Install auths

macOS: brew install auths
Linux: Download from releases

2. Set up signing

auths init
auths git setup

3. Re-sign and push

git rebase HEAD~96 --exec 'git commit --amend --no-edit -S'
git push --force-with-lease

Quickstart →

- regenerate attestation/identity-bundle/keri-icp schemas after caps/role removal
- bump rustls-webpki 0.103.12->0.103.13 for RUSTSEC-2026-0104 (reachable CRL panic)
- drop stale advisory ignores (RUSTSEC-2025-0134, -2026-0098, -2026-0099)
- add pnpm onlyBuiltDependencies: [esbuild]
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
e5e80fca ❌ Failed Signature from non-allowed signer
f23ab54b ❌ Failed Signature from non-allowed signer
71f6d26a ❌ Failed Signature from non-allowed signer
4d6e41a0 ❌ Failed No signature found
71777e2d ❌ Failed No signature found
47e3d48b ❌ Failed No signature found
6ea1f3a3 ❌ Failed No signature found
d7caaca8 ❌ Failed No signature found
5accc2ff ❌ Failed No signature found
2a6ec1ab ❌ Failed No signature found
f8c4cf06 ❌ Failed No signature found
9e7ff8e4 ❌ Failed No signature found
cd81d759 ❌ Failed No signature found
162a2200 ❌ Failed No signature found
d85f28d8 ❌ Failed No signature found
27652589 ❌ Failed No signature found
ef45e130 ❌ Failed No signature found
49ecf397 ❌ Failed No signature found
5348612e ❌ Failed No signature found
3de69cd2 ❌ Failed No signature found
c0645467 ❌ Failed No signature found
d9ab31a1 ❌ Failed No signature found
2a766391 ❌ Failed No signature found
5b120cad ❌ Failed No signature found
3035a4af ❌ Failed No signature found
b03ebcb0 ❌ Failed No signature found
8ae752f8 ❌ Failed No signature found
54dff176 ❌ Failed No signature found
6073acb8 ❌ Failed No signature found
59dc5b6a ❌ Failed No signature found
a123298f ❌ Failed No signature found
f0fa1373 ❌ Failed Signature from non-allowed signer
30ace9fd ❌ Failed Signature from non-allowed signer
0aee6436 ❌ Failed No signature found
3ac81ee5 ❌ Failed No signature found
1715c4be ❌ Failed No signature found
d9e9eec5 ❌ Failed No signature found
16259215 ❌ Failed No signature found
c0282186 ❌ Failed No signature found
e7ae53b7 ❌ Failed No signature found
fb1a25bc ❌ Failed No signature found
49587126 ❌ Failed No signature found
2b77ad7d ❌ Failed No signature found
fa261689 ❌ Failed No signature found
83718e5a ❌ Failed No signature found
a5c85a50 ❌ Failed No signature found
1f462ab0 ❌ Failed No signature found
84185870 ❌ Failed No signature found
6050c6c1 ❌ Failed No signature found
549f09ea ❌ Failed No signature found
39d2df30 ❌ Failed No signature found
389de257 ❌ Failed No signature found
170002dd ❌ Failed No signature found
ddb50f98 ❌ Failed No signature found
bb3797ce ❌ Failed No signature found
03852ba4 ❌ Failed No signature found
a1d03524 ❌ Failed No signature found
69f3133f ❌ Failed No signature found
9e6acdff ❌ Failed No signature found
a960d317 ❌ Failed No signature found
f2ccc683 ❌ Failed No signature found
eecbb45e ❌ Failed No signature found
b5f83e0f ❌ Failed No signature found
3f38ddcf ❌ Failed No signature found
723a2324 ❌ Failed No signature found
432dc69e ❌ Failed No signature found
ad919616 ❌ Failed No signature found
a55301b9 ❌ Failed No signature found
9b07f82a ❌ Failed No signature found
b52659af ❌ Failed No signature found
f2d0f7bb ❌ Failed No signature found
8a01f873 ❌ Failed No signature found
405d47f1 ❌ Failed No signature found
fe658ea6 ❌ Failed No signature found
d29862c0 ❌ Failed Signature from non-allowed signer
8fe1d2ab ❌ Failed No signature found
2ad5cd08 ❌ Failed No signature found
6efef5b6 ❌ Failed No signature found
74dcf5bd ❌ Failed No signature found
3dc28a68 ❌ Failed No signature found
9354fba1 ❌ Failed No signature found
f985f6eb ❌ Failed No signature found
508524e5 ❌ Failed No signature found
ad4ae53d ❌ Failed No signature found
5b44f0e5 ❌ Failed No signature found
54a1bc2a ❌ Failed No signature found
aa471f05 ❌ Failed No signature found
68576842 ❌ Failed No signature found
5ac8a434 ❌ Failed No signature found
224af930 ❌ Failed No signature found
3d0a0fd0 ❌ Failed No signature found
0f9c011b ❌ Failed No signature found
ec750122 ❌ Failed No signature found
16cce1f1 ❌ Failed No signature found
79ffea0e ❌ Failed No signature found
45e96b31 ❌ Failed No signature found
adea55fd ❌ Failed No signature found

Result: ❌ 0/97 commits verified


How to fix

Commit e5e80fca is not signed. To sign future commits:

1. Install auths

macOS: brew install auths
Linux: Download from releases

2. Set up signing

auths init
auths git setup

3. Re-sign and push

git rebase HEAD~97 --exec 'git commit --amend --no-edit -S'
git push --force-with-lease

Quickstart →

pnpm 10 no longer reads the package.json `pnpm` field; onlyBuiltDependencies
must live in pnpm-workspace.yaml to clear ERR_PNPM_IGNORED_BUILDS and let
esbuild's postinstall run.
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
d6378ad0 ❌ Failed Signature from non-allowed signer
e5e80fca ❌ Failed Signature from non-allowed signer
f23ab54b ❌ Failed Signature from non-allowed signer
71f6d26a ❌ Failed Signature from non-allowed signer
4d6e41a0 ❌ Failed No signature found
71777e2d ❌ Failed No signature found
47e3d48b ❌ Failed No signature found
6ea1f3a3 ❌ Failed No signature found
d7caaca8 ❌ Failed No signature found
5accc2ff ❌ Failed No signature found
2a6ec1ab ❌ Failed No signature found
f8c4cf06 ❌ Failed No signature found
9e7ff8e4 ❌ Failed No signature found
cd81d759 ❌ Failed No signature found
162a2200 ❌ Failed No signature found
d85f28d8 ❌ Failed No signature found
27652589 ❌ Failed No signature found
ef45e130 ❌ Failed No signature found
49ecf397 ❌ Failed No signature found
5348612e ❌ Failed No signature found
3de69cd2 ❌ Failed No signature found
c0645467 ❌ Failed No signature found
d9ab31a1 ❌ Failed No signature found
2a766391 ❌ Failed No signature found
5b120cad ❌ Failed No signature found
3035a4af ❌ Failed No signature found
b03ebcb0 ❌ Failed No signature found
8ae752f8 ❌ Failed No signature found
54dff176 ❌ Failed No signature found
6073acb8 ❌ Failed No signature found
59dc5b6a ❌ Failed No signature found
a123298f ❌ Failed No signature found
f0fa1373 ❌ Failed Signature from non-allowed signer
30ace9fd ❌ Failed Signature from non-allowed signer
0aee6436 ❌ Failed No signature found
3ac81ee5 ❌ Failed No signature found
1715c4be ❌ Failed No signature found
d9e9eec5 ❌ Failed No signature found
16259215 ❌ Failed No signature found
c0282186 ❌ Failed No signature found
e7ae53b7 ❌ Failed No signature found
fb1a25bc ❌ Failed No signature found
49587126 ❌ Failed No signature found
2b77ad7d ❌ Failed No signature found
fa261689 ❌ Failed No signature found
83718e5a ❌ Failed No signature found
a5c85a50 ❌ Failed No signature found
1f462ab0 ❌ Failed No signature found
84185870 ❌ Failed No signature found
6050c6c1 ❌ Failed No signature found
549f09ea ❌ Failed No signature found
39d2df30 ❌ Failed No signature found
389de257 ❌ Failed No signature found
170002dd ❌ Failed No signature found
ddb50f98 ❌ Failed No signature found
bb3797ce ❌ Failed No signature found
03852ba4 ❌ Failed No signature found
a1d03524 ❌ Failed No signature found
69f3133f ❌ Failed No signature found
9e6acdff ❌ Failed No signature found
a960d317 ❌ Failed No signature found
f2ccc683 ❌ Failed No signature found
eecbb45e ❌ Failed No signature found
b5f83e0f ❌ Failed No signature found
3f38ddcf ❌ Failed No signature found
723a2324 ❌ Failed No signature found
432dc69e ❌ Failed No signature found
ad919616 ❌ Failed No signature found
a55301b9 ❌ Failed No signature found
9b07f82a ❌ Failed No signature found
b52659af ❌ Failed No signature found
f2d0f7bb ❌ Failed No signature found
8a01f873 ❌ Failed No signature found
405d47f1 ❌ Failed No signature found
fe658ea6 ❌ Failed No signature found
d29862c0 ❌ Failed Signature from non-allowed signer
8fe1d2ab ❌ Failed No signature found
2ad5cd08 ❌ Failed No signature found
6efef5b6 ❌ Failed No signature found
74dcf5bd ❌ Failed No signature found
3dc28a68 ❌ Failed No signature found
9354fba1 ❌ Failed No signature found
f985f6eb ❌ Failed No signature found
508524e5 ❌ Failed No signature found
ad4ae53d ❌ Failed No signature found
5b44f0e5 ❌ Failed No signature found
54a1bc2a ❌ Failed No signature found
aa471f05 ❌ Failed No signature found
68576842 ❌ Failed No signature found
5ac8a434 ❌ Failed No signature found
224af930 ❌ Failed No signature found
3d0a0fd0 ❌ Failed No signature found
0f9c011b ❌ Failed No signature found
ec750122 ❌ Failed No signature found
16cce1f1 ❌ Failed No signature found
79ffea0e ❌ Failed No signature found
45e96b31 ❌ Failed No signature found
adea55fd ❌ Failed No signature found

Result: ❌ 0/98 commits verified


How to fix

Commit d6378ad0 is not signed. To sign future commits:

1. Install auths

macOS: brew install auths
Linux: Download from releases

2. Set up signing

auths init
auths git setup

3. Re-sign and push

git rebase HEAD~98 --exec 'git commit --amend --no-edit -S'
git push --force-with-lease

Quickstart →

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

Auths Commit Verification

Commit Status Details
4e4892bf ❌ Failed Signature from non-allowed signer
d6378ad0 ❌ Failed Signature from non-allowed signer
e5e80fca ❌ Failed Signature from non-allowed signer
f23ab54b ❌ Failed Signature from non-allowed signer
71f6d26a ❌ Failed Signature from non-allowed signer
4d6e41a0 ❌ Failed No signature found
71777e2d ❌ Failed No signature found
47e3d48b ❌ Failed No signature found
6ea1f3a3 ❌ Failed No signature found
d7caaca8 ❌ Failed No signature found
5accc2ff ❌ Failed No signature found
2a6ec1ab ❌ Failed No signature found
f8c4cf06 ❌ Failed No signature found
9e7ff8e4 ❌ Failed No signature found
cd81d759 ❌ Failed No signature found
162a2200 ❌ Failed No signature found
d85f28d8 ❌ Failed No signature found
27652589 ❌ Failed No signature found
ef45e130 ❌ Failed No signature found
49ecf397 ❌ Failed No signature found
5348612e ❌ Failed No signature found
3de69cd2 ❌ Failed No signature found
c0645467 ❌ Failed No signature found
d9ab31a1 ❌ Failed No signature found
2a766391 ❌ Failed No signature found
5b120cad ❌ Failed No signature found
3035a4af ❌ Failed No signature found
b03ebcb0 ❌ Failed No signature found
8ae752f8 ❌ Failed No signature found
54dff176 ❌ Failed No signature found
6073acb8 ❌ Failed No signature found
59dc5b6a ❌ Failed No signature found
a123298f ❌ Failed No signature found
f0fa1373 ❌ Failed Signature from non-allowed signer
30ace9fd ❌ Failed Signature from non-allowed signer
0aee6436 ❌ Failed No signature found
3ac81ee5 ❌ Failed No signature found
1715c4be ❌ Failed No signature found
d9e9eec5 ❌ Failed No signature found
16259215 ❌ Failed No signature found
c0282186 ❌ Failed No signature found
e7ae53b7 ❌ Failed No signature found
fb1a25bc ❌ Failed No signature found
49587126 ❌ Failed No signature found
2b77ad7d ❌ Failed No signature found
fa261689 ❌ Failed No signature found
83718e5a ❌ Failed No signature found
a5c85a50 ❌ Failed No signature found
1f462ab0 ❌ Failed No signature found
84185870 ❌ Failed No signature found
6050c6c1 ❌ Failed No signature found
549f09ea ❌ Failed No signature found
39d2df30 ❌ Failed No signature found
389de257 ❌ Failed No signature found
170002dd ❌ Failed No signature found
ddb50f98 ❌ Failed No signature found
bb3797ce ❌ Failed No signature found
03852ba4 ❌ Failed No signature found
a1d03524 ❌ Failed No signature found
69f3133f ❌ Failed No signature found
9e6acdff ❌ Failed No signature found
a960d317 ❌ Failed No signature found
f2ccc683 ❌ Failed No signature found
eecbb45e ❌ Failed No signature found
b5f83e0f ❌ Failed No signature found
3f38ddcf ❌ Failed No signature found
723a2324 ❌ Failed No signature found
432dc69e ❌ Failed No signature found
ad919616 ❌ Failed No signature found
a55301b9 ❌ Failed No signature found
9b07f82a ❌ Failed No signature found
b52659af ❌ Failed No signature found
f2d0f7bb ❌ Failed No signature found
8a01f873 ❌ Failed No signature found
405d47f1 ❌ Failed No signature found
fe658ea6 ❌ Failed No signature found
d29862c0 ❌ Failed Signature from non-allowed signer
8fe1d2ab ❌ Failed No signature found
2ad5cd08 ❌ Failed No signature found
6efef5b6 ❌ Failed No signature found
74dcf5bd ❌ Failed No signature found
3dc28a68 ❌ Failed No signature found
9354fba1 ❌ Failed No signature found
f985f6eb ❌ Failed No signature found
508524e5 ❌ Failed No signature found
ad4ae53d ❌ Failed No signature found
5b44f0e5 ❌ Failed No signature found
54a1bc2a ❌ Failed No signature found
aa471f05 ❌ Failed No signature found
68576842 ❌ Failed No signature found
5ac8a434 ❌ Failed No signature found
224af930 ❌ Failed No signature found
3d0a0fd0 ❌ Failed No signature found
0f9c011b ❌ Failed No signature found
ec750122 ❌ Failed No signature found
16cce1f1 ❌ Failed No signature found
79ffea0e ❌ Failed No signature found
45e96b31 ❌ Failed No signature found
adea55fd ❌ Failed No signature found

Result: ❌ 0/99 commits verified


How to fix

Commit 4e4892bf is not signed. To sign future commits:

1. Install auths

macOS: brew install auths
Linux: Download from releases

2. Set up signing

auths init
auths git setup

3. Re-sign and push

git rebase HEAD~99 --exec 'git commit --amend --no-edit -S'
git push --force-with-lease

Quickstart →

bordumb added 3 commits June 6, 2026 03:09
Part of the verify-action KEL-native migration: the action now reads commit
signatures via Auths-Id/Auths-Device trailers + KEL, with a committed identity
bundle as the stateless CI trust source instead of .auths/allowed_signers.

Requires .auths/ci-bundle.json (auths id export-bundle) to exist before this is
pushed, plus a post-refactor auths release and a re-tagged verify@v1.
KEL-native commit verification reads pinned trusted roots from
<toplevel>/.auths/roots (load_project_pinned_roots); without it every commit is
RootNotPinned. Commit the root pin (public did:keri:).

The legacy SSH allowed_signers file is unused by the KEL-native commit gate —
untrack the auths-managed file and gitignore it.
…K legacy TLS)

Same non-exploitable transitive path as the already-ignored RUSTSEC-2026-0049/
0098/0099: aws-smithy-http-client -> hyper-rustls 0.24 -> rustls 0.21 ->
rustls-webpki 0.101.7. No CRL parsing in auths or the AWS SDK TLS path, so the
reachable-panic advisory isn't exploitable. The 0.103.x copy is already patched
to 0.103.13; the 0.101.7 copy is pinned until the AWS SDK ships rustls 0.23+.
cargo-deny's target graph never sees 0.101.7; only whole-lock cargo audit does.
@bordumb bordumb merged commit a8d1d00 into main Jun 6, 2026
16 of 21 checks passed
@bordumb bordumb deleted the dev-keriCompliantDevices branch June 6, 2026 02:27
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