Repository navigation
feat: bring Tibi's general backend work from commitment-pool-experiment onto dev - #183
Merged
Merged
Conversation
Introduces `vf:Measure { numerical_value, has_unit }` as a shared type in
crates/shared, mirrored at the integrity + coordinator layers of both
zome_resource and zome_gouvernance.
- EconomicResource.{quantity, unit} -> quantity: Measure
- EconomicEvent.resource_quantity -> Measure (was f64)
- Commitment gains resource_quantity: Option<Measure> and
effort_quantity: Option<Measure> to track with ValueFlows flow fields
- propose_commitment accepts explicit receiver (was hardcoded to caller),
so third parties can author commitments on behalf of two other agents
- EconomicResourceView and TransitionContext.quantity_change kept but
switched to Measure / documented as magnitude-only
- Measure::validate() enforces non-NaN, finite, non-negative numerical_value
and non-empty unit; zero permitted (post-depletion observations)
- Integrity validation plumbed through on create for EconomicResource,
EconomicEvent, and Commitment
- Sweettest mirror structs updated accordingly (resource/mod.rs,
governance/mod.rs)
Preparing for commitment-pool-experiment:
- Grassroots-side tooling (and hREA) can read the same Measure shape
- Commitments on the pool can now carry resource/effort quantities
without squeezing them into free-text notes
cargo build + bun run build:zomes both clean.
Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit dcbc019)
Mirrors the Rust-side Measure migration across:
- packages/shared-types: adds Measure interface, migrates
EconomicResource.{quantity,unit} -> Measure, VfEconomicEvent /
VfCommitment / LogEconomicEventInput / ProposeCommitmentInput to
Measure, adds explicit receiver + resource_quantity + effort_quantity
on ProposeCommitmentInput
- ui/schemas: adds MeasureSchema, swaps number+string pair for Measure
in EconomicResourceInput, UIEconomicResource, UIEconomicEvent,
CommitmentInput, UICommitment
- UI components:
* EconomicEventCreateForm now takes quantity + unit (defaults 'each')
and submits a Measure
* CommitmentCreateForm now takes explicit receiver (defaults to self)
and optional resource/effort quantity+unit pairs
* ResourcesTab + ActivityTab render Measure.{numerical_value,has_unit}
- holochain-records: isEconomicResource guards against the Measure shape
- resource.store: updateResourceQuantity patches numerical_value only
(unit unchanged); documents that the backend fn is still not wired
- ndo.store: event dedup checks both numerical_value and has_unit
svelte-check: no new regressions. Error count 228 -> 224 (noise).
Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit 0fc0ab3)
The Group DNA's CommitmentAnchor points at commitment ActionHashes on the Nondominium cell, but to display 'commitments attached to this NDO' or to drive a Pool admissions UI, callers need an NDO-indexed reverse lookup without scanning the global AllCommitments anchor. Integrity (zome_gouvernance_integrity): - LinkTypes::NdoToCommitments (ndo_identity_hash -> Commitment) Coordinator (zome_gouvernance / commitment.rs): - propose_commitment now also writes an NdoToCommitments link in addition to AllCommitments, using the commitment's existing ndo_identity_hash field (Layer 0 anchor) - get_commitments_for_ndo(ndo_identity_hash) reads that per-NDO index directly — O(links) instead of O(total commitments) Pairs with the Group-side CommitmentAnchor so UIs can cross-reference 'commitments on this NDO' with 'pools this commitment is admitted to' via the shared commitment_action_hash. bun run build:zomes: clean. No new regressions. Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit f7e06a2)
Single coordinator call that closes a Commitment: 1. Validates the commitment and the caller's role (provider | receiver) 2. Fetches the counterparty's REAL cryptographic signature via call_remote -> fixes #14: the previous issue_participation_receipts flow wrote Signature([0u8; 64]) as the counterparty placeholder, so every PPR would fail validate_participation_claim_signature. The closure now produces a bilateral PPR where both signatures are real and verify. 3. Writes the EconomicEvent observation 4. Writes the Claim with fulfilled_by = the real event action hash -> fixes the pre-existing TODO in claim_commitment where fulfilled_by was wrongly set to the commitment hash itself 5. Optionally updates the EconomicResource.operational_state via a same-agent cross-zome call into zome_resource::update_operational_state (the custodian check still applies — if the fulfiller isn't the custodian, the whole closure rolls back cleanly) 6. Writes both bilateral PrivateParticipationClaim entries with real co-signatures from both parties Atomicity model: - call_remote-based countersign chosen over full Holochain countersigning session: smallest unit of atomicity that produces cryptographically valid PPRs, matches Grassroots Pool semantics (fulfillment is a two-sided act), and fails cleanly when the counterparty is offline rather than leaving a half-session for someone to roll back later. Shared signing payload (build_fulfillment_signing_data): - Deterministic across initiator + counterparty. - Binds: commitment hash, provider, receiver, resource hash, NDO identity hash, resource_quantity (Measure), VfAction, claim-type pair, timestamp. - Blake3-hashed; both sides sign the hash so verification is cheap. countersign_fulfillment (unrestricted cap grant via init): - Refetches the commitment and checks that call_info().provenance == the claimed initiator in the payload AND that initiator is in fact this agent's counterparty on the commitment. - Signs the shared payload with its own key and returns the signature. - Semantic authorisation (not cap-token based) — appropriate for a bilateral-event countersign where either party may initiate. MVP scope: both PPR private entries land on the fulfilling agent's source chain for now, both with real co-signatures (so cryptographic verification works end-to-end today). Mirroring the counterparty's copy onto their own source chain is a view/replication concern that can land later without changing the signing protocol. bun run build:zomes: clean (pre-existing dead_code warnings only). Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit 11085b5)
Adds two Sweettests on the governance zome:
* get_commitments_for_ndo_scopes_results — writes commitments on two
distinct NDOs by the same agent and asserts that the NdoToCommitments
index returns only the ones linked to the queried identity.
* fulfill_commitment_closure_happy_path — Alice creates an NDO, spec,
and resource, then proposes a commitment with Bob as receiver. Bob
calls fulfill_commitment_closure, which call_remotes back to Alice
via the unrestricted countersign_fulfillment grant. Asserts:
- event_hash != claim_hash (claim.fulfilled_by is the real event
hash, not the commitment hash)
- provider_claim_hash != receiver_claim_hash (bilateral issuance)
- a claim is readable where fulfills == commitment and
fulfilled_by == event (end-to-end closure)
Also fixes the countersign_fulfillment response decode on the initiator
side: the counterparty returns CountersignFulfillmentOutput (a struct
wrapping Signature), not a bare Signature, so decode as the wrapper and
extract .signature. Without this, every two-agent fulfillment would
fail at the call_remote boundary with 'invalid type: map, expected a
byte array of length 64'.
Related: #14
Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit 09c86a1)
…ailed) Backend slice of 033a63a on commitment-pool-experiment: CommitmentRecord pairs each Commitment with its ActionHash so a UI can act on a specific commitment (fulfill, admit, withdraw). The UI surfaces of that commit stay on the experiment branch. (cherry picked from commit 033a63a, backend slice only)
…rceSpecification Adds InventoryIntent, IdentificationPattern and DigitalLocatorKind, the optional Layer 1 foreshadow fields on ResourceSpecification, and their validation in validate_spec_foreshadow, with Sweettest coverage and the TypeScript mirror. The UI redesign that rode on the same commit (GovernanceTab, ResourcesTab, AgentPubkeyField) stays on the experiment branch for the v0.1 UI pass. (cherry picked from commit 3156120, backend, shared-types and docs slice only)
…hape
ZomeCallCapGrant and CapAccess::Unrestricted are gone in holochain 0.7;
the grant is now CapGrant { constraint: GrantConstraint::Unrestricted,
capability: Capability::ZomeCall(..) }.
…d foreshadow additions
…d the signer rebuilds - The initiator now signs signed_data_hash, as the counterparty does and as validate_participation_claim_signature verifies; before, every receipt the closure wrote failed that check. - countersign_fulfillment rebuilds the signing payload from the commitment it fetched, the observed quantity and the event time, refuses a mismatching hash, and signs its own hash rather than the one it is handed. - Consent: only the party who did not author the commitment may initiate; the author countersigns. A commitment that names an agent who never wrote it can no longer collect that agent's signature. - A commitment with a CommitmentToClaim link is refused on both sides. - Sweettests: both PPR signatures verify, a second fulfillment is refused, the author cannot initiate.
The quantity inputs are type=number, so Svelte binds a number or undefined; calling .trim() on it threw on submit. A Measure of 0 is valid, so the event form no longer turns 0 into 1.
…nt event time countersign_fulfillment is an unrestricted grant, so the non-author could call it directly to collect the author's signature over any unit or a backdated time. It now refuses an observed unit that differs from the committed one and an event time more than five minutes from its clock. The event form's empty quantity falls back to 1 as intended (an empty number input binds null).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings the general backend work from Tibi's
commitment-pool-experimentbranch ontodev, so the v0.1 line and the Grassroots Economics MVP share one backend. Quantities become a ValueFlowsMeasure, each NDO indexes its commitments (with hash-paired reads a UI can act on), commitment fulfillment closes atomically with a real counterparty countersignature, andResourceSpecificationgains the optional Layer 1 foreshadow fields. The commitment pool itself (CommitmentAnchoron the Group DNA, admit, withdraw and pool UI) stays on the experiment branch.Tibi's commits keep his authorship. On top: two small ports to Holochain 0.7.1, and fixes from an independent review of the fulfillment closure (its receipts failed the PPR signature check, the counterparty signed whatever hash it was handed, and a commitment could be fulfilled repeatedly), each its own commit with Sweettests.
Consent rule (new, please check). The party who did not author a commitment initiates its fulfillment, and the author countersigns. Writing the commitment is the author's consent, initiating is the other party's. A commitment naming an agent who never wrote it can no longer collect that agent's signature.
Intent
Tibi's branch forked from
devat7faf650and several of its commits are protocol-general rather than pool-specific (his own split, shared with Soushi on 2026-11-10). Landing them now keeps the two lines from drifting apart, and gives the v0.1 UI work theMeasureshape and commitment reads it will build on.Changes
Measure(dcbc019, 0fc0ab3):nondominium_shared::types::Measure { numerical_value, has_unit }with onevalidate(), replacingquantity: f64plusunit: Stringon commitments, economic events and economic resources; the TypeScript mirror inpackages/shared-typesand the NDO forms (commitment with an explicit receiver, economic event) follow.NdoToCommitmentslink type, written bypropose_commitment, read byget_commitments_for_ndo.CommitmentRecord { action_hash, commitment }fromget_commitments_for_ndo_detailedandget_all_commitments_detailed, plus its TS type. The admit, fulfill and pool modals of that commit are not included.fulfillment.rswithfulfill_commitment_closure, which logs the fulfilling event, writes theClaimwith the correctfulfilled_by, and issues both parties' participation receipts, the counterparty countersigning throughcall_remoteon an unrestrictedcountersign_fulfillmentgrant created ininit(the function itself checks the caller is the counterparty). Sweettest coverage included.signed_data_hashlike the counterparty, so both receipts passvalidate_participation_claim_signature;countersign_fulfillmentrebuilds the payload from the commitment, the observed quantity and the event time and signs its own hash; only the non-author initiates; a commitment with aCommitmentToClaimlink is refused on both sides; the commitment form's numeric inputs no longer call.trim()on a number, and a Measure of 0 stays 0 in the event form.InventoryIntent,IdentificationPattern,DigitalLocatorKindand the optional fields onResourceSpecification, validated invalidate_spec_foreshadow, with Sweettests. The UI redesign that rode on that commit (GovernanceTab, ResourcesTab, AgentPubkeyField and others) is left for the v0.1 UI pass.await_consistency_s(20, …); the countersign grant uses the 0.7CapGrant { constraint: GrantConstraint::Unrestricted, capability: Capability::ZomeCall(..) }.Decisions
countersign_fulfillmentwith a cap tokengetHow to test
Follow-ups (non-blocking, from the review)
update_operational_statecall rolls back with the closure when a later step fails (not verified).EconomicResourceupdates and no validation onClaimentries (authorship,fulfilled_by).determine_claim_types_for_actionduplicates the mapping inppr.rs.CommitmentAnchor, which are not ondev.tests/still uses the old quantity shapes.Documentation
CHANGELOG.md(0.1.0, Added, including the network reset: the nondominium DNA hash changes),documentation/IMPLEMENTATION_STATUS.mdanddocumentation/requirements/resources.md(foreshadow fields, from 3156120).Related
commitment-pool-experiment(stays open for the pool MVP)