Admin UI¶
Next.js web portal for managing the entire GE platform. Rebuilt from scratch Feb 9 2026 (v2). The old admin-ui is preserved at admin-ui-old/ for reference.
Source: admin-ui/
Tech Stack¶
| Component | Version |
|---|---|
| Next.js | 16 |
| React | 19 |
| Tailwind CSS | 4 |
| Drizzle ORM | PostgreSQL |
| ioredis | Redis Streams |
| WebAuthn | YubiKey authentication |
Routes¶
| Route | Purpose |
|---|---|
/ |
Dashboard — system overview, agent activity |
/agents |
Agent list, status, provider config |
/agents/[id] |
Agent detail + chat |
/tasks |
Task management |
/queue |
Redis stream queue viewer |
/billing |
Billing overview |
/billing/consumption |
LLM consumption tracking |
/billing/budgets |
Budget management |
/billing/invoices |
Invoice generation |
/clients |
Client list |
/clients/[id] |
Client detail |
/projects |
Project management |
/discussions |
Multi-agent discussions |
/discussions/[id] |
Discussion thread |
/audit |
Audit log |
/stream |
Live Redis stream viewer |
/api-management |
API key management |
/infrastructure |
K8s cluster health |
/knowledge |
Knowledge patterns + learnings |
/inbox |
Human inbox (clarifications, approvals) |
/halt |
HALT flag management |
/login |
WebAuthn login |
Key Services¶
| Service | File | Purpose |
|---|---|---|
| TaskService | lib/services/task-service.ts |
Unified task mutations: DB insert + Redis XADD to triggers.{agent} |
| agent-bootstrap | lib/services/agent-bootstrap.ts |
Upserts agent data from AGENT-REGISTRY.json to DB |
| claude-chat | lib/ge-integration/claude-chat.ts |
Chat with agents: multi-provider (Claude/OpenAI), persisted to DB |
| agent-registry | lib/ge-integration/agent-registry.ts |
Read/write registry + config publish |
| k8s client | lib/k8s/client.ts |
K8s API for cluster health page |
Authentication¶
- Method: WebAuthn with YubiKey
- Flow:
/api/auth/challenge→ store challenge in httpOnly cookie →/api/auth/verify - Critical: Challenge MUST be in httpOnly cookie, NOT in response body (old code had
body.challengewhich was undefined)
API Tiers¶
| Tier | Prefix | Auth | Purpose |
|---|---|---|---|
| Public | /api/auth/* |
None | Login flow |
| Internal | /api/internal/* |
Bearer token | Agent-to-admin communication |
| Authenticated | /api/* |
WebAuthn session | Human UI operations |
K8s Deployment¶
- Namespace:
ge-system - HostPath volumes: Code directory, ge-ops directory, kubeconfig
- Note: kubectl + kubeconfig are mounted into the pod for the infrastructure page
- Access:
https://office.growing-europe.com(via Traefik)
Database¶
PostgreSQL with Drizzle ORM. Key tables:
agent_task— task state + Redis trigger trackingagents— agent config (provider, model, status)session_learnings— structured learnings from agent sessionsknowledge_patterns— cross-session patterns with confidence scoreswork_package_deps— DAG dependencies with swimming lanesdiscussions,discussion_messages— multi-agent discussion threads
Migrations: admin-ui/drizzle/migrations/
Critical Rules¶
- Never trigger agent execution directly from admin-ui — use TaskService which goes through Redis
- Never call Claude API from sync/data pipeline code — only from explicit chat endpoints
- Always use
onConflictDoUpdatefor upserts (not select-then-insert) - All XADD calls must include MAXLEN (~100 for per-agent, ~1000 for system)
- Never XADD to both
triggers.{agent}ANDge:work:incomingfor the same task