Context
Photon currently manages server licenses via Stripe subscriptions. We need to introduce Content Packs: downloadable ZIP files sold separately as one-time purchases via Stripe Checkout, independent of subscription plans.
Key Requirements
- Admin System: Administrators need a panel to upload and manage content-pack ZIP files and metadata (name, version, category, description).
- Storage and Delivery: Store files on the server at /downloads/{pack_id}.zip. Deliver them through a protected endpoint that validates ownership.
- Ownership Tracking: Track user purchases by linking user email/UUID to the content pack ID, including first-download timestamps and claim status. Unlimited copies are allowed.
- Stripe Integration: Support one-time purchases (price_pack_vX) alongside ongoing subscriptions. Checkout sessions must dynamically route to the correct metadata field based on the product type.
- Purchase Flow: One-time pack purchases must charge immediately and grant instant download access without a trial period. Display both options on the UI.
Database Schema Suggestions
Table : Packs
id (TEXT, NOT NULL, PRIMARY KEY)
name (TEXT, NOT NULL)
description (TEXT, DEFAULT NULL)
category (VARCHAR(255))
stripe_price_id (TEXT, NOT NULL, UNIQUE)
file_path (TEXT, DEFAULT "/downloads/{id}")
version_number (TEXT, DEFAULT "1.0")
Table : PackOwnership
user_email (VARCHAR(50))
pack_id (TEXT, REFERENCES Packs id ON DELETE CASCADE)
purchased_at (DATETIME, NOT NULL, DEFAULT CURRENT_TIMESTAMP)
is_active (BOOLEAN, DEFAULT TRUE)
PRIMARY KEY (user_email, pack_id)
API Endpoints
- POST /api/content-packs/upload (Admin): Create/modify a content-pack entry and validate file upload to /downloads/{id}.
- GET /admin/content-packs/list (Admin): Retrieve all active packs (JSON: name, id, version, category, status).
- DELETE /api/content-packs/remove/:packId (Admin): Remove pack metadata and delete the file.
- POST /checkout/create-session-{contentType} (User): Create Stripe session. Metadata must include product type ("subscription" vs "one-time-pack").
- GET /downloads/{packId} (Owner): Validate ownership via middleware and serve the ZIP file (403 if unauthorized).
Frontend Components
- Admin Panel: Add a "Content Packs Management" sidebar tab for uploading, listing, and deleting packs.
- Purchase Page: Display one-time content-pack products alongside standard subscriptions.
- User Dashboard: Add a section showing the user's claimed downloadable resources with download buttons.
## Metadata and Naming Conventions
- File naming: {pack_id}.zip (e.g., worlds-v2.zip).
- Stripe Checkout Metadata payload must look like this:
"client_reference_id": "pk_pack_worlds"
"type": "one-time-pack"
"content_pack_metadata_id": "my-world-packs-v3"
Security Considerations
- Strict Ownership Validation: The download endpoint must verify the purchase before serving files or redirecting.
- Rate Limiting: Implement a cap on download requests (e.g., 3 attempts per hour) to prevent link sharing.
- Scalability: Design the delivery layer so it can easily be swapped to AWS S3 pre-signed URLs or Stripe signed URLs in the future.
Context
Photon currently manages server licenses via Stripe subscriptions. We need to introduce Content Packs: downloadable ZIP files sold separately as one-time purchases via Stripe Checkout, independent of subscription plans.
Key Requirements
Database Schema Suggestions
Table : Packs
Table : PackOwnership
API Endpoints
Frontend Components
## Metadata and Naming Conventions
Security Considerations