Files
agent-platform/docs/requirements_rbac.md
T
Leopold 4de5f8d8ab
tests / pytest (push) Has been cancelled
docs: update current_status.md and add requirements_rbac.md
2026-07-14 20:08:47 +02:00

38 KiB

Requirements: Multi-User RBAC Upgrade — agent-platform

Date: 2026-07-08 Status: Final Draft v3 Author: Requirements Analyst


1. Problem & Goal

The agent-platform currently uses a static Bearer token (AUTH_TOKEN) with no user management. All token holders have full admin access. The goal is to add multi-user support with role-based access control (RBAC), user administration, groups, conversation sharing, per-user/per-group tool permissions, per-user/per-group agent visibility, LLM token quotas, concurrent sessions, configurable password policy, GDPR data retention, full mobile responsiveness, Alembic DB migrations, and per-user audit trails — while maintaining backward compatibility for existing API clients and hardening existing MCP tools.

2. User Stories

ID Story
US-01 As an admin, I want to log in with username+password so I can access the platform securely.
US-02 As any user, I want to log out so my session is terminated.
US-03 As an admin, I want to create/edit/disable/delete users so I can control who has access.
US-04 As an admin, I want to assign roles to users so permissions are managed centrally.
US-05 As a user (editor/admin), I want to chat with agents according to my permissions.
US-06 As a user, I want to view audit logs if my role permits it.
US-07 As an admin, I want to manage agents (CRUD) while lower roles cannot.
US-08 As an API client, I want to keep using my Bearer token so existing integrations don't break.
US-09 As any user, I want to see only UI elements my role permits so the interface is clean.
US-10 As an admin, I want to view my own profile and change my password.
US-11 As an admin, I want to create and manage groups so I can organize users and assign shared permissions.
US-12 As a user, I want to share a conversation with another user or group so we can collaborate.
US-13 As an admin, I want to configure which tools are available to which users/groups so tool access is fine-grained.
US-14 As a viewer, I want to view shared conversations but not start new ones.
US-15 As an admin, I want a first-login setup wizard to set my username and password on initial deployment.
US-16 As an admin, I want to set token quotas per user so LLM costs are controlled.
US-17 As a user, I want to see my token usage so I know how much budget I have left.
US-18 As an admin, I want to assign agents to specific users or groups so not everyone sees all agents.
US-19 As an admin, I want to deactivate or delete users with proper data handling so compliance is maintained.
US-20 As an admin, I want to configure password rules (length, complexity) so security policies are enforced.
US-21 As a user, I want to have multiple concurrent sessions (e.g. desktop + mobile) and revoke them independently.
US-22 As an admin, I want to revoke any user's sessions so I can force logout if needed.
US-23 As a user, I want audit logs filtered to what I am allowed to see so data access is properly scoped.
US-24 As a developer, I want complete OpenAPI documentation so I can integrate with the API.
US-25 As a user, I want the platform to be fully usable on mobile so I can work from any device.
US-26 As an admin, I want to export and anonymize user data so GDPR compliance is maintained.

3. Roles & Permissions Matrix

Roles define the baseline permission level. Groups add fine-grained control on top.

Resource / Action admin editor viewer
Agents — create/update/delete YES YES NO
Agents — view/list YES assigned assigned
Agents — assign to users/groups YES NO NO
Chat — start conversation YES YES NO
Chat — view own conversations YES YES YES
Chat — view shared conversations YES YES YES
Chat — view all conversations YES NO NO
Chat — share conversation YES YES NO
Tools — view/list YES YES YES
Tools — use (per tool) per perm per perm per perm
Tools — configure permissions YES NO NO
Audit — view (all entries) YES NO NO
Audit — view (own + shared conv) YES YES NO
Audit — view (own only) YES YES YES
Users — CRUD YES NO NO
Groups — CRUD YES NO NO
Settings — system config YES NO NO
Token quotas — set/view YES NO NO
Token usage — view own YES YES YES
Sessions — manage own YES YES YES
Sessions — manage others YES NO NO
Password policy — configure YES NO NO
Data retention — configure YES NO NO
User data — export/anonymize YES NO NO

Roles defined:

  • admin — full access, user/group management, system settings, tool/agent permissions, token quotas, password policy, data retention
  • editor — agent CRUD, chat (start+share), audit (own+shared), no user/group management
  • viewer — read-only: view assigned agents, view shared conversations, view tools, view own audit entries; no new chats, no management

Agent visibility: Not global by default. Agents can be assigned to users OR groups. See [F-RBAC-21] Agent Visibility.

Tool access: Not role-only. Each tool can be allowed/denied per user AND per group. See [F-RBAC-15] Tool Permission Management.

4. Authentication Model

  • Login method: username + password (argon2id hashing)
  • Session management: HTTP-only, Secure, SameSite=Lax cookies (server-side session in sessions table)
  • Concurrent sessions: Multiple sessions per user allowed. Each session has independent cookie. Session list visible to user (can revoke others). Admin can revoke any user's sessions. See [F-RBAC-24].
  • Session timeout: Configurable via SESSION_TIMEOUT_HOURS env var, default 24h. Rationale: prevents stale sessions on shared/insecure devices while not interrupting active work sessions. 24h balances security and usability.
  • Token compatibility: existing Bearer token (AUTH_TOKEN) remains valid for API access; maps to a virtual admin identity
  • Registration: admin-only invite (no open registration)
  • Bootstrap admin: First-login setup wizard — on first launch with no users in DB, redirect to /setup page where admin sets username + password. AUTH_TOKEN still required to access the setup page (proves deployment ownership).
  • Password policy: Configurable. See [F-RBAC-23].
  • Password reset: NOT in v1 scope (see Non-Goals)
  • Failed login logging: Yes — all auth events (login, logout, failed login, session revoke) logged in audit table with user_id. See S5 security fix.

5. Data Model Changes

users table (new)

CREATE TABLE users (
  id TEXT PRIMARY KEY,
  username TEXT UNIQUE NOT NULL,
  email TEXT,
  password_hash TEXT NOT NULL,
  role TEXT NOT NULL DEFAULT 'viewer',  -- admin|editor|viewer
  enabled INTEGER NOT NULL DEFAULT 1,
  token_quota_daily INTEGER,            -- NULL = unlimited
  token_quota_monthly INTEGER,          -- NULL = unlimited
  created_at TEXT NOT NULL,
  last_login TEXT
);

groups table (new)

CREATE TABLE groups (
  id TEXT PRIMARY KEY,
  name TEXT UNIQUE NOT NULL,
  description TEXT,
  created_at TEXT NOT NULL
);

user_groups table (new)

CREATE TABLE user_groups (
  user_id TEXT NOT NULL REFERENCES users(id),
  group_id TEXT NOT NULL REFERENCES groups(id),
  PRIMARY KEY (user_id, group_id)
);

conversation_shares table (new)

CREATE TABLE conversation_shares (
  id TEXT PRIMARY KEY,
  conversation_id TEXT NOT NULL REFERENCES conversations(id),
  shared_with_user_id TEXT REFERENCES users(id),
  shared_with_group_id TEXT REFERENCES groups(id),
  shared_by TEXT NOT NULL REFERENCES users(id),
  permission TEXT NOT NULL DEFAULT 'read',  -- read|write
  created_at TEXT NOT NULL,
  CHECK (
    (shared_with_user_id IS NOT NULL AND shared_with_group_id IS NULL) OR
    (shared_with_user_id IS NULL AND shared_with_group_id IS NOT NULL)
  )
);

tool_permissions table (new)

CREATE TABLE tool_permissions (
  id TEXT PRIMARY KEY,
  tool_name TEXT NOT NULL,
  user_id TEXT REFERENCES users(id),
  group_id TEXT REFERENCES groups(id),
  allowed INTEGER NOT NULL DEFAULT 1,    -- 1=allow, 0=deny
  created_at TEXT NOT NULL,
  CHECK (
    (user_id IS NOT NULL AND group_id IS NULL) OR
    (user_id IS NULL AND group_id IS NOT NULL)
  )
);

agent_assignments table (new)

CREATE TABLE agent_assignments (
  id TEXT PRIMARY KEY,
  agent_id TEXT NOT NULL REFERENCES agents(id),
  user_id TEXT REFERENCES users(id),
  group_id TEXT REFERENCES groups(id),
  created_at TEXT NOT NULL,
  CHECK (
    (user_id IS NOT NULL AND group_id IS NULL) OR
    (user_id IS NULL AND group_id IS NOT NULL)
  )
);

user_token_usage table (new)

CREATE TABLE user_token_usage (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id),
  tokens_used INTEGER NOT NULL,
  model TEXT NOT NULL,
  period TEXT NOT NULL,                 -- daily|monthly
  period_key TEXT NOT NULL,             -- e.g. '2026-07-08' or '2026-07'
  created_at TEXT NOT NULL
);

settings table (new — key-value store for configurable settings)

CREATE TABLE settings (
  key TEXT PRIMARY KEY,
  value TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  updated_by TEXT REFERENCES users(id)
);

Default settings rows:

  • password_min_length = '8'
  • password_require_uppercase = 'true'
  • password_require_lowercase = 'true'
  • password_require_digit = 'true'
  • password_require_special = 'false'
  • data_retention_days = '365'

audit table (modified)

  • Add column user_id TEXT (nullable for legacy entries)
  • Existing rows: user_id = NULL (displayed as 'system/legacy')
  • New rows: user_id = authenticated user's ID or 'SYSTEM' for Bearer token
  • All auth events logged: login, logout, failed login, session revoke

sessions table (existing, repurposed)

  • Add columns: user_id TEXT, expires_at TEXT, session_type TEXT ('api'|'browser'), ip_address TEXT, user_agent TEXT

conversations table (modified)

  • Add column owner_id TEXT (references users.id, nullable for legacy conversations)

Migration strategy (Alembic)

Tool: Alembic for all schema migrations. No raw CREATE TABLE IF NOT EXISTS.

Initial migration (alembic revision 001):

  1. Create tables: users, groups, user_groups, conversation_shares, tool_permissions, agent_assignments, user_token_usage, settings
  2. Add columns to existing tables: audit.user_id, sessions.user_id/expires_at/ session_type/ip_address/user_agent, conversations.owner_id
  3. Insert default settings rows
  4. Insert bootstrap admin via /setup wizard (application-level, not migration)

Conversation owner migration (alembic revision 002, post-setup):

  • After bootstrap admin is created via /setup wizard: UPDATE conversations SET owner_id = <admin_user_id> WHERE owner_id IS NULL
  • All legacy conversations assigned to bootstrap admin

Migration runbook (3-phase — revision 002 is a DATA migration requiring application context):

  1. alembic upgrade 001 — creates schema (tables, columns, default settings). NO data changes.
  2. Start application — redirects to /setup if no users exist
  3. Admin sets username + password via /setup (requires AUTH_TOKEN Bearer) — creates bootstrap admin user
  4. alembic upgrade 002 — assigns orphan conversations: UPDATE conversations SET owner_id = <admin_user_id> WHERE owner_id IS NULL. Requires admin user to exist (created in step 3).
  5. AUTH_TOKEN continues to work — resolved as virtual admin user
  6. No data loss; all existing agents/conversations/messages preserved
  7. Rollback: alembic downgrade -1 (reverts last migration); alembic downgrade 001 (reverts schema migration only)

6. UI Changes

[F-RBAC-01] Login Page

Anforderung: Server-rendered login form at /login. POST submits credentials, sets HTTP-only cookie on success, redirects to dashboard.

Test Scenarios:

  1. Happy Path: Valid credentials submitted -> 302 redirect to /, cookie session_id set with HttpOnly+Secure flags.
  2. Edge Case: Wrong password -> 401, login page re-rendered with error message, no cookie set.
  3. Edge Case: Disabled user attempts login -> 403, error 'account disabled', no session created.

[F-RBAC-02] Logout

Anforderung: POST /logout destroys session, clears cookie, redirects to /login.

Test Scenarios:

  1. Happy Path: Authenticated user clicks logout -> session row deleted, cookie cleared, redirect to /login.
  2. Edge Case: Unauthenticated POST to /logout -> 302 to /login, no error.

[F-RBAC-03] User Management Page (admin only)

Anforderung: /users page with table of all users, create/edit/disable/delete actions, role assignment, group membership management, token quota setting. Admin-only.

Test Scenarios:

  1. Happy Path: Admin navigates to /users -> sees table with all users, can create new user with role 'editor'.
  2. Edge Case: Viewer navigates to /users -> 403 forbidden, no user data exposed.
  3. Integration: Admin disables a user -> that user's next request gets 401 and redirect to /login.

[F-RBAC-04] Role-Based UI Visibility

Anforderung: Jinja2 templates conditionally render admin controls based on the current user's role. All pages fully responsive (mobile-first).

Test Scenarios:

  1. Happy Path: Viewer sees dashboard -> no admin nav links, no delete buttons rendered in HTML.
  2. Happy Path: Admin sees dashboard -> all management links present.
  3. Edge Case: Viewer manually requests DELETE /api/agents -> 403 from middleware.

[F-RBAC-05] User Profile / Settings Page

Anforderung: /profile page showing username, email, role (read-only), group memberships (read-only), password change form, token usage summary, active sessions list with revoke buttons.

Test Scenarios:

  1. Happy Path: User submits new password (current+new) -> password_hash updated, next login works with new password.
  2. Edge Case: Wrong current password -> 401, error message, password not changed.

[F-RBAC-06] First-Login Setup Wizard

Anforderung: On first boot with empty users table, redirect all requests to /setup. Page requires AUTH_TOKEN as Bearer to access. Admin sets username + password. After setup, redirect to /login.

Test Scenarios:

  1. Happy Path: Fresh deploy -> any URL redirects to /setup -> admin sets username+password -> redirect to /login.
  2. Edge Case: /setup accessed after users exist -> redirect to /login.
  3. Edge Case: /setup without AUTH_TOKEN Bearer -> 401.

[F-RBAC-13] Group Management Page (admin only)

Anforderung: /groups page with table of all groups, create/edit/delete actions, and member assignment. Admin-only. Users can be in multiple groups.

Test Scenarios:

  1. Happy Path: Admin creates group 'Developers', adds 2 users -> group visible in table with member count.
  2. Edge Case: Editor navigates to /groups -> 403 forbidden.
  3. Integration: Admin deletes a group -> shares with that group removed, group memberships removed (cascade).

[F-RBAC-14] Conversation Sharing

Anforderung: On any conversation the user owns, a 'Share' button opens a dialog to share with a specific user or group, with read or write permission. Shared conversations appear in a 'Shared with me' section.

Test Scenarios:

  1. Happy Path: User shares conversation with another user (read) -> recipient sees conversation in 'Shared with me', can view but not send messages.
  2. Happy Path: User shares conversation with group (write) -> all group members can send messages.
  3. Edge Case: Viewer tries to share -> 403.
  4. Integration: Owner removes share -> recipient loses access immediately.

7. API Changes

Standard Error Response Schema

All error responses (401/403/400/404/409/429/500) use a uniform JSON body:

{
  "error_code": "forbidden",
  "message": "You do not have permission to access this resource.",
  "details": {"required_role": "admin", "current_role": "viewer"}
}
Field Type Required Description
error_code string YES Machine-readable error identifier (e.g. unauthorized, forbidden, validation_error, not_found, conflict, rate_limited, internal_error)
message string YES Human-readable error message in English
details object NO Optional structured details (e.g. validation field errors, required vs. current role)

This schema is enforced on all new endpoints and documented in the OpenAPI spec (see F-RBAC-27).

[F-RBAC-07] Auth Endpoints

Anforderung: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me. Login returns user info + sets cookie. /me returns current user identity including groups and token usage.

Test Scenarios:

  1. Happy Path: POST /api/auth/login with valid JSON -> 200, {user_id, username, role, groups[]}, cookie set.
  2. Edge Case: GET /api/auth/me without auth -> 401.
  3. Integration: After login, GET /api/auth/me with cookie -> 200, returns user data with groups + token usage.

[F-RBAC-08] User CRUD Endpoints (admin only)

Anforderung: GET/POST/PUT/DELETE /api/users — admin-only. Includes group membership, token quota setting, disable/delete with proper data handling.

Test Scenarios:

  1. Happy Path: Admin POST /api/users with valid data -> 201, new user created with hashed password.
  2. Edge Case: Editor GET /api/users -> 403.
  3. Edge Case: Admin DELETE own account -> 400, 'cannot delete yourself'.

[F-RBAC-09] Group CRUD Endpoints (admin only)

Anforderung: GET/POST/PUT/DELETE /api/groups. POST /api/groups/{id}/members, DELETE /api/groups/{id}/members/{user_id} for membership. Group deletion cascades: removes conversation_shares and user_groups entries for that group.

Test Scenarios:

  1. Happy Path: Admin POST /api/groups -> 201, new group created.
  2. Happy Path: Admin POST /api/groups/{id}/members with user_id -> 200, user added.
  3. Edge Case: Editor POST /api/groups -> 403.

[F-RBAC-10] Conversation Share Endpoints

Anforderung: POST /api/conversations/{id}/shares, DELETE .../{share_id}. Owner or admin only. Bulk revoke: DELETE /api/conversations/{id}/shares (all).

Test Scenarios:

  1. Happy Path: Owner POST share with user_id+permission=read -> 201.
  2. Happy Path: Owner POST share with group_id+permission=write -> 201.
  3. Edge Case: Non-owner non-admin POST share -> 403.
  4. Edge Case: Owner DELETE all shares -> 200, all recipients lose access.

[F-RBAC-11] Permission Middleware

Anforderung: FastAPI dependency checking user role, agent assignment, tool permission on every protected endpoint. Bearer token = virtual admin. Agent access: user must be assigned directly or via group. Admin sees all agents.

Test Scenarios:

  1. Happy Path: Viewer with cookie calls DELETE /api/agents/{id} -> 403.
  2. Happy Path: Bearer token calls DELETE /api/agents/{id} -> 200.
  3. Edge Case: No auth on protected endpoint -> 401.

[F-RBAC-12] Bearer Token Backward Compatibility

Anforderung: AUTH_TOKEN env var still accepted as Bearer header. Resolved as virtual admin user. No existing API client breaks.

Test Scenarios:

  1. Happy Path: Bearer AUTH_TOKEN on /api/agents -> 200, full admin access.
  2. Integration: Bearer token audit entries logged with user_id='SYSTEM'.

[F-RBAC-15] Tool Permission Management

Anforderung: Admin configures per-tool permissions per user and per group. GET/POST/PUT/DELETE /api/tools/permissions. Resolution: user-level -> group-level -> role default (editor: allow, viewer: deny). New users inherit role default.

Test Scenarios:

  1. Happy Path: Admin denies tool 'http_get' for user X -> user X cannot use http_get in chat.
  2. Happy Path: Admin allows tool 'calculate' for group 'Devs' -> members can use calculate.
  3. Edge Case: No explicit permission -> default applies (editor: allow, viewer: deny).

[F-RBAC-20] LLM Token Quota System

Anforderung: Each user has configurable token quota (daily/monthly) set by admin. user_token_usage table tracks tokens per user per period. Soft limit: warning at 80%. Hard limit: block new chat messages at 100%. User sees usage in profile. Admin sees all users' usage. Users without quota (NULL) = unlimited.

Test Scenarios:

  1. Happy Path: Admin sets daily quota 10000 for user X -> user X uses 8000 tokens -> warning shown. Uses 10000 -> next chat message blocked with 'quota exceeded'.
  2. Edge Case: User with NULL quota -> unlimited, no warnings, no blocks.
  3. Integration: Admin views /api/users/{id}/usage -> returns daily+monthly totals.

[F-RBAC-21] Agent Visibility per User/Group

Anforderung: Agents can be assigned to users OR groups via agent_assignments table. Only assigned users (or group members) can see/use agents. Admin sees all. Unassigned agents = admin only. Assignment managed via /api/agents/{id}/assignments.

Test Scenarios:

  1. Happy Path: Admin assigns agent A to user X -> user X sees agent A in dashboard, can chat.
  2. Happy Path: Admin assigns agent B to group 'Devs' -> group members see agent B.
  3. Edge Case: User Y (not assigned to agent A) -> agent A not visible in UI or API.
  4. Edge Case: Agent with no assignments -> only admin sees it.

[F-RBAC-22] User Deactivation vs Deletion

Anforderung: Admin can deactivate (enabled=false) or delete users. Deactivate: sessions invalidated, no new logins, conversations preserved (owner_id kept), audit entries preserved. Delete: conversations transferred to admin (owner_id = admin), shares removed, group memberships removed, audit entries preserved with user_id reference (not anonymized on delete — anonymization is separate GDPR action). Admin chooses deactivate or delete in UI.

Test Scenarios:

  1. Happy Path: Admin deactivates user X -> user X sessions deleted, login returns 403, conversations preserved with owner_id=X.
  2. Happy Path: Admin deletes user Y -> user Y conversations owner_id set to admin, shares removed, group memberships removed, audit entries preserved.
  3. Edge Case: Admin tries to delete self -> 400, 'cannot delete yourself'.

[F-RBAC-23] Password Policy (Configurable)

Anforderung: Password rules stored in settings table (min_length default=8, require_uppercase, require_lowercase, require_digit, require_special default=false). Admin configures via PUT /api/settings/password-policy. Enforced on user creation, password change, and setup wizard.

Test Scenarios:

  1. Happy Path: Admin sets min_length=12, require_special=true -> new user with password 'short1!' -> 400 (too short). Password 'Longenough1!' -> 201.
  2. Edge Case: User changes password to one that fails policy -> 400 with specific validation error.
  3. Integration: Policy change does not affect existing passwords (only future sets).

[F-RBAC-24] Concurrent Sessions

Anforderung: Multiple sessions per user allowed. Each session has independent cookie/token. User sees session list in /profile (IP, user_agent, created_at) and can revoke others. Admin can revoke any user's sessions via /api/users/{id}/sessions.

Test Scenarios:

  1. Happy Path: User logs in from desktop, then from mobile -> 2 active sessions, both work independently.
  2. Happy Path: User revokes mobile session from desktop -> mobile session invalidated, desktop still works.
  3. Integration: Admin revokes all sessions for user X -> user X gets 401 on next request.

[F-RBAC-25] Audit Visibility per Role

Anforderung: Admin sees all audit entries. Editor sees own entries + entries for conversations they have access to. Viewer sees own entries only. API filters automatically based on role. UI shows filtered audit log.

Test Scenarios:

  1. Happy Path: Admin GET /api/audit -> all entries returned.
  2. Happy Path: Editor GET /api/audit -> only own entries + entries for accessible conversations.
  3. Edge Case: Viewer GET /api/audit -> only own entries (e.g. own login/logout events).

[F-RBAC-26] OpenAPI Documentation

Anforderung: Every endpoint has complete OpenAPI schema via FastAPI auto-gen. /docs (Swagger UI) and /redoc available. All new endpoints have request/response schemas, error codes (401/403/400/429/500), auth requirements documented. OpenAPI spec tested: verify all endpoints have descriptions and schemas.

Test Scenarios:

  1. Happy Path: GET /openapi.json -> valid OpenAPI 3.1 spec with all endpoints documented.
  2. Happy Path: GET /docs -> Swagger UI renders, all endpoints visible with schemas.
  3. Edge Case: New endpoint without description -> test fails (CI check).

[F-RBAC-27] GDPR / Data Retention

Anforderung: User data (username, email, password_hash, audit entries) subject to data_retention_days setting (default 365). Admin can export user data as JSON via GET /api/users/{id}/export. Admin can anonymize deleted user data (replace username/email with 'anonymized', keep audit entries with anonymized user_id). Export includes: profile, conversations (owned), audit entries, token usage.

Test Scenarios:

  1. Happy Path: Admin GET /api/users/{id}/export -> JSON with user profile, conversations, audit entries, token usage.
  2. Happy Path: Admin anonymizes user X -> username='anonymized', email='anonymized', password_hash removed, audit entries preserved with user_id=X.
  3. Edge Case: Non-admin GET /api/users/{id}/export -> 403.

8. Security Requirements

[F-RBAC-16] Password Hashing (argon2id)

Anforderung: All passwords hashed with argon2id. No plaintext storage.

Test Scenarios:

  1. Happy Path: Create user with password 'test123' -> DB stores argon2id hash, not plaintext.
  2. Edge Case: Login with correct password -> succeeds; wrong password -> fails.

[F-RBAC-17] Login Rate Limiting + Auth Event Logging

Anforderung: Max 5 failed login attempts per IP per 60 seconds -> 429 for 60s. All auth events (login, logout, failed login, session revoke) logged in audit table with user_id, ip_address, user_agent.

Test Scenarios:

  1. Happy Path: 5 wrong passwords in 60s -> 6th attempt 429. Audit has 5 'login_failed' entries.
  2. Edge Case: 4 wrong + 1 correct -> no rate limit, user logged in, 'login' event in audit.

[F-RBAC-18] CSRF Protection

Anforderung: All cookie-authenticated state-changing requests require CSRF token. Bearer token requests exempt.

Test Scenarios:

  1. Happy Path: Form POST with valid CSRF token -> succeeds.
  2. Edge Case: Form POST without CSRF token -> 403.

[F-RBAC-19] Session Expiry (Configurable)

Anforderung: Browser sessions expire after SESSION_TIMEOUT_HOURS (default 24h). Expired sessions redirect to /login. Bearer tokens have no expiry.

Test Scenarios:

  1. Happy Path: Session idle >24h -> next request 401, redirect to /login.
  2. Edge Case: Active session within 24h -> normal access.
  3. Edge Case: SESSION_TIMEOUT_HOURS=2 -> sessions expire after 2h.

S2: http_get Tool Hardening

Anforderung: Disable follow_redirects (prevent SSRF via redirect). Add DNS pinning: resolve hostname once at first call, pin IP for subsequent calls in same session. Non-admin users cannot use http_get unless explicitly permitted via tool_permissions.

Test Scenarios:

  1. Happy Path: http_get to http://example.com -> follows no redirects, returns 200 from pinned IP.
  2. Edge Case: http_get to URL that redirects -> redirect not followed, original response returned.
  3. Edge Case: Non-admin user without http_get permission -> tool blocked.

S3: list_env Tool Hardening

Anforderung: Admin-only by default. Mask-whitelist expanded. Non-admin users see only non-sensitive vars (e.g. PATH, LANG). Sensitive vars (tokens, keys, passwords) hidden for non-admins. Admin sees all.

Test Scenarios:

  1. Happy Path: Admin calls list_env -> sees all env vars including AUTH_TOKEN (masked).
  2. Edge Case: Non-admin calls list_env -> sees only PATH, LANG, HOME, etc. No tokens/keys.
  3. Edge Case: Non-admin without list_env permission -> tool blocked.

S5: Auth Event Audit Logging

Anforderung: All auth events written to audit table: login (success), login (failed), logout, session revoke, session expiry. Each entry has user_id, ip_address, user_agent, timestamp.

Test Scenarios:

  1. Happy Path: User logs in -> audit entry: action='login', user_id=X, ip=..., user_agent=...
  2. Happy Path: User logs out -> audit entry: action='logout', user_id=X.
  3. Edge Case: Failed login -> audit entry: action='login_failed', user_id=NULL, details={username, ip}.

9. Non-Goals (v1)

  • NO OAuth/SSO integration (SAML, OIDC, Google/GitHub login)
  • NO Multi-tenant isolation (single-tenant only)
  • NO 2FA/MFA (TOTP, WebAuthn)
  • NO Per-user API key management (AUTH_TOKEN remains global)
  • NO Password reset / forgot-password email flow
  • NO User registration / self-signup
  • NO Session refresh tokens / sliding window renewal
  • NO Webhook notifications for user/group events
  • NO Email notifications (user create/disable, share notifications)
  • NO Conversation transfer of ownership (except on user deletion)
  • NO Real-time collaboration (concurrent editing of same conversation)
  • NO Token quota rollover (unused quota does not carry over)

10. Acceptance Criteria (Summary)

Criterion Verification
Login works with username+password Manual test on staging: login, access dashboard
First-login setup wizard works Fresh DB -> /setup -> set credentials -> login works
Logout clears session Manual test: logout, verify redirect + no access
3 roles enforced API test: each role gets correct 200/403 on all endpoints
Viewer cannot start new chats API test: viewer POST /api/chat -> 403
Bearer token still works curl with AUTH_TOKEN on /api/agents -> 200
User management admin-only Browser test: viewer gets 403 on /users
Group management admin-only Browser test: editor gets 403 on /groups
Groups: create, add members, multiple per user API test: create group, add user, verify
Conversation sharing (user read) Share -> recipient views, cannot send
Conversation sharing (group write) Share -> all group members can send
Tool permissions per user Deny tool for user -> blocked in chat
Tool permissions per group Allow tool for group -> members can use
Agent visibility per user Assign agent -> user sees it, unassigned don't
Agent visibility per group Assign agent to group -> members see it
Token quota enforced Set quota -> user hits limit -> blocked
Token usage visible User sees own usage in profile
User deactivation preserves data Deactivate -> sessions killed, convs preserved
User deletion transfers convs Delete -> convs to admin, shares removed
Password policy enforced Set min_length=12 -> short password rejected
Concurrent sessions work Login from 2 devices -> both work, revoke one
Admin can revoke sessions Admin revokes user sessions -> user gets 401
Audit filtered by role Viewer sees own only, editor sees own+shared
OpenAPI spec complete GET /openapi.json -> all endpoints documented
Swagger UI works GET /docs -> all endpoints visible with schemas
Mobile responsive Test at 320px, 768px, 1024px -> all pages usable
HTMX works on touch Tap buttons on mobile -> actions work
GDPR export Admin exports user data -> JSON with all data
GDPR anonymize Admin anonymizes -> username/email anonymized
Data retention configurable Set 30 days -> old audit entries flagged
Audit logs show user_id Create agent as user -> audit has user_id
Failed logins in audit Wrong password -> 'login_failed' in audit
Passwords argon2id hashed DB inspection: no plaintext
Rate limiting on login 6 rapid wrong -> 429 on 6th
CSRF on form POSTs Form POST without token -> 403
Session expires (configurable) Set 1h -> wait 1h -> expired
http_get hardened No redirect following, DNS pinning works
list_env hardened Non-admin sees only non-sensitive vars
Auth events logged Login/logout/failed/revoke in audit
Alembic migrations work alembic upgrade head -> all tables created
Migration rollback works alembic downgrade -1 -> reverts cleanly
All existing endpoints still function Full regression: agents CRUD, chat, tools, audit
No data loss on migration Existing agents/conversations preserved

11. Assumptions

  1. Single instance deployment (no horizontal scaling needed for sessions)
  2. SQLite remains the database (no migration to PostgreSQL needed)
  3. AUTH_TOKEN continues to be set in environment for backward compatibility
  4. Jinja2+HTMX stack stays — no SPA framework introduction
  5. Existing MCP tools container and FastMCP integration unchanged (tools themselves are hardened)
  6. staging.agent-platform.media-on.de remains the test environment
  7. argon2id available via argon2-cffi Python package
  8. Alembic available and configured for SQLite + aiosqlite
  9. User count is small (<50), no pagination needed for user/group lists in v1
  10. Conversation sharing is opt-in; conversations are private by default
  11. Tool permission resolution: user-level > group-level > role default
  12. Agent visibility: unassigned agents = admin only; admin always sees all agents
  13. Token quota: NULL = unlimited; quota tracks LLM tokens (prompt+completion)
  14. Mobile responsiveness uses CSS media queries + HTMX touch-compatible interactions
  15. GDPR anonymization keeps audit trail intact (user_id preserved, PII replaced)
  16. Data retention is advisory (admin sees expired entries, manual purge or scheduled cleanup post-v1)

12. Resolved Decisions

# Question Decision Rationale
Q1 Conversation visibility for editor Shareable with users/groups User wants sharing + groups; private by default
Q2 Viewer can start new chats? No — strictly read-only User: 'viewer kann nur sehen'
Q3 Session timeout needed? Yes, configurable, default 24h Security best practice; 24h balances security/usability
Q4 Bootstrap admin password First-login setup wizard Better UX; AUTH_TOKEN guards setup page
Q5 Failed logins in audit? Yes User confirmed
Q6 Email notifications? No User: 'erstmal nein'
Q7 Tool visibility per role? Per-user AND per-group User wants fine-grained control
Q8 Bulk 'unshare all'? Yes Owner/admin can revoke all shares at once
Q9 Group deletion cascades to shares? Yes Shares + memberships removed on group delete
Q10 Default tool perms for new users? Inherit role default Editor: allow all; viewer: deny all

13. Open Questions

All open questions resolved. No remaining open questions.

14. Discovery Checklist (20 Categories)

# Category Status Notes
1 Auth ja Login/logout/RBAC/session/setup wizard/concurrent sessions/password policy
2 Daten ja User/group/agent_assignment/tool_perm/share/token_usage/settings + Alembic migrations
3 Fehler ja 401/403/400/429 responses, login error messages, OpenAPI error schemas
4 Skalierung nein Single instance, <50 users, SQLite sufficient
5 Sicherheit ja argon2id, CSRF, rate limiting, session expiry, S2/S3/S5 tool hardening, GDPR
6 UX ja Login, setup wizard, role-based UI, profile, groups, sharing, mobile responsive
7 Infrastruktur nein Unchanged — existing Docker/staging; Alembic adds migration tooling
8 Multi-User ja RBAC + groups + sharing + agent visibility + tool perms + token quotas + concurrent sessions
9 Migration ja Alembic revisions, conversation owner assignment, setup wizard, rollback runbook
10 Mobile ja Full mobile responsive at 320/768/1024px, HTMX touch-compatible
11 Integration nein No external integrations added in this phase
12 Compliance ja Audit trail with user_id, GDPR export/anonymize, data retention setting
13 Performance nein Small user base, existing performance adequate
14 i18n nein German/English not required for v1
15 Accessibility spaeter Login form has labels/ARIA; full WCAG audit deferred
16 Analytics nein No usage tracking added (token usage is operational, not analytics)
17 Environments ja Staging for testing, production via existing Docker, Alembic runbook
18 Dokumentation ja OpenAPI/Swagger complete, all endpoints documented
19 Testing ja Manual + curl tests defined in acceptance criteria; OpenAPI spec testable
20 Naming/Branding nein Existing project name/branding unchanged
21 Scheduling nein No background jobs/cron needed for RBAC (data retention purge post-v1)

15. Feature Test Coverage

Feature ID Feature Test Count
F-RBAC-01 Login Page 3
F-RBAC-02 Logout 2
F-RBAC-03 User Management Page 3
F-RBAC-04 Role-Based UI Visibility 3
F-RBAC-05 Profile / Settings Page 2
F-RBAC-06 First-Login Setup Wizard 3
F-RBAC-07 Auth Endpoints 3
F-RBAC-08 User CRUD Endpoints 3
F-RBAC-09 Group CRUD Endpoints 3
F-RBAC-10 Conversation Share Endpoints 4
F-RBAC-11 Permission Middleware 3
F-RBAC-12 Bearer Token Compat 2
F-RBAC-13 Group Management Page 3
F-RBAC-14 Conversation Sharing UI 4
F-RBAC-15 Tool Permission Management 3
F-RBAC-16 Password Hashing (argon2id) 2
F-RBAC-17 Rate Limiting + Auth Event Logging 2
F-RBAC-18 CSRF Protection 2
F-RBAC-19 Session Expiry (Configurable) 3
F-RBAC-20 LLM Token Quota System 3
F-RBAC-21 Agent Visibility per User/Group 4
F-RBAC-22 User Deactivation vs Deletion 3
F-RBAC-23 Password Policy (Configurable) 3
F-RBAC-24 Concurrent Sessions 3
F-RBAC-25 Audit Visibility per Role 3
F-RBAC-26 OpenAPI Documentation 3
F-RBAC-27 GDPR / Data Retention 3
S2 http_get Tool Hardening 3
S3 list_env Tool Hardening 3
S5 Auth Event Audit Logging 3

Total: 27 RBAC features + 3 security fixes = 30 items, all with test scenarios, 87 total test scenarios


DISCOVERY_CHECK: categories=20/20, features_with_ids=27/27, test_scenarios=27/27, constraints=Y, non_goals=Y, domain=Y, ready_for_ui=Y