Admin Dashboard - Z-M-Huang/openhive GitHub Wiki

Admin Dashboard

Operator dashboard for observing OpenHive system state. The agent acts; the dashboard observes. Purpose-built views over the SQLite data model -- not a SQL browser, not a config editor.

See Architecture for system overview, Architecture-Decisions#ADR-31 for rationale, and Scenarios#14 for an operational walkthrough.


Table of Contents


Overview

The admin dashboard is an observability-first operator tool served from the same Docker container as the main process. It provides consolidated views of system health, org structure, task queues, logs, memories, triggers, conversation history, and plugin tool state -- everything an operator needs to diagnose issues without running SQLite queries.

The only dashboard-initiated mutations are trigger enable/disable toggling and plugin tool lifecycle actions (deprecate/remove). All other mutations go through the agent via normal channels.

Access model: Local-only. No authentication. For remote access, front the dashboard with a reverse proxy that provides auth (Traefik, Cloudflare Tunnel, or similar).


Technology Stack

Aspect Choice Rationale
Frontend Vanilla HTML/CSS/JS No React, no Vue, no build step, no npm on frontend
Serving Fastify via @fastify/static Serves /app/public/ directory; no companion container
API REST under /api/v1 JSON responses; reuses existing SQLite data access layer
Container Same Docker container No additional infrastructure; dashboard is a static asset
Auth None Local-only tool; reverse proxy for remote access

Zero frontend build toolchain. Files in /app/public/ are served as-is. The API routes import existing store instances from OrgToolContext -- no new data access code beyond query composition.


REST API Endpoints

All endpoints are mounted under /api/v1. Responses are JSON. The API is read-only except for trigger state toggling and plugin tool lifecycle actions (deprecate/remove).

Endpoint Method Purpose
/api/v1/overview GET Health + aggregated stats (uptime, SQLite size, team count, queue depth)
/api/v1/teams GET Org tree with aggregated stats per team
/api/v1/teams/:name GET Single team detail (config, scope, queue, active sessions)
/api/v1/tasks GET Paginated tasks (team, status, type, limit, offset query params)
/api/v1/tasks/:id GET Single task detail
/api/v1/tasks/stats GET Counts by status, type, and priority
/api/v1/logs GET Paginated log entries (level, team, since, search, limit query params)
/api/v1/memories GET Paginated memories (team, type, search, limit query params)
/api/v1/memories/:id/chain GET Supersede chain for a memory (full lineage)
/api/v1/triggers GET All triggers (team, state filters)
/api/v1/triggers/:id/enable POST Enable a trigger (pending/disabled -> active)
/api/v1/triggers/:id/disable POST Disable a trigger (active -> disabled)
/api/v1/topics GET Conversation topics (state filter)
/api/v1/interactions GET Message history (channel, team, limit query params)
/api/v1/vault GET Vault entries for a team (team required; returns keys + metadata, values NEVER shown for is_secret=1)
/api/v1/vault/:team/:key GET Single vault entry detail (value shown for is_secret=0 only; is_secret=1 returns key + metadata, no value)
/api/v1/learning GET Learning status summary (team filter; journal summary, last run, topic coverage)
/api/v1/learning/:team/journal GET Full learning journal for a team (topic_coverage, sessions_completed, sources_visited, deprioritized_sources)

Query patterns: Pagination uses limit + offset. Filtering uses query parameters. All endpoints return { data, total?, error? } envelopes.

| /api/v1/trust/audit | GET | Trust audit log (since, decision, limit filters) |

Plugin Tool Management Endpoints

Plugin tool lifecycle and security audit endpoints:

Endpoint Method Purpose
/api/v1/tools GET List all plugin tools across teams (team filter optional)
/api/v1/tools/:team/:name GET Single tool detail (source code, verification status, security scan results)
/api/v1/tools/:team/:name/deprecate POST Mark tool as deprecated (prevents new sessions from loading)
/api/v1/tools/:team/:name/remove POST Delete tool file (requires deprecated status first)
/api/v1/tools/audit GET Recent tool invocations, blocked attempts, security violations

/api/v1/tools and /api/v1/tools/:team/:name read lifecycle state and verification summaries from the SQLite plugin_tools table, then join source code from .run/teams/{team}/plugins/{name}.ts. deprecate updates the SQLite row to deprecated; remove deletes the file and archives the metadata row (status set to removed, row preserved for audit trail).

Tool listing response returns an array of tool objects, each containing the team name, tool name, namespaced name, file path, lifecycle status, verification summary, creation/verification timestamps, and 24-hour invocation count. Tool detail response extends the listing fields with the full source code, granular verification results (TypeScript validity, interface compliance, security scan findings), the list of skills that declare the tool, and the last invocation timestamp. In both responses, status and verification come from persisted SQLite metadata; source_code (in detail responses) comes from the plugin file on disk.

Vault API security note: The /api/v1/vault and /api/v1/vault/:team/:key endpoints NEVER return the value field for entries where is_secret=1. Not even masked. The response includes key, is_secret, updated_by, created_at, and updated_at -- but the value is omitted entirely. This matches the vault_list tool behavior (see Organization-Tools).


Dashboard Views

Ten views ship in v1. Each corresponds to a primary data domain and one or more API endpoints.

1. System Health Overview

Aggregated system state at a glance.

  • Uptime, SQLite database size, total team count
  • Queue backlogs (pending/running tasks across all teams)
  • Trigger health (active count, recent failures, circuit-breaker trips)
  • Auto-refreshes on a configurable interval

2. Live Org Tree

Visual hierarchy of the team structure.

  • Tree rendering of parent-child relationships from OrgStore
  • Per-node: team status, queue depth, scope keywords
  • Expand/collapse with drill-down to team detail

3. Task Queue Dashboard

Operational view of the task pipeline.

  • Pending, running, done, failed, and cancelled tasks
  • Filters: team, task type, priority, status
  • Sortable columns with pagination
  • Task detail on click (full task record, delegator, result)

4. Log Viewer

Structured log search over the log_entries table.

  • Filters: level, team, time range, free-text search
  • Expanded view shows full context JSON (team, taskId, tool name, duration)
  • Level-based color coding (error = red, warn = amber, info = neutral)

5. Memory Browser

Browse and inspect the memory system.

  • Filter by team and memory type (identity, lesson, decision, context, reference, historical)
  • View supersede chains: select a memory, see its full lineage via /memories/:id/chain
  • Badges distinguish injected types (identity, lesson, decision, context) from search-only types (reference, historical)

6. Trigger Manager

View and manage trigger state machines.

  • All triggers with current state (pending, active, disabled), type, failure count
  • Filter by team and state
  • Enable/disable toggles
  • Failure count and circuit-breaker status visible per trigger
  • Overlap policy per trigger (skip-then-replace, always-skip, always-replace, allow)
  • Overlap count: current consecutive overlap counter (0 = normal, 1+ = has been skipped)
  • Active task ID: links to task queue entry when a triggered task is pending or running
  • Visual badge when a trigger is in "overlap skipped" state (overlap_count > 0)

7. Conversation History

Message flow and topic lifecycle.

  • Inbound and outbound messages with timestamps
  • Topic states (active, idle, done) with filter
  • Channel activity breakdown (WebSocket, Discord)

The Trust Audit Viewer for the trust_audit_log table is accessible via /api/v1/trust/audit.

8. Vault Browser

Browse team vault entries with enforced secret protection.

  • Filter by team name
  • Displays all vault keys with metadata: key, is_secret, updated_by, created_at, updated_at
  • Values shown for is_secret=0 entries (team state data)
  • Values NEVER shown for is_secret=1 entries -- not even masked. The value column is omitted entirely for secret rows. This is a hard security boundary: the dashboard never requests, receives, or displays secret values
  • Badge distinguishes secret entries (locked icon) from state entries
  • Click-through to single entry detail via /api/v1/vault/:team/:key

9. Learning Status

Monitor autonomous learning cycle progression. Learning triggers are per subagent (ADR-40), not per team — the dashboard aggregates across subagents within a team.

  • Filter by team name, then by subagent
  • Trigger state per subagent: displays whether learning-cycle-{subagent} is active or disabled (matches trigger manager state)
  • Summary panel per subagent: sessions_completed, last_run timestamp, total findings stored across all topics
  • Topic coverage table: one row per learning topic showing last_searched, searches_completed, findings_stored, findings_discarded, consecutive_no_findings, next_focus (if set)
  • Corroboration confidence per finding: displays corroboration count and confidence level (single/partial/corroborated)
  • Exhausted topics visually flagged (dimmed row, "exhausted" badge when consecutive_no_findings >= 3)
  • Deprioritized sources: count displayed in summary panel; expandable list showing URL, reason, and since timestamp
  • Sources visited expandable per topic: URL, last_fetched, yielded_finding status
  • Per-subagent readiness gate status: displays whether each gate (tool bundle, bootstrapped=1, scope_keywords) is satisfied or blocking. See Architecture-Decisions#ADR-35
  • Click-through to full journal via /api/v1/vault/:team/learning:{team}:{subagent}:journal

Reflection Status

  • Trigger state per subagent: reflection-cycle-{subagent} active or disabled
  • Last reflection run: timestamp, diagnosis summary, outcome (change applied / skipped)
  • Reflection journal viewer: click-through to vault journal via /api/v1/vault/:team/reflection:{team}:{subagent}:journal
  • See Architecture-Decisions#ADR-37

Stall Detection Monitor

  • Pending task counts exceeding thresholds (>1 hr warning, >24 hr error)
  • Stalled task table: task ID, team, age, severity, last status change
  • Escalation history: recent stall detection alerts with resolution status
  • Stall detection is engine-level infrastructure, not a managed trigger. It does not appear in the Trigger Manager panel.
  • See Architecture-Decisions#ADR-38

10. Plugin Tools Manager

View and manage team-local plugin tools.

  • Filter by team name
  • List all plugin tools with namespaced name, verification status, invocation count
  • Status indicators: active, deprecated, failed verification
  • Click-through to tool detail: source code, verification results, security scan
  • Lifecycle state and verification badges are sourced from the SQLite plugin_tools table; source code is read from the team plugin directory
  • Lifecycle actions:
    • Deprecate — marks tool as deprecated, prevents new sessions from loading it
    • Remove — deletes tool file (requires deprecated status first)
  • Security audit view: recent invocations, blocked attempts, forbidden pattern detections
  • Skills using each tool: shows which skills declare the tool in ## Required Tools

Frontend File Structure

The frontend follows a single-page architecture rooted in public/. The SPA shell (index.html) loads a single stylesheet and a hash-based router (app.js). Ten view modules (health.js, org-tree.js, tasks.js, logs.js, memories.js, triggers.js, conversations.js, vault.js, learning.js, plugin-tools.js) each export a render(container) function called by the router. Shared components include a sortable table, tree renderer, filter bar, and toast notifications. Hash-based routing (#/health, #/tasks, etc.) means no server-side routing is required.


Visual Design

Premium dark theme with glassmorphism aesthetics. No external CSS frameworks -- hand-crafted CSS.

Property Value
Theme Dark with CSS custom properties for theming
Cards Glassmorphism: backdrop-filter: blur(), semi-transparent backgrounds
Animations Smooth transitions on view changes and data refresh
Typography Monospace accent font for data and metrics
Status indicators Glow effects color-coded by state
Layout Responsive, optimized for tablet monitoring

All visual tokens are CSS custom properties, making it straightforward to add a light theme or adjust branding without touching component code.


Deliberately Excluded from v1

Exclusion Reason
Rule/config editing Too dangerous without a governance UI; agents manage rules through normal channels
Raw SQL browser Structured views cover 95% of operator needs; raw SQL risks accidental mutations
Team creation/deletion Should go through the agent for governance enforcement
Build toolchain Zero npm on frontend; files served as-is
Authentication Local-only tool; reverse proxy for remote access

These are intentional scope boundaries, not missing features. Each was evaluated and deferred to avoid scope creep and security surface area.


Cross-References