feat: Add Go module and workspace test fixtures
- Created expected JSON files for Go modules and workspaces. - Added go.mod and go.sum files for example projects. - Implemented private module structure with expected JSON output. - Introduced vendored dependencies with corresponding expected JSON. - Developed PostgresGraphJobStore for managing graph jobs. - Established SQL migration scripts for graph jobs schema. - Implemented GraphJobRepository for CRUD operations on graph jobs. - Created IGraphJobRepository interface for repository abstraction. - Added unit tests for GraphJobRepository to ensure functionality.
This commit is contained in:
134
docs/schemas/advisory-key.schema.json
Normal file
134
docs/schemas/advisory-key.schema.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/advisory-key.v1.json",
|
||||
"title": "AdvisoryKey",
|
||||
"description": "Canonical advisory key for vulnerability correlation across VEX observations, policy findings, and risk assessments",
|
||||
"type": "object",
|
||||
"required": ["advisoryKey", "scope", "links"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"advisoryKey": {
|
||||
"type": "string",
|
||||
"description": "The canonical advisory key used for correlation and storage. CVE identifiers remain unchanged; non-CVE identifiers are prefixed with scope indicator (ECO:, VND:, DST:, UNK:)",
|
||||
"examples": ["CVE-2024-1234", "ECO:GHSA-XXXX-XXXX-XXXX", "VND:RHSA-2024:1234"]
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/$defs/AdvisoryScope"
|
||||
},
|
||||
"links": {
|
||||
"type": "array",
|
||||
"description": "Original and alias identifiers preserved for traceability",
|
||||
"items": {
|
||||
"$ref": "#/$defs/AdvisoryLink"
|
||||
},
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"AdvisoryScope": {
|
||||
"type": "string",
|
||||
"description": "The scope/authority level of the advisory",
|
||||
"enum": ["global", "ecosystem", "vendor", "distribution", "unknown"],
|
||||
"x-enum-descriptions": {
|
||||
"global": "Global identifiers (CVE)",
|
||||
"ecosystem": "Ecosystem-specific identifiers (GHSA)",
|
||||
"vendor": "Vendor-specific identifiers (RHSA, MSRC, ADV)",
|
||||
"distribution": "Distribution-specific identifiers (DSA, USN)",
|
||||
"unknown": "Unclassified or custom identifiers"
|
||||
}
|
||||
},
|
||||
"AdvisoryLink": {
|
||||
"type": "object",
|
||||
"description": "A link to an original or alias advisory identifier",
|
||||
"required": ["identifier", "type", "isOriginal"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"type": "string",
|
||||
"description": "The advisory identifier value",
|
||||
"examples": ["CVE-2024-1234", "GHSA-xxxx-xxxx-xxxx", "RHSA-2024:1234"]
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/$defs/AdvisoryType"
|
||||
},
|
||||
"isOriginal": {
|
||||
"type": "boolean",
|
||||
"description": "True if this is the original identifier provided at ingest time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AdvisoryType": {
|
||||
"type": "string",
|
||||
"description": "The type of advisory identifier",
|
||||
"enum": ["cve", "ghsa", "rhsa", "dsa", "usn", "msrc", "other"],
|
||||
"x-enum-descriptions": {
|
||||
"cve": "Common Vulnerabilities and Exposures (CVE-YYYY-NNNNN)",
|
||||
"ghsa": "GitHub Security Advisory (GHSA-xxxx-xxxx-xxxx)",
|
||||
"rhsa": "Red Hat Security Advisory (RHSA-YYYY:NNNN)",
|
||||
"dsa": "Debian Security Advisory (DSA-NNNN-N)",
|
||||
"usn": "Ubuntu Security Notice (USN-NNNN-N)",
|
||||
"msrc": "Microsoft Security Response Center (ADV-YYYY-NNNN)",
|
||||
"other": "Custom or unrecognized identifier format"
|
||||
}
|
||||
},
|
||||
"AdvisoryIdentifierPattern": {
|
||||
"type": "object",
|
||||
"description": "Patterns for recognizing advisory identifier formats",
|
||||
"properties": {
|
||||
"cve": {
|
||||
"type": "string",
|
||||
"const": "^CVE-\\d{4}-\\d{4,}$"
|
||||
},
|
||||
"ghsa": {
|
||||
"type": "string",
|
||||
"const": "^GHSA-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}$"
|
||||
},
|
||||
"rhsa": {
|
||||
"type": "string",
|
||||
"const": "^RH[A-Z]{2}-\\d{4}:\\d+$"
|
||||
},
|
||||
"dsa": {
|
||||
"type": "string",
|
||||
"const": "^DSA-\\d+(-\\d+)?$"
|
||||
},
|
||||
"usn": {
|
||||
"type": "string",
|
||||
"const": "^USN-\\d+(-\\d+)?$"
|
||||
},
|
||||
"msrc": {
|
||||
"type": "string",
|
||||
"const": "^(ADV|CVE)-\\d{4}-\\d+$"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"advisoryKey": "CVE-2024-1234",
|
||||
"scope": "global",
|
||||
"links": [
|
||||
{
|
||||
"identifier": "CVE-2024-1234",
|
||||
"type": "cve",
|
||||
"isOriginal": true
|
||||
},
|
||||
{
|
||||
"identifier": "GHSA-xxxx-xxxx-xxxx",
|
||||
"type": "ghsa",
|
||||
"isOriginal": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"advisoryKey": "ECO:GHSA-XXXX-XXXX-XXXX",
|
||||
"scope": "ecosystem",
|
||||
"links": [
|
||||
{
|
||||
"identifier": "GHSA-xxxx-xxxx-xxxx",
|
||||
"type": "ghsa",
|
||||
"isOriginal": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
233
docs/schemas/authority-effective-write.schema.json
Normal file
233
docs/schemas/authority-effective-write.schema.json
Normal file
@@ -0,0 +1,233 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/authority-effective-write.v1.json",
|
||||
"title": "AuthorityEffectiveWrite",
|
||||
"description": "Authority effective:write contract for effective policy and scope attachment management",
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"EffectivePolicy": {
|
||||
"type": "object",
|
||||
"description": "An effective policy binding that maps a policy to subjects",
|
||||
"required": ["effectivePolicyId", "tenantId", "policyId", "policyVersion", "subjectPattern", "priority", "enabled"],
|
||||
"properties": {
|
||||
"effectivePolicyId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Auto-generated unique identifier"
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string",
|
||||
"description": "Tenant this policy applies to"
|
||||
},
|
||||
"policyId": {
|
||||
"type": "string",
|
||||
"description": "Reference to the policy pack"
|
||||
},
|
||||
"policyVersion": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+\\.\\d+\\.\\d+$",
|
||||
"description": "SemVer of the policy"
|
||||
},
|
||||
"subjectPattern": {
|
||||
"type": "string",
|
||||
"description": "Glob-style pattern matching subjects",
|
||||
"examples": ["pkg:npm/*", "pkg:maven/com.example/*", "*"]
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Higher priority wins when patterns overlap"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"expiresAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Optional expiration time"
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Attached scope names"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"createdBy": {
|
||||
"type": "string",
|
||||
"description": "Actor who created this binding"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ScopeAttachment": {
|
||||
"type": "object",
|
||||
"description": "Attachment of a scope to an effective policy with conditions",
|
||||
"required": ["attachmentId", "effectivePolicyId", "scope"],
|
||||
"properties": {
|
||||
"attachmentId": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"effectivePolicyId": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"scope": {
|
||||
"type": "string",
|
||||
"description": "Scope name being attached",
|
||||
"examples": ["policy:read", "policy:write", "findings:read"]
|
||||
},
|
||||
"conditions": {
|
||||
"$ref": "#/$defs/AttachmentConditions"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AttachmentConditions": {
|
||||
"type": "object",
|
||||
"description": "Conditions under which the scope attachment applies",
|
||||
"properties": {
|
||||
"repositories": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Repository patterns (glob)"
|
||||
},
|
||||
"environments": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Environment names",
|
||||
"examples": [["production", "staging"]]
|
||||
},
|
||||
"branches": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Branch patterns (glob)"
|
||||
},
|
||||
"timeWindow": {
|
||||
"$ref": "#/$defs/TimeWindow"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeWindow": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"notBefore": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"notAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreateEffectivePolicyRequest": {
|
||||
"type": "object",
|
||||
"required": ["tenantId", "policyId", "policyVersion", "subjectPattern"],
|
||||
"properties": {
|
||||
"tenantId": {"type": "string"},
|
||||
"policyId": {"type": "string"},
|
||||
"policyVersion": {"type": "string"},
|
||||
"subjectPattern": {"type": "string"},
|
||||
"priority": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"expiresAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AttachScopeRequest": {
|
||||
"type": "object",
|
||||
"required": ["effectivePolicyId", "scope"],
|
||||
"properties": {
|
||||
"effectivePolicyId": {"type": "string", "format": "uuid"},
|
||||
"scope": {"type": "string"},
|
||||
"conditions": {"$ref": "#/$defs/AttachmentConditions"}
|
||||
}
|
||||
},
|
||||
"ResolvePolicyRequest": {
|
||||
"type": "object",
|
||||
"required": ["subject"],
|
||||
"properties": {
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Subject to resolve policy for",
|
||||
"examples": ["pkg:npm/lodash@4.17.20"]
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ResolvePolicyResponse": {
|
||||
"type": "object",
|
||||
"required": ["resolved"],
|
||||
"properties": {
|
||||
"resolved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"effectivePolicy": {
|
||||
"$ref": "#/$defs/EffectivePolicy"
|
||||
},
|
||||
"matchedPattern": {
|
||||
"type": "string"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PriorityResolutionRule": {
|
||||
"type": "object",
|
||||
"description": "Rules for resolving priority conflicts",
|
||||
"properties": {
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order": {"type": "integer"},
|
||||
"description": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"default": [
|
||||
{"order": 1, "description": "Higher priority value wins"},
|
||||
{"order": 2, "description": "More specific pattern wins (longest match)"},
|
||||
{"order": 3, "description": "Most recently updated wins"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"effectivePolicyId": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"tenantId": "default",
|
||||
"policyId": "default-policy",
|
||||
"policyVersion": "1.0.0",
|
||||
"subjectPattern": "pkg:npm/*",
|
||||
"priority": 10,
|
||||
"enabled": true,
|
||||
"scopes": ["policy:read", "findings:read"],
|
||||
"createdAt": "2025-12-06T00:00:00Z",
|
||||
"createdBy": "system"
|
||||
}
|
||||
]
|
||||
}
|
||||
461
docs/schemas/policy-studio.schema.json
Normal file
461
docs/schemas/policy-studio.schema.json
Normal file
@@ -0,0 +1,461 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/policy-studio.v1.json",
|
||||
"title": "PolicyStudio",
|
||||
"description": "Policy Studio API contract for policy lifecycle management - drafts, compilation, simulation, and approval workflows",
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"PolicyDraft": {
|
||||
"type": "object",
|
||||
"description": "A policy draft in the editing workflow",
|
||||
"required": ["draftId", "tenantId", "name", "status", "createdAt"],
|
||||
"properties": {
|
||||
"draftId": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 256
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/$defs/DraftStatus"
|
||||
},
|
||||
"dslSource": {
|
||||
"type": "string",
|
||||
"description": "StellaOps Policy DSL source code"
|
||||
},
|
||||
"compiledRego": {
|
||||
"type": "string",
|
||||
"description": "Compiled OPA Rego policy"
|
||||
},
|
||||
"compileDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"validationErrors": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/ValidationError"}
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"createdBy": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"submittedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"approvedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"approvedBy": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DraftStatus": {
|
||||
"type": "string",
|
||||
"description": "Policy draft lifecycle status",
|
||||
"enum": ["draft", "submitted", "approved", "active", "archived"]
|
||||
},
|
||||
"ValidationError": {
|
||||
"type": "object",
|
||||
"required": ["code", "message"],
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"line": {
|
||||
"type": "integer"
|
||||
},
|
||||
"column": {
|
||||
"type": "integer"
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"enum": ["error", "warning", "info"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreateDraftRequest": {
|
||||
"type": "object",
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"dslSource": {
|
||||
"type": "string"
|
||||
},
|
||||
"copyFrom": {
|
||||
"type": "string",
|
||||
"description": "Draft ID or policy ID to copy from"
|
||||
}
|
||||
}
|
||||
},
|
||||
"UpdateDraftRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"dslSource": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CompileRequest": {
|
||||
"type": "object",
|
||||
"required": ["dslSource"],
|
||||
"properties": {
|
||||
"dslSource": {
|
||||
"type": "string",
|
||||
"description": "StellaOps Policy DSL to compile"
|
||||
},
|
||||
"validateOnly": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Only validate, don't return compiled Rego"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CompileResponse": {
|
||||
"type": "object",
|
||||
"required": ["success"],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"compiledRego": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"errors": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/ValidationError"}
|
||||
},
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/ValidationError"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"SimulationRequest": {
|
||||
"type": "object",
|
||||
"required": ["draftId", "inputs"],
|
||||
"properties": {
|
||||
"draftId": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"inputs": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/SimulationInput"},
|
||||
"minItems": 1
|
||||
},
|
||||
"compareWith": {
|
||||
"type": "string",
|
||||
"description": "Policy ID to compare results against"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SimulationInput": {
|
||||
"type": "object",
|
||||
"required": ["componentPurl", "advisoryId"],
|
||||
"properties": {
|
||||
"componentPurl": {
|
||||
"type": "string"
|
||||
},
|
||||
"advisoryId": {
|
||||
"type": "string"
|
||||
},
|
||||
"cvss": {
|
||||
"type": "number"
|
||||
},
|
||||
"kev": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"reachability": {
|
||||
"type": "number"
|
||||
},
|
||||
"vexStatus": {
|
||||
"type": "string",
|
||||
"enum": ["affected", "not_affected", "fixed", "under_investigation"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"SimulationResponse": {
|
||||
"type": "object",
|
||||
"required": ["results"],
|
||||
"properties": {
|
||||
"results": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/SimulationResult"}
|
||||
},
|
||||
"summary": {
|
||||
"$ref": "#/$defs/SimulationSummary"
|
||||
},
|
||||
"comparison": {
|
||||
"$ref": "#/$defs/SimulationComparison"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SimulationResult": {
|
||||
"type": "object",
|
||||
"required": ["input", "decision", "severity"],
|
||||
"properties": {
|
||||
"input": {
|
||||
"$ref": "#/$defs/SimulationInput"
|
||||
},
|
||||
"decision": {
|
||||
"type": "string",
|
||||
"enum": ["allow", "review", "deny"]
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low", "informational"]
|
||||
},
|
||||
"score": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"matchedRules": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"rationale": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SimulationSummary": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"totalInputs": {
|
||||
"type": "integer"
|
||||
},
|
||||
"decisions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow": {"type": "integer"},
|
||||
"review": {"type": "integer"},
|
||||
"deny": {"type": "integer"}
|
||||
}
|
||||
},
|
||||
"severityCounts": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "integer"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"SimulationComparison": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"comparedWith": {
|
||||
"type": "string"
|
||||
},
|
||||
"decisionChanges": {
|
||||
"type": "integer"
|
||||
},
|
||||
"severityChanges": {
|
||||
"type": "integer"
|
||||
},
|
||||
"diff": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {"$ref": "#/$defs/SimulationInput"},
|
||||
"oldDecision": {"type": "string"},
|
||||
"newDecision": {"type": "string"},
|
||||
"oldSeverity": {"type": "string"},
|
||||
"newSeverity": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"SubmitForReviewRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"comment": {
|
||||
"type": "string"
|
||||
},
|
||||
"reviewers": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApproveRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"comment": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ActivateRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"effectiveAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "When activation should take effect"
|
||||
},
|
||||
"gradualRollout": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"rolloutPercent": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolicyVersion": {
|
||||
"type": "object",
|
||||
"description": "An immutable policy version",
|
||||
"required": ["policyId", "version", "digest", "createdAt"],
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"dslSource": {
|
||||
"type": "string"
|
||||
},
|
||||
"compiledRego": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["active", "superseded", "archived"]
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"createdBy": {
|
||||
"type": "string"
|
||||
},
|
||||
"activatedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EvaluationRequest": {
|
||||
"type": "object",
|
||||
"description": "Request to evaluate policy against input",
|
||||
"required": ["policyId", "input"],
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"description": "Specific version, or omit for active"
|
||||
},
|
||||
"input": {
|
||||
"type": "object",
|
||||
"description": "Policy evaluation input"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EvaluationResponse": {
|
||||
"type": "object",
|
||||
"required": ["policyId", "version", "digest", "decision"],
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string"
|
||||
},
|
||||
"decision": {
|
||||
"type": "string",
|
||||
"enum": ["allow", "review", "deny"]
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "string"
|
||||
},
|
||||
"cached": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"evaluatedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AuthorityScopes": {
|
||||
"type": "object",
|
||||
"description": "Required authority scopes for Policy Studio",
|
||||
"properties": {
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [
|
||||
"policy:read",
|
||||
"policy:write",
|
||||
"policy:submit",
|
||||
"policy:approve",
|
||||
"policy:activate",
|
||||
"policy:archive"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"draftId": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"tenantId": "default",
|
||||
"name": "Critical Vuln Policy",
|
||||
"status": "draft",
|
||||
"dslSource": "rule kev_critical {\n when kev = true\n then severity = critical\n}",
|
||||
"createdAt": "2025-12-06T00:00:00Z",
|
||||
"createdBy": "user@example.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
364
docs/schemas/risk-scoring.schema.json
Normal file
364
docs/schemas/risk-scoring.schema.json
Normal file
@@ -0,0 +1,364 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/risk-scoring.v1.json",
|
||||
"title": "RiskScoring",
|
||||
"description": "Risk scoring contract for vulnerability prioritization - job requests, results, and profiles",
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"RiskScoringJobRequest": {
|
||||
"type": "object",
|
||||
"description": "Request to create a risk scoring job",
|
||||
"required": ["tenantId", "contextId", "profileId", "findings"],
|
||||
"properties": {
|
||||
"tenantId": {
|
||||
"type": "string",
|
||||
"description": "Tenant identifier"
|
||||
},
|
||||
"contextId": {
|
||||
"type": "string",
|
||||
"description": "Context/snapshot identifier"
|
||||
},
|
||||
"profileId": {
|
||||
"type": "string",
|
||||
"description": "Risk profile to use for scoring"
|
||||
},
|
||||
"findings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/FindingInput"
|
||||
},
|
||||
"minItems": 1
|
||||
},
|
||||
"priority": {
|
||||
"$ref": "#/$defs/JobPriority"
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "string",
|
||||
"description": "Optional correlation ID for tracing"
|
||||
},
|
||||
"requestedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Request timestamp (defaults to now)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"FindingInput": {
|
||||
"type": "object",
|
||||
"required": ["findingId", "componentPurl", "advisoryId", "trigger"],
|
||||
"properties": {
|
||||
"findingId": {
|
||||
"type": "string",
|
||||
"description": "Finding identifier"
|
||||
},
|
||||
"componentPurl": {
|
||||
"type": "string",
|
||||
"description": "Package URL of affected component",
|
||||
"examples": ["pkg:npm/lodash@4.17.20", "pkg:maven/org.apache.log4j/log4j-core@2.14.1"]
|
||||
},
|
||||
"advisoryId": {
|
||||
"type": "string",
|
||||
"description": "Advisory/CVE identifier",
|
||||
"examples": ["CVE-2024-1234"]
|
||||
},
|
||||
"trigger": {
|
||||
"$ref": "#/$defs/ScoringTrigger"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ScoringTrigger": {
|
||||
"type": "string",
|
||||
"description": "Event that triggered rescoring",
|
||||
"enum": ["created", "updated", "enriched", "vex_applied"]
|
||||
},
|
||||
"JobPriority": {
|
||||
"type": "string",
|
||||
"description": "Job priority level",
|
||||
"enum": ["low", "normal", "high", "emergency"],
|
||||
"default": "normal"
|
||||
},
|
||||
"RiskScoringJob": {
|
||||
"type": "object",
|
||||
"description": "A queued or completed risk scoring job",
|
||||
"required": ["jobId", "tenantId", "contextId", "profileId", "status"],
|
||||
"properties": {
|
||||
"jobId": {
|
||||
"type": "string",
|
||||
"description": "Unique job identifier"
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string"
|
||||
},
|
||||
"contextId": {
|
||||
"type": "string"
|
||||
},
|
||||
"profileId": {
|
||||
"type": "string"
|
||||
},
|
||||
"profileHash": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$",
|
||||
"description": "SHA-256 hash of profile for reproducibility"
|
||||
},
|
||||
"findings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/FindingInput"
|
||||
}
|
||||
},
|
||||
"priority": {
|
||||
"$ref": "#/$defs/JobPriority"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/$defs/JobStatus"
|
||||
},
|
||||
"requestedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"startedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"completedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "string"
|
||||
},
|
||||
"errorMessage": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"JobStatus": {
|
||||
"type": "string",
|
||||
"description": "Job execution status",
|
||||
"enum": ["queued", "running", "completed", "failed", "cancelled"]
|
||||
},
|
||||
"RiskScoringResult": {
|
||||
"type": "object",
|
||||
"description": "Result of scoring a single finding",
|
||||
"required": ["findingId", "profileId", "profileVersion", "rawScore", "normalizedScore", "severity", "scoredAt"],
|
||||
"properties": {
|
||||
"findingId": {
|
||||
"type": "string"
|
||||
},
|
||||
"profileId": {
|
||||
"type": "string"
|
||||
},
|
||||
"profileVersion": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
||||
},
|
||||
"rawScore": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Unweighted sum of signal values"
|
||||
},
|
||||
"normalizedScore": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Weighted and clamped final score"
|
||||
},
|
||||
"severity": {
|
||||
"$ref": "#/$defs/Severity"
|
||||
},
|
||||
"signalValues": {
|
||||
"type": "object",
|
||||
"description": "Individual signal values",
|
||||
"additionalProperties": {
|
||||
"oneOf": [
|
||||
{"type": "number"},
|
||||
{"type": "boolean"}
|
||||
]
|
||||
},
|
||||
"examples": [{"cvss": 7.5, "kev": true, "reachability": 0.9}]
|
||||
},
|
||||
"signalContributions": {
|
||||
"type": "object",
|
||||
"description": "Weighted contribution of each signal",
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
}
|
||||
},
|
||||
"overrideApplied": {
|
||||
"type": "string",
|
||||
"description": "Name of override rule if applied"
|
||||
},
|
||||
"overrideReason": {
|
||||
"type": "string",
|
||||
"description": "Human-readable reason for override"
|
||||
},
|
||||
"scoredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Severity": {
|
||||
"type": "string",
|
||||
"description": "Risk severity level",
|
||||
"enum": ["critical", "high", "medium", "low", "informational"]
|
||||
},
|
||||
"RiskProfileModel": {
|
||||
"type": "object",
|
||||
"description": "Risk profile defining scoring rules",
|
||||
"required": ["id", "version", "signals", "weights"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Profile identifier",
|
||||
"examples": ["default-profile", "critical-only"]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"extends": {
|
||||
"type": "string",
|
||||
"description": "Parent profile to inherit from"
|
||||
},
|
||||
"signals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/RiskSignal"
|
||||
},
|
||||
"minItems": 1
|
||||
},
|
||||
"weights": {
|
||||
"type": "object",
|
||||
"description": "Signal name to weight mapping (must sum to 1.0)",
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"$ref": "#/$defs/RiskOverrides"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskSignal": {
|
||||
"type": "object",
|
||||
"description": "Definition of a scoring signal",
|
||||
"required": ["name", "source", "type"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"examples": ["cvss", "kev", "reachability", "fix_available"]
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"examples": ["nvd", "cisa", "scanner", "vex"]
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/$defs/SignalType"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "JSON Pointer to evidence value",
|
||||
"examples": ["/cvss/base_score", "/kev/in_catalog"]
|
||||
},
|
||||
"transform": {
|
||||
"type": "string",
|
||||
"description": "Normalization transform to apply",
|
||||
"examples": ["normalize_10", "invert", "threshold_0.5"]
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"examples": ["score", "percent", "days"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"SignalType": {
|
||||
"type": "string",
|
||||
"description": "Signal data type",
|
||||
"enum": ["boolean", "numeric", "categorical"]
|
||||
},
|
||||
"RiskOverrides": {
|
||||
"type": "object",
|
||||
"description": "Override rules for severity and decisions",
|
||||
"properties": {
|
||||
"severity": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/SeverityOverride"
|
||||
}
|
||||
},
|
||||
"decisions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/DecisionOverride"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"SeverityOverride": {
|
||||
"type": "object",
|
||||
"required": ["when", "set"],
|
||||
"properties": {
|
||||
"when": {
|
||||
"type": "object",
|
||||
"description": "Condition to match (signal name to value/expression)",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"set": {
|
||||
"$ref": "#/$defs/Severity"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DecisionOverride": {
|
||||
"type": "object",
|
||||
"required": ["when", "action"],
|
||||
"properties": {
|
||||
"when": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"action": {
|
||||
"$ref": "#/$defs/DecisionAction"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DecisionAction": {
|
||||
"type": "string",
|
||||
"description": "Policy decision action",
|
||||
"enum": ["allow", "review", "deny"]
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"jobId": "job-12345",
|
||||
"tenantId": "default",
|
||||
"contextId": "ctx-abcde",
|
||||
"profileId": "default-profile",
|
||||
"profileHash": "sha256:abc123def456...",
|
||||
"status": "completed",
|
||||
"findings": [
|
||||
{
|
||||
"findingId": "finding-001",
|
||||
"componentPurl": "pkg:npm/lodash@4.17.20",
|
||||
"advisoryId": "CVE-2024-1234",
|
||||
"trigger": "created"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
334
docs/schemas/sealed-mode.schema.json
Normal file
334
docs/schemas/sealed-mode.schema.json
Normal file
@@ -0,0 +1,334 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/sealed-mode.v1.json",
|
||||
"title": "SealedMode",
|
||||
"description": "Sealed mode contract for air-gapped operation - state management, egress policy, and bundle verification",
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"AirGapState": {
|
||||
"type": "object",
|
||||
"description": "Controller state for air-gapped environment",
|
||||
"required": ["id", "tenantId", "sealed", "lastTransitionAt"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"default": "singleton",
|
||||
"description": "State identifier (typically singleton)"
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string",
|
||||
"default": "default"
|
||||
},
|
||||
"sealed": {
|
||||
"type": "boolean",
|
||||
"description": "Whether environment is in sealed mode"
|
||||
},
|
||||
"policyHash": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$",
|
||||
"description": "Hash of active policy pack"
|
||||
},
|
||||
"timeAnchor": {
|
||||
"$ref": "#/$defs/TimeAnchor"
|
||||
},
|
||||
"lastTransitionAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "When seal/unseal last occurred"
|
||||
},
|
||||
"stalenessBudget": {
|
||||
"$ref": "#/$defs/StalenessBudget"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeAnchor": {
|
||||
"type": "object",
|
||||
"description": "Trusted time anchor for air-gapped time verification",
|
||||
"required": ["anchorTime", "source", "format"],
|
||||
"properties": {
|
||||
"anchorTime": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The anchored timestamp"
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Time source type",
|
||||
"enum": ["roughtime", "rfc3161", "unknown"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "Token format identifier"
|
||||
},
|
||||
"signatureFingerprint": {
|
||||
"type": "string",
|
||||
"description": "Hex-encoded fingerprint of signing key"
|
||||
},
|
||||
"tokenDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-f0-9]{64}$",
|
||||
"description": "SHA-256 digest of the time token"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StalenessBudget": {
|
||||
"type": "object",
|
||||
"description": "Thresholds for staleness warnings and breaches",
|
||||
"properties": {
|
||||
"warningThresholdSeconds": {
|
||||
"type": "integer",
|
||||
"default": 3600,
|
||||
"description": "Seconds until warning (default: 1 hour)"
|
||||
},
|
||||
"breachThresholdSeconds": {
|
||||
"type": "integer",
|
||||
"default": 7200,
|
||||
"description": "Seconds until breach (default: 2 hours)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StalenessEvaluation": {
|
||||
"type": "object",
|
||||
"description": "Result of staleness check",
|
||||
"required": ["ageSeconds", "isWarning", "isBreach"],
|
||||
"properties": {
|
||||
"ageSeconds": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Age of data since last sync"
|
||||
},
|
||||
"isWarning": {
|
||||
"type": "boolean",
|
||||
"description": "Age exceeds warning threshold"
|
||||
},
|
||||
"isBreach": {
|
||||
"type": "boolean",
|
||||
"description": "Age exceeds breach threshold"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SealRequest": {
|
||||
"type": "object",
|
||||
"description": "Request to seal the environment",
|
||||
"required": ["policyHash"],
|
||||
"properties": {
|
||||
"policyHash": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"timeAnchor": {
|
||||
"$ref": "#/$defs/TimeAnchor"
|
||||
},
|
||||
"stalenessBudget": {
|
||||
"$ref": "#/$defs/StalenessBudget"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SealResponse": {
|
||||
"type": "object",
|
||||
"required": ["success", "state"],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"state": {
|
||||
"$ref": "#/$defs/AirGapState"
|
||||
},
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SealedModeStatus": {
|
||||
"type": "object",
|
||||
"description": "Current sealed mode status with staleness evaluation",
|
||||
"required": ["sealed", "staleness"],
|
||||
"properties": {
|
||||
"sealed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"policyHash": {
|
||||
"type": "string"
|
||||
},
|
||||
"timeAnchor": {
|
||||
"$ref": "#/$defs/TimeAnchor"
|
||||
},
|
||||
"staleness": {
|
||||
"$ref": "#/$defs/StalenessEvaluation"
|
||||
},
|
||||
"lastTransitionAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EgressPolicy": {
|
||||
"type": "object",
|
||||
"description": "Network egress policy for sealed mode",
|
||||
"required": ["enabled", "rules"],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether egress policy is enforced"
|
||||
},
|
||||
"allowLoopback": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"allowPrivateNetworks": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/EgressRule"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"EgressRule": {
|
||||
"type": "object",
|
||||
"required": ["pattern", "action"],
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "Host pattern (domain or CIDR)"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["allow", "deny"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EgressRequest": {
|
||||
"type": "object",
|
||||
"required": ["host"],
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"protocol": {
|
||||
"type": "string",
|
||||
"enum": ["http", "https", "tcp"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"EgressDecision": {
|
||||
"type": "object",
|
||||
"required": ["allowed"],
|
||||
"properties": {
|
||||
"allowed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"matchedRule": {
|
||||
"type": "string"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
},
|
||||
"remediation": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"BundleVerifyRequest": {
|
||||
"type": "object",
|
||||
"description": "Request to verify an offline bundle",
|
||||
"required": ["bundlePath"],
|
||||
"properties": {
|
||||
"bundlePath": {
|
||||
"type": "string"
|
||||
},
|
||||
"verifyDsse": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"verifyTuf": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"verifyMerkle": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"BundleVerifyResponse": {
|
||||
"type": "object",
|
||||
"required": ["valid"],
|
||||
"properties": {
|
||||
"valid": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"dsseValid": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"tufValid": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"merkleValid": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"bundleDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"errors": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TelemetryMetrics": {
|
||||
"type": "object",
|
||||
"description": "Telemetry metrics for sealed mode monitoring",
|
||||
"properties": {
|
||||
"metrics": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"type": {"type": "string", "enum": ["gauge", "counter"]},
|
||||
"description": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"default": [
|
||||
{"name": "policy_airgap_sealed", "type": "gauge", "description": "1 if sealed, 0 if unsealed"},
|
||||
{"name": "policy_airgap_anchor_drift_seconds", "type": "gauge", "description": "Seconds since time anchor"},
|
||||
{"name": "policy_airgap_anchor_expiry_seconds", "type": "gauge", "description": "Seconds until anchor expiry"},
|
||||
{"name": "policy_airgap_seal_total", "type": "counter", "description": "Total seal operations"},
|
||||
{"name": "policy_airgap_unseal_total", "type": "counter", "description": "Total unseal operations"},
|
||||
{"name": "policy_airgap_bundle_import_blocked_total", "type": "counter", "description": "Blocked import attempts"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"id": "singleton",
|
||||
"tenantId": "default",
|
||||
"sealed": true,
|
||||
"policyHash": "sha256:abc123def456789...",
|
||||
"timeAnchor": {
|
||||
"anchorTime": "2025-12-06T00:00:00Z",
|
||||
"source": "roughtime",
|
||||
"format": "roughtime-v1",
|
||||
"tokenDigest": "abc123..."
|
||||
},
|
||||
"lastTransitionAt": "2025-12-06T00:00:00Z",
|
||||
"stalenessBudget": {
|
||||
"warningThresholdSeconds": 3600,
|
||||
"breachThresholdSeconds": 7200
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
670
docs/schemas/taskpack-control-flow.schema.json
Normal file
670
docs/schemas/taskpack-control-flow.schema.json
Normal file
@@ -0,0 +1,670 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/taskpack-control-flow.v1.json",
|
||||
"title": "TaskPackControlFlow",
|
||||
"description": "TaskPack control-flow contract for loop, conditional, and policy-gate step definitions",
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"LoopStep": {
|
||||
"type": "object",
|
||||
"description": "Loop iteration step - executes sub-steps for each item in a collection",
|
||||
"required": ["id", "type", "items", "body"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique step identifier within the pack"
|
||||
},
|
||||
"type": {
|
||||
"const": "loop"
|
||||
},
|
||||
"items": {
|
||||
"$ref": "#/$defs/LoopItemsExpression"
|
||||
},
|
||||
"iterator": {
|
||||
"type": "string",
|
||||
"description": "Variable name bound to current item (default: 'item')",
|
||||
"default": "item"
|
||||
},
|
||||
"index": {
|
||||
"type": "string",
|
||||
"description": "Variable name bound to current index (default: 'index')",
|
||||
"default": "index"
|
||||
},
|
||||
"body": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/Step"},
|
||||
"minItems": 1,
|
||||
"description": "Steps to execute for each iteration"
|
||||
},
|
||||
"maxIterations": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10000,
|
||||
"default": 1000,
|
||||
"description": "Safety limit to prevent infinite loops"
|
||||
},
|
||||
"continueOnError": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether to continue with next iteration on error"
|
||||
},
|
||||
"aggregation": {
|
||||
"$ref": "#/$defs/LoopAggregation"
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/$defs/ConditionalExpression",
|
||||
"description": "Optional condition to skip entire loop"
|
||||
}
|
||||
}
|
||||
},
|
||||
"LoopItemsExpression": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["expression"],
|
||||
"properties": {
|
||||
"expression": {
|
||||
"type": "string",
|
||||
"description": "JMESPath expression yielding an array"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["range"],
|
||||
"properties": {
|
||||
"range": {
|
||||
"type": "object",
|
||||
"required": ["start", "end"],
|
||||
"properties": {
|
||||
"start": {"type": "integer"},
|
||||
"end": {"type": "integer"},
|
||||
"step": {"type": "integer", "default": 1}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["static"],
|
||||
"properties": {
|
||||
"static": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"LoopAggregation": {
|
||||
"type": "object",
|
||||
"description": "How to aggregate loop iteration outputs",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["collect", "merge", "last", "first", "none"],
|
||||
"default": "collect",
|
||||
"description": "collect=array of outputs, merge=deep merge objects, last/first=single output"
|
||||
},
|
||||
"outputPath": {
|
||||
"type": "string",
|
||||
"description": "JMESPath to extract from each iteration result"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ConditionalStep": {
|
||||
"type": "object",
|
||||
"description": "Conditional branching step - if/else-if/else logic",
|
||||
"required": ["id", "type", "branches"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"const": "conditional"
|
||||
},
|
||||
"branches": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/ConditionalBranch"},
|
||||
"minItems": 1,
|
||||
"description": "Ordered list of condition/body pairs; first matching branch executes"
|
||||
},
|
||||
"else": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/Step"},
|
||||
"description": "Steps to execute if no branch conditions match"
|
||||
},
|
||||
"outputUnion": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether to union outputs from all branches (for deterministic output shape)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ConditionalBranch": {
|
||||
"type": "object",
|
||||
"required": ["condition", "body"],
|
||||
"properties": {
|
||||
"condition": {
|
||||
"$ref": "#/$defs/ConditionalExpression"
|
||||
},
|
||||
"body": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/Step"},
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"ConditionalExpression": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "JMESPath expression that evaluates to boolean"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["operator", "left", "right"],
|
||||
"properties": {
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"enum": ["eq", "ne", "gt", "ge", "lt", "le", "contains", "startsWith", "endsWith", "matches"]
|
||||
},
|
||||
"left": {"$ref": "#/$defs/ExpressionValue"},
|
||||
"right": {"$ref": "#/$defs/ExpressionValue"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["and"],
|
||||
"properties": {
|
||||
"and": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/ConditionalExpression"},
|
||||
"minItems": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["or"],
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/ConditionalExpression"},
|
||||
"minItems": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["not"],
|
||||
"properties": {
|
||||
"not": {"$ref": "#/$defs/ConditionalExpression"}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ExpressionValue": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "number"},
|
||||
{"type": "boolean"},
|
||||
{"type": "null"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["expr"],
|
||||
"properties": {
|
||||
"expr": {
|
||||
"type": "string",
|
||||
"description": "JMESPath expression to evaluate"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"PolicyGateStep": {
|
||||
"type": "object",
|
||||
"description": "Policy gate step - blocks until policy evaluation passes",
|
||||
"required": ["id", "type", "policyRef"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"const": "gate.policy"
|
||||
},
|
||||
"policyRef": {
|
||||
"$ref": "#/$defs/PolicyReference"
|
||||
},
|
||||
"input": {
|
||||
"type": "object",
|
||||
"description": "Input data for policy evaluation (can use expressions)",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"inputExpression": {
|
||||
"type": "string",
|
||||
"description": "JMESPath expression to construct policy input from step context"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+[smh]$",
|
||||
"default": "5m",
|
||||
"description": "Timeout for policy evaluation (e.g., '30s', '5m')"
|
||||
},
|
||||
"failureAction": {
|
||||
"$ref": "#/$defs/PolicyFailureAction"
|
||||
},
|
||||
"evidence": {
|
||||
"$ref": "#/$defs/PolicyEvidenceConfig"
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/$defs/ConditionalExpression",
|
||||
"description": "Optional condition to skip gate evaluation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolicyReference": {
|
||||
"type": "object",
|
||||
"required": ["policyId"],
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "string",
|
||||
"description": "Policy identifier in the policy registry"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+\\.\\d+\\.\\d+$",
|
||||
"description": "Specific policy version (semver); omit for active version"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$",
|
||||
"description": "Policy digest for reproducibility"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolicyFailureAction": {
|
||||
"type": "object",
|
||||
"description": "What to do when policy evaluation fails",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["abort", "warn", "requestOverride", "branch"],
|
||||
"default": "abort"
|
||||
},
|
||||
"retryCount": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 3,
|
||||
"default": 0
|
||||
},
|
||||
"retryDelay": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+[smh]$",
|
||||
"default": "10s"
|
||||
},
|
||||
"overrideApprovers": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Required approvers for override (if action=requestOverride)"
|
||||
},
|
||||
"branchTo": {
|
||||
"type": "string",
|
||||
"description": "Step ID to branch to on failure (if action=branch)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolicyEvidenceConfig": {
|
||||
"type": "object",
|
||||
"description": "Evidence recording for policy evaluations",
|
||||
"properties": {
|
||||
"recordDecision": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Record policy decision in evidence locker"
|
||||
},
|
||||
"recordInput": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Record policy input (may contain sensitive data)"
|
||||
},
|
||||
"recordRationale": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Record policy rationale/explanation"
|
||||
},
|
||||
"attestation": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Create DSSE attestation for policy decision"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApprovalGateStep": {
|
||||
"type": "object",
|
||||
"description": "Approval gate step - blocks until human approval received",
|
||||
"required": ["id", "type", "approvers"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"const": "gate.approval"
|
||||
},
|
||||
"approvers": {
|
||||
"$ref": "#/$defs/ApproverRequirements"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "Message shown to approvers"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+[smhd]$",
|
||||
"description": "Approval timeout (e.g., '24h', '7d')"
|
||||
},
|
||||
"autoApprove": {
|
||||
"$ref": "#/$defs/AutoApprovalConfig"
|
||||
},
|
||||
"evidence": {
|
||||
"$ref": "#/$defs/ApprovalEvidenceConfig"
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/$defs/ConditionalExpression"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApproverRequirements": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"default": 1,
|
||||
"description": "Minimum approvals required"
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Required approver roles/groups"
|
||||
},
|
||||
"users": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Specific user identities allowed to approve"
|
||||
},
|
||||
"excludeSubmitter": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Prevent pack submitter from self-approval"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AutoApprovalConfig": {
|
||||
"type": "object",
|
||||
"description": "Automatic approval rules",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"conditions": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/ConditionalExpression"},
|
||||
"description": "All conditions must match for auto-approval"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "Recorded reason for auto-approval"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ApprovalEvidenceConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"recordDecision": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"recordApprovers": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"attestation": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Create DSSE attestation for approval"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MapStep": {
|
||||
"type": "object",
|
||||
"description": "Map step - parallel iteration over deterministic collection",
|
||||
"required": ["id", "type", "items", "body"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"const": "map"
|
||||
},
|
||||
"items": {
|
||||
"$ref": "#/$defs/LoopItemsExpression"
|
||||
},
|
||||
"iterator": {
|
||||
"type": "string",
|
||||
"default": "item"
|
||||
},
|
||||
"body": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/Step"},
|
||||
"minItems": 1
|
||||
},
|
||||
"maxParallel": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"default": 10,
|
||||
"description": "Maximum concurrent iterations"
|
||||
},
|
||||
"aggregation": {
|
||||
"$ref": "#/$defs/LoopAggregation"
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/$defs/ConditionalExpression"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ParallelStep": {
|
||||
"type": "object",
|
||||
"description": "Parallel execution of independent sub-steps",
|
||||
"required": ["id", "type", "branches"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"const": "parallel"
|
||||
},
|
||||
"branches": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/Step"}
|
||||
},
|
||||
"minItems": 2,
|
||||
"description": "Independent step sequences to run concurrently"
|
||||
},
|
||||
"maxParallel": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"failFast": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Abort all branches on first failure"
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/$defs/ConditionalExpression"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RunStep": {
|
||||
"type": "object",
|
||||
"description": "Execute a module or built-in action",
|
||||
"required": ["id", "type", "module"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"const": "run"
|
||||
},
|
||||
"module": {
|
||||
"type": "string",
|
||||
"description": "Module reference (builtin:* or registry path)"
|
||||
},
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"outputs": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Output variable bindings"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d+[smh]$"
|
||||
},
|
||||
"when": {
|
||||
"$ref": "#/$defs/ConditionalExpression"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Step": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/$defs/RunStep"},
|
||||
{"$ref": "#/$defs/LoopStep"},
|
||||
{"$ref": "#/$defs/ConditionalStep"},
|
||||
{"$ref": "#/$defs/MapStep"},
|
||||
{"$ref": "#/$defs/ParallelStep"},
|
||||
{"$ref": "#/$defs/PolicyGateStep"},
|
||||
{"$ref": "#/$defs/ApprovalGateStep"}
|
||||
]
|
||||
},
|
||||
"PackRunStepKind": {
|
||||
"type": "string",
|
||||
"enum": ["run", "loop", "conditional", "map", "parallel", "gate.policy", "gate.approval"],
|
||||
"description": "All supported step types in TaskPack v1"
|
||||
},
|
||||
"ExecutionGraph": {
|
||||
"type": "object",
|
||||
"description": "Compiled execution graph from pack definition",
|
||||
"required": ["packId", "version", "steps"],
|
||||
"properties": {
|
||||
"packId": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"steps": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/Step"}
|
||||
},
|
||||
"dependencies": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"description": "Step ID -> dependent step IDs mapping"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DeterminismRequirements": {
|
||||
"type": "object",
|
||||
"description": "Determinism guarantees for control-flow execution",
|
||||
"properties": {
|
||||
"loopTermination": {
|
||||
"type": "string",
|
||||
"const": "guaranteed",
|
||||
"description": "Loops always terminate (maxIterations enforced)"
|
||||
},
|
||||
"iterationOrdering": {
|
||||
"type": "string",
|
||||
"const": "stable",
|
||||
"description": "Loop iterations execute in deterministic order"
|
||||
},
|
||||
"conditionalEvaluation": {
|
||||
"type": "string",
|
||||
"const": "pure",
|
||||
"description": "Conditional expressions have no side effects"
|
||||
},
|
||||
"policyEvaluation": {
|
||||
"type": "string",
|
||||
"const": "versioned",
|
||||
"description": "Policy gates use versioned/digested policies"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "1.0.0"
|
||||
},
|
||||
"supportedStepTypes": {
|
||||
"$ref": "#/$defs/PackRunStepKind"
|
||||
},
|
||||
"determinism": {
|
||||
"$ref": "#/$defs/DeterminismRequirements"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"id": "scan-all-repos",
|
||||
"type": "loop",
|
||||
"items": {"expression": "inputs.repositories"},
|
||||
"iterator": "repo",
|
||||
"maxIterations": 100,
|
||||
"body": [
|
||||
{
|
||||
"id": "scan-repo",
|
||||
"type": "run",
|
||||
"module": "builtin:scanner",
|
||||
"inputs": {"repository": "{{ repo }}"}
|
||||
}
|
||||
],
|
||||
"aggregation": {"mode": "collect"}
|
||||
},
|
||||
{
|
||||
"id": "severity-gate",
|
||||
"type": "gate.policy",
|
||||
"policyRef": {"policyId": "severity-threshold", "version": "1.0.0"},
|
||||
"input": {"findings": "{{ steps.scan.outputs.findings }}"},
|
||||
"failureAction": {"action": "requestOverride", "overrideApprovers": ["security-team"]},
|
||||
"evidence": {"recordDecision": true, "attestation": true}
|
||||
},
|
||||
{
|
||||
"id": "deploy-decision",
|
||||
"type": "conditional",
|
||||
"branches": [
|
||||
{
|
||||
"condition": {"operator": "eq", "left": {"expr": "inputs.environment"}, "right": "production"},
|
||||
"body": [
|
||||
{"id": "prod-approval", "type": "gate.approval", "approvers": {"minimum": 2, "roles": ["release-manager"]}}
|
||||
]
|
||||
}
|
||||
],
|
||||
"else": [
|
||||
{"id": "auto-deploy", "type": "run", "module": "builtin:deploy", "inputs": {"target": "{{ inputs.environment }}"}}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
340
docs/schemas/time-anchor.schema.json
Normal file
340
docs/schemas/time-anchor.schema.json
Normal file
@@ -0,0 +1,340 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/time-anchor.v1.json",
|
||||
"title": "TimeAnchor",
|
||||
"description": "Time anchor and TUF trust schema for air-gapped time verification",
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"TimeAnchor": {
|
||||
"type": "object",
|
||||
"description": "Trusted time anchor for offline environments",
|
||||
"required": ["anchorTime", "source", "format", "tokenDigest"],
|
||||
"properties": {
|
||||
"anchorTime": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "RFC3339 timestamp of the anchor"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/$defs/TimeSource"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "Format identifier for the time token",
|
||||
"examples": ["roughtime-v1", "rfc3161-v1"]
|
||||
},
|
||||
"signatureFingerprint": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-f0-9]+$",
|
||||
"description": "Hex-encoded fingerprint of the signing key"
|
||||
},
|
||||
"tokenDigest": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-f0-9]{64}$",
|
||||
"description": "SHA-256 hex digest of the time token"
|
||||
},
|
||||
"verification": {
|
||||
"$ref": "#/$defs/VerificationStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeSource": {
|
||||
"type": "string",
|
||||
"description": "Source of the time anchor",
|
||||
"enum": ["roughtime", "rfc3161", "unknown"]
|
||||
},
|
||||
"VerificationStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["unknown", "passed", "failed"]
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
},
|
||||
"verifiedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TrustRootsBundle": {
|
||||
"type": "object",
|
||||
"description": "Bundle of trusted time sources",
|
||||
"required": ["version"],
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"roughtime": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/RoughtimeRoot"
|
||||
}
|
||||
},
|
||||
"rfc3161": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/Rfc3161Root"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RoughtimeRoot": {
|
||||
"type": "object",
|
||||
"description": "Roughtime server trust root",
|
||||
"required": ["name", "publicKeyBase64", "validFrom", "validTo"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable server name"
|
||||
},
|
||||
"publicKeyBase64": {
|
||||
"type": "string",
|
||||
"description": "Base64-encoded Ed25519 public key"
|
||||
},
|
||||
"validFrom": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"validTo": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Rfc3161Root": {
|
||||
"type": "object",
|
||||
"description": "RFC 3161 TSA trust root",
|
||||
"required": ["name", "certificatePem", "validFrom", "validTo", "fingerprintSha256"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"certificatePem": {
|
||||
"type": "string",
|
||||
"description": "PEM-encoded X.509 certificate"
|
||||
},
|
||||
"validFrom": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"validTo": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"fingerprintSha256": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-F0-9]{64}$",
|
||||
"description": "SHA-256 fingerprint of certificate"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TufMetadata": {
|
||||
"type": "object",
|
||||
"description": "TUF (The Update Framework) metadata for secure updates",
|
||||
"required": ["specVersion", "version", "expires"],
|
||||
"properties": {
|
||||
"specVersion": {
|
||||
"type": "string",
|
||||
"const": "1.0.0"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Monotonically increasing version"
|
||||
},
|
||||
"expires": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TufRoot": {
|
||||
"type": "object",
|
||||
"description": "TUF root metadata",
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/TufMetadata"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["keys", "roles"],
|
||||
"properties": {
|
||||
"keys": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/$defs/TufKey"
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"root": {"$ref": "#/$defs/TufRole"},
|
||||
"snapshot": {"$ref": "#/$defs/TufRole"},
|
||||
"timestamp": {"$ref": "#/$defs/TufRole"},
|
||||
"targets": {"$ref": "#/$defs/TufRole"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"TufKey": {
|
||||
"type": "object",
|
||||
"required": ["keytype", "scheme", "keyval"],
|
||||
"properties": {
|
||||
"keytype": {
|
||||
"type": "string",
|
||||
"enum": ["ed25519", "rsa", "ecdsa"]
|
||||
},
|
||||
"scheme": {
|
||||
"type": "string",
|
||||
"enum": ["ed25519", "rsassa-pss-sha256", "ecdsa-sha2-nistp256"]
|
||||
},
|
||||
"keyval": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"public": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TufRole": {
|
||||
"type": "object",
|
||||
"required": ["keyids", "threshold"],
|
||||
"properties": {
|
||||
"keyids": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"threshold": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"TufSnapshot": {
|
||||
"type": "object",
|
||||
"description": "TUF snapshot metadata",
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/TufMetadata"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["meta"],
|
||||
"properties": {
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/$defs/TufFileMeta"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"TufTimestamp": {
|
||||
"type": "object",
|
||||
"description": "TUF timestamp metadata",
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/TufMetadata"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["meta"],
|
||||
"properties": {
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"snapshot.json": {
|
||||
"$ref": "#/$defs/TufFileMeta"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"TufFileMeta": {
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
"length": {
|
||||
"type": "integer"
|
||||
},
|
||||
"hashes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sha256": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-f0-9]{64}$"
|
||||
},
|
||||
"sha512": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-f0-9]{128}$"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TufValidationResult": {
|
||||
"type": "object",
|
||||
"description": "Result of TUF metadata validation",
|
||||
"required": ["valid"],
|
||||
"properties": {
|
||||
"valid": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"failureCode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"tuf-version-invalid",
|
||||
"tuf-expiry-invalid",
|
||||
"tuf-snapshot-hash-mismatch",
|
||||
"tuf-signature-invalid",
|
||||
"tuf-threshold-not-met"
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RootRotationPolicy": {
|
||||
"type": "object",
|
||||
"description": "Policy for rotating TUF root keys",
|
||||
"required": ["minApprovers", "pendingKeys"],
|
||||
"properties": {
|
||||
"minApprovers": {
|
||||
"type": "integer",
|
||||
"minimum": 2,
|
||||
"description": "Minimum distinct approvers required"
|
||||
},
|
||||
"pendingKeys": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"minItems": 1,
|
||||
"description": "Keys pending rotation"
|
||||
},
|
||||
"activeKeys": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"anchorTime": "2025-12-06T00:00:00Z",
|
||||
"source": "roughtime",
|
||||
"format": "roughtime-v1",
|
||||
"tokenDigest": "abc123def456789...",
|
||||
"verification": {
|
||||
"status": "passed",
|
||||
"verifiedAt": "2025-12-06T00:00:01Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
151
docs/schemas/verification-policy.schema.json
Normal file
151
docs/schemas/verification-policy.schema.json
Normal file
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/verification-policy.v1.json",
|
||||
"title": "VerificationPolicy",
|
||||
"description": "Attestation verification policy configuration for StellaOps",
|
||||
"type": "object",
|
||||
"required": ["policyId", "version", "predicateTypes", "signerRequirements"],
|
||||
"properties": {
|
||||
"policyId": {
|
||||
"type": "string",
|
||||
"description": "Unique policy identifier",
|
||||
"pattern": "^[a-z0-9-]+$",
|
||||
"examples": ["default-verification-policy", "strict-slsa-policy"]
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Policy version (SemVer)",
|
||||
"pattern": "^\\d+\\.\\d+\\.\\d+$",
|
||||
"examples": ["1.0.0", "2.1.0"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Human-readable policy description"
|
||||
},
|
||||
"tenantScope": {
|
||||
"type": "string",
|
||||
"description": "Tenant ID this policy applies to, or '*' for all tenants",
|
||||
"default": "*"
|
||||
},
|
||||
"predicateTypes": {
|
||||
"type": "array",
|
||||
"description": "Allowed attestation predicate types",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"examples": [
|
||||
["stella.ops/sbom@v1", "stella.ops/vex@v1"]
|
||||
]
|
||||
},
|
||||
"signerRequirements": {
|
||||
"$ref": "#/$defs/SignerRequirements"
|
||||
},
|
||||
"validityWindow": {
|
||||
"$ref": "#/$defs/ValidityWindow"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Free-form metadata",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"SignerRequirements": {
|
||||
"type": "object",
|
||||
"description": "Requirements for attestation signers",
|
||||
"properties": {
|
||||
"minimumSignatures": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"default": 1,
|
||||
"description": "Minimum number of valid signatures required"
|
||||
},
|
||||
"trustedKeyFingerprints": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"description": "List of trusted signer key fingerprints (SHA-256)"
|
||||
},
|
||||
"trustedIssuers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"description": "List of trusted issuer identities (OIDC issuers)"
|
||||
},
|
||||
"requireRekor": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Require Sigstore Rekor transparency log entry"
|
||||
},
|
||||
"algorithms": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["ES256", "ES384", "ES512", "RS256", "RS384", "RS512", "EdDSA"]
|
||||
},
|
||||
"description": "Allowed signing algorithms",
|
||||
"default": ["ES256", "RS256", "EdDSA"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"ValidityWindow": {
|
||||
"type": "object",
|
||||
"description": "Time-based validity constraints",
|
||||
"properties": {
|
||||
"notBefore": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Policy not valid before this time (ISO-8601)"
|
||||
},
|
||||
"notAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Policy not valid after this time (ISO-8601)"
|
||||
},
|
||||
"maxAttestationAge": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Maximum age of attestation in seconds (0 = no limit)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"policyId": "default-verification-policy",
|
||||
"version": "1.0.0",
|
||||
"description": "Default verification policy for StellaOps attestations",
|
||||
"tenantScope": "*",
|
||||
"predicateTypes": [
|
||||
"stella.ops/sbom@v1",
|
||||
"stella.ops/vex@v1",
|
||||
"stella.ops/vexDecision@v1",
|
||||
"stella.ops/policy@v1",
|
||||
"stella.ops/promotion@v1",
|
||||
"stella.ops/evidence@v1",
|
||||
"stella.ops/graph@v1",
|
||||
"stella.ops/replay@v1",
|
||||
"https://slsa.dev/provenance/v1",
|
||||
"https://cyclonedx.org/bom",
|
||||
"https://spdx.dev/Document",
|
||||
"https://openvex.dev/ns"
|
||||
],
|
||||
"signerRequirements": {
|
||||
"minimumSignatures": 1,
|
||||
"trustedKeyFingerprints": [
|
||||
"sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
|
||||
],
|
||||
"requireRekor": false,
|
||||
"algorithms": ["ES256", "RS256", "EdDSA"]
|
||||
},
|
||||
"validityWindow": {
|
||||
"maxAttestationAge": 86400
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
313
docs/schemas/vuln-explorer.schema.json
Normal file
313
docs/schemas/vuln-explorer.schema.json
Normal file
@@ -0,0 +1,313 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.io/schemas/vuln-explorer.v1.json",
|
||||
"title": "VulnExplorer",
|
||||
"description": "Vuln Explorer domain models for vulnerability management (GRAP0101)",
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"VulnSummary": {
|
||||
"type": "object",
|
||||
"description": "Summary view of a vulnerability finding",
|
||||
"required": ["id", "severity", "score", "exploitability", "cveIds", "purls", "policyVersion"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique finding identifier"
|
||||
},
|
||||
"severity": {
|
||||
"$ref": "#/$defs/Severity"
|
||||
},
|
||||
"score": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 10,
|
||||
"description": "CVSS or risk score"
|
||||
},
|
||||
"kev": {
|
||||
"type": "boolean",
|
||||
"description": "Is in CISA Known Exploited Vulnerabilities catalog"
|
||||
},
|
||||
"exploitability": {
|
||||
"$ref": "#/$defs/Exploitability"
|
||||
},
|
||||
"fixAvailable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether a fix/patch is available"
|
||||
},
|
||||
"cveIds": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Associated CVE identifiers"
|
||||
},
|
||||
"purls": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Affected package URLs"
|
||||
},
|
||||
"policyVersion": {
|
||||
"type": "string",
|
||||
"description": "Policy version used for determination"
|
||||
},
|
||||
"rationaleId": {
|
||||
"type": "string",
|
||||
"description": "Reference to policy rationale"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VulnDetail": {
|
||||
"type": "object",
|
||||
"description": "Detailed view of a vulnerability finding",
|
||||
"required": ["id", "severity", "score", "exploitability", "cveIds", "purls", "summary", "policyVersion", "firstSeen", "lastSeen"],
|
||||
"properties": {
|
||||
"id": {"type": "string"},
|
||||
"severity": {"$ref": "#/$defs/Severity"},
|
||||
"score": {"type": "number", "minimum": 0, "maximum": 10},
|
||||
"kev": {"type": "boolean"},
|
||||
"exploitability": {"$ref": "#/$defs/Exploitability"},
|
||||
"fixAvailable": {"type": "boolean"},
|
||||
"cveIds": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"purls": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"description": "Human-readable vulnerability description"
|
||||
},
|
||||
"affectedPackages": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/PackageAffect"}
|
||||
},
|
||||
"advisoryRefs": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/AdvisoryRef"}
|
||||
},
|
||||
"rationale": {
|
||||
"$ref": "#/$defs/PolicyRationale"
|
||||
},
|
||||
"paths": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Dependency paths to vulnerable component"
|
||||
},
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/EvidenceRef"}
|
||||
},
|
||||
"firstSeen": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"lastSeen": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"policyVersion": {"type": "string"},
|
||||
"rationaleId": {"type": "string"},
|
||||
"provenance": {"$ref": "#/$defs/EvidenceProvenance"}
|
||||
}
|
||||
},
|
||||
"Severity": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low", "informational", "unknown"]
|
||||
},
|
||||
"Exploitability": {
|
||||
"type": "string",
|
||||
"description": "Exploitability assessment",
|
||||
"enum": ["active", "poc", "theoretical", "unlikely", "none", "unknown"]
|
||||
},
|
||||
"PackageAffect": {
|
||||
"type": "object",
|
||||
"required": ["purl"],
|
||||
"properties": {
|
||||
"purl": {
|
||||
"type": "string",
|
||||
"description": "Package URL"
|
||||
},
|
||||
"versions": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Affected version ranges"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AdvisoryRef": {
|
||||
"type": "object",
|
||||
"required": ["url", "title"],
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolicyRationale": {
|
||||
"type": "object",
|
||||
"required": ["id", "summary"],
|
||||
"properties": {
|
||||
"id": {"type": "string"},
|
||||
"summary": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"EvidenceRef": {
|
||||
"type": "object",
|
||||
"required": ["kind", "reference"],
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"description": "Type of evidence",
|
||||
"examples": ["sbom", "vex", "scan", "reachability"]
|
||||
},
|
||||
"reference": {
|
||||
"type": "string",
|
||||
"description": "URI or identifier to evidence"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EvidenceProvenance": {
|
||||
"type": "object",
|
||||
"required": ["ledgerEntryId", "evidenceBundleId"],
|
||||
"properties": {
|
||||
"ledgerEntryId": {
|
||||
"type": "string",
|
||||
"description": "Findings ledger entry ID"
|
||||
},
|
||||
"evidenceBundleId": {
|
||||
"type": "string",
|
||||
"description": "Evidence bundle reference"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VulnListResponse": {
|
||||
"type": "object",
|
||||
"required": ["items"],
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/$defs/VulnSummary"}
|
||||
},
|
||||
"nextPageToken": {
|
||||
"type": "string",
|
||||
"description": "Token for next page of results"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VulnFilter": {
|
||||
"type": "object",
|
||||
"description": "Query filters for vulnerability listing",
|
||||
"properties": {
|
||||
"policyVersion": {"type": "string"},
|
||||
"pageSize": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 100,
|
||||
"default": 20
|
||||
},
|
||||
"pageToken": {"type": "string"},
|
||||
"cve": {
|
||||
"type": "string",
|
||||
"description": "Filter by CVE ID"
|
||||
},
|
||||
"purl": {
|
||||
"type": "string",
|
||||
"description": "Filter by package URL"
|
||||
},
|
||||
"severity": {"$ref": "#/$defs/Severity"},
|
||||
"exploitability": {"$ref": "#/$defs/Exploitability"},
|
||||
"fixAvailable": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"FindingProjection": {
|
||||
"type": "object",
|
||||
"description": "Findings ledger projection model",
|
||||
"required": ["tenantId", "findingId", "policyVersion", "status", "updatedAt"],
|
||||
"properties": {
|
||||
"tenantId": {"type": "string"},
|
||||
"findingId": {"type": "string"},
|
||||
"policyVersion": {"type": "string"},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["open", "resolved", "suppressed", "false_positive"]
|
||||
},
|
||||
"severity": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 10
|
||||
},
|
||||
"riskScore": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"riskSeverity": {"$ref": "#/$defs/Severity"},
|
||||
"riskProfileVersion": {"type": "string"},
|
||||
"riskExplanationId": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "string"}
|
||||
},
|
||||
"currentEventId": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"explainRef": {"type": "string"},
|
||||
"policyRationale": {
|
||||
"type": "array",
|
||||
"items": {"type": "object"}
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"cycleHash": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"FindingHistoryEntry": {
|
||||
"type": "object",
|
||||
"required": ["tenantId", "findingId", "policyVersion", "eventId", "status", "actorId", "occurredAt"],
|
||||
"properties": {
|
||||
"tenantId": {"type": "string"},
|
||||
"findingId": {"type": "string"},
|
||||
"policyVersion": {"type": "string"},
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"status": {"type": "string"},
|
||||
"severity": {"type": "number"},
|
||||
"actorId": {"type": "string"},
|
||||
"comment": {"type": "string"},
|
||||
"occurredAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"id": "finding-001",
|
||||
"severity": "high",
|
||||
"score": 7.5,
|
||||
"kev": true,
|
||||
"exploitability": "active",
|
||||
"fixAvailable": true,
|
||||
"cveIds": ["CVE-2024-1234"],
|
||||
"purls": ["pkg:npm/lodash@4.17.20"],
|
||||
"policyVersion": "2025.12.1",
|
||||
"rationaleId": "rat-001"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user