# Product Client (toju-app) Owns the user-facing Angular 21 desktop chat experience: rendering and orchestrating chat, voice, screen-share, plugin UI, theming, and identity flows on top of the Electron `window.api` bridge and the server WebSocket. Houses every bounded context the end user interacts with, organized DDD-style under `src/app/domains/`. > **Format reference:** > - **Vocabulary** — bold term, one-sentence definition, aliases to avoid. > - **Relationships** — bullets with bold terms and cardinality. > - **Boundaries / IO** — what this subdomain exposes and consumes. > - **Invariants** — rules that always hold. > - **Flagged ambiguities** — terms in dispute with proposed resolutions. > > See `agents-docs/AGENTS_CONTEXT.md` for the contract. Update in the same turn a trigger fires (see `agents-docs/AGENT_WORKFLOW.md` § CONTEXT.md upkeep). ## Vocabulary | Term | Definition | Aliases to avoid | |------|------------|------------------| | **Domain** | A bounded context under `src/app/domains//` that owns its own models, services, NgRx slice, and components — e.g. *chat*, *voice-session*, *plugins*. | "module", "feature" (Angular reserves these for different things) | | **Shared kernel** | Cross-domain contracts in `src/app/shared-kernel/` — wire-format models, P2P transfer utilities, plugin contracts, signaling contracts — imported by multiple domains. | "common", "core" | | **Infrastructure** | Technical-runtime concerns shared by domains: `persistence/` (client-side store wiring) and `realtime/` (WebSocket adapter). Not a domain. | "shared", "lib" | | **Rules file** | A pure-function module suffixed `*.rules.ts` that encodes domain logic without Angular or NgRx dependencies — easy to unit-test. | "helpers", "utils" | ## Relationships - A **Domain** owns zero or more **Components**, **Services**, **NgRx slices**, and **Rules files**. - A **Domain** may consume **Shared kernel** contracts but must never import from another **Domain** directly — cross-domain coupling goes through the shared kernel or NgRx events. - The **Realtime** infrastructure adapts server WebSocket envelopes (defined in `src/app/shared-kernel/signaling-contracts.ts` and mirrored in `server/src/websocket/types.ts`) into NgRx actions consumed by domains. - The **Plugins** domain consumes plugin manifests loaded by Electron's `plugin-library.ts` and exposes a sandboxed runtime that other domains may hook into. ## Boundaries / IO - **Exposes:** the Angular SPA bundle served at `:4200` in dev (`ng serve`) or mounted by Electron in production; NgRx store events that other domains in this subdomain consume; UI surface to the end user. - **Consumes:** - `window.api.*` IPC surface exposed by Electron preload (defined in `electron/preload.ts` and `electron/api/`). - WebSocket envelopes from `server/src/websocket/` (typed by `shared-kernel/signaling-contracts.ts`). - REST endpoints from the server's `server/src/routes/` (server directory, invites, join requests, link metadata, klipy). - Plugin manifests resolved by Electron's plugin library. ## Invariants - A **Domain** never imports from another **Domain** directly — only through the **Shared kernel** or NgRx actions. - **Rules files** stay framework-free (no Angular, no NgRx) so they can be Vitest-tested as plain functions. - Wire-format types (anything that crosses the WebSocket or IPC boundary) live in **Shared kernel**, never inside a single domain. ## Flagged ambiguities - _None recorded yet — add entries when a domain term resists clean definition._ --- *Agent-procedural rules (TDD, lint, etc.) live in `/AGENTS.md`. Per-domain implementation detail lives in `src/app/domains//README.md`. This file is the bounded-context domain artefact for the product client as a whole.*