Implements the protocol contract pinned in docs/mesh.md. Each peer runs a stdlib ThreadingHTTPServer; clients send Ed25519-signed envelopes carrying one of: ANNOUNCE_ROOT document_root + source_uri + versions ANNOUNCE_DERIVATION core_root <- surface_roots (proof-blob hash) ANNOUNCE_PROVIDENCE cache_key + audit_mode + answer_hash ANNOUNCE_FALSIFICATION cache_key + reason REQUEST_BODY/DELIVER_BODY pull-on-miss + Merkle-root verify WireEnvelope canonicalizes via sorted-key separator-tight JSON; the canonical bytes are what get signed. Receivers verify the signature against sender_id's sign_pub looked up in mesh_roster at the envelope's epoch_id — non-members of that epoch produce no valid signature, so they're silently rejected (401, no audit event). Each accepted ANNOUNCE_* writes one 'mesh_received' event into the local audit chain whose body is the full signed envelope (the remote's signature stays attached for non-repudiation). The receiver's chain stays internally consistent because we append in receive-order. REQUEST_BODY/DELIVER_BODY: the responder ships the document text plus per-chunk leaf hashes; the client re-derives the Merkle root from those leaves and refuses to return any body whose leaves don't reconstruct the requested root. Tests: 17 unit (envelope canonicalization, sig verify against roster, type validation, tampered-body rejection, audit-event write) + 5 end-to-end (two real HTTP peers on ephemeral ports exchanging announces and bodies). 22/22 green. Deferred to later commits, per docs/mesh.md: - CLI verbs (mesh serve, mesh sync) — pending downstream merge - per-peer chain-of-claims tracking (catchup, replay, fork detection) - optional AEAD encryption of message bodies (contract says optional)
47 lines
1 KiB
TOML
47 lines
1 KiB
TOML
[build-system]
|
|
requires = ["setuptools>=68"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "aborist"
|
|
version = "0.0.1"
|
|
description = "An arborist for trees and forests of cross-linked information"
|
|
readme = "README.md"
|
|
license = { text = "AGPL-3.0-only" }
|
|
requires-python = ">=3.10"
|
|
authors = [
|
|
{ name = "Russell Ballestrini", email = "russell@unturf.com" },
|
|
{ name = "foxhop" },
|
|
{ name = "TimeHexOn" },
|
|
]
|
|
dependencies = [
|
|
"httpx>=0.27",
|
|
"zstandard>=0.22",
|
|
"cryptography>=42",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
html = [
|
|
"selectolax>=0.3",
|
|
]
|
|
wikitext = [
|
|
"mwparserfromhell>=0.6",
|
|
]
|
|
mesh = [
|
|
# httpx is already in core deps; mesh wire only depends on stdlib +
|
|
# cryptography (also core). This extras block exists as the documented
|
|
# opt-in surface even though no extra packages are required today.
|
|
]
|
|
dev = [
|
|
"pytest>=8",
|
|
"aborist[html]",
|
|
"aborist[wikitext]",
|
|
"aborist[mesh]",
|
|
]
|
|
|
|
[project.scripts]
|
|
aborist = "aborist.cli:main"
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["."]
|
|
include = ["aborist*"]
|