particle alias survey
property #19 of the launch registry
freezes file::Particle as the one type bbg, cybergraph, foculus and tru
share. Before that decision lands, this is what exists in the owner's
working trees on 2026-09-19 (which carry unpushed work; line numbers were
re-verified against each repository's origin/master on 2026-09-22 and
corrected where they differ): five independent representations, two incompatible byte widths,
and no domain separation on the path that will address 3.1M migrated
bostrom files. This document makes no decision; it lists what a decision
must reconcile.
the definitions
-
file::Particle—cyber-filecrate,src/lib.rs:16.struct Particle([u8; 32]), a newtype with hex/debug/display impls.Particle::hash(data)atsrc/lib.rs:34callshemera::hash(data)directly on the whole byte slice — no chunking, no domain prefix. -
bbg::Particle—bbg/rs/src/types.rs:9.pub type Particle = [u8; 32]— a bare alias, no newtype, no hex/debug helpers of its own.ParticleRecordattypes.rs:19wraps it for storage. This is the type cybergraph re-exports (cybergraph/src/lib.rs:25onorigin/master,:34in the owner's working tree:pub use bbg::{NeuronId, Particle, IntentRecord, SignalRecord};) and the type foculus imports directly in five modules (conflict.rs:24,finality.rs:23,pay_proof.rs:24,finality_evidence.rs:11,reconcile.rs:23, alluse bbg::Particle;). -
A second, unrelated alias inside the same bbg crate —
bbg/rs/src/storage/application.rs:9:pub type Particle = [u8; 32]. This file is not on bbgorigin/master; it arrives with the owner's open bbg#9 (feat/atomic-application-storage, line 9 there, line 14 in the owner's working tree). Same shape as (2), declared independently in a different module. Two type aliases with the same name and the same representation, defined twice in one crate, is itself a finding independent of the cross-crate question: nothing stops the two from diverging in a future edit, and nothing today enforces that they stay the same alias. -
tru's local convention —tru/rs/vocab.rs. NoParticletype at all; a bare[u8; 32]field (vocab.rs:16) and a privateparticle_of()function (vocab.rs:28) that callscyber_hemera::hash(bytes)and copies the digest into an array. Same construction asfile::Particle::hash, but reimplemented rather than depending on thefilecrate, so a change to hashing infilewould not reachtruwithout a second edit. -
cybergraph/specs/particle.md— the specification, not code. Describes a 64-byte flat namespace (particle.md:3: "64 raw bytes, no headers, no version prefix"), shared by particles, edges, neurons, commitments and nullifiers with domain-separation prefixes (0x01edges,0x02records,0x03nullifiers,0x04Merkle internal nodes; particle content addressing itself uses no prefix, per the domain table atparticle.md:56-64, restated at:66; the 64-byte output format is at:70-73). It also specifies a tree structure for content over 4KB (particle.md:44-52, left-balanced binary,Hemera(chunk_bytes)leaves) that none of the four code definitions above implement — every one of them hashes the full byte slice in a single call, with no chunking. -
radio/particle— a CLI (radio/particle/src/main.rs), independent of all of the above, built directly oncyber_bao(Poseidon2 backend, BAO verified streaming:hash,encode,decode,outboard,verify). It does not importfile,bbg, ortru's particle types; it computes hashes itself.
the contradictions a decision must resolve
- byte width: 32 bytes (
file,bbg,tru) vs. 64 bytes (spec). Every particle computed today by code is half the width the spec says the namespace uses. - domain separation: none in any of the four code paths; the spec
reserves four prefix bytes for non-particle uses of the same hash
function and explicitly special-cases bare content addressing as the
unprefixed default. If particle identity is ever computed anywhere
with a domain prefix (BAO's tree-node hashing in
radio/particlehashes chunks and internal nodes together with content — worth checking against the spec's leaf/internal split before reuse), the address for the same bytes will not matchfile::Particle::hash's direct call. - chunking: the spec's 4KB tree applies past a size threshold; no
current implementation branches on input size. A large bostrom file
hashed by
file::Particle::hashtoday gets a different address than the spec's tree construction would assign it once implemented. - ownership:
bbgcarries two independently declared identical aliases in the same crate (finding 3); cybergraph re-exports bbg's alias rather than depending onfile;trureimplements the hash function rather than depending onfile. Freezingfile::Particleas the shared type means four call sites (bbg's two aliases, cybergraph's re-export, tru'sparticle_of) each need a migration, not one.
what this does not decide
Which definition wins — hemera(data) at 32 bytes with no prefix (the
code today) or hemera over a chunked tree at 64 bytes with domain
separation (the spec) — is still the open decision logged on the launch
tracker. This survey exists so that whichever way it resolves, the scope
of the migration is known in advance: five source locations across four
crates, plus the CLI in radio/particle if it is ever asked to compute
particle identities rather than generic content hashes.