prodlint 0.3.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,22 +4,26 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/prodlint.svg)](https://www.npmjs.com/package/prodlint)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
- Catch the bugs AI leaves behind.
7
+ The linter for vibe-coded apps.
8
8
 
9
- prodlint scans AI-generated JavaScript and TypeScript projects for production readiness issues — hallucinated imports, missing auth, exposed secrets, N+1 queries, and more. No LLM required, just pattern matching against known failure modes.
9
+ Cursor, v0, Bolt, and Copilot build fast. prodlint catches what they miss — hallucinated imports, missing auth, hardcoded secrets, unvalidated server actions, and the other production bugs that compile just fine. Zero config, no LLM, fast static analysis.
10
10
 
11
11
  ```bash
12
12
  npx prodlint
13
13
  ```
14
14
 
15
15
  ```
16
- prodlint v0.3.0
17
- Scanned 148 files in 92ms
16
+ prodlint v0.6.0
17
+ Scanned 148 files · 3 critical · 5 warnings
18
18
 
19
19
  src/app/api/checkout/route.ts
20
20
  12:1 CRIT No rate limiting — anyone could spam this endpoint and run up your API costs rate-limiting
21
21
  28:5 WARN Empty catch block silently swallows error shallow-catch
22
22
 
23
+ src/actions/submit.ts
24
+ 5:3 CRIT Server action uses formData without validation next-server-action-validation
25
+ ↳ Validate with Zod: const data = schema.safeParse(Object.fromEntries(formData))
26
+
23
27
  src/lib/db.ts
24
28
  1:1 CRIT Package "drizzle-orm" is imported but not in package.json hallucinated-imports
25
29
 
@@ -29,24 +33,26 @@ npx prodlint
29
33
  performance 95 ███████████████████░ (1 issue)
30
34
  ai-quality 90 ██████████████████░░ (3 issues)
31
35
 
32
- Overall: 85/100
36
+ Overall: 82/100 (weighted)
33
37
 
34
- 8 critical · 5 warnings · 3 info
38
+ 3 critical · 5 warnings · 3 info
35
39
  ```
36
40
 
37
41
  ## Why?
38
42
 
39
- AI code generators (Cursor, Copilot, v0, Bolt, Claude) write code that works in demos but breaks in production. Hardcoded secrets, hallucinated packages, missing auth, XSS vectors these pass type-checks and look correct but aren't.
43
+ Vibe coding is the fastest way to build. It's also the fastest way to ship hardcoded secrets, hallucinated packages, missing auth, and XSS vectors to production. These pass type-checks and look correct but they aren't.
40
44
 
41
- prodlint catches what TypeScript and ESLint miss: **production readiness gaps**.
45
+ prodlint catches what TypeScript and ESLint miss: **the bugs AI coding tools consistently write**.
42
46
 
43
47
  ## Install
44
48
 
45
49
  ```bash
46
- npx prodlint # Run directly (no install)
47
- npx prodlint ./my-app # Scan specific path
48
- npx prodlint --json # JSON output for CI
49
- npx prodlint --ignore "*.test.ts" # Ignore patterns
50
+ npx prodlint # Run directly (no install)
51
+ npx prodlint ./my-app # Scan specific path
52
+ npx prodlint --json # JSON output for CI
53
+ npx prodlint --ignore "*.test.ts" # Ignore patterns
54
+ npx prodlint --min-severity warning # Only warnings and criticals
55
+ npx prodlint --quiet # Suppress badge output
50
56
  ```
51
57
 
52
58
  Or install it:
@@ -56,9 +62,9 @@ npm i -D prodlint # Project dependency
56
62
  npm i -g prodlint # Global install
57
63
  ```
58
64
 
59
- ## 27 Rules across 4 Categories
65
+ ## 52 Rules across 4 Categories
60
66
 
61
- ### Security (10 rules)
67
+ ### Security (27 rules)
62
68
 
63
69
  | Rule | What it catches |
64
70
  |------|----------------|
@@ -68,12 +74,29 @@ npm i -g prodlint # Global install
68
74
  | `input-validation` | Request body used without validation |
69
75
  | `cors-config` | `Access-Control-Allow-Origin: *` |
70
76
  | `unsafe-html` | `dangerouslySetInnerHTML` with user data |
71
- | `sql-injection` | String-interpolated SQL queries |
77
+ | `sql-injection` | String-interpolated SQL queries (ORM-aware) |
72
78
  | `open-redirect` | User input passed to `redirect()` |
73
79
  | `rate-limiting` | API routes with no rate limiter |
74
80
  | `phantom-dependency` | Packages in node_modules but missing from package.json |
75
-
76
- ### Reliability (6 rules)
81
+ | `insecure-cookie` | Session cookies missing httpOnly/secure/sameSite |
82
+ | `leaked-env-in-logs` | `process.env.*` inside console.log calls |
83
+ | `insecure-random` | `Math.random()` used for tokens, secrets, or session IDs |
84
+ | `next-server-action-validation` | Server actions using formData without Zod/schema validation |
85
+ | `env-fallback-secret` | Security-sensitive env vars with hardcoded fallback values |
86
+ | `verbose-error-response` | Error stack traces or messages leaked in API responses |
87
+ | `missing-webhook-verification` | Webhook routes without signature verification |
88
+ | `server-action-auth` | Server actions with mutations but no auth check |
89
+ | `eval-injection` | `eval()`, `new Function()`, dynamic code execution |
90
+ | `next-public-sensitive` | `NEXT_PUBLIC_` prefix on secret env vars |
91
+ | `ssrf-risk` | User-controlled URLs passed to fetch in server code |
92
+ | `path-traversal` | File system operations with unsanitized user input |
93
+ | `unsafe-file-upload` | File upload handlers without type or size validation |
94
+ | `supabase-missing-rls` | `CREATE TABLE` in migrations without enabling RLS |
95
+ | `deprecated-oauth-flow` | OAuth Implicit Grant (response_type=token) |
96
+ | `jwt-no-expiry` | JWT tokens signed without an expiration |
97
+ | `client-side-auth-only` | Password comparisons or auth logic in client components |
98
+
99
+ ### Reliability (11 rules)
77
100
 
78
101
  | Rule | What it catches |
79
102
  |------|----------------|
@@ -83,8 +106,13 @@ npm i -g prodlint # Global install
83
106
  | `shallow-catch` | Empty catch blocks that swallow errors |
84
107
  | `missing-loading-state` | Client components that fetch without a loading state |
85
108
  | `missing-error-boundary` | Route layouts without a matching error.tsx |
109
+ | `missing-transaction` | Multiple Prisma writes without `$transaction` |
110
+ | `redirect-in-try-catch` | `redirect()` inside try/catch — Next.js redirect throws, catch swallows it |
111
+ | `missing-revalidation` | Server actions with DB mutations but no `revalidatePath` |
112
+ | `missing-useeffect-cleanup` | useEffect with subscriptions/timers but no cleanup return |
113
+ | `hydration-mismatch` | `window`/`Date.now()`/`Math.random()` in server component render path |
86
114
 
87
- ### Performance (4 rules)
115
+ ### Performance (6 rules)
88
116
 
89
117
  | Rule | What it catches |
90
118
  |------|----------------|
@@ -92,8 +120,10 @@ npm i -g prodlint # Global install
92
120
  | `no-n-plus-one` | Database calls inside loops |
93
121
  | `no-unbounded-query` | `.findMany()` / `.select('*')` with no limit |
94
122
  | `no-dynamic-import-loop` | `import()` inside loops |
123
+ | `server-component-fetch-self` | Server components fetching their own API routes |
124
+ | `missing-abort-controller` | Fetch calls without timeout or AbortController |
95
125
 
96
- ### AI Quality (7 rules)
126
+ ### AI Quality (8 rules)
97
127
 
98
128
  | Rule | What it catches |
99
129
  |------|----------------|
@@ -104,28 +134,34 @@ npm i -g prodlint # Global install
104
134
  | `comprehension-debt` | Functions over 80 lines, deep nesting, too many parameters |
105
135
  | `codebase-consistency` | Mixed naming conventions across the project |
106
136
  | `dead-exports` | Exported functions that nothing imports |
137
+ | `use-client-overuse` | `"use client"` on files that don't use any client-side APIs |
107
138
 
108
139
  ## Smart Detection
109
140
 
110
141
  prodlint avoids common false positives:
111
142
 
143
+ - **AST parsing** — Babel-based analysis for loops, imports, and SQL templates with regex fallback
144
+ - **Framework awareness** — Prisma, Drizzle, Supabase, Knex, and Sequelize whitelists prevent false SQL injection flags
145
+ - **Middleware detection** — Clerk, NextAuth, Supabase middleware detected — auth findings downgraded
112
146
  - **Block comment awareness** — patterns inside `/* */` are ignored
113
- - **Middleware detection** — if your project uses Clerk/NextAuth/Supabase middleware, auth findings are downgraded
114
147
  - **Path alias support** — `@/`, `~/`, and tsconfig paths aren't flagged as hallucinated imports
115
148
  - **Route exemptions** — auth, webhook, health, and cron routes are exempt from auth/rate-limit checks
116
149
  - **Test/script file awareness** — lower severity for non-production files
150
+ - **Fix suggestions** — findings include actionable `fix` hints with remediation code
117
151
 
118
152
  ## Scoring
119
153
 
120
154
  Each category starts at 100. Deductions per finding:
121
155
 
122
- | Severity | Deduction |
123
- |----------|-----------|
124
- | critical | -10 |
125
- | warning | -3 |
126
- | info | -1 |
156
+ | Severity | Deduction | Per-rule cap |
157
+ |----------|-----------|--------------|
158
+ | critical | -8 | max 1 |
159
+ | warning | -2 | max 2 |
160
+ | info | -0.5 | max 3 |
161
+
162
+ **Diminishing returns**: after 30 points deducted in a category, further deductions are halved; after 50, quartered.
127
163
 
128
- Overall score = average of the 4 category scores (floor 0). Exit code `1` if any critical findings exist.
164
+ **Weighted overall**: security 40%, reliability 30%, performance 15%, ai-quality 15%. Floor at 0. Exit code `1` if any critical findings exist.
129
165
 
130
166
  ## GitHub Action
131
167
 
package/action.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: 'Prodlint'
2
- description: 'Scan AI-generated projects for production readiness issues'
2
+ description: 'The linter for vibe-coded apps catch what AI coding tools miss'
3
3
  branding:
4
4
  icon: 'shield'
5
5
  color: 'green'
@@ -24,7 +24,7 @@ inputs:
24
24
 
25
25
  outputs:
26
26
  score:
27
- description: 'Overall production readiness score (0-100)'
27
+ description: 'Overall prodlint score (0-100)'
28
28
  value: ${{ steps.scan.outputs.score }}
29
29
  critical:
30
30
  description: 'Number of critical findings'