> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ooneex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat Resource

> A ready-to-run spec that scaffolds the `chat` module as a user-owned, three-level conversation store — conversations group driver-run histories, and each history holds its messages — with owner/admin permissions on every mutation.

## The prompt

```yaml theme={null}
title: "Scaffold the chat module and its resources"
context: |
  Build a `chat` domain: the persisted record of a user's AI conversations, a
  three-level hierarchy — a conversation groups driver runs (histories), each
  history holds ordered messages. The `@ooneex/ai` package already defines the
  base shape: `ChatConversationEntity`, `ChatHistoryEntity`, `ChatMessageEntity`
  (plus `flattenContent`) — align to those. A conversation is private: a user
  sees/edits only their own; an admin manages any. Auth is owner-or-admin on
  every read/list/mutation; histories and messages have no independent owner —
  they inherit the conversation's. If `modules/chat/` already exists, this work
  is void — do not run.
goal: |
  Create the `chat` module + needed resources, wired owner-or-admin on every op.

  ## Notes
  - If `modules/chat/` exists, STOP and report. Else `/module:create` chat, then
    build each resource via its `*:create` skill (`--module=chat`), respecting
    controllers → services → repositories → entities, registering all.
  - Dependency — `user`. Resolve before the `/module:create` step above: if
    `modules/user/` is missing, create it FIRST from its prompt at
    https://docs.ooneex.com/ai/prompts/resources/user-resource.
  - Model the three entities against `@ooneex/ai`: `ChatConversation` /
    `ChatHistory` / `ChatMessage` mirror their `*Entity`; reuse `MessageType` and
    `flattenContent`.
  - Judge each resource; create the justified, skip the rest with a reason.
    Defaults: entity + repository always (all three); service + controller per use
    case (start conversation, append history, append messages, read/list own with
    nested data, delete); permission always (owner-or-admin on reads/lists/writes
    so no user loads another's data, reuse the permission service); migration if
    the project uses migrations (mirror package migrations — index `chat_messages`
    on `(chat_history_id, created_at)`); event only if a real subscriber;
    translation/storage/seed/queue/workflow skip (user data, multimodal parts
    referenced not stored, append-only).
  - Persist content faithfully: `content` always holds the flattened plain text
    (via `flattenContent`); `parts` preserves the original multimodal
    `ContentPart[]` when not plain text.
  - Provenance: `ChatHistory.model` is the run's driver model; an assistant
    `ChatMessage.model` is its producing model; a user message has `null`.
  - Honor the package cascade/soft-delete: deleting a conversation cascades to
    histories and messages; all three soft-delete via `deletedAt`.
  - Throw typed exceptions (e.g. `ChatConversationNotFoundException`), never
    return null; another user's data must return not-found.

  ### Data Model
  - `ChatConversation.owner` ↔ `User.chatConversations` — ManyToOne / OneToMany
  - `ChatConversation.histories` ↔ `ChatHistory.conversation` — OneToMany /
    ManyToOne, cascade, `onDelete: CASCADE`
  - `ChatHistory.messages` ↔ `ChatMessage.history` — OneToMany / ManyToOne,
    cascade, `onDelete: CASCADE`
  - Histories and messages have no `owner`; they inherit it from the conversation.
dod: |
  - [ ] Aborts with a report if `modules/chat/` exists
  - [ ] Missing dependency module (`user`) created first from its docs prompt
  - [ ] `chat` module created and registered into the app and `SharedModule`
  - [ ] `ChatConversation` (aligned to `ChatConversationEntity`): `title`
    (nullable), `owner`, `histories`, `createdAt`, `updatedAt`, `deletedAt` (nullable)
  - [ ] `ChatHistory` (aligned to `ChatHistoryEntity`): `conversation`
    (`onDelete: CASCADE`), `model`, `systemPrompts` (jsonb, nullable), `metadata`
    (jsonb, nullable), `messages`, `createdAt`, `updatedAt`, `deletedAt` (nullable)
  - [ ] `ChatMessage` (aligned to `ChatMessageEntity`): `history`
    (`onDelete: CASCADE`), `role` (`MessageType["role"]`), `content` (flattened
    text), `parts` (multimodal `ContentPart[]`, jsonb, nullable), `model`
    (nullable for user messages), `createdAt`, `updatedAt`, `deletedAt` (nullable)
  - [ ] Conversations/histories/messages can be created, read, listed, deleted;
    user accesses only their own, admin any; another user's data returns not-found
  - [ ] `content` holds flattened text, `parts` preserves multimodal when present;
    assistant message records its `model`, user message none
  - [ ] Deleting a conversation cascades to histories and messages; all three
    soft-delete via `deletedAt`
  - [ ] If migrations are managed, `chat_messages` indexed on `(chat_history_id, created_at)`
  - [ ] Unneeded resources skipped and reported with a reason
  - [ ] `bun run fmt`, `bun run lint`, `bun run test` pass from the root
```
