Implement list allowed and explain
Some checks failed
CI / Build and Test (push) Has been cancelled
CI / Lint (push) Has been cancelled

This commit is contained in:
2026-05-17 05:45:36 +02:00
parent aa70dbebe1
commit faea068721
4 changed files with 309 additions and 9 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"os"
"path/filepath"
"strings"
"testing"
"gopkg.in/yaml.v3"
@@ -125,13 +126,77 @@ func TestBatchCheckPreservesResourceOrder(t *testing.T) {
}
}
func TestListAllowedReturnsOnlyAllowedResources(t *testing.T) {
store := newTestStore(t)
if err := store.ImportResourceManifest(api.ResourceManifest{
ID: "markitect-extra-documents",
System: "markitect-tool",
Resources: []api.Resource{
{ID: "document:public-note", Type: "document", TrustZone: "public"},
},
}); err != nil {
t.Fatalf("ImportResourceManifest: %v", err)
}
engine := newTestEngineWithStore(t, store)
got, err := engine.ListAllowed(context.Background(), decision.ListAllowedRequest{
Subject: api.SubjectRef{ID: "user:alice"},
Action: "read",
System: "markitect-tool",
Filters: map[string]any{
"resource_type": "document",
},
})
if err != nil {
t.Fatalf("ListAllowed: %v", err)
}
if len(got) != 1 {
t.Fatalf("len(got) = %d; want one allowed resource: %+v", len(got), got)
}
if got[0].Resource.ID != "document:internal-note" || got[0].Effect != api.DecisionEffectAllow {
t.Fatalf("allowed decision = %+v; want document:internal-note allow", got[0])
}
}
func TestExplainUsesRecordedDecision(t *testing.T) {
engine := newTestEngine(t)
var request api.CheckRequest
loadYAML(t, filepath.Join("..", "..", "examples", "caring", "check_request.yaml"), &request)
decisionEnvelope, err := engine.Check(context.Background(), request)
if err != nil {
t.Fatalf("Check: %v", err)
}
explanation, err := engine.Explain(decisionEnvelope.ID)
if err != nil {
t.Fatalf("Explain: %v", err)
}
if explanation.DecisionID != decisionEnvelope.ID {
t.Fatalf("explanation.DecisionID = %q; want %q", explanation.DecisionID, decisionEnvelope.ID)
}
if explanation.Effect != api.DecisionEffectAllow {
t.Fatalf("explanation.Effect = %q; want allow", explanation.Effect)
}
if !strings.Contains(explanation.Summary, "Customer Doer may View Data Plane resource document:internal-note") {
t.Fatalf("explanation.Summary = %q", explanation.Summary)
}
if _, err := engine.Explain("decision:missing"); err == nil {
t.Fatal("Explain accepted unknown decision id")
}
}
func newTestEngine(t *testing.T) *decision.Engine {
t.Helper()
store, err := registry.LoadFile(filepath.Join("..", "..", "examples", "caring", "registry_snapshot.json"))
if err != nil {
t.Fatalf("LoadFile registry: %v", err)
}
return newTestEngineWithStore(t, newTestStore(t))
}
func newTestEngineWithStore(t *testing.T, store *registry.Store) *decision.Engine {
t.Helper()
policyPackage, err := policy.LoadAndValidateFile(context.Background(), filepath.Join("..", "..", "examples", "caring", "policy_package.md"))
if err != nil {
t.Fatalf("LoadAndValidateFile policy: %v", err)
@@ -143,6 +208,16 @@ func newTestEngine(t *testing.T) *decision.Engine {
return engine
}
func newTestStore(t *testing.T) *registry.Store {
t.Helper()
store, err := registry.LoadFile(filepath.Join("..", "..", "examples", "caring", "registry_snapshot.json"))
if err != nil {
t.Fatalf("LoadFile registry: %v", err)
}
return store
}
func loadYAML(t *testing.T, path string, out any) {
t.Helper()