Admit initial decision lifecycle audience and patch evaluator dependencies
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a10780-6d41-7952-9718-dfbc1f41236f
This commit is contained in:
parent
c0f3f25be2
commit
d2d0b6feeb
25 changed files with 2644 additions and 102 deletions
21
examples/informed-decision-lifecycle/fixtures.json
Normal file
21
examples/informed-decision-lifecycle/fixtures.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
[
|
||||
{
|
||||
"id": "unknown-request-denied",
|
||||
"request": {
|
||||
"id": "unknown",
|
||||
"subject": {
|
||||
"id": "unknown",
|
||||
"type": "human"
|
||||
},
|
||||
"action": "lifecycle.register",
|
||||
"resource": {
|
||||
"id": "memo:unknown",
|
||||
"type": "decision-memo",
|
||||
"system": "informed-decision"
|
||||
}
|
||||
},
|
||||
"expect": {
|
||||
"effect": "deny"
|
||||
}
|
||||
}
|
||||
]
|
||||
5
examples/informed-decision-lifecycle/pin.json
Normal file
5
examples/informed-decision-lifecycle/pin.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"package": "informed-decision.lifecycle",
|
||||
"version": "v1",
|
||||
"package_digest": "sha256:cee6a79f74e81d0d389a2c2e2451a92be3434ea9dfcee4986e8c7e6cfdbb1827"
|
||||
}
|
||||
186
examples/informed-decision-lifecycle/policy.md
Normal file
186
examples/informed-decision-lifecycle/policy.md
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
---
|
||||
id: informed-decision.lifecycle
|
||||
name: Decision lifecycle authoring and collaboration
|
||||
namespace: informed-decision:decision-memo
|
||||
version: v1
|
||||
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]
|
||||
owner: flex-auth
|
||||
fixtures: [fixtures.json]
|
||||
caring:
|
||||
profile: caring-0.4.0-rc2
|
||||
enforce: false
|
||||
activation:
|
||||
mode: local
|
||||
---
|
||||
|
||||
# Initial lifecycle audience
|
||||
|
||||
Founder direction, 2026-10-04, INFD-WP-0007: net-kingdom-admins humans and
|
||||
system:serviceaccount:state-hub:state-hub. This package is evaluated by Access
|
||||
Engine; the consumer supplies authenticated identity and immutable record facts.
|
||||
The evaluator's workload caller remains informed-decision/review, audience
|
||||
flex-auth. The State Hub subject is authenticated separately for audience
|
||||
informed-decision-lifecycle using CA-verified TokenReview, never a browser token.
|
||||
|
||||
Humans require KeyCape AAL2 MFA within 12 hours for authoring. Actual human binding
|
||||
retains the separate review policy's 900-second MFA requirement. This package
|
||||
has no accept action. An initial caller can register and search; record access
|
||||
requires original authorship or an explicit publication audience. Published
|
||||
collaborators may research, discuss and refine. Publication and requesting review
|
||||
require original authorship or an admitted human collaborator. Publication may
|
||||
name only the initial human group; explicit subjects still require admitted
|
||||
identity. Review routing is fixed to State Hub, decision-record class and
|
||||
net-kingdom-admins. Every operation is fresh; neither content nor evaluation
|
||||
assertions confer permission. Command digests correlate commands, not signatures.
|
||||
No presentation/view hash enters this policy.
|
||||
|
||||
The sibling registry declares identity contract profiles, following the existing
|
||||
review packages. These are not real human or workload identifiers and mint no
|
||||
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.
|
||||
|
||||
```rego
|
||||
import rego.v1
|
||||
|
||||
common if {
|
||||
input.tenant == "tenant:platform"
|
||||
input.subject.tenant == input.tenant
|
||||
input.resource.tenant == input.tenant
|
||||
input.resource.system == "informed-decision"
|
||||
input.context.contract == "informed-decision.lifecycle.v1"
|
||||
regex.match("^sha256:[0-9a-f]{64}$", input.context.command_digest)
|
||||
input.subject.attributes.principal_type_source == "authentication-derived"
|
||||
input.subject.attributes.tenant_source in {"registration-supplied", "directory-asserted"}
|
||||
}
|
||||
|
||||
human if {
|
||||
input.subject.type == "human"
|
||||
"net-kingdom-admins" in input.subject.attributes.groups
|
||||
assurance := input.subject.attributes.assurance
|
||||
assurance.level == "aal2"
|
||||
assurance.mfa == true
|
||||
assurance.source == "key-cape"
|
||||
assurance.methods == ["pwd", "otp"]
|
||||
is_number(assurance.at)
|
||||
age := time.now_ns()/1000000000 - assurance.at
|
||||
age >= -30
|
||||
age <= 43200
|
||||
}
|
||||
|
||||
workload if {
|
||||
input.subject.type == "service"
|
||||
input.subject.id == "system:serviceaccount:state-hub:state-hub"
|
||||
input.subject.attributes.authentication_audience == "informed-decision-lifecycle"
|
||||
is_string(input.subject.attributes.workload_uid)
|
||||
input.subject.attributes.workload_uid != ""
|
||||
}
|
||||
|
||||
identity if human
|
||||
identity if workload
|
||||
|
||||
memo_resource if {
|
||||
input.resource.type == "decision-memo"
|
||||
regex.match("^memo:[A-Za-z0-9._:-]{1,256}$", input.resource.id)
|
||||
}
|
||||
|
||||
owner if {
|
||||
input.context.record.registered == true
|
||||
some author in [input.context.record.registered_by, input.context.record.revision_by]
|
||||
author.sub == input.subject.id
|
||||
author.kind == "person"
|
||||
human
|
||||
}
|
||||
owner if {
|
||||
input.context.record.registered == true
|
||||
some author in [input.context.record.registered_by, input.context.record.revision_by]
|
||||
author.sub == input.subject.id
|
||||
author.kind == "service"
|
||||
workload
|
||||
}
|
||||
|
||||
readable if owner
|
||||
readable if {
|
||||
input.context.record.registered == true
|
||||
input.subject.id in input.context.record.published_audience.subjects
|
||||
}
|
||||
readable if {
|
||||
human
|
||||
"net-kingdom-admins" in input.context.record.published_audience.groups
|
||||
}
|
||||
|
||||
may_publish if owner
|
||||
may_publish if {
|
||||
human
|
||||
readable
|
||||
}
|
||||
|
||||
audience_ok if {
|
||||
a := input.context.publication_audience
|
||||
is_array(a.subjects)
|
||||
is_array(a.groups)
|
||||
count(a.subjects) <= 32
|
||||
count(a.groups) <= 32
|
||||
count(a.subjects)+count(a.groups) > 0
|
||||
every group in a.groups { group == "net-kingdom-admins" }
|
||||
every subject in a.subjects { is_string(subject); subject != ""; subject != "*" }
|
||||
}
|
||||
|
||||
operation if {
|
||||
input.action == "lifecycle.register"
|
||||
memo_resource
|
||||
not input.context.record.registered
|
||||
input.context.memo_version == 1
|
||||
}
|
||||
operation if {
|
||||
input.action == "lifecycle.register"
|
||||
memo_resource
|
||||
owner
|
||||
input.context.memo_version == 1
|
||||
}
|
||||
operation if {
|
||||
input.action == "lifecycle.search"
|
||||
input.resource.type == "decision-collection"
|
||||
input.resource.id == "decisions"
|
||||
}
|
||||
operation if {
|
||||
input.action in {"lifecycle.read", "lifecycle.events", "lifecycle.packet", "lifecycle.outcomes",
|
||||
"lifecycle.revise", "lifecycle.source", "lifecycle.evaluation", "lifecycle.comment"}
|
||||
memo_resource
|
||||
readable
|
||||
}
|
||||
operation if {
|
||||
input.action == "lifecycle.publish"
|
||||
memo_resource
|
||||
may_publish
|
||||
audience_ok
|
||||
}
|
||||
operation if {
|
||||
input.action == "lifecycle.request_review"
|
||||
memo_resource
|
||||
may_publish
|
||||
routing := input.context.review_routing
|
||||
routing.submitter == "state-hub"
|
||||
routing.memo_class == "decision-record"
|
||||
routing.review_group == "net-kingdom-admins"
|
||||
}
|
||||
|
||||
decision := {"effect":"allow", "reason":"lifecycle_collaboration"} if {
|
||||
common
|
||||
identity
|
||||
operation
|
||||
} else := {"effect":"deny", "reason":"lifecycle_scope_or_identity_refused"}
|
||||
```
|
||||
|
||||
```rego test
|
||||
package flexauth.informed_decision.lifecycle_test
|
||||
import rego.v1
|
||||
import data.flexauth.informed_decision.lifecycle
|
||||
|
||||
test_empty_denied if {
|
||||
lifecycle.decision.effect == "deny" with input as {}
|
||||
}
|
||||
```
|
||||
29
examples/informed-decision-lifecycle/registry.json
Normal file
29
examples/informed-decision-lifecycle/registry.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"subjects": [
|
||||
{
|
||||
"id": "lifecycle-human-profile",
|
||||
"type": "Human",
|
||||
"display_name": "Human identity contract profile",
|
||||
"groups": [
|
||||
"net-kingdom-admins"
|
||||
],
|
||||
"claims": {
|
||||
"assurance": "aal2",
|
||||
"principal_type_source": "authentication-derived",
|
||||
"tenant_source": "registration-supplied"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "lifecycle-workload-profile",
|
||||
"type": "Service",
|
||||
"display_name": "TokenReview identity contract profile",
|
||||
"claims": {
|
||||
"principal_type_source": "authentication-derived",
|
||||
"tenant_source": "registration-supplied",
|
||||
"authentication_audience": "informed-decision-lifecycle",
|
||||
"workload_uid": "TokenReview response UID"
|
||||
}
|
||||
}
|
||||
],
|
||||
"resources": []
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue