Login, tenants and security
Keycloak issues the token; the tenant is a claim; the database enforces isolation.
Login
The console and the mobile app log in through Keycloak using the authorization code flow with PKCE. Nothing but Keycloak ever sees a password. Sessions refresh silently and end with Log out.
Tenant
Every user carries a tenant_id claim in the signed token, set when the user is created. The API reads the tenant from the token and never from the request. A token without a tenant claim is refused.
Isolation
Every tenant-owned table has row-level security in PostgreSQL: the database itself refuses to return another tenant's rows, whatever the application code does. The API connects as a role bound by that policy; system jobs use a separate role.
Roles
Realm roles decide what a user may do: tenant-admin manages a fleet; platform-admin is EaglesEye staff and sees, for example, leads from the website. Roles are read from the token.
Transport
Everything the browser touches is one https origin: the console, the API under /api, the live socket under /ws, and login under /auth. Tracker ports are plain TCP as the protocols require.