laxy-verify 1.2.3 → 1.3.1

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
@@ -1,451 +1,479 @@
1
- # laxy-verify
2
-
3
- `laxy-verify` is a deployment blocker gate for frontend apps.
4
-
5
- Every verification run includes build, Lighthouse, E2E, multi-viewport, security audit, visual diff, broken links, console error monitoring, and stability coverage regardless of plan. Optional opt-in checks add TypeScript type checking, secret scanning, bundle size analysis, outdated dependency detection, deep accessibility audit, deep SEO audit, and Core Web Vitals budget enforcement.
6
-
7
- ## Quick start
8
-
9
- Run it on a frontend app:
10
-
11
- ```bash
12
- cd your-project
13
- npx laxy-verify .
14
- ```
15
-
16
- Generate config plus GitHub Actions workflow:
17
-
18
- ```bash
19
- npx laxy-verify --init
20
- ```
21
-
22
- That creates:
23
-
24
- - `.laxy.yml`
25
- - `.github/workflows/laxy-verify.yml`
26
-
27
- Optional: log in to connect the CLI to your Laxy account:
28
-
29
- ```bash
30
- npx laxy-verify login
31
- npx laxy-verify whoami
32
- ```
33
-
34
- For CI, set `LAXY_TOKEN` instead of interactive login:
35
-
36
- ```yaml
37
- env:
38
- LAXY_TOKEN: ${{ secrets.LAXY_TOKEN }}
39
- ```
40
-
41
- ## Why laxy-verify?
42
-
43
- Most teams already have some mix of:
44
-
45
- - `npm run build`
46
- - Lighthouse
47
- - Playwright or smoke checks
48
- - CI status rules
49
-
50
- The gap is not "can these tools exist together?" The gap is "who turns that pile of output into a safe merge or release decision?"
51
-
52
- `laxy-verify` gives you:
53
-
54
- - one command instead of a custom build plus audit plus smoke-check script stack
55
- - one result file instead of scattered logs
56
- - one blocker-first decision instead of "build passed, but do we actually trust this release?"
57
- - optional account-linked automation on top of the same verification run
58
-
59
- This is most useful if you ship frontend apps and want a practical gate before:
60
-
61
- - merge
62
- - client review
63
- - QA handoff
64
- - production release
65
-
66
- ## Why not just LHCI?
67
-
68
- | | laxy-verify | LHCI | Checkly | Percy |
69
- |--|--|--|--|--|
70
- | Production build failure detection | Yes | No | No | No |
71
- | User-flow E2E verification | Yes | No | Manual setup | No |
72
- | Lighthouse scoring | Yes | Yes | No | No |
73
- | Visual regression check | Yes | No | No | Yes |
74
- | Broken link detection | Yes | No | No | No |
75
- | Console error monitoring | Yes | No | No | No |
76
- | Cross-browser (Firefox, WebKit) | Yes | No | Yes | No |
77
- | Release decision (`hold` / `client-ready`) | Yes | No, score only | No | No |
78
- | TypeScript type check | Yes | No | No | No |
79
- | Hardcoded secret scanning | Yes | No | No | No |
80
- | Bundle size analysis | Yes | No | No | No |
81
- | Outdated dependency check | Yes | No | No | No |
82
- | Deep WCAG audit (axe-core) | Yes | No | No | No |
83
- | Deep SEO audit | Yes | No | No | No |
84
- | Core Web Vitals budget | Yes | No | No | No |
85
- | Zero-config local start | Yes | No | No | No |
86
-
87
- LHCI measures Lighthouse. `laxy-verify` is for deciding whether this frontend is actually safe to ship.
88
-
89
- ## The failures it is meant to catch
90
-
91
- Use `laxy-verify` when you want to catch things like:
92
-
93
- - the production build passes locally but fails in CI
94
- - the app opens, but a key button or form flow is broken
95
- - desktop looks fine, but a mobile CTA is pushed out of view
96
- - Lighthouse looks acceptable, but the user-visible path is still not safe to ship
97
- - a PR needs a clear hold reason instead of a vague "something failed"
98
- - hardcoded API keys or secrets are about to be pushed to a public repo
99
- - TypeScript type errors could cause runtime crashes
100
- - bundle size has silently grown past acceptable limits
101
- - critical WCAG violations block real users
102
- - missing SEO meta tags hurt discoverability
103
-
104
- ## What it actually checks
105
-
106
- Every run includes:
107
-
108
- - **production build** runs your actual build command, exit code determines pass/fail
109
- - **Lighthouse** 3 runs averaged for stable performance, accessibility, SEO, and best practices scores
110
- - **E2E scenarios** Puppeteer-based user flow testing (auto-detected or configured via `.laxy.yml`)
111
- - **stability pass** E2E runs a second time to catch flaky behavior
112
- - **multi-viewport** Lighthouse at desktop (1350px), tablet (1024px), and mobile (390px)
113
- - **security audit** `npm audit` dependency vulnerability scan
114
- - **visual diff** pixel-level screenshot comparison against baseline
115
- - **broken links** crawls all internal links and validates HTTP responses
116
- - **console error monitoring** captures browser JS errors during E2E execution
117
- - **cross-browser** Playwright on Firefox and WebKit if `browsers` is configured in `.laxy.yml`
118
-
119
- ### Opt-in checks
120
-
121
- These checks are off by default. Enable them via CLI flags or `.laxy.yml`.
122
-
123
- | Flag | What it checks | Blocker or Advisory |
124
- |------|----------------|---------------------|
125
- | `--typecheck` | TypeScript type errors via `tsc --noEmit` | **Blocker** (5+ errors high severity) |
126
- | `--secret-scan` | Hardcoded secrets: AWS keys, GitHub tokens, Stripe keys, private keys, Bearer tokens, JWTs, generic password/token assignments | **Blocker** (always high severity) |
127
- | `--bundle-size` | Next.js or Vite bundle size analysis (first-load JS, largest chunk) | Advisory |
128
- | `--outdated-check` | Outdated dependencies via `npm outdated --json` | Advisory (major behind warning) |
129
- | `--a11y-deep` | Deep WCAG audit via axe-core (critical/serious violations) | **Blocker** (critical high severity) |
130
- | `--seo-deep` | SEO meta tags, canonical, robots, Open Graph, Twitter Card, JSON-LD | Advisory |
131
- | `--vitals-budget` | Core Web Vitals budget: LCP 2500ms, CLS 0.1, INP 200ms | Advisory |
132
-
133
- Secret scan never exposes actual credential values findings are masked with `***` in all output formats.
134
-
135
- ## What you get from one run
136
-
137
- - a release decision such as `quick-pass`, `client-ready`, `release-ready`, `hold`, or `investigate`
138
- - a verification grade: `Gold`, `Silver`, `Bronze`, or `Unverified`
139
- - `.laxy-result.json` for CI and automation
140
- - `laxy-verify-report.md` for human review and AI handoff
141
-
142
- Grades still exist, but they are not the main point. The main point is whether the run found blockers you should stop on.
143
-
144
- ## Example workflow
145
-
146
- 1. Run `npx laxy-verify .` locally before opening or merging a PR.
147
- 2. Fix broken builds, broken flows, and visible regressions.
148
- 3. Commit `.laxy.yml`.
149
- 4. Run `npx laxy-verify --init`.
150
- 5. Let the GitHub Action apply the same gate on every PR.
151
-
152
- Full verification with all opt-in checks:
153
-
154
- ```bash
155
- npx laxy-verify . --typecheck --secret-scan --bundle-size --outdated-check --a11y-deep --seo-deep --vitals-budget
156
- ```
157
-
158
- Or enable them in `.laxy.yml` and just run:
159
-
160
- ```bash
161
- npx laxy-verify .
162
- ```
163
-
164
- ## Example output
165
-
166
- ```text
167
- Decision: client-ready
168
- Grade: Gold
169
-
170
- Passed:
171
- - production build
172
- - Lighthouse thresholds (Performance 92, Accessibility 97, SEO 90, Best Practices 95)
173
- - core user flows (5/5 scenarios passed)
174
- - stability pass (second E2E run passed)
175
- - desktop, tablet, and mobile viewport checks
176
- - security audit (no known vulnerabilities)
177
- - visual diff (no regressions)
178
- - broken links (0 broken / 12 checked)
179
- - console errors (0 detected)
180
- - TypeScript (0 errors)
181
- - Secret scan (0 findings, 42 files)
182
- - Bundle size (vite, within thresholds)
183
- - Outdated deps (0 outdated)
184
- - WCAG deep (0 critical)
185
- - SEO deep (0 errors)
186
- - Core Web Vitals budget (LCP 1200ms, CLS 0.05, INP 80ms)
187
-
188
- Artifacts:
189
- - .laxy-result.json
190
- - laxy-verify-report.md
191
- ```
192
-
193
- ## The decision it helps you make
194
-
195
- `laxy-verify` answers a delivery decision, not just a score:
196
-
197
- - Would this break for real users right now?
198
- - What would block a client demo or QA handoff?
199
- - Is there enough evidence to merge or release with confidence?
200
-
201
- All verification checks already run without a paid plan gate.
202
-
203
- ## Grades
204
-
205
- | Grade | Meaning |
206
- |---|---|
207
- | Gold | Build passed, E2E passed, Lighthouse passed, and release-level evidence passed |
208
- | Silver | Build passed and E2E passed |
209
- | Bronze | Build passed |
210
- | Unverified | Build failed |
211
-
212
- Default Lighthouse thresholds:
213
-
214
- - Performance `>= 70`
215
- - Accessibility `>= 85`
216
- - SEO `>= 80`
217
- - Best Practices `>= 80`
218
-
219
- ## Config
220
-
221
- All fields in `.laxy.yml` are optional.
222
-
223
- ```yaml
224
- framework: auto
225
- build_command: ""
226
- dev_command: ""
227
- package_manager: auto
228
- port: 3000
229
- build_timeout: 300
230
- dev_timeout: 60
231
- lighthouse_runs: 3
232
- fail_on: bronze
233
-
234
- thresholds:
235
- performance: 70
236
- accessibility: 85
237
- seo: 80
238
- best_practices: 80
239
-
240
- crawl: false
241
- max_crawl_depth: 3
242
- max_crawl_pages: 10
243
- browsers:
244
- - chromium
245
-
246
- # Explicit route list for Lighthouse (optional)
247
- lighthouse_routes: []
248
- # Extra routes not discoverable by the crawler (optional)
249
- extra_routes: []
250
- # Max crawl-discovered routes to run Lighthouse on (default: 5)
251
- max_lighthouse_routes: 5
252
-
253
- # Visual diff fine-tuning (optional)
254
- visual_diff:
255
- pixelmatch_threshold: 0.1
256
- warn_threshold: 30
257
- rollback_threshold: 60
258
- ignore_selectors: []
259
- disable_animations: true
260
-
261
- # Opt-in checks (off by default)
262
- typecheck: false
263
- secret_scan: false
264
- secret_scan_ignore_paths: []
265
- bundle_size: false
266
- outdated_check: false
267
- a11y_deep: false
268
- seo_deep: false
269
- vitals_budget: false
270
- ```
271
-
272
- Useful adjustments:
273
-
274
- - raise `fail_on` in CI when you want stricter gates
275
- - set `build_command` or `dev_command` if auto-detection is not enough
276
- - increase `lighthouse_runs` for more stable performance evidence
277
- - point the CLI at the actual app directory in a monorepo
278
-
279
- ## CLI
280
-
281
- ```text
282
- npx laxy-verify [project-dir]
283
-
284
- Options:
285
- --format console|json
286
- --ci
287
- --config <path>
288
- --fail-on unverified|bronze|silver|gold
289
- --skip-lighthouse
290
- --plan-override free|pro|team
291
- --badge
292
- --init
293
- --multi-viewport
294
- --crawl Crawl the app to discover routes before E2E
295
- --typecheck Run TypeScript type check (tsc --noEmit)
296
- --secret-scan Scan for hardcoded secrets and credentials
297
- --bundle-size Analyze bundle size (Next.js/Vite)
298
- --outdated-check Check for outdated dependencies
299
- --a11y-deep Deep accessibility audit (axe-core)
300
- --seo-deep Deep SEO audit (meta, OG, JSON-LD)
301
- --vitals-budget Core Web Vitals budget check (LCP, CLS, INP)
302
- --share Save result and get a shareable URL (Pro)
303
- --compare <url> Compare Lighthouse scores against a reference URL (Pro)
304
- --help
305
-
306
- Subcommands:
307
- login [email]
308
- logout
309
- whoami
310
- ```
311
-
312
- `--plan-override` is only for plan-label and automation testing. Verification coverage stays the same on every plan.
313
-
314
- ## Pro features
315
-
316
- Pro and Team accounts unlock additional capabilities on top of the same verification run:
317
-
318
- - **Result saving and sharing** — `--share` saves the run to your dashboard and returns a shareable URL
319
- - **Environment comparison** — `--compare <url>` runs Lighthouse against a reference URL (e.g. staging or production) and shows score deltas between your local build and the reference
320
- - **AI failure analysis** — when a run ends in `hold`, Claude analyzes the failure context and returns a root cause summary with top fix suggestions
321
- - **Team Slack / Discord alerts** — grade drops and `hold` verdicts fire webhook notifications with score deltas and blocker details
322
- - **Weekly team report** automated weekly summary of verification activity across your team's repos
323
-
324
- ## Secret scan patterns
325
-
326
- When `--secret-scan` is enabled, the following patterns are detected:
327
-
328
- | Pattern | Example |
329
- |---------|--------|
330
- | AWS Access Key | `AKIA...` (20 chars) |
331
- | AWS Secret Key | `aws_secret_access_key = '...'` |
332
- | GitHub Token | `ghp_`, `gho_`, `ghs_`, `ghu_` |
333
- | Slack Token / Webhook | `xoxb-...`, `hooks.slack.com/...` |
334
- | Private Key Block | `-----BEGIN RSA PRIVATE KEY-----` |
335
- | Google API Key | `AIza...` |
336
- | Stripe Key | `sk_live_...`, `pk_live_...` |
337
- | Twilio / SendGrid / Mailgun | `SK...`, `SG...`, `key-...` |
338
- | Hardcoded Bearer Token | `Bearer abc123...` |
339
- | JWT-like Secret | `eyJ...` |
340
- | Generic Secret Assignment | `password = '...'`, `api_key = '...'` |
341
-
342
- False positive filtering:
343
-
344
- - `process.env.*`, `import.meta.env.*`, `NEXT_PUBLIC_*`, `VITE_*` references are ignored
345
- - GitHub Actions template variables (`${{ secrets.* }}`) are ignored
346
- - `test/`, `tests/`, `__tests__/`, `spec/` directories are excluded
347
- - Comment lines (`//`, `*`, `<!--`) are excluded — commented-out secrets are not flagged
348
- - Placeholder/example values are ignored
349
- - All secret values in findings are **masked with `***`** — never exposed in output
350
-
351
- ## Test fixture
352
-
353
- A sample Vite + React + TypeScript app is included at `fixtures/sample-app/` for testing all verification checks:
354
-
355
- ```bash
356
- cd fixtures/sample-app
357
- npm install
358
- npm run build
359
- npx laxy-verify . --typecheck --secret-scan --bundle-size --outdated-check --skip-lighthouse
360
- ```
361
-
362
- See `fixtures/sample-app/README.md` for details on what each check finds in the fixture.
363
-
364
- ## Result files
365
-
366
- Every run writes `.laxy-result.json`.
367
-
368
- When the run finds something worth reviewing, it also writes `laxy-verify-report.md`.
369
-
370
- Typical use:
371
-
372
- - `.laxy-result.json` for CI parsing and machine decisions
373
- - `laxy-verify-report.md` for human review, PR discussion, or AI-assisted fixes
374
-
375
- The markdown report is designed to be readable and easy to paste into coding tools.
376
-
377
- It includes:
378
-
379
- - the main stop-or-ship decision in plain English
380
- - what passed
381
- - blockers and warnings
382
- - exact verification evidence
383
- - failed scenarios
384
- - a `Copy For AI` section
385
-
386
- ## What this is good at
387
-
388
- Use `laxy-verify` when you want:
389
-
390
- - a merge or release gate for frontend apps
391
- - one repeatable command for build plus audit plus visible-flow verification
392
- - a decision that non-authors can understand
393
- - JSON output for automation without building your own wrapper
394
-
395
- ## What this is not
396
-
397
- `laxy-verify` is not trying to replace:
398
-
399
- - your full Playwright suite
400
- - deep visual QA by designers
401
- - production observability
402
- - manual exploratory testing
403
-
404
- It is a pre-merge and pre-release verification layer, not your entire quality system.
405
-
406
- ## Limitations
407
-
408
- - monorepos should target the real app subdirectory
409
- - dev-server-based Lighthouse is not identical to production hosting
410
- - visual diff and viewport checks increase runtime
411
- - best stability is on current LTS Node releases
412
-
413
- ## Requirements
414
-
415
- - Node `>=20.18.0 <25`
416
- - a frontend app with a runnable build flow
417
- - optional: `playwright` if your project already uses it
418
-
419
- ## Changelog
420
-
421
- ### v1.2.3 — Bug fix
422
-
423
- - Fix E2E and visual diff connection failure on Windows with Node.js 17+: `verifyUrl` now uses `localhost` instead of `127.0.0.1`. On Windows, Vite binds to `::1` (IPv6) which does not accept IPv4 connections.
424
-
425
- ### v1.2.2 Opt-in verification checks
426
-
427
- Added 7 opt-in checks (off by default, enable via CLI flags or `.laxy.yml`):
428
-
429
- - `--typecheck` TypeScript type error detection via `tsc --noEmit`
430
- - `--secret-scan` Hardcoded secret scanning with 11 regex patterns and `***` masking
431
- - `--bundle-size` Next.js/Vite bundle size analysis
432
- - `--outdated-check` — Outdated dependency detection via `npm outdated`
433
- - `--a11y-deep` — Deep WCAG audit via axe-core + Puppeteer
434
- - `--seo-deep` — SEO meta/OG/JSON-LD audit
435
- - `--vitals-budget` Core Web Vitals budget enforcement (LCP, CLS, INP)
436
-
437
- Other changes:
438
-
439
- - Secret scan findings are **masked** — real credential values never appear in JSON, markdown, or console output
440
- - Comment lines excluded from secret scanning to reduce false positives
441
- - `test/`, `tests/`, `__tests__/`, `spec/` directories excluded from scanning
442
- - `.laxy.yml` supports `secret_scan_ignore_paths` for custom exclusions
443
- - Verification report includes all new checks in passes checklist and improvement recommendations
444
- - Markdown report includes all new checks in the delivery evidence table
445
- - Added `fixtures/sample-app/` test fixture (Vite + React + TypeScript)
446
- - 17 test files, 88 unit tests
447
-
448
- ## Links
449
-
450
- - GitHub: https://github.com/SUNgm24/Laxy/tree/main/laxy-verify
451
- - Issues: https://github.com/SUNgm24/Laxy/issues
1
+ # laxy-verify
2
+
3
+ `laxy-verify` is a deployment blocker gate for frontend apps.
4
+
5
+ Every verification run includes build, Lighthouse, E2E, multi-viewport, security audit, visual diff, broken links, console error monitoring, and stability coverage regardless of plan. Optional opt-in checks add TypeScript type checking, secret scanning, bundle size analysis, outdated dependency detection, deep accessibility audit, deep SEO audit, and Core Web Vitals budget enforcement.
6
+
7
+ ## Quick start
8
+
9
+ Run it on a frontend app:
10
+
11
+ ```bash
12
+ cd your-project
13
+ npx laxy-verify .
14
+ ```
15
+
16
+ Generate config plus GitHub Actions workflow:
17
+
18
+ ```bash
19
+ npx laxy-verify --init
20
+ ```
21
+
22
+ That creates:
23
+
24
+ - `.laxy.yml`
25
+ - `.github/workflows/laxy-verify.yml`
26
+
27
+ Optional: log in to connect the CLI to your Laxy account:
28
+
29
+ ```bash
30
+ npx laxy-verify login
31
+ npx laxy-verify whoami
32
+ ```
33
+
34
+ For CI, set `LAXY_TOKEN` instead of interactive login:
35
+
36
+ ```yaml
37
+ env:
38
+ LAXY_TOKEN: ${{ secrets.LAXY_TOKEN }}
39
+ ```
40
+
41
+ ## Why laxy-verify?
42
+
43
+ Most teams already have some mix of:
44
+
45
+ - `npm run build`
46
+ - Lighthouse
47
+ - Playwright or smoke checks
48
+ - CI status rules
49
+
50
+ The gap is not "can these tools exist together?" The gap is "who turns that pile of output into a safe merge or release decision?"
51
+
52
+ `laxy-verify` gives you:
53
+
54
+ - one command instead of a custom build plus audit plus smoke-check script stack
55
+ - one result file instead of scattered logs
56
+ - one blocker-first decision instead of "build passed, but do we actually trust this release?"
57
+ - optional account-linked automation on top of the same verification run
58
+
59
+ This is most useful if you ship frontend apps and want a practical gate before:
60
+
61
+ - merge
62
+ - client review
63
+ - QA handoff
64
+ - production release
65
+
66
+ ## Why not just LHCI?
67
+
68
+ | | laxy-verify | LHCI | Checkly | Percy |
69
+ |--|--|--|--|--|
70
+ | Production build failure detection | Yes | No | No | No |
71
+ | User-flow E2E verification | Yes | No | Manual setup | No |
72
+ | Lighthouse scoring | Yes | Yes | No | No |
73
+ | Visual regression check | Yes | No | No | Yes |
74
+ | Broken link detection | Yes | No | No | No |
75
+ | Console error monitoring | Yes | No | No | No |
76
+ | Cross-browser (Firefox, WebKit) | Yes | No | Yes | No |
77
+ | Release decision (`hold` / `client-ready`) | Yes | No, score only | No | No |
78
+ | TypeScript type check | Yes | No | No | No |
79
+ | Hardcoded secret scanning | Yes | No | No | No |
80
+ | Bundle size analysis | Yes | No | No | No |
81
+ | Outdated dependency check | Yes | No | No | No |
82
+ | Deep WCAG audit (axe-core) | Yes | No | No | No |
83
+ | Deep SEO audit | Yes | No | No | No |
84
+ | Core Web Vitals budget | Yes | No | No | No |
85
+ | Zero-config local start | Yes | No | No | No |
86
+
87
+ LHCI measures Lighthouse. `laxy-verify` is for deciding whether this frontend is actually safe to ship.
88
+
89
+ ## The failures it is meant to catch
90
+
91
+ Use `laxy-verify` when you want to catch things like:
92
+
93
+ - the production build passes locally but fails in CI
94
+ - the app opens, but a key button or form flow is broken
95
+ - desktop looks fine, but a mobile CTA is pushed out of view
96
+ - Lighthouse looks acceptable, but the user-visible path is still not safe to ship
97
+ - a PR needs a clear hold reason instead of a vague "something failed"
98
+ - hardcoded API keys or secrets are about to be pushed to a public repo
99
+ - TypeScript type errors could cause runtime crashes
100
+ - bundle size has silently grown past acceptable limits
101
+ - critical WCAG violations block real users
102
+ - missing SEO meta tags hurt discoverability
103
+
104
+ ## What it actually checks
105
+
106
+ Every run includes:
107
+
108
+ - **production build** - runs your actual build command, exit code determines pass/fail
109
+ - **Lighthouse** - 3 runs averaged for stable performance, accessibility, SEO, and best practices scores
110
+ - **E2E scenarios** - Puppeteer-based user flow testing (auto-detected or configured via `.laxy.yml`)
111
+ - **stability pass** - E2E runs a second time to catch flaky behavior
112
+ - **multi-viewport** - Lighthouse at desktop (1350px), tablet (1024px), and mobile (390px)
113
+ - **security audit** - `npm audit` dependency vulnerability scan
114
+ - **visual diff** - pixel-level screenshot comparison against baseline
115
+ - **broken links** - crawls all internal links and validates HTTP responses
116
+ - **console error monitoring** - captures browser JS errors during E2E execution
117
+ - **cross-browser** - Playwright on Firefox and WebKit if `browsers` is configured in `.laxy.yml`
118
+
119
+ ### Opt-in checks
120
+
121
+ These checks are off by default. Enable them via CLI flags or `.laxy.yml`.
122
+
123
+ | Flag | What it checks | Blocker or Advisory |
124
+ |------|----------------|---------------------|
125
+ | `--typecheck` | TypeScript type errors via `tsc --noEmit` | **Blocker** (5+ errors -> high severity) |
126
+ | `--secret-scan` | Hardcoded secrets: AWS keys, GitHub tokens, Stripe keys, private keys, Bearer tokens, JWTs, generic password/token assignments | **Blocker** (always high severity) |
127
+ | `--bundle-size` | Next.js or Vite bundle size analysis (first-load JS, largest chunk) | Advisory |
128
+ | `--outdated-check` | Outdated dependencies via `npm outdated --json` | Advisory (major behind -> warning) |
129
+ | `--a11y-deep` | Deep WCAG audit via axe-core (critical/serious violations) | **Blocker** (critical -> high severity) |
130
+ | `--seo-deep` | SEO meta tags, canonical, robots, Open Graph, Twitter Card, JSON-LD | Advisory |
131
+ | `--vitals-budget` | Core Web Vitals budget: LCP <= 2500ms, CLS <= 0.1, INP <= 200ms | Advisory |
132
+
133
+ Secret scan never exposes actual credential values - findings are masked with `***` in all output formats.
134
+
135
+ ## What you get from one run
136
+
137
+ - a release decision such as `quick-pass`, `client-ready`, `release-ready`, `hold`, or `investigate`
138
+ - a verification grade: `Gold`, `Silver`, `Bronze`, or `Unverified`
139
+ - `.laxy-result.json` for CI and automation
140
+ - `laxy-verify-report.md` for human review and AI handoff
141
+
142
+ Grades still exist, but they are not the main point. The main point is whether the run found blockers you should stop on.
143
+
144
+ ## Example workflow
145
+
146
+ 1. Run `npx laxy-verify .` locally before opening or merging a PR.
147
+ 2. Fix broken builds, broken flows, and visible regressions.
148
+ 3. Commit `.laxy.yml`.
149
+ 4. Run `npx laxy-verify --init`.
150
+ 5. Let the GitHub Action apply the same gate on every PR.
151
+
152
+ Full verification with all opt-in checks:
153
+
154
+ ```bash
155
+ npx laxy-verify . --typecheck --secret-scan --bundle-size --outdated-check --a11y-deep --seo-deep --vitals-budget
156
+ ```
157
+
158
+ Or enable them in `.laxy.yml` and just run:
159
+
160
+ ```bash
161
+ npx laxy-verify .
162
+ ```
163
+
164
+ ## Example output
165
+
166
+ ```text
167
+ Decision: client-ready
168
+ Grade: Gold
169
+
170
+ Passed:
171
+ - production build
172
+ - Lighthouse thresholds (Performance 92, Accessibility 97, SEO 90, Best Practices 95)
173
+ - core user flows (5/5 scenarios passed)
174
+ - stability pass (second E2E run passed)
175
+ - desktop, tablet, and mobile viewport checks
176
+ - security audit (no known vulnerabilities)
177
+ - visual diff (no regressions)
178
+ - broken links (0 broken / 12 checked)
179
+ - console errors (0 detected)
180
+ - TypeScript (0 errors)
181
+ - Secret scan (0 findings, 42 files)
182
+ - Bundle size (vite, within thresholds)
183
+ - Outdated deps (0 outdated)
184
+ - WCAG deep (0 critical)
185
+ - SEO deep (0 errors)
186
+ - Core Web Vitals budget (LCP 1200ms, CLS 0.05, INP 80ms)
187
+
188
+ Artifacts:
189
+ - .laxy-result.json
190
+ - laxy-verify-report.md
191
+
192
+ Badge (auto-updates with each run):
193
+ [![Laxy Verify](https://laxy.app/api/badge/your-repo-id)](https://laxy.app)
194
+ ```
195
+
196
+ For Free accounts, the CLI prints a tip instead:
197
+
198
+ ```text
199
+ Tip: Pro tracks your last 30 runs so you can see if Performance or Grade is improving.
200
+ https://laxy.app/pricing
201
+ ```
202
+
203
+ ## The decision it helps you make
204
+
205
+ `laxy-verify` answers a delivery decision, not just a score:
206
+
207
+ - Would this break for real users right now?
208
+ - What would block a client demo or QA handoff?
209
+ - Is there enough evidence to merge or release with confidence?
210
+
211
+ All verification checks already run without a paid plan gate.
212
+
213
+ ## Grades
214
+
215
+ | Grade | Meaning |
216
+ |---|---|
217
+ | Gold | Build passed, E2E passed, Lighthouse passed, and release-level evidence passed |
218
+ | Silver | Build passed and E2E passed |
219
+ | Bronze | Build passed |
220
+ | Unverified | Build failed |
221
+
222
+ Default Lighthouse thresholds:
223
+
224
+ - Performance `>= 70`
225
+ - Accessibility `>= 85`
226
+ - SEO `>= 80`
227
+ - Best Practices `>= 80`
228
+
229
+ ## Config
230
+
231
+ All fields in `.laxy.yml` are optional.
232
+
233
+ ```yaml
234
+ framework: auto
235
+ build_command: ""
236
+ dev_command: ""
237
+ package_manager: auto
238
+ port: 3000
239
+ build_timeout: 300
240
+ dev_timeout: 60
241
+ lighthouse_runs: 3
242
+ fail_on: bronze
243
+
244
+ thresholds:
245
+ performance: 70
246
+ accessibility: 85
247
+ seo: 80
248
+ best_practices: 80
249
+
250
+ crawl: false
251
+ max_crawl_depth: 3
252
+ max_crawl_pages: 10
253
+ browsers:
254
+ - chromium
255
+
256
+ # Explicit route list for Lighthouse (optional)
257
+ lighthouse_routes: []
258
+ # Extra routes not discoverable by the crawler (optional)
259
+ extra_routes: []
260
+ # Max crawl-discovered routes to run Lighthouse on (default: 5)
261
+ max_lighthouse_routes: 5
262
+
263
+ # Visual diff fine-tuning (optional)
264
+ visual_diff:
265
+ pixelmatch_threshold: 0.1
266
+ warn_threshold: 30
267
+ rollback_threshold: 60
268
+ ignore_selectors: []
269
+ disable_animations: true
270
+
271
+ # Opt-in checks (off by default)
272
+ typecheck: false
273
+ secret_scan: false
274
+ secret_scan_ignore_paths: []
275
+ bundle_size: false
276
+ outdated_check: false
277
+ a11y_deep: false
278
+ seo_deep: false
279
+ vitals_budget: false
280
+ ```
281
+
282
+ Useful adjustments:
283
+
284
+ - raise `fail_on` in CI when you want stricter gates
285
+ - set `build_command` or `dev_command` if auto-detection is not enough
286
+ - increase `lighthouse_runs` for more stable performance evidence
287
+ - point the CLI at the actual app directory in a monorepo
288
+
289
+ ## CLI
290
+
291
+ ```text
292
+ npx laxy-verify [project-dir]
293
+
294
+ Options:
295
+ --format console|json
296
+ --ci
297
+ --config <path>
298
+ --fail-on unverified|bronze|silver|gold
299
+ --skip-lighthouse
300
+ --plan-override free|pro|team
301
+ --badge
302
+ --init
303
+ --multi-viewport
304
+ --crawl Crawl the app to discover routes before E2E
305
+ --typecheck Run TypeScript type check (tsc --noEmit)
306
+ --secret-scan Scan for hardcoded secrets and credentials
307
+ --bundle-size Analyze bundle size (Next.js/Vite)
308
+ --outdated-check Check for outdated dependencies
309
+ --a11y-deep Deep accessibility audit (axe-core)
310
+ --seo-deep Deep SEO audit (meta, OG, JSON-LD)
311
+ --vitals-budget Core Web Vitals budget check (LCP, CLS, INP)
312
+ --share Save result and get a shareable URL (Pro)
313
+ --compare <url> Compare Lighthouse scores against a reference URL (Pro)
314
+ --help
315
+
316
+ Subcommands:
317
+ login [email]
318
+ logout
319
+ whoami
320
+ ```
321
+
322
+ `--plan-override` is only for plan-label and automation testing. Verification coverage stays the same on every plan.
323
+
324
+ ## Pro features
325
+
326
+ Pro and Team accounts unlock additional capabilities on top of the same verification run:
327
+
328
+ - **Result saving and sharing** - `--share` saves the run to your dashboard and returns a shareable URL
329
+ - **Environment comparison** - `--compare <url>` runs Lighthouse against a reference URL (e.g. staging or production) and shows score deltas between your local build and the reference
330
+ - **AI failure analysis** - when a run ends in `hold`, Claude analyzes the failure context and returns a root cause summary with top fix suggestions
331
+ - **History trend tracking** - the last 30 runs are stored so you can see whether your grade and performance scores are improving or regressing over time
332
+ - **Dynamic README badge** - after each run, the CLI prints a Markdown badge snippet that links to your live verification status. The badge auto-updates with every run so your README always reflects current grade
333
+ - **Team Slack / Discord alerts** - grade drops and `hold` verdicts fire webhook notifications with score deltas and blocker details
334
+ - **Weekly team report** - automated weekly summary of verification activity across your team's repos
335
+
336
+ Free accounts see a hint after each run pointing to the history trend feature.
337
+
338
+ ## Secret scan patterns
339
+
340
+ When `--secret-scan` is enabled, the following patterns are detected:
341
+
342
+ | Pattern | Example |
343
+ |---------|--------|
344
+ | AWS Access Key | `AKIA...` (20 chars) |
345
+ | AWS Secret Key | `aws_secret_access_key = '...'` |
346
+ | GitHub Token | `ghp_`, `gho_`, `ghs_`, `ghu_` |
347
+ | Slack Token / Webhook | `xoxb-...`, `hooks.slack.com/...` |
348
+ | Private Key Block | `-----BEGIN RSA PRIVATE KEY-----` |
349
+ | Google API Key | `AIza...` |
350
+ | Stripe Key | `sk_live_...`, `pk_live_...` |
351
+ | Twilio / SendGrid / Mailgun | `SK...`, `SG...`, `key-...` |
352
+ | Hardcoded Bearer Token | `Bearer abc123...` |
353
+ | JWT-like Secret | `eyJ...` |
354
+ | Generic Secret Assignment | `password = '...'`, `api_key = '...'` |
355
+
356
+ False positive filtering:
357
+
358
+ - `process.env.*`, `import.meta.env.*`, `NEXT_PUBLIC_*`, `VITE_*` references are ignored
359
+ - GitHub Actions template variables (`${{ secrets.* }}`) are ignored
360
+ - `test/`, `tests/`, `__tests__/`, `spec/` directories are excluded
361
+ - Comment lines (`//`, `*`, `<!--`) are excluded - commented-out secrets are not flagged
362
+ - Placeholder/example values are ignored
363
+ - All secret values in findings are **masked with `***`** - never exposed in output
364
+
365
+ ## Test fixture
366
+
367
+ A sample Vite + React + TypeScript app is included at `fixtures/sample-app/` for testing all verification checks:
368
+
369
+ ```bash
370
+ cd fixtures/sample-app
371
+ npm install
372
+ npm run build
373
+ npx laxy-verify . --typecheck --secret-scan --bundle-size --outdated-check --skip-lighthouse
374
+ ```
375
+
376
+ See `fixtures/sample-app/README.md` for details on what each check finds in the fixture.
377
+
378
+ ## Result files
379
+
380
+ Every run writes `.laxy-result.json`.
381
+
382
+ When the run finds something worth reviewing, it also writes `laxy-verify-report.md`.
383
+
384
+ Typical use:
385
+
386
+ - `.laxy-result.json` for CI parsing and machine decisions
387
+ - `laxy-verify-report.md` for human review, PR discussion, or AI-assisted fixes
388
+
389
+ The markdown report is designed to be readable and easy to paste into coding tools.
390
+
391
+ It includes:
392
+
393
+ - the main stop-or-ship decision in plain English
394
+ - what passed
395
+ - blockers and warnings
396
+ - exact verification evidence
397
+ - failed scenarios
398
+ - a `Copy For AI` section
399
+
400
+ ## What this is good at
401
+
402
+ Use `laxy-verify` when you want:
403
+
404
+ - a merge or release gate for frontend apps
405
+ - one repeatable command for build plus audit plus visible-flow verification
406
+ - a decision that non-authors can understand
407
+ - JSON output for automation without building your own wrapper
408
+
409
+ ## What this is not
410
+
411
+ `laxy-verify` is not trying to replace:
412
+
413
+ - your full Playwright suite
414
+ - deep visual QA by designers
415
+ - production observability
416
+ - manual exploratory testing
417
+
418
+ It is a pre-merge and pre-release verification layer, not your entire quality system.
419
+
420
+ ## Limitations
421
+
422
+ - monorepos should target the real app subdirectory
423
+ - dev-server-based Lighthouse is not identical to production hosting
424
+ - visual diff and viewport checks increase runtime
425
+ - best stability is on current LTS Node releases
426
+
427
+ ## Requirements
428
+
429
+ - Node `>=20.18.0 <25`
430
+ - a frontend app with a runnable build flow
431
+ - optional: `playwright` if your project already uses it
432
+
433
+ ## Changelog
434
+
435
+ ### v1.3.1 - Publish fix
436
+
437
+ - Fix npm package contents so `login`, `logout`, and `whoami` ship with the required `dist/init-analysis.js` runtime dependency
438
+ - Republish the CLI artifact with the README badge, Pro history trend messaging, and Free-plan CLI tip aligned to the shipped code
439
+
440
+ ### v1.3.0 - Pro history trend, dynamic badge, CLI nudge
441
+
442
+ - **History trend tracking** - Pro accounts now store the last 30 verification runs. Grade and performance scores accumulate so you can see whether your app is improving or regressing over time
443
+ - **Dynamic README badge** - after each run, Pro accounts see a Markdown badge snippet in the CLI output. The badge auto-updates with every run via the `/api/badge/:id` endpoint
444
+ - **CLI nudge** - Free accounts see a one-line tip after each run pointing to the history trend feature
445
+ - Added `generateDynamicBadgeMarkdown(repoId, apiUrl)` export to the `badge` module
446
+ - Added `share_result` and `history_trend` flags to `EntitlementFeatures` interface
447
+ - 17 test files, 88 unit tests
448
+
449
+ ### v1.2.3 - Bug fix
450
+
451
+ - Fix E2E and visual diff connection failure on Windows with Node.js 17+: `verifyUrl` now uses `localhost` instead of `127.0.0.1`. On Windows, Vite binds to `::1` (IPv6) which does not accept IPv4 connections.
452
+
453
+ ### v1.2.2 - Opt-in verification checks
454
+
455
+ Added 7 opt-in checks (off by default, enable via CLI flags or `.laxy.yml`):
456
+
457
+ - `--typecheck` - TypeScript type error detection via `tsc --noEmit`
458
+ - `--secret-scan` - Hardcoded secret scanning with 11 regex patterns and `***` masking
459
+ - `--bundle-size` - Next.js/Vite bundle size analysis
460
+ - `--outdated-check` - Outdated dependency detection via `npm outdated`
461
+ - `--a11y-deep` - Deep WCAG audit via axe-core + Puppeteer
462
+ - `--seo-deep` - SEO meta/OG/JSON-LD audit
463
+ - `--vitals-budget` - Core Web Vitals budget enforcement (LCP, CLS, INP)
464
+
465
+ Other changes:
466
+
467
+ - Secret scan findings are **masked** - real credential values never appear in JSON, markdown, or console output
468
+ - Comment lines excluded from secret scanning to reduce false positives
469
+ - `test/`, `tests/`, `__tests__/`, `spec/` directories excluded from scanning
470
+ - `.laxy.yml` supports `secret_scan_ignore_paths` for custom exclusions
471
+ - Verification report includes all new checks in passes checklist and improvement recommendations
472
+ - Markdown report includes all new checks in the delivery evidence table
473
+ - Added `fixtures/sample-app/` test fixture (Vite + React + TypeScript)
474
+ - 17 test files, 88 unit tests
475
+
476
+ ## Links
477
+
478
+ - GitHub: https://github.com/SUNgm24/Laxy/tree/main/laxy-verify
479
+ - Issues: https://github.com/SUNgm24/Laxy/issues
package/dist/badge.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export declare function generateBadge(grade: string): string;
2
+ export declare function generateDynamicBadgeMarkdown(repoId: string, apiUrl: string): string;
package/dist/badge.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateBadge = generateBadge;
4
+ exports.generateDynamicBadgeMarkdown = generateDynamicBadgeMarkdown;
4
5
  function generateBadge(grade) {
5
6
  const gradeLower = grade.toLowerCase();
6
7
  const colors = {
@@ -12,3 +13,6 @@ function generateBadge(grade) {
12
13
  const color = colors[gradeLower] ?? "lightgrey";
13
14
  return `![Laxy Verify: ${grade}](https://img.shields.io/badge/laxy_verify-${gradeLower}-${color})`;
14
15
  }
16
+ function generateDynamicBadgeMarkdown(repoId, apiUrl) {
17
+ return `[![Laxy Verify](${apiUrl}/api/badge/${repoId})](${apiUrl})`;
18
+ }
package/dist/cli.js CHANGED
@@ -631,6 +631,8 @@ async function run() {
631
631
  parallel_execution: false,
632
632
  ai_failure_analysis: false,
633
633
  compare_env: false,
634
+ share_result: false,
635
+ history_trend: false,
634
636
  };
635
637
  let effectiveFeatures = features;
636
638
  if (args.planOverride) {
@@ -1172,13 +1174,13 @@ async function run() {
1172
1174
  writeResultFile(args.projectDir, resultObj);
1173
1175
  // Pro 이상: 결과를 서버에 저장 (배지, 공유 링크용)
1174
1176
  const token = (0, auth_js_1.loadToken)();
1177
+ const repoId = (0, auth_js_1.getOrCreateRepoId)(args.projectDir);
1175
1178
  const isPro = effectiveFeatures.plan === "pro" || effectiveFeatures.plan === "team";
1176
1179
  if (args.share && (!token || !isPro)) {
1177
1180
  console.warn(" [warn] --share requires a logged-in Pro or Team account.");
1178
1181
  }
1179
1182
  if (token && isPro) {
1180
1183
  try {
1181
- const repoId = (0, auth_js_1.getOrCreateRepoId)(args.projectDir);
1182
1184
  const { LAXY_API_URL } = await Promise.resolve().then(() => __importStar(require("./auth.js")));
1183
1185
  const saveRes = await fetch(`${LAXY_API_URL}/api/v1/cli-results`, {
1184
1186
  method: "POST",
@@ -1273,6 +1275,16 @@ async function run() {
1273
1275
  }
1274
1276
  else {
1275
1277
  consoleOutput(resultObj);
1278
+ if (effectiveFeatures.share_result) {
1279
+ const { LAXY_API_URL } = await Promise.resolve().then(() => __importStar(require("./auth.js")));
1280
+ const { generateDynamicBadgeMarkdown } = await Promise.resolve().then(() => __importStar(require("./badge.js")));
1281
+ console.log(`\n Badge (auto-updates with each run):`);
1282
+ console.log(` ${generateDynamicBadgeMarkdown(repoId, LAXY_API_URL)}`);
1283
+ }
1284
+ if (!effectiveFeatures.history_trend) {
1285
+ console.log(`\n Tip: Pro tracks your last 30 runs so you can see if Performance or Grade is improving.`);
1286
+ console.log(` https://laxy.app/pricing`);
1287
+ }
1276
1288
  }
1277
1289
  if (inGitHubActions && process.env.GITHUB_OUTPUT) {
1278
1290
  fs.appendFileSync(process.env.GITHUB_OUTPUT, `grade=${resultObj.grade}\n`);
@@ -5,6 +5,8 @@ export interface EntitlementFeatures {
5
5
  parallel_execution: boolean;
6
6
  ai_failure_analysis: boolean;
7
7
  compare_env: boolean;
8
+ share_result: boolean;
9
+ history_trend: boolean;
8
10
  }
9
11
  export type TestablePlan = "free" | "pro" | "team";
10
12
  export declare function normalizePlan(plan?: string | null): TestablePlan;
@@ -20,6 +20,8 @@ const FREE_FEATURES = {
20
20
  parallel_execution: false,
21
21
  ai_failure_analysis: false,
22
22
  compare_env: false,
23
+ share_result: false,
24
+ history_trend: false,
23
25
  };
24
26
  let cache = null;
25
27
  const CACHE_TTL_MS = 5 * 60 * 1000;
@@ -76,6 +78,8 @@ function applyPlanOverride(features, overridePlan) {
76
78
  github_actions: isPro,
77
79
  ai_failure_analysis: isPro,
78
80
  compare_env: isPro,
81
+ share_result: isPro,
82
+ history_trend: isPro,
79
83
  // queue_priority, parallel_execution — Team only
80
84
  queue_priority: isTeam,
81
85
  parallel_execution: isTeam,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "laxy-verify",
3
- "version": "1.2.3",
3
+ "version": "1.3.1",
4
4
  "description": "Frontend verification CLI for build checks, Lighthouse, E2E, and release readiness",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",