Ir para o conteúdo

Backlog

Backlog acionável do Quorum (quorum-sec-scan, v0.8.3) derivado do roadmap oficial (README.md §Roadmap e DESIGN.md §13) e das lacunas observadas no código-fonte (limitações conhecidas, itens ainda não implementados e oportunidades de hardening e UX). O backlog é organizado hierarquicamente Épico → Feature → História de Usuário → Tarefa → Subtarefa, com Critérios de Aceite, Prioridade (MoSCoW), Estimativa (story points, escala de Fibonacci) e Dependências.

Revisão v0.8.3 — 2026-07-04. Boa parte do backlog escrito na v0.2.3 já foi entregue entre a v0.3 e a v0.8.3: novos adaptadores (Polaris, kube-score, terrascan, tfsec, regula, Conftest), consenso de misconfig/K8s via crosswalk derivado de saída real, observabilidade (--metrics textfile Prometheus e --log-format json), hardening de supply-chain (pin por @sha256, verificação de checksum, atestado SLSA + SBOM SPDX da própria imagem), passthrough por scanner e caps anti-DoS, e — novidade na v0.8.3 — a camada advisory opt-in (--advice: remediação curada + referências OWASP, um corpus RAG pinado por digest, e um advisor LLM local/remoto opt-in com verify-the-fix). Itens entregues aparecem marcados ✅ Entregue e ficam aqui apenas para rastreabilidade; o trabalho restante (RBAC em consenso, mais crosswalk, peer do Dockle, Syft/SBOM do alvo, UX de CLI, perfis de imagem) segue como backlog ativo.

Este documento descreve trabalho planejado/proposto. O estado as-is da v0.8.3 está documentado em 01-visao-geral.md e 10-infraestrutura.md. Itens marcados como "proposta futura" e sem ainda não existem no código; são backlog.

Referências de código verificadas: cmd/quorum/scan.go, internal/cache/store.go, internal/adapter/ (12 adaptadores), internal/report/, internal/enrich/, internal/rag/, internal/advisor/, internal/evals/, crosswalk/, knowledge/, DESIGN.md, README.md.


1. Convenções do backlog

1.1 Hierarquia

flowchart LR
    E[Épico] --> F[Feature]
    F --> US[História de Usuário]
    US --> T[Tarefa]
    T --> ST[Subtarefa]
    US -.-> AC[Critérios de Aceite]
Nível Definição no Quorum Exemplo
Épico Objetivo de produto que atravessa vários pacotes/releases "Cache persistente de aliases"
Feature Capacidade entregável dentro de um Épico "Cache com TTL e pruning"
História de Usuário Necessidade de um usuário, no formato Como … quero … para que … ver §4+
Tarefa Unidade técnica de implementação "Adicionar campo expiresAt ao registro de cache"
Subtarefa Passo concreto dentro de uma Tarefa "Migrar o schema JSON v1→v2"

1.2 Prioridade — MoSCoW

Código Significado Critério de uso
M (Must) Necessário para a próxima minor Fecha uma lacuna do roadmap ou um risco de segurança
S (Should) Importante, mas não bloqueia a release Alto valor, com um workaround aceitável
C (Could) Desejável se houver folga Melhoria incremental
W (Won't, agora) Deliberadamente fora de escopo Itens N/A (ver §14) ou um produto futuro separado

1.3 Estimativa — story points (Fibonacci)

1, 2, 3, 5, 8, 13, 21. 1 = mudança trivial e localizada; 21 = um épico inteiro que deve ser quebrado antes de entrar num sprint. Pontos são esforço relativo, não horas.

1.4 Legenda de status (v0.8.3)

Marca Significado
✅ Entregue Já existe no código v0.8.3 (verificado no fonte). Mantido para rastreabilidade.
◑ Parcial Parte da feature está entregue; a fatia descrita permanece.
☐ Pendente Ainda não implementado; backlog ativo.

1.5 Definition of Done (DoD) — aplica-se a toda História de Usuário

  • [ ] Código segue a interface canônica (adaptadores não computam correlationKeyDESIGN.md §5).
  • [ ] Testes unitários cobrindo o caminho feliz e a degradação graciosa.
  • [ ] Para adaptadores: teste de contrato contra um fixture versionado em internal/adapter/testdata.
  • [ ] make test, make vet e make build verdes (cobertura verificada no CI).
  • [ ] Documentação atualizada (README + doc relevante em docs/; site MkDocs Material no GitHub Pages).
  • [ ] Princípio preservado: false split > false merge; "0 achados não é prova de segurança".
  • [ ] Sem regressão do determinismo de correlationKey/Fingerprint.
  • [ ] Crosswalk novo/alterado derivado de saída real dos scanners (não inferido) — crosswalk/.
  • [ ] A camada advisory permanece apenas de apresentação: nenhuma feature sob --advice/--fix pode alterar correlationKey/fingerprint/confidence/severidade agregada ou o gate fail-on — sem --advice a saída é byte-idêntica (DESIGN.md §13, 21-proposta-ia.md).

2. Mapa de épicos

flowchart TB
    subgraph done["Entregue (v0.3 → v0.8.3)"]
        E1d[E1 · Adaptadores ✅ 12 scanners]
        E2d[E2 · Observabilidade ✅ metrics+log json]
        E6d[E6 · Supply chain ✅ pin+SBOM+atestado]
        E10d[E10 · Camada advisory ✅ --advice/--fix]
    end
    subgraph now["Curto prazo (Must/Should)"]
        E5[E5 · Cache TTL/pruning]
        E4[E4 · Gate de política sobre achados]
        E7[E7 · UX / CLI]
    end
    subgraph mid["Médio prazo (Should/Could)"]
        E1r[E1 · peer do Dockle + Syft]
        E3[E3 · Export SBOM + HTML + SARIF++]
        E8[E8 · Perfis de imagem / templates]
    end
    subgraph future["Futuro / N/A"]
        E9[E9 · Segurança de runtime - produto separado]
    end

    E1r --> E3
    E4 --> E3
    E5 --> E2d
Épico Tema Origem Status v0.8.3 Prioridade restante
E1 Adaptadores (12 no total; faltam peer do Dockle e Syft/SBOM do alvo) Roadmap v0.3/v1.0; internal/adapter/ ✅ Polaris, kube-score, terrascan, tfsec, regula, Conftest entregues Should/Could
E2 Observabilidade (logs estruturados, métricas, run summary JSON) Lacuna original --metrics e --log-format json entregues; falta run-summary.json Should
E3 Export de SBOM do alvo e relatórios (HTML, SARIF enriquecido) Roadmap; lacuna de formato ☐ pendente (o SBOM da imagem já existe no supply chain) Should/Could
E4 Policy-as-code (Rego do usuário; gate sobre achados) Roadmap v1.0 ◑ Conftest roda o Rego do usuário (./policy); falta gate sobre achados Should
E5 Cache persistente (TTL, pruning, cache de findings/SBOM) Roadmap v1.0; internal/cache/store.go schemaVersion + perm 0600 entregues; falta TTL/pruning Must
E6 Hardening/supply chain (pin por digest, SBOM da imagem, SLSA) DESIGN.md §12/§14 ✅ pin @sha256 + checksum + atestado SLSA/SBOM SPDX entregues (incl. atestado do knowledge-pack) Should (falta runtime RO)
E7 UX / CLI (saída TTY, --baseline-write, explain, perfis) Lacuna de UX ☐ pendente Should/Could
E8 Action / distribuição (perfis de imagem, action versionada) Roadmap; action.yml ◑ action endurecida (cosign verify, socket, v0 auto, inputs advisory); faltam perfis Should/Could
E9 Segurança de runtime (Falco/Tetragon) DESIGN.md §2/§13fora de escopo Won't (agora) Won't
E10 Camada advisory (--advice/--fix, RAG, LLM local/remoto) 21-proposta-ia.md; Fases 0–3 ✅ Entregue (opt-in, apenas apresentação, off por padrão) Could (corpus/evals mais profundos)

3. Resumo priorizado (visão de portfólio)

ID Épico Feature Status MoSCoW SP Dependências
F-1.1 E1 Adaptador Polaris (posture K8s) ✅ Entregue M 8
F-1.2 E1 Adaptador Conftest/OPA (policy-as-code) ✅ Entregue S 13 F-4.1
F-1.3 E1 Adaptador Syft (SBOM do alvo) ☐ Pendente S 8
F-1.4 E1 Adaptador Hadolint (peer do Dockle) ☐ Pendente C 5
F-2.1 E2 Logs estruturados (JSON) com nível ✅ Entregue S 5
F-2.2 E2 run-summary.json legível por máquina ☐ Pendente S 5
F-2.3 E2 Métricas (Prometheus textfile / OTel) ◑ Parcial C 8 F-2.1
F-3.1 E3 Export de SBOM do alvo (CycloneDX/SPDX) ☐ Pendente S 8 F-1.3
F-3.2 E3 Relatório HTML estático ☐ Pendente C 8
F-3.3 E3 Enriquecer SARIF (help, tags, security-severity) ☐ Pendente S 3
F-4.1 E4 Camada policy-as-code (Rego do usuário) ◑ Parcial S 13
F-4.2 E4 Política de gate declarativa (quorum.policy.yaml) ☐ Pendente C 8 F-4.1
F-5.1 E5 Cache de aliases com TTL + pruning ◑ Parcial M 5
F-5.2 E5 Cache de SBOM/findings por digest ☐ Pendente C 13 F-1.3
F-6.1 E6 Pin de scanners por @sha256 + verificação ✅ Entregue M 8
F-6.2 E6 SBOM e atestado da própria imagem Quorum ✅ Entregue S 5
F-6.3 E6 Hardening de runtime do container (rootless, FS RO) ☐ Pendente S 5
F-6.4 E6 Atestado de build-provenance do knowledge-pack ✅ Entregue S 3 F-10.2
F-7.1 E7 Saída TTY colorida + tabela legível ☐ Pendente S 5
F-7.2 E7 quorum explain <fingerprint> ☐ Pendente C 5 F-2.2
F-7.3 E7 Modo --baseline-write (gerar baseline) ☐ Pendente S 3
F-8.1 E8 Perfis de imagem :sca/:iac/:k8s ☐ Pendente S 8 F-6.1
F-8.2 E8 Outputs ricos da Action + cache GH ◑ Parcial S 5
F-8.3 E8 Templates estendidos GitLab/Azure/Jenkins ☐ Pendente C 5
F-10.1 E10 Enriquecimento determinístico (remediação + refs OWASP) ✅ Entregue S 8
F-10.2 E10 RAG-as-artifact (corpus OWASP pinado por digest) ✅ Entregue S 8
F-10.3 E10 Advisor LLM local + --fix=suggest (verify-the-fix) ✅ Entregue C 13 F-10.1
F-10.4 E10 Provider remoto (gated por egress, recusa --fix) ✅ Entregue C 8 F-10.3
F-10.5 E10 Métricas advisory + harness de evals ✅ Entregue S 5 F-10.1
F-K.1 E1 RBAC em consenso (segundo engine com contexto de cluster) ☐ Pendente C 13
F-X.1 E1 Estender cobertura do crosswalk (controles top-N restantes) ☐ Pendente S 8

Entregue até a 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) + parciais (F-2.3, F-4.1, F-5.1, F-8.2). Restante (M+S+C): ~90 SP. Itens W (E9) não pontuam — são um produto separado.


4. Épico E1 — Adaptadores

Meta: ampliar o pool de scanners mantendo a interface Adapter (Name/Version/Supports/Capabilities/Run) e o teste de contrato por fixture (internal/adapter/adapter.go, DESIGN.md §5). Invariante: o novo adaptador emite model.Finding canônico e não computa correlationKey.

Estado v0.8.3 — 12 adaptadores registrados (init()→Register em internal/adapter/): trivy, grype (VULN/SCA), checkov, kics, terrascan, tfsec, regula, conftest (MISCONFIG/IaC), kubescape, polaris, kube-score (K8S_POSTURE), dockle (IMG_HARDENING). O consenso de misconfig/K8s foi habilitado por um crosswalk derivado de saída real (crosswalk/aws.yaml, azure.yaml, gcp.yaml, k8s.yaml) — princípio false split > false merge.

Feature F-1.1 — Adaptador Polaris (posture K8s) · ✅ Entregue · M · 8 SP

Status: ✅ Entregue. internal/adapter/polaris.go implementa Adapter com Capabilities → model.TypeK8sPosture (alvo k8s). O crosswalk crosswalk/k8s.yaml (hub kubescape C-####) correlaciona kubescape × polaris × kube-score em controles como privilege-escalation, privileged, non-root, limites de CPU/mem, probes, read-only-fs, linux-hardening, automount-SA, network-policy, host-network, host-PID/IPC, capabilities e secrets.

História de Usuário US-1.1.1 — ✅ atendida

Como engenheiro de plataforma validando manifests Kubernetes, quero que o Quorum rode o Polaris junto com o Kubescape, para que a posture K8s tenha consenso entre engines (detectionCount ≥ 2).

Critérios de Aceite

  • [x] quorum list-scanners mostra polaris com tipo K8S_POSTURE e alvo k8s.
  • [x] quorum scan ./k8s --type k8s --scanners kubescape,polaris,kube-score produz, para um manifest com privilégio elevado, um MergedFinding com detectedBy de múltiplos engines e detectionCount ≥ 2.
  • [x] A severidade do Polaris é normalizada pela tabela única (DESIGN.md §10).
  • [x] O crosswalk mapeia o check do Polaris → canonicalControl (hub C-####; categoria como fallback).
  • [x] Polaris ausente do PATH → status unavailable (o scan não falha).
  • [x] Teste de contrato contra um fixture versionado em testdata.

Nota: o Polaris também suporta o alvo repo (Supports retorna true para TargetRepo), mas a capability de consenso é K8S_POSTURE.


Feature F-1.2 — Adaptador Conftest/OPA · ✅ Entregue · S · 13 SP

Status: ✅ Entregue. internal/adapter/conftest.go avalia o Rego do usuário (por padrão em ./policy, ou via QUORUM_CONFTEST_ARGS="--policy <dir>"). Sem políticas, o adaptador reporta error de propósito — policy-as-code é opt-in e o Quorum não empacota políticas opinativas (DESIGN.md §2). Violações viram Findings MISCONFIG (isolados com RuleID: "policy", já que regras Rego não têm id estável).

História de Usuário US-1.2.1 — ✅ atendida

Como time de AppSec com nossas próprias políticas Rego, quero rodar minhas políticas OPA/Conftest pelo Quorum, para que violações de política apareçam no mesmo relatório de consenso.

Critérios de Aceite

  • [x] --scanners conftest roda políticas Rego sobre o alvo repo/k8s.
  • [x] Violações viram Findings do tipo MISCONFIG (com RuleID isolado policy).
  • [x] O usuário traz suas próprias regras via ./policy (ou QUORUM_CONFTEST_ARGS) — sem política empacotada.
  • [x] Nenhuma política configurada → adaptador error (comportamento esperado, opt-in), sem corromper o resto.

Restante (fatia de F-4): decidir se violações de política merecem um tipo POLICY próprio (hoje reusa MISCONFIG) e habilitar o modo B (política sobre []MergedFinding para o gate) — ver F-4.


Feature F-1.3 — Adaptador Syft (SBOM do alvo) · ☐ Pendente · S · 8 SP

Status: ☐ Pendente. O Syft já é usado no supply chain (GoReleaser/BuildKit e actions/attest-sbom geram um SBOM SPDX da própria imagem/binários — ver F-6.2), mas não há adaptador produzindo um SBOM do alvo escaneado consumível pelo pipeline (PURLs, cache, export).

História de Usuário US-1.3.1

Como engenheiro que precisa de um inventário de dependências, quero que o Quorum gere um SBOM do alvo via Syft, para que eu tenha o componente base reutilizável para SCA, export de SBOM e cache.

Critérios de Aceite

  • [ ] O Syft produz um inventário interno (PURLs) consumível pelo pipeline.
  • [ ] Quando habilitado, alimenta o export de SBOM (F-3.1) e o cache por digest (F-5.2).
  • [ ] Não emite "achados" por si só — é uma fonte de dados, não um detector (status próprio no resumo).

Dependências: nenhuma; habilita F-3.1 e F-5.2.


Feature F-1.4 — Adaptador Hadolint (peer do Dockle) · ☐ Pendente · C · 5 SP

Status: ☐ Pendente. Hoje dockle é single-engine para IMG_HARDENING ("sem peer para consenso ainda", README.md §scanners). Um segundo engine de imagem/Dockerfile permitiria detectionCount ≥ 2 nessa família.

História de Usuário US-1.4.1

Como desenvolvedor que mantém Dockerfiles, quero linting de Dockerfile via Hadolint no Quorum, para que problemas de build de imagem entrem no consenso IMG_HARDENING/MISCONFIG.

Critérios de Aceite

  • [ ] hadolint registrado; alvo repo (detecta Dockerfile*).
  • [ ] Regras DL**** mapeadas para canonicalControl quando equivalentes aos controles CIS-DI do Dockle (potencial detectionCount ≥ 2 — o peer que falta hoje).
  • [ ] Entradas de crosswalk derivadas de saída real (Hadolint × Dockle no mesmo alvo).
  • [ ] Teste de contrato com um fixture da saída JSON do Hadolint.

Feature F-K.1 — RBAC em consenso · ☐ Pendente · C · 13 SP

Status: ☐ Pendente (limitação documentada). RBAC segue single-engine: o crosswalk crosswalk/k8s.yaml deixa os controles RBAC do kubescape (C-0035/C-0185/C-0272/…) não mapeados de propósito, porque em manifests estáticos eles tipicamente requerem contexto de cluster vivo e nenhum segundo engine (polaris/kube-score) dispara no mesmo objeto — forçar um merge seria um false merge. Preserva o princípio false split > false merge.

História de Usuário US-K.1.1

Como engenheiro de segurança K8s, quero consenso em achados de RBAC, para que violações de RBAC ganhem detectionCount ≥ 2 sem um false merge.

Critérios de Aceite

  • [ ] Um segundo engine com contexto de cluster (ou um modo live) dispara nos mesmos objetos RBAC.
  • [ ] Sobreposição verificada contra saída real antes de mapear no crosswalk (não inferida).
  • [ ] Enquanto não houver sobreposição verificada, RBAC segue single-engine e documentado (sem regressão).

Nota: 13 SP — depende de uma decisão de escopo (scan estático vs. contexto de cluster).


Feature F-X.1 — Estender cobertura do crosswalk · ☐ Pendente · S · 8 SP

Status: ☐ Pendente (dívida gerenciada). O crosswalk já cobre um top-N sólido derivado de saída real: cloud (hub AVD) — S3/IAM/EBS/SG/RDS/KMS/CloudTrail/VPC-flow-logs, Azure Storage/Key Vault, GCP bucket/firewall/SQL; K8s (hub C-####) — ver F-1.1; tfsec auto-correlaciona com trivy porque emite AVD nativo. A cauda de controles resta estender.

Critérios de Aceite

  • [ ] Novos mapeamentos derivados de saída real dos scanners (evidência de sobreposição).
  • [ ] Cada entrada preserva false split > false merge (na dúvida, não mapear).
  • [ ] Cobertura incremental documentada por provider/família.

5. Épico E2 — Observabilidade

Estado v0.8.3: entregues --metrics <file> (textfile Prometheus, writeMetricsFile em cmd/quorum/scan.go + internal/report/metrics.go) e --log-format text|json. Sob --advice, três famílias extras de métricas também são emitidas: quorum_advice_enriched{kind=…}, quorum_advice_provider{provider} e quorum_advice_fix{stage=proposed|verified} (ver E10). O resumo humano no stderr (printSummary) permanece. Falta um run-summary.json estruturado.

Feature F-2.1 — Logs estruturados · ✅ Entregue · S · 5 SP

Status: ✅ Entregue. --log-format text|json (padrão text, compatível com [quorum] …); um valor inválido é rejeitado (invalid --log-format). --quiet ainda suprime o progresso.

História de Usuário US-2.1.1 — ✅ atendida

Como operador de CI que agrega logs num SIEM, quero logs JSON com nível e campos, para que eu possa filtrar e alertar sobre execuções de scan.

Critérios de Aceite

  • [x] Flag --log-format text|json (padrão text, retrocompatível).
  • [x] Eventos do orquestrador (start/stop/timeout/unavailable de scanner) emitidos no formato escolhido.
  • [x] --quiet ainda suprime logs de progresso; erros sempre visíveis.
  • [x] Sem segredos nos logs (redação: o Match do trivy é redigido; alvo/fingerprints/contagens permitidos).

Feature F-2.2 — run-summary.json legível por máquina · ☐ Pendente · S · 5 SP

Status: ☐ Pendente. Não há flag de resumo estruturado por execução; o printSummary humano permanece a única visão consolidada por scanner.

História de Usuário US-2.2.1

Como plataforma coletando métricas de N pipelines, quero um arquivo de resumo estruturado por execução, para que dashboards consumam o status por scanner e o rollup de severidade sem parsear texto.

Critérios de Aceite

  • [ ] Flag --summary-file run-summary.json escreve: por scanner {name,status,findings,duration,error}, mergedCount, multiDetected, rollup por severidade e elapsed.
  • [ ] O conteúdo espelha exatamente o printSummary atual (fonte única de verdade).
  • [ ] Ausência da flag = comportamento atual inalterado.

Dependências: reusa orchestrator.Result (cmd/quorum/scan.go).

Feature F-2.3 — Métricas · ◑ Parcial · C · 8 SP

Status: ◑ Parcial. --metrics <file> já escreve um textfile Prometheus (para node_exporter), incluindo as famílias advisory quando --advice está ligado. Falta a variante OTLP/OpenTelemetry via env.

História de Usuário US-2.3.1

Como SRE, quero exportar métricas via OpenTelemetry além do textfile Prometheus, para que eu acompanhe tendências de achados entre execuções em backends OTLP.

Critérios de Aceite

  • [x] Flag --metrics metrics.prom escreve métricas no formato textfile do node_exporter.
  • [ ] Alternativa: endpoint OTLP via env (opt-in).
  • [x] Desabilitado por padrão; nenhuma chamada de rede sem opt-in (respeita offline-first).

Dependências: F-2.1.


6. Épico E3 — Export de SBOM e relatórios

Estado v0.8.3: três reporters — SARIF/JSON/XML (internal/report/) — mais escrita de métricas Prometheus. Não há export de SBOM do alvo, nem relatório HTML, nem SARIF enriquecido. (O SBOM da própria imagem já existe no supply chain — ver F-6.2.)

Feature F-3.1 — Export de SBOM do alvo (CycloneDX/SPDX) · ☐ Pendente · S · 8 SP

História de Usuário US-3.1.1

Como responsável por compliance de supply-chain, quero exportar o SBOM do alvo em CycloneDX ou SPDX, para que eu atenda a requisitos regulatórios (ex.: EO 14028) com o mesmo comando de scan.

Critérios de Aceite

  • [ ] --sbom cyclonedx|spdx + --sbom-output sbom.json gera o SBOM do alvo.
  • [ ] SBOM derivado do inventário do Syft (F-1.3); PURLs consistentes com os achados VULN.
  • [ ] Operação não-bloqueante: uma falha de SBOM não derruba o scan principal (loga e continua).

Dependências: F-1.3.

Feature F-3.2 — Relatório HTML estático · ☐ Pendente · C · 8 SP

História de Usuário US-3.2.1

Como tech lead compartilhando resultados num PR, quero um único relatório HTML (sem servidor), para que revisores vejam consenso, confidence e status por scanner sem ferramentas extras.

Critérios de Aceite

  • [ ] --format html -o report.html produz HTML standalone (sem JS externo, sem rede).
  • [ ] Mostra uma tabela de MergedFinding ordenada por severity e confidence, com detectedBy.
  • [ ] Inclui o aviso "0 achados não é prova de segurança" e o status por scanner.
  • [ ] N/A explícito: não é um painel web/daemon — é um artefato estático (ver 13-ia.md para limites de escopo).

Feature F-3.3 — Enriquecer SARIF · ☐ Pendente · S · 3 SP

Status: ☐ Pendente. O SARIF já preserva partialFingerprints (internal/report/sarif.go), mas não emite ainda security-severity, help.text ou tags por regra.

História de Usuário US-3.3.1

Como usuário do GitHub code scanning, quero que o SARIF carregue security-severity, help e tags por regra, para que a triagem no GitHub mostre a severidade e o contexto corretos.

Critérios de Aceite

  • [ ] rules[].properties["security-severity"] derivado de CVSS/severidade.
  • [ ] rules[].help.text com origem (detectedBy) e o link do controle canônico (AVD/CIS) quando presente.
  • [x] partialFingerprints preservados (sem regressão de dedup — DESIGN.md §11).
  • [ ] Teste atualizado em internal/report/report_test.go.

7. Épico E4 — Policy-as-code

Roadmap v1.0: "camada policy-as-code OPA/Conftest". Princípio de design: OPA/Conftest não é um "scanner", é uma camada opcional onde o usuário traz as regras (DESIGN.md §2).

Feature F-4.1 — Camada policy-as-code · ◑ Parcial · S · 13 SP

Status: ◑ Parcial. O modo A (política Rego sobre o alvo IaC/K8s → violações viram Findings) já existe via conftest (F-1.2): carrega o Rego do usuário de ./policy/QUORUM_CONFTEST_ARGS, sem política empacotada, e degrada com status error sem corromper o relatório. Falta o modo B: avaliar política sobre os próprios []MergedFinding para decidir o gate.

História de Usuário US-4.1.1

Como time de governança, quero avaliar políticas Rego sobre o alvo e/ou sobre os próprios achados do Quorum, para que decisões de gate sigam nossas regras de negócio, não só a severidade.

Critérios de Aceite

  • [x] Carrega os bundles Rego do usuário (./policy / QUORUM_CONFTEST_ARGS; sem política empacotada).
  • [x] Modo A: política sobre o alvo (IaC/K8s) → violações viram Findings MISCONFIG.
  • [ ] Modo B: política sobre []MergedFinding → pode decidir o gate (ex.: "bloquear se algum finding tiver confidence ≥ 0.8 e severity ≥ HIGH").
  • [x] Degradação graciosa: um erro de avaliação de política → status error do "scanner" de política, sem corromper o resto do relatório.

Dependências: habilita F-4.2. Nota: o modo B é a fatia restante desta feature.

Feature F-4.2 — Política de gate declarativa · ☐ Pendente · C · 8 SP

História de Usuário US-4.2.1

Como mantenedor, quero declarar o gate em quorum.policy.yaml (thresholds por tipo/severidade/confidence), para que o critério de bloqueio seja versionado e auditável, além do simples --fail-on.

Critérios de Aceite

  • [ ] YAML declarativo: regras como {type: VULN, minSeverity: HIGH, minConfidence: 0.7 → fail}.
  • [ ] Coexiste com --fail-on/--min-severity (as flags seguem funcionando; o YAML refina).
  • [ ] Exit codes inalterados (0/1/2, README.md §Exit codes).

8. Épico E5 — Cache persistente

Estado v0.8.3: o cache persistente de aliases em JSON (internal/cache/store.go) foi endurecido: arquivo aliases.json com permissão 0600 e schemaVersion (versionamento de schema), flush atômico e tolerante a falhas (cache corrompido → cache vazio). Lacunas restantes: sem TTL/expiração de entrada e sem cache de SBOM/findings por digest. (A camada advisory adiciona seu próprio cache em disco chaveado por fingerprint+provider+model sob --advice-cache — ver F-10.3.)

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

Status: ◑ Parcial. schemaVersion e perm 0600 entregues (base para migração segura). Falta TTL/revalidação e o subcomando de pruning.

História de Usuário US-5.1.1

Como usuário de CI de longa duração, quero que entradas de alias expirem para que o cache não cresça indefinidamente, para que dados de alias obsoletos sejam revalidados e o arquivo fique pequeno.

Critérios de Aceite

  • [x] Registro versionado por schemaVersion (base para migração transparente).
  • [ ] Registro carrega fetchedAt; --cache-ttl 720h revalida entradas expiradas via OSV (respeita --offline).
  • [x] Cache corrompido/ilegível ainda gera um cache vazio (sem quebrar o scan — invariante atual).
  • [ ] quorum cache prune remove entradas expiradas.
Tarefa SP Subtarefas
T-5.1.1a · adicionar fetchedAt ao registro (schema já versionado) 2 struct com timestamp; migração via schemaVersion atual; teste
T-5.1.1b · lógica de TTL em alias.Resolver 1 considerar expirado antes do hit; respeitar --offline
T-5.1.1c · subcomando cache prune 1 iterar e remover expirados; logar a contagem

Feature F-5.2 — Cache de SBOM/findings por digest · ☐ Pendente · C · 13 SP

História de Usuário US-5.2.1

Como pipeline que re-escaneia a mesma imagem por digest, quero reusar SBOM/findings em cache pelo sha256 da imagem, para que re-scans sejam muito mais rápidos quando o conteúdo não mudou.

Critérios de Aceite

  • [ ] Chave de cache = digest do alvo (imagem) ou tree hash (repo).
  • [ ] --no-cache/cache miss recomputam; resultado determinístico idêntico a um scan sem cache.
  • [ ] Invalidações: mudança de versão do scanner → invalida (a versão entra na chave).

Dependências: F-1.3 (Syft). Nota: quebrar; risco de invalidação incorreta. 13 SP.


9. Épico E6 — Hardening de supply-chain

Estado v0.8.3 — em grande parte entregue. Dockerfile.full, .goreleaser.yaml e release.yml foram endurecidos: bases pinadas por @sha256; kubescape/tfsec/terrascan/regula/conftest verificados por checksum; atestado SLSA build-provenance e SBOM SPDX (actions/attest-sbom) da imagem e por-binário, mais BuildKit sbom: true; cosign keyless com retry; DB do grype pré-cacheado com GRYPE_DB_VALIDATE_AGE=false (nunca expira); THIRD_PARTY_NOTICES.md. Na v0.8.3 o knowledge pack + crosswalk também ganham seu próprio atestado de build-provenance a cada release (ver F-6.4). Além do hardening de execução: --output com filepath.Clean e perm 0600; id OSV validado e url.PathEscape; injeção de argumentos recusada (alvo iniciando com -); caps anti-DoS (QUORUM_MAX_OUTPUT_BYTES = 512 MiB; QUORUM_MAX_TARGET_BYTES = 20 GiB); redação de segredos.

Feature F-6.1 — Pin de scanners por @sha256 + verificação · ✅ Entregue · M · 8 SP

Status: ✅ Entregue. Bases pinadas por @sha256; scanners baixados verificados por checksum (o build falha em mismatch); DB do grype pré-cacheado sem expiração.

História de Usuário US-6.1.1 — ✅ atendida

Como consumidor da imagem :full, quero cada scanner embutido pinado por digest e verificado por checksum no build, para que um comprometimento de tag upstream não entre no meu trust boundary.

Critérios de Aceite

  • [x] Dockerfile.full referencia bases por @sha256:<digest> (não uma tag móvel).
  • [x] O build valida o checksum dos binários baixados (kubescape/tfsec/terrascan/regula/conftest) e falha em mismatch.
  • [x] Documentado em 10-infraestrutura.md e na seção de supply-chain do README.
  • [x] O CI release.yml assina keyless (cosign, com retry) e gera o atestado SLSA build-provenance.

Feature F-6.2 — SBOM e atestado da própria imagem Quorum · ✅ Entregue · S · 5 SP

Status: ✅ Entregue. actions/attest-sbom gera um SBOM SPDX atestado da imagem e por-binário (GoReleaser/syft), mais BuildKit sbom: true; atestado SLSA build-provenance verificável via gh attestation verify; assinatura keyless verificável via cosign verify. A GitHub Action (action.yml composite) cosign-verifica a imagem antes de rodar.

História de Usuário US-6.2.1 — ✅ atendida

Como auditor da minha supply chain, quero que as imagens :full/:slim publiquem seu próprio SBOM e atestado, para que eu inventarie o que há dentro do Quorum, não só o que ele escaneia.

Critérios de Aceite

  • [x] release.yml gera o SBOM SPDX atestado da imagem/binários e o anexa (GHCR/atestado).
  • [x] Atestado SLSA build-provenance verificável via gh attestation verify.
  • [x] cosign verify da assinatura keyless documentado e exercitado no fluxo de release e na Action.

Feature F-6.3 — Hardening de runtime do container · ☐ Pendente · S · 5 SP

Status: ☐ Pendente. O supply chain está endurecido, mas rodar o container como não-root com FS read-only por padrão ainda é backlog.

História de Usuário US-6.3.1

Como operador de segurança, quero que o container Quorum rode como não-root e com FS read-only, para que o raio de impacto de uma falha de orquestrador seja mínimo.

Critérios de Aceite

  • [ ] Imagens rodam com um UID não-root por padrão (o mount /work segue gravável quando necessário).
  • [ ] Compatível com --read-only + --cap-drop ALL documentados nos exemplos.
  • [ ] Exemplo de SecurityContext para uso como container: no GitHub Actions.
  • [ ] Cache (~/.cache/quorum) redirecionável via env quando o HOME não é gravável.

Feature F-6.4 — Atestado de build-provenance do knowledge-pack · ✅ Entregue · S · 3 SP

Status: ✅ Entregue. Na v0.8.3 o knowledge pack + crosswalk que embasam a camada advisory (knowledge/*.yaml, knowledge/owasp/corpus.yaml) recebem um atestado SLSA build-provenance a cada release (o job knowledge em release.yml), para que um consumidor possa provar que o corpus foi construído pelo pipeline e não adulterado.

História de Usuário US-6.4.1 — ✅ atendida

Como consumidor do corpus OWASP pinado por digest, quero que o knowledge pack carregue seu próprio atestado de build-provenance, para que eu possa verificar sua integridade antes de confiar na saída advisory.

Critérios de Aceite

  • [x] O job knowledge atesta knowledge/owasp/corpus.yaml (e o crosswalk) a cada release.
  • [x] Verificável com gh attestation verify knowledge/owasp/corpus.yaml.
  • [x] O corpus segue pinado por digest; o embedding via quorum advise-index preserva o pin (F-10.2).

10. Épico E7 — UX / CLI

Estado v0.8.3: comandos scan, list-scanners e advise-index; saída humana no summary do stderr (printSummary); baseline somente-leitura via --baseline (padrão .quorumignore, cmd/quorum/scan.go). Faltam UX de terminal (tabela colorida), geração de baseline e explain.

Feature F-7.1 — Saída TTY legível · ☐ Pendente · S · 5 SP

História de Usuário US-7.1.1

Como desenvolvedor rodando o Quorum localmente, quero uma tabela colorida de achados no terminal, para que eu entenda o resultado sem abrir o SARIF.

Critérios de Aceite

  • [ ] Quando stdout é um TTY e --format não foi forçado, mostrar uma tabela legível (severidade colorida, detectionCount, confidence).
  • [ ] Cores off se NO_COLOR estiver setado ou a saída for non-TTY (o CI segue estável).
  • [ ] --quiet suprime; formatos de máquina (sarif/json/xml) inalterados quando setados explicitamente.

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

História de Usuário US-7.2.1

Como analista triando um achado, quero quorum explain <fingerprint> a partir de um relatório, para que eu veja por que o confidence tem aquele valor (pesos de diversidade/severidade/autoridade).

Critérios de Aceite

  • [ ] Recebe um relatório JSON (--from report.json) + fingerprint.
  • [ ] Mostra os membros, detectedBy, e a decomposição da fórmula de confidence (DESIGN.md §9).
  • [ ] Mensagem clara se o fingerprint não existir.

Dependências: F-2.2 (resumo/relatório estável legível por máquina).

Feature F-7.3 — --baseline-write (gerar baseline) · ☐ Pendente · S · 3 SP

Status: ☐ Pendente. Hoje --baseline um arquivo existente (filter.LoadBaseline); não há geração automática.

História de Usuário US-7.3.1

Como time adotando --fail-on pela primeira vez num repo com achados legados, quero gerar um .quorumignore a partir do scan atual, para que eu congele o backlog existente e bloqueie apenas novas regressões.

Critérios de Aceite

  • [ ] quorum scan … --baseline-write .quorumignore escreve 1 fingerprint por linha com um comentário (# <title> [<severity>] reviewed <date>).
  • [ ] Formato 100% compatível com o leitor de baseline atual (filter.LoadBaseline).
  • [ ] Não escreve nada se o scan falhar com um erro de runtime (exit 2).

Exemplo de saída

# .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. Épico E8 — Action / distribuição

Estado v0.8.3: a Action composite (action.yml) cosign-verifica a imagem, auto-monta /var/run/docker.sock em type: image (evita um falso-zero num scan de imagem local) e expõe os inputs scanner-args e docker-socket. Na v0.8.3 também expõe todos os inputs advisory (advice, advice-provider, advice-endpoint, advice-model, advice-embed-model, advice-max, advice-cache, advice-allow-egress, advice-api-key, fix), auto-adiciona host-gateway para o provider local e encaminha a API key via env para remote. A tag móvel v0 é auto-avançada pelo tag-major.yml a cada release semver. Imagens :full (linux/amd64) e :slim (amd64+arm64) no GHCR; GoReleaser para binários; exemplos em examples/ci/. Faltam perfis de imagem enxutos e outputs numéricos ricos.

Feature F-8.1 — Perfis de imagem :sca/:iac/:k8s · ☐ Pendente · S · 8 SP

História de Usuário US-8.1.1

Como pipeline que só faz SCA, quero uma imagem enxuta com apenas Trivy+Grype, para que o pull e a superfície de ataque sejam menores que :full.

Critérios de Aceite

  • [ ] Tags :sca (trivy+grype), :iac (checkov+kics+terrascan+tfsec+regula+conftest) e :k8s (kubescape+polaris+kube-score) publicadas.
  • [ ] Cada perfil herda o pin por digest (F-6.1) e a assinatura/atestado (F-6.2).
  • [ ] README documenta a matriz de tags atualizada (hoje :full/:slim).

Dependências: F-6.1 (já entregue).

Feature F-8.2 — Outputs ricos da Action + cache GH · ◑ Parcial · S · 5 SP

Status: ◑ Parcial. A Action já está endurecida (cosign verify, docker-socket automático, scanner-args, tag móvel v0, inputs advisory). Faltam outputs numéricos e um exemplo de cache.

História de Usuário US-8.2.1

Como autor de workflow, quero outputs estruturados da Action e um cache do alias-store entre execuções, para que eu reaja ao resultado e acelere as execuções.

Critérios de Aceite

  • [ ] Outputs além de output-file/exit-code: critical-count, high-count, multi-detected-count.
  • [ ] Exemplo usando actions/cache para ~/.cache/quorum (integra com F-5.1).
  • [x] A tag móvel v0 funciona (auto-avançada por tag-major.yml); pin por @<sha> documentado.

Feature F-8.3 — Templates GitLab/Azure/Jenkins · ☐ Pendente · C · 5 SP

História de Usuário US-8.3.1

Como usuário fora do GitHub, quero exemplos prontos para GitLab CI, Azure Pipelines e Jenkins, para que eu adote o Quorum no meu CI sem reescrever do zero.

Critérios de Aceite

  • [ ] Novos arquivos em examples/ci/ para Azure e Jenkins (GitLab já existe).
  • [ ] Cada exemplo mostra gating por exit code, upload de artefato SARIF/JSON e cosign verify.

12. Épico E9 — Segurança de runtime (produto separado) · Won't (agora)

DESIGN.md §2/§13: runtime (Falco/Tetragon/Inspektor Gadget) segue um modelo de stream que não cabe num scan estático. Mantido como proposta futura, produto separado.

Item MoSCoW Justificativa
Módulo de runtime (stream Falco/Tetragon) W Modelo arquitetural incompatível com o orquestrador stateless atual
OpenSCAP host scanning W Alvo (host vivo) fora do escopo de scan de artefato CLI/Docker

Itens deste épico ficam no backlog apenas como sinal de não-escopo. Reabrir só com uma decisão formal de produto — seriam um repositório/produto distinto.


13. Épico E10 — Camada advisory · ✅ Entregue

Estado v0.8.3 — entregue e opt-in. A camada advisory (--advice, 21-proposta-ia.md, 13-ia.md) é apenas de apresentação e off por padrão: sem --advice a saída é byte-idêntica, e nenhuma fase toca em correlationKey/fingerprint/confidence/severidade agregada ou no gate fail-on. O core determinístico segue sem IA; as partes de IA são estritamente opt-in. Novos campos no modelo MergedFinding: Remediation, References, Advice (tipos model.Remediation/DocRef/Advice/Fix). Nova superfície de CLI: --advice, --advice-provider (none|local|remote), --advice-endpoint, --advice-model, --advice-embed-model, --advice-cache, --advice-max, --advice-allow-egress, --fix (off|suggest), mais o subcomando quorum advise-index.

Feature F-10.1 — Enriquecimento determinístico (Fase 0) · ✅ Entregue · S · 8 SP

Status: ✅ Entregue. Templates de remediação curados + referências OWASP, casados deterministicamente por canonicalControl/ruleId/category/typesem modelo (internal/enrich/; dados em knowledge/*.yaml — aws/azure/gcp/k8s/image/categories).

História de Usuário US-10.1.1 — ✅ atendida

Como engenheiro triando um achado, quero remediação curada e referências OWASP anexadas deterministicamente, para que eu tenha próximos passos acionáveis sem nenhuma IA e sem mudar o gate.

Critérios de Aceite

  • [x] --advice anexa Remediation/References casados por canonicalControl/ruleId/category/type.
  • [x] Totalmente determinístico, sem modelo; sem --advice a saída é byte-idêntica.
  • [x] Nunca altera correlationKey/fingerprint/confidence/severidade agregada ou o gate fail-on.

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

Status: ✅ Entregue. Retrieval determinístico de um corpus OWASP versionado e pinado por digest (knowledge/owasp/corpus.yaml, internal/rag/). Retrieval lexical por padrão (sem modelo); semântico (embeddings) quando o corpus é embutido via quorum advise-index — o scan escolhe semântico automaticamente quando o corpus tem vetores. O atestado de build-provenance do corpus é F-6.4.

História de Usuário US-10.2.1 — ✅ atendida

Como usuário querendo contexto OWASP mais rico, quero retrieval de um corpus pinado (lexical por padrão, semântico quando embutido), para que referências sejam reprodutíveis e verificáveis, sem dependência de runtime por padrão.

Critérios de Aceite

  • [x] Retrieval de knowledge/owasp/corpus.yaml, pinado por digest e versionado.
  • [x] Lexical por padrão (sem modelo); quorum advise-index embute o corpus preservando o pin.
  • [x] O scan auto-seleciona retrieval semântico quando o corpus carrega vetores.

Feature F-10.3 — Advisor LLM local + --fix=suggest (Fase 1) · ✅ Entregue · C · 13 SP

Status: ✅ Entregue. --advice-provider=local consulta um endpoint on-host compatível com OpenAI (ex.: Ollama) para uma recomendação em linguagem natural; --fix=suggest propõe um patch que deve passar por um re-scan verify-the-fix (aplica numa cópia temporária, re-escaneia com o mesmo scanner, mantém só se o achado sumiu e o arquivo parseia; nunca auto-aplica). Reprodutível via temperature=0 + um cache em disco chaveado por fingerprint+provider+model. Degradação graciosa: se o modelo estiver inalcançável o relatório segue sem advice de IA e o scan nunca falha. Todo anexo de IA é rotulado "AI-generated, advisory only" (internal/advisor/).

História de Usuário US-10.3.1 — ✅ atendida

Como desenvolvedor querendo uma recomendação em linguagem natural e um patch candidato, quero um advisor LLM on-host que verifique seu próprio fix antes de mostrá-lo, para que eu receba uma sugestão reprodutível e não-destrutiva que nunca faz meu scan falhar.

Critérios de Aceite

  • [x] --advice-provider=local consulta um endpoint on-host compatível com OpenAI (--advice-endpoint/--advice-model).
  • [x] --fix=suggest re-escaneia uma cópia temporária com o mesmo scanner e mantém o patch só se o achado sumiu e o arquivo parseia; nunca auto-aplica.
  • [x] Reprodutível (temperature=0 + cache por fingerprint+provider+model, --advice-cache).
  • [x] Modelo inalcançável → relatório segue sem advice de IA; scan nunca falha. Anexos rotulados "AI-generated, advisory only".

Feature F-10.4 — Provider remoto (Fase 3) · ✅ Entregue · C · 8 SP

Status: ✅ Entregue. --advice-provider=remote chama uma API externa (auth via QUORUM_ADVICE_API_KEY). Como dados saem do host, é gated por consentimento explícito (--advice-allow-egress), bloqueado por --offline, e recusa --fix (subiria código-fonte). Só o finding normalizado é enviado — nunca código-fonte.

História de Usuário US-10.4.1 — ✅ atendida

Como usuário optando por um modelo hospedado, quero que o provider remoto exija consentimento explícito de egress e nunca suba código-fonte, para que dados saindo do host sejam uma escolha deliberada e auditável.

Critérios de Aceite

  • [x] --advice-provider=remote requer --advice-allow-egress; bloqueado por --offline.
  • [x] Recusa --fix (subiria código-fonte); só o finding normalizado é enviado.
  • [x] Auth via QUORUM_ADVICE_API_KEY; a Action o encaminha via env.

Feature F-10.5 — Métricas advisory + harness de evals · ✅ Entregue · S · 5 SP

Status: ✅ Entregue. Sob --advice três famílias de métricas são emitidas: quorum_advice_enriched{kind=remediation|references|recommendation}, quorum_advice_provider{provider} e quorum_advice_fix{stage=proposed|verified} (verified/proposed = a taxa de verify-the-fix). O harness de evals (internal/evals/) mede a cobertura determinística de remediação, a relevância das referências OWASP e a taxa de verify-the-fix — roda no CI sem modelo pesado.

História de Usuário US-10.5.1 — ✅ atendida

Como mantenedor da camada advisory, quero métricas e um harness de evals para cobertura/relevância/verify-the-fix, para que a qualidade advisory seja observável e testada contra regressão no CI sem um modelo pesado.

Critérios de Aceite

  • [x] quorum_advice_enriched/quorum_advice_provider/quorum_advice_fix emitidas só sob --advice.
  • [x] Evals medem cobertura determinística de remediação, relevância de referências OWASP e a taxa de verify-the-fix.
  • [x] Evals rodam no CI sem um modelo pesado (sem dependência de rede).

14. Itens N/A do template corporativo

Templates corporativos de backlog costumam exigir épicos que não se aplicam ao Quorum por decisão arquitetural (só CLI/Docker, stateless). Declaração explícita (atualizada para v0.8.3):

Item do template Status Justificativa técnica Proposta futura (separada)
Frontend web / dashboard N/A Sem UI/daemon; a saída é um relatório estático e exit code F-3.2 (HTML estático, não um painel)
Banco de dados relacional N/A O estado mínimo é um cache JSON local (internal/cache/store.go); sem persistência relacional
API REST HTTP / autenticação / contas N/A Ferramenta de linha de comando; sem servidor, sem multiusuário
IA / LLM no core N/A confidence é uma fórmula determinística, não um modelo; ver 13-ia.md E10 (camada advisory opt-in, entregue — off por padrão)
Cloud/K8s em runtime N/A O Quorum escaneia manifests (--type k8s), não clusters vivos E9 (runtime, produto separado)

15. Rastreabilidade roadmap → backlog

flowchart LR
    R03["Roadmap v0.3<br/>Kubescape+Polaris, Dockle, XML"] --> F11["F-1.1 Polaris ✅"]
    R10["Roadmap v1.0<br/>OPA/Conftest, cache persistente de aliases, perfis de imagem"]
    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 Perfis de imagem ☐"]
    RS["Roadmap: Syft para SBOM"] --> F13["F-1.3 Syft ☐"]
    RS --> F31["F-3.1 Export SBOM ☐"]
    D12["DESIGN §12/§14<br/>pin por digest, supply chain"] --> F61["F-6.1 Pin digest ✅"]
    D12 --> F62["F-6.2 SBOM+atestado ✅"]
    OBS["Lacuna de observabilidade"] --> F21["F-2.1 log json ✅"]
    OBS --> F23["F-2.3 métricas ◑"]
    IA["21-proposta-ia.md<br/>Fases 0–3"] --> F101["E10 Advisory ✅"]
    RBAC["k8s.yaml: RBAC single-engine"] --> FK1["F-K.1 RBAC consenso ☐"]
    RF["Roadmap futuro<br/>runtime"] --> E9w["E9 · Won't"]
Origem (roadmap/doc) Backlog Status
v0.3 — Polaris F-1.1 ✅ entregue
v0.3 — XML / Dockle ✅ entregue (v0.2.x)
v0.3+ — kube-score, terrascan, tfsec, regula, Conftest E1 (adaptadores) ✅ entregue
v1.0 — policy-as-code OPA/Conftest F-1.2 (modo A ✅), F-4.1 (modo B ☐), F-4.2 ◑ parcial
v1.0 — cache persistente de aliases base + schemaVersion/0600 ✅; F-5.1 (TTL/pruning), F-5.2 ◑ parcial
v1.0 — perfis de imagem F-8.1 ☐ pendente
Syft para SBOM F-1.3, F-3.1 (do alvo) ☐ pendente (a imagem já tem SBOM)
DESIGN §12/§14 — pin por digest, supply chain F-6.1, F-6.2, F-6.4 ✅; F-6.3 ☐ ◑ parcial
Observabilidade (métricas/log) F-2.1 ✅, F-2.3 ◑, F-2.2 ☐ ◑ parcial
Caps anti-DoS + hardening de execução QUORUM_MAX_OUTPUT_BYTES/QUORUM_MAX_TARGET_BYTES, injeção de argumentos, redação ✅ entregue
Action endurecida (cosign, socket, v0 auto, inputs advisory) F-8.2 (parcial) ◑ parcial
21-proposta-ia.md — camada advisory Fases 0–3 E10 (F-10.1–F-10.5) ✅ entregue
crosswalk/k8s.yaml — RBAC single-engine F-K.1 ☐ pendente (documentado)
Limitação "0 achados não é prova de segurança" F-2.2, F-3.2 (avisos), F-7.1 ☐ pendente
Limitação de granularidade de MISCONFIG (README.md §Known limitations) candidato a um futuro Épico "identidade por recurso" (a refinar)
futuro — runtime E9 (Won't) Won't

16. Próximos passos sugeridos (candidato ao primeiro sprint)

Com os Musts de supply-chain (F-6.1/F-6.2), os adaptadores (F-1.1/F-1.2) e a camada advisory (E10) já entregues, a próxima janela foca em fechar as fatias parciais de maior desbloqueio, ~26 SP:

  • [ ] F-5.1 Cache TTL + pruning (5 SP) — fetchedAt + cache prune sobre o schema já versionado.
  • [ ] F-2.2 run-summary.json (5 SP) — desbloqueia dashboards e explain.
  • [ ] F-4.1 (modo B) Gate por política sobre achados (8 SP) — completa a camada policy-as-code.
  • [ ] F-1.4 Adaptador Hadolint (5 SP) — dá ao Dockle um peer para consenso IMG_HARDENING.
  • [ ] F-3.3 Enriquecer SARIF (3 SP) — melhora a triagem no GitHub sem regressão de dedup.

Premissas

  • Versão de referência. Backlog alinhado à v0.8.3 (revisão 2026-07-04); os estados as-is (o que já existe vs. lacuna) foram checados na leitura do código: cmd/quorum/scan.go, internal/adapter/ (12 adaptadores registrados via init()→Register), internal/cache/store.go, internal/report/, internal/enrich/, internal/rag/, internal/advisor/, crosswalk/, além de DESIGN.md e README.md.
  • Itens já entregues permanecem para rastreabilidade. Adaptadores (Polaris, kube-score, terrascan, tfsec, regula, Conftest), consenso via crosswalk, observabilidade (--metrics/--log-format json), supply chain (pin @sha256, checksum, atestado SLSA/SBOM SPDX), caps anti-DoS e a camada advisory opt-in (E10) já existem no código (v0.3→v0.8.3); aparecem marcados e o backlog cobre apenas suas evoluções restantes.
  • Estimativas são relativas. Story points de Fibonacci refletem o esforço/risco relativo de um time que conhece o código, não horas. Itens de 13/21 SP devem ser quebrados antes do sprint.
  • MoSCoW é por momento. A classificação reflete a próxima janela de release; "Won't" significa "agora não", não "nunca" (especialmente E9, condicional a uma decisão de produto).
  • Escopo CLI/Docker preservado. Nenhum item propõe um frontend web, banco de dados relacional, API REST HTTP, autenticação/contas ou IA/LLM no core; esses são listados como N/A (§14) por decisão arquitetural. A camada advisory (E10) é opt-in, apenas de apresentação e off por padrão — ela não muda isso: o core determinístico não tem IA.
  • Determinismo é um invariante. Qualquer feature deve preservar correlationKey/Fingerprint determinísticos e o princípio false split > false merge; mudanças que alteram a entrada (ex.: uma nova versão de scanner) podem legitimamente alterar a saída. A camada advisory nunca toca em correlationKey/fingerprint/confidence/severidade agregada ou no gate fail-on.
  • Flags/comandos entregues vs. propostos. Já na CLI: --metrics, --log-format, --baseline (leitura), --min-severity, --fail-on, --crosswalk, --cache, --offline, as flags advisory (--advice, --advice-provider, --advice-endpoint, --advice-model, --advice-embed-model, --advice-cache, --advice-max, --advice-allow-egress, --fix) e o subcomando advise-index, mais o passthrough por env QUORUM_<SCANNER>_ARGS (ex.: QUORUM_CHECKOV_ARGS com bc-api-key destrava políticas Prisma) e os caps QUORUM_MAX_OUTPUT_BYTES/QUORUM_MAX_TARGET_BYTES. Ainda inexistentes (são propostas deste backlog, a confirmar no refinamento): --summary-file, --sbom/--sbom-output, --baseline-write, --cache-ttl, quorum.policy.yaml e os subcomandos explain/cache prune.
  • Crosswalk como dívida gerenciada — porém já ativa. O consenso de misconfig/K8s está ligado com um crosswalk derivado de saída real (false split > false merge): cloud (hub AVD), K8s (hub C-####), tfsectrivy via AVD nativo. Novos mapeamentos assumem manutenção incremental (controles top-N) e evidência de sobreposição antes de mapear, conforme DESIGN.md §6/§14.
  • RBAC segue single-engine por decisão de qualidade. Os controles RBAC do kubescape ficam não mapeados em crosswalk/k8s.yaml porque requerem contexto de cluster vivo e nenhum segundo engine dispara no mesmo objeto estático; o consenso de RBAC (F-K.1) só entra com sobreposição verificada.