pub fn fold_roster(
inner_editions: &[Event],
community_id: &CommunityId,
floors: &HashMap<String, (u64, [u8; 32])>,
) -> FoldedRosterExpand description
Fold a set of (already-decrypted) inner edition events into the current roster.
Each edition’s inner Schnorr signature is verified (the authorship proof); editions are grouped
per entity and version-folded to a head (from scratch, floor 0). A head is folded into the trusted
roster ONLY if it is chain-anchored (not gapped — fail closed on withheld history) AND
its entity_id binds to its content (a Role lives at entity_id == role_id, a Grant at
entity_id == grant_locator(community_id, member)) — so a signed edition can’t relabel
itself to a different role/member. Anything else is dropped and counted in skipped. The grant
binding is keyed by the community id (stable across a base rotation), so a re-anchored grant
folds under any epoch’s root — the keystone for re-anchoring.
floors is each entity’s persisted head (entity_hex → (version, self_hash), from
crate::db::community::get_all_edition_heads) — the refuse-downgrade FLOOR. Each entity’s
chain is folded from ITS held floor, not from scratch, so a withholding relay serving editions below
what we already hold can’t roll an authority chain back (the attack: resurrecting a since-revoked
admin’s old grant by withholding the revocation). An entity absent from floors (a bootstrapping
joiner) folds from genesis (floor 0); an empty map = a fresh joiner. A relay that serves only
below-floor editions for an entity yields no head for it → that entity is simply absent from this
fold (fail closed: it is not re-authorized off a rolled-back view; it self-heals when a relay serves
≥ floor).
This does NOT apply delegation-chain authorization — the signature proves WHO; deciding WHETHER they were allowed (rank + chain to the owner) is a separate, later layer.