# Lilith — Technical Specifications

> Technical reference for the Lilith consciousness-experience platform: package
> inventory, domain objects, state machines, event contracts, API surfaces,
> persistence, smart contracts, and configuration.
>
> **Grounding note.** Every entity, enum, event, endpoint, and contract below is
> traceable to source under `apps/lilith/*` and `libs/lilith/*`. Where the
> codebase only scaffolds a capability, that is stated explicitly.

---

This document is the authoritative technical reference for engineers building on
or maintaining Lilith. It covers the exact package inventory, type definitions,
state machine transition tables, event payload shapes, API routes, database
schemas, smart contracts, authentication implementation details, environment
variables, and integration points — drawn directly from the source code. Where
the architecture and feature docs provide context and rationale, this document
provides the precise contracts.

---

## Package Inventory

Lilith is the largest domain in the Oshun monorepo. The code lives in two trees:

- `apps/lilith/` — **78 packages**: 9 non-service packages (`bff`, `cli`,
  `contracts`, `desktop`, `locales`, `mobile`, `seed-corpus`, `shared`, `web`)
  and **69 `svc-*` backend services**.
- `libs/lilith/` — **9 shared libraries**.

### Shared Libraries (`libs/lilith/`)

The nine libraries provide Lilith-specific shared infrastructure. Each is a
separate npm package under the `@lilith/` scope:

| Directory                  | Package                           | Purpose                                                                                                               |
| -------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `common/`                  | `@lilith/common`                  | Audit logger, CSPRNG ID generation, HTTP status map, language detection, session store, server/service templates      |
| `continuous-video-policy/` | `@lilith/continuous-video-policy` | Crisis-frame, narrative-cadence, persona-cap, sensitive-topic, and strobe policy checks for continuous video sessions |
| `event-handlers/`          | `@lilith/event-handlers`          | Cross-domain event subscriptions (Bellona, Isis, Sophia, Yemaya) with WebSocket fan-out                               |
| `event-publisher/`         | `@lilith/event-publisher`         | Typed Lilith domain-event publishing to `@oshun/event-bus`                                                            |
| `fastify-core/`            | `@lilith/fastify-core`            | `createServiceServer()` bootstrap: health routes, error handler, middleware registry                                  |
| `partner-sdk/`             | `@lilith/partner-sdk`             | External partner SDK with auth flows                                                                                  |
| `sdk/`                     | `@lilith/sdk`                     | TypeScript client (`APIClient`, `LilithApiClient`) plus generated OpenAPI types                                       |
| `service-lib/`             | `@lilith/service-lib`             | `LilithLogger`, type-safety validator, typed test helpers/mocks                                                       |
| `sophia-adapter/`          | `@lilith/sophia-adapter`          | Knowledge-access, knowledge-graph, and embedding adapters bridging Lilith to Sophia                                   |

Cross-cutting infrastructure (config, errors, logging, metrics, tracing,
testing, types) is provided by monorepo-wide `@oshun/*` packages, not by
Lilith-local libraries. `@lilith/service-lib` declares `@oshun/tracing`,
`@oshun/logging`, `@oshun/metrics`, `@oshun/errors`, and `@oshun/types` as
direct dependencies, so any service that imports `@lilith/service-lib` inherits
the full `@oshun/*` observability stack automatically.

### Backend Services (`apps/lilith/svc-*`)

The 69 services group functionally as follows. Service maturity varies: some
(`svc-ai`, `svc-auth`, `svc-metaverse`, `svc-group-meditation`, `svc-tts`) carry
hundreds of source files, while several Web3 and commerce services
(`svc-dao-governance`, `svc-native-token`, `svc-tiered-subscription`,
`svc-creator-royalty`, `svc-curricula`) are single-app implementations of
roughly 1,400–3,000 lines.

| Cluster               | Services                                                                                                                                                                                                                                                                                                                                     |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Core platform         | `svc-auth`, `svc-auth-orchestrator`, `svc-conversation`, `svc-ai`, `svc-content`, `svc-media`, `svc-notification`, `svc-moderation`, `svc-error-handler`, `svc-real-time-sync`, `svc-sync`                                                                                                                                                   |
| AI & knowledge        | `svc-ai`, `svc-indexer`                                                                                                                                                                                                                                                                                                                      |
| Meditation & wellness | `svc-meditation-core`, `svc-meditation-experience`, `svc-meditation-generation`, `svc-group-meditation`, `svc-breathwork`, `svc-yoga-practice`, `svc-spiritual-guidance`, `svc-journal`, `svc-notes`, `svc-daily-content`                                                                                                                    |
| Voice & audio         | `svc-tts`, `svc-stt`, `svc-voice-pipeline`, `svc-audio-handoff`, `svc-webrtc`                                                                                                                                                                                                                                                                |
| Content & delivery    | `svc-catalog`, `svc-curricula`, `svc-review`, `svc-content-licensing`, `svc-content-verification`, `svc-rights-management`, `svc-teacher-blessing`                                                                                                                                                                                           |
| User & progress       | `svc-user-preferences`, `svc-progress-sync`, `svc-biometric`, `svc-offline`, `svc-analytics`                                                                                                                                                                                                                                                 |
| Commerce              | `svc-tiered-subscription`, `svc-payment-orchestrator`, `svc-creator-royalty`, `svc-partner-api`, `svc-avatar-cosmetic`                                                                                                                                                                                                                       |
| Web3 & blockchain     | `svc-blockchain`, `svc-native-token`, `svc-token-core`, `svc-token-access`, `svc-token-verification`, `svc-staking-mechanism`, `svc-dao-governance`, `svc-defi-integration`, `svc-cross-chain-bridge`, `svc-ipfs-integration`, `svc-micro-transaction`, `svc-fiat-ramp`, `svc-settlement`, `svc-transaction-core`, `svc-transaction-manager` |
| Immersive             | `svc-metaverse`                                                                                                                                                                                                                                                                                                                              |
| Infrastructure        | `svc-observability`, `svc-operational-excellence`, `svc-multi-region-resilience`, `svc-safety-automation`                                                                                                                                                                                                                                    |
| Privacy & governance  | `svc-anonymization`, `svc-consent-management`, `svc-data-governance`                                                                                                                                                                                                                                                                         |
| Localization          | `svc-language-detection`, `svc-community-translation`                                                                                                                                                                                                                                                                                        |

The following service names do **not** exist in the codebase:
`svc-veilborn-core`, `svc-veilborn-strategy`, `svc-generative-fractal`,
`svc-comfyui`, `svc-rag`, `svc-knowledge`, `svc-vectordb`,
`svc-spiritual-embeddings`, `svc-curator-admin`. Knowledge ingestion and
retrieval are delegated to Sophia through `@lilith/sophia-adapter`.

---

## Shared Library Contracts

### `@lilith/fastify-core`

`@lilith/fastify-core` is the standard bootstrap layer for all `svc-*` services.
The primary factory is `createServiceServer(options)`, which returns
`{ app, start, shutdown }`. A `CreateServiceServerOptions` object accepts a
`serviceName` and an optional `healthCheckFn` returning service-specific health
details. Health routes are Kubernetes-shaped (liveness/readiness).

Additional exports:

- `quickStart` — convenience wrapper for one-line service startup
- `registerHealthRoutes`, `createHealthHandler` — Kubernetes liveness/readiness
- `registerErrorHandler`, `createErrorResponse`, `createErrorHelper` —
  structured error handling
- `MiddlewareRegistry`, `createMiddlewareRegistry` — middleware composition

The package exports a typed error hierarchy for consistent HTTP error responses
across all services:

`ValidationError`, `UnauthorizedError`, `ForbiddenError`, `NotFoundError`,
`ConflictError`, `RateLimitError`, `ServiceUnavailableError`.

### `@lilith/service-lib`

`@lilith/service-lib` is the common runtime dependency bundle for Lilith
services. It exports `LilithLogger` (the structured logger used by
`apps/lilith/bff` and other services), a type-safety validator/suggestions
module, and typed test helpers (`typed-mocks`, `test-helpers`, `test-types`).

Runtime dependencies bundled in `@lilith/service-lib` (so individual services do
not need to declare them separately): `fastify`, `@fastify/cors`,
`@fastify/websocket`, `ioredis`, `pg`, `@elastic/elasticsearch`, `axios`,
`ajv` + `ajv-formats`, `aws-sdk`, `jsonwebtoken`, `isomorphic-dompurify`,
`validator`, and `semver`.

### `@lilith/sophia-adapter`

`@lilith/sophia-adapter` is the sole interface through which Lilith reads from
and writes to Sophia's knowledge APIs. It exposes three adapters, all configured
from a shared `SophiaAdapterConfig` object (`baseUrl`, optional
`apiKey`/`bearerToken`, `timeout` default 30000 ms, `retries` default 3,
`debug`):

- **`KnowledgeAccessAdapter`** — maps Lilith `ContentBundle`, `AccessPolicy`,
  and `AccessPass` records to Sophia document/search/metadata APIs.
- **`KnowledgeGraphAdapter`** — maps `LilithEntity`/`LilithRelation` to Sophia's
  entity/relationship graph with entity resolution.
- **`EmbeddingAdapter`** — routes embedding and similarity-search requests to
  Sophia.

Failures from any adapter raise `SophiaAdapterError`, which carries `operation`,
`underlyingCause`, and `details`. Static factory methods `syncFailed`,
`queryFailed`, and `embeddingFailed` construct typed error instances for each
failure mode.

---

## Domain Objects

The richest concrete domain model in the codebase belongs to
`svc-meditation-core`, `svc-conversation`, and the bridging types in
`@lilith/sophia-adapter`. The sections below document the exact type shapes from
source.

### Meditation Domain (`apps/lilith/svc-meditation-core/src/types.ts`)

#### `MeditationSession`

A `MeditationSession` is the central record for a user's practice attempt. It
carries both the static configuration set at session creation and mutable
runtime state (current stage, biometric readings, timestamps, pause accounting):

| Field             | Type                       | Meaning                                          |
| ----------------- | -------------------------- | ------------------------------------------------ |
| `id`              | `string`                   | Session identifier                               |
| `state`           | `SessionState`             | Current state-machine state                      |
| `mode`            | `string \| undefined`      | Selected mode id (`quick` / `standard` / `deep`) |
| `tradition`       | `string`                   | Wisdom tradition for the session                 |
| `guidanceLevel`   | `GuidanceLevel`            | `beginner` / `intermediate` / `advanced`         |
| `durationMinutes` | `number`                   | Target duration                                  |
| `intention`       | `string \| undefined`      | User-stated intention                            |
| `userId`          | `string \| undefined`      | Owning user                                      |
| `createdAt`       | `string`                   | Creation timestamp                               |
| `startedAt`       | `string \| null`           | Start timestamp                                  |
| `completedAt`     | `string \| null`           | Completion timestamp                             |
| `pausedAt`        | `string \| null`           | Last pause timestamp                             |
| `totalPausedMs`   | `number`                   | Cumulative paused duration                       |
| `currentStage`    | `MeditationStage \| null`  | Active stage                                     |
| `stageHistory`    | `StageHistoryEntry[]`      | Stage entry/exit log                             |
| `script`          | `MeditationScript \| null` | Generated/loaded narration script                |
| `audioUri`        | `string \| null`           | Audio asset URI                                  |
| `biometricData`   | `BiometricDataPoint[]`     | Captured biometric readings                      |
| `metadata`        | `SessionMetadata`          | Voice/speed/cancel-reason and free-form data     |
| `rating`          | `number` (optional)        | Post-session rating                              |
| `notes`           | `string` (optional)        | Post-session notes                               |

Supporting types used throughout the meditation domain:

- `SessionConfig` — session-creation input
- `SessionSummary` — reduced read model with `targetDurationMinutes`,
  `actualDurationMinutes`, `stagesCompleted`, `totalBiometricReadings`
- `MeditationScript` — `voicePreset`, `stages`, `durationMinutes`, `tradition`,
  `intention`, `experienceLevel`
- `MeditationScriptStage`, `MeditationScriptSegment` — narration content
- `StageHistoryEntry` — records entry and exit timestamps for each stage
- `BiometricDataPoint` — timestamped biometric reading
- `SessionMetadata` — voice, speed, cancel-reason, and free-form extension data

#### Meditation Modes (`mode.ts`)

The `DEFAULT_MODES` constant defines exactly three session modes. The
`selectMeditationMode()` function picks among them by preferred id, nearest
session length, or experience level:

| Mode id    | Display name    | Duration | Cadence   | Intensity  |
| ---------- | --------------- | -------- | --------- | ---------- |
| `quick`    | Quick Reset     | 5 min    | `concise` | `light`    |
| `standard` | Guided Practice | 12 min   | `steady`  | `moderate` |
| `deep`     | Deep Dive       | 20 min   | `slow`    | `deep`     |

### Conversation Domain (`apps/lilith/svc-conversation/src/types.ts`)

The conversation domain models multi-participant threaded chat with full LLM
integration. The core types form a containment hierarchy: a `Conversation`
contains `Thread`s; a `Thread` contains `Message`s:

- **`Message`** — `id`, `thread_id`/`conversationId`, `role`
  (`user`/`assistant`/`system`), `content`, `metadata`, `created_at`,
  `parentId`, `tokens`, `model`, `edited`, `attachments`, `reactions`.
- **`Thread`** — `id`, `title`, `metadata`, `message_count`, `messages`,
  `resolved`/`resolvedAt`/`resolvedBy`.
- **`Conversation`** — `id`, `userId`, `title`, `description`, `model`,
  `messages`, `archived`, `pinned`, `tags`, `settings`, `participants`, `status`
  (`active`/`archived`/`deleted`), `messageCount`.
- **`ConversationSettings`** — LLM sampling parameters: `temperature`,
  `maxTokens`, `topP`, `topK`, `frequencyPenalty`, `presencePenalty`,
  `systemPrompt`, `stopSequences`.
- **`Participant`** — `userId`, `role` (`owner`/`member`/`viewer`), `joinedAt`,
  `lastSeenAt`, `permissions`.
- **`Attachment`** — `type` (`image`/`file`/`audio`/`video`), `url`, `name`,
  `size`, `mimeType`.
- **`ChatResponse.finishReason`** — `stop` / `length` / `tool_calls` /
  `content_filter`.
- **`Tool` / `ToolCall`** — function-calling primitives for tool-use responses.
- Metrics read models: `ConversationMetricsTotals`,
  `ConversationMetricsSnapshot`, `ConversationMetricsResponse`,
  `ConversationMetricsUpdate`.
- `IdempotencyRecord` — ensures duplicate message submissions are safely
  deduplicated on ingest.

### Knowledge-Bridge Domain (`@lilith/sophia-adapter`)

These types define the objects that cross the Lilith–Sophia boundary. Lilith
creates `ContentBundle`, `AccessPolicy`, and `AccessPass` records locally; the
adapter translates them to Sophia's API format:

- **`ContentBundle`** — `bundleId`, `contentKey`, `title`, `summary`,
  `category`, `tradition?`, `lessons[]`, `media[]`, `difficulty`,
  `estimatedHours`, `createdAt`, `updatedAt`, `status`.
- **`AccessPolicy`** — `policyId`, `bundleId`, `tier`, `accessType`,
  `expiresAt?`, `allowedRoles?`, `requiredTokens?`, `maxSeats?`, `currentSeats`,
  `price?`, `currency?`, `createdAt`, `status`.
- **`AccessPass`** — `passId`, `seekerAddress`, `seekerName`, `bundleId`,
  `policyId`, `tokenId?`, `transactionHash?`, `network?`, `grantedAt`,
  `expiresAt?`, `status`, `metadata`.
- **`TokenRequirement`** — `contractAddress`, `chainId`, `minBalance` — used
  within `AccessPolicy` for on-chain token-gating.
- **`LilithEntity`** — `id`, `type`, `name`, `properties` — entities sent to the
  Sophia knowledge graph.
- **`LilithRelation`** — `id`, `sourceId`, `targetId`, `type`, `properties?` —
  edges sent to the Sophia knowledge graph.
- Graph result types: `GraphQueryResult`, `GraphResultNode`, `GraphResultEdge`,
  `RelatedEntity` (with `hops` and `path`), `ResolvedEntity` (with `confidence`
  and `matchedFields`).
- Embedding types: `EmbeddingResult` (`vector`, `model`, `dimensions`,
  `tokenCount`), `SimilarityOptions` (`topK`, `minScore`, `filter`),
  `SimilarityResult` (`documentId`, `chunkId`, `text`, `score`, `metadata?`).

### Enumerations

The table below lists all domain-level enums and union types, with their source
file and complete value sets. These are the valid values that appear in database
rows, event payloads, and API requests — use them verbatim:

| Enum / union             | Source                     | Values                                                                                                                                                          |
| ------------------------ | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SessionState`           | meditation-core `types.ts` | `idle`, `preparing`, `active`, `paused`, `completing`, `completed`, `cancelled`                                                                                 |
| `SessionEvent`           | meditation-core `types.ts` | `start`, `pause`, `resume`, `complete`, `cancel`, `timeout`, `error`                                                                                            |
| `GuidanceLevel`          | meditation-core `types.ts` | `beginner`, `intermediate`, `advanced`                                                                                                                          |
| `BiometricType`          | meditation-core `types.ts` | `heart_rate`, `hrv`, `breathing_rate`, `skin_conductance`, `brain_wave`                                                                                         |
| `MeditationStage`        | meditation-core `types.ts` | `arrival`, `breath`, `body`, `visualization`, `integration`                                                                                                     |
| `LilithMeditationType`   | event-publisher `types.ts` | `guided`, `silent`, `breathing`, `body_scan`, `visualization`, `mantra`, `movement`, `sleep`, `focus`, `custom`                                                 |
| `LilithMeditationTheme`  | event-publisher `types.ts` | `stress_relief`, `anxiety`, `sleep`, `focus`, `gratitude`, `self_love`, `forgiveness`, `mindfulness`, `energy`, `creativity`, `healing`, `spiritual`, `general` |
| `LilithCompletionStatus` | event-publisher `types.ts` | `completed`, `partial`, `abandoned`, `skipped`                                                                                                                  |
| `ContentCategory`        | sophia-adapter `types.ts`  | `course`, `meditation`, `scripture`, `teaching`, `practice`                                                                                                     |
| `Difficulty`             | sophia-adapter `types.ts`  | `beginner`, `intermediate`, `advanced`                                                                                                                          |
| `BundleStatus`           | sophia-adapter `types.ts`  | `draft`, `published`, `archived`                                                                                                                                |
| `AccessTier`             | sophia-adapter `types.ts`  | `free`, `basic`, `premium`, `exclusive`                                                                                                                         |
| `AccessType`             | sophia-adapter `types.ts`  | `perpetual`, `subscription`, `time_limited`, `token_gated`                                                                                                      |
| `PolicyStatus`           | sophia-adapter `types.ts`  | `active`, `paused`, `expired`                                                                                                                                   |
| `PassStatus`             | sophia-adapter `types.ts`  | `active`, `expired`, `revoked`                                                                                                                                  |
| `LilithEntityType`       | sophia-adapter `types.ts`  | `tradition`, `concept`, `figure`, `practice`, `text`, `place`                                                                                                   |
| `ChatMode`               | sdk `index.ts`             | `text`, `voice`                                                                                                                                                 |
| `Depth`                  | sdk `index.ts`             | `practical`, `scholarly`                                                                                                                                        |
| `ChatEventName`          | sdk `index.ts`             | `token`, `citations`, `audio`, `done`, `error`                                                                                                                  |

---

## State Machines

### Meditation Session State Machine

`svc-meditation-core/src/types.ts` defines the transition tables that govern a
`MeditationSession`. The machine has seven states, two of which are terminal.
Understanding the valid transitions is important for any code that drives a
session programmatically — sending an event from an invalid state results in an
error transition rather than being silently ignored.

**States:** `idle`, `preparing`, `active`, `paused`, `completing`, `completed`,
`cancelled`. `completed` and `cancelled` are terminal states with no outgoing
transitions.

The `STATE_TRANSITIONS` table specifies which events are legal from each state:

| State        | Allowed events                         |
| ------------ | -------------------------------------- |
| `idle`       | `start`                                |
| `preparing`  | `start`, `cancel`, `error`             |
| `active`     | `pause`, `complete`, `cancel`, `error` |
| `paused`     | `resume`, `complete`, `cancel`         |
| `completing` | `complete`, `error`                    |
| `completed`  | (none)                                 |
| `cancelled`  | (none)                                 |

The `NEXT_STATE` table is keyed by the `${state}:${event}` `TransitionKey` and
gives the resulting state for each valid transition:

| Transition            | Result state |
| --------------------- | ------------ |
| `idle:start`          | `preparing`  |
| `preparing:start`     | `active`     |
| `preparing:cancel`    | `cancelled`  |
| `preparing:error`     | `cancelled`  |
| `active:pause`        | `paused`     |
| `active:complete`     | `completing` |
| `active:cancel`       | `cancelled`  |
| `active:error`        | `cancelled`  |
| `paused:resume`       | `active`     |
| `paused:complete`     | `completing` |
| `paused:cancel`       | `cancelled`  |
| `completing:complete` | `completed`  |
| `completing:error`    | `cancelled`  |

Within an active session, content delivery progresses through five ordered
`MeditationStage` values:
`arrival → breath → body → visualization → integration`. Stage transitions are
recorded in `stageHistory`.

---

## Event Contracts

Lilith integrates with the monorepo `@oshun/event-bus` (Redis Streams), created
with `sourceDomain: 'lilith'`. Events cross domain boundaries without requiring
direct HTTP service-to-service calls, which keeps integration loose and allows
independent scaling and deployment.

### Events Published by Lilith (`@lilith/event-publisher`)

`LilithEventTypes` defines exactly ten event types. `LilithEventPublisher`
exposes one typed publish method per event and routes each to default target
domains. All publish calls accept `PublishOptions`, which carry `correlationId`,
`causationId`, `targets` (override default targets), and a `metadata` block
(`serviceName`, `userId`, `sessionId`, `deviceType`, `appVersion`).

| Event type                    | Publish method               | Default targets    | Payload type                       |
| ----------------------------- | ---------------------------- | ------------------ | ---------------------------------- |
| `lilith.meditation.started`   | `publishMeditationStarted`   | `hathor`, `isis`   | `LilithMeditationStartedPayload`   |
| `lilith.meditation.completed` | `publishMeditationCompleted` | `hathor`, `sophia` | `LilithMeditationCompletedPayload` |
| `lilith.meditation.generated` | `publishMeditationGenerated` | `isis`, `sophia`   | `LilithMeditationGeneratedPayload` |
| `lilith.journal.created`      | `publishJournalCreated`      | `sophia`           | `LilithJournalCreatedPayload`      |
| `lilith.journal.updated`      | `publishJournalUpdated`      | `sophia`           | `LilithJournalUpdatedPayload`      |
| `lilith.session.started`      | `publishSessionStarted`      | publisher default  | `LilithSessionStartedPayload`      |
| `lilith.session.ended`        | `publishSessionEnded`        | publisher default  | `LilithSessionEndedPayload`        |
| `lilith.progress.updated`     | `publishProgressUpdated`     | `hathor`, `sophia` | `LilithProgressUpdatedPayload`     |
| `lilith.teacher.interaction`  | `publishTeacherInteraction`  | `isis`, `sophia`   | `LilithTeacherInteractionPayload`  |
| `lilith.content.downloaded`   | `publishContentDownloaded`   | publisher default  | `LilithContentDownloadedPayload`   |

The publisher `defaultTargets` fallback is `['hathor', 'isis', 'sophia']`.

Representative payload shapes for the most information-dense event types:

**`LilithMeditationCompletedPayload`** — the richest event payload, containing
session outcome data that downstream domains (Hathor for narrative progression,
Sophia for knowledge indexing) rely on:

- `meditationId`, `sessionId`, `userId`, `contentId?`
- `type` (`LilithMeditationType`), `theme?` (`LilithMeditationTheme`)
- `plannedDurationSeconds`, `actualDurationSeconds`
- `completionStatus` (`LilithCompletionStatus`), `completionPercentage`
- `teacherId?`, `streakCount?`, `totalSessionsCount?`
- `feedback?` — `rating`, `mood_before`, `mood_after`, `notes`

**`LilithProgressUpdatedPayload`** — progress milestones consumed by Hathor for
world-state progression and Sophia for user modeling:

- `userId`, `progressType` (`streak`/`milestone`/`achievement`/`level_up`)
- `currentStreak`, `longestStreak`, `totalMinutes`, `totalSessions`
- `achievementId?`, `achievementName?`, `level?`, `experiencePoints?`

**`LilithJournalCreatedPayload`** — journal metadata routed to Sophia for
knowledge graph enrichment:

- `entryId`, `userId`
- `type` (`free_form`/`guided`/`gratitude`/`reflection`/`dream`/`intention`)
- `wordCount`, `promptId?`, `linkedMeditationId?`, `mood?`, `tags?`, `isPrivate`

### Events Consumed by Lilith (`@lilith/event-handlers`)

`LILITH_SUBSCRIPTIONS` registers eight cross-domain subscriptions.
`setupLilithEventHandlers()` requires a fully wired `LilithHandlerServices`
bundle (`cache`, `metrics`, `notifications`, `scheduler`, `rooms`, `projects`)
and calls `assertServicesWired` at startup — a missing service member fails fast
rather than producing silent runtime errors.

Each handler invalidates caches, broadcasts to project WebSocket rooms, sends
per-user notifications, and records metrics. **No handler writes to
authoritative storage** — these are fan-out-only side effects.

| Event type                | Source domain | Handler                       | Default concurrency |
| ------------------------- | ------------- | ----------------------------- | ------------------- |
| `bellona.build.completed` | Bellona       | `handleBellonaBuildCompleted` | 5                   |
| `bellona.export.ready`    | Bellona       | `handleBellonaExportReady`    | 10                  |
| `isis.job.progress`       | Isis          | `handleIsisJobProgress`       | 50                  |
| `isis.job.completed`      | Isis          | `handleIsisJobCompleted`      | 20                  |
| `isis.job.failed`         | Isis          | `handleIsisJobFailed`         | 10                  |
| `isis.asset.generated`    | Isis          | `handleIsisAssetGenerated`    | 20                  |
| `sophia.index.updated`    | Sophia        | `handleSophiaIndexUpdated`    | 5                   |
| `yemaya.project.updated`  | Yemaya        | `handleYemayaProjectUpdated`  | 20                  |

Inbound payload types (`IsisAssetGeneratedPayload`, `SophiaIndexUpdatedPayload`,
`BellonaBuildCompletedPayload`, `BellonaExportReadyPayload`,
`YemayaProjectUpdatedPayload`, `IsisJobCompletedPayload`,
`IsisJobProgressPayload`, `IsisJobFailedPayload`) are defined in
`event-handlers/src/types.ts`.

---

## API Surface

### BFF — the Client Entry Point (`apps/lilith/bff`)

The BFF (`@lilith/bff`) is the single external entry point for all clients: a
Fastify server that proxies backend services, exposes GraphQL via Mercurius, and
streams AI chat responses over SSE. Its `server.ts` defaults `SERVICE_NAME` to
`bff` and `PORT` to `4000`; both are overridable via environment variables. The
published library README documents an API base of port `4006`.

`app.impl.ts` registers the following route groups (source files live under
`apps/lilith/bff/src/routes/` or `src/api/`):

`registerContentRoutes`, `registerGraphQLRoutes`, `registerWebhookRoutes`,
`registerAuthProxyRoutes`, `registerChatCoreRoutes`,
`registerContentFallbackRoutes`, `registerCurriculaRoutes`,
`registerErrorManagementRoutes`, `registerExperimentsAndModelsRoutes`,
`registerHealthRoutes`, `registerIsisGenerationRoutes`,
`registerMendeleyOAuthRoutes`, `registerObservabilityRoutes`,
`registerPaperExportRoutes`, `registerPartnerRoutes`, `registerPersonaRoutes`,
`registerReflectionsRoutes`, `registerScholarNotesRoutes`,
`registerSophiaKnowledgeRoutes`, `registerSophiaSearchRoutes`,
`registerUserRoutes`.

#### Representative REST Routes (all `/v1/`-prefixed)

The BFF exposes a broad REST surface covering all product areas. All routes are
prefixed with `/v1/`:

| Route                                                                             | Purpose                         |
| --------------------------------------------------------------------------------- | ------------------------------- |
| `GET /v1/health`                                                                  | Health check                    |
| `GET /v1/docs`                                                                    | API documentation               |
| `GET /v1/personas`, `GET /v1/personas/:personaId`                                 | AI persona catalog              |
| `GET /v1/personas/category/:category`                                             | Personas by category            |
| `GET /v1/curricula`, `GET /v1/curricula/:id`                                      | Learning-path catalog           |
| `POST /v1/curricula/:id/enroll`                                                   | Enroll in a curriculum          |
| `GET /v1/curricula/:id/progress`                                                  | Curriculum progress             |
| `POST /v1/curricula/:curriculum_id/lessons/:lesson_id/complete`                   | Mark lesson complete            |
| `GET/POST /v1/notes`, `/v1/notes/:id`                                             | Scholar notes                   |
| `GET /v1/notes/search`, `/v1/notes/tags`, `/v1/notes/recent`                      | Notes search and organization   |
| `GET/POST /v1/notes/collections`                                                  | Note collections                |
| `GET/POST /v1/highlights`, `/v1/highlights/:id`                                   | Content highlights              |
| `GET/POST /v1/reflections`, `/v1/reflections/:id`                                 | Reflections journal             |
| `GET /v1/reflections/today`, `/streak`, `/stats`, `/patterns`, `/calendar/:month` | Reflection insights             |
| `GET /v1/kg/search`, `/v1/kg/nodes`, `/v1/kg/nodes/:entityId`                     | Sophia-backed knowledge graph   |
| `GET /v1/kg/nodes/:entityId/neighbors`, `/traverse`                               | Graph traversal                 |
| `GET /v1/kg/paths`                                                                | Multi-hop path lookup           |
| `GET /v1/kg/documents`, `/v1/kg/documents/:documentId`                            | Knowledge documents             |
| `POST /v1/knowledge/ask`                                                          | Grounded answer generation      |
| `POST /v1/capability/knowledge/search`, `/ingest`                                 | Capability-routed knowledge ops |
| `POST /v1/capability/generation/jobs`                                             | Isis-routed generation jobs     |
| `GET /v1/capability/generation/jobs/:jobId`, `POST .../cancel`                    | Generation job status/cancel    |
| `GET /v1/capability/outputs/:outputId`                                            | Generation output retrieval     |
| `GET /v1/capability/workflows`                                                    | Available generation workflows  |
| `GET/POST /v1/users/:userId/preferences`                                          | User preferences                |
| `GET /v1/users/:userId/activity`, `/activity/stats`                               | User activity                   |
| `GET /v1/users/:userId/export`                                                    | Personal-data export            |
| `GET/POST /v1/users/:userId/memory`, `/memory/controls`                           | Conversation memory controls    |
| `GET/POST /v1/users/:userId/language-preferences`                                 | Language preferences            |
| `GET /v1/tiers`                                                                   | Subscription tiers              |
| `POST /v1/partners/register`, `/v1/partners/:partnerId/approve`                   | Partner onboarding              |
| `* /v1/partners/:partnerId/api-keys`, `/webhooks`, `/analytics`                   | Partner management              |
| `POST /v1/partner/chat`, `/v1/partner/content`, `/v1/partner/tts/synthesize`      | Partner-facing APIs             |
| `POST /v1/exports/papers`, `GET .../:jobId/download`, `.../stream`                | Paper-export jobs               |
| `GET /v1/insights`, `POST /v1/insights/generate`                                  | Insights                        |

The BFF also exposes Mendeley OAuth routes (`mendeley-oauth-routes.ts`),
experiment/model routes, observability routes, and a `chat-audio-routes` group.
A `comfyui-routes.ts` module exists alongside `isis-generation-routes.ts` under
`src/routes/`.

#### Chat SSE Streaming

`chat-orchestration-streaming.ts` streams an AI chat response as Server-Sent
Events. The event sequence follows a strict protocol that clients must handle in
order:

1. **`start`** — signals the beginning of a new stream; carries stream metadata.
2. **`token`** (repeated) — one content chunk per event, accumulated into the
   final response.
3. **`citations`** — RAG source attributions and retrieval metadata, emitted
   once after all tokens.
4. **`done`** — signals end of stream; carries usage metrics and the complete
   assembled response.

```
event: start       data: {streamId, persona, correlationId, conversationId, createdAt}
event: token       data: {index, text, correlationId}        (repeated)
event: citations   data: {citations, correlationId, retrievalResults?, ragMetadata?}
event: done        data: {streamId, totalTokens, correlationId, persona, response, metrics}
```

The `metrics` field on the `done` event carries `tokens_in`, `tokens_out`, and
`latency_ms`. The SDK's `ChatEventName` union (`token`, `citations`, `audio`,
`done`, `error`) is the client-side counterpart for typed SSE parsing.

#### BFF GraphQL Schema (`apps/lilith/bff/src/api/graphql/schema.ts`)

The GraphQL layer focuses on content and knowledge-graph operations, not session
or meditation management. Session-oriented flows use the REST API. The schema
exposes:

```graphql
type Query {
  content(id: ID!): Content
  contentBySlug(slug: String!): Content
  contents(first, after, last, before, filter, sort): ContentConnection!
  searchContent(query: String!, first, after, filter): SearchResult!
  suggestions(query: String!, limit: Int): [SearchSuggestion!]!
  author(id: ID!): Author
  authors(first, after, query): AuthorConnection!
  entity(id: ID!): Entity
  entities(first, after, filter): EntityConnection!
  entityTypes: [EntityType!]!
  relationship(id: ID!): Relationship
  relationshipsByEntity(entityId: ID!): [Relationship!]!
  relationshipTypes: [RelationshipType!]!
  knowledgeGraph(entityIds: [ID!]!, depth: Int, relationshipTypes): KnowledgeGraphResult!
}

type Mutation {
  createContent / updateContent / deleteContent / publishContent / archiveContent
  restoreContentVersion / bulkContentOperation
  createAuthor / updateAuthor / deleteAuthor
  createEntity / updateEntity / deleteEntity
  createRelationship / updateRelationship / deleteRelationship
}

type Subscription {
  contentUpdated(filter): ContentUpdateEvent!
  contentCreated: ContentUpdateEvent!
  contentPublished: ContentUpdateEvent!
  entityUpdated(types): EntityUpdateEvent!
}
```

### `svc-auth` API (`apps/lilith/svc-auth`)

`svc-auth` is one of the largest services in the codebase (164 source files).
All routes are `/v1/auth/`-prefixed. The service covers every modern
authentication pattern:

- **Registration / login** — `POST /v1/auth/register`,
  `POST /v1/auth/register-pseudonymous`, `POST /v1/auth/login`,
  `POST /v1/auth/login-pseudonymous`, `POST /v1/auth/logout`.
- **Tokens** — `POST /v1/auth/refresh`, `POST /v1/auth/token`,
  `POST /v1/auth/revoke`, `POST /v1/auth/introspect`, `GET /v1/auth/jwks`,
  `GET /v1/auth/validate`, `GET /v1/auth/userinfo`.
- **Passwords** — `POST /v1/auth/password/change`, `/password/confirm`,
  `/password/reset`, `/password/reset-request`,
  `/password/reset/validate/:token`, `/password/requirements`;
  `POST /v1/auth/password-reset/request`, `/password-reset/confirm`,
  `POST /v1/auth/change-password`.
- **Two-factor / MFA** — `POST /v1/auth/2fa/enable`, `/2fa/disable`,
  `/2fa/verify`, `/2fa/validate`, `GET /v1/auth/2fa/status`,
  `/2fa/backup-codes/regenerate`; SMS OTP under `/2fa/sms/*` (`enroll`,
  `request`, `resend`, `validate`, `verify`); `POST /v1/auth/mfa/toggle`.
- **WebAuthn** — `POST /v1/auth/webauthn/registration/begin`,
  `POST /v1/auth/webauthn/authenticate`.
- **Magic link** — `POST /v1/auth/magic-link`, `/magic-link/request`,
  `/magic-link/authenticate`.
- **OAuth** — `GET /v1/auth/oauth/providers`, `/oauth/authorize`,
  `/oauth/callback`, `/oauth/google`, `/oauth/github`,
  `POST /v1/auth/social/link`.
- **Email verification** — `POST /v1/auth/verify/email`,
  `GET /v1/auth/verify/email/:token`, `/verify/status/:email`.
- **Sessions** — `GET /v1/auth/sessions`, `DELETE /v1/auth/sessions/:sessionId`,
  `/sessions/revoke-all`.
- **Account & data rights** — `GET /v1/auth/profile`, `/v1/auth/account`,
  `/v1/auth/export`, `/v1/auth/audit-logs`; API keys under `/v1/auth/api-keys`
  and `/v1/auth/api-keys/:keyId`.

`svc-auth` source modules cover RBAC (`rbac.ts`, `rbac-enhanced.ts`,
`rbac-evaluator.ts`, `rbac-system-roles.ts`), bot detection (`bot-detection-*`),
a WAF (`waf-middleware.ts`, `waf-rules.ts`), IP filtering, breach detection,
CAPTCHA, account lockout, encryption (envelope/KMS/Vault), audit logging,
data-subject-request (DSR) handling, age verification, and parental consent.

### `svc-conversation` API

Real-time chat with threading. Routes live under `svc-conversation/src/routes/`
(`participants.ts`, `sharing.ts`, `index.ts`); the service supports WebSocket
connections and a conversation `reset` endpoint.

### SDK Client Surface (`@lilith/sdk`)

`APIClient` makes REST calls to `${baseUrl}/v1/...`. Its methods cover all
platform domains:

- **Chat** — `chat(ChatRequest)` and `streamChat()` → `POST /v1/chat`; the
  latter parses the SSE stream.
- **Conversations** — `listConversations`, `getConversation`,
  `deleteConversation`, `getConversationMessages`, `resetConversation` →
  `/v1/conversations[...]`.
- **Lectures and TTS** — `generateLecture` → `POST /v1/lectures`;
  `ttsSynthesize` → `POST /v1/tts:synthesize`.
- **Ingestion and notifications** — `ingest` → `POST /v1/ingest`;
  `sendTestNotification` → `POST /v1/notifications/test`.
- **Consciousness catalog** — methods for reading the mythology and
  consciousness domain catalog, each mapping to a specific REST path:
  - `listVisionQuestJournals` → `/v1/mythology/vision-quests`
  - `listEgoDeathSimulations` → `/v1/consciousness/ego-death-simulations`
  - `listCollectiveUnconsciousMaps` → `/v1/consciousness/collective-unconscious`
  - `listNoosphereNetworks` → `/v1/consciousness/noosphere`
  - `listSimulationProbes` → `/v1/consciousness/simulation-theory`
  - `listDigitalImmortalityPrograms` →
    `/v1/consciousness/digital-immortality-prep`
  - `listDivinationSystems` → `/v1/divination/oracles`
  - `listCollaborativeMythologyWorlds` → `/v1/mythology/collaborations`
  - `listConsciousnessResearchProjects` → `/v1/consciousness/research-projects`
  - Each has a matching `get…(slug)` detail call.
- **Admin** — `adminUpdateUserRoles`, `adminGetUserAuditLogs`, backup/restore
  (`createBackup`, `listBackups`, `getBackupStatus`, `deleteBackup`,
  `createRestore`, `getRestoreStatus`), system (`getSystemHealth`,
  `getSystemConfig`, `setMaintenanceMode`, `getMaintenanceStatus`),
  agents/workflows, and autoscaling (`getAutoscalingStatus`,
  `executeScalingAction`, `getGPUMetrics`).

`LilithApiClient` is a lower-level generic client exposing `get`/`post`/`put`/
`patch`/`delete`. The package re-exports an `auth` and `seamless-auth` module
plus a `SeamlessErrorClassifier`.

---

## Persistence

Each service owns its schema and migrates independently with **Knex.js**
(`db/migrations/` + `db/knexfile.ts`). There are no shared cross-service foreign
keys in the database layer — this is a hard architectural constraint, not just
convention. Services communicate via events and HTTP, never via database joins.

### `svc-auth` (10 migrations)

The auth schema covers the full user lifecycle from registration through
multi-device session management. Tables:

`users`, `user_profiles`, `user_sessions`, `refresh_tokens`,
`oauth_connections`, `verification_tokens`, `audit_logs`,
`webauthn_credentials`, plus check-constraint and session-column migrations.

### `svc-conversation` (8 migrations)

The conversation schema models threaded multi-participant chat with LLM
metadata. Key tables and their most important columns:

`threads` — `id` (uuid), `user_id`, `title`, `summary`, an enum `type`
(`general`, `meditation_guidance`, `spiritual_discussion`, `learning_session`,
`reflection`, `counseling`, `q_and_a`), `persona_id`, `persona_name`.

`messages` — `id` (uuid), `thread_id` (FK → `threads`, cascade), enum `role`
(`user`, `assistant`, `system`, `tool`), `user_id`, `content`, `content_html`,
`content_parts` (jsonb), enum `type` (`text`, `audio`, `image`, `mixed`,
`system_notification`, `tool_call`, `tool_result`), `sequence_number`,
`parent_id` (self-FK), `model`, `model_version`, `prompt_tokens`,
`completion_tokens`, `total_tokens`.

Additional tables: `message_citations`, `message_feedback`,
`conversation_summaries`, `conversation_participants`, `conversation_shares`.

### `svc-meditation-core` (6 migrations)

The meditation core schema persists session state, user progress, and
scheduling. The primary table:

`meditation_sessions` — `session_id` (pk, string), `user_id` (uuid, indexed),
`completed_at`, `duration_minutes`, `actual_duration_minutes`, `mode`,
`tradition`, `guidance_level`, `intention`, `biometric_summary` (jsonb),
`stages_completed`, `rating` (smallint, 1–5), `notes`, `created_at`,
`updated_at` (with `update_updated_at_column()` trigger).

Additional tables: `meditation_achievements`, `meditation_goals`,
`meditation_streaks`, `meditation_schedules`, plus a check-constraint migration.

`svc-meditation-core` ships PostgreSQL-backed storage classes —
`postgres-progress-storage.ts`, `postgres-schedule-storage.ts`,
`postgres-streak-storage.ts` — as reusable modules.

### Other Stores

Beyond PostgreSQL, Lilith uses three additional storage systems:

- **Redis** — caching, session storage (`svc-conversation` has a
  `session/redis-store.ts` alongside a `memory-store.ts`), pub/sub fan-out, and
  job queueing via BullMQ.
- **Elasticsearch** — content search and structured log aggregation
  (`@lilith/service-lib` ships an `@elastic/elasticsearch` client dependency).
- **Object storage** — S3-compatible (MinIO in dev, S3 in prod) for media and
  audio; `svc-ai` depends on `@aws-sdk/client-s3` and `s3-request-presigner`.

---

## Smart Contracts

Smart contracts live in `apps/lilith/contracts` (`@lilith/contracts`), built
with Hardhat and Foundry. The production Solidity sources under
`contracts/contracts/` define the on-chain access and rights infrastructure:

| Contract                    | Standard / type                            | Purpose                                                                                                                                                    |
| --------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AccessToken.sol`           | ERC-1155 multi-token                       | Subscription / access-control tokens (Basic, Premium, Lifetime); time-based expiration; non-transferable; payment distribution with platform fees          |
| `ContentLicenseNFT.sol`     | ERC-721 (with IERC2981)                    | Content-licensing and attribution NFTs; license types and scopes; royalty distribution; manifest metadata anchoring                                        |
| `CreatorRoyalties.sol`      | Royalty + licensing registry               | Creator onboarding/verification/reputation; license registration with collaborator splits; automatic royalty distribution; `purchaseLicenseFor` delegation |
| `RoyaltyLicenseManager.sol` | Marketplace hub                            | One-click license purchase: calls `CreatorRoyalties.purchaseLicenseFor` and mints a matching `ContentLicenseNFT` in one transaction; pull-payment refunds  |
| `IdentityReputation.sol`    | Identity / reputation                      | Verifiable identity claims with challenge flow; ECDSA-signed attestations                                                                                  |
| `ContentProvenance.sol`     | Provenance anchor (top-level `contracts/`) | On-chain content-provenance anchoring                                                                                                                      |
| `MockERC20.sol`             | Test ERC-20                                | Test fixture token                                                                                                                                         |

Upgradeable variants exist under `contracts/upgradeable/`
(`AccessTokenUpgradeable`, `ContentLicenseNFTUpgradeable`,
`CreatorRoyaltiesUpgradeable`, `IdentityReputationUpgradeable`). A
`FlashLoanGuard` security mixin lives under `contracts/security/`, and
reentrancy/malicious-recipient mocks under `contracts/mocks/`. All production
contracts inherit OpenZeppelin `Ownable2Step`, `Pausable`, `ReentrancyGuard`.
Deployment scripts target localhost (Hardhat), Sepolia, and Polygon.

The following contract names do **not** exist in the codebase: `LilithToken`,
`LilithGovernance`, `LilithStaking`, `LilithNFT`, `LilithBridge`. The on-chain
surface is access-token, content-licensing, royalty, and identity-reputation —
not a single named platform token contract.

---

## Authentication

### JWT

`svc-auth` issues and validates JWTs. RSA key management lives in `rsa-keys.ts`
and `jwt-security.ts`/`jwt-utils.ts`. The service exposes a JWKS endpoint
(`GET /v1/auth/jwks`) so other services can fetch public keys for offline
validation, and an introspection endpoint (`POST /v1/auth/introspect`) for
active token inspection. `jsonwebtoken` is a `@lilith/service-lib` dependency,
so all services have JWT utilities available without additional declarations.

### Passwordless and Multi-Factor

`svc-auth` implements every common MFA and passwordless pattern:

- **WebAuthn/FIDO2** — `webauthn-routes.ts`, passkeys stored in device secure
  enclave; phishing-resistant by design.
- **TOTP** — `totp-service.ts`, compatible with Google Authenticator and Authy.
- **SMS OTP** — `sms-otp-service.ts`, `twilio-sms.ts`; Twilio is the delivery
  provider.
- **Magic links** — `magic-link-routes.ts`; time-limited, single-use login links
  delivered via email.
- **OAuth** — `oauth-service.ts`, `oauth-providers.ts`; Google and GitHub
  observed as active providers.

Password security is enforced through `password-validation.ts` and
`password-requirements.ts`, with `password-history.ts` preventing reuse and
`breach-detection.ts` checking credentials against known breach databases.

### API Keys

API-key issuance and management are handled under `/v1/auth/api-keys`
(`api-key-routes.ts`). The BFF partner routes additionally manage partner-scoped
API keys under `svc-partner-api`.

### Pseudonymous Identity

`svc-auth` supports pseudonymous registration and login (`pseudonymous-auth.ts`,
`/v1/auth/register-pseudonymous`, `/v1/auth/login-pseudonymous`) for users who
do not wish to provide personally identifying information.

---

## Configuration

Configuration is loaded and validated at service startup using
`loadAndValidateConfig` from `@oshun/config/legacy` with a `baseServiceSchema`.
Required variables cause a fast-fail at startup rather than producing silent
runtime errors when a key is missing.

### Observed Environment Variables

| Variable                      | Used by         | Purpose                                                        |
| ----------------------------- | --------------- | -------------------------------------------------------------- |
| `SERVICE_NAME`                | all services    | Logical service name (BFF default `bff`)                       |
| `PORT`                        | all services    | Listen port (BFF default `4000`)                               |
| `NODE_ENV`                    | all services    | Runtime environment                                            |
| `REDIS_URL`                   | event-publisher | Event-bus / cache Redis URL (default `redis://localhost:6379`) |
| `SOPHIA_API_KEY`              | sophia-adapter  | Sophia API authentication                                      |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | tracing         | OpenTelemetry collector endpoint                               |

`svc-ai` additionally relies on AWS credentials for S3 access via the AWS SDK.
Service ports beyond the BFF are assigned per service through the same `PORT`
env mechanism rather than a fixed global map.

### Local Infrastructure

The dev `docker-compose.dev.yml` provisions all dependencies a developer needs
to run Lilith locally. Core services started by default:

- PostgreSQL (`pgvector/pgvector:pg16`) with PgBouncer connection pooling
- Redis 7
- MinIO (S3-compatible object storage)
- Elasticsearch 8.11
- Mailpit (local email capture)
- Jaeger (distributed tracing)

Optional profiles: Qdrant (vectors), Kafka (streaming), Neo4j (graph),
Prometheus and Grafana (observability dashboards).

---

## Integration Points

### Inter-Service Communication

Lilith services communicate through three mechanisms, each suited to different
interaction patterns:

1. **HTTP** — synchronous request-response calls between services (Axios is
   bundled in `@lilith/service-lib`). Used when the caller needs an immediate
   result.
2. **`@oshun/event-bus` (Redis Streams)** — asynchronous domain events published
   by `@lilith/event-publisher` and consumed by `@lilith/event-handlers`. Used
   for cross-domain side-effects that do not require a synchronous response.
3. **WebSocket** — real-time bidirectional communication for chat
   (`svc-conversation`), data sync (`svc-real-time-sync`, `svc-sync`), group
   meditation (`svc-group-meditation`), and the event-handlers' client fan-out.

### Cross-Domain Integration

| Integration      | Direction      | Channel                  | Detail                                                                                                 |
| ---------------- | -------------- | ------------------------ | ------------------------------------------------------------------------------------------------------ |
| Lilith → Hathor  | Outbound event | `@oshun/event-bus`       | `meditation.started`, `meditation.completed`, `progress.updated`                                       |
| Lilith → Isis    | Outbound event | `@oshun/event-bus`       | `meditation.started`, `meditation.generated`, `teacher.interaction`                                    |
| Lilith → Sophia  | Outbound event | `@oshun/event-bus`       | `meditation.completed`, `meditation.generated`, `journal.*`, `progress.updated`, `teacher.interaction` |
| Lilith ↔ Sophia  | Outbound HTTP  | `@lilith/sophia-adapter` | Knowledge access, knowledge graph, embeddings                                                          |
| Bellona → Lilith | Inbound event  | `@oshun/event-bus`       | `bellona.build.completed`, `bellona.export.ready`                                                      |
| Isis → Lilith    | Inbound event  | `@oshun/event-bus`       | `isis.job.progress`, `isis.job.completed`, `isis.job.failed`, `isis.asset.generated`                   |
| Sophia → Lilith  | Inbound event  | `@oshun/event-bus`       | `sophia.index.updated`                                                                                 |
| Yemaya → Lilith  | Inbound event  | `@oshun/event-bus`       | `yemaya.project.updated`                                                                               |

The BFF brokers Isis generation through `isis-generation-routes.ts` and the
`/v1/capability/generation/*` routes; `svc-ai` depends directly on
`@isis/client` for LLM calls.

### External Providers

| Provider                                 | Used by          | Purpose                                              |
| ---------------------------------------- | ---------------- | ---------------------------------------------------- |
| AWS S3                                   | `svc-ai`, others | Media / audio object storage                         |
| Twilio                                   | `svc-auth`       | SMS OTP delivery                                     |
| OAuth (Google, GitHub)                   | `svc-auth`       | Federated login                                      |
| Mendeley                                 | `bff`            | Reference-manager OAuth (`mendeley-oauth-routes.ts`) |
| Elasticsearch                            | `service-lib`    | Search and log aggregation                           |
| EVM chains (Hardhat / Sepolia / Polygon) | `contracts`      | Smart-contract deployment targets                    |
