# Feature Plan: Canonical Conversation Events (Append-Only Timeline) ## Goal Introduce a canonical append-only event log for conversations so adapters remain stateless and replay/debugging become deterministic. ## Why This Fits GIA - GIA already has `Person`, `PersonIdentifier`, `ChatSession`, `Message` and multi-transport routing. - This adds a durable event backbone without replacing current UI/features. ## Scope - Add `ConversationEvent` model (append-only). - Event types: `message_created`, `message_edited`, `message_deleted`, `reaction_added`, `reaction_removed`, `read_receipt`, `media_attached`, `participant_added`, `participant_removed`. - Persist source metadata: transport, upstream IDs, timestamps, actor, payload. - Write events from transport ingress and internal compose actions. - Build replay utility for one chat/session. ## Implementation 1. Add model + migration + indexes (`session`, `event_type`, `created_at`, `origin_transport+origin_message_id`). 2. Add write helper in a new module (`core/events/ledger.py`). 3. Update signal/whatsapp/xmpp ingress handlers to emit canonical events. 4. Update compose send/reaction/edit/delete paths to emit canonical events. 5. Add admin/diagnostic read view for event stream by session. 6. Add replay command to regenerate derived projections. ## Acceptance Criteria - Every new message/reaction/edit/delete creates exactly one canonical event. - Event ordering is deterministic per session. - Replay reproduces message projection for a selected session. - No adapter requires business logic to infer missing event state. ## Risks - Double-write races during transition. - Backfill complexity for old messages. ## Out of Scope - Full migration of all legacy records in one release.