@softspark/ai-toolkit 4.20.0 → 4.22.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/CHANGELOG.md +107 -0
- package/README.md +32 -22
- package/app/.claude-plugin/plugin.json +1 -1
- package/app/agents/code-reviewer.md +32 -15
- package/app/skills/a11y-validate/SKILL.md +61 -179
- package/app/skills/a11y-validate/reference/scanner-categories.md +174 -0
- package/app/skills/brainstorm/SKILL.md +174 -0
- package/app/skills/ci/SKILL.md +1 -0
- package/app/skills/debug/SKILL.md +2 -1
- package/app/skills/documentation-standards/SKILL.md +25 -5
- package/app/skills/fix/SKILL.md +1 -1
- package/app/skills/hipaa-validate/SKILL.md +25 -221
- package/app/skills/hipaa-validate/reference/scanner-categories.md +224 -0
- package/app/skills/pr/SKILL.md +1 -1
- package/app/skills/review/SKILL.md +49 -4
- package/app/skills/seo-validate/SKILL.md +63 -309
- package/app/skills/seo-validate/reference/scanner-categories.md +304 -0
- package/app/surface.json +296 -0
- package/benchmarks/ecosystem-doctor-snapshot.json +15 -19
- package/kb/procedures/release-preparation-sop.md +44 -2
- package/kb/reference/architecture-overview.md +3 -3
- package/kb/reference/skills-catalog.md +10 -14
- package/llms-full.txt +59 -20
- package/manifest.json +3 -3
- package/package.json +6 -3
- package/scripts/check_split.py +493 -0
- package/scripts/surface_manifest.py +246 -0
- package/scripts/sync_badges.py +133 -0
- package/scripts/validate.py +84 -2
|
@@ -48,7 +48,7 @@ Scan a codebase for HIPAA compliance issues using pattern-matching heuristics. D
|
|
|
48
48
|
Execute the Python scanner with the user's arguments:
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
python3
|
|
51
|
+
python3 ${CLAUDE_SKILL_DIR}/scripts/hipaa_scan.py [path] [--mode developer|compliance] [--severity high|warn] [--keywords term1,term2] [--output json]
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
The script handles all scanning logic deterministically:
|
|
@@ -65,6 +65,9 @@ If `--output json` is used, the script outputs structured JSON suitable for CI p
|
|
|
65
65
|
|
|
66
66
|
### Step 2: Interpret and Enrich Results
|
|
67
67
|
|
|
68
|
+
Read [reference/scanner-categories.md](reference/scanner-categories.md) once before
|
|
69
|
+
starting — you cannot judge a heuristic finding without the pattern that produced it.
|
|
70
|
+
|
|
68
71
|
For each finding from the script output:
|
|
69
72
|
|
|
70
73
|
1. **Read the flagged file and line** to understand the actual code context
|
|
@@ -74,226 +77,27 @@ For each finding from the script output:
|
|
|
74
77
|
|
|
75
78
|
### Scanner Reference
|
|
76
79
|
|
|
77
|
-
The
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|---------|----------|----------|-------------|
|
|
99
|
-
| `console\.log\(.*patient` | HIGH | JS/TS | Patient data in console |
|
|
100
|
-
| `console\.\w+\(.*req\.body` | WARN | JS/TS | Raw request body may contain PHI |
|
|
101
|
-
| `JSON\.stringify\(.*patient` | WARN | JS/TS | Full patient object serialization |
|
|
102
|
-
| `print\(.*\b(patient\|ssn\|social.security)` | HIGH | Python | PHI in print statements |
|
|
103
|
-
| `(logging\|logger\|pprint)\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | Python | PHI in logger/named logger/pprint output |
|
|
104
|
-
| `print\(.*request\.(data\|json\|form\|POST\|body)` | WARN | Python | Raw request body may contain PHI (Django/Flask/FastAPI) |
|
|
105
|
-
| `(logging\|logger)\.\w+\(.*request\.(data\|json\|form\|POST\|body)` | WARN | Python | Raw request body in logger |
|
|
106
|
-
| `\brepr\(.*\b(patient\|ssn\|mrn)` | WARN | Python | repr() may expose PHI fields |
|
|
107
|
-
| `\bvars\(.*\b(patient\|ssn\|mrn)` | WARN | Python | vars() dumps all PHI fields |
|
|
108
|
-
| `fmt\.Print.*\b(patient\|ssn\|mrn)` | HIGH | Go | PHI in fmt output |
|
|
109
|
-
| `log\.\w+\(.*\b(patient\|ssn\|mrn)` | HIGH | Go/Any | PHI in log calls |
|
|
110
|
-
| `System\.out\.print.*\b(patient\|ssn\|mrn)` | HIGH | Java | PHI in stdout |
|
|
111
|
-
| `logger\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | Java/Any | PHI fields in logger |
|
|
112
|
-
| `puts.*\b(patient\|ssn\|mrn)` | HIGH | Ruby | PHI in puts |
|
|
113
|
-
| `Rails\.logger.*\b(patient\|ssn\|mrn)` | HIGH | Ruby | PHI in Rails logger |
|
|
114
|
-
| `Console\.Write.*\b(patient\|ssn\|mrn)` | HIGH | C# | PHI in Console output |
|
|
115
|
-
| `_logger\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | C# | PHI in ILogger calls |
|
|
116
|
-
|
|
117
|
-
> **Language coverage note**: JS/TS and Python patterns are the most comprehensive. Go, Ruby, and Java have baseline coverage for common log patterns. Contributions for additional language-specific patterns are welcome.
|
|
118
|
-
|
|
119
|
-
**Minimum Necessary violations** (§164.502(b)):
|
|
120
|
-
|
|
121
|
-
| Pattern | Severity | Language | Description |
|
|
122
|
-
|---------|----------|----------|-------------|
|
|
123
|
-
| `res\.(json\|send)\(.*patient` without field projection | WARN | JS/TS | Full patient object in API response |
|
|
124
|
-
| `return.*patient` in route handler without field selection | WARN | Any | May expose unnecessary PHI fields |
|
|
125
|
-
| `SELECT\s+\*.*FROM.*(patient\|member\|enrollee)` | WARN | SQL | SELECT * on PHI tables violates minimum necessary |
|
|
126
|
-
| `JSON\.stringify\(.*patient` | WARN | JS/TS | Full patient object serialization |
|
|
127
|
-
| `json\.dumps\(.*patient` | WARN | Python | Full patient object serialization |
|
|
128
|
-
| `JsonConvert\.Serialize.*patient` | WARN | C# | Full patient object serialization |
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
#### Category 2: Missing Audit Logging
|
|
133
|
-
|
|
134
|
-
*Compliance mode only. Heuristic — flags potential gaps, not definitive findings.*
|
|
135
|
-
|
|
136
|
-
> **Developer mode**: This category is skipped. Run with `--mode compliance` to include audit gap checks.
|
|
137
|
-
|
|
138
|
-
Scan the full project for files that handle PHI data operations but lack audit-related keywords.
|
|
139
|
-
|
|
140
|
-
**PHI route file definition**: A file qualifies if it contains BOTH:
|
|
141
|
-
1. A healthcare keyword from Step 0 (`patient`, `diagnosis`, `medication`, etc.)
|
|
142
|
-
2. A data operation pattern: `router`, `app.get`, `app.post`, `app.put`, `app.delete`, `@RequestMapping`, `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `Model.find`, `Model.save`, `Model.update`, `db.query`, `db.execute`, `cursor.execute`, `repository.`, `findBy`, `save(`, `delete(`, `@app.route`, `@blueprint.route`, `@api_view`, `ViewSet`, `APIView`, `\bsession.(query|add|execute|delete|merge)\b` (word-anchored — SQLAlchemy only, avoids matching Express `req.session.save`)
|
|
143
|
-
|
|
144
|
-
Files with a healthcare keyword but no data operation pattern are excluded.
|
|
145
|
-
|
|
146
|
-
**Audit keywords** (co-occurrence check): `audit`, `AuditEvent`, `auditLog`, `logAccess`, `logEvent`, `createAuditEntry`, `recordAccess`, `ActivityLog`, `trail`, `writeAudit`
|
|
147
|
-
|
|
148
|
-
| Pattern | Severity | Description |
|
|
149
|
-
|---------|----------|-------------|
|
|
150
|
-
| PHI route file without any audit keywords in same file | HIGH | §164.312(b) — POTENTIAL audit gap: verify audit controls exist in call chain |
|
|
151
|
-
| CRUD operations on patient resources without audit keywords in same file | HIGH | POTENTIAL gap: all PHI access must be logged |
|
|
152
|
-
| Admin operations without audit trail reference | WARN | POTENTIAL gap: administrative actions need recording |
|
|
153
|
-
| Bulk data operations (`export`, `download`, `bulk`, `batch`) on PHI resources without audit keywords in same file | HIGH | POTENTIAL gap: mass PHI access must be tracked |
|
|
154
|
-
|
|
155
|
-
> **Note**: This category uses co-occurrence heuristics — checking whether PHI route keywords and audit keywords appear in the same file. False positives are expected when audit logging is handled by middleware or a separate call chain. Use `.hipaaignore` to suppress confirmed false positives.
|
|
156
|
-
|
|
157
|
-
See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.312(b) for audit control requirements.
|
|
158
|
-
|
|
159
|
-
---
|
|
160
|
-
|
|
161
|
-
#### Category 3: Unencrypted PHI Transmission
|
|
162
|
-
|
|
163
|
-
*Context-gated: scans PHI-adjacent files only.*
|
|
164
|
-
|
|
165
|
-
| Pattern | Severity | Language | Description |
|
|
166
|
-
|---------|----------|----------|-------------|
|
|
167
|
-
| `http://` in API calls (not `localhost`/`127.0.0.1`) | HIGH | Any | §164.312(e)(1) requires encryption in transit |
|
|
168
|
-
| Missing TLS/SSL config in database connections | HIGH | Any | Database connections must be encrypted |
|
|
169
|
-
| `rejectUnauthorized:\s*false` | HIGH | Any | TLS verification disabled |
|
|
170
|
-
| `ws://` (WebSocket without TLS) | WARN | Any | Unencrypted WebSocket may carry PHI |
|
|
171
|
-
| `verify\s*=\s*False` | HIGH | Python | TLS verification disabled (requests/httpx) |
|
|
172
|
-
| `InsecureRequestWarning` | WARN | Python | TLS warning suppressed |
|
|
173
|
-
| `[,(]\s*ssl\s*=\s*False\b` | HIGH | Python | SSL disabled in connector call (anchored to arg position to avoid matching `is_ssl_enabled = False`) |
|
|
174
|
-
| `ssl\.CERT_NONE` | HIGH | Python | TLS certificate verification disabled (anchored to `ssl.` module) |
|
|
175
|
-
| `check_hostname\s*=\s*False` | HIGH | Python | TLS hostname verification disabled |
|
|
176
|
-
| `urllib3\.disable_warnings` | WARN | Python | TLS warnings suppressed (urllib3) |
|
|
177
|
-
| `SECURE_SSL_REDIRECT\s*=\s*False` | WARN | Python | Django HTTPS redirect disabled (commonly False in dev settings — verify production config) |
|
|
178
|
-
| `NODE_TLS_REJECT_UNAUTHORIZED.*0` | HIGH | JS/TS | TLS rejection disabled globally |
|
|
179
|
-
|
|
180
|
-
See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.312(e)(1) for transmission security requirements.
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
#### Category 4: Hardcoded PHI/Test Data
|
|
185
|
-
|
|
186
|
-
*Context-gated: scans PHI-adjacent files only.*
|
|
187
|
-
|
|
188
|
-
**Built-in test directory exclusions**: Skip files in `test/`, `tests/`, `__tests__/`, `spec/`, `fixtures/`, `mocks/`, `__mocks__/`, `testdata/`, `test-data/` — test fixtures legitimately contain synthetic PHI.
|
|
189
|
-
|
|
190
|
-
| Pattern | Severity | Description |
|
|
191
|
-
|---------|----------|-------------|
|
|
192
|
-
| `\d{3}-\d{2}-\d{4}` in PHI-adjacent source files | HIGH | Hardcoded SSNs |
|
|
193
|
-
| MRN patterns near healthcare keywords | HIGH | Medical record numbers in code |
|
|
194
|
-
| `\b\d{5}(-\d{4})?\b` near `zip\|postal\|address` keywords | WARN | ZIP codes in healthcare context (§164.514(b)(2)(i)(B)) |
|
|
195
|
-
| Real-looking patient names in seed/fixture data | WARN | Use synthetic data generators |
|
|
196
|
-
| Date of birth + name co-occurrence in same file | WARN | Combined identifiers = PHI |
|
|
197
|
-
| Phone/email/IP regex matches in PHI-adjacent files | WARN | HIPAA identifiers in healthcare context |
|
|
198
|
-
| `\d{3}[\s.-]?\d{3}[\s.-]?\d{4}` near `phone` keyword | WARN | Phone numbers in healthcare context |
|
|
199
|
-
|
|
200
|
-
See: [reference/phi-identifiers.md](reference/phi-identifiers.md) for the full list of 18 HIPAA identifiers and detection patterns.
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
#### Category 5: Access Control Gaps
|
|
205
|
-
|
|
206
|
-
*Context-gated: scans PHI-adjacent files only. Heuristic — flags potential gaps.*
|
|
207
|
-
|
|
208
|
-
**Auth keywords** (co-occurrence check): `auth`, `authenticate`, `requireAuth`, `isAuthenticated`, `protect`, `guard`, `Authorize`, `login_required`, `Permission`, `permission_required`, `LoginRequiredMixin`, `PermissionRequiredMixin`, `IsAuthenticated`, `Depends`, `Security`
|
|
209
|
-
|
|
210
|
-
**Data operation patterns** (Python frameworks): `@app.route`, `@blueprint.route`, `@api_view`, `ViewSet`, `APIView`, `cursor.execute`, `\bsession.(query|execute)\b` (word-anchored — SQLAlchemy only)
|
|
211
|
-
|
|
212
|
-
| Pattern | Severity | Language | Description |
|
|
213
|
-
|---------|----------|----------|-------------|
|
|
214
|
-
| PHI route file without any auth keywords in same file | WARN | Any | POTENTIAL access control gap — verify auth middleware covers these routes (§164.312(d)) |
|
|
215
|
-
| `Access-Control-Allow-Origin:\s*\*` or `origin:\s*(true\|\*)` in PHI-adjacent files | HIGH | Any | Unrestricted cross-origin access to PHI endpoints |
|
|
216
|
-
| Routes marked `public`, `noAuth`, `anonymous` exposing PHI keywords | HIGH | Any | PHI must require authentication |
|
|
217
|
-
| `permission_classes\s*=.*AllowAny` | WARN | Python | DRF AllowAny — verify no PHI exposed |
|
|
218
|
-
|
|
219
|
-
> **Note**: Auth middleware is commonly applied at router-level or app-level. The co-occurrence heuristic checks the same file only. False positives expected when auth is configured globally. Use `.hipaaignore` to suppress.
|
|
220
|
-
|
|
221
|
-
See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.312(a)(1) and §164.312(d) for access control and authentication requirements.
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
#### Category 6: Missing BAA References
|
|
226
|
-
|
|
227
|
-
*Compliance mode only. Context-gated: scans PHI-adjacent files only.*
|
|
228
|
-
|
|
229
|
-
> **Developer mode**: This category is skipped. Run with `--mode compliance` to include BAA checks.
|
|
230
|
-
|
|
231
|
-
Instead of per-finding rows, emit a single **BAA Verification Checklist** in the compliance report:
|
|
232
|
-
|
|
233
|
-
1. Grep PHI-adjacent files for HTTP client calls (`fetch(`, `axios.`, `requests.`, `http.Get`, `HttpClient`, `RestTemplate`, `urllib`). Extract external domains.
|
|
234
|
-
2. Grep for cloud storage calls (`S3`, `GCS`, `BlobStorage`, `putObject`, `upload`). Note each service.
|
|
235
|
-
3. Grep for cloud database connections (`mongodb+srv://`, `postgres://`, `mysql://`, `firestore`, `dynamodb`, `CosmosClient`, `MongoClient`, connection strings with cloud hostnames). Note each service.
|
|
236
|
-
4. Grep for message queue / event streaming services (`SQS`, `SNS`, `RabbitMQ`, `redis://`, `kafka`, `EventBridge`, `PubSub`). Note each service.
|
|
237
|
-
5. Grep for CDN references (`CloudFront`, `Cloudflare`, `Akamai`, `Fastly`, `cdn.`) serving PHI-adjacent paths. Note each service.
|
|
238
|
-
6. Grep for observability / logging SDKs (`datadog`, `splunk`, `newrelic`, `sentry`, `logstash`, `elasticsearch`, `bugsnag`, `rollbar`). Note each SDK.
|
|
239
|
-
7. Grep for analytics SDK calls (`analytics.`, `gtag`, `mixpanel`, `segment`, `amplitude`, `posthog`). Note each SDK.
|
|
240
|
-
8. Read `.hipaa-config` at project root if it exists. Suppress vendors listed under `covered_vendors`.
|
|
241
|
-
9. Emit one checklist row per unverified domain/service.
|
|
242
|
-
|
|
243
|
-
**`.hipaa-config` format** (suppress known-covered vendors):
|
|
244
|
-
```json
|
|
245
|
-
{
|
|
246
|
-
"covered_vendors": ["aws", "twilio", "sendgrid", "stripe"]
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
**Output format for compliance mode**:
|
|
251
|
-
```
|
|
252
|
-
### BAA Verification Checklist
|
|
253
|
-
| Service/Domain | Pattern Detected | BAA Status |
|
|
254
|
-
|----------------|-----------------|------------|
|
|
255
|
-
| AWS S3 | `putObject` in src/storage/patient-files.ts | ✓ covered (covered_vendors) |
|
|
256
|
-
| sendgrid.com | `axios.post` in src/notifications/email.ts | ⚠️ verify BAA exists |
|
|
257
|
-
| analytics.google.com | `gtag` in src/components/Dashboard.tsx | ❌ verify no PHI flows here |
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
> **Note**: This is a documentation checklist, not a legal review. Items marked ⚠️ or ❌ require human verification, not code changes.
|
|
261
|
-
|
|
262
|
-
---
|
|
263
|
-
|
|
264
|
-
#### Category 7: Encryption at Rest
|
|
265
|
-
|
|
266
|
-
*Context-gated: scans PHI-adjacent files only. Developer mode.*
|
|
267
|
-
|
|
268
|
-
Detects PHI storage patterns without encryption references. Per §164.312(a)(2)(iv), ePHI must be encrypted when stored.
|
|
269
|
-
|
|
270
|
-
| Pattern | Severity | Language | Description |
|
|
271
|
-
|---------|----------|----------|-------------|
|
|
272
|
-
| `encrypt\s*[:=]\s*false` in database config files | HIGH | Any | §164.312(a)(2)(iv) — Encryption explicitly disabled |
|
|
273
|
-
| File write operations (`writeFile`, `fs.write`, `open(.*w`, `File.Create`) in PHI-adjacent code without encryption references | WARN | Any | PHI written to disk may lack encryption at rest |
|
|
274
|
-
| Database connection without `ssl`, `encrypt`, or `tls` keywords in PHI-adjacent config | WARN | Any | Database storing PHI should enforce encrypted connections |
|
|
275
|
-
| `localStorage.setItem` or `sessionStorage.setItem` with PHI keywords | HIGH | JS/TS | Browser storage is unencrypted — PHI must not be stored client-side without encryption |
|
|
276
|
-
| `SharedPreferences` or `UserDefaults` with PHI keywords | HIGH | Java/Any | Mobile local storage is unencrypted by default |
|
|
277
|
-
| `pickle\.(dump\|dumps)\(` with PHI keywords | HIGH | Python | pickle serialization is unencrypted — PHI must be encrypted at rest |
|
|
278
|
-
| `shelve\.open\(` with PHI keywords | HIGH | Python | shelve storage is unencrypted — PHI must be encrypted at rest |
|
|
279
|
-
|
|
280
|
-
See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.312(a)(2)(iv) for encryption requirements.
|
|
281
|
-
|
|
282
|
-
---
|
|
283
|
-
|
|
284
|
-
#### Category 8: PHI Temp File Exposure
|
|
285
|
-
|
|
286
|
-
*Context-gated: scans PHI-adjacent files only. Developer mode.*
|
|
287
|
-
|
|
288
|
-
Detects temporary file creation in PHI-adjacent code without secure deletion. Per §164.310(d)(2)(iii), media containing PHI must be sanitized before reuse or disposal.
|
|
289
|
-
|
|
290
|
-
| Pattern | Severity | Description |
|
|
291
|
-
|---------|----------|-------------|
|
|
292
|
-
| `/tmp/` or `tempfile\.` or `os\.tmpdir\(\)` or `Path\.GetTempPath` in PHI-adjacent code | WARN | §164.310(d)(2)(iii) — Temp files with PHI must be securely deleted |
|
|
293
|
-
| `mktemp` or `NamedTemporaryFile` or `createTempFile` near PHI keywords | WARN | Verify temp files are cleaned up after use |
|
|
294
|
-
| Cache directory writes (`cache/`, `.cache`, `Cache.set`) with PHI keywords | WARN | Cached PHI must be encrypted or purged on schedule |
|
|
295
|
-
|
|
296
|
-
See: [reference/hipaa-rules.md](reference/hipaa-rules.md) §164.310(d)(2)(iii) for disposal requirements.
|
|
80
|
+
The eight scan categories are implemented in `scripts/hipaa_scan.py`. The pattern
|
|
81
|
+
tables, severities, per-language coverage and rule citations live in
|
|
82
|
+
[reference/scanner-categories.md](reference/scanner-categories.md).
|
|
83
|
+
|
|
84
|
+
Read that file once, in full, before enriching findings in Step 2 — it is what lets
|
|
85
|
+
you explain *why* a line matched and judge whether a heuristic hit is a false
|
|
86
|
+
positive. The scan itself does not need it; the script already holds the patterns.
|
|
87
|
+
|
|
88
|
+
| # | Category | Scope | Mode |
|
|
89
|
+
|---|----------|-------|------|
|
|
90
|
+
| 1 | PHI in logs / console output (+ minimum-necessary violations) | full project | developer |
|
|
91
|
+
| 2 | Missing audit logging | full project | compliance only, heuristic |
|
|
92
|
+
| 3 | Unencrypted transmission | PHI-adjacent | developer |
|
|
93
|
+
| 4 | Hardcoded PHI test data | PHI-adjacent | developer |
|
|
94
|
+
| 5 | Access control gaps | PHI-adjacent | compliance only, heuristic |
|
|
95
|
+
| 6 | Missing BAA references | PHI-adjacent | compliance only, heuristic |
|
|
96
|
+
| 7 | Encryption at rest | PHI-adjacent | developer |
|
|
97
|
+
| 8 | PHI temp file exposure | PHI-adjacent | developer |
|
|
98
|
+
|
|
99
|
+
Categories 1 and 2 scan the full project; categories 3–8 scan only PHI-adjacent
|
|
100
|
+
files. Compliance mode adds the heuristic categories 2, 5 and 6 to the developer set.
|
|
297
101
|
|
|
298
102
|
### Step 3: Compile and Report
|
|
299
103
|
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# HIPAA Scanner Categories
|
|
2
|
+
|
|
3
|
+
## Scanner Reference
|
|
4
|
+
|
|
5
|
+
The script implements the following scan categories. This reference is provided so you can explain findings to the user and verify edge cases.
|
|
6
|
+
|
|
7
|
+
**Modes:**
|
|
8
|
+
- `developer` (default): Categories 1, 3, 4, 7, 8 — definitive regex matches only, low false-positive rate
|
|
9
|
+
- `compliance`: All 8 categories — includes heuristic checks (Cat 2, 5, 6)
|
|
10
|
+
|
|
11
|
+
**Default keywords**: `patient`, `diagnosis`, `medication`, `clinical`, `healthcare`, `medical`, `fhir`, `hl7`, `hipaa`, `phi`, `protected.health`, `health-record`, `health-plan`, `health-insurance`
|
|
12
|
+
|
|
13
|
+
> **Note**: Bare `health` is deliberately excluded — it matches infrastructure health checks in nearly every codebase.
|
|
14
|
+
|
|
15
|
+
**Built-in exclusions**: Binary files, lock files, vendored directories (`node_modules/`, `vendor/`, `.git/`, `dist/`, `build/`, `out/`, `.next/`). Test directories (`test/`, `tests/`, `__tests__/`, `spec/`, `fixtures/`, `mocks/`) are excluded for Category 4 only.
|
|
16
|
+
|
|
17
|
+
Categories 1 and 2 scan the full project. Categories 3–8 scan only PHI-adjacent files.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
### Category 1: PHI in Logs/Console Output
|
|
22
|
+
|
|
23
|
+
Scan the full project for log/print statements that reference PHI keywords.
|
|
24
|
+
|
|
25
|
+
| Pattern | Severity | Language | Description |
|
|
26
|
+
|---------|----------|----------|-------------|
|
|
27
|
+
| `console\.log\(.*patient` | HIGH | JS/TS | Patient data in console |
|
|
28
|
+
| `console\.\w+\(.*req\.body` | WARN | JS/TS | Raw request body may contain PHI |
|
|
29
|
+
| `JSON\.stringify\(.*patient` | WARN | JS/TS | Full patient object serialization |
|
|
30
|
+
| `print\(.*\b(patient\|ssn\|social.security)` | HIGH | Python | PHI in print statements |
|
|
31
|
+
| `(logging\|logger\|pprint)\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | Python | PHI in logger/named logger/pprint output |
|
|
32
|
+
| `print\(.*request\.(data\|json\|form\|POST\|body)` | WARN | Python | Raw request body may contain PHI (Django/Flask/FastAPI) |
|
|
33
|
+
| `(logging\|logger)\.\w+\(.*request\.(data\|json\|form\|POST\|body)` | WARN | Python | Raw request body in logger |
|
|
34
|
+
| `\brepr\(.*\b(patient\|ssn\|mrn)` | WARN | Python | repr() may expose PHI fields |
|
|
35
|
+
| `\bvars\(.*\b(patient\|ssn\|mrn)` | WARN | Python | vars() dumps all PHI fields |
|
|
36
|
+
| `fmt\.Print.*\b(patient\|ssn\|mrn)` | HIGH | Go | PHI in fmt output |
|
|
37
|
+
| `log\.\w+\(.*\b(patient\|ssn\|mrn)` | HIGH | Go/Any | PHI in log calls |
|
|
38
|
+
| `System\.out\.print.*\b(patient\|ssn\|mrn)` | HIGH | Java | PHI in stdout |
|
|
39
|
+
| `logger\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | Java/Any | PHI fields in logger |
|
|
40
|
+
| `puts.*\b(patient\|ssn\|mrn)` | HIGH | Ruby | PHI in puts |
|
|
41
|
+
| `Rails\.logger.*\b(patient\|ssn\|mrn)` | HIGH | Ruby | PHI in Rails logger |
|
|
42
|
+
| `Console\.Write.*\b(patient\|ssn\|mrn)` | HIGH | C# | PHI in Console output |
|
|
43
|
+
| `_logger\.\w+\(.*\b(patient\|ssn\|mrn\|dob)` | HIGH | C# | PHI in ILogger calls |
|
|
44
|
+
|
|
45
|
+
> **Language coverage note**: JS/TS and Python patterns are the most comprehensive. Go, Ruby, and Java have baseline coverage for common log patterns. Contributions for additional language-specific patterns are welcome.
|
|
46
|
+
|
|
47
|
+
**Minimum Necessary violations** (§164.502(b)):
|
|
48
|
+
|
|
49
|
+
| Pattern | Severity | Language | Description |
|
|
50
|
+
|---------|----------|----------|-------------|
|
|
51
|
+
| `res\.(json\|send)\(.*patient` without field projection | WARN | JS/TS | Full patient object in API response |
|
|
52
|
+
| `return.*patient` in route handler without field selection | WARN | Any | May expose unnecessary PHI fields |
|
|
53
|
+
| `SELECT\s+\*.*FROM.*(patient\|member\|enrollee)` | WARN | SQL | SELECT * on PHI tables violates minimum necessary |
|
|
54
|
+
| `JSON\.stringify\(.*patient` | WARN | JS/TS | Full patient object serialization |
|
|
55
|
+
| `json\.dumps\(.*patient` | WARN | Python | Full patient object serialization |
|
|
56
|
+
| `JsonConvert\.Serialize.*patient` | WARN | C# | Full patient object serialization |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### Category 2: Missing Audit Logging
|
|
61
|
+
|
|
62
|
+
*Compliance mode only. Heuristic — flags potential gaps, not definitive findings.*
|
|
63
|
+
|
|
64
|
+
> **Developer mode**: This category is skipped. Run with `--mode compliance` to include audit gap checks.
|
|
65
|
+
|
|
66
|
+
Scan the full project for files that handle PHI data operations but lack audit-related keywords.
|
|
67
|
+
|
|
68
|
+
**PHI route file definition**: A file qualifies if it contains BOTH:
|
|
69
|
+
1. A healthcare keyword from Step 0 (`patient`, `diagnosis`, `medication`, etc.)
|
|
70
|
+
2. A data operation pattern: `router`, `app.get`, `app.post`, `app.put`, `app.delete`, `@RequestMapping`, `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `Model.find`, `Model.save`, `Model.update`, `db.query`, `db.execute`, `cursor.execute`, `repository.`, `findBy`, `save(`, `delete(`, `@app.route`, `@blueprint.route`, `@api_view`, `ViewSet`, `APIView`, `\bsession.(query|add|execute|delete|merge)\b` (word-anchored — SQLAlchemy only, avoids matching Express `req.session.save`)
|
|
71
|
+
|
|
72
|
+
Files with a healthcare keyword but no data operation pattern are excluded.
|
|
73
|
+
|
|
74
|
+
**Audit keywords** (co-occurrence check): `audit`, `AuditEvent`, `auditLog`, `logAccess`, `logEvent`, `createAuditEntry`, `recordAccess`, `ActivityLog`, `trail`, `writeAudit`
|
|
75
|
+
|
|
76
|
+
| Pattern | Severity | Description |
|
|
77
|
+
|---------|----------|-------------|
|
|
78
|
+
| PHI route file without any audit keywords in same file | HIGH | §164.312(b) — POTENTIAL audit gap: verify audit controls exist in call chain |
|
|
79
|
+
| CRUD operations on patient resources without audit keywords in same file | HIGH | POTENTIAL gap: all PHI access must be logged |
|
|
80
|
+
| Admin operations without audit trail reference | WARN | POTENTIAL gap: administrative actions need recording |
|
|
81
|
+
| Bulk data operations (`export`, `download`, `bulk`, `batch`) on PHI resources without audit keywords in same file | HIGH | POTENTIAL gap: mass PHI access must be tracked |
|
|
82
|
+
|
|
83
|
+
> **Note**: This category uses co-occurrence heuristics — checking whether PHI route keywords and audit keywords appear in the same file. False positives are expected when audit logging is handled by middleware or a separate call chain. Use `.hipaaignore` to suppress confirmed false positives.
|
|
84
|
+
|
|
85
|
+
See: [hipaa-rules.md](hipaa-rules.md) §164.312(b) for audit control requirements.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### Category 3: Unencrypted PHI Transmission
|
|
90
|
+
|
|
91
|
+
*Context-gated: scans PHI-adjacent files only.*
|
|
92
|
+
|
|
93
|
+
| Pattern | Severity | Language | Description |
|
|
94
|
+
|---------|----------|----------|-------------|
|
|
95
|
+
| `http://` in API calls (not `localhost`/`127.0.0.1`) | HIGH | Any | §164.312(e)(1) requires encryption in transit |
|
|
96
|
+
| Missing TLS/SSL config in database connections | HIGH | Any | Database connections must be encrypted |
|
|
97
|
+
| `rejectUnauthorized:\s*false` | HIGH | Any | TLS verification disabled |
|
|
98
|
+
| `ws://` (WebSocket without TLS) | WARN | Any | Unencrypted WebSocket may carry PHI |
|
|
99
|
+
| `verify\s*=\s*False` | HIGH | Python | TLS verification disabled (requests/httpx) |
|
|
100
|
+
| `InsecureRequestWarning` | WARN | Python | TLS warning suppressed |
|
|
101
|
+
| `[,(]\s*ssl\s*=\s*False\b` | HIGH | Python | SSL disabled in connector call (anchored to arg position to avoid matching `is_ssl_enabled = False`) |
|
|
102
|
+
| `ssl\.CERT_NONE` | HIGH | Python | TLS certificate verification disabled (anchored to `ssl.` module) |
|
|
103
|
+
| `check_hostname\s*=\s*False` | HIGH | Python | TLS hostname verification disabled |
|
|
104
|
+
| `urllib3\.disable_warnings` | WARN | Python | TLS warnings suppressed (urllib3) |
|
|
105
|
+
| `SECURE_SSL_REDIRECT\s*=\s*False` | WARN | Python | Django HTTPS redirect disabled (commonly False in dev settings — verify production config) |
|
|
106
|
+
| `NODE_TLS_REJECT_UNAUTHORIZED.*0` | HIGH | JS/TS | TLS rejection disabled globally |
|
|
107
|
+
|
|
108
|
+
See: [hipaa-rules.md](hipaa-rules.md) §164.312(e)(1) for transmission security requirements.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### Category 4: Hardcoded PHI/Test Data
|
|
113
|
+
|
|
114
|
+
*Context-gated: scans PHI-adjacent files only.*
|
|
115
|
+
|
|
116
|
+
**Built-in test directory exclusions**: Skip files in `test/`, `tests/`, `__tests__/`, `spec/`, `fixtures/`, `mocks/`, `__mocks__/`, `testdata/`, `test-data/` — test fixtures legitimately contain synthetic PHI.
|
|
117
|
+
|
|
118
|
+
| Pattern | Severity | Description |
|
|
119
|
+
|---------|----------|-------------|
|
|
120
|
+
| `\d{3}-\d{2}-\d{4}` in PHI-adjacent source files | HIGH | Hardcoded SSNs |
|
|
121
|
+
| MRN patterns near healthcare keywords | HIGH | Medical record numbers in code |
|
|
122
|
+
| `\b\d{5}(-\d{4})?\b` near `zip\|postal\|address` keywords | WARN | ZIP codes in healthcare context (§164.514(b)(2)(i)(B)) |
|
|
123
|
+
| Real-looking patient names in seed/fixture data | WARN | Use synthetic data generators |
|
|
124
|
+
| Date of birth + name co-occurrence in same file | WARN | Combined identifiers = PHI |
|
|
125
|
+
| Phone/email/IP regex matches in PHI-adjacent files | WARN | HIPAA identifiers in healthcare context |
|
|
126
|
+
| `\d{3}[\s.-]?\d{3}[\s.-]?\d{4}` near `phone` keyword | WARN | Phone numbers in healthcare context |
|
|
127
|
+
|
|
128
|
+
See: [phi-identifiers.md](phi-identifiers.md) for the full list of 18 HIPAA identifiers and detection patterns.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### Category 5: Access Control Gaps
|
|
133
|
+
|
|
134
|
+
*Context-gated: scans PHI-adjacent files only. Heuristic — flags potential gaps.*
|
|
135
|
+
|
|
136
|
+
**Auth keywords** (co-occurrence check): `auth`, `authenticate`, `requireAuth`, `isAuthenticated`, `protect`, `guard`, `Authorize`, `login_required`, `Permission`, `permission_required`, `LoginRequiredMixin`, `PermissionRequiredMixin`, `IsAuthenticated`, `Depends`, `Security`
|
|
137
|
+
|
|
138
|
+
**Data operation patterns** (Python frameworks): `@app.route`, `@blueprint.route`, `@api_view`, `ViewSet`, `APIView`, `cursor.execute`, `\bsession.(query|execute)\b` (word-anchored — SQLAlchemy only)
|
|
139
|
+
|
|
140
|
+
| Pattern | Severity | Language | Description |
|
|
141
|
+
|---------|----------|----------|-------------|
|
|
142
|
+
| PHI route file without any auth keywords in same file | WARN | Any | POTENTIAL access control gap — verify auth middleware covers these routes (§164.312(d)) |
|
|
143
|
+
| `Access-Control-Allow-Origin:\s*\*` or `origin:\s*(true\|\*)` in PHI-adjacent files | HIGH | Any | Unrestricted cross-origin access to PHI endpoints |
|
|
144
|
+
| Routes marked `public`, `noAuth`, `anonymous` exposing PHI keywords | HIGH | Any | PHI must require authentication |
|
|
145
|
+
| `permission_classes\s*=.*AllowAny` | WARN | Python | DRF AllowAny — verify no PHI exposed |
|
|
146
|
+
|
|
147
|
+
> **Note**: Auth middleware is commonly applied at router-level or app-level. The co-occurrence heuristic checks the same file only. False positives expected when auth is configured globally. Use `.hipaaignore` to suppress.
|
|
148
|
+
|
|
149
|
+
See: [hipaa-rules.md](hipaa-rules.md) §164.312(a)(1) and §164.312(d) for access control and authentication requirements.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Category 6: Missing BAA References
|
|
154
|
+
|
|
155
|
+
*Compliance mode only. Context-gated: scans PHI-adjacent files only.*
|
|
156
|
+
|
|
157
|
+
> **Developer mode**: This category is skipped. Run with `--mode compliance` to include BAA checks.
|
|
158
|
+
|
|
159
|
+
Instead of per-finding rows, emit a single **BAA Verification Checklist** in the compliance report:
|
|
160
|
+
|
|
161
|
+
1. Grep PHI-adjacent files for HTTP client calls (`fetch(`, `axios.`, `requests.`, `http.Get`, `HttpClient`, `RestTemplate`, `urllib`). Extract external domains.
|
|
162
|
+
2. Grep for cloud storage calls (`S3`, `GCS`, `BlobStorage`, `putObject`, `upload`). Note each service.
|
|
163
|
+
3. Grep for cloud database connections (`mongodb+srv://`, `postgres://`, `mysql://`, `firestore`, `dynamodb`, `CosmosClient`, `MongoClient`, connection strings with cloud hostnames). Note each service.
|
|
164
|
+
4. Grep for message queue / event streaming services (`SQS`, `SNS`, `RabbitMQ`, `redis://`, `kafka`, `EventBridge`, `PubSub`). Note each service.
|
|
165
|
+
5. Grep for CDN references (`CloudFront`, `Cloudflare`, `Akamai`, `Fastly`, `cdn.`) serving PHI-adjacent paths. Note each service.
|
|
166
|
+
6. Grep for observability / logging SDKs (`datadog`, `splunk`, `newrelic`, `sentry`, `logstash`, `elasticsearch`, `bugsnag`, `rollbar`). Note each SDK.
|
|
167
|
+
7. Grep for analytics SDK calls (`analytics.`, `gtag`, `mixpanel`, `segment`, `amplitude`, `posthog`). Note each SDK.
|
|
168
|
+
8. Read `.hipaa-config` at project root if it exists. Suppress vendors listed under `covered_vendors`.
|
|
169
|
+
9. Emit one checklist row per unverified domain/service.
|
|
170
|
+
|
|
171
|
+
**`.hipaa-config` format** (suppress known-covered vendors):
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"covered_vendors": ["aws", "twilio", "sendgrid", "stripe"]
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Output format for compliance mode**:
|
|
179
|
+
```
|
|
180
|
+
### BAA Verification Checklist
|
|
181
|
+
| Service/Domain | Pattern Detected | BAA Status |
|
|
182
|
+
|----------------|-----------------|------------|
|
|
183
|
+
| AWS S3 | `putObject` in src/storage/patient-files.ts | ✓ covered (covered_vendors) |
|
|
184
|
+
| sendgrid.com | `axios.post` in src/notifications/email.ts | ⚠️ verify BAA exists |
|
|
185
|
+
| analytics.google.com | `gtag` in src/components/Dashboard.tsx | ❌ verify no PHI flows here |
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
> **Note**: This is a documentation checklist, not a legal review. Items marked ⚠️ or ❌ require human verification, not code changes.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### Category 7: Encryption at Rest
|
|
193
|
+
|
|
194
|
+
*Context-gated: scans PHI-adjacent files only. Developer mode.*
|
|
195
|
+
|
|
196
|
+
Detects PHI storage patterns without encryption references. Per §164.312(a)(2)(iv), ePHI must be encrypted when stored.
|
|
197
|
+
|
|
198
|
+
| Pattern | Severity | Language | Description |
|
|
199
|
+
|---------|----------|----------|-------------|
|
|
200
|
+
| `encrypt\s*[:=]\s*false` in database config files | HIGH | Any | §164.312(a)(2)(iv) — Encryption explicitly disabled |
|
|
201
|
+
| File write operations (`writeFile`, `fs.write`, `open(.*w`, `File.Create`) in PHI-adjacent code without encryption references | WARN | Any | PHI written to disk may lack encryption at rest |
|
|
202
|
+
| Database connection without `ssl`, `encrypt`, or `tls` keywords in PHI-adjacent config | WARN | Any | Database storing PHI should enforce encrypted connections |
|
|
203
|
+
| `localStorage.setItem` or `sessionStorage.setItem` with PHI keywords | HIGH | JS/TS | Browser storage is unencrypted — PHI must not be stored client-side without encryption |
|
|
204
|
+
| `SharedPreferences` or `UserDefaults` with PHI keywords | HIGH | Java/Any | Mobile local storage is unencrypted by default |
|
|
205
|
+
| `pickle\.(dump\|dumps)\(` with PHI keywords | HIGH | Python | pickle serialization is unencrypted — PHI must be encrypted at rest |
|
|
206
|
+
| `shelve\.open\(` with PHI keywords | HIGH | Python | shelve storage is unencrypted — PHI must be encrypted at rest |
|
|
207
|
+
|
|
208
|
+
See: [hipaa-rules.md](hipaa-rules.md) §164.312(a)(2)(iv) for encryption requirements.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Category 8: PHI Temp File Exposure
|
|
213
|
+
|
|
214
|
+
*Context-gated: scans PHI-adjacent files only. Developer mode.*
|
|
215
|
+
|
|
216
|
+
Detects temporary file creation in PHI-adjacent code without secure deletion. Per §164.310(d)(2)(iii), media containing PHI must be sanitized before reuse or disposal.
|
|
217
|
+
|
|
218
|
+
| Pattern | Severity | Description |
|
|
219
|
+
|---------|----------|-------------|
|
|
220
|
+
| `/tmp/` or `tempfile\.` or `os\.tmpdir\(\)` or `Path\.GetTempPath` in PHI-adjacent code | WARN | §164.310(d)(2)(iii) — Temp files with PHI must be securely deleted |
|
|
221
|
+
| `mktemp` or `NamedTemporaryFile` or `createTempFile` near PHI keywords | WARN | Verify temp files are cleaned up after use |
|
|
222
|
+
| Cache directory writes (`cache/`, `.cache`, `Cache.set`) with PHI keywords | WARN | Cached PHI must be encrypted or purged on schedule |
|
|
223
|
+
|
|
224
|
+
See: [hipaa-rules.md](hipaa-rules.md) §164.310(d)(2)(iii) for disposal requirements.
|
package/app/skills/pr/SKILL.md
CHANGED
|
@@ -28,7 +28,7 @@ Create a GitHub pull request.
|
|
|
28
28
|
Generate a structured PR summary from the commit history before writing the PR description:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
python3
|
|
31
|
+
python3 ${CLAUDE_SKILL_DIR}/scripts/pr-summary.py [base_branch]
|
|
32
32
|
# Default base branch: main
|
|
33
33
|
# Example: python3 scripts/pr-summary.py develop
|
|
34
34
|
```
|
|
@@ -19,6 +19,23 @@ Reviews code changes for quality and issues.
|
|
|
19
19
|
|
|
20
20
|
- Changes: !`git diff --stat main...HEAD 2>/dev/null || git diff --cached --stat 2>/dev/null || echo "no changes detected"`
|
|
21
21
|
|
|
22
|
+
## Signal Collection (never stop at the first red)
|
|
23
|
+
|
|
24
|
+
Collect every failing signal up front, then review the diff in full **anyway**:
|
|
25
|
+
|
|
26
|
+
| Signal | How to read it |
|
|
27
|
+
|--------|----------------|
|
|
28
|
+
| Merge conflict with base | `gh pr view --json mergeable,mergeStateStatus` or `git merge-tree` |
|
|
29
|
+
| Failing CI checks | `gh pr checks` or the platform equivalent |
|
|
30
|
+
| Lint / typecheck failure | the project's own commands |
|
|
31
|
+
|
|
32
|
+
Each failing signal becomes a `blocker` finding. **None of them ends the run.**
|
|
33
|
+
|
|
34
|
+
A review that aborts on the first red signal spends the whole cycle repeating what
|
|
35
|
+
the tracker already displayed, while the finding that would have told the author
|
|
36
|
+
something new never gets written. One invocation produces the most complete picture
|
|
37
|
+
of the change that it can.
|
|
38
|
+
|
|
22
39
|
## Automated Diff Analysis
|
|
23
40
|
|
|
24
41
|
Before starting manual review, run the diff analyzer script to get a structured risk assessment:
|
|
@@ -58,8 +75,8 @@ Each reviewer should report findings independently. Do NOT modify files.
|
|
|
58
75
|
|
|
59
76
|
After all reviewers complete:
|
|
60
77
|
1. Synthesize findings into unified Code Review Report
|
|
61
|
-
2. Prioritize by severity (
|
|
62
|
-
3. Issue verdict
|
|
78
|
+
2. Prioritize by severity (blocker > major > minor > nit)
|
|
79
|
+
3. Issue verdict per the verdict rule below — not by impression
|
|
63
80
|
|
|
64
81
|
> **When to use**: PRs with >5 files changed, cross-module changes, security-sensitive code.
|
|
65
82
|
> **READ-ONLY**: No teammate should modify files during review.
|
|
@@ -101,12 +118,15 @@ After all reviewers complete:
|
|
|
101
118
|
- [ ] A08: Integrity checks on deserialized data, CI/CD pipeline safety
|
|
102
119
|
- [ ] A09: Security-relevant events logged (without PII)
|
|
103
120
|
- [ ] A10: External URL handling validates scheme/host (SSRF prevention)
|
|
121
|
+
- [ ] Cross-scope replay: can an identifier from one tenant/user/org be replayed in another?
|
|
122
|
+
- [ ] Fails closed wherever the path affects security, money, or data retention
|
|
104
123
|
|
|
105
124
|
### API / Contract Changes
|
|
106
125
|
- [ ] Backward compatibility preserved (no silent breaking changes)
|
|
107
126
|
- [ ] API versioning updated if contract changed
|
|
108
127
|
- [ ] Schema validation on request/response
|
|
109
128
|
- [ ] Error responses follow project convention
|
|
129
|
+
- [ ] Wire-level contracts checked, not just code signatures: HTTP routes, webhook payloads, event/queue schemas
|
|
110
130
|
|
|
111
131
|
### Concurrency / Async
|
|
112
132
|
- [ ] Shared mutable state protected (locks, atomics, channels)
|
|
@@ -131,6 +151,26 @@ After all reviewers complete:
|
|
|
131
151
|
- [ ] Edge cases covered
|
|
132
152
|
- [ ] Mocks appropriate
|
|
133
153
|
|
|
154
|
+
## Severity & Verdict
|
|
155
|
+
|
|
156
|
+
| Tier | Meaning | Merge impact |
|
|
157
|
+
|------|---------|--------------|
|
|
158
|
+
| `blocker` | Causes damage: data loss, security hole, money, corruption | Blocks merge, no exceptions |
|
|
159
|
+
| `major` | Real defect that will bite in production | Blocks merge unless waived in writing |
|
|
160
|
+
| `minor` | Should be fixed, not worth blocking on | Does not block |
|
|
161
|
+
| `nit` | Polish, taste, style | Does not block |
|
|
162
|
+
|
|
163
|
+
**Verdict rule** — apply it mechanically, do not negotiate with yourself:
|
|
164
|
+
|
|
165
|
+
- any `blocker` → `REQUEST_CHANGES`
|
|
166
|
+
- any `major` without a documented waiver (who waived it, why, what the follow-up is) → `REQUEST_CHANGES`
|
|
167
|
+
- only `minor` / `nit` → `APPROVE`
|
|
168
|
+
- the change cannot be classified from the diff → `NEEDS_DISCUSSION`, and state what would resolve it
|
|
169
|
+
|
|
170
|
+
Severity describes impact, confidence describes certainty — they are independent
|
|
171
|
+
axes. A finding with confidence < 6 is reported at the tier its evidence supports
|
|
172
|
+
and is never promoted to `blocker` on suspicion alone.
|
|
173
|
+
|
|
134
174
|
## Output Format
|
|
135
175
|
|
|
136
176
|
```markdown
|
|
@@ -145,9 +185,9 @@ After all reviewers complete:
|
|
|
145
185
|
|
|
146
186
|
### Findings
|
|
147
187
|
|
|
148
|
-
####
|
|
188
|
+
#### Blocker
|
|
149
189
|
- **[file:line]**: [issue]
|
|
150
|
-
- Severity:
|
|
190
|
+
- Severity: blocker | Confidence: [1-10]
|
|
151
191
|
- Evidence: [specific code reference and reasoning]
|
|
152
192
|
- Suggested fix: [code]
|
|
153
193
|
|
|
@@ -181,6 +221,11 @@ After all reviewers complete:
|
|
|
181
221
|
|
|
182
222
|
### Verdict
|
|
183
223
|
[APPROVE / REQUEST_CHANGES / NEEDS_DISCUSSION]
|
|
224
|
+
|
|
225
|
+
State which clause of the verdict rule produced it, e.g.
|
|
226
|
+
"REQUEST_CHANGES — 1 blocker (auth.ts:88)" or
|
|
227
|
+
"APPROVE — 2 minor, 1 nit, no blocker or major".
|
|
228
|
+
Waived majors must name the waiver and the follow-up.
|
|
184
229
|
```
|
|
185
230
|
|
|
186
231
|
## Common Rationalizations
|