package policy_test import ( "context" "encoding/json" "os" "os/exec" "path/filepath" "strings" "testing" "time" "github.com/netkingdom/access-engine/internal/policy" "github.com/netkingdom/access-engine/pkg/api" ) // FLEX-WP-0040-T07: compact-sitting v14 admits the present-existing requester // service:nk-bind-executor (INFD-WP-0010, GH-DEC-2026-026 class C2). v13 stays // in examples/informed-decision-lifecycle-review as the rollback reference. func TestInformedDecisionPresentExistingV14(t *testing.T) { dir := filepath.Join(repoRoot(t), "examples", "informed-decision-present-existing-review") pkg, err := policy.LoadAndValidateFile(context.Background(), filepath.Join(dir, "policy.md")) if err != nil { t.Fatal(err) } if !pkg.Valid { t.Fatalf("invalid package: %+v", pkg.Validation) } if pkg.Metadata.ID != "informed-decision.compact-sitting" || pkg.Metadata.Version != "v14" { t.Fatalf("package %s %s", pkg.Metadata.ID, pkg.Metadata.Version) } raw, err := os.ReadFile(filepath.Join(dir, "pin.json")) if err != nil { t.Fatal(err) } var pin map[string]string if err := json.Unmarshal(raw, &pin); err != nil { t.Fatal(err) } if pin["package_digest"] != pkg.Digest() || pin["version"] != pkg.Metadata.Version || pin["package"] != pkg.Metadata.ID { t.Fatalf("stale pin %+v; digest %s", pin, pkg.Digest()) } base := func() map[string]any { return map[string]any{ "id": "v14", "tenant": "tenant:platform", "subject": map[string]any{"id": "founder-human", "type": "human", "tenant": "tenant:platform", "attributes": map[string]any{ "principal_type_source": "authentication-derived", "tenant_source": "registration-supplied", "groups": []any{"net-kingdom-admins"}, "assurance": map[string]any{"level": "aal2", "mfa": true, "source": "key-cape", "methods": []any{"pwd", "otp"}, "at": time.Now().Unix()}, }}, "resource": map[string]any{"id": "memo:bea-bind-rotation-01", "type": "decision-memo", "system": "informed-decision", "tenant": "tenant:platform"}, "action": "accept", "context": map[string]any{ "review_group": "net-kingdom-admins", "memo_class": "bounded-execution", "intake_submitter": "nk-bind-executor", "approval_requester": "service:nk-bind-executor", "approval_human_control": true, "approval_action": "bounded-execution", "memo_version": 1, "approval_id": "706f4205-aaa7-44f6-be30-d0f57664d69c", "approval_binding_digest": "sha256:c8a1a9c8fb22616e3aacfb877ba7974feb5eedaed491f856a6c90719c502ebe4", }, } } subject := func(d map[string]any) map[string]any { return d["subject"].(map[string]any) } assurance := func(d map[string]any) map[string]any { return subject(d)["attributes"].(map[string]any)["assurance"].(map[string]any) } ctx := func(d map[string]any) map[string]any { return d["context"].(map[string]any) } tests := []struct { name, effect, reason string change func(map[string]any) }{ {"executor approval accepted by founder at aal2", "allow", "present_existing_eligible", func(map[string]any) {}}, {"read", "allow", "present_existing_eligible", func(d map[string]any) { d["action"] = "read" }}, {"actor may not approve its own approval", "deny", "self_approval_refused", func(d map[string]any) { subject(d)["id"] = "service:nk-bind-executor" }}, {"submitter slug may not approve", "deny", "self_approval_refused", func(d map[string]any) { subject(d)["id"] = "nk-bind-executor" }}, {"aal1 refused", "deny", "identity_refused", func(d map[string]any) { assurance(d)["level"] = "aal1" }}, {"stale mfa refused", "deny", "stale_mfa", func(d map[string]any) { assurance(d)["at"] = time.Now().Unix() - 901 }}, {"other approval action refused", "deny", "approval_action_not_admitted", func(d map[string]any) { ctx(d)["approval_action"] = "rotate" }}, {"missing approval action refused", "deny", "approval_action_not_admitted", func(d map[string]any) { delete(ctx(d), "approval_action") }}, {"other submitter refused", "deny", "unknown_submitter", func(d map[string]any) { ctx(d)["intake_submitter"] = "state-hub" }}, {"other class refused", "deny", "unknown_class", func(d map[string]any) { ctx(d)["memo_class"] = "decision-record" }}, {"unregistered service requester refused", "deny", "unknown_class", func(d map[string]any) { ctx(d)["approval_requester"] = "service:other" }}, {"v13 informed-decision requester unchanged", "allow", "attribute_eligible", func(d map[string]any) { ctx(d)["approval_requester"] = "informed-decision" ctx(d)["intake_submitter"] = "state-hub" ctx(d)["memo_class"] = "decision-record" delete(ctx(d), "approval_action") }}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { d := base() tc.change(d) encoded, _ := json.Marshal(d) var request api.CheckRequest if err := json.Unmarshal(encoded, &request); err != nil { t.Fatal(err) } got, err := pkg.Evaluate(context.Background(), request) if err != nil { t.Fatal(err) } if string(got.Effect) != tc.effect || got.Reason != tc.reason { t.Fatalf("got %s %s; want %s %s", got.Effect, got.Reason, tc.effect, tc.reason) } }) } } // A present-existing registry row is skipped by the generated sets: it is // admitted only by the owner-authored present_existing_profiles. func TestAdmissionGeneratorSkipsPresentExistingRows(t *testing.T) { root := repoRoot(t) dir := t.TempDir() registry := filepath.Join(dir, "submitters.json") body := `{ "system:serviceaccount:sso:nk-bind-executor": { "submitter_id": "nk-bind-executor", "memo_classes": ["bounded-execution"], "review_groups": ["net-kingdom-admins"], "daily_limit": 10, "present_existing": {"approval_actor": "service:nk-bind-executor", "actions": ["bounded-execution"]} } }` if err := os.WriteFile(registry, []byte(body), 0o644); err != nil { t.Fatal(err) } check := exec.Command("python3", filepath.Join(root, "tools/gen_informed_decision_admission.py"), "--source", registry, "--policy", sittingPolicyPath(t), "--check") if out, err := check.CombinedOutput(); err != nil || !strings.Contains(string(out), "0 submitters, 0 classes; in sync") { t.Fatalf("present-existing row changed the generated sets: %v\n%s", err, out) } }