FLEX-WP-0035 T01-T03: application access readback pin
Contract accepted by user-engine; FLEX-DEC-2026-019 accepted. - serve-readback: dedicated pin, no enforcement routes, own caller binding - CheckRequest.purpose hashed into every digest when set; /v1/check refuses it - POST /v1/readback/application_access and GET /v1/readback/systems - optional client_binding on protected systems; readback schemas - schemaguard implements maxItems - T05 added: informed-decision needs an application.access rule over realm-level claims (its lifecycle rules read authentication_audience) 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:
parent
b6d6bff85e
commit
8f2ba75e4a
23 changed files with 1314 additions and 44 deletions
24
cmd/flex-auth/testdata/readback/demo-app/policy_fixtures.yaml
vendored
Normal file
24
cmd/flex-auth/testdata/readback/demo-app/policy_fixtures.yaml
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
- id: fixture:demo-app-access-allow
|
||||
request:
|
||||
subject:
|
||||
id: user:alice
|
||||
attributes:
|
||||
groups: [app-users]
|
||||
assurance: {level: aal2, mfa: true}
|
||||
action: application.access
|
||||
resource: {id: demo-app, type: application, system: demo-app}
|
||||
expect:
|
||||
effect: allow
|
||||
reason: app_user
|
||||
- id: fixture:demo-app-access-deny-no-mfa
|
||||
request:
|
||||
subject:
|
||||
id: user:bob
|
||||
attributes:
|
||||
groups: [app-users]
|
||||
assurance: {level: aal1, mfa: false}
|
||||
action: application.access
|
||||
resource: {id: demo-app, type: application, system: demo-app}
|
||||
expect:
|
||||
effect: deny
|
||||
reason: no_matching_rule
|
||||
53
cmd/flex-auth/testdata/readback/demo-app/policy_package.md
vendored
Normal file
53
cmd/flex-auth/testdata/readback/demo-app/policy_package.md
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
id: testdata.demo-app
|
||||
name: readback test package demo-app
|
||||
namespace: testdata:demo-app
|
||||
version: v1
|
||||
status: fixture
|
||||
package: flexauth.testdata.demo_app
|
||||
actions:
|
||||
- application.access
|
||||
- read
|
||||
owner: team:platform-security
|
||||
fixtures:
|
||||
- policy_fixtures.yaml
|
||||
caring:
|
||||
profile: caring-0.4.0-rc2
|
||||
enforce: false
|
||||
canonical_roles: [Operator]
|
||||
organization_relations: [ServiceProvider]
|
||||
scopes:
|
||||
- {level: Platform, id: platform:testdata, tenant: tenant:platform}
|
||||
planes: [Identity]
|
||||
capabilities: [Use]
|
||||
exposure_modes: [Metadata]
|
||||
conditions: [Logged]
|
||||
restrictions: [PrivilegeEscalationBlocked]
|
||||
---
|
||||
|
||||
# Readback test package (FLEX-WP-0035)
|
||||
|
||||
Test-only. Do not copy.
|
||||
|
||||
```rego
|
||||
import future.keywords.if
|
||||
import future.keywords.in
|
||||
|
||||
default decision := {"effect": "deny", "reason": "no_matching_rule"}
|
||||
|
||||
decision := {"effect": "allow", "reason": "app_user"} if {
|
||||
input.action == "application.access"
|
||||
"app-users" in input.subject.attributes.groups
|
||||
input.subject.attributes.assurance.mfa == true
|
||||
}
|
||||
```
|
||||
|
||||
```rego test
|
||||
package flexauth.testdata.demo_app_test
|
||||
import future.keywords.if
|
||||
import data.flexauth.testdata.demo_app
|
||||
|
||||
test_default_deny if {
|
||||
demo_app.decision.effect == "deny" with input as {"action": "read", "subject": {"attributes": {}}}
|
||||
}
|
||||
```
|
||||
28
cmd/flex-auth/testdata/readback/demo-app/registry_snapshot.json
vendored
Normal file
28
cmd/flex-auth/testdata/readback/demo-app/registry_snapshot.json
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"systems": [
|
||||
{
|
||||
"id": "demo-app",
|
||||
"name": "Demo App",
|
||||
"client_binding": {
|
||||
"issuer": "https://keycape.example/realms/netkingdom",
|
||||
"client_id": "demo-app"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subjects": [
|
||||
{
|
||||
"id": "demo-app-profile",
|
||||
"type": "Human",
|
||||
"display_name": "Readback contract profile (declares caller-supplied keys)",
|
||||
"groups": [
|
||||
"app-users"
|
||||
],
|
||||
"claims": {
|
||||
"assurance": {
|
||||
"level": "aal2",
|
||||
"mfa": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
14
cmd/flex-auth/testdata/readback/other-app/policy_fixtures.yaml
vendored
Normal file
14
cmd/flex-auth/testdata/readback/other-app/policy_fixtures.yaml
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# The rule would allow application.access, but this package does not declare
|
||||
# the action. The readback must answer not_applicable regardless (T01 §2).
|
||||
- id: fixture:other-app-undeclared-rule-would-allow
|
||||
request:
|
||||
subject:
|
||||
id: user:alice
|
||||
attributes:
|
||||
groups: [app-users]
|
||||
assurance: {level: aal2, mfa: true}
|
||||
action: application.access
|
||||
resource: {id: other-app, type: application, system: other-app}
|
||||
expect:
|
||||
effect: allow
|
||||
reason: app_user
|
||||
52
cmd/flex-auth/testdata/readback/other-app/policy_package.md
vendored
Normal file
52
cmd/flex-auth/testdata/readback/other-app/policy_package.md
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
id: testdata.other-app
|
||||
name: readback test package other-app
|
||||
namespace: testdata:other-app
|
||||
version: v1
|
||||
status: fixture
|
||||
package: flexauth.testdata.other_app
|
||||
actions:
|
||||
- read
|
||||
owner: team:platform-security
|
||||
fixtures:
|
||||
- policy_fixtures.yaml
|
||||
caring:
|
||||
profile: caring-0.4.0-rc2
|
||||
enforce: false
|
||||
canonical_roles: [Operator]
|
||||
organization_relations: [ServiceProvider]
|
||||
scopes:
|
||||
- {level: Platform, id: platform:testdata, tenant: tenant:platform}
|
||||
planes: [Identity]
|
||||
capabilities: [Use]
|
||||
exposure_modes: [Metadata]
|
||||
conditions: [Logged]
|
||||
restrictions: [PrivilegeEscalationBlocked]
|
||||
---
|
||||
|
||||
# Readback test package (FLEX-WP-0035)
|
||||
|
||||
Test-only. Do not copy.
|
||||
|
||||
```rego
|
||||
import future.keywords.if
|
||||
import future.keywords.in
|
||||
|
||||
default decision := {"effect": "deny", "reason": "no_matching_rule"}
|
||||
|
||||
decision := {"effect": "allow", "reason": "app_user"} if {
|
||||
input.action == "application.access"
|
||||
"app-users" in input.subject.attributes.groups
|
||||
input.subject.attributes.assurance.mfa == true
|
||||
}
|
||||
```
|
||||
|
||||
```rego test
|
||||
package flexauth.testdata.other_app_test
|
||||
import future.keywords.if
|
||||
import data.flexauth.testdata.other_app
|
||||
|
||||
test_default_deny if {
|
||||
other_app.decision.effect == "deny" with input as {"action": "read", "subject": {"attributes": {}}}
|
||||
}
|
||||
```
|
||||
24
cmd/flex-auth/testdata/readback/other-app/registry_snapshot.json
vendored
Normal file
24
cmd/flex-auth/testdata/readback/other-app/registry_snapshot.json
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"systems": [
|
||||
{
|
||||
"id": "other-app",
|
||||
"name": "Other App"
|
||||
}
|
||||
],
|
||||
"subjects": [
|
||||
{
|
||||
"id": "other-app-profile",
|
||||
"type": "Human",
|
||||
"display_name": "Readback contract profile (declares caller-supplied keys)",
|
||||
"groups": [
|
||||
"app-users"
|
||||
],
|
||||
"claims": {
|
||||
"assurance": {
|
||||
"level": "aal2",
|
||||
"mfa": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue