feat: JWT auth, /api prefix, SPA serving, OpenAPI, lean main.rs

- auth: register/login/refresh/logout w/ JWT+Argon2, protected mutations
- domain: User, RefreshSession, auth ports, Unauthorized/Forbidden errors
- presentation: context/state/factory/errors/extractors/openapi modules
- routes behind /api, SPA served from root w/ fallback
- OpenAPI Scalar at /docs
- frontend ssr:false, single-binary Dockerfile
This commit is contained in:
2026-07-11 21:28:52 +02:00
parent 13031347cc
commit 7bd27d9b9c
50 changed files with 1604 additions and 213 deletions

View File

@@ -1,46 +1,28 @@
# PocketChords homeserver deployment template
# PocketChords single-binary deployment
#
# Usage:
# cp .env.compose .env.compose.local # fill in your values
# docker compose --env-file .env.compose.local up -d --build
#
# VITE_API_URL is baked into the JS bundle at build time.
# Set it to the URL your BROWSER (and SSR server) will use to reach the API.
# On a LAN homeserver: http://192.168.x.x:8000
# Behind a reverse proxy: https://pocketchords.example.com/api
services:
api:
app:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
ports:
- "${API_PORT:-8000}:8000"
- "${PORT:-8000}:8000"
environment:
DATABASE_URL: sqlite:///app/data/pocket-chords.db
HOST: 0.0.0.0
PORT: 8000
# Comma-separated allowed origins, or * for any.
# Lock this down in production: https://pocketchords.yourdomain.com
JWT_SECRET: ${JWT_SECRET}
ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-false}
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-*}
SPA_DIR: /app/spa
volumes:
- api-data:/app/data
app:
build:
context: ./app
dockerfile: Dockerfile
args:
VITE_API_URL: ${VITE_API_URL:-http://localhost:8000}
restart: unless-stopped
ports:
- "${APP_PORT:-3000}:3000"
environment:
PORT: 3000
depends_on:
- api
- app-data:/app/data
volumes:
api-data:
app-data:
driver: local