Admit named-recipient discovery for lifecycle reviews
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a10780-6d41-7952-9718-dfbc1f41236f
This commit is contained in:
parent
1487bd901f
commit
f234d0175a
3 changed files with 99 additions and 8 deletions
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"package": "informed-decision.compact-sitting",
|
||||
"version": "v12",
|
||||
"package_digest": "sha256:c5387f7d198dc39ab5967e0c218ce05cc779693565c8875e3035e45ec002a2db"
|
||||
"package_digest": "sha256:31be5985c0c1e6b0c3a039ed7310d1e94daf523a94f6d926e6e8d759d3711873",
|
||||
"version": "v13"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
id: informed-decision.compact-sitting
|
||||
name: Compact sitting exact-record human review
|
||||
namespace: informed-decision:decision-memo
|
||||
version: v12
|
||||
version: v13
|
||||
status: ready
|
||||
package: flexauth.informed_decision.compact_sitting
|
||||
allow_ttl: 30s
|
||||
|
|
@ -129,6 +129,13 @@ route; it does not assert directory membership in tenant:platform.
|
|||
Only a real human uses accept. This package neither issues nor consumes
|
||||
approval. Native pins: `docs/evidence/2026-09-15-sitting-approval-creates.json`.
|
||||
|
||||
v13 adds attribute-based `list` for the retained named recipient. The consumer
|
||||
supplies `review_recipient` from the immutable memo and verifies the live native
|
||||
approval requester, human-control flag and binding digest before asking the PDP.
|
||||
Listing has the existing twelve-hour MFA window; read and all acts retain 900
|
||||
seconds. Existing exact-record branches retain precedence. A list allow exposes
|
||||
only overview metadata and cannot stand in for a read or act decision.
|
||||
|
||||
```rego
|
||||
import rego.v1
|
||||
|
||||
|
|
@ -265,7 +272,7 @@ exact_id if {
|
|||
|
||||
attribute_attempt if {
|
||||
not exact_id
|
||||
input.action in {"read", "acknowledge", "accept", "return", "discuss", "decline"}
|
||||
input.action in {"read", "acknowledge", "accept", "return", "discuss", "decline", "list"}
|
||||
ctx := object.get(input, "context", {})
|
||||
some key in {"review_group", "memo_class", "intake_submitter", "approval_requester", "approval_human_control"}
|
||||
object.get(ctx, key, null) != null
|
||||
|
|
@ -288,17 +295,26 @@ identity_core if {
|
|||
assurance.at > 0
|
||||
}
|
||||
|
||||
mfa_window := 43200 if input.action == "list" else := 900
|
||||
|
||||
mfa_fresh if {
|
||||
identity_core
|
||||
age := time.now_ns() / 1000000000 - input.subject.attributes.assurance.at
|
||||
age >= -30
|
||||
age <= 900
|
||||
age <= mfa_window
|
||||
}
|
||||
|
||||
stale_mfa if {
|
||||
identity_core
|
||||
age := time.now_ns() / 1000000000 - input.subject.attributes.assurance.at
|
||||
age > 900
|
||||
age > mfa_window
|
||||
}
|
||||
|
||||
recipient_ok if input.action != "list"
|
||||
|
||||
recipient_ok if {
|
||||
input.action == "list"
|
||||
input.context.review_recipient == input.subject.id
|
||||
}
|
||||
|
||||
resource_ok if {
|
||||
|
|
@ -433,6 +449,7 @@ decision := {"effect": "allow", "reason": "operator_admitted_compact_sitting"} i
|
|||
} else := {"effect": "allow", "reason": "attribute_eligible"} if {
|
||||
attribute_attempt
|
||||
mfa_fresh
|
||||
recipient_ok
|
||||
resource_ok
|
||||
review_group_ok
|
||||
class_ok
|
||||
|
|
@ -451,6 +468,9 @@ decision := {"effect": "allow", "reason": "operator_admitted_compact_sitting"} i
|
|||
} else := {"effect": "deny", "reason": "identity_refused"} if {
|
||||
attribute_attempt
|
||||
not mfa_fresh
|
||||
} else := {"effect": "deny", "reason": "recipient_refused"} if {
|
||||
attribute_attempt
|
||||
not recipient_ok
|
||||
} else := {"effect": "deny", "reason": "resource_refused"} if {
|
||||
attribute_attempt
|
||||
not resource_ok
|
||||
|
|
@ -671,10 +691,34 @@ test_bad_memo_id_refused if {
|
|||
eligible(object.union(attribute_input, {"resource": object.union(attribute_input.resource, {"id": "memo:NO"})})).reason == "resource_refused"
|
||||
}
|
||||
|
||||
test_list_does_not_use_attribute_admission if {
|
||||
test_list_requires_explicit_recipient if {
|
||||
got := eligible(object.union(attribute_input, {"action": "list"}))
|
||||
got.effect == "deny"
|
||||
got.reason == "compact_sitting_scope_or_identity_refused"
|
||||
got.reason == "recipient_refused"
|
||||
}
|
||||
|
||||
list_input := patched_context(object.union(attribute_input, {"action": "list"}), {"review_recipient": "test-human"})
|
||||
|
||||
test_list_admits_recipient_with_twelve_hour_mfa if {
|
||||
eligible(with_at(list_input, time.now_ns() / 1000000000 - 3600)).effect == "allow"
|
||||
eligible(with_at(list_input, time.now_ns() / 1000000000 - 43201)).reason == "stale_mfa"
|
||||
}
|
||||
|
||||
test_list_refuses_other_recipient if {
|
||||
eligible(patched_context(list_input, {"review_recipient": "other-human"})).reason == "recipient_refused"
|
||||
}
|
||||
|
||||
test_list_does_not_relax_read_or_accept if {
|
||||
every action in {"read", "accept"} {
|
||||
eligible(with_at(object.union(list_input, {"action": action}), time.now_ns() / 1000000000 - 3600)).reason == "stale_mfa"
|
||||
}
|
||||
}
|
||||
|
||||
test_list_retains_approval_and_group_guards if {
|
||||
eligible(patched_context(list_input, {"approval_human_control": false})).reason == "human_control_false"
|
||||
eligible(patched_context(list_input, {"approval_requester": "other"})).reason == "requester_mismatch"
|
||||
eligible(patched_context(list_input, {"review_group": "other"})).reason == "review_group_not_verified"
|
||||
eligible(patched_context(list_input, {"memo_class": "other"})).reason == "unknown_class"
|
||||
}
|
||||
|
||||
test_exact_record_ignores_attribute_context if {
|
||||
|
|
|
|||
47
workplans/FLEX-WP-0034-informed-decision-review-discovery.md
Normal file
47
workplans/FLEX-WP-0034-informed-decision-review-discovery.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
id: FLEX-WP-0034
|
||||
type: workplan
|
||||
title: "Named-recipient discovery for lifecycle reviews"
|
||||
domain: infotech
|
||||
repo: access-engine
|
||||
status: active
|
||||
owner: codex
|
||||
topic_slug: netkingdom
|
||||
created: "2026-10-05"
|
||||
updated: "2026-10-05"
|
||||
origin: demand
|
||||
origin_ref: INFD-WP-0007-T05
|
||||
---
|
||||
|
||||
## Implement and verify recipient-scoped list admission
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0034-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Compact-sitting v13 extends the admitted lifecycle attribute branch to list.
|
||||
It requires the carried immutable review recipient to equal the authenticated
|
||||
human subject, existing class/submitter/group admission and live native approval
|
||||
checks in the consumer. Existing exact records retain precedence. Listing uses
|
||||
the existing twelve-hour assurance window; read/acts retain fifteen minutes.
|
||||
32 embedded policy tests and owner InformedDecision regressions pass. Consumer
|
||||
integration covers list/read separation, another recipient and engine outage.
|
||||
Attribution remains unsigned; no new control claim is made.
|
||||
|
||||
## Release through the owning Helm workflow
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0034-T02
|
||||
status: progress
|
||||
priority: high
|
||||
```
|
||||
|
||||
Founder requested deploying the authoring increment and implementing the rest of
|
||||
INFD-WP-0007. Authority for its continuation: ADMINISTER @
|
||||
realm:kubernetes/railiance01, activation=APPROVED. Build immutable owner artifact,
|
||||
scan, dry-run/diff, then update the existing review Helm release. The consumer's
|
||||
pinned version/digest must match. Retain the previous artifact/config as rollback.
|
||||
No anonymous publication, additional workload identity or non-approval bind is
|
||||
admitted by this change.
|
||||
Loading…
Add table
Add a link
Reference in a new issue