# Policy system The policy system turns evidence into deterministic findings and explanations. Policies are authored in the Stella Policy DSL, compiled to canonical IR, and executed in the Policy Engine. Purpose and scope - Convert raw evidence into effective findings with explainability. - Keep decisions deterministic and reproducible across environments. - Support offline execution with content-addressed inputs. Inputs and signals - SBOM inventory and usage data from Scanner. - Advisory observations and linksets from Concelier. - VEX observations and linksets from Excititor. - Reachability graphs and runtime traces from Signals. - Trust, entropy, and uncertainty signals. DSL structure (stella-dsl@1) - metadata: optional descriptive fields surfaced in UI and CLI. - profile blocks: maps and scalar adjustments for severity or trust. - rule blocks: when-then logic with optional priority. - settings: evaluation toggles (shadow, defaults). Example (short) ```dsl policy "Baseline" syntax "stella-dsl@1" { metadata { description = "VEX first" } profile severity { map vendor_weight { source "OSV" => 0.0; } } rule vex_override priority 10 { when vex.any(status == "not_affected") then status := "not_affected" because "VEX claim" } } ``` Evaluation model - The engine evaluates tuples of (component, advisory, vex[]). - Rules execute by ascending priority; ties resolve by lexical order. - Actions set status, severity, and annotations; missing evidence yields unknown. - Suppressions and overrides must be explicit and explained. Outputs and explainability - effective findings with status, severity, and confidence fields. - explain trace with rule id, because text, and evidence hashes. - policy hash and input hashes recorded for replay and audit. Lifecycle and gates 1) Draft with shadow mode enabled. 2) Lint and simulate with coverage fixtures. 3) Review and approve with Authority scopes. 4) Publish with attestation and optional ledger anchor. 5) Promote to environments and activate runs. 6) Archive and retain audit history. Minimum gates for publish - Lint is clean. - Simulation diff is reviewed and attached. - Coverage fixtures pass in CI and shadow runs exist. - Reason and ticket metadata are provided for approvals. Fixtures and simulation - Fixtures live under tests/policy//cases/. - Each case includes inputs and expected status or severity. - Fixtures must include unknown reachability and VEX conflict cases. Fixture example (short) ```json { "caseId": "vex-not-affected", "sbom": { "components": [{ "purl": "pkg:npm/lodash@4.17.21" }] }, "advisories": [{ "id": "CVE-2024-1234", "purl": "pkg:npm/lodash@4.17.21" }], "vex": [{ "status": "not_affected", "justification": "component_not_present" }], "signals": { "reachability": { "state": "unknown" } }, "expect": { "status": "not_affected" } } ``` Simulation output (summary) - policyHash: canonical hash of the policy IR. - inputsHash: canonical hash of inputs and fixtures. - findingsCount: total findings produced. - determinismHash: stable hash for replay comparisons. Governance - Scopes include policy:author, policy:review, policy:approve, policy:publish, policy:promote, policy:operate, policy:audit. - Two-person approval is recommended for publish and promote. - Authors should not approve their own submissions. - Approval evidence and run history are immutable and exportable. - Offline governance follows the same workflow with signed bundles. Determinism and offline - Canonical JSON and stable ordering for IR and outputs. - No network calls or non-deterministic functions in evaluation. - Offline kits bundle policies, attestations, and fixtures. Testing - stella policy lint, simulate, and test must run in CI. - Coverage fixtures should include reachability unknown and VEX conflicts. Related references - docs/policy/overview.md - docs/policy/dsl.md - docs/policy/lifecycle.md - docs/policy/exception-effects.md - docs/60_POLICY_TEMPLATES.md