Chio/Docs

Pheromone Substrate

A stigmergic substrate of signed deposits with exponential decay. It is the missing wire format that makes cross-trust-boundary coordination swarm-shaped instead of committee-shaped.

Forward-looking concept

Wire format is in draft (v0.2) inside the research repo. The page below summarises the design intent so the rest of the docs section is self-contained. Field names quoted here track the spec verbatim.

Why this is gating

Without a substrate, cross-org coordination defaults to committee shape. Every other primitive (federation gossip surface, reputation weighting, ZK disclosure shape, action-class consistency model) ends up retrofitting around whatever wire eventually ships. The wire freeze comes first.

Required surface

  • Signed deposits with exponential decay. Canonical-JSON-signed bodies on top of the existing Chio crypto stack.
  • Subject hierarchy. Keyed on a domain-supplied class (threat class for cybersec, signal class for finance, compliance class for governance domains). Soft-pluggable.
  • Source-diversity enforcement. Deposits signed by per-agent passport keys (not kernel keys), counted as (kernel_id, agent_passport_key_hash) pairs. Per-pair token-bucket budget per epoch. Per-kernel cap of ceil(sqrt(active_peers_in_treaty)) distinct passport keys per subject-class per window.
  • Evaporation garbage collection.
  • Newcomer-discount. A passport’s effective weight is min(1, age_in_anchored_epochs / N) with a default of N = 8. Combine with org-level binding in revocation evidence so a fresh passport from a sanctioned org inherits the sanction.
  • Verifiable observation-cost commitment field. A hash-chain reference to telemetry receipts so peers that only co-sign without originating can be detected and weight-capped.
  • Federation gossip. Reuse the bilateral push-queue pattern from chio-federation::revocation_gossip, scoped per-treaty at subscribe boundary; FIFO with per-origin rate limit. Pheromones do not replace each other.
  • Receiver-side reputation weighting. Applied at concentration-query time via a closure injected by the runtime (the substrate stays unaware of reputation). Pinned to a chio-anchor epoch so concentrations are reproducible.
  • Optional ZK selective disclosure. Proof of concentration without revealing raw indicators. See the Selective Disclosure page.
  • Storage-agnostic substrate trait. Reference impls: in-memory and local-journal. Durable backends live in adapter crates so Chio’s “no host required” property survives.

Crate boundary

New top-level chio-pheromone beside chio-reputation and chio-federation, depending only on chio-core-types and chio-credentials. Reputation is not a dependency: pheromone outcomes feed reputation via outcome receipts, avoiding a cycle. Federation gossip lives in a thin sibling module under chio-federation.


Canonical signed deposit

The deposit is a chio.pheromone-deposit.v1 body in canonical JSON (RFC 8785). The signature is computed over the JCS encoding of the body with the signature field excluded, then reattached. The signing key is the agent passport key (Ed25519 by default, hybrid prefixed where the kernel admits it). Kernel keys are explicitly rejected by verifiers.

deposit.json
{
  "schema": "chio.pheromone-deposit.v1",
  "kernel_id": "did:chio:siegfried-soc",
  "agent_passport_key_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  "agent_passport_jwk_thumbprint": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs",
  "subject_class": "ttp.lateral-movement.kerberoast",
  "subject_class_namespace": "dev.chio.cybersec.mitre-attack",
  "indicator": {
    "asset_kind": "host",
    "obs_kind": "auth-failure-burst",
    "host_id": "h-2af1"
  },
  "severity": "high",
  "confidence": 0.72,
  "timestamp_unix_ms": 1746710400000,
  "decay_half_life_secs": 1800,
  "evaporation_floor": 0.01,
  "nonce": "AQIDBAUGBwgJCgsMDQ4PEA",
  "treaty_scope": ["treaty:cybersec.regional-soc.v1"],
  "cost_commitment": {
    "schema": "chio.pheromone-cost-commitment.v1",
    "telemetry_chain_root": "5b41362bc82b7f3d56edc5a306db22105707d01ff4819e26faef9724a2d406c9",
    "chain_position": 184223,
    "chain_position_proof": "{\"path\":[\"...\"],\"root\":\"5b41362b...\"}",
    "observed_at_unix_ms": 1746710395120
  },
  "signature": "ed25519:7e2b1f3a...c104"
}

Notable fields: decay_half_life_secs is per-deposit (the substrate config supplies a default but the depositor owns the curve), treaty_scope lists every treaty under which this deposit may be gossiped (an empty list means local-only), and cost_commitment is REQUIRED by default for any subject class the participant’s ladder manifest declares destructive: true.

Bilateral gossip envelope

Federation gossip mirrors chio-federation::revocation_gossip: bilateral push queues, per-peer FIFO ring, deterministic flush. Pheromones differ in two ways. (1) No supersession: a newer deposit never replaces an older one, since concentration is a sum, not a current state. (2) Per-origin rate limit: every receiver enforces a token bucket keyed on the originating depositor tuple, not the gossiping peer.

gossip-envelope.json
{
  "schema": "chio.pheromone-batch.v1",
  "recipient_kernel_id": "did:chio:vega-soc",
  "treaty_id": "treaty:cybersec.regional-soc.v1",
  "frames": [
    {
      "schema": "chio.pheromone-deposit-gossip.v1",
      "deposit": { "...": "chio.pheromone-deposit.v1 body with signature" },
      "origin_kernel_id": "did:chio:siegfried-soc",
      "gossiping_peer_kernel_id": "did:chio:siegfried-soc",
      "treaty_id": "treaty:cybersec.regional-soc.v1",
      "ts_unix_ms": 1746710400420
    }
  ],
  "flushed_at_unix_ms": 1746710401000
}

Frames are FIFO within a batch; the substrate MUST NOT reorder by epoch or coalesce by deposit identity. Receivers run the structural envelope check (schema, origin agreement, treaty membership), then run validate_deposit (signature, replay nonce, diversity caps, observation-cost gate where required) before merging. Failures drop fail-closed; the per-origin rate-limit overflow surfaces as rate_limit_exhausted.

Concentration query

Concentration is computed receiver-side at query time. The substrate stays unaware of reputation: the runtime injects a peer-weight closure that returns a value in [0.0, 1.0] for each contributing kernel, pinned to a chio-anchor epoch. Per-deposit contribution is strength_at(t) * peer_weight(kernel_id, epoch) * newcomer_discount(passport, epoch).

Pinning the reputation_epoch makes results reproducible: a third party that reconstructs from the deposit corpus and the same anchored reputation snapshot recovers the same total_strength. The substrate refuses queries whose epoch is unknown to the local anchor view, with no silent fallback to the latest epoch.

rendering…
Deposit lifecycle: depositor signs with passport key, peer gossips under a treaty, receiver runs structural and validate checks, then computes a weighted, decayed concentration pinned to a chio-anchor epoch.

The result body is a chio.pheromone-concentration.v1 carrying total_strength, unweighted_total_strength (the same sum without per-peer reputation, for diagnostics), distinct_origin_pairs, peak_confidence, and the pinned reputation_epoch so the answer is replayable.

Source-diversity caps

Origin diversity is counted as the number of distinct (kernel_id, agent_passport_key_hash) pairs contributing to a concentration. A single kernel running ten passports counts as ten origins only if all ten are bound to live, non-revoked agent passports under that kernel’s federation handshake. Two caps stack on this counting rule.

  • Per-pair token bucket. A token bucket per (kernel_id, agent_passport_key_hash, subject_class) per anchored epoch. Overruns reject with diversity_cap_exceeded.
  • Per-kernel sqrt(N) cap. The receiving kernel caps, per subject-class per window, the number of distinct passport keys it accepts from any single origin kernel at ceil(sqrt(active_peers_in_treaty)). Overruns reject with sqrt_n_passport_cap_exceeded. The window length SHOULD align with the reputation epoch cadence.

Worked example. A treaty has admitted 64 active peers in the current window. The cap is ceil(sqrt(64)) = 8: any single origin kernel may contribute deposits from at most 8 distinct passport keys per subject-class per window. Origin kernel A pushes 8 passports under subject_class = "ttp.lateral-movement" and the eighth deposit is accepted. The ninth (under a fresh ninth passport) is rejected with sqrt_n_passport_cap_exceeded; prior eight deposits remain stored. Halving the treaty population to 16 active peers tightens the cap to 4. Doubling to 256 raises it to 16.

What the cap actually does

Per the v0.2 honest framing, the sqrt(N) cap is a cost-shifter, not a cost-reducer: an adversary capped on per-kernel passport keys is forced to provision more cover operator-orgs to spread the same passport mass, and the operator-org admission cost absorbs the savings on key issuance one-for-one. The cap is mandatory for forensic reasons (it forces operator-org admissions onto the federation handshake surface, prevents single-kernel mass-minting without footprint, and bounds reputation-graph fan-out for collusion analysis), not as a quantitative Sybil deterrent. Adversary-budget defense lives in the newcomer-discount horizon, the observation-cost commitment, and the underlying passport-issuance cost.