diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 7c67d62..4ab4b38 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -73,13 +73,13 @@ Requirements for v1 (the Płytarium port). Each maps to roadmap phases. "User" b ### Płytarium API (API) -- [ ] **API-01**: Collections: CRUD, active-context switch (me/context returns an opaque channel name), editor invitations and acceptance, share link regeneration, public token views -- [ ] **API-02**: Albums: CRUD, ratings, reservations, photo upload and manual cover URL, Discogs cover price, artists/genres/styles lookups, search that treats Typesense as a pre-filter re-gated in SQL -- [ ] **API-03**: Wishlist: items, subscriptions, public-wishlist/{token} views, purchase and digest triggers +- [ ] **API-01**: Collections: CRUD, active-context switch (me/context flags plus the opaque channel name from realtime/channels), editor invitations and acceptance, owner-only share link show/update/regenerate +- [ ] **API-02**: Albums: CRUD, ratings, photo upload and manual cover URL, Discogs cover import (cover_urls), artists/genres/styles lookups, search that treats Typesense as a pre-filter with both the items and the total re-gated in SQL +- [ ] **API-03**: Wishlist: items, subscriptions, public-wishlist/{token} views, album reservations (reserve/reveal), purchase and digest triggers - [ ] **API-04**: Notifications: list, mark read, prune; realtime token endpoint owned by the websockets plugin - [ ] **API-05**: CSV import as a multi-step session (store, show/poll, mapping patch, per-row edit, commit, cancel) and CSV export on both authenticated groups - [ ] **API-06**: Per-user and per-org Discogs and AI credentials CRUD with encrypted storage, org-lock flag, and env-to-org-to-user resolution -- [ ] **API-07**: Onboarding, public and invitation inspection routes with their public rate-limit buckets +- [ ] **API-07**: Onboarding, public and invitation inspection routes, including the anonymous collection public-token views (public/{token}, its albums and album detail), with their public rate-limit buckets - [ ] **API-08**: Feedback submissions and sitemap output from the stack plugins - [ ] **API-09**: All 154 routes are registered on the correct groups with identical paths, methods, status codes and bodies @@ -102,7 +102,7 @@ Requirements for v1 (the Płytarium port). Each maps to roadmap phases. "User" b ### Integrations (INTG) -- [ ] **INTG-01**: Discogs client with proactive rate threshold, bounded in-request wait budget, retry-after fallback, and host-locked cover fetch +- [ ] **INTG-01**: Discogs client with proactive rate threshold, bounded in-request wait budget, retry-after fallback, and host-locked cover fetch, plus the albums/{id}/cover-price/discogs route - [ ] **INTG-02**: AI cover recognition through provider adapters (Anthropic Go SDK, OpenAI-compatible) with per-credential model and base URL overrides ### Admin (ADMIN) diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 42e808b..7555c97 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -600,16 +600,16 @@ Plans: ### Phase 12: Płytarium API — Collections and Albums -**Goal**: Collections and Albums endpoints are ported with byte-compatible request/response shapes, including active-context switching, editor invitations, ratings, reservations, cover handling and search. +**Goal**: Collections and Albums endpoints are ported with byte-compatible request/response shapes, including active-context switching, editor invitations, ratings, manual cover URL and Discogs cover import, and search. **Mode:** mvp **Depends on**: Phase 5, Phase 6, Phase 7, Phase 11 **Repos:** fonoteka.go, sm-user-plugin (submodule at fonoteka.go/plugins/golem15/user) **Requirements**: API-01, API-02 **Success Criteria** (what must be TRUE): - 1. Collections CRUD, the `me/context` active-collection switch (returning an opaque channel name), editor invitation/acceptance, share-link regeneration and public token views all pass the parity diff. - 2. Albums CRUD, ratings, reservations, photo upload, manual cover URL and Discogs cover price all pass the parity diff. - 3. Album search treats Typesense results as a pre-filter re-gated in SQL, verified by a security test that a stale/mis-scoped search document cannot leak an unauthorized result. + 1. Collections CRUD with photos and image, the `collections/{id}/switch` and `me/context` flags, the opaque channel name from `GET realtime/channels`, editor invitation/acceptance and members, and the owner-only `collection/share` show/update/regenerate all pass the parity diff (anonymous public token views moved to Phase 13). + 2. Albums CRUD, ratings, photo upload, manual cover URL and Discogs cover import on create/bulk (`cover_urls`), plus sync/stats/value/missing/bulk all pass the parity diff (reservations moved to Phase 13, the Discogs cover-price route to Phase 14). + 3. Album search treats Typesense results as a pre-filter re-gated in SQL, and the search total is the re-gated SQL count over at most 1000 engine ids (Scout v10.25.0), verified by a security test that a stale/mis-scoped search document can neither leak an unauthorized result nor be counted in the total. 4. Artists/genres/styles lookup endpoints used by the Albums UI pass the parity diff. 5. A request-DTO-level fuzz over every write endpoint asserts unknown and server-owned keys are never persisted (inherits the HTTP half of Phase 5 criterion 3; the HTTP layer does not exist until Phase 6/12). @@ -641,11 +641,11 @@ Plans: **Requirements**: API-03, API-04, API-05, API-06, API-07 **Success Criteria** (what must be TRUE): - 1. Wishlist items, subscriptions, `public-wishlist/{token}` views and purchase/digest triggers pass the parity diff. + 1. Wishlist items, subscriptions, `public-wishlist/{token}` views, reservations (`wishlist/albums/{id}/reserve|reveal`) and purchase/digest triggers pass the parity diff. 2. Notifications list/mark-read/prune endpoints pass the parity diff (the realtime token endpoint itself is owned by the websockets plugin, ported in Phase 11). 3. CSV import runs as a multi-step session (store, show/poll, mapping patch, per-row edit, commit, cancel) and CSV export works on both authenticated groups, all passing the parity diff. 4. Per-user and per-org Discogs/AI credentials CRUD store encrypted values, honor the org-lock flag, and resolve env-to-org-to-user correctly. - 5. Onboarding, public and invitation-inspection routes are reachable without auth and enforce their own public rate-limit buckets. + 5. Onboarding, public and invitation-inspection routes, including the anonymous collection views `public/{token}`, `public/{token}/albums` and `public/{token}/albums/{id}`, are reachable without auth and enforce their own public rate-limit buckets. **Plans**: TBD @@ -661,7 +661,7 @@ Plans: 1. The CSV import write job and the self-redispatching Discogs match job (240s timeout, self-redispatching with a delay on a Discogs rate-limit error) both complete correctly. 2. The wishlist digest job coalesces a 30-minute window and deletes its queue row on completion. 3. The `reindex` command asserts zero `collection_id`-0 documents before and after and can drop the legacy index. - 4. The Discogs client enforces its proactive rate threshold, bounded wait budget, retry-after fallback and host-locked cover fetch. + 4. The Discogs client enforces its proactive rate threshold, bounded wait budget, retry-after fallback and host-locked cover fetch, and the `albums/{id}/cover-price/discogs` route passes the parity diff. 5. AI cover recognition works through both Anthropic and OpenAI-compatible adapters with per-credential model/base-URL overrides. 6. Feedback submissions and sitemap output work; the ported `oauth-client`/`prune-notifications`/`reindex` commands all run correctly. diff --git a/.planning/todos/pending/lagoon-validate-min-message.md b/.planning/todos/done/lagoon-validate-min-message.md similarity index 100% rename from .planning/todos/pending/lagoon-validate-min-message.md rename to .planning/todos/done/lagoon-validate-min-message.md