0002
July 20, 2026 · View on GitHub
- Status: Accepted
- Date: 2025-06-09
- Deciders: quantakrypto-tools maintainers
- Supersedes / Superseded by: —
Context
Three of the four user-facing tools — qscan (CLI), mcp (agent server), and
action (CI) — answer the same question ("where is the quantum-vulnerable
crypto, and what replaces it?"). If each re-implemented detection, inventory, or
remediation logic, the tools would drift: a finding that fails CI might not appear
in the editor, and a remediation the agent suggests might differ from the one the
report prints. Sieve is the exception — it tests other people's crypto and
shares no detection logic (see ADR-0004).
The crypto-analysis knowledge — detectors, the vulnerable-dependency DB, the inventory/readiness scoring, the remediation table, and the SARIF/JSON/human reporters — is the asset. It must live in exactly one place.
Decision
We will keep all cryptographic-analysis logic in @quantakrypto/core and treat its
public surface (src/index.ts re-exports + the types in src/types.ts) as the
contract. qscan, mcp, and action are thin shells that consume core;
they do I/O and policy, never detection. (The later opt-in @quantakrypto/agent
also consumes core — for the shared agent-plane types, the context redactor, and
the triage/remediate rubrics — so the same contract discipline applies to it, giving
core four consumers across the six workspace packages.) The MCP HOSTING.md
states the rule directly: transports do I/O and policy; McpServer does
protocol; @quantakrypto/core does cryptographic analysis.
The locked contract is:
scan(ScanOptions): Promise<ScanResult>and the walkerwalkFiles.- The data types
Finding,CryptoInventory,Severity,AlgorithmFamily,FindingCategory. - The reporters
toSarif,toJson,formatSummaryandbuildInventory. remediationFor, thedetectorsarray,vulnerableDependencies,VERSION.
Consumers must reuse core's primitives rather than re-derive them. (The
architecture audit and/P1-3
flagged two violations here: the qScan/Action baseline fingerprint schism and
the Action re-implementing fingerprint/applyBaseline/renderReport instead of
importing runQscan. Both are now closed — the Action imports runQscan and the
single canonical baseline module lives in core, so the divergent copies are gone.
Keeping consumers thin remains conformance to this ADR, not a new decision.)
Consequences
Easier: one definition of a finding; identical verdicts across CLI/agent/CI; one place to add a detector, a CWE tag, or a CBOM exporter and have all three tools benefit; a stable public API to version (see VERSIONING.md).
Harder (costs accepted): the core surface is now a compatibility commitment
— changes to Finding, ScanResult, or a reporter's output shape ripple to every
consumer and, post-1.0, are breaking. We accept the discipline of treating
src/types.ts as load-bearing and gating changes to it through SemVer.
Enforcement: the build's project references (see ADR-0003)
make the dependency direction explicit; a future public-API reference + a
review rule ("does this PR add detection logic outside core?") keep consumers
thin. The baseline-unification work (P1-1) has landed: the one shared baseline
module now lives in core (fingerprintFinding / applyBaseline / loadBaseline /
…), so the two divergent copies cannot persist.
Alternatives considered
- Let each tool own its slice of logic for independence. Rejected: it guarantees the drift this ADR exists to prevent and multiplies the maintenance and audit surface by three.
- A looser "core is a library, copy what you need" convention without treating the surface as a contract. Rejected: that is the status quo that produced the baseline schism; an explicit contract with versioning is the fix.