Context. surface admin · domain content · route /personas · auth signed-in (admin) + scope:admin:workspace:persona · source apps/oshun/admin/src/app/personas/page.tsx
Last walked. —
Purpose#
Govern persona registry, voice profiles, avatar packs, release channels, policy
packs, and disclosure state. operatorPromise: "Every persona, voice, and
avatar carries an attested policy pack, lineage, and release posture visible to
operators."
Entry points#
- Sidebar item "Personas" (AdminSidebar — content group)
- Review → personas handoff (
review → personasperOSHUN_ADMIN_WORKSPACE_RELATIONSHIPS) — "Review decision must be applied to a persona release channel."
Layout regions#
Inside AdminShell:
<WorkspaceEntryPoint workspaceId="personas" ...>- When
detail.accessible, ten panels in this order:<PersonaRegistryPanel registryEntries={registrySnapshot.registryEntries}><TaraAiPersonaSponsorPanel /><TaraAiPersonaSequenceScriptPanel /><TaraAiPersonaNameplatePanel /><PersonaGovernanceEditor entries={governanceSnapshot.entries}><ToneCalibrationReviewPanel runs={releaseSnapshot.toneCalibrationRuns}><RehearsalOutcomesPanel rehearsals={releaseSnapshot.rehearsals}><PremiumCastApprovalPanel approvals={releaseSnapshot.premiumCastApprovals}><VoiceProfileReviewPanel voiceProfileReviews={voiceSnapshot.voiceProfileReviews}><AvatarPackReviewPanel avatarPackReviews={avatarSnapshot.avatarPackReviews}>
Five separate snapshot extractors run against detail.result.value:
extractPersonaRegistrySnapshot→registryEntriesextractPersonaGovernanceSnapshot→entriesextractPersonaReleaseSnapshot→toneCalibrationRuns,rehearsals,premiumCastApprovalsextractVoiceProfileSnapshot→voiceProfileReviewsextractAvatarPackSnapshot→avatarPackReviews
Three of the panels (TaraAiPersonaSponsorPanel,
TaraAiPersonaSequenceScriptPanel, TaraAiPersonaNameplatePanel) take no props
from the snapshot.
States#
- Anonymous → middleware redirect to
/unauthorized?reason=missing-session&returnTo=/personas - Signed-in (admin) without
admin:*,admin:studio, oradmin:workspace:persona→WorkspaceEntryPoint"Access not granted"; the ten panels hidden - Scope ok + BFF ok → all ten panels render
- Scope ok + BFF
workspace-unavailable→ entry-point "Workspace data unavailable"; panels hidden - Snapshot extractors fall through to defaults when
detailValueis null - Note IA id
personas(plural),bffWorkspaceId: 'persona'(singular) — BFF endpoint is/v1/admin/workspaces/persona
Interactions#
Top-level interactive elements live inside each child panel:
- PersonaRegistryPanel — registry list / table
- TaraAiPersonaSponsorPanel — sponsor management (no props)
- TaraAiPersonaSequenceScriptPanel — sequence-script editing
- TaraAiPersonaNameplatePanel — nameplate management
- PersonaGovernanceEditor — governance entry editor
- ToneCalibrationReviewPanel — tone calibration run results
- RehearsalOutcomesPanel — rehearsal outcomes
- PremiumCastApprovalPanel — premium cast approvals
- VoiceProfileReviewPanel — voice profile review (overlap with
../../isis/isis-voice-cloning.md) - AvatarPackReviewPanel — avatar pack review
Data & contracts#
- Reads:
loadWorkspaceDetail('personas', session)→/v1/admin/workspaces/persona; five snapshot extractors share the samedetail.result.value - Writes: per panel (governance edits, calibration runs, rehearsal outcomes, premium cast approvals, voice / avatar review dispositions)
- Realtime: None at page level.
- Auth/role check: middleware + page
(
canEnterAdminWorkspace(scopes, 'personas')→ required scopes['admin:*', 'admin:studio', 'admin:workspace:persona'])
Cross-references#
- Shell:
shell/01-app-shell.md,shell/04-workspace-pattern.md - Workspace definition:
libs/oshun/navigation/src/admin-ia.ts(personas—kind: 'registry',operatorRelationship: 'register',bffWorkspaceId: 'persona') - Handoff origin (
from → personas):../governance/review.md - Handoff destination (
personas → rights):../safety/rights.md - Library:
apps/oshun/admin/src/lib/persona-registry-detail.ts,persona-governance-detail.ts,persona-release-detail.ts,voice-profile-detail.ts,avatar-pack-detail.ts - Related Isis route (model side):
../../isis/isis-voice-cloning.md(clone workflow) - Component sources:
PersonaRegistryPanel.tsx,TaraAiPersonaSponsorPanel.tsx,TaraAiPersonaSequenceScriptPanel.tsx,TaraAiPersonaNameplatePanel.tsx,PersonaGovernanceEditor.tsx,ToneCalibrationReviewPanel.tsx,RehearsalOutcomesPanel.tsx,PremiumCastApprovalPanel.tsx,VoiceProfileReviewPanel.tsx,AvatarPackReviewPanel.tsx
Open questions / known gaps#
- The three
TaraAiPersonaXxxPanelcomponents take no props — document their internal data sources (self-fetching panels? module-level constants like Lilith?) - Naming inconsistency: IA
personas(plural), BFFpersona(singular). Other workspaces also drift (incidents/incident, models/model) -
VoiceProfileReviewPaneloverlap with both../safety/trust-safety.md(cloned-voice review) and the isis voice-cloning admin route — clarify ownership boundaries