82 lines
5.5 KiB
Markdown
82 lines
5.5 KiB
Markdown
|
|
# ADR 0044: Shared spaces and collaboration, people and agents alike
|
||
|
|
|
||
|
|
- **Status:** decided 10 Nov 2026 by the developer: D8 is their own request, D9 and D10
|
||
|
|
their choices over the agent's recommendations (all ticked at first; agents editing
|
||
|
|
directly), D1 to D7 the agent's recommendations, which they chose. Not built yet; the
|
||
|
|
open questions below come first.
|
||
|
|
- **Builds on:** ADR 0005 (publishing, reports and suggestions), ADR 0014 (the module),
|
||
|
|
ADR 0016 (one account across an instance), ADR 0017 (key pairs), ADR 0019 (private
|
||
|
|
studysets), ADR 0021 (operators and assistants).
|
||
|
|
|
||
|
|
## Context
|
||
|
|
|
||
|
|
A studyset belongs to one person: their rows are in their personal space, a private
|
||
|
|
one sealed with a data key that only their own devices unwrap. The developer asked (10
|
||
|
|
Nov 2026) for Vaia's sharing (*Manage collaborators*: invite by email, an invite link,
|
||
|
|
the members and their roles; *Collaboration settings*: joining by link, collaborators
|
||
|
|
inviting others; *Share with the community*: choosing what material goes public) and
|
||
|
|
for collaboration with everyone, people and agents alike: *invite @Paul or @Claude to a
|
||
|
|
studyset*, Claude Code on halkyon.li's host working as an agent account, as Copilot or
|
||
|
|
Claude work on a GitHub repository.
|
||
|
|
|
||
|
|
The sync engine already has shared spaces (`OfflineSyncSpaces`: create, grant, revoke,
|
||
|
|
members), with two roles, `readOnly` and `readWrite`, which limit writes alone: a
|
||
|
|
member reads everything in the space.
|
||
|
|
|
||
|
|
## Decisions
|
||
|
|
|
||
|
|
- **D1.** **Shared spaces live in halkyon_base,** for every app: members, roles,
|
||
|
|
invitations, links, settings and the wrapped keys. Learn's studysets use them first,
|
||
|
|
Todo's projects later on the same tables.
|
||
|
|
- **D2.** **Roles: Owner, Editor, Viewer.** The Owner can do everything, delete the
|
||
|
|
studyset and hand it to another member; an Editor changes content; a Viewer reads and
|
||
|
|
studies, with their own reviews in their own space. Editor and Owner are the engine's
|
||
|
|
`readWrite`, a Viewer its `readOnly`; who is Owner is the module's own table, checked
|
||
|
|
by its endpoints.
|
||
|
|
- **D3.** **A private studyset's key is wrapped to each member's public key** (ADR
|
||
|
|
0017's key pairs) by a member's device that holds it, at its next sync after someone
|
||
|
|
joined. The instance never sees the key; reading waits for that sync. A member
|
||
|
|
removed gets no new content: the studyset rolls to a new key, as ADR 0019's rewrites.
|
||
|
|
- **D4.** **Invites by @handle or by email.** An @handle adds a person on the instance at
|
||
|
|
once (they see it in their Inbox and may leave). An email address gets a mail with a
|
||
|
|
link to join, which works after signing up; the address is never shown to the other
|
||
|
|
members.
|
||
|
|
- **D5.** **Joining by link is off at first;** someone joining by it is a Viewer, whom
|
||
|
|
the Owner can raise. *Collaborators may invite others* is off at first too.
|
||
|
|
- **D6.** **Agents are accounts of their own,** marked as agents, each owned by a person
|
||
|
|
who made it from their Profile; listed in the owner's Profile, deleted with them. An
|
||
|
|
agent has its own key pair, kept where it runs, signs in with a token the owner made
|
||
|
|
(never a password), and is invited like a person: *@claude*.
|
||
|
|
- **D7.** **An agent reaches the instance through a small CLI or MCP server** run beside
|
||
|
|
it (Claude Code on halkyon.li's host runs as its own user, without Docker): it signs
|
||
|
|
in with its token, syncs the spaces it is a member of, opens the sealed rows with its
|
||
|
|
own keys, and writes through the same endpoints an app uses.
|
||
|
|
- **D8.** **Share with the community** (publishing to Explore, ADR 0005) gets a step
|
||
|
|
confirming the material: every PDF, other file and note listed by kind.
|
||
|
|
- **D9.** That step's choice: **all unticked at first**, with per kind *tick all*, and
|
||
|
|
on any item *everything but this* and *nothing but this*. Cards and the learning path
|
||
|
|
always go.
|
||
|
|
- **D10.** **An agent suggests; a person accepts.** An agent is a Viewer in the engine's
|
||
|
|
sense and writes nothing into the studyset; its changes go as suggestions, which a
|
||
|
|
member with Editor's rights accepts or declines, each marked as by @claude. Learn's
|
||
|
|
reports and suggestions (ADR 0005, stage 4: `feedback_thread`, the author's
|
||
|
|
decisions, accepted suggestions applied by their item) are the start: they become
|
||
|
|
suggestions within a shared space too, not only on published releases.
|
||
|
|
|
||
|
|
## Open questions, before building
|
||
|
|
|
||
|
|
- **Moving rows between spaces.** A studyset's rows are in its owner's personal space;
|
||
|
|
sharing moves them into a new shared space. Row IDs are unique across a table and the
|
||
|
|
engine keeps a deleted row's tombstone until its space goes, so a row can't simply be
|
||
|
|
deleted in one space and inserted in another under the same ID. Either the engine
|
||
|
|
learns to move a row between spaces (a change to our fork), or sharing copies the tree
|
||
|
|
under new IDs and rewrites what names them (cards' reviews, tags, the learning path),
|
||
|
|
as ADR 0019's rewrites do with keys. To try against the fork first.
|
||
|
|
- **Whose reviews.** A Viewer's or Editor's schedule for a shared card stays in their own
|
||
|
|
space, keyed by the card's ID; the card's own review rows today assume one learner.
|
||
|
|
- **Handing on and leaving.** An Owner leaving must hand the studyset on first, or it
|
||
|
|
goes with them, as their account's deletion deletes their spaces.
|
||
|
|
- **Members across services.** On an instance with a register (ADR 0016), handles are
|
||
|
|
the register's; a member of a Learn studyset needs no Todo account and the reverse.
|
||
|
|
- **The agent's token:** made and revoked in the owner's Profile, scoped to the agent's
|
||
|
|
account, never shown again after making; whether it expires.
|