Add unit tests for PackRunAttestation and SealedInstallEnforcer
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
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.
This commit is contained in:
745
docs/schemas/exception-lifecycle.schema.json
Normal file
745
docs/schemas/exception-lifecycle.schema.json
Normal file
@@ -0,0 +1,745 @@
|
||||
{
|
||||
"$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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user