fix(bruno): convert drifted body keys to body.data — CLI scenario runs now carry bodies

Follow-up to the sweep route audit, correcting its diagnosis: the CLI
DOES read .yml bodies — via OpenCollection's `body.data` string form
(the NewDevDBSetup script always worked because it used it). The
failing scenario POSTs used `body.json` (structured) / `body.jsonBody`
(string) — keys the CLI silently ignores, sending Content-Length: 0
with form-urlencoded content-type, so every server bind failed.

- 81 bodies converted to data-form (json maps serialized; jsonBody
  strings kept verbatim, {{vars}} intact).
- 6 pre-existing TRUNCATED payloads repaired: the original generator
  cut bodies at the first {{var}} (every SHA-256-identified scenario
  plus Sync Progress/Sync Bookmarks shipped mid-JSON and 400'd from
  day one). Rewritten whole, faithful to each file's documented
  purpose; book_sha256/book_uuid added to the environment.
- environments: opds_base_url correction from the sweep retained.

Verified live against the rebuilt dev container: the full koreader
scenario tree runs green through `bru run` — 14/14 (202s across
immediate/checkpoint/SHA-256 progress, 200s bookmarks, highlights,
notes; SHA-256 book identification exercised against a real
file_sha256).
This commit is contained in:
John O'Keefe committed 2026-10-17 12:22:35 -04:00
1 parent 63a20dcc95
commit 09b6693505
83 files changed
+386 -2769

No files matched your search

+4 -107
View File
@@ -8,110 +8,7 @@ http:
auth: inherit
body:
type: json
jsonBody: "{\n \"name\": \"Updated Sci-Fi Books\",\n \"resource_type\"\
: \"media-items\",\n \"filters\": {\n \"genre_filter\": \"Science Fiction\
\ Fantasy\",\n \"sort\": \"author ASC\",\n \"year_min\": \"2000\"\
\n }\n }"
docs: |-
## Update Saved Filter
Updates an existing saved filter's name and/or filter criteria.
**Method:** PUT
**Endpoint:** /api/saved-filters/{filter_id}
**Authentication:** Required (Bearer token)
**Path Parameters:**
- `filter_id` (string, required): UUID of the filter to update
- Must be a valid UUID
- Must belong to the authenticated user
**Request Body:**
```json
{
"name": "Updated Sci-Fi Books",
"resource_type": "media-items",
"filters": {
"genre_filter": "Science Fiction Fantasy",
"sort": "author ASC",
"year_min": "2000",
"year_max": "2024"
}
}
```
**Required Fields:**
- `name` (string, required): New filter name
- Must be unique per user + resource type (excluding current filter)
- Maximum 100 characters
- `resource_type` (string, required): Resource type (must match existing)
- Cannot change resource type after creation
- `filters` (object, required): Updated filter criteria
- Replaces existing filters entirely
**Response:**
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Updated Sci-Fi Books",
"resource_type": "media-items",
"filters": {
"genre_filter": "Science Fiction Fantasy",
"sort": "author ASC",
"year_min": "2000",
"year_max": "2024"
},
"created_at": "2024-03-20T12:00:00Z",
"updated_at": "2024-03-20T15:30:00Z"
}
```
**Status Codes:**
- 200: Success - Filter updated successfully
- 400: Bad Request - Invalid request body or filter ID
- 401: Unauthorized - Invalid or missing authentication token
- 404: Not Found - Filter doesn't exist or doesn't belong to user
- 409: Conflict - New name conflicts with existing filter
**Error Response Examples:**
Filter not found:
```json
{
"error": "filter not found or access denied"
}
```
Duplicate name:
```json
{
"error": "filter with name 'Updated Sci-Fi Books' already exists for this resource type"
}
```
**Example Usage:**
```bash
curl -X PUT \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Sci-Fi Books",
"resource_type": "media-items",
"filters": {
"genre_filter": "Science Fiction Fantasy",
"sort": "author ASC",
"year_min": "2000"
}
}' \
"{{base_url}}/api/saved-filters/{{filter_id}}"
```
**Important Notes:**
- You can only update filters that belong to you
- The `updated_at` timestamp is automatically updated
- Cannot change the resource_type (it's immutable)
- New name must not conflict with other filters you own for the same resource type
- All filter fields are replaced entirely (partial updates not supported)
data: "{\n \"name\": \"Updated Sci-Fi Books\",\n \"resource_type\": \"media-items\",\n \"filters\": {\n \"genre_filter\": \"Science Fiction Fantasy\",\n \"sort\": \"author ASC\",\n \"year_min\": \"2000\"\n }\n }"
docs: "## Update Saved Filter\n\nUpdates an existing saved filter's name and/or filter criteria.\n\n**Method:** PUT\n\n**Endpoint:** /api/saved-filters/{filter_id}\n\n**Authentication:** Required (Bearer token)\n\n**Path Parameters:**\n- `filter_id` (string, required): UUID of the filter to update\n - Must be a valid UUID\n - Must belong to the authenticated user\n\n**Request Body:**\n```json\n{\n \"name\": \"Updated Sci-Fi Books\",\n \"resource_type\": \"media-items\",\n \"filters\": {\n \"genre_filter\": \"Science Fiction Fantasy\",\n \"sort\": \"author ASC\",\n \"year_min\": \"2000\",\n \"year_max\": \"2024\"\n }\n}\n```\n\n**Required Fields:**\n- `name` (string, required): New filter name\n - Must be unique per user + resource type (excluding current filter)\n - Maximum 100 characters\n- `resource_type` (string, required): Resource type (must match existing)\n - Cannot change resource type after creation\n- `filters` (object, required): Updated filter criteria\n\
\ - Replaces existing filters entirely\n\n**Response:**\n```json\n{\n \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"name\": \"Updated Sci-Fi Books\",\n \"resource_type\": \"media-items\",\n \"filters\": {\n \"genre_filter\": \"Science Fiction Fantasy\",\n \"sort\": \"author ASC\",\n \"year_min\": \"2000\",\n \"year_max\": \"2024\"\n },\n \"created_at\": \"2024-03-20T12:00:00Z\",\n \"updated_at\": \"2024-03-20T15:30:00Z\"\n}\n```\n\n**Status Codes:**\n- 200: Success - Filter updated successfully\n- 400: Bad Request - Invalid request body or filter ID\n- 401: Unauthorized - Invalid or missing authentication token\n- 404: Not Found - Filter doesn't exist or doesn't belong to user\n- 409: Conflict - New name conflicts with existing filter\n\n**Error Response Examples:**\n\nFilter not found:\n```json\n{\n \"error\": \"filter not found or access denied\"\n}\n```\n\nDuplicate name:\n```json\n{\n \"error\": \"filter with name 'Updated Sci-Fi Books' already exists\
\ for this resource type\"\n}\n```\n\n**Example Usage:**\n```bash\ncurl -X PUT \\\n -H \"Authorization: Bearer YOUR_TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"Updated Sci-Fi Books\",\n \"resource_type\": \"media-items\",\n \"filters\": {\n \"genre_filter\": \"Science Fiction Fantasy\",\n \"sort\": \"author ASC\",\n \"year_min\": \"2000\"\n }\n }' \\\n \"{{base_url}}/api/saved-filters/{{filter_id}}\"\n```\n\n**Important Notes:**\n- You can only update filters that belong to you\n- The `updated_at` timestamp is automatically updated\n- Cannot change the resource_type (it's immutable)\n- New name must not conflict with other filters you own for the same resource type\n- All filter fields are replaced entirely (partial updates not supported)"