docs(evidence): teach relying-party integration in application code - #653
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e02b8c7431
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2394081e1a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
8f041d1 to
f400f54
Compare
2394081 to
cec952e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cec952e4dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
cec952e to
20fddb2
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20fddb2cc7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The consumer tutorial states the verification boundary abstractly. A relying party still has to decide where the trusted key set, the request policy, and the subject binding live in its own program. Walk that journey once with the Python client: give the application its own identity, pin the issuer keys out of band, build the expectations while the answer is still unknown, and read a value only after offline verification returns. The page is deliberately not registered in EVIDENCE_TUTORIALS: the executable tutorial gate mounts the repo read-only and injects only the Evidence binaries, so the Python extension module cannot be built inside it. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Copying a 64-hex configuration revision into source by hand is a poor first experience and invites the reader to keep re-copying it whenever verification starts failing. Save the discovery document instead, transform it offline into a procedure.json the application owns, and load that file at startup. The pinning act stays explicit and still happens before any answer is read; it is only automated instead of transcribed. Regenerating is documented as a review step, with the diff to look at, not a retry. expected_outputs stays hand-written: a concept's published form and a verification expectation's form are separate vocabularies, so deriving one from the other would work for this requirement and mislead on the next. The generator checks the concept identifiers against discovery so a deployment that stops publishing one fails at review time. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Review surfaced eight defects, each confirmed against source: - the policy and client ids collided with the access-control tutorial, so authoring refused for a reader who had followed the other page; both pages now carry their own ids and this one says why they compose - the source clone was unpinned, so a reader could build the client from a tree that need not match the installed evidencectl; it now pins the tag of the installed version - the review step accepted a subset of the published concepts, which the verifier rejects at request time; it now requires the exact set - the application hard-coded the selector profile instead of reading the shape it had reviewed - the binding-stability prose named only subject and audience, while the MAC also covers purpose, role, selector profile, and the deployment's binding key and key version - the bindings store dropped a concurrent run's entry, and its replacement stays owner-only whatever umask the shell carries - the page never restarted the registry the prerequisite leaves stopped, and evidencectl dev reports ready without reaching the source - the error-mapping prose implied any body code maps, where the contract honors a code only under a status registered for it Verified by replaying all thirty-one fences against binaries built from this checkout: every documented output matches apart from the deliberate revision placeholder. docs/site npm test and npm run check pass. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
20fddb2 to
4fb65fd
Compare
|
Consolidated into #649: these three tutorial commits are now on All ten review threads here were answered and resolved first: eight fixed, two refuted on the evidence (both cited commits were rebase-superseded and are not present in the repository; every commit on the head carries a sign-off). Review continues on #649. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4fb65fdbb7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -0,0 +1,704 @@ | |||
| --- | |||
| title: Request Evidence from your application | |||
There was a problem hiding this comment.
Fresh evidence after the earlier threads: the reviewed replacement commit df805ceb9c51346a41fc7f67b6353d1d2ec26833 itself has no Signed-off-by trailer, so it still violates the mandatory DCO policy and cannot pass the DCO gate; recreate the commit with the author's sign-off before merging.
AGENTS.md reference: AGENTS.md:L190-L190
Useful? React with 👍 / 👎.
| # keeping the identifiers above. | ||
| [subject] = definition["subjects"] | ||
| selector = subject["selector"] | ||
| fields = {field["name"] for field in selector["fields"]} |
There was a problem hiding this comment.
Retain complete selector field metadata
Fresh evidence after the earlier subject-shape thread: the replacement now reduces each selector field to its name, so changing person_id from a string to another type, or changing its byte bounds while retaining the name and profile, still passes this check and produces the same published_shape apart from the revision. An application can therefore accept what looks like a revision-only update and continue sending values that the new selector rejects, contradicting the page's claim that a changed request shape cannot pass review; compare and retain the complete field objects, including type and constraints.
AGENTS.md reference: docs/site/AGENTS.md:L25-L28
Useful? React with 👍 / 👎.
Stacked on #649 (
feat/evidence-client-library). Review that one first; this branch adds one page and one sidebar line on top of it.Why
verify-an-assertion-as-a-consumeralready states the verification boundary, but it states it abstractly: "put the boundary in application code" in six steps, with no program. A relying party integrating for the first time still has to decide, in its own codebase, where the trusted key set lives, where the request expectations come from, and what it does with a subject binding the first time it sees one. Those are exactly the decisions that go wrong quietly.This page walks that journey once, concretely, with the Python client from #649.
What it teaches
docs/site/src/content/docs/tutorials/request-evidence-from-an-application.mdx,doc_type: tutorial, personaconsumer or verifier. It continues thefirst-evidence-assertionproject rather than starting a new one.The spine, in order:
evidencectl access policy addplusaccess client add --generate-local-key, reusing the commands fromcontrol-who-can-request-evidenceverbatim. The generated client file setsevidenceAudience, which is what makes the audience expectation in step 4 deterministic.evidencectl jwks --out trusted-issuer-keys.jsonis the local stand-in for the independent channel production requires. The page says so rather than implying the local shortcut generalizes.crates/registry-evidence-client-py/tests/python/bootstrap.py, because nothing here is published to PyPI.registry-evidence-client/src/definitions.rs:1-10says the document is for.procedure.jsonthe application owns. No network call and no client construction, because pinning is something you do to a document you already reviewed. Nothing is hand-copied, so no reader transcribes a 64-hex digest.expected_outputsstays a hand-written literal on purpose: a concept's publishedformand a verification expectation'sformare separate vocabularies (definitions.rs:205-219foldscontrolled-code,controlled-category, andbounded-decimalontostring), so deriving one from the other would work for this requirement and mislead on the next. The generator checks the concept identifiers against discovery, so a deployment that stops publishing one fails at review time with a named error rather than at verification time.pythonfence that loadsprocedure.jsonand holds no discovery client at all.preparebuilds the policy and the nonce before the answer exists;request_and_verifyis the only thing that returns a payload; answers are read into a dict keyed byprovidesValueFor, never by position.configuration_revisioninprocedure.json, both fail closed with apolicycode and print nothing about the subject.The page also states, in prose, that regenerating
procedure.jsonis a review step and not a retry: keep the reviewed copy, write a new one,diffthem, and treat a changedevidence_type,issued_by, or concept set as the question itself having moved.It also documents the client's error hierarchy as a table (all eight kinds), including the hazard the crate README calls out: 401/403/429 map to
deniedwhatever code the body carries, and every other non-2xx maps toprotocol.RuntimeError/ValueErrorsit outsideEvidenceClientError.Verification
I ran the whole journey end to end on this machine, from a fresh project, and then replayed it a second time in a clean directory by extracting the page's own fences programmatically and running them verbatim. Every documented command output in the page is a real transcript, not a reconstruction.
Proven along the way, and reflected in the prose:
client.discover()is what makes it work.private_key_jwtassertion audience defaults to the token endpoint, which matches whatevidencectl devconfigures for Mint.person-123(adult) andperson-456(minor) both return verified answers; the accept-first-use to pinned progression persists tosubject-bindings.jsonunderumask 077.configuration_revisionboth fail verification, with nothing read. Both surface the same generic message, which is deliberate:registry-evidence-verifier/src/verifier.rs:795-823collapses every policy mismatch onto one error so verification does not reveal which hidden comparison failed.discovery.json(no client file, no key set, no built module, no project), it exits 0 and reproduces the documentedprocedure.jsonbyte for byte. The fence names no client, no URL, and no HTTP library.evidencectl dev cleanretains the reader's own files (age_check.py, the trusted key set, the bindings file, the built module, the client private key), so the page's teardown is safe to follow.devhas ever run,request preparewithout--clientfails on the missing private directory, not on the missing client. The fence that documents the missing-client message now sits afterdev --detach, where it reproduces.Docs gates, all run in this worktree:
npm run check(full chain) exit 0npm test310 pass / 0 failcheck:content"Frontmatter check passed."check:style0 errors, 0 warnings, 0 suggestions in 131 filescheck:markdown0 errorsDeliberately not registered in
EVIDENCE_TUTORIALSdocs/site/scripts/check-evidence-tutorials.shreplays a registered tutorial'sshfences in a container that mounts the repo read-only and injects only the three Evidence binaries. This page needs a Rust build of a Python extension module inside that container, which the sandbox cannot do by design. Registration is opt-in and no gate requires it, so the page ships unregistered and verified by hand.Follow-up worth deciding on: whether the executable-tutorial gate should grow a variant that can build the client bindings, or whether client-integration tutorials stay hand-verified. I did not change the gate.
Scope
Entirely
docs/site/: one new page, one sidebar entry inastro.config.mjs. No crate, product-spec, or release changes.Unrelated, flagging rather than fixing
docs/evidence-ux-resetcarries a committedshfence indocs/site/src/content/docs/tutorials/request-evidence-as-sd-jwt-vc.mdxthat fails/bin/sh -n, sonpm testindocs/siteis red on that branch. It is not reachable from this stack and I did not touch it.