spec(evidence): signer-key resolution (v0.2 additive draft layer)#112
Conversation
Per the design agreed with APS on cycles-protocol#103 / aeoess#43. Adds the signature-AUTHORITY layer (the (b) half; (a) signature-validity already ships in APS #45), additive over v0.1 so raw-hex signer_did + expected_signer pinning keep working unchanged. - signer_did: promote to TWO valid forms — raw 64-hex pubkey (v0.1) OR did:cycles:<sha256(server_id)>#<kid> (resolvable). - New CyclesEvidenceJwks / CyclesEvidenceJwk schemas: the server_id-relative JWK Set (GET {server_id}/.well-known/cycles-jwks.json), Ed25519 OKP keys with cycles_nbf_ms / cycles_exp_ms / status; MUST include retired keys. - Normative WINDOW selection rule (pick the key whose [nbf,exp) covers issued_at_ms — never "the current key"; that easy impl breaks archival verification), the raw-hex<->JWK x bridge, and the four distinct verify dispositions (authentic / binding_only / signer_resolution_failed / signature_invalid — the latter two MUST stay distinct: a network failure is not a forgery). - Out-of-scope note + spec-index evidence_envelope entry updated to reflect the layer is now specified (moves to cycles-evidence-v0.2.yaml on the normative cut). Draft-only; spectral 0 errors, no merged drift, changelog valid.
Five findings from the APS maintainer on the #43 design comment, all applied to the draft: - Add `signer_authority_failed` disposition (Medium): resolution SUCCEEDED but the key is not authorized — DID↔server_id hash mismatch, no window-covering key, raw-hex key absent from the set, ambiguous/duplicate-kid selection. Kept distinct from `signer_resolution_failed` (fetch failed) and `signature_invalid` (forgery): a successful-fetch-but-unauthorized case is neither. - Redefine `binding_only` vs PR #45 (Medium): now "signature valid, authority not established," subsuming PR #45's `signature_valid`; an `issuer_pin_matched` companion boolean carries the `pinned_issuer` facet. Closes the unpinned-valid gap. - Make the .well-known path explicitly server_id-relative / API-base-relative, NOT RFC 8615 origin (Medium): stated intent + rationale — server_id (path included) is the hash anchor, pure string append avoids the origin-parsing normalization split, and allows co-hosting. - Define exact server_id_hash input bytes (Low): sha256 over the verbatim UTF-8 server_id string, NO URL normalization; producer emits one canonical form. - Add deterministic JWK selection rules (Low): kid uniqueness, duplicate-kid / overlapping-window / multiple-raw-hex-match → authority error; malformed x / missing cycles_nbf_ms → excluded; unparseable set → resolution error. Draft-only; spectral 0 errors, no merged drift.
|
Updated per APS review on aeoess#43 (commit
|
…s#43) Second APS review pass on the signer-key resolution draft: - High — `issuer_pin_matched` was wrongly equated with APS PR #45's `pinned_issuer`. They are DIFFERENT trust anchors: `issuer_pin_matched` is this (Cycles) verifier pinning the Cycles ENVELOPE signer (`signer_did`); PR #45's `pinned_issuer` pins the APS RECEIPT issuer (the APS object's own `signer`). Reworded to state the Cycles-side anchor and call out the distinction explicitly; dropped the "subsumes pinned_issuer facet" claim. - Medium — OAS 3.1.0 nullability: `cycles_exp_ms` switched from the OAS-3.0 `nullable: true` to JSON-Schema `type: [integer, "null"]` so tooling accepts the documented absent/null. - Low — `alg`: clarified it is OPTIONAL (RFC 7517) but a present-but-non-EdDSA value makes the JWK invalid and excludes it from candidacy, same as a wrong `kty`/`crv`; absent `alg` is fine. Added to both the field and the deterministic-selection rule. - Low — spec-index `evidence_envelope` owns-list said "four verify dispositions"; corrected to five (now naming all of them). Draft-only; spectral 0 errors, no merged drift.
…ss#43) The companion boolean on `binding_only` records a Cycles-side pin of the Cycles ENVELOPE signer (`signer_did`); "issuer" read like APS PR #45's receipt-issuer anchor (a different trust anchor). `signer_pin_matched` is clearer while the text is still draft. No semantic change.
…s#43) After the issuer_pin_matched -> signer_pin_matched rename, the v0.1 out-of-scope note still described expected_signer as "pinning for issuer trust", which reintroduces the APS receipt-issuer ambiguity. expected_signer pins the Cycles ENVELOPE signer; reworded accordingly. (The one remaining "issuer" is the deliberate reference to APS PR #45's receipt-issuer anchor.)
…WKS path (aeoess#43)
APS signed off on keeping the .well-known path API-base-relative. Folding their
reasoning into the spec text so the choice reads as deliberate:
- Lead with AUTHORITY SCOPE (the decisive reason): the did:cycles hash covers
server_id with its path, so origin-rooting would let the host-root principal
answer for a signer whose DID only committed to {host}/v1 — a cross-tenant
authority broadening on path-multi-tenant hosts. Keeping the JWK Set under the
same base holds key authority and identity anchor in one scope.
- Keep the determinism reason (pure lexical append, no URL-normalization drift;
same rule as the hash input).
- Position vs RFC 8414: OAuth AS metadata inserts .well-known host-rooted; OIDC's
append-after-path is the interop wart. We take append-after-path on purpose
because host-rooted insertion splits metadata authority from the committed
path — turns "that's not RFC 8615" into a one-line answer for a standards
reviewer.
- Note the literal .well-known segment is kept for its "this is metadata, do not
route it" signal.
Draft-only; spectral 0 errors, no merged drift.
…s-authority wording (aeoess#43) Two APS review findings on #112: - Medium — CyclesEvidenceJwks had additionalProperties:false, contradicting the "RFC 7517 JWK Set" framing. RFC 7517 §5 lets a JWK Set carry extra top-level members and requires ignoring unknown ones (the child CyclesEvidenceJwk already does this). A harmless set-level extension would have spuriously failed schema validation. Set to true with a note. - Low — signer_resolution_failed said "the kid lookup could not be resolved/reached", which an implementer could read as mapping a missing kid in a fetched set to resolution failure — but the deterministic-selection rule already classes that as signer_authority_failed. Reworded: resolution_failed is about OBTAINING the set (DID method / fetch / parse), not searching it; a missing/duplicate kid or no covering key in a parsed set is authority_failed. Draft-only; spectral 0 errors, no merged drift.
What
Adds the signer-key resolution layer to the CyclesEvidence draft as an
additive v0.2 — the (b) half of the signature story (signature authority),
where APS#45 already shipped (a) (signature validity). Draft-only; no merged
artifacts change.
This is the spec follow-up to the design agreed on #103 / aeoess#43.
Changes (
drafts/cycles-evidence-v0.1.yaml)signer_didnow has two valid forms: the v0.1 raw 64-hex Ed25519 pubkey(still valid — nothing breaks), OR a resolvable
did:cycles:<sha256(server_id)>#<kid>.CyclesEvidenceJwks/CyclesEvidenceJwkschemas — theserver_id-relative JWK Set published atGET {server_id}/.well-known/cycles-jwks.json. Ed25519 OKP keys carryingcycles_nbf_ms/cycles_exp_msvalidity windows + advisorystatus;rotation MUST keep retired keys in the set.
[nbf, exp)window covers theenvelope's
issued_at_ms— explicitly not "the current key" (that naiveimpl breaks archival verification after a rotation).
xbridge, and the five distinct verify dispositions:authentic/binding_only/signer_authority_failed/signer_resolution_failed/signature_invalid— resolution-failure and invalid-signature MUST stay distinct (a network
failure is not a forgery).
cycles-spec-index.yamlevidence_envelopeentry updated:the layer is now specified, and promotes to
cycles-evidence-v0.2.yamlon thenormative cut.
Validation
oas3-unused-componentwarning for thenot-yet-referenced JWKS schema)
merged/)Review ask
@aeoess — this is the layout posted to aeoess#43. Flagging the member names
(
cycles_nbf_ms/cycles_exp_ms/status) and the window semantics before thev0.2 normative cut, in case anything is awkward for the APS resolver. Not merging
until the design has a thumbs-up.
Refs: #103, aeoess#43