Add an offline attribute-admission branch beside exact-record review.
Compact-sitting v8 can admit a new memo from carried class, submitter, and approval attributes, but shipped sets are empty and exact-record decisions stay on their pins. The sitting image pin is unchanged. Assistant: grok Assistant-Session: 01a10329-31cb-78d3-b7a3-788c2f91d6d4
This commit is contained in:
parent
d014453a1a
commit
e85f511c4f
8 changed files with 1237 additions and 10 deletions
87
internal/decision/attribute_context_test.go
Normal file
87
internal/decision/attribute_context_test.go
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package decision_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/netkingdom/flex-auth/internal/decision"
|
||||
"github.com/netkingdom/flex-auth/internal/policy"
|
||||
"github.com/netkingdom/flex-auth/internal/registry"
|
||||
"github.com/netkingdom/flex-auth/pkg/api"
|
||||
)
|
||||
|
||||
func TestAttributeContextCarriedWithoutViewHash(t *testing.T) {
|
||||
root := filepath.Join("..", "..")
|
||||
pkg, err := policy.LoadAndValidateFile(context.Background(), filepath.Join(root, "examples", "informed-decision-sitting", "policy.md"))
|
||||
if err != nil {
|
||||
t.Fatalf("LoadAndValidateFile: %v", err)
|
||||
}
|
||||
store, err := registry.LoadFile(filepath.Join(root, "examples", "informed-decision-sitting", "registry.json"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
engine, err := decision.NewEngine(store, pkg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
request := api.CheckRequest{
|
||||
ID: "attribute-context",
|
||||
Tenant: "tenant:platform",
|
||||
Subject: api.SubjectRef{
|
||||
ID: "synthetic-attribute-reviewer",
|
||||
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(),
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: "accept",
|
||||
Resource: api.ResourceRef{
|
||||
ID: "memo:intake-new-memo", Type: "decision-memo",
|
||||
System: "informed-decision", Tenant: "tenant:platform",
|
||||
},
|
||||
Context: map[string]any{
|
||||
"review_group": "net-kingdom-admins",
|
||||
"memo_class": "credential-lane",
|
||||
"intake_submitter": "state-hub",
|
||||
"approval_requester": "informed-decision",
|
||||
"approval_human_control": true,
|
||||
"memo_version": 1,
|
||||
"approval_id": "706f4205-aaa7-44f6-be30-d0f57664d69c",
|
||||
"approval_binding_digest": "sha256:c8a1a9c8fb22616e3aacfb877ba7974feb5eedaed491f856a6c90719c502ebe4",
|
||||
},
|
||||
PolicyVersion: "v8",
|
||||
}
|
||||
got, err := engine.Check(context.Background(), request)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.Effect != api.DecisionEffectDeny || got.Reason != "unknown_class" {
|
||||
t.Fatalf("effect = %s %s; shipped sets must refuse the class", got.Effect, got.Reason)
|
||||
}
|
||||
if got.Binding == nil {
|
||||
t.Fatal("binding missing")
|
||||
}
|
||||
for _, key := range []string{
|
||||
"review_group", "memo_class", "intake_submitter", "approval_requester",
|
||||
"approval_human_control", "memo_version", "approval_id", "approval_binding_digest",
|
||||
} {
|
||||
if _, ok := got.Binding.Context[key]; !ok {
|
||||
t.Fatalf("binding context missing %s", key)
|
||||
}
|
||||
}
|
||||
if _, ok := got.Binding.Context["view_hash"]; ok {
|
||||
t.Fatal("view_hash entered the decision binding")
|
||||
}
|
||||
if got.Binding.Context["approval_requester"] != "informed-decision" || got.Binding.Context["approval_human_control"] != true {
|
||||
t.Fatalf("binding context = %#v", got.Binding.Context)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue