SEC-07 — committed secrets:
- Replace real-looking defaults in .env.example (JWT_SECRET/JWT_REFRESH_SECRET
"changeme", MANUAL_INVITE_PASSWORD "pm.local@zghl.de") with CHANGE_ME
placeholders, and drop the personal DOME_LIGHT_WEBHOOK_URL default.
- Add a Nitro startup plugin (server/plugins/validate-secrets.ts) that refuses
to boot in production when JWT_SECRET is unset, looks like a placeholder, or
is shorter than 32 chars (warns only in development).
OPS-02 / SEC-09 — cron endpoints:
- requireCronSecret now fails closed: when no CRON_SECRET/KPI_CRON_SECRET is
configured the endpoint returns 503 instead of being publicly callable
(previously it allowed the request with a warning). Both cron routes already
call the guard. Prefer the x-cron-secret header over the loggable ?secret=
query param; document CRON_SECRET in .env.example.
Operational note: production deployments must now set JWT_SECRET (>=32 chars)
and CRON_SECRET, or the server won't start / crons return 503.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Usage tracking:
- new UsageEvent collection records every STT/TTS/LLM call per user with
provider, model, volume (audio seconds, characters, tokens) and an
estimated USD cost; self-hosted providers (Speaches/Piper) and cache
hits record at $0
- pricing table for whisper-1, tts-1, gpt-5-nano & co. in server/utils/usage.ts
- weekly KPI mail gains an "AI-Nutzung & Kosten" section: weekly and
rolling 30-day cost, per-kind breakdown, top 5 users by cost
- quota alert mail when rolling 30-day cost exceeds USAGE_ALERT_USD
(default $5), at most once per calendar month (UsageAlertDelivery)
Hardening:
- /api/atc/say now requires an authenticated session (middleware
exemption removed); useFlightLabAudio sends the bearer token
- /api/service/tools/latency requires auth (was a public LLM endpoint)
- per-user rate limits: PTT 20/min, say 60/min, latency 5/min
- cron endpoints (waitlist-drip, weekly-kpi-report) require a shared
secret via ?secret= or x-cron-secret (CRON_SECRET, falls back to
KPI_CRON_SECRET); allowed with a warning while unset so existing
deployments keep working
- PTT records the actual transcribed audio duration for billing accuracy
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add collapsible sidebar with phase stepper (jump between phases)
- Add SimBridge conditions panel in sidebar (live values, progress bars, targets)
- Add global progress bar (top edge, glowing) + phase-local TTS progress bar
- Add skip button to skip TTS speech while ATC is speaking
- Add skipSpeech() to audio composable (stops current Pizzicato sound)
- Wire up bridge data.post.ts with user auth (JWT) + example payload
- Add server-side telemetry store with pub/sub for Bridge→WS relay
- Extend WS handler with subscribe-telemetry message + userId tracking
- Extend sync composable with subscribeTelemetry() + onTelemetry() callback
- Add require-auth middleware to all flightlab pages
- Fix instructor station ECONNREFUSED via import.meta.client guard
- Add animations: phase transitions, button lists, fade-scale, check-pop, pulse
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>