Skip to content

Navigation Menu

Sign in
Sign up

Nondominium x ValiChord integration #109

Soushi888 started this conversation in Ideas
Discussion options

Ceri:

Hi, this is Ceri from ValiChord (https://github.com/topeuph-ai/ValiChord), a blind commit-reveal validation protocol built on Holochain.

The commented-out validate_new_resource() call in create_economic_resource() is exactly where we've been scoping ValiChord's role — as the "Evaluate" step for driving ResourceState::PendingValidation → Active once multi-validator consensus is reached. ValiChord produces a HarmonyRecord on a shared DHT as its output; the open question we've been thinking through is how that outcome maps to a GovernanceTransitionResult.

One constraint we've hit: update_resource_state() is currently custodian-gated, so an external system can't drive the transition directly. Would a governance-gated pathway (accepting a HarmonyRecord hash rather than requiring custodianship) be in scope as part of this work?

As you work through this and #41, would it be worth coordinating on what the external validator side of the interface needs to look like? We've written up integration design notes if that's useful context.

Soushi:

Hi Ceri, thanks for the thorough read-through and the well-structured integration notes. You identified the exact gap we've been aware of.

On your concrete question (the custodian gate on update_resource_state()): we'd rather not add a new validate_and_activate_resource() function at this stage. The architectural direction we're leaning toward keeps the custodian gate intact and solves the authorization differently.

Our current thinking: capability slots, not core dependencies

The NDO core is intended to keep only hREA as a hard dependency. External integrations (ValiChord, Flowsta, Unyt) would attach to NDO resources and agent identities via the capability slot surface rather than through compile-time coupling.

Concretely for ValiChord: your HarmonyRecord would be attached as a capability slot link from the EconomicResource (or NondominiumIdentity) hash to the HarmonyRecord action hash on ValiChord's shared DHT. The governance operator would gain a GovernanceRuleType::ExternalValidation variant that knows how to read and verify that slot. When a resource enters PendingValidation, a governance rule can specify the required slot type and consensus threshold.

For Decision 5 specifically: the researcher (who holds custody) calls the existing update_resource_state() once the ValiChord slot is populated. Inside that call, the governance operator checks whether the required slot is present and its content meets threshold. The custodian gate stays; the governance check replaces the need for ValiChord to directly drive the transition. This keeps sovereignty with the researcher: they choose when to pull the trigger.

This also gives a clean answer to Decision 1: Option B (HarmonyRecord as authoritative record, not NDO's ResourceValidation.status). NDO governance rules check the slot rather than tracking parallel state.

The key technical question for us

Can the HarmonyRecord action hash be written as a DHT link that NDO's governance operator can resolve and verify at transition time, without ValiChord being a compile-time dependency in the NDO Rust crates? Specifically: does verifying a HarmonyRecord require calling into ValiChord coordinator functions, or is it sufficient to check the entry hash and its content against a known schema?

If it's hash-verifiable without coordinator calls, the integration is clean. If it requires cross-zome calls into ValiChord, that's a tighter coupling we'd want to think through carefully.

Happy to coordinate further on what the slot schema and governance rule interface would need to look like from ValiChord's side.

You must be logged in to vote

Replies: 3 comments

Comment options

Thanks for the detailed question — this is exactly the right thing to nail down before writing any integration code.

Short answer: yes, HarmonyRecord is hash-verifiable from NDO without ValiChord as a compile-time Rust dependency.

Here is how it works in practice.


DHT locality — one constraint to know upfront

get(action_hash) in an NDO zome searches NDO's DHT. ValiChord's governance DNA runs on a separate DHT network. A raw get() call from NDO will not find a ValiChord HarmonyRecord — the two networks are not connected at that layer.

This is not a showstopper. There are two clean paths, depending on what NDO needs at each call site.


Path 1 — Threshold verification at update_resource_state() time (no network fetch, no ValiChord types)

The capability slot link carries all the threshold data NDO needs in its tag:

base: NDO resource ActionHash
target: ValiChord HarmonyRecord ActionHash (unforgeable link to the actual record)
tag: { "agreement_level": "ExactMatch", "validator_count": 3 } — msgpack

agreement_level serialises as a plain string in ValiChord (AgreementLevel has no serde tag attribute — it uses the default external-tag encoding, so unit variants are just strings: "ExactMatch", "WithinTolerance", "MajorityConsensus", "Inconclusive").

This means NDO's GovernanceRuleType::ExternalValidation rule can decode the tag using a locally-defined two-field struct:

#[derive(Deserialize)]
struct SlotTag {
 agreement_level: String,
 validator_count: u32,
}

No ValiChord crate needed. The governance rule checks validator_count >= required and agreement_level matches (or exceeds) the configured threshold, then permits the Active transition. The HarmonyRecord ActionHash in the link target is the unforgeable commitment — NDO does not need to fetch it to enforce the threshold, just to hold it as a reference.


Path 2 — Full record verification (same conductor, no Rust dependency)

If NDO wants to verify the full HarmonyRecord content — validator identities, discipline, full outcome — it can make a cross-hApp call using CallTargetCell::OtherCell { cell_id } to a ValiChord governance cell running on the same conductor.

ValiChord exposes two read functions, both Unrestricted (no capability secret needed):

  • get_harmony_record(ExternalHash) — looks up by request_ref (the data hash the researcher submitted). Takes a HoloHash<hash_type::External>, not an ActionHash.
  • get_harmony_record_by_hash(ActionHash) — looks up directly by ActionHash. This is the natural counterpart for the slot link target.

The call returns a Record (msgpack-serialised). NDO decodes the entry fields it cares about with a locally-defined partial struct — no ValiChord crate import required.

For MVP threshold enforcement Path 1 is sufficient and simpler. Path 2 is available for audit trails or governance displays that want to show validator identities.


Who writes the slot link

ValiChord's governance DNA participates in ValiChord's DHT — it cannot write to NDO's DHT directly. The slot link is written by the researcher from their NDO agent context. This fits naturally: the researcher is already the one calling update_resource_state(), so the flow is:

  1. ValiChord produces the HarmonyRecord → researcher's client receives the ActionHash
  2. Researcher calls (new NDO function): write capability slot link → base: resource hash, target: HarmonyRecord ActionHash, tag: {agreement_level, validator_count}
  3. Researcher calls update_resource_state() as normal → governance rule checks slot → transition proceeds

The custodian gate stays intact. Sovereignty over the state transition stays with the researcher.


One open question for your team

Where should the slot-writing function live — zome_resource (alongside the state transition logic) or zome_gouvernance (alongside the validation machinery)? Either works from ValiChord's side. Happy to follow whatever fits NDO's zome boundary conventions.


On versions: ValiChord is at hdk = "=0.6.1" / hdi = "=0.7.1", same minor as NDO's ^0.6.0. No upgrade needed to begin.

Let me know if it would help to sketch out the Rust struct for the slot tag, or the partial deserialisation struct for Path 2.

You must be logged in to vote
0 replies
Comment options

Soushi888
Jun 16, 2026
Maintainer Author

Hi @topeuph-ai! Apologies for the delay.

I'd like to set up a call with the three of us: @TiberiusB, you, and me.

The capability slot / attachment surface is becoming one of the load-bearing pieces of the Nondominium architecture, and the pressure to get it implemented well is growing. It's the stigmergic surface that lets external modules attach capabilities to an NDO's (or an agent's) identity without ever touching the core protocol. That's precisely what keeps Nondominium composable instead of monolithic: it's the contract between the core and modules like Valichord.

For that reason I don't want to design it in isolation. The people best placed to pressure-test the surface are the ones who will actually build against it, so your perspective as a candidate module is exactly what we need to get the shape right.

You must be logged in to vote
0 replies
Comment options

Hi @Soushi888 — yes, let's set up the three-way call with @TiberiusB. The capability-slot surface is exactly the right thing to design with its first consumer in the room, and it's where ValiChord's needs are most concrete. I'll bring written notes so we can work from something.

Before we meet, I want to refine one thing I said earlier in this thread — it's load-bearing enough that I'd rather correct it now than discover it mid-implementation. Earlier I wrote that for MVP threshold enforcement, Path 1 (reading the slot-link tag) is sufficient. On reflection, for a gate that controls a medical-device lifecycle transition, it isn't — and the reason is exactly the kind of thing this surface needs to get right.

The slot link and its {agreement_level, validator_count} tag are written by the researcher — the party with the incentive to inflate the result — and NDO's link validate() can't cross-fetch the ValiChord record at validation time (separate DHT networks, no network in validation). So a tag-only gate is forgeable two ways:

  1. a tag that overstates the record it points at ("ExactMatch", 7 on a study that was actually "Inconclusive", 1), and
  2. a target that points at a real-but-unrelated good record from a different study.

Either one re-creates the "trust the claimant" gap that ValiChord exists to remove — so I'd argue the ExternalValidation governance rule should, at decision time, verify the actual HarmonyRecord rather than decide from the tag:

  • fetch the record via the same-conductor OtherCell call to get_harmony_record_by_hash (Path 2), and
  • check (a) the record's own agreement_level + validator count meet threshold, and (b) its request_ref binds to this resource's deposited data.

The tag is still useful as a cheap pre-filter and for display — it just shouldn't be the thing the gate trusts.

Two things worth stressing, because they're good news:

  • This doesn't reopen the "no compile-time dependency" conclusion. Path 2 is a runtime cross-cell read of an Unrestricted function, decoded against a local partial struct — still no ValiChord crate in your Rust. The clean-integration story holds; the work just moves from "read a tag" to "read the record."
  • It preserves your custodian model exactly. The researcher still holds the trigger and decides when to transition — they just can't fabricate what the record says. Sovereignty over when, not over what.

One scoping caveat I'll bring to the call: this closes the forged-result hole. There's a separate hole — a researcher who controls the reviewer pool can produce a genuine passing record — that the gate fetch can't catch; it's closed upstream by how reviewers are admitted and kept independent. Happy to walk through both, and to sketch the request_ref-binding check and the partial deserialisation struct, whenever suits.

A quick note on how I work: I'm not a developer myself I drive ValiChord's design and direction, and lean on AI tooling to turn that into the technical detail (including drafting comments like this one). So if I ask you to put something in plainer terms on the call, that's why. I'd always rather ask than nod along. Looking forward to it.

See you soon.

Ceri

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Ideas
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /