> ## Documentation Index
> Fetch the complete documentation index at: https://docs.equa.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Admin Panel

> Site-wide administration dashboard for user management, statistics, and domain/email blacklists

# SPEC 019 — Admin Panel

| Field    | Value                         |
| -------- | ----------------------------- |
| Status   | DRAFT                         |
| Priority | P1 — Core Product             |
| Backend  | `equa-server/modules/admin/`  |
| Frontend | `equa-web/src/modules/admin/` |

***

## 1. Feature Purpose

The Admin Panel provides site-level administrators with tools to manage users, view platform statistics, and enforce domain/email blacklists. Unlike organization-level roles (SPEC 012), admin access is granted through the `GlobalRolesUsers` table and operates across all organizations on the platform. This is the control plane for platform operators to monitor health, manage abuse, and support users.

***

## 2. Current State (Verified)

### 2.1 Global Role System

| Detail     | Value                                                                      |
| ---------- | -------------------------------------------------------------------------- |
| Entity     | `GlobalRolesUsers` — maps users to site-level roles                        |
| Role field | `role` (GlobalRole integer enum)                                           |
| Guard      | Middleware checks `GlobalRolesUsers` before allowing admin endpoint access |
| Scope      | Admin privileges are platform-wide, not scoped to any organization         |

### 2.2 User Management

| Detail       | Value                                                                       |
| ------------ | --------------------------------------------------------------------------- |
| Capabilities | List all users, search by email, enable/disable accounts, view user details |
| Backend      | `equa-server/modules/admin/` handles user queries and mutations             |
| Endpoints    | `equa-server/modules/api/src/endpoints/admin-endpoints.ts`                  |

### 2.3 Site Statistics

| Detail  | Value                                                                       |
| ------- | --------------------------------------------------------------------------- |
| Metrics | Total users, organizations, active sessions, recent sign-ups, storage usage |
| Source  | Aggregation queries against Users, Organizations, Sessions tables           |
| Display | Dashboard cards and charts on the admin frontend                            |

### 2.4 Blacklists

| Detail           | Value                                                                |
| ---------------- | -------------------------------------------------------------------- |
| Domain blacklist | `DomainBlacklists` — blocks registration from specific email domains |
| Email blacklist  | `EmailBlacklists` — blocks specific email addresses                  |
| Enforcement      | Checked during registration and invitation flows                     |

### 2.5 Frontend

| Component       | Path                                    |
| --------------- | --------------------------------------- |
| Admin module    | `equa-web/src/modules/admin/`           |
| Dashboard       | Admin landing page with stats cards     |
| User management | Searchable user table with action menus |

***

## 3. Data Model

### GlobalRolesUsers

| Column | Type    | Constraints                      |
| ------ | ------- | -------------------------------- |
| user   | uuid    | PK, FK → Users                   |
| role   | integer | NOT NULL — GlobalRole enum value |

### DomainBlacklists

| Column    | Type      | Constraints                               |
| --------- | --------- | ----------------------------------------- |
| id        | uuid      | PK                                        |
| domain    | varchar   | UNIQUE, NOT NULL — e.g. `spam-domain.com` |
| reason    | varchar   | nullable                                  |
| createdBy | uuid      | FK → Users                                |
| createdAt | timestamp | DEFAULT now()                             |

### EmailBlacklists

| Column    | Type      | Constraints      |
| --------- | --------- | ---------------- |
| id        | uuid      | PK               |
| email     | citext    | UNIQUE, NOT NULL |
| reason    | varchar   | nullable         |
| createdBy | uuid      | FK → Users       |
| createdAt | timestamp | DEFAULT now()    |

***

## 4. API Endpoints

| Method | Path                                   | Auth  | Description                                               |
| ------ | -------------------------------------- | ----- | --------------------------------------------------------- |
| GET    | `/api/v1/admin/stats`                  | Admin | Platform-wide statistics (users, orgs, sessions, storage) |
| GET    | `/api/v1/admin/users`                  | Admin | Paginated user list with search and filters               |
| GET    | `/api/v1/admin/users/:userId`          | Admin | Single user detail (orgs, sessions, activity)             |
| PUT    | `/api/v1/admin/users/:userId`          | Admin | Update user (enable/disable, modify fields)               |
| DELETE | `/api/v1/admin/users/:userId`          | Admin | Soft-delete or permanently remove a user account          |
| GET    | `/api/v1/admin/organizations`          | Admin | Paginated organization list                               |
| GET    | `/api/v1/admin/blacklists/domains`     | Admin | List domain blacklist entries                             |
| POST   | `/api/v1/admin/blacklists/domains`     | Admin | Add a domain to the blacklist                             |
| DELETE | `/api/v1/admin/blacklists/domains/:id` | Admin | Remove a domain from the blacklist                        |
| GET    | `/api/v1/admin/blacklists/emails`      | Admin | List email blacklist entries                              |
| POST   | `/api/v1/admin/blacklists/emails`      | Admin | Add an email to the blacklist                             |
| DELETE | `/api/v1/admin/blacklists/emails/:id`  | Admin | Remove an email from the blacklist                        |

All "Admin" auth endpoints require the requesting user to have an entry in `GlobalRolesUsers` with an appropriate admin role.

***

## 5. Frontend Components

| Component       | Path                        | Description                                                              |
| --------------- | --------------------------- | ------------------------------------------------------------------------ |
| AdminDashboard  | `admin/AdminDashboard.tsx`  | Landing page with statistics cards (users, orgs, sessions, storage)      |
| UserManagement  | `admin/UserManagement.tsx`  | Searchable, paginated user table with inline actions                     |
| UserDetail      | `admin/UserDetail.tsx`      | Full user profile view with organization memberships and session history |
| DomainBlacklist | `admin/DomainBlacklist.tsx` | CRUD table for blocked domains                                           |
| EmailBlacklist  | `admin/EmailBlacklist.tsx`  | CRUD table for blocked email addresses                                   |
| OrgBrowser      | `admin/OrgBrowser.tsx`      | Paginated organization list with summary stats                           |

### Frontend Behavior

* **Route guard** — Admin routes are protected by a global role check; non-admins see a 403 page or are redirected.
* **Search** — User management supports real-time search by email, username, or user ID with debounced API calls.
* **Bulk actions** — User list supports multi-select for bulk enable/disable operations.
* **Statistics refresh** — Dashboard stats auto-refresh on a 60-second interval while the page is visible.
* **Confirmation modals** — Destructive actions (disable user, delete blacklist entry) require confirmation before execution.

***

## 6. Business Rules

1. **Global role separation** — Admin access is completely separate from organization-level roles. Being an org admin does not grant platform admin access.
2. **GlobalRolesUsers is the single source of truth** — All admin middleware checks this table; there is no fallback to environment variables or hardcoded user IDs.
3. **Domain blacklist enforcement** — During registration and team invitation, the email domain is checked against `DomainBlacklists`; matching domains are rejected with a generic error (no leak of blacklist existence).
4. **Email blacklist enforcement** — Specific email addresses in `EmailBlacklists` are blocked from registration and invitation with the same generic error.
5. **Blacklist is case-insensitive** — Domain comparison is lowercase; email comparison uses `citext` for case-insensitive matching.
6. **User disable vs delete** — Disabling a user (`enabled = false`) blocks login but preserves data. Deletion removes the account and is irreversible.
7. **Audit trail** — Blacklist entries record `createdBy` to track which admin added them.
8. **Self-protection** — Admins cannot disable or delete their own account through the admin panel.
9. **No self-promotion** — Adding entries to `GlobalRolesUsers` is restricted to existing admins or direct database access; there is no self-service admin promotion endpoint.
10. **Statistics are real-time** — Stats endpoints run live aggregation queries; no materialized views or caches are used.

***

## 7. Acceptance Criteria

* [ ] Only users with a `GlobalRolesUsers` entry can access admin endpoints and routes
* [ ] Non-admin users receive 403 on admin API calls and are redirected on frontend
* [ ] Admin dashboard displays correct counts for users, organizations, and active sessions
* [ ] User management table supports pagination and search by email/username
* [ ] Admin can disable a user account; disabled user cannot log in
* [ ] Admin can re-enable a disabled user account
* [ ] Admin cannot disable their own account
* [ ] Admin can add a domain to the blacklist; new registrations from that domain are blocked
* [ ] Admin can add a specific email to the blacklist; that email cannot register or be invited
* [ ] Blacklist checks are case-insensitive
* [ ] Blacklist rejections show generic error messages (no information leak)
* [ ] Admin can remove blacklist entries; previously blocked domains/emails can register again
* [ ] Organization browser displays all organizations with summary information
* [ ] Destructive actions require confirmation modal

***

## 8. Risks

| Risk                                                              | Impact                                               | Mitigation                                                              |
| ----------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------- |
| Privilege escalation via direct DB insert into `GlobalRolesUsers` | Unauthorized admin access                            | Restrict DB write access; audit `GlobalRolesUsers` changes              |
| Admin account compromise                                          | Full platform control                                | Require 2FA for admin accounts; log all admin actions                   |
| Real-time stats queries on large datasets                         | Slow dashboard load, DB strain                       | Add query timeouts; consider materialized views if scale demands        |
| Blacklist bypass via email aliases (e.g. `user+tag@domain.com`)   | Blocked users re-register                            | Normalize emails (strip `+` aliases) before blacklist check             |
| Accidental user deletion                                          | Irreversible data loss                               | Implement soft-delete with grace period before hard purge               |
| No rate limiting on admin endpoints                               | Abuse by compromised admin session                   | Add rate limiting; log and alert on unusual admin activity patterns     |
| Blacklist reason field is optional                                | Poor audit trail for why domains/emails were blocked | Consider making reason required or defaulting to a standard message     |
| Self-protection rule bypass via API                               | Admin disables own account, locks themselves out     | Server-side check preventing self-targeting on disable/delete endpoints |
