QualityPilot

QualityPilot

Changelog

Every shipping change to qlens.dev. Most recent first.

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). Pinned runtime = "nodejs" because react-pdf needs Node APIs. Returns application/pdf with Content-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 %PDF header / %%EOF trailer 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 test green (1537 → 1549). npx tsc --noEmit clean. npx eslint clean on touched files. npx next build green (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, single bin: { qlens } entry). Two trivial deps: commander (~50KB, real subcommand UX with help text per command) and picocolors (~5KB, NO_COLOR-aware). Justification on the deps: built-in util.parseArgs works 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 are set -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/usage since the existing endpoint already answers "does my key work".
  • Config: API key stored at ~/.qlens/config.json with mode 0600 (owner read/write only) — same posture as ~/.netrc and gh auth token. QLENS_API_KEY env var overrides the file. QLENS_API_URL env 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/config walk-up-the-tree, config round-trip with restrictive perms verified, badge SVG parsing across legacy A and production B · 71 formats, formatter snapshots for all command outputs, fetch-stubbed API client request shape. Vitest config extended to also pick up packages/cli/src/**/*.test.js.
  • Docs: /docs/cli rewritten from "coming soon" placeholder to full command reference with sample output, options table, env-var reference, and exit-code table.
  • Quality bar: npm test green (1508/1508). npx tsc --noEmit clean. npx eslint clean on every touched file. npx next build green.
  • 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 dep cypress >=13. Mirrors the file shape of @qlens/jest-reporter and @qlens/playwright-reporter (single index.js + index.d.ts + README, no build step).
  • Integration model: hooks Cypress's plugin event channel (after:spec, after:run) via setupNodeEvents rather 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: passed and attempts.length > 1 are mapped to status flaky (not passed), matching the playwright reporter's convention.
  • Wizard: src/lib/ci-yaml-generator.ts extended with cypress + npm/pnpm/yarn combos; install line is npx cypress install, run line is npx cypress run. Reporter wires in via cypress.config.ts (similar to playwright). 3 new GitHub Actions YAML snapshots covering each PM.
  • Docs: /docs/install adds Cypress to the framework dropdown + a manual configure section with the setupNodeEvents snippet.
  • Tests: +13 unit tests for the reporter (buildPayload shape against canned after:run results, 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 --noEmit clean. eslint clean 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-fixes review page, metrics tile (#41-#43)
  • GitHub PR webhook keeps pr_state fresh on merge/close (#44)
  • Per-repo HMAC webhook secrets for self-serve install (#47) — replaces shared-secret model
  • 'broken' pr_state via check_run webhook (#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 by ADMIN_GITHUB_IDS
  • productionFilePath plumbed 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 findTestWorkflows heuristic (#74)
  • GitHub Actions YAML generator wizard on /docs/install for 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=cap pre-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/og replaces static PNG (#68)
  • Vs-competitor microsites at /vs/buildpulse, /vs/trunk, /vs/testdino with 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-metrics endpoints + 8 schemas (#62)
  • 4-step first-time onboarding tour on /dashboard with 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.apphttps://www.qlens.dev/api/stripe-webhook. Prior to fix, EVERY checkout would have completed payment but failed to update DB → subscriptions.plan_id stayed Free. Caught + fixed before any real customer hit it.
  • Resend qlens.dev domain 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 --noEmit clean. eslint clean 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._-]+$. Filters public=true so 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 with xmlns="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.ts 17 — grade colours, untested fallback, score formatting, well-formed XML, XSS-shaped repo name; scan-badge-route.test.ts 10 — 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-NULL referral_code enforced 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] — sets qp_ref cookie (HttpOnly, SameSite=Lax, 30-day, host-only), redirects to /?from=referral. Bad shape → soft-redirect with ref=invalid flag, 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), sets referred_by_user_id ONCE on the new user (sticky first-touch), then deletes the cookie. Failure to attribute is non-blocking — login always succeeds.
  • Stripe webhookcheckout.session.completed now invokes maybeGrantReferralCredit() after the existing upsert. First-paid heuristic: subscription row created within last 30s. Idempotent against retries via referral_credit_months > 0 CAS guard.
  • Daily cron (/api/cron/apply-referral-credits) — picks active subs with credit, calls stripe.subscriptions.update({trial_end}) to push the next charge by N months, decrements counter, stamps referral_credit_applied_until. Caps: 12 months/user/run, 200 subs/tick. Stripe stays the source of truth for billing dates. Wired into existing daily email-digest-cron.yml workflow.
  • Dashboard widget (/dashboard/settings) — invite URL with copy-to-clipboard + 3 counters (invited / converted / months credit). Copy fallback selects input text for browsers that block navigator.clipboard.writeText.
  • Telemetry[referral] and [referral-credit] log lines stamped at every state transition.
  • Tests: +40 (referral.test.ts 32, referral-credits.test.ts 8). 729 → 769 total. All green.

Design decisions:

  • Cookie scope: host-only (Domain attribute omitted). Production is www.qlens.dev; widening to .qlens.dev would 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_grants ledger table: two integers on subscriptions express the state machine. We can add a ledger if/when audit trail is needed beyond users.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 (migration 011_user_onboarding.sql). localStorage was rejected — gets cleared and re-trains the tour.
  • Endpoints: GET /api/users/onboarding-status returns { completed, hasIngestedTests, hasEnabledRepos }. POST /api/users/onboarding-complete sets 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-fix page. 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 via aggregateFlaky (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 its errorMessage in 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 pytest11 entry point, no conftest.py changes. Uses urllib (stdlib) — zero extra runtime deps. Flakiness via pytest-rerunfailures report.rerun.

2026-04-17

Added

  • First-touch UTM attribution (PR#9, AB#479) — <UtmCapture> stores utm_source/medium/campaign on homepage arrival in localStorage (30d TTL). On GitHub sign-in, posts to /api/referral, which persists to users.referral_source if 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-ingest page with endpoint, payload, response, use cases. Unblocks @qlens/jest-reporter package.json homepage link.
  • API keys UI (PR#2, AB#470) — /dashboard/keys with create/list/revoke, max 5 active keys/user, SHA-256 hashed, qlens prefix. 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-webhook with HMAC signature validation, posts commit-status checks. Needs GITHUB_WEBHOOK_SECRET env + user-installed GitHub App.
  • @qlens/jest-reporter package (PR#2) — source in packages/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_KEY env.
  • 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_URL env.
  • QA Advisor dogfood (PR#6) — .github/workflows/qa-advisor.yml posts test scenarios on every PR. Consuming i-kosheliev/qa-advisor-action@v1 from 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_PRO and STRIPE_PRICE_TEAM are 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_REGEX missed *.test.ts outside tests/** (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.