Repository navigation
Releases: shsingh/pqscan
Release list
pqscan 2026.01
pqscan 2026.01 — the release cut
2026.01 is the first general-availability cut. The rc series (2026.01-rc1,
rc2, rc3) stays the historical record. One release page carries this cut; the
rc pages remain for the record.
What this cut carries
- The QUIC census grows two rungs (PQ-69, merged through the #182 estate).
The deep census dials the RFC 9369 (QUIC v2) transport version and completes
one real HTTP/3 GET through the pinned quic-go stack. The record's
h3_directclaim = the handshake's ALPN answer; the deep findings carry the
functional h3 verdict beside it.quic/v2andquic/h3-exchangeride the
existing QUIC rung gate (-quic-off and an unhinted target stay QUIC-free). - The binary size bound = 10,000,000 bytes (10 MB) on both planes
(PQ-70, PR #186's ledger cure). The measured rows: linux/amd64 7,581,858 B
(the CI-pinned go1.26.0 chain), 8,085,664 B (the go1.27.2 host),
darwin/arm64 7,644,994 B — every row measured live on the merge tree
ba89d23; the gate, the ledger and the site card read one bound. - The measured performance: 2,750 h/s aggregate (W=8, loopback fixture,
the runner's same-day reading at the census tip; the SLO ≥ 2,500/s/core
stays green with every run). The site card and this README carry the same
number. - The sites live on their own domains: pqscan.kalatopi.sh,
opensase.kalatopi.sh, ai-sec-lab.kalatopi.sh — HTTPS enforced, per-domain
certificates, the DNS records live. - The writing standard (ASD-STE100) rides every user-facing surface:
the CLI's help and refusal strings, the -explain prose, the repository
documents, the site pages. The rendered pages carry no tracking ids.
The install
The release page carries the per-platform binaries, CHECKSUMS-sha256.txt, and
per-asset attestations. The install paths read INSTALL.md; the examples pin
2026.01.
- Homebrew: the tap formula bumps with this cut.
- Source:
go install github.com/shsingh/pqscan/cmd/pqscan@2026.01
The tag carries a signed annotated object; the publish gate ran the full
strict consistency check at the tagged tree before the dispatch.
pqscan 2026.01-rc3
pqscan 2026.01-rc3
The successor release candidate to 2026.01-rc2. rc3 is the
quality-gate day: the CLI surface went through a three-way parity census
against the reference tools, every documented flag combination is
machine-run on CI, the chain adapters read version-stamped pinned captures,
and error records finally meet the same schema contract success records
have had since schema 1.
The surface census: the documented surface is the real surface
The three-way census over the CLI surface — every spec row against its
USAGE.md row against the implemented state — landed in
docs/surface-census.md
(issue #146, PR
#151):
- Planned-list cuts:
-quic(superseded by the shipped-quic-always/
-quic-offpair; the bare flag has no independent reading) and-verify
(owned by no contract row; naabu's-verifyis a captured name collision)
leave the planned surface. - The spec's never-needed negative rows are cut:
-stream,-ja4,
-ca-bundle,-no-ptr,-no-color. -jarmearned its documented row (httpx v1.12.0's-jarmis the captured
convention) and stays a documented-ahead row in the planned surface.-from-nucleientered the surface and shipped in this same wave (below).
Every parity claim is a captured help line, version-stamped offline
(captures: naabu 2.6.1, httpx v1.12.0, subfinder v2.16.0, nuclei v3.11.1 —
help/version surfaces only, no scanned targets). The verdict rule: a row
earns its place iff a contract row plus a reference-tool or chain contract
needs it; it is cut iff superseded by a shipped sibling or owned by nothing.
The flag matrix
PQ-53 (issue #147, PR
#152): a generated pairwise
covering array over the CLI surface — the domain table
(tests/matrix/domains.json), 20 cases (tests/matrix/cases.jsonl) —
regenerated by scripts/gen_flag_matrix.go behind a self-verifying gate: CI
re-pins the array, regenerates, and compares three-way. The flag-matrix
context joined the required checks: every change is machine-run against the
documented combinations.
The combination batteries
PQ-54 (issue #148, PR
#155): the whole-argv property
battery over the unenumerated input space — two fixed seeds × 200 vectors
per tests/matrix/battery_test.go run (rotatable via PQ54_SEEDS; the
fixed seeds always run) — plus the documented exit-64 refusal classes as
deliberate battery rows whose expected text quotes the binary's own refusal
lines. Pooled and calibrated to the CI runner's wall budget.
The chain matrix and the adapters
PQ-55 (issue #149, PR
#158): -from-nuclei reads
the pinned capture (nuclei -l hosts.txt -silent -j — one JSON finding per
line, the matched-at host:port with the url as the fallback, scheme and path
stripped) into the one composition shared with -u / -l / -- and the
other adapters, deduped by host:port. The adapters' consumer cells joined
the matrix run, and every adapter input dialect is pinned by a
version-stamped capture before its parse contract — the httpx -csv
dialect's real captured shape is the pinned reality the docs quote.
The combination ledger
PQ-56 (issue #150, PR
#160):
tests/matrix/LEDGER.md pins landed truth — one
checkbox per matrix cell in the issue registry, a per-cell PASS/SKIP line
posted per build, green cells ticked with the proven commit, and every fix
or feature landing its own cell in the same change.
The doc-reference scrub
PQ-57 (issue #153, PRs
#161 and
#163): the tool's user-facing
strings carry zero PRD references — no doc-file paths, no internal tokens,
no issue-register mentions anywhere user-facing. The surface audit gained a
zero-reference census (it renders the live surface and greps one inventory:
doc-file paths, .md tokens, PQ-N ids, status words), so a re-introduced
reference fails CI. The sweep is recorded in the spec's test-and-verification
chapter (section 10).
Errors meet the record contract
PQ-60 (issue #157, PR
#162): schema-required blocks
emit unconditionally on BOTH record classes — the handshake zero-halves and
the quic block appear on error-class and skipped runs exactly as on success
records (omitempty is forbidden on the schema's required field list), and
TestErrorRecordSchemaContract pins the uniform contract against the
published docs/schema-v1.json. The error.* goldens
regenerated; the success-class goldens stayed byte-identical — the cure did
not disturb the valid shapes.
The recipes and the docs re-capture
PQ-58 (issue #154, PR
#164): every recipe line on
the site is executed live against the current surface and its Observation
quotes that exact run's output; the external-input examples pin the
reference tools' captured dialects (subfinder v2.16.0, httpx v1.12.0,
nuclei v3.11.1, version-stamped in the fixtures).
The performance and size surfaces move with the cut
From rc3 on, every release build is preceded by the release-prep pass
(issue #156): the throughput
SLO + size + resume suites re-run live on the to-be-cut tree, and README's
SLO cell, the site's performance surfaces and the size ledger
(docs/size-ledger.md) carry the measured numbers — the
release gate then verifies rather than prepares. At this cut the throughput
SLO cell stands at 2,952 h/s (re-run 3,026; the engine's handshake planes
are unchanged since 2026.01-rc2 and the CI runner's same-day readings
bracket the documented cell), while the size ledger moved to the measured
tree: 7,131,298 bytes CI-enforced (go1.26.0), 7,643,296 bytes local at
go1.27.2.
Release notes reference: 2026.01-rc2.md. Attestation: gh attestation verify <asset> --owner shsingh; all assets carry SLSA provenance (ADR-0003).
pqscan 2026.01-rc2
pqscan 2026.01-rc2
The successor release candidate to 2026.01-rc1. rc2 carries the post-rc1 operator wave: the CLI now speaks for itself, the record's human line tells the same story the machine formats carry, the input grammar works the way the Project Discovery chains actually hand off, and the forced PQ ladder is finally visible.
The CLI speaks for itself
-versionprints the stamp and nothing else — no status words, no internal document references:pqscan 2026.01-rc2.-his a real help for the practitioner: what the tool observes on both planes, the readiness verdict and its HNDL consequence in plain language, the whole implemented surface grouped (descriptions read straight off the registration surface — one source), runnable examples, the real exit codes (0/1/64), and the reading-the-output glossary. Every flag also parses under two dashes (--word≡-word), and the completions + the man page say so.-explainadds a plain-language block under each target line: the verdict in words (zero-signal scans state that scoring is an error state, not a grade), what the negotiated group means (PQ hybrid / classical / obsolete draft, with the harvest-now-decrypt-later consequence), the certificate layer with the rotation that closes the gap, the QUIC plane, and an error-class hint when nothing negotiated. Deep mode adds the executed plan's reading — counts, the matrix yield rolled up by probe family, and the accepted rows named — and pq mode's ladder carries the same reading for the forced offers.
The record's human line tells the whole truth
The default -text line carries the same facts as the machine formats, suffix-appended (existing fields byte-stable):
pq=<label>(<score>)— the readiness verdict on the linedeep=<plan>:<N>p/<N>ok/<N>rej— the executed plan (or forced ladder) countscert=<sigAlg>/<keyAlg>with+pq-sig/+pq-key/+dualmarkers when true — the certificate layer in every modeptr=/sni=enrichment when present
Rejections stay observations: a refused probe is a result, never an error.
The input grammar works the way the chains do
- Implicit piped stdin —
subfinder -d example.com | pqscan --still works, andcat targets.txt | pqscan -jsonlnow works with no marker at all: piped input is the default target source when no-u/-l/--/adapters are given. -l -— the universal stdin-file alias.scheme://host[:port]lines parse everywhere the host:port grammar does — thehttpx -silenthandoff flows through the pipe unstripped.- The full documented chain now runs end to end:
subfinder -d example.com -silent | httpx -silent -p 443 | pqscan -jsonl.
The forced PQ ladder is visible
-mode pq records what the ladder did: a ladder block in the record (mode: "pq", attempted/ok/rejected + one finding per forced offer — the same shape the deep executor uses) and the counts on the line (deep=pq:…p/…ok/…rej). -mode fast and -mode pq no longer look identical.
Shell completions
pqscan -completion bash|zsh emits deterministic completion scripts covering every implemented flag, the choice values, and file completion where a flag takes a path — install one-liners ride the help, USAGE.md and INSTALL.md.
The audit that guards all of the above
go test ./cmd/pqscan/ -run TestCLISurfaceContract -v re-checks the whole human-facing surface on every change — per-flag help/man-page/completion coverage, the meta paths, the exit-code table, a live scan with -explain, and the gate verdicts — so verifying the CLI never requires cutting a binary.
Labels and hygiene
Repository labels are area:* (the primary axis — every issue files the right area) + bug (a genuine operator-facing defect, kept after closure) + the milestone/effort slices; the board's status stays a project field.
Release notes reference: 2026.01-rc1.md. Attestation: gh attestation verify <asset> --owner shsingh; all assets carry SLSA provenance (ADR-0003).
pqscan 2026.01-rc1
pqscan 2026.01-rc1 — TLS/QUIC cipher-configuration and PQC readiness scanner
2026.01-rc1 is the milestone-completion candidate: every register leaf
(PQ-02 through
PQ-37) has landed via
reviewed, GPG-signed watched-RED pairs — grammar, pipeline, encoders/WAL/
resume, the usage-drift gate, the IANA registry, the readiness rubric
(+ the live verdict), certificate PQ analytics, congestion control
(limiter/AIMD/breakers with -rate/-threads), the deep-mode plan and
executor, the h3 discovery, the resolver pool and the PD-dialect input
adapters. Artifacts are verifiable before they run
(ADR-0003); the release
gate (PQ-34) re-verifies the
signed tag, the repo's version sync, the site render and FRESH
performance numbers as part of every publish.
Verify
sha256sum -c <(grep <artifact> CHECKSUMS-sha256.txt)
gh attestation verify <artifact> -R shsingh/pqscan2026.01-rc1 content:
- goreleaser consolidation (PQ-27):
the release matrix is now five targets — linux/amd64+arm64,
darwin/amd64+arm64, windows/amd64 — built by
goreleaser (v2) from
.goreleaser.yaml, withCHECKSUMS-sha256.txtover the bare
pqscan-<os>-<arch>asset names and a deterministic
GORELEASER_CURRENT_TAGversion stamp. - Pre-built windows/amd64 binary (the
PQ-29 install-story
promise kept):pqscan-windows-amd64.exe, attested like the rest. - Release gate as publish pre-flight: the publish job runs
scripts/check_release_consistency.sh <tag>before creating the release
(the runner has no release key, so the tag signature is verified at the
cut machine and recorded here in
PQ-27). - Sample scan dataset committed:
docs/sample-scan.jsonl— one live
fast-mode record againstgoogle.com(the reference
PQ-36 target),
captured by this cut's build.
pqscan v0.0.2-alpha
pqscan v0.0.2-alpha — TLS/QUIC cipher-configuration and PQC readiness scanner
pqscan is a small, fast, chainable TLS/QUIC cipher-configuration and
post-quantum readiness scanner shipped as a single static binary (the
PD-ecosystem contract in
docs/spec.md#5-feature-set).
v0.0.2-alpha is the first development cut; the 2026.01-rc1 name is
reserved for the release that follows completion of the current
milestone set (M1-M5). It packages the engine state
that closed the M0 gate
together with the tooling needed to verify it. Artifacts are verifiable
before they are run — that is the governance contract of this tool.
What is included
- Both-plane engine proven live. Forced-group probing negotiates the
PQC hybrid groupX25519MLKEM768(4588) on both transport planes:
on the TCP plane (internal/tlsx) — TLS 1.3,TLS_AES_128_GCM_SHA256
(version 772) — and inside QUIC v1 with ALPNh3
(internal/quicx). Measured against a live hybrid edge, evidence
verbatim on issue #8
(TCP) and issue #9
(QUIC). Rejections are results, not errors: UDP failures are
classified (refused/blocked) and recorded; on-the-wire HRR
observation (RFC 8446 §4.1.3) extracts the group a server demands,
including the obsolete Kyber draft 25497 still honoured by some
edges — the finding that seeds the compat-oracle ladder. -debug/-debug-outdiagnostics. Every engine decision point
(ladder step, QUIC handshake, refusal classification) emits a
diagnostics event: a human stream on stderr under-debug, and a
schema-1 machine report via-debug-out diag.json
(USAGE.md,
issue #29).- Single-target fast mode (
-u). The binary scans a single target
(host,host:port,ip:port) in fast mode: both planes probed
(QUIC skippable via-quic-off), jsonl/text output via-jsonl/
-o— live on the proven engines (PQ-30,
PR #55). - Measured benchmarks. The M0 gate measured the single-target fast
path end to end on the loopback fixture: 2,952 handshakes/s at
W=8 (re-run 3,026) against the ≥ 2,500 target
(issue #10). The
latency decomposition holds on live hosts: connect ≈ 1 RTT
(18.94 ms), handshake 23.44 ms, total ≈ 2 RTT + server compute
(42.4 ms, cloudflare seq×20); QUIC per-conn cost 22.5 ms avg
handshake, goroutine delta 3, heap 665 KB. Full SLO cells in
docs/m0-report.md. - SLSA provenance on every artifact. Every binary in this release
is built in Actions and attested in the same job that produces it
(actions/attest-build-provenance, no post-hoc wrapping):
Sigstore-signed SLSA build provenance bound to the repository/OID
issuer
(ADR-0003: SLSA provenance via GitHub Artifact Attestations).
Verify before running
Every artifact carries SLSA build provenance; verify it — the digests
must match the artifacts for this repository. With the gh CLI:
gh attestation verify <artifact> -R shsingh/pqscan
A verified run exits 0; a non-TTY invocation of the CLI may print
nothing on success — for the structured proof (subject digest, signer
identity, Rekor timestamp, build invocation) use:
gh attestation verify <artifact> -R shsingh/pqscan --format json
The Sigstore bundle is also retrievable offline per artifact with
gh attestation download <artifact> -R shsingh/pqscan.
Each release also carries CHECKSUMS-sha256.txt (sha256 over every
binary). From the directory holding the artifacts:
sha256sum --check CHECKSUMS-sha256.txt
Limitations
2026.01-rc1 is an engine-gate release candidate, not the full M1/M2
surface:
- Multi-target grammar and run pipeline land with M1: target
grammar and the run pipeline
(#38), output encoders
and the WAL (#39).
Until then the rc1 binary's scan surface is intentionally minimal —
single targets via the fast mode (-u) on the live-proven engines
and the diagnostics path fully functional; targets-as-grammar
(CIDRs, ranges, lists) are rejected until PQ-15 lands. - Deep- and pq-mode ladders land with M2: the deep-mode plan
executor (offer-one matrix, pruned DAG)
(#43), PQC readiness
scoring (#42), IANA
regen tables (#41) and
the surrounding analytics — the full range is tracked under issues
#38–#45. - M0 deferred SLO cells — aggregate sustained under load, p95
per-target, RSS at 50k in-flight and deep-mode rate are measured at
their owning milestones (M3/M4) and are listed explicitly in
docs/m0-report.md
so no cell is silently skipped.