feat(admin-ui): scaffold + 7 screens + same-origin mount (phase 13.1)#59
Merged
Conversation
Lands the admin web UI per docs/admin-ui-design.md. Vite + React 18 +
TypeScript + Tailwind + TanStack Query, lives at apps/admin-ui/, ships
inside the production Docker image, mounted at /admin/* on the existing
MyPalace server. No CORS, no new endpoints, no extra service.
UI surface (v1):
- Login — admin key in sessionStorage, sent as X-Palace-Key on every
call. Closing the tab signs out. 401 from any API call clears the key
and bounces back to login.
- Health — backend-by-backend status from /ready, polling every 10s.
- Tenants — list / create / drop (with the same 409-data-present guard
the API enforces).
- Keys — list (with show-revoked toggle), mint (one-time plaintext
display, with the "save it now" warning), revoke.
- Stats — per-tenant or ALL with row counts, 7d activity, FSRS health,
top users.
- Audit — paginated browse with key_id / path_prefix filters and
status_class chips.
- Memories — read-only per-user browser (write paths stay on the API
for safety, per design §1).
Server side:
- mypalace/main.py grows _mount_admin_ui() — looks for the built bundle
at /app/static/admin (production image) or apps/admin-ui/dist (dev
tree). Mounts /admin/assets/* via StaticFiles and /admin/{full_path}
→ index.html for SPA routing. Logs at INFO if disabled (no bundle).
- mypalace/auth/scopes.py: /admin and /admin/* added to the public
allowlist so the page can render before login. /v1/admin/* still
requires the admin scope — tripwire test asserts this.
- Dockerfile: multi-stage build adds a node:24-alpine ui-build stage
that runs `npm install && npm run build`, copies dist/ into the
Python image at /app/static/admin/.
Tests:
- 13 vitest tests cover the auth-storage roundtrip and the request()
client (header injection, 401 → key wipe, query encoding, 204, JSON
body, error messages, key-preserved-on-403).
- 9 pytest tests cover the public-path classification (incl. the
tripwire that /v1/admin/* must NOT be public) and SPA index.html
serving.
- TypeScript strict + noUncheckedIndexedAccess on; tsc clean.
- Vite build: 232 KB JS / 71 KB gzipped. CSS 3.5 KB gzipped.
Server suite 587 passes (was 578; +9 new mount tests). Ruff clean.
Out of scope for this slice (per design):
- Personality / entity-alias screens (defer to v2).
- Memory editing / write paths (stay on the API).
- WebSocket event streaming.
- Light/dark theme toggle (just match prefers-color-scheme).
- E2E Playwright tests (re-evaluate once usage patterns settle).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lands the admin web UI per `docs/admin-ui-design.md` (PR #58). Vite + React 18 + TypeScript + Tailwind + TanStack Query, lives at `apps/admin-ui/`, ships inside the production Docker image, mounted at `/admin/*` on the existing MyPalace server. No CORS, no new endpoints, no extra service.
Surface (v1)
Server changes
Test plan
Out of scope (per design doc)
Personality / entity-alias screens, memory editing, WebSocket events, manual theme toggle, E2E Playwright. Re-evaluate v2 once usage patterns settle.
🤖 Generated with Claude Code