Admit the four STATE-WP-0094 sitting memos as exact records (v10).
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 1m14s

Version v10 pins approvals 974eae4d, 77993081, 4ae04c8e and b75752d1 from
informed-decision docs/evidence/2026-10-04-state-hub-wp0094-approval-create.json.
All earlier exact records, including v9's profile memo, stay. The attribute
branch still admits nobody. Package digest
sha256:ede11f888d57809dfce1b04d2323708c7244f36187fd5a58dd738437a05e7e91.
The values pin stays on the v9 image until CI builds this commit.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 692292@bnt-lap001
Assistant-Session: 89c7d8e8-e1b3-47eb-9411-a0ab227fca2f
This commit is contained in:
tegwick 2026-10-04 14:26:14 +02:00
parent 58e33d29c9
commit 58026ea34a
5 changed files with 213 additions and 5 deletions

View file

@ -1,6 +1,6 @@
{ {
"policy_id": "informed-decision.compact-sitting", "policy_id": "informed-decision.compact-sitting",
"policy_version": "v9", "policy_version": "v10",
"note": "Offline request/response fixtures. Shipped admitted sets are empty, so attribute_eligible is not in this file. An allow here is an exact-record pin, not proof of a live approval.", "note": "Offline request/response fixtures. Shipped admitted sets are empty, so attribute_eligible is not in this file. An allow here is an exact-record pin, not proof of a live approval.",
"cases": [ "cases": [
{ {

View file

@ -2,7 +2,7 @@
id: informed-decision.compact-sitting id: informed-decision.compact-sitting
name: Compact sitting exact-record human review name: Compact sitting exact-record human review
namespace: informed-decision:decision-memo namespace: informed-decision:decision-memo
version: v9 version: v10
status: ready status: ready
package: flexauth.informed_decision.compact_sitting package: flexauth.informed_decision.compact_sitting
allow_ttl: 30s allow_ttl: 30s
@ -88,6 +88,17 @@ v9 (2026-10-04, EMERGENT-WP-0002 profile adoption) adds exactly one record,
attribute branch remains beside them and still admits nobody, because the attribute branch remains beside them and still admits nobody, because the
shipped submitter and class sets are empty. shipped submitter and class sets are empty.
v10 (2026-10-04, STATE-WP-0094 production-steps sitting) adds exactly four
records: `memo:state-hub-edge-receiving-rollout-c287ed8`,
`memo:owner-return-pickup-plan-b6222af`,
`memo:freshness-runner-deploy-trial-e77f8b4` and
`memo:freshness-schedule-enable-retire-sweep`. Native pins come from
informed-decision `docs/evidence/2026-10-04-state-hub-wp0094-approval-create.json`,
approvals `974eae4d-782d-41ed-93be-e34433b5fe59`,
`77993081-1db2-4bba-99f2-74ca1f8652b1`, `4ae04c8e-d604-4d8b-b166-693eef855da8`
and `b75752d1-bab6-4cf3-9308-5368c1d5aa91`. Existing exact records, including
v9's, stay. The v8 attribute branch still admits nobody.
`admitted_submitters` and `admitted_classes` are generated from `admitted_submitters` and `admitted_classes` are generated from
informed-decision `deploy/intake-submitters.json`. The shipped registry is informed-decision `deploy/intake-submitters.json`. The shipped registry is
empty, so both sets are empty and this branch admits nobody. Regenerate with empty, so both sets are empty and this branch admits nobody. Regenerate with
@ -106,6 +117,22 @@ approval. Native pins: `docs/evidence/2026-09-15-sitting-approval-creates.json`.
import rego.v1 import rego.v1
records := { records := {
"memo:state-hub-edge-receiving-rollout-c287ed8": {
"approval_id": "974eae4d-782d-41ed-93be-e34433b5fe59",
"binding_digest": "sha256:84735b88b2db20d9445af369e28a8d40bd495dd20c0303ff3a764666ec976dde"
},
"memo:owner-return-pickup-plan-b6222af": {
"approval_id": "77993081-1db2-4bba-99f2-74ca1f8652b1",
"binding_digest": "sha256:e745ef64658e77e41b2a5ef569ec0f6986e120d338656d75749425f5f29b7ca0"
},
"memo:freshness-runner-deploy-trial-e77f8b4": {
"approval_id": "4ae04c8e-d604-4d8b-b166-693eef855da8",
"binding_digest": "sha256:f8ff89dd353c1d2006622c45996c0f05f050865f8c203373dc74da1ba3f05e24"
},
"memo:freshness-schedule-enable-retire-sweep": {
"approval_id": "b75752d1-bab6-4cf3-9308-5368c1d5aa91",
"binding_digest": "sha256:cc3e8fe6ace5438f19d647d3de226407c8b009985c82ad9a993e81226e6f316f"
},
"memo:infd-20261003-p01": { "memo:infd-20261003-p01": {
"approval_id": "706f4205-aaa7-44f6-be30-d0f57664d69c", "approval_id": "706f4205-aaa7-44f6-be30-d0f57664d69c",
"binding_digest": "sha256:c8a1a9c8fb22616e3aacfb877ba7974feb5eedaed491f856a6c90719c502ebe4" "binding_digest": "sha256:c8a1a9c8fb22616e3aacfb877ba7974feb5eedaed491f856a6c90719c502ebe4"

View file

@ -372,5 +372,73 @@
} }
}, },
"memo_version": 1 "memo_version": 1
},
"memo:state-hub-edge-receiving-rollout-c287ed8": {
"approval_id": "974eae4d-782d-41ed-93be-e34433b5fe59",
"binding_digest": "sha256:84735b88b2db20d9445af369e28a8d40bd495dd20c0303ff3a764666ec976dde",
"label": "wp0094-m1-state-hub-c287ed8",
"binding": {
"action": "accept",
"actor": "informed-decision",
"principal": "state-hub",
"purpose": "Production rollout of tested source; rollback is helm rollback to revision 72 without schema downgrade.",
"target": {
"id": "state-hub:source:c287ed82594313394ca8e67ce40714c90e744af6",
"system": "state-hub",
"type": "service-release"
}
},
"memo_version": 1
},
"memo:owner-return-pickup-plan-b6222af": {
"approval_id": "77993081-1db2-4bba-99f2-74ca1f8652b1",
"binding_digest": "sha256:e745ef64658e77e41b2a5ef569ec0f6986e120d338656d75749425f5f29b7ca0",
"label": "wp0094-m2-owner-return-b6222af",
"binding": {
"action": "accept",
"actor": "informed-decision",
"principal": "activity-core",
"purpose": "Plan approval plus a gated single-repo trial; the definition stays disabled and wakeups never clear waits.",
"target": {
"id": "activity-core:source:b6222af2cfd1094360a0d430e3907e8788a3acf9:owner-return-pickup",
"system": "activity-core",
"type": "activity-plan"
}
},
"memo_version": 1
},
"memo:freshness-runner-deploy-trial-e77f8b4": {
"approval_id": "4ae04c8e-d604-4d8b-b166-693eef855da8",
"binding_digest": "sha256:f8ff89dd353c1d2006622c45996c0f05f050865f8c203373dc74da1ba3f05e24",
"label": "wp0094-m3-freshness-runner-e77f8b4",
"binding": {
"action": "accept",
"actor": "informed-decision",
"principal": "repo-manager",
"purpose": "Deployment and limited data-writing trials; no schedule.",
"target": {
"id": "repo-manager:source:e77f8b457647ff23697e45a74615edde5f42d39d",
"system": "repo-manager",
"type": "service-release"
}
},
"memo_version": 1
},
"memo:freshness-schedule-enable-retire-sweep": {
"approval_id": "b75752d1-bab6-4cf3-9308-5368c1d5aa91",
"binding_digest": "sha256:cc3e8fe6ace5438f19d647d3de226407c8b009985c82ad9a993e81226e6f316f",
"label": "wp0094-m4-freshness-schedule",
"binding": {
"action": "accept",
"actor": "informed-decision",
"principal": "activity-core",
"purpose": "Recurring schedule activation after clean trials, and permanent retirement of the legacy sweep.",
"target": {
"id": "activity-core:definition:repo-manager-bounded-freshness:b2c6c5613218dea9dbaef303aff22a8d1b07f074",
"system": "activity-core",
"type": "activity-schedule"
}
},
"memo_version": 1
} }
} }

View file

@ -23,8 +23,8 @@ func TestInformedDecisionAttributeAdmission(t *testing.T) {
if !pkg.Valid { if !pkg.Valid {
t.Fatalf("package invalid: %+v", pkg.Validation) t.Fatalf("package invalid: %+v", pkg.Validation)
} }
if pkg.Metadata.Version != "v9" { if pkg.Metadata.Version != "v10" {
t.Fatalf("version = %s; want v9", pkg.Metadata.Version) t.Fatalf("version = %s; want v10", pkg.Metadata.Version)
} }
if strings.Contains(pkg.RegoModule, "view_hash") { if strings.Contains(pkg.RegoModule, "view_hash") {
t.Fatal("rule module reads view_hash") t.Fatal("rule module reads view_hash")
@ -50,7 +50,7 @@ func TestInformedDecisionAttributeAdmission(t *testing.T) {
if err := json.Unmarshal(raw, &doc); err != nil { if err := json.Unmarshal(raw, &doc); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if doc.PolicyVersion != "v9" { if doc.PolicyVersion != "v10" {
t.Fatalf("fixture policy_version = %s", doc.PolicyVersion) t.Fatalf("fixture policy_version = %s", doc.PolicyVersion)
} }
exactKeys := map[string]bool{"memo_version": true, "approval_id": true, "approval_binding_digest": true} exactKeys := map[string]bool{"memo_version": true, "approval_id": true, "approval_binding_digest": true}

View file

@ -0,0 +1,113 @@
package policy_test
import (
"context"
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/netkingdom/flex-auth/internal/policy"
"github.com/netkingdom/flex-auth/pkg/api"
)
// v10 admits exactly the four STATE-WP-0094 sitting memos. Pins come from
// informed-decision docs/evidence/2026-10-04-state-hub-wp0094-approval-create.json.
var wp0094Records = map[string][2]string{
"memo:state-hub-edge-receiving-rollout-c287ed8": {"974eae4d-782d-41ed-93be-e34433b5fe59", "sha256:84735b88b2db20d9445af369e28a8d40bd495dd20c0303ff3a764666ec976dde"},
"memo:owner-return-pickup-plan-b6222af": {"77993081-1db2-4bba-99f2-74ca1f8652b1", "sha256:e745ef64658e77e41b2a5ef569ec0f6986e120d338656d75749425f5f29b7ca0"},
"memo:freshness-runner-deploy-trial-e77f8b4": {"4ae04c8e-d604-4d8b-b166-693eef855da8", "sha256:f8ff89dd353c1d2006622c45996c0f05f050865f8c203373dc74da1ba3f05e24"},
"memo:freshness-schedule-enable-retire-sweep": {"b75752d1-bab6-4cf3-9308-5368c1d5aa91", "sha256:cc3e8fe6ace5438f19d647d3de226407c8b009985c82ad9a993e81226e6f316f"},
}
func TestWP0094ExactRecords(t *testing.T) {
pkg, err := policy.LoadAndValidateFile(context.Background(), sittingPolicyPath(t))
if err != nil || !pkg.Valid {
t.Fatalf("load: %v %+v", err, pkg)
}
var doc struct {
Cases []struct {
ID string `json:"id"`
Assurance string `json:"assurance"`
Request api.CheckRequest `json:"request"`
} `json:"cases"`
}
raw, err := os.ReadFile(filepath.Join(sittingDir(t), "attribute_admission_v8.json"))
if err != nil {
t.Fatal(err)
}
if err := json.Unmarshal(raw, &doc); err != nil {
t.Fatal(err)
}
templates := map[string]api.CheckRequest{}
for _, c := range doc.Cases {
req := c.Request
stampAssurance(t, &req, c.Assurance)
templates[c.ID] = req
}
exact, ok := templates["exact-record-allow"]
if !ok {
t.Fatal("exact-record-allow template missing")
}
attr, ok := templates["attribute-unknown-class"]
if !ok {
t.Fatal("attribute-unknown-class template missing")
}
var shipped map[string]struct {
ApprovalID string `json:"approval_id"`
BindingDigest string `json:"binding_digest"`
}
if err := json.Unmarshal(mustRead(t, filepath.Join(sittingDir(t), "records.json")), &shipped); err != nil {
t.Fatal(err)
}
eval := func(name string, req api.CheckRequest, effect, reason string) {
t.Helper()
got, err := pkg.Evaluate(context.Background(), req)
if err != nil {
t.Fatalf("%s: %v", name, err)
}
if string(got.Effect) != effect || got.Reason != reason {
t.Fatalf("%s: got %s %s; want %s %s", name, got.Effect, got.Reason, effect, reason)
}
}
for memo, pin := range wp0094Records {
if r := shipped[memo]; r.ApprovalID != pin[0] || r.BindingDigest != pin[1] {
t.Fatalf("records.json pin for %s = %+v", memo, r)
}
req := exact
req.Resource.ID = memo
req.Context = copyContext(exact.Context)
req.Context["approval_id"] = pin[0]
req.Context["approval_binding_digest"] = pin[1]
eval(memo+" exact", req, "allow", "operator_admitted_compact_sitting")
wrong := req
wrong.Context = copyContext(req.Context)
wrong.Context["approval_binding_digest"] = "sha256:0000000000000000000000000000000000000000000000000000000000000000"
eval(memo+" wrong digest", wrong, "deny", "compact_sitting_scope_or_identity_refused")
swapped := req
swapped.Context = copyContext(req.Context)
swapped.Context["approval_id"] = "05751e09-3a5b-4a41-a4e8-b79e96de6484"
eval(memo+" foreign approval id", swapped, "deny", "compact_sitting_scope_or_identity_refused")
}
// v9's record stays admitted.
v9 := exact
v9.Resource.ID = "memo:emergent-profile-adoption-0-2-6"
v9.Context = copyContext(exact.Context)
v9.Context["approval_id"] = "05751e09-3a5b-4a41-a4e8-b79e96de6484"
v9.Context["approval_binding_digest"] = "sha256:7843e660694dcd7c806dc02ee0cca05dd3a96488f614b1946291496259a02001"
eval("v9 record", v9, "allow", "operator_admitted_compact_sitting")
// An unlisted sibling memo in attribute shape is not admitted.
unlisted := attr
unlisted.Resource.ID = "memo:freshness-schedule-enable-retire-sweep-v2"
unlisted.Context = copyContext(attr.Context)
unlisted.Context["approval_id"] = "b75752d1-bab6-4cf3-9308-5368c1d5aa91"
unlisted.Context["approval_binding_digest"] = "sha256:cc3e8fe6ace5438f19d647d3de226407c8b009985c82ad9a993e81226e6f316f"
eval("unlisted memo", unlisted, "deny", "unknown_class")
}