# 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; D11 to D13 the agent's recommendations, which they chose on 11 Nov 2026, D14 too. Not built yet; the steps below. - **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. - **D11.** **A shared studyset passes on.** Leaving, the Owner picks the next Owner first. Deleting their account, ownership passes by itself to the Editor who joined first, else to the Viewer who joined first; only with no other member does the studyset go with them. - **D12.** **An agent's token lapses after 90 days unused;** while used it has no fixed end, the owner revokes it any time, and their Profile shows when it was last used. - **D13.** **An invitation by @handle waits** for someone who has an account on the instance's register but has never used the app: they find it in their Inbox the first time they sign in to it, and the inviter sees them as invited until then. - **D14.** **Sharing copies the studyset under new IDs** into the shared space, rewrites what names its rows (reviews, tags, the learning path, files) and deletes the old ones, as ADR 0019's rewrites do; the fork stays as it is. Found 11 Nov 2026: the engine's delete is soft (`insteadOfDelete`: the domain row stays, hidden by a tombstone in its space's `crdt_data_rows`), and a synced table's primary key is the row's ID alone, so the same ID can't be inserted into another space; teaching the engine to move a row was the other way, set aside as a deeper change to its merge, kept on every rebase. ## Steps 1. **Share with the community's confirmation** (D8, D9), needing nothing else here. 2. **Shared spaces in halkyon_base** (D1, D2, D11, D13): the module's tables (a shared space, its members and roles, its Owner), its endpoints with their denial tests, the engine's grants kept in step, the hand-on as an account is deleted. 3. **Keys** (D3): a private studyset's key wrapped to each member's key pair. 4. **Learn shares a studyset** (D14): the copy, *Manage collaborators* (invite by @handle, the members, their roles, leaving), each member's own reviews. 5. **Invitations by email and by link** (D4, D5), the Inbox. 6. **Agents** (D6, D7, D10, D12). ## Open questions, before building - **Moving rows between spaces.** Decided: D14. - **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.** Decided: D11. To build: the account's deletion hands the shared spaces it owns on before it deletes the person's own. - **Members across services.** Decided: D13. 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; its lapse decided: D12.