Skip to content

Backlog

Actionable backlog for Quorum (quorum-sec-scan, v0.8.3) derived from the official roadmap (README.md §Roadmap and DESIGN.md §13) and from the gaps observed in the source code (known limitations, items not yet implemented, and opportunities for hardening and UX). The backlog is organized hierarchically Epic → Feature → User Story → Task → Subtask, with Acceptance Criteria, Priority (MoSCoW), Estimate (story points, Fibonacci scale) and Dependencies.

Revision v0.8.3 — 2026-07-04. Much of the backlog written in v0.2.3 has already been delivered between v0.3 and v0.8.3: new adapters (Polaris, kube-score, terrascan, tfsec, regula, Conftest), misconfig/K8s consensus via a crosswalk derived from real output, observability (--metrics Prometheus textfile and --log-format json), supply-chain hardening (pin by @sha256, checksum verification, SLSA attestation + SPDX SBOM of the image itself), per-scanner passthrough and DoS caps, and — new in v0.8.3 — the opt-in advisory layer (--advice: curated remediation + OWASP references, a digest-pinned RAG corpus, and an opt-in local/remote LLM advisor with verify-the-fix). Delivered items are marked ✅ Delivered and kept here only for traceability; the remaining work (RBAC in consensus, more crosswalk, Dockle peer, Syft/SBOM of the target, CLI UX, image profiles) continues as active backlog.

This document describes planned/proposed work. The as-is state of v0.8.3 is documented in 01-visao-geral.md and 10-infraestrutura.md. Items marked "future proposal" and without do not exist yet in the code; they are backlog.

Verified code references: cmd/quorum/scan.go, internal/cache/store.go, internal/adapter/ (12 adapters), internal/report/, internal/enrich/, internal/rag/, internal/advisor/, internal/evals/, crosswalk/, knowledge/, DESIGN.md, README.md.


1. Backlog conventions

1.1 Hierarchy

flowchart LR
    E[Epic] --> F[Feature]
    F --> US[User Story]
    US --> T[Task]
    T --> ST[Subtask]
    US -.-> AC[Acceptance Criteria]
Level Definition in Quorum Example
Epic Product objective spanning several packages/releases "Persistent alias cache"
Feature Deliverable capability within an Epic "Cache with TTL and pruning"
User Story A user's need, in the As a … I want … so that … format see §4+
Task Technical unit of implementation "Add expiresAt field to the cache record"
Subtask Concrete step inside a Task "Migrate the JSON schema v1→v2"

1.2 Priority — MoSCoW

Code Meaning Usage criterion
M (Must) Required for the next minor Closes a roadmap gap or a security risk
S (Should) Important, but does not block the release High value, with an acceptable workaround
C (Could) Desirable if there is slack Incremental improvement
W (Won't, now) Deliberately out of scope N/A items (see §14) or a separate future product

1.3 Estimate — story points (Fibonacci)

1, 2, 3, 5, 8, 13, 21. 1 = trivial localized change; 21 = a whole epic that must be broken down before entering a sprint. Points are relative effort, not hours.

1.4 Status legend (v0.8.3)

Mark Meaning
✅ Delivered Already exists in the v0.8.3 code (verified in the source). Kept for traceability.
◑ Partial Part of the feature is delivered; the described slice remains.
☐ Pending Not yet implemented; active backlog.

1.5 Definition of Done (DoD) — applies to every User Story

  • [ ] Code follows the canonical interface (adapters do not compute correlationKeyDESIGN.md §5).
  • [ ] Unit tests covering the happy path and graceful degradation.
  • [ ] For adapters: contract test against a versioned fixture in internal/adapter/testdata.
  • [ ] make test, make vet and make build green (coverage verified in CI).
  • [ ] Documentation updated (README + relevant doc in docs/; MkDocs Material site on GitHub Pages).
  • [ ] Principle preserved: false split > false merge; "0 findings is not proof of safety".
  • [ ] No regression of correlationKey/Fingerprint determinism.
  • [ ] New/changed crosswalk derived from real output of the scanners (not inferred) — crosswalk/.
  • [ ] Advisory layer stays presentation-only: no feature under --advice/--fix may alter correlationKey/fingerprint/confidence/aggregated severity or the fail-on gate — without --advice the output is byte-identical (DESIGN.md §13, 21-proposta-ia.md).

2. Epic map

flowchart TB
    subgraph done["Delivered (v0.3 → v0.8.3)"]
        E1d[E1 · Adapters ✅ 12 scanners]
        E2d[E2 · Observability ✅ metrics+log json]
        E6d[E6 · Supply chain ✅ pin+SBOM+attestation]
        E10d[E10 · Advisory layer ✅ --advice/--fix]
    end
    subgraph now["Short term (Must/Should)"]
        E5[E5 · Cache TTL/pruning]
        E4[E4 · Policy gate over findings]
        E7[E7 · UX / CLI]
    end
    subgraph mid["Medium term (Should/Could)"]
        E1r[E1 · Dockle peer + Syft]
        E3[E3 · SBOM export + HTML + SARIF++]
        E8[E8 · Image profiles / templates]
    end
    subgraph future["Future / N/A"]
        E9[E9 · Runtime security - separate product]
    end

    E1r --> E3
    E4 --> E3
    E5 --> E2d
Epic Theme Origin Status v0.8.3 Remaining priority
E1 Adapters (12 total; missing Dockle peer and Syft/SBOM of the target) Roadmap v0.3/v1.0; internal/adapter/ ✅ Polaris, kube-score, terrascan, tfsec, regula, Conftest delivered Should/Could
E2 Observability (structured logs, metrics, JSON run summary) Original gap --metrics and --log-format json delivered; run-summary.json missing Should
E3 Target SBOM export and reports (HTML, enriched SARIF) Roadmap; format gap ☐ pending (the image SBOM already exists in the supply chain) Should/Could
E4 Policy-as-code (user Rego; gate over findings) Roadmap v1.0 ◑ Conftest runs the user's Rego (./policy); gate over findings missing Should
E5 Persistent cache (TTL, pruning, findings/SBOM cache) Roadmap v1.0; internal/cache/store.go schemaVersion + 0600 perm delivered; TTL/pruning missing Must
E6 Hardening/supply chain (pin by digest, image SBOM, SLSA) DESIGN.md §12/§14 ✅ pin @sha256 + checksum + SLSA/SPDX SBOM attestation delivered (incl. knowledge-pack attestation) Should (RO runtime remains)
E7 UX / CLI (TTY output, --baseline-write, explain, profiles) UX gap ☐ pending Should/Could
E8 Action / distribution (image profiles, versioned action) Roadmap; action.yml ◑ action hardened (cosign verify, socket, auto v0, advisory inputs); profiles missing Should/Could
E9 Runtime security (Falco/Tetragon) DESIGN.md §2/§13out of scope Won't (now) Won't
E10 Advisory layer (--advice/--fix, RAG, local/remote LLM) 21-proposta-ia.md; Phases 0–3 ✅ Delivered (opt-in, presentation-only, off by default) Could (deeper corpus/evals)

3. Prioritized summary (portfolio view)

ID Epic Feature Status MoSCoW SP Dependencies
F-1.1 E1 Polaris adapter (K8s posture) ✅ Delivered M 8
F-1.2 E1 Conftest/OPA adapter (policy-as-code) ✅ Delivered S 13 F-4.1
F-1.3 E1 Syft adapter (target SBOM) ☐ Pending S 8
F-1.4 E1 Hadolint adapter (Dockle peer) ☐ Pending C 5
F-2.1 E2 Structured logs (JSON) with level ✅ Delivered S 5
F-2.2 E2 run-summary.json machine-readable ☐ Pending S 5
F-2.3 E2 Metrics (Prometheus textfile / OTel) ◑ Partial C 8 F-2.1
F-3.1 E3 Target SBOM export (CycloneDX/SPDX) ☐ Pending S 8 F-1.3
F-3.2 E3 Static HTML report ☐ Pending C 8
F-3.3 E3 Enrich SARIF (help, tags, security-severity) ☐ Pending S 3
F-4.1 E4 Policy-as-code layer (user Rego) ◑ Partial S 13
F-4.2 E4 Declarative gate policy (quorum.policy.yaml) ☐ Pending C 8 F-4.1
F-5.1 E5 Alias cache with TTL + pruning ◑ Partial M 5
F-5.2 E5 SBOM/findings cache by digest ☐ Pending C 13 F-1.3
F-6.1 E6 Pin scanners by @sha256 + verification ✅ Delivered M 8
F-6.2 E6 SBOM and attestation of the Quorum image itself ✅ Delivered S 5
F-6.3 E6 Container runtime hardening (rootless, RO FS) ☐ Pending S 5
F-6.4 E6 Knowledge-pack build-provenance attestation ✅ Delivered S 3 F-10.2
F-7.1 E7 Colored TTY output + readable table ☐ Pending S 5
F-7.2 E7 quorum explain <fingerprint> ☐ Pending C 5 F-2.2
F-7.3 E7 --baseline-write mode (generate baseline) ☐ Pending S 3
F-8.1 E8 Image profiles :sca/:iac/:k8s ☐ Pending S 8 F-6.1
F-8.2 E8 Rich Action outputs + GH cache ◑ Partial S 5
F-8.3 E8 Extended GitLab/Azure/Jenkins templates ☐ Pending C 5
F-10.1 E10 Deterministic enrichment (remediation + OWASP refs) ✅ Delivered S 8
F-10.2 E10 RAG-as-artifact (digest-pinned OWASP corpus) ✅ Delivered S 8
F-10.3 E10 Local LLM advisor + --fix=suggest (verify-the-fix) ✅ Delivered C 13 F-10.1
F-10.4 E10 Remote provider (egress-gated, refuses --fix) ✅ Delivered C 8 F-10.3
F-10.5 E10 Advisory metrics + evals harness ✅ Delivered S 5 F-10.1
F-K.1 E1 RBAC in consensus (second engine with cluster context) ☐ Pending C 13
F-X.1 E1 Extend crosswalk coverage (remaining top-N controls) ☐ Pending S 8

Delivered through v0.8.3: F-1.1, F-1.2, F-2.1, F-6.1, F-6.2, F-6.4, F-10.1–F-10.5 (~76 SP) + partials (F-2.3, F-4.1, F-5.1, F-8.2). Remaining (M+S+C): ~90 SP. W items (E9) do not score — they are a separate product.


4. Epic E1 — Adapters

Goal: grow the scanner pool while keeping the Adapter interface (Name/Version/Supports/Capabilities/Run) and the per-fixture contract test (internal/adapter/adapter.go, DESIGN.md §5). Invariant: the new adapter emits canonical model.Finding and does not compute correlationKey.

State v0.8.3 — 12 registered adapters (init()→Register in internal/adapter/): trivy, grype (VULN/SCA), checkov, kics, terrascan, tfsec, regula, conftest (MISCONFIG/IaC), kubescape, polaris, kube-score (K8S_POSTURE), dockle (IMG_HARDENING). misconfig/K8s consensus was enabled by a crosswalk derived from real output (crosswalk/aws.yaml, azure.yaml, gcp.yaml, k8s.yaml) — principle false split > false merge.

Feature F-1.1 — Polaris adapter (K8s posture) · ✅ Delivered · M · 8 SP

Status: ✅ Delivered. internal/adapter/polaris.go implements Adapter with Capabilities → model.TypeK8sPosture (target k8s). The crosswalk crosswalk/k8s.yaml (kubescape C-#### hub) correlates kubescape × polaris × kube-score on controls such as privilege-escalation, privileged, non-root, CPU/mem limits, probes, read-only-fs, linux-hardening, automount-SA, network-policy, host-network, host-PID/IPC, capabilities and secrets.

User Story US-1.1.1 — ✅ met

As a platform engineer validating Kubernetes manifests, I want Quorum to run Polaris alongside Kubescape, so that the K8s posture has consensus across engines (detectionCount ≥ 2).

Acceptance Criteria

  • [x] quorum list-scanners shows polaris with type K8S_POSTURE and target k8s.
  • [x] quorum scan ./k8s --type k8s --scanners kubescape,polaris,kube-score produces, for a manifest with elevated privilege, a MergedFinding with detectedBy from multiple engines and detectionCount ≥ 2.
  • [x] Polaris severity is normalized by the single table (DESIGN.md §10).
  • [x] Crosswalk maps the Polaris check → canonicalControl (C-#### hub; category as fallback).
  • [x] Polaris absent from PATH → status unavailable (scan does not fail).
  • [x] Contract test against a versioned fixture in testdata.

Note: Polaris also supports target repo (Supports returns true for TargetRepo), but the consensus capability is K8S_POSTURE.


Feature F-1.2 — Conftest/OPA adapter · ✅ Delivered · S · 13 SP

Status: ✅ Delivered. internal/adapter/conftest.go evaluates the user's Rego (by default in ./policy, or via QUORUM_CONFTEST_ARGS="--policy <dir>"). Without policies, the adapter reports error on purpose — policy-as-code is opt-in and Quorum does not bundle opinionated policies (DESIGN.md §2). Violations become MISCONFIG Findings (isolated with RuleID: "policy", since Rego rules have no stable id).

User Story US-1.2.1 — ✅ met

As an AppSec team with our own Rego policies, I want to run my OPA/Conftest policies through Quorum, so that policy violations appear in the same consensus report.

Acceptance Criteria

  • [x] --scanners conftest runs Rego policies over the repo/k8s target.
  • [x] Violations become MISCONFIG-type Findings (with isolated RuleID policy).
  • [x] The user brings their own rules via ./policy (or QUORUM_CONFTEST_ARGS) — no bundled policy.
  • [x] No policies configured → adapter error (expected, opt-in behavior), without corrupting the rest.

Remaining (slice of F-4): decide whether policy violations deserve their own POLICY type (today reuses MISCONFIG) and enable mode B (policy over []MergedFinding for the gate) — see F-4.


Feature F-1.3 — Syft adapter (target SBOM) · ☐ Pending · S · 8 SP

Status: ☐ Pending. Syft is already used in the supply chain (GoReleaser/BuildKit and actions/attest-sbom generate an SPDX SBOM of the image/binaries themselves — see F-6.2), but there is no adapter producing an SBOM of the scanned target consumable by the pipeline (PURLs, cache, export).

User Story US-1.3.1

As an engineer who needs a dependency inventory, I want Quorum to generate an SBOM of the target via Syft, so that I have the reusable base component for SCA, SBOM export and cache.

Acceptance Criteria

  • [ ] Syft produces an internal inventory (PURLs) consumable by the pipeline.
  • [ ] When enabled, it feeds the SBOM export (F-3.1) and the cache by digest (F-5.2).
  • [ ] Emits no "findings" by itself — it is a data source, not a detector (own status in the summary).

Dependencies: none; enables F-3.1 and F-5.2.


Feature F-1.4 — Hadolint adapter (Dockle peer) · ☐ Pending · C · 5 SP

Status: ☐ Pending. Today dockle is single-engine for IMG_HARDENING ("no peer for consensus yet", README.md §scanners). A second image/Dockerfile engine would allow detectionCount ≥ 2 in that family.

User Story US-1.4.1

As a developer maintaining Dockerfiles, I want Dockerfile linting via Hadolint in Quorum, so that image-build issues enter the IMG_HARDENING/MISCONFIG consensus.

Acceptance Criteria

  • [ ] hadolint registered; targets repo (detects Dockerfile*).
  • [ ] DL**** rules mapped to canonicalControl when equivalent to Dockle's CIS-DI controls (potential detectionCount ≥ 2 — the peer missing today).
  • [ ] Crosswalk entries derived from real output (Hadolint × Dockle on the same target).
  • [ ] Contract test with a fixture of Hadolint's JSON output.

Feature F-K.1 — RBAC in consensus · ☐ Pending · C · 13 SP

Status: ☐ Pending (documented limitation). RBAC remains single-engine: the crosswalk crosswalk/k8s.yaml leaves the kubescape RBAC controls (C-0035/C-0185/C-0272/…) unmapped on purpose, because on static manifests they typically require live-cluster context and no second engine (polaris/kube-score) fires on the same object — forcing a merge would be a false merge. Preserves the false split > false merge principle.

User Story US-K.1.1

As a K8s security engineer, I want consensus on RBAC findings, so that RBAC violations earn detectionCount ≥ 2 without a false merge.

Acceptance Criteria

  • [ ] A second engine with cluster context (or a live mode) fires on the same RBAC objects.
  • [ ] Overlap verified against real output before mapping in the crosswalk (not inferred).
  • [ ] Until verified overlap exists, RBAC stays single-engine and documented (no regression).

Note: 13 SP — depends on a scope decision (static scan vs. cluster context).


Feature F-X.1 — Extend crosswalk coverage · ☐ Pending · S · 8 SP

Status: ☐ Pending (managed debt). The crosswalk already covers a solid top-N derived from real output: cloud (AVD hub) — S3/IAM/EBS/SG/RDS/KMS/CloudTrail/VPC-flow-logs, Azure Storage/Key Vault, GCP bucket/firewall/SQL; K8s (C-#### hub) — see F-1.1; tfsec auto-correlates with trivy because it emits native AVD. The tail of controls remains to extend.

Acceptance Criteria

  • [ ] New mappings derived from real output of the scanners (evidence of overlap).
  • [ ] Each entry preserves false split > false merge (when in doubt, do not map).
  • [ ] Incremental coverage documented per provider/family.

5. Epic E2 — Observability

State v0.8.3: delivered --metrics <file> (Prometheus textfile, writeMetricsFile in cmd/quorum/scan.go + internal/report/metrics.go) and --log-format text|json. Under --advice, three extra metric families are also emitted: quorum_advice_enriched{kind=…}, quorum_advice_provider{provider} and quorum_advice_fix{stage=proposed|verified} (see E10). The human summary on stderr (printSummary) remains. Missing a structured run-summary.json.

Feature F-2.1 — Structured logs · ✅ Delivered · S · 5 SP

Status: ✅ Delivered. --log-format text|json (default text, backward-compatible with [quorum] …); an invalid value is rejected (invalid --log-format). --quiet still suppresses progress.

User Story US-2.1.1 — ✅ met

As a CI operator aggregating logs into a SIEM, I want JSON logs with level and fields, so that I can filter and alert on scan runs.

Acceptance Criteria

  • [x] Flag --log-format text|json (default text, backward-compatible).
  • [x] Orchestrator events (scanner start/stop/timeout/unavailable) emitted in the chosen format.
  • [x] --quiet still suppresses progress logs; errors always visible.
  • [x] No secrets in logs (redaction: trivy's Match is redacted; target/fingerprints/counts allowed).

Feature F-2.2 — run-summary.json machine-readable · ☐ Pending · S · 5 SP

Status: ☐ Pending. There is no structured per-run summary flag; the human printSummary remains the only consolidated per-scanner view.

User Story US-2.2.1

As a platform collecting metrics from N pipelines, I want a structured per-run summary file, so that dashboards consume per-scanner status and the severity rollup without parsing text.

Acceptance Criteria

  • [ ] Flag --summary-file run-summary.json writes: per-scanner {name,status,findings,duration,error}, mergedCount, multiDetected, per-severity rollup and elapsed.
  • [ ] The content mirrors exactly the current printSummary (single source of truth).
  • [ ] Absence of the flag = current behavior unchanged.

Dependencies: reuses orchestrator.Result (cmd/quorum/scan.go).

Feature F-2.3 — Metrics · ◑ Partial · C · 8 SP

Status: ◑ Partial. --metrics <file> already writes a Prometheus textfile (for node_exporter), including the advisory families when --advice is on. Missing the OTLP/OpenTelemetry variant via env.

User Story US-2.3.1

As an SRE, I want to export metrics via OpenTelemetry in addition to the Prometheus textfile, so that I track findings trends across runs on OTLP backends.

Acceptance Criteria

  • [x] Flag --metrics metrics.prom writes metrics in the node_exporter textfile format.
  • [ ] Alternative: OTLP endpoint via env (opt-in).
  • [x] Disabled by default; no network call without opt-in (respects offline-first).

Dependencies: F-2.1.


6. Epic E3 — SBOM export and reports

State v0.8.3: three reporters — SARIF/JSON/XML (internal/report/) — plus Prometheus metric writing. There is no SBOM export of the target, no HTML report, and no enriched SARIF. (The SBOM of the image itself already exists in the supply chain — see F-6.2.)

Feature F-3.1 — Target SBOM export (CycloneDX/SPDX) · ☐ Pending · S · 8 SP

User Story US-3.1.1

As the person responsible for supply-chain compliance, I want to export the target's SBOM in CycloneDX or SPDX, so that I meet regulatory requirements (e.g. EO 14028) with the same scan command.

Acceptance Criteria

  • [ ] --sbom cyclonedx|spdx + --sbom-output sbom.json generates the target's SBOM.
  • [ ] SBOM derived from Syft's inventory (F-1.3); PURLs consistent with the VULN findings.
  • [ ] Non-blocking operation: an SBOM failure does not bring down the main scan (logs and continues).

Dependencies: F-1.3.

Feature F-3.2 — Static HTML report · ☐ Pending · C · 8 SP

User Story US-3.2.1

As a tech lead sharing results on a PR, I want a single HTML report (no server), so that reviewers see consensus, confidence and per-scanner status without extra tools.

Acceptance Criteria

  • [ ] --format html -o report.html produces standalone HTML (no external JS, no network).
  • [ ] Shows a MergedFinding table ordered by severity and confidence, with detectedBy.
  • [ ] Includes the "0 findings is not proof of safety" warning and the per-scanner status.
  • [ ] Explicit N/A: it is not a web panel/daemon — it is a static artifact (see 13-ia.md for scope limits).

Feature F-3.3 — Enrich SARIF · ☐ Pending · S · 3 SP

Status: ☐ Pending. SARIF already preserves partialFingerprints (internal/report/sarif.go), but does not yet emit security-severity, help.text or tags per rule.

User Story US-3.3.1

As a GitHub code scanning user, I want SARIF to carry security-severity, help and tags per rule, so that triage in GitHub shows the correct severity and context.

Acceptance Criteria

  • [ ] rules[].properties["security-severity"] derived from CVSS/severity.
  • [ ] rules[].help.text with origin (detectedBy) and the canonical control link (AVD/CIS) when present.
  • [x] partialFingerprints preserved (no dedup regression — DESIGN.md §11).
  • [ ] Test updated in internal/report/report_test.go.

7. Epic E4 — Policy-as-code

Roadmap v1.0: "OPA/Conftest policy-as-code layer". Design principle: OPA/Conftest is not a "scanner", it is an optional layer where the user brings the rules (DESIGN.md §2).

Feature F-4.1 — Policy-as-code layer · ◑ Partial · S · 13 SP

Status: ◑ Partial. Mode A (Rego policy over the IaC/K8s target → violations become Findings) already exists via conftest (F-1.2): it loads the user's Rego from ./policy/QUORUM_CONFTEST_ARGS, no bundled policy, and degrades with status error without corrupting the report. Mode B is missing: evaluate policy over the []MergedFinding themselves to decide the gate.

User Story US-4.1.1

As a governance team, I want to evaluate Rego policies over the target and/or over Quorum's own findings, so that gate decisions follow our business rules, not just severity.

Acceptance Criteria

  • [x] Loads the user's Rego bundles (./policy / QUORUM_CONFTEST_ARGS; no bundled policy).
  • [x] Mode A: policy over the target (IaC/K8s) → violations become MISCONFIG Findings.
  • [ ] Mode B: policy over []MergedFinding → can decide the gate (e.g. "block if any finding has confidence ≥ 0.8 and severity ≥ HIGH").
  • [x] Graceful degradation: a policy-evaluation error → error status of the policy "scanner", without corrupting the rest of the report.

Dependencies: enables F-4.2. Note: mode B is the remaining slice of this feature.

Feature F-4.2 — Declarative gate policy · ☐ Pending · C · 8 SP

User Story US-4.2.1

As a maintainer, I want to declare the gate in quorum.policy.yaml (thresholds by type/severity/confidence), so that the blocking criterion is versioned and auditable, beyond the simple --fail-on.

Acceptance Criteria

  • [ ] Declarative YAML: rules like {type: VULN, minSeverity: HIGH, minConfidence: 0.7 → fail}.
  • [ ] Coexists with --fail-on/--min-severity (the flags keep working; the YAML refines).
  • [ ] Exit codes unchanged (0/1/2, README.md §Exit codes).

8. Epic E5 — Persistent cache

State v0.8.3: the persistent JSON alias cache (internal/cache/store.go) was hardened: aliases.json file with 0600 permission and schemaVersion (schema versioning), atomic and fault-tolerant flush (corrupted cache → empty cache). Remaining gaps: no TTL/entry expiration and no SBOM/findings cache by digest. (The advisory layer adds its own on-disk cache keyed by fingerprint+provider+model under --advice-cache — see F-10.3.)

Feature F-5.1 — Cache TTL + pruning · ◑ Partial · M · 5 SP

Status: ◑ Partial. schemaVersion and 0600 perm delivered (base for safe migration). Missing TTL/revalidation and the pruning subcommand.

User Story US-5.1.1

As a long-running CI user, I want alias entries to expire so the cache does not grow indefinitely, so that stale alias data is revalidated and the file stays small.

Acceptance Criteria

  • [x] Record versioned by schemaVersion (base for transparent migration).
  • [ ] Record carries fetchedAt; --cache-ttl 720h revalidates expired entries via OSV (respects --offline).
  • [x] Corrupted/unreadable cache still yields an empty cache (without breaking the scan — current invariant).
  • [ ] quorum cache prune removes expired entries.
Task SP Subtasks
T-5.1.1a · add fetchedAt to the record (schema already versioned) 2 struct with timestamp; migration via current schemaVersion; test
T-5.1.1b · TTL logic in alias.Resolver 1 consider expired before the hit; respect --offline
T-5.1.1c · cache prune subcommand 1 iterate and remove expired; log the count

Feature F-5.2 — SBOM/findings cache by digest · ☐ Pending · C · 13 SP

User Story US-5.2.1

As a pipeline that re-scans the same image by digest, I want to reuse cached SBOM/findings by the image sha256, so that re-scans are much faster when the content has not changed.

Acceptance Criteria

  • [ ] Cache key = target digest (image) or tree hash (repo).
  • [ ] --no-cache/cache miss recompute; deterministic result identical to a no-cache scan.
  • [ ] Invalidations: scanner version changes → invalidates (the version enters the key).

Dependencies: F-1.3 (Syft). Note: break down; risk of incorrect invalidation. 13 SP.


9. Epic E6 — Supply-chain hardening

State v0.8.3 — largely delivered. Dockerfile.full, .goreleaser.yaml and release.yml were hardened: bases pinned by @sha256; kubescape/tfsec/terrascan/regula/conftest verified by checksum; SLSA build-provenance attestation and SPDX SBOM (actions/attest-sbom) for the image and per-binary, plus BuildKit sbom: true; keyless cosign with retry; grype DB pre-cached with GRYPE_DB_VALIDATE_AGE=false (never expires); THIRD_PARTY_NOTICES.md. In v0.8.3 the knowledge pack + crosswalk also get their own build-provenance attestation each release (see F-6.4). Plus execution hardening: --output with filepath.Clean and 0600 perm; OSV id validated and url.PathEscape; argument injection refused (target starting with -); DoS caps (QUORUM_MAX_OUTPUT_BYTES = 512 MiB; QUORUM_MAX_TARGET_BYTES = 20 GiB); secret redaction.

Feature F-6.1 — Pin scanners by @sha256 + verification · ✅ Delivered · M · 8 SP

Status: ✅ Delivered. Bases pinned by @sha256; downloaded scanners verified by checksum (build fails on mismatch); grype DB pre-cached without expiration.

User Story US-6.1.1 — ✅ met

As a consumer of the :full image, I want each embedded scanner pinned by digest and verified by checksum at build, so that an upstream tag compromise does not enter my trust boundary.

Acceptance Criteria

  • [x] Dockerfile.full references bases by @sha256:<digest> (not a moving tag).
  • [x] Build validates the checksum of downloaded binaries (kubescape/tfsec/terrascan/regula/conftest) and fails on mismatch.
  • [x] Documented in 10-infraestrutura.md and in the README supply-chain section.
  • [x] CI release.yml signs keyless (cosign, with retry) and generates the SLSA build-provenance attestation.

Feature F-6.2 — SBOM and attestation of the Quorum image itself · ✅ Delivered · S · 5 SP

Status: ✅ Delivered. actions/attest-sbom generates an attested SPDX SBOM for the image and per-binary (GoReleaser/syft), plus BuildKit sbom: true; SLSA build-provenance attestation verifiable via gh attestation verify; keyless signature verifiable via cosign verify. The GitHub Action (action.yml composite) cosign-verifies the image before running.

User Story US-6.2.1 — ✅ met

As an auditor of my supply chain, I want the :full/:slim images to publish their own SBOM and attestation, so that I inventory what is inside Quorum, not just what it scans.

Acceptance Criteria

  • [x] release.yml generates the attested SPDX SBOM of the image/binaries and attaches it (GHCR/attestation).
  • [x] SLSA build-provenance attestation verifiable via gh attestation verify.
  • [x] cosign verify of the keyless signature documented and exercised in the release flow and in the Action.

Feature F-6.3 — Container runtime hardening · ☐ Pending · S · 5 SP

Status: ☐ Pending. The supply chain is hardened, but running the container as non-root with a read-only FS by default is still backlog.

User Story US-6.3.1

As a security operator, I want the Quorum container to run as non-root and with a read-only FS, so that the blast radius of an orchestrator failure is minimal.

Acceptance Criteria

  • [ ] Images run as a non-root UID by default (/work mount stays writable when needed).
  • [ ] Compatible with --read-only + --cap-drop ALL documented in the examples.
  • [ ] SecurityContext example for use as container: in GitHub Actions.
  • [ ] Cache (~/.cache/quorum) redirectable via env when HOME is not writable.

Feature F-6.4 — Knowledge-pack build-provenance attestation · ✅ Delivered · S · 3 SP

Status: ✅ Delivered. In v0.8.3 the knowledge pack + crosswalk that back the advisory layer (knowledge/*.yaml, knowledge/owasp/corpus.yaml) receive a SLSA build-provenance attestation each release (the knowledge job in release.yml), so a consumer can prove the corpus was built by the pipeline and not tampered with.

User Story US-6.4.1 — ✅ met

As a consumer of the digest-pinned OWASP corpus, I want the knowledge pack to carry its own build-provenance attestation, so that I can verify its integrity before trusting advisory output.

Acceptance Criteria

  • [x] The knowledge job attests knowledge/owasp/corpus.yaml (and the crosswalk) each release.
  • [x] Verifiable with gh attestation verify knowledge/owasp/corpus.yaml.
  • [x] The corpus stays digest-pinned; embedding via quorum advise-index preserves the pin (F-10.2).

10. Epic E7 — UX / CLI

State v0.8.3: commands scan, list-scanners and advise-index; human output on the stderr summary (printSummary); read-only baseline via --baseline (default .quorumignore, cmd/quorum/scan.go). Missing terminal UX (colored table), baseline generation and explain.

Feature F-7.1 — Readable TTY output · ☐ Pending · S · 5 SP

User Story US-7.1.1

As a developer running Quorum locally, I want a colored table of findings in the terminal, so that I understand the result without opening the SARIF.

Acceptance Criteria

  • [ ] When stdout is a TTY and --format was not forced, show a readable table (colored severity, detectionCount, confidence).
  • [ ] Colors off if NO_COLOR is set or output is non-TTY (CI stays stable).
  • [ ] --quiet suppresses; machine formats (sarif/json/xml) unchanged when explicitly set.

Feature F-7.2 — quorum explain <fingerprint> · ☐ Pending · C · 5 SP

User Story US-7.2.1

As an analyst triaging a finding, I want quorum explain <fingerprint> from a report, so that I see why the confidence has that value (diversity/severity/authority weights).

Acceptance Criteria

  • [ ] Takes a JSON report (--from report.json) + fingerprint.
  • [ ] Shows members, detectedBy, and the decomposition of the confidence formula (DESIGN.md §9).
  • [ ] Clear message if the fingerprint does not exist.

Dependencies: F-2.2 (stable machine-readable summary/report).

Feature F-7.3 — --baseline-write (generate baseline) · ☐ Pending · S · 3 SP

Status: ☐ Pending. Today --baseline only reads an existing file (filter.LoadBaseline); there is no automatic generation.

User Story US-7.3.1

As a team adopting --fail-on for the first time on a repo with legacy findings, I want to generate a .quorumignore from the current scan, so that I freeze the existing backlog and block only new regressions.

Acceptance Criteria

  • [ ] quorum scan … --baseline-write .quorumignore writes 1 fingerprint per line with a comment (# <title> [<severity>] reviewed <date>).
  • [ ] Format 100% compatible with the current baseline reader (filter.LoadBaseline).
  • [ ] Writes nothing if the scan fails with a runtime error (exit 2).

Example output

# .quorumignore — generated by quorum --baseline-write on 2026-07-04
2f1a…e9c4   # CVE-2021-… in apk-tools [HIGH] reviewed 2026-07-04
MISCONFIG|main.tf|aws_s3_bucket|AVD-AWS-0089   # S3 logging [MEDIUM] reviewed 2026-07-04

11. Epic E8 — Action / distribution

State v0.8.3: the composite Action (action.yml) cosign-verifies the image, auto-mounts /var/run/docker.sock on type: image (avoids a false-zero on a local image scan) and exposes the scanner-args and docker-socket inputs. In v0.8.3 it also exposes all advisory inputs (advice, advice-provider, advice-endpoint, advice-model, advice-embed-model, advice-max, advice-cache, advice-allow-egress, advice-api-key, fix), auto-adds host-gateway for the local provider and forwards the API key via env for remote. The moving v0 tag is auto-advanced by tag-major.yml on each semver release. :full (linux/amd64) and :slim (amd64+arm64) images on GHCR; GoReleaser for binaries; examples in examples/ci/. Missing lean image profiles and rich numeric outputs.

Feature F-8.1 — Image profiles :sca/:iac/:k8s · ☐ Pending · S · 8 SP

User Story US-8.1.1

As a pipeline that only does SCA, I want a lean image with just Trivy+Grype, so that the pull and the attack surface are smaller than :full.

Acceptance Criteria

  • [ ] Tags :sca (trivy+grype), :iac (checkov+kics+terrascan+tfsec+regula+conftest) and :k8s (kubescape+polaris+kube-score) published.
  • [ ] Each profile inherits the digest pin (F-6.1) and the signature/attestation (F-6.2).
  • [ ] README documents the updated tag matrix (today :full/:slim).

Dependencies: F-6.1 (already delivered).

Feature F-8.2 — Rich Action outputs + GH cache · ◑ Partial · S · 5 SP

Status: ◑ Partial. The Action is already hardened (cosign verify, automatic docker-socket, scanner-args, moving v0 tag, advisory inputs). Missing numeric outputs and a cache example.

User Story US-8.2.1

As a workflow author, I want structured Action outputs and an alias-store cache across runs, so that I react to the result and speed up runs.

Acceptance Criteria

  • [ ] Outputs beyond output-file/exit-code: critical-count, high-count, multi-detected-count.
  • [ ] Example using actions/cache for ~/.cache/quorum (integrates with F-5.1).
  • [x] Moving v0 tag works (auto-advanced by tag-major.yml); pin by @<sha> documented.

Feature F-8.3 — GitLab/Azure/Jenkins templates · ☐ Pending · C · 5 SP

User Story US-8.3.1

As a user outside GitHub, I want ready-made examples for GitLab CI, Azure Pipelines and Jenkins, so that I adopt Quorum in my CI without rewriting from scratch.

Acceptance Criteria

  • [ ] New files in examples/ci/ for Azure and Jenkins (GitLab already exists).
  • [ ] Each example shows gating by exit code, SARIF/JSON artifact upload and cosign verify.

12. Epic E9 — Runtime security (separate product) · Won't (now)

DESIGN.md §2/§13: runtime (Falco/Tetragon/Inspektor Gadget) follows a stream model that does not fit a static scan. Kept as a future proposal, separate product.

Item MoSCoW Justification
Runtime module (Falco/Tetragon stream) W Architectural model incompatible with the current stateless orchestrator
OpenSCAP host scanning W Target (live host) outside the CLI/Docker artifact-scan scope

Items in this epic remain in the backlog only as a non-scope signal. Reopen only with a formal product decision — they would be a distinct repository/product.


13. Epic E10 — Advisory layer · ✅ Delivered

State v0.8.3 — delivered and opt-in. The advisory layer (--advice, 21-proposta-ia.md, 13-ia.md) is presentation-only and off by default: without --advice the output is byte-identical, and no phase ever touches correlationKey/fingerprint/confidence/aggregated severity or the fail-on gate. The deterministic core still has no AI; the AI parts are strictly opt-in. New model fields on MergedFinding: Remediation, References, Advice (types model.Remediation/DocRef/Advice/Fix). New CLI surface: --advice, --advice-provider (none|local|remote), --advice-endpoint, --advice-model, --advice-embed-model, --advice-cache, --advice-max, --advice-allow-egress, --fix (off|suggest), plus the subcommand quorum advise-index.

Feature F-10.1 — Deterministic enrichment (Phase 0) · ✅ Delivered · S · 8 SP

Status: ✅ Delivered. Curated remediation templates + OWASP references, matched deterministically by canonicalControl/ruleId/category/typeno model (internal/enrich/; data in knowledge/*.yaml — aws/azure/gcp/k8s/image/categories).

User Story US-10.1.1 — ✅ met

As an engineer triaging a finding, I want curated remediation and OWASP references attached deterministically, so that I get actionable next steps without any AI and without changing the gate.

Acceptance Criteria

  • [x] --advice attaches Remediation/References matched by canonicalControl/ruleId/category/type.
  • [x] Fully deterministic, no model; without --advice the output is byte-identical.
  • [x] Never alters correlationKey/fingerprint/confidence/aggregated severity or the fail-on gate.

Feature F-10.2 — RAG-as-artifact (Phase 2) · ✅ Delivered · S · 8 SP

Status: ✅ Delivered. Deterministic retrieval from a versioned, digest-pinned OWASP corpus (knowledge/owasp/corpus.yaml, internal/rag/). Lexical retrieval by default (no model); semantic (embeddings) when the corpus is embedded via quorum advise-indexscan auto-picks semantic when the corpus has vectors. The build-provenance attestation of the corpus is F-6.4.

User Story US-10.2.1 — ✅ met

As a user wanting richer OWASP context, I want retrieval from a pinned corpus (lexical by default, semantic when embedded), so that references are reproducible and verifiable, with no runtime dependency by default.

Acceptance Criteria

  • [x] Retrieval from knowledge/owasp/corpus.yaml, digest-pinned and versioned.
  • [x] Lexical by default (no model); quorum advise-index embeds the corpus preserving the pin.
  • [x] scan auto-selects semantic retrieval when the corpus carries vectors.

Feature F-10.3 — Local LLM advisor + --fix=suggest (Phase 1) · ✅ Delivered · C · 13 SP

Status: ✅ Delivered. --advice-provider=local queries an on-host OpenAI-compatible endpoint (e.g. Ollama) for a natural-language recommendation; --fix=suggest proposes a patch that must pass a verify-the-fix re-scan (apply to a temp copy, re-scan with the same scanner, keep only if the finding is gone and the file parses; never auto-applies). Reproducible via temperature=0 + an on-disk cache keyed by fingerprint+provider+model. Graceful degradation: if the model is unreachable the report ships without AI advice and the scan never fails. Every AI attachment is labeled "AI-generated, advisory only" (internal/advisor/).

User Story US-10.3.1 — ✅ met

As a developer wanting a natural-language recommendation and a candidate patch, I want an on-host LLM advisor that verifies its own fix before showing it, so that I get a reproducible, non-destructive suggestion that never fails my scan.

Acceptance Criteria

  • [x] --advice-provider=local queries an on-host OpenAI-compatible endpoint (--advice-endpoint/--advice-model).
  • [x] --fix=suggest re-scans a temp copy with the same scanner and keeps the patch only if the finding is gone and the file parses; never auto-applies.
  • [x] Reproducible (temperature=0 + cache by fingerprint+provider+model, --advice-cache).
  • [x] Model unreachable → report ships without AI advice; scan never fails. Attachments labeled "AI-generated, advisory only".

Feature F-10.4 — Remote provider (Phase 3) · ✅ Delivered · C · 8 SP

Status: ✅ Delivered. --advice-provider=remote calls an external API (auth via QUORUM_ADVICE_API_KEY). Because data leaves the host, it is gated on explicit consent (--advice-allow-egress), blocked by --offline, and refuses --fix (would upload source). Only the normalized finding is sent — never source code.

User Story US-10.4.1 — ✅ met

As a user opting into a hosted model, I want the remote provider to require explicit egress consent and never upload source, so that data leaving the host is a deliberate, auditable choice.

Acceptance Criteria

  • [x] --advice-provider=remote requires --advice-allow-egress; blocked by --offline.
  • [x] Refuses --fix (would upload source); only the normalized finding is sent.
  • [x] Auth via QUORUM_ADVICE_API_KEY; the Action forwards it via env.

Feature F-10.5 — Advisory metrics + evals harness · ✅ Delivered · S · 5 SP

Status: ✅ Delivered. Under --advice three metric families are emitted: quorum_advice_enriched{kind=remediation|references|recommendation}, quorum_advice_provider{provider} and quorum_advice_fix{stage=proposed|verified} (verified/proposed = the verify-the-fix rate). The evals harness (internal/evals/) measures deterministic remediation coverage, OWASP reference relevance, and the verify-the-fix rate — runs in CI with no heavy model.

User Story US-10.5.1 — ✅ met

As a maintainer of the advisory layer, I want metrics and an evals harness for coverage/relevance/verify-the-fix, so that advisory quality is observable and regression-tested in CI without a heavy model.

Acceptance Criteria

  • [x] quorum_advice_enriched/quorum_advice_provider/quorum_advice_fix emitted only under --advice.
  • [x] Evals measure deterministic remediation coverage, OWASP reference relevance and the verify-the-fix rate.
  • [x] Evals run in CI without a heavy model (no network dependency).

14. N/A items from the enterprise template

Corporate backlog templates often require epics that do not apply to Quorum by architectural decision (CLI/Docker only, stateless). Explicit declaration (updated for v0.8.3):

Template item Status Technical justification Future proposal (separate)
Web frontend / dashboard N/A No UI/daemon; output is a static report and exit code F-3.2 (static HTML, not a panel)
Relational database N/A Minimal state is a local JSON cache (internal/cache/store.go); no relational persistence
HTTP REST API / authentication / accounts N/A Command-line tool; no server, no multi-user
AI / LLM in the core N/A confidence is a deterministic formula, not a model; see 13-ia.md E10 (opt-in advisory layer, delivered — off by default)
Runtime cloud/K8s N/A Quorum scans manifests (--type k8s), not live clusters E9 (runtime, separate product)

15. Roadmap → backlog traceability

flowchart LR
    R03["Roadmap v0.3<br/>Kubescape+Polaris, Dockle, XML"] --> F11["F-1.1 Polaris ✅"]
    R10["Roadmap v1.0<br/>OPA/Conftest, persistent alias cache, image profiles"]
    R10 --> F41["F-4.1 Policy-as-code ◑"]
    R10 --> F12["F-1.2 Conftest ✅"]
    R10 --> F51["F-5.1 Cache TTL ◑"]
    R10 --> F81["F-8.1 Image profiles ☐"]
    RS["Roadmap: Syft for SBOM"] --> F13["F-1.3 Syft ☐"]
    RS --> F31["F-3.1 SBOM export ☐"]
    D12["DESIGN §12/§14<br/>pin by digest, supply chain"] --> F61["F-6.1 Pin digest ✅"]
    D12 --> F62["F-6.2 SBOM+attestation ✅"]
    OBS["Observability gap"] --> F21["F-2.1 log json ✅"]
    OBS --> F23["F-2.3 metrics ◑"]
    IA["21-proposta-ia.md<br/>Phases 0–3"] --> F101["E10 Advisory ✅"]
    RBAC["k8s.yaml: RBAC single-engine"] --> FK1["F-K.1 RBAC consensus ☐"]
    RF["Future roadmap<br/>runtime"] --> E9w["E9 · Won't"]
Origin (roadmap/doc) Backlog Status
v0.3 — Polaris F-1.1 ✅ delivered
v0.3 — XML / Dockle ✅ delivered (v0.2.x)
v0.3+ — kube-score, terrascan, tfsec, regula, Conftest E1 (adapters) ✅ delivered
v1.0 — OPA/Conftest policy-as-code F-1.2 (mode A ✅), F-4.1 (mode B ☐), F-4.2 ◑ partial
v1.0 — persistent alias cache base + schemaVersion/0600 ✅; F-5.1 (TTL/pruning), F-5.2 ◑ partial
v1.0 — image profiles F-8.1 ☐ pending
Syft for SBOM F-1.3, F-3.1 (of the target) ☐ pending (image already has SBOM)
DESIGN §12/§14 — pin by digest, supply chain F-6.1, F-6.2, F-6.4 ✅; F-6.3 ☐ ◑ partial
Observability (metrics/log) F-2.1 ✅, F-2.3 ◑, F-2.2 ☐ ◑ partial
DoS caps + execution hardening QUORUM_MAX_OUTPUT_BYTES/QUORUM_MAX_TARGET_BYTES, argument-injection, redaction ✅ delivered
Hardened Action (cosign, socket, v0 auto, advisory inputs) F-8.2 (partial) ◑ partial
21-proposta-ia.md — advisory layer Phases 0–3 E10 (F-10.1–F-10.5) ✅ delivered
crosswalk/k8s.yaml — RBAC single-engine F-K.1 ☐ pending (documented)
Limitation "0 findings is not proof of safety" F-2.2, F-3.2 (warnings), F-7.1 ☐ pending
MISCONFIG granularity limitation (README.md §Known limitations) candidate for a future "identity per resource" Epic (to refine)
future — runtime E9 (Won't) Won't

16. Suggested next steps (candidate first sprint)

With the supply-chain Musts (F-6.1/F-6.2), adapters (F-1.1/F-1.2) and the advisory layer (E10) already delivered, the next window focuses on closing the highest-unblocking partial slices, ~26 SP:

  • [ ] F-5.1 Cache TTL + pruning (5 SP) — fetchedAt + cache prune over the already-versioned schema.
  • [ ] F-2.2 run-summary.json (5 SP) — unblocks dashboards and explain.
  • [ ] F-4.1 (mode B) Gate by policy over findings (8 SP) — completes the policy-as-code layer.
  • [ ] F-1.4 Hadolint adapter (5 SP) — gives Dockle a peer for IMG_HARDENING consensus.
  • [ ] F-3.3 Enrich SARIF (3 SP) — improves GitHub triage without a dedup regression.

Assumptions

  • Reference version. Backlog aligned to v0.8.3 (revision 2026-07-04); the as-is states (what already exists vs. gap) were checked in the code read: cmd/quorum/scan.go, internal/adapter/ (12 adapters registered via init()→Register), internal/cache/store.go, internal/report/, internal/enrich/, internal/rag/, internal/advisor/, crosswalk/, plus DESIGN.md and README.md.
  • Already-delivered items remain for traceability. Adapters (Polaris, kube-score, terrascan, tfsec, regula, Conftest), consensus via crosswalk, observability (--metrics/--log-format json), supply chain (pin @sha256, checksum, SLSA/SPDX SBOM attestation), DoS caps and the opt-in advisory layer (E10) already exist in the code (v0.3→v0.8.3); they appear marked and the backlog covers only their remaining evolutions.
  • Estimates are relative. Fibonacci story points reflect the relative effort/risk of a team that knows the codebase, not hours. 13/21 SP items must be broken down before the sprint.
  • MoSCoW is per moment. The classification reflects the next release window; "Won't" means "not now", not "never" (especially E9, conditional on a product decision).
  • CLI/Docker scope preserved. No item proposes a web frontend, relational database, HTTP REST API, authentication/accounts or AI/LLM in the core; those are listed as N/A (§14) by architectural decision. The advisory layer (E10) is opt-in, presentation-only and off by default — it does not change this: the deterministic core has no AI.
  • Determinism is an invariant. Any feature must preserve deterministic correlationKey/Fingerprint and the false split > false merge principle; changes that alter the input (e.g. a new scanner version) may legitimately alter the output. The advisory layer never touches correlationKey/fingerprint/confidence/aggregated severity or the fail-on gate.
  • Delivered vs. proposed flags/commands. Already in the CLI: --metrics, --log-format, --baseline (read), --min-severity, --fail-on, --crosswalk, --cache, --offline, the advisory flags (--advice, --advice-provider, --advice-endpoint, --advice-model, --advice-embed-model, --advice-cache, --advice-max, --advice-allow-egress, --fix) and the subcommand advise-index, plus the per-env passthrough QUORUM_<SCANNER>_ARGS (e.g. QUORUM_CHECKOV_ARGS with bc-api-key unlocks Prisma policies) and the caps QUORUM_MAX_OUTPUT_BYTES/QUORUM_MAX_TARGET_BYTES. Not yet existing (they are proposals of this backlog, to confirm in refinement): --summary-file, --sbom/--sbom-output, --baseline-write, --cache-ttl, quorum.policy.yaml and the explain/cache prune subcommands.
  • Crosswalk as managed debt — yet already active. misconfig/K8s consensus is on with a crosswalk derived from real output (false split > false merge): cloud (AVD hub), K8s (C-#### hub), tfsectrivy via native AVD. New mappings assume incremental maintenance (top-N controls) and evidence of overlap before mapping, per DESIGN.md §6/§14.
  • RBAC stays single-engine by a quality decision. The kubescape RBAC controls stay unmapped in crosswalk/k8s.yaml because they require live-cluster context and no second engine fires on the same static object; RBAC consensus (F-K.1) only enters with verified overlap.