# Oshun — Systems Deep Dive

> The `apps/oshun/` area: the nine deployable **V1 application surfaces** of the
> Oshun platform — one backend-for-frontend, plus the web, admin, tenant,
> mobile, and Telegram clients that consume it.

## What this area is

Where `libs/contracts/` owns the wire types and `libs/*` own the domain engines,
`apps/oshun/` is where Oshun is actually _served_. These are the leaf nodes of
the dependency graph — the runnable processes and bundles a person or operator
opens. Each is a standalone Nx `projectType: "application"` tagged
`scope:oshun`, `type:app`, and a `platform:*` tag (`node`, `web`, `admin-web`,
`tenant-web`, `mobile`). None of them implements domain logic of its own; they
compose the domain libraries and the BFF into a shippable experience.

The area has one hub and eight spokes. The hub is `@oshun/bff` — a large Fastify
backend-for-frontend (1,000+ source files, 488 route modules) that aggregates
every domain (Nisaba, Nyx, Veritas, Arete, Tara, Metis, Lilith, Isis, Aja,
Psyche, Sophia, Iris, and the admin/operator surfaces) behind one HTTP edge. The
spokes are the clients that call it: `@oshun/web` (the consumer website / PWA),
`@oshun/admin` (operator cockpit) and `@oshun/tenant-admin` (tenant console) as
Next.js apps, `@oshun/mobile` and `@oshun/admin-mobile` as Expo/React-Native
shells, and `@oshun/telegram-bot` + `@oshun/telegram-miniapp` for the Telegram
channel. `@oshun/content-service-app` is a ninth, smaller deployable: a thin
process entrypoint that boots the agentic content service.

The split is deliberate. The BFF is the only app that talks to the domain
libraries directly; every other surface talks to the BFF over HTTP and stays
free of domain runtime. That keeps the clients thin and lets the platform expose
one canonical, validated API instead of N drifting ones.

### Surface model

The web and mobile clients render the _consumer_ shell (Home, Explore, Activity,
Library, Profile, plus per-domain surfaces like Nisaba reading, Nyx sky, Tara
ritual). The admin apps render the _operator_ cockpit (review queues, incidents,
policy, moderation, research integrity), and `@oshun/tenant-admin` renders the
_tenant_ cockpit (members, integrations, policy attestation, tenant-scoped
audit). The README for `@oshun/admin-mobile` states the boundary rule plainly:
"Admin routes render dedicated operator wayfinding and never inherit customer
shell chrome."

## How it fits the wider system

The dependency arrow points one way: clients depend on the BFF, the BFF depends
on the domain libraries and contracts. `@oshun/web`, `@oshun/admin`, and
`@oshun/tenant-admin` reach the BFF over HTTP (e.g. `tenant-admin`'s
`src/lib/tenant-bff.ts` forwards the tenant session cookie as a bearer token to
`OSHUN_BFF_URL`, defaulting to `http://localhost:4010`); the mobile shells do
the same through their runtime config. The Telegram bot composes
`@oshun/messaging-channels` rather than the BFF directly. Shared shell
vocabulary (workspace models, shell-mode gating like `canEnterAdminShell`) comes
from `@oshun/navigation`, so all surfaces agree on information architecture.

The boundary these apps enforce is "validated edge, thin client": the BFF parses
and validates every payload against the contract schemas and degrades per-domain
honestly (its `/readyz` returns a "normalized per-domain degradation summary"),
while the clients render whatever the BFF returns — including honest "backend
unreachable" states rather than fabricated data. Walk the "used by" / "depends
on" edges on any node below to see exactly which domains and contracts each app
composes.

## Entity reference

### @oshun/bff

The platform backend-for-frontend (`apps/oshun/bff`), a Fastify TypeScript
service and by far the largest node in this area (~1,062 non-test source files;
`src/app.ts` alone wires 464 `register*Routes` modules). `createApp` in
`src/app.ts` assembles the whole surface: request tracing, tenant + residency
middleware, idempotency, then the consumer feeds (`/home`, `/continue`,
`/library`, `/search`, `/activity`, `/notifications`, `/profile`), the
per-domain routes (Nisaba, Nyx, Veritas, Arete, Tara, Metis, Lilith, Isis, Aja,
Psyche, Sophia, Iris, Themis, safety), and a vast admin/operator surface
(`admin-isis-*`, `admin-aja-*`, `admin-yemaya-*`, `admin-bellona-*`,
`admin-hathor-*`, `admin-studio-*`). Its `package.json` depends on dozens of
`@oshun/*`, `@aja/*`, `@euterpe/*`, `@metis/*`, and `@yemaya/*` workspace
libraries plus `pg`, `ioredis`, and `zod` — it is the one app that composes the
domain engines directly. Seams are injectable and fail-closed (e.g. the Sophia
answer synthesizer is `null` ⇒ extractive composer; the deletion runner stays
`scheduled` rather than fabricating completion when the bus is absent).

### @oshun/web

The consumer-facing website and installable PWA (`apps/oshun/web`), a Next.js +
TypeScript app and the largest client surface (~5,600 `.ts`/`.tsx` files; 52
route directories under `src/app`). It renders the full unified shell — Home,
Explore, Activity, Library, Profile — plus dedicated per-domain surfaces
(`nisaba`, `nyx`, `veritas`, `arete`, `tara`, `sophia`, `metis`, `lilith`,
`personas`, `studio`/`egbe-studio`/`mawu-studio`, billing, legal, settings) and
operator/tenant entry points. It carries real PWA infrastructure
(`public/sw.js`, `public/manifest.json`), critical-route performance budgets
(`src/performance/criticalRouteBudgets.ts`) gated by Lighthouse via
`lighthouserc.cjs`, axe-core accessibility specs, and an extensive Playwright
e2e suite. Production-grade and mature, not scaffold.

### @oshun/admin

The operator cockpit (`apps/oshun/admin`), a Next.js app (~628 `.ts`/`.tsx`
files; 24 route groups under `src/app`: `review`, `inbox`, `incidents`,
`policy`, `moderation`, `trust-safety`, `research-integrity`, `privacy`,
`rights`, `support`, `editorial`, `isis`, `lilith`, `personas`,
`tenant-console`, `messaging`, `models`, …). `src/middleware.ts` gates entry,
and the app ships ~48 Playwright e2e specs covering operator flows (unified
inbox, policy-bundle editor, DSAR review, moderation appeals, copilot audit
invariants, persona release, redesign signoff). It is a real, deeply-featured
admin surface that drives the BFF's `admin-*` routes; runs on port 3020.

### @oshun/tenant-admin

The tenant console (`apps/oshun/tenant-admin`), a Next.js app for tenant-scoped
administration — members, integrations, policy attestation, and tenant audit
history. `src/app/page.tsx` renders the tenant home over `TenantShell`, listing
workspaces from `@oshun/navigation`'s `listOshunTenantWorkspaceDefinitions()`,
gated by `getTenantServerSession()`. Its `src/lib/tenant-bff.ts` performs
server-side BFF reads, forwarding the `tenant.`-prefixed session cookie as a
bearer token and returning `null` (honest "backend unreachable") on failure
rather than fabricating data. Smaller than `@oshun/admin` but real and
session-gated; runs on port 3030.

### @oshun/mobile

The unified consumer mobile shell (`apps/oshun/mobile`), an Expo Router +
TypeScript app (~480 `.ts`/`.tsx` files) targeting iOS, Android, and web. Its
structural tabs are Home, Explore, Activity, Library, Profile (per `ADR-0056`),
with the assistant exposed as a global continuity sheet rather than a sixth tab.
It includes domain launch tiles (`v2/`, `v3/`, `v6/` with companion apps like
`V3CompanionApp`, `EgbeStewardApp`), profile settings persistence, and runtime
config. The `project.json` carries an extensive Maestro-based e2e/device matrix
(core, nisaba-study, signoff, offline-retry suites across an iPhone profile and
a lower-tier Android profile) plus EAS build/submit and store-asset generation
targets. A real, launch-oriented app.

### @oshun/admin-mobile

The admin mobile companion (`apps/oshun/admin-mobile`), an Expo Router app (~94
`.ts`/`.tsx` files) described in its README as "the urgent operations companion
for escalations, on-call approvals, and high-priority incident acknowledgement."
It implements `V1-AMOB-001`: four thumb-reachable operator tabs (Urgent, Inbox,
Incidents, More) over the canonical admin workspace model, with shell-entry
gating via `canEnterAdminShell`/`canEnterAdminWorkspace` from
`@oshun/navigation` and session-expiry checks on mount. Real source under `src/`
(urgent-queue model + client + hook, review queue/decision/routing/evidence
clients, a dozen `AdminMobile*` components) and a Maestro e2e suite (auth,
step-up, review, incidents, signoff). Implemented, not scaffold.

### @oshun/telegram-bot

The Oshun Telegram bot service (`apps/oshun/telegram-bot`), a TypeScript package
built on `grammy` that composes the V1 messaging-channel policy core from
`@oshun/messaging-channels`. `src/index.ts` defines per-environment
configuration (dev/staging/prod tokens + webhook secrets), a
webhook-secret-checked update handler, a per-process rate limiter, crisis-phrase
detection, a Sophia grounder (real retriever-backed or fixture), and real
speech-to-text via `resolveSttVoiceProvider` (fail-closed without credentials —
it replies "could not transcribe" rather than fabricating). It fails loud in
production against the `UNCONFIGURED_PROD_BOT_TOKEN` sentinel.
`crypto-invoice-handler.ts` implements the `/upgrade` crypto-paywall command. A
real, fail-closed integration.

### @oshun/telegram-miniapp

The static Telegram Mini App surfaces (`apps/oshun/telegram-miniapp`), a Next.js
app exposing seven read-oriented surfaces — `today` (Tara ritual), `sophia`
(grounded Q&A), `veritas` (claim review), `nyx` (sky), `arete` (check-in),
`nisaba` (reader), `illustration` (Isis card) — defined in
`src/app/surface-data.ts` and rendered through
`src/app/[surface]/SurfaceWorkspace.tsx`. `src/lib/telegram-webapp.ts` handles
the Telegram WebApp bridge. Honest scope note: the per-surface content in
`surface-data.ts` is curated, statically-typed launch fixture data (each
surface's evidence, provenance, and payload are hand-authored constants), so
this app demonstrates the Mini App surface shapes and Telegram integration
rather than serving live per-user domain data.

### @oshun/content-service-app

A small deployable shell, honestly thin (`apps/oshun/content-service`; the Nx
project name is `@oshun/content-service-app`, a single `src/main.ts` plus its
`package.json`). It is the process entrypoint for the agentic content service
(ledger §3.2): `main()` boots `createDurableContentService` /
`createContentHttpServer` from `@oshun/content-service` over an Iris-routed
Anthropic writer (`wrapSharedProvider(createAnthropicProvider())`) and a
three-member `JudgePanel` from `@oshun/content-quality-judge`, with creative
models pinned via `resolveCreativeModel`. It fails loud at startup without
`ANTHROPIC_API_KEY` ("generates with a real model or fails loud — it never
fabricates output") and supports `CONTENT_SERVICE_DISABLED_MODELS` for incident
downgrades. The real logic lives in the libraries it composes; this node is the
wiring + fail-loud guard around them, and the cloud deploy itself is tracked as
`[~]`.

### @oshun/clipper-extension

Browser clipper WebExtension (`apps/oshun/clipper-extension/src`): MV3
`background`/`content` scripts behind a typed `capture-contract`, a
`chrome-adapter` isolating the extension APIs, `clip-flow`/`clip-payload` for
capture-to-upload, and a `health-check` module — tested at the flow level
without a live browser.

### @oshun/wearable

Native watch companions for the OSHUN mobile app (`apps/oshun/wearable`):
`watchos/` (SwiftUI Swift Package) and `wearos/` (Kotlin/Jetpack Compose), both
implementing the companion contract whose canonical TypeScript source of truth
is `libs/oshun/shell-wearable` — streaks/milestones, complications, guided
breath sessions with amplitude-mapped haptics under battery/skin budgets, quiet
hours, and consent-gated summaries.
