create-qa-architect 5.13.6 → 5.14.0
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/.semgrep/defensive-patterns.yaml +356 -0
- package/.semgrep/vibe-audit-rules.yaml +332 -0
- package/LICENSE +192 -39
- package/README.md +98 -46
- package/config/requirements-dev.txt +2 -2
- package/docs/POLAR-DEPLOYMENT.md +157 -0
- package/docs/plans/PLAN-vibe-code-auditor.md +130 -0
- package/docs/plans/POLAR-MIGRATION.md +111 -0
- package/docs/plans/pro-features-2026-05.md +159 -0
- package/lib/commands/analyze-ci.js +20 -11
- package/lib/commands/audit.js +668 -0
- package/lib/commands/ci-doctor.js +341 -0
- package/lib/commands/history-scan.js +342 -0
- package/lib/commands/index.js +8 -0
- package/lib/commands/pr-check.js +484 -0
- package/lib/commands/prelaunch-setup.js +4 -0
- package/lib/commands/ship-check.js +570 -0
- package/lib/license-validator.js +200 -6
- package/lib/licensing.js +99 -11
- package/package.json +7 -6
- package/scripts/deploy-consumers.sh +10 -5
- package/scripts/risk-policy-gate.js +410 -0
- package/setup.js +132 -4
- /package/docs/{STRIPE-LIVE-MODE-DEPLOYMENT.md → _archive/STRIPE-LIVE-MODE-DEPLOYMENT.md} +0 -0
- /package/lib/{billing-dashboard.html → _archive/billing-dashboard.html} +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Plan: Vibe-Code Auditor
|
|
2
|
+
|
|
3
|
+
**Created:** 2026-05-27
|
|
4
|
+
**Status:** Active
|
|
5
|
+
**Branch:** feat/vibe-code-auditor (new from feat/polar-migration)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
QA Architect currently covers 2/7 security audit categories (secrets via Gitleaks Pro, and CVEs via npm audit free). The product is positioned as a quality bootstrap tool, but the 2026 market opportunity is "vibe-code security auditor" — a self-serve CLI that catches OWASP Top-10 patterns, injection vectors, auth gaps, production misconfigs, and hallucinated packages in AI-generated code. No CLI tool in the market does this for solo/indie developers. New web-based competitors (VibeDoctor, Vibe App Scanner) are filling the web-SaaS gap but not the CLI gap. The current product needs a new `audit` subcommand powered by semgrep, covering 5/7 categories in free tier, repositioned to match the buyer persona: "worried vibe coder about to ship."
|
|
12
|
+
|
|
13
|
+
Additionally the pricing needs a drop from $49/mo to $29/mo to match market expectations, and the README/help text needs a full repositioning.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Options Considered
|
|
18
|
+
|
|
19
|
+
### Option A: Add `audit` subcommand via semgrep (chosen)
|
|
20
|
+
|
|
21
|
+
Add `lib/commands/audit.js` that runs semgrep with an extended security ruleset covering SQL injection, XSS, command injection, auth bypass, production misconfigs, hardcoded secrets, and hallucinated package checks. Integrate as free-tier feature (basic 5 categories) with Pro extension (hallucination check + full OWASP pack + `--fix` prompt generation).
|
|
22
|
+
|
|
23
|
+
**Pros:**
|
|
24
|
+
|
|
25
|
+
- Semgrep rules already exist in `.semgrep/defensive-patterns.yaml` — extend rather than build from scratch
|
|
26
|
+
- Consistent with existing spawnSync/arg-array security pattern
|
|
27
|
+
- CLI-native = key differentiator vs web-based competitors
|
|
28
|
+
- Adds credible "auditor" positioning without changing existing ship-check/pr-check Pro features
|
|
29
|
+
|
|
30
|
+
**Cons:**
|
|
31
|
+
|
|
32
|
+
- Semgrep must be installed on user machine (document in README, add detection+guidance)
|
|
33
|
+
- Semgrep rules won't catch everything — must be honest about coverage
|
|
34
|
+
|
|
35
|
+
### Option B: Use eslint-plugin-security only
|
|
36
|
+
|
|
37
|
+
Run eslint with security plugin, no new dependency.
|
|
38
|
+
|
|
39
|
+
**Pros:** No semgrep required
|
|
40
|
+
|
|
41
|
+
**Cons:** Much weaker coverage — misses SQL injection, auth bypass, command injection patterns. eslint-plugin-security already part of existing setup flow so no net new value for "audit" use case.
|
|
42
|
+
|
|
43
|
+
### Option C: Bundle semgrep binary (like gitleaks)
|
|
44
|
+
|
|
45
|
+
Pin and cache semgrep binary like gitleaks v8.28.0.
|
|
46
|
+
|
|
47
|
+
**Cons:** Semgrep binary is 50-100MB — not viable for npm package. Document as prerequisite instead.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Decision
|
|
52
|
+
|
|
53
|
+
**Approach:** Option A — semgrep-powered `audit` subcommand + pricing update + README repositioning
|
|
54
|
+
|
|
55
|
+
**Rationale:** Semgrep is the de-facto OSS SAST engine with a large rule library and a simple CLI. The existing `.semgrep/defensive-patterns.yaml` gives a head start. The CLI gap in the market is real — web SaaS competitors all require uploading code to their service; this runs entirely locally, which is a trust advantage for security-conscious builders. Pricing drop from $49 to $29 reduces conversion friction without undermining value.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Implementation Plan
|
|
60
|
+
|
|
61
|
+
### New Files to Create
|
|
62
|
+
|
|
63
|
+
- `lib/commands/audit.js` — main audit command handler
|
|
64
|
+
- `.semgrep/vibe-audit-rules.yaml` — extended security ruleset (SQL, XSS, command injection, auth, CORS, debug mode, hardcoded secrets, missing validation, hallucinated packages)
|
|
65
|
+
- `tests/audit.test.js` — unit tests for audit command
|
|
66
|
+
|
|
67
|
+
### Files to Modify
|
|
68
|
+
|
|
69
|
+
- `setup.js` — add `--audit` flag parsing + routing to `handleAudit()`, add to help text
|
|
70
|
+
- `lib/licensing.js` — add `auditBasic` (free) and `auditPro` (Pro) feature flags; update pricing from $49→$29
|
|
71
|
+
- `README.md` — full repositioning: vibe-code security auditor, lead with `audit` command, update pricing table
|
|
72
|
+
- `package.json` — update description, add `audit` to scripts if helpful
|
|
73
|
+
|
|
74
|
+
### Execution Order
|
|
75
|
+
|
|
76
|
+
1. **Create branch** `feat/vibe-code-auditor` from `feat/polar-migration`
|
|
77
|
+
2. **Create `.semgrep/vibe-audit-rules.yaml`** — the audit categories (SQL/XSS/cmd injection, auth bypass, CORS/debug misconfigs, hardcoded creds, missing rate limits). Build on existing defensive-patterns.yaml, add new categories.
|
|
78
|
+
3. **Create `lib/commands/audit.js`** — the audit command:
|
|
79
|
+
- Detect if semgrep is installed, provide install guidance if not
|
|
80
|
+
- Run semgrep with both defensive-patterns.yaml and vibe-audit-rules.yaml
|
|
81
|
+
- Run npm audit (CVEs, free)
|
|
82
|
+
- Check for hallucinated packages (Pro: verify package names against npm registry)
|
|
83
|
+
- Produce structured output: Critical/High/Medium/Low findings with file:line, what's wrong, why it matters, suggested fix
|
|
84
|
+
- Pro: `--fix` flag generates Claude Code prompts for each finding
|
|
85
|
+
- Support `--json` output flag
|
|
86
|
+
- Support `--out <path>` to write markdown report to file
|
|
87
|
+
4. **Update `setup.js`** — add `--audit` and `--audit-fix` flags, routing, and help text
|
|
88
|
+
5. **Update `lib/licensing.js`** — add feature flags, change Pro price from 4900 to 2900 (cents)
|
|
89
|
+
6. **Create `tests/audit.test.js`** — tests for: semgrep not installed handling, result parsing, severity mapping, json output, markdown output
|
|
90
|
+
7. **Update `README.md`** — full rewrite of positioning sections: new tagline, lead with `audit`, update pricing table ($29/mo), update command reference
|
|
91
|
+
8. **Run full test suite** — `npm test`, `npm run lint`
|
|
92
|
+
9. **Version bump** to 5.14.0 (new feature, not patch)
|
|
93
|
+
10. **Commit + PR** with `/bs:quality --merge`
|
|
94
|
+
|
|
95
|
+
### Out of Scope
|
|
96
|
+
|
|
97
|
+
- Supabase RLS gap detection (requires DB schema access — defer to v2)
|
|
98
|
+
- GDPR/soft-delete/audit-log checks (high false-positive risk — defer)
|
|
99
|
+
- Python audit rules (defer — focus on JS/TS/Next.js stack for v1)
|
|
100
|
+
- IDE plugin (CLI only)
|
|
101
|
+
- Web dashboard
|
|
102
|
+
- Auto-fix (only generates Claude Code prompts, doesn't apply them)
|
|
103
|
+
- Agentic workflow scanning (LangGraph/CrewAI — different product)
|
|
104
|
+
- Renaming the product (not worth it at this stage)
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Verification Steps
|
|
109
|
+
|
|
110
|
+
1. `node setup.js --audit` on this repo — should detect 0 critical findings (or real ones in test fixtures)
|
|
111
|
+
2. `node setup.js --audit --json` — valid JSON output
|
|
112
|
+
3. `node setup.js --audit --out /tmp/report.md` — file written
|
|
113
|
+
4. Test with semgrep not installed — should show clear install guidance, not crash
|
|
114
|
+
5. `node tests/audit.test.js` — all pass
|
|
115
|
+
6. `npm test` — all 50+ tests still pass
|
|
116
|
+
7. `npm run lint` — clean
|
|
117
|
+
8. `node setup.js --license-status` — confirms Pro price shows $29/mo
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Notes / Gotchas
|
|
122
|
+
|
|
123
|
+
- Semgrep detection: use `which semgrep` or `semgrep --version` via spawnSync, handle ENOENT gracefully
|
|
124
|
+
- Semgrep output is JSON (`semgrep --json`), parse `results[].path`, `.start.line`, `.check_id`, `.message`, `.severity`, `.extra.message`
|
|
125
|
+
- Semgrep severity levels: `ERROR` → Critical, `WARNING` → High/Medium depending on rule metadata
|
|
126
|
+
- The existing `.semgrep/defensive-patterns.yaml` rules are already good for SQL injection, command injection, auth bypass, CORS, hardcoded secrets — extend rather than duplicate
|
|
127
|
+
- Hallucinated package check (Pro): hit `https://registry.npmjs.org/<package>` for each dep in package.json, flag 404s. Cache results to avoid rate limits.
|
|
128
|
+
- Pricing: `lib/licensing.js` stores price in cents. Change from `4900` to `2900`. Also update any string references to "$49" → "$29".
|
|
129
|
+
- The `quality.yml` template-as-product invariant: if audit is added to the project's own CI, ensure it uses `npx @latest` pattern and not `node_modules/` references.
|
|
130
|
+
- `--fix` flag for Pro: format as "Copy this prompt into Claude Code:" followed by a structured prompt that includes the file path, line number, issue, and the recommended fix pattern.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Polar.sh Migration Plan
|
|
2
|
+
|
|
3
|
+
**Status:** in progress
|
|
4
|
+
**Date:** 2026-05-17
|
|
5
|
+
**Replaces:** Stripe-direct billing
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
We're migrating billing from **Stripe-direct** to **Polar.sh** (Merchant-of-Record).
|
|
10
|
+
|
|
11
|
+
| | Stripe direct | Polar.sh (MoR) |
|
|
12
|
+
| ---------------------------------------- | ------------------------------------------------------------------------- | ----------------------- |
|
|
13
|
+
| Effective fee on $49/mo | ~3.5% | ~4.8% (~1.3% premium) |
|
|
14
|
+
| Global sales tax / VAT / GST | **We owe it** (~$200-400/mo for Anrok at scale, plus state registrations) | Polar collects + remits |
|
|
15
|
+
| Customer portal (cancel/update/invoices) | Build it | Built-in |
|
|
16
|
+
| Dunning / failed payment retries | Build it | Built-in |
|
|
17
|
+
| Effort to ship v1 | High (tax, portal, dunning) | Low (webhook swap only) |
|
|
18
|
+
|
|
19
|
+
Crossover where Stripe-direct wins: ~$50K MRR. Until then, Polar is **cheaper in total cost** and ships faster.
|
|
20
|
+
|
|
21
|
+
## Architecture: what stays, what changes
|
|
22
|
+
|
|
23
|
+
### Stays (the moat)
|
|
24
|
+
|
|
25
|
+
- `lib/license-signing.js` — Ed25519 signing primitives (re-exports `@buildproven/license-core`)
|
|
26
|
+
- `lib/license-validator.js` — offline signature verification
|
|
27
|
+
- `lib/licensing.js` — tier definitions, feature gates, activation flow
|
|
28
|
+
- `public-key.pem` bundled in the npm package — CLI verifies signed payloads offline
|
|
29
|
+
- `lib/blob-storage.js` — Vercel Blob layout for private DB + public signed registry
|
|
30
|
+
- `--activate-license` CLI flow — fetches public registry, falls back to cached offline data
|
|
31
|
+
- License key format `QAA-XXXX-XXXX-XXXX-XXXX`, deterministic from customer ID
|
|
32
|
+
|
|
33
|
+
### Changes
|
|
34
|
+
|
|
35
|
+
- `webhook-handler.js` — event source swap: Stripe `checkout.session.completed` → Polar `subscription.created/active/canceled/revoked`. Same Vercel Blob writes, same signing.
|
|
36
|
+
- `docs/STRIPE-LIVE-MODE-DEPLOYMENT.md` → archived. Replaced by `docs/POLAR-DEPLOYMENT.md`.
|
|
37
|
+
- `lib/billing-dashboard.html` → archived. Polar's hosted customer portal replaces it.
|
|
38
|
+
- Buy URLs (`buildproven.ai/qa-architect`) → Polar checkout URL.
|
|
39
|
+
- `admin-license.js` → kept, comments updated to clarify it's a manual fallback only.
|
|
40
|
+
|
|
41
|
+
### New
|
|
42
|
+
|
|
43
|
+
- `subscription.canceled` / `subscription.revoked` → revocation list. Signed JSON at known URL, cached by CLI with grace period so offline CI doesn't break. Closes the "cancel but keep Pro forever" loophole.
|
|
44
|
+
- `COMMERCIAL.md` — paid-tier terms gated by the license-key check at runtime.
|
|
45
|
+
- `LICENSE` swap: custom EULA → standard **Apache-2.0**.
|
|
46
|
+
|
|
47
|
+
## Why we don't use Polar's built-in license keys
|
|
48
|
+
|
|
49
|
+
Polar's built-in license-key benefit requires online validation against `/v1/customer-portal/license-keys/validate`. Our CLI is designed for **offline verification** — `npx create-qa-architect` must work in CI sandboxes with no outbound HTTP. We use Polar only for billing/MoR/checkout/portal/dunning. Our existing Ed25519 signing + Vercel Blob + offline-verifying CLI stays as-is.
|
|
50
|
+
|
|
51
|
+
## Polar webhook events we handle
|
|
52
|
+
|
|
53
|
+
| Event | Action |
|
|
54
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
55
|
+
| `subscription.created` | Generate license key, sign payload, write to private DB + public signed registry |
|
|
56
|
+
| `subscription.active` | Idempotent re-issue (covers renewal + late activations) |
|
|
57
|
+
| `subscription.updated` | If `product_id` changed (plan switch), update tier in DB |
|
|
58
|
+
| `subscription.canceled` | Mark as `pending_cancel` in private DB. Subscription is still active until `current_period_end`. **Do not** revoke yet. |
|
|
59
|
+
| `subscription.revoked` | Move license key to revocation list. CLI will refuse it after next registry pull (with cache + grace period). |
|
|
60
|
+
|
|
61
|
+
## Polar product setup (manual, user does this)
|
|
62
|
+
|
|
63
|
+
1. Create Polar org at https://polar.sh
|
|
64
|
+
2. Create product **"QA Architect Pro"** with two prices:
|
|
65
|
+
- $49/mo (recurring monthly)
|
|
66
|
+
- $490/yr (recurring yearly)
|
|
67
|
+
3. Save the `product_id` — single product, two prices.
|
|
68
|
+
4. Configure webhook endpoint: `https://<your-vercel-domain>/webhook`
|
|
69
|
+
5. Webhook secret → env var `POLAR_WEBHOOK_SECRET`
|
|
70
|
+
6. API token (for any server-side Polar API calls) → env var `POLAR_ACCESS_TOKEN`
|
|
71
|
+
|
|
72
|
+
## Env vars (replaces Stripe vars)
|
|
73
|
+
|
|
74
|
+
| Old (Stripe) | New (Polar) |
|
|
75
|
+
| ------------------------------ | ----------------------------------------- |
|
|
76
|
+
| `STRIPE_SECRET_KEY` | `POLAR_ACCESS_TOKEN` |
|
|
77
|
+
| `STRIPE_WEBHOOK_SECRET` | `POLAR_WEBHOOK_SECRET` |
|
|
78
|
+
| `LICENSE_REGISTRY_PRIVATE_KEY` | (unchanged) |
|
|
79
|
+
| `LICENSE_REGISTRY_KEY_ID` | (unchanged) |
|
|
80
|
+
| `BLOB_READ_WRITE_TOKEN` | (unchanged) |
|
|
81
|
+
| (none) | `POLAR_PRO_PRODUCT_ID` — maps to PRO tier |
|
|
82
|
+
|
|
83
|
+
## Verification
|
|
84
|
+
|
|
85
|
+
Before declaring done:
|
|
86
|
+
|
|
87
|
+
1. `npm test` — full suite passes
|
|
88
|
+
2. `npm run lint` — clean
|
|
89
|
+
3. Manual smoke test: simulate a `subscription.created` event with Polar's CLI / Postman → verify license appears in Blob → run `npx . --activate-license` with the issued key → confirm Pro feature unlocks.
|
|
90
|
+
4. Manual revocation test: simulate `subscription.revoked` → confirm license appears in revocation list → confirm CLI rejects key after registry pull.
|
|
91
|
+
|
|
92
|
+
## Replicate to claude-kit-pro
|
|
93
|
+
|
|
94
|
+
Same migration, same architecture. Differences:
|
|
95
|
+
|
|
96
|
+
- License key prefix differs (`CKP-` instead of `QAA-`)
|
|
97
|
+
- Webhook URL differs (deploy under claude-kit-pro's Vercel project)
|
|
98
|
+
- `POLAR_PRO_PRODUCT_ID` env var points at claude-kit-pro's Polar product
|
|
99
|
+
|
|
100
|
+
Follow this doc step-by-step in `../claude-kit-pro/`.
|
|
101
|
+
|
|
102
|
+
## Rollback
|
|
103
|
+
|
|
104
|
+
If Polar fails for any reason, the migration is reversible in ~half a day:
|
|
105
|
+
|
|
106
|
+
1. Restore `webhook-handler.js` from git (it was just an event-source swap)
|
|
107
|
+
2. Restore `docs/STRIPE-LIVE-MODE-DEPLOYMENT.md`
|
|
108
|
+
3. Repoint Vercel webhook to Stripe events
|
|
109
|
+
4. Existing signed licenses in Vercel Blob keep working — they're product-agnostic.
|
|
110
|
+
|
|
111
|
+
The signing/verification layer never depended on the billing provider. That's why this swap is cheap.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Pro Feature Expansion — May 2026
|
|
2
|
+
|
|
3
|
+
Spec for 4 new Pro-tier commands. Positioning: "quality gate for AI-assisted small teams."
|
|
4
|
+
|
|
5
|
+
## 1. `--ship-check` (unified release readiness)
|
|
6
|
+
|
|
7
|
+
**CLI**: `npx create-qa-architect --ship-check [--json] [--out <path>]`
|
|
8
|
+
|
|
9
|
+
**Module**: `lib/commands/ship-check.js`
|
|
10
|
+
|
|
11
|
+
**Gating**: requires Pro tier (proxy: `hasFeature('coverageThresholds')`).
|
|
12
|
+
|
|
13
|
+
**Behavior**: orchestrates existing Pro checks, never re-implements them. For each check:
|
|
14
|
+
|
|
15
|
+
- run the existing command/validator in a child process or via direct import
|
|
16
|
+
- capture pass/fail + summary
|
|
17
|
+
- never fail-fast; collect all results
|
|
18
|
+
|
|
19
|
+
Checks (in order):
|
|
20
|
+
|
|
21
|
+
1. Lint (`npm run lint` if script exists)
|
|
22
|
+
2. Tests (`npm test` if script exists — short timeout, allow opt-out via `--skip-tests`)
|
|
23
|
+
3. Security scan (gitleaks current-files, plus `npm audit --omit=dev` if package.json)
|
|
24
|
+
4. Coverage thresholds (read `coverage/coverage-summary.json` if present, compare to `.qualityrc.json` thresholds)
|
|
25
|
+
5. Bundle size (run `size-limit` if configured)
|
|
26
|
+
6. Lighthouse thresholds (skip if not configured — info only)
|
|
27
|
+
7. Env validation (check `.env.example` vs documented env vars)
|
|
28
|
+
8. CI cost summary (call existing `analyze-ci` module functions in `--summary` mode)
|
|
29
|
+
9. Docs validation (existing docs validator)
|
|
30
|
+
|
|
31
|
+
**Output**:
|
|
32
|
+
|
|
33
|
+
- Default: human-readable terminal report with section headers + final verdict.
|
|
34
|
+
- `--json`: machine-readable JSON (for CI consumption).
|
|
35
|
+
- `--out report.md`: write markdown suitable for PR comments.
|
|
36
|
+
|
|
37
|
+
**Verdict logic**:
|
|
38
|
+
|
|
39
|
+
- `SHIP`: zero failures, zero critical warnings.
|
|
40
|
+
- `REVIEW`: warnings but no failures.
|
|
41
|
+
- `BLOCK`: any failure.
|
|
42
|
+
|
|
43
|
+
**Exit code**: 0 on SHIP/REVIEW, 1 on BLOCK.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. `--pr-check` (diff-aware risk classifier)
|
|
48
|
+
|
|
49
|
+
**CLI**: `npx create-qa-architect --pr-check [--base <branch>] [--json] [--out <path>]`
|
|
50
|
+
|
|
51
|
+
**Module**: `lib/commands/pr-check.js`
|
|
52
|
+
|
|
53
|
+
**Gating**: requires Pro tier.
|
|
54
|
+
|
|
55
|
+
**Behavior**:
|
|
56
|
+
|
|
57
|
+
1. Determine base branch (default: `main`, fallback `master`).
|
|
58
|
+
2. Get diff: `git diff --name-status <base>...HEAD`.
|
|
59
|
+
3. Classify each changed file by path patterns + content sniff:
|
|
60
|
+
- **HIGH risk**: auth, crypto, payments, env files, db migrations, GitHub workflows, security headers, license logic, anything matching `/auth|crypto|payment|stripe|webhook|migration|secret|token|key/i`.
|
|
61
|
+
- **MEDIUM risk**: config (package.json, tsconfig, eslint), public API surface (`index.ts`, `lib/**` exports), dependency changes (`package*.json`, `requirements.txt`).
|
|
62
|
+
- **LOW risk**: docs (`*.md`), tests (`*.test.*`, `tests/**`), comments-only.
|
|
63
|
+
4. For each non-test source file changed, check if a matching test file changed too. Flag missing tests.
|
|
64
|
+
5. For HIGH-risk files: check if covered by CODEOWNERS (if file exists).
|
|
65
|
+
6. Emit risk summary + per-file table.
|
|
66
|
+
|
|
67
|
+
**Output**: markdown report (PR-comment-ready) with:
|
|
68
|
+
|
|
69
|
+
- Risk summary (counts per tier)
|
|
70
|
+
- Missing tests warning
|
|
71
|
+
- High-risk file list with reasons
|
|
72
|
+
- Verdict: SHIP / REVIEW / BLOCK (BLOCK only if HIGH + no tests + no codeowner)
|
|
73
|
+
|
|
74
|
+
**Exit code**: 0 on SHIP/REVIEW, 1 on BLOCK (configurable via `--no-fail`).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 3. CI Doctor (expand `--analyze-ci`)
|
|
79
|
+
|
|
80
|
+
**CLI**: existing `--analyze-ci` adds new `--doctor` flag for the extra checks. Default still shows cost analysis.
|
|
81
|
+
|
|
82
|
+
**Module**: extend `lib/commands/analyze-ci.js` — add a `runDoctor(workflows)` function.
|
|
83
|
+
|
|
84
|
+
**New findings** (each with concrete fix suggestion):
|
|
85
|
+
|
|
86
|
+
1. **Duplicated jobs**: detect jobs with identical `runs-on` + steps signature → suggest reusable workflow.
|
|
87
|
+
2. **Missing path filters**: workflows triggered on every push without `paths:` or `paths-ignore:` → suggest path filters for monorepos / docs-only changes.
|
|
88
|
+
3. **Expensive matrix**: matrix with >10 combinations → suggest pruning or `include`/`exclude`.
|
|
89
|
+
4. **Cache mistakes**: `actions/setup-node` without `cache:` parameter → suggest enabling.
|
|
90
|
+
5. **Unnecessary scheduled runs**: cron more frequent than weekly with no obvious need → suggest reducing.
|
|
91
|
+
6. **Flaky test detection**: parse `gh run list --json` if `gh` CLI available, look for jobs with success rate <90% over last 30 runs. Skip gracefully if `gh` not authenticated.
|
|
92
|
+
|
|
93
|
+
**Output**: appended section to existing report. Each finding shows: title, affected workflow/job, fix suggestion (1-2 lines), estimated savings if applicable.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 4. `--history-scan` (historical secrets)
|
|
98
|
+
|
|
99
|
+
**CLI**: `npx create-qa-architect --history-scan [--depth <N>] [--json]`
|
|
100
|
+
|
|
101
|
+
**Module**: `lib/commands/history-scan.js`
|
|
102
|
+
|
|
103
|
+
**Gating**: requires `hasFeature('securityScanning')`.
|
|
104
|
+
|
|
105
|
+
**Behavior**:
|
|
106
|
+
|
|
107
|
+
1. Reuse `resolveGitleaksBinary()` from `lib/validation/config-security.js`.
|
|
108
|
+
2. Run: `<gitleaks> detect --no-banner --redact --report-format=json --report-path=<tmp> --log-opts="--all"` (or `HEAD~<depth>` if `--depth` given).
|
|
109
|
+
3. Parse JSON output, deduplicate by `{secret, file, commit}`.
|
|
110
|
+
4. Group findings by commit SHA, list files, secret types.
|
|
111
|
+
5. Report counts per secret type + top 10 oldest exposures.
|
|
112
|
+
|
|
113
|
+
**Output**: terminal report + optional JSON. Markdown export for PR.
|
|
114
|
+
|
|
115
|
+
**Exit code**: 0 if zero findings, 1 if any.
|
|
116
|
+
|
|
117
|
+
**Safety**: pass `--all` only when explicitly requested; default `HEAD~1000` to bound cost on huge repos.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Licensing changes
|
|
122
|
+
|
|
123
|
+
Add flags to `lib/licensing.js` FEATURES map:
|
|
124
|
+
|
|
125
|
+
- `shipCheck`: PRO only
|
|
126
|
+
- `prCheck`: PRO only
|
|
127
|
+
- `ciDoctor`: PRO only (expansion of existing `ciCostAnalysis`)
|
|
128
|
+
- `historicalSecretsScan`: PRO only (under existing `securityScanning` umbrella)
|
|
129
|
+
|
|
130
|
+
Update PRO roadmap array. Add FREE roadmap line: "❌ No release readiness gate (--ship-check), risk-aware PR review, CI doctor, or historical secrets scan".
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Testing
|
|
135
|
+
|
|
136
|
+
One test file per command:
|
|
137
|
+
|
|
138
|
+
- `tests/ship-check.test.js`
|
|
139
|
+
- `tests/pr-check.test.js`
|
|
140
|
+
- `tests/ci-doctor.test.js`
|
|
141
|
+
- `tests/history-scan.test.js`
|
|
142
|
+
|
|
143
|
+
Each covers:
|
|
144
|
+
|
|
145
|
+
- Free tier blocked (proper upgrade message)
|
|
146
|
+
- Pro tier runs (via `QAA_DEVELOPER=true` or stub license)
|
|
147
|
+
- Output format validates (markdown structure / JSON shape)
|
|
148
|
+
- Edge cases: empty diff (pr-check), no workflows (ci-doctor), no .git history (history-scan), no coverage report (ship-check)
|
|
149
|
+
|
|
150
|
+
Goal: keep coverage ≥75% lines / 70% functions per project standard.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Out of scope (deferred)
|
|
155
|
+
|
|
156
|
+
- LLM-powered fix suggestions (depends on API key, adds cost dimension)
|
|
157
|
+
- Monorepo selective CI (deeper architecture change)
|
|
158
|
+
- Team dashboard (needs hosted component)
|
|
159
|
+
- PR inline annotations via Checks API (depends on GH App / token model; document for v6)
|
|
@@ -12,7 +12,11 @@ const path = require('path')
|
|
|
12
12
|
const { execSync } = require('child_process')
|
|
13
13
|
const yaml = require('js-yaml')
|
|
14
14
|
const { showProgress } = require('../ui-helpers')
|
|
15
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
hasFeature,
|
|
17
|
+
showUpgradeMessage,
|
|
18
|
+
ensureLicenseFresh,
|
|
19
|
+
} = require('../licensing')
|
|
16
20
|
|
|
17
21
|
const DAYS_PER_MONTH = 30
|
|
18
22
|
const DEFAULT_PULL_REQUEST_FACTOR = 0.8
|
|
@@ -771,20 +775,26 @@ function generateReport(analysis) {
|
|
|
771
775
|
}
|
|
772
776
|
|
|
773
777
|
/**
|
|
774
|
-
* Main handler for --analyze-ci command
|
|
778
|
+
* Main handler for --analyze-ci command. When `options.doctor` is true,
|
|
779
|
+
* appends the CI Doctor diagnostics (flaky tests, duplicated jobs, etc.)
|
|
775
780
|
*/
|
|
776
|
-
async function handleAnalyzeCi() {
|
|
781
|
+
async function handleAnalyzeCi(options = {}) {
|
|
777
782
|
const projectPath = process.cwd()
|
|
778
783
|
|
|
784
|
+
await ensureLicenseFresh()
|
|
779
785
|
if (!hasFeature('ciCostAnalysis')) {
|
|
780
786
|
showUpgradeMessage('GitHub Actions cost analysis')
|
|
781
787
|
process.exit(1)
|
|
782
788
|
}
|
|
783
789
|
|
|
790
|
+
if (options.doctor && !hasFeature('ciDoctor')) {
|
|
791
|
+
showUpgradeMessage('CI Doctor (workflow health + flaky test detection)')
|
|
792
|
+
process.exit(1)
|
|
793
|
+
}
|
|
794
|
+
|
|
784
795
|
const spinner = showProgress('Analyzing GitHub Actions workflows...')
|
|
785
796
|
|
|
786
797
|
try {
|
|
787
|
-
// Step 1: Discover workflows
|
|
788
798
|
const workflowFiles = discoverWorkflows(projectPath)
|
|
789
799
|
|
|
790
800
|
if (workflowFiles.length === 0) {
|
|
@@ -796,7 +806,6 @@ async function handleAnalyzeCi() {
|
|
|
796
806
|
process.exit(1)
|
|
797
807
|
}
|
|
798
808
|
|
|
799
|
-
// Step 2: Parse and analyze workflows
|
|
800
809
|
const workflows = []
|
|
801
810
|
for (const wf of workflowFiles) {
|
|
802
811
|
try {
|
|
@@ -815,13 +824,8 @@ async function handleAnalyzeCi() {
|
|
|
815
824
|
}
|
|
816
825
|
}
|
|
817
826
|
|
|
818
|
-
// Step 3: Get commit frequency
|
|
819
827
|
const commitStats = getCommitFrequency(projectPath)
|
|
820
|
-
|
|
821
|
-
// Step 4: Calculate costs
|
|
822
828
|
const costs = calculateMonthlyCosts(workflows, commitStats.commitsPerDay)
|
|
823
|
-
|
|
824
|
-
// Step 5: Analyze optimization opportunities
|
|
825
829
|
const optimizations = analyzeOptimizations(
|
|
826
830
|
workflows,
|
|
827
831
|
commitStats.commitsPerDay
|
|
@@ -829,7 +833,6 @@ async function handleAnalyzeCi() {
|
|
|
829
833
|
|
|
830
834
|
spinner.succeed('Analysis complete')
|
|
831
835
|
|
|
832
|
-
// Step 6: Generate report
|
|
833
836
|
generateReport({
|
|
834
837
|
workflows,
|
|
835
838
|
costs,
|
|
@@ -837,6 +840,12 @@ async function handleAnalyzeCi() {
|
|
|
837
840
|
optimizations,
|
|
838
841
|
})
|
|
839
842
|
|
|
843
|
+
if (options.doctor) {
|
|
844
|
+
const { runDoctorChecks, buildDoctorReport } = require('./ci-doctor')
|
|
845
|
+
const findings = runDoctorChecks(workflows, projectPath, options)
|
|
846
|
+
process.stdout.write(buildDoctorReport(findings))
|
|
847
|
+
}
|
|
848
|
+
|
|
840
849
|
process.exit(0)
|
|
841
850
|
} catch (error) {
|
|
842
851
|
spinner.fail('Analysis failed')
|