Suite auth
Two kinds of caller. One human issuer.
Humans
A person signs in at /login in oxykit-console. Which modules are shown is config.json. Mail Identity issues the JWT (Jwt:Issuer, Jwt:Audience, Jwt:Key, 32+ characters).
The app stores that token as the oxykit.access_token cookie (Path=/, SameSite=Lax) and a sessionStorage copy. Render and Flow in the same app send Authorization: Bearer. The refresh token stays in Mail. When the access token is missing, /, /render, and /flow open /login?returnUrl=. A saved API key does not skip sign-in.
Every signed-in role can replace their own password (POST /api/v1/auth/change-password, Bearer, current password required).
| Role | Render | Flow | |
|---|---|---|---|
| Admin | all screens | pack write + render | create, retry, read |
| User | dashboard, API keys | pack read + render | read jobs |
| Sender | send | render only | no jobs |
Machines
Flow calling Render, Flow calling Mail, NuGet Clients, and Hoppscotch use each product's API key. They do not use a user JWT.
| Product | Header |
|---|---|
| Render | X-OxyKit-Render-Key |
X-Api-Key | |
| Flow | X-OxyKit-Flow-Key |
An API key is full access for that product. If that product's API key header is present, it is the only credential checked — a wrong key does not fall through to the Bearer token. Compose shares Mail's JWT triple with Render and Flow as Security:Jwt so they can validate the human token. API keys stay separate env vars.