- remove setup-ssl.sh (mkcert IP certs) - superseded by install.sh's
self-signed cert and the backend-managed TLS identity
- manager: "Waiter Domain (παλιό σύστημα)" - shown only for sites that
still have one
- .env.example: REGISTRY=registry.bonamin.net and
CLOUD_URL=https://xenia-api.bonamin.net (it pointed at the admin panel,
xenia-admin, even before the domain move); install.sh points to the
sysadmin panel at xenia-admin.bonamin.net
- pack README registry example updated
Proxy config unchanged (HTTPS domain blocks stay so not-yet-migrated sites
keep working until their visit).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phones can now open the waiter app at http://<LAN IP> with no domain, DNS
record or certificate (works around DNS-rebinding failures, KI-001). The
manager gets http://<LAN IP>:8081, with http://<LAN IP>/manager redirecting
there. waiter.*/manager.* hostnames on :80 still redirect to https, so
legacy domain sites behave as before.
- Both plain-HTTP servers are LAN-only (allow RFC1918/loopback/ULA/link-local,
deny all -> 403), so a router port-forward can't expose an unencrypted POS
- nginx-proxy/nginx.conf and the install.sh heredoc are now byte-identical
(one canonical config, routing map in its header)
- install.sh generates a 10-year self-signed cert when certs/ is empty (nginx
won't start its TLS listeners without one), detects HOST_IP via
'ip route get', prompts for it on fresh installs and backfills it into an
existing .env, always starts the stack, prints the LAN URLs
- docker-compose publishes 8081; .env.example documents HOST_IP
- pack README: ports/request path updated, CS-5 byte-identical check
Verified: nginx -t; install.sh in Debian (fresh / upgrade without HOST_IP /
re-run - no duplicate HOST_IP, cert SAN includes HOST_IP, key 600); full
stack from freshly built images: every entry point returns the expected
200/301/302, and removing the gateway's range from the allow list yields 403
on :80 and :8081.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New waiter_pwa/src/config/server.js is the single place that knows where the
backend is. Served by the venue's server (https domain or http://<LAN IP>)
nothing changes: same-origin URLs and the original storage keys, so existing
installs keep their token and unsynced offline queue. With an active venue
(native app, or dev builds with VITE_SERVER_URL) URLs become absolute and all
venue data is namespaced by siteId: token/savedUsername keys, the Dexie DB
(pos_snapshot__<siteId>, which also covers the WS cursor), favorites and
table-view prefs. Switching venue reloads the app.
- api client baseURL, WebSocket and SSE URLs routed through the layer
- product images / waiter avatars rendered via assetUrl()
- service-worker update prompt skipped in native builds
- InstallAppBanner: shown only in plain-HTTP browser mode and only when
VITE_APP_DOWNLOAD_URL is set at build time (dismiss for 7 days)
- VITE_SERVER_URL override is DEV-only (a URL-controlled server in prod would
let a crafted link capture PINs)
- pack README: rule CS-8 on never assuming same-origin
Verified with Playwright/Edge against a local backend: prod build same-origin,
prod build via LAN IP over plain HTTP (insecure context, no SW, banner shown),
and dev build pointed at the backend by URL - all three log in, reach /tables
and receive the WebSocket 'ready' frame; storage keys and IndexedDB names are
as expected. Lint: no new problems (103 before/after). Build passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Documents the request path through proxy -> waiter nginx -> backend,
the _run_migrations requirement, real-time event handling, offline
expectations and the duplicated nginx config in install.sh.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>