Access & login
Where the admin lives
Section titled “Where the admin lives”| Environment | URL | Notes |
|---|---|---|
| Local dev | http://localhost:3100 | Started by npm run admin from repo root. |
| Staging / prod (planned) | https://admin.twistcue.com | Behind Apache + Let’s Encrypt on the same box as the API. |
The admin is a standalone Next.js 16 app. It talks to the API at https://api.twistcue.connectorme.com/v1 server-side (https://api.twistcue.local/v1 in dev): you never call the admin API from the browser directly.
Getting an account
Section titled “Getting an account”Admin users are managed by anyone with admins:write (the built-in superadmin role). Ask them to run:
# From the admin panel: System → Admin users → New# Fields: email, name, role, password (temporary, user must reset on first login)…or if you’re bootstrapping the very first admin, seed the database (see Local dev setup).
Logging in
Section titled “Logging in”- Go to
/login. - Enter your email and password.
- On success, the API returns a JWT that’s set as an HttpOnly cookie (
tc_admin_token). The token expires after 12 hours. - You’re redirected to the Dashboard (
/).
Session behavior
Section titled “Session behavior”- 12h expiry: you’re logged out automatically. Re-authenticate.
- IP change: the guard will re-auth on IP mismatch (planned; WebAuthn column already in schema for phase 2).
- Concurrent sessions allowed: no single-session lock.
- Logout: clears the cookie server-side; JWT is stateless so any un-expired token is technically still valid until
token_versionbumps.
Where things fail loudly
Section titled “Where things fail loudly”| Error | Meaning | Fix |
|---|---|---|
insufficient_permissions (403) | Your role lacks the required permission for that endpoint. Response includes the required perm array. | Ask a superadmin to grant you the perm, or use a role that has it. |
invalid_credentials (401) | Wrong email/password. | Reset password from the admin user detail page. |
admin_disabled (403) | The admin record is inactive. | Have a superadmin re-enable it. |
token_expired / token_invalid (401) | 12h TTL hit, or token_version bumped. | Log in again. |
Where the UI hides things you can’t do
Section titled “Where the UI hides things you can’t do”The sidebar and inline buttons are permission-aware: routes and actions you can’t perform are hidden. The UI is not the security boundary: the API is. The PermissionsGuard server-side re-checks every mutating endpoint against your JWT claims. Hiding a button just prevents accidental 403s.