generated from coulomb/repo-seed
Pin FlexAuthResourceManifest schema (resource-registration-v0)
Closes FLEX-WP-0005 T03. Shape pinned against the Markitect-side emitter in markitect-tool/src/markitect_tool/policy/enterprise.py (FlexAuthResource + FlexAuthResourceManifest dataclasses, MKTT-WP-0014). Artifacts: - schemas/resource_manifest.schema.json (JSON Schema draft 2020-12) - examples/markitect/resource_manifest.yaml (mirrors markitect-tool's example; metadata.flex_auth_contract = resource-registration-v0) - pkg/api/resource_manifest.go (Go type with json + yaml tags, plus FlexAuthContractV0 const) - pkg/api/resource_manifest_test.go (golden parse of the example + minimal-fields round-trip) First external dep: gopkg.in/yaml.v3 v3.0.1. SBOM ingested into State Hub (2 entries) — repo last_sbom_at now non-null. Makefile sbom target gains a GOPATH/bin fallback so it works without ~/go/bin on PATH. Interface change published to State Hub (a4a5293e-…) and inbox-notified markitect-tool. The change is additive — Markitect's existing emitter matches the pinned schema exactly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
30
pkg/api/resource_manifest.go
Normal file
30
pkg/api/resource_manifest.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package api
|
||||
|
||||
// ResourceManifest is the shape a protected system publishes to register
|
||||
// its resources with flex-auth. The shape is pinned against the
|
||||
// Markitect-side emitter in markitect-tool (MKTT-WP-0014); see
|
||||
// schemas/resource_manifest.schema.json for the JSON Schema and
|
||||
// examples/markitect/resource_manifest.yaml for the canonical example.
|
||||
type ResourceManifest struct {
|
||||
ID string `json:"id" yaml:"id"`
|
||||
System string `json:"system" yaml:"system"`
|
||||
Resources []Resource `json:"resources" yaml:"resources"`
|
||||
Actions []string `json:"actions,omitempty" yaml:"actions,omitempty"`
|
||||
Metadata map[string]any `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// Resource is one entry in a ResourceManifest.
|
||||
type Resource struct {
|
||||
ID string `json:"id" yaml:"id"`
|
||||
Type string `json:"type" yaml:"type"`
|
||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||
Parent string `json:"parent,omitempty" yaml:"parent,omitempty"`
|
||||
Labels []string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
TrustZone string `json:"trust_zone,omitempty" yaml:"trust_zone,omitempty"`
|
||||
Owner string `json:"owner,omitempty" yaml:"owner,omitempty"`
|
||||
Attributes map[string]any `json:"attributes,omitempty" yaml:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
// FlexAuthContractV0 is the metadata.flex_auth_contract value that
|
||||
// signals the v0 resource-registration contract.
|
||||
const FlexAuthContractV0 = "resource-registration-v0"
|
||||
89
pkg/api/resource_manifest_test.go
Normal file
89
pkg/api/resource_manifest_test.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package api_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/netkingdom/flex-auth/pkg/api"
|
||||
)
|
||||
|
||||
// TestResourceManifestExampleParses is the golden test for the pinned
|
||||
// FlexAuthResourceManifest shape. It loads examples/markitect/resource_manifest.yaml
|
||||
// and verifies every field the Markitect emitter produces.
|
||||
func TestResourceManifestExampleParses(t *testing.T) {
|
||||
path := filepath.Join("..", "..", "examples", "markitect", "resource_manifest.yaml")
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("read %s: %v", path, err)
|
||||
}
|
||||
|
||||
var got api.ResourceManifest
|
||||
if err := yaml.Unmarshal(data, &got); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
|
||||
if got.ID != "markitect-example-knowledge-base" {
|
||||
t.Errorf("ID = %q; want markitect-example-knowledge-base", got.ID)
|
||||
}
|
||||
if got.System != "markitect-tool" {
|
||||
t.Errorf("System = %q; want markitect-tool", got.System)
|
||||
}
|
||||
if got.Metadata["flex_auth_contract"] != api.FlexAuthContractV0 {
|
||||
t.Errorf("metadata.flex_auth_contract = %v; want %q", got.Metadata["flex_auth_contract"], api.FlexAuthContractV0)
|
||||
}
|
||||
|
||||
wantActions := []string{"read", "query", "search", "package", "export"}
|
||||
if len(got.Actions) != len(wantActions) {
|
||||
t.Fatalf("Actions len = %d; want %d", len(got.Actions), len(wantActions))
|
||||
}
|
||||
for i, a := range wantActions {
|
||||
if got.Actions[i] != a {
|
||||
t.Errorf("Actions[%d] = %q; want %q", i, got.Actions[i], a)
|
||||
}
|
||||
}
|
||||
|
||||
if len(got.Resources) != 3 {
|
||||
t.Fatalf("Resources len = %d; want 3", len(got.Resources))
|
||||
}
|
||||
|
||||
kb := got.Resources[0]
|
||||
if kb.ID != "knowledge-base:markitect-example" || kb.Type != "knowledge_base" {
|
||||
t.Errorf("resources[0] = %+v; want knowledge-base header", kb)
|
||||
}
|
||||
if kb.TrustZone != "public" {
|
||||
t.Errorf("resources[0].trust_zone = %q; want public", kb.TrustZone)
|
||||
}
|
||||
|
||||
internal := got.Resources[2]
|
||||
if internal.ID != "document:internal-note" {
|
||||
t.Errorf("resources[2].ID = %q; want document:internal-note", internal.ID)
|
||||
}
|
||||
if internal.Parent != "knowledge-base:markitect-example" {
|
||||
t.Errorf("resources[2].parent = %q; want knowledge-base:markitect-example", internal.Parent)
|
||||
}
|
||||
if internal.TrustZone != "internal" {
|
||||
t.Errorf("resources[2].trust_zone = %q; want internal", internal.TrustZone)
|
||||
}
|
||||
if len(internal.Labels) != 1 || internal.Labels[0] != "internal" {
|
||||
t.Errorf("resources[2].labels = %v; want [internal]", internal.Labels)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceManifestRequiredFields(t *testing.T) {
|
||||
const minimalYAML = `id: m1
|
||||
system: s1
|
||||
resources:
|
||||
- id: r1
|
||||
type: document
|
||||
`
|
||||
var m api.ResourceManifest
|
||||
if err := yaml.Unmarshal([]byte(minimalYAML), &m); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if m.ID == "" || m.System == "" || len(m.Resources) != 1 {
|
||||
t.Fatalf("minimal manifest did not round-trip: %+v", m)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user