@fourteensystems/shipguard 0.1.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 +213 -0
- package/bin/shipguard.mjs +2 -0
- package/dist/cli/commands/baseline.d.ts +7 -0
- package/dist/cli/commands/baseline.d.ts.map +1 -0
- package/dist/cli/commands/baseline.js +22 -0
- package/dist/cli/commands/baseline.js.map +1 -0
- package/dist/cli/commands/ci.d.ts +13 -0
- package/dist/cli/commands/ci.d.ts.map +1 -0
- package/dist/cli/commands/ci.js +91 -0
- package/dist/cli/commands/ci.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +2 -0
- package/dist/cli/commands/explain.d.ts.map +1 -0
- package/dist/cli/commands/explain.js +20 -0
- package/dist/cli/commands/explain.js.map +1 -0
- package/dist/cli/commands/init.d.ts +7 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +91 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/rules.d.ts +2 -0
- package/dist/cli/commands/rules.d.ts.map +1 -0
- package/dist/cli/commands/rules.js +13 -0
- package/dist/cli/commands/rules.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +10 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +55 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/waive.d.ts +8 -0
- package/dist/cli/commands/waive.d.ts.map +1 -0
- package/dist/cli/commands/waive.js +34 -0
- package/dist/cli/commands/waive.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +63 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/engine/baseline.d.ts +11 -0
- package/dist/engine/baseline.d.ts.map +1 -0
- package/dist/engine/baseline.js +39 -0
- package/dist/engine/baseline.js.map +1 -0
- package/dist/engine/config.d.ts +8 -0
- package/dist/engine/config.d.ts.map +1 -0
- package/dist/engine/config.js +130 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/extensions/load.d.ts +11 -0
- package/dist/engine/extensions/load.d.ts.map +1 -0
- package/dist/engine/extensions/load.js +26 -0
- package/dist/engine/extensions/load.js.map +1 -0
- package/dist/engine/extensions/registry.d.ts +5 -0
- package/dist/engine/extensions/registry.d.ts.map +1 -0
- package/dist/engine/extensions/registry.js +11 -0
- package/dist/engine/extensions/registry.js.map +1 -0
- package/dist/engine/extensions/types.d.ts +51 -0
- package/dist/engine/extensions/types.d.ts.map +1 -0
- package/dist/engine/extensions/types.js +2 -0
- package/dist/engine/extensions/types.js.map +1 -0
- package/dist/engine/report.d.ts +5 -0
- package/dist/engine/report.d.ts.map +1 -0
- package/dist/engine/report.js +88 -0
- package/dist/engine/report.js.map +1 -0
- package/dist/engine/run.d.ts +9 -0
- package/dist/engine/run.d.ts.map +1 -0
- package/dist/engine/run.js +101 -0
- package/dist/engine/run.js.map +1 -0
- package/dist/engine/sarif.d.ts +3 -0
- package/dist/engine/sarif.d.ts.map +1 -0
- package/dist/engine/sarif.js +58 -0
- package/dist/engine/sarif.js.map +1 -0
- package/dist/engine/score.d.ts +13 -0
- package/dist/engine/score.d.ts.map +1 -0
- package/dist/engine/score.js +97 -0
- package/dist/engine/score.js.map +1 -0
- package/dist/engine/types.d.ts +119 -0
- package/dist/engine/types.d.ts.map +1 -0
- package/dist/engine/types.js +2 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/engine/version.d.ts +5 -0
- package/dist/engine/version.d.ts.map +1 -0
- package/dist/engine/version.js +15 -0
- package/dist/engine/version.js.map +1 -0
- package/dist/engine/waivers.d.ts +9 -0
- package/dist/engine/waivers.d.ts.map +1 -0
- package/dist/engine/waivers.js +55 -0
- package/dist/engine/waivers.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/next/deps.d.ts +4 -0
- package/dist/next/deps.d.ts.map +1 -0
- package/dist/next/deps.js +102 -0
- package/dist/next/deps.js.map +1 -0
- package/dist/next/detect.d.ts +10 -0
- package/dist/next/detect.d.ts.map +1 -0
- package/dist/next/detect.js +57 -0
- package/dist/next/detect.js.map +1 -0
- package/dist/next/index.d.ts +5 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +41 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/middleware.d.ts +3 -0
- package/dist/next/middleware.d.ts.map +1 -0
- package/dist/next/middleware.js +33 -0
- package/dist/next/middleware.js.map +1 -0
- package/dist/next/routes.d.ts +5 -0
- package/dist/next/routes.d.ts.map +1 -0
- package/dist/next/routes.js +125 -0
- package/dist/next/routes.js.map +1 -0
- package/dist/next/server-actions.d.ts +4 -0
- package/dist/next/server-actions.d.ts.map +1 -0
- package/dist/next/server-actions.js +107 -0
- package/dist/next/server-actions.js.map +1 -0
- package/dist/next/trpc.d.ts +3 -0
- package/dist/next/trpc.d.ts.map +1 -0
- package/dist/next/trpc.js +339 -0
- package/dist/next/trpc.js.map +1 -0
- package/dist/next/types.d.ts +100 -0
- package/dist/next/types.d.ts.map +1 -0
- package/dist/next/types.js +2 -0
- package/dist/next/types.js.map +1 -0
- package/dist/rules/auth-boundary-missing.d.ts +5 -0
- package/dist/rules/auth-boundary-missing.d.ts.map +1 -0
- package/dist/rules/auth-boundary-missing.js +278 -0
- package/dist/rules/auth-boundary-missing.js.map +1 -0
- package/dist/rules/index.d.ts +12 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +41 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/rate-limit-missing.d.ts +5 -0
- package/dist/rules/rate-limit-missing.d.ts.map +1 -0
- package/dist/rules/rate-limit-missing.js +230 -0
- package/dist/rules/rate-limit-missing.js.map +1 -0
- package/dist/rules/tenancy-scope-missing.d.ts +5 -0
- package/dist/rules/tenancy-scope-missing.d.ts.map +1 -0
- package/dist/rules/tenancy-scope-missing.js +149 -0
- package/dist/rules/tenancy-scope-missing.js.map +1 -0
- package/dist/util/paths.d.ts +6 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +18 -0
- package/dist/util/paths.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Shipguard
|
|
2
|
+
|
|
3
|
+
CI guardrail that blocks unprotected mutation routes in Next.js SaaS.
|
|
4
|
+
|
|
5
|
+
Shipguard statically analyzes your Next.js App Router codebase and flags mutation endpoints missing auth boundaries, rate limiting, or tenant scoping. It understands your stack — Auth.js, Clerk, Supabase, tRPC, Prisma — and stays quiet when protections are in place.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx shipguard init
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Detects your framework and dependencies, generates a config, and runs your first scan.
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Shipguard 0.1.0
|
|
17
|
+
Detected: next-app-router · clerk · prisma · trpc · middleware
|
|
18
|
+
Score: 85 PASS
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Scan and print report
|
|
25
|
+
shipguard
|
|
26
|
+
|
|
27
|
+
# Only run specific rules
|
|
28
|
+
shipguard scan --only AUTH-BOUNDARY-MISSING,RATE-LIMIT-MISSING
|
|
29
|
+
|
|
30
|
+
# Exclude paths
|
|
31
|
+
shipguard scan --exclude "app/api/internal/**"
|
|
32
|
+
|
|
33
|
+
# JSON or SARIF output
|
|
34
|
+
shipguard scan --format json
|
|
35
|
+
shipguard scan --format sarif --output report.sarif
|
|
36
|
+
|
|
37
|
+
# CI mode (fail on critical findings)
|
|
38
|
+
shipguard ci --fail-on critical --min-confidence high
|
|
39
|
+
|
|
40
|
+
# Save baseline for regression detection
|
|
41
|
+
shipguard baseline --write
|
|
42
|
+
|
|
43
|
+
# Waive a finding
|
|
44
|
+
shipguard waive RATE-LIMIT-MISSING --file app/api/foo/route.ts --reason "Handled by Cloudflare WAF"
|
|
45
|
+
|
|
46
|
+
# List rules
|
|
47
|
+
shipguard rules
|
|
48
|
+
|
|
49
|
+
# Explain a rule
|
|
50
|
+
shipguard explain AUTH-BOUNDARY-MISSING
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## What It Detects
|
|
54
|
+
|
|
55
|
+
### Rules
|
|
56
|
+
|
|
57
|
+
| Rule | Severity | What it catches |
|
|
58
|
+
|------|----------|----------------|
|
|
59
|
+
| AUTH-BOUNDARY-MISSING | critical | Mutation endpoints without auth checks |
|
|
60
|
+
| RATE-LIMIT-MISSING | critical | Public API routes without rate limiting |
|
|
61
|
+
| TENANCY-SCOPE-MISSING | critical | Prisma queries without tenant scoping |
|
|
62
|
+
|
|
63
|
+
### Stack Support
|
|
64
|
+
|
|
65
|
+
Shipguard auto-detects your stack and adjusts detection accordingly:
|
|
66
|
+
|
|
67
|
+
| Stack | What Shipguard understands |
|
|
68
|
+
|-------|---------------------------|
|
|
69
|
+
| **Auth.js / NextAuth** | `auth()`, `getServerSession()`, `withAuth()`, middleware auth |
|
|
70
|
+
| **Clerk** | `auth()`, `currentUser()`, `clerkMiddleware()` |
|
|
71
|
+
| **Supabase** | `.auth.getUser()`, `.auth.getSession()` (call-based, not import-based) |
|
|
72
|
+
| **Kinde** | `getKindeServerSession()` |
|
|
73
|
+
| **WorkOS / AuthKit** | `withAuth()`, `getUser()`, `authkitMiddleware()` |
|
|
74
|
+
| **Better Auth** | `auth()` |
|
|
75
|
+
| **Lucia** | `validateRequest()`, `validateSession()` |
|
|
76
|
+
| **Auth0** | `getSession()`, `withApiAuthRequired()` |
|
|
77
|
+
| **iron-session** | `getIronSession()` |
|
|
78
|
+
| **Firebase Auth** | `verifyIdToken()`, `getTokens()`, `verifySessionCookie()` |
|
|
79
|
+
| **tRPC** | `protectedProcedure` vs `publicProcedure`, `.mutation()` surfaces |
|
|
80
|
+
| **Prisma** | `.create()`, `.update()`, `.delete()` as mutation evidence, tenant scoping |
|
|
81
|
+
| **Drizzle** | Detected but gracefully degraded (tenancy rule skips) |
|
|
82
|
+
| **Upstash** | `Ratelimit`, `ratelimit.limit()` as rate-limit evidence |
|
|
83
|
+
| **Arcjet** | `fixedWindow()`, `slidingWindow()`, `tokenBucket()` |
|
|
84
|
+
| **Unkey** | `withUnkey()`, `verifyKey()` |
|
|
85
|
+
|
|
86
|
+
### What It Skips
|
|
87
|
+
|
|
88
|
+
- Webhook routes (`/api/webhooks/*`) — exempt from rate-limit
|
|
89
|
+
- Cron routes (`/api/cron/*`) — exempt from rate-limit
|
|
90
|
+
- `GET`-only route handlers — not mutation surfaces
|
|
91
|
+
- Routes covered by `middleware.ts` auth — no double-flagging
|
|
92
|
+
- HOF-wrapped handlers (`withAuth(handler)`) — detected as auth boundary
|
|
93
|
+
|
|
94
|
+
See [PATTERNS.md](PATTERNS.md) for full detection logic.
|
|
95
|
+
|
|
96
|
+
## GitHub Action
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
name: Shipguard
|
|
100
|
+
on: [pull_request]
|
|
101
|
+
|
|
102
|
+
permissions:
|
|
103
|
+
contents: read
|
|
104
|
+
pull-requests: write
|
|
105
|
+
|
|
106
|
+
jobs:
|
|
107
|
+
shipguard:
|
|
108
|
+
runs-on: ubuntu-latest
|
|
109
|
+
steps:
|
|
110
|
+
- uses: actions/checkout@v4
|
|
111
|
+
- uses: actions/setup-node@v4
|
|
112
|
+
with:
|
|
113
|
+
node-version: 20
|
|
114
|
+
- run: npm ci
|
|
115
|
+
- uses: shipguard/action@v1
|
|
116
|
+
env:
|
|
117
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
118
|
+
with:
|
|
119
|
+
min-score: 70
|
|
120
|
+
fail-on: critical
|
|
121
|
+
min-confidence: high
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The action:
|
|
125
|
+
- Comments on PRs with findings, score, and detected stack
|
|
126
|
+
- Adds inline annotations on flagged files
|
|
127
|
+
- Shows score delta when a baseline is provided
|
|
128
|
+
- Updates the same comment on re-runs (no spam)
|
|
129
|
+
|
|
130
|
+
### Action Inputs
|
|
131
|
+
|
|
132
|
+
| Input | Default | Description |
|
|
133
|
+
|-------|---------|-------------|
|
|
134
|
+
| `fail-on` | `critical` | Minimum severity to fail the check |
|
|
135
|
+
| `min-confidence` | `high` | Minimum confidence to include |
|
|
136
|
+
| `min-score` | `70` | Minimum passing score |
|
|
137
|
+
| `baseline` | — | Path to baseline file for regression detection |
|
|
138
|
+
| `max-new-critical` | `0` | Max new critical findings allowed |
|
|
139
|
+
| `max-new-high` | — | Max new high findings allowed |
|
|
140
|
+
| `comment` | `true` | Post a PR comment with findings |
|
|
141
|
+
| `annotations` | `true` | Add inline file annotations |
|
|
142
|
+
|
|
143
|
+
### Action Outputs
|
|
144
|
+
|
|
145
|
+
| Output | Description |
|
|
146
|
+
|--------|-------------|
|
|
147
|
+
| `score` | Shipguard score (0-100) |
|
|
148
|
+
| `findings` | Total number of findings |
|
|
149
|
+
| `result` | `PASS`, `WARN`, or `FAIL` |
|
|
150
|
+
|
|
151
|
+
## Configuration
|
|
152
|
+
|
|
153
|
+
Most teams do not need to configure Shipguard. Run `shipguard init` and commit the generated config.
|
|
154
|
+
|
|
155
|
+
For advanced use cases, create `shipguard.config.json`:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"framework": "next-app-router",
|
|
160
|
+
"include": ["app/**", "src/**"],
|
|
161
|
+
"exclude": ["**/*.test.*", "**/*.spec.*"],
|
|
162
|
+
"ci": {
|
|
163
|
+
"failOn": "critical",
|
|
164
|
+
"minConfidence": "high",
|
|
165
|
+
"minScore": 70,
|
|
166
|
+
"maxNewCritical": 0
|
|
167
|
+
},
|
|
168
|
+
"hints": {
|
|
169
|
+
"auth": {
|
|
170
|
+
"functions": ["auth", "getServerSession", "currentUser"],
|
|
171
|
+
"middlewareFiles": ["middleware.ts"],
|
|
172
|
+
"allowlistPaths": ["app/api/public/**"]
|
|
173
|
+
},
|
|
174
|
+
"rateLimit": {
|
|
175
|
+
"wrappers": ["rateLimit", "withRateLimit"],
|
|
176
|
+
"allowlistPaths": ["app/api/webhooks/**"]
|
|
177
|
+
},
|
|
178
|
+
"tenancy": {
|
|
179
|
+
"orgFieldNames": ["orgId", "tenantId", "workspaceId"]
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Hints
|
|
186
|
+
|
|
187
|
+
Hints tell Shipguard about your codebase-specific patterns. If you use a custom auth wrapper like `requireAuth()` or a rate limiting function like `withRateLimit()`, add it to hints so Shipguard recognizes it and doesn't flag protected routes.
|
|
188
|
+
|
|
189
|
+
Most built-in patterns (Auth.js, Clerk, Supabase, Kinde, WorkOS, Lucia, Auth0, Firebase, tRPC, Upstash, Arcjet, Unkey) are detected automatically — hints are for your custom wrappers.
|
|
190
|
+
|
|
191
|
+
## Confidence Levels
|
|
192
|
+
|
|
193
|
+
Every finding has a confidence level:
|
|
194
|
+
|
|
195
|
+
- **high** — strong evidence (e.g., `publicProcedure.mutation()` with `prisma.create`)
|
|
196
|
+
- **med** — likely but uncertain (e.g., unrecognized procedure type)
|
|
197
|
+
- **low** — possible issue, may be false positive
|
|
198
|
+
|
|
199
|
+
Use `--min-confidence` in CI to control noise:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
shipguard ci --min-confidence high
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Compatibility
|
|
206
|
+
|
|
207
|
+
Shipguard has no runtime dependency on Next.js, but it tracks evolving ecosystem patterns. Updates primarily add new detectors and improve confidence — not compatibility fixes.
|
|
208
|
+
|
|
209
|
+
Requires Next.js App Router (13.4+). Pages Router is not supported.
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseline.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/baseline.ts"],"names":[],"mappings":"AAIA,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBtE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { runScan } from "../../engine/run.js";
|
|
3
|
+
import { writeBaseline } from "../../engine/baseline.js";
|
|
4
|
+
export async function cmdBaseline(opts) {
|
|
5
|
+
if (!opts.write) {
|
|
6
|
+
console.log(pc.dim(" Use --write to save a baseline snapshot."));
|
|
7
|
+
console.log(pc.dim(" Example: shipguard baseline --write"));
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const rootDir = process.cwd();
|
|
12
|
+
const result = await runScan({ rootDir });
|
|
13
|
+
const dest = writeBaseline(rootDir, result, opts.output);
|
|
14
|
+
console.log(pc.green(` Baseline written to ${dest}`));
|
|
15
|
+
console.log(pc.dim(` Score: ${result.score} | Findings: ${result.findings.length}`));
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
console.error(pc.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../../src/cli/commands/baseline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAOzD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAqB;IACrD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAEzD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,gBAAgB,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACxF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface CiOptions {
|
|
2
|
+
failOn: string;
|
|
3
|
+
minConfidence: string;
|
|
4
|
+
minScore: string;
|
|
5
|
+
baseline?: string;
|
|
6
|
+
maxNewCritical: string;
|
|
7
|
+
maxNewHigh?: string;
|
|
8
|
+
format: string;
|
|
9
|
+
output?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function cmdCi(opts: CiOptions): Promise<void>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=ci.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ci.ts"],"names":[],"mappings":"AAQA,UAAU,SAAS;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAiG1D"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
import { runScan } from "../../engine/run.js";
|
|
4
|
+
import { formatPretty, formatJson } from "../../engine/report.js";
|
|
5
|
+
import { formatSarif } from "../../engine/sarif.js";
|
|
6
|
+
import { loadBaseline, diffBaseline } from "../../engine/baseline.js";
|
|
7
|
+
import { confidenceLevel, severityLevel, parseConfidence, parseSeverity, parseIntOrThrow } from "../../engine/score.js";
|
|
8
|
+
export async function cmdCi(opts) {
|
|
9
|
+
try {
|
|
10
|
+
const rootDir = process.cwd();
|
|
11
|
+
const result = await runScan({ rootDir });
|
|
12
|
+
const minConf = parseConfidence(opts.minConfidence ?? "high");
|
|
13
|
+
const failOnSeverity = parseSeverity(opts.failOn ?? "critical");
|
|
14
|
+
const minScore = parseIntOrThrow(opts.minScore ?? "70", "min-score");
|
|
15
|
+
const maxNewCritical = parseIntOrThrow(opts.maxNewCritical ?? "0", "max-new-critical");
|
|
16
|
+
const maxNewHigh = opts.maxNewHigh !== undefined ? parseIntOrThrow(opts.maxNewHigh, "max-new-high") : undefined;
|
|
17
|
+
// Filter findings by confidence for failure evaluation
|
|
18
|
+
const gatedFindings = result.findings.filter((f) => confidenceLevel(f.confidence) >= confidenceLevel(minConf));
|
|
19
|
+
// Check baseline
|
|
20
|
+
let diff;
|
|
21
|
+
if (opts.baseline) {
|
|
22
|
+
const baseline = loadBaseline(opts.baseline);
|
|
23
|
+
if (baseline) {
|
|
24
|
+
diff = diffBaseline(baseline, result);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Output report
|
|
28
|
+
let output;
|
|
29
|
+
switch (opts.format) {
|
|
30
|
+
case "json":
|
|
31
|
+
output = formatJson(result);
|
|
32
|
+
break;
|
|
33
|
+
case "sarif":
|
|
34
|
+
output = formatSarif(result);
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
output = formatPretty(result, diff);
|
|
38
|
+
}
|
|
39
|
+
if (opts.output) {
|
|
40
|
+
writeFileSync(opts.output, output);
|
|
41
|
+
}
|
|
42
|
+
console.log(output);
|
|
43
|
+
// Evaluate gates
|
|
44
|
+
const failures = [];
|
|
45
|
+
// Score gate
|
|
46
|
+
if (result.score < minScore) {
|
|
47
|
+
failures.push(`Score ${result.score} is below minimum ${minScore}`);
|
|
48
|
+
}
|
|
49
|
+
// Severity gate: any findings at or above fail-on severity with sufficient confidence
|
|
50
|
+
const failingSeverities = gatedFindings.filter((f) => severityLevel(f.severity) >= severityLevel(failOnSeverity));
|
|
51
|
+
if (failingSeverities.length > 0) {
|
|
52
|
+
failures.push(`${failingSeverities.length} finding(s) at ${failOnSeverity} or above (${minConf}+ confidence)`);
|
|
53
|
+
}
|
|
54
|
+
// New findings gate (baseline)
|
|
55
|
+
if (diff) {
|
|
56
|
+
const newCritical = diff.newFindings.filter((f) => f.severity === "critical").length;
|
|
57
|
+
const newHigh = diff.newFindings.filter((f) => f.severity === "high").length;
|
|
58
|
+
if (newCritical > maxNewCritical) {
|
|
59
|
+
failures.push(`${newCritical} new critical finding(s) exceeds max ${maxNewCritical}`);
|
|
60
|
+
}
|
|
61
|
+
if (maxNewHigh !== undefined && newHigh > maxNewHigh) {
|
|
62
|
+
failures.push(`${newHigh} new high finding(s) exceeds max ${maxNewHigh}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (failures.length > 0) {
|
|
66
|
+
console.log(pc.red("\n CI FAILED:"));
|
|
67
|
+
for (const f of failures) {
|
|
68
|
+
console.log(pc.red(` - ${f}`));
|
|
69
|
+
}
|
|
70
|
+
// Show specific rule IDs + files that triggered the failure
|
|
71
|
+
if (failingSeverities.length > 0) {
|
|
72
|
+
console.log("");
|
|
73
|
+
console.log(pc.dim(" Failing findings:"));
|
|
74
|
+
for (const f of failingSeverities) {
|
|
75
|
+
const loc = f.line ? `:${f.line}` : "";
|
|
76
|
+
console.log(` ${pc.red(f.ruleId)} ${pc.dim(`(${f.severity})`)} ${pc.dim(f.file + loc)}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
console.log("");
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.log(pc.green("\n CI PASSED\n"));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
console.error(pc.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=ci.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../../../src/cli/commands/ci.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/explain.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB9D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { RULE_REGISTRY } from "../../rules/index.js";
|
|
3
|
+
export async function cmdExplain(ruleId) {
|
|
4
|
+
const rule = RULE_REGISTRY.find((r) => r.id === ruleId || r.id === ruleId.toUpperCase());
|
|
5
|
+
if (!rule) {
|
|
6
|
+
console.error(pc.red(` Unknown rule: ${ruleId}`));
|
|
7
|
+
console.error(pc.dim(` Run \`shipguard rules\` to see available rules.`));
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
console.log(`\n ${pc.bold(rule.id)}`);
|
|
11
|
+
console.log(` ${rule.name}`);
|
|
12
|
+
console.log(` Default severity: ${rule.defaultSeverity}`);
|
|
13
|
+
console.log("");
|
|
14
|
+
console.log(` ${rule.description}`);
|
|
15
|
+
console.log("");
|
|
16
|
+
console.log(` ${pc.dim("How it works:")}`);
|
|
17
|
+
console.log(` ${rule.docs}`);
|
|
18
|
+
console.log("");
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=explain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../../src/cli/commands/explain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc;IAC7C,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,CACxD,CAAC;IAEF,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA8E9D"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { findConfigFile, writeDefaultConfig } from "../../engine/config.js";
|
|
3
|
+
import { runScan } from "../../engine/run.js";
|
|
4
|
+
import { scoreStatus } from "../../engine/score.js";
|
|
5
|
+
import { readDeps } from "../../next/deps.js";
|
|
6
|
+
import { detectNextAppRouter } from "../../next/detect.js";
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
export async function cmdInit(opts) {
|
|
10
|
+
const rootDir = process.cwd();
|
|
11
|
+
// 1. Detect framework
|
|
12
|
+
const det = detectNextAppRouter(rootDir);
|
|
13
|
+
if (!det.ok) {
|
|
14
|
+
console.error(pc.red(`\n Shipguard v1 requires a Next.js App Router project.`));
|
|
15
|
+
console.error(pc.dim(` Reason: ${det.reason}`));
|
|
16
|
+
console.error(pc.dim(` Make sure you're in the project root with package.json and app/ directory.\n`));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
console.log(pc.green(" Detected Next.js App Router"));
|
|
20
|
+
// 2. Detect dependencies and print what we found
|
|
21
|
+
const deps = readDeps(rootDir);
|
|
22
|
+
const detected = ["next-app-router"];
|
|
23
|
+
if (deps.hasNextAuth)
|
|
24
|
+
detected.push("next-auth");
|
|
25
|
+
if (deps.hasClerk)
|
|
26
|
+
detected.push("clerk");
|
|
27
|
+
if (deps.hasSupabase)
|
|
28
|
+
detected.push("supabase");
|
|
29
|
+
if (deps.hasPrisma)
|
|
30
|
+
detected.push("prisma");
|
|
31
|
+
if (deps.hasDrizzle)
|
|
32
|
+
detected.push("drizzle");
|
|
33
|
+
if (deps.hasTrpc)
|
|
34
|
+
detected.push("trpc");
|
|
35
|
+
if (deps.hasUpstashRatelimit)
|
|
36
|
+
detected.push("upstash-ratelimit");
|
|
37
|
+
// Check for middleware
|
|
38
|
+
const hasMiddleware = existsSync(path.join(rootDir, "middleware.ts"))
|
|
39
|
+
|| existsSync(path.join(rootDir, "middleware.js"))
|
|
40
|
+
|| existsSync(path.join(rootDir, "src/middleware.ts"))
|
|
41
|
+
|| existsSync(path.join(rootDir, "src/middleware.js"));
|
|
42
|
+
if (hasMiddleware)
|
|
43
|
+
detected.push("middleware.ts");
|
|
44
|
+
console.log(pc.green(` Detected: ${detected.join(" · ")}`));
|
|
45
|
+
// 3. Write config (idempotent)
|
|
46
|
+
const existingConfig = findConfigFile(rootDir);
|
|
47
|
+
if (existingConfig && !opts.force) {
|
|
48
|
+
console.log(pc.dim(` Found existing config → skipping generation (${path.basename(existingConfig)})`));
|
|
49
|
+
}
|
|
50
|
+
else if (opts.dryRun) {
|
|
51
|
+
console.log(pc.dim(" Would create shipguard.config.json (--dry-run)"));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
writeDefaultConfig(rootDir, { force: Boolean(opts.force) });
|
|
55
|
+
console.log(pc.green(" Created shipguard.config.json"));
|
|
56
|
+
}
|
|
57
|
+
// 4. Run scan
|
|
58
|
+
console.log(pc.dim("\n Running scan..."));
|
|
59
|
+
try {
|
|
60
|
+
const result = await runScan({ rootDir });
|
|
61
|
+
const status = scoreStatus(result.score);
|
|
62
|
+
const scoreColor = status === "PASS" ? pc.green : status === "WARN" ? pc.yellow : pc.red;
|
|
63
|
+
console.log(`\n Shipguard Score: ${scoreColor(String(result.score))} ${scoreColor(status)}`);
|
|
64
|
+
if (result.findings.length === 0) {
|
|
65
|
+
console.log(pc.green(" No findings — looking good!"));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Show top 5 findings
|
|
69
|
+
const top = result.findings.slice(0, 5);
|
|
70
|
+
for (const f of top) {
|
|
71
|
+
const loc = f.line ? `:${f.line}` : "";
|
|
72
|
+
const conf = pc.dim(`(${f.confidence})`);
|
|
73
|
+
console.log(` ${pc.red(f.ruleId)} ${conf} ${pc.dim(f.file + loc)}`);
|
|
74
|
+
}
|
|
75
|
+
if (result.findings.length > 5) {
|
|
76
|
+
console.log(pc.dim(` ... and ${result.findings.length - 5} more`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Next steps
|
|
80
|
+
console.log(pc.dim("\n Next:"));
|
|
81
|
+
console.log(pc.dim(" shipguard baseline --write Save current state as baseline"));
|
|
82
|
+
console.log(pc.dim(" shipguard explain <RULE> Learn about a specific rule"));
|
|
83
|
+
console.log(pc.dim(" shipguard ci Run in CI mode"));
|
|
84
|
+
console.log("");
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
console.error(pc.red(` Scan failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/rules.ts"],"names":[],"mappings":"AAGA,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAW9C"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { RULE_REGISTRY } from "../../rules/index.js";
|
|
3
|
+
export async function cmdRules() {
|
|
4
|
+
console.log("\n Shipguard Rules (v1)\n");
|
|
5
|
+
for (const rule of RULE_REGISTRY) {
|
|
6
|
+
const severityColor = rule.defaultSeverity === "critical" ? pc.red : pc.yellow;
|
|
7
|
+
console.log(` ${pc.bold(rule.id)} ${severityColor(`[${rule.defaultSeverity}]`)}`);
|
|
8
|
+
console.log(` ${pc.dim(rule.description)}`);
|
|
9
|
+
console.log("");
|
|
10
|
+
}
|
|
11
|
+
console.log(pc.dim(" Run `shipguard explain <RULE>` for full details.\n"));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/cli/commands/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,aAAa,CAAC,IAAI,IAAI,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC,CAAC;QACnF,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsD9D"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
import { runScan } from "../../engine/run.js";
|
|
4
|
+
import { formatPretty, formatJson } from "../../engine/report.js";
|
|
5
|
+
import { formatSarif } from "../../engine/sarif.js";
|
|
6
|
+
import { computeScore, summarizeFindings, confidenceLevel, parseConfidence } from "../../engine/score.js";
|
|
7
|
+
export async function cmdScan(opts) {
|
|
8
|
+
try {
|
|
9
|
+
const rootDir = process.cwd();
|
|
10
|
+
// Build config overrides from CLI flags
|
|
11
|
+
const configOverrides = {};
|
|
12
|
+
if (opts.only) {
|
|
13
|
+
const onlyRules = opts.only.split(",").map((r) => r.trim().toUpperCase());
|
|
14
|
+
const rules = {};
|
|
15
|
+
for (const ruleId of onlyRules) {
|
|
16
|
+
rules[ruleId] = { severity: "critical" };
|
|
17
|
+
}
|
|
18
|
+
configOverrides.rules = rules;
|
|
19
|
+
}
|
|
20
|
+
const additionalExclude = opts.exclude
|
|
21
|
+
? opts.exclude.split(",").map((g) => g.trim())
|
|
22
|
+
: undefined;
|
|
23
|
+
const result = await runScan({ rootDir, configOverrides, additionalExclude });
|
|
24
|
+
// Filter by confidence if specified, recalculate score and summary
|
|
25
|
+
if (opts.minConfidence) {
|
|
26
|
+
const minConf = parseConfidence(opts.minConfidence);
|
|
27
|
+
result.findings = result.findings.filter((f) => confidenceLevel(f.confidence) >= confidenceLevel(minConf));
|
|
28
|
+
result.score = computeScore(result.findings);
|
|
29
|
+
const counts = summarizeFindings(result.findings);
|
|
30
|
+
result.summary = { total: result.findings.length, ...counts, waived: result.summary.waived };
|
|
31
|
+
}
|
|
32
|
+
let output;
|
|
33
|
+
switch (opts.format) {
|
|
34
|
+
case "json":
|
|
35
|
+
output = formatJson(result);
|
|
36
|
+
break;
|
|
37
|
+
case "sarif":
|
|
38
|
+
output = formatSarif(result);
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
output = formatPretty(result);
|
|
42
|
+
}
|
|
43
|
+
if (opts.output) {
|
|
44
|
+
writeFileSync(opts.output, output);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(output);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
console.error(pc.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waive.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/waive.ts"],"names":[],"mappings":"AAIA,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BhF"}
|