Federated sharing UX: separate it from the share dialog and design its own flow #529

Closed
opened 2026-09-14 00:29:09 +00:00 by Cordy · 5 comments
Owner

From the #389 real-phone pass (Nikola, 2026-09-14): the share dialog currently carries an "or send to a federated address" section alongside the link controls. Decision: sharing and sharing-with-federations should be separated from the initial interaction — clicking Share should not suggest federating.

We got Cairn Peering's UX nailed down (#105/#131/#134/#136) but never gave the OCM/federation send the same treatment; the current section is cramped (recipient field, permission select and Send button competing for one row — visibly broken at phone width) and conceptually muddles two different acts: minting a link vs addressing another instance's user.

Interim (shipped separately): the federated section is hidden in the share dialog; the OCM plumbing and the Federated view stay untouched.

Deep dive to do here (later):

  • Where federated send LIVES instead: its own kebab entry ("Send to federated address…") gated on feat.ocm? inside the Federated view? both?
  • Whether it should adopt the peering send pattern (recipient picker with known contacts — /api/v1/ocm/contacts already exists — plus permission choice and clear failure surface for the allow-list error).
  • Relationship to Cairn Peering send in the UI: two entries with clear naming, or one "Send to another instance" entry that branches by transport.
  • The allow-list error copy ("the server must be on this instance's allow-list…") belongs in the flow, not as a permanent hint.
  • Mockup first, per house rules; i18n ×4.
From the #389 real-phone pass (Nikola, 2026-09-14): the share dialog currently carries an "or send to a federated address" section alongside the link controls. Decision: **sharing and sharing-with-federations should be separated from the initial interaction** — clicking Share should not suggest federating. We got Cairn Peering's UX nailed down (#105/#131/#134/#136) but never gave the OCM/federation send the same treatment; the current section is cramped (recipient field, permission select and Send button competing for one row — visibly broken at phone width) and conceptually muddles two different acts: minting a link vs addressing another instance's user. **Interim (shipped separately):** the federated section is hidden in the share dialog; the OCM plumbing and the Federated view stay untouched. **Deep dive to do here (later):** - Where federated send LIVES instead: its own kebab entry ("Send to federated address…") gated on `feat.ocm`? inside the Federated view? both? - Whether it should adopt the peering send pattern (recipient picker with known contacts — `/api/v1/ocm/contacts` already exists — plus permission choice and clear failure surface for the allow-list error). - Relationship to Cairn Peering send in the UI: two entries with clear naming, or one "Send to another instance" entry that branches by transport. - The allow-list error copy ("the server must be on this instance's allow-list…") belongs in the flow, not as a permanent hint. - Mockup first, per house rules; i18n ×4.
Author
Owner

Scope grows: the sharing model changes here, not just where federated send lives (Nikola, 2026-09-16).

Context for why this landed on this issue. While auditing the #550 Groups tab against its mockup, the "Used by" column could not count shares, and the reason was structural: Cairn has no group-addressed sharing. A share link points at a path and is never addressed to anyone; group access happens only through spaces, which are pairs of IdP groups. So an app-owned group can never be "used by" a share.

Decision: do not keep that divergence. Diverging from what a large userbase already knows creates confusion and a bad launch. Sharing should sit adjacent to how OpenCloud does it, and links get subdivided.

Target model

  • Share with people and groups (internal): address a share to a user or a group, with a permission level. This is what OpenCloud calls internal sharing — share with members or groups inside the organisation, with Can view / Can upload / Can edit — and it is the interaction users arrive expecting.
  • Links, subdivided:
    • Internal link — a link that resolves for signed-in users who already have access; it grants nothing by itself. (OpenCloud/ownCloud and Nextcloud both carry this concept, and it is a known source of confusion when it is not distinguished from a public link.)
    • Public link — today's /s/ surface: unauthenticated, optional password and expiry, the thing you send outside the organisation. OpenCloud's external sharing is the reference.
  • Federated / peering send stays a third, clearly separate act — which is what this issue was originally about.

Why this is worth the work beyond parity

Nextcloud's own documentation makes the argument for us: link shares are useful for one-time sharing but poor for collaboration, because everyone acting through a link is identified as "guest", whereas a user or group share keeps identity attached to every action in the activity view. Cairn's audit log is one of its selling points, and link-only sharing quietly undermines it: today, anything shared outside a space is attributable to a link, not a person.

Knock-on effects to design here

  • share.Store gains an addressee (user or group) alongside path-addressed links; authorisation then resolves through User.Groups, which since #550 already merges app-owned and directory groups — so app groups become share targets for free once the addressee exists.
  • The scope decorator and audit need to attribute a group share to the acting person, not to the group.
  • #550's "Used by" column then gains a real share count, which is what the original mockup promised.
  • Deletion semantics: removing a group must state what stops resolving — Nextcloud has a long tail of bugs and complaints in exactly this area, where group membership changes silently delete shares. Cairn's fail-closed rule (references simply stop matching, nothing is mutated) should hold for group shares too.
  • Encryption: a group share must resolve to per-recipient keys the same way space membership does — worth checking against the custody model before committing to a design.

Mockup first, per house rules, covering: the reworked share dialog (people/groups + the two link kinds), where federated send lives, and the empty/permission states. i18n ×4.

**Scope grows: the sharing *model* changes here, not just where federated send lives** (Nikola, 2026-09-16). Context for why this landed on this issue. While auditing the #550 Groups tab against its mockup, the "Used by" column could not count shares, and the reason was structural: **Cairn has no group-addressed sharing**. A share link points at a path and is never addressed to anyone; group access happens only through spaces, which are pairs of IdP groups. So an app-owned group can never be "used by" a share. Decision: **do not keep that divergence.** Diverging from what a large userbase already knows creates confusion and a bad launch. Sharing should sit adjacent to how OpenCloud does it, and links get subdivided. ### Target model - **Share with people and groups** (internal): address a share to a user or a group, with a permission level. This is what OpenCloud calls internal sharing — [share with members or groups inside the organisation, with Can view / Can upload / Can edit](https://docs.opencloud.eu/docs/user/sharing/internal/) — and it is the interaction users arrive expecting. - **Links, subdivided:** - **Internal link** — a link that resolves for signed-in users who already have access; it grants nothing by itself. (OpenCloud/ownCloud and Nextcloud both carry this concept, and it is a known source of confusion when it is *not* distinguished from a public link.) - **Public link** — today's `/s/` surface: unauthenticated, optional password and expiry, the thing you send outside the organisation. [OpenCloud's external sharing](https://docs.opencloud.eu/docs/user/sharing/external/) is the reference. - **Federated / peering send** stays a third, clearly separate act — which is what this issue was originally about. ### Why this is worth the work beyond parity Nextcloud's own documentation makes the argument for us: [link shares are useful for one-time sharing but poor for collaboration, because everyone acting through a link is identified as "guest"](https://help.nextcloud.com/t/group-folders-vs-folder-shares-whats-the-difference/19207), whereas a user or group share keeps identity attached to every action in the activity view. Cairn's audit log is one of its selling points, and link-only sharing quietly undermines it: today, anything shared outside a space is attributable to a link, not a person. ### Knock-on effects to design here - **`share.Store` gains an addressee** (user or group) alongside path-addressed links; authorisation then resolves through `User.Groups`, which since #550 already merges app-owned *and* directory groups — so app groups become share targets for free once the addressee exists. - **The scope decorator and audit** need to attribute a group share to the acting person, not to the group. - **#550's "Used by" column** then gains a real share count, which is what the original mockup promised. - **Deletion semantics:** removing a group must state what stops resolving — Nextcloud has a long tail of bugs and complaints in exactly this area, where [group membership changes silently delete shares](https://github.com/nextcloud/server/issues/25755). Cairn's fail-closed rule (references simply stop matching, nothing is mutated) should hold for group shares too. - **Encryption:** a group share must resolve to per-recipient keys the same way space membership does — worth checking against the custody model before committing to a design. Mockup first, per house rules, covering: the reworked share dialog (people/groups + the two link kinds), where federated send lives, and the empty/permission states. i18n ×4.
Author
Owner

Scope addition: the group "Used by" column depends on this rework

Carried over from #552 / #550. Decision taken 2026-09-16: keep the column, ship it thin, let this issue fill it in. No work in #552; the fix is a consequence of the model change described in the previous comment.

What the column is

#admin/users/groups gives every group a Used by cell whose job is to answer one question before a destructive edit: what breaks if I rename or delete this group? Cairn already refuses a delete that would strand a reference (409 with the referencing names). The column is the preview; the 409 is the backstop. A refusal you could have seen coming is a worse experience than one you saw coming.

Why it's currently thin

It lists peering refs, admin-group grants and space membership — but no share count, because Cairn's shares point at paths and are never addressed to a group. There is nothing to count. The #550 mockup promised a share count; the shipped column can't deliver one until sharing can address a group, which is exactly what this issue introduces.

So this is not a Used-by bug. It is the sharing model showing through.

What this issue must do about it

Once share.Store gains an addressee (previous comment), the column gets wired:

  • Used by shows a real share count for app-owned and directory groups alike — "4 shares · 1 space · peering" rather than today's reference-only list.
  • The count is a link, not a dead number: clicking it lists the shared paths with their owner and permission, so the admin can act on them rather than go hunting.
  • Deletion stays fail-closed. A group holding shares cannot be deleted silently. Either the 409 extends to cover shares, or the delete dialog requires an explicit choice about what happens to them. Never a quiet cascade — see the competitor findings below for why this line matters.
  • Membership changes must not silently destroy shares. Removing a member from a group that holds shares revokes that person's access; it must not delete the share for everyone, and must not delete shares owned by a third party.
  • Internal vs public links counted separately in the cell, matching the subdivision this issue introduces. A group can only ever hold internal shares, so a public-link count on a group row would be a category error — worth an explicit assertion in the test.
  • Lazy-loaded like the member counts already are; the groups table must not block on a share scan.

Findings — why the column is worth keeping at all

Nikola asked whether this is a gain or invented work. Researched 2026-09-16. No competitor surfaces this in the UI.

  • Nextcloud has no view for it. The community answer to "which files is this group used by" is query the oc_share table directly. That is the documented workaround, not a feature.
  • nextcloud/server#5586 — open user request for precisely this listing ("how to easily list all shared files and access/permissions users/groups have"). Users are asking; it has not shipped.
  • nextcloud/server#25755 — removing a user from a group silently deletes shares, including shares owned by someone else. No warning, no preview, no undo. This is the failure mode the column and the fail-closed deletion rule above exist to prevent, and it is the direct source of the third and fourth checkboxes.
  • nextcloud/groupfolders#2827 — the mirror-image bug: shares that should be revoked on membership change, staying. Both bugs have the same root cause: nobody, admin included, can see what a group touches.
  • ownCloud is the same picture. The admin manual documents blacklisting large groups from receiving shares and warns that deleting a user destroys everything they shared, but offers no impact view. Their advisory on group shares (a recipient can remove a received group share for the whole group) is another instance of group-share blast radius being invisible until it fires.
  • OpenCloud inherits the ownCloud model; the sharing docs describe sharing from the file side only. Nothing group-side.

Conclusion: this is differentiator work, not parity work — one of the few places where we are not catching up but shipping something three competitors' users have asked for and not received. It also sits squarely in Cairn's positioning: the instance admin is accountable for what is on their own hardware, and "I can see what this group touches before I break it" is that accountability made visible.

The caveat to hold honestly: the column is only as valuable as the model beneath it. Until this issue lands it shows two real reference types and no shares, which is honest but thin. Do not market it before the count is real.

Sources

## Scope addition: the group "Used by" column depends on this rework Carried over from #552 / #550. Decision taken 2026-09-16: **keep the column, ship it thin, let this issue fill it in.** No work in #552; the fix is a consequence of the model change described in the previous comment. ### What the column is `#admin/users/groups` gives every group a **Used by** cell whose job is to answer one question before a destructive edit: *what breaks if I rename or delete this group?* Cairn already refuses a delete that would strand a reference (409 with the referencing names). The column is the preview; the 409 is the backstop. A refusal you could have seen coming is a worse experience than one you saw coming. ### Why it's currently thin It lists peering refs, admin-group grants and space membership — but **no share count**, because Cairn's shares point at paths and are never addressed to a group. There is nothing to count. The #550 mockup promised a share count; the shipped column can't deliver one until sharing can address a group, which is exactly what this issue introduces. So this is not a Used-by bug. It is the sharing model showing through. ### What this issue must do about it Once `share.Store` gains an addressee (previous comment), the column gets wired: - [ ] **Used by shows a real share count** for app-owned and directory groups alike — "4 shares · 1 space · peering" rather than today's reference-only list. - [ ] **The count is a link**, not a dead number: clicking it lists the shared paths with their owner and permission, so the admin can act on them rather than go hunting. - [ ] **Deletion stays fail-closed.** A group holding shares cannot be deleted silently. Either the 409 extends to cover shares, or the delete dialog requires an explicit choice about what happens to them. Never a quiet cascade — see the competitor findings below for why this line matters. - [ ] **Membership changes must not silently destroy shares.** Removing a member from a group that holds shares revokes that person's access; it must not delete the share for everyone, and must not delete shares owned by a third party. - [ ] **Internal vs public links counted separately** in the cell, matching the subdivision this issue introduces. A group can only ever hold internal shares, so a public-link count on a group row would be a category error — worth an explicit assertion in the test. - [ ] Lazy-loaded like the member counts already are; the groups table must not block on a share scan. ### Findings — why the column is worth keeping at all Nikola asked whether this is a gain or invented work. Researched 2026-09-16. **No competitor surfaces this in the UI.** - **Nextcloud** has no view for it. The community answer to "which files is this group used by" is *query the `oc_share` table directly*. That is the documented workaround, not a feature. - [nextcloud/server#5586](https://github.com/nextcloud/server/issues/5586) — open user request for precisely this listing ("how to easily list all shared files and access/permissions users/groups have"). Users are asking; it has not shipped. - [nextcloud/server#25755](https://github.com/nextcloud/server/issues/25755) — removing a user from a group silently deletes shares, **including shares owned by someone else**. No warning, no preview, no undo. This is the failure mode the column and the fail-closed deletion rule above exist to prevent, and it is the direct source of the third and fourth checkboxes. - [nextcloud/groupfolders#2827](https://github.com/nextcloud/groupfolders/issues/2827) — the mirror-image bug: shares that *should* be revoked on membership change, staying. Both bugs have the same root cause: nobody, admin included, can see what a group touches. - **ownCloud** is the same picture. The admin manual documents blacklisting large groups from receiving shares and warns that deleting a user destroys everything they shared, but offers no impact view. Their [advisory on group shares](https://owncloud.com/security-advisories/deleting-received-group-share-for-whole-group) (a recipient can remove a received group share for the whole group) is another instance of group-share blast radius being invisible until it fires. - **OpenCloud** inherits the ownCloud model; [the sharing docs](https://docs.opencloud.eu/docs/user/sharing/internal/) describe sharing from the file side only. Nothing group-side. **Conclusion:** this is differentiator work, not parity work — one of the few places where we are not catching up but shipping something three competitors' users have asked for and not received. It also sits squarely in Cairn's positioning: the instance admin is accountable for what is on their own hardware, and "I can see what this group touches before I break it" is that accountability made visible. The caveat to hold honestly: the column is only as valuable as the model beneath it. Until this issue lands it shows two real reference types and no shares, which is honest but thin. Do not market it before the count is real. ### Sources - [nextcloud/server#5586 — list all shared files and who has access](https://github.com/nextcloud/server/issues/5586) - [nextcloud/server#25755 — removing a user from a group deletes others' shares](https://github.com/nextcloud/server/issues/25755) - [nextcloud/groupfolders#2827 — shares remain after a user leaves a group](https://github.com/nextcloud/groupfolders/issues/2827) - [ownCloud security advisory — deleting a received group share for the whole group](https://owncloud.com/security-advisories/deleting-received-group-share-for-whole-group) - [ownCloud file sharing configuration](https://doc.owncloud.com/server/next/admin_manual/configuration/files/file_sharing_configuration.html) - [OpenCloud internal sharing](https://docs.opencloud.eu/docs/user/sharing/internal/)
Author
Owner

Mockup rev 1 + the constraint that shaped it

sharing-rework-529-mockup.html delivered for review. Two decisions were taken before drawing, because the second one changes what the mockup can even depict.

The constraint: in Cairn the path decides who can decrypt, not the share

My earlier comment said "a group share must resolve to per-recipient keys the same way space membership does — worth checking against the custody model before committing to a design." Checked. The answer is that space membership works because the content lives in the space's path, and that does not generalise.

internal/storage/encrypt/group.go derives the key scope from the backend path: anything under /spaces/<name>/ is encrypted to that space's group recipient, everything else to the owning user. Its own comment on cross-scope moves is explicit — a rename or copy across the boundary must re-encrypt, "otherwise the moved ciphertext keeps its old key and the destination's readers cannot open it".

So adding an addressee to share.Store grants authorisation and changes nothing about decryption. Bob would be permitted to fetch bytes he cannot read. This is a real difference from OpenCloud and Nextcloud, where a share is a grant attached to a file wherever it sits.

Decision 1 — grant authorises, path keys, server re-wraps on read

Three options were on the table: re-encrypt on every share (collides with legal holds #138, versioning #541 and quota, and rewrites content on every membership change); keep sharing as space membership only (the divergence already rejected); or let the grant carry authorisation while reads go through the owner's key scope — the same mechanism the public-link handler already uses for unauthenticated callers.

Chosen: the third. No re-encryption, no data movement, membership changes take effect immediately, and it is consistent with ARCHITECTURE §4.3, which states plainly that Cairn is server-side transparent encryption and not client-side E2E.

The consequence, stated rather than buried: an internal share means the server opens the owner's file on the recipient's behalf. That is already true of Cairn today, but "per-user encryption" invites a stronger reading, so the handbook gains a sentence saying what the encryption does and does not protect against. The same wording should serve #238, which is deciding this at the peering boundary.

Decision 2 — #529 lands before #538

#538's Shares panel renders whatever the sharing model is. Building it first means building it against a model that is about to change. #530's build order becomes #529#538 → #539/#540 → #541.

What the mockup covers

Today's dialog versus the reworked panel (people and groups first, then links split into internal — resolves for people who already have access, grants nothing — and public, today's /s/ surface); three role labels mapped onto primitives that already exist (read, write, AllowUpload) rather than a new permission system; federated send relocated to its own act with one entry that branches by transport; the handbook wording; and the states that decide whether it feels finished — nothing shared yet, public links disabled by policy, an addressee that no longer resolves (fail-closed, says so rather than vanishing), and the recipient picker on an instance with no directory.

Four decisions I did not take

  1. Is an internal link a stored object or just the file's URL? Drawn as the plain URL — nothing to expire, revoke or count.
  2. Can a recipient re-share? Drawn as no. Re-sharing is where Nextcloud's model gets genuinely confusing, and adding it later is easier than removing it.
  3. What happens to shares when the owner's account is removed? Not drawn — Nextcloud deletes everything and surprises people; Cairn's fail-closed instinct says the grants stop resolving and an admin can see them, but that deserves its own decision.
  4. Is this one issue or three? The panel rework, the addressee in share.Store, and the federated-send relocation are separable and could ship in that order.

Nothing implemented. Review and mark up as usual.

## Mockup rev 1 + the constraint that shaped it `sharing-rework-529-mockup.html` delivered for review. Two decisions were taken before drawing, because the second one changes what the mockup can even depict. ### The constraint: in Cairn the path decides who can decrypt, not the share My earlier comment said "a group share must resolve to per-recipient keys the same way space membership does — worth checking against the custody model before committing to a design." Checked. The answer is that space membership works *because the content lives in the space's path*, and that does not generalise. `internal/storage/encrypt/group.go` derives the key scope from the backend path: anything under `/spaces/<name>/` is encrypted to that space's group recipient, everything else to the owning user. Its own comment on cross-scope moves is explicit — a rename or copy across the boundary **must re-encrypt**, "otherwise the moved ciphertext keeps its old key and the destination's readers cannot open it". So adding an addressee to `share.Store` grants **authorisation** and changes nothing about **decryption**. Bob would be permitted to fetch bytes he cannot read. This is a real difference from OpenCloud and Nextcloud, where a share is a grant attached to a file wherever it sits. ### Decision 1 — grant authorises, path keys, server re-wraps on read Three options were on the table: re-encrypt on every share (collides with legal holds #138, versioning #541 and quota, and rewrites content on every membership change); keep sharing as space membership only (the divergence already rejected); or let the grant carry authorisation while reads go through the owner's key scope — the same mechanism the public-link handler already uses for unauthenticated callers. **Chosen: the third.** No re-encryption, no data movement, membership changes take effect immediately, and it is consistent with ARCHITECTURE §4.3, which states plainly that Cairn is server-side transparent encryption and not client-side E2E. The consequence, stated rather than buried: an internal share means **the server opens the owner's file on the recipient's behalf**. That is already true of Cairn today, but "per-user encryption" invites a stronger reading, so the handbook gains a sentence saying what the encryption does and does not protect against. The same wording should serve #238, which is deciding this at the peering boundary. ### Decision 2 — #529 lands before #538 #538's Shares panel renders whatever the sharing model is. Building it first means building it against a model that is about to change. #530's build order becomes **#529 → #538 → #539/#540 → #541**. ### What the mockup covers Today's dialog versus the reworked panel (people and groups first, then links split into **internal** — resolves for people who already have access, grants nothing — and **public**, today's `/s/` surface); three role labels mapped onto primitives that already exist (`read`, `write`, `AllowUpload`) rather than a new permission system; federated send relocated to its own act with one entry that branches by transport; the handbook wording; and the states that decide whether it feels finished — nothing shared yet, public links disabled by policy, an addressee that no longer resolves (fail-closed, says so rather than vanishing), and the recipient picker on an instance with no directory. ### Four decisions I did not take 1. Is an internal link a stored object or just the file's URL? Drawn as the plain URL — nothing to expire, revoke or count. 2. Can a recipient re-share? Drawn as no. Re-sharing is where Nextcloud's model gets genuinely confusing, and adding it later is easier than removing it. 3. What happens to shares when the owner's account is removed? Not drawn — Nextcloud deletes everything and surprises people; Cairn's fail-closed instinct says the grants stop resolving and an admin can see them, but that deserves its own decision. 4. Is this one issue or three? The panel rework, the addressee in `share.Store`, and the federated-send relocation are separable and could ship in that order. Nothing implemented. Review and mark up as usual.
Author
Owner

Mockup approved — split into three, this becomes the tracking issue

All four open decisions answered (Nikola, 2026-09-17):

  1. Internal link is just the file's URL — no stored object, nothing to expire, revoke or count.
  2. Recipients cannot re-share. Only the owner manages the grant list.
  3. Owner-deletion semantics split out to #569, with a deep-research brief comparing ownCloud, oCIS, Nextcloud and Seafile.
  4. Split into three.

Sub-issues

  • #570 — shares gain an addressee (store, authorisation, read path, audit attribution, fail-closed resolution). Backend, TDD, invisible until #571.
  • #571 — the share panel (people and groups first, links split internal/public, roles, states). Blocked by #570.
  • #572 — federated send moves to its own act — the thing this issue was originally about. Independent; can land in any order.

Build order #570#571, with #572 whenever convenient. Then #538 follows, per the earlier decision that its Shares panel must render a settled model.

One correction to my own mockup

The mockup's block 7 proposed splitting as "panel rework, then the addressee, then federated relocation, in that order". That order is wrong and I am not propagating it: the panel has nothing to render without the addressee. Backend first. The issue bodies carry the corrected order; the mockup file does not, so read the issues as authoritative on sequencing.

Decisions recorded for the record

The grant authorises; the path keys. An addressee cannot make a recipient able to decrypt — encrypt/group.go derives the key scope from the backend path. The read goes through the owner's key scope, the mechanism the public-link handler already uses. Rejected: re-encrypt on every share (collides with holds #138, versioning #541, quota; rewrites on every membership change), and sharing-as-space-membership-only (the divergence this issue exists to close).

The consequence is stated, not buried. A share means the server opens the owner's file for the recipient. Already true today, but "per-user encryption" invites a stronger reading, so the handbook gains a sentence — carried in #571, and it should serve #238 at the peering boundary too.

Starting on #570.

## Mockup approved — split into three, this becomes the tracking issue All four open decisions answered (Nikola, 2026-09-17): 1. **Internal link is just the file's URL** — no stored object, nothing to expire, revoke or count. 2. **Recipients cannot re-share.** Only the owner manages the grant list. 3. **Owner-deletion semantics split out to #569**, with a deep-research brief comparing ownCloud, oCIS, Nextcloud and Seafile. 4. **Split into three.** ### Sub-issues - **#570 — shares gain an addressee** (store, authorisation, read path, audit attribution, fail-closed resolution). Backend, TDD, invisible until #571. - **#571 — the share panel** (people and groups first, links split internal/public, roles, states). Blocked by #570. - **#572 — federated send moves to its own act** — the thing this issue was originally about. Independent; can land in any order. Build order **#570 → #571**, with #572 whenever convenient. Then **#538** follows, per the earlier decision that its Shares panel must render a settled model. ### One correction to my own mockup The mockup's block 7 proposed splitting as "panel rework, then the addressee, then federated relocation, in that order". That order is wrong and I am not propagating it: the panel has nothing to render without the addressee. Backend first. The issue bodies carry the corrected order; the mockup file does not, so read the issues as authoritative on sequencing. ### Decisions recorded for the record **The grant authorises; the path keys.** An addressee cannot make a recipient able to decrypt — `encrypt/group.go` derives the key scope from the backend path. The read goes through the owner's key scope, the mechanism the public-link handler already uses. Rejected: re-encrypt on every share (collides with holds #138, versioning #541, quota; rewrites on every membership change), and sharing-as-space-membership-only (the divergence this issue exists to close). **The consequence is stated, not buried.** A share means the server opens the owner's file for the recipient. Already true today, but "per-user encryption" invites a stronger reading, so the handbook gains a sentence — carried in #571, and it should serve #238 at the peering boundary too. Starting on #570.
Author
Owner

Both remaining gates are closed: #572 (the send act, narrowed to peering after the send/share split — the OCM share continues as #603) shipped in v0.6.216, and #598 (Used-by real share counts + fail-closed group delete) shipped in the same release. The full arc of this tracker — grants model (#570), share panel (#571, eyeballed live and closed), send act (#572), and the scope addition (#598) — is built, tested, released, and live on both dogfoods. Closing the tracker.

Both remaining gates are closed: #572 (the send act, narrowed to peering after the send/share split — the OCM share continues as #603) shipped in v0.6.216, and #598 (Used-by real share counts + fail-closed group delete) shipped in the same release. The full arc of this tracker — grants model (#570), share panel (#571, eyeballed live and closed), send act (#572), and the scope addition (#598) — is built, tested, released, and live on both dogfoods. Closing the tracker.
Cordy closed this issue 2026-09-18 12:27:43 +00:00
Sign in to join this conversation.
No labels
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#529
No description provided.