Melhorias e Recomendações¶
Este documento reúne sugestões de evolução para o Quorum (quorum-sec-scan, v0.8.3),
priorizadas por eixo (Arquitetura, Segurança, UX, Performance, Custos, Escalabilidade,
Qualidade, DevOps e Automação). Toda recomendação está ancorada no código real
do repositório (arquivos e funções citados explicitamente), seguindo o princípio de produto
de que "false split > false merge" e "0 findings não é prova de segurança". Cada item traz
status → problema → recomendação → esforço → impacto, e o documento encerra com uma tabela
priorizada por impacto × esforço, um roadmap sugerido e uma seção de premissas.
Revisão: 2026-07-04 · versão do produto v0.8.3 (documento originalmente escrito em v0.2.3 e agora atualizado). Entre essas duas versões o pool cresceu de 6 para 12 scanners (trivy, grype, checkov, kics, dockle, kubescape, polaris, kube-score, terrascan, tfsec, regula, conftest — adapters em
internal/adapter/), o consenso passou a se aplicar além do SCA (crosswalk multi-cloud + k8s) e boa parte das recomendações abaixo foi implementada. Itens implementados são mantidos para rastreabilidade, com o marcador [IMPLEMENTADO v0.8.3]; itens parciais levam [PARCIAL] e os pendentes [ABERTO].Escopo: o Quorum é uma ferramenta CLI/Docker de consensus security scanning. Itens que tocariam um frontend web, banco de dados relacional ou API REST de runtime são marcados como N/A com justificativa, e qualquer ideia nessa direção aparece como Proposta futura claramente separada. Desde a v0.8.3 também existe uma camada consultiva opt-in (
--advice) — ela é apenas de apresentação e desligada por padrão, então o núcleo de consenso determinístico continua sem IA. Ver DESIGN.md e o README.
0. O que já foi entregue desde a v0.2.3 (resumo)¶
Estas recomendações do documento original já estão no código v0.8.3 — os detalhes ficam inline em cada eixo, com o marcador [IMPLEMENTADO v0.8.3]:
- [x] Observabilidade de execução.
--metrics <file>emite métricas em Prometheus text-format (report.WriteMetrics,internal/report/metrics.go) e--log-format text|jsonestrutura o log de progresso no stderr (scan.go,logf). (AU1, U1-parcial) - [x] Caps de DoS.
QUORUM_MAX_OUTPUT_BYTES(padrão 512 MiB,internal/adapter/adapter.gocapWriter/maxOutputBytes) aborta scanners que despejam uma saída gigante;QUORUM_MAX_TARGET_BYTES(padrão 20 GiB,scan.gocheckTargetSize) recusa árvores patológicas antes do scan. (mitiga A1/A2) - [x] Cadeia de suprimentos endurecida. SLSA build-provenance e SBOM SPDX atestado
(
actions/attest-build-provenance,actions/attest-sbom) para a imagem e por binário (GoReleaser + syft), além dosbom: truedo BuildKit; cosign keyless com retry; bases pinadas por@sha256:; kubescape/tfsec/terrascan/regula/conftest verificados por checksum; o knowledge pack + crosswalk agora também carregam uma atestação SLSA build-provenance a cada release (release.ymljobknowledge);THIRD_PARTY_NOTICES.md. (S3/D2, S1-parcial, S2-parcial) - [x] Consenso multi-cloud e k8s. Crosswalk derivado de saída real cobre AWS/Azure/GCP
(
crosswalk/{aws,azure,gcp}.yaml, hub AVD) e Kubernetes (crosswalk/k8s.yaml, hubC-####do kubescape); tfsec auto-correlaciona com trivy (AVD nativo). (cumpre a promessa E2) - [x] Auto-mount do socket Docker. A Action (
action.yml) monta/var/run/docker.sockautomaticamente emtype: image, evitando o falso-zero ao escanear uma imagem local. (fecha uma classe de U4) - [x] Tag móvel
v0automatizada.tag-major.ymlavançav0a cada release semver. (D4) - [x] Endurecimento de I/O.
--outputcomfilepath.Cleane perm0600; cachealiases.json0600+schemaVersion(internal/cache/store.go); id OSV validado +url.PathEscape(internal/alias/osv.go); target começando com-recusado (validateTargetRef); redação de segredos (redactSecretText); Grype DB comGRYPE_DB_VALIDATE_AGE=false(não expira). - [x] Camada consultiva opt-in (
--advice). Uma camada apenas de apresentação que nunca tocacorrelationKey/fingerprint/confidence/severidade agregada ou o gate--fail-on(sem--advicea saída é byte-idêntica). Quatro fases, todas implementadas: Fase 0 — templates determinísticos e curados de remediação + referências OWASP (internal/enrich,knowledge/*.yaml); Fase 2 — RAG-as-artifact a partir de um corpus OWASP pinado por digest (knowledge/owasp/corpus.yaml,internal/rag), lexical por padrão, semântico quando embutido viaquorum advise-index; Fase 1 — LLM local opt-in (--advice-provider=local) mais--fix=suggestguardado por um re-scan verify-the-fix (internal/advisor); Fase 3 — provider remoto opt-in (--advice-provider=remote, guardado por--advice-allow-egress). Novos evals (internal/evals) rodam no CI. (ver §11, 13-ia.md, 21-proposta-ia.md) - [x] Cobertura de testes no CI (
ci.yml,go test -race -coverprofile) e docs no GitHub Pages (MkDocs Material,docs.yml).
Ainda abertos (detalhados abaixo): consenso de RBAC (single-engine — o RBAC do kubescape precisa
de contexto de cluster), pin do Checkov pip com hashes, mais cobertura de crosswalk, um peer de
consenso para o Dockle (postura de imagem sem um segundo engine), concorrência limitada (A1), --format table (U2),
--require-scanners (U4), pin de actions por SHA (D1) e imagem non-root (S4).
1. Como ler este documento¶
Cada recomendação usa esta convenção:
- Status:
[IMPLEMENTADO v0.8.3],[PARCIAL]ou[ABERTO]. - Esforço:
S(pequeno, ≤ 1 dia),M(médio, 2–5 dias),L(grande, > 1 semana). - Impacto:
Alto,Médio,Baixo— efeito sobre confiabilidade, segurança da cadeia, experiência de CI ou custo operacional. - Âncora de código: arquivo/função onde a mudança aterrissa.
quadrantChart
title Prioritization impact x effort (open backlog v0.8.3)
x-axis "Low effort" --> "High effort"
y-axis "Low impact" --> "High impact"
quadrant-1 "Plan"
quadrant-2 "Do now (quick wins)"
quadrant-3 "Backlog"
quadrant-4 "Weigh cost/benefit"
"Limit concurrency (A1)": [0.30, 0.82]
"require-scanners (U4)": [0.18, 0.80]
"Pin Checkov pip (S1)": [0.30, 0.78]
"Pin actions by SHA (D1)": [0.20, 0.72]
"Validate empty output (A2)": [0.40, 0.75]
"NO_COLOR / TTY (U1)": [0.15, 0.45]
"Batched cache flush (P1)": [0.25, 0.55]
"--format table (U2)": [0.45, 0.60]
"Concurrent alias (P3)": [0.55, 0.66]
"RBAC consensus": [0.70, 0.62]
"More crosswalk (E2)": [0.55, 0.68]
"Non-root image (S4)": [0.45, 0.55]
2. Arquitetura¶
A1. Limitar a concorrência de scanners pesados (fan-out sem teto)¶
- Status.
[ABERTO](mitigação parcial via caps de DoS). O orquestrador ainda faz fan-out sem teto. - Problema.
orchestrator.Run(internal/orchestrator/orchestrator.go) ainda lança uma goroutine por adapter de uma vez (for _, a := range adapters { go func() {...} }, semMaxConcurrency/semáforo). Com os 12 scanners do:full— agora incluindo três engines Python pesados (Checkov, KICS+assets e o próprio ecossistema IaC) — a pressão de memória num runner pequeno é maior do que na v0.2.3. O comentáriodefaultProbeTime = 60sainda reconhece "while every scanner launches at once on a memory-constrained runner", erunOneainda diagnostica OOM post-mortem (killedSignal, "version probe killed — likely out of memory"). O que mudou: os capsQUORUM_MAX_OUTPUT_BYTES/QUORUM_MAX_TARGET_BYTESjá bloqueiam uma classe de OOM (saída/target gigante), mas não limitam o número de processos simultâneos. - Recomendação. Introduzir
Options.MaxConcurrency(padrão =runtime.NumCPU(), configurável via flag--max-concurrencyou envQUORUM_MAX_CONCURRENCY) e usar um semáforo bufferizado (chan struct{}) ougolang.org/x/sync/errgroupcomSetLimit. Tratar mitigação de OOM como controle de admissão, não apenas como diagnóstico post-mortem. - Esforço: S–M. Impacto: Alto (estabilidade do
:fullcom 12 scanners em runners pequenos — o caso de uso primário de CI).
A2. Validar a saída de cada scanner antes de fazer parsing (contrato de runtime)¶
- Status.
[PARCIAL]. Truncamento por overflow já é detectado; JSON vazio ainda passa. - Problema.
runCmd(internal/adapter/adapter.go) trata "exit != 0 mas com stdout" como sucesso (convenção findings-found), o que está correto. Avanço v0.8.3:capWritersinalizaoverquando a saída excede o cap erunCmdfalha de forma limpa ("output exceeded N bytes — aborting to avoid OOM"), evitando fazer parsing de um dump truncado por overflow. Ainda aberto: um JSON sintaticamente válido mas vazio ({}) — ou um morto no meio do dump sem exceder o cap — produz 0 findings com statusran, indistinguível de "o scanner rodou e não encontrou nada". - Recomendação. Adicionar validação leve por adapter: (a) checar que a saída decodifica na
estrutura esperada e que os campos-âncora existem (ex.:
Resultspresente no Trivy); (b) quando o exit foi != 0 e o JSON não tem o formato esperado, marcar o run comoerrorcom uma mensagem clara em vez deran/0 findings. Reaproveitar as fixtures de contrato (internal/adapter/testdata,realdata_test.go) como arquivos golden dessa validação — agora com 12 adapters cobertos. - Esforço: M. Impacto: Alto (evita o falso negativo silencioso — o anti-objetivo declarado do produto, DESIGN §14).
A3. Tornar o pipeline de enriquecimento streamable e observável¶
- Status.
[PARCIAL]. Métricas de pipeline já existem via--metrics; paralelizar o enriquecimento, não. - Problema.
Correlator.Enrich(internal/correlate/correlate.go) percorre todos os findings num único loop sequencial e, paraVULN, chamaAlias.Canonicalum id por vez, cada um podendo bater na rede (OSV). Resolução de alias, crosswalk e keying acontecem juntos. O que mudou: o reporter--metricsjá expõe agregados por scanner e de consenso, fornecendo o ponto de instrumentação que faltava. - Recomendação. Separar "resolução de alias" (I/O-bound, paralelizável — ver P3) de "crosswalk +
keying" (CPU puro, determinístico). Estender
--metricscom contadores de resolução (cache vs OSV vs local) eunmapped. - Esforço: M. Impacto: Médio.
A4. Perfis de imagem (:sca, :iac, :k8s)¶
- Status.
[ABERTO]. Só existem:fulle:slim. - Problema. Hoje há
:full(todos os 12 scanners,linux/amd64) e:slim(orquestrador,amd64+arm64), ambos no GHCR.:fullembute Python+Checkov+KICS, terrascan/tfsec/regula/ conftest, um Grype DB pré-cacheado etc., resultando numa imagem grande (DESIGN §12 "avoid the monster image"). Muitos pipelines só fazem SCA. - Recomendação. Adicionar variantes por perfil em
release.yml(matrix) que embutam só o subconjunto necessário de binários, reaproveitando o mesmoDockerfile.fullparametrizado por stage. Cada perfil mapeia para o conjunto de adapters daquele tipo (SCA = trivy+grype; IaC = checkov+kics+terrascan+tfsec+regula+conftest; K8s = kubescape+polaris+kube-score). - Esforço: M. Impacto: Médio (custo de pull/storage no CI; ver Custos).
3. Segurança (da própria cadeia)¶
S1. Pinar TODAS as ferramentas do :full por digest/checksum imutável¶
- Status.
[PARCIAL]. Bases e a maioria dos scanners já pinados/verificados; Checkov (pip) ainda pendente. - Problema. Avanço v0.8.3: as bases do
Dockerfile.fullestão pinadas por@sha256:e kubescape, tfsec, terrascan, regula e conftest agora são verificados por um checksum fixo (além de Trivy/KICS já pinados na v0.2.3). Ainda aberto: o Checkov é instalado viapip install "checkov==..."sem--require-hashes, então a resolução transitiva do pip continua mutável — um pacote comprometido entra na trust boundary (DESIGN §12). - Recomendação.
- [x] Substituir
curl | shpor um artefato versionado + verificação por checksum para Grype/Syft/Kubescape/tfsec/terrascan/regula/conftest. - [ ] Para o Checkov, pinar
checkov==<ver>com hashes (pip install --require-hashes+requirements.txtgerado porpip-compile --generate-hashes). - [x] Documentar re-resolução de digest (
docker buildx imagetools inspect). - Esforço: S–M (restante). Impacto: Alto (integridade da cadeia distribuída aos usuários).
S2. Verificar os binários dos scanners com cosign no build (não apenas confiar no instalador)¶
- Status.
[PARCIAL]. Integridade por checksum coberta; procedência por assinatura upstream, não. - Problema. Avanço v0.8.3: o checksum fixo do build garante integridade dos binários baixados. Ainda aberto: Anchore (Grype/Syft) e Kubescape publicam suas próprias assinaturas cosign que o build não verifica — o gate de procedência upstream está ausente.
- Recomendação. No stage de runtime do
Dockerfile.full, após baixar cada binário, rodarcosign verify-blob/cosign verifycom a identidade OIDC do projeto upstream, falhando o build se a verificação falhar. Complementa S1 (checksum = integridade; cosign = procedência). - Esforço: M. Impacto: Médio–Alto.
S3. Estender SLSA/atestação aos artefatos do GoReleaser (e ao knowledge pack)¶
- Status.
[IMPLEMENTADO v0.8.3]. - O que foi feito.
release.ymlagora gera SLSA build-provenance e um SBOM SPDX atestado tanto para a imagem (actions/attest-build-provenance@v2,actions/attest-sbom@v2,anchore/sbom-action, maissbom: true/provenance: truedo BuildKit) quanto por binário no canal GoReleaser (anchore/sbom-action/download-syft+sboms:no.goreleaser.yaml), re-verificados ponta a ponta comgh attestation verify. Além disso, o knowledge pack + crosswalk agora ganham sua própria atestação SLSA build-provenance a cada release (o jobknowledgeemrelease.yml), verificável comgh attestation verify knowledge/owasp/corpus.yaml. A assimetria entre os canais de distribuição foi fechada. - Follow-up. Manter a paridade quando novos artefatos entrarem no release.
- Esforço: — (feito). Impacto: Médio. (Ver Q4 / DevOps.)
S4. Endurecer a imagem em runtime (usuário non-root, capabilities, FS read-only)¶
- Status.
[ABERTO]. ODockerfile.fullainda não declaraUSER(roda comoroot). - Problema. O
Dockerfile.fulltermina comoroot, comdocker-cliinstalado (para scan de imagem). Rodar como root amplia o raio de dano se um scanner embutido tiver um RCE ao processar entrada hostil. Com 12 scanners a superfície de parsing cresceu. - Recomendação. Criar um usuário non-root e
USER quorum; documentar rodar com--read-only,--cap-drop ALLe o mínimo de bind-mounts. Quando o socket do Docker for necessário para--type image, documentar o trade-off (a Action já auto-monta o socket — tornar explícito o contrato de confiança desse mount). - Esforço: M. Impacto: Médio.
S5. Auto-escanear o próprio Quorum no CI¶
- Status.
[PARCIAL]. Cobertura de testes no CI já roda; um scanner de vulnerabilidades sobre o próprio repo/imagem, não. - Problema. Avanço v0.8.3:
ci.ymlagora rodago test -race -covermode=atomic -coverprofile=coverage.out ./...e publica a cobertura no summary. Ainda aberto: o CI não rodagovulncheck,golangci-lint, nem o próprio Quorum/Trivy contra o repositório/imagem. "A ferramenta de segurança que não escaneia a si mesma" continua sendo um sinal ruim. - Recomendação. Adicionar um step que rode Trivy/govulncheck contra o repo e a imagem, e faça upload do SARIF para o GitHub code scanning — dogfooding do próprio Quorum.
- Esforço: S. Impacto: Médio. (Ver Q2 e Automação.)
S6. Consenso de RBAC (single-engine) — uma lacuna conhecida e documentada¶
- Status.
[ABERTO](documentada como limitação do design atual). - Problema. O crosswalk de k8s (
crosswalk/k8s.yaml) já cruza kubescape × polaris × kube-score para postura de workload (privilege-escalation, privileged, non-root, cpu/mem limits, probes, read-only-fs, linux-hardening, automount-SA, network-policy, host-network, host-PID/IPC, capabilities, secrets). Mas o RBAC continua single-engine: o consenso de RBAC do kubescape precisa de um contexto de cluster ativo (não derivável só de manifestos estáticos), então não há um segundo engine para corroborar — findings de RBAC saem sem multi-detecção. - Recomendação. Documentar explicitamente a lacuna no relatório (uma marca
single-enginepara a família RBAC) e, como proposta, avaliar um adapter com contexto de cluster opcional (--type cluster) que habilite o cross-check — mantendo o modo estático como padrão. - Esforço: M–L. Impacto: Médio (transparência do consenso de k8s).
4. UX (experiência de CI/linha de comando)¶
U1. Respeitar NO_COLOR e detecção de TTY na saída de progresso¶
- Status.
[PARCIAL]. O log de progresso já é estruturável (--log-format json); uma política de cor/TTY, não. - Problema. Avanço v0.8.3:
--log-format text|json(scan.go,logf) permite emitir o progresso como JSON estruturado no CI, o que ajuda a separar o ruído de stderr dos 12 scanners. Ainda aberto: a saída humana (logfprefixo[quorum],printSummary) usa texto puro sem política de cor, eprintSummarydesenha box-drawing Unicode (──) que pode renderizar ilegível em terminais Windows legados/não-UTF. - Recomendação. Centralizar a saída humana atrás de um helper que: (a) honre
NO_COLOR(https://no-color.org) e--no-color; (b) detecte se stderr é um TTY (golang.org/x/term.IsTerminal); (c) faça fallback para ASCII puro quando non-TTY ouNO_COLOR. Adotá-lo antes de introduzir cores. - Esforço: S. Impacto: Médio (legibilidade do log no CI e no Windows).
U2. Saída legível por humanos além de SARIF/JSON/XML (--format table)¶
- Status.
[ABERTO].report.ParseFormatainda aceita sósarif|json|xml. - Problema. O único resumo humano é o
printSummaryno stderr (contagem por severidade + status por scanner). Para uso interativo/local não há uma tabela legível de findings no stdout. - Recomendação. Adicionar
--format table(e talvezmarkdown) que liste osMergedFindings comseverity,detectedBy,detectionCount,confidencee localização — ótimo para comentários de PR e runs locais (habilita AU3). - Esforço: M. Impacto: Médio.
U3. Mensagens de erro acionáveis em mais pontos do fluxo¶
- Status.
[PARCIAL]. Alguns pontos melhoraram; a padronização geral, não. - Problema. Avanço v0.8.3: a probe já tem mensagens excelentes (OOM, start lento) e o
crosswalk ganhou um fallback para
/opt/quorum/crosswalkquando./crosswalkestá ausente (resolveCrosswalkDir), evitando o silencioso "0 rules loaded" ao rodardocker run … scan .. Ainda aberto: umcrosswalk.Loadque falha ainda retorna o cru"loading crosswalk: %w";LoadBaselineretorna o erro cru. - Recomendação. Padronizar erros de runtime/uso (exit 2) com a tríade o que falhou → por quê →
como corrigir, no estilo da probe. Ex.: um aviso de crosswalk vazio "0 rules loaded — misconfigs
will be
unmapped". - Esforço: S. Impacto: Médio.
U4. Aviso explícito quando nenhum scanner rodou¶
- Status.
[ABERTO]no CLI; parcialmente coberto na Action. - Problema.
printSummaryjá imprime "0 findings is not proof of safety". Mas se todos os scanners terminaremunavailable/skipped/timeout, o relatório sai com 0 findings e exit 0. Avanço v0.8.3: a Action (action.yml) auto-monta/var/run/docker.sockemtype: imagee avisa quando o socket está ausente, fechando a causa mais comum do falso-zero de imagem local. Ainda aberto: não há um--require-scannersno CLI que transforme "0 scanners rodaram" em falha. - Recomendação. Quando
count(status==ran) == 0, emitir um aviso destacado e oferecer uma flag opt-in--require-scanners(ou--fail-if-no-scanner) que retorne exit 2 — sem mudar o padrão. - Esforço: S. Impacto: Alto (corrige a classe mais perigosa de falso-negativo).
5. Performance¶
P1. Persistir o cache de aliases em lote (evitar reescrever o arquivo inteiro por chave)¶
- Status.
[ABERTO](o endurecimento do cache aterrissou; o flush em lote não). - Problema.
cache.Store.Put(internal/cache/store.go) ainda serializa e reescreve o JSON inteiro a cada chamada (snapshot completo →MarshalIndent→ write-temp → rename). Num scan de imagem grande com centenas de CVEs novos é O(n²) em I/O. Avanço v0.8.3: o arquivo ganhouschemaVersione perm0600(write-temp+rename atômico mantido) — mais robusto, mas ainda com flush-por-Put. - Recomendação. Adicionar um modo batched: acumular os
Puts em memória e fazer um único flush ao final (Store.Flush()chamado emrunScanapósEnrich), mantendo flush-por-Putcomo fallback. Preserva a atomicidade do rename e oschemaVersion. - Esforço: S. Impacto: Médio.
P2. Reaproveitar a versão já obtida na probe (evitar Version() duas vezes)¶
- Status.
[ABERTO]. - Problema.
runOnechamaa.Version(verCtx)na probe; depois vários adapters chamamVersionde novo dentro deRunpara estamparScannerVersion. Doisexecdo binário por scan — agora multiplicado por 12 scanners no:full. - Recomendação. Passar a versão já resolvida para
Run(viaTarget/RunContext) ou cachear a versão por adapter dentro de uma execução. - Esforço: S. Impacto: Baixo–Médio.
P3. Resolver aliases de VULN de forma concorrente (com pool limitado)¶
- Status.
[ABERTO]. - Problema.
Enrichresolve aliases um id por vez e cada um pode bater no OSV (OSVClient.Aliases, timeout + retries com backoff; agora com id validado +url.PathEscape). Centenas de CVEs únicos não cacheados = centenas de round-trips sequenciais. Em--offlineo ponto é irrelevante; online (padrão) é o maior gargalo do pipeline. - Recomendação. Deduplicar ids antes da resolução, resolver o conjunto único em paralelo com um pool limitado (respeitando o rate-limit do OSV) e mapear de volta. Combinar com P1 (flush único).
- Esforço: M. Impacto: Médio–Alto (latência de scans online no CI).
P4. Reaproveitar o DB do Grype/Trivy entre runs¶
- Status.
[PARCIAL]. Resolvido no:full; orientação para:slim/binário nativo, não. - Problema. Avanço v0.8.3: o
:fullpré-cacheia o Grype DB em/opt/grype/dbcomGRYPE_DB_AUTO_UPDATE=falseeGRYPE_DB_VALIDATE_AGE=false(o DB congelado não expira, então não força re-download num runner offline). Ainda aberto: no uso:slim/ binário-nativo cada runner pode re-baixar o DB, sem orientação na doc para montar/persistir esse cache. - Recomendação. Documentar (e talvez expor via flag/env) o reaproveitamento de
GRYPE_DB_CACHE_DIRe do cache do Trivy DB montado como cache de CI. - Esforço: S (doc). Impacto: Médio (latência de cold-start).
6. Custos¶
C1. Reduzir o tamanho do :full (multi-stage agressivo / perfis)¶
- Status.
[ABERTO]. - Problema. O
:fullcarrega Python+pip+venv (Checkov), a stack IaC (kics, terrascan, tfsec, regula, conftest), git, docker-cli, tar/curl e o Grype DB congelado. Com 12 scanners a imagem cresceu; pesa no egress do GHCR e no tempo de pull a cada job. - Recomendação. (a) Remover ferramentas de build (
curl,tar, headers pip) do stage final via multi-stage; (b) oferecer perfis (A4) para que pipelines de SCA não puxem a stack Python; (c) limpar*.pyc/--no-cache-dir. - Esforço: M. Impacto: Médio (custo recorrente de CI).
C2. Cachear layers de build no release (já parcialmente feito)¶
- Status.
[PARCIAL]. - Problema.
release.ymljá usacache-from/cache-to: type=gha. O custo restante é ogrype dba cada build. - Recomendação. Cachear o Grype DB como layer estável (versão pinada) para que rebuilds sem bump não re-baixem; documentar a cadência de refresh (relaciona com AU4).
- Esforço: S. Impacto: Baixo–Médio.
7. Escalabilidade¶
E1. Limitar e priorizar o fan-out por classe de scanner¶
- Status.
[ABERTO]. - Problema. Mesmo com A1 (cap global), os 12 scanners têm perfis de recurso muito diferentes: Checkov/KICS (Python) são lentos para iniciar e pesados em memória; Dockle e kube-score são leves. Um único cap trata todos igual.
- Recomendação. Permitir pesos por adapter (via
Capabilities/metadata) e um scheduler que nunca rode dois scanners "pesados" ao mesmo tempo em runners pequenos. Começar simples: uma classeheavy|lighte um cap separado para heavy. - Esforço: M. Impacto: Médio.
E2. Crosswalk como ativo escalável (validação + cobertura)¶
- Status.
[PARCIAL]. A cobertura cresceu muito; validação/automação de relatório, não. - Problema. Avanço v0.8.3: o crosswalk deixou de ser só-SCA e agora habilita o consenso
multi-cloud e k8s, derivado de saída real com o viés "false split > false merge":
crosswalk/{aws,azure,gcp}.yaml(hub AVD: S3/IAM/EBS/SG/RDS/KMS/CloudTrail/VPC-flow-logs, Azure Storage/Key Vault, GCP bucket/firewall/SQL) ecrosswalk/k8s.yaml(hubC-####do kubescape, cruzando kubescape × polaris × kube-score). tfsec auto-correlaciona com trivy (AVD nativo). Ainda aberto: a cobertura é dívida conhecida (DESIGN §14) e manter a consistência do YAML à mão não escala; faltam um validador de CI, um relatório de cobertura e a lacuna do Dockle (ver E3). - Recomendação. (a) Um validador de schema do crosswalk no CI (campos obrigatórios, IDs únicos,
AVD/
C-####bem-formados); (b) um relatório de cobertura (% das regras de cada scanner com mapeamento, gerado das fixtures reais); (c) uma métricaunmappedexposta em--metrics. - Esforço: M. Impacto: Médio (qualidade do consenso MISCONFIG/K8S).
E3. Peer de consenso para o Dockle (postura de imagem single-engine)¶
- Status.
[ABERTO](lacuna conhecida). - Problema. A postura de configuração de imagem (CIS Docker Benchmark) hoje é coberta apenas pelo Dockle — não há um segundo engine para corroborar esses findings, então eles saem sem multi-detecção (análogo ao RBAC em S6). Diferente de MISCONFIG/IaC e workload k8s, que já têm 2–3 engines cruzados.
- Recomendação. Avaliar um peer para a família de postura-de-imagem (ex.: Trivy config/image
checks ou hadolint para o Dockerfile) e mapeá-lo no crosswalk contra os controles do Dockle; até lá,
marcar a família como
single-engineno relatório. - Esforço: M. Impacto: Médio (transparência do consenso de imagem).
E4. Saída para targets com alto volume de findings¶
- Status.
[ABERTO]. - Problema. Hoje
report.Writemonta tudo numbytes.Bufferantes de escrever (emitemscan.go). Para imagens com milhares de vulns, mantém o relatório inteiro em memória. - Recomendação. Streaming opcional do writer para o
io.Writerde destino (JSON Lines / SARIF streaming) quando o volume justificar; manter o buffer como padrão. - Esforço: M. Impacto: Baixo (caso de cauda).
8. Qualidade¶
Q1. Cobertura de erro nos parsers (fuzz + golden de saída malformada)¶
- Status.
[ABERTO]. A base de testes de contrato cresceu para 12 adapters; entrada hostil falta. - Problema. Há testes de contrato por adapter contra fixtures reais
(
internal/adapter/testdata,realdata_test.go) — agora cobrindo os 12 scanners. Falta cobertura de entrada hostil/malformada (JSON truncado, campos ausentes, números fora de faixa). - Recomendação. Adicionar
go test -fuzznos parsers e golden tests com fixtures deliberadamente quebradas, pareados com a validação A2. - Esforço: M. Impacto: Médio.
Q2. golangci-lint e govulncheck no CI¶
- Status.
[PARCIAL]. Cobertura de testes aterrissou; um linter abrangente e vuln check, não. - Problema. Avanço v0.8.3:
ci.ymlrodago test -race -coverprofilee publica a cobertura. Ainda aberto: não hágolangci-lintnemgovulncheckdas dependências Go. - Recomendação.
- [ ] Adicionar
golangci-lint(errcheck, staticcheck, gocritic, gosec). - [ ] Adicionar
govulncheck ./...como step obrigatório. - [x] Reportar cobertura (
go test -coverprofile) no summary. - Esforço: S. Impacto: Médio.
Q3. Teste determinístico ponta a ponta do consenso (além do e2e.yml)¶
- Status.
[ABERTO]. - Problema. Há
e2e.yml(consenso). Vale garantir que a matemática do consenso (confidence,detectionCount,aggregateSeverity) tenha table tests cobrindo os pesos do DESIGN §9 e os limites (clamp 0..1, log normalizado), agora com mais famílias de engine (consensus.scannerCategorycruzando 12 scanners). - Recomendação. Testes unitários explícitos para
confidence(...)com casos-âncora (3 linters na mesma linha vs SCA+IaC concordando; kubescape+polaris+kube-score no mesmo controle k8s). - Esforço: S–M. Impacto: Médio.
Q4. Documentar e versionar o schema de saída (JSON/SARIF) como contrato¶
- Status.
[ABERTO]. - Problema. O JSON é um "dump direto de
[]MergedFinding"; consumidores (DefectDojo, scripts) dependem desse formato. Não há versionamento de schema explícito além departialFingerprints["quorum/v1"]. - Recomendação. Publicar um JSON Schema da saída e um teste que falhe se o formato mudar sem um bump da versão do schema. Tratar a saída como uma API pública (mesmo sem REST).
- Esforço: M. Impacto: Médio.
Q5. Evals da camada consultiva como gate de qualidade (entregue)¶
- Status.
[IMPLEMENTADO v0.8.3]. - O que foi feito. O harness
internal/evalsmede cobertura determinística de remediação, relevância das referências OWASP e a taxa verify-the-fix, e roda no CI sem modelo pesado (Fase 0/Fase 2 são determinísticas, então o eval é reproduzível). Isso mantém a camada consultiva opt-in honesta sem acoplar o CI a um LLM externo. - Follow-up. Estender o corpus de eval conforme o knowledge pack cresce; conectar a taxa
verify-the-fix à métrica
quorum_advice_fix{stage=verified|proposed}para acompanhar tendência. - Esforço: — (feito). Impacto: Médio.
9. DevOps¶
D1. Pinar actions de terceiros por SHA¶
- Status.
[ABERTO]. - Problema. Os workflows ainda usam tags móveis (
actions/checkout@v4,actions/setup-go@v5,docker/build-push-action@v6,sigstore/cosign-installer@v3,actions/attest-*@v2, etc.). Tags de action são mutáveis — o mesmo risco de supply-chain que o produto combate (DESIGN §12), agora mais crítico porque o release faz atestação/assinatura. - Recomendação. Pinar cada
uses:por@<sha40>e usar Dependabot/Renovate para bumps controlados. Consistente com a postura de segurança de cadeia do próprio Quorum. - Esforço: S. Impacto: Médio–Alto.
D2. SBOM dos binários no release (paridade com a imagem)¶
- Status.
[IMPLEMENTADO v0.8.3]. Ver S3 —sboms:no.goreleaser.yaml+attest-sbompor binário fecham a paridade com a imagem. - Follow-up. Manter a paridade ao adicionar novos artefatos de release.
- Esforço: — (feito). Impacto: Médio.
D3. Verificação de reprodutibilidade / targets make completos¶
- Status.
[ABERTO]. - Problema. O
Makefilecobretest/vet/build/docker-full. Falta um único target de pré-release (lint + vuln + sbom local + smoke do:full) para reduzir surpresas no CI. - Recomendação. Um target
make cique reproduza o pipeline localmente, incluindocosign verifyda imagem recém-buildada (a Action já faz cosign-verify da imagem antes de rodar). - Esforço: S. Impacto: Baixo–Médio.
D4. Tag móvel v0 da Action: automatizar e proteger¶
- Status.
[IMPLEMENTADO v0.8.3]. - O que foi feito. O workflow dedicado
tag-major.ymlavança a tag móvelv0(major/minor) para o commit recém-lançado a cada release semver, separado do build da imagem. O README recomendauses: Martinez1991/quorum-sec-scan@v0(pinar por@<sha>em produção). - Follow-up. Documentar a política de pin no README/docs de release.
- Esforço: — (feito). Impacto: Médio.
10. Automação¶
AU1. --metrics (telemetria de execução em formato consumível)¶
- Status.
[IMPLEMENTADO v0.8.3]. - O que foi feito.
--metrics <file>(scan.go,writeMetricsFile→report.WriteMetrics,internal/report/metrics.go) emite métricas em Prometheus text-format (para o textfile collector donode_exporterou Pushgateway): por scanner (status,durationMs,findings,version— dados deScannerRun), agregados de consenso (merged,multiDetected,bySeverity) e de pipeline. Complementado por--log-format text|jsonpara o log de progresso. Sob--adviceo reporter também emite as séries consultivasquorum_advice_enriched{kind=remediation|references| recommendation},quorum_advice_provider{provider}equorum_advice_fix{stage=proposed| verified}(a razão verified/proposed é a taxa verify-the-fix) — desligadas por padrão e ausentes sem--advice. - Follow-up. Estender com contadores de cache de alias (hits vs OSV) e
unmapped(ver A3/E2). - Esforço: — (feito). Impacto: Médio (observabilidade de CI sem inventar um daemon).
AU2. Geração assistida de baseline (--write-baseline)¶
- Status.
[ABERTO]. - Problema. Adotar
--fail-onexige um baseline (.quorumignore) montado à mão a partir dos fingerprints do relatório (README "Baseline"). Fricção de adoção. - Recomendação. Uma flag
--write-baseline <file>que escreva os fingerprints atuais (com comentários: título, severidade, scanners) para o usuário triar. Nunca suprime silenciosamente; só materializa o que já está no relatório. - Esforço: S–M. Impacto: Médio (adoção do gate de CI).
AU3. Decoração de PR / comentário automático¶
- Status.
[ABERTO]. - Problema. A Action faz upload de SARIF (GitHub code scanning), mas não há um resumo legível no PR.
- Recomendação. Um step opcional da Action que poste um comentário com o resumo do consenso
(reaproveitando
--format table/markdownde U2). Mantém o produto CLI-only; a automação vive na Action. - Esforço: M. Impacto: Médio.
AU4. Atualização agendada do DB de vulnerabilidades / rebuild do :full¶
- Status.
[ABERTO](urgência reduzida porGRYPE_DB_VALIDATE_AGE=false). - Problema. O Grype DB no
:fullfica "congelado no momento do build"; sem rebuild ele envelhece. Avanço v0.8.3:GRYPE_DB_VALIDATE_AGE=falseimpede que o DB congelado quebre scans offline por expiração — mas ele de fato continua envelhecendo. - Recomendação. Um workflow agendado (cron) que rebuilde e re-publique o
:fullperiodicamente (sem um novo semver), atualizando só o DB; assinatura/atestação seguem o mesmo fluxo (SLSA + SBOM atestado + cosign). - Esforço: M. Impacto: Médio.
AU5. Passthrough por scanner e auto-mount de socket (entregue)¶
- Status.
[IMPLEMENTADO v0.8.3]. - O que foi feito. (a)
QUORUM_<SCANNER>_ARGS(internal/adapter/adapter.go,extraArgs) permite ampliar cobertura ou passar uma chave de plataforma sem tocar o adapter — ex.:QUORUM_CHECKOV_ARGS="--bc-api-key <key>"destrava políticas Prisma Cloud/Bridgecrew através do Checkov OSS embutido; a Action expõetrivy-args/checkov-args/etc. (b) A Action (action.yml) auto-monta/var/run/docker.sockemtype: image(inputdocker-socketpara forçar/desabilitar), eliminando o falso-zero ao escanear uma imagem buildada localmente, e faz cosign-verify da imagem antes de rodar. A Action agora também expõe todos os inputs consultivos (advice,advice-provider,advice-endpoint,advice-model,advice-embed-model,advice-max,advice-cache,advice-allow-egress,advice-api-key,fix), auto-adicionandohost-gatewayparalocale encaminhando a API key via env pararemote. - Follow-up. Nenhum imediato.
- Esforço: — (feito). Impacto: Médio–Alto (cobertura e correção de falso-zero).
AU6. quorum advise-index — embedding semântico do corpus OWASP (entregue)¶
- Status.
[IMPLEMENTADO v0.8.3]. - O que foi feito. O novo subcomando
quorum advise-indexfaz embedding do corpus OWASP pinado por digest (knowledge/owasp/corpus.yaml,internal/rag), preservando o pin, para que a recuperação da Fase 2 possa rodar semântica (embeddings) em vez da busca lexical padrão —scanescolhe semântica automaticamente quando o corpus carrega vetores. A recuperação continua determinística e RAG-as-artifact (sem modelo no momento do scan para lexical), e a atestação do corpus permite aos consumidores verificar o pack comgh attestation verify knowledge/owasp/corpus.yaml. - Follow-up. Publicar um artefato de corpus embutido por release para que os usuários tenham
recuperação semântica sem rodar
advise-indexlocalmente. - Esforço: — (feito). Impacto: Médio.
11. Itens marcados N/A (com justificativa)¶
Esta fronteira arquitetural fica em grande parte inalterada da v0.2.3 à v0.8.3: o produto cresceu em profundidade (mais scanners, consenso multi-cloud/k8s, uma cadeia de suprimentos endurecida, uma camada consultiva opt-in), não em superfície.
| Tema do template | Status | Justificativa |
|---|---|---|
| Frontend web / SPA | N/A | O Quorum é só CLI/Docker ("no panel, no daemon", README). Não há UI. |
| Banco de dados relacional | N/A | A persistência é apenas o cache JSON de aliases (internal/cache, schemaVersion+0600) e o cache on-disk de advice (chaveado por fingerprint+provider+model). Sem RDBMS por design (DESIGN §7 evita CGO/DB). |
| API REST HTTP de runtime | N/A | A integração é por exit code (0 ok / 1 gate / 2 error) + SARIF/JSON/XML no CI. A rede de saída é o OSV.dev (id validado + PathEscape) e, só sob --advice-provider, um endpoint compatível com OpenAI (local por padrão; remote guardado por --advice-allow-egress). |
| Autenticação / contas | N/A | Sem multiusuário ou sessão. A confiança vem de cosign/SLSA/SBOM atestado (e o knowledge pack atestado) na distribuição. |
| IA / LLM no núcleo | N/A (camada consultiva opt-in existe, desligada por padrão) | O núcleo de consenso é determinístico (correlationKey, a fórmula de confidence, crosswalk YAML) — sem ML. As partes de IA são a camada consultiva apenas de apresentação (--advice, Fases 1/3), desligada por padrão e nunca tocando o score ou o gate; o OWASP LLM Top 10 aplica-se apenas quando essa camada está habilitada. Ver 13-ia.md e 21-proposta-ia.md. |
| Orquestração K8s de runtime (Falco/Tetragon) | N/A (futuro separado) | Um modelo de stream, não um scan estático — um produto separado (DESIGN §2, §13). |
Proposta futura (claramente separada): se algum dia houver demanda por agregação centralizada de resultados entre muitos pipelines, o caminho coerente com o design seria um consumidor externo do SARIF/JSON (ex.: DefectDojo), não embutir um banco/API no Quorum. O fingerprint portável (
quorum/v1) foi projetado exatamente para isso (DESIGN §11).
12. Tabela priorizada (impacto × esforço)¶
Ordenada por prioridade sugerida. Itens concluídos na v0.8.3 ficam no fim, para rastreabilidade.
| # | Eixo | Recomendação | Esforço | Impacto | Status | Prioridade |
|---|---|---|---|---|---|---|
| A1 | Arquitetura | Limitar concorrência de scanners (semáforo/errgroup) | S–M | Alto | Aberto | P0 |
| U4 | UX | Aviso/flag quando nenhum scanner rodou (--require-scanners) |
S | Alto | Aberto | P0 |
| A2 | Arquitetura | Validar saída (JSON vazio) antes do parsing | M | Alto | Parcial | P0 |
| S1 | Segurança | Pinar o Checkov pip com hashes (--require-hashes) |
S–M | Alto | Parcial | P0 |
| D1 | DevOps | Pinar actions de terceiros por SHA | S | Médio–Alto | Aberto | P1 |
| Q2 | Qualidade | golangci-lint + govulncheck no CI |
S | Médio | Parcial | P1 |
| S5 | Segurança | Auto-scan (dogfooding: trivy/govulncheck) no CI | S | Médio | Parcial | P1 |
| P1 | Performance | Cache de alias com flush em lote | S | Médio | Aberto | P1 |
| U1 | UX | NO_COLOR/TTY antes de qualquer cor |
S | Médio | Parcial | P1 |
| P3 | Performance | Resolução concorrente de alias + dedup | M | Médio–Alto | Aberto | P1 |
| U2 | UX | --format table/markdown |
M | Médio | Aberto | P2 |
| U3 | UX | Mensagens de erro acionáveis (crosswalk vazio, baseline) | S | Médio | Parcial | P2 |
| AU2 | Automação | --write-baseline |
S–M | Médio | Aberto | P2 |
| P2 | Performance | Reaproveitar a versão da probe (não chamar Version 2x) |
S | Baixo–Médio | Aberto | P2 |
| S2 | Segurança | Cosign-verify de binários upstream no build | M | Médio–Alto | Parcial | P2 |
| S4 | Segurança | Imagem non-root + hardening de runtime | M | Médio | Aberto | P2 |
| S6 | Segurança | Consenso de RBAC (2º engine / contexto de cluster) | M–L | Médio | Aberto | P2 |
| E3 | Escalabilidade | Peer de consenso para o Dockle (postura de imagem) | M | Médio | Aberto | P2 |
| A4/C1 | Arquitetura/Custos | Perfis de imagem (:sca/:iac/:k8s) + redução de tamanho |
M | Médio | Aberto | P2 |
| E2 | Escalabilidade | Validador de crosswalk + cobertura no CI | M | Médio | Parcial | P2 |
| Q1 | Qualidade | Fuzz/golden de saída malformada nos parsers | M | Médio | Aberto | P2 |
| Q3 | Qualidade | Table tests da fórmula de consenso | S–M | Médio | Aberto | P2 |
| Q4 | Qualidade | JSON Schema versionado da saída | M | Médio | Aberto | P2 |
| AU4 | Automação | Rebuild agendado do :full (DB fresco) |
M | Médio | Aberto | P2 |
| AU6+ | Automação | Publicar um corpus OWASP embutido por release | S | Médio | Aberto | P3 |
| P4 | Performance | Reuso documentado do DB Grype/Trivy no CI (:slim) |
S | Médio | Parcial | P3 |
| AU3 | Automação | Decoração de PR via Action | M | Médio | Aberto | P3 |
| E1 | Escalabilidade | Pesos por classe de scanner (heavy/light) | M | Médio | Aberto | P3 |
| A3 | Arquitetura | Separar/observar o enriquecimento | M | Médio | Parcial | P3 |
| E4 | Escalabilidade | Writer em streaming para relatórios enormes | M | Baixo | Aberto | P3 |
| C2 | Custos | Cache do layer do Grype DB no build | S | Baixo–Médio | Parcial | P3 |
| D3 | DevOps | Target make ci de pré-release |
S | Baixo–Médio | Aberto | P3 |
| — | — | Concluídos na v0.8.3 ↓ | ||||
| AU1 | Automação | --metrics (Prometheus textfile) + --log-format + séries de advice |
M | Médio | Feito | — |
| AU5 | Automação | Passthrough QUORUM_<SCANNER>_ARGS + auto-socket + inputs consultivos |
M | Médio–Alto | Feito | — |
| AU6 | Automação | quorum advise-index (corpus OWASP semântico) |
M | Médio | Feito | — |
| Q5 | Qualidade | Evals da camada consultiva no CI (internal/evals) |
M | Médio | Feito | — |
| S3/D2 | Segurança/DevOps | SLSA + SBOM SPDX atestado (imagem + binários + knowledge pack) | S–M | Médio | Feito | — |
| D4 | DevOps | Automatizar a tag móvel v0 (tag-major.yml) |
S | Médio | Feito | — |
| — | Produto | Camada consultiva opt-in (--advice, Fases 0–3) |
L | Alto | Feito | — |
| — | Segurança | Caps de DoS (MAX_OUTPUT_BYTES/MAX_TARGET_BYTES) |
S | Médio | Feito | — |
| — | Segurança | Consenso multi-cloud/k8s (crosswalk aws/azure/gcp/k8s) | L | Alto | Feito | — |
13. Roadmap sugerido por release¶
O bloco entregue reúne o que já está na v0.8.3; os blocos seguintes são backlog, não comportamento atual.
flowchart LR
subgraph delivered["Delivered through v0.8.3"]
m1["AU1 --metrics + --log-format"]
m2["AU5 args passthrough + auto-socket"]
m3["S3/D2 SLSA + attested SBOM"]
m4["DoS caps (bytes)"]
m5["Multi-cloud/k8s consensus"]
m6["D4 moving v0 tag"]
m7["Advisory layer --advice (0-3)"]
m8["AU6 advise-index + Q5 evals"]
end
subgraph v0_9["v0.9 (stability + gate)"]
a1["A1 limit concurrency"]
u4["U4 require-scanners"]
a2["A2 validate empty output"]
s1["S1 pin Checkov pip (hashes)"]
d1["D1 pin actions SHA"]
end
subgraph v0_10["v0.10 (supply chain++ / consensus)"]
s2["S2 cosign upstream"]
s4["S4 non-root image"]
s6["S6 RBAC consensus"]
e3["E3 Dockle peer"]
e2["E2 crosswalk coverage in CI"]
end
subgraph v1_0["v1.0 (stable contract)"]
a4["A4 image profiles"]
q4["Q4 versioned schema"]
u2["U2 --format table"]
au3["AU3 PR decoration"]
end
delivered --> v0_9 --> v0_10 --> v1_0
Premissas¶
- A versão atual analisada é a v0.8.3 (revisão 2026-07-04); as afirmações refletem o código no
estado atual do repositório (branch
main), em particular:internal/orchestrator/orchestrator.go,cmd/quorum/scan.go,cmd/quorum/root.go,cmd/quorum/advise_index.go,internal/adapter/{adapter.go,trivy.go,conftest.go,…}(12 adapters),internal/cache/store.go,internal/alias/{osv.go,resolver.go},internal/correlate/correlate.go,internal/report/metrics.go,internal/{enrich,rag,advisor,evals},knowledge/{aws,azure,gcp,k8s,image,categories}.yaml,knowledge/owasp/corpus.yaml,crosswalk/{aws,azure,gcp,k8s}.yaml,Dockerfile.full,action.yml,.github/workflows/{ci,release,tag-major}.yml,.goreleaser.yaml. - Os marcadores [IMPLEMENTADO v0.8.3] / [PARCIAL] / [ABERTO] foram atribuídos pela leitura
do código tal como está: por exemplo,
--metrics/--log-formatexistem emscan.go; os caps de DoS existem emadapter.go/scan.go; a camada consultiva (--advice, Fases 0–3) existe eminternal/{enrich,rag,advisor}e é desligada por padrão; o fan-out emorchestrator.Runainda não tem cap de concorrência;report.ParseFormatainda aceita sósarif|json|xml;ci.ymlroda cobertura mas nãogovulncheck/golangci-lint;Dockerfile.fullnão declaraUSER; o Checkov é instalado porpip installsem--require-hashes. - "Esforço" é uma estimativa de engenharia relativa, sem contabilizar review/QA externos; serve para priorização, não para planejamento preciso de sprint.
- Assumi que o objetivo do produto permanece só CLI/Docker (sem painel, daemon, API REST ou banco
relacional), e que o núcleo determinístico continua sem IA — a camada consultiva é opt-in e
desligada por padrão (
--advice), apenas de apresentação, e nunca afeta o score ou o gate. Conforme README/DESIGN, recomendações rumo a painel/daemon/RDBMS foram tratadas como N/A ou propostas futuras externas. Essa fronteira permanece inalterada da v0.2.3 à v0.8.3. - Assumi que o público primário é CI/CD (gating por exit code, consumo de SARIF), o que pesa na priorização de estabilidade em runners pequenos, segurança de cadeia e UX de log.
- Não rodei os scanners nem o pipeline completo; as conclusões de performance (P1–P4) derivam de
leitura de código (ex.:
cache.Store.Putreescrevendo o snapshot completo a cada chamada;Versionchamado na probe e emRun; resolução sequencial de aliases emEnrich), não de profiling empírico. - A ausência de cores hoje (U1) é uma observação de código (
printSummary/logfusam texto puro, agora com--log-format jsondisponível); o item de cor/TTY fica preventivo para terminais legados. - Os nomes de flag propostos (
--max-concurrency,--require-scanners,--format table,--write-baseline,--no-color) são sugestões; os definitivos devem seguir a convençãocobraexistente emscan.go(onde--metrics,--log-format,--min-severity,--advice, etc. já vivem).
Ver também¶
- DESIGN.md — modelo de dados, matriz de correlação (§6), matemática do consenso (§9), cadeia de suprimentos (§12), status dos scanners (§14).
- README.md — uso, exit codes, baseline, distribuição assinada.
- THIRD_PARTY_NOTICES.md — inventário de licenças das ferramentas embutidas.