Quorum Documentation — Index¶
This is the landing page (master index) of the enterprise documentation for Quorum (quorum-sec-scan),
a consensus security scanning tool delivered as a CLI and Docker images. Quorum
orchestrates a pool of 12 OSS scanners — trivy, grype, checkov, kics, dockle, kubescape, polaris,
kube-score, terrascan, tfsec, regula and conftest (policy-as-code over the operator's Rego in ./policy) —
normalizes everything into a canonical model (model.Finding), resolves vulnerability aliases
(CVE/GHSA via OSV.dev), correlates equivalent findings through a deterministic correlationKey,
computes a confidence (consensus) score and emits a SARIF (primary), JSON or XML report.
Consensus goes beyond SCA and covers multi-cloud IaC (AWS/Azure/GCP via the AVD hub) and Kubernetes
posture (the kubescape C-#### hub, correlating kubescape × polaris × kube-score), with
crosswalks derived from real output; RBAC stays single-engine (documented). The design principle is
"false split > false merge" and the operational motto is "0 findings is not proof of safety".
This documentation describes the product AS-IS at version v0.8.3 (branch main as the source of truth);
items for web frontend and relational database, HTTP REST API are marked N/A by
architecture, with a technical rationale and, where useful, a clearly separated "future proposal".
AI/LLM stays out of the deterministic core, but since v0.8.3 there is an opt-in advisory layer
(--advice, off by default) — presentation-only, byte-identical output when disabled.
Table of Contents (TOC)¶
| # | Document | Description (1 line) |
|---|---|---|
| 00 | Index | This page: landing, reading map, assumption/gap registers and metadata. |
| 01 | Overview | What Quorum is, CLI/Docker scope, principles and N/A boundaries. |
| 02 | Functional Requirements | Commands, flags (--metrics/--log-format/--advice/--fix), exit codes, 12 scanners and target matrix. |
| 03 | Non-Functional Requirements | Performance, target SLO/SLI, supply chain (SLSA/SBOM/knowledge-pack attested), interpretive compliance. |
| 04 | Architecture | Pipeline, internal/* packages, orchestrator fan-out, consensus crosswalks and sequence. |
| 05 | Data Modeling | model.Finding, MergedFinding (Remediation/References/Advice/Fix), crosswalk YAML, fingerprints and JSON/XML shapes. |
| 06 | Interfaces (CLI) and Output Formats | CLI contract, list-scanners, advise-index, advisory flags, SARIF/JSON/XML and invocation examples. |
| 07 | Persistence and Artifacts | Alias cache, Grype DB, crosswalk YAML, advice cache, .quorumignore baseline and reports. |
| 08 | Frontend / Terminal Experience | Terminal UX: stdout/stderr, summary, absence of color/TTY (web is N/A). |
| 09 | Backend | cmd/quorum + internal/* as the CLI "backend"; no server/daemon (web N/A). |
| 10 | Infrastructure | Build, GHCR distribution (:full/:slim), cosign keyless + SLSA + SBOM SPDX + knowledge-pack attestation; hosted runtime N/A. |
| 11 | DevOps | CI/e2e/release workflows, PR flow, automatic moving v0 tag (tag-major.yml) and consumer verification. |
| 12 | Security | Threat model, risks R1–R8, supply chain, egress controls for the remote advisor and framework mappings. |
| 13 | AI (Artificial Intelligence) | Honest framing: the core has no AI/LLM/ML; an opt-in local/remote advisory layer exists (off by default); OSV is a deterministic lookup. |
| 14 | Observability | [quorum] logs on stderr, SARIF/JSON fields, --metrics textfile and the quorum_advice_* metrics. |
| 15 | Testing | Test strategy, contract tests, consensus e2e, the internal/evals advisory harness and coverage proposals. |
| 16 | Roadmap | V1/V2/V3 phases, Polaris status and SemVer release gates. |
| 17 | Backlog | Prioritized Epics/Stories (MoSCoW, Fibonacci story points). |
| 18 | Risk Matrix | Technical/supply-chain/operational risks with a qualitative 5x5 matrix. |
| 19 | Costs | Cost modeling (Actions/GHCR/headcount), licenses and FX. |
| 20 | Improvements and Recommendations | Prioritized performance/UX/supply-chain opportunities. |
| 21 | Proposal — Advisory AI (opt-in) | The AI design proposal (Phases 0–3), now implemented in v0.8.3 without touching the deterministic core. |
| 99 | Checklists | Actionable adoption, operation and release checklists. |
How to read / documentation map¶
Pick the trail that matches your role:
flowchart TD
Start([You are...]) --> Dev[Developer / Contributor]
Start --> Ops[CI/CD / Platform Engineer]
Start --> Sec[Security / AppSec]
Start --> PM[Product / Stakeholder]
Dev --> D1[01 Overview]
Dev --> D2[04 Architecture]
Dev --> D3[05 Data Model]
Dev --> D4[09 Backend]
Dev --> D5[15 Testing]
Ops --> O1[06 CLI Interfaces]
Ops --> O2[07 Persistence]
Ops --> O3[10 Infrastructure]
Ops --> O4[11 DevOps]
Ops --> O5[14 Observability]
Sec --> S1[12 Security]
Sec --> S2[18 Risks]
Sec --> S3[13 AI]
PM --> P1[01 Overview]
PM --> P2[02 Functional Requirements]
PM --> P3[16 Roadmap]
PM --> P4[17 Backlog]
PM --> P5[19 Costs]
Suggested trails:
- First contact: 01-visao-geral → 06-interfaces-cli-e-formatos → 99-checklists.
- Understand "how it works": 04-arquitetura → 05-modelo-de-dados → 09-backend.
- Adopt in a pipeline: 06-interfaces-cli-e-formatos → 10-infraestrutura → 11-devops → 14-observabilidade.
- Assess security posture: 12-seguranca → 18-riscos → 13-ia.
- Plan the advisory layer: 21-proposta-ia → 13-ia → 06-interfaces-cli-e-formatos.
- Plan the evolution: 16-roadmap → 17-backlog → 20-melhorias.
Naming convention: files follow the NN-file.md pattern, with 00 as the index and 99 for
checklists. Cross-links use relative paths inside docs/.
Scope boundaries (AS-IS)¶
Quorum is CLI/Docker only. The domains below are N/A by architecture in v0.8.3:
| Domain | Status | Technical rationale | Where to dig deeper |
|---|---|---|---|
| Web frontend / UI | N/A | There is no HTTP server nor browser assets; the UX is terminal (stdout/stderr). | 08-frontend |
| Relational database | N/A | There is no persistent domain datastore; only rebuildable file caches (aliases, Grype DB, advice cache). | 07-persistencia-e-artefatos |
| HTTP REST API | N/A | There is no resident endpoint/service; the interface is the CLI binary and the Docker image. | 06-interfaces-cli-e-formatos |
| Authentication / accounts | N/A | There are no users, sessions or identity managed by the product. | 12-seguranca |
| AI / LLM / ML | N/A in the core; opt-in advisory | The deterministic core has no AI (OSV.dev is a deterministic lookup, not ML). Since v0.8.3 an opt-in advisory layer (--advice, off by default) can attach natural-language recommendations; it never touches correlationKey/confidence/severity/the fail-on gate. |
13-ia, 21-proposta-ia |
| Runtime security (Falco/Tetragon), hosted/K8s runtime | N/A (future proposal) | The product runs in batch in the pipeline; there is no cluster-resident component. | 10-infraestrutura, 16-roadmap |
Assumptions Register (consolidated)¶
Cross-cutting assumptions that govern the whole documentation suite. Assumptions specific to each document appear in the "## Assumptions" section of the respective file.
| ID | Assumption | Source documents |
|---|---|---|
| A-01 | The main branch (product v0.8.3) is the source of truth; where DESIGN.md (Draft v0.1) diverges, the code prevails. |
04, 05, 09, 18 |
| A-02 | The version constant in root.go is 0.1.0 because it is overridden at build-time via -ldflags (GoReleaser); releases inject 0.8.3. Examples use 0.8.3. |
02, 05, 06, 09 |
| A-03 | report.Version = "0.1.0" is reported faithfully and treated as the contract version / fingerprint namespace (quorum/v1), not the product version. |
05, 06 |
| A-04 | Quorum is CLI/Docker only: web, RDBMS, REST API and auth are N/A by architecture; AI/LLM stays out of the deterministic core and only appears as an opt-in advisory layer (off by default). | 01, 03, 08, 09, 13, 15, 17, 20, 99 |
| A-05 | OSV.dev is the only runtime network dependency of the core, optional and with graceful degradation; --offline disables it (air-gapped operation) and also blocks the remote advisor. |
01, 02, 03, 12 |
| A-06 | --timeout maps to PerScannerTime (per scanner); the 60s ProbeTime (defaultProbeTime) is separate and not exposed as a flag in v0.8.3. |
02, 14, 99 |
| A-07 | correlationKey and confidence are deterministic over the normalized data; the advisory layer is presentation-only and does not alter them. |
01, 05 |
| A-08 | ~~polaris appears in scannerCategory without an adapter~~ — resolved: polaris and kube-score are real adapters (K8S_POSTURE) since v0.5.0 (see G-03), participating in the K8s posture consensus. There is no phantom scanner. |
02, 05, 09, 16 |
| A-09 | The target matrix reflects Supports/Capabilities read from the code, preserving divergences (e.g. kubescape Supports repo+k8s but declares capability only k8s). |
02 |
| A-10 | The alias cache has no TTL; management/cleanup are manual; improvements listed as a future proposal. | 02, 07 |
| A-11 | Performance targets and SLO/SLI are engineering targets, not validated by a formal benchmark in the repo. | 03, 20 |
| A-12 | PCI/ISO/ASVS/Top10/DREAD mappings are interpretive of the code as-is, not a compliance attestation; DREAD scores are qualitative. | 03, 12 |
| A-13 | Owner/repo is Martinez1991/quorum-sec-scan and the registry is ghcr.io/martinez1991/quorum-sec-scan (lowercase). |
10, 11, 99 |
| A-14 | The :full image is linux/amd64 (Grype DB pre-cached at build-time); :slim covers amd64+arm64 with scanners on the PATH, changing the performance/availability profile. |
03, 09, 10, 99 |
| A-15 | The production consumer verifies the image/binary (cosign + gh attestation) and pins by digest; the product only provides the means. |
03, 11 |
| A-16 | Distribution availability depends on third parties (GHCR/Releases/OSV) outside the project's control. | 03 |
| A-17 | Logs are text with a [quorum] prefix on stderr (not JSON by default, no per-line levels/timestamps); the telemetry consumer is the invoking platform. |
03, 14 |
| A-18 | The repository is public OSS (free Actions/storage quotas); paid tiers model the private/overage case. FX US$ 1 ≈ R$ 5.50. | 19 |
| A-19 | Quorum's license is Apache-2.0 (confirmed via LICENSE); the licenses of the bundled scanners are estimates to confirm upstream. |
19 |
| A-20 | Image/artifact sizes are qualitative (inferred from the Dockerfiles), not measured in the repo. | 10, 19 |
| A-21 | Fixtures in internal/adapter/testdata are not part of the production execution path. |
13, 15 |
| A-22 | The advisory layer is opt-in and off by default; without --advice the output is byte-identical. Phase 0 (curated templates + OWASP refs) and Phase 2 (RAG over a digest-pinned OWASP corpus) are deterministic and model-free; Phase 1 (local LLM) and Phase 3 (remote provider) are opt-in, reproducible (temperature=0 + cache) and gated (remote requires --advice-allow-egress, is blocked by --offline and refuses --fix). Every AI attachment is labeled "AI-generated, advisory only". |
05, 06, 12, 13, 14, 15, 21 |
Gap Register¶
Items not verified at the source, divergences and known debts. These are natural candidates for the backlog (17-backlog) and improvements (20-melhorias).
✅ G-02, G-09, G-10 and G-11 were resolved in v0.2.4 (issues #15–#18, milestone hardening v0.2.4). The rows below remain for historical traceability.
| ID | Gap | Impact | Source documents |
|---|---|---|---|
| G-01 | Divergent version: report.Version hardcoded to 0.1.0 vs product v0.8.3; the intent (stable contract vs drift) is not clear in the code. |
Medium | 05 |
| G-02 | ✅ Resolved in v0.2.4 (#18). ~~durationMs in scanners[] serialized as nanoseconds~~ — now ScannerRun.MarshalJSON emits milliseconds, consistent with summary.durationMs. |
Medium | 06 |
| G-03 | ✅ Resolved in v0.5.0: polaris stopped being dead-config and became a real adapter (K8S_POSTURE), together with kube-score — re-added to scannerCategory. There is no more phantom scanner. |
Low | 02, 05, 09, 16 |
| G-04 | ✅ Resolved/accepted: cache with schemaVersion (v0.4.1). TTL and cross-process locking are intentionally omitted (decision): CVE↔GHSA aliases are immutable facts (they do not age), and the atomic write (tmp+rename) already prevents corruption — a concurrent loss is benign (just a re-lookup). |
Low | 07, 02 |
| G-05 | ✅ Resolved in v0.4.2: the crosswalk Load accepts a versioned document (schemaVersion + controls) in addition to the legacy list (backward-compatible), allowing the format to evolve. |
Low | 07 |
| G-06 | Grype DB frozen in the :full build — it can still miss recent CVEs without a rebuild/repull (staleness by design). ⚠️ Bug fixed in v0.2.6: GRYPE_DB_VALIDATE_AGE=false was missing, so after 5 days grype failed every scan (DB age validation); now the embedded DB does not expire (it only ages). |
High | 07, 18 |
| G-07 | ✅ Much improved / accepted residue: bases @sha256; SBOM SPDX attested (image) and per-binary; kubescape by SHA256; trivy/kics/dockle by digest/checksum; Grype/Syft via anchore install.sh (internal checksum). Accepted residue: Checkov via pip is version-pinned (==3.3.6) — the full hash-lock of the dep tree was deferred (high maintenance cost per bump + cross-platform musl fragility vs. low return). |
Low | 03, 12, 18 |
| G-08 | ✅ Resolved (v0.4.2/v0.4.4): --metrics <file> exports a Prometheus textfile and --log-format json emits the progress logs as JSON lines ({ts,level,msg}) for ingestion. |
Low | 03, 14 |
| G-09 | ✅ Resolved in v0.2.4 (#15). ~~--output without Clean (perm 0644)~~ — now filepath.Clean + write with perm 0o600 (R3). |
High | 12 |
| G-10 | ✅ Resolved in v0.2.4 (#16). ~~OSV id without url.PathEscape/validation~~ — now validated (^[A-Za-z][A-Za-z0-9._-]{0,127}$) + url.PathEscape (R6). |
Medium | 12 |
| G-11 | ✅ Resolved in v0.2.4 (#17). ~~target ref without rejecting -~~ — now the CLI boundary refuses a target starting with - (R1 argument injection). |
Medium | 12 |
| G-12 | ✅ Resolved (v0.4.1/v0.4.4): runCmd caps the scanner stdout (512 MiB, QUORUM_MAX_OUTPUT_BYTES) (R2) and there is a target size cap for repo/k8s (20 GiB, QUORUM_MAX_TARGET_BYTES, walk with early-abort) (R5). |
Low | 12 |
| G-13 | aliases.json without integrity/signature (perm 0644): cache poisoning risk (R7). |
Medium | 12 |
| G-14 | No redaction of secret values in the report (R8). | Medium | 12 |
| G-15 | Test coverage not collected in CI; internal/{model,purl,consensus,crosswalk} without dedicated _test.go; non-deterministic e2e (the gate only checks multiDetected>=1). |
Medium | 15 |
| G-16 | ✅ Resolved. ~~Moving v0 tag moved manually~~ — now the .github/workflows/tag-major.yml workflow advances v0/v0.2 automatically on each semver release. |
Low | 11, 99 |
| G-17 | ⚠️ Partially measured: image sizes confirmed — :full ≈ 3.3 GB, :slim ≈ 27 MB (2026-07-03). Actions minutes and GHCR storage remain under provider quotas (variable); performance benchmarks remain a target. |
Low | 19, 03, 10, 20 |
| G-18 | ✅ Resolved: THIRD_PARTY_NOTICES.md lists the bundled scanners (all Apache-2.0), and the attested SBOM SPDX per release is the authoritative list of components/licenses. | Medium | 19 |
| G-19 | ⚠️ Reduced: test coverage is now collected in CI (~60%), with new tests in purl/model/consensus/crosswalk and in the security flows; the exhaustive line-by-line verification of all adapters/reporters remains a documentary caveat (non-blocking). | Low | 02, 04, 09, 12, 20 |
Open questions (for stakeholders)¶
Decisions that depend on product/maintainers and that unblock or adjust the documentation.
Product and scope
- [x] Polaris: will it become an adapter or should the
scannerCategoryentry be removed? (G-03) — ✅ resolved:polaris+kube-scoreare real adapters (K8S_POSTURE) since v0.5.0. - [ ] kubescape: is the
Supportsrepo+k8s vs capability only k8s divergence intentional? It may confuse users onrepotargets. (A-09) - [ ] Is there appetite for additional image profiles (
:sca/:iac/:k8s) or is the:full/:slimpair definitive? - [ ] Is there appetite for
--format table/markdownand PR decoration while keeping the product strictly CLI (automation only in the Action)?
Contracts and versioning
- [ ] Should
report.Versionreflect the product version via ldflags or is it deliberate independent contract versioning? (G-01) - [ ] Is the
[]MergedFindingdump in the JSONfindingsfield (with fullMembers) a stable contract or an internal detail subject to change? - [ ] Should
durationMsinscanners[]be converted to milliseconds (consistency withsummary)? (G-02) - [ ] Is there an intent to officially publish the JSON Schema (
quorum-report-v1.json) as a versioned file?
Configuration and operation
- [ ] Should the 60s ProbeTime be exposed as a CLI/Action flag or stay internal? (A-06)
- [ ] Introduce
schemaVersioninaliases.jsonand/or in the crosswalk YAMLs for explicit migration? (G-04, G-05) - [ ] Offer a configurable TTL or a
quorum cache clearcommand for the alias cache? (A-10) - [ ] Should a custom crosswalk merge with the bundled one (instead of replacing it) when
--crosswalkpoints to another directory? - [ ] What is the recommended official cadence for rebuilding/repulling the
:fullimage (fresh Grype DB)? (G-06)
Advisory layer (AI)
- [ ] Should the default
--advice-providerever move beyondnone, or does an opt-in-only default stay the policy? (A-22) - [ ] Which local endpoints/models are officially supported/documented for
--advice-provider=local(e.g. Ollama)? - [ ] What is the cadence for refreshing and re-attesting the digest-pinned OWASP corpus (
quorum advise-index)?
Supply chain, security and CI
- [ ] Is there a plan to harden all scanners in
Dockerfile.fullto@sha256and generate an SBOM for:full? (G-07) - [ ] Does
release.ymlpublish SLSA attestation + cosign signature for both images (:fulland:slim), the binaries and the knowledge pack? - [ ] Is there an intent for an internal/configurable OSV mirror (BaseURL via env) for air-gapped beyond
--offline? - [ ] Do SAST (golangci-lint/gosec/CodeQL) and secret scanning (gitleaks) enter
ci.ymlor a dedicated workflow? - [ ] Should there be a blocking coverage gate in CI and what is the official target (suggestion: 80% global / 90% core)? (G-15)
- [ ] Should a self-scan (dogfooding) of the published images run in
release.ymlbefore the push? - [x] Will the moving
v0tag be moved by automation after the release? (G-16) — ✅ yes, viatag-major.yml. - [ ] Is there branch protection with required checks (ci/e2e) configured in the GitHub settings to formally reflect it?
Business and governance
- [ ] Is the repository public (OSS quotas) or private (subject to overage)? Is there a real budget/headcount or a volunteer regime? (A-18)
- [ ] What is the retention/GC policy for old tags in GHCR? (G-17)
- [ ] Officially confirm the license of each bundled scanner and the obligation to include a third-party NOTICE in
:full. (G-18) - [ ] Should there be an automatic warning for the "all scanners
ranbut 0 findings" case or does it stay only in the documentation?
Assumptions¶
Assumptions specific to this index (in addition to the consolidated ones above):
- The TOC was built from a real
Glob docs/*.md(21 documents present besides this index); the one-line descriptions derive from the H1s and the known scope of each file. - The Assumptions, Gaps and Questions registers consolidate the content of the sections of the same name in documents 01–20 and 99; each item references the source documents for traceability.
- The gap impact classification (Low/Medium/High) is qualitative and serves prioritization, it is not a measurement.
- Cross-links use relative
NN-file.mdpaths and assume that all files listed in the TOC remain in thedocs/directory.
Metadata¶
| Field | Value |
|---|---|
| Product | Quorum (quorum-sec-scan) |
| Documented version | v0.8.3 (AS-IS) |
| Source of truth | branch main |
| Scanners | 12 (trivy, grype, checkov, kics, dockle, kubescape, polaris, kube-score, terrascan, tfsec, regula, conftest) |
| Language | Go 1.26 (CLI with cobra) |
| Advisory layer | Opt-in --advice (off by default); Phases 0–3 implemented (internal/enrich, internal/rag, internal/advisor, internal/evals) |
| Distribution | Docker GHCR :full (linux/amd64) / :slim (amd64+arm64) + GoReleaser binaries; cosign keyless, SLSA build-provenance and SBOM SPDX attested (image and per-binary), plus knowledge-pack attestation |
| Owner/repo | Martinez1991/quorum-sec-scan |
| Registry | ghcr.io/martinez1991/quorum-sec-scan |
| License | Apache-2.0 |
| Doc language | en (default) |
| Revision date | 2026-07-04 |
| Status | Under review — pending stakeholder answers (see "Open questions") |