# Feature Plan: Aether Chat ## Decision: manifest capability Use `chat@1`, not `group_chat@1`. Rationale: the first shipped feature is group chat, but the capability should be able to grow to DMs, stream-adjacent chats, support rooms, or other conversation types later. The `chat@1` contract should therefore mean "conversation provider and reusable chat UI". The provider can advertise supported conversation kinds; initially Aether supports public group-style channels and later Marmot-backed channels. Backward-compatible additions, such as optional DM support, can stay under `chat@1` as long as existing consumers keep working. Breaking provider API changes should become `chat@2`. ## Goals - Add a standalone Aether chat experience. - Provide an embeddable chat panel that Sender can mount next to a live video stream. - Support two backends: - `public_sync`: plaintext messages stored in plugin-owned synced Ash resources. - `marmot`: Marmot/Nostr-backed encrypted transport using `@internet-privacy/marmot-ts@0.5.1`, without claiming true E2EE while the current web UI/server trust model is in place. - Build a high-quality Telegram-like UI that can support media later. ## Non-goals for the first slice - Full true E2EE claims. - Media upload/storage. - DMs. - Sender integration before Aether exposes a stable provider surface. ## Capability contract sketch Aether should provide: ```json "provides": ["social@1", "chat@1"] ``` Initial `chat@1` provider responsibilities: - ensure or find a channel for a context, e.g. `{provider: "sender", type: "stream", id: stream_id}` - expose supported conversation kinds/backends - render standalone chat routes - provide an embeddable compact panel for consumers Initial supported kinds: - `:group` - `:context_group`, for stream/sidebar-style group channels Future optional kinds: - `:dm` - `:multi_dm` - `:support_room` ## Data model: public_sync backend Plugin-owned Ash domain/resources: - `TribeOne.TribesPlugin.Aether.Chat.Channel` - `id` - `slug` - `title` - `description` - `backend`: `:public_sync | :marmot` - `conversation_kind`: initially `:group | :context_group` - context fields: `context_provider`, `context_type`, `context_id` - `metadata` - timestamps - `TribeOne.TribesPlugin.Aether.Chat.Message` - `id` - `channel_id` - `author_id` - `author_pubkey` - `body` - `client_message_id` - `metadata` - timestamps Both public resources should be added deliberately to Aether's `ash_domains` and `AshNostrSync` so public chat replicates across cluster nodes. ## UI plan One reusable chat surface with modes: - standalone page mode - compact embedded mode for Sender MVP UI: - message stream with stable DOM IDs - sticky composer - multiline textarea - send button - sender display label - timestamp display - empty state - signed-out state - compact mode support - auto-scroll hook later Media-ready UI affordances can be added later without implementing uploads now. ## Marmot plan Use `@internet-privacy/marmot-ts@0.5.1` if/when implementing the Marmot backend. Marmot backend constraints: - document as encrypted/Marmot-backed, not true E2EE yet - keep behind a feature flag or explicit backend choice until stable - use browser local storage for Marmot state if using `marmot-ts` - integrate with Parrhesia relay interfaces - decide signing bridge/key handling before productizing ## Phases 1. Add plan, capability, public Ash resources, migrations, and standalone public chat MVP. 2. Extract/shape embeddable panel API and tests. 3. Integrate Sender stream pages with Aether chat provider. 4. Add Marmot spike using `marmot-ts@0.5.1`. 5. Productize Marmot backend behind explicit configuration. 6. Add media support later. ## Validation For Aether work: ```sh scripts/plugin validate scripts/plugin test scripts/plugin precommit ``` For host/plugin API changes: ```sh cd ../tribes devenv shell -- mix test ``` For Sender integration: ```sh cd ../tribes-plugin-sender scripts/plugin test ```