Uploads and Storage
The app has two storage classes: public uploads for browser-rendered media and private document storage for rule/source files.
Public Uploads
Public uploads include campaign covers, avatars, and NPC profile photos. They
are served from /uploads by FastAPI and proxied by Vite during development.
Primary files:
server/app/lib/uploads.pyserver/app/main.pyweb/src/lib/api.ts(resolveAssetUrl)
Public upload routes must validate file type and size. Store only paths that can be safely resolved by the serving layer.
Private Documents
Core-rule uploads are private and live under server/storage/. Campaign
documents are also managed through storage helpers and exposed through scoped
download routes, not raw file serving.
Primary files:
server/app/lib/core_rules_storage.pyserver/app/lib/campaign_docs_storage.pyserver/app/routers/admin.pyserver/app/routers/campaign_documents.py
Sidecar Files
Document ingestion stores extracted Markdown sidecars so Process can re-derive chunks without re-parsing the original source file.
Change Checklist
- Decide whether the file is public media or private source material.
- Validate size and MIME/content type before writing.
- Clean up replaced or deleted files when practical.
- Never put admin core-rule files under
/uploads. - Update proxy/static serving if a new public path is introduced.