Delete directory 'docs/superpowers'
Local Build and Deploy / deploy (push) Successful in 1m11s

This commit is contained in:
Simo committed 2026-07-17 21:26:05 +02:00
1 parent f6871807c9
commit e7a6587b7f
14 files changed
-1045

No files matched your search

@@ -1,33 +0,0 @@
# ACL and import backend design
## Goal
Complete the administration ACL management and make every existing asset-import page functional end to end.
## ACL architecture
`acl_permissions`, `acl_roles`, `acl_model_permissions`, and `acl_model_roles` are the only CMS authorization source. Emulator ranks remain in `permission_ranks`; each rank maps to the CMS role `rank_<id>`. Legacy `website_permissions` and `website_housekeeping_permissions` may be migrated but are not written by the new management flow.
The permissions screen manages emulator ranks, rank roles, role permission assignments, and direct user roles/permissions. Rank creation, editing, and deletion use the emulator rank service, refresh RCON permissions, invalidate the permission cache, and log staff activity. Every mutation requires `admin.permissions.manage` and fails closed.
## Import authorization
All import pages and every `/api/admin/import/**` handler require `admin.assets.import`. Catalog deletion or repair operations that mutate catalog data additionally require `admin.catalog.edit`. Page-level checks are navigation guards only; API handlers repeat authorization before reading remote sources, writing the database, or writing files.
## Import pipeline
Port the reference import core, services, API routes, and tests for badges, clone, clothing, effects, furni, pets, and repair. Adapt imports to EpicNext's generated Prisma names and locale-free routes. Do not copy generated Prisma files.
The furni success boundary is atomic at the workflow level: verify database rows, repository asset output, configured live Nitro asset output, and `FurnitureData.json`. External Windows paths use the existing cross-platform resolver. Repair/audit reports partial state instead of treating a database insert as success.
## Migration
Add an idempotent migration that seeds `admin.assets.import`, normalizes ACL discriminator casing to `Role` and `User`, creates missing `rank_<id>` roles, migrates compatible legacy permission assignments, and grants the highest rank explicit management/import permissions. Dynamic highest-rank bypass remains an emergency compatibility path, not the persisted assignment model.
## Error handling and verification
Remote download errors, invalid archives/data, filesystem failures, schema mismatches, and partial writes return structured errors and are logged without exposing secrets. Contract tests assert route coverage and server-side ACL guards. Service tests cover path resolution, batch behavior, data reconciliation, and fail-closed authorization. Final verification runs all tests, TypeScript, and the production build.
## Scope boundary
This block does not add moderation, analytics, detailed logs, or DevOps pages. Those remain the next phase after ACL and imports are verified.
@@ -1,46 +0,0 @@
# Admin events, polls, banners, and prefixes design
## Goal
Port the complete events, CMS polls, banners, and user-prefix administration modules from `habbo-next` into EpicNext without duplicating existing features or changing emulator-owned data.
## Compatibility boundary
EpicNext keeps its existing legacy `polls`, `polls_questions`, and `polls_answers` models untouched. The imported module uses independent `website_polls`, `website_poll_questions`, and `website_poll_votes` tables.
Events use dedicated `website_event_*` tables. Banners use `website_banners`. Prefixes use `user_prefixes` plus their configuration/blacklist tables. Every new table is CMS-owned and introduced through an idempotent versioned migration compatible with the existing migration runner.
## Application architecture
Each module is a complete vertical slice:
- Prisma models map the CMS tables and relations.
- Zod validators define action inputs for events and polls.
- Server actions use EpicNext's existing `adminAction`, audit logging, and ACL helpers.
- Pages live under `/admin/events`, `/admin/polls`, `/admin/banners`, and `/admin/prefixes` without `[locale]` routing.
- Components use EpicNext semantic theme variables and existing admin primitives.
- Navigation exposes modules only through the existing staff guard.
No direct copy retains `habbo-next` locale parameters, route prefixes, or repository-specific imports.
## Permissions
The canonical permission list gains view/edit pairs for events, polls, banners, and prefixes. The ACL seed migration inserts the new slugs idempotently. Existing highest-rank super-admin behavior remains unchanged. Administrator fallback grants view permissions only; edit permissions remain explicit except for the dynamic super-admin.
## Migration and deployment
One numbered migration creates the CMS tables, indexes, foreign keys where safe, and ACL permission rows. It never drops or renames emulator tables. Prisma generation runs after migration through the existing deploy workflow.
## Failure behavior
Actions validate input, fail closed on missing permissions, log administrative mutations, and return the existing safe-action result shape. Pages handle missing records with `notFound()` and empty tables with themed empty states.
## Verification
- migration contract and idempotency tests;
- schema contract tests for every new mapped table;
- validator tests for invalid dates, statuses, and poll questions;
- action permission/import contract tests;
- route existence and locale-free import audit;
- targeted module tests, complete test suite, typecheck, Prisma generation, and production build;
- final Git audit excludes the local `package.json` modification.
@@ -1,47 +0,0 @@
# Admin operations design
## Goal
Add complete administration verticals for moderation and calls for help, detailed logs, analytics, DevOps, and online users. Each vertical includes its data source, mutations or API handlers, ACL enforcement, themed UI, and tests.
## Delivery order
1. Moderation dashboard, actions, CFH list/detail, and moderation team.
2. Audit, chat, command, and trade logs.
3. Analytics overview, activity, economy, and export.
4. DevOps overview/errors/health and online users.
Each group must compile and pass its focused contract before the next group begins.
## Data architecture
Use existing emulator and CMS tables where they already contain the required data. Queries must adapt to EpicNext's Prisma model names and live-schema conventions; generated Prisma files are never copied. When a reference page assumes a column absent from EpicNext, use a compatible projection or raw query rather than changing the emulator schema without evidence.
Moderation reads support CFH topics/categories, bans, users, and staff ranks. Mutations validate target identity and duration, call the emulator/RCON only after authorization, and write staff audit activity. Log pages are read-only and paginate/filter server-side. Analytics aggregates database data and exports only fields already visible to the authorized administrator. DevOps health exposes non-secret operational state and never returns credentials, connection strings, or raw environment variables.
## Authorization
Page guards and server-side actions/API handlers use:
- `admin.moderation.view` and `admin.moderation.edit`
- `admin.logs.view`
- `admin.analytics.view` and `admin.analytics.export`
- `admin.devops.view` and `admin.devops.edit`
Online-user administration uses `admin.users.view`; any mutation additionally requires its specific user/moderation permission. Authorization fails closed, and denied or failed privileged operations are logged.
## UI and theme
All new routes are locale-free under `/admin`. Components use the semantic `--admin-*` palette and existing shared admin components. Status colors use semantic admin status tokens; no public structural theme variables or hard-coded palette utilities are introduced.
## Error handling
Missing optional emulator tables produce an explicit unavailable/empty state rather than crashing the entire admin panel. Invalid filters return validation errors. RCON failures are reported separately from successful database changes, and destructive moderation actions never report success when the emulator operation fails.
## Verification
Contract tests assert route presence, ACL guards, and source-theme compliance. Focused tests cover moderation validation, log filters, analytics export authorization, and DevOps response redaction. Final verification runs every test, TypeScript, migration contracts, and the production build.
## Scope boundary
This block does not add public feed, forum, social, finance, betting, album/gallery, staff-login, PIN, or security pages. Those remain later public-facing phases.
@@ -1,31 +0,0 @@
# Admin theme isolation
## Objective
Keep every administration page readable and visually coherent in light and dark mode, independently of the public website palette. The audit covers the whole `/admin` tree, including every `/admin/import/*` workflow.
## Root cause
Administration components currently consume public theme variables such as `--color-primary`, `--color-background`, `--color-text`, and `--color-navbar`. A valid public preset can therefore produce poor contrast in the administration panel. A smaller set of pages also contains literal Tailwind colors, hexadecimal colors, and fixed overlays.
## Design
Define a semantic admin palette under the admin layout using `--admin-*` variables. Derive accessible foregrounds for light and dark surfaces, then migrate administration components and shared admin CSS to these semantic variables. Public pages continue using the existing public palette.
Admin colors represent roles rather than specific hues: canvas, surface, elevated surface, text, muted text, border, accent, accent foreground, success, warning, error, info, sidebar, input, overlay, and focus ring. Presets may influence the admin accent, but may not override readable foregrounds or structural surfaces with unsafe combinations.
## Import pages
The same rules apply to badge, clone, clothing, effects, furni, pets, and repair imports. Status text, selection state, borders, shadows, gradients, tooltips, dialogs, and overlays use admin semantic tokens. Colors that are part of imported content or asset previews remain unchanged because they represent data rather than interface chrome.
## Intentional color values
Literal values remain allowed only for user-editable data and faithful previews, including banner colors, prefix colors, favicon generation, event-type colors, tag/team configuration, and image-preview backdrops where a neutral checker or black canvas is required. Each exception must be explicit in the audit test.
## Verification
Extend the admin source audit so it fails when an administration UI introduces public structural theme variables, unapproved literal colors, or unapproved palette utilities. Run the focused audit test, all tests, TypeScript checking, and the production build. Manually inspect representative light and dark pages, including one dense import workflow and one modal.
## Scope boundary
This change does not port missing routes or alter database behavior. After theme isolation is complete, the next route-porting block is moderation, detailed logs, analytics, and DevOps.
@@ -1,76 +0,0 @@
# EpicNext multitheme design
## Goal
Make every built-in EpicNext preset visually complete in both light and dark mode. The administrator selects the global preset; each visitor may independently choose its light or dark variant without replacing the selected palette with a generic hardcoded theme.
The CMS information popup is rebranded from AtomCMS to EpicNext as part of the same visual consistency update.
## Current problem
The application currently combines two unrelated systems:
- `ThemeVars` injects database-controlled colors into `:root`.
- `html.dark` in `globals.css` replaces many of those colors with one hardcoded dark palette.
Consequently, every preset loses its identity in dark mode. Presets also define only a subset of the colors accepted by the theme editor, so values such as secondary buttons, danger buttons, outline buttons, links, and gradients can leak from the previously selected preset.
## Theme model
Each built-in preset will expose two complete variants:
```ts
type ThemeMode = "light" | "dark";
type ThemePalette = Record<ThemeColorKey, string>;
type ThemePreset = Record<ThemeMode, ThemePalette>;
```
`ThemeColorKey` is the single canonical list shared by presets, the admin form, persistence, runtime CSS generation, and tests. It includes all color values used by the editor and `ThemeVars`, including semantic colors, every button family, links, borders, and gradients.
The administrator-selected preset remains global. The visitor preference stored in `localStorage` remains only `light` or `dark`.
## Runtime flow
1. The administrator applies a preset.
2. Both complete variants are persisted using mode-qualified setting keys.
3. `ThemeVars` reads both variants and emits variables for `:root` and `html.dark`.
4. The pre-paint initialization script applies the visitor's saved mode, or the configured default mode.
5. The browser changes mode by toggling the existing `dark` class. It does not replace the preset.
The hardcoded palette currently declared in `html.dark` will be reduced to non-color behavioral rules. All dark-mode colors will come from the active preset.
## Custom themes
The admin editor will display light and dark sections. Saving updates both variants as one operation. Existing unqualified settings remain the source for the initial light variant so current installations retain their configured appearance.
For installations without dark-specific settings, EpicNext will use the selected preset's dark variant. This provides a deterministic migration path without trying to generate unreliable dark colors at request time.
Applying a preset writes every canonical color key for both modes. This prevents values from an earlier preset leaking into the newly selected one.
## Contrast and fallback behavior
Readable foreground variables continue to be derived independently for each mode. Invalid custom color input is rejected by the existing sanitizer. Missing keys fall back to the corresponding complete built-in palette, never to values from another preset.
## EpicNext popup
The footer trigger and popup copy will use EpicNext branding:
- `EpicNext Info` trigger
- `EpicNext` title
- `Modern Next.js CMS` badge
- EpicNext-focused description and credits
The popup continues to use semantic CSS variables, so it follows both variants of every preset.
## Verification
Automated tests will verify:
- every preset supplies every canonical key in both modes;
- every foreground/background semantic pair meets the existing contrast requirement;
- applying one preset cannot retain keys from another preset;
- runtime CSS contains separate light and dark values;
- the mode toggle only changes mode and preserves the active preset;
- the EpicNext popup renders its new branding.
Build, typecheck, and the complete test suite are required before publication.
@@ -1,46 +0,0 @@
# EpicNext semantic theme contrast design
## Goal
Guarantee readable text and controls across every built-in light/dark preset, including the complete admin panel, without flattening intentional status colors or graphical previews.
## Root cause
EpicNext calculates readable foregrounds for a limited set of theme values, while admin pages still contain hundreds of fixed Tailwind colors and raw hex values. Fixed gray, white, green, red, amber, and blue classes cannot adapt to arbitrary preset surfaces. The result is low-contrast or invisible copy when a preset changes luminosity.
## Semantic token contract
Runtime theme generation will expose adaptive tokens for:
- normal, muted, subtle, and disabled text;
- surface, elevated surface, dropdown, input, and overlay content;
- admin sidebar background, text, muted text, active item, and border;
- success, warning, error, and info foregrounds on page surfaces;
- success, warning, error, and info foregrounds on solid semantic backgrounds;
- subtle semantic backgrounds and borders for badges, notices, and statuses.
Every token is derived independently for light and dark mode from the active complete preset. Readable foregrounds must meet WCAG AA 4.5:1 for normal text. Decorative borders and non-text graphics are not forced to meet text contrast.
## Component migration
Admin components will use semantic utilities instead of palette-specific Tailwind colors. The migration covers layout, navigation, tables, forms, notices, badges, statuses, and action feedback across `src/app/admin` and `src/components/admin`.
Intentional graphical colors remain local in favicon/image previews, catalog artwork, color pickers, and user-authored preview content. These exceptions must be explicit and are not used for ordinary text.
The admin sidebar will stop using a fixed purple/black palette and will consume dedicated sidebar tokens. Public components touched by the audit will use the same semantic text and status tokens.
## CSS architecture
`theme-css.ts` remains the single runtime generator. It will emit semantic variables for each palette. `globals.css` will define reusable semantic classes for text hierarchy, notices, badges, tables, inputs, and admin navigation. Component code will select meaning (`success`, `muted`, `warning`) rather than a concrete color.
No global override of arbitrary Tailwind utility classes will be introduced because that would make third-party and graphical components unpredictable.
## Verification
Automated verification will include:
- contrast tests for every semantic foreground/background pair in every preset and mode;
- contract tests requiring every runtime semantic variable;
- a source audit that rejects new risky hard-coded text/background combinations in admin UI outside an explicit graphical allowlist;
- complete test suite, typecheck, and production build;
- a final diff audit ensuring the existing local `package.json` change is not staged.
@@ -1,155 +0,0 @@
# Admin UX Cleanup — Design Spec
**Date:** 2026-07-17
**Status:** Approved in chat (Phase 1); Phases 2–3 queued after Phase 1 ships
**Scope:** Admin panel (`/admin/*`) — EpicNext-cms
## Context
The admin already has hub chrome (`AdminHubChrome` + `AdminPageShell` + `AdminSectionTabs`), a condensed sidebar, theme/language switchers, and ACL. Remaining pain is inconsistency: double headers, orphan routes, duplicated chrome controls, crowded Radio tabs, and identical icons for Access vs Moderation.
This document covers a **three-phase** program. **Only Phase 1 is in scope for the next implementation plan.**
---
## Goals
1. One clear page hierarchy under each hub (no stacked titles).
2. Every useful admin route reachable from hub tabs (no orphan pages).
3. Theme/language controls in one primary place (no desktop duplicate).
4. Radio hub usable on smaller widths without losing URLs.
5. Access vs Moderation visually distinct in the sidebar.
## Non-goals (Phase 1)
- Full admin i18n (Phase 2).
- Full design-token / shadcn unification (Phase 3).
- New features, new pages, or permission model changes.
- Changing public-site chrome or avatar/imager behavior.
---
## Phase 1 — UX cleanup
### 1.1 Single hub header
**Current:** `AdminHubChrome` renders hub `title` + `subtitle` + tabs; many child pages also render `h1` / intro copy (often `text-3xl font-bold`), producing double titles.
**Rule:**
| Page type | Hub shell title | Page-level `h1` |
|-----------|-----------------|-----------------|
| Hub list / overview (matches a hub tab) | Keep | Remove (or demote to section heading if needed for a11y only when content blocks require it) |
| Nested create / edit / show (`…/new`, `…/[id]`, `…/create`, `…/show/[id]`) | Keep hub title | Keep entity-specific title (e.g. poll name, “Create Event”) |
| Dashboard `/admin` (no hub) | N/A | Keep its own header |
**Implementation approach:**
- Prefer removing redundant page chrome blocks (icon + `h1` + muted description that duplicates hub subtitle).
- Keep action rows (Create buttons, filters, search) that sit next to the old `h1`; restructure to a toolbar without a second page title.
- Do not strip semantic headings inside content cards/tables.
**Acceptance:** Opening any hub tab shows exactly one primary title (from `AdminPageShell`). Detail pages still show the entity/create title below the hub chrome.
### 1.2 Wire orphan routes into hub tabs
Add tabs (English labels for Phase 1; i18n keys in Phase 2):
| Hub | New / adjusted tabs | Hrefs |
|-----|---------------------|-------|
| **Users** | Multi-accounts | `/admin/users/multi-accounts` |
| **Engagement** | Event types, Templates | `/admin/events/types`, `/admin/tickets/templates` |
| **Observability** | Chat, Commands, Trades | `/admin/logs/chat`, `/admin/logs/commands`, `/admin/logs/trades` |
| **Observability** | Activity, Economy (under analytics) | `/admin/analytics/activity`, `/admin/analytics/economy` |
| **Observability** | Errors (under devops) | `/admin/devops/errors` |
**Tab matching notes:**
- Users “Directory” must keep `match` that includes `/admin/users` but **not** steal active state from `/admin/users/multi-accounts` (exact / longest-prefix matching already in `AdminSectionTabs` — verify Directory `match` does not list multi-accounts; multi-accounts gets its own tab with `href` only or explicit `match`).
- Logs “Logs” tab (`/admin/logs`) must not stay active on `/admin/logs/chat` etc. Prefer exact match for the main Logs index, or give sub-log tabs longer prefixes so they win (existing scorer prefers longer / exact — verify).
- Analytics “Analytics” vs Activity/Economy: same longest-match rule.
- Engagement Event types: `/admin/events/types` must win over Events `match: ["/admin/events"]` — longest prefix already favors `/admin/events/types` if that tab is listed.
**Acceptance:** Every orphan page above is one click from its hub tab strip. No new routes required.
### 1.3 Theme / language control placement
**Decision:** Primary controls stay in the **sidebar** (desktop). **Topbar** keeps theme + language only on **mobile** (when the sidebar is not persistently visible), or remove from topbar entirely if `AdminMobileWrapper` already exposes sidebar controls on mobile.
**Preferred behavior:**
- Desktop (`lg+`): switchers **only in sidebar** header row; remove from `Topbar`.
- Mobile: switchers remain reachable via the mobile sidebar drawer (already present). If the drawer is hard to discover, keep a compact pair in the topbar **only below `lg`**.
**Acceptance:** On desktop, theme/language appear once. Mobile users can still change theme and locale without hunting.
### 1.4 Radio hub tab grouping
URLs unchanged. UI presents two rows (or a primary row + overflow “More” row):
**Primary:** Overview, History, Moderation, Monitoring, Settings
**Tools:** Banners, Embed, API keys, Points, Ranks, Auto DJ
**Implementation options (pick one in plan):**
- **A (recommended):** Extend `AdminSectionTabs` / hub definition with optional `group?: "primary" | "tools"` and render two labeled rows for Radio only.
- **B:** Nested “Tools” dropdown tab — less discoverable; avoid unless row A overflows badly.
**Acceptance:** Radio remains fully linked; primary ops are visible without horizontal scroll on a typical laptop width (~1280px).
### 1.5 Distinct Access vs Moderation icons
- **Access & security** sidebar: keep `Ban` (or `Shield`) — already distinct from Users.
- **Moderation** sidebar: change from `Shield` to something like `Gavel` or `ShieldAlert` so it does not match Access.
Hub definition icons for Access vs Moderation should also differ if both appear in chrome.
**Acceptance:** Sidebar icons for Access and Moderation are not the same glyph.
---
## Phase 2 — Admin i18n (queued)
- Move hub `title` / `subtitle` / tab `label` to `labelKey` + `pages.admin.hubs.*` (and tab keys).
- Translate high-traffic pages: Users, Events, Logs, Settings, Moderation.
- i18n theme switcher aria/title strings for `variant="admin"`.
- Do not block Phase 1 on this; Phase 1 may leave English hub strings as today.
## Phase 3 — Design system (queued)
- Standardize list pages on `--admin-*` tokens (`admin-card`, shared empty state, table chrome).
- Optional shared `AdminListToolbar` for actions formerly next to removed `h1`s.
- Gradual migration; no big-bang rewrite of catalog/user detail.
---
## Risks & mitigations
| Risk | Mitigation |
|------|------------|
| Removing `h1` hurts accessibility | Hub shell already exposes one `h1`; detail pages keep entity `h1`. Spot-check with one screen reader pass on Users + Events. |
| Tab active-state regressions | Add/adjust `match` arrays; manually verify Directory vs Multi-accounts, Logs vs Chat. |
| Radio two-row tabs feel heavy | Only Radio uses groups; other hubs stay single row. |
| Mobile loses theme/lang | Keep switchers in sidebar drawer; optional `lg:hidden` topbar pair. |
## Out of scope leftovers
- Calendar under Shop hub (IA smell) — defer unless requested.
- Legacy user route folder split (`show/[id]` vs `[id]`) — defer.
- Avatar `/imaging` proxy — separate track.
## Success criteria (Phase 1)
1. No double hub+page title on representative pages: Articles, Users directory, Events list, Logs index, Radio overview.
2. Orphan routes listed above reachable from tabs.
3. Desktop: single theme/language control location.
4. Radio primary tabs visible without scrolling on 1280px width.
5. Moderation and Access icons differ.
---
## Approval
- Phase 1 approach approved in conversation (2026-07-17).
- Implementation proceeds via a Phase-1 plan under `docs/superpowers/plans/`.