Skip to content

UX Persona Audit — 2026-03-25 23:02 #1355

@Dexploarer

Description

@Dexploarer

Audit timestamp: 2026-03-25 23:02
Git state: develop @ 78f620090 — pulled from origin/develop before this run
Latest commits:


Runtime Environment

Service Port Status Startup Time
API + WebSocket 31337 ✅ Running ~15s
Dashboard UI (Vite) 2138 ✅ Running ~15s

Environment Startup Log

Database shutting-down error observed during startup:

Unhandled rejection: Error: Database is shutting down - operation rejected
    at withDatabase (@elizaos/plugin-sql/dist/node/index.node.js:6841:25)

Server recovered after this error. Migrations completed successfully. UI stuck on "INITIALIZING ENTITY" indefinitely.


Issue Index

ID Severity Title
UX-1 P0 UI stuck on "INITIALIZING ENTITY" — chat unusable
SEC-1 P1 /api/config returns cloud API key without authentication
SEC-2 P1 /api/database/tables returns full DB schema without authentication
SEC-3 P2 /api/permissions leaks platform info (_shellEnabled) without auth
UX-2 P2 No loading timeout or error recovery — infinite spinner
UX-3 P2 Database "shutting down" unhandled rejection on startup
A11Y-1 P2 Header icon buttons (Companion/Character/Native mode) lack accessible labels
A11Y-2 P3 Loading spinner has no aria-live region for screen readers
UX-4 P3 Chat input enabled while entity still initializing — messages would fail silently

Per-Persona Findings

1. Alex (Solo Dev) — ⭐⭐⭐ (3/5)

Likes:

  • CLI and config system well-structured (~/.milady/milady.json)
  • Plugin auto-enable and NODE_PATH resolution documented and functional
  • Multiple token header formats supported (Bearer, X-Eliza-Token, X-Milady-Token, X-Api-Key, X-Api-Token)

Dislikes:

  • Entity initialization hangs indefinitely in dev mode — blocks iterating on agent config
  • Database "shutting down" error appears in logs with no user-facing explanation
  • /api/agents returns 404 — unclear how to list agents via API

Issues:

  • [UX-1/P0] UI stuck on "INITIALIZING ENTITY" — apps/app/src/main.tsx launches companion view, but the entity init call never resolves. Observed live: spinner and "INITIALIZING ENTITY" text persist indefinitely.
  • [UX-3/P2] Database "shutting down" unhandled rejection in @elizaos/plugin-sql — observed in /tmp/milady-audit-dev.log line with withDatabase at index.node.js:6841. Does not crash server but may cause entity init failures.

2. Maria (Non-Technical Creator) — ⭐⭐ (2/5)

Likes:

  • Clean, dark-themed UI with clear "New Chat" and "Voice" buttons
  • Language selector visible in header (currently EN with flag)
  • Cloud credits balance ($18.9) visible at a glance

Dislikes:

  • Cannot get past loading screen — "INITIALIZING ENTITY" blocks all interaction
  • No onboarding wizard visible despite onboardingComplete: true in config — unclear how a new user would create their first agent
  • Chat input appears clickable during loading but would fail silently

Issues:

  • [UX-1/P0] Same entity initialization hang — Maria cannot interact at all
  • [UX-2/P2] No timeout, retry button, or error message after loading stalls — infinite spinner with no escape hatch. Loading component needs a timeout (e.g. 30s) with actionable error message.
  • [UX-4/P3] Chat input textbox "Chat message" is enabled during loading — confirmed via accessibility tree (ref_26 has no disabled attribute)

3. Jordan (DevOps Engineer) — ⭐⭐⭐ (3/5)

Likes:

  • Port configuration well-documented with env overrides (MILADY_API_PORT, MILADY_PORT, etc.)
  • ELIZA_DEV_ONCHAIN=0 correctly disables Foundry/Anvil when not installed
  • Dev server starts cleanly with PID trackable for process management

Dislikes:

  • No health check endpoint — /api/agents returns 404, root returns {"error":"Not found"}
  • Database shutdown error in startup logs would trigger alerts in monitoring
  • No readiness probe pattern for container orchestration

Issues:

  • [UX-3/P2] Database "shutting down" unhandled rejection — would cause false-positive alerts in production monitoring. Needs proper error handling in @elizaos/plugin-sql.

4. Sam (Crypto-Native Power User) — ⭐⭐⭐ (3/5)

Likes:

  • Wallet key endpoint (/api/wallet/keys) properly gated behind ensureCompatSensitiveRouteAuthorized() at packages/app-core/src/api/server.ts:2419
  • Wallet keys endpoint disabled after onboarding via temporal check (line 2428-2432)
  • OS keystore integration (/api/wallet/os-store) requires sensitive route auth

Dislikes:

  • /api/wallet returns 404 — no wallet status endpoint available
  • /api/wallet/export returns 404 — wallet export flow unclear from API perspective

Issues:

  • No new wallet-specific issues beyond the general P0 loading hang.

5. Priya (Enterprise Evaluator) — ⭐⭐ (2/5)

Likes:

  • Timing-safe token comparison using crypto.timingSafeEqual() in packages/app-core/src/api/auth.ts:36-41
  • Security headers properly set: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, X-XSS-Protection: 1; mode=block at packages/agent/src/api/server.ts:6358-6361
  • Auth gate applied BEFORE CORS processing to prevent DNS rebinding (packages/agent/src/api/server.ts:5821-5824)
  • Sensitive routes properly wrapped with ensureCompatSensitiveRouteAuthorized()

Dislikes:

  • /api/config returns full configuration including cloud API key (eliza_baaf6c...) without any auth — confirmed via live curl returning HTTP 200 with full config JSON
  • /api/database/tables returns full database schema (all tables, columns, types) without auth — full schema enumeration
  • /api/permissions returns {"_platform":"darwin","_shellEnabled":true} without auth — platform info disclosure

Issues:

  • [SEC-1/P1] /api/config unauthenticated — returns cloud API key, agent config, plugin settings. Confirmed at packages/app-core/src/api/server.ts:3193. The route handler does not call any auth middleware. An attacker on the same network could steal the cloud API key.
  • [SEC-2/P1] /api/database/tables unauthenticated — returns full DB schema with all table names, column types, and constraints. Confirmed live: 24 tables exposed including agents, memories, embeddings, pairing_requests.
  • [SEC-3/P2] /api/permissions unauthenticated — exposes _platform (darwin) and _shellEnabled (true). Useful for targeted attacks.

6. Chen (Plugin Developer) — ⭐⭐⭐ (3/5)

Likes:

  • NODE_PATH correctly set in three required locations per CLAUDE.md
  • bun run setup:eliza-workspace for local Eliza development documented
  • Plugin auto-enable system with config schemas in packages/app-core/src/config/
  • 78 skills loaded successfully per startup logs

Dislikes:

  • Plugin load failures are silent — NODE_PATH setup could fail with unclear errors (packages/agent/src/runtime/eliza.ts:155-188)
  • /api/plugins endpoint is open (no auth) — leaks installed plugin list

Issues:

  • No new plugin-specific issues beyond general findings.

7. Riley (Mobile-First User) — ⭐⭐ (2/5)

Likes:

  • Chat input and send button are appropriately sized for touch targets
  • Bottom-anchored message bar pattern is mobile-friendly

Dislikes:

  • Header bar does not collapse at narrow viewports — all 7+ buttons remain in a single row
  • No hamburger menu or responsive navigation pattern detected
  • "INITIALIZING ENTITY" loading state blocks all mobile interaction

Issues:

  • [UX-1/P0] Loading hang blocks all mobile interaction
  • [UX-2/P2] No responsive breakpoint for header navigation — buttons would overflow on small screens

8. Taylor (Accessibility User) — ⭐⭐ (2/5)

Likes:

  • Chat input has proper textbox role with placeholder="Type a message..." label
  • Buttons have text content for screen readers (e.g. "New Chat", "Agent voice on", "Toggle theme")
  • Page has banner, complementary, and region landmarks for navigation

Dislikes:

  • Mode toggle buttons (Companion/Character Edit/Native) identified as generic button with text but wrapped in a generic "Switch shell view" container with no role="tablist" or aria-selected
  • Loading state has no aria-live="polite" region — screen reader won't announce "INITIALIZING ENTITY" status changes
  • File upload button (ref_24) has no accessible label — just button with type="file"

Issues:

  • [A11Y-1/P2] Mode toggle lacks ARIA tab pattern — ref_4, ref_5, ref_6 are buttons inside ref_2 (generic div). Should use role="tablist" with aria-selected on the active tab.
  • [A11Y-2/P3] Loading spinner lacks aria-live — the "LOADING..." / "INITIALIZING ENTITY" text is not in an aria-live region so screen readers won't announce state changes.
  • File upload button (ref_24) has no label — needs aria-label="Attach file" or similar.

9. Jamie (Multi-Platform User) — ⭐⭐⭐ (3/5)

Likes:

  • Connectors endpoint (/api/connectors) properly returns connector status
  • Platform connector architecture in packages/app-core/src/connectors/
  • WebSocket broadcast callback wired for real-time sync per startup logs

Dislikes:

  • No connectors currently enabled (/api/connectors returns {"connectors":{}}) — unclear how to enable Telegram/Discord from UI
  • Loading hang prevents testing multi-platform chat sync

Issues:

  • No new platform-specific issues beyond general findings.

10. Casey (First-Time Visitor) — ⭐ (1/5)

Likes:

  • Dark theme is visually appealing
  • Layout is clean and uncluttered

Dislikes:

  • App immediately goes to companion view with infinite loading spinner — zero context for what's happening
  • No welcome message, tutorial, or explanation of what Milady is
  • "INITIALIZING ENTITY" provides no actionable information to a new user
  • Chat input is enabled but nonfunctional during loading — sending a message would fail with no feedback
  • No error recovery path — no "Try Again" button, no settings link, no help text

Issues:

  • [UX-1/P0] Critical first impression failure — new user sees infinite spinner with no escape
  • [UX-2/P2] No timeout or error recovery UI
  • [UX-4/P3] Misleading enabled chat input during loading

Confirmed Non-Issues

Area What Was Checked Result
Auth on sensitive routes /api/wallet/keys, /api/wallet/os-store, /api/agent/reset ✅ All gated behind ensureCompatSensitiveRouteAuthorized()
Token comparison Timing-safe comparison ✅ Uses crypto.timingSafeEqual()
Security headers X-Content-Type-Options, X-Frame-Options, X-XSS-Protection ✅ All set correctly
DNS rebinding Auth checked before CORS ✅ Implemented at packages/agent/src/api/server.ts:5821-5824
Deep link validation validateAndSetApiBase() ✅ Blocks public IPs over HTTP, validates localhost/loopback
Null origin file:// origin handling ✅ Requires explicit ELIZA_ALLOW_NULL_ORIGIN=1 flag
Plugin migrations SQL migration system ✅ Both @elizaos/plugin-sql and @elizaos/plugin-todo migrated successfully

Prioritized Fix Checklist

P0 — Critical

  • UX-1: Fix entity initialization hang — investigate why "INITIALIZING ENTITY" never resolves in dev mode. Check if the database "shutting down" error causes entity creation to fail silently.

P1 — High

  • SEC-1: Add auth middleware to /api/config route at packages/app-core/src/api/server.ts:3193 — this endpoint returns the cloud API key unauthenticated
  • SEC-2: Add auth middleware to /api/database/tables route — full schema exposure is an information disclosure risk

P2 — Medium

  • SEC-3: Add auth to /api/permissions endpoint — platform info leakage
  • UX-2: Add loading timeout (30s) with retry button and error message to the loading/initializing component
  • UX-3: Handle database "shutting down" error gracefully in @elizaos/plugin-sql — add retry logic or surface error to UI
  • A11Y-1: Add role="tablist" and aria-selected to mode toggle buttons

P3 — Low

  • A11Y-2: Add aria-live="polite" to loading status region
  • UX-4: Disable chat input (textbox "Chat message") while entity is initializing
  • Add aria-label="Attach file" to the unlabeled file upload button

Positive Security Findings (Do-Not-Regress)

  1. Timing-safe token comparisoncrypto.timingSafeEqual() in packages/app-core/src/api/auth.ts:36-41
  2. Auth before CORS — DNS rebinding prevention at packages/agent/src/api/server.ts:5821-5824
  3. Security headers — nosniff, DENY, XSS protection at packages/agent/src/api/server.ts:6358-6361
  4. Sensitive route protection — wallet, agent reset, plugin mutation endpoints all gated
  5. Deep link URL validationvalidateAndSetApiBase() in apps/app/src/main.tsx:243-280 blocks unsafe origins
  6. Null origin protection — requires explicit ELIZA_ALLOW_NULL_ORIGIN=1 for file:// origins
  7. Wallet key temporal gating/api/wallet/keys disabled after onboarding at packages/app-core/src/api/server.ts:2428-2432
  8. Referrer policystrict-origin-when-cross-origin at packages/agent/src/api/server.ts:5954

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions