Content Module Feature List
Feature surfaces for newsletter publishing, tier entitlement, featured placement, and subscriber delivery workflows.
Content Module - Feature List
1. Feature Overview
Content module implements newsletter publishing with two access levels:
- public preview for published items
- entitled full access via active subscription tiers (
newsletter.basic,newsletter.premium)
The module is split into leaf API surfaces for:
- content series
- content items
- featured content
2. Route Ownership and Surfaces
| Surface | Route prefix | Owner |
|---|---|---|
| Admin API (series) | /api/admin/content-series | SeriesAdminController |
| Admin API (items) | /api/admin/content-items | ContentAdminController |
| Admin API (featured) | /api/admin/content-featured | ContentFeaturedAdminController |
| Customer API (series) | /api/content/series | SeriesCustomerController |
| Customer API (items + library) | /api/content | ContentCustomerController |
| Customer API (featured) | /api/content/items/featured | ContentFeaturedCustomerController |
| Mobile-composed customer API | /api/mobile/content/... | MobileModule composition |
3. Admin Feature Matrix
| Capability | Endpoint | AuthZ |
|---|---|---|
| List/create/update/delete series | /api/admin/content-series + /:id | ContentSeries_* |
| Set series tier | POST /api/admin/content-series/:id/tier | ContentSeries_UPDATE |
| List/create/update/delete items | /api/admin/content-items + /:id | Content_* |
| Publish/unpublish item | `POST /api/admin/content-items/:id/publish | unpublish` |
| Set item tier | POST /api/admin/content-items/:id/tier | Content_UPDATE |
| Send newsletter | `POST /api/admin/content-items/:id/send-email | send-push` |
| Subscriber list | GET /api/admin/content-items/subscribers | Content_READ |
| Featured list/detail/create/update/delete | /api/admin/content-featured + /:id | Content_READ/CREATE/UPDATE/DELETE |
| Featured reorder | POST /api/admin/content-featured/reorder | Content_UPDATE |
4. Customer/Mobile Feature Matrix
| Capability | Endpoint | Auth mode |
|---|---|---|
| List active series | GET /api/content/series | Public |
| Series detail by slug | GET /api/content/series/:slug | Public |
| List published items | GET /api/content/items | Public |
| Preview by slug | GET /api/content/items/:slug | Public |
| Full item by slug | GET /api/content/items/:slug/full | JWT |
| My library | GET /api/content/my-library | JWT |
| Featured active list | GET /api/content/items/featured | Public |
| Featured paginated list | GET /api/content/items/featured/all | Public |
Mobile equivalents are available under /api/mobile/content/....
5. Key Business Rules
- Content type is currently constrained to
newsletter(content_typeenum). - Tier requirement is resolved from
newsletter_content_tierwith item-level rule taking precedence over series-level rule. basicaccess can be satisfied bybasicorpremium;premiumrequirespremium.featured_contentis a separate model; newsletter pinning is not read fromcontent_item.isPinned.- Featured date windows are DB validated:
start_date <= end_datewhen both are present. - Slug-history fallback is used for backward-compatible series/item URL lookups.
6. State Models
6.1 Newsletter item status model
Additional runtime constraints:
publishedwith a futurescheduledAtis rejected (CONTENT_STATUS_INVALID).- archived content cannot be republished (
CONTENT_ARCHIVED_NOT_PUBLISHABLE).
6.2 Entitlement state model
no tier rule -> preview/free content
tier rule (basic|premium) + active user_feature_access_window -> full access
missing entitlement -> CONTENT_ACCESS_DENIED
7. Caching Strategy
Content customer keyspaces:
content:customer:items:list:content:customer:item:slug:content:customer:library:content:customer:subscriptions:content:customer:series:list:content:customer:series:slug:
Featured keyspaces:
content:featured:admin:list:content:featured:customer:active:content:featured:customer:all:
Implementation notes:
- deterministic keys via
CacheKeyUtil.build(...) - invalidation via
invalidatePattern(prefix*)after admin writes - Redis read/write failures degrade gracefully to DB reads with warning logs
8. Rate Limiting
Content rate-limit envs:
CONTENT_ADMIN_RATE_LIMITCONTENT_ADMIN_RATE_WINDOW_SECONDSCONTENT_CUSTOMER_ITEM_RATE_LIMITCONTENT_CUSTOMER_ITEM_RATE_WINDOW_SECONDSCONTENT_CUSTOMER_SERIES_RATE_LIMITCONTENT_CUSTOMER_SERIES_SEARCH_RATE_LIMITCONTENT_CUSTOMER_SERIES_RATE_WINDOW_SECONDS
Operational behavior:
- Redis sorted-set sliding windows keyed per client/user and endpoint class
- request identifiers use UUIDv7
- threshold breach throws
RateLimitExceededExceptionwithRATE_LIMIT_EXCEEDED
9. Queue/Worker Features
Content module triggers newsletter delivery jobs:
9.1 Newsletter Email Delivery
| Property | Value |
|---|---|
| Queue | QueueName.NOTIFICATIONS |
| Job ID | newsletter:email:{contentItemId} |
| Trigger | Admin sends via /api/admin/content-items/:id/send-email |
9.2 Newsletter Push Delivery
| Property | Value |
|---|---|
| Queue | QueueName.NOTIFICATIONS |
| Job ID | newsletter:push:{contentItemId} |
| Trigger | Admin sends via /api/admin/content-items/:id/send-push |
10. Error UX Mapping
| Scenario | API behavior | Recommended UI |
|---|---|---|
| Content not found | 404 CONTENT_NOT_FOUND | Show "Newsletter not found" toast |
| Series not found | 404 CONTENT_SERIES_NOT_FOUND | Show "Series not found" toast |
| Access denied (no tier) | 403 CONTENT_ACCESS_DENIED | Show subscribe CTA, redirect to pricing |
| Access denied (expired) | 403 CONTENT_ACCESS_DENIED | Show renewal CTA |
| Published status invalid | 400 CONTENT_STATUS_INVALID | Show "Cannot schedule future publish" |
| Archived republish | 400 CONTENT_ARCHIVED_NOT_PUBLISHABLE | Show "Archived content cannot be republished" |
| Category not found | 404 CONTENT_CATEGORY_NOT_FOUND | Show "Category not found" toast |
| Featured not found | 404 FEATURED_CONTENT_NOT_FOUND | Show not-found toast |
| Featured invalid date | 400 FEATURED_CONTENT_INVALID_DATE_RANGE | Show date validation error |
| Tag not found | 404 TAG_NOT_FOUND | Show "Tag not found" error |
| Rate limit exceeded | 429 RATE_LIMIT_EXCEEDED | Show "Please wait" with backoff |
11. Newsletter Features
- subscription-based entitlement model (not
product_access) - admin tier assignment for series/items (
basicorpremium) - subscriber listing with tier filter (
all,basic,premium) - email and push delivery endpoints for newsletter broadcasts
Flow diagram:
12. Integration Flows
12.1 Newsletter Publishing Flow
An admin creates and sends a newsletter to subscribers.
- Admin calls
POST /api/admin/content-seriesto create a series with tier configuration. - Admin calls
POST /api/admin/content-itemsto create a newsletter item linked to the series. - Admin calls
POST /api/admin/content-items/:id/publishto publish the newsletter. - (Optional) Admin calls
POST /api/admin/content-items/:id/send-emailto email subscribers orsend-pushfor push notifications. - System enqueues newsletter delivery job to
QueueName.NOTIFICATIONS.
12.2 Subscriber Access Flow
A customer accesses full newsletter content via subscription entitlement.
- Customer browses public newsletter list via
GET /api/content/items. - Customer clicks a newsletter, triggering
GET /api/content/items/:slugwhich returns preview content. - Customer calls
GET /api/content/items/:slug/fullwith JWT. - System checks
newsletter_content_tierfor item-level or series-level requirement. - System resolves active tiers from
user_feature_access_window. - If entitled, system returns full content; if not, returns
CONTENT_ACCESS_DENIEDwith subscribe CTA.
12.3 Featured Newsletter Flow
An admin promotes a newsletter via featured placement.
- Admin calls
POST /api/admin/content-featuredwith newsletter item ID and date window. - Admin calls
POST /api/admin/content-featured/reorderto adjust display priority. - Customer calls
GET /api/content/items/featuredto see active featured newsletters. - Customer calls
GET /api/content/items/featured/allfor paginated featured list.
13. Release/QA Checklist
- Admin series/item/featured routes resolve and enforce respective permission codes.
- Publish/unpublish and scheduling constraints enforce status invariants.
- Tier assignment works at item and series level with item-first precedence.
- Preview is public and full content stays JWT + entitlement protected.
- Featured date-window validation rejects invalid ranges.
- Series/item slug-history fallback resolves legacy slugs.
- Customer and featured cache keyspaces invalidate correctly on admin mutations.
- Content and series customer endpoints enforce configured rate windows.
Time fields in this module are stored as timezone-aware values and should be handled as ISO-8601 instants by API consumers.
See Also
- API Reference: See Content - API & Integration Guide Section 11 (Endpoint Reference + Payload Cheatsheet) for complete request/response DTOs.
- Backend Reference: See Content - Backend Documentation Section 3 (Data Model) for schema details.