Asset Management Architecture¶
This document describes the asset management and license system architecture in Diskover.
Overview¶
The asset system enables sellers to upload digital files to their organization's storage, link them to products, and allow buyers to download them after purchase. Access is controlled through entitlements created on purchase completion.
Key Components¶
License System¶
Organizations have licenses that define usage limits:
| Field | Description | Default (Free Tier) |
|---|---|---|
max_upload_size_mb |
Maximum single file upload size | 100 MB |
max_total_storage_mb |
Total storage quota | 1000 MB (1 GB) |
max_assets_count |
Maximum number of assets | 100 |
max_products_count |
Maximum number of products | 50 |
max_members_count |
Maximum organization members | 5 |
Licenses are assigned to organizations via the org_licenses table. New organizations automatically receive the default "free" license.
Asset Storage¶
Assets are stored in S3-compatible storage (Railway Object Storage, AWS S3, MinIO, etc.).
Storage Key Format: {org_id}/{asset_id}/{filename}
Presigned URLs: - Upload URLs: 15-minute expiration - Download URLs: 1-hour expiration
Entitlements¶
Entitlements grant users access to specific assets:
- Created automatically when a transaction completes
- For digital products: expires_at is NULL (lifetime access)
- For memberships: expires_at matches subscription period end
System Architecture Diagram¶
FRONTEND (React)
+---------------------------------------------------------------------------+
| Dashboard UI Product Pages Asset Upload (S3) |
| - Org Mgmt - List/Detail - Direct upload via |
| - Asset Mgmt - Checkout presigned URL |
| - Purchases - Downloads |
+----------+----------------+------------------------+----------------------+
| | |
| HTTP + JWT | | S3 Presigned URL
v v v
+---------------------------------------------------------------------------+
| BACKEND (Go + Chi) |
| +---------------------------------------------------------------------+ |
| | Clerk Auth Middleware | |
| | (JWT validation, user sync) | |
| +---------------------------------------------------------------------+ |
| | |
| +-------------+ +-------------+ +-------------+ +-------------------+ |
| |User Handler | |Org Handler | |Asset Handler| |Transaction Handler| |
| +------+------+ +------+------+ +------+------+ +--------+----------+ |
| | | | | |
| +------v------+ +------v------+ +------v------+ +--------v----------+ |
| |User Service | |Org Service | |Asset Service| |Transaction Service| |
| +------+------+ +------+------+ +------+------+ +--------+----------+ |
| | | | | |
| | | +------v------+ | |
| | | |Storage Svc |----------+------------+ |
| | | |(S3 presign) | | | |
| | | +-------------+ | | |
| +------v---------------v---------------+-----------------v---------+ | |
| | Repository Layer | | |
| | UserRepo | OrgRepo | AssetRepo | ProductRepo | TransactionRepo | | |
| | | EntitlementRepo | SubscriptionRepo | | |
| +----------------------------------------+-------------------------+ | |
+--------------------------------------------|----------------------------+ |
| |
v v
+------------------------+ +-------------------+
| PostgreSQL | | Railway S3 |
| +--------+ +--------+ | | (Object Storage) |
| | users | | orgs | | | |
| |products| | assets | | | {org_id}/ |
| |trans- | |entitle-| | | {asset_id}/ |
| |actions | |ments | | | {filename} |
| +--------+ +--------+ | +-------------------+
+------------------------+
Data Flow Diagrams¶
Purchase & Download Flow¶
PURCHASE FLOW
Buyer Frontend Backend DB
| | | |
| 1. Add to cart | | |
|-------------------->| | |
| | | |
| 2. Checkout | | |
|-------------------->| | |
| | 3. POST /transactions |
| |-------------------->| |
| | | 4. Create |
| | | transaction |
| | |-------------------->|
| | | |
| | | 5. Get product |
| | | assets |
| | |-------------------->|
| | | |
| | | 6. Create |
| | | entitlements |
| | |-------------------->|
| | | |
| | 7. Success | |
| |<--------------------| |
| 8. Show confirm | | |
|<--------------------| | |
DOWNLOAD FLOW
Buyer Frontend Backend DB S3
| | | | |
| 1. View purchases | | | |
|-------------------->| | | |
| | 2. GET /assets/{id}/download | |
| |-------------------->| | |
| | | 3. Check | |
| | | entitlement | |
| | |-------------------->| |
| | | 4. Valid | |
| | |<--------------------| |
| | | | |
| | | 5. Generate presigned URL |
| | |------------------------------------------->|
| | | 6. Presigned URL |
| | |<-------------------------------------------|
| | | | |
| | 7. Download URL | | |
| |<--------------------| | |
| | |
| | 8. Download file directly from S3 |
| |---------------------------------------------------------------->|
| 9. File download | |
|<--------------------| |
Asset Upload Flow¶
UPLOAD FLOW
Seller Frontend Backend DB S3
| | | | |
| 1. Select file | | | |
|-------------------->| | | |
| | | | |
| | 2. POST /orgs/{id}/assets | |
| | (name, type, size) | |
| |-------------------->| | |
| | | | |
| | | 3. Check license | |
| | | limits | |
| | |-------------------->| |
| | | | |
| | | 4. Create asset | |
| | | record | |
| | |-------------------->| |
| | | | |
| | | 5. Generate upload presigned URL |
| | |------------------------------------------->|
| | | 6. Presigned URL |
| | |<-------------------------------------------|
| | | | |
| | 7. Asset + URL | | |
| |<--------------------| | |
| | |
| | 8. PUT file to S3 (direct upload) |
| |---------------------------------------------------------------->|
| | 9. Upload complete |
| |<----------------------------------------------------------------|
| 10. Success | | | |
|<--------------------| | | |
Entity Relationship Diagram¶
+------------------+ +------------------+ +------------------+
| users | | orgs | | products |
+------------------+ +------------------+ +------------------+
| id | +-->| id |<--+ | id |
| clerk_id | | | name | | | org_id ----------+---+
| email | | | slug | | | name | |
| name | | | is_personal | | | type | |
| personal_org_id -+---+ +------------------+ | | price | |
+------------------+ | | | subscription_days| |
| | | +------------------+ |
| +-----------+---------+ | | |
| | org_members | | +------+--------+ |
| +---------------------+ | | product_assets | |
| | org_id | | +---------------+ |
+------------->| user_id | | | product_id | |
| role | | | asset_id -----+---+ |
+---------------------+ | +---------------+ | |
| | |
+------------------+ +------------------+ | | |
| transactions | | assets | | | |
+------------------+ +------------------+ | | |
| id | | id |<--+-----------------------+ |
| user_id ---------+--+ | org_id ----------+---+ |
| product_id ------+--+----| name | |
| amount | | | storage_key |<-----------------------------+
| status | | | content_type |
+------------------+ | | size_bytes |
| | +------------------+
| |
+------+---------+ | +------------------+ +------------------+
| entitlements | | | subscriptions | | licenses |
+----------------+ | +------------------+ +------------------+
| id | | | id | | id |<---------+
| user_id -------+----+ | user_id ---------+->+ | name | |
| asset_id | | product_id | | | max_upload_size | |
| product_id | | status | | | max_total_storage| |
| transaction_id | | period_start | | | max_assets | |
| expires_at | | period_end | | | max_products | |
+----------------+ +------------------+ | | max_members | |
| | monthly_fee | |
| | is_default | |
| +------------------+ |
| |
| +------------------+ |
| | org_licenses | |
| +------------------+ |
| | org_id ----------+-> orgs |
| | license_id ------+----------+
| | expires_at |
| +------------------+
API Endpoint Reference¶
Asset Management¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /orgs/{org_id}/assets |
List organization assets |
| POST | /orgs/{org_id}/assets |
Create asset and get upload URL |
| GET | /orgs/{org_id}/assets/{id} |
Get asset details |
| PATCH | /orgs/{org_id}/assets/{id} |
Update asset metadata |
| DELETE | /orgs/{org_id}/assets/{id} |
Delete asset |
| GET | /orgs/{org_id}/assets/usage |
Get storage usage |
Product-Asset Linking¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /orgs/{org_id}/products/{id}/assets |
List product assets |
| POST | /orgs/{org_id}/products/{id}/assets |
Add asset to product |
| DELETE | /orgs/{org_id}/products/{id}/assets/{asset_id} |
Remove asset from product |
Downloads¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /assets/{id}/download |
Get download URL (validates entitlement) |
Organization License¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /orgs/{org_id}/license |
Get organization license info |
Organization Role Permissions¶
| Action | Owner | Admin | Member | Viewer |
|---|---|---|---|---|
| View org details | Yes | Yes | Yes | Yes |
| Upload assets | Yes | Yes | Yes | No |
| Delete own assets | Yes | Yes | Yes | No |
| Delete any asset | Yes | Yes | No | No |
| Create products | Yes | Yes | No | No |
| Edit/delete products | Yes | Yes | No | No |
| Link assets to products | Yes | Yes | No | No |
| Invite members | Yes | Yes | No | No |
| Change member roles | Yes | Yes (not owner) | No | No |
| Remove members | Yes | Yes (not owner) | No | No |
| Edit org settings | Yes | Yes | No | No |
| Delete org | Yes | No | No | No |
| Transfer ownership | Yes | No | No | No |
S3 Storage Configuration¶
Environment Variables¶
# Railway Object Storage or S3-compatible provider
S3_ENDPOINT=https://<bucket>.railway.app
S3_REGION=us-east-1
S3_BUCKET=diskover-assets
S3_ACCESS_KEY_ID=your_access_key
S3_SECRET_ACCESS_KEY=your_secret_key
S3_USE_PATH_STYLE=true # Required for Railway and MinIO
Storage Key Structure¶
Example: diskover-assets/550e8400-e29b-41d4-a716-446655440000/6ba7b810-9dad-11d1-80b4-00c04fd430c8/design-course.zip
License Tiers¶
| Tier | Upload | Storage | Assets | Products | Members | Price |
|---|---|---|---|---|---|---|
| Free | 100 MB | 1 GB | 100 | 50 | 5 | $0/mo |
| Starter | 500 MB | 10 GB | 500 | 100 | 10 | $19/mo |
| Pro | 2 GB | 100 GB | 2000 | 500 | 50 | $49/mo |
| Enterprise | 10 GB | 1 TB | Unlimited | Unlimited | Unlimited | Contact |
Note: Only the free tier is implemented. Paid tiers are for future billing integration.
File Upload Validation¶
Client-Side¶
- Check file size against
max_upload_size_bytesfrom usage endpoint - Validate content type (frontend can show appropriate icons)
- Display upload progress during S3 direct upload
Server-Side¶
- Verify
size_bytesagainst licensemax_upload_size_mb - Check total storage usage against
max_total_storage_mb - Verify asset count against
max_assets_count - Reject uploads that exceed any limit with clear error messages
Related Documentation¶
- Architecture Overview - System-wide architecture
- Features Reference - Complete feature list
- Deployment Guide - Production deployment
- Testing Guide - Testing procedures