The issue named the design question exactly — "the relay would learn the
fan-out shape unless the tokens hide it, and hiding it is the entire design
question". This answers it, in docs/FANOUT.md, with the measurements pinned by
GroupFanOutTests.
The premise was wrong twice, and both are now tests. /e2e/messages takes one
account and a LIST of that account's devices, so ten people with two devices is
ten requests, not twenty (relay#38 found this). And the blob is not what
repeats at all: an attachment is uploaded ONCE and named from inside every
recipient's sealed envelope by a token any member can fetch with — one 64 KB
picture sent to six people leaves exactly one row in attachments, and all six
download it.
So what a sender repeats is the envelope, measured at 572 bytes per member.
The entire prize is ~17.7 KB at the 32-member cap, not nineteen copies of a
photo.
And the tokens cannot hide the shape, for a structural reason rather than a
cryptographic one. Relay-side fan-out requires the relay to hold, at one
moment, a mapping from one blob to N destinations — and that mapping IS the
fan-out shape. It is not a leak beside the feature that might be engineered
away; it is the feature, described. Delivery tokens already do the part they
can, making destinations unlinkable to accounts; they cannot make the relay not
notice that N destinations are getting the same bytes, because copying is the
act of knowing that. Splitting it across N requests reassembles the same
mapping and pays the round trips being optimised. Blinding the reference needs
proxy re-encryption or oblivious storage, which is a different project with the
same §21.4 prerequisites. Delay obscures timing, not the row.
What would be given up is asserted as a test, so anyone implementing this has
to delete a passing test whose name says what they are deleting: nothing in the
database links the envelopes of one group message today. That matters more than
17 KB because sealed rosters (§8.9b) exist so a dump does not reveal your
groups — the claim /metadata makes in those words — and this would put the
group back in a row.
Precise about what is not claimed: a RUNNING relay can already infer a lot
from an identified send. The protection is against reading it later out of
stored rows, and against sealed sends where there is no sender to correlate on.
If round trips ever become the real complaint — a different issue from the one
filed — the narrow answer is recorded: batch several accounts per request on
the IDENTIFIED path only, where the relay already sees the sender and can
correlate the burst by timing, and never on the sealed one.
Everything is bounded by Group.maxMembers == 32, and the test fails if that
moves, so the document cannot go stale behind a raised cap.
650 relay tests in 58 suites green, core paths 7/7.
The issue named the design question exactly — "the relay would learn the
fan-out shape unless the tokens hide it, and hiding it is the entire design
question". This answers it, in docs/FANOUT.md, with the measurements pinned by
GroupFanOutTests.
The premise was wrong twice, and both are now tests. /e2e/messages takes one
account and a LIST of that account's devices, so ten people with two devices is
ten requests, not twenty (relay#38 found this). And the blob is not what
repeats at all: an attachment is uploaded ONCE and named from inside every
recipient's sealed envelope by a token any member can fetch with — one 64 KB
picture sent to six people leaves exactly one row in `attachments`, and all six
download it.
So what a sender repeats is the envelope, measured at 572 bytes per member.
The entire prize is ~17.7 KB at the 32-member cap, not nineteen copies of a
photo.
And the tokens cannot hide the shape, for a structural reason rather than a
cryptographic one. Relay-side fan-out requires the relay to hold, at one
moment, a mapping from one blob to N destinations — and that mapping IS the
fan-out shape. It is not a leak beside the feature that might be engineered
away; it is the feature, described. Delivery tokens already do the part they
can, making destinations unlinkable to accounts; they cannot make the relay not
notice that N destinations are getting the same bytes, because copying is the
act of knowing that. Splitting it across N requests reassembles the same
mapping and pays the round trips being optimised. Blinding the reference needs
proxy re-encryption or oblivious storage, which is a different project with the
same §21.4 prerequisites. Delay obscures timing, not the row.
What would be given up is asserted as a test, so anyone implementing this has
to delete a passing test whose name says what they are deleting: nothing in the
database links the envelopes of one group message today. That matters more than
17 KB because sealed rosters (§8.9b) exist so a dump does not reveal your
groups — the claim /metadata makes in those words — and this would put the
group back in a row.
Precise about what is not claimed: a RUNNING relay can already infer a lot
from an identified send. The protection is against reading it later out of
stored rows, and against sealed sends where there is no sender to correlate on.
If round trips ever become the real complaint — a different issue from the one
filed — the narrow answer is recorded: batch several accounts per request on
the IDENTIFIED path only, where the relay already sees the sender and can
correlate the burst by timing, and never on the sealed one.
Everything is bounded by Group.maxMembers == 32, and the test fails if that
moves, so the document cannot go stale behind a raised cap.
650 relay tests in 58 suites green, core paths 7/7.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The issue named the design question exactly — "the relay would learn the
fan-out shape unless the tokens hide it, and hiding it is the entire design
question". This answers it, in docs/FANOUT.md, with the measurements pinned by
GroupFanOutTests.
The premise was wrong twice, and both are now tests. /e2e/messages takes one
account and a LIST of that account's devices, so ten people with two devices is
ten requests, not twenty (relay#38 found this). And the blob is not what
repeats at all: an attachment is uploaded ONCE and named from inside every
recipient's sealed envelope by a token any member can fetch with — one 64 KB
picture sent to six people leaves exactly one row in
attachments, and all sixdownload it.
So what a sender repeats is the envelope, measured at 572 bytes per member.
The entire prize is ~17.7 KB at the 32-member cap, not nineteen copies of a
photo.
And the tokens cannot hide the shape, for a structural reason rather than a
cryptographic one. Relay-side fan-out requires the relay to hold, at one
moment, a mapping from one blob to N destinations — and that mapping IS the
fan-out shape. It is not a leak beside the feature that might be engineered
away; it is the feature, described. Delivery tokens already do the part they
can, making destinations unlinkable to accounts; they cannot make the relay not
notice that N destinations are getting the same bytes, because copying is the
act of knowing that. Splitting it across N requests reassembles the same
mapping and pays the round trips being optimised. Blinding the reference needs
proxy re-encryption or oblivious storage, which is a different project with the
same §21.4 prerequisites. Delay obscures timing, not the row.
What would be given up is asserted as a test, so anyone implementing this has
to delete a passing test whose name says what they are deleting: nothing in the
database links the envelopes of one group message today. That matters more than
17 KB because sealed rosters (§8.9b) exist so a dump does not reveal your
groups — the claim /metadata makes in those words — and this would put the
group back in a row.
Precise about what is not claimed: a RUNNING relay can already infer a lot
from an identified send. The protection is against reading it later out of
stored rows, and against sealed sends where there is no sender to correlate on.
If round trips ever become the real complaint — a different issue from the one
filed — the narrow answer is recorded: batch several accounts per request on
the IDENTIFIED path only, where the relay already sees the sender and can
correlate the burst by timing, and never on the sealed one.
Everything is bounded by Group.maxMembers == 32, and the test fails if that
moves, so the document cannot go stale behind a raised cap.
650 relay tests in 58 suites green, core paths 7/7.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
assigned to @paulhitt
mentioned in issue #27
deleted the
feat/attachment-range-requestsbranch. This merge request now targets themainbranchmentioned in commit
8146ce02f0changed the description