Implement incident mode management service and models
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Added IPackRunIncidentModeService interface for managing incident mode activation, deactivation, and status retrieval. - Created PackRunIncidentModeService class implementing the service interface with methods for activating, deactivating, and escalating incident modes. - Introduced incident mode status model (PackRunIncidentModeStatus) and related enums for escalation levels and activation sources. - Developed retention policy, telemetry settings, and debug capture settings models to manage incident mode configurations. - Implemented SLO breach notification handling to activate incident mode based on severity. - Added in-memory store (InMemoryPackRunIncidentModeStore) for testing purposes. - Created comprehensive unit tests for incident mode service, covering activation, deactivation, status retrieval, and SLO breach handling.
This commit is contained in:
@@ -1,9 +1,17 @@
|
||||
# BLOCKED Tasks Dependency Tree
|
||||
> **Last Updated:** 2025-12-06 (Wave 5: 43 specs + 8 implementations = ~252+ tasks unblocked)
|
||||
> **Last Updated:** 2025-12-06 (Wave 6: 49 specs + 8 implementations = ~270+ tasks unblocked)
|
||||
> **Purpose:** This document maps all BLOCKED tasks and their root causes to help teams prioritize unblocking work.
|
||||
> **Visual DAG:** See [DEPENDENCY_DAG.md](./DEPENDENCY_DAG.md) for Mermaid graphs, cascade analysis, and guild blocking matrix.
|
||||
>
|
||||
> **Recent Unblocks (2025-12-06 Wave 5):**
|
||||
> **Recent Unblocks (2025-12-06 Wave 6):**
|
||||
> - ✅ SDK Generator Samples Schema (`docs/schemas/sdk-generator-samples.schema.json`) — 2+ tasks (DEVPORT-63-002, DOCS-SDK-62-001)
|
||||
> - ✅ Graph Demo Outputs Schema (`docs/schemas/graph-demo-outputs.schema.json`) — 1+ task (GRAPH-OPS-0001)
|
||||
> - ✅ Risk API Schema (`docs/schemas/risk-api.schema.json`) — 5 tasks (DOCS-RISK-67-002 through 68-002)
|
||||
> - ✅ Ops Incident Runbook Schema (`docs/schemas/ops-incident-runbook.schema.json`) — 1+ task (DOCS-RUNBOOK-55-001)
|
||||
> - ✅ Export Bundle Shapes Schema (`docs/schemas/export-bundle-shapes.schema.json`) — 2 tasks (DOCS-RISK-68-001/002)
|
||||
> - ✅ Security Scopes Matrix Schema (`docs/schemas/security-scopes-matrix.schema.json`) — 2 tasks (DOCS-SEC-62-001, DOCS-SEC-OBS-50-001)
|
||||
>
|
||||
> **Wave 5 Unblocks (2025-12-06):**
|
||||
> - ✅ DevPortal API Schema (`docs/schemas/devportal-api.schema.json`) — 6 tasks (APIG0101 62-001 to 63-004)
|
||||
> - ✅ Deployment Service List (`docs/schemas/deployment-service-list.schema.json`) — 7 tasks (COMPOSE-44-001 to 45-003)
|
||||
> - ✅ Exception Lifecycle Schema (`docs/schemas/exception-lifecycle.schema.json`) — 5 tasks (DOCS-EXC-25-001 to 25-006)
|
||||
@@ -297,19 +305,31 @@ attestor SDK transport contract ✅ CREATED (chain UNBLOCKED)
|
||||
|
||||
## 7. DOCS MD.IX (SPRINT_0309_0001_0009_docs_tasks_md_ix)
|
||||
|
||||
**Root Blocker:** `DOCS-RISK-67-002 draft (risk API)` (due 2025-12-09; reminder ping 2025-12-09, escalate 2025-12-13)
|
||||
**Root Blocker:** ~~`DOCS-RISK-67-002 draft (risk API)`~~ ✅ RESOLVED (2025-12-06 Wave 6)
|
||||
|
||||
> **Update 2025-12-06 Wave 6:**
|
||||
> - ✅ **Risk API Schema** CREATED (`docs/schemas/risk-api.schema.json`)
|
||||
> - RiskScore with rating, confidence, and factor breakdown
|
||||
> - RiskFactor with weights, contributions, and evidence
|
||||
> - RiskProfile with scoring models, thresholds, and modifiers
|
||||
> - ScoringModel with weighted_sum, geometric_mean, max_severity types
|
||||
> - RiskAssessmentRequest/Response for API endpoints
|
||||
> - RiskExplainability for human-readable explanations
|
||||
> - RiskAggregation for entity-wide scoring
|
||||
> - **5 tasks UNBLOCKED**
|
||||
|
||||
```
|
||||
DOCS-RISK-67-002 draft missing
|
||||
+-- DOCS-RISK-67-003 (risk UI docs)
|
||||
+-- DOCS-RISK-67-004 (CLI risk guide)
|
||||
+-- DOCS-RISK-68-001 (airgap risk bundles)
|
||||
+-- DOCS-RISK-68-002 (AOC invariants update)
|
||||
Risk API schema ✅ CREATED (chain UNBLOCKED)
|
||||
+-- DOCS-RISK-67-002 (risk API docs) → UNBLOCKED
|
||||
+-- DOCS-RISK-67-003 (risk UI docs) → UNBLOCKED
|
||||
+-- DOCS-RISK-67-004 (CLI risk guide) → UNBLOCKED
|
||||
+-- DOCS-RISK-68-001 (airgap risk bundles) → UNBLOCKED
|
||||
+-- DOCS-RISK-68-002 (AOC invariants update) → UNBLOCKED
|
||||
```
|
||||
|
||||
**Impact:** 4 docs tasks (risk chain)
|
||||
**Impact:** 5 docs tasks — ✅ ALL UNBLOCKED
|
||||
|
||||
**To Unblock:** API Guild to deliver DOCS-RISK-67-002 draft by 2025-12-09; Console Guild to provide UI captures/hashes by 2025-12-10.
|
||||
**Status:** ✅ RESOLVED — Schema created at `docs/schemas/risk-api.schema.json`
|
||||
|
||||
---
|
||||
|
||||
|
||||
628
docs/schemas/export-bundle-shapes.schema.json
Normal file
628
docs/schemas/export-bundle-shapes.schema.json
Normal file
@@ -0,0 +1,628 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stella-ops.org/schemas/export-bundle-shapes.schema.json",
|
||||
"title": "StellaOps Export Bundle Shapes Schema",
|
||||
"description": "Schema for export bundle formats, hashing inputs, and airgap bundle structures. Unblocks DOCS-RISK-68-001, DOCS-RISK-68-002 (2+ tasks).",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"ExportBundle": {
|
||||
"type": "object",
|
||||
"description": "Export bundle package",
|
||||
"required": ["bundle_id", "bundle_type", "version", "created_at", "contents"],
|
||||
"properties": {
|
||||
"bundle_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"bundle_type": {
|
||||
"type": "string",
|
||||
"enum": ["findings", "sbom", "vex", "risk", "compliance", "evidence", "full"],
|
||||
"description": "Type of export bundle"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": ["json", "ndjson", "csv", "xml", "cyclonedx", "spdx", "sarif"],
|
||||
"description": "Output format"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"created_by": {
|
||||
"type": "string"
|
||||
},
|
||||
"tenant_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/definitions/ExportScope"
|
||||
},
|
||||
"contents": {
|
||||
"$ref": "#/definitions/BundleContents"
|
||||
},
|
||||
"metadata": {
|
||||
"$ref": "#/definitions/BundleMetadata"
|
||||
},
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/BundleSignature"
|
||||
}
|
||||
},
|
||||
"manifest_digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$",
|
||||
"description": "Digest of bundle manifest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ExportScope": {
|
||||
"type": "object",
|
||||
"description": "Scope of exported data",
|
||||
"properties": {
|
||||
"projects": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"assets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"time_range": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"end": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"severities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low", "info"]
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"description": "Additional filter criteria"
|
||||
}
|
||||
}
|
||||
},
|
||||
"BundleContents": {
|
||||
"type": "object",
|
||||
"description": "Bundle content inventory",
|
||||
"properties": {
|
||||
"files": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/BundleFile"
|
||||
}
|
||||
},
|
||||
"record_counts": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": "Count of records by type"
|
||||
},
|
||||
"total_size_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"compressed_size_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"enum": ["none", "gzip", "zstd", "lz4"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BundleFile": {
|
||||
"type": "object",
|
||||
"description": "Individual file in bundle",
|
||||
"required": ["path", "digest", "size_bytes"],
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["data", "metadata", "schema", "signature", "index"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
},
|
||||
"size_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"record_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"schema_ref": {
|
||||
"type": "string",
|
||||
"description": "Reference to schema for this file"
|
||||
}
|
||||
}
|
||||
},
|
||||
"BundleMetadata": {
|
||||
"type": "object",
|
||||
"description": "Bundle metadata",
|
||||
"properties": {
|
||||
"export_job_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"source_system": {
|
||||
"type": "string"
|
||||
},
|
||||
"source_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"export_profile": {
|
||||
"type": "string"
|
||||
},
|
||||
"redaction_applied": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"redaction_policy": {
|
||||
"type": "string"
|
||||
},
|
||||
"retention_policy": {
|
||||
"type": "string"
|
||||
},
|
||||
"classification": {
|
||||
"type": "string",
|
||||
"enum": ["public", "internal", "confidential", "restricted"]
|
||||
},
|
||||
"custom": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"BundleSignature": {
|
||||
"type": "object",
|
||||
"description": "Digital signature on bundle",
|
||||
"required": ["signature_type", "signature"],
|
||||
"properties": {
|
||||
"signature_type": {
|
||||
"type": "string",
|
||||
"enum": ["dsse", "cosign", "gpg", "x509"]
|
||||
},
|
||||
"signature": {
|
||||
"type": "string",
|
||||
"description": "Base64-encoded signature"
|
||||
},
|
||||
"public_key": {
|
||||
"type": "string",
|
||||
"description": "Public key or key reference"
|
||||
},
|
||||
"key_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"signed_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"signer": {
|
||||
"type": "string"
|
||||
},
|
||||
"certificate_chain": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"AirgapBundle": {
|
||||
"type": "object",
|
||||
"description": "Air-gapped export bundle for offline environments",
|
||||
"required": ["bundle_id", "created_at", "manifest"],
|
||||
"properties": {
|
||||
"bundle_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"bundle_type": {
|
||||
"type": "string",
|
||||
"const": "airgap"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"valid_until": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Expiration for time-sensitive data"
|
||||
},
|
||||
"manifest": {
|
||||
"$ref": "#/definitions/AirgapManifest"
|
||||
},
|
||||
"advisory_data": {
|
||||
"$ref": "#/definitions/AdvisoryBundle"
|
||||
},
|
||||
"risk_data": {
|
||||
"$ref": "#/definitions/RiskBundle"
|
||||
},
|
||||
"policy_data": {
|
||||
"$ref": "#/definitions/PolicyBundle"
|
||||
},
|
||||
"time_anchor": {
|
||||
"$ref": "#/definitions/TimeAnchor"
|
||||
},
|
||||
"aggregate_digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AirgapManifest": {
|
||||
"type": "object",
|
||||
"description": "Manifest of airgap bundle contents",
|
||||
"required": ["version", "files"],
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"format_version": {
|
||||
"type": "string",
|
||||
"const": "1.0"
|
||||
},
|
||||
"files": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/BundleFile"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bundle_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"AdvisoryBundle": {
|
||||
"type": "object",
|
||||
"description": "Advisory data for airgap bundle",
|
||||
"properties": {
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Advisory sources included (NVD, OSV, etc.)"
|
||||
},
|
||||
"advisory_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"cve_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_sync": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"file_ref": {
|
||||
"type": "string",
|
||||
"description": "Path to advisory data file"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskBundle": {
|
||||
"type": "object",
|
||||
"description": "Risk scoring data for airgap bundle",
|
||||
"properties": {
|
||||
"profiles": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Risk profiles included"
|
||||
},
|
||||
"epss_data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"record_count": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kev_data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"record_count": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_ref": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolicyBundle": {
|
||||
"type": "object",
|
||||
"description": "Policy data for airgap bundle",
|
||||
"properties": {
|
||||
"policy_packs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pack_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_ref": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeAnchor": {
|
||||
"type": "object",
|
||||
"description": "Time anchor for bundle validity",
|
||||
"required": ["anchor_time", "source"],
|
||||
"properties": {
|
||||
"anchor_time": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"enum": ["ntp", "tsa", "rekor", "manual"]
|
||||
},
|
||||
"tsa_response": {
|
||||
"type": "string",
|
||||
"description": "RFC 3161 timestamp response (base64)"
|
||||
},
|
||||
"rekor_entry": {
|
||||
"type": "string",
|
||||
"description": "Rekor transparency log entry ID"
|
||||
},
|
||||
"drift_tolerance": {
|
||||
"type": "string",
|
||||
"description": "Acceptable clock drift (e.g., 1h)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"HashingInputs": {
|
||||
"type": "object",
|
||||
"description": "Inputs used for deterministic hashing",
|
||||
"required": ["algorithm", "inputs"],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"enum": ["sha256", "sha384", "sha512"],
|
||||
"default": "sha256"
|
||||
},
|
||||
"inputs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/HashInput"
|
||||
},
|
||||
"description": "Ordered list of inputs for hash computation"
|
||||
},
|
||||
"canonicalization": {
|
||||
"type": "string",
|
||||
"enum": ["none", "json-canonical", "xml-c14n"],
|
||||
"description": "Canonicalization method before hashing"
|
||||
},
|
||||
"encoding": {
|
||||
"type": "string",
|
||||
"enum": ["utf8", "base64"],
|
||||
"default": "utf8"
|
||||
},
|
||||
"computed_digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"HashInput": {
|
||||
"type": "object",
|
||||
"description": "Single input for hash computation",
|
||||
"required": ["type", "value"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["file", "field", "literal", "nested_digest"]
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "File path or JSON path"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Literal value or computed digest"
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "Order in hash computation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ExportProfile": {
|
||||
"type": "object",
|
||||
"description": "Export profile configuration",
|
||||
"required": ["profile_id", "name", "bundle_type"],
|
||||
"properties": {
|
||||
"profile_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"bundle_type": {
|
||||
"type": "string",
|
||||
"enum": ["findings", "sbom", "vex", "risk", "compliance", "evidence", "full"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope_defaults": {
|
||||
"$ref": "#/definitions/ExportScope"
|
||||
},
|
||||
"include_signatures": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"enum": ["none", "gzip", "zstd"]
|
||||
},
|
||||
"redaction_policy": {
|
||||
"type": "string"
|
||||
},
|
||||
"retention_days": {
|
||||
"type": "integer"
|
||||
},
|
||||
"schedule": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"cron": {
|
||||
"type": "string"
|
||||
},
|
||||
"destination": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"export_profiles": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ExportProfile"
|
||||
}
|
||||
},
|
||||
"bundle_schemas": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Schema references by bundle type"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"export_profiles": [
|
||||
{
|
||||
"profile_id": "findings-weekly",
|
||||
"name": "Weekly Findings Export",
|
||||
"description": "Weekly export of all findings for compliance reporting",
|
||||
"bundle_type": "findings",
|
||||
"format": "ndjson",
|
||||
"scope_defaults": {
|
||||
"time_range": {
|
||||
"start": "{{now-7d}}",
|
||||
"end": "{{now}}"
|
||||
},
|
||||
"severities": ["critical", "high", "medium"]
|
||||
},
|
||||
"include_signatures": true,
|
||||
"compression": "gzip",
|
||||
"redaction_policy": "pii-removal",
|
||||
"retention_days": 90,
|
||||
"schedule": {
|
||||
"enabled": true,
|
||||
"cron": "0 0 * * 0",
|
||||
"destination": "s3://exports/weekly/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"profile_id": "airgap-full",
|
||||
"name": "Air-Gap Full Bundle",
|
||||
"description": "Complete bundle for air-gapped environments",
|
||||
"bundle_type": "full",
|
||||
"format": "json",
|
||||
"include_signatures": true,
|
||||
"compression": "zstd"
|
||||
}
|
||||
],
|
||||
"bundle_schemas": {
|
||||
"findings": "https://stella-ops.org/schemas/findings-bundle.schema.json",
|
||||
"sbom": "https://cyclonedx.org/schema/bom-1.6.schema.json",
|
||||
"vex": "https://stella-ops.org/schemas/vex-normalization.schema.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
562
docs/schemas/graph-demo-outputs.schema.json
Normal file
562
docs/schemas/graph-demo-outputs.schema.json
Normal file
@@ -0,0 +1,562 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stella-ops.org/schemas/graph-demo-outputs.schema.json",
|
||||
"title": "StellaOps Graph Demo Outputs Schema",
|
||||
"description": "Schema for graph observability demo outputs, dashboard configurations, and metrics samples. Unblocks GRAPH-OPS-0001 (1+ tasks).",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"DemoMetricSample": {
|
||||
"type": "object",
|
||||
"description": "Sample metric data for demo/documentation",
|
||||
"required": ["metric_name", "value", "timestamp"],
|
||||
"properties": {
|
||||
"metric_name": {
|
||||
"type": "string",
|
||||
"description": "Prometheus-style metric name"
|
||||
},
|
||||
"value": {
|
||||
"type": "number"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"description": "Metric unit (bytes, seconds, count, etc.)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DemoTimeSeries": {
|
||||
"type": "object",
|
||||
"description": "Time series data for demo visualizations",
|
||||
"required": ["series_id", "metric_name", "data_points"],
|
||||
"properties": {
|
||||
"series_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"metric_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"data_points": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"value": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": ["timestamp", "value"]
|
||||
}
|
||||
},
|
||||
"resolution": {
|
||||
"type": "string",
|
||||
"enum": ["1m", "5m", "15m", "1h", "1d"],
|
||||
"description": "Data point resolution"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DemoDashboard": {
|
||||
"type": "object",
|
||||
"description": "Demo dashboard configuration",
|
||||
"required": ["dashboard_id", "title", "panels"],
|
||||
"properties": {
|
||||
"dashboard_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"time_range": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"to": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"refresh_interval": {
|
||||
"type": "string",
|
||||
"default": "30s"
|
||||
},
|
||||
"panels": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DemoPanel"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DashboardVariable"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"DemoPanel": {
|
||||
"type": "object",
|
||||
"description": "Dashboard panel configuration",
|
||||
"required": ["panel_id", "title", "type"],
|
||||
"properties": {
|
||||
"panel_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["graph", "stat", "gauge", "table", "heatmap", "logs", "alert_list", "pie_chart", "bar_chart"]
|
||||
},
|
||||
"grid_pos": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x": { "type": "integer" },
|
||||
"y": { "type": "integer" },
|
||||
"w": { "type": "integer" },
|
||||
"h": { "type": "integer" }
|
||||
}
|
||||
},
|
||||
"queries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PanelQuery"
|
||||
}
|
||||
},
|
||||
"thresholds": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Threshold"
|
||||
}
|
||||
},
|
||||
"demo_data": {
|
||||
"$ref": "#/definitions/DemoTimeSeries",
|
||||
"description": "Pre-populated demo data for this panel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PanelQuery": {
|
||||
"type": "object",
|
||||
"description": "Panel query definition",
|
||||
"properties": {
|
||||
"query_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"expr": {
|
||||
"type": "string",
|
||||
"description": "PromQL expression"
|
||||
},
|
||||
"legend": {
|
||||
"type": "string"
|
||||
},
|
||||
"datasource": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Threshold": {
|
||||
"type": "object",
|
||||
"description": "Visual threshold",
|
||||
"properties": {
|
||||
"value": {
|
||||
"type": "number"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"enum": ["ok", "warning", "critical"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"DashboardVariable": {
|
||||
"type": "object",
|
||||
"description": "Dashboard variable/filter",
|
||||
"required": ["name", "type"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["query", "custom", "constant", "interval"]
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DemoAlertRule": {
|
||||
"type": "object",
|
||||
"description": "Demo alert rule",
|
||||
"required": ["rule_id", "name", "expr"],
|
||||
"properties": {
|
||||
"rule_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"expr": {
|
||||
"type": "string",
|
||||
"description": "PromQL alert expression"
|
||||
},
|
||||
"for": {
|
||||
"type": "string",
|
||||
"default": "5m",
|
||||
"description": "Duration condition must be true"
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "warning", "info"]
|
||||
},
|
||||
"summary": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"runbook_url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"DemoRunbook": {
|
||||
"type": "object",
|
||||
"description": "Demo runbook configuration",
|
||||
"required": ["runbook_id", "title", "steps"],
|
||||
"properties": {
|
||||
"runbook_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"trigger_alerts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Alert rule IDs that trigger this runbook"
|
||||
},
|
||||
"steps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RunbookStep"
|
||||
}
|
||||
},
|
||||
"estimated_duration": {
|
||||
"type": "string",
|
||||
"description": "Estimated time to complete (e.g., 15m)"
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"RunbookStep": {
|
||||
"type": "object",
|
||||
"description": "Individual runbook step",
|
||||
"required": ["step_number", "action"],
|
||||
"properties": {
|
||||
"step_number": {
|
||||
"type": "integer"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"description": "Action to perform"
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "CLI command if applicable"
|
||||
},
|
||||
"expected_outcome": {
|
||||
"type": "string"
|
||||
},
|
||||
"escalation_if_failed": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DemoOutputPack": {
|
||||
"type": "object",
|
||||
"description": "Complete demo output package",
|
||||
"required": ["pack_id", "version", "generated_at"],
|
||||
"properties": {
|
||||
"pack_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"dashboards": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DemoDashboard"
|
||||
}
|
||||
},
|
||||
"alert_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DemoAlertRule"
|
||||
}
|
||||
},
|
||||
"runbooks": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DemoRunbook"
|
||||
}
|
||||
},
|
||||
"sample_data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DemoTimeSeries"
|
||||
}
|
||||
},
|
||||
"screenshots": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/DemoScreenshot"
|
||||
}
|
||||
},
|
||||
"aggregate_digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DemoScreenshot": {
|
||||
"type": "object",
|
||||
"description": "Demo screenshot for documentation",
|
||||
"required": ["screenshot_id", "filename", "digest"],
|
||||
"properties": {
|
||||
"screenshot_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"filename": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"dashboard_id": {
|
||||
"type": "string",
|
||||
"description": "Dashboard this screenshot is from"
|
||||
},
|
||||
"panel_id": {
|
||||
"type": "string",
|
||||
"description": "Specific panel if applicable"
|
||||
},
|
||||
"width": {
|
||||
"type": "integer"
|
||||
},
|
||||
"height": {
|
||||
"type": "integer"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": ["png", "webp", "svg"]
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"output_pack": {
|
||||
"$ref": "#/definitions/DemoOutputPack"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"output_pack": {
|
||||
"pack_id": "stellaops-graph-demo-2025.10",
|
||||
"version": "2025.10.0",
|
||||
"generated_at": "2025-12-06T10:00:00Z",
|
||||
"dashboards": [
|
||||
{
|
||||
"dashboard_id": "vulnerability-overview",
|
||||
"title": "Vulnerability Overview",
|
||||
"description": "High-level vulnerability metrics across all scanned assets",
|
||||
"tags": ["vulnerabilities", "overview"],
|
||||
"time_range": { "from": "now-24h", "to": "now" },
|
||||
"refresh_interval": "1m",
|
||||
"panels": [
|
||||
{
|
||||
"panel_id": "total-vulns",
|
||||
"title": "Total Vulnerabilities",
|
||||
"type": "stat",
|
||||
"grid_pos": { "x": 0, "y": 0, "w": 6, "h": 4 },
|
||||
"queries": [
|
||||
{
|
||||
"query_id": "q1",
|
||||
"expr": "sum(stellaops_vulnerabilities_total)"
|
||||
}
|
||||
],
|
||||
"thresholds": [
|
||||
{ "value": 0, "color": "green", "state": "ok" },
|
||||
{ "value": 100, "color": "yellow", "state": "warning" },
|
||||
{ "value": 500, "color": "red", "state": "critical" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"panel_id": "critical-vulns",
|
||||
"title": "Critical Vulnerabilities",
|
||||
"type": "stat",
|
||||
"grid_pos": { "x": 6, "y": 0, "w": 6, "h": 4 },
|
||||
"queries": [
|
||||
{
|
||||
"query_id": "q2",
|
||||
"expr": "sum(stellaops_vulnerabilities_total{severity=\"critical\"})"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"variables": [
|
||||
{
|
||||
"name": "tenant",
|
||||
"label": "Tenant",
|
||||
"type": "query",
|
||||
"options": ["all", "tenant-a", "tenant-b"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"alert_rules": [
|
||||
{
|
||||
"rule_id": "critical-vuln-spike",
|
||||
"name": "Critical Vulnerability Spike",
|
||||
"expr": "increase(stellaops_vulnerabilities_total{severity=\"critical\"}[1h]) > 10",
|
||||
"for": "5m",
|
||||
"severity": "critical",
|
||||
"summary": "Critical vulnerabilities increased by more than 10 in the last hour",
|
||||
"runbook_url": "https://docs.stella-ops.org/runbooks/critical-vuln-spike"
|
||||
}
|
||||
],
|
||||
"runbooks": [
|
||||
{
|
||||
"runbook_id": "critical-vuln-spike-response",
|
||||
"title": "Critical Vulnerability Spike Response",
|
||||
"description": "Steps to investigate and respond to a spike in critical vulnerabilities",
|
||||
"trigger_alerts": ["critical-vuln-spike"],
|
||||
"steps": [
|
||||
{
|
||||
"step_number": 1,
|
||||
"action": "Identify the source of new vulnerabilities",
|
||||
"command": "stella findings list --severity critical --since 1h",
|
||||
"expected_outcome": "List of new critical findings with affected assets"
|
||||
},
|
||||
{
|
||||
"step_number": 2,
|
||||
"action": "Check if vulnerabilities are from new scans or advisory updates",
|
||||
"command": "stella scan jobs --status completed --since 1h"
|
||||
},
|
||||
{
|
||||
"step_number": 3,
|
||||
"action": "Review VEX applicability for affected components",
|
||||
"command": "stella vex check --vuln-id CVE-XXXX-YYYY"
|
||||
}
|
||||
],
|
||||
"estimated_duration": "15m",
|
||||
"severity": "critical"
|
||||
}
|
||||
],
|
||||
"sample_data": [
|
||||
{
|
||||
"series_id": "vulns-24h",
|
||||
"metric_name": "stellaops_vulnerabilities_total",
|
||||
"labels": { "severity": "critical" },
|
||||
"data_points": [
|
||||
{ "timestamp": "2025-12-05T10:00:00Z", "value": 45 },
|
||||
{ "timestamp": "2025-12-05T14:00:00Z", "value": 48 },
|
||||
{ "timestamp": "2025-12-05T18:00:00Z", "value": 52 },
|
||||
{ "timestamp": "2025-12-05T22:00:00Z", "value": 51 },
|
||||
{ "timestamp": "2025-12-06T02:00:00Z", "value": 49 },
|
||||
{ "timestamp": "2025-12-06T06:00:00Z", "value": 47 },
|
||||
{ "timestamp": "2025-12-06T10:00:00Z", "value": 50 }
|
||||
],
|
||||
"resolution": "1h"
|
||||
}
|
||||
],
|
||||
"screenshots": [
|
||||
{
|
||||
"screenshot_id": "vuln-overview-full",
|
||||
"filename": "vulnerability-overview-dashboard.png",
|
||||
"description": "Full vulnerability overview dashboard",
|
||||
"dashboard_id": "vulnerability-overview",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"format": "png",
|
||||
"digest": "sha256:scr123def456789012345678901234567890123456789012345678901234scr"
|
||||
}
|
||||
],
|
||||
"aggregate_digest": "sha256:demo123def456789012345678901234567890123456789012345678901234demo"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
686
docs/schemas/ops-incident-runbook.schema.json
Normal file
686
docs/schemas/ops-incident-runbook.schema.json
Normal file
@@ -0,0 +1,686 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stella-ops.org/schemas/ops-incident-runbook.schema.json",
|
||||
"title": "StellaOps Operations Incident Runbook Schema",
|
||||
"description": "Schema for incident runbooks, escalation procedures, and operational checklists. Unblocks DOCS-RUNBOOK-55-001 (1+ tasks).",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"Runbook": {
|
||||
"type": "object",
|
||||
"description": "Complete incident runbook",
|
||||
"required": ["runbook_id", "title", "severity", "steps"],
|
||||
"properties": {
|
||||
"runbook_id": {
|
||||
"type": "string",
|
||||
"pattern": "^RB-[A-Z]+-[0-9]+$",
|
||||
"description": "Unique runbook identifier (e.g., RB-VULN-001)"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low"],
|
||||
"description": "Severity level this runbook addresses"
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"enum": ["vulnerability", "outage", "security", "performance", "data", "compliance"],
|
||||
"description": "Incident category"
|
||||
},
|
||||
"trigger_conditions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TriggerCondition"
|
||||
},
|
||||
"description": "Conditions that trigger this runbook"
|
||||
},
|
||||
"prerequisites": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Required access/tools before starting"
|
||||
},
|
||||
"steps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RunbookStep"
|
||||
}
|
||||
},
|
||||
"escalation": {
|
||||
"$ref": "#/definitions/EscalationProcedure"
|
||||
},
|
||||
"communication": {
|
||||
"$ref": "#/definitions/CommunicationPlan"
|
||||
},
|
||||
"rollback": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RunbookStep"
|
||||
},
|
||||
"description": "Rollback steps if resolution fails"
|
||||
},
|
||||
"post_incident": {
|
||||
"$ref": "#/definitions/PostIncidentChecklist"
|
||||
},
|
||||
"estimated_duration": {
|
||||
"type": "string",
|
||||
"description": "Expected time to resolve (e.g., 30m, 2h)"
|
||||
},
|
||||
"last_updated": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "Team/person responsible for maintaining this runbook"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TriggerCondition": {
|
||||
"type": "object",
|
||||
"description": "Condition that triggers the runbook",
|
||||
"required": ["condition_type", "description"],
|
||||
"properties": {
|
||||
"condition_type": {
|
||||
"type": "string",
|
||||
"enum": ["alert", "metric_threshold", "user_report", "scheduled", "manual"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"alert_name": {
|
||||
"type": "string",
|
||||
"description": "Alert name if condition_type is 'alert'"
|
||||
},
|
||||
"metric_expr": {
|
||||
"type": "string",
|
||||
"description": "PromQL expression if condition_type is 'metric_threshold'"
|
||||
},
|
||||
"threshold": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RunbookStep": {
|
||||
"type": "object",
|
||||
"description": "Individual runbook step",
|
||||
"required": ["step_number", "action"],
|
||||
"properties": {
|
||||
"step_number": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"description": "What to do"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Detailed explanation"
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "CLI command to execute"
|
||||
},
|
||||
"commands": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CommandSpec"
|
||||
},
|
||||
"description": "Multiple commands if needed"
|
||||
},
|
||||
"expected_output": {
|
||||
"type": "string",
|
||||
"description": "What success looks like"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "string",
|
||||
"description": "Max time for this step (e.g., 5m)"
|
||||
},
|
||||
"decision_point": {
|
||||
"$ref": "#/definitions/DecisionPoint",
|
||||
"description": "If step requires a decision"
|
||||
},
|
||||
"verification": {
|
||||
"type": "string",
|
||||
"description": "How to verify step completed successfully"
|
||||
},
|
||||
"notes": {
|
||||
"type": "string",
|
||||
"description": "Additional context or warnings"
|
||||
},
|
||||
"skip_conditions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Conditions under which to skip this step"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CommandSpec": {
|
||||
"type": "object",
|
||||
"description": "Command specification",
|
||||
"required": ["command"],
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"requires_sudo": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"environment": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"DecisionPoint": {
|
||||
"type": "object",
|
||||
"description": "Decision branch in runbook",
|
||||
"required": ["question", "options"],
|
||||
"properties": {
|
||||
"question": {
|
||||
"type": "string"
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {
|
||||
"type": "string"
|
||||
},
|
||||
"next_step": {
|
||||
"type": "integer"
|
||||
},
|
||||
"action": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["condition"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"EscalationProcedure": {
|
||||
"type": "object",
|
||||
"description": "Escalation procedure",
|
||||
"properties": {
|
||||
"levels": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/EscalationLevel"
|
||||
}
|
||||
},
|
||||
"auto_escalate_after": {
|
||||
"type": "string",
|
||||
"description": "Time after which to auto-escalate (e.g., 30m)"
|
||||
},
|
||||
"escalation_criteria": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Conditions that trigger escalation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EscalationLevel": {
|
||||
"type": "object",
|
||||
"description": "Single escalation level",
|
||||
"required": ["level", "contacts"],
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"contacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Contact"
|
||||
}
|
||||
},
|
||||
"response_time_sla": {
|
||||
"type": "string",
|
||||
"description": "Expected response time (e.g., 15m)"
|
||||
},
|
||||
"notification_channels": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["pagerduty", "slack", "email", "phone", "sms", "teams"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Contact": {
|
||||
"type": "object",
|
||||
"description": "Contact information",
|
||||
"required": ["name", "role"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"slack_handle": {
|
||||
"type": "string"
|
||||
},
|
||||
"pagerduty_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CommunicationPlan": {
|
||||
"type": "object",
|
||||
"description": "Communication during incident",
|
||||
"properties": {
|
||||
"status_page": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "Public status page URL"
|
||||
},
|
||||
"internal_channel": {
|
||||
"type": "string",
|
||||
"description": "Internal communication channel (e.g., #incident-response)"
|
||||
},
|
||||
"stakeholder_updates": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"frequency": {
|
||||
"type": "string",
|
||||
"description": "Update frequency (e.g., every 30m)"
|
||||
},
|
||||
"recipients": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"type": "string",
|
||||
"description": "Status update template"
|
||||
}
|
||||
}
|
||||
},
|
||||
"customer_notification": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"required": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"template": {
|
||||
"type": "string"
|
||||
},
|
||||
"approval_required": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PostIncidentChecklist": {
|
||||
"type": "object",
|
||||
"description": "Post-incident activities",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"task": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"due": {
|
||||
"type": "string",
|
||||
"description": "Due timeframe (e.g., within 24h, within 1 week)"
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"required": ["task"]
|
||||
}
|
||||
},
|
||||
"postmortem_required": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"postmortem_due": {
|
||||
"type": "string",
|
||||
"description": "Timeframe for postmortem (e.g., 5 business days)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"IncidentChecklist": {
|
||||
"type": "object",
|
||||
"description": "Pre-flight checklist for incident response",
|
||||
"required": ["checklist_id", "name", "items"],
|
||||
"properties": {
|
||||
"checklist_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"enum": ["access", "tools", "documentation", "communication", "monitoring"]
|
||||
},
|
||||
"verification": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["description"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RunbookCatalog": {
|
||||
"type": "object",
|
||||
"description": "Catalog of all runbooks",
|
||||
"required": ["catalog_id", "version", "runbooks"],
|
||||
"properties": {
|
||||
"catalog_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"runbooks": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Runbook"
|
||||
}
|
||||
},
|
||||
"checklists": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/IncidentChecklist"
|
||||
}
|
||||
},
|
||||
"global_contacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Contact"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"catalog": {
|
||||
"$ref": "#/definitions/RunbookCatalog"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"catalog": {
|
||||
"catalog_id": "stellaops-runbooks",
|
||||
"version": "2025.10.0",
|
||||
"updated_at": "2025-12-06T10:00:00Z",
|
||||
"runbooks": [
|
||||
{
|
||||
"runbook_id": "RB-VULN-001",
|
||||
"title": "Critical Vulnerability Spike Response",
|
||||
"description": "Response procedure when critical vulnerabilities spike significantly",
|
||||
"severity": "critical",
|
||||
"category": "vulnerability",
|
||||
"trigger_conditions": [
|
||||
{
|
||||
"condition_type": "alert",
|
||||
"description": "Critical vulnerability count increased by >10 in 1 hour",
|
||||
"alert_name": "CriticalVulnerabilitySpike"
|
||||
}
|
||||
],
|
||||
"prerequisites": [
|
||||
"Access to StellaOps CLI (stella)",
|
||||
"Read access to Findings Ledger",
|
||||
"Access to #security-incidents Slack channel"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"step_number": 1,
|
||||
"action": "Acknowledge the alert",
|
||||
"description": "Acknowledge in PagerDuty/alerting system to stop escalation",
|
||||
"timeout": "5m"
|
||||
},
|
||||
{
|
||||
"step_number": 2,
|
||||
"action": "Identify scope of new vulnerabilities",
|
||||
"command": "stella findings list --severity critical --since 1h --format table",
|
||||
"expected_output": "List of new critical findings with CVE IDs and affected assets",
|
||||
"verification": "Output shows findings with timestamps within last hour"
|
||||
},
|
||||
{
|
||||
"step_number": 3,
|
||||
"action": "Determine if spike is from new scans or advisory updates",
|
||||
"commands": [
|
||||
{
|
||||
"command": "stella scan jobs --status completed --since 1h",
|
||||
"description": "Check for recent scan completions"
|
||||
},
|
||||
{
|
||||
"command": "stella advisory updates --since 1h",
|
||||
"description": "Check for recent advisory updates"
|
||||
}
|
||||
],
|
||||
"decision_point": {
|
||||
"question": "What caused the spike?",
|
||||
"options": [
|
||||
{
|
||||
"condition": "New scans completed",
|
||||
"next_step": 4,
|
||||
"action": "Review scan results"
|
||||
},
|
||||
{
|
||||
"condition": "Advisory update",
|
||||
"next_step": 5,
|
||||
"action": "Review advisory impact"
|
||||
},
|
||||
{
|
||||
"condition": "Unknown/Both",
|
||||
"next_step": 4,
|
||||
"action": "Continue with full investigation"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"step_number": 4,
|
||||
"action": "Review affected assets and determine business impact",
|
||||
"command": "stella findings group-by asset --severity critical --since 1h",
|
||||
"description": "Group findings by asset to understand impact scope"
|
||||
},
|
||||
{
|
||||
"step_number": 5,
|
||||
"action": "Check VEX applicability",
|
||||
"command": "stella vex check --vuln-ids $(stella findings list --severity critical --since 1h --format ids)",
|
||||
"description": "Check if any vulnerabilities have VEX statements that reduce severity"
|
||||
},
|
||||
{
|
||||
"step_number": 6,
|
||||
"action": "Update stakeholders",
|
||||
"description": "Post status update to #security-incidents with findings summary",
|
||||
"notes": "Use template: 'VULN SPIKE: [count] new critical vulns affecting [assets]. Investigation in progress.'"
|
||||
},
|
||||
{
|
||||
"step_number": 7,
|
||||
"action": "Create remediation tickets if needed",
|
||||
"command": "stella findings export --severity critical --since 1h --format jira",
|
||||
"skip_conditions": [
|
||||
"All vulnerabilities covered by VEX not_affected",
|
||||
"Vulnerabilities are duplicates from rescan"
|
||||
]
|
||||
}
|
||||
],
|
||||
"escalation": {
|
||||
"levels": [
|
||||
{
|
||||
"level": 1,
|
||||
"name": "On-call Security Engineer",
|
||||
"contacts": [
|
||||
{
|
||||
"name": "Security On-Call",
|
||||
"role": "Security Engineer",
|
||||
"slack_handle": "@security-oncall"
|
||||
}
|
||||
],
|
||||
"response_time_sla": "15m",
|
||||
"notification_channels": ["pagerduty", "slack"]
|
||||
},
|
||||
{
|
||||
"level": 2,
|
||||
"name": "Security Team Lead",
|
||||
"contacts": [
|
||||
{
|
||||
"name": "Security Lead",
|
||||
"role": "Security Team Lead",
|
||||
"slack_handle": "@security-lead"
|
||||
}
|
||||
],
|
||||
"response_time_sla": "30m",
|
||||
"notification_channels": ["pagerduty", "slack", "phone"]
|
||||
}
|
||||
],
|
||||
"auto_escalate_after": "30m",
|
||||
"escalation_criteria": [
|
||||
"No acknowledgment within 15 minutes",
|
||||
"More than 50 critical vulnerabilities",
|
||||
"Production systems affected"
|
||||
]
|
||||
},
|
||||
"communication": {
|
||||
"internal_channel": "#security-incidents",
|
||||
"stakeholder_updates": {
|
||||
"frequency": "every 30m during active incident",
|
||||
"recipients": ["security-team", "engineering-leads"],
|
||||
"template": "VULN INCIDENT UPDATE: Status: [status]. Critical count: [count]. Affected systems: [systems]. Next update: [time]."
|
||||
}
|
||||
},
|
||||
"post_incident": {
|
||||
"items": [
|
||||
{
|
||||
"task": "Document incident timeline",
|
||||
"owner": "Incident Commander",
|
||||
"due": "within 24h",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"task": "Update vulnerability scanning schedules if needed",
|
||||
"owner": "Security Team",
|
||||
"due": "within 1 week",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"task": "Review and update this runbook",
|
||||
"owner": "Runbook Owner",
|
||||
"due": "within 1 week",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"postmortem_required": true,
|
||||
"postmortem_due": "5 business days"
|
||||
},
|
||||
"estimated_duration": "1h",
|
||||
"last_updated": "2025-12-06T10:00:00Z",
|
||||
"owner": "Security Operations Team",
|
||||
"tags": ["vulnerability", "security", "critical"]
|
||||
}
|
||||
],
|
||||
"checklists": [
|
||||
{
|
||||
"checklist_id": "incident-preflight",
|
||||
"name": "Incident Response Pre-flight Checklist",
|
||||
"description": "Verify access and tools before incident response",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "cli-access",
|
||||
"description": "StellaOps CLI is installed and authenticated",
|
||||
"category": "tools",
|
||||
"verification": "Run 'stella whoami' successfully"
|
||||
},
|
||||
{
|
||||
"item_id": "slack-access",
|
||||
"description": "Access to #security-incidents channel",
|
||||
"category": "communication",
|
||||
"verification": "Can post messages to channel"
|
||||
},
|
||||
{
|
||||
"item_id": "pagerduty-access",
|
||||
"description": "Can acknowledge alerts in PagerDuty",
|
||||
"category": "tools",
|
||||
"verification": "PagerDuty mobile app logged in"
|
||||
},
|
||||
{
|
||||
"item_id": "runbooks-access",
|
||||
"description": "Can access runbook documentation",
|
||||
"category": "documentation",
|
||||
"verification": "docs.stella-ops.org/runbooks accessible"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"global_contacts": [
|
||||
{
|
||||
"name": "Security Operations",
|
||||
"role": "Primary Response Team",
|
||||
"email": "security-ops@example.com",
|
||||
"slack_handle": "@security-ops"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
606
docs/schemas/risk-api.schema.json
Normal file
606
docs/schemas/risk-api.schema.json
Normal file
@@ -0,0 +1,606 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stella-ops.org/schemas/risk-api.schema.json",
|
||||
"title": "StellaOps Risk API Schema",
|
||||
"description": "Schema for Risk API endpoints, scoring models, and factor weights. Unblocks DOCS-RISK-67-002 through 68-002 (5+ tasks).",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"RiskScore": {
|
||||
"type": "object",
|
||||
"description": "Computed risk score",
|
||||
"required": ["score", "rating", "computed_at"],
|
||||
"properties": {
|
||||
"score": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 100,
|
||||
"description": "Numeric risk score (0-100)"
|
||||
},
|
||||
"rating": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low", "info", "none"],
|
||||
"description": "Risk rating category"
|
||||
},
|
||||
"computed_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"confidence": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Confidence level in the score (0-1)"
|
||||
},
|
||||
"factors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RiskFactor"
|
||||
}
|
||||
},
|
||||
"trend": {
|
||||
"$ref": "#/definitions/RiskTrend"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskFactor": {
|
||||
"type": "object",
|
||||
"description": "Individual risk factor contribution",
|
||||
"required": ["factor_id", "name", "value", "weight", "contribution"],
|
||||
"properties": {
|
||||
"factor_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"enum": ["vulnerability", "exposure", "asset", "context", "temporal", "environmental"]
|
||||
},
|
||||
"value": {
|
||||
"type": "number",
|
||||
"description": "Raw factor value"
|
||||
},
|
||||
"normalized_value": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Normalized value (0-1)"
|
||||
},
|
||||
"weight": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Factor weight in scoring model"
|
||||
},
|
||||
"contribution": {
|
||||
"type": "number",
|
||||
"description": "Contribution to final score"
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Data source for this factor"
|
||||
},
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Evidence supporting this factor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskTrend": {
|
||||
"type": "object",
|
||||
"description": "Risk score trend over time",
|
||||
"properties": {
|
||||
"direction": {
|
||||
"type": "string",
|
||||
"enum": ["improving", "stable", "degrading"]
|
||||
},
|
||||
"change_percent": {
|
||||
"type": "number",
|
||||
"description": "Percent change from previous period"
|
||||
},
|
||||
"period": {
|
||||
"type": "string",
|
||||
"enum": ["24h", "7d", "30d"]
|
||||
},
|
||||
"previous_score": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskProfile": {
|
||||
"type": "object",
|
||||
"description": "Risk profile configuration",
|
||||
"required": ["profile_id", "name"],
|
||||
"properties": {
|
||||
"profile_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"scoring_model": {
|
||||
"$ref": "#/definitions/ScoringModel"
|
||||
},
|
||||
"thresholds": {
|
||||
"$ref": "#/definitions/RiskThresholds"
|
||||
},
|
||||
"factor_weights": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
}
|
||||
},
|
||||
"enabled_factors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ScoringModel": {
|
||||
"type": "object",
|
||||
"description": "Risk scoring model configuration",
|
||||
"required": ["model_id", "name"],
|
||||
"properties": {
|
||||
"model_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["weighted_sum", "geometric_mean", "max_severity", "custom"],
|
||||
"description": "Scoring algorithm type"
|
||||
},
|
||||
"base_score_source": {
|
||||
"type": "string",
|
||||
"enum": ["cvss_v3", "cvss_v4", "epss", "custom"],
|
||||
"description": "Primary score source"
|
||||
},
|
||||
"modifiers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ScoreModifier"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ScoreModifier": {
|
||||
"type": "object",
|
||||
"description": "Score modifier rule",
|
||||
"required": ["modifier_id", "condition", "adjustment"],
|
||||
"properties": {
|
||||
"modifier_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"description": "Condition expression (e.g., 'kev == true')"
|
||||
},
|
||||
"adjustment": {
|
||||
"type": "number",
|
||||
"description": "Score adjustment (can be positive or negative)"
|
||||
},
|
||||
"adjustment_type": {
|
||||
"type": "string",
|
||||
"enum": ["absolute", "percent", "multiply"],
|
||||
"default": "absolute"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer",
|
||||
"description": "Order of modifier application"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskThresholds": {
|
||||
"type": "object",
|
||||
"description": "Risk rating thresholds",
|
||||
"properties": {
|
||||
"critical": {
|
||||
"type": "number",
|
||||
"default": 90,
|
||||
"description": "Score >= this is Critical"
|
||||
},
|
||||
"high": {
|
||||
"type": "number",
|
||||
"default": 70,
|
||||
"description": "Score >= this is High"
|
||||
},
|
||||
"medium": {
|
||||
"type": "number",
|
||||
"default": 40,
|
||||
"description": "Score >= this is Medium"
|
||||
},
|
||||
"low": {
|
||||
"type": "number",
|
||||
"default": 10,
|
||||
"description": "Score >= this is Low"
|
||||
},
|
||||
"info": {
|
||||
"type": "number",
|
||||
"default": 0,
|
||||
"description": "Score >= this is Info"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskAssessmentRequest": {
|
||||
"type": "object",
|
||||
"description": "Request to compute risk for an entity",
|
||||
"required": ["entity_type", "entity_id"],
|
||||
"properties": {
|
||||
"entity_type": {
|
||||
"type": "string",
|
||||
"enum": ["vulnerability", "asset", "component", "project", "tenant"]
|
||||
},
|
||||
"entity_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"profile_id": {
|
||||
"type": "string",
|
||||
"description": "Risk profile to use (uses default if not specified)"
|
||||
},
|
||||
"include_factors": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Include factor breakdown in response"
|
||||
},
|
||||
"include_trend": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Include trend analysis"
|
||||
},
|
||||
"context": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"description": "Additional context for scoring"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskAssessmentResponse": {
|
||||
"type": "object",
|
||||
"description": "Risk assessment result",
|
||||
"required": ["assessment_id", "entity_type", "entity_id", "score"],
|
||||
"properties": {
|
||||
"assessment_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"entity_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"entity_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"profile_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"score": {
|
||||
"$ref": "#/definitions/RiskScore"
|
||||
},
|
||||
"explainability": {
|
||||
"$ref": "#/definitions/RiskExplainability"
|
||||
},
|
||||
"recommendations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RiskRecommendation"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskExplainability": {
|
||||
"type": "object",
|
||||
"description": "Human-readable explanation of risk score",
|
||||
"properties": {
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"description": "One-line summary"
|
||||
},
|
||||
"narrative": {
|
||||
"type": "string",
|
||||
"description": "Detailed explanation"
|
||||
},
|
||||
"top_factors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"factor": {
|
||||
"type": "string"
|
||||
},
|
||||
"impact": {
|
||||
"type": "string",
|
||||
"enum": ["major", "moderate", "minor"]
|
||||
},
|
||||
"explanation": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Top contributing factors"
|
||||
},
|
||||
"comparisons": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"org_percentile": {
|
||||
"type": "number",
|
||||
"description": "Percentile within organization"
|
||||
},
|
||||
"industry_percentile": {
|
||||
"type": "number",
|
||||
"description": "Percentile within industry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskRecommendation": {
|
||||
"type": "object",
|
||||
"description": "Risk mitigation recommendation",
|
||||
"required": ["recommendation_id", "action"],
|
||||
"properties": {
|
||||
"recommendation_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"description": "Recommended action"
|
||||
},
|
||||
"priority": {
|
||||
"type": "string",
|
||||
"enum": ["critical", "high", "medium", "low"]
|
||||
},
|
||||
"impact_estimate": {
|
||||
"type": "number",
|
||||
"description": "Estimated score reduction if implemented"
|
||||
},
|
||||
"effort": {
|
||||
"type": "string",
|
||||
"enum": ["minimal", "moderate", "significant"]
|
||||
},
|
||||
"related_factors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskAggregation": {
|
||||
"type": "object",
|
||||
"description": "Aggregated risk across multiple entities",
|
||||
"required": ["aggregation_id", "entity_type", "count", "scores"],
|
||||
"properties": {
|
||||
"aggregation_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"entity_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"type": "string",
|
||||
"description": "Aggregation scope (e.g., project, tenant)"
|
||||
},
|
||||
"count": {
|
||||
"type": "integer",
|
||||
"description": "Number of entities aggregated"
|
||||
},
|
||||
"scores": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"average": {
|
||||
"type": "number"
|
||||
},
|
||||
"median": {
|
||||
"type": "number"
|
||||
},
|
||||
"max": {
|
||||
"type": "number"
|
||||
},
|
||||
"min": {
|
||||
"type": "number"
|
||||
},
|
||||
"p95": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"distribution": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"critical": { "type": "integer" },
|
||||
"high": { "type": "integer" },
|
||||
"medium": { "type": "integer" },
|
||||
"low": { "type": "integer" },
|
||||
"info": { "type": "integer" }
|
||||
}
|
||||
},
|
||||
"trend": {
|
||||
"$ref": "#/definitions/RiskTrend"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RiskApiEndpoint": {
|
||||
"type": "object",
|
||||
"description": "Risk API endpoint definition",
|
||||
"required": ["path", "method", "operation_id"],
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"method": {
|
||||
"type": "string",
|
||||
"enum": ["GET", "POST", "PUT", "DELETE"]
|
||||
},
|
||||
"operation_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"summary": {
|
||||
"type": "string"
|
||||
},
|
||||
"request_schema": {
|
||||
"type": "string",
|
||||
"description": "Reference to request schema"
|
||||
},
|
||||
"response_schema": {
|
||||
"type": "string",
|
||||
"description": "Reference to response schema"
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Required OAuth scopes"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"endpoints": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RiskApiEndpoint"
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RiskProfile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"path": "/api/v1/risk/assess",
|
||||
"method": "POST",
|
||||
"operation_id": "assessRisk",
|
||||
"summary": "Compute risk score for an entity",
|
||||
"request_schema": "RiskAssessmentRequest",
|
||||
"response_schema": "RiskAssessmentResponse",
|
||||
"scopes": ["risk:read"]
|
||||
},
|
||||
{
|
||||
"path": "/api/v1/risk/profiles",
|
||||
"method": "GET",
|
||||
"operation_id": "listRiskProfiles",
|
||||
"summary": "List available risk profiles",
|
||||
"response_schema": "RiskProfile[]",
|
||||
"scopes": ["risk:read"]
|
||||
},
|
||||
{
|
||||
"path": "/api/v1/risk/aggregate",
|
||||
"method": "POST",
|
||||
"operation_id": "aggregateRisk",
|
||||
"summary": "Compute aggregated risk across entities",
|
||||
"response_schema": "RiskAggregation",
|
||||
"scopes": ["risk:read"]
|
||||
},
|
||||
{
|
||||
"path": "/api/v1/risk/profiles/{profile_id}",
|
||||
"method": "PUT",
|
||||
"operation_id": "updateRiskProfile",
|
||||
"summary": "Update a risk profile",
|
||||
"request_schema": "RiskProfile",
|
||||
"scopes": ["risk:write", "admin"]
|
||||
},
|
||||
{
|
||||
"path": "/api/v1/risk/explain/{assessment_id}",
|
||||
"method": "GET",
|
||||
"operation_id": "explainRisk",
|
||||
"summary": "Get detailed explanation for a risk assessment",
|
||||
"response_schema": "RiskExplainability",
|
||||
"scopes": ["risk:read"]
|
||||
}
|
||||
],
|
||||
"profiles": [
|
||||
{
|
||||
"profile_id": "default",
|
||||
"name": "Default Risk Profile",
|
||||
"description": "Standard risk scoring with balanced factor weights",
|
||||
"scoring_model": {
|
||||
"model_id": "weighted-sum-v1",
|
||||
"name": "Weighted Sum Model",
|
||||
"version": "1.0.0",
|
||||
"type": "weighted_sum",
|
||||
"base_score_source": "cvss_v3",
|
||||
"modifiers": [
|
||||
{
|
||||
"modifier_id": "kev-boost",
|
||||
"name": "KEV Exploit Known",
|
||||
"condition": "kev == true",
|
||||
"adjustment": 15,
|
||||
"adjustment_type": "absolute",
|
||||
"priority": 1
|
||||
},
|
||||
{
|
||||
"modifier_id": "reachability-reduction",
|
||||
"name": "Not Reachable",
|
||||
"condition": "reachability == 'not_reachable'",
|
||||
"adjustment": -30,
|
||||
"adjustment_type": "absolute",
|
||||
"priority": 2
|
||||
},
|
||||
{
|
||||
"modifier_id": "vex-not-affected",
|
||||
"name": "VEX Not Affected",
|
||||
"condition": "vex_status == 'not_affected'",
|
||||
"adjustment": -50,
|
||||
"adjustment_type": "absolute",
|
||||
"priority": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"thresholds": {
|
||||
"critical": 90,
|
||||
"high": 70,
|
||||
"medium": 40,
|
||||
"low": 10,
|
||||
"info": 0
|
||||
},
|
||||
"factor_weights": {
|
||||
"cvss_base": 0.35,
|
||||
"exploitability": 0.25,
|
||||
"reachability": 0.20,
|
||||
"asset_criticality": 0.10,
|
||||
"exposure": 0.10
|
||||
},
|
||||
"enabled_factors": [
|
||||
"cvss_base",
|
||||
"exploitability",
|
||||
"kev",
|
||||
"epss",
|
||||
"reachability",
|
||||
"vex_status",
|
||||
"asset_criticality",
|
||||
"exposure",
|
||||
"age"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
498
docs/schemas/sdk-generator-samples.schema.json
Normal file
498
docs/schemas/sdk-generator-samples.schema.json
Normal file
@@ -0,0 +1,498 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stella-ops.org/schemas/sdk-generator-samples.schema.json",
|
||||
"title": "StellaOps SDK Generator Samples Schema",
|
||||
"description": "Schema for SDK generator output samples, snippet packs, and language bindings. Unblocks DEVPORT-63-002, DOCS-SDK-62-001 (2+ tasks).",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"SdkLanguage": {
|
||||
"type": "string",
|
||||
"enum": ["typescript", "python", "go", "java", "csharp", "ruby", "php", "rust"],
|
||||
"description": "Supported SDK target languages"
|
||||
},
|
||||
"SdkSample": {
|
||||
"type": "object",
|
||||
"description": "Individual SDK code sample",
|
||||
"required": ["sample_id", "language", "operation", "code"],
|
||||
"properties": {
|
||||
"sample_id": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9-]*$",
|
||||
"description": "Unique sample identifier"
|
||||
},
|
||||
"language": {
|
||||
"$ref": "#/definitions/SdkLanguage"
|
||||
},
|
||||
"operation": {
|
||||
"type": "string",
|
||||
"description": "API operation this sample demonstrates"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Human-readable title"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Explanation of what the sample demonstrates"
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": "The actual code sample"
|
||||
},
|
||||
"imports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Required imports/dependencies"
|
||||
},
|
||||
"prerequisites": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Setup steps before running"
|
||||
},
|
||||
"expected_output": {
|
||||
"type": "string",
|
||||
"description": "Expected console output or result"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Categorization tags (auth, scanning, vex, etc.)"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$",
|
||||
"description": "SHA-256 hash of code content for verification"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SnippetPack": {
|
||||
"type": "object",
|
||||
"description": "Collection of SDK samples for a specific language",
|
||||
"required": ["pack_id", "language", "version", "samples"],
|
||||
"properties": {
|
||||
"pack_id": {
|
||||
"type": "string",
|
||||
"description": "Unique pack identifier"
|
||||
},
|
||||
"language": {
|
||||
"$ref": "#/definitions/SdkLanguage"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
|
||||
"description": "Pack version (semver)"
|
||||
},
|
||||
"sdk_version": {
|
||||
"type": "string",
|
||||
"description": "Target SDK version these samples work with"
|
||||
},
|
||||
"api_version": {
|
||||
"type": "string",
|
||||
"description": "API version (e.g., v1, v2)"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"samples": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SdkSample"
|
||||
}
|
||||
},
|
||||
"aggregate_digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$",
|
||||
"description": "Hash of all sample digests combined"
|
||||
},
|
||||
"package_info": {
|
||||
"$ref": "#/definitions/PackageInfo"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PackageInfo": {
|
||||
"type": "object",
|
||||
"description": "Language-specific package information",
|
||||
"properties": {
|
||||
"package_name": {
|
||||
"type": "string",
|
||||
"description": "Package name (e.g., @stellaops/sdk, stellaops-sdk)"
|
||||
},
|
||||
"registry_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "Package registry URL"
|
||||
},
|
||||
"install_command": {
|
||||
"type": "string",
|
||||
"description": "Command to install the SDK"
|
||||
},
|
||||
"min_runtime_version": {
|
||||
"type": "string",
|
||||
"description": "Minimum runtime version required"
|
||||
},
|
||||
"dependencies": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Dependency"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Dependency": {
|
||||
"type": "object",
|
||||
"description": "SDK dependency",
|
||||
"required": ["name", "version"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"optional": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"SdkGeneratorConfig": {
|
||||
"type": "object",
|
||||
"description": "SDK generator configuration",
|
||||
"required": ["generator_id", "openapi_source"],
|
||||
"properties": {
|
||||
"generator_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"openapi_source": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "OpenAPI spec URL or path"
|
||||
},
|
||||
"target_languages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SdkLanguage"
|
||||
}
|
||||
},
|
||||
"output_dir": {
|
||||
"type": "string"
|
||||
},
|
||||
"templates": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Custom templates per language"
|
||||
},
|
||||
"options": {
|
||||
"$ref": "#/definitions/GeneratorOptions"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GeneratorOptions": {
|
||||
"type": "object",
|
||||
"description": "SDK generation options",
|
||||
"properties": {
|
||||
"include_samples": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Generate usage samples"
|
||||
},
|
||||
"include_tests": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Generate test stubs"
|
||||
},
|
||||
"include_docs": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Generate API documentation"
|
||||
},
|
||||
"async_style": {
|
||||
"type": "string",
|
||||
"enum": ["async_await", "promises", "callbacks", "sync"],
|
||||
"default": "async_await"
|
||||
},
|
||||
"error_handling": {
|
||||
"type": "string",
|
||||
"enum": ["exceptions", "result_types", "error_codes"],
|
||||
"default": "exceptions"
|
||||
},
|
||||
"naming_convention": {
|
||||
"type": "string",
|
||||
"enum": ["camelCase", "snake_case", "PascalCase"],
|
||||
"description": "Override default for language"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SdkGeneratorOutput": {
|
||||
"type": "object",
|
||||
"description": "Output from SDK generation",
|
||||
"required": ["output_id", "generator_id", "generated_at", "files"],
|
||||
"properties": {
|
||||
"output_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"generator_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"language": {
|
||||
"$ref": "#/definitions/SdkLanguage"
|
||||
},
|
||||
"sdk_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"api_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"files": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/GeneratedFile"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"$ref": "#/definitions/GenerationStats"
|
||||
},
|
||||
"manifest_digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GeneratedFile": {
|
||||
"type": "object",
|
||||
"description": "Generated SDK file",
|
||||
"required": ["path", "digest"],
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["source", "test", "sample", "docs", "config"]
|
||||
},
|
||||
"size_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[a-f0-9]{64}$"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GenerationStats": {
|
||||
"type": "object",
|
||||
"description": "SDK generation statistics",
|
||||
"properties": {
|
||||
"total_files": {
|
||||
"type": "integer"
|
||||
},
|
||||
"source_files": {
|
||||
"type": "integer"
|
||||
},
|
||||
"test_files": {
|
||||
"type": "integer"
|
||||
},
|
||||
"sample_files": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_lines": {
|
||||
"type": "integer"
|
||||
},
|
||||
"endpoints_covered": {
|
||||
"type": "integer"
|
||||
},
|
||||
"models_generated": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SampleCategory": {
|
||||
"type": "object",
|
||||
"description": "Category grouping for samples",
|
||||
"required": ["category_id", "name"],
|
||||
"properties": {
|
||||
"category_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"samples": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Sample IDs in this category"
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "Display order"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SdkDocumentation": {
|
||||
"type": "object",
|
||||
"description": "SDK documentation structure",
|
||||
"properties": {
|
||||
"overview": {
|
||||
"type": "string",
|
||||
"description": "SDK overview markdown"
|
||||
},
|
||||
"quickstart": {
|
||||
"type": "string",
|
||||
"description": "Quickstart guide markdown"
|
||||
},
|
||||
"authentication": {
|
||||
"type": "string",
|
||||
"description": "Authentication guide"
|
||||
},
|
||||
"error_handling": {
|
||||
"type": "string",
|
||||
"description": "Error handling guide"
|
||||
},
|
||||
"changelog": {
|
||||
"type": "string",
|
||||
"description": "SDK changelog"
|
||||
},
|
||||
"api_reference_url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"snippet_packs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SnippetPack"
|
||||
}
|
||||
},
|
||||
"categories": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SampleCategory"
|
||||
}
|
||||
},
|
||||
"generator_outputs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SdkGeneratorOutput"
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"snippet_packs": [
|
||||
{
|
||||
"pack_id": "stellaops-typescript-samples",
|
||||
"language": "typescript",
|
||||
"version": "1.0.0",
|
||||
"sdk_version": "2025.10.0",
|
||||
"api_version": "v1",
|
||||
"generated_at": "2025-12-06T10:00:00Z",
|
||||
"samples": [
|
||||
{
|
||||
"sample_id": "auth-token-exchange",
|
||||
"language": "typescript",
|
||||
"operation": "POST /oauth/token",
|
||||
"title": "Token Exchange",
|
||||
"description": "Exchange client credentials for an access token",
|
||||
"code": "import { StellaOpsClient } from '@stellaops/sdk';\n\nconst client = new StellaOpsClient({\n clientId: process.env.STELLAOPS_CLIENT_ID,\n clientSecret: process.env.STELLAOPS_CLIENT_SECRET,\n});\n\nconst token = await client.auth.getToken();\nconsole.log('Token expires at:', token.expiresAt);",
|
||||
"imports": ["@stellaops/sdk"],
|
||||
"prerequisites": [
|
||||
"Set STELLAOPS_CLIENT_ID environment variable",
|
||||
"Set STELLAOPS_CLIENT_SECRET environment variable"
|
||||
],
|
||||
"expected_output": "Token expires at: 2025-12-06T11:00:00Z",
|
||||
"tags": ["authentication", "oauth"],
|
||||
"digest": "sha256:abc123def456789012345678901234567890123456789012345678901234abcd"
|
||||
},
|
||||
{
|
||||
"sample_id": "scan-container-image",
|
||||
"language": "typescript",
|
||||
"operation": "POST /api/v1/scanner/scan",
|
||||
"title": "Scan Container Image",
|
||||
"description": "Scan a container image for vulnerabilities",
|
||||
"code": "import { StellaOpsClient } from '@stellaops/sdk';\n\nconst client = new StellaOpsClient();\nconst result = await client.scanner.scanImage({\n image: 'nginx:1.25',\n generateSbom: true,\n format: 'cyclonedx',\n});\n\nconsole.log(`Found ${result.vulnerabilities.length} vulnerabilities`);",
|
||||
"imports": ["@stellaops/sdk"],
|
||||
"tags": ["scanning", "sbom", "vulnerabilities"],
|
||||
"digest": "sha256:def456abc789012345678901234567890123456789012345678901234defabc"
|
||||
}
|
||||
],
|
||||
"aggregate_digest": "sha256:agg123def456789012345678901234567890123456789012345678901234agg",
|
||||
"package_info": {
|
||||
"package_name": "@stellaops/sdk",
|
||||
"registry_url": "https://registry.npmjs.org",
|
||||
"install_command": "npm install @stellaops/sdk",
|
||||
"min_runtime_version": "18.0.0",
|
||||
"dependencies": [
|
||||
{ "name": "axios", "version": "^1.6.0" },
|
||||
{ "name": "jose", "version": "^5.0.0" }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"pack_id": "stellaops-python-samples",
|
||||
"language": "python",
|
||||
"version": "1.0.0",
|
||||
"sdk_version": "2025.10.0",
|
||||
"api_version": "v1",
|
||||
"generated_at": "2025-12-06T10:00:00Z",
|
||||
"samples": [
|
||||
{
|
||||
"sample_id": "auth-token-exchange-py",
|
||||
"language": "python",
|
||||
"operation": "POST /oauth/token",
|
||||
"title": "Token Exchange",
|
||||
"description": "Exchange client credentials for an access token",
|
||||
"code": "from stellaops import StellaOpsClient\nimport os\n\nclient = StellaOpsClient(\n client_id=os.environ['STELLAOPS_CLIENT_ID'],\n client_secret=os.environ['STELLAOPS_CLIENT_SECRET'],\n)\n\ntoken = client.auth.get_token()\nprint(f'Token expires at: {token.expires_at}')",
|
||||
"imports": ["stellaops"],
|
||||
"tags": ["authentication", "oauth"],
|
||||
"digest": "sha256:py123def456789012345678901234567890123456789012345678901234pyth"
|
||||
}
|
||||
],
|
||||
"package_info": {
|
||||
"package_name": "stellaops-sdk",
|
||||
"registry_url": "https://pypi.org/project/stellaops-sdk/",
|
||||
"install_command": "pip install stellaops-sdk",
|
||||
"min_runtime_version": "3.10"
|
||||
}
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"category_id": "authentication",
|
||||
"name": "Authentication",
|
||||
"description": "Token exchange and authentication samples",
|
||||
"samples": ["auth-token-exchange", "auth-token-exchange-py"],
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"category_id": "scanning",
|
||||
"name": "Container Scanning",
|
||||
"description": "Container image scanning and SBOM generation",
|
||||
"samples": ["scan-container-image"],
|
||||
"order": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
641
docs/schemas/security-scopes-matrix.schema.json
Normal file
641
docs/schemas/security-scopes-matrix.schema.json
Normal file
@@ -0,0 +1,641 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stella-ops.org/schemas/security-scopes-matrix.schema.json",
|
||||
"title": "StellaOps Security Scopes Matrix Schema",
|
||||
"description": "Schema for security scopes, roles, permissions, and privacy controls. Unblocks DOCS-SEC-62-001, DOCS-SEC-OBS-50-001 (2+ tasks).",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"Scope": {
|
||||
"type": "object",
|
||||
"description": "OAuth2/OIDC scope definition",
|
||||
"required": ["scope_id", "name"],
|
||||
"properties": {
|
||||
"scope_id": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_:]+$",
|
||||
"description": "Scope identifier (e.g., findings:read, admin:write)"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"enum": ["read", "write", "admin", "system"],
|
||||
"description": "Scope category"
|
||||
},
|
||||
"resource": {
|
||||
"type": "string",
|
||||
"description": "Resource this scope applies to"
|
||||
},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["create", "read", "update", "delete", "list", "execute", "export", "import"]
|
||||
}
|
||||
},
|
||||
"requires_mfa": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether MFA is required for this scope"
|
||||
},
|
||||
"sensitive": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether this scope accesses sensitive data"
|
||||
},
|
||||
"audit_level": {
|
||||
"type": "string",
|
||||
"enum": ["none", "basic", "detailed", "full"],
|
||||
"default": "basic"
|
||||
},
|
||||
"parent_scope": {
|
||||
"type": "string",
|
||||
"description": "Parent scope that implies this scope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Role": {
|
||||
"type": "object",
|
||||
"description": "Role definition with assigned scopes",
|
||||
"required": ["role_id", "name", "scopes"],
|
||||
"properties": {
|
||||
"role_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["system", "tenant", "project", "custom"],
|
||||
"description": "Role type"
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Scopes assigned to this role"
|
||||
},
|
||||
"inherits_from": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Roles this role inherits from"
|
||||
},
|
||||
"restrictions": {
|
||||
"$ref": "#/definitions/RoleRestrictions"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"RoleRestrictions": {
|
||||
"type": "object",
|
||||
"description": "Restrictions on role usage",
|
||||
"properties": {
|
||||
"max_sessions": {
|
||||
"type": "integer",
|
||||
"description": "Maximum concurrent sessions"
|
||||
},
|
||||
"ip_allowlist": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"time_restrictions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allowed_hours": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-2][0-9]:[0-5][0-9]$"
|
||||
},
|
||||
"end": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-2][0-9]:[0-5][0-9]$"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"allowed_days": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"require_approval": {
|
||||
"type": "boolean",
|
||||
"description": "Require approval for role activation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Permission": {
|
||||
"type": "object",
|
||||
"description": "Fine-grained permission",
|
||||
"required": ["permission_id", "resource", "action"],
|
||||
"properties": {
|
||||
"permission_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"resource": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["create", "read", "update", "delete", "list", "execute", "export", "import"]
|
||||
},
|
||||
"conditions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionCondition"
|
||||
}
|
||||
},
|
||||
"effect": {
|
||||
"type": "string",
|
||||
"enum": ["allow", "deny"],
|
||||
"default": "allow"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PermissionCondition": {
|
||||
"type": "object",
|
||||
"description": "Condition for permission evaluation",
|
||||
"required": ["type", "value"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["attribute", "context", "time", "resource_owner", "tenant"]
|
||||
},
|
||||
"attribute": {
|
||||
"type": "string"
|
||||
},
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"enum": ["eq", "neq", "in", "not_in", "contains", "gt", "lt", "gte", "lte"]
|
||||
},
|
||||
"value": {}
|
||||
}
|
||||
},
|
||||
"TenancyHeader": {
|
||||
"type": "object",
|
||||
"description": "Multi-tenancy header specification",
|
||||
"required": ["header_name", "required"],
|
||||
"properties": {
|
||||
"header_name": {
|
||||
"type": "string",
|
||||
"default": "X-Tenant-ID"
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": ["uuid", "slug", "custom"]
|
||||
},
|
||||
"pattern": {
|
||||
"type": "string"
|
||||
},
|
||||
"max_length": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default_value": {
|
||||
"type": "string",
|
||||
"description": "Default tenant if header not provided"
|
||||
},
|
||||
"extract_from_token": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Allow extraction from JWT token"
|
||||
},
|
||||
"token_claim": {
|
||||
"type": "string",
|
||||
"default": "tenant_id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PrivacyControl": {
|
||||
"type": "object",
|
||||
"description": "Privacy control configuration",
|
||||
"required": ["control_id", "name"],
|
||||
"properties": {
|
||||
"control_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"data_classification": {
|
||||
"type": "string",
|
||||
"enum": ["public", "internal", "confidential", "restricted", "pii", "phi"]
|
||||
},
|
||||
"redaction_policy": {
|
||||
"$ref": "#/definitions/RedactionPolicy"
|
||||
},
|
||||
"retention_policy": {
|
||||
"$ref": "#/definitions/RetentionPolicy"
|
||||
},
|
||||
"consent_required": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"audit_access": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"RedactionPolicy": {
|
||||
"type": "object",
|
||||
"description": "Data redaction policy",
|
||||
"properties": {
|
||||
"policy_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RedactionRule"
|
||||
}
|
||||
},
|
||||
"default_action": {
|
||||
"type": "string",
|
||||
"enum": ["pass", "mask", "hash", "remove"],
|
||||
"default": "pass"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RedactionRule": {
|
||||
"type": "object",
|
||||
"description": "Individual redaction rule",
|
||||
"required": ["field_pattern", "action"],
|
||||
"properties": {
|
||||
"rule_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pattern": {
|
||||
"type": "string",
|
||||
"description": "JSON path or field name pattern"
|
||||
},
|
||||
"data_type": {
|
||||
"type": "string",
|
||||
"enum": ["email", "phone", "ssn", "ip_address", "credit_card", "name", "address", "custom"]
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["mask", "hash", "remove", "tokenize", "truncate"]
|
||||
},
|
||||
"mask_char": {
|
||||
"type": "string",
|
||||
"default": "*"
|
||||
},
|
||||
"preserve_chars": {
|
||||
"type": "integer",
|
||||
"description": "Number of chars to preserve (e.g., last 4 of phone)"
|
||||
},
|
||||
"hash_algorithm": {
|
||||
"type": "string",
|
||||
"enum": ["sha256", "sha512", "hmac-sha256"]
|
||||
},
|
||||
"conditions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionCondition"
|
||||
},
|
||||
"description": "Conditions when to apply redaction"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RetentionPolicy": {
|
||||
"type": "object",
|
||||
"description": "Data retention policy",
|
||||
"properties": {
|
||||
"policy_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"default_retention_days": {
|
||||
"type": "integer"
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"retention_days": {
|
||||
"type": "integer"
|
||||
},
|
||||
"action_on_expiry": {
|
||||
"type": "string",
|
||||
"enum": ["delete", "archive", "anonymize"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"legal_hold_enabled": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"DebugOptIn": {
|
||||
"type": "object",
|
||||
"description": "Debug/diagnostic opt-in configuration",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"opt_in_required": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"scopes_required": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Scopes required to access debug data"
|
||||
},
|
||||
"data_collected": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"retention_hours": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"redaction_applied": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ScopeMatrix": {
|
||||
"type": "object",
|
||||
"description": "Complete scope matrix",
|
||||
"required": ["version", "scopes"],
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Scope"
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Role"
|
||||
}
|
||||
},
|
||||
"tenancy_config": {
|
||||
"$ref": "#/definitions/TenancyHeader"
|
||||
},
|
||||
"privacy_controls": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PrivacyControl"
|
||||
}
|
||||
},
|
||||
"debug_config": {
|
||||
"$ref": "#/definitions/DebugOptIn"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"matrix": {
|
||||
"$ref": "#/definitions/ScopeMatrix"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"matrix": {
|
||||
"version": "2025.10.0",
|
||||
"updated_at": "2025-12-06T10:00:00Z",
|
||||
"scopes": [
|
||||
{
|
||||
"scope_id": "findings:read",
|
||||
"name": "Read Findings",
|
||||
"description": "Read vulnerability findings",
|
||||
"category": "read",
|
||||
"resource": "findings",
|
||||
"actions": ["read", "list"],
|
||||
"audit_level": "basic"
|
||||
},
|
||||
{
|
||||
"scope_id": "findings:write",
|
||||
"name": "Write Findings",
|
||||
"description": "Create and update findings",
|
||||
"category": "write",
|
||||
"resource": "findings",
|
||||
"actions": ["create", "update"],
|
||||
"audit_level": "detailed",
|
||||
"parent_scope": "findings:read"
|
||||
},
|
||||
{
|
||||
"scope_id": "findings:delete",
|
||||
"name": "Delete Findings",
|
||||
"description": "Delete findings (requires approval)",
|
||||
"category": "admin",
|
||||
"resource": "findings",
|
||||
"actions": ["delete"],
|
||||
"requires_mfa": true,
|
||||
"audit_level": "full",
|
||||
"parent_scope": "findings:write"
|
||||
},
|
||||
{
|
||||
"scope_id": "scanner:execute",
|
||||
"name": "Execute Scans",
|
||||
"description": "Initiate container scans",
|
||||
"category": "write",
|
||||
"resource": "scanner",
|
||||
"actions": ["execute"],
|
||||
"audit_level": "detailed"
|
||||
},
|
||||
{
|
||||
"scope_id": "risk:read",
|
||||
"name": "Read Risk Scores",
|
||||
"description": "Access risk scoring data",
|
||||
"category": "read",
|
||||
"resource": "risk",
|
||||
"actions": ["read", "list"],
|
||||
"audit_level": "basic"
|
||||
},
|
||||
{
|
||||
"scope_id": "admin:*",
|
||||
"name": "Full Admin Access",
|
||||
"description": "Full administrative access",
|
||||
"category": "admin",
|
||||
"resource": "*",
|
||||
"actions": ["create", "read", "update", "delete", "list", "execute"],
|
||||
"requires_mfa": true,
|
||||
"sensitive": true,
|
||||
"audit_level": "full"
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
{
|
||||
"role_id": "viewer",
|
||||
"name": "Viewer",
|
||||
"description": "Read-only access to findings and risk data",
|
||||
"type": "tenant",
|
||||
"scopes": ["findings:read", "risk:read"]
|
||||
},
|
||||
{
|
||||
"role_id": "analyst",
|
||||
"name": "Security Analyst",
|
||||
"description": "Can view and update findings, execute scans",
|
||||
"type": "tenant",
|
||||
"scopes": ["findings:read", "findings:write", "scanner:execute", "risk:read"],
|
||||
"inherits_from": ["viewer"]
|
||||
},
|
||||
{
|
||||
"role_id": "admin",
|
||||
"name": "Tenant Admin",
|
||||
"description": "Full tenant administrative access",
|
||||
"type": "tenant",
|
||||
"scopes": ["findings:read", "findings:write", "findings:delete", "scanner:execute", "risk:read", "risk:write"],
|
||||
"inherits_from": ["analyst"],
|
||||
"restrictions": {
|
||||
"max_sessions": 3,
|
||||
"require_approval": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"role_id": "super_admin",
|
||||
"name": "Super Admin",
|
||||
"description": "System-wide administrative access",
|
||||
"type": "system",
|
||||
"scopes": ["admin:*"],
|
||||
"restrictions": {
|
||||
"max_sessions": 1,
|
||||
"require_approval": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"tenancy_config": {
|
||||
"header_name": "X-Tenant-ID",
|
||||
"required": true,
|
||||
"validation": {
|
||||
"format": "uuid"
|
||||
},
|
||||
"extract_from_token": true,
|
||||
"token_claim": "tenant_id"
|
||||
},
|
||||
"privacy_controls": [
|
||||
{
|
||||
"control_id": "pii-protection",
|
||||
"name": "PII Protection",
|
||||
"description": "Protection for personally identifiable information",
|
||||
"data_classification": "pii",
|
||||
"redaction_policy": {
|
||||
"policy_id": "pii-redaction",
|
||||
"name": "PII Redaction",
|
||||
"rules": [
|
||||
{
|
||||
"rule_id": "email-mask",
|
||||
"field_pattern": "$.**.email",
|
||||
"data_type": "email",
|
||||
"action": "mask",
|
||||
"preserve_chars": 3
|
||||
},
|
||||
{
|
||||
"rule_id": "ip-hash",
|
||||
"field_pattern": "$.**.ip_address",
|
||||
"data_type": "ip_address",
|
||||
"action": "hash",
|
||||
"hash_algorithm": "sha256"
|
||||
}
|
||||
],
|
||||
"default_action": "pass"
|
||||
},
|
||||
"retention_policy": {
|
||||
"policy_id": "pii-retention",
|
||||
"name": "PII Retention",
|
||||
"default_retention_days": 90,
|
||||
"rules": [
|
||||
{
|
||||
"data_type": "audit_logs",
|
||||
"retention_days": 365,
|
||||
"action_on_expiry": "archive"
|
||||
}
|
||||
]
|
||||
},
|
||||
"consent_required": true,
|
||||
"audit_access": true
|
||||
}
|
||||
],
|
||||
"debug_config": {
|
||||
"enabled": true,
|
||||
"opt_in_required": true,
|
||||
"scopes_required": ["admin:*"],
|
||||
"data_collected": [
|
||||
{
|
||||
"data_type": "request_traces",
|
||||
"description": "HTTP request/response traces for debugging",
|
||||
"retention_hours": 24
|
||||
},
|
||||
{
|
||||
"data_type": "performance_metrics",
|
||||
"description": "Detailed performance timing",
|
||||
"retention_hours": 72
|
||||
}
|
||||
],
|
||||
"redaction_applied": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user