Skip to Content
API Service (Rust)Admin & RBAC

Admin & RBAC

RBAC Enforcement

Authorization is enforced at two layers:

  1. auth_middleware — validates the session token and injects role: Role into request extensions. All /admin routes require this middleware.
  2. require_admin — reads role from extensions and returns 403 Forbidden if not Role::Admin. Zero additional DB queries.

Admin Stats

GET /admin/stats aggregates platform-wide metrics in a single handler, performing multiple DB queries:

  • COUNT(*) FROM users WHERE deleted_at IS NULL
  • COUNT(*) FROM users WHERE created_at > NOW() - INTERVAL '24 hours' (active today = created today, a proxy metric)
  • COUNT(*) FROM conversations
  • COUNT(*) FROM messages (API layer messages table)
  • Count of intelligence resources via gRPC ResourceService.ListResources

User Management

OperationQuery
list_usersSELECT * FROM users ORDER BY created_at DESC LIMIT $1 OFFSET $2 with optional ILIKE search on email or username
get_userSELECT * FROM users WHERE id = $1
update_user_roleUPDATE users SET role = $1::user_role WHERE id = $2
delete_userDELETE FROM users WHERE id = $1 (hard delete, cascades sessions/accounts)

Note: Admin delete_user is a hard delete (DELETE FROM users), whereas user self-deletion via DELETE /user/delete-account is a soft delete (SET deleted_at = NOW()). These two paths have different cascade behaviors.

Resource Management

Admin-managed resources (documents for RAG ingestion) are now exposed on /resources (admin-only middleware), and proxied to the Intelligence service:

Resource types (mapped from string to pb::ResourceType enum):

  • "text"TEXT
  • "markdown"MARKDOWN
  • "pdf"PDF
  • "html"HTML
  • "url"WEBSITE (triggers Playwright scraper)
  • "code"CODE
  • "file" → file-content ingestion path

Global resources (is_global: true): searchable by all users in hybrid search. Global resources are typically set by admins for shared knowledge base documents.

Contributor Queue (Admin Review)

Admins also review contributor submissions via:

  • GET /resources/submissions?status=pending|approved|rejected
  • POST /resources/submissions/{id}/review with { action: "approve" | "reject", feedback?: string }

On approve, the API forwards content to the Intelligence service (AddResource) and marks the submission as approved.

Weaknesses

  1. Role change inconsistency (admin path): Changing a user’s role via PATCH /admin/users/{id}/role updates users.role but does NOT update existing sessions’ role column. Active sessions retain the old role until expiry (7 days) or re-login.

  2. Hard vs soft delete asymmetry: Hard-deleting a user via admin bypasses the recovery mechanism available through POST /auth/recover-account.

  3. No audit log: Admin operations (role changes, user deletions, resource additions) are not logged to an audit trail. Only TraceLayer HTTP logs exist.

  4. gRPC timeout: Resource ingestion timeout is 3000s (50 min). A failure mid-ingestion may leave an ingestion_job in processing state with no recovery path from the Rust layer.

Last updated on