|
|
|
@@ -0,0 +1,752 @@
|
|
|
|
|
# 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)
|
|
|
|
|
```sql
|
|
|
|
|
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)
|
|
|
|
|
```sql
|
|
|
|
|
CREATE TABLE groups (
|
|
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
|
name TEXT UNIQUE NOT NULL,
|
|
|
|
|
description TEXT,
|
|
|
|
|
created_at TEXT NOT NULL
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### user_groups table (new)
|
|
|
|
|
```sql
|
|
|
|
|
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)
|
|
|
|
|
```sql
|
|
|
|
|
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)
|
|
|
|
|
```sql
|
|
|
|
|
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)
|
|
|
|
|
```sql
|
|
|
|
|
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)
|
|
|
|
|
```sql
|
|
|
|
|
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)
|
|
|
|
|
```sql
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"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**
|