Skip to main content

Module org_rotation

Module org_rotation 

Source
Expand description

Org-key ROTATION on member removal (slice 10) — the granter-side primitive that bumps the epoch, plus the authenticated freshness marker that decides which epoch is allowed to author the org’s present.

§Inertness — scoped precisely (grep-provable)

As of slice 11 exactly ONE function here has a live call site: resolve_all_org_roots, wired into open_sync_subsystem behind the DEFAULT-OFF PARSLEE_SYNC_ORG_SCOPE gate (unset → byte-identical personal-only path; still audit-gated for real tenants). It only READS the epochs a member can unwrap — provisioning, no rotation authority.

Everything ELSE remains a leaf primitive with NO live call site — like slice 9’s MultiEpochOrgCipher, shipping the MECHANISM and leaving the wiring for later (audit-gated): rotate_org_key, sign_rotation_floor, verify_rotation_floor, and in particular is_authoritative, a PURE predicate deliberately NOT wired into the reducer (SyncState/fold_onto) — live-fold enforcement of freshness is deferred to the cryptographer audit. No floor is consumed anywhere yet, so the anti-rollback caller obligation (see verify_rotation_floor) does not attach to any live path.

§What rotation is (and is NOT)

Rotation does not — cannot — take a key away. History was authored under the old K_org, and remaining members must keep reading it (crate::org_key_provider::OrgAwareKeyProvider holds every epoch it can unwrap). Rotation is about which key is allowed to author NEW ops: mint a fresh K_org@(N+1) (crate::crypto::generate_org_key, independent of N), wrap it for the REMAINING members only, publish at epoch N+1, and raise a signed RotationFloor so remaining members treat post-cut epoch-N writes as non-authoritative.

§The freshness boundary — what it does and does NOT prove (audit note)

is_authoritative gates on kid >= floor_epoch || hlc <= rotation_hlc. The kid half is UNFORGEABLE: a removed member cannot produce an op at epoch N+1 (they lack K_org@(N+1) and cannot derive it). The hlc half is only a best-effort partition of HONEST history — the HLC is client-stamped (crate::oplog::Hlc), so a removed member holding K_org@N can BACKDATE an op to hlc <= rotation_hlc and slip past the historical side. That is tolerable ONLY because such a forged op is confined to epoch N (already readable to them, constraint (c)) and can only ever LOSE last-writer-wins to a genuine epoch-(N+1) op. Fully refusing a removed member’s writes needs per-op author signatures bound to a membership epoch, or backend admission authz — both DEFERRED to the audit / later slices. Do not read this module as closing that residual.

Structs§

ProvisionReport
The per-member outcome of provision_org_members. Best-effort: granted are the account ids that received a wrap this round; skipped pairs every other account id with WHY it got none (malformed pubkey, a low-order / non-contributory key that wrap_org_key rejects, or a publish failure). A non-empty skipped is NOT a batch abort — the caller reports both.
RotationFloor
A signed, monotonic marker that org org rotated to floor_epoch at logical time rotation_hlc. Remaining members use it via is_authoritative to stop treating a removed member’s post-cut epoch-<floor_epoch> writes as the org’s current truth.

Enums§

RotationError
Failures rotating an org key or handling a rotation floor.

Functions§

is_authoritative
Is an op — identified by its org-cipher epoch kid and its hlc — still the org’s CURRENT authoritative truth under floor?
provision_org_members
Wrap k_org at epoch for every member in members and publish each wrap — the granter’s provisioning entry point over the DIRECTORY-NATIVE MemberPublicKey shape (OrgKeyDirectory::fetch_pubkeys output), so a granter tool never has to touch X25519 types.
resolve_all_org_roots
Resolve EVERY epoch of org’s K_org a member can currently unwrap — the plural of crate::resolve_org_root. This is what populates the multi-epoch map crate::org_key_provider::OrgAwareKeyProvider already accepts: after a rotation a remaining member holds {N, N+1} and reads both generations.
rotate_org_key
Rotate org to new_epoch: wrap k_org_new for the REMAINING members ONLY and publish each wrap at new_epoch. The removed member is simply absent from remaining, so no wrap is ever authored for them — that omission, not any revocation, is the whole mechanism.
sign_rotation_floor
Sign a rotation floor as a trusted granter. Callers must ensure floor_epoch > prev_floor_epoch (also re-checked on verify).
verify_rotation_floor
Verify a rotation floor: its car_floor tag must be [ALG_ROTATION_FLOOR], its signature must verify_strict against one of the caller’s trusted granter keys, AND it must be internally well-formed (floor_epoch > prev_floor_epoch). Returns the verified floor_epoch on success. Fail-closed: any tag/parse/verify/well-formedness failure is an Err, never a silently-accepted floor.