- name
- apiaudit
- description
- Forensic API quality audit v1 (Gestalt-Popper). 23-phase deep analysis of every API surface: Endpoint inventory, REST/GraphQL contract compliance, Authentication (every endpoint — owns STATIC auth correctness; /secaudit owns RUNTIME exploitation), Authorization (role-based access), Input validation (every parameter), Error response format, Status code correctness, Pagination, Rate limiting, Versioning strategy, Documentation accuracy, Response time benchmarks, N+1 detection, Idempotency, Webhook reliability, CORS configuration, Content negotiation, API deprecation handling, plus verdict, fix plan, fix execution, re-audit, and rate-limit safety gate. Reads audits/.dataaudit/verdict.json for schema types when available. Outputs audits/.apiaudit/verdict.json consumed by /secaudit for auth surface exploitation. Score /360. Preamble v1.0 compliant. Audit -> Plan -> Fix -> Re-audit. Use when user says "/apiaudit", "api audit", "api quality check", "endpoint audit", "api security check", "api contract verification".
- allowed-tools
- ["Read","Write","Edit","Bash","Glob","Grep","Agent","TaskCreate","TaskUpdate","TaskList","TaskGet"]
- domain
- api
- phases
- 23
- max_score
- 360
- read_only
- false
- triggers
- ["api audit","audit api","api contracts","endpoint audit","api quality"]
<!-- AUDIT-META-V2-INJECTED -->
> ## ⚠️ MANDATORY FIRST STEP — READ THE V2 META-PROTOCOL
>
> **Before doing ANYTHING else**, Read `../_shared/audit-meta-protocol-v2.md`.
>
> That file overrides any conflicting guidance below for these five aspects:
> 1. Required CLI inputs (`--user-need`, `--hinge` are MANDATORY since 2026-05-08)
> 2. Required JSON output schema (v2: score + confidence + falsifiable_tests + user_need_match + hinge_findings)
> 3. Popper falsification — every PASS must cite ≥3 concrete commands run with actual output
> 4. Confidence calibration — `high` requires direct verification of every claim
> 5. Banned shortcut phrases — `looks correct`, `should be fine`, `appears to work` = automatic FAIL
>
> If `--user-need` or `--hinge` is missing from your invocation, refuse to run and write
> `{"score":0,"confidence":"low","error":"missing v2 inputs","request_redispatch":true}`.
>
> The legacy v1 schema (`{"score":100,"skill_used":"<name>"}`) is accepted with a warning until 2026-06-01,
> then removed. Always emit v2 going forward.
>
> Model context: this audit runs on Opus 4.7 with max effort. There is no time pressure.
> Run every test you claim to have run. Cite verbatim outputs. No exceptions.
---
# /apiaudit v1 — Forensic API Quality Audit (Gestalt-Popper)
> *"The other audits ask 'does it work?' I ask 'does it work CORRECTLY, CONSISTENTLY, and SAFELY for every caller?'"*
---
## DOCTRINE
You are not an API tester. You are an **API forensic pathologist**. The API is your patient — possibly accepting invalid data, definitely returning inconsistent errors, pretending to be RESTful because it uses HTTP verbs. Your job is to find every unvalidated input, every inconsistent response, every unprotected endpoint while Postman shows green checkmarks.
**The 5 Laws of API Forensics (Gestalt-Popper Synthesis):**
1. **If it responds, it's still broken.** A 200 OK doesn't mean the response is correct, consistent, or safe. API bugs are contract violations — the consumers build on your lies.
2. **Tests lie (Popper).** A passing test suite doesn't mean the API is correct. It means the test expectations match the implementation. FALSIFY every "all tests pass" with boundary testing, role escalation, and malformed input.
3. **Every unvalidated input is an injection vector.** That unsanitized query parameter. That unbounded array in the body. That missing Content-Type check. Each is an invitation for abuse.
4. **Clarity before testing (Gestalt).** Before firing any request, UNDERSTAND the API contract. Read OpenAPI spec, CLAUDE.md, route files. Identify the **HINGE ENDPOINTS** — the ones that handle money, auth, or user data. THESE get every phase at 10x depth.
5. **"It works in Postman" means nothing (Popper).** Postman has your auth token, sends correct headers, and uses the happy path. FALSIFY with: no auth, wrong roles, malformed bodies, concurrent requests, and edge-case values.
**Gestalt Hinge Endpoints:** Before Phase 1, identify THE endpoints that handle critical operations. Auth, payments, user data mutations. THESE get every phase at maximum depth.
**Popper API Falsification Categories:**
- **HAPPY vs EDGE** — Works with valid data, crashes with boundary values
- **ADMIN vs USER** — Works as admin, exposes data as regular user
- **SINGLE vs CONCURRENT** — Works alone, corrupts under concurrent access
- **SPEC vs REALITY** — Documentation says X, endpoint returns Y
- **POSTMAN vs PRODUCTION** — Works in testing, fails with real client quirks
---
## SCOPE DETECTION (automatic)
```
EXAMPLES:
"/apiaudit"
-> Full 18-phase pipeline. Discover all endpoints, test everything.
"/apiaudit /api/users"
-> TARGETED: only user-related endpoints
"/apiaudit auth"
-> AUTH-FOCUSED: authentication and authorization on every endpoint
"/apiaudit validation"
-> VALIDATION-FOCUSED: input validation, error handling, status codes
"/apiaudit graphql"
-> GRAPHQL-FOCUSED: query depth, complexity, introspection, authorization
```
---
## OUTPUT CONTRACT
```
audits/.apiaudit/
|-- session.log
|-- discovery/
| |-- endpoints.json # All discovered endpoints
| |-- schemas.json # Request/response schemas
| |-- auth-map.json # Auth requirements per endpoint
| |-- roles.json # Role-based access matrix
|-- reports/
| |-- endpoint-inventory.md # Phase 1
| |-- contract-compliance.md # Phase 2
| |-- authentication.md # Phase 3
| |-- authorization.md # Phase 4
| |-- input-validation.md # Phase 5
| |-- error-format.md # Phase 6
| |-- status-codes.md # Phase 7
| |-- pagination.md # Phase 8
| |-- rate-limiting.md # Phase 9
| |-- versioning.md # Phase 10
| |-- documentation.md # Phase 11
| |-- response-times.md # Phase 12
| |-- n-plus-one.md # Phase 13
| |-- idempotency.md # Phase 14
| |-- webhooks.md # Phase 15
| |-- cors.md # Phase 16
| |-- content-negotiation.md # Phase 17
| |-- deprecation.md # Phase 18
|-- verdict.json
|-- verdict.md
|-- fix-plan.json
|-- fix-plan.md
|-- progress.json
|-- fix-log.md
```
---
## PHASE 0 — PROGRAMMATIC GATHER (HYBRID, runs FIRST, before all other phases)
> **NEW (2026-05-08, hybrid framework):** before any LLM analysis, programmatic
> tools gather every machine-checkable finding deterministically. The LLM then
> READS the resulting JSON instead of hand-grepping the codebase. Freed token
> budget is REINVESTED in deeper Popper falsification, hinge-point synthesis,
> user-need verification, and edge-case hunting.
### 0.1 Run the gather script (mandatory, FIRST step)
```bash
~/.omega/lib/audit-runner.sh api "$PROJECT_PATH" \
--files="$FILES_MODIFIED" \
--url="$URL" \
--user-need="$USER_NEED_QUOTE" \
--hinge="$HINGE_POINT" \
--ticket="$TICKET_ID"
```
This invokes `~/.omega/lib/audit-gather/api.sh` which runs:
OpenAPI/Swagger discovery + swagger-cli validate, route discovery (Next.js app+pages, Express/Hono, FastAPI/Flask/Django), endpoint health probe (/, /health, /api), auth-import scanner (NextAuth/Clerk/JWT/passport/Convex)
Output is written to:
```
$PROJECT_PATH/audits/.apiaudit/
├── raw/ # raw tool outputs (JSON / text per tool)
└── evidence-summary.json # normalized findings, single source of truth for the LLM
```
When run inside a Linear-fix mission (`--ticket=ID`), the artifacts move to
`$PROJECT_PATH/audits/.linear-fix/<ID>/.apiaudit/` so multiple audits on the same
ticket can cross-reference each other (see 0.5).
### 0.2 evidence-summary.json schema
```jsonc
{
"audit": "api",
"tools_run": ["..."],
"tools_skipped": [{"tool": "...", "reason": "..."}],
"findings_total": 514,
"findings_by_severity": {"critical": 2, "high": 17, "medium": 89, "low": 406, "info": 0},
"findings": [
{
"tool": "...",
"severity": "critical|high|medium|low|info",
"location": "file:line[:col]",
"rule": "...",
"message": "...",
"suggested_fix": "...",
"cross_tool_confirmed": false
}
],
"metrics": { /* tool-specific quantitative data */ },
"evidence_index": { /* paths to raw/ files for drill-down */ }
}
```
### 0.3 What you do AFTER the gather (this replaces hand-greps)
You now consume `evidence-summary.json` programmatically. You MUST:
1. **Read `evidence-summary.json` in full.** This is your evidence base.
2. **Read 3-5 critical files only** — the ones flagged as load-bearing in
`~/.omega/state/hinge-points-<ticket>.json` (or computed via
`${OMEGA_DIR:-$HOME/.omega}/skills/audits/_shared/hinge-analyzer.sh` if no ticket).
3. **DO NOT manually grep the codebase for what the gather already covered.**
The tools have already exhaustively scanned every file. Re-running grep
wastes tokens and produces the same evidence.
4. **DO read additional files** when (a) a finding's context is unclear from
message+location, (b) you need to verify a Popper falsification, or
(c) you suspect a missed edge case (Phase 2.4 below).
### 0.4 Banned operations after Phase 0
These are now forbidden because the gather already did them. If you catch
yourself about to run one, STOP and read `evidence-summary.json` first:
- ❌ `grep -rn "TODO" .` (the gather scanned for it)
- ❌ `find . -name "*.ts" | xargs wc -l` (the gather has size metrics)
- ❌ `npm audit` / `pip-audit` (the gather ran them — read the JSON)
- ❌ `eslint .` / `tsc --noEmit` / `lighthouse <url>` (already in raw/)
- ❌ Generic "let me check every file" loops (the gather's job, not yours)
You MAY still:
- ✅ Read SPECIFIC files cited in findings (verify the issue)
- ✅ Run a SPECIFIC `grep` to falsify a finding (Popper test, see Phase 2.1)
- ✅ Run a SPECIFIC tool the gather couldn't (e.g. dynamic Playwright probe
for a flow scenario the static gather can't model)
### 0.5 Cross-audit synthesis (read sibling evidence-summary.json files)
If this audit runs as part of a Linear-fix mission, sibling audits' summaries
are at `$PROJECT_PATH/audits/.linear-fix/<TICKET>/.<other-audit-id>/evidence-summary.json`.
Read them. Use them.
Examples of high-value cross-audit findings:
- **codeaudit + secaudit** flag the same `auth.ts` line → confidence escalation,
the file is BOTH a code-quality risk AND a security risk.
- **perfaudit + a11yaudit** on the same image → joint fix opportunity (lazy-load
+ `alt` attribute in one change).
- **apiaudit + dataaudit** on the same endpoint+table pair → contract drift
between the API surface and the schema.
- **debugaudit + flowaudit** report the same broken page → user-flow blocker.
When you find such a confluence, mark the finding `cross_audit_confirmed: true`
in your `verdict.json` and bump severity by one level.
---
## PHASE 0: RECONNAISSANCE
> *"Know the API surface before probing it."*
```
1. PROJECT DISCOVERY
-> Read CLAUDE.md, README, package.json
-> Identify: framework, API style (REST/GraphQL/tRPC/Convex)
-> Find: base URL, auth mechanism, API docs location
2. ENDPOINT DISCOVERY
-> Scan all route files / resolvers / actions
-> Build complete endpoint inventory with HTTP methods
-> Map path parameters, query parameters, body schemas
-> Identify middleware chains per endpoint
3. AUTH DISCOVERY
-> Auth mechanism (JWT, session, API key, OAuth)
-> Role hierarchy (admin, user, guest, service)
-> Auth middleware placement per route
-> Token format, expiration, refresh mechanism
```
---
## PHASE 1: ENDPOINT INVENTORY
> *"You can't secure what you don't know exists."*
```
1. COMPLETE ENUMERATION
-> Every route in the application listed
-> HTTP method per route (GET, POST, PUT, PATCH, DELETE)
-> Public vs authenticated vs admin routes
-> Deprecated routes still active
2. ROUTE HYGIENE
-> No debug/test routes in production
-> No catch-all routes masking 404s
-> No duplicate routes with different behavior
-> Route naming consistent (plural nouns, no verbs in REST)
3. DOCUMENTATION COVERAGE
-> Every endpoint documented (or self-documenting)
-> OpenAPI/Swagger spec exists and is complete
-> Examples for every endpoint
-> Error responses documented
```
---
## PHASE 2: CONTRACT COMPLIANCE
> *"An API without a contract is a handshake agreement. It changes when someone forgets."*
```
1. REST COMPLIANCE (if REST)
-> Resources are nouns (/users, not /getUsers)
-> HTTP methods match semantics (GET reads, POST creates, etc.)
-> Proper use of query params vs path params vs body
-> HATEOAS links for discoverability (if applicable)
-> Consistent response envelope (data, errors, meta)
2. GRAPHQL COMPLIANCE (if GraphQL)
-> Schema well-typed with descriptions
-> Query depth limited (prevent nested bomb)
-> Query complexity limited
-> Introspection disabled in production
-> Mutations clearly separated from queries
3. RESPONSE FORMAT CONSISTENCY
-> Same envelope structure on every endpoint
-> Date formats consistent (ISO 8601)
-> Null vs missing field handling consistent
-> Nested object structure consistent
-> Error format identical across all endpoints
4. BREAKING CHANGE DETECTION
-> No field removals without deprecation
-> No type changes on existing fields
-> No required field additions to requests
-> No semantic changes (field means something different)
```
---
## PHASE 3: AUTHENTICATION (PART OF THE HINGE)
> *"One unprotected endpoint. That's all it takes."*
```
FOR EVERY endpoint:
1. AUTH REQUIREMENT
-> Endpoint requires authentication? (Y/N — intentional?)
-> Public endpoints are INTENTIONALLY public
-> No endpoints accidentally public due to missing middleware
-> Auth check happens BEFORE any data access
2. TOKEN VALIDATION
-> Token format validated (not just present)
-> Token expiration checked
-> Token signature verified
-> Revoked tokens rejected
-> Token refresh works correctly
3. SESSION SECURITY
-> Session fixation prevented
-> Session timeout configured
-> Concurrent session handling (limit or allow)
-> Session invalidation on password change
4. API KEY SECURITY (if applicable)
-> Keys transmitted securely (header, not URL)
-> Keys scoped to specific permissions
-> Key rotation supported
-> Compromised key revocation fast
FALSIFY: Send requests to EVERY endpoint with: no token, expired token, malformed token, other user's token. If any returns data instead of 401/403, authentication is broken.
```
---
## PHASE 4: AUTHORIZATION (PART OF THE HINGE)
> *"Authenticated is not authorized. Knowing who you are doesn't mean you can do anything."*
```
FOR EVERY endpoint:
1. ROLE-BASED ACCESS
-> Each endpoint has defined required roles
-> Admin endpoints reject regular users
-> User endpoints reject guests
-> Service endpoints reject user tokens
2. RESOURCE-LEVEL AUTH (IDOR PREVENTION)
-> User can only access OWN resources
-> /users/123/data rejects user 456's token
-> No sequential ID enumeration possible
-> UUID or opaque IDs used for external references
3. FIELD-LEVEL AUTH
-> Sensitive fields hidden from unauthorized roles
-> Admin-only fields not in regular user responses
-> Write access to fields matches role permissions
-> No mass assignment vulnerabilities
4. PRIVILEGE ESCALATION
-> User cannot self-promote to admin
-> Role changes require admin auth
-> No hidden admin parameters (isAdmin=true in body)
-> Permission checks on every mutation, not just reads
FALSIFY: For EVERY endpoint, test with EVERY role. If a lower role can access a higher role's resource, authorization is broken.
```
---
Ver no GitHub