Skip to content

Developer Guide

topeuph-ai edited this page May 6, 2026 · 3 revisions

Developer Guide


Prerequisites

Rust / Holochain

# Rust WASM toolchain
rustup target add wasm32-unknown-unknown

# Holochain + CLI tools
cargo install holochain hc --locked

# Verify
holochain --version   # currently 0.6.0
hc --version

Node.js / Tryorama

cd valichord/tests
npm install

Building

Warning: Never use pack_dna.py — it is broken and embeds the same (attestation) DNA bytes for all four roles. Always use hc dna pack + hc app pack.

cd valichord

# Set PATH if needed
export PATH="/home/codespace/.cargo/bin:$PATH"

# 1. Compile WASM zomes (all four DNAs)
cargo build --target wasm32-unknown-unknown --release

# 2. Pack each DNA
hc dna pack dnas/attestation            -o workdir/attestation.dna
hc dna pack dnas/researcher_repository  -o workdir/researcher_repository.dna
hc dna pack dnas/validator_workspace    -o workdir/validator_workspace.dna
hc dna pack dnas/governance             -o workdir/governance.dna

# 3. Bundle the hApp
hc app pack . -o workdir/valichord.happ

The compiled DNAs and happ land in valichord/workdir/.

Build optimisation

Cargo.toml (workspace root) includes a release profile optimised for WASM size:

[profile.release]
opt-level = "z"
lto = "thin"

This halves WASM binary size, which halves JIT compilation time at test startup — critical when each runScenario launches a fresh Holochain conductor that JIT-compiles all 8 WASM modules.


Running Tests

Before every test run

pkill -f holochain; pkill -f lair-keystore; sleep 2

Orphaned Holochain or lair-keystore processes from a previous run will cause port conflicts or deadlocks. This cleanup is essential.

Tryorama integration tests

cd valichord/tests
npm test

Rust sweettest suite

cd valichord
cargo test -p valichord_sweettest_integration

Or run both in one go via the CI matrix (cargo test in the workspace root picks up all test targets).

Test timeouts

Per-test timeouts are set to 900,000 ms (15 minutes) in the Tryorama runner config. This is necessary because each runScenario call starts a fresh Holochain conductor that JIT-compiles ~30 MB of WASM. On slow hardware (e.g. a shared Codespace), startup alone can take 60 seconds per player.


Test Suite Overview

166 passing, 1 skipped across two suites. Tests are integration tests — each launches independent Holochain conductors with real agent identities, source chains, and DHT participation.

Tryorama suite — 97 passing, 1 skipped (valichord/tests/)

DNA 1: Researcher Repository (14 tests)

  • Study registration and retrieval
  • Protocol registration and retrieval
  • Snapshot creation and retrieval
  • Deviation declaration and retrieval
  • Data hash computation (return type, determinism, collision resistance)
  • Immutability enforcement
  • Source-chain querying

DNA 2: Validator Workspace (7 tests)

  • Task reception and retrieval
  • Private attestation sealing and retrieval
  • Source-chain querying
  • Privacy: Bob cannot read Alice's sealed private attestation

Key pattern: get_private_attestation_for_task uses query() (source-chain-only) not get() — private entries cannot cross cell boundaries.

DNA 3: Attestation (46 tests, 1 skipped)

  • Membrane and joining (5 tests): valid proof, no proof, short proof, real Ed25519, wrong signature
  • Blind commit-reveal (5 tests): two validators commit and reveal, late joiner, immutability
  • Profiles and indexing (8 tests)
  • Phase management and discipline filtering (2 tests)
  • Cross-DNA coordination: seal triggers notify_commitment_sealed (1 test)
  • Phase threshold: minimum validators triggers phase open (1 test)
  • Badge issuance: Bronze (3), Silver (5), Gold SKIPPED (7 — RAM-limited on Codespaces)
  • Failed reproduction badge (1 test)
  • Validator self-assignment: claim, duplicate prevention, COI rejection, capacity limit, release (5 tests)
  • Dropout recovery: timeout not elapsed, timeout elapsed, already attested (3 tests)

DNA 4: Governance (22 tests)

  • Duplicate check logic
  • Harmony Record creation from attestations
  • Reputation update permissions
  • Records by discipline, badge by study
  • Badge thresholds (Bronze, Silver, Gold)
  • Mixed outcome records
  • Governance decisions
  • Delete immutability
  • Force finalize round

Security Tests (9 tests)

  • S1: Duplicate attestation guard
  • S2: Duplicate commitment guard
  • S3: Researcher commitment idempotency
  • S4.1/S4.2: reclaim_abandoned_claim timeout floor
  • S5: force_finalize_round conservative abort
  • S6: reveal_researcher_result idempotency

Rust sweettest suite — 69 passing (valichord/sweettest_integration/)

In-process tests using holochain_sweettest — faster startup, no external conductor process. Run in 5 parallel CI matrix jobs alongside the Tryorama suite. Covers:

  • Full blind commit-reveal protocol end-to-end
  • Badge issuance including GoldReproducible (7 validators — runnable in sweettest; RAM-limited only in Tryorama)
  • CertificationTier promotion boundaries (Provisional → Standard)
  • Mixed outcome HarmonyRecord assembly
  • Cross-DNA call chain: DNA 2 seal → DNA 3 anchor → DNA 4 record

Pure outcome unit tests (no conductor) run under cargo test -p valichord_shared_types:

  • derive_majority_outcome and derive_agreement_level — run in < 1 s

Project Structure

valichord/
├── Cargo.toml                          # Workspace manifest
├── happ.yaml                           # Bundle (4 roles)
├── shared_types/
│   ├── Cargo.toml
│   └── src/lib.rs                      # Cross-DNA types (Discipline, outcomes, etc.)
├── dnas/
│   ├── attestation/
│   │   ├── dna.yaml
│   │   ├── zomes/
│   │   │   ├── attestation_integrity/  # Entry + link types, validate()
│   │   │   └── attestation/            # Coordinator: CRUD, membrane, protocol
│   │   └── workdir/
│   ├── researcher_repository/
│   │   ├── dna.yaml
│   │   └── zomes/
│   │       ├── researcher_repository_integrity/
│   │       └── researcher_repository/
│   ├── validator_workspace/
│   │   ├── dna.yaml
│   │   └── zomes/
│   │       ├── validator_workspace_integrity/
│   │       └── validator_workspace/
│   └── governance/
│       ├── dna.yaml
│       └── zomes/
│           ├── governance_integrity/
│           └── governance/
├── sweettest_integration/              # Rust sweettest suite
├── tests/
│   ├── package.json                    # Tryorama, @holochain/client
│   ├── src/
│   │   ├── researcher_repository.test.ts
│   │   ├── validator_workspace.test.ts
│   │   ├── attestation.test.ts
│   │   ├── governance.test.ts
│   │   └── security.test.ts
│   └── README.md                       # Test inventory
└── workdir/                            # Compiled output
    ├── attestation.dna
    ├── researcher_repository.dna
    ├── validator_workspace.dna
    ├── governance.dna
    └── valichord.happ

valichord-ui/                           # Svelte 5 + TypeScript browser UI
├── dev.sh                              # Start conductor + install app + write auth token
├── dev-setup.mjs                       # Node.js bootstrap (installs hApp, issues token)
└── src/lib/
    ├── holochain.ts                    # AppWebsocket singleton + callZome wrapper
    ├── types.ts                        # TypeScript mirrors of all Rust types
    ├── ResearcherView.svelte
    ├── ValidatorView.svelte
    └── GovernanceView.svelte

valichord_attestation/                  # Python attestation library (AI evals)
├── valichord_attestation/
│   ├── builder.py                      # build_bundle()
│   ├── canonical.py                    # RFC 8785 JCS encoding + hash_bundle()
│   ├── merkle.py                       # Merkle root, proof, verify
│   ├── challenge.py                    # Probabilistic challenge-response
│   └── response.py                     # build_response(), verify_response()
├── examples/
│   ├── mistral_7b_gsm8k_demo/         # Real-data demo (Mistral-7B, GSM8K-100)
│   └── challenge_response_demo.py
├── spec/attestation_format_v1.md
└── tests/                              # 142 tests, 100% line coverage

demo/
├── docker-compose.yml                  # 5-container decentralised demo
├── ai_validator.py                     # Python orchestrator (Claude API validators)
├── researcher-node.mjs                 # HTTP API wrapper for researcher conductor
└── validator-node.mjs                  # HTTP API wrapper for each validator conductor

Running the Browser UI

cd valichord-ui
npm install

# Terminal 1: start conductor + install hApp + write auth token
bash dev.sh

# Terminal 2: start Vite dev server (once Terminal 1 prints "Token written")
npm run dev
# → http://localhost:5173

dev.sh launches a local conductor via dev-conductor.yaml, installs the hApp with membrane-proof bypass, attaches the app interface, issues an auth token, and writes VITE_HC_TOKEN + VITE_HC_SIGNING_CREDENTIALS to .env.local.

Full UX walkthrough: valichord-ui/FRONTEND.md


Running the Decentralised Demo

export ANTHROPIC_API_KEY=sk-ant-...
docker compose -f demo/docker-compose.yml up --build -d

# Wait for all 4 node APIs to be ready
until [ "$(docker compose -f demo/docker-compose.yml logs 2>/dev/null | grep -c 'node API →')" -ge 4 ]; do sleep 3; done && echo "Ready"

python3 demo/ai_validator.py --mode decentralised

Five Docker containers — researcher, 3 validators, kitsune2 bootstrap server — each run their own Holochain conductor. The only communication between containers is the DHT.

Full guide: demo/DECENTRALISED_DEMO.md


valichord_attestation — AI Evaluation Attestation

A standalone Python library for producing cryptographically verifiable attestation bundles for AI evaluation runs.

cd valichord_attestation
pip install -e ".[dev]"
pytest tests/

# Real-data demo (no GPU required)
python examples/mistral_7b_gsm8k_demo/challenge_response_demo.py

See valichord_attestation/README.md and spec/attestation_format_v1.md.


Serialisation Reference

Serde encoding for shared types — important for JS test interop:

Type Serde attribute JS encoding
Discipline #[serde(tag="type", content="content")] {type: "ComputationalBiology"}
AttestationOutcome #[serde(tag="type", content="content")] {type: "Reproduced"}
DeviationType #[serde(tag="type", content="content")] {type: "MethodVariant"}
ValidationTier (no tag) plain string "Basic"
AttestationConfidence (no tag) plain string "High"
AgreementLevel (no tag) plain string "ExactMatch"
ValidationPhase (no tag) plain string "RevealOpen"

ExternalHash in JS: Use hashFrom32AndType(core32, HoloHashType.External) from @holochain/client. Do NOT construct manually (new Uint8Array(39).fill(byte)) — DHT location bytes must be a valid blake2b checksum.

Signal format: Signals use adjacent-tag serde (#[serde(tag = "type", content = "content")]), delivering { type: "RevealOpen", content: { ... } } over the AppWebsocket. Do not test for the variant name as a top-level key — unwrap type and content explicitly.


Known Gaps / Skipped Tests

Gap Reason Path forward
Gold badge — Tryorama (7 validators) Requires 7 simultaneous Tryorama conductors; RAM-limited on Codespaces Covered in sweettest; Tryorama version skipped
force_finalize_round success (Tryorama) ROUND_TIMEOUT_SECS hardcoded; Tryorama cannot advance clock Parameterise timeout; mock time in test

Production Deployment

For institutional operators deploying ValiChord to a live network, see docs/DEPLOYMENT_CHECKLIST.md — a consolidated reference for all DNA properties, dev/test bypass values, production requirements, and misconfiguration failure modes.

Key properties to set correctly before going live:

  • authorized_joining_certificate_issuer (DNA 3) — empty string lets anyone join
  • minimum_validators (DNA 3) — 0 lets a researcher bypass the multi-party protocol
  • min_claim_timeout_secs (DNA 3) — 0 enables claim-cycling attacks

Pending Upgrade: Holochain 0.6.1 + tryorama 0.19.1

Currently running Holochain 0.6.0. When 0.6.1 is available:

  1. cargo install holochain --version 0.6.1 --locked
  2. In valichord/tests/package.json: "@holochain/tryorama": "0.19.0""0.19.1"
  3. cd valichord/tests && npm install
  4. Verify tests still pass

Why: tryorama 0.19.1 switches transport from WebRTC/tx5 → iroh/QUIC, requiring Holochain 0.6.1. Currently pinned to 0.19.0 (exact pin, not ^).