Replaces a static SPA that shipped an Airtable PAT in the JS bundle.
The new architecture holds all secrets server-side, fronts the app
behind Apache on optical-dev with the shared-vhost split-build pattern,
and is designed for a later Azure AD/MSAL swap-in.
- backend/ FastAPI + uvicorn, local auth (Azure AD stub), Airtable
proxy with TTL cache, Zoho .xlsx/.csv parser, merge
service for utilisation summaries. 28 pytest tests.
- frontend/ React + Vite + TS + Tailwind + Recharts SPA. Login entry
chunk 12.83 KB gzipped; Recharts lazy-loaded. No tokens
or Airtable URLs in the built bundle.
- deploy/ Idempotent deploy.sh (port auto-pick 8200-8299,
.env-persisted) + split-build Apache include template.
- docker-compose.yml pins name: utilisation-dept and binds 127.0.0.1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 lines
1.3 KiB
Text
37 lines
1.3 KiB
Text
# Copy to .env and fill in. Never commit .env.
|
|
|
|
# --- Airtable ---
|
|
# Personal Access Token (read-only scope on the base below).
|
|
# Generate at https://airtable.com/create/tokens — scopes: data.records:read on base appoByydxIQANKtSh, tables Resource + Booking Resource.
|
|
AIRTABLE_PAT=
|
|
AIRTABLE_BASE_ID=appoByydxIQANKtSh
|
|
|
|
# --- Session / auth ---
|
|
# Random 32+ bytes. Generate with: python -c "import secrets; print(secrets.token_urlsafe(48))"
|
|
SESSION_SECRET=
|
|
|
|
# Local admin (used while AUTH_MODE=local).
|
|
# Generate hash with: python -c "from passlib.hash import bcrypt; print(bcrypt.hash('your-password-here'))"
|
|
# IMPORTANT: wrap the hash in SINGLE QUOTES — bcrypt hashes contain $ characters
|
|
# that docker-compose will otherwise interpret as variable substitutions.
|
|
ADMIN_USERNAME=admin
|
|
ADMIN_PASSWORD_BCRYPT=''
|
|
|
|
# AUTH_MODE: local (v1) or azure (v2 — not yet implemented).
|
|
AUTH_MODE=local
|
|
|
|
# Skip auth entirely in local dev. NEVER set true in production.
|
|
DEV_AUTH_BYPASS=false
|
|
|
|
# --- Server ---
|
|
# Host port to bind the container to. Auto-picked by deploy.sh from 8200-8299 and persisted here.
|
|
UTILISATION_DEPT_PORT=8200
|
|
|
|
# Optional Sentry-style overrides for cache TTLs (seconds).
|
|
CACHE_TTL_RESOURCES=600
|
|
CACHE_TTL_BOOKINGS=60
|
|
CACHE_TTL_META=600
|
|
|
|
# --- Azure AD (unused in v1, present for v2 swap) ---
|
|
AZURE_TENANT_ID=
|
|
AZURE_CLIENT_ID=
|