Task: Fan Subscription Feed API — Cursor, Visibility, Scale Path (Hard)
Overview
No aggregated timeline exists. Implement the core fan feed API with cursor pagination, strict visibility, stable ordering, empty-state semantics, and query plans that won’t melt under many subscriptions — not IN (all creator ids) without thought.
Scope (must all ship)
API
GET /api/v1/feed/subscriptions?cursor&limit&filter? — authenticated fan
- Envelope:
{ data, nextCursor, hasMore } (match existing pagination conventions)
filter: all | media | text (or documented equivalent)
- Default limit + hard max (e.g. 50)
Semantics
- Only active subscriptions
- Include posts visible to fan:
public + subscribers from those creators; never others’ private
- Exclude soft-deleted posts and non-published
- Order
publishedAt DESC, id DESC for stable cursors
- Cursor opaque (base64 of
{publishedAt,id}) — no raw offset pages as primary
Query design
- Prefer SQL that scales: join subscriptions ↔ posts with proper indexes
- Document EXPLAIN for representative seed (in PR or docs)
- Soft upper bound: if fan has >N subscriptions, still correct (test with ≥25 creators seeded)
Caching (optional but scored)
- Document why HTTP cache not used (auth) OR ETag stub
Errors
- Unauthenticated →
401
- Invalid cursor →
400 with VALIDATION_ERROR
Swagger + docs
docs/feed.md: cursor format, visibility, empty vs unsubscribed
Testing (≥12)
- Auth required
- Sees subscriber-only from subscribed creator
- Does not see subscriber-only after cancel
- Does not see other creators’ posts
- Cursor page 2 continuity + no dupes
- Empty subscriptions → empty data
hasMore: false
- Filter media/text
- Soft-deleted excluded
- Invalid cursor 400
- Ordering stability with same timestamp
Deliverables
FeedModule (or posts extension), DTOs, indexes/migration, Swagger
- Docs + ≥12 tests
Acceptance Criteria
Out of scope
- Ranked/ML feed
- Following non-paid “follow” graph (subscriptions only)
Task: Fan Subscription Feed API — Cursor, Visibility, Scale Path (Hard)
Overview
No aggregated timeline exists. Implement the core fan feed API with cursor pagination, strict visibility, stable ordering, empty-state semantics, and query plans that won’t melt under many subscriptions — not
IN (all creator ids)without thought.Scope (must all ship)
API
GET /api/v1/feed/subscriptions?cursor&limit&filter?— authenticated fan{ data, nextCursor, hasMore }(match existing pagination conventions)filter:all | media | text(or documented equivalent)Semantics
public+subscribersfrom those creators; never others’ privatepublishedAt DESC, id DESCfor stable cursors{publishedAt,id}) — no raw offset pages as primaryQuery design
Caching (optional but scored)
Errors
401400withVALIDATION_ERRORSwagger + docs
docs/feed.md: cursor format, visibility, empty vs unsubscribedTesting (≥12)
hasMore: falseDeliverables
FeedModule(or posts extension), DTOs, indexes/migration, SwaggerAcceptance Criteria
Out of scope