Auth And Mutation Authority
Snapshot date: 2026-04-24
This is the current internal authority contract for dashboard and operator auth. It separates who can reach a surface from what that surface is allowed to change.
Current Summary
The dashboard is a tailnet-first operator visibility surface with mixed-mode auth and compatibility-only mutation.
Current truth:
- Kubernetes, ARC, and Prometheus are the primary read-side monitoring sources.
- Trusted proxy identity through Tailscale or mTLS is the preferred operator access model.
- GitLab OAuth remains the current interactive compatibility login path.
- WebAuthn remains supported for interactive passkey login.
- OpenTofu remains the infrastructure mutation authority.
- Dashboard runner pause/resume and GitOps submission are GitLab-backed compatibility flows when configured.
- There is no settled forge-neutral, GitHub-native, or cluster-native mutation authority yet.
Do not infer mutation authority from access auth. A tailnet-authenticated operator can be a valid dashboard actor while the dashboard still lacks a forge-neutral write path.
Access Auth Modes
| Mode | Status | Role |
|---|---|---|
| Tailscale proxy identity | preferred internal operator path | Request identity through trusted proxy headers |
| mTLS proxy identity | preferred internal operator path where enabled | Request identity through trusted client certificate headers |
| GitLab OAuth | compatibility interactive path | Establishes signed dashboard session cookies |
| WebAuthn | supported interactive path | Establishes signed dashboard session cookies after passkey authentication |
| Development fallback | local dev only | Creates a local operator identity in SvelteKit dev mode |
Trusted proxy identity is only valid when TRUST_PROXY_HEADERS=true and the
dashboard is actually behind a trusted proxy that owns or strips the accepted
headers. Do not enable trusted proxy headers on an untrusted public ingress.
The app currently reads these proxy identity headers:
x-webauth-userx-webauth-emailx-client-cert-cn
When proxy identity resolves, it outranks a stored interactive session cookie. That keeps the request aligned with the tailnet or mTLS ingress trust boundary instead of an older OAuth or passkey session.
Roles
The current role model is:
| Role | Meaning |
|---|---|
viewer |
Can use authenticated monitoring and runner-status reads |
operator |
Can use operator reads and compatibility mutation flows |
admin |
Can use admin auth and control-audit workflows |
Role assignment is environment-driven:
PROXY_AUTH_DEFAULT_ROLEcontrols the fallback role for trusted proxy identities and defaults tooperator.AUTH_ADMIN_IDENTITIESmaps usernames or emails toadmin.AUTH_OPERATOR_IDENTITIESmaps usernames or emails tooperator.AUTH_VIEWER_IDENTITIESmaps usernames or emails toviewer.
Read Authority
| Surface | Minimum role | Current source of truth |
|---|---|---|
/api/health |
public | Process health only |
| Dashboard monitoring | viewer |
Kubernetes, ARC, Prometheus |
| Runner status | viewer |
Kubernetes/ARC plus compatibility forge readers |
| Config and drift reads | operator |
Local repo tfvars checkout and comparison logic |
| Auth runtime summary | admin |
Runtime env and auth-policy shape |
| Auth event history | admin |
Dashboard PostgreSQL audit table |
| Control event history | admin |
Dashboard PostgreSQL audit table |
Read-side authority does not make the dashboard the owner of managed infrastructure. For managed resources, desired state still comes from repo code and OpenTofu inputs, and managed-resource authority comes from the active S3-compatible OpenTofu state.
Mutation Authority
| Mutation surface | Minimum role | Current backend | Authority status |
|---|---|---|---|
| Runner pause/resume | operator |
GitLab runner API when configured; mock fallback otherwise | Compatibility only |
| GitOps config submission | operator |
GitLab branch and merge-request APIs when configured | Compatibility only |
| ARC runner registration/routing | Not dashboard-owned | GitHub App credentials and ARC controller | Platform runtime authority |
| Infrastructure changes | Not dashboard-owned | OpenTofu apply with S3-compatible state | Managed-resource authority |
| Shared runner class changes | Not dashboard-owned | Repo PR plus explicit apply path | Platform operator authority |
Current dashboard mutation is deliberately narrow. It does not provide:
- GitHub-native runner control
- direct ARC scale-set mutation
- cluster-native controller mutation
- forge-neutral GitOps submission
- public self-service enrollment mutation
If a dashboard page exposes a compatibility mutation, describe it as
compatibility and require an operator or admin role. If the GitLab backend
is not configured, mock mutation is local/dev fallback behavior and must not be
treated as live authority.
Session And Cookie Contract
SESSION_SECRET enables signed dashboard session cookies. Production-like
deployments should set it.
When SESSION_SECRET is absent, the app keeps an unsigned compatibility cookie
path for local/dev use. Do not describe unsigned cookies as the production
operator contract.
Passkey registration currently depends on an interactive OAuth session. That means WebAuthn is supported, but passkey bootstrap is not yet independent of the GitLab compatibility login path.
Deployment Rules
- Prefer tailnet-private dashboard exposure.
- Enable
SESSION_SECRETfor any persistent dashboard deployment. - Enable
TRUST_PROXY_HEADERSonly behind a trusted Tailscale or mTLS proxy. - Keep GitLab OAuth credentials only when the compatibility login path is intentionally enabled.
- Keep GitLab tokens and project/group IDs classified as compatibility mutation inputs, not the strategic control-plane API.
- Keep OpenTofu as the source of managed infrastructure changes until a new mutation authority is explicitly designed and implemented.
Future Decisions
The next authority decisions are still open:
- whether first-class mutation should move to GitHub PR/GitOps APIs
- whether first-class mutation should move to a cluster-native controller
- whether monitoring and mutation should remain separate operator surfaces
- how passkey bootstrap works without GitLab OAuth
- how multi-tenant managed-control-plane auth maps to the FOSS core substrate
Until those decisions land, the honest operator story is:
- monitoring is primary
- tailnet or mTLS identity is preferred for access
- GitLab OAuth and GitLab mutation remain compatibility paths
- the platform does not yet have a forge-neutral mutation authority