Skip to content

[Feature] Multi-user accounts + role-based access control for the API/dashboard #584

@brendandebeasi

Description

@brendandebeasi

Summary

Spacebot's API auth today is a single shared bearer token (api_auth_middleware in src/api/server.rs:346-376). There are no users, no roles, and no audit trail. As soon as more than one person operates an instance — or it's exposed beyond localhost — anyone with the token can read all channels, edit all secrets, run any worker, and rewrite identity files.

Current state

  • src/api/server.rs:351 — middleware checks an optional state.auth_token against an Authorization: Bearer … header
  • src/api/server.rs:351-353 — if no token is configured, all auth is skipped (see also API authentication is silently skipped when auth_token is not configured #356 which proposes failing closed)
  • All routes share the same single principal; no per-route or per-action authz
  • The dashboard frontend is unprotected (src/api/server.rs:322 "Static file handler for frontend (unprotected)") — only API calls go through the middleware

Proposed change

A basic local user system, opt-in via config:

  • New SQLite migration: users(id, username, password_hash, role, created_at) (argon2/bcrypt for hashing)
  • Roles to start: owner, admin, editor, viewer
  • Sessions via HTTP-only Secure cookies (configurable TTL); existing Authorization: Bearer … path retained for scripts/CLI as PAT-style tokens scoped to a role
  • New auth middleware variant that resolves the principal (user or PAT) and attaches it to the request extensions
  • Permission matrix per surface area: channels, agents, secrets, settings, cron, memory, workers, identity files
  • auth.mode = single-token | multi-user | disabled in config — disabled retains today's silently-open behavior only when explicitly opted into (so API authentication is silently skipped when auth_token is not configured #356 stays addressed); single-token preserves backward compat; multi-user enables the new system
  • First-run bootstrap: create an owner account via CLI (spacebot user create --owner) or a one-time setup token

Out of scope (follow-ups)

Open questions

  • Should internal cortex/worker calls go through the same middleware with a synthetic system principal, or bypass it as today?
  • Where should sessions be stored — same SQLite, or a dedicated key-value store?
  • Should the dashboard's static bundle stay public, or also be gated behind auth?

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions