flex-auth/examples/informed-decision-sitting/policy.md
tegwick d5c91095ed
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Successful in 1m24s
Pin IR-WP-0005-T02 review to memo version 3.
The consumed T03 approval IDs cannot be created again. The T03 review
package and the sitting list pins now name three new approval IDs.
Binding digests and the sitting act records stay as they are.

Assistant: grok
Assistant-Session: 01a0e2a1-8058-7553-9999-b7d106c17047
2026-09-27 15:29:25 +02:00

8 KiB

id name namespace version status package allow_ttl actions owner fixtures caring activation
informed-decision.compact-sitting Compact sitting exact-record human review informed-decision:decision-memo v3 ready flexauth.informed_decision.compact_sitting 30s
read
acknowledge
accept
return
discuss
decline
list
flex-auth
fixtures.json
profile enforce
caring-0.4.0-rc2 false
mode
local

Compact sitting review mandate

This is a new exact-record package for seven 2026-09-14 sitting memos. v2 (2026-09-21) adds exactly one record, memo:infd-20260921-b01 (the SECRETS-WP-0009-T03 spend envelope), with native pins from informed-decision docs/evidence/2026-09-21-budget-approval-create.json. The seven v1 records and the identity bar are unchanged. It is not an expansion of examples/informed-decision-t03 / FLEX-WP-0027. memo:infd-20260914-c01 is omitted (create-client still undecided).

v3 (2026-09-21, FLEX-WP-0032, FLEX-DEC-2026-017) adds one action, list, for informed-decision's decision overview (INFD-IN-0008). It is a separate rule, not an extra member of the act set, and it changes nothing else:

  • read and the five acts keep the v2 rule unchanged — the same eight records, the same 900-second MFA window. A list allow satisfies no other action.
  • list covers the union of this package's eight records and the three SECRETS-WP-0010-T03-* records from informed-decision.t03-review, each pinned by approval id, binding digest and its own memo version (T03 at 3). Scope stays exact-record: a memo is listable only once someone admitted it. The operator declined resource-type-wide scope because the PDP checks no recipient, and a type-wide rule would have left consumer code — which the consumer itself says is not an entitlement — as the only scope.
  • list carries the same identity bar with a 12-hour MFA window instead of 900 seconds. Looking back at your own outcomes is not binding a new one. The bar is lighter, not absent: the PDP still states a bound.
  • The KeyCape stale-timestamp defect (INFD-IN-0005) is not worked around here. read stays strict; that defect is key-cape's to fix.

The identity bar matches T03: authenticated informed-decision caller, net-kingdom-admins, fresh KeyCape AAL2 MFA. No permission follows from memo content or presentation state. TokenReview must admit system:serviceaccount:informed-decision:review before this package is served. Membership tenant provenance may follow the accepted registration 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.

import rego.v1

records := {
  "memo:infd-20260914-c02": {
    "approval_id": "ccfd8007-2061-48fd-9356-99b16279dac1",
    "binding_digest": "sha256:942cf7d5e6805987df2077a0cc6cde75b148e1729a96dd0692153287820b6a0a"
  },
  "memo:infd-20260914-c03": {
    "approval_id": "a0611d0d-b9ef-4b9a-aa79-e94a9e3fcd5f",
    "binding_digest": "sha256:95cae135b994acea6dad9da978dd3df1aa3354de900a1f43c2e5a03a20e8e844"
  },
  "memo:infd-20260914-c04": {
    "approval_id": "22ac6df3-e6a9-472b-a68e-c8caca4289a7",
    "binding_digest": "sha256:dec960b30efaf654abbdcd8a2cdd20d4ff6bf52e170744f817dc55845d9cb192"
  },
  "memo:infd-20260914-d01": {
    "approval_id": "9f7c3506-68de-4826-86ff-e301f428408d",
    "binding_digest": "sha256:8cb7cc93f38db9d19b49e201e0554b50af1891fec853fef333a06ea078541d15"
  },
  "memo:infd-20260914-d02": {
    "approval_id": "b3ce2c01-0a3b-401e-b4ed-c1954af169c9",
    "binding_digest": "sha256:be0c7de123216740d2c2eeaed80384e03e6b6d1668104f94bb8f9cbae7dfe30f"
  },
  "memo:infd-20260914-d03": {
    "approval_id": "3b483e6b-0b92-45ff-83b6-bc5057c0a496",
    "binding_digest": "sha256:3c562278e86bb5e7f747452cf2e99d3a136853ab748676e8359262b835cd1425"
  },
  "memo:infd-20260914-d04": {
    "approval_id": "356e67a3-5539-46a1-922a-f5591fd38ee5",
    "binding_digest": "sha256:3c2d7759679d871cb7c5cac8999542a365e64c918d59d0c4ce864ffb837453e4"
  },
  "memo:infd-20260921-b01": {
    "approval_id": "ba5ce2d8-8b6d-40be-af89-2e8c147029a3",
    "binding_digest": "sha256:e9eaf454e94871ec2060855fcfbd327bcaec873d2c61cae031bec9f95a34bcae"
  }
}

list_only_records := {
  "memo:SECRETS-WP-0010-T03-apply": {
    "approval_id": "b5fcbfcc-ad56-456f-bc36-c823052e9917",
    "binding_digest": "sha256:03cc5b37437f14e86b686ce4054f976556334eff3fa260b03e8014ed3d9217e5",
    "memo_version": 3
  },
  "memo:SECRETS-WP-0010-T03-verify": {
    "approval_id": "4e9ff881-d59f-4143-9155-929afbe8dd43",
    "binding_digest": "sha256:72d9267d038c17107c880ffc9009793ce9c70defbddfe2219628854b811a04b2",
    "memo_version": 3
  },
  "memo:SECRETS-WP-0010-T03-exec": {
    "approval_id": "a24e0898-b3c5-4e50-85a8-18a2c2aa229e",
    "binding_digest": "sha256:f2cf0fb53b740900756ccde5587c3578fcff44beef2f1edab17b9a198a4033d8",
    "memo_version": 3
  }
}

# listable is the union list may range over. Sitting records are memo version 1,
# as the act rule pins; T03 records carry their own version (3).
listable := object.union(
  {id: object.union(r, {"memo_version": 1}) | some id, r in records},
  list_only_records,
)

decision := {"effect": "allow", "reason": "operator_admitted_compact_sitting"} if {
  input.tenant == "tenant:platform"
  input.subject.tenant == "tenant:platform"
  input.subject.type == "human"
  is_string(input.subject.id)
  input.subject.id != ""
  input.subject.attributes.principal_type_source == "authentication-derived"
  input.subject.attributes.tenant_source in {"registration-supplied", "directory-asserted"}
  "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)
  assurance.at > 0
  age := time.now_ns() / 1000000000 - assurance.at
  age >= -30
  age <= 900
  input.resource.tenant == "tenant:platform"
  input.resource.system == "informed-decision"
  input.resource.type == "decision-memo"
  record := records[input.resource.id]
  input.context.memo_version == 1
  input.context.approval_id == record.approval_id
  input.context.approval_binding_digest == record.binding_digest
  input.action in {"read", "acknowledge", "accept", "return", "discuss", "decline"}
} else := {"effect": "allow", "reason": "operator_admitted_overview_list"} if {
  input.action == "list"
  input.tenant == "tenant:platform"
  input.subject.tenant == "tenant:platform"
  input.subject.type == "human"
  is_string(input.subject.id)
  input.subject.id != ""
  input.subject.attributes.principal_type_source == "authentication-derived"
  input.subject.attributes.tenant_source in {"registration-supplied", "directory-asserted"}
  "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)
  assurance.at > 0
  age := time.now_ns() / 1000000000 - assurance.at
  age >= -30
  age <= 43200
  input.resource.tenant == "tenant:platform"
  input.resource.system == "informed-decision"
  input.resource.type == "decision-memo"
  record := listable[input.resource.id]
  input.context.memo_version == record.memo_version
  input.context.approval_id == record.approval_id
  input.context.approval_binding_digest == record.binding_digest
} else := {"effect": "deny", "reason": "compact_sitting_scope_or_identity_refused"} if {
  true
}
package flexauth.informed_decision.compact_sitting_test
import rego.v1
import data.flexauth.informed_decision.compact_sitting

test_unknown_request_denied if {
  compact_sitting.decision.effect == "deny" with input as {}
}

test_listable_is_exact_union if {
  count(compact_sitting.listable) == count(compact_sitting.records) + count(compact_sitting.list_only_records)
}

test_t03_records_not_in_act_scope if {
  every id, _ in compact_sitting.list_only_records {
    not compact_sitting.records[id]
  }
}