Admit the four STATE-WP-0094 sitting memos as exact records (v10).
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:
parent
58e33d29c9
commit
58026ea34a
5 changed files with 213 additions and 5 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"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.",
|
||||
"cases": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
id: informed-decision.compact-sitting
|
||||
name: Compact sitting exact-record human review
|
||||
namespace: informed-decision:decision-memo
|
||||
version: v9
|
||||
version: v10
|
||||
status: ready
|
||||
package: flexauth.informed_decision.compact_sitting
|
||||
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
|
||||
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
|
||||
informed-decision `deploy/intake-submitters.json`. The shipped registry is
|
||||
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
|
||||
|
||||
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": {
|
||||
"approval_id": "706f4205-aaa7-44f6-be30-d0f57664d69c",
|
||||
"binding_digest": "sha256:c8a1a9c8fb22616e3aacfb877ba7974feb5eedaed491f856a6c90719c502ebe4"
|
||||
|
|
|
|||
|
|
@ -372,5 +372,73 @@
|
|||
}
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ func TestInformedDecisionAttributeAdmission(t *testing.T) {
|
|||
if !pkg.Valid {
|
||||
t.Fatalf("package invalid: %+v", pkg.Validation)
|
||||
}
|
||||
if pkg.Metadata.Version != "v9" {
|
||||
t.Fatalf("version = %s; want v9", pkg.Metadata.Version)
|
||||
if pkg.Metadata.Version != "v10" {
|
||||
t.Fatalf("version = %s; want v10", pkg.Metadata.Version)
|
||||
}
|
||||
if strings.Contains(pkg.RegoModule, "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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if doc.PolicyVersion != "v9" {
|
||||
if doc.PolicyVersion != "v10" {
|
||||
t.Fatalf("fixture policy_version = %s", doc.PolicyVersion)
|
||||
}
|
||||
exactKeys := map[string]bool{"memo_version": true, "approval_id": true, "approval_binding_digest": true}
|
||||
|
|
|
|||
113
internal/policy/informed_decision_wp0094_test.go
Normal file
113
internal/policy/informed_decision_wp0094_test.go
Normal 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")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue