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>
This commit is contained in:
parent
25237b8011
commit
5efa552489
1 changed files with 28214 additions and 27 deletions
78
docs/adr/0013-discussions.md
Normal file
78
docs/adr/0013-discussions.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# 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.
|
||||
Loading…
Reference in a new issue