// Package layer asserts the NetKingdom security-layer-model §11 declaration. package layer import ( "fmt" "os" "path/filepath" "regexp" "strings" "gopkg.in/yaml.v3" ) // Layer vocabulary from security-layer-model_v0.7 §3. var validLayers = map[string]bool{ "Staff": true, "Engine": true, "Tooling": true, } // Engine roles from §3.3. An Engine declaration must state one. var validEngineRoles = map[string]bool{ "PDP": true, "PIP": true, } // Tooling clients are invocations, not mentions. These match import paths and // argv construction that would actually contact OpenBao/Vault. var toolingPatterns = []*regexp.Regexp{ regexp.MustCompile(`github\.com/hashicorp/vault`), regexp.MustCompile(`github\.com/openbao/`), regexp.MustCompile(`exec\.Command\([^)]*["'](?:bao|vault)["']`), } // Declaration is the machine-readable §11 form carried in INTENT.md frontmatter. type Declaration struct { Layer string `yaml:"layer"` Role string `yaml:"role"` Framework string `yaml:"framework"` StandardVersion string `yaml:"standard_version"` DeclaredBy string `yaml:"declared_by"` DeclaredAt string `yaml:"declared_at"` PepStance any `yaml:"pep_stance"` ToolingContacts []any `yaml:"tooling_contacts"` } // Check parses INTENT.md, asserts the Engine/PDP declaration, and scans // production Go sources for undeclared Tooling clients. func Check(root string) error { decl, err := LoadDeclaration(filepath.Join(root, "INTENT.md")) if err != nil { return err } if err := ValidateDeclaration(decl); err != nil { return err } hits, err := ScanToolingClients(root) if err != nil { return err } if len(hits) > 0 { return fmt.Errorf("undeclared Tooling client(s) under §11: %s", strings.Join(hits, "; ")) } return nil } // LoadDeclaration reads YAML frontmatter from INTENT.md. func LoadDeclaration(path string) (Declaration, error) { data, err := os.ReadFile(path) if err != nil { return Declaration{}, fmt.Errorf("read layer declaration: %w", err) } frontmatter, err := splitFrontmatter(string(data)) if err != nil { return Declaration{}, err } var decl Declaration if err := yaml.Unmarshal([]byte(frontmatter), &decl); err != nil { return Declaration{}, fmt.Errorf("parse layer declaration: %w", err) } return decl, nil } // ValidateDeclaration asserts §3 vocabulary and Engine-role presence. func ValidateDeclaration(decl Declaration) error { if !validLayers[decl.Layer] { return fmt.Errorf("layer %q is not in the §3 vocabulary (Staff, Engine, Tooling)", decl.Layer) } if decl.Layer == "Engine" && !validEngineRoles[decl.Role] { return fmt.Errorf("Engine declaration must state role PDP or PIP; got %q", decl.Role) } if decl.Layer != "Engine" && strings.TrimSpace(decl.Role) != "" { return fmt.Errorf("layer %q must not state an Engine role", decl.Layer) } if len(decl.ToolingContacts) > 0 { return fmt.Errorf("Engine/PDP holds no Tooling client; tooling_contacts must be empty") } if decl.PepStance != nil { return fmt.Errorf("flex-auth is not PEP-shaped; pep_stance must be null") } return nil } // ScanToolingClients returns production Go files that invoke OpenBao/Vault. func ScanToolingClients(root string) ([]string, error) { var hits []string for _, dir := range []string{"cmd", "internal", "pkg"} { err := filepath.WalkDir(filepath.Join(root, dir), func(path string, d os.DirEntry, err error) error { if err != nil { return err } if d.IsDir() || !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") { return nil } body, err := os.ReadFile(path) if err != nil { return err } for _, pattern := range toolingPatterns { if pattern.Find(body) != nil { rel, _ := filepath.Rel(root, path) hits = append(hits, rel) break } } return nil }) if err != nil && !os.IsNotExist(err) { return nil, err } } return hits, nil } func splitFrontmatter(document string) (string, error) { document = strings.TrimPrefix(document, "\ufeff") lines := strings.SplitAfter(document, "\n") if len(lines) == 0 || strings.TrimSpace(lines[0]) != "---" { return "", fmt.Errorf("INTENT.md must start with YAML frontmatter") } for i := 1; i < len(lines); i++ { if strings.TrimSpace(lines[i]) == "---" { return strings.Join(lines[1:i], ""), nil } } return "", fmt.Errorf("INTENT.md frontmatter is not closed") }