FLEX-WP-0035-T05: informed-decision lifecycle v2 declares application.access
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 1m5s

- application.access allows only with purpose=readback and the authoring
  human bar; no workload path, no audience or client-scoped claims
- v1 operations unchanged; pin.json moves to v2; live pin stays v1 until T04
- examples/application-readback: readback catalogue with informed-decision's
  key-cape client binding; integration test over the shipped files

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 609675@bnt-lap001
Assistant-Session: 4987a36e-eb38-4b10-803c-15a29cd78212
This commit is contained in:
tegwick 2026-10-09 20:10:50 +02:00
parent a4103272e1
commit b5da745063
10 changed files with 207 additions and 12 deletions

View file

@ -0,0 +1,17 @@
# Application access readback catalogue
The readback pin's own registry (`FLEX-WP-0035`, `FLEX-DEC-2026-019`). It holds
one entry per application that user-engine may list: id, display name, and the
key-cape client its users sign in through. The entries are descriptive only and
never decide an allow. Allow comes from each application's own package, which
must declare `application.access`.
Participants' registries are loaded alongside this one, and their packages are
loaded at the same files their own pins run:
| System | Package | Registry |
| --- | --- | --- |
| `informed-decision` | `examples/informed-decision-lifecycle/policy.md` (v2) | `examples/informed-decision-lifecycle/registry.json` |
`client_binding` sources: `informed-decision/docs/keycape-client-registration.md`
(`client_id`) and `informed-decision/informed_decision/oidc.py` (issuer).

View file

@ -0,0 +1,13 @@
{
"systems": [
{
"id": "informed-decision",
"name": "Informed Decision",
"description": "Decision memos: authoring, collaboration and human review.",
"client_binding": {
"issuer": "https://kc.coulomb.social",
"client_id": "informed-decision-approver"
}
}
]
}

View file

@ -17,5 +17,42 @@
"expect": {
"effect": "deny"
}
},
{
"id": "application-access-without-readback-purpose-denied",
"request": {
"id": "application-access-enforcement",
"tenant": "tenant:platform",
"subject": {
"id": "human-one",
"type": "human",
"tenant": "tenant:platform",
"attributes": {
"groups": [
"net-kingdom-admins"
],
"assurance": {
"level": "aal2",
"mfa": true,
"source": "key-cape",
"methods": [
"pwd",
"otp"
],
"at": 0
}
}
},
"action": "application.access",
"resource": {
"id": "informed-decision",
"type": "application",
"system": "informed-decision"
}
},
"expect": {
"effect": "deny",
"reason": "lifecycle_scope_or_identity_refused"
}
}
]

View file

@ -1,5 +1,5 @@
{
"package": "informed-decision.lifecycle",
"version": "v1",
"package_digest": "sha256:cee6a79f74e81d0d389a2c2e2451a92be3434ea9dfcee4986e8c7e6cfdbb1827"
"version": "v2",
"package_digest": "sha256:da01e045fc108adec6b489e5d51f7e57366793016c5a64776963780a6aae457c"
}

View file

@ -2,11 +2,11 @@
id: informed-decision.lifecycle
name: Decision lifecycle authoring and collaboration
namespace: informed-decision:decision-memo
version: v1
version: v2
status: ready
package: flexauth.informed_decision.lifecycle
allow_ttl: 30s
actions: [lifecycle.register, lifecycle.read, lifecycle.search, lifecycle.revise, lifecycle.source, lifecycle.evaluation, lifecycle.comment, lifecycle.events, lifecycle.packet, lifecycle.publish, lifecycle.request_review, lifecycle.outcomes]
actions: [lifecycle.register, lifecycle.read, lifecycle.search, lifecycle.revise, lifecycle.source, lifecycle.evaluation, lifecycle.comment, lifecycle.events, lifecycle.packet, lifecycle.publish, lifecycle.request_review, lifecycle.outcomes, application.access]
owner: flex-auth
fixtures: [fixtures.json]
caring:
@ -43,6 +43,23 @@ identity. Authentication-derived values still come from the enforced consumer
boundary (KeyCape sessions or CA-verified TokenReview). This remains a consumer
claim trust boundary; a registry declaration is not independent verification.
## Application access readback (v2)
v2 adds one action, `application.access`, for the advisory readback that tells
user-engine whether to list informed-decision for a signed-in person
(`FLEX-WP-0035-T05`, `FLEX-DEC-2026-019`). v1's twelve operations are
unchanged.
The rule is the same `human` bar authoring uses: net-kingdom-admins, KeyCape
AAL2 `pwd`+`otp` within 12 hours, tenant platform. It reads only realm-level
IAM Profile v0.3 claims (groups and normalized `assurance`). It reads no
audience, authorized party or client-scoped role, because the forwarded
claims were issued for user-engine's client. The workload path is excluded:
it turns on `authentication_audience`, and the readback lists applications for
people. It also requires `purpose == "readback"`, so it can never allow on an
enforcement pin, which refuses a purpose-bearing request. The allow grants
nothing inside informed-decision; every operation is still checked above.
```rego
import rego.v1
@ -168,7 +185,20 @@ operation if {
routing.review_group == "net-kingdom-admins"
}
decision := {"effect":"allow", "reason":"lifecycle_collaboration"} if {
application_access if {
input.action == "application.access"
input.purpose == "readback"
input.tenant == "tenant:platform"
input.subject.tenant == input.tenant
input.resource.system == "informed-decision"
input.resource.type == "application"
input.resource.id == "informed-decision"
human
}
decision := {"effect":"allow", "reason":"application_access_readback"} if {
application_access
} else := {"effect":"allow", "reason":"lifecycle_collaboration"} if {
common
identity
operation
@ -183,4 +213,12 @@ import data.flexauth.informed_decision.lifecycle
test_empty_denied if {
lifecycle.decision.effect == "deny" with input as {}
}
test_application_access_needs_readback_purpose if {
lifecycle.decision.effect == "deny" with input as {
"action": "application.access", "tenant": "tenant:platform",
"subject": {"type": "human", "tenant": "tenant:platform"},
"resource": {"id": "informed-decision", "type": "application", "system": "informed-decision"}
}
}
```