pqcheck 0.16.9 → 0.16.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,19 +6,22 @@
6
6
  [![npm downloads](https://img.shields.io/npm/dm/pqcheck.svg?style=flat-square&color=06b6d4)](https://www.npmjs.com/package/pqcheck)
7
7
  [![license](https://img.shields.io/npm/l/pqcheck.svg?style=flat-square&color=06b6d4)](./LICENSE)
8
8
 
9
+ > **Latest: v0.16.12** — README rewritten to lead with the AI deploy gate (drift between deploys) as the product; DBR repositioned as the severity model the gate uses. No CLI behavior changes. [Full changelog →](./CHANGELOG.md)
10
+
9
11
  ```bash
10
12
  npx pqcheck deploy-check yourdomain.com --ai
11
13
  ```
12
14
 
13
15
  ```
14
- ◆ Cipherwake · yourdomain.com ⚠ REVIEW · DBR 4.1 C · HIGH
16
+ ◆ Cipherwake · yourdomain.com ⚠ REVIEW · 2 changes since last scan · HIGH
15
17
 
16
- Top finding:
17
- [HIGH] ECDHE-only — quantum-vulnerable key exchange
18
+ Surface changes:
19
+ + New third-party script: widget.intercom.io
20
+ ~ Strict-Transport-Security weakened: max-age=31536000 → max-age=3600
18
21
 
19
22
  CIPHERWAKE_AI_GUARD_RESULT
20
23
  ship_decision=review
21
- top_issue=tls.ecdhe_only_quantum_vulnerable
24
+ top_issue=vendor.new_third_party_script
22
25
  END_CIPHERWAKE_AI_GUARD_RESULT
23
26
  ```
24
27
 
@@ -32,11 +35,18 @@ Zero install. Works in any terminal with Node 18+. Free, no signup, no API key r
32
35
 
33
36
  ## What pqcheck actually checks
34
37
 
35
- Each `pqcheck <domain>` scans your site's public HTTPS surface and produces:
38
+ Each `pqcheck deploy-check <domain>` compares your site's public HTTPS surface *now* against your last scan and surfaces what changed:
39
+
40
+ - **New third-party scripts** loading on the page that weren't there before (the Polyfill.io-class supply-chain risk)
41
+ - **Header regressions** — CSP weakened, HSTS shortened or removed, X-Frame-Options dropped, permissive tokens (`'unsafe-inline'`, `*`) introduced
42
+ - **Certificate / SPKI changes** — unexpected rotations, key reuse across renewals, intermediate-chain changes
43
+ - **TLS posture changes** — ciphersuite shifts, hybrid PQC key-agreement (`X25519MLKEM768`) added or removed
44
+ - **Vendor surface changes** — new email senders (SPF/DMARC), new CDN origins, new analytics endpoints
45
+ - **Subdomain takeover exposure** — new dangling CNAMEs pointing at AWS S3 / GitHub Pages / Heroku / Fastly / etc.
46
+
47
+ The gate routes each change through a severity model — the **Decryption Blast Radius** score (DBR, 0–10) — to decide `pass` / `review` / `block`. Cosmetic drift passes; high-severity drift (new script from an unknown origin, header regression that breaks defense-in-depth, cert SPKI change without a rotation event) triggers `review`; critical drift (expired cert served, takeover-vulnerable subdomain, malicious vendor injected) triggers `block`. DBR's full severity rubric is documented at [/methodology/decryption-blast-radius](https://cipherwake.io/methodology/decryption-blast-radius).
36
48
 
37
- - a **DBR score** (Decryption Blast Radius, 0–10) how much of today's traffic would be readable to an attacker who's storing it now and waiting for quantum computers to break today's encryption (the "harvest-now, decrypt-later" risk, typically 5–10 years out per NIST timelines)
38
- - a **letter grade** (A–F)
39
- - a **findings list** ranked by severity — TLS cipher suites, certificate quality, security headers (CSP / HSTS / etc.), third-party scripts loaded by the page, key reuse across subdomains, and more
49
+ On **first use** (no prior scan to diff against), `deploy-check` falls back to absolute-posture grading: it scores the current state and surfaces the highest-severity findings so you start with a baseline. Every subsequent run is drift-relative to the previous scan.
40
50
 
41
51
  You get the same scanner that powers [cipherwake.io](https://cipherwake.io), the browser extension, and the GitHub Action.
42
52
 
@@ -44,54 +54,74 @@ You get the same scanner that powers [cipherwake.io](https://cipherwake.io), the
44
54
 
45
55
  ## Commands at a glance
46
56
 
57
+ Grouped by intent: **deploy gate** (the flagship wedge) → **drift comparison** (the engine the gate runs on) → **AI setup / install** → **workflow scaffolds** → **committable artifacts** → **posture grade + tracking** → **diagnostic**. Every CLI command is listed here exactly once; flags / output formats / exit codes are in [Flags, formats & exit codes](#flags-formats--exit-codes) further down.
58
+
47
59
  | Command | What it gives you |
48
60
  |---|---|
49
- | `npx pqcheck <domain>` | The basic scan. Returns DBR score (0–10), letter grade (A–F), and a list of findings ranked by severity. The fastest way to ask "is my site's HTTPS posture healthy today?" |
50
- | `npx pqcheck deploy-check <domain> --ai` | The flagship command. Wraps the scan with `ship_decision=pass\|review\|block` for your AI coding agent to gate the deploy announcement. Works anonymously on first use; subsequent runs compare against the previous scan. |
61
+ | **Deploy gate the flagship wedge** | |
62
+ | `npx pqcheck deploy-check <domain> --ai` | **The flagship.** Scans the domain, compares against the previous scan (first run sets the baseline), and emits a `ship_decision=pass\|review\|block` field your AI coding agent parses to decide whether to announce the deploy, ask you, or stop. Works anonymously no signup needed. |
63
+ | **`npx pqcheck guard --domain <D> -- <cmd>`** | **Deploy guard wrapper.** Wraps any deploy command. Runs `deploy-check` first; conditionally runs `<cmd>` based on `ship_decision`. Modes: `--gate-mode balanced` (default) / `advisory` / `strict`. ONE command instead of two — the strongest single artifact for AI-coder workflows because the AI never has to remember to chain check + deploy. |
64
+ | **`--ai` flag** (any of the above) | **AI Coder Mode.** Three-layer output (banner / body / structured `CIPHERWAKE_AI_GUARD_RESULT` block) tuned for Claude Code / Cursor / Aider / Zed. Includes a `ship_decision=pass\|review\|block` field your AI coworker parses to decide whether to announce the deploy, ask you, or revert. See [/methodology/ai-coder-mode](https://cipherwake.io/methodology/ai-coder-mode). |
65
+ | **Drift comparison — what the gate runs on** | |
51
66
  | `npx pqcheck trust-diff <domain>` | Compare today's HTTPS surface against a saved baseline (last week / last month / a saved CI baseline). For CI gates and release checklists. |
52
- | `npx pqcheck preview-diff --preview <URL> --production <URL>` | Compare a Vercel/Netlify preview deployment URL to production. Surfaces new third-party scripts, header regressions, and DBR score drops *inside the PR*, before merge. **v0.16.3** — now renders per-signal N vs N+1 status on every run (scripts, headers, cert SPKI, TLS, …) so you can see *every* check fired, not just "did something change." Add `--verbose` for the full side-by-side table. |
53
- | `npx pqcheck vendors export/check/sync <domain>` | Vendor lockfile (`cipherwake.vendors.json`) + CI gate that exits non-zero when a new third-party origin appears. Like `package-lock.json` for vendor scripts. |
67
+ | `npx pqcheck preview-diff --preview <URL> --production <URL>` | Compare a Vercel/Netlify preview deployment URL to production. Surfaces new third-party scripts, header regressions, and DBR score drops *inside the PR*, before merge. Renders per-signal N vs N+1 status on every run (scripts, headers, cert SPKI, TLS, …) so you can see *every* check fired, not just "did something change." Add `--verbose` for the full side-by-side table. |
68
+ | **AI setup / install** | |
69
+ | **`npx pqcheck setup --auto --domain <D>`** | **One-command full setup for every AI coder.** Installs (idempotently): GitHub Action workflow, AI Coder Protocol across all detected rules files (Claude / Cursor / Copilot / Aider / Windsurf / Continue / Cline / AGENTS.md) using fenced markers (`<!-- CIPHERWAKE_AI_CODER_PROTOCOL_START/END -->`), git pre-push hook, Claude Code statusLine + 2 hooks (PostToolUse Bash + **UserPromptSubmit**), per-repo `.cipherwake/last-status.json` for Cursor / Copilot / Continue to read as context. Skip flags available. Backups taken before any `~/.claude/settings.json` write. Audit trail at `~/.config/cipherwake/install-prefs.json`; install manifest at `~/.config/cipherwake/install-manifest.json`. |
70
+ | **`npx pqcheck setup --plan --domain <D>`** | **Dry-run mode.** Prints every file change `--auto` would make (target paths + operation type: create / append-markered / deep-merge / backup-first) without writing anything. Run this first when you're not sure what `--auto` will touch. |
71
+ | **`npx pqcheck protocol install`** | **Opt-in installer** for the AI Coder Protocol — appends the pre-deploy verification rule to your `CLAUDE.md` / `.cursorrules` / `.aider.conf.yml` with explicit consent (Rule 17). One upfront question (auto / manual / no). Never silent writes. |
72
+ | **`UserPromptSubmit` hook** | **Claude sees `ship_decision` before responding to every prompt.** When `pqcheck setup --auto` runs, it wires `cipherwake-prompt-hook` as a Claude Code UserPromptSubmit hook. On every user prompt, the hook injects `additionalContext` with the current scan's `ship_decision` IF it's `review`/`block` and the state is <24h old. Silent when state is missing, stale, or `pass`. Different timing from the PostToolUse chat-hook: this fires *before* Claude thinks (proactive), the chat-hook fires *after* a Bash command (reactive). |
73
+ | **Per-repo state file** `.cipherwake/last-status.json` | **Cursor / Copilot / Continue read this for workspace context.** Every `pqcheck` scan writes the same payload as the per-user file. Created by `setup --auto`; auto-added to `.gitignore` (per-developer state, not committable). Gives AI agents inside VS Code-family editors a repo-local artifact they pick up automatically when reading workspace files. |
74
+ | **Workflow scaffolds** | |
54
75
  | `npx pqcheck onboard <domain>` | One command: scan → scaffold the GitHub Action → capture a vendor lockfile → set a baseline → commit + push. Zero copy-paste from docs. |
55
- | **`npx pqcheck guard --domain <D> -- <cmd>`** 🆕 | **Deploy guard wrapper.** Wraps any deploy command. Runs `deploy-check` first; conditionally runs `<cmd>` based on `ship_decision`. Modes: `--gate-mode balanced` (default) / `advisory` / `strict`. ONE command instead of two — the strongest single artifact for AI-coder workflows because the AI never has to remember to chain check + deploy. |
56
- | **`npx pqcheck protocol install`** 🆕 | **Opt-in installer** for the AI Coder Protocol — appends the pre-deploy verification rule to your `CLAUDE.md` / `.cursorrules` / `.aider.conf.yml` with explicit consent (Rule 17). One upfront question (auto / manual / no). Never silent writes. |
57
- | **`npx pqcheck setup --auto --domain <D>`** 🆕 | **One-command full setup for every AI coder.** Installs (idempotently): GitHub Action workflow, AI Coder Protocol across all detected rules files (Claude / Cursor / Copilot / Aider / Windsurf / Continue / Cline / AGENTS.md) using fenced markers (`<!-- CIPHERWAKE_AI_CODER_PROTOCOL_START/END -->`), git pre-push hook, Claude Code statusLine + 2 hooks (PostToolUse Bash + **UserPromptSubmit** ⓝ), per-repo `.cipherwake/last-status.json` for Cursor / Copilot / Continue to read as context. Skip flags available. Backups taken before any `~/.claude/settings.json` write. Audit trail at `~/.config/cipherwake/install-prefs.json`; install manifest at `~/.config/cipherwake/install-manifest.json`. |
58
- | **`UserPromptSubmit` hook** (v0.15.1 ⓝ) | **Claude sees `ship_decision` before responding to every prompt.** When `pqcheck setup --auto` runs, it wires `cipherwake-prompt-hook` as a Claude Code UserPromptSubmit hook. On every user prompt, the hook injects `additionalContext` with the current scan's `ship_decision` IF it's `review`/`block` and the state is <24h old. Silent when state is missing, stale, or `pass`. Different timing from the PostToolUse chat-hook: this fires *before* Claude thinks (proactive), the chat-hook fires *after* a Bash command (reactive). |
59
- | **Per-repo state file** `.cipherwake/last-status.json` (v0.15.1 ⓝ) | **Cursor / Copilot / Continue read this for workspace context.** Every `pqcheck` scan writes the same payload as the per-user file. Created by `setup --auto`; auto-added to `.gitignore` (per-developer state, not committable). Gives AI agents inside VS Code-family editors a repo-local artifact they pick up automatically when reading workspace files. |
60
- | **`npx pqcheck setup --plan --domain <D>`** 🆕 | **Dry-run mode.** Prints every file change `--auto` would make (target paths + operation type: create / append-markered / deep-merge / backup-first) without writing anything. Run this first when you're not sure what `--auto` will touch. |
61
- | **`npx pqcheck debug-network`** 🆕 | **Connectivity diagnostic.** Probes cipherwake.io API, homepage, crt.sh upstream, and the direct Vercel URL (bypassing Cloudflare). Reports HTTP status + timing per hop. Use when "scan hung" / "command not found" / corporate proxy issues come up — surfaces the actual broken hop with an actionable cause list. |
62
- | **`--ai` flag** (any of the above) | **AI Coder Mode** (0.15.0). Three-layer output (banner / body / structured `CIPHERWAKE_AI_GUARD_RESULT` block) tuned for Claude Code / Cursor / Aider / Zed. Includes a `ship_decision=pass\|review\|block` field your AI coworker parses to decide whether to announce the deploy, ask you, or revert. See [/methodology/ai-coder-mode](https://cipherwake.io/methodology/ai-coder-mode). |
76
+ | `npx pqcheck init` | Interactive scaffold for `.github/workflows/cipherwake.yml`. Use when you want manual control instead of `onboard`'s all-in-one flow. |
77
+ | `npx pqcheck release-checklist [domain]` | Pre-release trust checklist (markdown, offline). Paste into release notes. |
78
+ | `npx pqcheck vendors export/check/sync <domain>` | Vendor lockfile (`cipherwake.vendors.json`) + CI gate that exits non-zero when a new third-party origin appears. Like `package-lock.json` for vendor scripts. |
79
+ | **Committable artifacts (SBOM-style)** | |
80
+ | `npx pqcheck lock <domain>` | Generate `cipherwake.lock` (QXM committable manifest) + human-readable `cipherwake-report.md`. SBOM-style artifact for quantum exposure commit both, diff in PRs. |
81
+ | `npx pqcheck diff <old.lock> <new.lock>` | Compare two QXM lockfiles; exit 2 on regression. For CI PR-comment diffs. |
82
+ | `npx pqcheck deps <domain>` | Scan all third-party origins on the page (supply-chain HNDL grading). `--lock` writes `cipherwake-deps.lock` + `.md`; `--allowlist`, `--baseline`, `--fail-on-new` for CI vendor gates. |
83
+ | `npx pqcheck cert <file.pem>` | Analyze a local PEM/CRT cert file offline (no network). |
84
+ | **Posture grade + tracking** | |
85
+ | `npx pqcheck <domain>` | **Posture grade (no diff baseline).** Returns DBR score (0–10), letter grade (A–F), and a list of findings ranked by severity. Use when you want a one-shot health check without setting up a baseline — for first-time audits, ad-hoc spot checks, or grading a domain you don't own. For ongoing deploys, use `deploy-check` instead. |
86
+ | `npx pqcheck history <domain>` | 90-day score history (sparkline + samples). `--days <N>` to change window. |
87
+ | `npx pqcheck changes <domain>` | Summarize public attack-surface changes in last 14 days. |
88
+ | `npx pqcheck watch <domain>` | Add domain to your watched list on the server (needs `CIPHERWAKE_API_KEY`). Distinct from the `--watch <secs>` flag, which is local polling. |
89
+ | **Diagnostic** | |
90
+ | **`npx pqcheck debug-network`** | **Connectivity diagnostic.** Probes cipherwake.io API, homepage, crt.sh upstream, and the direct Vercel URL (bypassing Cloudflare). Reports HTTP status + timing per hop. Use when "scan hung" / "command not found" / corporate proxy issues come up — surfaces the actual broken hop with an actionable cause list. |
63
91
 
64
92
  Free tier covers all of the above within 100 Trust Diff calls/month per repo via OIDC. **Founder Pro** ($19.99/mo, locked while subscription active) raises that to 5,000 calls/month + unlocks custom thresholds, vendor lockfile, CI fail rules, and 5 watched domains. Single-domain scans (`npx pqcheck <domain>`) are anonymous + rate-limited per IP — no account or key needed. `npx pqcheck deploy-check <domain> --ai` also works fully anonymously for first-deploy gating.
65
93
 
66
94
  ### AI Coder Mode in 30 seconds
67
95
 
68
96
  ```bash
69
- npx pqcheck cipherwake.io --ai
97
+ npx pqcheck deploy-check cipherwake.io --ai
70
98
  ```
71
99
 
72
100
  Output:
73
101
 
74
102
  ```
75
- ◆ Cipherwake · cipherwake.io ⚠ REVIEW · DBR 4.1 C · HIGH
103
+ ◆ Cipherwake · cipherwake.io ⚠ REVIEW · 1 change since last scan · HIGH
76
104
 
77
- Top finding:
78
- [HIGH] ECDHE-only — quantum-vulnerable key exchange
105
+ Surface changes:
106
+ + New third-party script: widget.intercom.io
107
+ Loaded from an origin not present in your last scan.
79
108
 
80
109
  Why it matters:
81
- Forward-secret against classical attackers. Shor's algorithm decrypts
82
- recorded handshakes once a CRQC exists.
110
+ New third-party scripts execute in full page context. A script that
111
+ appeared without an intentional code change = supply-chain risk vector
112
+ (Polyfill.io-class). Confirm it was added on purpose.
83
113
 
84
114
  Recommended next action:
85
- Review finding above and decide if it was intentional.
115
+ Review the change above and decide if it was intentional.
86
116
  View full report: https://cipherwake.io/r/cipherwake.io
87
- Re-scan with --fresh after fix: npx pqcheck cipherwake.io --fresh --ai
117
+ Re-scan after fix: npx pqcheck deploy-check cipherwake.io --ai
88
118
 
89
119
  CIPHERWAKE_AI_GUARD_RESULT
90
120
  status=review
91
121
  domain=cipherwake.io
92
122
  ship_decision=review
93
123
  max_severity=high
94
- top_issue=tls.ecdhe_only_quantum_vulnerable
124
+ top_issue=vendor.new_third_party_script
95
125
  advisory_only=true
96
126
  END_CIPHERWAKE_AI_GUARD_RESULT
97
127
  ```
@@ -215,15 +245,7 @@ npx pqcheck vendors sync mycompany.com # Founder Pro — pull dashboard all
215
245
 
216
246
  `pqcheck deps` also surfaces a one-line site-wide **CSP verdict** above the supply-chain table (`✗ No CSP enforcement` / `⚠ CSP is permissive` / `✓ Strict CSP enforced`) and friendly vendor labels (`New Relic · errors` / `Cloudflare · cdn` / `Adobe Fonts · fonts`) instead of raw hostnames. Same data shape ships on `/r/<domain>` and in the browser extension.
217
247
 
218
- ### Developer habit-loop subcommands
219
-
220
- ```bash
221
- npx pqcheck init # interactive scaffold for .github/workflows/cipherwake.yml
222
- npx pqcheck deploy-check # pre-deploy gate (Trust Diff alias, last-scan baseline)
223
- npx pqcheck release-checklist # markdown trust checklist for release notes (offline)
224
- ```
225
-
226
- The GitHub Action posts a **sticky PR comment** with results when `comment-on-pr: true` is set on `pull_request` events. Comment auto-edits on subsequent pushes — no spam.
248
+ > **GitHub Action note:** when scaffolded via `pqcheck onboard` or `pqcheck init`, the Action posts a **sticky PR comment** with results when `comment-on-pr: true` is set on `pull_request` events. The comment auto-edits on subsequent pushes — no spam.
227
249
 
228
250
  ---
229
251
 
@@ -243,33 +265,9 @@ Plus a full ASM check suite for credibility:
243
265
  - **HTTP header security** — HSTS (with preload + max-age), CSP, X-Frame-Options, Referrer-Policy, Permissions-Policy, COOP, CORP
244
266
  - **Subdomain takeover detection** — fingerprint-based scan against AWS S3, GitHub Pages, Heroku, Shopify, Fastly, etc.
245
267
 
246
- ## Commands
268
+ ## Flags, formats & exit codes
247
269
 
248
- ```
249
- npx pqcheck <domain> Scan + print human-readable report
250
- npx pqcheck lock <domain> Generate cipherwake.lock (QXM) committable manifest
251
- npx pqcheck deps <domain> Scan all third-party origins on the page (supply-chain HNDL)
252
- npx pqcheck diff <old.lock> <new.lock> Compare two QXM lockfiles; exit 2 on regression
253
- npx pqcheck history <domain> Show 90-day score history (sparkline + samples)
254
- npx pqcheck changes <domain> Summarize public attack-surface changes in last 14 days
255
- npx pqcheck cert <file.pem> Analyze a local PEM/CRT cert file (offline, no network)
256
- npx pqcheck trust-diff <domain> Trust Diff vs configured baseline; CI gate (Free: 100/repo/mo)
257
- npx pqcheck preview-diff --preview U --production U Preview-URL vs production-URL diff; new scripts + header regressions + score drops (NEW in 0.14.0)
258
- npx pqcheck deploy-check <domain> Pre-deploy gate (Trust Diff alias with last-scan baseline)
259
- npx pqcheck onboard <domain> One-command setup wizard (scan + init + vendors + checklist)
260
- npx pqcheck init Interactive scaffold for .github/workflows/cipherwake.yml
261
- npx pqcheck release-checklist [domain] Pre-release trust checklist (markdown, offline)
262
- npx pqcheck vendors export <domain> Write cipherwake.vendors.json from observed third-party scripts
263
- npx pqcheck vendors check <domain> CI gate; exit 4 on new origins not in lockfile
264
- npx pqcheck vendors sync <domain> Pull dashboard allowlist into lockfile (Founder Pro, needs API key)
265
- npx pqcheck watch <domain> Add domain to your watched list (needs CIPHERWAKE_API_KEY)
266
- npx pqcheck guard --domain <D> -- <cmd> AI Coder Mode (0.15.0) — wrap any deploy command with a Trust Diff gate
267
- npx pqcheck deploy-check <D> --ai AI Coder Mode (0.15.0) — frictionless first-deploy, anonymous, emits CIPHERWAKE_AI_GUARD_RESULT block
268
- npx pqcheck setup --auto --domain <D> AI Coder Mode (0.15.0) — one-command install across CLAUDE.md/.cursorrules/.github + git pre-push hook + statusline
269
- npx pqcheck setup --plan --domain <D> AI Coder Mode (0.15.0) — dry-run: print every file change before --auto writes anything
270
- npx pqcheck protocol install --auto AI Coder Mode (0.15.0) — append AI Coder Protocol to detected rules files (idempotent, fenced markers)
271
- npx pqcheck debug-network Probe upstream connectivity (cipherwake.io / crt.sh / Vercel) — for "scan hung" diagnosis
272
- ```
270
+ Every CLI command is documented in [Commands at a glance](#commands-at-a-glance) above. What follows is reference material for usage patterns, flags, output formats, and exit codes shared across commands.
273
271
 
274
272
  ### Multi-domain
275
273
 
@@ -109,6 +109,10 @@ const {
109
109
  domain, score, grade, ship_decision, written_at, max_severity, unreachable,
110
110
  // v0.16.4 — preview-diff-specific fields for the 4-line render
111
111
  kind, delta_count, diff_no_change, sector_ranking, verified_signal_categories, last_changed,
112
+ // v0.16.11 — top finding ID so REVIEW/BLOCK lines say WHAT'S WRONG
113
+ // inline. Without this, the customer sees "⚠ REVIEW" with no cause and
114
+ // has to run a separate `pqcheck deploy-check --ai` to find out why.
115
+ top_issue,
112
116
  } = state;
113
117
  const age = ageHours(written_at);
114
118
 
@@ -179,6 +183,41 @@ if (!isUnreachable && stabilitySource) {
179
183
  else stabilitySegment = ` · stable ${days}d`;
180
184
  }
181
185
 
186
+ // v0.16.11 — terse human label for the top_issue finding ID. Only rendered
187
+ // when ship_decision is review or block (the cases where the customer needs
188
+ // to know WHY without running another command). Mapping covers the
189
+ // finding IDs from lib/findingRegistry.ts that drive verdicts; for unknown
190
+ // IDs, derive a fallback by taking the last dotted segment and replacing
191
+ // underscores with spaces. "as few words as possible" — typical render is
192
+ // 2-4 words; never more than ~30 chars.
193
+ const TOP_ISSUE_LABELS = {
194
+ "chain.weakest_link.intermediate": "weak intermediate cert",
195
+ "chain.weakest_link.root": "weak root cert",
196
+ "tls.ecdhe_only_quantum_vulnerable": "quantum-vulnerable kex",
197
+ "tls.pqc_test_inconclusive_scanner_limit": "PQC test inconclusive",
198
+ "tls.rsa_kex_only": "RSA kex only",
199
+ "tls.rsa_kex_fallback": "RSA fallback",
200
+ "tls.rsa_kex_accepted_legacy": "RSA kex accepted",
201
+ "tls.version_obsolete": "obsolete TLS",
202
+ "tls.domain_unreachable": "unreachable",
203
+ "email.spf.missing": "no SPF",
204
+ "email.dmarc.missing": "no DMARC",
205
+ "email.dkim.missing": "no DKIM",
206
+ };
207
+ function topIssueLabel(id) {
208
+ if (!id || id === "none") return null;
209
+ if (TOP_ISSUE_LABELS[id]) return TOP_ISSUE_LABELS[id];
210
+ // Fallback: last dotted segment, underscores → spaces, cap 30 chars.
211
+ const tail = String(id).split(".").pop() || id;
212
+ return tail.replace(/_/g, " ").slice(0, 30);
213
+ }
214
+ const issueSegment = (!isUnreachable && (ship_decision === "review" || ship_decision === "block"))
215
+ ? (() => {
216
+ const label = topIssueLabel(top_issue);
217
+ return label ? ` · ${label}` : "";
218
+ })()
219
+ : "";
220
+
182
221
  process.stdout.write(
183
222
  c(cdec, "◆") +
184
223
  " " +
@@ -188,6 +227,6 @@ process.stdout.write(
188
227
  " " +
189
228
  c(C.bold, displayDomain) +
190
229
  " " +
191
- c(cdec, `${symbol} ${labelWord}`) +
230
+ c(cdec, `${symbol} ${labelWord}${issueSegment}`) +
192
231
  c(C.dim, `${dbrSegment}${stabilitySegment} · ${formatAge(written_at)}`)
193
232
  );
package/bin/pqcheck.js CHANGED
@@ -24,7 +24,7 @@
24
24
  })();
25
25
 
26
26
  const API_BASE = process.env.PQCHECK_API_BASE || "https://cipherwake.io";
27
- const VERSION = "0.16.9";
27
+ const VERSION = "0.16.11";
28
28
 
29
29
  // API-key support — paid tiers (Starter $29 / Growth $79 / Scale $199) get
30
30
  // per-account monthly quotas instead of the per-IP rate limit. Set via:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pqcheck",
3
- "version": "0.16.9",
3
+ "version": "0.16.12",
4
4
  "description": "Deploy gate for AI-coded web apps. `pqcheck deploy-check --ai` returns ship_decision=pass|review|block for Claude Code / Cursor / Copilot / Aider to gate deploys before they ship. Anonymous, no signup, free for first use.",
5
5
  "keywords": [
6
6
  "ai-coder",