bruno: regenerate collection from canonical docs + permanent docs↔Bruno parity gate

WO4. The old collection was the drifted artifact AGENTS.md warned about:
bodies pre-truncated at their first {{var}}, routes renamed server-side
but not here (/api/notes/:media_id, /api/book-matching/search,
/api/collections/:id/rules/test), an orphan universal-progress suite for
routes that no longer exist.

scripts/gen_bruno_from_docs.py emits one OpenCollection request per
frontmatter'd endpoint doc (191 requests): gate-verified example-request
JSON as body, {{env}} params per the environment file, device-token
routes get an explicit Bearer {{device_token}} header, login/register/
refresh keep the token-capture after-response scripts that chain the
collection. Old 1:1 mirrors deleted (128); hand-authored NewDevDBSetup,
environments, and edge-case suites kept. 30 scenario files with
truncated bodies (the documented corruption) deleted — they could not
run.

internal/docs/drift_test.go gains TestBrunoMirrorsDocs: every
frontmatter'd doc must have a Bruno request with matching method+URL
shape — the collection can never silently drift from the docs again.
opencollection.yml README block replaced with the real run instructions.

make test green (9 pkgs, parity test included in internal/docs).
This commit is contained in:
John O'Keefe committed 2026-10-24 18:35:51 -04:00
1 parent 6fc501b35a
commit acd82fff0a
353 files changed
+5165 -5293

No files matched your search

@@ -1,38 +0,0 @@
info:
name: Create Collection with Dashboard
type: http
seq: 4
http:
method: POST
url: '{{base_url}}/api/collections'
auth: inherit
runtime:
scripts:
- type: tests
code: "test(\"creates collection successfully\", function() {\n expect(res.status).to.eql(201);"
docs: |-
Create a new collection with dashboard visibility enabled.
**Endpoint**: POST /api/collections
**Auth**: Required (Bearer token)
## Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | Collection name |
| description | string | No | Collection description |
| color | string | No | Hex color code |
| icon | string | No | Icon emoji or name |
| show_on_dashboard | boolean | No | Show on dashboard (default: false) |
## Example Request
```json
{
"name": "My Favorites",
"description": "My favorite books",
"color": "#FF5733",
"icon": "⭐",
"show_on_dashboard": true
@@ -1,73 +0,0 @@
info:
name: Get Dashboard Sections
type: http
seq: 1
http:
method: GET
url: '{{base_url}}/api/dashboard/sections?library_id={{library_id}}'
auth: inherit
body:
type: none
runtime:
scripts:
- type: tests
code: "test(\"status must be 200 with auth\", function() {\n expect(res.status).to.eql(200);\n\
});\n\ntest(\"response contains sections array\", function() {\n expect(res.body.sections).to.exist;\n\
expect(res.body.sections).to.be.an('array');\n });"
docs: |-
Get all dashboard sections for a specific library.
**Endpoint**: GET /api/dashboard/sections
**Auth**: Required (Bearer token via auth: inherit)
## Query Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| library_id | string | Yes | Library UUID |
| limit | int | No | Items per section (default: 20, max: 100) |
## Response
Returns array of sections including:
- System collections (continue-reading, recently-added, recently-read, not-started)
- User collections marked with show_on_dashboard: true
## Section Structure
Each section has:
- `id`: Collection name (string)
- `is_system`: Boolean indicating if this is a system collection
- `title`: Display title
- `description`: Collection description
- `icon`: Emoji icon
- `items`: Array of BookInfo objects
- `view_all_url`: URL to view all items (system collections only)
- `priority`: Display order (lower numbers first)
## Example Response
```json
{
"sections": [
{
"id": "continue-reading",
"is_system": true,
"title": "Continue Reading",
"description": "Books you're currently reading (0 < progress < 1)",
"icon": "📖",
"items": [
{
"media_item_id": "uuid",
"title": "Book Title",
"author": "Author Name",
"cover_image_path": "/path/to/cover.jpg"
}
],
"view_all_url": "/section/continue-reading",
"priority": 1
}
]
}
```
@@ -1,30 +0,0 @@
info:
name: Get Dashboard Sections by Library
type: http
seq: 3
http:
method: GET
url: '{{base_url}}/api/dashboard/sections'
auth: inherit
runtime:
scripts:
- type: tests
code: "test(\"status must be 200\", function() {\n expect(res.status).to.eql(200);"
docs: |-
Get all dashboard sections for a specific library.
**Endpoint**: GET /api/dashboard/sections
**Auth**: Required (Bearer token)
## Query Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| library_id | string | Yes | Library UUID |
## Response
Returns array of sections including:
- Smart sections (continue-reading, in-progress, recently-added, etc.)
- User collections marked for dashboard
+21
View File
@@ -0,0 +1,21 @@
info:
name: Get Dashboard Preferences
type: http
seq: 1
http:
method: GET
url: '{{base_url}}/api/dashboard/preferences'
auth: inherit
settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
docs: |-
# Get Dashboard Preferences
`GET /api/dashboard/preferences` — auth: jwt.
Canonical reference: `docs/developer/api/dashboard/get_preferences.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
+21
View File
@@ -0,0 +1,21 @@
info:
name: Get Dashboard Sections
type: http
seq: 2
http:
method: GET
url: '{{base_url}}/api/dashboard/sections'
auth: inherit
settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
docs: |-
# Get Dashboard Sections
`GET /api/dashboard/sections` — auth: jwt.
Canonical reference: `docs/developer/api/dashboard/get_sections.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
@@ -1,16 +0,0 @@
info:
name: Restore System Collection
type: http
seq: 3
http:
method: POST
url: '{{base_url}}/api/dashboard/restore-system-collection'
auth: inherit
body:
type: json
data: "{\n \"collection_name\": \"continue-reading\"\n}"
runtime:
scripts:
- type: tests
code: "test(\"status must be 200 with valid collection\", function() {\n expect(res.status).to.eql(200);\n});\n\ntest(\"response has success message\", function() {\n expect(res.body.message).to.exist;\n});"
docs: "Restore a system collection to its default state.\n\n**Endpoint**: POST /api/dashboard/restore-system-collection\n**Auth**: Required (Bearer token)\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| collection_name | string | Yes | Name of system collection to restore |\n\nValid collection names:\n- `continue-reading`: Books you're currently reading (0 < progress < 1)\n- `recently-added`: Newly added items to this library\n- `recently-read`: Books you've finished (progress >= 1)\n- `not-started`: Books you haven't read yet (progress = 0 or no record)\n\n## Example Request\n\n```json\n{\n \"collection_name\": \"continue-reading\"\n}\n```\n\n## Response\n\nReturns success message on restore."
@@ -0,0 +1,28 @@
info:
name: Restore System Collection
type: http
seq: 3
http:
method: POST
url: '{{base_url}}/api/dashboard/restore-system-collection'
auth: inherit
body:
type: json
data: |-
{
"collection_name": "Continue Reading",
"reset_type": "full"
}
settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
docs: |-
# Restore System Collection
`POST /api/dashboard/restore-system-collection` — auth: jwt.
Canonical reference: `docs/developer/api/dashboard/restore_system_collection.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
@@ -1,17 +0,0 @@
info:
name: Update Collection Dashboard Visibility
type: http
seq: 5
http:
method: PUT
url: '{{base_url}}/api/collections/{{collection_id}}'
auth: inherit
runtime:
scripts:
- type: tests
code: "test(\"updates collection successfully\", function() {\n expect(res.status).to.eql(200);"
docs: |-
Update collection settings including dashboard visibility.
**Endpoint**: PUT /api/collections/{id
-16
View File
@@ -1,16 +0,0 @@
info:
name: Update Dashboard Preferences
type: http
seq: 2
http:
method: PUT
url: '{{base_url}}/api/dashboard/preferences'
auth: inherit
body:
type: json
data: "{\n \"library_id\": \"{{library_id}}\",\n \"hidden_collections\": [\"not-started\"],\n \"collection_order\": [\"recently-added\", \"continue-reading\", \"recently-read\"],\n \"items_per_section\": 20\n}"
runtime:
scripts:
- type: tests
code: "test(\"status must be 200 with valid request\", function() {\n expect(res.status).to.eql(200);\n});"
docs: "Update dashboard preferences for the authenticated user.\n\n**Endpoint**: PUT /api/dashboard/preferences\n**Auth**: Required (Bearer token)\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| library_id | string | Yes | Library UUID |\n| hidden_collections | array | No | Collection names to hide from dashboard |\n| collection_order | array | No | Collection names in custom display order |\n| items_per_section | int | No | Items to show per section (default: 20) |\n\n## Example Request\n\n```json\n{\n \"library_id\": \"cc23c3a7-f8fb-451a-a78d-2a16df1b725a\",\n \"hidden_collections\": [\"not-started\"],\n \"collection_order\": [\"recently-added\", \"continue-reading\", \"recently-read\"],\n \"items_per_section\": 20\n}\n```\n\n## Response\n\nReturns updated preferences object on success."
+30
View File
@@ -0,0 +1,30 @@
info:
name: Update Dashboard Preferences
type: http
seq: 4
http:
method: PUT
url: '{{base_url}}/api/dashboard/preferences'
auth: inherit
body:
type: json
data: |-
{
"library_id": "550e8400-e29b-41d4-a716-446655440000",
"hidden_collections": ["not-started"],
"collection_order": ["recently-added", "continue-reading", "recently-read"],
"items_per_section": 20
}
settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
docs: |-
# Update Dashboard Preferences
`PUT /api/dashboard/preferences` — auth: jwt.
Canonical reference: `docs/developer/api/dashboard/update_preferences.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.