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