What You Share With the Group Doesn't Carry Your Name
Everything you contribute to a shared group in NAOMS replicates to the other members as signed, verifiable records โ and until recently, every one of those records was stamped with your permanent root identity. This week's celebrated work closes that: contributions are attributed to a per-group pseudonym, the root identity appears nowhere on what leaves your machine, and โ the hard part โ the receiving side can verify and accept your contribution without ever being told who the pseudonym belongs to.
The most dangerous identifier is the one that appears everywhere.
NAOMS models a person as more than an account: at the bottom sits a single root identity โ a cryptographic self that owns everything you are in the system. That root is precious, and precious things should be scarce. Every place the root identifier is written down is a place where two observers can compare records and link them: the same person in the family group and the activist group, the same person behind two different public faces. Unlinkability isn't a feature you add at the end. It's a property you either preserve at every persistence boundary or lose at the first one.
We lost it at one โ and this week's celebrated work (item 1682) won it back at the hardest boundary the system has: the records that leave your machine.
Where the name was leaking
Groups in NAOMS โ we call them hives โ keep a shared, append-only history. Hives can issue credentials, carry shared memories, and record consent decisions; every entry is signed, and every member's machine replicates the history and verifies it independently.
The leak was in the sharing machinery itself. Every record you contributed to a group โ every shared memory, and even the consent receipt saying yes, I agree to share this here โ carried an attribution field, and that field held your root identity. Signed with it, replicated with it, stored with it on every other member's disk. The signature made the record trustworthy; the attribution made you linkable. Any two groups with one member in common, or anyone who ever obtained copies of two groups' histories, could join them on that field and collapse your separate contexts into one person.
The fix sounds simple to state: attribute contributions to a per-group pseudonym instead. Each member's pseudonym is derived from their root identity and the specific group, so the same person shows up under a different, unrelated name in every group they belong to. Knowing the pseudonym in one group tells you nothing about the pseudonym in another โ and nothing about the root.
Stating it is easy. Two things make it genuinely hard.
Hard part one: verification must survive
A signed history is only worth having if every member can verify it. If we strip the author's identity off the records, what stops a forger from writing entries under someone else's pseudonym?
The answer is a separation the design leans on hard: the key that verifies is not the name that attributes. Entries in a group's shared history are verified against the group chain's own signing identity โ that part is untouched, and verification is exactly as strong as before. The attribution field is a label, not a proof. The change moves the label from "your root identity" to "your per-group pseudonym" while the cryptographic spine underneath stays where it was. Nothing about trust in the history was traded away for the privacy โ a pattern we care about deeply, because a system that quietly weakens verification to gain a feature is lying to itself.
Hard part two: the receiver must recognize you without being told who you are
Here is the genuinely surprising part, and the reason this item spent days with a "blocked" banner before it celebrated.
When your contribution arrives on another member's machine, that machine wants to file it under a member it knows โ to maintain its own attribution table mapping pseudonyms to membership rows. The obvious design is to send the pseudonym's public key along with the record, or to run some enrichment exchange where peers distribute pseudonym keys to each other. Both were considered. Both have the same flaw: anything transmitted is a new surface โ something to bind, something to forge, something to get wrong.
The design that shipped transmits nothing. The receiving machine derives the answer itself. Membership in the group already tells it which identity keys belong to which members; the pseudonym derivation is deterministic; so the receiver can compute, from what it already legitimately holds, which member's pseudonym would match the arriving record โ and lazily provision its own attribution row on the spot. No key crosses the wire. There's no distribution protocol to attack because there is no distribution. The question the earlier design agonized over โ how do you stop a forged pseudonym key from being bound to the wrong member? โ simply never arises, because nobody ever accepts a pseudonym key from anyone.
sequenceDiagram
participant A as Your machine
participant H as Group history (replicates)
participant B as Co-member's machine
A->>A: derive per-group pseudonym
(root identity + this group, deterministic)
A->>H: append contribution
attributed to pseudonym โ root identity nowhere
H->>B: replicate signed record
B->>B: verify against the group's
own signing identity (unchanged)
B->>B: self-derive which member's pseudonym
matches โ from keys it already holds
B->>B: provision its own attribution row,
accept + store
Note over A,B: nothing on the wire or on B's disk
contains A's root identity
Proving it fired, and proving it can refuse
Green tests are necessary and not sufficient โ we've been burned before by tests that passed for the wrong reason. So the proof here is built to a stricter standard, one we now apply across the project: assert the mechanism, not just the outcome.
The capstone test runs two real, separate NAOMS instances talking over the real peer-to-peer transport. One member shares into a multi-member group under their pseudonym; the co-member's instance accepts it. The test doesn't just check the record arrived โ it reads the receiving instance's own logs to confirm the self-derivation path actually executed. And it checks the negative space: the plaintext root identity appears nowhere on the replicated record.
Then there's a committed kill-switch test โ a negative control that lives permanently in the suite. With the self-derivation path deliberately disabled, the receiving side must reject the pseudonymous contribution as an invalid signature and store nothing. It does. That test is the difference between "the door happened to be locked when we checked" and "we've proven the lock is what holds the door."
What this doesn't do โ the honest edges
Two limits, stated plainly, both from the signed-off record of the work.
One-to-one relationships still use your real name. Friendship in NAOMS โ a promise two keys must sign โ records the root identities of both parties, and its authorization logic accepts only them. Pseudonymous friendship is intended, but it is not wired: a pseudonym-signed friendship record would be rejected by the receiver today. The team explicitly declined to reroute that path just to make a broader claim true โ it's named follow-on work, not quietly-included scope.
What already left cannot be recalled. Group records shared before this fix carried the root identity, and they replicated. Copies on other members' machines are permanently beyond reach โ that's not a policy choice, it's distributed-systems physics, and pretending otherwise would be the worst kind of comfort. What the fix guarantees is the future: new contributions leak nothing, and your own machine's historical records were cleaned. The system says exactly this in its own sign-off, because a privacy property you overstate is a privacy property you don't have.
The shape of the lesson
The deepest design move here is subtraction. Every earlier sketch of this feature added something โ a key-distribution message, an enrichment protocol, a binding ceremony โ and every addition brought a forgery question along with it. The version that shipped removes the transmission entirely and lets each machine answer from what it already knows. The attack surface didn't get defended; it got deleted.
Unlinkability, it turns out, is less about hiding information than about refusing to move it.
Written by AI agents from real project logs; owned and edited by Mujo.
Written by AI agents from real project logs; owned and edited by Mujo.