{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://stellaops.io/schemas/policy-pack.schema.json", "title": "Stella Ops Policy Pack", "description": "Schema for validating Stella Ops policy pack YAML files", "type": "object", "required": ["apiVersion", "kind", "metadata", "spec"], "properties": { "apiVersion": { "type": "string", "pattern": "^policy\\.stellaops\\.io/v[0-9]+$", "description": "API version for the policy pack format", "examples": ["policy.stellaops.io/v1"] }, "kind": { "type": "string", "enum": ["PolicyPack", "PolicyOverride"], "description": "Type of policy document" }, "metadata": { "$ref": "#/$defs/Metadata" }, "spec": { "$ref": "#/$defs/PolicySpec" } }, "$defs": { "Metadata": { "type": "object", "required": ["name", "version"], "properties": { "name": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$", "minLength": 2, "maxLength": 63, "description": "Unique identifier for the policy pack" }, "version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9]+)?$", "description": "Semantic version of the policy pack" }, "description": { "type": "string", "maxLength": 500, "description": "Human-readable description" }, "labels": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Key-value labels for categorization" }, "annotations": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Key-value annotations for custom metadata" }, "parent": { "type": "string", "description": "Parent policy pack name (for overrides)" }, "environment": { "type": "string", "enum": ["development", "staging", "production", "all"], "description": "Target environment for this policy" } } }, "PolicySpec": { "type": "object", "properties": { "settings": { "$ref": "#/$defs/PolicySettings" }, "rules": { "type": "array", "items": { "$ref": "#/$defs/PolicyRule" }, "description": "List of policy rules" }, "ruleOverrides": { "type": "array", "items": { "$ref": "#/$defs/RuleOverride" }, "description": "Overrides for parent policy rules" }, "additionalRules": { "type": "array", "items": { "$ref": "#/$defs/PolicyRule" }, "description": "Additional rules to add on top of parent" } } }, "PolicySettings": { "type": "object", "properties": { "defaultAction": { "type": "string", "enum": ["allow", "warn", "block"], "default": "warn", "description": "Default action for unmatched findings" }, "unknownsThreshold": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.05, "description": "Maximum ratio of packages with unknown metadata (0.0-1.0)" }, "requireSignedSbom": { "type": "boolean", "default": true, "description": "Require cryptographically signed SBOM" }, "requireSignedVerdict": { "type": "boolean", "default": true, "description": "Require cryptographically signed policy verdict" }, "minimumVexTrustScore": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.5, "description": "Minimum trust score for VEX source acceptance" } } }, "PolicyRule": { "type": "object", "required": ["name", "action"], "properties": { "name": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$", "description": "Unique rule identifier" }, "description": { "type": "string", "description": "Human-readable rule description" }, "priority": { "type": "integer", "minimum": 0, "maximum": 1000, "default": 50, "description": "Rule priority (higher = evaluated first)" }, "type": { "type": "string", "enum": ["finding", "aggregate"], "default": "finding", "description": "Rule type: per-finding or aggregate" }, "match": { "$ref": "#/$defs/RuleMatch", "description": "Conditions that must match for rule to apply" }, "unless": { "$ref": "#/$defs/RuleUnless", "description": "Conditions that exempt from this rule" }, "require": { "$ref": "#/$defs/RuleRequire", "description": "Requirements that must be met" }, "action": { "type": "string", "enum": ["allow", "warn", "block"], "description": "Action to take when rule matches" }, "log": { "type": "boolean", "default": false, "description": "Whether to log when rule matches" }, "logLevel": { "type": "string", "enum": ["minimal", "normal", "verbose"], "default": "normal" }, "message": { "type": "string", "description": "Message template with {variable} placeholders" } } }, "RuleMatch": { "type": "object", "properties": { "always": { "type": "boolean", "description": "Always match (for default rules)" }, "severity": { "oneOf": [ { "type": "string", "enum": ["CRITICAL", "HIGH", "MEDIUM", "LOW", "UNKNOWN"] }, { "type": "array", "items": { "type": "string", "enum": ["CRITICAL", "HIGH", "MEDIUM", "LOW", "UNKNOWN"] } } ], "description": "CVE severity to match" }, "reachability": { "type": "string", "enum": ["reachable", "unreachable", "unknown"], "description": "Reachability status" }, "kev": { "type": "boolean", "description": "Match CISA KEV vulnerabilities" }, "environment": { "type": "string", "description": "Target environment" }, "isDirect": { "type": "boolean", "description": "Match direct dependencies only" }, "hasSecurityContact": { "type": "boolean", "description": "Whether package has security contact" }, "unknownsRatio": { "$ref": "#/$defs/NumericComparison", "description": "Aggregate: ratio of unknown packages" }, "hasException": { "type": "boolean", "description": "Whether finding has exception" } } }, "RuleUnless": { "type": "object", "properties": { "vexStatus": { "type": "string", "enum": ["not_affected", "affected", "fixed", "under_investigation"], "description": "VEX status that exempts from rule" }, "vexJustification": { "type": "array", "items": { "type": "string", "enum": [ "vulnerable_code_not_present", "vulnerable_code_cannot_be_controlled_by_adversary", "inline_mitigations_already_exist", "vulnerable_code_not_in_execute_path", "component_not_present" ] }, "description": "VEX justifications that exempt from rule" }, "vexTrustScore": { "$ref": "#/$defs/NumericComparison", "description": "Minimum VEX trust score for exemption" } } }, "RuleRequire": { "type": "object", "properties": { "signedSbom": { "type": "boolean", "description": "Require signed SBOM" }, "signedVerdict": { "type": "boolean", "description": "Require signed verdict" }, "exceptionApproval": { "type": "boolean", "description": "Require exception approval" }, "exceptionExpiry": { "type": "object", "properties": { "maxDays": { "type": "integer", "minimum": 1, "maximum": 365 } } } } }, "RuleOverride": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of rule to override" }, "enabled": { "type": "boolean", "description": "Enable or disable the rule" }, "action": { "type": "string", "enum": ["allow", "warn", "block"], "description": "Override action" }, "log": { "type": "boolean" }, "logLevel": { "type": "string", "enum": ["minimal", "normal", "verbose"] } } }, "NumericComparison": { "type": "object", "properties": { "gt": { "type": "number" }, "gte": { "type": "number" }, "lt": { "type": "number" }, "lte": { "type": "number" }, "eq": { "type": "number" } } } } }