---
path: /editorial
surface: admin
domain: content
auth: signed-in (admin) + scope:admin:workspace:editorial
source: apps/oshun/admin/src/app/editorial/page.tsx
status: drafted
last_walked: '—'
---

# Content · Editorial and content

## Purpose

Plan, QA, and publish content across Tara, curriculum, teacher programs, and
editorial campaigns with release-gate discipline. `operatorPromise`: "Editorial
work has a calendar, review checklists, and a single publishing surface tied
back to review and rights workspaces."

## Entry points

- Sidebar item **"Editorial"** (AdminSidebar — content group)
- Editorial → review handoff (`editorial → review` per
  `OSHUN_ADMIN_WORKSPACE_RELATIONSHIPS`) — operator follows the ready-for-review
  gate out to `/review`

## Layout regions

Inside `AdminShell`:

- `<WorkspaceEntryPoint workspaceId="editorial" ...>`
- When `detail.accessible`:
  - `<ContentCalendarPanel entries={snapshot.calendarEntries}>`
  - `<ContentQaChecklistPanel checklists={snapshot.qaChecklists} calendarEntries={snapshot.calendarEntries}>`
  - `<TaraLineageGroundingPanel review={taraLineageReview}>` — note the review
    object is built via `buildTaraLineageEditorialReview()` imported from
    `@oshun/tenant-tara-studio` (not from the BFF snapshot)
  - `<TeacherPublishingFlowPanel flows={snapshot.teacherFlows} calendarEntries={snapshot.calendarEntries}>`
  - `<EditorialReleaseStreamPanel />` — self-fetching panel

## States

- [ ] Anonymous → middleware redirect to
      `/unauthorized?reason=missing-session&returnTo=/editorial`
- [ ] Signed-in (admin) without `admin:*`, `admin:studio`, or
      `admin:workspace:editorial` → `WorkspaceEntryPoint` "Access not granted";
      the five panels hidden
- [ ] Scope ok + BFF ok → all five panels render
- [ ] Scope ok + BFF `workspace-unavailable` → entry-point "Workspace data
      unavailable"; panels hidden
- [ ] `taraLineageReview` is built statically each render via
      `buildTaraLineageEditorialReview()` — its data does not depend on
      `detail.result` so it always renders the same content regardless of BFF
      state
- [ ] Per-panel empty / loading states handled inside each child

## Interactions

Top-level interactive elements live inside each child panel:

- [ ] **ContentCalendarPanel** — calendar / list of editorial entries with
      publish dates
- [ ] **ContentQaChecklistPanel** — QA checklist progress, gated by
      `calendarEntries`
- [ ] **TaraLineageGroundingPanel** — Tara lineage grounding review (read-only
      against the canned review object)
- [ ] **TeacherPublishingFlowPanel** — teacher publishing flows cross-referenced
      with calendar entries
- [ ] **EditorialReleaseStreamPanel** — release-stream activity feed (likely
      fetches its own data, since it takes no props)

The page itself exposes no buttons / inputs.

## Data & contracts

- **Reads**:
  - `loadWorkspaceDetail('editorial', session)` →
    `/v1/admin/workspaces/editorial`; snapshot via
    `extractEditorialSnapshot(detail.result.value)` provides `calendarEntries`,
    `qaChecklists`, `teacherFlows`
  - `buildTaraLineageEditorialReview()` from `@oshun/tenant-tara-studio` — pure
    / synthesized review
- **Writes**: per panel (QA checkbox state, teacher publish action, calendar
  mutation)
- **Realtime**: `EditorialReleaseStreamPanel` likely subscribes internally
  (release stream is real-time-friendly)
- **Auth/role check**: middleware + page
  (`canEnterAdminWorkspace(scopes, 'editorial')` → required scopes
  `['admin:*', 'admin:studio', 'admin:workspace:editorial']`)

## Cross-references

- Shell: `shell/01-app-shell.md`, `shell/04-workspace-pattern.md`
- Workspace definition: `libs/oshun/navigation/src/admin-ia.ts` (`editorial` —
  `kind: 'operations-console'`, `operatorRelationship: 'curate'`,
  `bffWorkspaceId: 'editorial'`)
- Handoff destination (`editorial → review`): `../governance/review.md`
- Library: `apps/oshun/admin/src/lib/editorial-detail.ts`;
  `@oshun/tenant-tara-studio` (Tara lineage review builder)
- Component sources: `ContentCalendarPanel.tsx`, `ContentQaChecklistPanel.tsx`,
  `TaraLineageGroundingPanel.tsx`, `TeacherPublishingFlowPanel.tsx`,
  `EditorialReleaseStreamPanel.tsx`

## Open questions / known gaps

- [ ] `buildTaraLineageEditorialReview()` returns static review data — should it
      be promoted to a BFF-backed source so the panel reflects live editorial
      review state?
- [ ] `EditorialReleaseStreamPanel` takes no props; document its own fetch
      endpoint (likely `/api/admin/editorial/release-stream` or similar)
- [ ] Cross-link with `../safety/rights.md` — editorial publishing flows touch
      rights & provenance (the relationships table doesn't declare this edge
      today)
