The spec defines Thread as a separate protobuf entity (Section 5.3) with its own ID, creator, access policy. Community discussion converged on the idea that the DAG of messages IS the fundamental data structure, and "threads/chats/channels" are projections over it, not first-class entities.
Proposal:
Remove Thread as a separate entity. A "thread" = a subtree in the DAG, identified by the root message's ID.
Message.thread_id = root message ID. No separate ID namespace. Creating a "chat" = publishing a root message.
ACL as extension on any message, inherited by children (see related issue on per-message ACL).
Multiple parents: reply_to becomes repeated bytes parents for cross-thread references and merges (true DAG, not just tree).
Tags in message extensions field, no protocol-level semantics. Clients build indexes locally. Public subtrees: tags visible and discoverable. Private subtrees: tags inside ciphertext, invisible to non-members.
This naturally maps to different UX modes with the same protocol: "Twitter" = public roots + global tag index, "Slack" = private roots + member-only subtrees, "DM" = root with two-party ACL.
Open questions: does removing Thread as entity lose anything not recoverable from DAG + ACL? Tag collision across unrelated subtrees — acceptable (like hashtags) or needs namespacing?
Discussion origin: foxcool — "the essence is message graphs; everything else is sugar."
The spec defines Thread as a separate protobuf entity (Section 5.3) with its own ID, creator, access policy. Community discussion converged on the idea that the DAG of messages IS the fundamental data structure, and "threads/chats/channels" are projections over it, not first-class entities.
Proposal:
Remove Thread as a separate entity. A "thread" = a subtree in the DAG, identified by the root message's ID.
Message.thread_id = root message ID. No separate ID namespace. Creating a "chat" = publishing a root message.
ACL as extension on any message, inherited by children (see related issue on per-message ACL).
Multiple parents: reply_to becomes repeated bytes parents for cross-thread references and merges (true DAG, not just tree).
Tags in message extensions field, no protocol-level semantics. Clients build indexes locally. Public subtrees: tags visible and discoverable. Private subtrees: tags inside ciphertext, invisible to non-members.
This naturally maps to different UX modes with the same protocol: "Twitter" = public roots + global tag index, "Slack" = private roots + member-only subtrees, "DM" = root with two-party ACL.
Open questions: does removing Thread as entity lose anything not recoverable from DAG + ACL? Tag collision across unrelated subtrees — acceptable (like hashtags) or needs namespacing?
Discussion origin: foxcool — "the essence is message graphs; everything else is sugar."