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:
John O'Keefe committed 2026-10-24 15:29:24 -04:00
1 parent 7471ca99e8
commit fa00d6d3cb
20 files changed
+714 -416

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
---
method: GET
path: /api/series
auth: jwt
area: series
---
<!-- source: internal/handlers/series.go:29 SeriesHandler.GetSeries -->
# List Series
Returns a paginated list of series for the requesting user's visible libraries.
## Example response
```json example-response
{
"series": [
{
"name": "The Witcher",
"library_id": "550e8400-e29b-41d4-a716-446655440000",
"book_count": 5,
"total_in_series": 8,
"cover_paths": [],
"last_entry_at": "2026-10-24T13:57:01Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}
```
## Query parameters
| Param | Type | Required | Notes |
| ----- | ---- | -------- | ----- |
| library_id | uuid | No | Scope to one library (must be visible) |
| limit | int | No | 1-100 (default 20) |
| offset | int | No | Pagination offset |
## Errors
| Status | Body | When |
| ------ | ---- | ---- |
| 400 | `{"error": "invalid library_id"}` | malformed library_id |
| 403 | `{"error": "library not accessible"}` | library not in visible set |
| 500 | `{"error": "Failed to load series"}` | unexpected server error |