Ir para o conteúdo

Checklists

Este documento reúne cinco checklists acionáveis para o ciclo de vida do Quorum (quorum-sec-scan, v0.8.3): Desenvolvimento, QA, Segurança, Deploy/Release e Produção/Operação. Cada item é específico ao fluxo real do projeto — uma ferramenta CLI/Docker de consensus security scanning escrita em Go 1.26, distribuída como imagens assinadas no GHCR e binários nativos via GoReleaser. Os itens são verificáveis (com um comando ou critério de aceite) e ancorados no comportamento do código (cmd/quorum, internal/*) e dos workflows (.github/workflows/{ci,e2e,release,tag-major}.yml, action.yml).

Princípio que atravessa todas as checklists: "false split > false merge" e "0 findings não é prova de segurança". Um item só está "pronto" quando você consegue provar que os scanners rodaram (status ran) — não quando o relatório voltou vazio.

Links úteis: Visão geral · Arquitetura · DevOps · Infraestrutura · Observabilidade · Roadmap.


Mapa do fluxo (onde cada checklist atua)

flowchart LR
    DEV["1. Desenvolvimento\n(branch + código + testes locais)"]
    PR["Pull Request → main"]
    CI["CI: ci.yml + e2e.yml\n(vet, test -race, coverage, build, consenso real)"]
    QA["2. QA\n(verificação funcional + testes de contrato)"]
    SEC["3. Segurança\n(fronteira de confiança, supply chain)"]
    MERGE["Merge na main"]
    TAG["Tag semver vX.Y.Z"]
    REL["4. Deploy/Release\nrelease.yml: imagens + binários\ncosign + SLSA + SBOM atestados"]
    OPS["5. Produção/Operação\nmount, socket, fail-on, baseline, verificação"]

    DEV --> PR --> CI
    CI --> QA
    CI --> SEC
    QA --> MERGE
    SEC --> MERGE
    MERGE --> TAG --> REL --> OPS
    OPS -. feedback / triagem de baseline .-> DEV
Estágio real Gatilho Workflow / artefato Checklist
Código numa branch trabalho local make test/vet/build 1. Desenvolvimento
PR para main pull_request ci.yml, e2e.yml 2. QA
Revisão da cadeia PR / pré-release release.yml, action.yml, Dockerfile.full 3. Segurança
Tag vX.Y.Z push de uma tag semver release.yml (imagens+binários) 4. Deploy/Release
Tag móvel v0/v0.8 release publicado tag-major.yml (auto-avança) 4. Deploy/Release
Uso em pipeline docker run / action imagem :full/:slim 5. Produção/Operação

1. Checklist de Desenvolvimento

Objetivo: garantir que uma mudança seja fiel à arquitetura do Quorum, passe pelos gates locais antes do PR e honre os contratos dos adapters. Reproduz localmente o que o ci.yml exige.

1.1 Setup e branch

  • [ ] Go 1.26+ instalado (go version) — é a versão fixada em ci.yml, e2e.yml e release.yml.
  • [ ] Trabalho feito numa branch a partir da main (nunca commit direto na main); o fluxo é sempre via PR.
  • [ ] Scanners OSS necessários no PATH para teste manual ponta a ponta, ou uso da imagem :full. Há 12 adapters registrados (internal/adapter/*.go, via init()/Register):
  • [ ] VULN/SCA: trivy, grype.
  • [ ] MISCONFIG/IaC: trivy, checkov, kics, terrascan, tfsec, regula (+ conftest para policy-as-code).
  • [ ] K8S_POSTURE: kubescape, polaris, kube-score.
  • [ ] IMG_HARDENING: dockle.
  • [ ] SECRET: trivy (com redação do Match).
  • Ferramentas ausentes são reportadas como unavailable e não quebram o build.

1.2 Aderência à arquitetura (as-is)

  • [ ] A mudança respeita as fronteiras de pacotes: cmd/quorum (CLI cobra) vs. internal/{adapter,orchestrator,correlate,consensus,alias,cache,crosswalk,filter,model,purl,report,severity}.
  • [ ] Nada introduz dependência de um frontend web, banco de dados relacional ou API REST — fora do escopo do produto (apenas CLI/Docker).
  • [ ] O núcleo determinístico permanece sem IA: qualquer IA/LLM vive na camada consultiva opt-in (internal/{enrich,rag,advisor}), está desligada por padrão e é apenas de apresentação — nunca toca correlationKey, fingerprint, confidence, severidade agregada ou o gate de fail-on.
  • [ ] Nova saída/normalização converge para o modelo canônico model.Finding (nenhum formato bruto de scanner vaza para fora do adapter). Os novos campos consultivos (Remediation, References, Advice) pendem de MergedFinding e são preenchidos apenas sob --advice.
  • [ ] Se a mudança afeta a correlação, o correlationKey permanece determinístico por tipo (VULN/MISCONFIG/K8S_POSTURE/etc — DESIGN §6) e o princípio false split > false merge se sustenta (na dúvida, isolar e marcar unmapped).
  • [ ] O secret/Match do Trivy é redigido antes de sair do adapter (não vazar uma credencial para o relatório).

1.3 Adapters (quando aplicável)

  • [ ] O adapter implementa toda a interface Adapter: Name / Version / Supports / Capabilities / Run.
  • [ ] Existe um teste de contrato contra um fixture versionado em internal/adapter/testdata (uma mudança de formato deve quebrar o teste antes de quebrar a produção).
  • [ ] Version(ctx) é leve o bastante para o probe de 60s (Options.ProbeTime) e distingue corretamente ausência vs. lentidão.
  • [ ] Supports(target) reflete os alvos reais do scanner (ex.: grype não suporta k8s; dockle/kube-score são single-target; trivy suporta os três tipos).
  • [ ] Passthrough honrado: o adapter anexa extraArgs(<name>) (lido de QUORUM_<NAME>_ARGS) aos seus argumentos, sem quebrar o parse da saída.
  • [ ] Buffer de stdout limitado por QUORUM_MAX_OUTPUT_BYTES (padrão 512 MiB) — saída acima disso é abortada com um erro claro (anti-OOM).

1.4 Camada consultiva (quando aplicável)

  • [ ] Fase 0 (determinística, sem modelo): templates de remediação curados + referências OWASP casados por canonicalControl/ruleId/category/type (pacote internal/enrich; dados em knowledge/*.yaml — aws/azure/gcp/k8s/image/categories). Templates novos/editados mantêm a saída byte-idêntica quando --advice está desligado.
  • [ ] Fase 2 (RAG-as-artifact, determinística): recuperação a partir de um corpus OWASP versionado e com digest fixado (knowledge/owasp/corpus.yaml, pacote internal/rag). Recuperação lexical por padrão (sem modelo); semântica apenas quando o corpus é embedado via quorum advise-index, e o scan escolhe automaticamente a semântica quando o corpus tem vetores — o digest fixado é preservado.
  • [ ] Fase 1 (LLM local opt-in, internal/advisor): reproduzível via temperature=0 + um cache em disco chaveado por fingerprint+provider+model; --fix=suggest precisa passar por um re-scan verify-the-fix (aplicar numa cópia temporária, re-escanear com o mesmo scanner, manter só se o finding sumiu e o arquivo parseia) e nunca aplica automaticamente. Degradação graciosa: se o modelo estiver inacessível o relatório sai sem o conselho de IA e o scan nunca falha.
  • [ ] Fase 3 (provedor remoto opt-in): envia apenas o finding normalizado, nunca código-fonte; condicionada a --advice-allow-egress, bloqueada por --offline e recusa --fix.
  • [ ] Todo anexo de IA é rotulado "AI-generated, advisory only".
  • [ ] Evals atualizados quando o comportamento consultivo muda: 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).

1.5 Gates locais (espelho do ci.yml)

  • [ ] make vet (ou go vet ./...) sem findings.
  • [ ] make test / go test -race ./... verde (testes unitários + de contrato + de eval); cobertura reportada no CI.
  • [ ] make build / go build -trimpath -o dist/quorum ./cmd/quorum compila.
  • [ ] Smoke: ./dist/quorum list-scanners lista os 12 adapters registrados.
  • [ ] Teste funcional manual: ./dist/quorum scan <target> --format json produz um relatório e o resumo em stderr mostra o status por scanner.
  • [ ] Smoke consultivo (opcional): ./dist/quorum scan <target> --advice anexa remediação/referências determinísticas sem alterar os fingerprints; o mesmo scan sem --advice produz saída byte-idêntica.

1.6 Higiene do PR

  • [ ] Crosswalk novo/alterado em crosswalk/*.yaml segue o schema e o hub por família de nuvem/plataforma:
  • [ ] aws.yaml / azure.yaml / gcp.yaml — hub AVD (S3/IAM/EBS/SG/RDS/ KMS/CloudTrail/VPC-flow-logs; Azure Storage/Key Vault; GCP bucket/ firewall/SQL).
  • [ ] k8s.yaml — hub C-#### (kubescape) correlacionando kubescape × polaris × kube-score (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, secrets).
  • Uma regra sem mapeamento não é "adivinhada" (permanece unmapped); o crosswalk é derivado de saída real (favorece false split sobre false merge).
  • [ ] Uma mudança em ./policy (Rego) para conftest vem com um teste — o conftest não tem regras próprias, ele avalia SEU Rego (padrão ./policy).
  • [ ] Documentação atualizada quando o comportamento muda (README.md, README.pt-BR.md, DESIGN.md, este docs/ e a documentação publicada no GitHub Pages via MkDocs Material).
  • [ ] PR aberto contra main; aguarda ci.yml e e2e.yml verdes.

2. Checklist de QA

Objetivo: validar o comportamento observável do Quorum — consenso real, exit codes, formatos e transparência de status — não apenas "os testes unitários passaram". Ancorado no e2e.yml, que roda scanners reais (não fixtures).

2.1 Suíte automatizada (PR)

  • [ ] ci.yml verde: vet + go test -race ./... + cobertura + build + smoke.
  • [ ] e2e.yml verde nos cenários de consenso:
  • [ ] IaC/MISCONFIG (Trivy + Checkov/KICS/tfsec/terrascan/regula sobre examples/terraform) com summary.multiDetected >= 1.
  • [ ] SCA/VULN (Trivy + Grype sobre alpine:3.10) com summary.multiDetected >= 1.
  • [ ] K8S_POSTURE (kubescape × polaris × kube-score) correlacionando via crosswalk/k8s.yaml.
  • [ ] Testes de contrato dos adapters cobrem o fixture atualizado da versão real da ferramenta.

2.2 Transparência de execução (status por scanner)

  • [ ] O relatório expõe status por scanner: ran | skipped | unavailable | error | timeout.
  • [ ] O cenário "ferramenta ausente" produz unavailable e não falha o scan.
  • [ ] O cenário "timeout por scanner" (--timeout curto) produz status timeout e uma mensagem de erro associada, não ran.
  • [ ] conftest sem políticas em ./policy reporta error (esperado — policy-as-code é opt-in), não ran com 0 findings.
  • [ ] Validar manualmente que "0 findings" vem acompanhado dos status — um 0 com tudo ran é diferente de um 0 com tudo unavailable.

2.3 Exit codes (gate)

Cenário de teste Comando Exit esperado
Sem --fail-on, ou nada atinge o limiar scan … 0
Finding ≥ --fail-on scan … --fail-on high 1
Erro de uso / runtime scan sem target, --type inválido, --log-format inválido 2
  • [ ] 0 quando nenhum finding atinge --fail-on (ou a flag está ausente).
  • [ ] 1 quando há um finding com severidade ≥ --fail-on (gate dispara, log gate: found … >= --fail-on … → exit 1).
  • [ ] 2 em erro de uso/runtime (ex.: --fail-on inválido, --format inválido, --log-format diferente de text|json, uma baseline inexistente passada explicitamente via --baseline, um target começando com - recusado, um target acima de QUORUM_MAX_TARGET_BYTES, um --advice-provider inválido, ou --advice-provider=remote sem --advice-allow-egress).

2.4 Formatos de saída e telemetria

  • [ ] SARIF (padrão): contém partialFingerprints["quorum/v1"] = sha256(correlationKey) e properties.detectedBy/detectionCount/confidence.
  • [ ] JSON: campo fingerprint, summary.multiDetected, scanners[] com status e contagem, rollup de severidade.
  • [ ] XML: a mesma estrutura serializada (pipelines legadas/estilo JUnit).
  • [ ] --output/-o escreve num arquivo: o caminho passa por filepath.Clean, cria o diretório pai se preciso e escreve com perm 0600 (o relatório pode conter detalhe sensível); sem -o escreve em stdout.
  • [ ] --metrics <file> escreve métricas em formato texto Prometheus (textfile collector), perm 0644 (contagens não sensíveis).
  • [ ] --log-format text|json controla o log de progresso em stderr (json emite {ts,level,msg}).

2.5 Severidade, baseline e min-severity

  • [ ] --min-severity remove findings abaixo do limiar do relatório e do gating; as supressões são logadas (filtered: … below min-severity <sev>).
  • [ ] --baseline/.quorumignore suprime por fingerprint ou correlationKey; as supressões são sempre logadas (nunca descartadas silenciosamente; o log carrega a contagem de entradas e de itens suprimidos).
  • [ ] Uma linha de comentário (#) e linhas em branco no .quorumignore são ignoradas corretamente.

2.6 Resolução de aliases

  • [ ] Com rede: CVE-… (Trivy) e GHSA-… (Grype) para o mesmo bug correlacionam (alias local → cache ~/.cache/quorum/aliases.json → OSV.dev, CVE preferido). O id OSV é validado e passa por url.PathEscape.
  • [ ] --offline: nenhuma chamada à OSV; degradação graciosa (usa aliases locais + cache).
  • [ ] Uma falha de rede simulada não derruba o scan (degradação graciosa).
  • [ ] O cache de aliases é escrito com perm 0600 e carrega um schemaVersion compatível (um arquivo corrompido/de versão antiga é ignorado, não quebra).

2.7 Camada consultiva (apenas sob --advice)

  • [ ] Byte-idêntico sem --advice: o mesmo scan com e sem a flag produz saída idêntica (a camada consultiva é só de apresentação; nunca toca correlationKey/fingerprint/confidence/severidade/o gate).
  • [ ] A Fase 0 anexa Remediation/References determinísticos casados por controle/regra/categoria/tipo; sem necessidade de rede.
  • [ ] Fase 2: a recuperação lexical funciona com o corpus de digest fixado offline; após quorum advise-index, o scan escolhe automaticamente a recuperação semântica.
  • [ ] --advice-provider=local degrada graciosamente quando o endpoint está inacessível (relatório sai sem o conselho de IA, scan não falha); reproduzível via temperature=0 + cache por fingerprint.
  • [ ] --fix=suggest só mantém um patch que passa no re-scan verify-the-fix (finding sumiu + arquivo ainda parseia) e nunca aplica automaticamente.
  • [ ] --advice-provider=remote envia apenas o finding normalizado (títulos, caminhos, controles — nunca o fonte), exige --advice-allow-egress, é bloqueado por --offline e recusa --fix.
  • [ ] Todo anexo de IA é rotulado "AI-generated, advisory only".
  • [ ] Métricas sob --advice presentes quando --metrics é usado: quorum_advice_enriched{kind=remediation|references|recommendation}, quorum_advice_provider{provider}, quorum_advice_fix{stage=proposed|verified} (verified/proposed = a taxa de verify-the-fix).

3. Checklist de Segurança

Objetivo: tratar a própria cadeia do Quorum como uma fronteira de confiança e validar as garantias de supply chain (DESIGN §12). Cobre tanto o que o Quorum produz quanto o que ele consome (binários de scanner empacotados).

3.1 Supply chain do release

  • [ ] Imagens são assinadas com cosign sem chave (OIDC), sobre o digest do manifest, com retry — verificar antes de usar:
    cosign verify ghcr.io/martinez1991/quorum-sec-scan:slim \
      --certificate-identity-regexp \
        "https://github.com/Martinez1991/quorum-sec-scan/.github/workflows/release.yml@.*" \
      --certificate-oidc-issuer https://token.actions.githubusercontent.com
    
  • [ ] Atestação de build-provenance SLSA presente e verificável (imagem):
    gh attestation verify oci://ghcr.io/martinez1991/quorum-sec-scan:full \
      --repo Martinez1991/quorum-sec-scan
    
  • [ ] SBOM SPDX atestado (actions/attest-sbom, via syft) verificável — além da atestação sbom: true do BuildKit:
    gh attestation verify oci://ghcr.io/martinez1991/quorum-sec-scan:full \
      --repo Martinez1991/quorum-sec-scan --predicate-type https://spdx.dev/Document
    
  • [ ] Binários nativos: checksums.txt + assinatura cosign (cosign verify-blob) + atestação SLSA por subject-checksums (gh attestation verify quorum_<ver>_<os>_<arch>.tar.gz --repo …) + SBOM SPDX por binário (GoReleaser/syft).
  • [ ] Knowledge pack atestado: o knowledge pack consultivo + crosswalk recebem uma atestação de build-provenance SLSA a cada release (job knowledge do release.yml) — verifique o corpus antes de confiar na camada consultiva offline:
    gh attestation verify knowledge/owasp/corpus.yaml \
      --repo Martinez1991/quorum-sec-scan
    
  • [ ] O próprio release.yml re-verifica a atestação (imagem e binário) como etapa do release, com retry — um release com atestação quebrada deve falhar.

3.2 Permissões e identidade no CI

  • [ ] release.yml mantém permissions mínimas: contents: read (job images), packages: write, id-token: write (cosign keyless), attestations: write (SLSA + SBOM + knowledge pack).
  • [ ] O job binaries usa contents: write apenas para criar o release (mais id-token/attestations: write).
  • [ ] O gatilho de release é restrito a tags semver v[0-9]+.[0-9]+.[0-9]+ — tags móveis (v0, v0.8, usadas para fixar a action) não disparam um build; elas são avançadas por tag-major.yml no evento release.

3.3 GitHub Action composta (action.yml)

  • [ ] Por padrão verify: "true" → cosign-verifica a imagem :full antes de rodá-la (instala o cosign se ausente).
  • [ ] Em produção, image é fixada por @sha256:<digest> (não uma tag móvel) e a action é fixada por @<sha>.
  • [ ] docker-socket revisado: para type: image o socket /var/run/docker.sock é auto-montado (evita um falso-zero ao escanear uma imagem local recém-buildada); off desativa mesmo para imagem, true força para outros tipos. Sem o socket, um scan de imagem local emite um warning.
  • [ ] Inputs de passthrough (trivy-args, grype-args, checkov-args, kics-args, dockle-args, kubescape-args) revisados — podem carregar secrets (ex.: checkov --bc-api-key para Prisma/Bridgecrew) e por isso não são ecoados no log.
  • [ ] Inputs consultivos revisados: advice, advice-provider, advice-endpoint, advice-model, advice-embed-model, advice-max, advice-cache, advice-allow-egress, advice-api-key, fix. Para local a action auto-adiciona host-gateway; para remote a advice-api-key é encaminhada via env (nunca na linha de comando) e o egress exige consentimento explícito.
  • [ ] Inputs sensíveis (baseline, crosswalk, offline) revisados quanto a impacto de segurança (ex.: uma baseline não estar suprimindo um risco real).

3.4 Binários de scanner empacotados (imagem :full)

  • [ ] Reconhecido que os binários OSS empacotados fazem parte da fronteira de confiança do consumidor (THIRD_PARTY_NOTICES.md lista as licenças).
  • [ ] Bases de imagem fixadas por @sha256; downloads de scanner (kubescape, tfsec, terrascan, regula, conftest) verificados por checksum no Dockerfile.full.
  • [ ] DB do Grype pré-cacheado no :full, de fonte confiável (Anchore), buildado com GRYPE_DB_VALIDATE_AGE=false (não expira em runners sem egress) — a versão bate com o schema suportado.

3.5 Seguro por padrão (hardening)

  • [ ] --offline disponível para ambientes sem egress (desliga a OSV e bloqueia --advice-provider=remote).
  • [ ] O egress de IA é desligado por padrão e opt-in: --advice-provider=remote exige --advice-allow-egress explícito, envia apenas o finding normalizado (nunca o fonte) e recusa --fix. --advice-provider=local e as fases determinísticas nunca saem do host.
  • [ ] Injeção de argumento bloqueada: um target começando com - é recusado (use ./-name).
  • [ ] Limites anti-DoS ativos: QUORUM_MAX_OUTPUT_BYTES (512 MiB) e QUORUM_MAX_TARGET_BYTES (20 GiB) — sobrescrever/desativar por env.
  • [ ] --output normalizado (filepath.Clean) e escrito com perm 0600; métricas com 0644.
  • [ ] Supressões (--baseline, --min-severity) são auditáveis: sempre logadas; a revisão garante que nenhuma entrada está mascarando um finding ativo.
  • [ ] Cache de aliases (~/.cache/quorum/aliases.json, perm 0600, com schemaVersion) tratado como dado não confiável/derivado (pode ser apagado sem perda de correção); o cache consultivo (--advice-cache) é igualmente derivado e seguro de apagar.
  • [ ] O secret do Trivy (Match) é redigido — o relatório não vaza uma credencial.
  • [ ] Falsos negativos por um mount malformado são prevenidos (ver checklist 5.1) — um /work vazio reporta 0 findings.

4. Checklist de Deploy/Release

Objetivo: executar um release reproduzível e assinado. O release é disparado por um push de uma tag semver vX.Y.Z; release.yml builda/publica imagens (:full, :slim) e binários (GoReleaser), assina e atesta tudo (cosign + SLSA + SBOM SPDX + knowledge pack).

4.1 Pré-tag

  • [ ] main está verde (ci.yml + e2e.yml) no commit a ser tagueado.
  • [ ] A versão escolhida segue semver estrito vX.Y.Z (ex.: v0.8.3) — o release.yml só dispara para v[0-9]+.[0-9]+.[0-9]+.
  • [ ] CHANGELOG/notas conferidos; o GoReleaser tem histórico completo (fetch-depth: 0) para gerar o changelog.
  • [ ] O crosswalk empacotado revisado (crosswalk/{aws,azure,gcp,k8s}.yaml) — é empacotado em /opt/quorum/crosswalk nas imagens e binários.
  • [ ] Políticas Rego em ./policy (se houver) revisadas — vão junto para uso do conftest.
  • [ ] O knowledge pack consultivo revisado (knowledge/*.yaml, knowledge/owasp/corpus.yaml) — o digest fixado do corpus está intacto e o pack vai empacotado para a Fase 0/2 offline.

4.2 Disparando o release

  • [ ] Tag criada e enviada:
    git tag v0.8.3
    git push origin v0.8.3
    
  • [ ] O workflow release.yml iniciou para a tag (não para uma tag móvel).

4.3 Imagens (job images)

  • [ ] :full publicada em linux/amd64 com as tags :full, :<version>, :<version>-full, :latest (todos os 12 scanners empacotados; DB do Grype pré-cacheado).
  • [ ] :slim publicada em linux/amd64,linux/arm64 com as tags :slim, :<version>-slim (apenas o orquestrador).
  • [ ] provenance: true e sbom: true no build-push (BuildKit).
  • [ ] cosign sign (com retry) aplicado ao digest do manifest (cobre todas as tags que apontam para ele).
  • [ ] actions/attest-build-provenance gerou e enviou a atestação SLSA para o GHCR.
  • [ ] actions/attest-sbom gerou e enviou o SBOM SPDX atestado (syft → sbom.spdx.json).
  • [ ] A etapa "Verify provenance attestation" passou (re-checagem ponta a ponta, com retry).

4.4 Binários (job binaries, apenas em tag)

  • [ ] GoReleaser publicou arquivos por OS/arch + checksums.txt + assinatura cosign, com SBOMs SPDX por binário (syft).
  • [ ] Atestação SLSA por subject-checksums: dist/checksums.txt gerada.
  • [ ] A etapa de verificação ("spot-check" de um artefato) passou (com retry).

4.5 Knowledge pack (job knowledge)

  • [ ] O knowledge pack consultivo + crosswalk receberam uma atestação de build-provenance SLSA neste release — verifique antes de confiar na camada consultiva:
    gh attestation verify knowledge/owasp/corpus.yaml \
      --repo Martinez1991/quorum-sec-scan
    

4.6 GitHub Action / tag móvel

  • [ ] Tag móvel v0 (e v0.8) auto-avançada por tag-major.yml no evento release — pin da action uses: Martinez1991/quorum-sec-scan@v0.
  • [ ] Mover v0/v0.8 não dispara um novo build de release (o gatilho é restrito a semver).

4.7 Validação pós-publicação (lado do consumidor)

  • [ ] cosign verify da imagem recém-publicada OK (ver 3.1).
  • [ ] gh attestation verify da imagem (provenance e SBOM), de um binário, e do corpus de knowledge OK.
  • [ ] docker run --rm … :full list-scanners lista os 12 scanners empacotados.
  • [ ] Smoke real: um scan de um target conhecido produz consenso (detectionCount > 1 em pelo menos um finding).
sequenceDiagram
    participant Dev
    participant GH as GitHub (tag vX.Y.Z)
    participant REL as release.yml
    participant GHCR
    participant Sigstore as Sigstore/OIDC

    Dev->>GH: git push origin vX.Y.Z
    GH->>REL: trigger (apenas semver)
    REL->>GHCR: build & push :full / :slim (+SBOM/provenance BuildKit)
    REL->>Sigstore: cosign sign (digest, keyless, retry)
    REL->>GHCR: atesta build-provenance SLSA
    REL->>GHCR: atesta SBOM SPDX (syft)
    REL->>GHCR: atesta knowledge pack (SLSA)
    REL->>GHCR: gh attestation verify (re-check, retry) ✓
    REL->>GH: release GoReleaser (binários + checksums + sig + SBOM)
    GH->>GH: tag-major.yml avança v0 / v0.8

5. Checklist de Produção/Operação

Objetivo: rodar o Quorum corretamente em pipelines, evitar o falso negativo clássico (mount errado / socket ausente) e operar o gate com confiança. Aplica-se a um docker run direto, a container:/CI e à action composta.

5.1 Mount correto e socket do Docker (o erro nº 1)

  • [ ] Fonte montada em /work com os dois-pontos corretos do separador host:container:
  • [ ] Linux/macOS: -v "$PWD:/work"
  • [ ] PowerShell: -v "${PWD}:/work"
  • [ ] cmd.exe: -v "%cd%:/work"
  • [ ] Não use um mount malformado como -v "%cd%/work" (sem :), que monta um /work vazio → reporta 0 findings para tudo (falso negativo).
  • [ ] Workdir do contêiner coerente (-w /work) quando o target é ..
  • [ ] Scan de imagem local (--type image de uma imagem recém-buildada): montar o socket do daemon do host, senão a imagem é invisível de dentro do contêiner → falso-zero:
  • [ ] docker run: -v /var/run/docker.sock:/var/run/docker.sock.
  • [ ] Action: auto-montado para type: image (opt-out docker-socket: "off", forçar com "true").
  • [ ] Validação anti-falso-negativo: confirmar no resumo que os scanners estão ran (não unavailable) e que o número de arquivos analisados faz sentido.

5.2 Verificar antes de rodar

  • [ ] Imagem verificada com cosign antes do uso (ou verify: true na action) — ver 3.1.
  • [ ] SLSA + SBOM verificados quando a política exige (gh attestation verify para provenance e para o SBOM SPDX); verifique a atestação do corpus de knowledge ao depender da camada consultiva offline.
  • [ ] Em produção, a imagem é fixada por @sha256:<digest> e a action por @<sha>.

5.3 Configuração do scan

  • [ ] --type correto (image|repo|k8s) ou confirmado que a inferência (caminho existente → repo, senão image) acerta o target certo.
  • [ ] --scanners define o pool desejado (ou é omitido para todos que suportam o target) — lembre que grype não faz k8s e dockle/kube-score são single-target.
  • [ ] --crosswalk: usando o /opt/quorum/crosswalk empacotado (auto-detectado na imagem quando ./crosswalk está ausente) ou apontando para seus próprios mapeamentos; o log inicial mostra crosswalk=N rules (<dir>).
  • [ ] conftest: políticas Rego em ./policy (ou QUORUM_CONFTEST_ARGS="--policy <dir>") — sem elas o scanner fica em error, o que é esperado.
  • [ ] Passthrough por scanner via QUORUM_<SCANNER>_ARGS quando precisar ampliar a cobertura ou destravar políticas (ex.: QUORUM_CHECKOV_ARGS="--bc-api-key <key> …"). Trate como secret (não ecoe).
  • [ ] --timeout por scanner adequado ao runner (padrão 5m); se houver unavailable de um probe lento/OOM (60s), aumente a memória do contêiner ou reduza --scanners.
  • [ ] Limites anti-DoS ajustados se preciso: QUORUM_MAX_OUTPUT_BYTES (512 MiB), QUORUM_MAX_TARGET_BYTES (20 GiB).

5.4 Gate de build

  • [ ] --fail-on <sev> definido por política (o gate dispara exit 1).
  • [ ] O pipeline trata os exit codes corretamente: 0 ok · 1 gate · 2 erro (não confundir 1 com 2).
  • [ ] --min-severity usado para reduzir ruído sem mascarar o gate (revise que o limiar não esconde a severidade do --fail-on).

5.5 Baseline e triagem contínua

  • [ ] .quorumignore versionado, com um fingerprint/correlationKey por linha + um comentário de justificativa + uma data de revisão.
  • [ ] Fingerprints copiados do próprio relatório (partialFingerprints["quorum/v1"] no SARIF / fingerprint no JSON).
  • [ ] Supressões revisadas periodicamente (toda supressão é logada — audite o log do CI).

5.6 Integração, artefatos e telemetria

  • [ ] SARIF publicado no GitHub code scanning / DefectDojo (dedupe gratuito via partialFingerprints).
  • [ ] O relatório (-o quorum.sarif/.json/.xml, perm 0600) salvo como artefato do pipeline (sempre, inclusive numa falha de gate).
  • [ ] --metrics <file> exportado para o textfile collector do Prometheus quando existe observabilidade (contagens por scanner/severidade; mais quorum_advice_* quando --advice está ligado).
  • [ ] --log-format json habilitado quando o agregador de logs consome NDJSON.
  • [ ] Ambiente sem egress: --offline ligado (desliga a OSV e bloqueia o advice remoto; o consenso de alias recai no cache local). O DB do Grype no :full não expira.

5.7 Camada consultiva opcional

  • [ ] A camada consultiva é desligada por padrão; habilite com --advice quando quiser remediação/referências legíveis anexadas — a saída permanece só de apresentação e nunca muda o gate.
  • [ ] As Fases 0/2 rodam offline e deterministicamente (templates curados + o corpus OWASP de digest fixado); quorum advise-index embeda o corpus para recuperação semântica, preservando o pin.
  • [ ] --advice-provider=local aponta para um endpoint compatível com OpenAI no host (ex.: Ollama via --advice-endpoint); reproduzível (temperature=0 + --advice-cache); degrada graciosamente se o modelo estiver inacessível.
  • [ ] --advice-provider=remote usado apenas com consentimento explícito (--advice-allow-egress, QUORUM_ADVICE_API_KEY), é bloqueado por --offline, recusa --fix e envia apenas o finding normalizado.
  • [ ] As propostas de --fix=suggest são tratadas como apenas sugestões (re-scan verify-the-fix, nunca aplicadas automaticamente); um humano ainda revisa e aplica.
  • [ ] Todo anexo de IA é lido como "AI-generated, advisory only".

5.8 Operação e diagnóstico

  • [ ] O resumo em stderr (── quorum summary ──) inspecionado: status por scanner, contagem de multi-detected, severidades, elapsed.
  • [ ] Status unavailable/timeout/error tratados como sinal — não como "limpo". Lembre: "0 findings não é prova de segurança".
  • [ ] Em OOM (version probe killed/signal: killed ou saída acima do limite): eleve o limite de memória do contêiner ou o cap.
  • [ ] quorum list-scanners usado para confirmar quais dos 12 adapters estão registrados/empacotados na imagem em uso.

Premissas

  • Versão de referência: documentação escrita para o Quorum v0.8.3 (revisão 2026-07-04), baseada no estado atual do repositório (README.md, DESIGN.md, cmd/quorum/{root,scan,advise_index}.go, internal/adapter/*.go, internal/orchestrator/orchestrator.go, internal/{enrich,rag,advisor,evals}, knowledge/*.yaml, .github/workflows/{ci,e2e,release,tag-major}.yml, action.yml, Dockerfile.full, .goreleaser.yaml, crosswalk/*.yaml). Itens marcados como comportamento (exit codes, status, flags, env) refletem o código as-is.
  • Escopo do produto: assume-se apenas CLI/Docker. Itens de checklist que em templates corporativos tratariam de frontend web, banco de dados relacional ou API REST são N/A por design e foram deliberadamente omitidos (não há superfície correspondente no código). IA/LLM não está fora de escopo, mas vive estritamente na camada consultiva opt-in (desligada por padrão, só de apresentação); o núcleo determinístico não tem IA.
  • Owner/repo: os comandos de verificação usam ghcr.io/martinez1991/quorum-sec-scan e Martinez1991/quorum-sec-scan, como em README.md/action.yml/release.yml. Em forks, ajuste o owner/identidade de certificado do cosign.
  • Ambiente típico de produção: assume-se execução num pipeline CI/CD (GitHub Actions, GitLab CI ou docker run), não um runtime de cluster — o Quorum não tem componente residente. Os itens de "Produção/Operação" referem-se a operar o scanner num pipeline. O RBAC via kubescape é single-engine (precisa de contexto de cluster) e está documentado como tal.
  • Plataformas: :full é só linux/amd64 (os binários de scanner são amd64); :slim cobre amd64+arm64. Checklists de mount/execução assumem um host capaz de rodar a imagem alvo (ex.: emulação para arm64).
  • Probe de versão: o valor de 60s (Options.ProbeTime/defaultProbeTime) é tratado como fixo; se exposto via flag em versões futuras, o item 5.3 deve ser atualizado.
  • Versão no binário: main.version tem padrão 0.1.0, sobrescrito em build-time via -ldflags "-X main.version=…" no release; v0.8.3 aqui refere-se à versão publicada do produto, não a um literal cravado no código.