Skip to content

Monsieur Wifi Migration

Monsieur Wifi is a Laravel application being moved onto the platform stack — a Go Connect service with a SvelteKit frontend — by strangler fig: the Laravel app serves everything that has not been carved out yet.

One domain, one login, one look

One domain A router sends carved paths to Svelte and everything else to PHP
One login Zitadel OIDC for both halves, so crossing the seam does not re-prompt
One look The portal's design tokens are shared, so the two halves match

The seam

graph TD
    U[Browser] --> R{mrwifi-router<br/>Cloudflare Worker}
    R -->|carved path| S[mr-wifi-svelte<br/>Cloudflare Pages]
    R -->|everything else| P[Laravel PHP<br/>FrankenPHP on Scaleway]
    S -->|Connect| G[mr-wifi-go]
    P --> DB[(Postgres)]
    G --> DB
    P --> A[authz]
    G --> A

platform/mr-wifi/router routes by path. src/routes.ts holds the ledger:

List Paths
CARVED_PATHS /qos
SVELTE_ALWAYS /_app, /callback, /favicon

Carving a page is one line in CARVED_PATHS plus deleting the PHP route and view. Both halves use the same database, so a page moves without a data migration.

mr-wifi-svelte also has an /access route (access management, deep-linked from the PHP share widget). It is not in CARVED_PATHS.

mr-wifi-go is a peer of Nexus: same Connect shape, same Zitadel bearer-token validation, same authz service. Services: IdentityService.WhoAmI, QosService.ListClasses, AccessService.ListRoles/ListHolders/Grant/Revoke, HealthService.Check.

Identity

  • Zitadel is the only identity provider. The PHP app is a confidential OIDC client and redirects straight to Zitadel (no local login page); logout ends the Zitadel session. The Svelte SPA uses PKCE.
  • Both send a bearer token that mr-wifi-go validates against Zitadel's JWKS.
  • Authorization comes from authz, with grants keyed by the raw Zitadel subject. A user who exists in Zitadel but holds no grant sees an empty application; that is an authorization outcome, not an error.

Database

Postgres (DB_CONNECTION=pgsql, its own database per environment from terraform). The PHP code goes through App\Support\SqlDialect for driver-specific SQL, and mr-wifi-go uses pgx. Schema changes must work for both halves at once: add a column before either side uses it, drop it only after neither reads it.

deploy/pgloader/ holds the MySQL → Postgres data copy (migrate-to-pg.sh, data-only.load).

Not yet done

  • Most pages are still served by Laravel.
  • Navigation between Monsieur Wifi and the Edge Gateway portal is a link, not a shared shell.
  • mr-wifi-svelte keeps a copy of the protos rather than depending on the backend's through buf.