Colloq GitHub

Two-node Colloq/Iroh runbook

This is the first end-to-end path in which the two Colloq roles are independent operating-system processes with persistent identities and local authorization policy. It is intended for a laptop, two routable data-center hosts, or a Miren UDP node port. It is not yet a production key-management system.

Trust artifacts

Colloq deliberately separates three files:

Artifact Contains Distribution
*.colloqnode.json Ed25519 private key and derived Iroh Endpoint ID Local secret; mode 0600 on Unix
*.colloqendpoint.json Public Endpoint ID and direct socket addresses Give to connecting peers
*.authorization.json Exact Endpoint ID → role → Colloq Plan grants Local policy

There are no wildcard grants in v0. A changed conversation produces a changed plan identity and therefore needs a new explicit authorization.

One-machine two-process acceptance run

The repository runs this complete acceptance path on Linux and macOS in CI. Locally:

cargo build --locked
scripts/two-node-smoke.sh

The harness checks a successful Generate session, independently edited draft convergence and promotion, private identity file permissions, and fail-closed rejection of an unknown endpoint.

Create two node identities and reciprocal policy for both the Generate workload and the colloq.draft-sync control conversation:

cargo run -- bootstrap-two-node --out build/two-node

Start the server in one terminal. It writes a public ticket before accepting one connection:

cargo run -- serve-iroh \
  --listen 127.0.0.1:7880 \
  --ticket-out build/two-node/server.colloqendpoint.json \
  --report-out build/two-node/server-report.json \
  --tokens 4

Connect from another terminal and verify the independently recorded outcomes:

cargo run -- connect-iroh \
  --server build/two-node/server.colloqendpoint.json \
  --report-out build/two-node/client-report.json

cargo run -- verify-session \
  --client build/two-node/client-report.json \
  --server build/two-node/server-report.json

The verifier requires the same conversation identity, plan identity, semantic-trace identity, tokens, success result, and terminal outcome.

Two physical servers

Generate each identity on the machine that will own it:

cargo run -- node-init --out /secure/colloq/server.colloqnode.json
cargo run -- node-init --out /secure/colloq/client.colloqnode.json

Exchange only the printed public Endpoint IDs. On the server, grant the client ID the client role; on the client, grant the server ID the server role:

cargo run -- policy-allow --policy /secure/colloq/server.authorization.json \
  --peer CLIENT_ENDPOINT_ID --role client

cargo run -- policy-allow --policy /secure/colloq/client.authorization.json \
  --peer SERVER_ENDPOINT_ID --role server

The server binds all interfaces but advertises the address reachable by the client:

cargo run --release --locked -- serve-iroh \
  --identity /secure/colloq/server.colloqnode.json \
  --policy /secure/colloq/server.authorization.json \
  --listen 0.0.0.0:7880 \
  --advertise 10.20.0.12:7880 \
  --ticket-out /tmp/server.colloqendpoint.json

Copy only /tmp/server.colloqendpoint.json to the client, then run connect-iroh with the client identity and policy. Allow UDP on the selected port. Iroh authenticates both Endpoint IDs; Colloq then binds the exact roles, compiled plan, wire encoding, and TLS exporter before frame zero.

Authenticated collaborative draft sync

Draft synchronization is itself a projected Colloq conversation. The peers exchange incremental Automerge sync messages as typed sync transitions; completion is an explicit done choice.

# Create the same initial draft on both hosts, then edit independently.
cargo run -- draft-create examples/generate.colloqconv.json \
  --out build/two-node/server.colloqdraft

# Server
cargo run -- draft-serve-iroh \
  --draft build/two-node/server.colloqdraft \
  --listen 127.0.0.1:7881

# Client
cargo run -- draft-connect-iroh \
  --draft build/two-node/client.colloqdraft \
  --server build/two-node/draft-server.colloqendpoint.json

Both draft files are saved after synchronization. Automerge convergence does not bypass Colloq's promotion gate: unresolved meaning conflicts are still rejected, then the materialized graph is strictly deserialized, validated, and compiled.

Miren path

Miren v0.5+ supports UDP node ports for non-HTTP services. Generate an Iroh-specific manifest:

cargo run -- emit-miren examples/generate.colloqconv.json \
  --transport iroh --port 7880

The manifest exposes UDP 7880 and declares three required values:

  • COLLOQ_NODE_IDENTITY_JSON — sensitive node identity JSON;
  • COLLOQ_AUTHORIZATION_JSON — sensitive exact authorization policy JSON;
  • COLLOQ_ADVERTISE_ADDRESS — the Miren host or overlay socket address peers can reach.

Set those through Miren's environment management and run miren deploy. A connecting node receives the corresponding public ticket out of band, or supplies it through COLLOQ_SERVER_TICKET_JSON. Miren owns image placement, restart, and UDP forwarding; Colloq/Iroh owns peer authentication and the language session. See the official Miren app.toml reference and non-HTTP traffic routing.

The repository does not contain node secrets. Deployment requires a configured Miren CLI/cluster and operator-provided identities; a source checkout alone cannot safely deploy an authenticated node.

Remaining security work

v0 is fail-closed for an unknown identity, wrong role, wrong plan, wrong encoding, and replaying a preface on another TLS connection. Rotation and revocation distribution, session nonces, durable anti-replay state, protected hardware keys, long-running multiplexed sessions, and workload-identity attestation remain future work.

Edit this page on GitHub