The complete byte-level reference: anchor layout, packet types, dispatcher rules, both consensus protocols, fragment routing, the governance pipeline, and the full threat model.
New to PHEUN? Start with the whitepaper — a shorter, self-contained paper covering the problem, the mechanism and the mathematics. This document is what you read to implement or audit the protocol.
This specification is a living document and will change. It describes the implementation as it stands on the date above, down to byte offsets and packet codes, so it moves whenever the code moves — implement against the newest revision, not a saved copy. The whitepaper is the stable document: it states the architecture and the reasoning, names no packet codes or version numbers, and is not expected to change.
A purely peer-to-peer system would let humans publish, communicate, and govern without intermediaries — without companies that can suspend accounts, governments that can compel disclosure, advertisers that can financialise attention, or moderators that can rewrite history. Existing decentralised systems either reduce to a single global chain (sequencing bottleneck, ~10⁴ writes per second ceiling), depend on a privileged validator set (a rebranded admin), or sacrifice security to scale (variable-format payloads, classical cryptography vulnerable to quantum attack).
We propose an alternative. The Peace and Harmony Earth United Network — PHEUN — is an anchor-stream of immutable 420-byte records distributed across 10,000 payload-addressed Sacred Anchor Index buckets, with consensus reached not through a global ordering but through deterministic byte placement, NIST post-quantum cryptography (ML-DSA-65, ML-KEM-1024, AES-256-GCM, BLAKE3), and a self-verifying propagation check at every anchor's birth (each receiver re-runs the author's own proof). Identity is regenerated at login from nine personal inputs the human alone holds. Every citizen runs one node; the node IS the user; the user IS the server. There is no token, no fee, no admin, no kill-switch, no global delete operation.
Sybil resistance is provided by the storage curve, not by stake or proof-of-work. Per-anchor admission is self-verifying: every receiver re-runs the author's signature and matches the carried genesis against the canonical one at SAI(GUIDE), so a forged or impostor anchor dies at every hop. Privacy-sensitive packet classes are wrapped in a 3-hop ML-KEM-1024 onion. Governance is universal and SIGN-scoped: any document — including the network's own Constitution — uses the same proposal/vote/consensus pipeline at a 75 % threshold. Protocol evolution is soft-fork-only by design: the wire format never changes, but new schemas, new packet types, and new algorithm selectors ride additively through a published extension lane.
Centralised platforms now mediate almost all of human communication, publication, payment, and political organisation. The platform decides which posts are visible, which accounts exist, which transactions clear, which speech is illegal, and which words may be typed.
Decentralised alternatives have, by and large, repeated the same architecture under a new logo. A blockchain with a sequencing committee is still a sequencing committee. A fediverse with admins is still a federation of admins. Even peer-to-peer storage protocols typically presume a separate identity layer, a separate payment layer, a separate moderation layer — and each of those layers re-introduces a privileged actor.
The thesis of this paper is that a different architecture is possible. One in which the protocol contains no privileged actor; the wire format is byte-frozen and never changes between governance cycles; identity is generated locally from inputs the human alone holds; consensus is a property of deterministic placement combined with a small Byzantine fault-tolerant gate at the moment each record is born. Combined with NIST-standardised post-quantum primitives in fail-closed cryptographic paths, the result is a network in which:
PHEUN is not a payment system, although it can host barter; it is not an anonymity network, although it onion-routes its sensitive packets; it is not a blockchain, although it is an immutable signed ledger. It is the substrate on which all of those services can be expressed without re-introducing a privileged operator. Where Bitcoin replaced the central bank with proof-of-work and Tor replaced the trusted ISP with onion routing, PHEUN replaces the centralised internet substrate itself with a single deterministic mesh.
The architectural soul of PHEUN, and the single non-negotiable invariant that every other design choice in this paper preserves, is the equivalence: one human user equals one Guide ID equals one Node ID equals one server equals one profile equals one Guide login equals one device equals one codebase instance. This is not a relation. It is a hard equality across every clause.
Every citizen of Earth who joins the network runs their own full node on their own device, and the node is the user. The user is the server. There is no scenario in which N users use node X. There is no hosting tier, no operator class, no lite-client downgrade path, no shared instance that any citizen would log into. "Concurrent viewers" on a node means the same human with multiple browser tabs open on the same machine running the same node — never two different people.
The only multi-user interaction in PHEUN is node-to-node: peer Alice's node talking to peer Bob's node. Per-node load equals per-user load. Per-node metrics are per-user metrics. Per-node subscriptions are per-user subscriptions. The 1:1:1:1 invariant has six immediate consequences:
The invariant is enforced at multiple layers: a node-owner lock file binds the device to exactly one Guide ID at first login; the vault, session, notification, and PAC tables are all keyed by a single Guide ID with no tenant column; WebSocket browser tabs share one connection set associated with one Guide ID; ML-DSA-65 signatures bind every anchor to one signing keypair derivable only from one citizen's nine personal inputs.
Identity in PHEUN is regenerated locally from nine personal inputs the human alone holds. The server stores the public key and a BLAKE3 fingerprint of it (so a restarted node can resume identity verification); the private key never leaves the device; the keypair itself is recreated from the inputs at every login and zeroed from memory immediately after the session is signed.
The nine inputs are facts the citizen knows in combination — not in isolation. They are typed at first registration and remembered (or, with explicit acceptance of the recovery risk, recorded) by the human alone: date of birth; naming day; keyword; phrases 1, 2, and 3; a memory word; a trinity code; and the chosen Guide ID handle itself. The combination matters. Any single input may be guessable from public sources or social engineering; the conjunction of all nine is intended to require either the citizen's full participation or a brute-force search large enough to be economically unattractive.
The nine-input scheme is self-sovereign in the strict sense: the protocol does not store any of these inputs, the network never sees them, and the citizen's recovery path is to re-enter them. There is no email, no SMS code, no recovery question, no key-file. Loss of all nine inputs is loss of the identity, and PHEUN has no path to recover it. This is by design.
The nine inputs feed a deterministic key derivation pipeline. The inputs are concatenated in a canonical order with a domain-separating prefix and length-prefixed encoding. The concatenation is hashed with BLAKE3 to a 32-byte seed. The seed is the input to ML-DSA-65 KeyGen, which is itself deterministic when called with a fixed seed: the same inputs always produce the same keypair on any device. The 16-character public Guide ID handle is derived from the BLAKE3 of the public key, base32-encoded and truncated.
The derivation is intentionally cheap on the citizen's device and intentionally expensive at adversarial scale. ML-DSA-65 KeyGen is sub-millisecond on consumer hardware, so a single login is invisible to the citizen. A brute-force attacker, however, must run the full nine-input concatenation, BLAKE3, and ML-DSA-65 KeyGen for every guess.
The first anchor any Guide ID ever signs is its Genesis Profile (category byte 0x01, type byte 0x00). The Genesis Profile binds the Guide ID to the public key by carrying the public key's BLAKE3 fingerprint in the PROOF field of the 420-byte record (bytes 65–96). Every subsequent anchor signed by this Guide ID is verified against this single source of truth. SVAP enforces uniqueness at admission: the home holders at SAI(GUIDE) reject any second genesis for a Guide ID already claimed (first-claim-wins).
At every login the citizen retypes the nine inputs into the local browser. The browser regenerates the seed, the keypair, and signs a presence attestation. The local server verifies the attestation under the supplied public key, computes BLAKE3 of the supplied public key in constant time and compares it to the on-chain Genesis Profile's PROOF, and walks the citizen's AnchorChain (§14) for fork detection. If all three checks pass, the server issues a session token — secured by HTTPS and instant revocation on logout rather than pinned to the requesting IP, so a mobile or CGNAT citizen whose carrier rotates its public IP is not logged out mid-session — and the keypair is zeroed from browser memory. The session lasts the node's process lifetime — there is no timed auto-logout, so a logged-in node stays a full LIVE anchor-holding participant for as long as it runs. A session ends only on process restart (which forces a fresh login: the ML-DSA-65 private key is RAM-only and gone on restart, per Vision principle 21), explicit logout, or a PAC fork-lock. A non-blocking modal reminds the citizen every 30 days to confirm they still remember their nine (irrecoverable) keys — a reminder, never a logout.
The deterministic derivation property — same inputs, same keypair — has a deliberate consequence: the citizen can log in from any device by re-entering the nine inputs. There is no "device pairing" step, no QR-code handoff, no key export. This creates a self-forking risk: if the citizen logs in concurrently from two devices and posts an anchor from each, both devices may sign distinct anchors at the same PAC_COUNT. PHEUN ships three layers of defence — login-time educational modal, login walk plus self-subscription, and local mint hook (full detail in §14). A locked Guide ID is dead by design; the citizen creates a new Guide ID, the sealed history of the old one stays readable forever.
PHEUN's content model has exactly two layers, and the boundary between them is enforced everywhere — in storage, in routing, in cryptography, and in propagation. Layer 1 is the anchor: a public, permanent, signed, 420-byte record that names a piece of content. Layer 2 is the payload: the actual content the anchor names, encrypted, fragmented, and distributed across the mesh by content-addressed routing. Anchors are SAI-routed (§6); payloads are XOR-DHT-routed (§13).
Private conversation is the deliberate exception. Because anchors are public by construction, direct messages and calls are not anchors and never enter the AnchorStream — they are end-to-end encrypted peer-to-peer traffic with store-and-forward delivery, held in each participant's own local message store. Minting an anchor per message would place a permanent, undeletable, publicly-visible record of who spoke to whom and when into a ledger with no delete operation — a metadata disclosure far worse than anything payload encryption prevents. What a citizen publishes is permanent; what they say privately is not.
The anchor is the atomic ledger record. Every action a citizen publishes — post, comment, governance vote, economy offer, document amendment, subscription change, share — is born as exactly one 420-byte anchor. Anchors are public by construction. They are the ledger. There is no anchor encryption. There is no private anchor. Every anchor that any citizen ever signs is, the moment it is admitted to the network, available to every other citizen to read, mirror, query, cite, and subscribe to. This is the price of an open permissionless ledger and PHEUN owns it explicitly: the protocol provides no filter, no takedown, no flag, no allow-list, no admin, no moderator, and no global delete.
The payload is the actual content of an action — the body of a post, the audio of a voice memo, the bytes of a film, the source of a wiki article, the text of a direct message, the photographs of a catalog item. PHEUN supports payloads up to 10 GB per anchor, which covers the great majority of human content including full-length films at distribution-quality bitrates.
Payloads are not stored inside the anchor. They are AES-256-GCM authenticated-encrypted with a key derived per anchor from BLAKE3(CORE ‖ SEAL ‖ PAC), split into sacred-math-sized fragments, and distributed across the mesh by PayloadWeave (§13), a Kademlia-style XOR-DHT keyed by the anchor's CORE. Every fragment of one anchor lives in the same XOR neighborhood (K_NEIGHBORHOOD = FLOOR × totalFragments closest peers to CORE, author excluded); each peer holds exactly one fragment, assigned by XOR rank — the r-th closest peer holds index (r mod totalFragments), a coverage-complete rule that guarantees no index is orphaned (§13.1). A 1000-fragment film therefore scatters across thousands of unique peer-slots, with mobile-class nodes typically holding zero or one fragment of any specific anchor where they fall in the neighborhood, never the whole film.
The CORE hash binds both layers. CORE is computed as BLAKE3 over the concatenation of (the manifest section bytes ‖ the payload bytes), with the signature slot excluded. The manifest section carries the payload's metadata — payload count, MIME types, file names, sizes, the embedded public key — and the fragment manifest. Tampering with any payload byte breaks CORE; tampering with any manifest field breaks CORE; tampering with the embedded public key breaks CORE. Any of these tamperings invalidates the anchor's ML-DSA-65 signature, which every receiver re-verifies at admission.
The two-layer model gives PHEUN three properties that single-layer ledgers cannot have at the same time. Routability with arbitrarily large content: the anchor stream stays small (420 bytes per record), so every node can hold its share of the ledger and every query is cheap. Encrypted-by-default content with public-by-construction metadata: the anchor is public; the payload is encrypted. A peer that holds a fragment can verify its integrity but cannot read its plaintext without the anchor. Right-to-erasure compliance without anchor rewrite: GDPR-style erasure is satisfied by destroying the AES key derived from the citizen's anchor — the encrypted fragments on the mesh become unreadable forever, even though the ciphertext continues to exist. The anchor itself stays on the chain (Vision §20: anchors are permanent); the payload is forgotten by erasing the key.
The atomic unit of the anchor stream is a fixed-size 420-byte record. Every action on PHEUN — across all categories and types — is one of these. The byte layout is byte-frozen for the lifetime of the V1 protocol and never changes between governance cycles. The wire-form representation is the 840-character lowercase hex encoding of the buffer.
| Block | Range | Bytes | Concept |
|---|---|---|---|
| 1 | 0–124 | 125 | Cryptographic Identity |
| 2 | 125–229 | 105 | Chain and Stream |
| 3 | 230–237 | 8 | Sacred Anchor Index Routing |
| 4 | 238–255 | 18 | Content Classification |
| 5 | 256–266 | 11 | Consensus Governance |
| 6 | 267–276 | 10 | Mesh and Payload |
| 7 | 277–370 | 94 | Social Discovery and Avatar |
| 8 | 371–419 | 49 | Soft-Fork Lane |
| Range | Field | L | Description |
|---|---|---|---|
| 0–31 | CORE | 32 | BLAKE3(manifest section ‖ payload bytes), excluding the signature slot. The anchor's identity hash and primary key. |
| 32–63 | SEAL | 32 | BLAKE3 of the full ML-DSA-65 signature — the immutable ledger's only binding to that 3,309-byte signature, which is far too large for the anchor and lives in the payload's signature slot instead. checkSignature enforces BLAKE3(sig) == SEAL before the payload opens. It is also an input to the payload key, BLAKE3(CORE ‖ SEAL ‖ PAC) — but that is a use, not an identity: SEAL is a signature fingerprint, not a key seed or a nonce. |
| 64 | SEAL_PROTOCOL | 1 | Hash family for SEAL derivation. V1 = 0x01 (BLAKE3). |
| 65–96 | PROOF | 32 | BLAKE3 of the signer's ML-DSA-65 public key. The genesis-anchor PROOF binds the Guide ID. |
| 97 | PROOF_PROTOCOL | 1 | Hash family for PROOF computation. V1 = 0x01. |
| 98 | CRYPT | 1 | Payload cipher selector. V1 = 0x01 (AES-256-GCM with BLAKE3-KDF). |
| 99 | GUARD | 1 | Quantum signature algorithm selector. V1 = 0x01 (ML-DSA-65). |
| 100–115 | GUIDE | 16 | Author's Guide ID, UTF-8, null-padded. |
| 116–124 | TIME | 9 | Unix milliseconds at sign time, big-endian. Byte 116 reserved as a CLOCK_SOURCE soft-fork slot. |
The four selector bytes (SEAL_PROTOCOL, PROOF_PROTOCOL, CRYPT, GUARD) are the protocol's primary upgrade lane for cryptographic primitives. A future ML-DSA-87 deployment would land at GUARD = 0x02, with 0x01 continuing to be served by readers for all anchors signed under V1.
| Range | Field | L | Description |
|---|---|---|---|
| 125–156 | PAC | 32 | WHO chain. Pointer to the previous anchor in this Guide ID's chain. The only walked chain in PHEUN. |
| 157–160 | PAC_COUNT | 4 | Monotonic per-Guide-ID counter. Genesis = 1; each subsequent anchor increments by one. |
| 161–192 | LINK | 32 | WHERE pointer. CORE of the anchor this one replies to or builds on. Stored, not walked. |
| 193–224 | ORIGIN | 32 | WHAT pointer. CORE of the genesis anchor of the document, thread, or stream. |
| 225–227 | LINE | 3 | Document line counter, 24-bit (~16.7M lines per document). |
| 228–229 | LINE_VERSION | 2 | Per-line revision counter, 16-bit (65,535 revisions per line). |
| Range | Field | L | Description |
|---|---|---|---|
| 230–231 | SAI | 2 | This anchor's home Sacred Anchor Index, computed by the dispatcher (§6). |
| 232–233 | PAC_SAI | 2 | SAI of the PAC-linked anchor (a routing hint for chain walks). |
| 234–235 | LINK_SAI | 2 | SAI of the LINK parent. |
| 236–237 | ORIGIN_SAI | 2 | SAI of the ORIGIN genesis. |
| Range | Field | L | Description |
|---|---|---|---|
| 238 | CATEGORY | 1 | Anchor category. The eight categories are enumerated in §7. |
| 239 | TYPE | 1 | Type within the category. 0x00 universally = Genesis Sign. |
| 240 | FLAGS | 1 | 0x00 regular, 0x01 consensus lock, 0x02 tally checkpoint. |
| 241 | TONGUE | 1 | ISO language code byte. |
| 242 | MATURITY | 1 | Self-declared content maturity (All / 13+ / 18+ / 21+). |
| 243–245 | ZONE | 3 | Geographic zone code. One byte country, two bytes city or region. |
| 246–255 | TAGS | 10 | Ten one-byte content tag codes from a shared 256-value namespace. Three mandatory non-zero, seven optional. |
| Range | Field | L | Description |
|---|---|---|---|
| 256–260 | ACCORD | 5 | Aggregate yes-vote tally as of this anchor's mint. 5-byte big-endian integer. |
| 261–265 | DISSENT | 5 | Aggregate no-vote tally as of this anchor's mint. |
| 266 | RATIO | 1 | Approval ratio mapped to 0–200 range; 150 is the 75 % threshold. |
| Range | Field | L | Description |
|---|---|---|---|
| 267–268 | FRAGMENT | 2 | Total fragment count for this anchor's payload. |
| 269–270 | PAYLOAD_COUNT | 2 | Logical payload count. 0 = metadata-only, 1 = text+preview, 2+ = attachments. |
| 271–276 | TALLY | 6 | Running interaction count within thread or stream. 48-bit monotonic. |
| Range | Field | L | Description |
|---|---|---|---|
| 277 | SIGN | 1 | Document id from the closed registry — 0x00 none, 0x01 Constitution, 0x02 Curriculum, 0x03–0xFF unallocated (§15). Not text. |
| 278–293 | TITLE | 16 | Short display label. |
| 294–309 | HASHTAG | 16 | Discoverability tag (#hashtag or @mention). |
| 310–341 | PREVIEW | 32 | First 32 bytes of payload text — the card-render quote. |
| 342 | SPAN | 1 | Runtime of the payload's timed media in minutes (0 = none, ceiling 255). Range-searchable by length. |
| 343–344 | CLIENT_VERSION | 2 | Build version that minted this anchor. Used for soft-fork dispatch (§20). |
| 345–370 | AVATAR | 26 | Required compact SVG reconstruction key selected explicitly for this anchor. 208 bits: 20 glyphs at 8 bits each, plus palette, alignment, weight, case, letter-spacing, frame and texture. Keys may be reused, but are never inherited or defaulted. |
| Range | Field | L | Description |
|---|---|---|---|
| 371–372 | FREE_SCHEMA | 2 | Schema selector for the FREE_PAYLOAD that follows. 0x0000 = empty, 0xFFFF = TLV container. |
| 373–419 | FREE_PAYLOAD | 47 | Schema-defined payload bytes. Up to 47 bytes; layout depends on FREE_SCHEMA. |
Block 8 is the protocol's additive extension lane. New features land as new schema IDs in the FREE_SCHEMA registry; old readers see an unrecognised schema as opaque hex and ignore the schema-specific behaviour, but verify CORE and the signature normally. §20 specifies the soft-fork model.
The 10,000 Sacred Anchor Index buckets are not a chain. There is no chain zero. There is no genesis block. There is no global ordering. Sacred Anchor Indexes are payload-addressed storage targets: each anchor's home SAI is computed deterministically from its own bytes by a published dispatcher table, and two nodes walking the same SAI with the same inputs observe the same byte order.
The fundamental SAI computation reduces a 32-byte hash to a 16-bit Sacred Anchor Index by taking the first two bytes as a big-endian integer modulo 10,000:
SAI(h) = uint16_be(h[0:2]) mod 10000
SAI(SIGN) = SAI(BLAKE3(SIGN_bytes))
Because the inputs to the reduction are uniform random (BLAKE3 outputs and Guide-derived signed values), the resulting SAI is uniformly distributed across the 10,000 buckets.
| Cat | Type | Flags | Routes to | Anchor class |
|---|---|---|---|---|
| any | 0x00 | any | SAI(SIGN) | Genesis Sign — opens a governed document, once, from that document's own page. |
0x01 | 0x00 | any | SAI(GUIDE) | Genesis Profile — identity binding. |
0x04 | 0x60 | any | SAI(SIGN) | Governance proposal. |
0x06 | 0xA1 | any | SAI(LINK) | Comment / Reply — co-located with parent. |
0x04 | 0x61 | 0x00 | SAI(CORE) | Vote Yes ballot — scattered. |
0x04 | 0x62 | 0x00 | SAI(CORE) | Vote No ballot — scattered. |
0x04 | 0x61 | 0x01 | SAI(SIGN) | Consensus Approved — co-located with document. |
0x04 | 0x62 | 0x01 | SAI(SIGN) | Consensus Denied. |
0x04 | 0x61 | 0x02 | SAI(LINK) | Tally Yes snapshot — co-located with proposal. |
0x04 | 0x62 | 0x02 | SAI(LINK) | Tally No snapshot. |
| default | default | default | SAI(CORE) | Regular content anchors. |
The split between SIGN-co-located writes (proposal, consensus) and CORE-scattered writes (ballots) is the load-balancing primitive that lets a single proposal absorb a billion ballots without saturating any one bucket. A single-SAI query at SAI(SIGN) returns the document outline; a single-SAI query at SAI(LINK) returns every tally snapshot for one proposal; the actual ballots are aggregated on demand by a 10,000-SAI count fanout.
The dispatcher is fully deterministic. Two nodes with the same anchor bytes always compute the same SAI. This is the foundation of consensus by placement: two nodes never disagree about where an anchor belongs. Within a Sacred Anchor Index, sort order is also deterministic — primary key is TIME; ties on TIME break on PAC; ties on PAC break on the full 840-character hex transaction string. Two nodes walking the same SAI bucket observe the same byte order, byte for byte.
Even the Sacred Anchor Index this node owns is queried through an outbound announce-and-pull cycle against the peer that covers it, never by reading the local table directly. A node with one Sacred Anchor Index cannot trust itself as a query source, because trust would presume the node had already verified its own data through some other channel — which it has not, except by virtue of having received those anchors from peers via gossip cascade or sync. A query is, in PHEUN, always a network operation.
Every anchor in PHEUN belongs to exactly one of eight semantic categories, encoded in the CATEGORY byte at position 238.
| Byte | Category | Primary Use |
|---|---|---|
0x01 | Identity | Genesis Profile, profile updates, presence attestations, device-binding anchors. |
0x02 | Shelter | Places, properties, community spaces, building info, host pages. |
0x03 | Education | Courses, lessons, syllabi, study materials, quizzes, flashcards. |
0x04 | Democracy | Proposals, votes (yes/no), consensus locks, tally snapshots. The governance category. |
0x05 | Economy | Barter offers (compute, bandwidth, storage, services, physical goods). |
0x06 | Social | Posts, comments, replies, shares, quotes, reactions. |
0x07 | Media | Films, music, podcasts, photo albums, channels, streams. |
0x08 | Knowledge | Wiki articles, encyclopaedia entries, research papers, citations, glossaries. |
PHEUN has exactly eight platform categories. There is no reserved 9th slot. The eight cover every use case identified to date — health and wellness logs sit naturally as Identity sub-types or Social posts depending on privacy intent; spirituality, sports, journalism, hobbies, dating, and pets all distribute across the existing eight without a dedicated home of their own. Consensus and tally semantics are FLAGS-byte states on Democracy anchors (FLAGS=0x01 = consensus lock, FLAGS=0x02 = tally snapshot), not a separate category. Future protocol evolution rides on the soft-fork lane (§20) by adding new TYPE bytes inside an existing category's range, new FREE_SCHEMA values, or new dispatcher subtypes — never by allocating a 9th category.
The split is use-case-shaped, not technology-shaped. Categories determine the default feed scope, the discovery filters available, and the subset of types and flags that have meaning. Categories do not enforce content rules — there is no protocol-level content moderation — but they organise the substrate for citizen-driven discovery. The TYPE byte at position 239 lives in a single global 256-slot namespace partitioned into per-category byte ranges (Identity 0x01–0x1F, Shelter 0x20–0x3F, Education 0x40–0x5F, Democracy 0x60–0x7F, Economy 0x80–0x9F, Social 0xA0–0xBF, Media 0xC0–0xDF, Knowledge 0xE0–0xFF). Type 0x00 is universally the Genesis Sign across every category.
The network fingerprint is the single 32-byte digest that walls off forks at handshake time, before any authenticated traffic flows between two peers. Two peers with different fingerprints are different networks; the protocol drops the connection at the handshake boundary. There is no fingerprint negotiation, no version handshake that allows partial compatibility, no graceful degradation. A fingerprint mismatch is a hard reject.
fingerprint = BLAKE3-32(
HOPE_VERSION
‖ SAI_COUNT
‖ ANCHOR_BYTE_LAYOUT
‖ sorted(GENESIS_AUTHORITY_PROOF_HASHES)
‖ approved_crypto_primitives
‖ approved_packet_type_table
)
The Genesis Authority PROOF hashes are the BLAKE3-32 fingerprints of the public keys associated with the twenty-one Genesis Authority Guide IDs (nateofearth2100z, bootstrapnode001..bootstrapnode020); they are sorted before hashing so the order of declaration does not affect the digest.
Negotiation creates a downgrade attack surface, requires the protocol to define partial compatibility windows, and makes byte semantics depend on which version a particular peer happens to be speaking. PHEUN takes the opposite stance. The wire format is byte-frozen; all evolution happens through the soft-fork lane (§20): new schemas in the FREE region, new algorithm selector bytes, new packet types, new dispatcher subtypes — all additive, all opaque to old readers, none of which rotate the network fingerprint. A real protocol upgrade — one that would change the byte layout, the SAI count, the crypto primitives' approval list, or the Genesis Authority roster — produces a new fingerprint, and PHEUN does not implement any mechanism to coordinate such a departure across the existing network.
HOPE is the pure-UDP node-to-node transport. The acronym maps to the design intent: Hardened (fail-closed cryptography, egress limiter, fingerprint check, BFT), Onion (Triple Sentry three-hop relay on sensitive packets), Post-quantum (ML-DSA-65, ML-KEM-1024, AES-256-GCM, BLAKE3 throughout), Exchange (peer-to-peer mesh). HOPE is not QUIC and shares no wire format with QUIC. WebSocket is reserved for the local browser-to-node UI link inside the citizen's own device and is never used between nodes.
TOTAL = 66,666 connections mesh = 50,000 // 5 community peers × 10,000 SAIs reserve = 16,666 // multi-coverage / heavy peers / bursts passport cache = 1,000,000 entries on disk (~1.5 GB)
Live mesh covers the security substrate (5 community peers per SAI minimum; §24); passport cache covers the discovery substrate. At billion-user scale the live edges of one node × N nodes give linear network growth with O(1) per-anchor work; ~99 % of lookups hit the cache and never touch the mesh.
Pairwise sessions use ML-KEM-1024 key encapsulation with AES-256-GCM payload encryption. SESSION_KEY_EXCHANGE bootstraps a fresh ML-KEM-1024 session post-handshake; SESSION_KEY_ROTATE re-keys an existing session every N packets or M minutes for forward secrecy. A decapsulation failure during rotation drops the rotation and the old key remains in use until the next sweep — fail-closed.
A passport is a signed record carrying a peer's identity (Guide ID, ML-DSA-65 public key fingerprint), network coordinates (IP, UDP port), Sacred Anchor Index assignment, an availability score (locally measured from probe-ack loss and observed uptime — a soft ranking preference that never excludes a peer), and capability flags. Each passport is signed once and cached locally with a 24-hour freshness window. At billion-user scale the live mesh is statistically empty for any specific peer or fragment lookup; the passport cache is the actual substrate for discovery, and the live mesh is the launchpad for the cache-miss path.
Per-peer token-bucket egress limiters cap send rates on bursty channels — gossip 120 capacity / 20 refill per second, fragment 60/10, query 240/60. Below the limiter, a transport-layer fair-queue scheduler enforces per-peer round-robin (1 ms tick, 64 packets per tick, 256-entry per-peer queue). Seen-cache dedup prevents gossip cascade loops with a 5-minute TTL. UDP socket spoof-cap absorbs spoofed-source floods up to 100,000 simultaneous source addresses.
UDP packets are bounded by the network's MTU. HOPE's chunking layer fragments larger payloads into chunks of at most ~1.3 kB; reassembly is bounded by three caps to prevent memory exhaustion: a global session count of at most 2,000 concurrent reassemblies, a per-peer cap of at most 5 concurrent reassemblies from a single source peer, and a global byte cap of 500 MB across all in-flight reassemblies.
A node behind NAT does not know the address the rest of the world sees it at, yet it needs that address to advertise a reachable endpoint. Every conventional answer is a third party — a STUN server, or an HTTP “what is my IP” service — and each hands one external operator a complete log of which node came online, from which address, and when. That is precisely the metadata the rest of this design exists to avoid. PHEUN contacts neither. There is no external STUN endpoint, no IP-echo service, and no fallback to one anywhere in the tree.
Peers already have the answer: a peer had to observe our post-NAT source address in order to receive our packet at all. It reports it back as two extra fields on the ENDPOINT_PROOF packet. That placement is the security control — the proof echoes a nonce encapsulated to the peer's genesis-bound ML-KEM key, and the challenge identifier is single-use, so the reporter is cryptographically established rather than claimed. Carrying it on the plaintext handshake instead would let one attacker satisfy the threshold alone under two invented identities.
A reported address is untrusted input, so two distinct peers must agree before it is adopted; a tie adopts neither, and each reporter gets one vote so re-handshaking cannot stuff the ballot. Without this, a single lying peer could make a node advertise a black hole (nobody can reach it) or a third party's address (a traffic-reflection primitive).
Cold start needs no mesh at all, but the question is asked per address family. The ordinary consumer shape is a global IPv6 beside a CGNAT'd IPv4, so taking the first global address of either family would declare the node publicly reachable and advertise a relay host no IPv4-only peer can reach. Eligibility turns on IPv4 — the family every peer can still use — while a genuinely IPv6-only host qualifies on IPv6.
The same principle covers voice and video. Only a party that receives a packet from the browser's own socket can supply a server-reflexive ICE candidate — that is what a STUN server is, and PHEUN nodes already are that party. Each node answers RFC 5389 Binding requests on its existing HOPE port, so the browser asks its own mesh. Three independent checks (length, a message type with its top two bits clear, and the magic cookie) demultiplex STUN from HOPE unambiguously. When no publicly-addressable peer is known the candidate list is simply empty and a cross-NAT call may fail — the honest outcome, with deliberately no external fallback to make it quietly succeed.
PHEUN is pseudonymous-by-default with onion-protected sensitive channels — not a global anonymity network. The passport system binds Guide ID to IP:port at the pairwise mesh layer by design, because home-holder selection, fragment placement, anchor propagation, and Dual-Witness corroboration all require wire-layer authenticated identity. Triple Sentry hides the content and destination of six sensitive packet classes from all but the first and last hop in a three-hop onion path: direct messages (which also carry store-and-forward delivery), the four call-control types, and WebRTC signalling. Subscription forwards are sent direct — the elected subscription peer must know the subscriber in order to deliver matches back to it, so an onion would hide that identity from the only party needing it. Peer-ban announcement and CALL_MEDIA are reserved slots with no sender. Call media itself never crosses the mesh: once a call is set up, voice and video frames travel browser-to-browser over WebRTC’s own DTLS-SRTP, so what Triple Sentry protects for a call is the signalling — who is calling whom — not the stream.
payload = inner-encrypted to recipient's session key hop3 = AES-256-GCM(K3, payload) // to exit relay hop2 = AES-256-GCM(K2, hop3 ‖ next=relay3) hop1 = AES-256-GCM(K1, hop2 ‖ next=relay2) // to entry relay each Ki = ML-KEM-1024 origin-session key
Each hop's session key is established through the same ML-KEM-1024 bootstrap as a regular session — there are no public-input-derived keys anywhere in the production path. A path-expiry / LRU target cap prevents long-lived correlation. Anchors are public by construction (§23); the onion only protects the sensitive packet classes whose content is not intended for the ledger.
Triple Sentry does not defend against: sender identity from any one of the three relay hops (each relay sees its predecessor and successor by IP:port; mesh is pairwise authenticated); coordinated all-three-relay compromise (multi-source candidate selection from manual seeds, availability-score-ranked relay-capable peers, and Genesis Authority fallback mitigates this but does not eliminate it); a global passive adversary with both endpoint visibility (out of scope).
Direct messages and calls are the one part of PHEUN that is deliberately not an anchor. Everything a citizen publishes becomes a 420-byte record on a permanent public ledger; what they say privately does not, and that exception is load-bearing rather than an omission.
Minting an anchor per message would place an undeletable, publicly visible record of who spoke to whom and when into a ledger with no delete operation. The content would be sealed, but the social graph and its timing would be permanent, public and queryable by anyone, forever — worse than anything payload encryption offsets. So a DM is peer-to-peer traffic held in each participant's own local store, and a call is signalling plus a browser-to-browser media path. Neither touches the AnchorStream: 0xA9 ('Direct Message') is a reserved TYPE byte with no server-side usage, and there is no anchor mint anywhere in the messaging path.
The consequence cuts both ways and is worth stating plainly: private conversation is not backed up by the network. An anchor survives because thousands of strangers replicate the bucket it landed in. A DM survives because the two people in it kept it. Store-and-forward holds a message for an offline peer, but that is delivery, not durability.
A call adds one layer. Call signalling — invitation, acceptance, SDP and ICE exchange — travels as onion-wrapped HOPE packets, so no third-party signalling server learns who is calling whom, and the reflexive address each browser needs is answered by PHEUN peers acting as STUN responders rather than by Google or Twilio. Call media then flows browser-to-browser and never enters the mesh at all, which is why CALL_MEDIA is a reserved slot with no handler.
Triple Sentry protects a conversation once it exists. A separate mechanism decides whether it exists at all, and it answers a problem the onion cannot: a Guide ID appears in every anchor its owner writes, which is correct for authorship and wrong as a contact address. Without a gate, anyone who reads a post can ring that node forever, with only a reactive ban list in response.
Two fields, two jobs. The Guide ID is the citizen's permanent name — public, unchanging, what authorship is proved against. The contact code is their number: a 64-bit secret shown as 13 Crockford base32 characters, handed out and replaceable at will. Separating them lets the name stay permanent while reachability stays revocable.
What crosses the wire is a proof, never the code: BLAKE3(DOMAIN ‖ code ‖ senderGuide ‖ recipientGuide ‖ epoch). Binding sender, recipient and epoch means a captured proof is neither replayable by an observer nor usable against a third party. A short PIN is not an option — six digits is ~220, which a distributed guesser walks.
The gate runs before ICE, and that placement IS the control. WebRTC hands the local public address to whoever it negotiates with, so a check performed when the call rings has already leaked the thing it was protecting.
The proof is re-checked on every inbound — there is no accepted-contact short-circuit. This is the central trade and it is deliberate: with a one-time promotion, rotating the code was a no-op for anyone who had already used it, so a citizen who published a code and was then spammed had no remedy but removing peers by hand. Re-checking means a rotation cuts off everyone holding the old code, friends included — which is exactly what makes rotation a remedy rather than a gesture. The people a citizen keeps are restored through one channel only: their next message to that person carries the new code inside the ML-KEM envelope, and the recipient's node updates its record after sender authentication. There is deliberately no bulk push — a citizen with a thousand unwanted threads would hand the new code straight back to every one of them, so the broadcast would be the leak.
Guessing is bounded per-sender and node-wide, because a per-sender cap alone gives an attacker with N throwaway Guide IDs N fresh allowances. A correct proof is verified first and never consults a budget: with no short-circuit above it, budget-first would let a stranger spray wrong codes until the node-wide allowance was spent and every real conversation stopped.
What the code buys is revocability, not secrecy. Publishing it is a supported choice — put it in an anchor or on a PHEUN Site to be openly reachable — but a code in a payload is network-readable forever, because payload keys derive from the public anchor. Private by default, public by choice, reversible either way.
PHEUN admits each anchor at the moment it is born, and it does so without a jury, an attester, or a witness. The mechanism is Self-Verifying Anchor Propagation (SVAP): the anchor carries, on every propagation, everything a receiver needs to prove it is genuine, and every receiver re-runs that proof independently. There is no trusted third party whose verdict must be believed. The propagation is the verification.
A committee model authenticates the committee, not the anchor — and at billion-user scale a receiver almost never holds a given juror's public key, so it could not verify such a signature. The author's proof has no such weakness: the author's public-key fingerprint (PROOF) is inside the 420-byte anchor, and the full public key and signature travel with it, so any node anywhere can verify the author directly.
The self-verifying payload is ANCHOR_FULL (~6.5 KB, fixed binary layout): the new anchor, its genesis (the identity root), its previous (the chain link), the author's full ML-DSA-65 public key (1,952 B), and the author's full signature (3,309 B). A genesis carries only the new anchor; a second anchor's previous is its genesis.
Offline math over the carried bytes (cheap, rejects garbage before any query): BLAKE3(pubkey)==PROOF, BLAKE3(sig)==SEAL, the ML-DSA-65 signature verifies over CORE; new, genesis and previous all share one PROOF (one keypair); new.PAC==prev.CORE and new.PAC_COUNT==prev.PAC_COUNT+1; dispatcher-SAI recomputed; TIME within the 5-minute sanity window. This proves a valid signed chain under one keypair — but not that the keypair owns the Guide ID.
Mesh corroboration closes that gap and is the load-bearing check: the carried genesis must match, byte-for-byte, the canonical genesis the network holds at SAI(GUIDE) (earliest-TIME on a fork, first-claim-wins). The Guide ID is a chosen input, not derived from the public key, so an impostor can self-sign an anchor stamped with a victim's Guide ID under their own keypair — the signature verifies, but the carried genesis has a different CORE than the canonical one and the anchor is rejected with GENESIS_MISMATCH. The signature proves this keypair signed this anchor; the genesis corroboration proves this keypair owns this Guide ID. Both are required, both re-run by every receiver.
The author announces with ANCHOR_HAVE (34 B: CORE + home SAI) to the peers covering the anchor's home SAI; one that lacks it replies ANCHOR_WANT (32 B); the holder answers ANCHOR_FULL. A verifying home holder forwards the HAVE onward, deduplicated by CORE, so propagation stays inside that bucket's ~5 holders and never loops. A holder that verifies and stores the anchor returns ANCHOR_STORED to the author, which ships the payload fragments only after two distinct home holders receipt — so a published anchor is always addressable.
Against forgery, SVAP is not probabilistic: there is no committee to corrupt. A forged anchor (bad signature) or an impostor anchor (valid signature under a foreign keypair, wrong canonical genesis) dies at the first honest hop and every hop after. The private key never leaves its owner's device, so collecting others' ANCHOR_FULL packets yields nothing forgeable. The one thing SVAP does not prevent is a same-key cross-device self-fork — two anchors at the same PAC_COUNT from one citizen's two devices — which is caught at the next login by the AnchorChain walk. Bandwidth per node scales with the anchors landing in a node's one Sacred Anchor Index, not with total network throughput.
An ANCHOR_HAVE is a single unacknowledged UDP datagram, and the loss that matters is not an independent per-packet failure rate but a correlated stall: a receiver that pauses for a few hundred milliseconds — a garbage-collection cycle, a full socket buffer — drops the entire cascade burst at once, so the redundancy of announcing to several holders dies with it. And because every receiver refuses an anchor whose TIME falls outside the ±5-minute sanity window, the live path will never carry that anchor again. A missed announce is permanent unless something re-offers it: propagation over an unreliable datagram transport cannot, by itself, guarantee that every holder receives every anchor.
The repair belongs where the loss happened — inside a bounded live window of 60 seconds — and rests on three mechanisms. First, the ANCHOR_FULL cache is the live window, and it is the only structure on a node that can serve an ANCHOR_FULL at all: it cannot be rebuilt from storage, because the persisted 420-byte anchor carries BLAKE3(pubkey) as PROOF and BLAKE3(sig) as SEAL but never the 1,952-byte public key or the 3,309-byte signature themselves, which travel in the payload. A holder that has evicted the cached frame can no longer answer a WANT for that anchor under any circumstances, so the cache is sized in anchors from the per-bucket arrival rate — a community node holds one Sacred Anchor Index, and at a billion citizens a single bucket takes on the order of twenty anchors per second, so sixty seconds is roughly 1,200 frames. Second, the author re-announces to home holders that have not yet returned an ANCHOR_STORED receipt, on a backoff landing inside the store-receipt deadline — a retry issued after the stall is the only one that can arrive. Third, co-holders top each other up: each node periodically re-announces its whole live window to the peers holding the same bucket, which reply ANCHOR_WANT for anything they lack. This reuses HAVE/WANT/FULL exactly — no new packet type, and therefore no change to the network's wire identity — and is paced beneath the receiver's inbound-HAVE meter so a top-up is never mistaken for a flood. One constraint is load-bearing: the rotation must re-offer the window to every co-holder within a single cache lifetime, because a rotation slower than the cache is worse than none — the anchor ages out of the only structure that could have served it before that peer's turn ever comes.
Together these make propagation reliable enough that a LIVE bucket is never re-swept on a timer. A dropped announce is repaired inside the live window that dropped it, not by periodically re-reconciling settled history — which would collapse the catch-up layer and the live layer into one and dissolve the distinction the two-layer model rests on.
SVAP verifies each anchor at birth. Dual-Witness Sync (DWS) is the replication-time integrity check and convergence engine that runs when one node copies a Sacred Anchor Index bucket from another. It is implemented as windowed Merkle anti-entropy — the technique that reconciles arbitrarily large datasets at a cost proportional to their difference, not their size. SVAP is birth-time verification; DWS is integrity-and-convergence during replication. This is set reconciliation over an unordered bucket — the same role a Merkle tree plays in a distributed database — and is explicitly not a blockchain: no blocks, no linear chain, no global order, no mining.
Every anchor falls into a fixed one-minute TIME window. Each window has a BLAKE3 digest over the canonically-ordered (TIME, then full-anchor bytes) list of the full 420-byte anchors it holds — not their CORE hashes alone, since CORE addresses only the payload and would leave the record's other 388 bytes uncommitted; this leaf-commitment rule is bound into the network fingerprint. Windows fold up a fixed 16-ary tree to a single root. The tree is insertion-stable — a late-arriving old anchor dirties only its own leaf plus its ancestor path — and empty spans collapse to a per-level constant, so building it costs work proportional to the number of populated windows, never to wall-clock time. Settled-window digests are computed once and cached forever.
A whole-bucket root is useless to compare — the live edge (anchors from the last few minutes) always differs. DWS splits the bucket at now − LIVE_ZONE_MS, sized as the maximum-propagation margin (~10 min at V1): any window older than it has had time to spread the whole mesh, so a settled-root match provably means “I hold everything that has had time to propagate.” The frozen settled zone is the basis for comparison; the live zone is the moving edge, received through SVAP propagation once LIVE and excluded from the comparison. Two synced nodes match the settled root in a single exchange — O(tree-depth) regardless of whether the bucket holds a hundred anchors or a hundred billion. On mismatch the node drills the tree, asking a peer for a node's child digests over the same requester-supplied window-count (so clock skew never causes a false mismatch), and recurses only into divergent children until it has localised the exact divergent windows — then pulls only those.
Because the live zone is defined by age, not by count, going LIVE is a binary predicate on the settled root — “do I hold every window older than the margin?” — never a percentage of the whole bucket. A fraction-of-all-anchors threshold would be a perpetually moving target: anchors are minted continuously, so the denominator never settles and a node in a busy mesh could approach but never reach it. Anchoring the gate to the frozen settled zone gives a fixed, provable finish line that a node always reaches. A node may thus go LIVE and start serving while the last few minutes of the live edge are still arriving — being settled-complete, not caught up to the instant, is the correct and sufficient bar.
A divergent window is corroborated only among the peers that actually hold it; an empty or behind peer casts no vote and never vetoes a real holder. The requiredHolders threshold is pinned to identity, never derived from timing: every node requires two agreeing holders, with exactly one exception — roster index-1 (bootstrapnode001), the designated cold-start bridge, may use one while it still sees fewer than two other holders. Index-0 (nateofearth2100z) solos the genesis; index-2 onward and every community node always require two. A divergent window is ingested only when at least that many holders agree. So if a non-bridge node can reach only one holder it does not pull and does not go LIVE — it stays SYNCING and retries when a second holder appears. It never single-trusts. The single-witness path is the one identity-pinned cold-start exception: the index-1 bridge replicates the solo'd genesis's already-validated history and becomes the second holder, so everyone after it has two to corroborate against. That is why the protocol is named Dual-Witness — two is the rule for all but one bridge identity, never a routine mode granted by timing. With two or more agreeing holders, a fabricated anchor held by a single malicious peer is contested by the honest holder and is never corroborated, ingested, or propagated. Live and historical anchors travel two separate paths: a LIVE node receives every new anchor through SVAP propagation (self-verified at receive, direct insert, no DWS — this is how two LIVE nodes stay byte-aligned), while DWS replicates only missed history; a SYNCING bucket does not receive propagation, so a multi-day backfill is never polluted by live tip-inserts. A node goes LIVE only once it is missing no corroborated settled content, and the live edge is corroborated byte-for-byte (a tampered variant under an honest CORE is a distinct key, never corroborated). The transition is a smooth handoff: reconcile the settled history, go LIVE, then a bounded post-LIVE convergence window (one live-zone) additively re-reconciles to catch any anchor minted in the handoff gap before releasing to pure cascade delivery. A live-zone anchor that a syncing node defers (only one witness) or misses is never lost: the live zone slides, so as the clock advances the anchor crosses the margin into a settled window and the ordinary settled-root compare covers it. The moving edge is thus self-healing through three overlapping mechanisms — cascade delivery, byte-for-byte pull corroboration, and aging into the settled zone as the final backstop — so nothing on it is accepted from a single source (outside the index-1 bridge) and nothing can be permanently stranded.
Cold start. The very first node has no peer to reconcile against, so declaring a bucket LIVE from local state alone (solo) is the last-resort origin primitive — never a default, and restricted to roster index-0. The cold-start ladder is pinned to identity: index-0 (nateofearth2100z) solos the genesis; index-1 (bootstrapnode001) is the single-trust bridge that pulls index-0's already-validated history and becomes the second holder; index-2 onward and every community node require two agreeing holders and wait rather than pulling from one. Solo fires only after a short grace with no peer appearing, and a simultaneous fleet boot cannot deadlock because index-0 is the deterministic origin. A community node never solos: a GA covers every bucket, so a peer always exists once the network is up, and going LIVE unsynced would make it an authoritative source for a bucket it never reconciled — instead it stays SYNCING and waits. So the first node solos, index-1 single-trust-syncs from it, and everyone after dual-witness-syncs — never “all solo,” and no start-stagger is needed because a fresh network has no settled zone to wait on. Catch-up is event-driven: a node re-reconciles its buckets when peers (re)connect, so an offline node catches up on rejoin, not on a clock. Synchronisation is never time-bounded — a cold node may take days to load years of history.
LIVE is a claim with two halves: that a bucket is byte-for-byte identical to its co-holders, and that it is receiving every new anchor by propagation. A node that has lost every co-holder for a bucket is no longer doing the second — no peer can deliver propagation to it, and the live-window top-up (§11.5) has nobody to pull from. Whether it still holds thousands of other connections is irrelevant: for that bucket, it is offline.
The response depends entirely on duration, and the boundary is the live window. A blackout shorter than the window needs nothing — the top-up re-offers every missed anchor the moment a co-holder is reachable again, so a brief disconnect must not flap the bucket in and out of service. A blackout longer than the window is different in kind: those anchors have aged out of every holder's ANCHOR_FULL cache and can never arrive on the live path again, so the bucket is genuinely incomplete and the LIVE claim is false. It is demoted LIVE → SYNCING, and Dual-Witness Sync — the catch-up layer — restores it, promoting it back to LIVE on a settled-root match.
The demotion is what prevents one node's gap from becoming the whole network's. A node that keeps advertising LIVE coverage while missing anchors continues to be elected as a DWS witness, a synchronisation source, a home holder and a storage-receipt issuer for a bucket whose recent history it does not have; a cold-starting node that samples it as a witness then finds its settled digest disagreeing with the honest holders, and the window comes back contested — so one isolated node degrades the synchronisation of every newcomer that happens to pick it. Clearing the coverage bit on demotion removes it from every such election until it has caught up. It follows that total peer count is the wrong signal for liveness: a node holds one Sacred Anchor Index out of ten thousand, so the handful of peers sharing its bucket are a vanishing fraction of its 66,666 connections — it can lose every one of them while its overall peer count barely moves. Coverage of the held bucket, not the size of the peer set, is what LIVE asserts.
DWS validates bytes only against corroborating witnesses, not against external truth; if all witnesses collude on identical corrupted bytes the check passes — tolerated because forgery is already closed at birth by SVAP. It does not auto-delete an attacker's locally-injected anchor (anchors are immutable) — the fake simply stays inert and unpropagated on the attacker's own node. The digest tree is pure local derived state: never shipped as authoritative data, contributing nothing to the network fingerprint, with a rebuildable crash-safe-validated on-disk cache.
Payloads up to 10 GB are AES-256-GCM authenticated-encrypted, split into sacred-math-sized fragments, and distributed across the mesh via a Kademlia-style XOR-DHT keyed by the anchor's CORE. Anchors are SAI-routed; fragments are content-addressed via the anchor-scoped K_NEIGHBORHOOD, not SAI-bucketed.
coreRoutingKey = CORE_bytes(32) // already uniform via BLAKE3 peerKey(g) = BLAKE3(g.guideId) distance(a,b) = uint256(a XOR b) K_NEIGHBORHOOD = FLOOR × totalFragments closest peers to coreRoutingKey, author EXCLUDED rankFragmentIndex = sort eligible peers by distance(peerKey, coreRoutingKey); // rank r peer at rank r holds index (r mod totalFragments) // coverage-complete
Every fragment of one anchor lives in the same XOR neighborhood. Placement is by XOR rank, not an independent per-peer hash: the eligible peers (author excluded — the author retrieves through the mesh and never stores its own fragments) are sorted by XOR distance to the routing key, and the peer at rank r holds index r mod totalFragments. This is coverage-complete — whenever ≥ totalFragments non-author peers exist, the closest take indices 0…F−1 one each, so no index is ever orphaned, and each index gets FLOOR redundant holders. An independent per-peer hash could not guarantee this — it could assign every available peer the same index and leave another with zero holders (a two-fragment-genesis data-loss case) — which is why placement is by rank, not by hash. With FLOOR=20 and a 1000-fragment film, K_NEIGHBORHOOD = 20,000 peers, mean 20 holders per index; per-peer storage stays at one fragment regardless of file size (FLOOR is a launch knob: 1 on the smoke testnet, 10 at launch, 20 at the mature target). The receiver does not re-derive the rank on a FRAGMENT_STORE (the author-excluded rank is not locally recomputable) — it range-checks the index only; integrity is closed by the (CORE,N) primary key plus the AES-GCM tag at reconstruction.
Distributed QUERY_FORWARD — the reader does not connect to the holders to find them. At a billion nodes the holders of an arbitrary CORE are almost never in the reader's own mesh, and dialing the thousands a cold lookup touches would cost megabytes of post-quantum handshakes merely to ask — fatal for a 1 KB post. Instead the reader originates a ~170-byte (CORE, neededIndexes, ttl, originGuideId) query and hands it to its closest-to-CORE neighbours over tunnels that already exist; the mesh forwards it the rest of the way, each node doing O(1) work, so the cost is distributed across the mesh rather than piled on the fetcher. The candidate substrate each hop forwards toward is the live K-bucket (66 k peers) ∪ the passport cache (1 M peers); the routing table's k-buckets live in raw-Guide-ID space — uncorrelated with the BLAKE3 CORE space fragments are keyed in — so the cache is the de-facto CORE-space knowledge, and every node maintains a PeerXorIndex over it (a leaf-compressed binary trie over peer BLAKE3 keys) that returns the k peers nearest any CORE in O(k+depth) ≈ microseconds, not an O(N) scan. Each receiving node does four O(1) things: dedup by requestId against a 30-second seen-cache (the same mechanism as the gossip cascade, so a query never loops); record the predecessor so a reply can be routed back along the reverse path; bloom-check which needed indexes it actually holds (keyed by fragmentLookupKey) and, if any, reply toward the origin with its Guide ID, the indexes it really holds, and its reach — IP:port, plus a relay Guide ID when NAT'd — so the reader can pull direct; and forward the still-needed indexes onward, ttl permitting (the ceiling is 32 hops). Discovery never trusts a predicted assignment — a node answers only for fragments it really holds, bloom-confirmed, since the author-excluded rank is not remotely recomputable. The fan-out is adaptive: NARROW (three closest) while still routing toward the CORE, and wide once a node is itself inside the anchor's K-neighborhood — detected in O(1) via the sibling CoreBloom (one entry per anchor it holds any fragment of) — so the query spreads across all F holders, who are XOR-close to one another, covering every index. That width is sized to what is left to find, clamp(stillNeeded, NARROW, WIDE) with a ceiling of 64, so a nearly-finished search stops recruiting sixty-four peers to locate three fragments; measured on a 26-fragment payload that cut contacts 34,131 → 12,515 at unchanged hops and delivery. Because the recursion re-fans at every in-neighborhood node, a ceiling of 64 suffices where the retired single-fetcher walk needed an additive per-hop ceiling many times larger. Holders in a wave reply in parallel, so wall-clock latency tracks the hop count, not the nodes touched. The at-scale measurement is npm run bench:sweep, which executes the real qfOriginate/qfOnQuery/qfOnReply in rank space — a node is only its global XOR-distance rank to the CORE, so the network size is exact at a billion instead of scaled down, which matters because in a mesh of a few tens of thousands the FLOOR×F holders of a large payload are several percent of the whole network and coverage looks perfect for reasons that vanish at real scale. Nearest-first alone is not enough, and the reason is the whole shape of the problem. A node's nearest-to-an-arbitrary-CORE sits near global rank N ÷ 1,066,560 — about 938 at a billion nodes, but about nine at ten million — so every participant in a ripple offers very nearly the same low ranks, the search converges on the innermost sliver of a FLOOR×F holder band, and the seen-cache turns the repeats into no-ops until the frontier dies. A band is 25,600 ranks wide for a 10 GB film and rank r holds index r mod F, so reaching only the inner few hundred ranks yields only a few hundred distinct indexes. Measured on the shipped engine with no complete copy anywhere, such a payload reached 33% and did not open at ten million nodes while a post, a song and a 100 MB clip all reached 100%; more search budget did not help, because the ripple had saturated rather than been cut off. So a node that is already inside the neighbourhood forwards additionally to peers beyond its own XOR distance, and the wavefront sweeps the whole band instead of collapsing into its centre. The sweep is additive rather than a share of the fan — taking it out of the fan halves the in-neighbourhood breadth a replica census depends on — and the covering half carries no floor at all, because a band narrower than one node's reach is swept by that half alone and a pure outward sweep would step straight past its holders. With that, the shipped engine locates every payload from a 1 KB post to the 10 GB maximum 100% of the time in a single round, at ten million, a hundred million and a billion nodes alike, from canonical placement alone — no vaulter, no cache, no source list: about 4,400 nodes asked for the film at ten million and 83,878 at a billion. Replication depth is therefore a durability property rather than a discovery one — at one copy per index a single holder leaving orphans that index permanently — while a short read remains a failure and never a partial result, because the manifest and ML-DSA signature are split across fragments and one absent index makes the stream unparseable. A short read is a failure, not a partial result — which is why the origin's deadline scales with the number of indexes sought rather than being a flat timeout, and why a short search is retried rather than accepted. The bloom self-check is O(1) via a phi-progressive RAM filter keyed by fragmentLookupKey (16 → 178 MB tiers); the sibling CoreBloom (2 → 24 MB) backs the WIDE-fan-out trigger.
Discovery and download are not separate connection phases: a reply hands back each holder's reach, so the reader pulls direct. It registers a UDP binding from the reach — a public holder answers directly, a NAT'd holder is reached through the relay Guide ID its passport carries — and sends one FRAG_PULL with an empty index list, meaning "send whatever you hold for this CORE". Under the one-fragment-per-peer law the holder normally returns exactly one fragment, so discovery and download collapse into one round-trip per holder; equal-stripe load distribution is emergent (with a deep swarm every holder serves a single fragment — the BitTorrent property), not a planner. The reader dedups returned indexes against what it still needs and stops once covered; any index momentarily unfound is returned partial and healed by census and the next reader's re-fetch. The auth tag rejects tampered bytes at decipher.final(); reconstruction abandons before any plaintext leaks.
Census: holder-driven probing of K=20 XOR-closest peers per fragment on phi-progressive backoff (1 h → φh → φ²h → … → 1 wk STABLE → 30 d COLD). When count drops below the replication trigger (FLOOR=20, healing trigger ≈10 active replicas), the holder phi-burst-replicates back to FLOOR × φ ≈ 32 copies. Active-fetch fragments (fetchCount7d ≥ 10) skip census entirely — the swarm keeps replicas alive without intervention.
Every payload fragment is sealed with AES-256-GCM. Wire format on disk and across the mesh is base64( IV(12B) ‖ TAG(16B) ‖ ciphertext ). Key plus base IV are derived once per anchor via BLAKE3(CORE ‖ SEAL ‖ PAC); each fragment's 96-bit nonce is BLAKE3(baseIV ‖ fragmentIndex)[:12]. Decryption is fail-closed.
Durability is the placement FLOOR plus whoever chooses to keep it. Three tiers hold fragment copies and contribute differently. xor_storage is the canonical network-duty tier — the FLOOR closest-rank holders per index, healed back to FLOOR forever by census; the guaranteed floor, present regardless of demand. It is the durability/immortality guarantee — every anchor, cold or hot, survives on its FLOOR. vault is permanent citizen pins: a vaulter snapshots all fragments locally, adding one permanent copy to every index. viewer_cache is the serving tier — LRU-evictable copies a reader keeps after reconstruction; transient, raising serving capacity, not durability. Viewing never creates a permanent copy: xor_storage is populated only by placement and census, never by what a citizen reads.
Permanent per-index redundancy is therefore R = FLOOR + vaulters. Payload recoverability under per-holder availability a is P = (1 − (1−a)^R)^F, where the fragment count F is a coupon-collector exponent: every one of the F indices must keep a live holder, since every fragment is needed to reconstruct — which is why file size governs durability and not only discovery. Modelled over the tiers, a 1 GB file (F=363) at FLOOR=10 recovers ~100% / 70% / 0% at 80% / 50% / 20% holder availability; a 10 GB film (F=2,560) recovers ~100% / 8% / 0%. The bare floor is ample for a healthy mesh (availability ≥ 80% recovers everything) but the coupon-collector tax makes a multi-thousand-fragment film genuinely fragile under heavy churn. Two knobs close that gap: for content people care about, vault is the lever (5 vaulters lift the 10 GB film from 8% to about 92% at 50% availability, 20 past 99%, 100 to durable even at 20%); for huge cold archives nobody pins, the lever is the FLOOR profile itself (PRODUCTION_20 / _32). Cold content nobody pins or watches sits at exactly the FLOOR — census keeps it there, which is the point: the vast majority of anchors (a vote, a one-shot post) are never re-fetched after going live, and their immortality rests entirely on the census-healed FLOOR. The serving tier scales inversely: a viral payload with V recent viewers spreads the pull across up to V transient cache holders, so popularity speeds the fetch (per-holder load → F/V). Popularity buys speed through viewer_cache; durability comes from the FLOOR plus voluntary vaulting.
The three tiers above are only as useful as they are reachable, and two of them are not. Fragments are placed by XOR distance, so the canonical holders sit beside an anchor's CORE and every search arrives at them. A citizen who vaulted a payload — or who merely watched it and still holds it cached — sits at BLAKE3(their own Guide ID), a position with no relationship to that CORE. They can serve every index and they answer the bloom, but no hop of a CORE-directed search ever routes to them. Measured over a modelled mesh: zero of fifty vaulters and zero of five hundred cached copies reached, at every network size. The R = FLOOR + vaulters term above was, in practice, worth nothing.
The fix is a pointer, placed where searches already go. Each node keeps a small source list for the COREs nearest it in the keyspace, and any query passing through collects it on the way. One hit returns a source holding every index, so the cost of finding a large file stops growing with the number of fragments it was split into — and because every completed download registers the reader as a new source, popular content becomes easier to find as it spreads rather than concentrating on whoever seeded it. The list is bounded by memory rather than by a clock: a fresher source is offered first, and an entry is removed only when a fetch proves it gone, because a vault copy is neither permanent nor perishable on a schedule.
A complete copy is the best thing to find and the worst thing to drain. One hit on it answers every index at once, which is precisely what makes discovery independent of fragment count. But rank it first for bytes and every reader pulls the whole payload from that one node: a ten-gigabyte film served to a thousand citizens is ten terabytes out of a single uplink — worse than the problem the source list was built to solve. A canonical holder is the opposite: it carries one fragment by XOR rank, exactly the load the placement law sized for, and there are FLOOR × F of them.
So the reader schedules the fetch: canonical holders carry the bulk, complete copies fill only the gap routing could not reach, and several complete copies split that gap between them. More complete copies therefore mean less work each rather than a bigger target. Within a request the scarcest indexes go first, so a fragment only one node can serve is taken while that node is in hand, and each request takes roughly its fair share of what remains — without that, the first complete copy reached would claim everything. The ceiling on a single request is denominated in bytes, not rows, because fragment size grows with payload: a fixed row cap bounds two megabytes of a post and a gigabyte of a film. It shapes each request without ever refusing delivery, since a source is simply asked again for the rest — a payload missing one index does not open at all.
The decision is made when each request is sent, not once at the start. An assignment written before the first fragment lands is stale immediately: sources hand back more than they were asked for, and every early arrival makes some later source's share redundant, so a frozen plan re-requests fragments already in hand and pays for them twice.
Searching and downloading run together. The reader does not wait for the search to finish before pulling: holders stream back as replies arrive, the schedule absorbs them mid-fetch, and the download keeps spreading across nodes as more are found. Phasing the two would cost the entire search window on an idle link, because nothing about the first holder found requires the last one to be known.
The Personal Anchor Chain (PAC) is the only chain in PHEUN that is cryptographically walked. It is per-Guide-ID, append-only, pinned by a 32-byte pointer (PAC, bytes 125–156) and a 4-byte monotonic counter (PAC_COUNT, bytes 157–160) in every anchor.
anchor_n.PAC = BLAKE3(anchor_{n-1}.bytes)
anchor_n.PAC_COUNT = anchor_{n-1}.PAC_COUNT + 1
fork detected ⟺ ∃ a, b : a.GUIDE = b.GUIDE
∧ a.PAC_COUNT = b.PAC_COUNT
∧ a.CORE ≠ b.CORE
The chain is walkable, bounded by a hard cap of approximately 50 years × 144 anchors per day = 2,628,000 anchors per Guide ID — large enough for a lifetime, small enough for tractable login walks.
pacWalker.walk(guideId) before the session is issued. The walker pulls every anchor under the citizen's Guide ID via the global query engine, filtered by guide + pacCount range. A fork detected mid-walk writes a pac_locks row, refuses the login with HTTP 423, and surfaces the locked-Guide-ID modal.SUBSCRIPTION_FORWARD within 1–120 s; cross-device forks are detected the moment the conflicting anchor arrives. The currently-authenticated session is killed at the next request via the request-time PAC lock check.pacState.ingest with mintedLocally=true before the gossip cascade, so the dropdown indicator distinguishes "you posted" from "another device posted".Every node walking the same chain arrives at the same fork verdict independently. There is no broadcast, no admin override, no recovery path. Locked Guide IDs are dead by design. The citizen creates a new Guide ID; the sealed history remains readable but inert. The device-binding lock file (data/guide-id.lock) is cleared by the human physically present at the device — there is intentionally no network endpoint to release it remotely.
Democracy is the only governance machinery in PHEUN. Both governed documents — the Constitution and the Curriculum — use the same proposal/vote/consensus pipeline (cat 0x04, types 0x60 Proposal / 0x61 Vote Yes / 0x62 Vote No, FLAGS 0x00 regular / 0x01 consensus / 0x02 tally), scoped by SIGN.
SIGN is one byte holding an id from a registry compiled into every node: 0x00 no document, 0x01 Constitution, 0x02 Curriculum, 0x03–0xFF unallocated. There is no user-typed document name anywhere in the system, so there is no uniqueness race and nothing to squat — every node resolves 0x01 to the same document at compile time.
This is a deliberate narrowing. A free-form name could not deliver the property a governed document actually needs: that every citizen is reading, amending and voting on the same one. Two citizens who wrote constitution and Constitution opened two documents; two who raced the same name from opposite sides of the mesh opened two that both looked canonical, and — anchors being permanent — both persisted. The name also became the prize, accruing to whoever minted first.
A document's first anchor can be minted only from that document's own page, the sole surface that knows which document it is, and the mint refuses any non-governance anchor carrying a non-zero SIGN. Adding a document costs a registry row, a page and a nav slot — an additive, soft-fork-class change, since the registry is not a network-fingerprint input and an older node simply renders an unrecognised id as no document while still verifying and storing the anchor. The cost is deliberation, not machinery: a new institution should be a code change someone argues for, not a form submission.
A document is opened once, and the check fails closed on both sides. One query at SAI(SIGN) returns every opener for a document, and that query has three outcomes rather than two: an opener exists; no opener exists and holders answered; or nobody answered. Silence is not absence — treating an unanswered query as "unopened" is what mints a second opener for a document that already exists. So the read reports whether its answer was proven, and both callers refuse an unproven one: the mint returns GENESIS_EXISTS when it can prove an opener exists and GENESIS_UNVERIFIABLE when it cannot prove one is absent, and the page offers "open this document" only on a proven absence — and stops offering it the moment this citizen's own opener is signed, because an anchor is not queryable until its home holders admit it, and that gap is exactly when a duplicate gets minted.
Propagation deliberately does not enforce this. Rejecting a duplicate opener at the wire layer would be arrival-order dependent — a holder that had seen the sibling would refuse while one that had not would accept — so two honest nodes would disagree permanently about a bucket's contents. Uniqueness that diverges the mesh is worse than none. The reader is decisive instead: partitioned nodes can each mint an opener and both anchors persist forever, so every node picks the canonical one by the same pure rule — earliest TIME, CORE ascending to break a tie. The tiebreak matters because TIME is milliseconds and real ties happen; without it the winner would be whatever order a query merged results in. With it, every node renders the same document and the loser is inert.
LINE=0.LINE = max(existing LINE) + 1, LINE_VERSION=1.LINE_VERSION = max version for LINE + 1.0x01) on a (LINE, LINE_VERSION) pair makes that version the canonical line content.Approval requires 75 % YES of total ballots (FLAGS=0x00) cast within the voting window (default 7 days). Ballots dispatch to SAI(CORE) — scattered across the 10 k mesh so 100 k+ votes per proposal load-balance. Any citizen may run the count fanout (two parallel 10 k-SAI count-only queries); the resulting numbers ride into their next vote and are promoted to a tally snapshot (FLAGS=0x02) with on-chain ACCORD/DISSENT/RATIO bytes. Finalisation requires an explicit Verify Proposal action; the server enforces window closed, no prior FLAGS=0x01 anchor, SIGN match, and 75 % threshold met. There is no auto-finalisation; two code paths producing a consensus anchor for the same proposal would be a determinism violation.
PHEUN ships without age check, ID upload, phone binding, email confirmation, or any pre-participation gate. The Digital Constitution itself is an anchor; rules of conduct can be added, amended, or rescinded by the citizenry at the 75 % threshold. The protocol enforces nothing technically — enforcement is social, legal, and constitutional, never coded.
There is no algorithmic feed in PHEUN. There is no recommender, no engagement-optimised ranking, no editor, no human moderator, no content team. Discovery is the protocol itself: a citizen subscribes to the Guide IDs, hashtags, document SIGNs, link chains, and stream origins they care about; every future matching anchor flows back into their feed in 1–120 seconds.
#hashtag or an @mention).Instead of registering each subscription with every peer covering every SAI (potentially 10⁵+ registrations per user), SPS elects ONE peer per SAI we need coverage for, sends the bundled filter set via SUBSCRIPTION_FORWARD, and re-elects automatically when the elected peer drops. Two-tier detection: explicit handlePeerDisconnect for sub-second re-election, plus a 30 s safety-net contract verification that catches passport-cache eviction without an explicit disconnect packet.
The bundled filter is a 64 KB Bloom filter with 4 BLAKE3-derived hash functions, giving approximately 210 million entries at less than 0.1 % false-positive rate. The bloom is rebuilt from the contract list on subscription change and shipped to the elected peer in the registration packet. The elected peer evaluates each anchor at its SAI bucket against the bloom; a hit triggers a SUBSCRIPTION_FORWARD back to the subscriber. False positives are rejected at the subscriber's local filter check.
Every search, feed back-fill, research lookup, governance count, profile pull, and lineage query in PHEUN flows through a single unified two-phase per-Sacred-Index fanout.
Phase 1 — Announce and count. The engine sends one QUERY_ANNOUNCE per Sacred Anchor Index, addressed to a peer covering that SAI. Each announce carries the queryId, the SAI, and the filter. The covering peer runs a count-only query against its local SAI bucket using SQL field extractors that map filter fields to indexed Postgres expressions. The peer replies with QUERY_COUNT_REPLY. Per-peer announce timeout: 2 seconds.
Phase 2 — PHI-allocated pull. With per-SAI counts in hand, the engine allocates the pull budget across SAIs by the golden ratio. The budget comes from the read's contract (§17.2). When the matched anchors exceed it, no single peer ships more than floor(budget / phi) — so no peer dominates a contested result. That cap applies only under contention: when everything matched fits inside the budget there is nothing to ration, and capping a peer that happens to hold most of it would discard anchors the query asked for and nobody was competing over.
A pull is continued, not issued once. QUERY_PULL carries an offset, and a peer answers at most a fixed number of anchors per request — a bound on the work one request may ask of one peer, not on what a query can retrieve. The requester resumes from where the previous reply ended until the peer is exhausted. Deadlines scale with the work requested rather than sitting at a flat 8 seconds, because a peer answers in paced pages: for a large read the pacing alone outlasts a timeout sized for a feed, and the pull would die and return a partial while reporting nothing wrong.
A read is one of exactly two things, and conflating them is what let six separate layers each pick their own limit without knowing about the others.
A slice is a page of something larger. Feeds, searches and comment threads are slices, and the cap is a decision about the citizen rather than about correctness — ten thousand anchors is more than anyone reads at once, so coming back capped is the expected outcome and nothing is wrong when one is short. A thread is a slice because replies dispatch to SAI(LINK): a widely-read anchor gathers as many children as the world writes, and "showing 50 of N" is the honest shape of a page.
A complete read is the opposite: the subject is the answer, so a silent partial is not smaller but wrong. A Constitution missing its recent amendments does not look truncated — it looks as though those amendments were never made. Complete reads retrieve everything they can, repair what did not arrive, and are then honest about the rest. None is ever cached short.
A Guide chain proves its completeness rather than asking for it. PAC_COUNT is monotonic from one with no gaps, ever, so the anchors that arrived say for themselves whether any are missing — checked locally, trusting no peer's count, which can be wrong in both directions. Because the proof names the missing positions, the repair re-pulls exactly that span rather than a lifetime again. Anything still absent is reported alongside the chain and shown to the citizen: a document that cannot be read whole is refused, because a governed text rendered short misinforms everyone reading it, but nearly all of a citizen's history beats an error page, and a named gap is one refresh from repair.
Every filter family exists in both forms. Exclusions answer "not this" — Guide IDs, categories, types, tags, languages, maturity ratings, zones, documents, hashtags, Sacred Anchor Indexes. Inclusions answer the question a person actually asks: show me this. The positive half is not a convenience: with subtraction alone, narrowing to one subject means excluding the other 255 tag codes across ten slots per anchor, which is 2,550 conditions to express "show me art" and inverts the shape of the question.
They compose by conjunction, with exclusion as a veto — asking for art while excluding violence drops an anchor carrying both, which is what a person means by that pair. Within a list the semantics are disjunctive, and a separate intersection form requires an anchor to carry all of a named set. That is the difference between browsing and research: a union of three tags widens as the list grows, an intersection narrows, and narrowing is the only way to isolate a small body of work out of a century of anchors.
Even the Sacred Anchor Index this node owns is queried through an outbound announce-and-pull cycle against the peer that covers it. A node with one Sacred Anchor Index cannot trust itself as a query source. Every query is a network operation. Two nodes issuing the same query at the same time, with the same passport-cache view of covering peers, get identical results modulo per-peer flake.
Per-user in-flight cap: 8 queries. Node-global in-flight cap: 512. Per-peer outbound rate is bounded by the query egress limiter (240 capacity / 60 refill per second). Two queries with the same filter hash within a 5-second window share one network round; the second enters as a rider and resolves with the first's result. Coverage report on every result makes partial-mesh queries explicit rather than silently truncating.
A fanout costs seconds of wall time and touches thousands of peers. Issuing one every time a citizen re-sorts a column, navigates back to a page, or relaunches their browser would be indefensible — for the citizen and for the ten thousand peers who answer. So a query's result is held in the node's RAM and re-read from there. This is the read-path expression of Vision principle 25 (the cache is the fanout engine), and it is possible only because of principle 7 (1:1:1:1). In a conventional web architecture the server is shared by strangers, so per-user result sets must be recomputed or paid for out of a shared budget. In PHEUN the server is the user: one operator, one node, one long-running process with gigabytes of free RAM, while the browser in front of it is disposable. A module-level store is not an optimisation here; it is the correct data structure, because there is no other citizen's data to isolate it from.
Five namespaces — feeds, global searches, Guide chains, documents, comment threads — each entry stamped with when its underlying mesh pull actually ran. Nothing in it is durable. A citizen's vault and their notifications are the only state that survives a node restart, because they are the only state that cannot be re-derived; everything here is a snapshot of a mesh query, so losing it costs time, never data, and it re-warms on the next read.
Eviction is three-stage, and the unit is bytes rather than entries. Entry sizes differ by two orders of magnitude across surfaces: a feed or a search is a slice capped at 10,000 anchors (~15 MB), while a Guide chain is a complete read of an entire life and grows for as long as the citizen posts. A few chains would consume the whole node budget and evict every loaded feed on the way, so counting entries can never bound memory. Nothing short is ever stored, so a later reader cannot inherit someone else's failed fanout. Each stage evicts least-recently-used: a per-namespace entry cap, so no surface crowds out another; a per-namespace byte ceiling, so an enormous Guide chain displaces older chains and not the citizen's loaded feeds; and a node-wide byte budget as the hard backstop. The entry just written is never the victim.
Because anchors are immutable (principle 20), a cached result is a strict subset of the truth rather than a contradiction of it — stale, never wrong. That is what makes serving it acceptable at all. It is surfaced rather than concealed: every cached surface shows the age of its underlying pull, and a fresh fanout is always an explicit ask. Documents cache their raw anchors rather than the assembled outline and re-derive the outline against the current clock on every read, so a proposal's voting window opens and closes correctly even while the pull beneath it ages.
A read that queries the mesh requires an authenticated session. Anchors are public by construction (principle 28), so reading one carries no permission; but causing a node to fan out across 10,000 Sacred Anchor Indexes is a bandwidth-amplification vector against the citizen who owns that node, which binds a public interface. Every route that originates a mesh query requires a session. The one sanctioned exception is the Guide ID uniqueness check, which necessarily runs before any Guide ID exists to authenticate with.
Three physically separate tiers, each with a distinct purpose, eviction policy, and read priority.
Cache appears in two unrelated senses in this paper. This section concerns the on-disk payload fragment tiers — encrypted ciphertext chunks of anchors' payloads. §17.6's anchor cache is an in-RAM store of query result sets — 420-byte anchors, not payloads — and is never persisted. The two share no code path, budget, or lifetime.
| Tier | Table | Purpose | Eviction |
|---|---|---|---|
| Tier 1 | vault_collections / vault_members / vault_fragments | Citizen-permanent personal store. 420-byte snapshot + encrypted fragments. Pinned anchors render offline forever. | Never (citizen controls). |
| Tier 2 | anchor_fragments (origin = viewer_cache) | Fragments fetched to view, plus the citizen's own posts once placed on peers; speeds the next view and makes this node a source. | By value — least demand, then least recently used, then oldest. |
| Tier 3 | anchor_fragments (origin = xor_storage) | Network duty — fragments held because this node is closest by XOR rank. Held in trust for others; never the citizen's own material. | Permanent (reject new placements at budget). |
Read priority: vault → any local fragment row → mesh fetch. A fragment already on this disk is used whatever tier filed it, because authenticity is settled by the AES-256-GCM auth tag at decryption, not by a label. Isolation is about ownership, not reading: network-duty bytes are never evicted by the cache sweep, never counted against the cache budget, never surfaced as the citizen's own material, and never released by a personal storage decision — but refusing to read them is not isolation, it is re-downloading what the node is already holding.
Vaulting therefore never re-downloads bytes this node has. Each candidate row must pass the auth tag before it is vaulted — strictly stronger than the origin filter it replaces, since a label says nothing about contents — and once the vault is complete the anchor's now-unreadable cache rows are released, so keeping a 10 GB film costs 10 GB rather than 20.
DESKTOP : RAM ≥ 16 GB, free disk ≥ 200 GB → cache 50 GB, vault 100 GB, xor 1 TB LAPTOP : RAM ≥ 8 GB, free disk ≥ 50 GB → cache 10 GB, vault 20 GB, xor 500 GB MOBILE : RAM ≥ 4 GB, free disk ≥ 10 GB → cache 2 GB, vault 5 GB, xor 100 GB MINI : everything below → cache 500 MB, vault 1 GB, xor 100 GB
Citizens override at any time via Settings → Storage; vault overflow returns HTTP 413 with a pointer to the slider, never silently drops content.
Every node either runs as CLIENT (real IP hidden behind 1–3 relay hosts) or HOST (publicly addressable, accepts slot reservations) — same code, same protocol. Relay slot tokens are unguessable BLAKE3 of host secret + owner Guide ID + counter; rotation triggers on per-slot DDoS detection (1000 PPS over 5 s sliding window) with 30 s cooldown.
Every wire byte is classified at the UDP boundary into one of 12 flow classes (DM, CALL_SETUP, CALL_MEDIA, FRAG_SMALL, FRAG_LARGE, QUERY, GOSSIP, PROPAGATION, SYNC, RELAY_FORWARD, RELAY_OUTBOUND, OVERHEAD) with per-direction and per-peer attribution. Single integer add per packet on the hot path; persisted hourly to data/bandwidth-history.bin as a 90-day rolling window.
The only budget gate is on the RELAY_FORWARD class. Operator monthly cap defaults are device-tier: MINI 100 GB / LAPTOP 500 GB / DESKTOP 1 TB / SERVER 5 TB. At 95 % of the resolved cap, the Host's handleRegister refuses NEW slot mints. Existing slots TTL out naturally over 24 h. No mid-transfer kills, ever. DM, calls, fragments, queries, gossip, propagation, and sync flows are never throttled.
Client-mode nodes whose monthly RELAY_OUTBOUND exceeds 50 GB activate up to 5 relays; over 200 GB, up to 10. Distributes outbound load across more hosts so no single host bears the full burden of one whale client.
PHEUN extends through three orthogonal channels, all additive, none of which touch the network fingerprint. The wire format is byte-frozen for the lifetime of V1; new features ride alongside the old ones rather than replacing them. PHEUN does not implement a hard-fork mechanism, by design.
SAI(CORE) rule for unknown subtypes; new nodes process the subtype with its dedicated rule.The four selector bytes (SEAL_PROTOCOL, PROOF_PROTOCOL, CRYPT, GUARD) are the cryptographic upgrade lane. A future post-quantum signature lands at GUARD = 0x02, with 0x01 continuing to be served forever for V1 anchors. CLIENT_VERSION at bytes 358–359 is a build label — not a digest input — letting readers branch on the minting client's version.
A new feature becomes live when the network's readiness signal crosses a 95 % threshold across two independent sources: the anchor signal (of the last 1024 anchors, the share carrying the new client_version or free_schema) and the handshake signal (of cached + connected peers, the share advertising the feature in their handshake envelope). Both must clear independently. Activation is a pure local decision; every node walking the same anchor stream and the same passport cache arrives at the same activation verdict deterministically.
The three channels plus the algorithm selector bytes plus the CLIENT_VERSION dispatch cover every realistic protocol-evolution scenario without rotating the network fingerprint or invalidating stored anchors. PHEUN is not a blockchain — it has no consensus rule that needs to change, no block size to bump, no transaction format that needs retroactive replacement. The 420-byte anchor is the wire identity; changing it is creating a different network, not upgrading PHEUN. If a community ever ideologically forks, that's a sibling network running its own fingerprint, not a PHEUN-mediated upgrade.
Every anchor on PHEUN can carry a payload, and one specific payload format is the PHEUN Site — a static, immutable, cryptographically-signed, mesh-distributed page primitive that replaces the centralised Web 2 page substrate.
Sites are deliberately constrained. Every site is a single-page scroll. No multi-page navigation; no live data; no in-site media playback (clicking a pheun:// link to a video anchor opens the standard payload viewer); no user-supplied JavaScript or CSS escape hatch. The constraints are not deficits but design choices: a static, immutable site has a known set of bytes, a known signature, a known author, and a known content for the rest of time. Live content would render differently to different viewers depending on when they loaded — defeating the determinism that PHEUN's other layers depend on.
A site is composed from a fixed registry of 31 component types, each a platform-trusted React renderer that takes structured data and draws UI. The author writes the data, not the code. Components fall into eight families: visual headers (Hero, Spotlight, Stat Cards), anchor rendering (Anchor List, Grid, Gallery, Ranked List), text and citation (Text Block, Quote Block, Citation Block, Inline Image, Table), education (Quizzes, Flashcards), identity and social (Bio Card, Subscribe, Contact Card), catalogue (Catalog), governance (Pros and Cons, Position Card), and layout and page furniture (Table of Contents, Timeline, Event Card, Call to Action, Accordion, Button Row, Feature Grid, Divider, Countdown, Marquee, Footer). The renderer is platform code; citizens cannot ship custom JavaScript or CSS, eliminating the user-supplied-script attack surface.
Fifteen templates (Profile, Gallery, Library, Article, Document, Showcase, Directory, Event, Manifesto, Landing, Course, Proposal, Link-in-bio, Contact, Help) and ten themes (Midnight, Ocean, Forest, Solar, Light, Civic, Tape, Terminal, Aurora, Print) ship as starter section sets and CSS variable schemes. A site's payload is a .pheun.zip archive containing a manifest JSON and an assets/ folder of images; the ZIP is fragmented and distributed via PayloadWeave like any other payload.
A site carries no marker byte in the anchor, and needs none. It is not a destination in the way a domain is — it is one way of presenting a payload, alongside markdown in a text block or the fields of an event card. An author who wants readers to know a site is attached says so where every anchor already says what it is: the title, the 32-byte preview, the hashtag, the avatar. Spending an anchor field on "this one is a site" would rank a rendering choice alongside authorship and time, and it would imply one site per citizen — where in fact a citizen keeps as many as they have purposes, each its own payload.
One human approximates one Guide ID, enforced by two compounding floors that emerge from the protocol's own design.
There is no PoW, no stake, no captcha, no phone-number binding, no KYC. The protocol does not punish attackers; the storage curve does. Per-IP passport caps, egress limiters, and SVAP self-verification cover short-horizon coordinated attacks. Persistent peer reputation (24 h default + permanent ban entries, atomic temp+rename writes to data/ban-list.json) survives node restart; cross-node ban gossip via PEER_BAN_ANNOUNCE is reserved for a future coordinated upgrade.
PHEUN has no cryptocurrency, no gas fee, no staking, no paid-node incentive, no premium subscription, no advertising plane, no platform-level currency, no marketplace operator, no payment processor.
Resource sharing happens through the economy anchor category — a citizen posts an economy anchor offering compute, bandwidth, storage, physical goods, or services; the counterparty arranges fulfilment through direct messaging or calling. Pure peer-to-peer barter and exchange, expressed as anchors. The protocol is the medium; humans handle the transaction.
The 420-byte anchor is public and permanent by design — it is the ledger. The payload it points to is AES-256-GCM-sealed with a key derived per anchor; the mesh stores ciphertext fragments. Citizens agree to the Digital Constitution at every post, which forbids illegal content as a matter of social contract. There is no filter, no ban list, no takedown, no content-hash allowlist, no flag, no moderator, no admin, no report button, and no CORE-hash refusal. If illegal content is uploaded, it stays — because no mechanism exists to remove it and none will ever be built. This is the cost of an open permissionless network and PHEUN owns it fully. Enforcement is social and legal, never technical. GDPR-style erasure is satisfied by key destruction (the payload becomes unreadable), never by anchor rewrite.
The AnchorStream itself is the discovery layer (§16). Subscribe to a Guide ID, hashtag, sign, link chain, or origin and every future matching anchor flows into your feed in 1–120 s. Word-of-mouth share of a 16-character Guide ID unlocks discovery of every anchor tied to that identity — past, present, future. No central index, no search-engine dependency, no advertising auction, no boosted post.
A Guide ID is a claimed name, and the handle race is real — what is missing is the market around it. The handle is input 1 of the nine (§3.2), chosen by the citizen and claimed first-come-first-served, with the uniqueness gate at SAI(GUIDE) and earliest-TIME resolution inside the propagation window. A desirable name can be taken before its obvious owner arrives, exactly as in DNS, and the protocol does not pretend otherwise. What it removes is every mechanism that makes squatting profitable or reversible by an authority: no registrar (no fee, no renewal, no expiry, no arbitration, and no entity that can revoke, reassign or seize a name — including us); no resale, structurally, because the handle is one of the nine seed inputs and so selling it would mean surrendering the whole identity and every anchor it has ever signed; and no impersonation, because the keypair matching a genesis PROOF needs all nine inputs, not the public one. Names are first-come and squatting is possible; squatting has no exit, and no authority can undo it either.
Bootstrap nodes are the 21 Genesis Authority Guide IDs (nateofearth2100z, bootstrapnode001..bootstrapnode020). They serve all 10,000 SAIs while community coverage is incomplete. Bootstrap mode is a pure function of Genesis Authority roster membership — a GA serves while it runs, a community node never does. The 5-per-SAI coverage invariant is the goal the operator watches, not a gate on that service.
bootstrap_active(node) = is_genesis_authority(node.guideId)
When the mesh has ≥5 live-or-cached community peers for every SAI, the bootstrap-status endpoint reports coverage satisfied and the operator stops the GA node (npm run node:stop). Bootstrap mode does not auto-toggle — an earlier auto-retire/re-activate design caused mode-flapping, so V1 makes retirement an operator decision. Training wheels, not architecture. Production code must work in a community-only mesh with zero bootstrap nodes.
5 community peers × 10,000 SAIs = 50,000 mesh edges (security floor)
+ 16,666 reserve (multi-coverage / heavy peers / bursts)
= 66,666 per-node connection budget
Bootstrap peer counts are tracked separately per SAI as a redundancy metric, never summed into the invariant decision. Five community peers form the home-holder set for every SAI; V1 chose five over six to spend the freed slots on reserve capacity (16,666 rather than 6,666), leaning on the emergency floor (two peers) plus bootstrap and passport-cache fallback to heal transient dips.
What each subsystem defends against, and what it explicitly does not.
| Subsystem | Defends | Does NOT defend |
|---|---|---|
| ML-DSA-65 signature | Anchor origin authentication; binds Guide ID to Genesis Profile via PROOF. | Signing-key leak, insider Guide-derivation bypass. |
| ML-KEM-1024 session | Pairwise confidentiality + integrity vs. quantum adversary. | Compromised endpoint, stolen device key. |
| AES-256-GCM payload | Bit-flip detection at decipher.final(); reconstruction abandoned before plaintext leaks. | Holder of the derived AES key (any peer with the anchor). |
| Triple Sentry onion | Packet-type unlinkability + traffic-shape resistance for the 6 onion-wrapped packet classes (DM, the 4 call-control types, WebRTC signalling). | Sender identity from any one of 3 relay hops; coordinated all-three-relay compromise; global passive adversary; subscription forwards, which are sent direct; live call media, which never enters the mesh (WebRTC DTLS-SRTP) — only call signalling is wrapped. |
| SVAP self-verifying admission | Forged + impostor anchors die at every honest hop — re-checked by every receiver, not probabilistic. | Same-key cross-device self-fork (caught at login); the author's own signing-key theft. |
| Dual-Witness Sync | Windowed Merkle anti-entropy: a divergent window is ingested only when 2 independent witnesses agree on its digest, so a fake on any single peer is never corroborated and never propagates. | An all-colluding witness set serving identical corrupted bytes (tolerated — forgery is closed at birth by SVAP); cross-session reputation. |
| Network Fingerprint | Forked / mismatched peers dropped at handshake. | Flood-level DoS of handshake attempts. |
| Egress limiter | Bursty / runaway broadcast; bounds per-peer send rate. | Coordinated many-peer floods (peer reputation + ban list). |
| Seen-cache dedup | Cascade loops, repeat processing. | Distinct-spam from a malicious peer. |
| Passport cache | Bandwidth-efficient peer-state propagation; identity signed once at handshake. | Self-reported metrics like neuralScore (advisory only). |
| Passport IP binding | Pairwise-only Guide-ID↔IP visibility for home-holder / fragment / propagation. | Logging by direct peer for offline correlation. |
| PAC fork detection | Login walk + SPS forward + local mint hook; lock written within seconds. | Recovery of a forked Guide ID — recovery is creating a new Guide ID by design. |
| 5-per-SAI invariant | Bootstrap retirement based on community peers only. | Premature retirement under stale coverage cache. |
| UDP socket spoof-cap | Spoofed-IP floods up to 100k simultaneous source addresses. | Coordinated per-connection floods. |
| Persistent ban list | Misbehaving peer outlasting their ban via operator restart. | Cross-node ban gossip — node-local at V1. |
| 75 % governance threshold | Constitutional change requires supermajority. | Vote-buying off-protocol; coordinated voting blocs. |
| No filter, no takedown | No actor with the authority to remove content. | The mesh hosting illegal content; enforcement is social and legal (Vision §28). |
This list is not exhaustive; the canonical threat-model matrix lives in CLAUDE.md and is updated in the same PR as any new packet type or onion layer.
The architecture is designed to be linear in user count with O(1) per-anchor work.
// at billion-user scale with 115k anchors / sec network-wide: anchors received per node ≈ 5–20 / sec // 1 / 10,000 SAIs bandwidth (SVAP propagation) ≈ 2.5 Mbps passport cache hit rate (lookups) ≈ 99 % live mesh queries (1 % miss path) ≈ O(log N) hops fragment self-check (bloom) ≈ O(1)
A community node holds 1 SAI of 10,000 — every per-SAI metric is a per-anchor metric divided by 10,000. Subscriptions are SPS-elected (one peer per SAI, not one per peer covering every SAI), so the registration count is proportional to the citizen's interests, not to the user base.
The AnchorStream grows monotonically. At 115 k anchors/sec network-wide × 420 bytes ≈ 48 MB/s of total anchor growth; a community node holding 1 SAI handles approximately 1/10,000 of that — about 4.8 KB/sec of anchor metadata, or ~150 GB per year per SAI bucket. Tier 3 XOR storage (K-closest fragments held as network duty) scales with the operator's chosen budget. The Storage Trajectory module on every node tracks linear-regression slopes over 7 / 30-day windows and projects days-until-floor; the citizen's response is the storage tier slider, not an admin action.
Every governance, feed, search, and lineage query goes through the unified two-phase per-SAI fanout — one announce per SAI, PHI-allocated pull, MAX_GLOBAL_BUDGET = 10,000 anchors per response. The requester never reads its own DB. Per-user concurrency cap is 8; per-peer query egress limiter caps outbound at 240 capacity / 60 refill.
Three load-bearing properties give PHEUN linear scaling. The Sacred Anchor Index dispatcher partitions the anchor stream by 10,000 — every per-anchor metric is divided at any one node. PayloadWeave anchor-scoped placement scatters payloads across the K_NEIGHBORHOOD = FLOOR × totalFragments closest peers to CORE, each holding one rank-assigned fragment (coverage-complete, no index orphaned) — fragment load is bounded by the neighborhood, and one cache-indexed walk (the O(log N) PeerXorIndex) discovers the entire holder map regardless of file size, 100% coverage from a 10 k-node testnet to a 1 B-node mesh. SPS subscription election turns N×M into N — registration is one peer per SAI per citizen, not one per peer per SAI per citizen.
This paper has specified PHEUN — a decentralised internet replacement built on a byte-frozen 420-byte ledger, NIST post-quantum cryptography, 1:1:1:1 single-user-per-node identity, deterministic Sacred Anchor Index routing, a self-verifying propagation check at every anchor's birth, a Dual-Witness Sync integrity check at replication, an XOR-DHT for content-addressed payload storage, a three-layer PAC fork-detection model, a closed-namespace document governance pipeline, and a soft-fork-only protocol evolution lane.
The architectural commitments are honest. The protocol contains no privileged actor: no admin, no moderator, no operator class, no kill-switch, no global delete. The wire format is byte-frozen for the lifetime of V1; all evolution rides through the soft-fork lane. Identity is regenerated locally from inputs the human alone holds; the server stores the public key and a BLAKE3 fingerprint, never the private key or the inputs. Consensus is a property of deterministic placement combined with a small BFT gate at birth, rather than a global vote. There is no token, no fee, no mining, no advertising plane, no payment processor.
The costs are owned explicitly. Identity is irrecoverable if all nine Guide ID inputs are forgotten. Every anchor signed remains permanent. The mesh hosts whatever citizens upload. The disk-cost floor commits citizens to running their nodes for years.
PHEUN is not a payment system, although it can host barter. It is not an anonymity network, although it onion-routes its sensitive packets. It is not a blockchain, although it is an immutable signed ledger. It is the substrate on which all of those services can be expressed without re-introducing a privileged operator.
Where Bitcoin replaced the central bank with proof-of-work and Tor replaced the trusted ISP with onion routing, PHEUN replaces the centralised internet substrate itself — the layer beneath social media, document publishing, identity, voice and video communication, and resource exchange — with a single deterministic mesh.
The protocol is what it does. Read the source.
shared/anchor-value-mappings.tsshared/network-config.ts, shared/coverage-config.ts, shared/hope-constants.tsshared/propagation-config.ts, server/lib/hope/anchor-propagation.tsshared/fragment-id.ts — PayloadWeave constitutional law.CLAUDE.md