prodlint 0.10.3 → 0.10.4

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
@@ -13,7 +13,7 @@ npx prodlint
13
13
  ```
14
14
 
15
15
  ```
16
- prodlint v0.10.3
16
+ prodlint v0.10.4
17
17
  Scanned 148 files · 2 critical · 5 warnings · 1 info
18
18
 
19
19
  src/app/api/checkout/route.ts
@@ -145,7 +145,7 @@ npm i -g prodlint # Global install
145
145
 
146
146
  prodlint avoids common false positives:
147
147
 
148
- - **AST parsing** — Babel-based analysis for 12 rules (imports, catch blocks, redirects, SSRF, path traversal, JWT, HTML injection, hydration, transactions, env leaks, loops, SQL) with regex fallback
148
+ - **AST parsing** — Babel-based analysis for 13 rules (imports, catch blocks, redirects, redirects in try/catch, SSRF, path traversal, JWT, HTML injection, hydration, transactions, env leaks, loops, SQL) with regex fallback
149
149
  - **Monorepo support** — npm/yarn/pnpm workspace dependencies resolved automatically
150
150
  - **Framework awareness** — Prisma, Drizzle, Supabase, Knex, and Sequelize whitelists prevent false SQL injection flags
151
151
  - **Middleware detection** — Clerk, NextAuth, Supabase middleware detected — auth findings downgraded
@@ -187,14 +187,16 @@ jobs:
187
187
  threshold: 50
188
188
  ```
189
189
 
190
- Posts a score breakdown as a PR comment and fails the build if below threshold. Each
191
- release of the action runs its matching prodlint version, so pinning the action (`@v1`,
192
- a version tag, or a commit SHA) also pins the scanner.
190
+ Posts a score breakdown as a PR comment, and fails the build when the scan finds critical
191
+ issues or the score is below `threshold`. Each release of the action runs its matching
192
+ prodlint version, so pinning the action (`@v1`, a version tag, or a commit SHA) also pins
193
+ the scanner.
193
194
 
194
195
  | Input | Default | Description |
195
196
  |-------|---------|-------------|
196
197
  | `path` | `.` | Path to scan |
197
198
  | `threshold` | `0` | Minimum score to pass (0-100) |
199
+ | `fail-on-critical` | `true` | Fail when the scan finds critical issues; `false` reports them without failing |
198
200
  | `ignore` | | Comma-separated glob patterns to ignore |
199
201
  | `comment` | `true` | Post PR comment with results |
200
202
 
@@ -236,7 +238,7 @@ Use prodlint inside Cursor, Claude Code, or any MCP-compatible editor:
236
238
 
237
239
  **Claude Code:**
238
240
  ```bash
239
- claude mcp add prodlint -- npx -y -p prodlint prodlint-mcp
241
+ claude mcp add prodlint -- npx -y prodlint-mcp
240
242
  ```
241
243
 
242
244
  **Cursor / Windsurf:**
@@ -245,17 +247,26 @@ claude mcp add prodlint -- npx -y -p prodlint prodlint-mcp
245
247
  "mcpServers": {
246
248
  "prodlint": {
247
249
  "command": "npx",
248
- "args": ["-y", "-p", "prodlint", "prodlint-mcp"]
250
+ "args": ["-y", "prodlint-mcp"]
249
251
  }
250
252
  }
251
253
  }
252
254
  ```
253
255
 
254
- `-p prodlint` runs the MCP server straight from the `prodlint` package, so you always get
255
- the current scanner.
256
+ `prodlint-mcp` is a thin launcher for the server built into `prodlint`. It's published with
257
+ every prodlint release, so it always runs the matching scanner.
256
258
 
257
259
  Ask your AI: *"Run prodlint on this project"* and it calls the `scan` tool directly.
258
260
 
261
+ | Tool | Inputs | Returns |
262
+ |------|--------|---------|
263
+ | `scan` | `path` (project directory), optional `ignore`, `minSeverity` (`critical` / `warning` / `info`), `categories`, `maxFindings` (default 30) | Score, category scores, and findings most severe first. Every critical finding is listed, even past `maxFindings`. |
264
+ | `scan-web` | `url` | Site score, grade, and the 14 agent-readiness checks |
265
+
266
+ Both tools return a Markdown summary plus structured output (`structuredContent` matching
267
+ each tool's `outputSchema`), and both are marked read-only (`readOnlyHint`), which hosted
268
+ reviewers such as GitHub Copilot code review require before they call an MCP tool.
269
+
259
270
  ## Site Score
260
271
 
261
272
  Check any deployed website for AI agent-readiness — 14 checks covering emerging standards like llms.txt, TDMRep, AgentCard, AI-Disclosure, HTTP Signatures (RFC 9421), and more.
package/action.yml CHANGED
@@ -13,6 +13,10 @@ inputs:
13
13
  description: 'Minimum score to pass (0-100). Fails the check if score is below this.'
14
14
  required: false
15
15
  default: '0'
16
+ fail-on-critical:
17
+ description: 'Fail the check when the scan finds critical issues (true/false)'
18
+ required: false
19
+ default: 'true'
16
20
  ignore:
17
21
  description: 'Glob patterns to ignore (comma-separated)'
18
22
  required: false
@@ -58,49 +62,33 @@ runs:
58
62
 
59
63
  # The exact release this action ships with (scripts/sync-versions.cjs bumps it), so
60
64
  # pinning the action — @v1, a version tag or a commit SHA — also pins the scanner.
61
- OUTPUT=$(npx -y prodlint@0.10.3 "${CMD_ARGS[@]}" 2>&1) || true
62
-
63
- SCORE=$(echo "$OUTPUT" | node -e "
64
- const d = JSON.parse(require('fs').readFileSync(0, 'utf8'));
65
- console.log(Number(d.overallScore) || 0);
66
- " 2>/dev/null || echo "0")
67
- SCORE=$(echo "$SCORE" | tr -cd '0-9')
68
-
69
- CRITICAL=$(echo "$OUTPUT" | node -e "
70
- const d = JSON.parse(require('fs').readFileSync(0, 'utf8'));
71
- console.log(Number(d.summary.critical) || 0);
72
- " 2>/dev/null || echo "0")
73
- CRITICAL=$(echo "$CRITICAL" | tr -cd '0-9')
74
-
75
- echo "score=${SCORE:-0}" >> "$GITHUB_OUTPUT"
76
- echo "critical=${CRITICAL:-0}" >> "$GITHUB_OUTPUT"
77
- echo "$OUTPUT" > "$RUNNER_TEMP/prodlint-result.json"
65
+ # It exits 1 when it finds criticals and 2 when the scan fails; "Check results" decides.
66
+ EXIT_CODE=0
67
+ npx -y prodlint@0.10.4 "${CMD_ARGS[@]}" > "$RUNNER_TEMP/prodlint-result.json" || EXIT_CODE=$?
68
+ echo "exit-code=$EXIT_CODE" >> "$GITHUB_OUTPUT"
69
+ node "$GITHUB_ACTION_PATH/scripts/action-check.cjs" outputs "$RUNNER_TEMP/prodlint-result.json" >> "$GITHUB_OUTPUT"
78
70
 
79
71
  # Built by a script file rather than inline `node -e`: the comment carries file paths
80
72
  # and messages from the scanned repo, and the script's escaping is unit-tested.
81
73
  - name: Generate comment body
82
- if: inputs.comment == 'true' && github.event_name == 'pull_request'
74
+ if: inputs.comment == 'true' && github.event_name == 'pull_request' && steps.scan.outputs.scanned == 'true'
83
75
  id: comment
84
76
  shell: bash
85
77
  run: node "$GITHUB_ACTION_PATH/scripts/action-comment.cjs" "$RUNNER_TEMP/prodlint-result.json" "$RUNNER_TEMP/prodlint-comment.md"
86
78
 
87
79
  - name: Post PR comment
88
- if: inputs.comment == 'true' && github.event_name == 'pull_request'
80
+ if: inputs.comment == 'true' && github.event_name == 'pull_request' && steps.scan.outputs.scanned == 'true'
89
81
  uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
90
82
  with:
91
83
  header: prodlint
92
84
  path: ${{ runner.temp }}/prodlint-comment.md
93
85
 
94
- - name: Check threshold
95
- if: inputs.threshold != '0'
86
+ # Fails on critical findings (unless fail-on-critical is false), on a score below
87
+ # threshold, and when the scan didn't produce a result.
88
+ - name: Check results
96
89
  shell: bash
97
90
  env:
98
- SCAN_SCORE: ${{ steps.scan.outputs.score }}
91
+ SCAN_EXIT_CODE: ${{ steps.scan.outputs.exit-code }}
99
92
  INPUT_THRESHOLD: ${{ inputs.threshold }}
100
- run: |
101
- SCORE="$SCAN_SCORE"
102
- THRESHOLD="$INPUT_THRESHOLD"
103
- if [ "$SCORE" -lt "$THRESHOLD" ]; then
104
- echo "::error::Prodlint score ($SCORE) is below threshold ($THRESHOLD)"
105
- exit 1
106
- fi
93
+ INPUT_FAIL_ON_CRITICAL: ${{ inputs.fail-on-critical }}
94
+ run: node "$GITHUB_ACTION_PATH/scripts/action-check.cjs" check "$RUNNER_TEMP/prodlint-result.json"