feat: add institutional contextual authorization and retire Mint - #1029
Conversation
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Work-package checkpoint for contextual authorization. Integration acceptance remains in progress; unfinished fixture migrations are intentionally WIP. Citizen federation is preserved but deferred and is not required for phases 1-3. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Work-package checkpoint for contextual authorization. Integration acceptance remains in progress; unfinished fixture migrations are intentionally WIP. Citizen federation is preserved but deferred and is not required for phases 1-3. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Work-package checkpoint for contextual authorization. Integration acceptance remains in progress; unfinished fixture migrations are intentionally WIP. Citizen federation is preserved but deferred and is not required for phases 1-3. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Work-package checkpoint for contextual authorization. Integration acceptance remains in progress; unfinished fixture migrations are intentionally WIP. Citizen federation is preserved but deferred and is not required for phases 1-3. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Work-package checkpoint for contextual authorization. Integration acceptance remains in progress; unfinished fixture migrations are intentionally WIP. Citizen federation is preserved but deferred and is not required for phases 1-3. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Work-package checkpoint for contextual authorization. Integration acceptance remains in progress; unfinished fixture migrations are intentionally WIP. Citizen federation is preserved but deferred and is not required for phases 1-3. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Exercise registered private-key JWT issuance and the protected lookup against pinned ThunderID 1.0.1. The Docker acceptance gate passes explicitly with --ignored; normal unit runs do not gain a Docker prerequisite. Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8407737953
ℹ️ 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".
8407737 to
8b74414
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8b74414164
ℹ️ 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".
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
8b74414 to
a1e7d7b
Compare
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01eb7f987d
ℹ️ 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".
| TaskApproved, | ||
| TaskRevoked, | ||
| TaskInvalidated, |
There was a problem hiding this comment.
Include task events in client history unions
Adding these variants makes history() return task_approved, task_revoked, and task_invalidated, but both registry-casework-client-node/client.d.ts and registry-casework-client-py/python/registry_casework_client/__init__.pyi still define HistoryKind without them; the unified bindings copy the same stale unions. Typed callers therefore see valid runtime responses as impossible and exhaustive event handling can silently omit every new task-grant event. Update the maintained binding types and regenerate the unified facades.
AGENTS.md reference: AGENTS.md:L381-L389
Useful? React with 👍 / 👎.
| grant_id: Uuid, | ||
| ) -> Result<CaseworkComplete<registry_casework_core::TaskGrantRevocation>, CaseworkClientError> | ||
| { | ||
| require_source_profile(&auth)?; |
There was a problem hiding this comment.
Allow revocation without a source profile
When a currently eligible officer cannot read the source, this precondition makes the maintained client reject revocation locally unless the caller supplies an unrelated or fabricated source profile. The HTTP handler authenticates only the Casework profile and deliberately performs no source read, matching the documented non-source-dependent revocation flow; the Node and Python bindings likewise unnecessarily require source_profile. Remove this client precondition and align the binding signatures and OpenAPI generator.
Useful? React with 👍 / 👎.
| validate_len(self.grants.len(), 1, 128, "authority grants")?; | ||
| for grant in &self.grants { | ||
| grant.validate()?; | ||
| } | ||
| if self.uses_task_grant() { |
There was a problem hiding this comment.
Restrict task-grant profiles to delegated authority
When a profile using authenticated-grant is declared as statutory, organizational, consent, or explicit-request authority, this validation accepts it, and match_entitlement only requires AuthorityKind::Delegated when act.sub is present; Casework task assertions omit act, so a valid agent grant is authorized and audited under the non-delegated kind. Fresh evidence beyond the earlier Version 1 concern is that the updated Concept now approves task grants specifically on configured delegated paths, so reject task-grant profiles whose kind is not delegated.
AGENTS.md reference: AGENTS.md:L220-L224
Useful? React with 👍 / 👎.
| description: "Explicit local service client".into(), | ||
| client_id: client.id.clone(), | ||
| public_jwks: json!({"keys":[public]}).to_string(), | ||
| token_attributes: attributes.keys().cloned().collect(), |
There was a problem hiding this comment.
Copy Evidence context through local task exchange
When caseworkctl dev provisions an Evidence task-exchange client without static claims, as in the documented serviceClients shape, this list contains only the client attributes plus registry_actor_kind; the ThunderID exchange user configuration consequently omits evidence_tags and evidence_audience even though Casework signed both into the assertion. Evidence requires those direct claims and rejects every exchanged task token, so add the Evidence assertion attribute names for clients referenced by Evidence templates without deriving their values from static client claims.
Useful? React with 👍 / 👎.
| && self.scopes.as_ref().is_none_or(|scopes| { | ||
| !scopes.is_empty() | ||
| && scopes.len() <= registry_platform_httputil::MAXIMUM_REQUESTED_SCOPES |
There was a problem hiding this comment.
Reject aggregate scope values at profile load
When oauth.scopes contains up to 32 distinct valid 256-byte tokens whose space-joined representation exceeds 4,096 bytes, this predicate accepts the profile, but PrivateKeyJwt::new rejects the same set through MAXIMUM_SCOPE_PARAMETER_BYTES after service discovery. This leaves a deployment-invalid profile passing its documented load-time validation; include the joined scope length in this check using the shared constant.
Useful? React with 👍 / 👎.
| let key = registry_platform_crypto::PrivateJwk::parse(text) | ||
| .map_err(|_| StoreError::Configuration)?; | ||
| if !matches!(key.alg.as_deref(), Some("ES256" | "RS256")) | ||
| || key.kid.as_deref().is_none_or(str::is_empty) |
There was a problem hiding this comment.
Reject unusable task-authority keys at startup
When the configured JWK parses and declares ES256 or RS256 but cannot actually sign, such as a zero EC scalar, inconsistent RSA components, or a key whose algorithm does not match its material, this load path still marks the authority usable and lets the service become ready and publish its public half. Every later assertion request then fails as unavailable instead of exposing the deployment fault at startup; perform the same sign-and-public-verify probe used by PrivateKeyJwt before accepting the key.
Useful? React with 👍 / 👎.
Behavior
Add institutional contextual authorization using stock ThunderID 1.0.1. Casework officers approve governed task templates; an agent exchanges a short-lived Casework assertion for access constrained to the approved client, resource, purpose, subjects, operations and grant deadline. Evidence preserves requester context and enforces the signed deadline. BREG task writes use governed change requests and fresh authority status checks, including retries and approval/application transitions.
Rename BREG profile
grantstopermissions, expose task approval through typed client bindings, and provide localdev tokenanddev grantjourneys. Institutional source-backed Casework development uses explicitly bound BREG readers, separate bootstrap/status clients and a public-only issuer JWKS endpoint. Ordinary source-backed tutorials can reuse the BREG stock issuer, with all-source credential validation before retained-state publication. Retire Mint source, toolset entries and maintained development launchers in favor of the stock issuer. Published v0.30.0 manifests and notes remain unchanged; migration notes describe unreleased changes.Citizen federation is deferred. The candidate patch and citizen tooling are preserved on
spike/citizen-federation-candidateand are absent from this delivery. eSignet retains its identity-provider role and existing BREG plugin contract; its companion change migrates totoken_client.Validation
registry_grant_exp; the Evidence resource refuses it.Authorization review covers exact signed context, absence of standing-profile fallback, fresh write status, bounded retained read access, public-only JWKS publication and owner-only client credentials. No deployment, release publication or tag is included.
Companion drafts
App Kit validation uses the hash-verified local companion client candidate. Ordinary installation needs a compatible future client release; this PR does not publish it.
Citizen federation deferred; candidate preserved on spike/citizen-federation-candidate.