@testsmith/api-spector 0.6.0 → 0.6.2

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.
Files changed (42) hide show
  1. package/docs/ai/api-spector-scripting-reference.md +149 -0
  2. package/docs/ai/collection-file-format.md +110 -0
  3. package/docs/ai/functional-testing-guide.md +145 -0
  4. package/docs/ai/security-testing-guide.md +253 -0
  5. package/out/main/agents.js +2 -1
  6. package/out/main/chunks/{snapshots-Y33M1SEy.js → broker-client-WEymdqAK.js} +119 -10
  7. package/out/main/chunks/{cli-common-BKYgsbGB.js → cli-common-vASoDfQH.js} +3 -2
  8. package/out/main/chunks/data-files-Br2h3Dt2.js +85 -0
  9. package/out/main/chunks/escape-BwPM4Tf6.js +9 -0
  10. package/out/main/chunks/{handle-BFaeFA0A.js → handle-CL-nWtYA.js} +11 -2
  11. package/out/main/chunks/{import-D9LH0isB.js → import-DdXhO56X.js} +2 -2
  12. package/out/main/chunks/{request-collection-BQIo1765.js → request-collection-Hqh3I3rs.js} +75 -15
  13. package/out/main/chunks/{request-exec-5_3279w1.js → request-exec-DAFA6Fap.js} +19 -1
  14. package/out/main/chunks/{soap-handler-CWn3o6Py.js → soap-handler-BAPCALkN.js} +2 -2
  15. package/out/main/compare.js +2 -1
  16. package/out/main/contract.js +50 -147
  17. package/out/main/coverage.js +2 -1
  18. package/out/main/generate-tests.js +2 -1
  19. package/out/main/index.js +131 -36
  20. package/out/main/lib.js +2 -2
  21. package/out/main/mock.js +2 -1
  22. package/out/main/record.js +2 -1
  23. package/out/main/runner.js +95 -13
  24. package/out/main/wsdl.js +5 -4
  25. package/out/preload/index.js +21 -3
  26. package/out/renderer/assets/{GraphQLEditor-DITvPhtG.js → GraphQLEditor-DtppmZJO.js} +3 -1
  27. package/out/renderer/assets/{SoapEditor-Bf-oE-rS.js → SoapEditor-BwSm12wH.js} +4 -2
  28. package/out/renderer/assets/ajv-2MAg6kGF.js +6153 -0
  29. package/out/renderer/assets/codemirror-F6m3Hm1M.js +26552 -0
  30. package/out/renderer/assets/index-B3mtLdU3.css +2 -0
  31. package/out/renderer/assets/{index-MMIHKSKx.js → index-D6-zmXen.js} +17493 -49301
  32. package/out/renderer/index.html +4 -2
  33. package/package.json +4 -2
  34. package/src/cli/agent-templates/aider/conventions.md +10 -0
  35. package/src/cli/agent-templates/claude/skills/api-spector-api-audit.md +135 -0
  36. package/src/cli/agent-templates/claude/skills/api-spector-functional-tests.md +73 -0
  37. package/src/cli/agent-templates/claude/skills/api-spector-generate-mocks.md +182 -0
  38. package/src/cli/agent-templates/claude/skills/api-spector-security-tests.md +73 -0
  39. package/src/cli/agent-templates/copilot/copilot-instructions.md +38 -0
  40. package/src/cli/agent-templates/cursor/rules/api-spector.mdc +21 -0
  41. package/src/cli/agent-templates/windsurf/windsurfrules +19 -0
  42. package/out/renderer/assets/index-CkHujZU3.css +0 -2
@@ -5,8 +5,10 @@
5
5
  <meta charset="UTF-8" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>API Spector</title>
8
- <script type="module" crossorigin src="./assets/index-MMIHKSKx.js"></script>
9
- <link rel="stylesheet" crossorigin href="./assets/index-CkHujZU3.css">
8
+ <script type="module" crossorigin src="./assets/index-D6-zmXen.js"></script>
9
+ <link rel="modulepreload" crossorigin href="./assets/codemirror-F6m3Hm1M.js">
10
+ <link rel="modulepreload" crossorigin href="./assets/ajv-2MAg6kGF.js">
11
+ <link rel="stylesheet" crossorigin href="./assets/index-B3mtLdU3.css">
10
12
  </head>
11
13
 
12
14
  <body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@testsmith/api-spector",
3
3
  "productName": "API Spector",
4
- "version": "0.6.0",
4
+ "version": "0.6.2",
5
5
  "description": "Local-first API testing tool to inspect, test and mock APIs",
6
6
  "repository": {
7
7
  "type": "git",
@@ -26,7 +26,9 @@
26
26
  "bin/",
27
27
  "resources/splash.html",
28
28
  "build/icon.png",
29
- "build/icon.ico"
29
+ "build/icon.ico",
30
+ "src/cli/agent-templates/",
31
+ "docs/ai/"
30
32
  ],
31
33
  "scripts": {
32
34
  "dev": "electron-vite dev",
@@ -0,0 +1,10 @@
1
+ # API Spector Conventions
2
+
3
+ This project uses API Spector for API testing. Reference docs are in `.aider/docs/`:
4
+
5
+ - `api-spector-scripting-reference.md` — `sp.*` API (assertions, variables, TOTP, JSONPath)
6
+ - `collection-file-format.md` — `.spector` and `.env.json` structure
7
+ - `functional-testing-guide.md` — functional test design patterns
8
+ - `security-testing-guide.md` — OWASP API Top 10 test patterns
9
+
10
+ Use `sp.test()` for assertions, `sp.response.json()` for body parsing, `sp.environment.set()` for cross-request variables.
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: Audit API for Inconsistencies
3
+ description: Analyze an OpenAPI spec for design inconsistencies, naming violations, missing fields, and best-practice deviations
4
+ ---
5
+
6
+ # Audit API for Inconsistencies
7
+
8
+ Analyze an OpenAPI spec and produce a detailed audit report of design inconsistencies, naming violations, missing documentation, and deviations from REST best practices. This is a read-only analysis — no tests or collections are generated.
9
+
10
+ ## Execution steps — follow in order
11
+
12
+ 1. Ask the user for an OpenAPI spec URL or file path
13
+ 2. Fetch/read the spec
14
+ 3. Run every check listed below
15
+ 4. **Call the Write tool to create `api-audit-report.md` in the project directory.** Do NOT just print results in chat — write the full report to disk as a file.
16
+ 5. After writing, tell the user: "Audit report written to api-audit-report.md" and show a brief summary (total errors/warnings/info count) in chat.
17
+ 6. Rate each finding as: **error** (breaks clients), **warning** (inconsistent/confusing), or **info** (suggestion)
18
+
19
+ ## Checks to perform
20
+
21
+ ### 1. Naming consistency
22
+
23
+ - **Path casing**: are paths consistently kebab-case (`/user-profiles`), snake_case (`/user_profiles`), or camelCase (`/userProfiles`)? Flag any that deviate from the majority.
24
+ - **Path pluralization**: are collection endpoints plural (`/users`) and singleton endpoints singular (`/user/{id}`)? Flag inconsistent pluralization like `/user` for a list and `/products` for another list.
25
+ - **Parameter naming**: are path/query params consistently camelCase, snake_case, or kebab-case? Flag mixed conventions (e.g. `userId` in one endpoint, `brand_id` in another).
26
+ - **Schema property naming**: same casing check across all request/response schemas. Flag if some schemas use `firstName` and others use `first_name`.
27
+ - **Operation IDs**: are they present? Are they consistently formatted (camelCase, snake_case)?
28
+
29
+ ### 2. HTTP method usage
30
+
31
+ - **GET with request body**: GET endpoints should not have a request body. Flag any that do.
32
+ - **POST for retrieval**: POST endpoints that only return data (no creation) — might be better as GET with query params.
33
+ - **DELETE returning body**: flag DELETE endpoints that return 200 with a body (should typically be 204 No Content).
34
+ - **PATCH vs PUT confusion**: flag PUT endpoints that accept partial updates (should be PATCH) or PATCH endpoints that require all fields (should be PUT).
35
+
36
+ ### 3. Response consistency
37
+
38
+ - **Status codes**: do similar operations return the same codes? E.g. all successful creates return 201, all deletes return 204. Flag inconsistencies (one POST returns 200, another returns 201).
39
+ - **Error schema**: do all error responses use the same shape? Flag if some return `{ "message": "..." }` and others return `{ "error": "..." }` or `{ "errors": [...] }`.
40
+ - **Pagination**: do all list endpoints use the same pagination structure? Flag if some use `page/per_page`, others use `offset/limit`, and others have no pagination.
41
+ - **Envelope consistency**: do some endpoints wrap data in `{ "data": [...] }` while others return bare arrays? Flag the inconsistency.
42
+
43
+ ### 4. Missing documentation
44
+
45
+ - **Endpoints without descriptions**: list them.
46
+ - **Parameters without descriptions**: list the count per endpoint.
47
+ - **Schemas without property descriptions**: flag schemas where >50% of properties lack descriptions.
48
+ - **Missing examples**: flag request/response schemas without examples (makes the spec harder to use).
49
+ - **Missing operationId**: flag endpoints without operationId (breaks code generators).
50
+
51
+ ### 5. Schema issues
52
+
53
+ - **Identical schemas with different names**: detect schemas that have the same properties/types but different names (copy-paste duplication).
54
+ - **Overly permissive types**: flag `type: string` without `format`, `minLength`, `maxLength`, or `pattern` for fields that should be constrained (email, phone, URL, date).
55
+ - **Missing required fields**: flag schemas that define properties like `id`, `email`, `name` but don't list them in `required`.
56
+ - **Inconsistent ID types**: flag if some schemas use `type: integer` for IDs and others use `type: string`.
57
+ - **Nullable vs optional confusion**: flag fields that are nullable but not marked as such, or optional fields that should be required.
58
+
59
+ ### 6. Security
60
+
61
+ - **Endpoints without security**: flag endpoints that don't reference any security scheme (and aren't public-by-design like login/register).
62
+ - **Inconsistent auth**: flag if some endpoints use Bearer tokens and others use API keys without clear reason.
63
+ - **Sensitive data in query params**: flag endpoints that pass tokens, passwords, or keys as query parameters (should be headers or body).
64
+ - **Missing security schemes**: flag if the spec references security schemes that aren't defined.
65
+
66
+ ### 7. Versioning & deprecation
67
+
68
+ - **Mixed versioning**: flag if some paths use `/v1/...` and others use `/v2/...` or no version.
69
+ - **Deprecated endpoints without replacement**: flag endpoints marked deprecated that don't document what to use instead.
70
+ - **Deprecated endpoints without timeline**: flag deprecated endpoints that don't specify when they'll be removed.
71
+
72
+ ### 8. REST best practices
73
+
74
+ - **Nested resources too deep**: flag paths with more than 3 levels of nesting (e.g. `/users/{id}/orders/{orderId}/items/{itemId}/details`).
75
+ - **Verbs in paths**: flag paths that contain action verbs (e.g. `/getUser`, `/createOrder`, `/deleteProduct`) — the HTTP method should convey the action.
76
+ - **Inconsistent trailing slashes**: flag if some paths end with `/` and others don't.
77
+ - **Missing CORS headers in spec**: flag if no security headers or CORS configuration is documented.
78
+
79
+ ## Output format
80
+
81
+ ```markdown
82
+ # API Audit Report: <API Name>
83
+
84
+ **Spec**: <URL or file>
85
+ **Version**: <spec version>
86
+ **Endpoints analyzed**: <count>
87
+ **Schemas analyzed**: <count>
88
+
89
+ ## Summary
90
+
91
+ | Category | Errors | Warnings | Info |
92
+ |---|---|---|---|
93
+ | Naming consistency | 0 | 3 | 1 |
94
+ | HTTP method usage | 1 | 0 | 0 |
95
+ | Response consistency | 0 | 2 | 0 |
96
+ | ... | ... | ... | ... |
97
+ | **Total** | **1** | **5** | **1** |
98
+
99
+ ## Findings
100
+
101
+ ### Naming Consistency
102
+
103
+ #### ⚠️ WARNING: Mixed parameter naming convention
104
+ - `GET /users/{userId}` uses camelCase
105
+ - `GET /brands/{brand_id}` uses snake_case
106
+ - `GET /categories/{categoryId}` uses camelCase
107
+ **Recommendation**: Standardize on one convention (snake_case is most common in REST APIs).
108
+
109
+ #### ℹ️ INFO: Consider adding operationId to all endpoints
110
+ - 12 out of 45 endpoints lack operationId
111
+ **Recommendation**: Add operationId for better code generation support.
112
+
113
+ ### HTTP Method Usage
114
+
115
+ #### 🔴 ERROR: GET endpoint has request body
116
+ - `GET /reports/custom` defines a request body
117
+ **Recommendation**: Use query parameters or POST for complex filters.
118
+
119
+ ...
120
+ ```
121
+
122
+ ## Important rules
123
+
124
+ - This is **analysis only** — don't generate tests, collections, or code
125
+ - Be specific: list the exact endpoints/schemas that have issues, don't just say "some endpoints"
126
+ - Provide concrete recommendations for each finding
127
+ - Don't flag things that are valid design choices (e.g. using UUIDs vs integers for IDs is a choice, not an inconsistency — unless both are used)
128
+ - Group related findings (e.g. all naming issues together)
129
+ - Count the total findings per severity in the summary table
130
+
131
+ ## Token efficiency
132
+
133
+ - Don't reproduce the full spec in the output
134
+ - Cite endpoints by method + path only
135
+ - If 20+ endpoints have the same issue, show 3 examples and say "and N more"
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: Generate Functional Tests from OpenAPI
3
+ description: Fetch an OpenAPI spec and generate an API Spector collection with functional test scripts
4
+ ---
5
+
6
+ # Generate Functional Tests from OpenAPI
7
+
8
+ ## Execution steps — follow in order
9
+
10
+ ### 1. Get the spec
11
+
12
+ Ask the user for an OpenAPI spec URL or file path. Fetch/read it.
13
+
14
+ ### 2. Create the workspace + collection + environment
15
+
16
+ #### If workspace.json already exists
17
+
18
+ Read it. Add the new collection/environment to existing arrays.
19
+
20
+ #### If no workspace exists
21
+
22
+ Create:
23
+ ```
24
+ {project}/
25
+ ├── workspace.json
26
+ ├── collections/{name}.spector
27
+ └── environments/{name}.env.json
28
+ ```
29
+
30
+ Environment must include `baseUrl` from the spec + credential placeholders.
31
+
32
+ ### 3. Tell the user
33
+
34
+ After creating everything, tell the user:
35
+ - "Workspace created with collection and environment"
36
+ - "Open the workspace in API Spector, fill in environment variables, and run"
37
+
38
+ ## URL and path parameters — CRITICAL
39
+
40
+ NEVER use `:param` or `{param}`. Always use `{{variable}}`:
41
+ - WRONG: `{{baseUrl}}/brands/:id`
42
+ - RIGHT: `{{baseUrl}}/brands/{{brand_id}}`
43
+
44
+ Every `{{var}}` in a URL must be set by a prior request via `sp.environment.set("var", ...)`.
45
+
46
+ ## Variable naming — CRITICAL
47
+
48
+ Use simple snake_case. The name in `sp.environment.set("x", ...)` MUST exactly match every `{{x}}` reference.
49
+
50
+ Before outputting, build a dependency chain and verify every `{{var}}` has a matching setter that runs first.
51
+
52
+ ## Collection structure
53
+
54
+ - One folder per API tag
55
+ - `beforeAll` login hook that extracts `{{access_token}}`
56
+ - ONE request per test scenario
57
+ - `postRequestScript` with `sp.test()` assertions
58
+ - Path params as `paramType: "path"` in params array AND `{{var}}` in URL
59
+ - Use `{{baseUrl}}` prefix
60
+ - Order: list/create before get/update/delete (so IDs are extracted first)
61
+
62
+ ## References
63
+
64
+ - `.claude/docs/api-spector-scripting-reference.md` — `sp.*` API
65
+ - `.claude/docs/functional-testing-guide.md` — test patterns
66
+ - `.claude/docs/collection-file-format.md` — JSON format
67
+
68
+ ## Token efficiency
69
+
70
+ - Extract only paths, methods, required fields from spec
71
+ - Ask which tags to cover, generate one at a time
72
+ - Skip boilerplate headers (Accept/Content-Type are defaults)
73
+ - Use compact JSON
@@ -0,0 +1,182 @@
1
+ ---
2
+ name: Generate Mock Server from OpenAPI
3
+ description: Create an API Spector mock server with dynamic responses from an OpenAPI spec
4
+ ---
5
+
6
+ # Generate Mock Server from OpenAPI
7
+
8
+ ## What to do
9
+
10
+ 1. Ask the user for an OpenAPI spec URL or file path
11
+ 2. Ask which endpoints/tags to mock (or all)
12
+ 3. Ask what port to use (default: 3900)
13
+ 4. Generate a `.mock.json` file with routes for each endpoint
14
+
15
+ ## Mock server file format
16
+
17
+ ```json
18
+ {
19
+ "version": "1.0",
20
+ "id": "uuid",
21
+ "name": "My API Mock",
22
+ "port": 3900,
23
+ "routes": [
24
+ {
25
+ "id": "uuid",
26
+ "method": "GET",
27
+ "path": "/users/:id",
28
+ "statusCode": 200,
29
+ "headers": { "Content-Type": "application/json" },
30
+ "body": "{ ... }",
31
+ "description": "Get user by ID",
32
+ "script": "// optional JS to make response dynamic"
33
+ }
34
+ ]
35
+ }
36
+ ```
37
+
38
+ ### Route fields
39
+ - `method`: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, or ANY
40
+ - `path`: Express-style with `:param` for path params (e.g. `/users/:id`)
41
+ - `statusCode`: default HTTP status
42
+ - `headers`: response headers (Content-Type defaults to application/json)
43
+ - `body`: static JSON string response body
44
+ - `script`: JavaScript that runs before sending. Has access to `request`, `response`, `faker`, `dayjs`
45
+ - `delay`: optional ms delay before responding
46
+
47
+ ### Path params
48
+
49
+ Use Express-style `:param` syntax, NOT OpenAPI `{param}`:
50
+ - OpenAPI: `/users/{userId}` → Mock: `/users/:userId`
51
+
52
+ ### Script context
53
+
54
+ ```javascript
55
+ // Available in route scripts:
56
+ request.method // "GET"
57
+ request.path // "/users/42"
58
+ request.params // { id: "42" }
59
+ request.query // { page: "1" }
60
+ request.body // parsed JSON body (or null)
61
+ request.headers // { authorization: "Bearer ...", ... }
62
+
63
+ response.statusCode // mutable — change to e.g. 404
64
+ response.body // mutable — replace the response body
65
+ response.headers // mutable — add/change headers
66
+
67
+ faker // @faker-js/faker — generate dynamic data
68
+ dayjs // dayjs — date/time helpers
69
+ ```
70
+
71
+ ## Making responses dynamic
72
+
73
+ Use `script` on routes to generate realistic data with faker:
74
+
75
+ ### List endpoint with faker data
76
+ ```json
77
+ {
78
+ "method": "GET",
79
+ "path": "/users",
80
+ "statusCode": 200,
81
+ "body": "[]",
82
+ "script": "const users = Array.from({length: 10}, (_, i) => ({ id: i + 1, name: faker.person.fullName(), email: faker.internet.email(), role: faker.helpers.arrayElement(['admin', 'user']), created_at: faker.date.recent().toISOString() })); response.body = JSON.stringify(users);"
83
+ }
84
+ ```
85
+
86
+ ### Single resource using path param
87
+ ```json
88
+ {
89
+ "method": "GET",
90
+ "path": "/users/:id",
91
+ "statusCode": 200,
92
+ "body": "{}",
93
+ "script": "response.body = JSON.stringify({ id: request.params.id, name: faker.person.fullName(), email: faker.internet.email(), created_at: faker.date.recent().toISOString() });"
94
+ }
95
+ ```
96
+
97
+ ### POST that echoes back with generated ID
98
+ ```json
99
+ {
100
+ "method": "POST",
101
+ "path": "/users",
102
+ "statusCode": 201,
103
+ "body": "{}",
104
+ "script": "const body = request.body || {}; response.body = JSON.stringify({ id: faker.string.uuid(), ...body, created_at: dayjs().toISOString() });"
105
+ }
106
+ ```
107
+
108
+ ### Conditional responses (not found, validation)
109
+ ```json
110
+ {
111
+ "method": "GET",
112
+ "path": "/users/:id",
113
+ "statusCode": 200,
114
+ "body": "{}",
115
+ "script": "if (request.params.id === '0' || request.params.id === 'notfound') { response.statusCode = 404; response.body = JSON.stringify({ message: 'User not found' }); } else { response.body = JSON.stringify({ id: request.params.id, name: faker.person.fullName() }); }"
116
+ }
117
+ ```
118
+
119
+ ### Auth validation mock
120
+ ```json
121
+ {
122
+ "method": "GET",
123
+ "path": "/users/me",
124
+ "statusCode": 200,
125
+ "body": "{}",
126
+ "script": "if (!request.headers.authorization) { response.statusCode = 401; response.body = JSON.stringify({ message: 'Unauthorized' }); } else { response.body = JSON.stringify({ id: 1, name: faker.person.fullName(), email: faker.internet.email() }); }"
127
+ }
128
+ ```
129
+
130
+ ## What to generate per endpoint type
131
+
132
+ | OpenAPI pattern | Mock behavior |
133
+ |---|---|
134
+ | `GET /resources` (list) | faker array of 5-10 items with realistic field values |
135
+ | `GET /resources/:id` | faker single item using `request.params.id` |
136
+ | `POST /resources` | 201 + echo body with generated `id` and `created_at` |
137
+ | `PUT /resources/:id` | 200 + echo body merged with `request.params.id` |
138
+ | `PATCH /resources/:id` | 200 + echo body merged with `request.params.id` |
139
+ | `DELETE /resources/:id` | 204 + empty body |
140
+ | Auth endpoint (`POST /login`) | Return `{ access_token: faker.string.uuid() }` |
141
+
142
+ ## When to use static vs dynamic
143
+
144
+ - **IDs, timestamps, emails, names**: always dynamic (faker)
145
+ - **Enum fields** (status, role, type): use `faker.helpers.arrayElement([...])`
146
+ - **Booleans**: use `faker.datatype.boolean()`
147
+ - **Prices/amounts**: use `faker.number.float({ min: 1, max: 999, fractionDigits: 2 })`
148
+ - **Fixed structure fields** (pagination meta, error shapes): static in `body`
149
+ - **Path-param-dependent data**: use `request.params.x` in scripts
150
+
151
+ ## Token efficiency
152
+
153
+ - Extract only paths, methods, and response schemas from the spec — skip descriptions
154
+ - Ask which tags to mock before generating all
155
+ - Generate compact JSON
156
+ - One script per route, no comments in scripts (they're in `description` field)
157
+
158
+ ## File output — create or update workspace
159
+
160
+ ### If no workspace.json exists, create the full workspace:
161
+
162
+ ```
163
+ <project>/
164
+ ├── workspace.json
165
+ └── mocks/
166
+ └── <api-name>.mock.json
167
+ ```
168
+
169
+ `workspace.json`:
170
+ ```json
171
+ {
172
+ "version": "1.0",
173
+ "collections": [],
174
+ "environments": [],
175
+ "mocks": ["mocks/<api-name>.mock.json"],
176
+ "activeEnvironmentId": null
177
+ }
178
+ ```
179
+
180
+ ### If workspace.json already exists:
181
+
182
+ Add the mock file path to the existing `mocks` array (create the array if it doesn't exist). Don't overwrite collections or environments.
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: Generate Security Tests from OpenAPI (OWASP API Top 10)
3
+ description: Generate OWASP API Top 10 security test cases with attack payloads for API Spector
4
+ ---
5
+
6
+ # Generate Security Tests from OpenAPI (OWASP API Top 10)
7
+
8
+ ## Execution steps — follow in order
9
+
10
+ ### 1. Get the spec
11
+
12
+ Ask the user for an OpenAPI spec URL or file path. Fetch/read it.
13
+
14
+ ### 2. Analyze auth
15
+
16
+ Check the spec for `securityDefinitions`, `security`, `securitySchemes`, or login endpoints.
17
+
18
+ - **No auth found** → skip BOLA, Broken Auth, Function-Level Auth. Only generate: Injection, Security Config, Resource Consumption, SSRF. Do NOT ask for credentials.
19
+ - **Auth found** → ask for credential variable names (`{{user_a_token}}`, `{{user_b_token}}`, `{{admin_token}}`, `{{user_b_id}}`).
20
+
21
+ ### 3. Create the workspace + collection + environment
22
+
23
+ #### If workspace.json already exists
24
+
25
+ Read it. Add the new security collection/environment to existing arrays.
26
+
27
+ #### If no workspace exists
28
+
29
+ Create:
30
+ ```
31
+ {project}/
32
+ ├── workspace.json
33
+ ├── collections/{name}-security.spector
34
+ └── environments/{name}.env.json
35
+ ```
36
+
37
+ Environment must include `baseUrl` from the spec + credential placeholders (if auth exists).
38
+
39
+ ### 4. Tell the user
40
+
41
+ After creating everything, tell the user:
42
+ - "Workspace created with security collection and environment"
43
+ - "Open the workspace in API Spector, fill in environment variables, and run"
44
+
45
+ ## Applicability rules
46
+
47
+ | Condition | BOLA | Auth | Mass Assign | Func Auth | Injection | SSRF | Config | Resources |
48
+ |---|---|---|---|---|---|---|---|---|
49
+ | Has auth + user IDs in paths | YES | YES | YES | YES | YES | maybe | YES | YES |
50
+ | Has auth, no user IDs | no | YES | YES | maybe | YES | maybe | YES | YES |
51
+ | No auth at all | no | no | maybe | no | YES | maybe | YES | YES |
52
+
53
+ ## URL syntax — CRITICAL
54
+
55
+ NEVER use `:param` or `{param}`. Always use `{{variable}}`:
56
+ - WRONG: `{{baseUrl}}/users/:id`
57
+ - RIGHT: `{{baseUrl}}/users/{{user_b_id}}`
58
+
59
+ ## Variable naming — CRITICAL
60
+
61
+ Use consistent snake_case. `sp.environment.set("x", ...)` must match `{{x}}` everywhere.
62
+
63
+ ## References
64
+
65
+ - `.claude/docs/api-spector-scripting-reference.md` — `sp.*` API
66
+ - `.claude/docs/security-testing-guide.md` — OWASP patterns
67
+ - `.claude/docs/collection-file-format.md` — JSON format
68
+
69
+ ## Token efficiency
70
+
71
+ - Ask which OWASP categories to focus on before generating all
72
+ - Skip categories that don't apply
73
+ - Generate in batches if 20+ endpoints
@@ -0,0 +1,38 @@
1
+ # GitHub Copilot Instructions — API Spector
2
+
3
+ This project uses **API Spector**, a local-first API testing tool. When working with test scripts, collections, or test generation, refer to the documentation in `.github/docs/`.
4
+
5
+ ## Key references
6
+
7
+ - **Scripting API**: See `.github/docs/api-spector-scripting-reference.md` for the full `sp.*` API (assertions, response access, variables, TOTP, JSONPath)
8
+ - **Collection format**: See `.github/docs/collection-file-format.md` for `.spector` file structure
9
+ - **Functional testing**: See `.github/docs/functional-testing-guide.md` for test design patterns
10
+ - **Security testing**: See `.github/docs/security-testing-guide.md` for OWASP API Top 10 patterns
11
+
12
+ ## Quick reference
13
+
14
+ Scripts use the `sp` global:
15
+
16
+ ```javascript
17
+ // Test assertion
18
+ sp.test('name', function() {
19
+ const json = sp.response.json();
20
+ sp.expect(json.field).to.equal("value");
21
+ });
22
+
23
+ // Variable extraction
24
+ sp.environment.set("token", String(sp.response.json().access_token));
25
+
26
+ // Status check
27
+ sp.expect(sp.response.code).to.equal(200);
28
+ ```
29
+
30
+ Variables use `{{name}}` interpolation in URLs, headers, body, and scripts.
31
+
32
+ ## When asked to generate tests
33
+
34
+ 1. Read the relevant `.github/docs/` guide
35
+ 2. Use `sp.test()` blocks with descriptive names
36
+ 3. Parse JSON once: `const json = sp.response.json();`
37
+ 4. Cover: happy path, missing fields, wrong types, auth, edge cases
38
+ 5. Use `sp.environment.set()` for cross-request data flow
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: API Spector API testing tool — scripting API, collection format, and test generation
3
+ globs: ["**/*.spector", "**/*.env.json", "**/workspace.json"]
4
+ ---
5
+
6
+ # API Spector
7
+
8
+ This project uses API Spector for API testing. When editing collection files (`.spector`), environment files (`.env.json`), or generating test scripts, follow these references:
9
+
10
+ - `.cursor/docs/api-spector-scripting-reference.md` — Full `sp.*` scripting API
11
+ - `.cursor/docs/collection-file-format.md` — `.spector` and `.env.json` file structure
12
+ - `.cursor/docs/functional-testing-guide.md` — Functional test design patterns
13
+ - `.cursor/docs/security-testing-guide.md` — OWASP API Top 10 security tests
14
+
15
+ ## Script conventions
16
+
17
+ - Wrap assertions in `sp.test('descriptive name', function() { ... })`
18
+ - Parse JSON once per script: `const json = sp.response.json();`
19
+ - Use `sp.environment.set("key", value)` to pass data between requests
20
+ - Use `{{variable}}` interpolation in URLs, headers, body, and scripts
21
+ - Hooks: `beforeAll` runs once per folder, `before` runs per request
@@ -0,0 +1,19 @@
1
+ # API Spector — Windsurf Rules
2
+
3
+ This project uses API Spector for API testing.
4
+
5
+ ## References
6
+
7
+ When working with test scripts or collection files, read:
8
+ - `.windsurf/docs/api-spector-scripting-reference.md` — Full `sp.*` scripting API
9
+ - `.windsurf/docs/collection-file-format.md` — Collection and environment file format
10
+ - `.windsurf/docs/functional-testing-guide.md` — Functional test patterns
11
+ - `.windsurf/docs/security-testing-guide.md` — OWASP API Top 10 test patterns
12
+
13
+ ## Script conventions
14
+
15
+ - Use `sp.test('name', function() { ... })` for assertions
16
+ - Use `sp.expect(value)` with `.to.equal()`, `.to.include()`, `.to.be.a()`, etc.
17
+ - Parse body: `const json = sp.response.json();`
18
+ - Set variables: `sp.environment.set("key", "value")`
19
+ - Use `{{variable}}` in URLs, headers, body, and scripts