dev.cocore.compute.dispute
{
"$type": "com.atproto.lexicon.schema",
"defs": {
"disputeOutcome": {
"description": "Exchange's verdict and any side-effects. The compensating refund (if any) is published as its own dev.cocore.compute.settlement with status=refunded and refundOf pointing at the original; this object strong-refs that record so verifiers don't need to scan.",
"properties": {
"decidedAt": {
"format": "datetime",
"type": "string"
},
"rationale": {
"description": "Exchange's plain-English explanation. Public; bind it carefully — this is the audit trail when the same parties dispute future charges.",
"maxLength": 2048,
"type": "string"
},
"refundSettlement": {
"description": "When verdict is refund-*, strong-ref to the dev.cocore.compute.settlement record (status=refunded) the exchange published as the compensating action. Required when the verdict involves a refund.",
"ref": "com.atproto.repo.strongRef",
"type": "ref"
},
"verdict": {
"description": "What happened. `refund-full` and `refund-partial` reverse value to the requester; `uphold-charge` keeps the original settlement intact; `forfeit-payout` keeps the requester's funds with the exchange but withholds the provider payout.",
"knownValues": [
"refund-full",
"refund-partial",
"uphold-charge",
"forfeit-payout"
],
"type": "string"
}
},
"required": [
"verdict",
"decidedAt"
],
"type": "object"
},
"disputeReason": {
"description": "Bucketed reason plus free-form detail. Buckets exist so the AppView can index disputes; detail is for the operator's own audit.",
"properties": {
"category": {
"description": "Bucket the dispute fits into. `processor-chargeback` is reserved for cases where the card network fired the chargeback ahead of any direct complaint.",
"knownValues": [
"fraud",
"non-delivery",
"quality-failure",
"processor-chargeback",
"duplicate-charge",
"other"
],
"type": "string"
},
"detail": {
"description": "Operator-supplied free-form detail. Public; do not include personally identifying information.",
"maxLength": 2048,
"type": "string"
}
},
"required": [
"category"
],
"type": "object"
},
"main": {
"key": "tid",
"record": {
"properties": {
"createdAt": {
"format": "datetime",
"type": "string"
},
"evidenceCid": {
"description": "Optional CID of the encrypted evidence bundle the exchange relied on (request/response logs, customer correspondence, processor chargeback metadata). Encrypted to the exchange + parties; opaque to public verifiers.",
"format": "cid",
"type": "string"
},
"exchange": {
"description": "Exchange DID. MUST equal the repo this record is published in. Adjudication is the exchange's prerogative; only the exchange that signed the settlement may sign its dispute.",
"format": "did",
"type": "string"
},
"outcome": {
"description": "Required when status=resolved. Captures the verdict and any compensating settlement record.",
"ref": "#disputeOutcome",
"type": "ref"
},
"raisedAt": {
"description": "When the complaint was first received. May predate `createdAt` (this record is published when the exchange opens or resolves the case, which can be after intake).",
"format": "datetime",
"type": "string"
},
"raisedBy": {
"description": "DID of the party who raised the complaint. Typically the requester (charge dispute) or the provider (non-payment claim). The exchange itself MAY raise a dispute when it detects a problem (e.g. processor chargeback fired before the requester reached out).",
"format": "did",
"type": "string"
},
"reason": {
"description": "Why the dispute was raised. Free-form rationale plus an enum bucket for matchmaking / analytics.",
"ref": "#disputeReason",
"type": "ref"
},
"settlement": {
"description": "Strong-ref to the dev.cocore.compute.settlement under dispute. Verifiers MUST resolve this to confirm both sides reference the same charge.",
"ref": "com.atproto.repo.strongRef",
"type": "ref"
},
"sig": {
"description": "ES256 signature (base64url, no padding) over the canonical JSON of every other field. Verified against the same verificationMethod that signs settlements for this exchange. Required for trust-tier=hardware-attested exchanges; optional in v0.3.x as we roll out signing across all records.",
"maxLength": 256,
"type": "string"
},
"status": {
"description": "Lifecycle state. The exchange opens the dispute (`open`) when intake is complete; once adjudicated, the same record is updated in place to `resolved` with outcome populated. Records at this NSID with status=open and no `outcome` are valid by construction; status=resolved without `outcome` is invalid.",
"knownValues": [
"open",
"resolved"
],
"type": "string"
}
},
"required": [
"settlement",
"exchange",
"raisedBy",
"raisedAt",
"reason",
"status",
"createdAt"
],
"type": "object"
},
"type": "record"
}
},
"description": "An exchange-signed adjudication of a complaint about a settled receipt. Published in the exchange's repo. The exchange's DID is the only DID permitted to publish a record at this NSID for a given settlement; any record at this NSID outside the exchange's repo is invalid by construction. The dispute lifecycle is open->resolved (terminal); resolution carries the outcome the exchange has already enacted (e.g. a refund settlement) and a signed rationale. Verifiers reading a settlement see status=disputed when an open dispute exists, and a paired settlement of status=refunded with `refundOf` pointing at the original when the outcome warranted a refund.",
"id": "dev.cocore.compute.dispute",
"lexicon": 1
}
Metadata
- DID
-
did:plc:5quuhkmwe2q4k3azfsgg7kdz - CID
-
bafyreieqdbe3p3pzrl3b7kfqxp2r3r47vdy35vq6f5l5s4qmhzmozxub7a - Indexed At
- 2026-06-17 21:16 UTC
- AT-URI
-
at://did:plc:5quuhkmwe2q4k3azfsgg7kdz/com.atproto.lexicon.schema/dev.cocore.compute.dispute
Similar Lexicons
Lexicons whose schemas describe something close to this one. Check them before publishing a new one that overlaps.
-
An exchange's signed proof of payment for a receipt. Published by the exchange in its own repo. Strong-refs both the receipt being settled and the requester's payment authorization, so the full chain is independently ve…
-
app.matakite.dispute record
A public counter-attestation against a resolution. With no bonds available (no money), the deterrent is reputational: disputes are signed records attached to the disputer's DID, so frivolous disputes cost the disputer. …
-
A user-submitted dispute flag against a trade listing, mirrored to AT Protocol as a real org.swappulse.tradeDispute record. Filed when a collector has an issue with cards received. Moderators review and resolve.
-
A contested claim about a 287(g) agreement record. Written into the DISPUTING PARTY'S OWN repository, not the publisher's, and referencing the disputed record by AT-URI and CID. Anyone may publish one: the agreement's p…