
Real-world MOTH files to learn from and adapt for your projects.
Multi-tenant Digital Asset Management system with vector search, rights management, and automation
#MOTH:repo
meta:{project:MediaHub-DAM;version:1.0;date:2025-10-27;author:System}
[GOAL]
Build a multi-tenant Digital Asset Management and Services backend with API, web app, vector search, reviews, rights, delivery, and automation. Cloud-agnostic deployment; strict RLS and typed contracts.
[FEATURES]
TenantAuth:P0; RBAC:P0; Ingest:P0; Assets:P0; Versions:P0; Renditions:P0; Search:P0; Rights:P0; Reviews:P0; Jobs:P0; Delivery:P0; Audit:P0; Monitoring:P0; Security:P0
AutoTagging:P1; Billing:P2; Watermarking:P2; WorkflowDesigner:P3
[RULES]
api_style:REST+GraphQL; tenancy:RLS_enforced; id_format:uuid_v7; originals:immutable; timestamps:utc_iso8601; webhooks:ack_fast→enqueue; rbac:model=role_acl; pii:encrypted; codegen:types_first
[SCHEMAS]
tenants:{*id=uuid;*name=string;*domain=hostname}
users:{*id=uuid;*email=email;(name)=string}
roles:{*id=uuid;*tenant_id=uuid;*user_id=uuid;*role=enum[owner,admin,editor,viewer]}
projects:{*id=uuid;*tenant_id=uuid;*name=string}
assets:{*id=uuid;*tenant_id=uuid;*project_id=uuid;*kind=enum[image,video,doc];*uri=url;*bytes=int;*hash=string;status=enum[active,deleted]}
versions:{*id=uuid;*asset_id=uuid;*seq=int;*uri=url;*bytes=int}
renditions:{*id=uuid;*version_id=uuid;*profile=enum[thumb,proxy,full];*uri=url;*width=int;*height=int}
rights:{*id=uuid;*tenant_id=uuid;*name=string;(start)=string;(end)=string}
asset_rights:{*asset_id=uuid;*rights_id=uuid;status=enum[granted,expired]}
reviews:{*id=uuid;*asset_id=uuid;*user_id=uuid;state=enum[open,approved,changes]}
jobs:{*id=uuid;*asset_id=uuid;*type=enum[thumb,proxy,tag,transcode];*status=enum[pending,done,failed]}
audit:{*id=uuid;*tenant_id=uuid;*actor=uuid;*action=enum[create,update,delete,export];*object=string;*ts=string}
[RELATIONSHIPS]
tenants→projects; projects→assets; assets→versions; versions→renditions; assets←→rights; assets→reviews; assets→jobs
[VALIDATIONS]
assets.kind=image→width!>=256;height!>=256
versions.seq:strictly_increasing
rights_window:now∉[rights.start,rights.end]→status=expired
audit_required:asset.read,asset.export
[WORKFLOWS]
ingest:{received→scanned→registered→ready}
review:{open→approved|changes→closed}
jobs:{pending→processing→done|failed}
[API]
POST:/v1/assets{project_id,kind,bytes,mime,hash}→{asset_id,upload_url}
GET:/v1/assets/{id}→{asset,versions,renditions}
POST:/v1/search/text{q,limit}→{asset_ids}
POST:/v1/reviews{asset_id,version_seq}→{review_id}
POST:/v1/jobs{asset_id,type}→{job_id}
POST:/v1/exports{asset_id,policy_id}→{uri}
GET:/v1/audit{tenant_id,limit}
[FORBIDDEN]
no_plaintext_secrets:true; no_public_originals:true; no_egress_bypass:true; no_admin_without_rbac:true
[AUTOMATION]
minute:job_dispatcher; hourly:rights_checker; nightly:index_rebuild
retry:exponential; idempotency:true; dlq:true
[DEPLOYMENT]
platform:CloudAgnostic; runtime:{API=FastAPI|Node;Workers=Queues;Storage=S3|GCS;DB=Postgres+pgvector}; ci_cd:GitHubActions
[ENVIRONMENTS]
dev:{domain=api.dev.mediahub.local}
prod:{domain=api.mediahub.io}
[INTEGRATIONS]
Auth0:OIDC; S3:SignedURLs; FFmpeg:Transcode; OpenAI:Embeddings; Cloudflare:CDN
[METRICS]
KPI:{ingest_to_ready<60s; job_success>0.98; search_p95<300ms}
alert:on_job_fail>5%; on_dlq_growth:true; on_db_p95>100ms
[END]
checksum:sha1:3f4d9bcaf1