Some checks failed
AOC Guard CI / aoc-verify (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
mock-dev-release / package-mock-release (push) Has been cancelled
- Introduced OpenAPI specification for the StellaOps Policy Registry API, covering endpoints for verification policies, policy packs, snapshots, violations, overrides, sealed mode operations, and advisory staleness tracking. - Defined schemas, parameters, and responses for comprehensive API documentation. chore(scanner): Add global usings for scanner analyzers - Created GlobalUsings.cs to simplify namespace usage across analyzer libraries. feat(scanner): Implement Surface Service Collection Extensions - Added SurfaceServiceCollectionExtensions for dependency injection registration of surface analysis services. - Included methods for adding surface analysis, surface collectors, and entry point collectors to the service collection.
606 lines
17 KiB
JSON
606 lines
17 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://stella-ops.org/schemas/notify-rules.schema.json",
|
|
"title": "StellaOps Notification Rules Schema",
|
|
"description": "Schema for notification rules, webhook payloads, and digest formats. Unblocks CLI-NOTIFY-38-001.",
|
|
"type": "object",
|
|
"definitions": {
|
|
"NotifyRule": {
|
|
"type": "object",
|
|
"required": ["rule_id", "name", "event_types", "channels", "created_at"],
|
|
"properties": {
|
|
"rule_id": {
|
|
"type": "string",
|
|
"format": "uuid",
|
|
"description": "Unique identifier for the notification rule"
|
|
},
|
|
"name": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 128,
|
|
"description": "Human-readable rule name"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"maxLength": 512
|
|
},
|
|
"event_types": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"$ref": "#/definitions/EventType"
|
|
},
|
|
"description": "Event types that trigger this rule"
|
|
},
|
|
"filters": {
|
|
"$ref": "#/definitions/NotifyFilters"
|
|
},
|
|
"channels": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"$ref": "#/definitions/NotifyChannel"
|
|
}
|
|
},
|
|
"throttle": {
|
|
"$ref": "#/definitions/ThrottleConfig"
|
|
},
|
|
"digest": {
|
|
"$ref": "#/definitions/DigestConfig"
|
|
},
|
|
"templates": {
|
|
"$ref": "#/definitions/NotifyTemplates"
|
|
},
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"priority": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 100,
|
|
"default": 50,
|
|
"description": "Rule priority (higher = processed first)"
|
|
},
|
|
"tenant_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"created_by": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"EventType": {
|
|
"type": "string",
|
|
"enum": [
|
|
"vulnerability.new",
|
|
"vulnerability.updated",
|
|
"vulnerability.resolved",
|
|
"vulnerability.critical",
|
|
"vex.status_changed",
|
|
"vex.consensus_changed",
|
|
"policy.violation",
|
|
"policy.override_requested",
|
|
"policy.override_approved",
|
|
"policy.override_expired",
|
|
"scan.completed",
|
|
"scan.failed",
|
|
"attestation.created",
|
|
"attestation.verification_failed",
|
|
"airgap.staleness_warning",
|
|
"airgap.staleness_critical",
|
|
"airgap.bundle_imported",
|
|
"export.completed",
|
|
"export.failed",
|
|
"system.health_degraded",
|
|
"system.error"
|
|
]
|
|
},
|
|
"NotifyFilters": {
|
|
"type": "object",
|
|
"description": "Filters to apply before triggering notification",
|
|
"properties": {
|
|
"severity": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["critical", "high", "medium", "low", "info"]
|
|
},
|
|
"description": "Only trigger for these severities"
|
|
},
|
|
"cvss_minimum": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 10,
|
|
"description": "Minimum CVSS score to trigger"
|
|
},
|
|
"components": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "PURL patterns to match"
|
|
},
|
|
"environments": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"tags": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"kev_only": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Only trigger for Known Exploited Vulnerabilities"
|
|
},
|
|
"fix_available": {
|
|
"type": "boolean",
|
|
"description": "Filter by fix availability"
|
|
}
|
|
}
|
|
},
|
|
"NotifyChannel": {
|
|
"type": "object",
|
|
"required": ["type"],
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["email", "slack", "teams", "webhook", "pagerduty", "opsgenie", "sns"]
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"config": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
},
|
|
"allOf": [
|
|
{
|
|
"if": { "properties": { "type": { "const": "email" } } },
|
|
"then": {
|
|
"properties": {
|
|
"config": {
|
|
"type": "object",
|
|
"required": ["recipients"],
|
|
"properties": {
|
|
"recipients": {
|
|
"type": "array",
|
|
"items": { "type": "string", "format": "email" }
|
|
},
|
|
"cc": {
|
|
"type": "array",
|
|
"items": { "type": "string", "format": "email" }
|
|
},
|
|
"subject_prefix": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": { "properties": { "type": { "const": "slack" } } },
|
|
"then": {
|
|
"properties": {
|
|
"config": {
|
|
"type": "object",
|
|
"required": ["webhook_url"],
|
|
"properties": {
|
|
"webhook_url": { "type": "string", "format": "uri" },
|
|
"channel": { "type": "string" },
|
|
"username": { "type": "string" },
|
|
"icon_emoji": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": { "properties": { "type": { "const": "teams" } } },
|
|
"then": {
|
|
"properties": {
|
|
"config": {
|
|
"type": "object",
|
|
"required": ["webhook_url"],
|
|
"properties": {
|
|
"webhook_url": { "type": "string", "format": "uri" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": { "properties": { "type": { "const": "webhook" } } },
|
|
"then": {
|
|
"properties": {
|
|
"config": {
|
|
"type": "object",
|
|
"required": ["url"],
|
|
"properties": {
|
|
"url": { "type": "string", "format": "uri" },
|
|
"method": { "type": "string", "enum": ["POST", "PUT"], "default": "POST" },
|
|
"headers": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
"auth_type": { "type": "string", "enum": ["none", "basic", "bearer", "hmac"] },
|
|
"auth_secret": { "type": "string" },
|
|
"retry_count": { "type": "integer", "minimum": 0, "maximum": 5, "default": 3 },
|
|
"timeout_seconds": { "type": "integer", "minimum": 1, "maximum": 60, "default": 30 }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"if": { "properties": { "type": { "const": "pagerduty" } } },
|
|
"then": {
|
|
"properties": {
|
|
"config": {
|
|
"type": "object",
|
|
"required": ["routing_key"],
|
|
"properties": {
|
|
"routing_key": { "type": "string" },
|
|
"severity_mapping": {
|
|
"type": "object",
|
|
"additionalProperties": { "type": "string", "enum": ["critical", "error", "warning", "info"] }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"ThrottleConfig": {
|
|
"type": "object",
|
|
"description": "Throttling configuration to prevent notification storms",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"max_per_hour": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"default": 100
|
|
},
|
|
"max_per_day": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"default": 1000
|
|
},
|
|
"dedupe_window_seconds": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"default": 300,
|
|
"description": "Window for deduplicating identical notifications"
|
|
},
|
|
"dedupe_key_fields": {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"default": ["event_type", "cve_id", "purl"],
|
|
"description": "Fields to use for deduplication key"
|
|
}
|
|
}
|
|
},
|
|
"DigestConfig": {
|
|
"type": "object",
|
|
"description": "Configuration for digest/summary notifications",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false
|
|
},
|
|
"frequency": {
|
|
"type": "string",
|
|
"enum": ["hourly", "daily", "weekly"],
|
|
"default": "daily"
|
|
},
|
|
"schedule": {
|
|
"type": "string",
|
|
"description": "Cron expression for digest delivery"
|
|
},
|
|
"timezone": {
|
|
"type": "string",
|
|
"default": "UTC"
|
|
},
|
|
"min_events": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"default": 1,
|
|
"description": "Minimum events required to send digest"
|
|
},
|
|
"group_by": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": ["severity", "event_type", "component", "environment"]
|
|
},
|
|
"description": "Fields to group events by in digest"
|
|
},
|
|
"include_summary": {
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"include_details": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Include full event details in digest"
|
|
}
|
|
}
|
|
},
|
|
"NotifyTemplates": {
|
|
"type": "object",
|
|
"description": "Custom notification templates",
|
|
"properties": {
|
|
"subject": {
|
|
"type": "string",
|
|
"description": "Template for notification subject (supports {{variables}})"
|
|
},
|
|
"body": {
|
|
"type": "string",
|
|
"description": "Template for notification body"
|
|
},
|
|
"body_html": {
|
|
"type": "string",
|
|
"description": "HTML template for email body"
|
|
}
|
|
}
|
|
},
|
|
"WebhookPayload": {
|
|
"type": "object",
|
|
"description": "Standard webhook payload format",
|
|
"required": ["id", "timestamp", "event_type", "data"],
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"format": "uuid",
|
|
"description": "Unique notification ID"
|
|
},
|
|
"timestamp": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"event_type": {
|
|
"$ref": "#/definitions/EventType"
|
|
},
|
|
"version": {
|
|
"type": "string",
|
|
"default": "1.0.0"
|
|
},
|
|
"tenant_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"data": {
|
|
"type": "object",
|
|
"description": "Event-specific payload data",
|
|
"additionalProperties": true
|
|
},
|
|
"metadata": {
|
|
"type": "object",
|
|
"properties": {
|
|
"rule_id": { "type": "string", "format": "uuid" },
|
|
"rule_name": { "type": "string" },
|
|
"retry_count": { "type": "integer" },
|
|
"digest_id": { "type": "string", "format": "uuid" }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"DigestPayload": {
|
|
"type": "object",
|
|
"description": "Digest/summary notification payload",
|
|
"required": ["id", "timestamp", "period", "summary"],
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"timestamp": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"period": {
|
|
"type": "object",
|
|
"required": ["start", "end"],
|
|
"properties": {
|
|
"start": { "type": "string", "format": "date-time" },
|
|
"end": { "type": "string", "format": "date-time" }
|
|
}
|
|
},
|
|
"summary": {
|
|
"type": "object",
|
|
"properties": {
|
|
"total_events": { "type": "integer" },
|
|
"by_severity": {
|
|
"type": "object",
|
|
"additionalProperties": { "type": "integer" }
|
|
},
|
|
"by_event_type": {
|
|
"type": "object",
|
|
"additionalProperties": { "type": "integer" }
|
|
},
|
|
"new_vulnerabilities": { "type": "integer" },
|
|
"resolved_vulnerabilities": { "type": "integer" },
|
|
"policy_violations": { "type": "integer" }
|
|
}
|
|
},
|
|
"events": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/WebhookPayload"
|
|
},
|
|
"description": "Optional detailed event list"
|
|
},
|
|
"groups": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"key": { "type": "string" },
|
|
"count": { "type": "integer" },
|
|
"sample_events": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/definitions/WebhookPayload" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"NotifySimulationRequest": {
|
|
"type": "object",
|
|
"description": "Request to simulate a notification rule",
|
|
"required": ["event"],
|
|
"properties": {
|
|
"rule_id": {
|
|
"type": "string",
|
|
"format": "uuid",
|
|
"description": "Rule to simulate (optional, uses all matching if not specified)"
|
|
},
|
|
"event": {
|
|
"$ref": "#/definitions/WebhookPayload"
|
|
},
|
|
"dry_run": {
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "If true, don't actually send notifications"
|
|
}
|
|
}
|
|
},
|
|
"NotifySimulationResult": {
|
|
"type": "object",
|
|
"required": ["matched_rules", "would_notify"],
|
|
"properties": {
|
|
"matched_rules": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"rule_id": { "type": "string", "format": "uuid" },
|
|
"rule_name": { "type": "string" },
|
|
"matched": { "type": "boolean" },
|
|
"reason": { "type": "string" }
|
|
}
|
|
}
|
|
},
|
|
"would_notify": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"channel_type": { "type": "string" },
|
|
"channel_name": { "type": "string" },
|
|
"payload_preview": { "type": "object" }
|
|
}
|
|
}
|
|
},
|
|
"throttled": {
|
|
"type": "boolean"
|
|
},
|
|
"throttle_reason": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"NotifyAckToken": {
|
|
"type": "object",
|
|
"description": "Acknowledgement token for notifications",
|
|
"required": ["token", "notification_id", "expires_at"],
|
|
"properties": {
|
|
"token": {
|
|
"type": "string",
|
|
"description": "Opaque acknowledgement token"
|
|
},
|
|
"notification_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"event_type": {
|
|
"$ref": "#/definitions/EventType"
|
|
},
|
|
"expires_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"ack_url": {
|
|
"type": "string",
|
|
"format": "uri",
|
|
"description": "URL to acknowledge the notification"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"properties": {
|
|
"rules": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/NotifyRule"
|
|
}
|
|
}
|
|
},
|
|
"examples": [
|
|
{
|
|
"rules": [
|
|
{
|
|
"rule_id": "550e8400-e29b-41d4-a716-446655440002",
|
|
"name": "Critical Vulnerability Alert",
|
|
"description": "Immediate notification for critical vulnerabilities",
|
|
"event_types": ["vulnerability.critical", "vulnerability.new"],
|
|
"filters": {
|
|
"severity": ["critical"],
|
|
"kev_only": false
|
|
},
|
|
"channels": [
|
|
{
|
|
"type": "slack",
|
|
"name": "security-alerts",
|
|
"config": {
|
|
"webhook_url": "https://hooks.slack.com/services/xxx",
|
|
"channel": "#security-alerts",
|
|
"icon_emoji": ":warning:"
|
|
}
|
|
},
|
|
{
|
|
"type": "pagerduty",
|
|
"name": "security-oncall",
|
|
"config": {
|
|
"routing_key": "xxx",
|
|
"severity_mapping": {
|
|
"critical": "critical",
|
|
"high": "error"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"throttle": {
|
|
"enabled": true,
|
|
"max_per_hour": 50,
|
|
"dedupe_window_seconds": 300
|
|
},
|
|
"enabled": true,
|
|
"priority": 100,
|
|
"created_at": "2025-12-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|