---
path: /studio/isis/controlnet
surface: studio
domain: isis
auth:
  signed-in + studio entitlement (AAA-gated — segment `controlnet` in
  `AAA_ONLY_STUDIO_ROUTES`)
source: apps/oshun/web/src/app/studio/isis/controlnet/page.tsx
status: walked
last_walked:
  '2026-07-03 real-dev-infra Playwright walk — direct Studio Isis boundary
  hard-block, authenticated localhost-only lane bypass, real BFF catalog load,
  ControlNet/IP-Adapter/InstantID alias resolution, pending-submit lockout,
  unresolved/invalid/malformed/network failure states, non-admin fail-closed
  auth, direct BFF auth/schema gates, route map, quick actions, 44 px controls,
  mobile containment, and shared axe scan. Evidence:
  apps/oshun/web/e2e/studio-isis-controlnet.spec.ts and
  WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md.'
---

# Isis ControlNet

## Purpose

Admin lane console for the canonical control-conditioning catalog (ControlNet /
IP-Adapter / InstantID) and alias resolution. It lists the canonical ControlNet
modes and the default blend precedence, then resolves a raw mode or alias for a
given domain to its canonical mode and legacy workflow name.

## Entry points

- Sibling quick-action card from `/studio/isis/comfyui-nodes`
- Studio index (`/studio`)
- Direct URL / bookmark

## Layout regions

`page.tsx` mounts `ShellLayout active="studio"` and three panels (no breadcrumb
panel).

- **Workspace panel** (`data-isis-controlnet-workspace`):
  - `<h1>` "Isis ControlNet Workspace" (`WorkspaceHeading`)
  - Summary paragraph (`data-isis-controlnet-summary`)
  - Canonical-modes section (`<h2>`) listing `data-controlnet-mode={m}` items +
    blend precedence (`data-controlnet-precedence`)
  - The "Resolve a mode" form (`data-controlnet-resolve-form`,
    `data-controlnet-form-state=idle|pending`)
  - Resolution result (`data-controlnet-resolved` with
    `data-controlnet-canonical` / `data-controlnet-legacy`, or
    `data-controlnet-unresolved`)
- **Route map panel** (`data-isis-controlnet-route-map`): `<h2>` "Route Map"
  enumerating `STUDIO_ISIS_CONTROLNET_ROUTE_MAP`; each article carries
  `data-isis-controlnet-route=<path>`
- **Quick-actions panel** (`data-isis-controlnet-quick-actions`,
  `data-isis-controlnet-quick-action-count=2`): `quickAction` links to
  `/studio/isis/animatediff-lightning` and "Back to Studio workspace index" →
  `/studio`; each link carries `data-isis-controlnet-quick-action=<id>`

## States

- [x] **Loading** — `data-controlnet-loading` "Loading control modes…"; the
      Playwright spec holds the catalog request open and asserts the resolve
      form is absent until the request settles.
- [x] **Unauthorized** — `data-controlnet-unauthorized` (admin-scope fail-closed
      on 401/403)
- [x] **Error** — `data-controlnet-error` on non-OK / malformed response or
      network failure; the form and mode rows remain hidden.
- [x] **Ready (form)** — canonical modes + resolve form render, backed by live
      `GET /v1/admin/isis/controlnet` and exact domain options
      `controlnet | ipadapter | instantid`
- [x] **Result** — `data-controlnet-resolved` (resolved),
      `data-controlnet-unresolved` (no match), or
      `data-controlnet-resolve-error` (error)

## Interactions

### Resolve a mode (`data-controlnet-resolve-form`)

- [x] **Domain** — `data-controlnet-field-domain` select (options from catalog
      `domains`); Playwright asserts the live option order and switches across
      all three domains.
- [x] **Mode / alias** — `data-controlnet-field-mode` text input; tested with
      `openpose`, `identity`, `instant-id`, `not-a-mode`, and a whitespace-only
      invalid payload.
- [x] **Resolve mode** — `data-controlnet-resolve-submit` submit; POSTs to
      `/v1/admin/isis/controlnet/resolve`, disables while pending, exposes
      `data-controlnet-submit-state=pending|idle`, and renders the live BFF
      response without fabricating missing fields.

### Route map

- [x] **Route-map articles** — non-interactive path + purpose entries; exact
      five-entry route map is asserted via `data-isis-controlnet-route=<path>`.

### Quick-actions

- [x] **Open Isis AnimateDiff Lightning workspace** →
      `/studio/isis/animatediff-lightning`
- [x] **Back to Studio workspace index** → `/studio`

## Data & contracts

- **Reads**: `GET /v1/admin/isis/controlnet` (`CONTROLNET_ENDPOINT`) on mount —
  catalog (controlNetModes, defaultBlendPrecedence, domains)
- **Writes**: `POST /v1/admin/isis/controlnet/resolve` (`RESOLVE_ENDPOINT`) —
  resolve a mode/alias
- **Realtime**: None
- **Caching**: client `fetch` on mount, `cache: 'no-store'`,
  `buildBffAuthHeaders()`
- **Auth**: admin-scoped fail-closed (401/403 → unauthorized state); AAA-gated
  studio route behind the signed-in + studio proxy gate
- **Component sources**:
  - `apps/oshun/web/src/components/studio/StudioIsisControlNetWorkspace.tsx`
  - `apps/oshun/web/src/components/studio/StudioIsisControlNetRouteMap.ts`

## Cross-references

- Studio overview: [`../../studio-overview.md`](../../studio-overview.md)
- Sibling routes:
  - [`studio-isis-comfyui-nodes.md`](./studio-isis-comfyui-nodes.md)
  - [`studio-isis-ip-adapter.md`](./studio-isis-ip-adapter.md)
  - [`studio-isis-instantid.md`](./studio-isis-instantid.md)
  - [`studio-isis-animatediff-lightning.md`](./studio-isis-animatediff-lightning.md)

## Open questions / known gaps

- [x] Resolution is a catalog lookup: aliases are registered in the real
      `@isis/job-envelope` normalizers (`normalizeIsisControlNetMode`,
      `normalizeIsisIpAdapterMode`, `normalizeIsisInstantIdMode`) and are
      surfaced through `apps/oshun/bff/src/routes/admin-isis-controlnet.ts`;
      this view only resolves aliases and does not add new ones.
