37 Commits

Author SHA1 Message Date
itsrubberduck
c8c2365c4d refactor(split): make the app self-hosting ready
Remove the transitional website auth, admin hooks, SEO and hosted analytics together, then align the app routes, runtime configuration, tests and dependencies. These changes form one atomic cleanup because the filtered app must switch its identity and runtime surfaces as a unit.
2026-07-27 19:17:27 +02:00
itsrubberduck
2b792eb57f refactor(split): decouple app from website in preparation for the repo split
Phase 0 of the OpenSquawk repo separation. Everything happens inside the
monorepo so that the split itself becomes a mechanical path filter — filtering
first and repairing afterwards would leave two broken repos at once.

AUTH_MODE (0.1)
  New server/utils/authMode.ts, session.ts and jwt.ts (the latter extracted
  from auth.ts). requireUserSession now resolves in three steps: the app's own
  session cookie, an app-minted bearer token, then the website access token.
  Only the last one is transitional; it is marked PHASE 1 and disappears with
  the User collection. The app's session is its own JWT in a host-only cookie
  plus a short-lived bearer, so the existing Authorization call sites are
  unchanged.

  AUTH_MODE defaults to 'sso', not 'open' as the plan proposed: while the admin
  and editor surface still lives here, an unset variable would otherwise serve
  it to everyone as a local admin. requireAdmin additionally refuses in open
  mode. Both are one-line removals in Phase 1 and marked as such.

SSO handoff (0.2)
  Issuer: /api/service/auth/sso/{authorize,exchange}. Codes are stored as
  SHA-256 hashes with a TTL index and claimed by a single atomic update, so
  concurrent redemption cannot succeed twice. redirect_uri is matched against
  SSO_REDIRECT_ORIGINS by exact origin — a prefix check would accept
  app.opensquawk.de.evil.tld. There is no default and no wildcard: an empty
  allowlist disables the handoff rather than opening a redirector.
  Consumer: /api/auth/sso/callback plus app/pages/auth/callback.vue. The
  browser only ever carries the code; it is redeemed server-to-server.

Hardcoded values and leaks (0.3)
  Hotjar ID, the dome-light webhook URL and the bug-report recipient were
  compiled in. All three are env-gated and off by default now, so a foreign
  instance cannot ship analytics, cockpit telemetry or its users' bug reports
  to us. Setting HOTJAR_ID, DOME_LIGHT_WEBHOOK_URL and BUG_REPORT_NOTIFY_EMAIL
  restores the current behaviour on opensquawk.de.

Two databases, no shared Mongo (0.6)
  AppUser mirrors an identity locally. Its _id is deliberately the SSO subject,
  i.e. the website's User._id, so every existing LearnProfile, PilotProfile and
  BridgeToken reference keeps resolving without a migration.
  telemetry.ts mirrors records to the hosted service only when TELEMETRY_URL
  and SERVICE_SECRET are both set — the self-host default is that nothing ever
  leaves the instance. It writes locally first, buffers with a bound, drops on
  overflow and never blocks the request path.
  /api/service/user-deleted purges the app's half on account deletion. Unlike
  telemetry this is deliberately loud: the admin delete aborts with the user
  intact if the purge fails, because their id is the only handle for retrying.
  ?force=true overrides it and says so in the response.

Also here
  /api/service/analytics/product-session was an unauthenticated public write
  endpoint; it moves to /api/analytics/product-session behind the auth guard.
  The bridge no longer populates against User but resolves through the mirror,
  backfilling missing rows so live bridges never have to re-pair.
  .claude/worktrees was tracked and would have reached the public repo.

scripts/split-paths.txt carries the filter list, verified by
scripts/verify-split-paths.mjs: every path exists, nothing website-only is
kept, and no kept file imports a dropped one. That check found real gaps —
tests/ cannot be taken wholesale, and two shared modules were missing. Ten
remaining edges are allowlisted, each annotated PHASE 1 in the code.

Open item, flagged and not resolved: flightlabTelemetryStore is an in-process
singleton written by the bridge (app) and read by FlightLab (website). Two
repos means two processes, so that read breaks regardless of which side it
lands on. FlightLab needs an HTTP path in Phase 2/3.

Verified: 609 tests pass, vue-tsc clean. Ran against two throwaway local
MongoDBs: open mode reaches /classroom and /live-atc with no login and
persists progress; the full SSO loop works and the mirror _id matches the
website User._id; lookalike origins, code reuse, forged codes and wrong
service secrets are all rejected; ingest is idempotent on bug-report code;
deletion purges all five collections; and with the app unreachable the admin
delete fails 502 with the user still present.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 18:46:34 +02:00
itsrubberduck
2fec78df91 feat: add complete SEO metadata and indexing controls 2026-07-18 21:29:31 +02:00
itsrubberduck
9f0a51e678 atc header 2026-07-10 08:33:36 +02:00
itsrubberduck
8fd643a748 feat(pm): add light/dark/system theme toggle
Defaults to dark (matching the rest of the app) with a menu to switch
to Light or System. Custom CSS-variable overrides handle the
hand-rolled Tailwind classes; a second Vuetify theme is swapped in
sync for Vuetify components. Scoped entirely to /pm.
2026-07-09 17:26:21 +02:00
leubeem
e21414e45a feat(pm): ignore sub-threshold voice transmissions (STT noise gate)
Whisper hallucinates short real words ("Test", "Thank you", "Okay") on
near-silent or noisy audio. Unfiltered these reached the backend as a wrong
readback attempt — counting toward the 3x-skip — and triggered paid
LLM-router calls. Drop voice (PTT) transcripts below NUXT_PUBLIC_PTT_MIN_WORDS
(default 2); text input is exempt so deliberate short commands still work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 11:35:47 +02:00
leubeem
e807e483ce Wire /pm to Python backend for stateful ATC training sessions
Replace the LLM-per-request flow in /pm with a stateful Python backend
(OpenSquawk-LiveATC-api). The backend owns session state, does regex-first
routing with readback evaluation, and returns the next state + ATC speech.
The frontend keeps its local cursor (communicationsEngine) for TTS and
monitoring UI, but no longer calls /api/llm/decide.

Changes:

app/composables/useRadioBackend.ts (new)
  Typed Nuxt composable wrapping the Python REST API:
  createSession, transmit, deleteSession, fetchFlows.
  Base URL read from NUXT_PUBLIC_RADIO_BACKEND_URL (default 127.0.0.1:8000).

nuxt.config.ts
  Expose radioBackendUrl as a public runtime config key so the composable
  and communicationsEngine can both reach the Python backend.

shared/utils/communicationsEngine.ts
  - fetchRuntimeTree now accepts an optional baseUrl so it fetches from the
    Python backend instead of the Nuxt server when a URL is provided.
  - renderTpl handles both {var} (old MongoDB schema) and {{var}} (new YAML
    schema) — double-brace matched first to avoid partial matches.
  - stateSayTpl / stateUtteranceTpl helpers unify say_tpl|say_template and
    utterance_tpl|expected_pilot_template across both schema versions.
  - auto_transitions from the new YAML schema are included when collecting
    eligible transitions in collectAtcStatesUntilPilotTurn.

shared/types/decision.ts
  RuntimeDecisionState extended with say_template and expected_pilot_template
  fields (new YAML schema field names alongside the existing legacy names).

app/pages/pm.vue
  - startMonitoring: loads tree from Python backend, then creates a backend
    session (backendSessionId). Cursor synced to session.current_state.
  - handlePilotTransmission: calls radioBackend.transmit instead of
    /api/llm/decide. Applies auto_advanced_states via moveToSilent, then
    the final state. Speaks controller_say_template via TTS.
  - Both fetchRuntimeTree calls now pass radioBackendUrl so they hit the
    Python backend, not the Nuxt flow-from-MongoDB path.

AGENTS.md (new)
  Project guide updated to document the new two-backend architecture,
  the Python backend session lifecycle, and the dual template schema.

docs/plans/2026-05-06-pm-python-runtime-contract.md (new)
  Implementation plan and API contract written before the work started.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 17:49:28 +02:00
itsrubberduck
36ad4677dc add the lidl dome light temporarily 2026-02-18 21:49:03 +01:00
itsrubberduck
4a01593612 fix typescript errors and update dependencies 2026-02-17 18:13:04 +01:00
itsrubberduck
57fc0e3150 Fix local sharp setup for Nuxt image processing 2026-02-15 15:47:06 +01:00
itsrubberduck
37dbfc17e9 feat(flightlab): add WebSocket handler for instructor-participant session sync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:45:18 +01:00
Remi
1133dbb6e1 feat: integrate nuxt hotjar module 2025-10-18 14:31:16 +02:00
Remi
18f25998f5 Allow configuring OpenAI base URL 2025-10-16 11:15:31 +02:00
itsrubberduck
cccea3f8cf add nuxt-img 2025-10-12 16:53:12 +02:00
itsrubberduck
61edec95a2 minor design adjustments 2025-10-05 16:45:58 +02:00
itsrubberduck
8062deb60e insight into research 2025-10-04 16:49:44 +02:00
itsrubberduck
4ba95c998d use new favicon 2025-09-24 17:32:05 +02:00
Remi
c57eaeed4a Align Learn intro buttons with shared Learn styling 2025-09-22 18:19:41 +02:00
Remi
03b86ae637 Add ATIS quick actions and airport frequency data 2025-09-18 18:16:40 +02:00
Remi
7a44d67844 Harden runtime config and input validation 2025-09-18 14:03:25 +02:00
Remi
c20ed6b702 Fix Hotjar loading after cookie consent 2025-09-18 13:37:29 +02:00
Remi
e1d892af83 feat: add manual invitation generator 2025-09-17 20:26:33 +02:00
itsrubberduck
c01c7d2801 “Adopt Nuxt Image and replace landing video with static image 2025-09-17 20:07:02 +02:00
itsrubberduck
8eaace39d1 merge 2025-09-17 19:38:37 +02:00
itsrubberduck
9ff6f6c533 ⚖️ Update legal & privacy pages, add Nuxt Image module
* Updated  and  with new company details (Faktor Mensch MEDIA UG), updated email to , and refreshed  dates.
* Replaced references to old OpenSquawk UG with new entity information.
* Added  module to  for image optimization support.
* Adjusted  dependencies: added , ensured  is correctly listed.
* Regenerated  to include new dependencies (, High performance, secure and easy-to-use image optimizer. (ipx v2.1.1)

USAGE ipx serve

COMMANDS

  serve    Start IPX Server

Use ipx <command> --help for more information about a command., Usage: svgo [options] [INPUT...]

Nodejs-based tool for optimizing SVG vector graphics files

Arguments:
  INPUT                      Alias to --input

Options:
  -v, --version              output the version number
  -i, --input <INPUT...>     Input files, "-" for STDIN
  -s, --string <STRING>      Input SVG data string
  -f, --folder <FOLDER>      Input folder, optimize and rewrite all *.svg files
  -o, --output <OUTPUT...>   Output file or folder (by default the same as the
                             input), "-" for STDOUT
  -p, --precision <INTEGER>  Set number of digits in the fractional part,
                             overrides plugins params
  --config <CONFIG>          Custom config file, only .js is supported
  --datauri <FORMAT>         Output as Data URI string (base64), URI encoded
                             (enc) or unencoded (unenc)
  --multipass                Pass over SVGs multiple times to ensure all
                             optimizations are applied
  --pretty                   Make SVG pretty printed
  --indent <INTEGER>         Indent number when pretty printing SVGs
  --eol <EOL>                Line break to use when outputting SVG: lf, crlf.
                             If unspecified, uses platform default.
  --final-newline            Ensure SVG ends with a line break
  -r, --recursive            Use with '--folder'. Optimizes *.svg files in
                             folders recursively.
  --exclude <PATTERN...>     Use with '--folder'. Exclude files matching
                             regular expression pattern.
  -q, --quiet                Only output error messages, not regular status
                             messages
  --show-plugins             Show available plugins and exit
  --no-color                 Output plain text without color
  -h, --help                 display help for command, etc.).
2025-09-17 19:36:15 +02:00
itsrubberduck
c751d45090 add hotjar 2025-09-17 19:25:46 +02:00
Remi
e355d0ba18 Align public messaging and add news banners 2025-09-17 19:22:56 +02:00
Remi
19f253f53e Implement authentication, waitlist, and logging upgrades 2025-09-16 17:28:34 +02:00
itsrubberduck
ee90ebfe54 sehr schlechte erste version vom p 2025-09-15 20:04:04 +02:00
itsrubberduck
fff07663b9 add glas ui 2025-09-15 11:46:12 +02:00
itsrubberduck
d77ac4a25e globales css hinzu 2025-09-15 00:00:03 +02:00
itsrubberduck
99b8c87536 ssr false 2025-09-14 23:34:13 +02:00
itsrubberduck
8528b2518b kann ein bisschen normalized sprechen 2025-09-14 23:20:01 +02:00
itsrubberduck
70db201abd webseite sieht gut aus 2025-09-14 21:36:45 +02:00
itsrubberduck
f17624518d neue landing page 2025-09-14 21:14:20 +02:00
itsrubberduck
4a1e4df391 add tailwind 2025-09-14 21:10:30 +02:00
itsrubberduck
94ea407402 init 2025-09-14 21:09:47 +02:00