6.4 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	SCHED-MODELS-20-001 — Policy Engine Run DTOs
Status: 2025-10-26 — Complete
Defines the scheduler contracts that Policy Engine (Epic 2) relies on for orchestration, simulation, and explainability. DTOs serialize with CanonicalJsonSerializer to guarantee deterministic ordering, enabling replay and signed artefacts.
PolicyRunRequest — scheduler.policy-run-request@1
Posted by CLI/UI or the orchestrator to enqueue a run. Canonical sample lives at samples/api/scheduler/policy-run-request.json.
{
  "schemaVersion": "scheduler.policy-run-request@1",
  "tenantId": "default",
  "policyId": "P-7",
  "policyVersion": 4,
  "mode": "incremental",               // full | incremental | simulate
  "priority": "normal",                // normal | high | emergency
  "runId": "run:P-7:2025-10-26:auto",  // optional idempotency key
  "queuedAt": "2025-10-26T14:05:00+00:00",
  "requestedBy": "user:cli",
  "correlationId": "req-...",
  "metadata": {"source": "stella policy run", "trigger": "cli"},
  "inputs": {
    "sbomSet": ["sbom:S-318", "sbom:S-42"],   // sorted uniques
    "advisoryCursor": "2025-10-26T13:59:00+00:00",
    "vexCursor": "2025-10-26T13:58:30+00:00",
    "environment": {"exposure": "internet", "sealed": false},
    "captureExplain": true
  }
}
- Environment values accept any JSON primitive/object; keys normalise to lowercase for deterministic hashing.
- metadatais optional contextual breadcrumbs (lowercased keys). Use it for orchestrator provenance or offline bundle identifiers.
PolicyRunStatus — scheduler.policy-run-status@1
Captured in policy_runs collection and returned by run status APIs. Sample: samples/api/scheduler/policy-run-status.json.
{
  "schemaVersion": "scheduler.policy-run-status@1",
  "runId": "run:P-7:2025-10-26:auto",
  "tenantId": "default",
  "policyId": "P-7",
  "policyVersion": 4,
  "mode": "incremental",
  "status": "succeeded",          // queued|running|succeeded|failed|canceled|replay_pending
  "priority": "normal",
  "queuedAt": "2025-10-26T14:05:00+00:00",
  "startedAt": "2025-10-26T14:05:11+00:00",
  "finishedAt": "2025-10-26T14:06:01+00:00",
  "determinismHash": "sha256:...", // optional until run completes
  "traceId": "01HE0BJX5S4T9YCN6ZT0",
  "metadata": {"orchestrator": "scheduler", "sbombatchhash": "sha256:..."},
  "stats": {
    "components": 1742,
    "rulesFired": 68023,
    "findingsWritten": 4321,
    "vexOverrides": 210,
    "quieted": 12,
    "durationSeconds": 50.8
  },
  "inputs": { ... }  // same schema as request
}
- determinismHashmust be a- sha256:digest combining ordered input digests + policy digest.
- attempts(not shown) increases per retry.
- Error responses populate errorCode(ERR_POL_00x) anderrormessage; omitted when successful.
PolicyDiffSummary — scheduler.policy-diff-summary@1
Returned by simulation APIs; referenced by CLI/UI diff visualisations. Sample: samples/api/scheduler/policy-diff-summary.json.
{
  "schemaVersion": "scheduler.policy-diff-summary@1",
  "added": 12,
  "removed": 8,
  "unchanged": 657,
  "bySeverity": {
    "critical": {"up": 1},
    "high": {"up": 3, "down": 4},
    "medium": {"up": 2, "down": 1}
  },
  "ruleHits": [
    {"ruleId": "rule-block-critical", "ruleName": "Block Critical Findings", "up": 1},
    {"ruleId": "rule-quiet-low", "ruleName": "Quiet Low Risk", "down": 2}
  ]
}
- Severity bucket keys normalise to camelCase for JSON determinism across CLI/UI consumers.
- Zero-valued counts (down/up) are omitted to keep payloads compact.
- ruleHitssorts by- ruleIdto keep diff heatmaps deterministic.
PolicyExplainTrace — scheduler.policy-explain-trace@1
Canonical explain tree embedded in findings explainers and exported bundles. Sample: samples/api/scheduler/policy-explain-trace.json.
{
  "schemaVersion": "scheduler.policy-explain-trace@1",
  "findingId": "finding:sbom:S-42/pkg:npm/lodash@4.17.21",
  "policyId": "P-7",
  "policyVersion": 4,
  "tenantId": "default",
  "runId": "run:P-7:2025-10-26:auto",
  "evaluatedAt": "2025-10-26T14:06:01+00:00",
  "verdict": {"status": "blocked", "severity": "critical", "score": 19.5},
  "ruleChain": [
    {"ruleId": "rule-allow-known", "action": "allow", "decision": "skipped"},
    {"ruleId": "rule-block-critical", "action": "block", "decision": "matched", "score": 19.5}
  ],
  "evidence": [
    {"type": "advisory", "reference": "CVE-2025-12345", "source": "nvd", "status": "affected", "weight": 1, "metadata": {}},
    {"type": "vex", "reference": "vex:ghsa-2025-0001", "source": "vendor", "status": "not_affected", "weight": 0.5}
  ],
  "vexImpacts": [
    {"statementId": "vex:ghsa-2025-0001", "provider": "vendor", "status": "not_affected", "accepted": true}
  ],
  "history": [
    {"status": "blocked", "occurredAt": "2025-10-26T14:06:01+00:00", "actor": "policy-engine"}
  ],
  "metadata": {"componentpurl": "pkg:npm/lodash@4.17.21", "sbomid": "sbom:S-42", "traceid": "01HE0BJX5S4T9YCN6ZT0"}
}
- Rule chain preserves execution order; evidence & VEX arrays sort for deterministic outputs.
- Evidence metadata is always emitted (empty object when no attributes) so clients can merge annotations deterministically.
- Metadata keys lower-case for consistent lookups (componentpurl,traceid, etc.).
- verdict.statususes- passed|warned|blocked|quieted|ignoredreflecting final policy decision.
Compliance Checklist
| Item | Owner | Status | Notes | 
|---|---|---|---|
| Canonical samples committed (`policy-run-request | status | diff-summary | explain-trace`) | 
| DTOs documented here and linked from /docs/policy/runs.mdchecklist | Scheduler Models Guild | ☑ 2025-10-26 | Added Run DTO schema section. | 
| Serializer ensures deterministic ordering for new types | Scheduler Models Guild | ☑ 2025-10-26 | CanonicalJsonSerializerupdated with property order + converters. | 
| Tests cover DTO validation and sample fixtures | Scheduler Models Guild | ☑ 2025-10-26 | PolicyRunModelsTests+ extendedSamplePayloadTests. | 
| Scheduler guilds notified (Models, Worker, WebService) | Scheduler Models Guild | ☑ 2025-10-26 | Posted in #scheduler-guildwith sample links. | 
Last updated: 2025-10-26.