Skip to content

feat(evidencectl): bind local task-grant and first-party exchange clients to the borrowed issuer - #1068

Merged
jeremi merged 5 commits into
mainfrom
feat/evidence-dev-exchange-client-bindings
Sep 15, 2026
Merged

jeremi merged 5 commits into
mainfrom
feat/evidence-dev-exchange-client-bindings

Conversation

@jeremi

@jeremi jeremi commented Sep 14, 2026

Copy link
Copy Markdown
Member

Summary

Evidence dev sessions that borrow a BREG issuer owner can now serve institutional task-grant and first-party exchange clients. Before this change, a local Evidence gateway refused any client the owner had registered as an exchange client, so a composition with an assistant acting under a Casework task grant could not read Evidence.

  • evidencectl access policies may declare an optional taskGrant (kind, exact sourceIssuer, active requesterClients, per-question selector bindings to verified token claims). The compiler emits authenticated-grant origins and binds the policy tag to the full grant semantics.
  • evidencectl access client add gains --grant-bootstrap-scope/--grant-bootstrap-resource for institutional exchange clients and --first-party-bootstrap-scope/--first-party-bootstrap-resource/--first-party-issuer for first-party context exchange clients. The two modes are mutually exclusive; clap enforces the first-party flag set as a whole.
  • A borrowed bundle now states the owner's per-client pairing in authentication.assertionIssuers, derived the same way the owner's BREG runtime derives it from the exchange connections that list each client. An owner-registered exchange client is admitted only with a declared binding whose source authorities that pairing names. The owner's pairing is re-read at startup and must match the compiled bundle.
  • Nondefault Evidence resources derive distinct provider, issuer and service identifiers so several local Evidence services stay separate in Discovery.

Owning area: crates/registry-evidencectl, crates/registry-evidence-authoring, and the evidencectl reference page.

Checks

  • cargo fmt --all -- --check
  • cargo test --locked -p registry-evidencectl -p registry-evidence-authoring (all pass). New coverage in crates/registry-evidencectl/tests/access.rs (flag combinations and persisted exchange documents that must not publish a client) and in dev.rs/authoring.rs unit tests: compiled assertionIssuers emission, owner pairing that no longer matches the bundle, an unpaired task source authority, exchange clients without a declared binding, and client_task_sources (unassigned requester, institutional binding without a task policy, task requester using first-party exchange, requester without a binding, binding without a borrowed owner).
  • cargo clippy --locked -p registry-evidencectl -p registry-evidence-authoring --all-targets -- -D warnings
  • End to end: a local three-authority composition (three BREG, three Evidence, Casework, Discovery, shared dev issuer) built from this branch ran a browser journey with verified prefill and an assistant reading Evidence under a Casework task grant, plus a refusal journey covering a foreign subject, revocation and the grant deadline.
  • check:cli-reference: the new access client add options and constraints were reviewed against the catalog on main, and the review record now carries their digests.

Notes

Security-sensitive: authorization (local dev composition only; no server runtime change).

  • Review focus: verify_borrowed_registrations and the pairing derivation in crates/registry-evidencectl/src/dev.rs, and ActiveClientExchange::validate in access.rs.
  • The pairing is resource-server side. Stock ThunderID still issues a token for a client from any assertion authority it trusts; per-client restriction at the issuer waits on Restrict token-exchange assertion authorities per OAuth client thunder-id/thunderid#5387. A resource server with an empty assertionIssuers map applies no pairing rule, which is why the borrowed bundle must state the owner's pairing rather than leave it empty.
  • A client that is both a task-grant requester and a first-party exchanger is refused.
  • Persisted access/clients/*.yaml gains an optional exchange object; documents without it are unchanged.

DCO

  • Every commit includes a Signed-off-by trailer.
  • I reviewed the submitted changes and am responsible for the contribution.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@jeremi
jeremi force-pushed the feat/evidence-dev-exchange-client-bindings branch from 117b245 to 81231a3 Compare September 14, 2026 17:56
An Evidence access policy may name an institutional task grant: the
requester clients, the grant source issuer, and the selector bindings
read from the exchanged token. A local session registers those clients
against the borrowed BREG issuer owner as institutional exchange clients
with their declared bootstrap scope.

A borrowed bundle already names the machine clients it admits. It now
also states the owner's per-client assertion pairing in
`authentication.assertionIssuers`, derived the way the owner's BREG
runtime derives its own from the exchange connections that list each
client. An Evidence client the owner registered as an exchange client is
admitted only with a declared exchange binding whose source authorities
that pairing names; without one it is still refused. The owner's pairing
is re-read before the session starts and must match the compiled one.

Security-sensitive: authorization.
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
An active Evidence client may declare a signed first-party context
exchange: one bootstrap scope, its resource, and the exact trusted issuer
of the signed context. A local session borrowing a BREG issuer owner
registers that client as a first-party exchange client, and refuses a
client that is both a task grant requester and a first-party exchanger.

Startup requires the owner to register the client against a
`first_party` connection for that issuer and to pair the client with it,
so the borrowed bundle's `assertionIssuers` names the authority.

Security-sensitive: authorization.
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
…sing

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi force-pushed the feat/evidence-dev-exchange-client-bindings branch from 81231a3 to a2e7c52 Compare September 15, 2026 02:05
@jeremi
jeremi merged commit 042e6da into main Sep 15, 2026
41 checks passed
@jeremi
jeremi deleted the feat/evidence-dev-exchange-client-bindings branch September 15, 2026 02:14
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