dragonflight/services/web-ui/public
opencode 002e5acb82 auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap
Scope (locked in via planning Q&A):
  - Identity: local accounts only (PG users table) + existing bearer
    tokens for headless callers.
  - Transport: httpOnly cookie session for browser, Bearer for API.
  - RBAC: admin / editor / viewer roles, plus an orthogonal
    is_client flag for external (agency, talent, customer) accounts.
  - Bootstrap: ADMIN_BOOTSTRAP_USER + ADMIN_BOOTSTRAP_PASSWORD env
    seed the first admin on a clean install. Set ADMIN_BOOTSTRAP_RESET
    to force-reset the named user (break-glass).
  - Rate limit: in-memory, 10 fails per 15min per (IP, username).
  - Password policy: \u22658 chars, mixed case, digit, symbol; small
    blocklist of common passwords; cannot equal username.
  - Self-service: change own display name + password. Everything
    else (role, is_client, other-user mgmt) is admin only.
  - Audit log: append-only table, indexed by actor + event_type +
    created_at, populated by every auth/admin event.

Files added:
  - services/mam-api/src/db/migrations/022-auth-rework.sql
        users.is_client + last_login_at + failed_attempts; audit_log
        table with FK to users (ON DELETE SET NULL).
  - services/mam-api/src/middleware/audit.js
        Fire-and-forget audit() helper. Caller never awaits, failure
        logs but never throws — auditing cannot break the request
        that triggered it.
  - services/mam-api/src/middleware/passwordPolicy.js
        Shared checkPassword(pw, { username }) used by setup, user
        create/update, and self-service password change.
  - services/mam-api/src/tasks/bootstrapAdmin.js
        Runs after migrations. No-ops unless ADMIN_BOOTSTRAP_USER +
        ADMIN_BOOTSTRAP_PASSWORD are set AND (users table empty OR
        ADMIN_BOOTSTRAP_RESET=true).
  - services/mam-api/src/routes/audit.js
        Admin-only GET /audit (paginated, filter by event_type /
        actor / target / date) and GET /audit/event-types.
  - services/web-ui/public/modal-account-settings.jsx
        Profile + Password tabs. Triggered by sidebar user button.

Files rewritten:
  - services/mam-api/src/routes/auth.js
        - POST /login: regenerate(), no manual save(); audit success/
          fail/lockout; updates last_login_at + failed_attempts.
        - POST /logout: destroys session, audits logout.
        - GET /me: returns is_client + last_login_at. Synthetic admin
          when AUTH_ENABLED=false.
        - GET /setup-status: drives login.html UI state.
        - POST /setup: blocked once any user exists; password policy.
        - POST /password: self-service. Requires current pw, runs
          policy, audits, invalidates other sessions implicitly via
          users.js if changed by admin.
        - PATCH /me: self-service display_name update.
  - services/mam-api/src/routes/users.js
        - is_client field in create/update/list/get.
        - Guardrails: cannot delete or demote last admin, cannot
          delete self, admins cannot be flagged is_client.
        - Password change invalidates all sessions for that user
          (DELETE FROM sessions WHERE sess->>'userId' = id).
        - Audit on every mutation.
        - Password policy enforced.
  - services/mam-api/src/middleware/auth.js
        - requireAuth now exposes req.user.is_client.
        - New requireRole(["admin","editor"], { rejectClients: true })
          helper. Applied to cluster, sdk, capture routes (infra).
        - Synthetic user when AUTH_ENABLED=false has is_client=false.
  - services/mam-api/src/index.js
        - Loads bootstrap admin after migrations.
        - Wires /api/v1/audit.
        - Cleans up an earlier comment block.
  - services/web-ui/public/login.html
        - Password hint added next to setup-mode password field.
  - services/web-ui/public/shell.jsx
        - Sidebar user footer is a button that opens AccountSettings.
        - CLIENT badge next to role when is_client=true.
        - Nav filters: clients lose ingest tree + jobs + editor;
          viewers lose ingest + editor; only admins see the Admin
          section. Power button hidden when synthetic user.
  - services/web-ui/public/screens-admin.jsx
        - Users table: new Client column with inline toggle.
        - InviteUserModal: Client checkbox + password hint, gated
          off when role=admin.
        - Last login column replaces Created in primary view.
        - CSV export includes client + last_login.
  - services/web-ui/public/data.jsx
        - ZAMPP_DATA.ME carries is_client + display_name.
  - services/web-ui/public/index.html
        - Loads dist/modal-account-settings.js.
  - services/web-ui/public/styles-rest.css
        - .user-row grid widened to 6 columns.
  - docker-compose.yml
        - Plumbs SESSION_COOKIE_SECURE + ADMIN_BOOTSTRAP_* env vars.

Deploy:
  cd /opt/wild-dragon
  git pull origin main
  # In .env:
  #   AUTH_ENABLED=true
  #   SESSION_SECRET=<openssl rand -hex 48>
  #   ADMIN_BOOTSTRAP_USER=admin
  #   ADMIN_BOOTSTRAP_PASSWORD=<strong>
  docker compose build mam-api web-ui
  docker compose up -d --force-recreate --no-deps mam-api web-ui
2026-05-27 03:21:16 +00:00
..
css fix: remove Google Fonts, fix editor link to :47435, fix page titles 2026-05-18 22:56:51 -04:00
downloads release: add v1.1.0 ZXP artifact (Growing tab + visual system alignment) 2026-05-26 16:09:52 -04:00
fonts web-ui: wave-1 finish — self-host fonts + multi-stage Dockerfile 2026-05-21 16:32:55 +00:00
img feat(brand): add Wild Dragon logo + favicon 2026-05-18 14:11:29 +00:00
js feat(admin): live video-presence indicators on cluster DeckLink ports 2026-05-26 22:02:38 +00:00
app.jsx auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
data.jsx auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
favicon.ico feat(brand): add Wild Dragon logo + favicon 2026-05-18 14:11:29 +00:00
icons.jsx feat(home,users): real metrics, working Users row actions + Groups CRUD 2026-05-23 03:30:10 +00:00
index.html auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
login.html auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
modal-account-settings.jsx auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
modal-new-recorder.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
screens-admin.jsx auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
screens-asset.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
screens-editor.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
screens-home.jsx dashboard: rebuild as control-room status board (on air / up next / attention / work) 2026-05-26 23:10:23 -04:00
screens-ingest.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
screens-jobs.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
screens-library.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
screens-projects.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
shell.jsx auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
styles-asset.css chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
styles-fixes.css fix: remove gradient text from launcher wordmark and token counter (design ban) 2026-05-26 23:02:06 -04:00
styles-modal.css feat(web-ui): Z-AMPP screen + component CSS: styles-modal.css 2026-05-22 08:03:57 -04:00
styles-rest.css auth: top-to-bottom rework — local accounts, RBAC + client tag, audit log, env-bootstrap 2026-05-27 03:21:16 +00:00
styles-screens.css dashboard: add dense stat cards, cluster bars, job rows, sparkline fixes 2026-05-26 22:58:23 -04:00
styles.css chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
tweaks-panel.jsx Add Z-AMPP UI: visuals + tweaks-panel: tweaks-panel.jsx 2026-05-22 08:13:37 -04:00
visuals.jsx chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00