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,17 +0,0 @@
info:
name: Get Analytics Tests
type: http
seq: 7
http:
method: POST
url: '{{base_url}}/api/sync/kobo/{{kobo_device_token}}/v1/analytics/gettests'
auth: inherit
headers:
- key: Content-Type
value: application/json
body:
type: json
data: "{\n \"platform\": \"android\",\n \"firmware_version\": \"4.30.19023\"\n}"
docs: "## Get Kobo Analytics Tests\n\nRetrieves A/B testing configuration and feature flags for Kobo device.\n\n**Method:** POST\n\n**Endpoint:** /api/sync/kobo/v1/analytics/gettests\n\n**Authentication:** Bearer token\n\n**Request Body:**\n- `platform` (string): Device platform\n - `android`: Kobo Android app\n - `kobo`: Native Kobo firmware\n- `firmware_version` (string): Firmware version (e.g., \"4.30.19023\")\n- `device_model` (string, optional): Device model identifier\n- `locale` (string, optional): Device locale (e.g., \"en_US\")\n\n**Response:**\n- `tests` (array): Active A/B tests\n - `test_name` (string): Test identifier\n - `variant` (string): Assigned variant (A, B, C, etc.)\n - `enabled` (boolean): Whether test is active\n - `parameters` (object): Test-specific parameters\n- `features` (object): Feature flags\n - `feature_name` (boolean/string): Feature state\n- `configuration` (object): Device configuration\n - `sync_interval_minutes` (integer): Recommended sync frequency\n\
\ - `batch_size` (integer): Max items per batch sync\n - `timeout_seconds` (integer): Request timeout\n- `version` (string): Configuration version\n\n**Status Codes:**\n- 200: Success\n- 401: Unauthorized\n- 400: Invalid request parameters\n\n**Analytics Testing Purpose:**\n- Kobo uses A/B testing for UX features\n- Feature flags for gradual rollout\n- Performance monitoring configuration\n- Sync behavior optimization\n- Device-specific tuning\n\n**Common Tests:**\n- Sync frequency optimization\n- UI/UX variations\n- Network usage patterns\n- Battery life improvements\n- Feature set variations by model\n\n**Feature Flags:**\n- New sync features\n- Beta functionality\n- Platform-specific capabilities\n- Experimental features\n\n**Configuration Parameters:**\n- Optimal sync intervals for device\n- Batch size limits based on device capabilities\n- Timeout values for network conditions\n- Retry logic configuration\n- Cache policy settings\n\n**Usage:**\n- Called during device initialization\n\
- Refreshed daily or weekly\n- Cached on device\n- Affects sync behavior\n- Can be overridden by server\n\n**Use Cases:**\n- Device initialization\n- Feature rollout testing\n- Performance optimization\n- UX experiment participation\n- Configuration management"
-81
View File
@@ -1,81 +0,0 @@
info:
name: Get Kobo Library
type: http
seq: 6
http:
method: GET
url: '{{base_url}}/api/sync/kobo/{{kobo_device_token}}/v1/initialization'
auth: inherit
docs: |-
## Get Kobo Library
Retrieves the user's Kobo library metadata for device sync.
**Method:** GET
**Endpoint:** /api/sync/kobo/library
**Authentication:** Bearer token
**Query Parameters:**
None (returns entire library)
**Response:**
- `books` (array): Library items
- `ContentId` (string): Unique book identifier
- `Title` (string): Book title
- `Author` (string): Author name
- `Publisher` (string): Publisher name
- `Description` (string): Book description
- `ISBN` (string, optional): ISBN-13
- `PublicationDate` (string): Release date
- `EntitlementId` (string): Kobo entitlement ID
- `CrossRevisionId` (string): Revision identifier
- `MimeType` (string): Content type (application/epub+zip)
- `FileSize` (integer): File size in bytes
- `CoverImageId` (string): Cover image identifier
- `DownloadUrls` (object): Download URLs
- `download_url` (string): Direct download link
- `download_acquisition_url` (string): OPDS acquisition URL
- `sync_metadata` (object):
- `last_sync` (string): Last library sync timestamp
- `total_books` (integer): Total book count
- `has_updates` (boolean): Whether updates are available
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 403: Device not approved
**Library Sync Purpose:**
- Kobo device needs to know available books
- Enables download via device browser
- Provides metadata for device display
- Supports Kobo's "My Books" feature
- Enables on-device purchasing integration
**Kobo Device Usage:**
- Device fetches library on registration
- Refreshed daily or on manual sync
- User can browse library on device
- Books downloaded wirelessly to device
- Supports "Buy on Kobo, read on device" workflow
**Authentication Methods:**
This endpoint uses **Bearer token authentication** (token in Authorization header).
Alternative: Use `/sync/kobo/{token}/library` with token in URL path.
**Performance:**
- Typical response: 50-200KB for 100 books
- Processing time: 200-800ms
- Cache duration: 5 minutes
- Pagination available for large libraries (>500 books)
**Use Cases:**
- Initial device registration
- Library refresh on device
- Book discovery on device
- Download link generation
- Metadata sync for OPDS
@@ -1,22 +0,0 @@
info:
name: Get Unlinked Book Suggestions
type: http
seq: 1
http:
method: GET
url: '{{base_url}}/api/sync/unlinked-books/{{unlinkedBookId}}/suggestions'
auth: inherit
body:
type: none
headers:
- key: Authorization
value: Bearer {{authToken
docs: |-
## Get Unlinked Book Suggestions
Retrieves suggested media items from the library that match an unlinked book, enabling manual linking.
**Method:** GET
**Endpoint:** /sync/unlinked-books/{unlinkedBookId
@@ -1,17 +0,0 @@
info:
name: Auto-Link Unlinked Books
type: http
seq: 1
http:
method: POST
url: '{{base_url}}/api/sync/auto-link-books'
auth: inherit
body:
type: json
data: "{\n \"confidence_threshold\": 0.8,\n \"limit\": 50"
headers:
- key: Content-Type
value: application/json
- key: Authorization
value: Bearer {{authToken
docs: "## Auto-Link Unlinked Books\n\n Automatically links unlinked books to media items based on title and author matching with a configurable confidence threshold.\n\n **Method:** POST\n\n **Endpoint:** /sync/auto-link-books\n\n **Authentication:** Bearer token\n\n **Request Body:**\n - `confidence_threshold` (number, optional): Minimum confidence score for auto-linking (0-1, default: 0.8)\n - `limit` (number, optional): Maximum number of books to auto-link (default: 50)\n\n **Response:**\n - `results` (array): Results for each auto-link attempt\n - `total` (number): Total number of books processed\n - `success` (number): Number of successful links\n - `failed` (number): Number of failed links\n\n **Status Codes:**\n - 200: Success\n - 400: Invalid request data\n - 401: Unauthorized\n - 500: Internal server error\n\n **Note:** Higher confidence thresholds produce fewer but more accurate matches. Consider the tradeoff between automation and accuracy."
@@ -1,17 +0,0 @@
info:
name: Bulk Link Unlinked Books
type: http
seq: 1
http:
method: POST
url: '{{base_url}}/api/sync/bulk-link-books'
auth: inherit
body:
type: json
data: "{\n \"links\": [\n {\n \"unlinked_book_id\": \"{{unlinkedBookId1"
headers:
- key: Content-Type
value: application/json
- key: Authorization
value: Bearer {{authToken
docs: "## Bulk Link Unlinked Books\n\n Links multiple unlinked books to media items in a single request.\n\n **Method:** POST\n\n **Endpoint:** /sync/bulk-link-books\n\n **Authentication:** Bearer token\n\n **Request Body:**\n - `links` (array): Array of link objects\n - `unlinked_book_id` (string): Unlinked book UUID\n - `media_item_id` (string): Media item UUID to link to\n - `confidence_score` (number): Match confidence (0-1)\n\n **Response:**\n - `results` (array): Results for each link attempt\n - `total` (number): Total number of links processed\n - `success` (number): Number of successful links\n - `failed` (number): Number of failed links\n\n **Status Codes:**\n - 200: Success\n - 400: Invalid request data\n - 401: Unauthorized\n - 500: Internal server error\n\n **Note:** Use this endpoint after reviewing suggestions from the Get Unlinked Book Suggestions endpoint."
@@ -1,16 +0,0 @@
info:
name: Sync from Bookhoard to Kobo
type: http
seq: 1
http:
method: POST
url: '{{base_url}}/api/sync/kobo/{{kobo_device_token}}/sync-from-server'
auth: inherit
body:
type: json
data: "[\n {\n \"ContentId\": \"{{bookUUID"
headers:
- key: Authorization
value: Bearer {{koboToken
docs: "## Sync from Bookhoard to Kobo\n\n Server-initiated sync pushing progress, bookmarks, and highlights from Bookhoard to Kobo device. Two-way sync endpoint.\n\n **Method:** POST\n\n **Endpoint:** /api/sync/kobo/sync-from-server\n\n **Authentication:** Bearer token with Kobo device identification\n\n **Headers:**\n - `x-kobo-device` (string): JSON string containing Kobo device info\n - `DeviceId`: Kobo device ID\n - `Model`: Kobo device model\n - `SerialNumber`: Kobo device serial number\n\n **Request Body:** Array of sync data objects\n - `ContentId` (string): Book UUID\n - `PercentRead` (number): Reading progress percentage (0-100)\n - `LastModified` (string): ISO 8601 timestamp\n - `Bookmarks` (array, optional): Array of bookmark objects\n - `BookmarkId`: Unique bookmark ID\n - `ContentId`: Book UUID\n - `BookmarkText`: Bookmark text/note\n - `BookmarkType`: Type (bookmark, annotation, etc.)\n - `BookmarkTitle`: Bookmark title\n - `Highlights` (array,\
\ optional): Array of highlight objects (same structure as bookmarks)\n\n **Response:**\n - Sync result confirmation\n\n **Status Codes:**\n - 200: Success\n - 401: Unauthorized\n - 500: Internal server error\n\n **Note:** Allows Bookhoard server to push updates to Kobo device, including reading progress, bookmarks, and highlights."
@@ -1,15 +0,0 @@
info:
name: Kobo Bookmark Sync
type: http
seq: 3
http:
method: POST
url: '{{base_url}}/api/sync/kobo/{{kobo_device_token}}/bookmark'
auth: inherit
body:
type: json
data: "{\n \"BookmarkSync\": [\n {\n \"BookmarkId\": \"bookmark_2\",\n \"ContentId\": \"kobo_xyz789\",\n \"BookmarkText\": \"Important note\",\n \"BookmarkType\": \"bookmark\",\n \"DateCreated\": \"2026-01-31T12:00:00Z\""
headers:
- key: Authorization
value: Bearer {{device_token
docs: "## Kobo Bookmark Sync\n\n Synchronizes bookmarks from a Kobo device to the Bookhoard server.\n\n **Method:** POST\n\n **Endpoint:** /api/v1/kobo/bookmark\n\n **Authentication:** Bearer token (device token)\n\n **Request Body:**\n - `BookmarkSync` (array): Array of bookmark objects\n - `BookmarkId` (string): Unique bookmark ID\n - `ContentId` (string): Book/content ID\n - `BookmarkText` (string): Bookmark text or note\n - `BookmarkType` (string): Type (bookmark, highlight, note)\n - `DateCreated` (string): ISO 8601 timestamp\n\n **Response:**\n - `Status` (string): Sync status (Success, Partial)\n - `BookmarksSynced` (number): Number of bookmarks synced\n\n **Status Codes:**\n - 200: Success\n - 401: Unauthorized\n - 500: Internal server error"
@@ -1,39 +0,0 @@
info:
name: Get Unlinked Books - User View
type: http
seq: 4
http:
method: GET
url: '{{base_url}}/api/devices/{{device_id}}/sync/unlinked-books'
auth: inherit
body:
type: none
headers:
- key: Authorization
value: Bearer {{user_token
docs: |-
## Get Unlinked Books - User View
Retrieves all unlinked books for the authenticated user that need manual linking.
**Method:** GET
**Endpoint:** /api/sync/unlinked-books
**Authentication:** Bearer token
**Response:**
- `unlinked` (array): Array of unlinked book objects
- `id` (string): Unlinked book UUID
- `title` (string): Book title
- `author` (string): Book author
- `device_id` (string): Source device ID
- `device_name` (string): Source device name
- `detected_at` (string): Detection timestamp
- `total` (number): Total count of unlinked books
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 500: Internal server error
@@ -1,15 +0,0 @@
info:
name: Link Unlinked Book - Manual Resolution
type: http
seq: 5
http:
method: POST
url: '{{base_url}}/api/devices/{{device_id}}/sync/link-book'
auth: inherit
body:
type: json
data: "{\n \"unlinked_book_id\": \"{{unlinked_book_id"
headers:
- key: Authorization
value: Bearer {{user_token
docs: "## Link Unlinked Book - Manual Resolution\n\n Manually links an unlinked book to a media item in the library.\n\n **Method:** POST\n\n **Endpoint:** /api/sync/link-book\n\n **Authentication:** Bearer token\n\n **Request Body:**\n - `unlinked_book_id` (string): Unlinked book UUID\n - `media_item_id` (string): Media item UUID to link to\n - `confidence_score` (number): Match confidence (0-1, 1.0 for manual)\n\n **Response:**\n - `status` (string): Link status (linked)\n - `unlinked_book_id` (string): Unlinked book UUID\n - `media_item_id` (string): Media item UUID\n - `message` (string): Success message\n\n **Status Codes:**\n - 200: Success - book linked\n - 400: Invalid request\n - 401: Unauthorized\n - 404: Book or media item not found\n - 500: Internal server error"
@@ -1,15 +0,0 @@
info:
name: Sync Bookmark - URL Path Token
type: http
seq: 2
http:
method: POST
url: '{{base_url}}/api/sync/kobo/{{kobo_device_token}}/bookmark'
auth: none
body:
type: json
data: "{\n \"ContentId\": \"book-uuid\",\n \"BookmarkText\": \"Highlighted text\",\n \"BookmarkType\": \"annotation\",\n \"BookmarkTitle\": \"Chapter 3\""
headers:
- key: Content-Type
value: application/json
docs: "## Sync Bookmark - URL Path Token\n\n Synchronizes bookmarks and annotations from Kobo device using token in URL path.\n\n **Method:** POST\n\n **Endpoint:** /sync/kobo/{kobo_device_token"
@@ -1,15 +0,0 @@
info:
name: Sync Markup - URL Path Token
type: http
seq: 1
http:
method: POST
url: '{{base_url}}/api/sync/kobo/{{kobo_device_token}}/markup'
auth: none
body:
type: json
data: "{\n \"ReadingSync\": [\n {\n \"ContentId\": \"book-uuid\",\n \"PercentRead\": 45.6,\n \"EntitlementId\": \"entitlement-id\",\n \"RemainingTimeMinutes\": 120,\n \"FirstReadTime\": \"2026-01-25T10:00:00Z\",\n \"LastModified\": \"2026-01-30T20:00:00Z\""
headers:
- key: Content-Type
value: application/json
docs: "## Sync Reading Progress - URL Path Token\n\n Synchronizes reading progress from Kobo device using token in URL path.\n\n **Method:** POST\n\n **Endpoint:** /sync/kobo/{kobo_device_token"