Skip to content

Workflow Studio Architecture

Workflow Studio is the browser authoring application under apps/admin-web. It is a Next.js 16 React 19 app that lets authenticated administrators edit step-gate workflows, inspect legacy modules, validate exact revisions, publish signed releases, and inspect channel state. It is not exposed as participant MCP and does not execute participant workflow steps.

Runtime entrypoints

SurfaceSourceResponsibility
Page appapps/admin-web/app/page.tsxMain client component, navigation views, data loading, draft editing, validation/publish orchestration.
Session APIapps/admin-web/app/api/session/route.tsPrivate staging login/logout using STUDIO_ACCESS_TOKEN and HttpOnly cookie.
Backend BFFapps/admin-web/app/api/backend/[...path]/route.tsServer-side proxy to Admin API. Filesystem reader could not load bracket path, but grep shows it uses ADMIN_API_URL, ADMIN_API_BEARER_TOKEN, and upstream fetch.
API helperapps/admin-web/lib/api.tsBrowser fetch helper for /api/backend/{path}, JSON decoding, no-store cache, and ApiError.
Domain typesapps/admin-web/lib/types.tsTypeScript shapes for legacy and engine workflow documents, assets, validators, releases, channels, and dependency views.

The package scripts are pnpm typecheck, pnpm build, and pnpm test:e2e.

Session and BFF trust boundary

/api/session implements a private staging credential, not production OIDC. GET returns anonymous unless the configured token is at least 32 characters and matches the HttpOnly cookie. POST accepts { token }, compares it with timingSafeEqual, and sets rimthan_studio_session with httpOnly, sameSite: "strict", production-only secure, path /, and eight-hour max age. DELETE clears the cookie.

Browser code calls api<T>(path, init) in lib/api.ts. That helper always sends JSON to /api/backend/{path}, sets cache: "no-store", and maps non-OK responses to ApiError. The BFF holds ADMIN_API_BEARER_TOKEN; the browser receives only the Studio session cookie. The deployment contract in deploy/workflow-studio/env.example names these variables and states neither backend credential is exposed to browser JavaScript.

Main page state model

app/page.tsx is a single rich client component. Important state groups include:

  • authentication and view: authenticated, view (workflows, content, modules, releases);
  • catalogue data: workflows, catalog, presentations, registryAssetDrafts, validatorDrafts, releases, channels;
  • selected workflow: selectedWorkflow, revisions, selectedRevision, draft, working, workingLayout, selectedNode;
  • release flow: targetRelease, validation, releaseSheetOpen, busy;
  • editor drawers: module, step, asset, validator, and create workflow sheet state;
  • UI feedback: notice, search, per-editor errors.

loadAll fetches workflows, modules, assets, releases, and channels in parallel. Draft selection fetches the current draft and revision list. Historical revision selection fetches exact revision snapshots and editor layout, allowing immutable history inspection without mutating the draft head.

Domain model split

lib/types.ts explicitly models two workflow document families:

  • LegacyWorkflowDocument uses nodes, module references/candidates, route_module, and presentation bundles. It is retained for migration and legacy module editing.
  • EngineWorkflowDocument uses definition, steps, assets, and validators. It is the current step-gate workflow-engine authoring model.

The type guards isEngineWorkflow and isLegacyWorkflow drive UI branching. This is the frontend equivalent of the backend workflow_kind split in Admin API.

Data operations

The page implements these authoring operations against Admin API routes:

  • create/load/select workflow drafts;
  • save workflow draft head with expected_revision and editor_layout;
  • load revision summaries and snapshots;
  • edit legacy module candidates;
  • edit engine step instructions and step JSON;
  • edit registry assets and validator definitions;
  • validate exact workflow revision for a target release;
  • publish validated revision to production channel;
  • inspect release detail and dependency views;
  • activate/observe channels indirectly via release/publish flow.

The helper withAssetContent computes SHA-256 in the browser using crypto.subtle.digest, enforces the 1 MiB content limit, and validates JSON asset content before saving. This mirrors backend asset digest and size validation but does not replace it.

Relationship to other pages

Focused validation

  • cd apps/admin-web && pnpm typecheck
  • cd apps/admin-web && pnpm build
  • cd apps/admin-web && pnpm test:e2e

Generated from the committed OpenWiki knowledge bundle.