GloriousFlywheel Tailnet Operator Identity 2026-04-16

GloriousFlywheel Tailnet Operator Identity 2026-04-16

Snapshot date: 2026-04-16

Purpose

Capture the first executable auth-model tightening for #172.

This note is about request identity and session handling. It does not claim the full dashboard auth redesign is complete.

Companion notes:

Current Executed Contract

The repo now treats auth sources in this order:

  1. trusted proxy identity headers when TRUST_PROXY_HEADERS=true
  2. stored interactive session cookies
  3. development fallback in local dev mode only

That means tailnet and mTLS request identity is now authoritative when the dashboard is behind the trusted proxy path.

Executed Changes

1. Signed Dashboard Sessions

app/src/lib/server/auth/session.ts now signs session cookies with SESSION_SECRET when it is configured.

Implications:

  • production-style deployments no longer rely on unsigned base64 JSON cookies
  • tampered or legacy unsigned cookies are rejected when a session secret is present
  • local/dev environments without SESSION_SECRET still use the simpler unsigned cookie path for compatibility

2. Proxy Identity Takes Precedence

app/src/hooks.server.ts now resolves trusted proxy identity before stored interactive sessions.

Implications:

  • a tailnet or mTLS-authenticated request is no longer silently shadowed by an older OAuth or passkey cookie
  • request auth matches the ingress trust boundary instead of whichever cookie happened to exist first

3. Proxy Roles Are No Longer Hard-Coded Viewer

Trusted proxy identities no longer default to viewer.

Current role contract:

  • proxy-header auth defaults to operator
  • AUTH_ADMIN_IDENTITIES, AUTH_OPERATOR_IDENTITIES, and AUTH_VIEWER_IDENTITIES can override the fallback role by username or email
  • PROXY_AUTH_DEFAULT_ROLE can change the proxy fallback when needed

4. Interactive Auth Remains Compatibility

Interactive auth remains available, but it is now more clearly bounded:

  • GitLab OAuth still backs the current compatibility login flow
  • WebAuthn still provides interactive passwordless auth for registered users
  • passkey registration still depends on the GitLab interactive compatibility path today

Why This Matters

Before this slice:

  • proxy auth existed, but only as a thin helper behind cookie auth
  • trusted proxy users were always mapped to viewer
  • session cookies were not protected by the already-provisioned SESSION_SECRET

After this slice:

  • tailnet/mTLS operator identity is first-class at request time
  • the hook logic now matches the intended operator-plane direction better
  • interactive auth and mutation compatibility remain available without defining the strategic future too early

Remaining Gap

This does not finish #172.

The repo still needs:

  • a final operator permission model tied to mutation authority
  • a deliberate story for passkeys outside the GitLab interactive compatibility path
  • a replacement mutation authority if the dashboard stops using GitLab-backed compatibility flows

Exit Condition

  • request auth precedence is explicit and tailnet-first
  • signed session handling is in place when a session secret exists
  • trusted proxy identities can be treated as real operators instead of fallback viewers

GloriousFlywheel