Part of the Workshop channels epic; depends on the channel-lifecycle sub-issue and runs parallel to the mention and wake-policy work. Threads as a first-class structure in channels.
Design
- Schema: additive migration giving
messages a nullable thread_root_id referencing the root message of the thread. A reply carries the root's id; roots and non-threaded messages carry null. The message.created payload carries the field when present.
- Timeline: the channel timeline returns top-level messages only, with a reply count and latest-reply timestamp per root. A new
GET /v1/channels/{channel_id}/threads/{root_message_id} route pages one thread, gated by the same authorization as the channel timeline.
- Client: a thread pane opened from a root message, with its own composer posting replies that carry the root id.
- Telegram delivery: flattens thread replies into the linear channel stream. Rendering fidelity may differ between clients but information is never lost.
Tests
- Replies carry
thread_root_id; the top-level timeline excludes them but reports correct counts.
- Thread route pages correctly and enforces channel authorization.
- Replying to a non-existent or foreign-channel root fails cleanly.
- Projection rebuild preserves thread structure.
- Telegram flattening preserves reply content and order.
Part of the Workshop channels epic; depends on the channel-lifecycle sub-issue and runs parallel to the mention and wake-policy work. Threads as a first-class structure in channels.
Design
messagesa nullablethread_root_idreferencing the root message of the thread. A reply carries the root's id; roots and non-threaded messages carry null. Themessage.createdpayload carries the field when present.GET /v1/channels/{channel_id}/threads/{root_message_id}route pages one thread, gated by the same authorization as the channel timeline.Tests
thread_root_id; the top-level timeline excludes them but reports correct counts.