Files
UmbraTrans/docs/umbratrans-ui-design.md
umbra audio d1b19fbdb3 Update the site icon and wire the UI to email login
Icon: the supplied artwork is now UmbraTrans_Icon2_899x920.jpg, gold and
cyan on white, with the wordmark corrected to "UmbraTrans". It is copied
verbatim to web/assets/umbratrans-icon.jpg as the source, and
web/assets/umbratrans-emblem.png is derived from it and is what the pages
load: the book cropped to its ink bounds, the white page made transparent
by flood-filling inward from the corners so the white lettering inside
the book survives, letterboxed square rather than side-trimmed so no part
of the emblem is cut, and emitted at 256px.

A square crop of a 827x695 emblem has to choose between trimming the
sides and letterboxing, and trimming was cutting the book's frame. The
glow also moved from box-shadow to filter, because a box-shadow follows
the border box rather than the artwork's alpha and would have drawn a
glowing rectangle behind a book-shaped emblem.

The UI was still written against username login, so the sign-in form
could not have worked against the API: it posted {username, password} and
LoginRequest requires {email, password}. Fixed, along with the rest of
the email-verification flow that had no UI at all:

- the sign-in form collects an email address, and its copy says so;
- a 403 email_not_verified, which is only ever reached once the password
  is already proven correct, reveals a panel offering a new link. The
  resend wording is the server's and is identical for real and unknown
  addresses;
- a confirmation view accepts a pasted link or token, and one is opened
  automatically when the URL carries a token, which is then stripped from
  the address bar so it is not left in history;
- the password-policy hint read the sign-in field to tell the user their
  password must avoid their "account name", but the rule checks the
  account's username. It now uses the signed-in account's handle, and
  says nothing rather than the wrong thing when there is no handle;
- the provision form called email optional while the API requires it,
  and let a member be created with no organization, which the store
  rejects. Both are caught client-side now with wording that names the
  field to fix;
- `serve` accepts --repository postgres, so the app can be exercised
  against the authoritative store.

Verified against a live server on PostgreSQL: sign-in with the email
address, forced first-password change, provisioning an invited member,
401 for a wrong password and 403 email_not_verified for the right one,
and byte-identical resend answers for a real and an unknown address.
2026-09-26 22:05:35 -07:00

114 lines
5.5 KiB
Markdown

# UmbraTrans Web UI design
**Status:** static prototype for review
**Database transition:** paused
**Primary URL:** `https://umbratrans.bdmurphy.me/`
**Admin URL:** `https://umbratrans.bdmurphy.me/uadmin/`
**Prototype listener:** local machine, TCP `8442`
## Product shape
UmbraTrans has two related surfaces:
1. **Workspace** — the daily working environment for a signed-in user. It is project-focused and optimized for reviewing books, speakers, voices, translations, audio runs, and delivery status.
2. **Control** — the `/uadmin/` management surface for account provisioning, organizations, projects, maintenance, audit, and system statistics.
The workspace and control surfaces share the Umbra brand and accessibility conventions, but intentionally use different layouts and visual emphasis.
## Visual reference
The control surface references the existing Umbra Audio Review UI at `umbraudio.bdmurphy.me`:
- background: `#1a1a2e`
- panel: `#16213e`
- elevated/stat panel: `#0f3460`
- primary accent: `#7c3aed`
- secondary accent: `#a78bfa`
- text: `#e0e0e0`
- muted text: `#94a3b8`
- success: `#10b981`
- warning: `#f59e0b`
- danger: `#ef4444`
- compact cards, top navigation, status badges, and data tables
- supplied site icon: `/home/umbra/Documents/UmbraTrans_Icon2_899x920.jpg` (899x920, gold and cyan, wordmark corrected to "UmbraTrans"), copied verbatim to `web/assets/umbratrans-icon.jpg` as the source artwork
- `web/assets/umbratrans-emblem.png` is derived from it and is what the pages actually load: the book cropped to its ink bounds (x 47-873, y 81-776, the 776-796 gap being the separation from the wordmark), the white page made transparent by flood-filling inward from the corners so the white lettering inside the book survives, letterboxed square rather than side-trimmed so no part of the emblem is cut, and emitted at 256px. The favicon and every `.brand-image` reference it.
The workspace uses a deliberately different **Studio** language: a slate/indigo canvas, left navigation rail, teal action accent, amber review accent, larger reading areas, and a pipeline-oriented layout. It should feel like a production desk rather than an admin console.
## Routes
| Route | Purpose | Access |
|---|---|---|
| `/` | Sign-in and account entry | Public |
| `/workspace/` or `/workspace.html` | Authenticated project workspace | Authenticated user |
| `/uadmin/` | Accounts, projects, maintenance, statistics | Organization/platform administrator |
| `/uadmin/accounts` | Account provisioning and lifecycle | Administrator |
| `/uadmin/projects` | Project management | Administrator |
| `/uadmin/maintenance` | Worker, queue, and storage operations | Administrator |
| `/uadmin/statistics` | Usage and system health | Administrator |
The static prototype uses `index.html`, `workspace.html`, and `uadmin/index.html`. The eventual application should serve the same routes without exposing filesystem paths.
## Authentication direction
The UI supports two account-enrollment paths:
1. **Temporary local password** — an administrator provisions an account with a one-time temporary password. Only an Argon2id hash is stored. The account is marked `must_change_password`; the first login must change it before any workspace access.
2. **OIDC enrollment** — an administrator provisions an account or invitation and the identity provider completes credential setup. No local password is created.
The application should hide this choice behind an authentication adapter. Both paths must resolve to the same canonical `users` identity, organization membership, project membership, and server-side session. The browser must never supply a trusted `user_id`, `organization_id`, `project_id`, or role.
The prototype does not authenticate, store credentials, or call a database.
## Admin workflows to design
- Create/suspend/reactivate an account.
- Issue a temporary password or OIDC invitation.
- Require first-login password change for temporary-password accounts.
- Assign organization and project memberships.
- View account status, last login, and MFA state.
- Create, archive, and transfer projects.
- View worker health, queue depth, failed jobs, and storage status.
- View audit history and export a sanitized report.
Every destructive action requires a confirmation step, an explicit permission check, and an audit event.
## Workspace workflows to design
- Select an authorized project.
- View source book, analysis version, speakers, canonical voices, and voice cast.
- Review translation status by locale.
- Monitor analysis, audio, QA, and release stages.
- Inspect job progress without exposing filesystem paths.
- Download only artifacts authorized for the current project and release state.
## Prototype limitations
The current prototype uses mock data and client-side navigation only. It does not:
- connect to PostgreSQL;
- authenticate users;
- issue or validate passwords;
- expose real accounts or projects;
- accept real credentials;
- perform administrative actions.
Buttons demonstrate intended states and interactions only. The UI must remain a prototype until the database transition and security gates are approved.
## Local review
From the workspace root:
```bash
cd /home/umbra/src/UmbraTrans
python3 -m http.server 8442 --bind 0.0.0.0 --directory web
```
Then open:
- `http://<local-host>:8442/`
- `http://<local-host>:8442/workspace.html`
- `http://<local-host>:8442/uadmin/`
For production, terminate TLS at the approved reverse proxy, restrict the application listener to the required interface, and define the network allow-list before exposing port 8442.