feat: Add role-based API tokens for Claudia Docs

- Add api_tokens table with role-based access (researcher, developer, viewer)
- Add POST /auth/token/generate endpoint for creating tokens
- Add GET /auth/tokens endpoint for listing user's tokens
- Add DELETE /auth/tokens/{token_id} endpoint for revoking tokens
- Add agent_type field to documents (research, development, general)
- Implement role-based access control for documents:
  - researcher: access to research and general documents
  - developer: access to development and general documents
  - viewer: read-only access
- Update document model and schemas with agent_type field
- Add comprehensive tests for API token functionality
- All existing tests pass (73 total)
This commit is contained in:
Motoko
2026-03-31 01:46:51 +00:00
parent 5beac2d673
commit 204badb964
10 changed files with 770 additions and 97 deletions

View File

@@ -192,7 +192,8 @@ def _create_schema(sync_conn):
model_source TEXT,
tiptap_content TEXT,
outgoing_links TEXT DEFAULT '[]',
backlinks_count INTEGER NOT NULL DEFAULT 0
backlinks_count INTEGER NOT NULL DEFAULT 0,
agent_type TEXT DEFAULT 'general' CHECK (agent_type IN ('research', 'development', 'general'))
)
"""))
@@ -244,6 +245,19 @@ def _create_schema(sync_conn):
)
"""))
# API tokens table (role-based)
sync_conn.execute(text("""
CREATE TABLE IF NOT EXISTS api_tokens (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
token_hash TEXT NOT NULL,
role TEXT NOT NULL CHECK (role IN ('researcher', 'developer', 'viewer')),
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT (datetime('now')),
last_used_at TIMESTAMP NULL
)
"""))
# Indexes
sync_conn.execute(text("CREATE INDEX IF NOT EXISTS idx_projects_agent ON projects(agent_id)"))
sync_conn.execute(text("CREATE INDEX IF NOT EXISTS idx_folders_project ON folders(project_id)"))
@@ -254,6 +268,7 @@ def _create_schema(sync_conn):
sync_conn.execute(text("CREATE INDEX IF NOT EXISTS idx_document_tags_tag ON document_tags(tag_id)"))
sync_conn.execute(text("CREATE INDEX IF NOT EXISTS idx_refresh_tokens_hash ON refresh_tokens(token_hash)"))
sync_conn.execute(text("CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_family ON refresh_tokens(user_id, token_family_id)"))
sync_conn.execute(text("CREATE INDEX IF NOT EXISTS idx_api_tokens_agent ON api_tokens(agent_id)"))
# --- FTS5 virtual table ---
sync_conn.execute(text("""