Three configuration defects and one screen of invented people. API base. The client defaulted to https://platform.loyaly.ai when LOYALY_API_BASE was unset, and that host serves THIS console, not the Behavision API - verified live: it answers /api/auth/me with the console's own 404 HTML and a login POST with the console's own BFF envelope. So an unset variable in production made the BFF call its own origin, which fails looking like a broken login form rather than a misconfiguration. There is now no remote fallback: development defaults to 127.0.0.1:8088 and production throws, naming the variable, the way tokenStore already refuses to run without AUTH_SECRET. A wrong host that appears to work is worse than a startup failure that says what is missing. The template. .env.example documented that same wrong host, and .gitignore's `.env*` matched the template itself, so it was never committed - a fresh clone got no template at all, for an app that cannot start in production without AUTH_SECRET. Added `!.env.example` after the ignore rule; .env.local and every other .env* stay ignored. The template carries placeholders only, no values. Team. /settings/team listed five invented people - aravind@nearle.in, Vikram Seth, Priya Sharma - with store names no endpoint supplies and roles that do not exist upstream, behind four controls that mutated local state and were lost on refresh. A merchant could not tell any of it from the real thing. It now reads GET /api/team, which the platform already serves and scopes by session, and renders what actually comes back: name, email, role, whether the account is still active, and last sign-in (or "Never", which is a fact worth seeing). The route used to map each row through toAuthUser, which reads client_name - a field GET /api/team does not send - so organisation was undefined on every row while active, last_login_at and created_at were discarded. ApiTeamMember now describes that payload properly and ApiUser is left to authentication. The screen is READ-ONLY on purpose. Accounts are born from invitations, and that flow already exists in the platform's own web app: a manager mints a code, the holder redeems it and chooses their own password. A second way to create a login does not belong here, least of all on the screen that lists them. Role changes and deactivation are supported upstream by PATCH /api/team/{id} and are deliberately not wired: deactivating revokes every session that person holds immediately, so it wants a confirmation step and 409 last_owner handling, neither of which belongs in a change whose purpose is removing invented data. types.ts also gains the Sales/Floor/Customer interfaces. They are inert here - nothing imports them yet - and land with this commit so the screens that consume them arrive as one reviewable change. Verified against the live local platform: two tenants, correct member lists for each, and no cross-tenant leakage. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161AMotQ8FxGPZ9gFGb5wiK
22 lines
957 B
Plaintext
22 lines
957 B
Plaintext
# The one shared Loyaly platform API (Behavision). Server-side only and
|
|
# deliberately NOT NEXT_PUBLIC: publishing the host would let a browser bypass
|
|
# the BFF, which is what keeps the access token out of JavaScript.
|
|
#
|
|
# local dev http://127.0.0.1:8088
|
|
# production https://mcp.loyaly.ai
|
|
#
|
|
# NOT platform.loyaly.ai — that host serves THIS console, not the API. Pointing
|
|
# the variable there makes the BFF call its own origin, which fails in a way
|
|
# that looks like a broken login form rather than a misconfiguration.
|
|
#
|
|
# There is no fallback: production refuses to start without this set.
|
|
LOYALY_API_BASE=http://127.0.0.1:8088
|
|
|
|
# Signs the session cookie and encrypts the platform token bundle.
|
|
# Required in production — the app refuses to start signing sessions with the
|
|
# development key. Generate with: openssl rand -base64 48
|
|
AUTH_SECRET=
|
|
|
|
# Browser → this app's own BFF routes. Same origin, so normally left empty.
|
|
NEXT_PUBLIC_API_BASE=
|