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 (
--metricstextfile 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
correlationKey—DESIGN.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 vetemake buildverdes (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/--fixpode alterarcorrelationKey/fingerprint/confidence/severidade agregada ou o gatefail-on— sem--advicea 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/§13 — fora 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 emitemodel.Findingcanônico e não computacorrelationKey.Estado v0.8.3 — 12 adaptadores registrados (
init()→Registereminternal/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.goimplementaAdaptercomCapabilities → model.TypeK8sPosture(alvok8s). O crosswalkcrosswalk/k8s.yaml(hub kubescapeC-####) 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-scannersmostrapolariscom tipoK8S_POSTUREe alvok8s. - [x]
quorum scan ./k8s --type k8s --scanners kubescape,polaris,kube-scoreproduz, para um manifest com privilégio elevado, umMergedFindingcomdetectedByde múltiplos engines edetectionCount ≥ 2. - [x] A severidade do Polaris é normalizada pela tabela única (
DESIGN.md§10). - [x] O crosswalk mapeia o check do Polaris →
canonicalControl(hubC-####; 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.goavalia o Rego do usuário (por padrão em./policy, ou viaQUORUM_CONFTEST_ARGS="--policy <dir>"). Sem políticas, o adaptador reportaerrorde propósito — policy-as-code é opt-in e o Quorum não empacota políticas opinativas (DESIGN.md§2). Violações viramFindingsMISCONFIG(isolados comRuleID: "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 conftestroda políticas Rego sobre o alvorepo/k8s. - [x] Violações viram
Findings do tipoMISCONFIG(comRuleIDisoladopolicy). - [x] O usuário traz suas próprias regras via
./policy(ouQUORUM_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-sbomgeram 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 paraIMG_HARDENING("sem peer para consenso ainda",README.md§scanners). Um segundo engine de imagem/Dockerfile permitiriadetectionCount ≥ 2nessa 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
- [ ]
hadolintregistrado; alvorepo(detectaDockerfile*). - [ ] Regras
DL****mapeadas paracanonicalControlquando equivalentes aos controles CIS-DI do Dockle (potencialdetectionCount ≥ 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.yamldeixa 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 ≥ 2sem 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;tfsecauto-correlaciona comtrivyporque 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,writeMetricsFileemcmd/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}equorum_advice_fix{stage=proposed|verified}(ver E10). O resumo humano nostderr(printSummary) permanece. Falta umrun-summary.jsonestruturado.
Feature F-2.1 — Logs estruturados · ✅ Entregue · S · 5 SP¶
Status: ✅ Entregue.
--log-format text|json(padrãotext, compatível com[quorum] …); um valor inválido é rejeitado (invalid --log-format).--quietainda 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ãotext, retrocompatível). - [x] Eventos do orquestrador (start/stop/timeout/unavailable de scanner) emitidos no formato escolhido.
- [x]
--quietainda suprime logs de progresso; erros sempre visíveis. - [x] Sem segredos nos logs (redação: o
Matchdo 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
printSummaryhumano 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.jsonescreve: por scanner{name,status,findings,duration,error},mergedCount,multiDetected, rollup por severidade eelapsed. - [ ] O conteúdo espelha exatamente o
printSummaryatual (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--adviceestá 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.promescreve 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.jsongera 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,
confidencee status por scanner sem ferramentas extras.
Critérios de Aceite
- [ ]
--format html -o report.htmlproduz HTML standalone (sem JS externo, sem rede). - [ ] Mostra uma tabela de
MergedFindingordenada porseverityeconfidence, comdetectedBy. - [ ] 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 aindasecurity-severity,help.textoutagspor regra.
História de Usuário US-3.3.1¶
Como usuário do GitHub code scanning, quero que o SARIF carregue
security-severity,helpetagspor 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.textcom origem (detectedBy) e o link do controle canônico (AVD/CIS) quando presente. - [x]
partialFingerprintspreservados (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 viaconftest(F-1.2): carrega o Rego do usuário de./policy/QUORUM_CONFTEST_ARGS, sem política empacotada, e degrada com statuserrorsem corromper o relatório. Falta o modo B: avaliar política sobre os próprios[]MergedFindingpara 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
FindingsMISCONFIG. - [ ] Modo B: política sobre
[]MergedFinding→ pode decidir o gate (ex.: "bloquear se algum finding tiverconfidence ≥ 0.8eseverity ≥ HIGH"). - [x] Degradação graciosa: um erro de avaliação de política → status
errordo "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: arquivoaliases.jsoncom permissão0600eschemaVersion(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.
schemaVersione perm0600entregues (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 720hrevalida entradas expiradas via OSV (respeita--offline). - [x] Cache corrompido/ilegível ainda gera um cache vazio (sem quebrar o scan — invariante atual).
- [ ]
quorum cache pruneremove 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
sha256da 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.yamlerelease.ymlforam 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, maisBuildKit sbom: true; cosign keyless com retry; DB do grype pré-cacheado comGRYPE_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:--outputcomfilepath.Cleane perm0600; id OSV validado eurl.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.fullreferencia 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.ymlassina 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-sbomgera um SBOM SPDX atestado da imagem e por-binário (GoReleaser/syft), maisBuildKit sbom: true; atestado SLSA build-provenance verificável viagh attestation verify; assinatura keyless verificável viacosign verify. A GitHub Action (action.ymlcomposite) 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/:slimpubliquem 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.ymlgera 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 verifyda 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
/worksegue gravável quando necessário). - [ ] Compatível com
--read-only+--cap-drop ALLdocumentados 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 jobknowledgeemrelease.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
knowledgeatestaknowledge/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-indexpreserva o pin (F-10.2).
10. Épico E7 — UX / CLI¶
Estado v0.8.3: comandos
scan,list-scannerseadvise-index; saída humana nosummarydostderr(printSummary); baseline somente-leitura via--baseline(padrão.quorumignore,cmd/quorum/scan.go). Faltam UX de terminal (tabela colorida), geração de baseline eexplain.
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--formatnão foi forçado, mostrar uma tabela legível (severidade colorida,detectionCount,confidence). - [ ] Cores off se
NO_COLORestiver setado ou a saída for non-TTY (o CI segue estável). - [ ]
--quietsuprime; 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 oconfidencetem 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
--baselinesó lê 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-onpela primeira vez num repo com achados legados, quero gerar um.quorumignorea 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 .quorumignoreescreve 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.sockemtype: image(evita um falso-zero num scan de imagem local) e expõe os inputsscanner-argsedocker-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-adicionahost-gatewaypara o providerlocale encaminha a API key via env pararemote. A tag móvelv0é auto-avançada pelotag-major.ymla cada release semver. Imagens:full(linux/amd64) e:slim(amd64+arm64) no GHCR; GoReleaser para binários; exemplos emexamples/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óvelv0, 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/cachepara~/.cache/quorum(integra com F-5.1). - [x] A tag móvel
v0funciona (auto-avançada portag-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--advicea saída é byte-idêntica, e nenhuma fase toca emcorrelationKey/fingerprint/confidence/severidade agregada ou no gatefail-on. O core determinístico segue sem IA; as partes de IA são estritamente opt-in. Novos campos no modeloMergedFinding:Remediation,References,Advice(tiposmodel.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 subcomandoquorum 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/type— sem modelo (internal/enrich/; dados emknowledge/*.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]
--adviceanexaRemediation/Referencescasados porcanonicalControl/ruleId/category/type. - [x] Totalmente determinístico, sem modelo; sem
--advicea saída é byte-idêntica. - [x] Nunca altera
correlationKey/fingerprint/confidence/severidade agregada ou o gatefail-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 viaquorum advise-index— oscanescolhe 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-indexembute o corpus preservando o pin. - [x] O
scanauto-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=localconsulta um endpoint on-host compatível com OpenAI (ex.: Ollama) para uma recomendação em linguagem natural;--fix=suggestpropõ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 viatemperature=0+ um cache em disco chaveado porfingerprint+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=localconsulta um endpoint on-host compatível com OpenAI (--advice-endpoint/--advice-model). - [x]
--fix=suggestre-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 porfingerprint+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=remotechama uma API externa (auth viaQUORUM_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=remoterequer--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
--advicetrês famílias de métricas são emitidas:quorum_advice_enriched{kind=remediation|references|recommendation},quorum_advice_provider{provider}equorum_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_fixemitidas 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 prunesobre o schema já versionado. - [ ] F-2.2
run-summary.json(5 SP) — desbloqueia dashboards eexplain. - [ ] 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 viainit()→Register),internal/cache/store.go,internal/report/,internal/enrich/,internal/rag/,internal/advisor/,crosswalk/, além deDESIGN.mdeREADME.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/Fingerprintdeterminí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 emcorrelationKey/fingerprint/confidence/severidade agregada ou no gatefail-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 subcomandoadvise-index, mais o passthrough por envQUORUM_<SCANNER>_ARGS(ex.:QUORUM_CHECKOV_ARGScombc-api-keydestrava políticas Prisma) e os capsQUORUM_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.yamle os subcomandosexplain/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 (hubC-####),tfsec↔trivyvia AVD nativo. Novos mapeamentos assumem manutenção incremental (controles top-N) e evidência de sobreposição antes de mapear, conformeDESIGN.md§6/§14. - RBAC segue single-engine por decisão de qualidade. Os controles RBAC do kubescape ficam não mapeados
em
crosswalk/k8s.yamlporque 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.