-
Notifications
You must be signed in to change notification settings - Fork 2
plat 104
| Field | Value |
|---|---|
| Status |
open — design recorded; implementation intentionally deferred |
| Priority | P1 |
| Owner | frontend chat transport and event-store contract |
| Reported | 2026-08-14 |
| Related | PLAT-102), PLAT-103) |
Live chat uses HTTP to deliver a command and SSE to receive the durable event, but both paths can independently create the visible user message:
- the backend records
user_messageand SSE publishes it; - the frontend appends an optimistic
user_messageafter HTTP acknowledges; - arrival-order-specific filtering tries to collapse the two copies.
This produced a real duplicate when SSE arrived during the 79 ms HTTP request.
The current narrow repair checks the acknowledgement's backend-generated
message_id before appending the optimistic copy. It handles both arrival
orders, but message reconciliation still lives inside ChatArea instead of
being a single event-store invariant.
HTTP plus SSE is not itself the defect. The defect is that they are treated as two message producers instead of two observations of one command.
- The frontend creates a stable
message_idbefore sending. - It immediately upserts one optimistic message under that ID.
- HTTP carries the same ID and returns only delivery acknowledgement/status.
- The backend persists and emits the same ID through SSE.
- The frontend event store upserts the canonical SSE event by ID, transitioning the existing optimistic record to confirmed.
- Components never deduplicate messages by text or arrival order.
- A later intentional repeat of identical text gets a new ID and remains visible as a distinct message.
- Keep HTTP as the command/acknowledgement transport.
- Keep SSE as the authoritative event/state transport.
- Do not delay optimistic rendering until SSE arrives.
- Do not use message content as identity.
- Preserve queued, failed, retried, and accepted delivery states on the same record rather than creating replacement bubbles.
- Every submission creates exactly one frontend record before HTTP completes.
- HTTP and SSE reconcile through the same client-generated
message_idin either arrival order. - The event store, not
ChatArea, owns reconciliation. - Delivery failure updates the optimistic record to failed while retaining the draft/retry affordance.
- Repeating identical text intentionally creates a second message.
- Tests cover SSE-before-HTTP, HTTP-before-SSE, retry, failure, reload, and two identical intentional submissions.
Do not implement this refactor yet. Keep the narrow message-ID race repair from PLAT-103 and revisit when simplifying the frontend chat/event architecture.
Auto-synced from docs/ on main. Edit there, not here.