Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
release-manifest-verify / verify (push) Has been cancelled
- Implement comprehensive tests for PackRunAttestationService, covering attestation generation, verification, and event emission. - Add tests for SealedInstallEnforcer to validate sealed install requirements and enforcement logic. - Introduce a MonacoLoaderService stub for testing purposes to prevent Monaco workers/styles from loading during Karma runs.
746 lines
18 KiB
JSON
746 lines
18 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://stella-ops.org/schemas/exception-lifecycle.schema.json",
|
|
"title": "StellaOps Exception Lifecycle Schema",
|
|
"description": "Schema for exception lifecycle, routing, approvals, and governance. Unblocks DOCS-EXC-25-001 through 25-006 (5 tasks).",
|
|
"type": "object",
|
|
"definitions": {
|
|
"Exception": {
|
|
"type": "object",
|
|
"description": "Security exception request",
|
|
"required": ["exception_id", "finding_id", "status", "justification", "requested_at", "requested_by"],
|
|
"properties": {
|
|
"exception_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"finding_id": {
|
|
"type": "string",
|
|
"format": "uuid",
|
|
"description": "Finding this exception applies to"
|
|
},
|
|
"finding_ids": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"description": "Multiple findings for bulk exception"
|
|
},
|
|
"exception_type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"false_positive",
|
|
"risk_accepted",
|
|
"compensating_control",
|
|
"deferred_remediation",
|
|
"not_applicable",
|
|
"wont_fix"
|
|
]
|
|
},
|
|
"status": {
|
|
"$ref": "#/definitions/ExceptionStatus"
|
|
},
|
|
"justification": {
|
|
"type": "string",
|
|
"minLength": 10,
|
|
"description": "Business justification for exception"
|
|
},
|
|
"compensating_controls": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/CompensatingControl"
|
|
}
|
|
},
|
|
"scope": {
|
|
"$ref": "#/definitions/ExceptionScope"
|
|
},
|
|
"effective_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"expires_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"requested_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"requested_by": {
|
|
"type": "string",
|
|
"description": "User who requested exception"
|
|
},
|
|
"approvals": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/Approval"
|
|
}
|
|
},
|
|
"routing": {
|
|
"$ref": "#/definitions/RoutingInfo"
|
|
},
|
|
"audit_trail": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/AuditEntry"
|
|
}
|
|
},
|
|
"risk_assessment": {
|
|
"$ref": "#/definitions/RiskAssessment"
|
|
},
|
|
"attachments": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/Attachment"
|
|
}
|
|
},
|
|
"tags": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"metadata": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
},
|
|
"ExceptionStatus": {
|
|
"type": "string",
|
|
"enum": [
|
|
"draft",
|
|
"pending_review",
|
|
"pending_approval",
|
|
"approved",
|
|
"rejected",
|
|
"expired",
|
|
"revoked",
|
|
"superseded"
|
|
]
|
|
},
|
|
"CompensatingControl": {
|
|
"type": "object",
|
|
"description": "Compensating control for accepted risk",
|
|
"required": ["control_id", "description"],
|
|
"properties": {
|
|
"control_id": {
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"control_type": {
|
|
"type": "string",
|
|
"enum": ["technical", "administrative", "physical", "procedural"]
|
|
},
|
|
"effectiveness": {
|
|
"type": "string",
|
|
"enum": ["high", "medium", "low"]
|
|
},
|
|
"verification_method": {
|
|
"type": "string"
|
|
},
|
|
"last_verified_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"ExceptionScope": {
|
|
"type": "object",
|
|
"description": "Scope of the exception",
|
|
"properties": {
|
|
"scope_type": {
|
|
"type": "string",
|
|
"enum": ["finding", "component", "project", "organization"]
|
|
},
|
|
"tenant_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"project_ids": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
},
|
|
"component_patterns": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "PURL patterns to match"
|
|
},
|
|
"cve_patterns": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "CVE patterns to match"
|
|
}
|
|
}
|
|
},
|
|
"Approval": {
|
|
"type": "object",
|
|
"description": "Approval record",
|
|
"required": ["approver_id", "decision", "decided_at"],
|
|
"properties": {
|
|
"approval_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"approver_id": {
|
|
"type": "string"
|
|
},
|
|
"approver_name": {
|
|
"type": "string"
|
|
},
|
|
"approver_role": {
|
|
"type": "string"
|
|
},
|
|
"decision": {
|
|
"type": "string",
|
|
"enum": ["approved", "rejected", "deferred"]
|
|
},
|
|
"decided_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"comments": {
|
|
"type": "string"
|
|
},
|
|
"conditions": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "Conditions attached to approval"
|
|
},
|
|
"signature": {
|
|
"type": "string",
|
|
"description": "Digital signature of approval"
|
|
}
|
|
}
|
|
},
|
|
"RoutingInfo": {
|
|
"type": "object",
|
|
"description": "Routing configuration for exception workflow",
|
|
"properties": {
|
|
"workflow_id": {
|
|
"type": "string"
|
|
},
|
|
"current_step": {
|
|
"type": "string"
|
|
},
|
|
"approval_chain": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/ApprovalStep"
|
|
}
|
|
},
|
|
"escalation_policy": {
|
|
"$ref": "#/definitions/EscalationPolicy"
|
|
},
|
|
"notifications": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/NotificationConfig"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ApprovalStep": {
|
|
"type": "object",
|
|
"description": "Step in approval chain",
|
|
"required": ["step_id", "approvers"],
|
|
"properties": {
|
|
"step_id": {
|
|
"type": "string"
|
|
},
|
|
"step_name": {
|
|
"type": "string"
|
|
},
|
|
"approvers": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/ApproverConfig"
|
|
}
|
|
},
|
|
"approval_type": {
|
|
"type": "string",
|
|
"enum": ["any", "all", "quorum"],
|
|
"default": "any"
|
|
},
|
|
"quorum_count": {
|
|
"type": "integer",
|
|
"minimum": 1
|
|
},
|
|
"timeout_hours": {
|
|
"type": "integer"
|
|
},
|
|
"status": {
|
|
"type": "string",
|
|
"enum": ["pending", "completed", "skipped"]
|
|
}
|
|
}
|
|
},
|
|
"ApproverConfig": {
|
|
"type": "object",
|
|
"description": "Approver configuration",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["user", "role", "group", "dynamic"]
|
|
},
|
|
"identifier": {
|
|
"type": "string"
|
|
},
|
|
"fallback_approvers": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"EscalationPolicy": {
|
|
"type": "object",
|
|
"description": "Escalation policy for stalled approvals",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"escalation_after_hours": {
|
|
"type": "integer",
|
|
"default": 48
|
|
},
|
|
"max_escalation_levels": {
|
|
"type": "integer",
|
|
"default": 3
|
|
},
|
|
"escalation_targets": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"auto_approve_on_timeout": {
|
|
"type": "boolean",
|
|
"default": false
|
|
},
|
|
"auto_reject_on_timeout": {
|
|
"type": "boolean",
|
|
"default": false
|
|
}
|
|
}
|
|
},
|
|
"NotificationConfig": {
|
|
"type": "object",
|
|
"description": "Notification configuration",
|
|
"properties": {
|
|
"event": {
|
|
"type": "string",
|
|
"enum": [
|
|
"exception_created",
|
|
"pending_approval",
|
|
"approved",
|
|
"rejected",
|
|
"expiring_soon",
|
|
"expired",
|
|
"escalated"
|
|
]
|
|
},
|
|
"channels": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["email", "slack", "teams", "webhook"]
|
|
}
|
|
},
|
|
"recipients": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"AuditEntry": {
|
|
"type": "object",
|
|
"description": "Audit trail entry",
|
|
"required": ["action", "actor", "timestamp"],
|
|
"properties": {
|
|
"entry_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"action": {
|
|
"type": "string",
|
|
"enum": [
|
|
"created",
|
|
"updated",
|
|
"submitted",
|
|
"approved",
|
|
"rejected",
|
|
"revoked",
|
|
"expired",
|
|
"escalated",
|
|
"comment_added"
|
|
]
|
|
},
|
|
"actor": {
|
|
"type": "string"
|
|
},
|
|
"timestamp": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"details": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
},
|
|
"ip_address": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"RiskAssessment": {
|
|
"type": "object",
|
|
"description": "Risk assessment for exception",
|
|
"properties": {
|
|
"original_risk_score": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 10
|
|
},
|
|
"residual_risk_score": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 10,
|
|
"description": "Risk after compensating controls"
|
|
},
|
|
"risk_factors": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/RiskFactor"
|
|
}
|
|
},
|
|
"business_impact": {
|
|
"type": "string",
|
|
"enum": ["critical", "high", "medium", "low", "minimal"]
|
|
},
|
|
"data_sensitivity": {
|
|
"type": "string",
|
|
"enum": ["public", "internal", "confidential", "restricted"]
|
|
},
|
|
"assessed_by": {
|
|
"type": "string"
|
|
},
|
|
"assessed_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"RiskFactor": {
|
|
"type": "object",
|
|
"description": "Individual risk factor",
|
|
"properties": {
|
|
"factor_name": {
|
|
"type": "string"
|
|
},
|
|
"impact": {
|
|
"type": "string",
|
|
"enum": ["increase", "decrease", "neutral"]
|
|
},
|
|
"weight": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
"rationale": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"Attachment": {
|
|
"type": "object",
|
|
"description": "Supporting attachment",
|
|
"required": ["attachment_id", "filename"],
|
|
"properties": {
|
|
"attachment_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"filename": {
|
|
"type": "string"
|
|
},
|
|
"content_type": {
|
|
"type": "string"
|
|
},
|
|
"size_bytes": {
|
|
"type": "integer"
|
|
},
|
|
"storage_uri": {
|
|
"type": "string",
|
|
"format": "uri"
|
|
},
|
|
"checksum": {
|
|
"type": "string",
|
|
"pattern": "^sha256:[a-f0-9]{64}$"
|
|
},
|
|
"uploaded_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"uploaded_by": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"ExceptionPolicy": {
|
|
"type": "object",
|
|
"description": "Exception governance policy",
|
|
"required": ["policy_id", "name"],
|
|
"properties": {
|
|
"policy_id": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"max_exception_duration_days": {
|
|
"type": "integer",
|
|
"minimum": 1
|
|
},
|
|
"require_compensating_controls": {
|
|
"type": "boolean",
|
|
"default": false
|
|
},
|
|
"require_risk_assessment": {
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"severity_thresholds": {
|
|
"$ref": "#/definitions/SeverityThresholds"
|
|
},
|
|
"auto_renewal": {
|
|
"$ref": "#/definitions/AutoRenewalConfig"
|
|
},
|
|
"compliance_frameworks": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "Applicable compliance frameworks"
|
|
}
|
|
}
|
|
},
|
|
"SeverityThresholds": {
|
|
"type": "object",
|
|
"description": "Approval thresholds by severity",
|
|
"properties": {
|
|
"critical": {
|
|
"$ref": "#/definitions/ThresholdConfig"
|
|
},
|
|
"high": {
|
|
"$ref": "#/definitions/ThresholdConfig"
|
|
},
|
|
"medium": {
|
|
"$ref": "#/definitions/ThresholdConfig"
|
|
},
|
|
"low": {
|
|
"$ref": "#/definitions/ThresholdConfig"
|
|
}
|
|
}
|
|
},
|
|
"ThresholdConfig": {
|
|
"type": "object",
|
|
"properties": {
|
|
"max_duration_days": {
|
|
"type": "integer"
|
|
},
|
|
"required_approver_roles": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"min_approvers": {
|
|
"type": "integer",
|
|
"minimum": 1
|
|
},
|
|
"allow_exception": {
|
|
"type": "boolean",
|
|
"default": true
|
|
}
|
|
}
|
|
},
|
|
"AutoRenewalConfig": {
|
|
"type": "object",
|
|
"description": "Auto-renewal configuration",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false
|
|
},
|
|
"max_renewals": {
|
|
"type": "integer"
|
|
},
|
|
"renewal_review_required": {
|
|
"type": "boolean",
|
|
"default": true
|
|
}
|
|
}
|
|
},
|
|
"ExceptionSearchQuery": {
|
|
"type": "object",
|
|
"description": "Query for searching exceptions",
|
|
"properties": {
|
|
"exception_ids": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
},
|
|
"finding_ids": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
},
|
|
"statuses": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/ExceptionStatus"
|
|
}
|
|
},
|
|
"exception_types": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"requested_by": {
|
|
"type": "string"
|
|
},
|
|
"approved_by": {
|
|
"type": "string"
|
|
},
|
|
"created_after": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"created_before": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"expiring_within_days": {
|
|
"type": "integer"
|
|
},
|
|
"page": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"default": 1
|
|
},
|
|
"page_size": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 200,
|
|
"default": 50
|
|
}
|
|
}
|
|
},
|
|
"ExceptionSearchResult": {
|
|
"type": "object",
|
|
"description": "Search result",
|
|
"required": ["exceptions", "total_count"],
|
|
"properties": {
|
|
"exceptions": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/Exception"
|
|
}
|
|
},
|
|
"total_count": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"page": {
|
|
"type": "integer"
|
|
},
|
|
"page_size": {
|
|
"type": "integer"
|
|
},
|
|
"next_page_token": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"properties": {
|
|
"exceptions": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/Exception"
|
|
}
|
|
}
|
|
},
|
|
"examples": [
|
|
{
|
|
"exceptions": [
|
|
{
|
|
"exception_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"finding_id": "660e8400-e29b-41d4-a716-446655440001",
|
|
"exception_type": "risk_accepted",
|
|
"status": "approved",
|
|
"justification": "This vulnerability exists in a test-only dependency that is not deployed to production. The affected code path is never executed in any deployed environment.",
|
|
"compensating_controls": [
|
|
{
|
|
"control_id": "CC-001",
|
|
"description": "Network segmentation prevents access to affected component",
|
|
"control_type": "technical",
|
|
"effectiveness": "high"
|
|
}
|
|
],
|
|
"scope": {
|
|
"scope_type": "component",
|
|
"component_patterns": ["pkg:npm/test-lib@*"]
|
|
},
|
|
"effective_at": "2025-12-06T00:00:00Z",
|
|
"expires_at": "2026-06-06T00:00:00Z",
|
|
"requested_at": "2025-12-01T10:00:00Z",
|
|
"requested_by": "dev-team-lead@example.com",
|
|
"approvals": [
|
|
{
|
|
"approval_id": "770e8400-e29b-41d4-a716-446655440002",
|
|
"approver_id": "security-manager@example.com",
|
|
"approver_name": "Jane Security",
|
|
"approver_role": "Security Manager",
|
|
"decision": "approved",
|
|
"decided_at": "2025-12-05T14:00:00Z",
|
|
"comments": "Approved with 6-month duration due to low residual risk",
|
|
"conditions": ["Re-evaluate if component moves to production"]
|
|
}
|
|
],
|
|
"risk_assessment": {
|
|
"original_risk_score": 7.5,
|
|
"residual_risk_score": 2.0,
|
|
"business_impact": "low",
|
|
"data_sensitivity": "internal"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|