Changelog — QualityPilot (qlens.dev)
Notable changes to the QualityPilot SaaS. Public repository history — see individual PRs for full diffs.
2026-04-19
Added — PDF export for Quality Time Machine ROI report
PR#99 shipped the Quality Time Machine dashboard but parked PDF export as "coming soon". This closes that gap. Power users can now download the same ROI numbers as a finance-friendly PDF and forward to their VP / attach to expense reports / drop into a deck — the formats finance and leadership actually accept. Conversion lever for Pro+ (the kind of artefact people circulate to justify the line item).
- Module
src/lib/roi-pdf.ts— pure server-side PDF builder via@react-pdf/renderer(~3 MB node_modules, ~17 KB on the route's nft trace). No headless Chrome — react-pdf renders in pure Node, so cold starts stay fast on Vercel and we don't need a Chromium binary in the image. - Endpoint
GET /api/auto-fix-roi/pdf— NextAuth-gated, same query shape as/api/auto-fix-roi(repo,days,hourly_rate). Pinnedruntime = "nodejs"because react-pdf needs Node APIs. Returnsapplication/pdfwithContent-Disposition: attachment; filename="qualitypilot-roi-YYYY-MM-DD.pdf". Empty-state still returns a valid PDF (predictable download for fresh accounts). - Layout: cover header (brand + generated date) → big-number hero (hours saved + dollars) → spent-vs-saved comparison + ROI badge → 8-week trend table → top-5 flaky-source files → payback callout → methodology footer → page-numbered footer fixed at the bottom of every page. Letter portrait, multi-page if content overflows.
- Trend rendered as table, not chart image: react-pdf's SVG support is partial; baking the bar chart as a PNG would need a rasterizer + double the bundle. Tables also reproduce cleanly when copy-pasted into a deck and stay accessible. The on-screen dashboard already has the visual chart — the PDF is the "expense report" view where the data matters more than the visual.
- UI
/dashboard/roi— replaced the disabled "Export to PDF (coming soon)" button with a working<a download>that hits the new endpoint with the current filter params. Brief "Preparing PDF…" indicator with spinner on click. - Tests: +12 (
src/tests/roi-pdf.test.ts) — full round-trip rendering with%PDFheader /%%EOFtrailer assertions, content text-extraction (inflate flate streams + decode TJ hex arrays) for headline strings, singular/plural payback wording, empty-state survival, filename UTC-day formatting, document-metadata snapshot. Sample 50-fix scenario PDF is 8.65 KB; test enforces a 100 KB upper bound to flag font-bloat regressions. - Quality bar:
npm testgreen (1537 → 1549).npx tsc --noEmitclean.npx eslintclean on touched files.npx next buildgreen (new route shows asƒ /api/auto-fix-roi/pdf).
Added — @qlens/cli for local scan + auto-fix from any terminal
Brings QualityPilot to every dev's local environment. qlens scan from any project root prints the latest test-health grade in 1s. qlens auto-fix <test-file> runs the AI Bug Detective playground on a local failing test — same pipeline as the cron worker for paying customers, no sign-up required for the first 5 attempts/day. Funnels CLI users to the dashboard for keys.
- Package
packages/cli/—@qlens/cli, MIT, ESM, Node 20+. Mirrors the file shape of the reporter packages (no build step, singlebin: { qlens }entry). Two trivial deps:commander(~50KB, real subcommand UX with help text per command) andpicocolors(~5KB, NO_COLOR-aware). Justification on the deps: built-inutil.parseArgsworks for one command but compounds in cost when you have 6 subcommands with their own help text and option validation; reinventing this is wasted effort for a CLI of this size. - Commands:
qlens scan,qlens auto-fix <test-file> [-f framework] [-p production-file],qlens status,qlens login,qlens config set api-key <key>,qlens config get api-key. Exit codes areset -e-friendly — 0 happy, 1 user error, 2 argument error. - No new API routes: scan reads the public badge SVG (no auth needed, CDN-cached), auto-fix POSTs to
/api/playground(anonymous 5/day IP cap), status hits/api/v1/auto-fix-metrics(existing API-key endpoint — a 200 confirms key validity, 401 means revoked). Status command intentionally uses metrics rather than a dedicated/api/v1/usagesince the existing endpoint already answers "does my key work". - Config: API key stored at
~/.qlens/config.jsonwith mode0600(owner read/write only) — same posture as~/.netrcandgh auth token.QLENS_API_KEYenv var overrides the file.QLENS_API_URLenv var overrides the base URL for staging. - Tests: +61 unit tests (1447 → 1508 total). Coverage: git URL parsing across HTTPS/SSH/git:// formats including token-in-URL credentials,
.git/configwalk-up-the-tree, config round-trip with restrictive perms verified, badge SVG parsing across legacyAand productionB · 71formats, formatter snapshots for all command outputs, fetch-stubbed API client request shape. Vitest config extended to also pick uppackages/cli/src/**/*.test.js. - Docs:
/docs/clirewritten from "coming soon" placeholder to full command reference with sample output, options table, env-var reference, and exit-code table. - Quality bar:
npm testgreen (1508/1508).npx tsc --noEmitclean.npx eslintclean on every touched file.npx next buildgreen. - Operator follow-up post-merge:
- cd packages/cli && npm publish --access=public (requires npm OTP) - Update root README to mention npm install -g @qlens/cli alongside the reporter packages. - Update the cli entry in src/lib/docs-routes.ts to drop the "Coming soon" wording from the sidebar summary.
Added — Cypress test reporter as 4th supported framework
Closes the Cypress gap. Cypress is one of the top 3 JS test frameworks; QA-heavy teams that picked Cypress for E2E couldn't onboard to QualityPilot without a reporter. Adding it widens addressable JS market by ~30-50%.
- Package
packages/cypress-reporter/—@qlens/cypress-reporter, MIT, peer depcypress >=13. Mirrors the file shape of@qlens/jest-reporterand@qlens/playwright-reporter(singleindex.js+index.d.ts+ README, no build step). - Integration model: hooks Cypress's plugin event channel (
after:spec,after:run) viasetupNodeEventsrather than the Mocha reporter slot. Cypress runs each spec in its own browser process, so the Mocha slot is per-spec only — the plugin channel runs in the parent Node process and lets us aggregate one upload per run. Same payload contract as the other 3 reporters, no backend changes needed. - Flakiness: tests with terminal
state: passedandattempts.length > 1are mapped to statusflaky(notpassed), matching the playwright reporter's convention. - Wizard:
src/lib/ci-yaml-generator.tsextended with cypress + npm/pnpm/yarn combos; install line isnpx cypress install, run line isnpx cypress run. Reporter wires in viacypress.config.ts(similar to playwright). 3 new GitHub Actions YAML snapshots covering each PM. - Docs:
/docs/installadds Cypress to the framework dropdown + a manual configure section with thesetupNodeEventssnippet. - Tests: +13 unit tests for the reporter (
buildPayloadshape against cannedafter:runresults, flakiness mapping, error-message truncation, env-var auto-detection, registration wiring) + 3 new YAML snapshots + 3 assertions extending existing combo tests. 1071 → 1106 total. All green.tsc --noEmitclean.eslintclean on touched files. - Operator follow-up post-merge:
cd packages/cypress-reporter && npm publish --access=public. Update root README badges section once the package is live on npm.
Added — Day roundup of revenue-driving features
Single high-velocity day shipping the AI Bug Detective end-to-end value loop + monetization surfaces. PR refs in parens.
AI Bug Detective pipeline (foundational):
- Stories 6/7/8 — PR opener cron, dedicated
/dashboard/auto-fixesreview page, metrics tile (#41-#43) - GitHub PR webhook keeps
pr_statefresh on merge/close (#44) - Per-repo HMAC webhook secrets for self-serve install (#47) — replaces shared-secret model
'broken'pr_state viacheck_runwebhook (#52)- Native GitHub Check Run on auto-fix PR commit with confidence + reasoning + token cost (#53)
- Side-by-side diff view in expanded auto-fix row, lazy-fetched per row (#54)
- Bulk merge UI with checkbox selection + sticky action bar (#46)
- Cross-user admin metrics dashboard at
/dashboard/admin/auto-fix(#48), gated byADMIN_GITHUB_IDS productionFilePathplumbed through worker so fixes record the right path when LLM targets production (#41)
CI integrations + reporters:
- Auto-trigger CI rerun on opened fix PR — workflow-dispatch with
findTestWorkflowsheuristic (#74) - GitHub Actions YAML generator wizard on
/docs/installfor 8 framework × package-manager combos (#55) - README badges + 30-second install + value bullets for all 3 reporters (#56, #57, #60, #61)
Engagement channels:
- Slack notifications per-repo with
notify_on_open(default true) +notify_on_merged(default false) + masked URL field + Test button (#50) - Weekly email digest via Resend with subject + 4 stat tiles + top-5 fixes + failure modes (#59)
- Reactivation email cron for sign-ups who never enabled auto-fix (3-7d window) (#70)
- Webhook install hint in repo settings with "How to install" + amber/green pills (#45)
Conversion + monetization:
- Hero rewrite + AI Bug Detective featured card on landing (#49, #51)
- Live AI fix demo on landing — 3-pane layout, 5 preset fixtures (#66)
- Public shareable scan results page
/scan/{owner}/{repo}/results/{id}+ dynamic OG image (#65) - Smart upgrade prompts at plan cap — warning at 80%, critical at 100%,
?from=cappre-selects Pro (#64) - 14-day Pro trial without credit card via
resolveEffectivePlan()— 11 endpoints switched to read effective plan (#67) - Pricing redesign: comparison table vs BuildPulse/Trunk/TestDino, FAQ, 4-tier display, mobile sticky CTA (#69)
- Annual plans with 20% discount via Stripe LIVE prices Pro $278/yr + Team $950/yr (#79)
SEO + discoverability:
- Site-wide metadata + OG describes new positioning (AI Bug Detective) (#63)
- Dynamic OG image via
next/ogreplaces static PNG (#68) - Vs-competitor microsites at
/vs/buildpulse,/vs/trunk,/vs/testdinowith feature matrix + FAQ + comparison CTA (#78) - Honest FAQ pass: tightened over-promises on self-host, languages, accept-rate (#72)
- iklab.dev meta description leads with QualityPilot AI Bug Detective (iklab #17)
Public API:
- OpenAPI v1.1.0 with new
/api/v1/auto-fixes+/api/v1/auto-fix-metricsendpoints + 8 schemas (#62) - 4-step first-time onboarding tour on
/dashboardwith server-side completion (#58)
Operator surfaces:
- Self-monitoring health-check cron every 15 min (5 endpoints), GitHub Actions email-on-fail (#72)
- GitHub App scaffold for programmatic webhook install — manifest, install/callback endpoints, migration 017 (#76). Cutover deferred until env vars set.
- Marketplace listing draft (6 docs) ready for publish post-stealth (#73). Decision: Enterprise stays off-Marketplace (GitHub 25% rake vs Stripe 3%).
Operational fixes done out-of-band:
- Stripe webhook URL fixed:
qualitypilot-two.vercel.app→https://www.qlens.dev/api/stripe-webhook. Prior to fix, EVERY checkout would have completed payment but failed to update DB →subscriptions.plan_idstayed Free. Caught + fixed before any real customer hit it. - Resend
qlens.devdomain verified end-to-end (DKIM TXT + SPF MX + SPF TXT in Cloudflare via API). Test email landed in inbox, not spam. - Migrations 007-019 applied to prod via Supabase Management API — webhook tracking, trial state, referral, marketplace prep, slack columns, reactivation, GitHub installations, feedback, outbound webhook (some still being applied by in-flight agents).
Quality:
- Test count rose from 412 → 918+ over the day (depending on which agents land between writes of this entry).
- 38 PRs merged in qualitypilot + 4 in iklab-landing.
- All
tsc --noEmitclean.eslintclean on all touched files (pre-existing warnings in unrelated files unchanged). - No prod regressions. Health-check cron will start emitting after deploy + first 15-min tick.
Added — Embeddable README badge for scan results
Pure viral / SEO surface: every README that adopts the badge sends a backlink and shows our brand on every visitor of that repo. Industry standard (Codecov, Coveralls, Snyk, Dependabot all live off this).
- Endpoint:
GET /scan/{owner}/{repo}/badge.svg— public, no auth, returns shields.io-style flat SVG (~140×20px). Path segments validated against^[a-zA-Z0-9._-]+$. Filterspublic=trueso private scans never leak through a badge. Same response shape for "no scan" vs "private scan" (info-leak guard). - Cache:
public, max-age=300, stale-while-revalidate=3600— 5 min edge cache, 1 h SWR for graceful behaviour during traffic spikes. CORS*so any README renderer (GitHub camo, GitLab, npm, dev.to) can proxy. - Resilience: a Supabase blip falls through to the neutral "untested" badge instead of breaking every README that embeds it. 200 status maintained so the README image slot never shows a broken-image icon.
- Pure renderer (
src/lib/scan-badge.ts) —buildBadgeSvg({ grade, score, repoFullName, scannedAt })is fully testable: per-grade colours (A=green, B=blue, C=amber, D=orange, F=red), score rounding, XML-well-formed output withxmlns="http://www.w3.org/2000/svg", escapes the five XML metacharacters in the aria-label. - Embed UI (
src/components/badge-embed.tsx) — drops onto the public scan-results page next to the share toolbar. Live preview + Markdown snippet (wrapped in a clickable link to the public scan page) + copy button. The link wrap means a click on the badge in any README lands on our scan page (where the visitor sees the full report + sign-up CTA) rather than just opening the SVG. - Tests: +27 (
scan-badge.test.ts17 — grade colours, untested fallback, score formatting, well-formed XML, XSS-shaped repo name;scan-badge-route.test.ts10 — headers, validation, query shape, DB-error resilience). 881 → 908 total. All green.
The legacy /badge/{owner}/{repo}.svg route stays alive for older READMEs but new embeds shown in the UI use the new path (consistent URL hierarchy under /scan/...).
Added — Viral referral program: 1 month free Pro per converted invite
Compounding-growth surface. Every user gets qlens.dev/r/{code} to share — when an invited user upgrades to paid Pro, BOTH sides get 1 month Pro free. Industry-standard model, baked in at the schema layer so we can analyse cohort lift later.
- Schema (
supabase/migrations/014_referral_program.sql) —users.referral_code(8-char URL-safe, unique, backfilled via SQL with the same alphabet the app uses),users.referred_by_user_id(FK, set on first sign-up),subscriptions.referral_credit_months(unspent),subscriptions.referral_credit_applied_until(audit). NOT-NULLreferral_codeenforced after backfill; check constraint guards against negative credit. - Pure module (
src/lib/referral.ts) —generateReferralCode()uses crypto.getRandomValues with rejection sampling (no modulo bias);parseReferralCookie()rejects malformed/injection-shaped values before any DB hit;applyReferralCredit()does calendar-aware date math (Jan 31 + 1mo → Feb 28/29, leap years, year wrap, EOM clamping). 32 unit tests cover every edge case. GET /r/[code]— setsqp_refcookie (HttpOnly, SameSite=Lax, 30-day, host-only), redirects to/?from=referral. Bad shape → soft-redirect withref=invalidflag, no DB lookup. Logs hashed prefix only (PII-light).- Sign-in callback — reads cookie via
cookies(), verifies the inviter exists, blocks self-referrals (same github_id), setsreferred_by_user_idONCE on the new user (sticky first-touch), then deletes the cookie. Failure to attribute is non-blocking — login always succeeds. - Stripe webhook —
checkout.session.completednow invokesmaybeGrantReferralCredit()after the existing upsert. First-paid heuristic: subscription row created within last 30s. Idempotent against retries viareferral_credit_months > 0CAS guard. - Daily cron (
/api/cron/apply-referral-credits) — picks active subs with credit, callsstripe.subscriptions.update({trial_end})to push the next charge by N months, decrements counter, stampsreferral_credit_applied_until. Caps: 12 months/user/run, 200 subs/tick. Stripe stays the source of truth for billing dates. Wired into existing dailyemail-digest-cron.ymlworkflow. - Dashboard widget (
/dashboard/settings) — invite URL with copy-to-clipboard + 3 counters (invited / converted / months credit). Copy fallback selects input text for browsers that blocknavigator.clipboard.writeText. - Telemetry —
[referral]and[referral-credit]log lines stamped at every state transition. - Tests: +40 (
referral.test.ts32,referral-credits.test.ts8). 729 → 769 total. All green.
Design decisions:
- Cookie scope: host-only (
Domainattribute omitted). Production iswww.qlens.dev; widening to.qlens.devwould surface every future subdomain we ever spin up. - Credit cap: no global cap on stacking. A power user can earn arbitrarily many months in their ledger; the per-cron-tick cap of 12 just bounds blast radius. Re-evaluate if anyone abuses it.
- Self-referral guard: best-effort at the app layer (same github_id check) rather than DB constraint — the app already has the cookie context.
- No
referral_grantsledger table: two integers onsubscriptionsexpress the state machine. We can add a ledger if/when audit trail is needed beyondusers.referred_by_user_id.
Added — First-time onboarding tour on /dashboard
A 4-step floating tour fires for new users on first dashboard visit and guides them from sign-in to the AI Bug Detective. Killer feature was buried behind several config steps; this closes the gap.
- 4 steps: Welcome → Scan a repo → (Connect CI ingest or Enable auto-fix on a repo, branched on whether the user has ingested test_runs) → done. Re-install users with auto-fix already enabled get a single condensed "you're set up" step.
- Server-side persistence: new column
users.onboarding_completed_at(migration011_user_onboarding.sql). localStorage was rejected — gets cleared and re-trains the tour. - Endpoints:
GET /api/users/onboarding-statusreturns{ completed, hasIngestedTests, hasEnabledRepos }.POST /api/users/onboarding-completesets the timestamp once (idempotent). - UI: bottom-right floating card, NOT a modal — user can keep clicking around the dashboard while the tour is up. Plain Tailwind, no joyride lib. Skip + Dismiss + Done all mark complete.
- Tests: 455 → 464 (+9).
selectSteps()is a pure function so the branch logic is unit-tested without jsdom.
2026-04-18 (latest)
Added — AI Bug Detective Phase 1
Killer feature. Other test-quality tools tell you you have flaky tests; we open PRs that fix them.
- Schema (PR#26, AB#489) —
repo_settings(per-repo opt-in default OFF),auto_fix_jobs(work queue with status machine + UNIQUE dedup_key),auto_fixes(results with confidence + cost tracking + pr_state). Plan caps: Free 0 / Pro 5 / Team 25 / Enterprise 100. - Source fetcher + redaction (PR#27, AB#490) —
fetchFile()pinned to commit SHA, 5min cache, 256KB cap, secret-redacted before any LLM call (OpenAI/Anthropic/Stripe/AWS/GitHub PAT/npm/JWT/Slack/Google + generic env-style fallback). - LLM analyzer (PR#28, AB#491) —
analyzeFix()returns typed discriminated union, never throws. Strict JSON schema validation. Confidence floor 0.5 enforced server-side independently of model self-report. - Cron enqueue (PR#29, AB#492) — hourly. Pure
planEnqueue()with opt-in + plan-cap + dedup. Race-safe via DB UNIQUE backstop. - Cron worker (PR#30, AB#493) — every 15min. Heartbeat recovery (10min stale window).
decideJobOutcome()exhaustively maps every analyzer result to a job status, with retry only for recoverable errors (timeout/api_error). - Idempotent PR opener (PR#31, AB#494) — branch name = sha256 of (test, file). Re-runs update existing PR instead of duplicating. Labels:
qualitypilot/auto-fix,automated,confidence-{high|medium|low}. Never automerges. Never pushes to default branch. - Settings UI + widget + endpoints (PR#32, AB#495) —
GET /api/auto-fixes+GET/PUT /api/auto-fix-settings+<AutoFixesWidget />on /dashboard +/dashboard/settings/auto-fixpage. Server clamps confidence threshold to [0.5, 0.95] regardless of client value. - /docs/auto-fix (PR#33, AB#496) — full operator's guide: how it works, secret redaction guarantees, GitHub permissions used, costs, the explicit list of things it does NOT do, disable instructions.
Tests
- 149 → 240 (+91 in this feature). All green.
Pre-deploy checklist for Ihor (when ready to enable)
1. Run supabase/migrations/006_auto_fix.sql in Supabase 2. Add to vercel.json crons: ``json { "path": "/api/cron/enqueue-auto-fixes", "schedule": "0 " }, { "path": "/api/cron/process-auto-fixes", "schedule": "/15 *" } ` 3. Verify env: CRON_SECRET, OPENAI_API_KEY, GitHub OAuth (already set) 4. Dogfood: enable on i-kosheliev/qualitypilot` first, observe one fix cycle 5. After dogfood: advertise as Pro feature on /pricing
2026-04-18 (later)
Added — CI ingest value loop closed
Reporters wrote to test_runs + test_run_cases but the dashboard didn't show them. Without this, the reporters were write-only and provided no user value. Now closed.
GET /api/runs(PR#22, AB#485) — list endpoint, NextAuth-gated, paginated keyset (default 50, max 100), repo filter, returns distinct-repo dropdown options.GET /api/runs/[id](PR#22, AB#485) — single run + cases. UUID-validated, cross-user 404 (no enumeration). Cases ordered status desc so failed/flaky float to top.GET /api/runs/flaky?limit=(PR#22, AB#485) — top flaky tests last 7 days. Aggregated in JS viaaggregateFlaky(repo+suite+name grouping, ranks by occurrences then attempts then alpha)./dashboard"CI Runs" tab (PR#23, AB#486) — table with repo dropdown, status badges, pass/fail/flaky counts, duration, "X ago". Empty state pitches/docs/install./dashboard/runs/[id](PR#24, AB#487) — detail page. Header (repo+commit+branch+framework+CI+duration), 5 stat tiles, cases list with filter pills (all / failed / flaky / passed). Filter defaults to "failed" when the run had any. Each case expands itserrorMessagein a code block.<TopFlakyWidget />on the main /dashboard Scan tab (PR#24) — top 5 flaky tests last 7 days, hits/api/runs/flaky?limit=5. Renders nothing when empty so it doesn't pitch CI ingest at users without runs.
Tests
- 10 new for
runs-shape(shaper + aggregator). 149/149 pass.
2026-04-18
Released to npm
- @qlens/jest-reporter v0.1.0 (release) — first public release. Posts Jest run summaries to
/api/v1/test-runs. Auto-detects GitHub Actions / GitLab CI / CircleCI / Jenkins envs. - @qlens/playwright-reporter v0.1.0 (release) — first public release. Same payload contract; flakiness = passed-on-retry.
Released to PyPI
- qlens-pytest-reporter v0.1.0 (release) — first public release. Auto-registers via
pytest11entry point, noconftest.pychanges. Usesurllib(stdlib) — zero extra runtime deps. Flakiness viapytest-rerunfailuresreport.rerun.
2026-04-17
Added
- First-touch UTM attribution (PR#9, AB#479) —
<UtmCapture>storesutm_source/medium/campaignon homepage arrival in localStorage (30d TTL). On GitHub sign-in, posts to/api/referral, which persists tousers.referral_sourceif unset. First-touch wins across devices. Matches QA Advisor v1.1.0 CTA params. Needs Supabase migration 005_referral_source.sql before merge. - CI ingest docs page (PR#10) — static
/docs/ci-ingestpage with endpoint, payload, response, use cases. Unblocks@qlens/jest-reporterpackage.json homepage link. - API keys UI (PR#2, AB#470) —
/dashboard/keyswith create/list/revoke, max 5 active keys/user, SHA-256 hashed,qlensprefix. Pro+Team only. - GitHub Issue autocreate from findings (PR#2, AB#465) —
POST /api/issue-tracker/create. - GitHub webhook quality gate (PR#2, AB#464) —
POST /api/github-webhookwith HMAC signature validation, posts commit-status checks. NeedsGITHUB_WEBHOOK_SECRETenv + user-installed GitHub App. @qlens/jest-reporterpackage (PR#2) — source inpackages/jest-reporter/. Publish blocked on npm token refresh (AB#476).- AI Improvement PRs MVP (PR#1, AB#457) — scan finding → LLM fix suggestion → auto-PR. Pro: 5/mo, Team: 25/mo. Needs
OPENAI_API_KEYenv. - Trends dashboard (PR#1, AB#458) — per-repo history sparkline + grade delta.
- Multi-repo Overview (PR#1, AB#462) — org dashboard with summary cards. Sort control + grade distribution bar added in PR#3 (AB#471).
- CI ingest endpoint (PR#1, AB#461) —
POST /api/v1/test-runs, API-key authed. - Slack grade-change webhook (PR#1, AB#463) — optional
SLACK_WEBHOOK_URLenv. - QA Advisor dogfood (PR#6) —
.github/workflows/qa-advisor.ymlposts test scenarios on every PR. Consumingi-kosheliev/qa-advisor-action@v1from Marketplace.
Changed
- Pricing rebrand (PR#1, AB#460) — Free 3 scans / Pro $29/mo / Team $99/mo. Matches competitor parity (CodeRabbit $24/dev, Qodo $30/user).
STRIPE_PRICE_PROandSTRIPE_PRICE_TEAMare live. - Supabase lazy-init (PR#1) — Proxy-based client so Vercel preview builds don't crash when env vars absent.
- checkout@v4 → v5 (PR#8) — Node 24 runtime, clears remaining deprecation warning.
- CLAUDE.md synced (PR#10) — hosting + pricing strings reflect current state.
Fixed
- **
TEST_FILE_REGEXmissed*.test.tsoutsidetests/** (PR#2) — regression test added.
Security
- All new endpoints (
/api/keys,/api/github-webhook,/api/issue-tracker/create,/api/referral) are auth-gated (NextAuth session or HMAC) and return 401 for unauthenticated requests. Smoke-tested on prod after each deploy.
See the project board for tickets AB#454-479 tracking this work.