Auth & Permissions
Identity model
- Google Workspace is the primary sign-in for staff, restricted to the company hosted domain. A valid Google identity is not enough on its own — the user must already be provisioned in IPFOS and be
ACTIVE. - Local email/password exists only for the root/fallback admin (bootstrap and recovery).
- The auth service issues JWT access tokens plus rotating refresh tokens. Required claims:
sub,role,permissions,email,iat,exp(issueros-auth-service, audienceos-platform).
Where auth is enforced
Each service enforces JWT validation and permission checks itself — the NestJS services via src/auth/jwt-auth.guard.ts and permissions.guard.ts, the auth service via Spring Security. Gateway-level JWT validation at Traefik is planned but not implemented today; do not assume a request that reached a service was pre-authenticated.
On the frontend, the decoded role and permissions ride along in the session cookie, and AccessControlProvider gates routes and dashboard cards — but that is UX, not security. The backend check is the real one.
Roles and permissions
Permissions are resource:action strings, seeded by Flyway migrations in the auth service (V2, V4, V6, V11, V13). There is deliberately no admin UI for editing roles — the catalog is code-managed.
| Domain | Permissions |
|---|---|
| Users | users:read, users:write, users:invite, users:offboard |
| Tickets | tickets:read:self, tickets:read:department, tickets:read:all, tickets:create, tickets:update, tickets:assign, tickets:comment, tickets:transition |
| Meals | meals:read, meals:write, meals:select |
Seeded roles:
| Role | Intent |
|---|---|
ROOT_ADMIN | Bootstrap/recovery superuser (local login) |
ADMIN | Full user and ticket control + meals read |
EMPLOYEE | Standard staff: read users, read/select meals, create/comment/transition own and department tickets |
MEALS_STAFF | Meals read/write only |
The frontend mirrors this catalog read-only at Users → Roles Management (roles-catalog.ts); keep it in sync when Flyway seeds change.
Ticket-level access
Beyond global permissions, ticket actions depend on the caller's participant role on the specific ticket (ASSIGNEE, MANAGER, PMO, PM, OBSERVER) — e.g. only the assignee can close from IN_PROGRESS, while oversight roles, admins, and the creator can cancel-close a still-open ticket. See the User Guide's ticketing chapter for the full rules expressed in user terms.