Skip to content

Commit 7e1a1bc

Browse files
committed
Fix fixture payloads, route accuracy, and expected status codes from adversarial review
- Label fixture: use `colorHex` instead of `color` to match CreateLabelDto - Agent fixture: add required `templateKey` and `scopeType` fields - Knowledge fixture: add required `sourceType` field - B-31: use POST method (ExternalImportsController has no GET) - B-91: use `/cards/{id}/provenance` (no single-card GET endpoint exists) - B-104: note that fake proposal ID returns 404 before Idempotency-Key check - B-151: correct expected status to 200 (no admin gate in current code) - Add AbuseContainmentActive to status-to-errorCode mapping table
1 parent 6f8fa85 commit 7e1a1bc

1 file changed

Lines changed: 12 additions & 9 deletions

File tree

docs/testing/manual-validation-b-authz-contracts.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,19 @@ CARD_A=$(curl -s -X POST http://localhost:5000/api/boards/$BOARD_A/cards \
6868
LABEL_A=$(curl -s -X POST http://localhost:5000/api/boards/$BOARD_A/labels \
6969
-H "Content-Type: application/json" \
7070
-H "Authorization: Bearer $TOKEN_A" \
71-
-d '{"name":"Priority","color":"#ff0000"}' | tee /dev/stderr | jq -r '.id')
71+
-d '{"name":"Priority","colorHex":"#ff0000"}' | tee /dev/stderr | jq -r '.id')
7272

73-
## 8. UserA creates an agent profile (for cross-user agent isolation tests)
73+
# 8. UserA creates an agent profile (for cross-user agent isolation tests)
7474
AGENT_A=$(curl -s -X POST http://localhost:5000/api/agents \
7575
-H "Content-Type: application/json" \
7676
-H "Authorization: Bearer $TOKEN_A" \
77-
-d '{"name":"UserA Test Agent","description":"Fixture agent"}' | tee /dev/stderr | jq -r '.id')
77+
-d '{"name":"UserA Test Agent","templateKey":"default","scopeType":"User","description":"Fixture agent"}' | tee /dev/stderr | jq -r '.id')
7878

7979
# 9. UserA creates a knowledge item (for cross-user knowledge isolation tests)
8080
KNOWLEDGE_A=$(curl -s -X POST http://localhost:5000/api/knowledge \
8181
-H "Content-Type: application/json" \
8282
-H "Authorization: Bearer $TOKEN_A" \
83-
-d '{"title":"UserA Knowledge","content":"Fixture content"}' | tee /dev/stderr | jq -r '.id')
83+
-d '{"title":"UserA Knowledge","content":"Fixture content","sourceType":"Manual"}' | tee /dev/stderr | jq -r '.id')
8484

8585
echo "TOKEN_A=$TOKEN_A"
8686
echo "TOKEN_B=$TOKEN_B"
@@ -160,7 +160,7 @@ Note: ASP.NET Core's JWT middleware may return a bare `401` without a JSON body
160160
| B-28 | GET | `/api/knowledge` | 401 | Same |
161161
| B-29 | GET | `/api/export/boards/{random-guid}` | 401 | Same |
162162
| B-30 | GET | `/api/export/database` | 401 | Same |
163-
| B-31 | GET | `/api/boards/{random-guid}/imports/external` | 401 | Same (POST only, GET should be 405 or 401) |
163+
| B-31 | POST | `/api/boards/{random-guid}/imports/external` | 401 | Same |
164164
| B-32 | GET | `/api/workspace/preferences` | 401 | Same |
165165

166166
### Curl template for unauthenticated checks
@@ -251,7 +251,7 @@ Verify that accessing a genuinely nonexistent resource returns `404` with the co
251251
| ID | Method | Route | Token | Expected | Notes |
252252
|-------|--------|--------------------------------------------------|---------|----------|--------------------------------|
253253
| B-90 | GET | `/api/boards/00000000-0000-0000-0000-000000000001` | UserA | 404 | Board does not exist |
254-
| B-91 | GET | `/api/boards/{BOARD_A}/cards/00000000-0000-0000-0000-000000000001` | UserA | 404 | Card does not exist on own board |
254+
| B-91 | GET | `/api/boards/{BOARD_A}/cards/00000000-0000-0000-0000-000000000001/provenance` | UserA | 404 | Card provenance for nonexistent card on own board |
255255
| B-92 | GET | `/api/boards/{BOARD_A}/columns` (after deleting all) | UserA | 200 | Empty list, not 404 |
256256
| B-93 | GET | `/api/capture/items/00000000-0000-0000-0000-000000000001` | UserA | 404 | Capture item does not exist |
257257
| B-94 | GET | `/api/llm/chat/sessions/00000000-0000-0000-0000-000000000001` | UserA | 404 | Chat session does not exist |
@@ -290,6 +290,7 @@ Known `errorCode` values (from `ErrorCodes` in `Taskdeck.Domain.Exceptions`):
290290
| 404 | `NotFound` |
291291
| 409 | `Conflict`, `InvalidOperation` |
292292
| 429 | `TooManyRequests`, `LlmQuotaExceeded` |
293+
| 500 | `UnexpectedError`, `AbuseContainmentActive` (no explicit mapping -- falls to default) |
293294
| 503 | `LlmKillSwitchActive` |
294295

295296
### Targeted error-contract checks
@@ -300,7 +301,7 @@ Known `errorCode` values (from `ErrorCodes` in `Taskdeck.Domain.Exceptions`):
300301
| B-101 | `POST /api/auth/login` with wrong password | 401 | `AuthenticationFailed`| `errorCode`+`message` present |
301302
| B-102 | `POST /api/auth/register` with duplicate username | 409 | `Conflict` | `errorCode`+`message` present |
302303
| B-103 | `GET /api/llm-queue/status/not-a-real-status` | 400 | `ValidationError` | `errorCode`+`message` present |
303-
| B-104 | `POST /api/automation/proposals/{id}/execute` without `Idempotency-Key` header | 400 | `ValidationError` | `errorCode`+`message` present |
304+
| B-104 | `POST /api/automation/proposals/{id}/execute` without `Idempotency-Key` header (use a real approved proposal ID -- a fake ID returns 404 before the header check) | 400 | `ValidationError` | `errorCode`+`message` present |
304305
| B-105 | `GET /api/export/database` (sandbox disabled) | 403 | `Forbidden` | `errorCode`+`message` present |
305306
| B-106 | `POST /api/import/database` (sandbox disabled) | 403 | `Forbidden` | `errorCode`+`message` present |
306307
| B-107 | `POST /api/boards/{BOARD_A}/cards` with missing `columnId` | 400 | `ValidationError` | `errorCode`+`message` present |
@@ -325,8 +326,10 @@ curl -s -o /tmp/b_103.json -w "%{http_code}" \
325326
cat /tmp/b_103.json | jq .
326327

327328
# B-104: Execute proposal without Idempotency-Key
329+
# NOTE: Replace the proposal ID below with a real approved proposal ID.
330+
# Using a fake ID will return 404 before reaching the Idempotency-Key check.
328331
curl -s -o /tmp/b_104.json -w "%{http_code}" \
329-
-X POST http://localhost:5000/api/automation/proposals/00000000-0000-0000-0000-000000000001/execute \
332+
-X POST http://localhost:5000/api/automation/proposals/<REAL_APPROVED_PROPOSAL_ID>/execute \
330333
-H "Authorization: Bearer $TOKEN_A" \
331334
-H "Content-Type: application/json"
332335
cat /tmp/b_104.json | jq .
@@ -387,7 +390,7 @@ These controllers have specialized auth or role requirements beyond standard boa
387390
| ID | Method | Route | Token | Expected | Notes |
388391
|-------|--------|-----------------------------------------------|---------|----------|--------------------------------|
389392
| B-150 | GET | `/api/abuse/actors/{UserA_ID}/status` | UserA | 200 or 403 | May require admin role |
390-
| B-151 | POST | `/api/abuse/actors/override` | UserA | 403 | Admin-only override |
393+
| B-151 | POST | `/api/abuse/actors/override` | UserA | 200 | **No admin gate in current code** -- any authenticated user can override; file security issue if unexpected |
391394

392395
### LLM Quota (`/api/llm`)
393396

0 commit comments

Comments
 (0)