Phase 1 of the federation/gossip layer fox sketched as the natural
extension of v9.8 admissibility's content-addressed identity. Two
peers ingesting the same dump already compute identical document_roots
and identical 8-dim cache_keys; the mesh layer is the wire-and-trust
plumbing that lets them dedup answers, exchange Merkle proofs, and
cleanly distrust an evicted member without a hard fork.
Cryptography (cryptography lib, audited):
Ed25519 — every membership mutation + (future) gossip envelope
is signed by the actor's pubkey.
X25519 ECDH — wraps each epoch's symmetric mesh secret to every
current member's DH pubkey via HKDF-derived AEAD key.
ChaCha20-P1305— AEAD for envelope payloads + per-member secret wrap.
State machine:
mesh_identity — singleton; this peer's keys + group name
mesh_roster — per-epoch (member_id, sign_pub, dh_pub, role)
mesh_epochs — epoch_id -> {started_at, started_event_hash,
secret_envelope JSON, reason}
meta:mesh.enabled flag — off by default; gates everything
Eviction works by rotating to a new epoch whose envelope omits the
kicked member. Their prior signatures stay verifiable (the older
roster row is retained), but any gossip from epoch+1 onward is
opaque to them — the secret was never shared with their pubkey.
Authority gate: only roster members with role='admin' can add or
kick. Self-kick is rejected explicitly. The last admin can't be
kicked. Schedule-rotate (refresh secret, no roster change) is open
to any current member as a session-hygiene op.
Audit-chain integration: every mesh state mutation writes an audit
event (mesh_init, mesh_enable/disable, mesh_epoch_rotate). The
epoch's started_event_hash backfills into mesh_epochs after the
audit row commits, giving each epoch a tamper-evident pin into the
ledger.
CLI subcommands: mesh init, mesh status, mesh enable, mesh disable,
mesh members, mesh add, mesh kick, mesh rotate. All read-only or
local-state-only — no network code paths in this commit.
The HTTP gossip wire (`mesh sync`, `mesh serve`) is the next phase.
Schema, cryptography, and roster state machine are all in place to
support it without further migration.
65 lines
1.8 KiB
Python
65 lines
1.8 KiB
Python
"""Mesh — gossip / membership layer for federated aborist trees.
|
|
|
|
Off by default. Loaded only when the user explicitly opts in via
|
|
`aborist mesh init` (creates this peer's identity) and
|
|
`aborist mesh enable` (flips the gating flag in the meta table).
|
|
|
|
The cryptographic substrate:
|
|
- Ed25519 (signing) — every gossip message and every membership
|
|
mutation event is signed by the sender's pubkey.
|
|
- X25519 (ECDH) — used to wrap each epoch's symmetric mesh
|
|
secret to every current member's DH pubkey, so the new secret
|
|
is reconstructible only by the post-rotation roster.
|
|
|
|
Membership state is per-epoch:
|
|
epoch 0 = group genesis (just the founder)
|
|
epoch N = the N-th roster mutation (add member, kick, scheduled rotate)
|
|
|
|
Eviction is a rotate where the kicked member's pubkey isn't in the
|
|
new envelope. Their previously-signed events stay verifiable forever
|
|
(historical roster preserved in mesh_roster), but they no longer have
|
|
the new secret, so any AEAD-protected gossip for epoch N+1 is opaque
|
|
to them.
|
|
|
|
This module deliberately avoids networking. The wire layer (HTTP/TLS
|
|
gossip server + sync client) lives in `aborist.mesh.wire` and is also
|
|
opt-in.
|
|
"""
|
|
|
|
from aborist.mesh.crypto import (
|
|
aead_decrypt,
|
|
aead_encrypt,
|
|
ecdh_shared_secret,
|
|
generate_dh_keypair,
|
|
generate_signing_keypair,
|
|
sign,
|
|
verify,
|
|
)
|
|
from aborist.mesh.state import (
|
|
MESH_ENABLED_KEY,
|
|
MeshIdentity,
|
|
MeshRosterEntry,
|
|
current_epoch,
|
|
init_identity,
|
|
is_enabled,
|
|
load_identity,
|
|
set_enabled,
|
|
)
|
|
|
|
__all__ = [
|
|
"MESH_ENABLED_KEY",
|
|
"MeshIdentity",
|
|
"MeshRosterEntry",
|
|
"aead_decrypt",
|
|
"aead_encrypt",
|
|
"current_epoch",
|
|
"ecdh_shared_secret",
|
|
"generate_dh_keypair",
|
|
"generate_signing_keypair",
|
|
"init_identity",
|
|
"is_enabled",
|
|
"load_identity",
|
|
"set_enabled",
|
|
"sign",
|
|
"verify",
|
|
]
|