Skip to content

server: removing a member from an album's roster reclaims nothing — their uploaded bytes stay charged to an account that can no longer reach them #473

Description

@justin13888

What happens today

S-C51 (PR #458) widened album writes from the owner to writer members. A writer member's upload is:

  • filed under the album owner's namespace (owner_id), because the owner's feed is the one every member's devices read; and
  • billed to the uploader (upload_user_id) — capsule-server/src/routes/upload.rs, and design/server.md's "owner_id is the namespace and upload_user_id is billed".

Publishing a later roster that omits that member changes neither fact. The asset stays in the owner's album, and its bytes stay attributed to the removed member in the quota ledger.

The ledger is not wrong — the bytes are still stored — but the account they are charged against can no longer reach them: a removed member may not write ops to that album, so they cannot delete their way back under quota. The only path that ever releases the attribution is the refcount collector (capsule-server/src/gc/mod.rs, QuotaStore::release_attribution, S-C44), which runs when the last reference to the bytes goes, i.e. only if the owner deletes the asset.

Why it was not fixed in #458

Reclaiming on removal is a protocol question no design document in this tree answers:

  • does the owner inherit the storage cost of what a departed member contributed?
  • does the member keep paying for bytes the owner still holds and still reads?
  • is removal from a roster a deletion at all, or explicitly not one (the MLS side treats it as a key rotation, not a data event)?

Each answer is a different product decision, and two of them let one account's quota pressure delete another account's photos. Inventing one inside a storage port would be the wrong place to decide it.

What a fix would need

  1. A decision recorded in design/quota.md and design/authorization.md about who owns the cost of a departed member's contributions.
  2. Whatever seam that decision implies — a re-attribution on apply_roster, an owner-initiated adoption, or an explicit "no reclaim, by design" note. QuotaStore already has both halves it would need (charge is idempotent per address; release_attribution releases by address to whoever holds it), so the port does not need widening for any of the three.
  3. Conformance coverage for whichever is chosen, in capsule-server/src/quota/conformance.rs.

Where it is currently recorded

capsule-server/src/membership/mod.rs module docs ("Removing a member reclaims nothing, and that is observable") and capsule-server/src/routes/roster.rs.

Refs #405. Found by review of PR #458.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions