docs(saved-filters,dashboard,system,series): Beam WO3 batch 5 — 15 endpoints + dedupe
Beam drafted 15 frontmatter'd docs (saved-filters CRUD, dashboard
sections/preferences/restore, system config/settings, series list + books);
Claude verified shapes against handlers and pinned the registry:
- saved-filters: SavedFilterResponse pinned by type (RFC3339 timestamps here,
unlike most of the API); create/update share CreateSavedFilterRequest
(resource_type oneof media-items|collections|devices)
- dashboard: preferences GET pin {hidden_collections, collection_order,
items_per_section}; PUT returns full UserDashboardPreferences row; sections
wrapper {sections}
- system: GET+PUT /api/system/config are admin-defined key/value maps — new
AnyJSONObject sentinel (gate shape-checks without key comparison; request
side too). UpdateSystemConfiguration returns {status, message} — verified,
not guessed. GET /api/system/settings returns []SettingEntry.
- series: {series[{name, library_id, book_count, total_in_series,
cover_paths, last_entry_at}], total, limit, offset}; books by
?name=&library_id= with family-lens 403
Dedupe: deleted dashboard.md, system/config.md, system/settings.md — each
covered the same endpoints as Beam's per-endpoint files (content merged by
the gate-verified shapes; old prose recoverable from git).
Beam clarifications confirmed: scanner routes are WO5 (docs exist);
progress/books-match are WO5.
This commit is contained in:
1 parent
7471ca99e8
commit
fa00d6d3cb
20 files changed
+714
-416
No files matched your search
@@ -0,0 +1,34 @@
|
||||
---
|
||||
method: GET
|
||||
path: /api/dashboard/preferences
|
||||
auth: jwt
|
||||
area: dashboard
|
||||
---
|
||||
<!-- source: internal/handlers/dashboard.go:285 DashboardHandler.GetPreferences -->
|
||||
|
||||
# Get Dashboard Preferences
|
||||
|
||||
Returns the signed-in user's dashboard preferences for a library (or the
|
||||
global scope when `library_id` is omitted).
|
||||
|
||||
## Example response
|
||||
|
||||
```json example-response
|
||||
{
|
||||
"hidden_collections": [],
|
||||
"collection_order": [],
|
||||
"items_per_section": 20
|
||||
}
|
||||
```
|
||||
|
||||
## Query parameters
|
||||
|
||||
| Param | Type | Required | Notes |
|
||||
| ----- | ---- | -------- | ----- |
|
||||
| library_id | uuid | No | Library scope; omitted = global |
|
||||
|
||||
## Errors
|
||||
|
||||
| Status | Body | When |
|
||||
| ------ | ---- | ---- |
|
||||
| 400 | `{"error": "invalid library_id"}` | malformed library_id |
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
method: GET
|
||||
path: /api/dashboard/sections
|
||||
auth: jwt
|
||||
area: dashboard
|
||||
---
|
||||
<!-- source: internal/handlers/dashboard.go:28 DashboardHandler.GetSections -->
|
||||
|
||||
# Get Dashboard Sections
|
||||
|
||||
Returns all dashboard sections for a library, in the user's customized order.
|
||||
Respects `collection_order` and `hidden_collections` preferences. `library_id`
|
||||
is optional; when omitted the global (all-libraries) scope is used.
|
||||
|
||||
## Example response
|
||||
|
||||
```json example-response
|
||||
{
|
||||
"sections": [
|
||||
{
|
||||
"id": "continue-reading",
|
||||
"collection_id": "",
|
||||
"is_system": true,
|
||||
"title": "Continue Reading",
|
||||
"description": "Books you're currently reading (0 < progress < 1)",
|
||||
"icon": "📖",
|
||||
"items": [],
|
||||
"view_all_url": "",
|
||||
"priority": 1,
|
||||
"is_playlist": false,
|
||||
"complete": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Query parameters
|
||||
|
||||
| Param | Type | Required | Notes |
|
||||
| ----- | ---- | -------- | ----- |
|
||||
| library_id | uuid | No | Library to scope sections to |
|
||||
| limit | int | No | Items per section (1-100, default from preferences) |
|
||||
|
||||
## Errors
|
||||
|
||||
| Status | Body | When |
|
||||
| ------ | ---- | ---- |
|
||||
| 400 | `{"error": "invalid library_id"}` | malformed library_id |
|
||||
| 500 | `{"error": "Failed to load dashboard sections"}` | unexpected server error |
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
method: POST
|
||||
path: /api/dashboard/restore-system-collection
|
||||
auth: jwt
|
||||
area: dashboard
|
||||
---
|
||||
<!-- source: internal/handlers/dashboard.go:132 DashboardHandler.RestoreSystemCollection -->
|
||||
|
||||
# Restore System Collection
|
||||
|
||||
Resets a system collection to its default state, removing user customizations.
|
||||
|
||||
## Example request
|
||||
|
||||
```json example-request
|
||||
{
|
||||
"collection_name": "Continue Reading",
|
||||
"reset_type": "full"
|
||||
}
|
||||
```
|
||||
|
||||
## Example response
|
||||
|
||||
```json example-response
|
||||
{
|
||||
"message": "System collection restored to defaults"
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Type | Required | Notes |
|
||||
| ----- | ---- | -------- | ----- |
|
||||
| collection_name | string | Yes | One of `Continue Reading`, `Recently Added`, `Recently Read`, `Not Started`, `Continue Series` |
|
||||
| reset_type | string | No | `full` (default) or `keep_books` |
|
||||
|
||||
## Errors
|
||||
|
||||
| Status | Body | When |
|
||||
| ------ | ---- | ---- |
|
||||
| 400 | `{"error": "Invalid request"}` / `{"error": "collection_name required"}` / `{"error": "Invalid system collection name"}` / `{"error": "reset_type must be 'full' or 'keep_books'"}` | malformed body or invalid values |
|
||||
| 500 | `{"error": "Failed to restore system collection"}` | unexpected server error |
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
method: PUT
|
||||
path: /api/dashboard/preferences
|
||||
auth: jwt
|
||||
area: dashboard
|
||||
---
|
||||
<!-- source: internal/handlers/dashboard.go:83 DashboardHandler.UpdatePreferences -->
|
||||
|
||||
# Update Dashboard Preferences
|
||||
|
||||
Saves or updates the signed-in user's dashboard preferences for a library.
|
||||
|
||||
## Example request
|
||||
|
||||
```json example-request
|
||||
{
|
||||
"library_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"hidden_collections": ["not-started"],
|
||||
"collection_order": ["recently-added", "continue-reading", "recently-read"],
|
||||
"items_per_section": 20
|
||||
}
|
||||
```
|
||||
|
||||
## Example response
|
||||
|
||||
```json example-response
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"user_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"library_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"hidden_collections": ["not-started"],
|
||||
"collection_order": ["recently-added", "continue-reading", "recently-read"],
|
||||
"items_per_section": 20,
|
||||
"created_at": "2026-10-24T13:57:01Z",
|
||||
"updated_at": "2026-10-24T13:57:01Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Type | Required | Notes |
|
||||
| ----- | ---- | -------- | ----- |
|
||||
| library_id | string (uuid) | No | `null`/absent = global scope; empty string is rejected |
|
||||
| hidden_collections | array | No | Collection ids to hide |
|
||||
| collection_order | array | No | Ordered list of collection ids |
|
||||
| items_per_section | int | No | Items per section |
|
||||
|
||||
## Errors
|
||||
|
||||
| Status | Body | When |
|
||||
| ------ | ---- | ---- |
|
||||
| 400 | `{"error": "Invalid request"}` / `{"error": "invalid library_id"}` | malformed body or library_id |
|
||||
| 500 | `{"error": "Failed to save preferences"}` | unexpected server error |
|
||||
Reference in new issue
Block a user