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

+18 -178
View File
@@ -21,184 +21,24 @@ request:
docs:
content: |-
# Bruno OpenCollection YAML API Tests for Bookhoard
This directory contains Bruno OpenCollection YAML format tests for testing the Bookhoard API with comprehensive REST documentation.
Setup
1. Install Bruno: https://www.usebruno.com/
2. Open Bruno and import this collection folder
3. Select the "localhost" environment
4. Start the application with `podman-compose up --build` or `docker-compose up --build`
5. Register/Login first, then use Bearer token for protected endpoints
Available Tests
Authentication (Public & Private)
- **Register User**: POST /api/auth/register - Create new account with role-based restrictions
- **Login User**: POST /api/auth/login - Authenticate (email or username)
- **Refresh Token**: POST /api/auth/refresh - Get new access token
- **Logout**: POST /api/auth/logout - Invalidate refresh token
User Profile Management
- **Get Profile**: GET /api/auth/profile - Get current user info
- **Update Profile**: PUT /api/auth/profile - Update first_name, last_name
- **Update Email**: PUT /api/auth/email - Update email address
- **Update Username**: PUT /api/auth/username - Update username
- **Update Password**: PUT /api/auth/password - Update password
- **Update Theme**: PUT /api/auth/theme - Update theme preference
Admin User Management
- **List Users**: GET /api/auth/users - Get all users with complete info (admin only)
- **Delete Account**: DELETE /api/auth/account - Delete own account or admin deletes other accounts
Libraries (Admin Only)
- **Create Library**: POST /api/libraries - Create new library (Ebooks, Comics, Manga)
- **Get Libraries**: GET /api/libraries - List all libraries (admin)
- **Get Library**: GET /api/libraries/:id - Get library details
- **Update Library**: PUT /api/libraries/:id - Update library settings
- **Delete Library**: DELETE /api/libraries/:id - Remove library
- **Add Library Folder**: POST /api/libraries/:id/folders - Add scanning folder
- **Get Library Folders**: GET /api/libraries/:id/folders - List folders
- **Delete Library Folder**: DELETE /api/libraries/:id/folders/:folder_id - Remove folder
- **Get Library Stats**: GET /api/libraries/:id/stats - Library statistics
- **Get Library Types**: GET /api/libraries/types - Available library types
Media Items (Mixed Access)
- **List Media Items**: GET /api/media-items - Paginated list (filter/sort by library, author, series, etc.)
- **Get Media Item**: GET /api/media-items/:id - Single item details (all users)
- **Create Media Item**: POST /api/media-items - Add new item (admin only)
- **Update Media Item**: PUT /api/media-items/:id - Modify metadata (admin only)
- **Delete Media Item**: DELETE /api/media-items/:id - Remove item (admin only)
- **Filter Media Items**: POST /api/media-items/filter - Advanced filtering
- **EPUB Download**: GET /api/media-items/:id/download - Download EPUB file
- **Cover Image**: GET /api/media-items/:id/cover - Get cover image
Reading Progress (All Users)
- **Get Progress**: GET /api/progress/:media_id - User's reading progress for media item
- **Update Progress**: PUT /api/progress/:media_id - Update reading progress
- **Get Device Progress**: GET /api/progress/device/:device_id - Progress by device
Universal Progress (All Users)
- **Get Universal Progress**: GET /api/universal-progress/:sha256 - Get progress by book hash
- **Update Universal Progress**: PUT /api/universal-progress - Update universal progress
Notes (All Users)
- **Get Notes**: GET /api/notes/:media_id - Get notes for media item
- **Create Note**: POST /api/notes - Add new note
- **Update Note**: PUT /api/notes/:id - Update note content
- **Delete Note**: DELETE /api/notes/:id - Remove note
Highlights (All Users)
- **Get Highlights**: GET /api/highlights/:media_id - Get highlights for media item
- **Create Highlight**: POST /api/highlights - Add new highlight
- **Update Highlight**: PUT /api/highlights/:id - Update highlight
- **Delete Highlight**: DELETE /api/highlights/:id - Remove highlight
Ratings (All Users)
- **Get Rating**: GET /api/media-items/:id/rating - User's rating (returns null if unrated)
- **Create/Update Rating**: POST /api/media-items/:id/rating - Rate media item (1-10 scale, displayed as 1-5 stars with half-star precision). POST upserts; PUT also available.
- **Update Rating**: PUT /api/media-items/:id/rating - Update rating (upsert)
- **Delete Rating**: DELETE /api/media-items/:id/rating - Remove rating
Collections (All Users)
- **List Collections**: GET /api/collections - Get user's collections
- **Get Collection**: GET /api/collections/:id - Collection details with media items
- **Create Collection**: POST /api/collections - Create new collection
- **Update Collection**: PUT /api/collections/:id - Update collection
- **Delete Collection**: DELETE /api/collections/:id - Remove collection
- **Add Auto-Assign Rule**: POST /api/collections/:id/rules - Add automatic rule
- **Remove Auto-Assign Rule**: DELETE /api/collections/:id/rules/:rule_id - Remove rule
- **Test Rule**: POST /api/collections/:id/rules/test - Preview rule matches
- **Bulk Assign**: POST /api/collections/:id/assign - Manually add media items
Device Management (All Users)
- **Register Device**: POST /api/devices/register - Register new device
- **List Devices**: GET /api/devices - Get user's devices
- **Get Device**: GET /api/devices/:id - Device details
- **Delete Device**: DELETE /api/devices/:id - Unregister device
- **Sync Device**: POST /api/devices/:id/sync - Trigger device sync
Sync Protocols (Device Integration)
- **KOReader Sync**: POST /api/sync/koreader - KOReader progress/notes/highlights sync
- **Kobo Sync**: POST /api/sync/kobo - Kobo progress/notes/highlights sync
Scanner (Admin Only)
- **Scan Libraries**: POST /api/scanner/scan - Scan library folders
- **Start Scanner**: POST /api/scanner/start - Start real-time monitoring
- **Stop Scanner**: POST /api/scanner/stop - Stop monitoring
- **Get Scan Settings**: GET /api/scanner/settings - Scan configuration
Analytics (Admin Only)
- **Get Analytics**: GET /api/analytics - Usage statistics and metrics
Book Matching (All Users)
- **Search Books**: GET /api/book-matching/search - Search by ISBN, title, author
- **Link Book**: POST /api/book-matching/link - Link media item to external database
OPDS (All Users)
- **OPDS Feeds**: GET /opds/* - OPDS catalog for e-reader integration
- **OPDS Acquisition**: GET /opds/acquisition/* - Download media items
WebSocket (Real-time)
- **WebSocket**: WS /ws/sync - Real-time sync events (progress, notes, highlights)
Collection Organization
bruno/
├── user/ # User authentication and profile
│ ├── auth/ # Login, register, refresh
│ ├── profile/ # Profile management
│ └── admin/ # User administration (admin only)
├── library/ # Library management
│ ├── Create/Update/Delete Libraries
│ ├── Library Folders
│ ├── Library Stats
│ └── Scan Settings
├── media-items/ # Media item operations
│ ├── List/Get/Create/Update/Delete
│ ├── Filter and Sort
│ ├── Download EPUB
│ ├── Cover Images
│ └── Ratings
├── progress/ # Reading progress tracking
├── universal-progress/ # Cross-device universal progress
├── notes/ # User notes
├── highlights/ # Book highlights
├── collections/ # Smart collections
├── devices/ # Device registration
├── sync-koreader/ # KOReader sync protocol
├── sync-kobo/ # Kobo sync protocol
├── scanner/ # Library scanning
├── analytics/ # Usage statistics
├── books/ # Book matching/linking
├── kobo/ # Kobo-specific operations
├── koreader/ # KOReader-specific operations
├── opds/ # OPDS catalog feeds
└── admin/ # Admin operations
## Security Features
### Registration Restrictions
- **First User**: Automatically gets admin role regardless of request
- **Existing Admins**: Only authenticated admins can create new admin accounts
- **Regular Users**: Anyone can create regular user accounts
- **Unauthenticated**: Can only create first admin, not subsequent admins
### User Management
- **Self-Deletion**: Users can delete their own accounts
- **Admin Override**: Admins can delete any user account
- **Last Admin Protection**: Cannot delete the last admin account in the system
### Role System
- **Admin**: Full access - manage libraries, media items, users, scanner
- **User**: Read access - view media items, create collections, track progress, rate, annotate
### Device Authentication
- **No Passwords**: Devices use QR code registration and access tokens
- **User Approval**: Device registration requires user approval via web interface
### JWT Tokens
- **Access Token**: Valid for 1 hour, sent via Bearer header
- **Refresh Token**: Valid for 7 days, used to get new access tokens
### Rate Limiting
- **Auth Endpoints**: 10 requests/minute per IP
### Data Isolation
- **Progress, Notes, Highlights, Ratings**: User-specific
- **Collections**: User-specific (admins see all users' collections)
- **Devices**: User-specific
## Documentation Features
Each request includes:
- **Detailed descriptions** of functionality
- **Parameter specifications** (required/optional, types)
- **Request/Response examples**
- **Error response codes** and meanings
- **Authentication requirements**
## Notes
- **Authentication Flow**: Register → Login → Use Bearer token for all other requests
- **Media Items vs Books**: The API uses "media items" (supports ebooks, comics, manga)
- **Library System**: Organized by libraries (Ebooks, Comics, Manga) with scanning folders
- **Universal Progress**: Cross-device sync using SHA-256 book hashes
- **Smart Collections**: Auto-assign rules based on genre, author, series, tags, etc.
- **OPDS Support**: Wireless book delivery to e-readers (Kobo, KOReader)
- **Device Protocols**: Native sync for KOReader and Kobo devices
- **Rating System**: Half-star precision (1-10 scale internally, displayed as 1-5 stars)
- **Admin Setup**: First admin must be created by updating user role in database
- **Variables**: Update collection variables for testing (media_id, library_id, device_id, etc.)
- **Security**: Passwords hashed with bcrypt, unique email/username constraints, role-based access control
- **JSON**: All requests/responses use JSON format
- **WebSocket**: Real-time events for sync updates across devices
# Bookhoard API — executable verification (OpenCollection / Bruno)
Every request in this collection is GENERATED from the canonical API
docs (docs/developer/api/**). Do not hand-edit request files — edit
the doc and re-run scripts/gen_bruno_from_docs.py --apply.
Hand-authored exceptions (not generated):
- NewDevDBSetup/ — ordered dev-database bootstrap sequence
- */scenarios/, media-items/filters, media-items/search — edge-case suites
- environments/Bookhoard.yml — variables
Run order: NewDevDBSetup (RegisterUser captures {{token}}), then any
request. Device-token routes (kobo/koreader/opds) need {{device_token}}
or {{kobo_device_token}} in the environment.
The docs site (Developer → API) is the single source of truth for
shapes; internal/docs/drift_test.go enforces docs-to-routes and
docs-to-Bruno parity.
type: text/markdown
bundled: false
extensions: {}