---
path: /studio/hathor/character-modeling
surface: studio
domain: hathor
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/hathor/character-modeling/page.tsx
status: walked
last_walked:
  - '2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data
    (2xx), console/page-errors, expected content, screenshot verified; live
    screen-reader, touch, offline, and telemetry-delivery checks pending a
    manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md;
    body re-derived 2026-06-03 from current source (lane-console architecture)'
  - '2026-07-03 focused real-dev-infra walk —
    apps/oshun/web/e2e/studio-hathor-character-modeling.spec.ts now covers
    anonymous redirect, Hathor-admin live catalog, real @hathor/characters
    complete and incomplete packet validation through the local BFF, auth
    propagation, client/BFF/malformed/transport errors, loading/503/malformed
    catalog states, non-admin fail-closed state, pending lockout, route-map and
    quick-action selectors, mobile 44px/no-overflow checks, scoped axe, and
    direct BFF auth/schema gates. Evidence:
    WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md §272.'
---

# Studio Hathor · Character Modeling

## Purpose

Admin lane console for the `@hathor/characters` CGI packet validator. The single
**CGI Packet Validation Lane** submits a character CGI export packet and checks
its completeness — required cast, costume and visual-reference coverage, and a
well-formed CGI export descriptor — returning a per-issue verdict. Admin-scoped
and fail-closed.

## Entry points

- **Direct URL / bookmark** — `/studio/hathor/character-modeling`;
  `alternates.canonical` is set.
- **Quick-action from siblings** — this page links out to Culture Modeling and
  Location Modeling; other Hathor lanes link here.
- **Studio overview** — see
  [`../../studio-overview.md`](../../studio-overview.md).

## Layout regions

`page.tsx` renders inside `<ShellLayout active="studio">`:

- **Workspace** (`StudioHathorCharacterModelingWorkspace`,
  `data-hathor-character-modeling-workspace`):
  - `<h1>` `WorkspaceHeading` — "Hathor Character Modeling Workspace"
  - Summary `<p data-hathor-character-modeling-summary>`
  - **CGI Packet Validation Lane** (`<h2 data-char-lane-heading>`): the
    fetch-on-mount catalog state, then the validation form + result.
- **Route Map panel** (`<section data-hathor-character-modeling-route-map>`,
  `data-char-route-count="5"`, `<h2>Route Map</h2>`): 5
  `data-char-route-map-entry` entries from
  `STUDIO_HATHOR_CHARACTER_MODELING_ROUTE_MAP`, each carrying `data-route-path`.
- **Quick-action lane** (`data-char-quick-actions`,
  `data-char-quick-action-count="3"`): Culture Modeling, Location Modeling, Back
  to Studio workspace index.

## States

- [x] **Loading** — `<p data-char-loading role="status" aria-live="polite">`
      "Loading character packet validator…" while the GET catalog request is in
      flight.
- [x] **Unauthorized** — `data-char-unauthorized role="alert"` notice on 401/403
      (admin-scope required); reason from the BFF `message` or the default scope
      string.
- [x] **Error** — `data-char-error role="alert"` notice on a non-OK catalog
      response, malformed catalog, or network failure.
- [x] **Ready (form)** — `data-char-issue-types role="status"` count +
      `data-char-form data-char-form-state="idle" aria-busy="false"` with the
      packet textarea and submit button.
- [x] **Pending validation** — `data-char-form-state="pending"`,
      `aria-busy="true"`, disabled textarea, disabled submit button, and
      `data-char-submit-state="pending"`.
- [x] **Result** — `data-char-result role="status" aria-live="polite"` with
      `data-char-headline` (`data-valid`, characterCount / blockingCount /
      warningCount) and, if any, `data-char-issues` rows (`data-char-issue-row`
      carrying `data-issue-type` and `data-issue-severity`).
- [x] **Validation error** — `data-char-validate-error role="alert"` for
      malformed JSON, BFF 400 `detail`, malformed 200 result payload, or
      transport failure.

## Interactions

- [x] **`data-char-payload`** (textarea, `aria-label="character packet json"`) —
      edit the CGI character packet JSON
      (`{ packet:{ packetId, worldId, title, characters[], required*Ids[], cgiExport } }`).
- [x] **`data-char-submit`** ("Validate packet" / "Validating…") — parses the
      JSON and POSTs `{ packet }` to the validate endpoint; on 200 with a valid
      result it renders the verdict, otherwise sets `data-char-validate-error`;
      the pending state disables the textarea and button.
- [x] **Route Map entries** — verify against
      `STUDIO_HATHOR_CHARACTER_MODELING_ROUTE_MAP` (5 entries).
- [x] **Quick-action links** — Culture Modeling
      (`data-char-quick-action="culture-modeling"` →
      `/studio/hathor/culture-modeling`), Location Modeling
      (`data-char-quick-action="location-modeling"` →
      `/studio/hathor/location-modeling`), Back to Studio
      (`data-char-quick-action="studio-index"` → `/studio`).

## Data & contracts

- **Reads**: `GET /v1/admin/hathor/workbench-characters` (catalog:
  `issueTypes`).
- **Writes**: `POST /v1/admin/hathor/workbench-characters/validate` with
  `{ packet }`.
- **Realtime**: none.
- **Caching**: client fetch on mount, `cache: 'no-store'`,
  `buildBffAuthHeaders()`, `AbortController` on unmount.
- **Auth**: admin-scoped, fail-closed (401/403 → unauthorized state); route is
  behind the signed-in + studio proxy gate.
- **Client parsing**: GET catalog requires `issueTypes: string[]`; POST success
  requires numeric counts, boolean `valid`, and well-formed issue rows before a
  result is rendered.

## Cross-references

- Parent: [`../../studio-overview.md`](../../studio-overview.md)
- Component sources:
  - `apps/oshun/web/src/components/studio/StudioHathorCharacterModelingWorkspace.tsx`
  - `apps/oshun/web/src/components/studio/StudioHathorCharacterModelingRouteMap.ts`
- Siblings:
  [`./studio-hathor-workbench-characters.md`](./studio-hathor-workbench-characters.md)
  (the same `/v1/admin/hathor/workbench-characters` validator),
  [`./studio-hathor-culture-modeling.md`](./studio-hathor-culture-modeling.md),
  [`./studio-hathor-location-modeling.md`](./studio-hathor-location-modeling.md)

## Automated coverage

- `apps/oshun/web/e2e/studio-hathor-character-modeling.spec.ts` covers:
  anonymous redirect, Hathor-admin shell entry, live issue-type catalog,
  complete packet validation, incomplete packet blocking/warning issues, browser
  bearer propagation, scoped axe, 44 px controls, route map, quick actions,
  client-only malformed JSON with zero POSTs, BFF `invalid_packet` detail
  surfacing, malformed success payload handling, transport failure, catalog
  loading/503/malformed states, non-admin fail-closed state, pending validation
  lockout, mobile no-overflow containment, and direct BFF auth/schema gates.
- Focused component tests: `StudioHathorCharacterModelingWorkspace.test.tsx` and
  `StudioHathorCharacterModelingWorkspace.integration.test.tsx`.
- Focused BFF route test:
  `apps/oshun/bff/src/__tests__/admin-hathor-workbench-characters-route.test.ts`.

## Open questions / known gaps

- [ ] This route and `/studio/hathor/workbench-characters` mount different
      components against the **same** `/v1/admin/hathor/workbench-characters`
      endpoint; confirm whether both surfaces are intended to ship or one is the
      canonical home.
- [x] Hathor is `unconfirmed-v1` per `WALKTHROUGH/matrix/routes.csv`; confirm
      whether the dedicated `/studio/hathor/*` admin lanes ship V1 or are
      internal-only. Confirmed in V1 via `V1/TODOS.md` §34 and the 2026-05-29
      surface inventory.
- [ ] The route-map sub-routes are listed but their concrete `page.tsx` files
      are not present; confirm whether they remain route-map placeholders or
      need dedicated deep-link pages.
- [ ] Manual assistive-technology pass remains pending; automated scoped axe and
      keyboard/touch-target assertions pass for this route.
