halkyon/docs/adr/0013-discussions.md
Tizian 「ティツィアーン」 5efa552489
feat(discussions): questions on published studysets, answered by learners
A learner asks about a published studyset, a topic in it, or one card,
note or step of a release, and others answer, as on Stack Exchange
(ADR 0013): questions and answers in the app's editor without images,
sounds or videos, comments of up to 600 characters under the question
and each answer. There are no votes: the asker accepts an answer, which
comes first, then the oldest; the author's posts are marked. The
instance reads from git's file list which topics a question's target
sits in, so a topic lists what is asked within it and below it.

Posts live in two server-only tables, written through endpoints, so the
synced tables stay as they are and v0.17.0 keeps syncing. Everyone
signed in reads; writing needs an identity and a public profile; the
studyset's author hides posts and blocks people with feedback's blocks;
a withdrawn studyset takes no new questions; anyone writes at most 30
posts an hour. A post with others' replies under it is emptied when
deleted, else deleted; deletePerson deletes what a person wrote the same
way, and a published studyset's deletion takes its discussions with it.

The migration adds Serverpod's gen_random_uuid_v7(), discussion_post
and discussion_seen with their indexes and cascading foreign keys, and
changes nothing else.

In the app, discussions open from a copy's studyset or topic menu, a
studied card's "Ask about this", Explore's summary and the Publish
sheet; the Profile tab's inbox lists those the person follows, and its
count includes what is new in them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-17 19:46:32 +02:00

4.9 KiB
Raw Permalink Blame History

ADR 0013: Discussions on published studysets

  • Status: accepted
  • Date: 2026-10-15

Context

A published studyset has reports and suggestions (ADR 0005, rule 11): a line between one writer and its author, written as rows in each writer's own synced space and gathered by the instance as they are read. Learners also have questions about what they learn, and other learners can answer them, as on Stack Exchange; the developer's example was "Meaning of 青い衝撃 in this situation?" in Japanese › Grammar. The working notes (11 Oct) planned these as discussions "built on the feedback threads", the step before federation.

Feedback's storage doesn't fit them well: many people answer, the asker accepts one, posts are edited, and lists are ordered and paged by activity. Rows spread across writers' spaces could only encode acceptance in decision rows, and could never be edited (synced content is only ever blanked). New synced tables would make every app older than the change stop syncing (the sync engine refuses an app whose synced tables differ).

Decision

The developer decided (2026-10-15), each as recommended:

  1. Server tables, not synced. discussion_post holds questions, answers and comments, discussion_seen when each person last read a discussion; both are server-only, written through endpoints, online only. Counting, ordering, accepting and editing are plain queries, posts are ready to federate later (ADR 0005, stages 5 and 6), and the synced tables stay as they are, so older apps keep syncing.
  2. Questions, answers and comments, as Stack Exchange has them: comments go under the question and under each answer, never under a comment; questions and answers are rich text in the app's editor (without images, sounds or videos: the person's files are theirs alone, and nobody else could load them), comments plain text of up to 600 characters.
  3. No votes. The accepted answer first, then the oldest first; the author's posts marked. Votes cost nothing to fake (rule 8 of ADR 0005), so they count for nothing. The asker accepts an answer, and can take it back.
  4. About the studyset, a topic or an item. A question names what it is about as the release names it: the published studyset or a topic in it, a card, a note or a step, by its id in a release. The instance reads where that sits in the release (git's file list alone) and keeps the topics it is within, so a topic lists what is asked within it and in the topics below it. A copy's items know their ids and releases, so the app asks about them directly; Explore asks about the studyset as a whole, naming no item.
  5. Deleting keeps others' replies. A post nobody else replied under goes for good; a post with others' replies under it stays for them, its title, text and writer gone ("Deleted question"). Deleting a person deletes what they wrote the same way, in deletePerson's transaction; deleting a published studyset deletes its discussions.
  6. The feedback rules stay: everyone signed in reads; writing needs an identity and a public profile (posts name their writer); the studyset's author hides posts (then only their writer and the author see them) and blocks people (the same blocks as feedback's: what a blocked person writes shows to them alone). A withdrawn studyset keeps its discussions readable and answerable, but takes no new questions. A person writes at most 30 posts an hour.
  7. Where it shows: a copy's menu opens the discussions within that studyset or topic; a studied card from a release offers "Ask about this"; Explore's summary and the author's Publish sheet open the whole studyset's; the person's inbox (Profile) lists the discussions they follow (on their studysets, or asked, answered or commented in), what others wrote since they last read one marked and counted on the Profile tab.

Consequences

  • The synced tables don't change: v0.17.0 keeps syncing with an instance that has discussions.
  • Writing needs the instance; a question being written stays in the composer meanwhile.
  • Moderation is the author's alone; an instance's operator has no tools for it yet.
  • Federation (Fedify, ADR 0005 rule 7) can announce posts as the instance holds them.

Alternatives considered

  • Rows in each writer's synced space, as feedback: offline writing, one pattern for both; but no edits, and acceptance and ordering pieced together from many spaces.
  • New synced tables: offline and clean, but older apps stop syncing until updated.
  • Votes ordering answers, or shown without ordering: the familiar way, but votes are free to fake, and Explore already refuses to rank by them.
  • Flat replies (a forum thread): simpler, but no accepted answer, and short remarks mix with answers.
  • Everything goes with a deleted question: simpler, but people's answers would vanish with someone else's choice.