/** * Dispute types — motebit/dispute@1.0. * * Permissive floor (Apache-2.0): these types define the interoperable format * for dispute resolution in agent-to-agent delegations. Any implementation can * produce and verify dispute artifacts using these types. */ import type { MerkleInclusionProof } from "./retention-policy.js"; /** Dispute lifecycle states. Terminal states (final, expired) are irreversible. */ export type DisputeState = "opened" | "evidence" | "arbitration" | "resolved" | "appealed" | "final" | "expired"; /** Dispute resolution outcome. */ export type DisputeOutcome = "upheld" | "overturned" | "split"; /** Dispute category (§4.2). */ export type DisputeCategory = "quality" | "non_payment" | "receipt_invalid" | "unauthorized" | "other"; /** Fund action resulting from dispute resolution (§7.2). */ export type DisputeFundAction = "release_to_worker" | "refund_to_delegator" | "split"; /** * Request to open a dispute on a completed task. * * Foundation Law (§4.4): * - task_id and allocation_id are required — no economic binding, no dispute * - Filing party must be a direct party to the referenced task * - At least one evidence reference is required at filing time * - A relay must not reject an eligible dispute */ export interface DisputeRequest { /** UUID v7, generated by filing party. */ dispute_id: string; /** Must reference an existing task. */ task_id: string; /** Must reference the task's BudgetAllocation. */ allocation_id: string; /** MotebitId of the filing party. */ filed_by: string; /** MotebitId of the other task party. */ respondent: string; /** Dispute category. */ category: DisputeCategory; /** Human-readable explanation. */ description: string; /** At least one reference to a signed artifact. */ evidence_refs: string[]; /** Unix ms. */ filed_at: number; /** * Cryptosuite discriminator. Always `"motebit-jcs-ed25519-b64-v1"` — * JCS canonicalization, Ed25519 primitive, base64url signature * encoding. Verifiers reject missing or unknown values fail-closed. */ suite: "motebit-jcs-ed25519-b64-v1"; /** Ed25519 over canonical JSON of all fields except signature. */ signature: string; } /** Evidence types that can be submitted in a dispute (§5.1). */ export type DisputeEvidenceType = "execution_receipt" | "credential" | "anchor_proof" | "settlement_proof" | "execution_ledger" | "attestation"; /** * Evidence submitted in a dispute. * * Foundation Law (§5.4): * - Evidence must be cryptographically verifiable * - Both parties must have equal access to the evidence window * - The relay must not tamper with or withhold submitted evidence */ export interface DisputeEvidence { /** Must reference an open dispute. */ dispute_id: string; /** MotebitId of the submitting party. */ submitted_by: string; /** Evidence type. */ evidence_type: DisputeEvidenceType; /** The signed artifact itself. */ evidence_data: Record; /** What this evidence demonstrates. */ description: string; /** Unix ms. */ submitted_at: number; /** * Cryptosuite discriminator. Always `"motebit-jcs-ed25519-b64-v1"` * (see DisputeRequest for the full recipe). */ suite: "motebit-jcs-ed25519-b64-v1"; /** Ed25519 over canonical JSON of all fields except signature. */ signature: string; } /** * Individual vote by a federation peer in federation adjudication (§6.2). * * Foundation Law (§6.5): * - Federation resolution must include individual AdjudicatorVote entries * - Aggregated-only verdicts are rejected * - Each vote signature MUST cover `dispute_id` AND `round` — votes are * not portable across disputes OR adjudication rounds (a malicious * adjudicator collecting old votes from other disputes cannot stuff * them into a new resolution because the dispute_id binding breaks * the signature; a leader cannot replay round-1 vote bytes as round-2 * evidence because the round binding breaks the signature). */ export interface AdjudicatorVote { /** * Dispute this vote applies to. Signature-bound: the canonical body * includes this field, so a vote signed for dispute A is rejected * on submission to dispute B (the relay/aggregator reconstructs the * canonical bytes against the target dispute_id and the signature * fails to verify against the wrong binding). */ dispute_id: string; /** * Adjudication round. 1 for original adjudication; 2 for §8.3 appeal. * Signature-bound (§6.5): a peer's round-1 vote bytes do not satisfy * round-2 binding even for the same evidence. The §8.3 round-isolation * property is enforced cryptographically, not by leader bookkeeping. */ round: number; /** Federation peer MotebitId. */ peer_id: string; /** Vote outcome. */ vote: DisputeOutcome; /** Per-peer explanation. */ rationale: string; /** * Cryptosuite discriminator. Always `"motebit-jcs-ed25519-b64-v1"` * (see DisputeRequest for the full recipe). */ suite: "motebit-jcs-ed25519-b64-v1"; /** Ed25519 by the voting peer over canonical JSON of all fields except signature. */ signature: string; } /** * Federation vote request — leader-to-peer fan-out body for §6.2 * federation adjudication. The leader (the relay where the dispute * resolution was requested AND named in the dispute as filer or * respondent) POSTs this to each active federation peer; each peer * returns a signed `AdjudicatorVote`. * * Wire-format protocol type for `relay-federation@1.2` §16. The * peer-side gate ladder (`spec/relay-federation-v1.md` §16.2) enforces: * schema → known peer → requester-id binding → signature → freshness * → operator policy configured. * * Foundation Law (`spec/dispute-v1.md` §6.5): * - Signature MUST cover `dispute_id`, `round`, `requester_id`, and the * evidence bundle. Cross-round replay and request-tampering both * fail-closed. * - For round=2 (appeal), `evidence_bundle` MUST carry the original * round-1 evidence plus any new evidence introduced with the appeal * (per §8.4). */ export interface VoteRequest { /** The dispute being adjudicated. MUST equal the URL `:disputeId` parameter. */ dispute_id: string; /** * Adjudication round. 1 for original adjudication; 2 for §8.3 appeal. * Signature-bound — cross-round vote replay is cryptographically * rejected. */ round: number; /** Original signed dispute artifact (§4.2). The peer can re-verify the dispute's provenance from this alone. */ dispute_request: DisputeRequest; /** * All evidence collected during the dispute's evidence window (§5.2). * For round=2, MUST carry the original round-1 evidence plus any new * evidence introduced with the appeal. */ evidence_bundle: DisputeEvidence[]; /** Leader relay's `motebit_id`. MUST be a known peer to the receiver (gate 2). */ requester_id: string; /** Unix ms when the leader signed. Used by gate 5 freshness check (default ±60s). */ requested_at: number; /** * Cryptosuite discriminator. Always `"motebit-jcs-ed25519-b64-v1"` * (see DisputeRequest for the full recipe). */ suite: "motebit-jcs-ed25519-b64-v1"; /** Base64url Ed25519 by the leader over `canonicalJson(body minus signature)`. */ signature: string; } /** * Dispute resolution by adjudicator. * * Foundation Law (§6.5): * - Resolution must include a signed rationale * - A relay must not self-adjudicate when it is the defendant */ export interface DisputeResolution { /** Must reference the dispute. */ dispute_id: string; /** Resolution outcome. */ resolution: DisputeOutcome; /** Signed explanation of the decision. */ rationale: string; /** How funds are distributed. */ fund_action: DisputeFundAction; /** [0, 1], worker's portion. 1.0 = all to worker. */ split_ratio: number; /** MotebitId or relay ID of the adjudicating entity. */ adjudicator: string; /** For federation — empty for single-relay. */ adjudicator_votes: AdjudicatorVote[]; /** Unix ms. */ resolved_at: number; /** * Cryptosuite discriminator. Always `"motebit-jcs-ed25519-b64-v1"` * (see DisputeRequest for the full recipe). */ suite: "motebit-jcs-ed25519-b64-v1"; /** Ed25519 over canonical JSON of all fields except signature. */ signature: string; } /** * Appeal filed against a dispute resolution. * * Foundation Law (§8.4): * - One appeal per dispute — final state after appeal is terminal * - New evidence may be submitted with the appeal */ export interface DisputeAppeal { /** Must reference a resolved dispute. */ dispute_id: string; /** MotebitId of the appealing party. */ appealed_by: string; /** Why the resolution is incorrect. */ reason: string; /** Optional: new evidence references. */ additional_evidence?: string[]; /** Unix ms. */ appealed_at: number; /** * Cryptosuite discriminator. Always `"motebit-jcs-ed25519-b64-v1"` * (see DisputeRequest for the full recipe). */ suite: "motebit-jcs-ed25519-b64-v1"; /** Ed25519 over canonical JSON of all fields except signature. */ signature: string; } /** * Evidence shape #1: disputant proves their peer pubkey is committed * in the cert's `federation_graph_anchor.merkle_root` via an inclusion * proof, but `witnessed_by[]` does not include them. * * Verifier in `@motebit/crypto` recomputes the proof against the cert's * anchor root and asserts the leaf hash matches the canonical * leaf-of-disputant-pubkey encoding (same hashing recipe as * `relay-federation-v1.md` §7.6 / `credential-anchor-v1.md` §3). */ export interface WitnessOmissionInclusionProofEvidence { kind: "inclusion_proof"; /** * Hex-encoded SHA-256 leaf hash for the disputant's federation pubkey * under the anchor's canonicalization (lowercase hex pubkey bytes). */ leaf_hash: string; /** Inclusion proof against `cert.federation_graph_anchor.merkle_root`. */ proof: MerkleInclusionProof; } /** * Evidence shape #2: disputant claims a peering relationship at * `cert.horizon_ts` outside the cert's published anchor — i.e., the * issuer published an incomplete or wrong anchor that omitted a peer * who was peered with them at the horizon. * * The disputant supplies a signed peering artifact issued by the cert's * issuer (e.g., a relay-federation PeeringConfirm or Heartbeat) whose * timestamp window covers `cert.horizon_ts`. The verifier in * `@motebit/crypto` asserts the embedded signature validates against * the cert issuer's pubkey and the artifact's window covers * `cert.horizon_ts`. Wire format of `peering_artifact` is opaque at this * layer; verification dispatches on the artifact's own kind/spec. */ export interface WitnessOmissionAlternativePeeringEvidence { kind: "alternative_peering"; /** * Signed peering artifact from the cert issuer — embeds its own * signature. Carries enough fields for the verifier to re-check * the issuer's signature and the peering window. */ peering_artifact: Record; } /** Discriminated evidence union — exactly one shape per dispute. */ export type WitnessOmissionEvidence = WitnessOmissionInclusionProofEvidence | WitnessOmissionAlternativePeeringEvidence; /** * Witness-omission dispute — files within 24h of `cert.issued_at` * (`WITNESS_OMISSION_DISPUTE_WINDOW_MS` in `@motebit/crypto`) by a peer * claiming the disputed cert's `witnessed_by[]` wrongly omits them. * * Foundation Law (Phase 4b-3 §4.4): * - `cert_issuer` + `cert_signature` together pin the disputed cert — * the relay reconciles the dispute against the cert in its local * `relay_horizon_certs` table at validation time. * - At least one evidence shape is required at filing time — either * `inclusion_proof` (membership in the published anchor) or * `alternative_peering` (peering attested outside the anchor). * - The cert's `issued_at` is the lookup-derived clock for the 24h * window — disputant-attested timestamps cannot widen the window. * - Sustained disputes are reputation signals; the cert remains * terminal (retention-policy.md decision 5). */ export interface WitnessOmissionDispute { /** UUID v7, generated by the disputant. */ dispute_id: string; /** MotebitId / operator-id of the cert issuer — the relay that signed the disputed horizon cert. */ cert_issuer: string; /** * Hex-encoded signature of the disputed `append_only_horizon` cert. * Opaque pointer; the relay resolves the cert from its local * `relay_horizon_certs` table. */ cert_signature: string; /** MotebitId of the disputant peer claiming wrongful omission. */ disputant_motebit_id: string; /** Exactly one of the two evidence shapes. */ evidence: WitnessOmissionEvidence; /** Unix ms. */ filed_at: number; /** * Cryptosuite discriminator. Always `"motebit-jcs-ed25519-b64-v1"` * (see DisputeRequest for the full recipe). */ suite: "motebit-jcs-ed25519-b64-v1"; /** Ed25519 by disputant over canonical JSON of all fields except signature. */ signature: string; } //# sourceMappingURL=dispute.d.ts.map