Dragon Guard WMS Web hosts two distinct surfaces inside the same Angular shell: a tenant surface for company admins managing their warehouse, and a SaaS surface for Grupo MAS super-administrators managing the platform itself. These surfaces share a login screen but diverge immediately after authentication — different routes, different Angular services, different backend API namespaces, and different session metadata. The split is intentional and fail-closed: access to the wrong surface is rejected by both the frontend guard and the backend authorization layer.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/CodexaCP/DG_WEB/llms.txt
Use this file to discover all available pages before exploring further.
Two Surfaces at a Glance
- Tenant Surface
- SaaS Surface
Served to: Company admins (
ADMIN role and below)Root route: /dashboard (and sub-paths like /dashboard/receipts, /dashboard/admin)Angular service: WmsService — resolves companyId automatically from session; scopes every request to the authenticated tenant.Backend namespace: /api/* (standard WMS endpoints)Guard: authGuard (all routes) + adminGuard (/dashboard/admin/**)Session Keys
After a successful login,AuthService writes the following keys to sessionStorage. All downstream services and guards read from this store. localStorage is never used.
| Key | Type | Purpose |
|---|---|---|
token | string | JWT bearer token attached to every API request |
active_company_id | number | The tenant context injected by WmsService into scoped requests |
active_role | string | Role string used by guards (ADMIN, SUPERADMIN_SUPREMO, etc.) |
is_supreme_admin | boolean | Fast flag used at login to determine post-auth redirect destination |
active_company_id is intentionally absent from a super-admin’s session when they have no operational tenant. WmsService will not inject a fallback company ID — requests that require a tenant context must originate from a tenant-scoped session.SupremeService Endpoints
The SaaS surface is backed by a dedicated set of API endpoints under the/api/supreme/ namespace. These endpoints are only called by SupremeService and are never invoked from tenant screens.
Login and Role-Based Routing
Credentials submitted
Both super-admins and company admins use the same
/auth/login screen. The POST /api/Auth/login response includes is_supreme_admin alongside the JWT and company list.Session keys written
AuthService writes all four session keys to sessionStorage. For a super-admin with no operational tenant, active_company_id is left unset.Redirect decision
AuthService reads is_supreme_admin:true→ redirect to/dashboard/supremefalse→ redirect to/dashboard
Business Rules
The following rules govern the multi-tenant model and must be respected in all future frontend and backend work:- SUPERADMIN_SUPREMO is always redirected to
/dashboard/supremeafter login. They do not land on the tenant dashboard, even if they somehow also have acompanyIdin their token. - Only the SaaS menu is shown for SUPERADMIN_SUPREMO. Tenant screens are not rendered, not merely hidden.
- Company admins use the standard dashboard and tenant modules. They have no visibility into other companies’ data.
- A super-admin with no operational tenant can still log in. The absence of
active_company_idis a valid session state for the SaaS surface. - No default fallback company is injected for super-admins. If a super-admin accidentally triggers a tenant-scoped request,
WmsServicewill not silently pick a company — the call will fail rather than leak data. - Prefer additive changes to the session schema. Adding a new session key is safe. Renaming or removing a key requires updating every guard, service, and component that reads it.
Security Model
The multi-tenant security model has two layers that must both hold:| Layer | Mechanism | What it prevents |
|---|---|---|
| Frontend | supremeGuard on /dashboard/supreme/** | Prevents accidental navigation; fast rejection without a network round-trip |
| Backend | JWT claims checked on every /api/supreme/* call | Prevents any client — Angular, MAUI, curl — from accessing cross-tenant data |
/dashboard/supreme/companies directly into the address bar is rejected by supremeGuard before the route loads. If they somehow bypass the guard, the first API call returns 401 or 403 from Wms.Api. Neither layer alone is sufficient.
Edge Cases
| Scenario | Expected behaviour |
|---|---|
Super-admin navigates directly to /dashboard/receipts | authGuard passes (valid token), but the tenant-scoped API calls fail because active_company_id is unset |
Company admin navigates directly to /dashboard/supreme/companies | supremeGuard rejects the navigation; user stays on current route |
| Token expires mid-session on the SaaS surface | JWT interceptor catches 401, clears sessionStorage, redirects to /auth/login |
| Super-admin has an operational tenant account | is_supreme_admin: true always wins; user is routed to SaaS surface regardless |
| Multi-company tenant admin switches company | active_company_id is updated in sessionStorage; WmsService picks up the new value on the next request |
Architecture Overview
Module structure, lazy routing, central service rule, JWT auth flow, and the web/handheld responsibility boundary.
API Contracts
Endpoint inventory, contract stability rules, MAUI compatibility requirements, and the versioning strategy.