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

78 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.