# description
Support-resolution attestation envelope — the cs-side architectural twin of ip.review.attestation.v1 (cycle 316). Same architecture as the R16 P2 ip-merge-gate killer feature: a SECOND agent (or panel) verifies whether the FIRST agent's customer-support resolution was correct, complete, and policy-compliant. cs_agent_judging_cs_agent = same structural argument as code_review_agent_judging_code_review_agent — the agent that emitted the resolution cannot also be the agent that attests to its correctness. THIRTEENTH JSON Schema in IntelligencePro's catalog. Closes SYNTHESIS-acquisition Round 18 P3 [[ai-customer-support-platforms]] CS1 ship-first action — ip/support-attest@v1, the first cryptographic peer-attestation substrate for AI customer support. Same impossibility argument as ip.review: Intercom Fin (reported high resolution rates, contested), Zendesk Answer Bot / Resolution Bot (Zendesk acquired Klaus for CX QA), Ada (CX automation), Forethought, Cognigy, Decagon (raised $131M Mar-2026 + Snowflake partnership), Sierra AI ($4.5B val Bret Taylor), Salesforce Service Cloud Einstein Copilot / Agentforce (1.0 GA Q4-2024, 2.0 Q1-2025), ServiceNow Now Assist for CSM, HubSpot Breeze, Glean Agents for support, Microsoft Copilot Studio for service, Aircall AI cannot ship self-attestation — THEY ARE THE AGENTS BEING VERIFIED. IntelligencePro's detached peer attestation = the only architecture that delivers it. Anchors the high-profile Intercom Fin '99% resolution' contestation pattern (publicly disputed by Klaus / Zendesk Quality Assurance teams; the metric was self-reported with no independent verification — exactly the gap a peer-attestation substrate closes). Composes UPSTREAM with ip.retrieval.citation.attestation.v1 (R20 Q1, planned) via citedEvidenceShaArray[] — a CS QA attestation can cite WHICH knowledge-base article a resolution drew on. Composes DOWNSTREAM with ip.governance.compliance.v1 (cycle 315) via evidenceShaArray[] — a SOC 2 CC7.1 / GDPR Art. 22 (automated decision-making) / EU AI Act Art. 50 (transparency) control cites support-resolution attestations as evidence of QA practice.

# $comment
Discovery: https://ip.tekton.cc/.well-known/ip-knowledge.json (full descriptor) | Badge: https://ip.tekton.cc/api/badge/v1/attestation/support.resolution.attestation.v1/<subjectSha256> (shields.io endpoint) | Free dry-run: POST https://ip.tekton.cc/api/credentials/dry-run with body {kind:"support.resolution.attestation.v1", body:<candidate>} (no auth required, validates against this schema) | Verification recipe: https://ip.tekton.cc/docs/verification-recipe.md (3-layer trust model + curl trail) | Revocation: https://ip.tekton.cc/credentials/status/v1 (W3C BitstringStatusList v1.0; check bit at credentialStatus.statusListIndex)

# properties.schemaVersion.description
Semver of this schema. Bumps to 2.0.0 land at /credentials/support-resolution/v2 — v1 stays immutable (see /docs/schema-versioning.md for the cycle-726 canonical bump-mechanics + soft-change-detection contract).

# properties.resolutionId.description
Unique RFC 4122 UUID v4 or v7 — this support-resolution attestation's canonical identifier. Distinct from conversationId (which is the support-platform's external ticket/conversation ID) because the same conversation may have multiple resolution attestations (initial AI-resolved → re-opened by customer → human-escalated → final-resolved). Links to ip.attestation.event.v1 wire row via ipAttestationEventId.

# properties.supportAgentId.description
Stable handle for the AI support agent whose resolution is being attested. Examples: 'intercom-fin-v3', 'zendesk-answer-bot', 'zendesk-resolution-bot', 'ada-cx-v2', 'forethought-solve', 'cognigy-ai', 'decagon-agent', 'sierra-cx-agent', 'salesforce-agentforce-2-service', 'servicenow-now-assist-csm', 'hubspot-breeze-service', 'glean-support-agent', 'copilot-studio-service', 'aircall-ai', 'kustomer-iq'. Lowercase + hyphen + digit + dot so the value doubles as a URL slug + docker-tag fragment. Community owns its own supportAgentId namespace.

# properties.supportAgentVersionSha256.description
Optional sha256 of the canonical support-agent-release artifact at runtime. For SaaS agents: vendor-published version manifest sha. For self-hosted: sha256 of the deployed wheel/package/container. Pins WHICH BUILD of the support agent generated the resolution. Defeats the silent-prompt-update class of post-hoc behavior changes.

# properties.resolutionKind.description
Classification of the support surface. 'billing' = invoice/payment dispute. 'shipping' = order-status/delivery. 'technical-support' = product malfunction. 'refund-request' = chargeback/refund. 'compliance-request' = GDPR DSAR / CCPA-opt-out / data-deletion. 'abuse-report' = safety/policy violation. Different kinds carry different evidentiary weight + regulatory exposure (refund-request feeds chargeback dispute; compliance-request feeds GDPR Art. 22 audit). Routes downstream verifiers.

# properties.conversationId.description
External identifier of the conversation/ticket. Platform-conventional format. For Zendesk: 'zendesk.com/<subdomain>/agent/tickets/<id>'. For Intercom: 'intercom.com/a/inbox/<workspaceId>/conversation/<id>'. For Salesforce: 'salesforce.com/<orgId>/case/<caseNumber>'. For ServiceNow: 'servicenow.com/<instance>/incident/<sysId>'. For Decagon / Sierra / Ada: vendor-conventional. Lets a downstream auditor jump from attestation → platform-native record.

# properties.conversationTranscriptSha256.description
Sha256 of the canonical bytes of the conversation transcript at resolution time. Required because conversation contents are mutable — a customer adding a new message after the AI marked the case 'resolved' must invalidate the attestation. Canonical form: JCS-encoded chronological array of {speaker, role, timestamp, contentSha256}. ContentSha256 anchors each individual message; transcript-level sha anchors the conversation shape.

# properties.resolutionVerdict.description
The bottom-line resolution decision. 'resolved' = customer's issue addressed, no further action needed (the metric Intercom Fin reports as '99%' — now cryptographically attestable). 'partially-resolved' = some progress, customer expected to follow up. 'deflected' = answered a FAQ without ticket creation. 'escalated-to-human' = AI handed off to a human agent. 'refund-issued' / 'refund-rejected' = explicit monetary action (feeds chargeback evidence). 'policy-action-taken' = ban / suspension / restriction (feeds Trust & Safety audit). 'abandoned-by-user' = customer never returned. 'failed-resolution' = AI explicitly admits it cannot resolve. 'abstain' = attestation panel ran but declines to score. LOAD-BEARING for a downstream auto-close action analogous to ip-merge-gate.

# properties.scores.properties.customerSatisfaction.description
Post-resolution CSAT (0..1). Derived from customer survey response if available; otherwise inferred from sentiment of the customer's last message.

# properties.scores.properties.policyCompliance.description
Whether the resolution followed company policy (refund rules, escalation thresholds, data-handling). 1.0 = no policy violations detected. Feeds SOC 2 CC7.1 + GDPR Art. 22 audits.

# properties.scores.properties.resolutionAccuracy.description
Whether the AI's resolution actually addressed the customer's stated issue. 1.0 = the customer's question/problem was fully answered/fixed. The Klaus/Zendesk QA dimension that's been publicly cited in the Intercom Fin contestation.

# properties.scores.properties.firstContactResolution.description
FCR rate dimension — was this issue closed without re-opening or follow-up? 1.0 = resolved on first contact; 0.0 = customer re-opened or escalated.

# properties.scores.properties.hallucinationRisk.description
Estimated probability the AI's response contained factual hallucination not grounded in citedEvidenceShaArray. 0.0 = fully grounded; 1.0 = response is fabricated. High hallucinationRisk on a refund-issued or policy-action-taken verdict is a critical audit signal.

# properties.scores.properties.composite.description
Weighted composite of sub-scores. Attester-defined weights.

# properties.scores.description
Optional per-dimension scores. Downstream auto-close config may consume specific dimensions (e.g., 'do NOT auto-close if hallucinationRisk > 0.3 even when overall composite is high').

# properties.rationaleSha256.description
Sha256 of the canonical attester-rationale text. The rationale TEXT itself lives in a private QA-tool surface (Klaus, Zendesk QA, MaestroQA, Loris) or in the attester's logging surface — this field binds WHICH rationale was emitted. Lets a downstream auditor cross-check that the QA-surface comment matches the signed attestation.

# properties.citedEvidenceShaArray.items.properties.sha256.description
Sha256 of the cited evidence artifact's canonical bytes.

# properties.citedEvidenceShaArray.items.properties.scope.description
Optional scope description (e.g., 'KB article the agent cited for the refund-policy explanation', 'policy version in force at resolvedAt').

# properties.citedEvidenceShaArray.description
Array of cited evidence artifacts the support agent consulted while resolving — KB articles, policy snapshots, retrieval citations, eval results, legal citations (for compliance-requests). Lets a downstream verifier (QA lead, compliance auditor, chargeback adjudicator) walk the evidence chain backward. The KEY anti-hallucination signal: a resolution with rationale-text claiming a refund policy but with EMPTY citedEvidenceShaArray cannot prove the claimed policy actually exists.

# properties.resolvedAt.description
Epoch milliseconds when the AI emitted the resolution verdict. Required because conversation state evolves — a 'resolved' verdict at message-index N may not apply after message-index N+1.

# properties.attesterDid.description
DID of the attester entity (the SECOND agent or panel evaluating the FIRST agent's resolution). did:web for institutional QA agent (did:web:klaus.app, did:web:zendesk.com/qa, did:web:maestroqa.com, did:web:loris.ai); did:key for individual / OSS-self-hosted QA. LOAD-BEARING: gate config pins which attesterDids count as authoritative. NOTE: attesterDid SHOULD NOT equal the supportAgentId-resolved DID — that would defeat the peer-attestation property. Producers MUST enforce this separation.

# properties.autoCloseAsserted.description
True when this attestation is being submitted as evidence for an auto-close action (analog to ip-merge-gate: close the ticket without further human review). When true, downstream consumers (the auto-close pipeline) treat resolutionVerdict + scores as gating signals. When false, this is an informational attestation only (e.g., posted to a QA-review surface but not connected to an auto-close).

# properties.humanReviewerDid.description
Optional DID of a human co-signer (typically a CS lead or shift supervisor) who endorsed the AI's resolution. Auto-close config may require BOTH attesterDid + humanReviewerDid for high-risk resolutions (refund > $X, policy-action-taken, compliance-request).

# properties.supersedes.description
Optional resolutionId of a prior attestation this supersedes. When a re-opened ticket gets re-resolved, the new attestation supersedes the old.

# properties.judgesDigest.description
When this attestation results from a multi-attester QA panel (3+ independent QA agents per CP's standard peer-review economy), the canonical digest of the judges manifest.

# properties.policySnapshotSha256.description
Optional sha256 of the canonical bytes of the company refund/escalation/data-handling policy in force at resolvedAt. Pins WHICH POLICY was the resolution's reference. Defeats the silent-policy-update class of post-hoc audit gaps — if the policy was updated between the resolution and the audit, this anchor proves which version the resolution was scored against.

# properties.regulatoryContext.properties.gdprArticle22Applicable.description
True when the resolution involves an automated decision producing legal effects or similarly significant effects per GDPR Article 22(1) (e.g., automated refund-rejection, automated account suspension). Triggers downstream right-to-human-review requirements.

# properties.regulatoryContext.properties.euAiActArticle50Applicable.description
True when the resolution involves an interaction the EU AI Act Article 50(1) requires be disclosed as AI-generated (active 2026-08-02; €15M / 3% global turnover). Triggers downstream transparency-disclosure requirements.

# properties.regulatoryContext.properties.ftcEndorsementGuidesApplicable.description
True when the AI made a product/service recommendation the FTC Endorsement Guides (revised 2023; AI applies) require be disclosed.

# properties.regulatoryContext.description
Regulatory-context flags. Lets a downstream auditor filter the attestation stream by regulatory regime. Optional but strongly recommended for resolutionKind in {refund-request, cancellation, complaint, compliance-request, account-update, policy-action-taken}.

# properties.ipAttestationEventId.description
When this attestation was emitted as a ip.attestation.event.v1 row (R11 T1) to the platform's pipeline, the eventId of that wire row.

# properties.signature.description
Ed25519 signature (128 hex = 64 raw bytes) over the canonical-JSON bytes of (resolutionId ⊕ supportAgentId ⊕ supportAgentVersionSha256? ⊕ resolutionKind? ⊕ conversationId ⊕ conversationTranscriptSha256 ⊕ resolutionVerdict ⊕ scores? ⊕ rationaleSha256? ⊕ citedEvidenceShaArray? ⊕ resolvedAt ⊕ attesterDid ⊕ autoCloseAsserted? ⊕ humanReviewerDid? ⊕ supersedes? ⊕ judgesDigest? ⊕ policySnapshotSha256? ⊕ regulatoryContext? ⊕ ipAttestationEventId?). Verify against the publicKey published in the attesterDid's JWKS. RFC 8037 + JCS (RFC 8785). ⚠ INTEGRITY GAP (aa-824-P0-1, cycle 848 honest disclosure): `chain.*` and `extra` are presently OUTSIDE this signature pre-image. A wire-path or post-hoc rewrite of `chain.parentSha256` / `chain.parentKind` / `chain.parentAttestationId` does NOT invalidate this `signature`. Offline verifiers using `signature`+`publicKey` (the documented embedded-verification path) MUST treat `chain.*` as ADVISORY pointer-shape, NOT cryptographically bound to this attestation. For full-integrity verification including chain pointers, fetch the W3C DataIntegrityProof envelope from /credentials/<sha>/v1 and verify against the proof.cryptosuite=eddsa-jcs-2022 signature (which signs the FULL canonical-JSON body including chain). Cycle-484 added the chain block; cycles 778-784 swept it; the signature pre-image was not re-derived. Migration target: v2 schema slug ($id pin per cycle-462). See cycles 825-829 (5/5 wedge-tier ring) + cycle 830 (verification-recipe.md dual-path teaching) for the canonical write-up; cycle 848 fans this disclosure to the 12 remaining chain-bearing leaf schemas in one batch.

# properties.publicKey.description
Ed25519 public key (32 raw bytes = 64 hex) corresponding to the signature.

# properties.extra.description
Open extension slot — platform-specific payload (Klaus QA scorecard categories, Zendesk QA dimensions, MaestroQA tags). Consumers MUST ignore unknown keys.

# properties.affectsIdentifiableIndividual.description
Cycle 538 (regulatory-compliance RC-480-F9 fan-out): support-resolution attestations almost always cover an identifiable customer — flag exists for completeness AND for the rare case where the resolution attests to a non-individual interaction (status check, vendor account, anonymized ticket). When true (the typical case), GDPR Article 22 + EU AI Act Article 50 attach: the customer MUST be able to appeal the AI-driven resolution, find a human reviewer, and lodge a complaint. Defaults to absent (treated as false for back-compat with pre-cycle-538 records); operators SHOULD set this to true on customer-facing resolutions.

# properties.dataSubjectSafeguards.description
Cycle 538 (RC-480-F9 fan-out): same-shape mirror of ip.governance.compliance.v1 (cycle 390) + ip.synthetic.media.attestation.v1 (cycle 487). Required when affectsIdentifiableIndividual=true. The audit observed support-resolution as one of the four schema kinds whose subjects can be identifiable individuals; cycle 538 closes that residual.

# properties.dataSubjectSafeguards.properties.appealUrl.description
HTTPS URL where the customer submits an appeal of the AI-driven resolution. GDPR Art 22(3).

# properties.dataSubjectSafeguards.properties.humanReviewerDid.description
DID of the human reviewer (or team). did:web for institutional teams. Distinct from humanReviewerDid on the resolution attestation itself (which is the original reviewer); this is the APPEAL reviewer — typically a different team to avoid conflict of interest.

# properties.dataSubjectSafeguards.properties.complaintIntakeUrl.description
HTTPS URL for filing a complaint about the support-resolution policy itself. GDPR Art 77.

# properties.dataSubjectSafeguards.properties.automatedDecisionScope.description
Honest classification of how the AI-driven resolution affects the customer. 'fully-automated' = no human in the loop (highest GDPR scrutiny); 'decision-with-human-review' = customer-service rep approved before close.

# properties.dataSubjectSafeguards.properties.retentionPeriodDays.description
How long the operator retains the resolution transcript + provenance. GDPR Art 5(1)(e).

# properties.chain.properties.parentSha256.description
Sha256 of the canonical-JSON bytes of the parent attestation. For a support.resolution.attestation typical parents reflect the upstream evidence chain: ip.retrieval.citation.attestation.v1 (the KB article the CS agent's resolution drew on — the dominant path; the schema description already names citedEvidenceShaArray[] composing UPSTREAM with retrieval-citation), OR ip.experiment.receipt.v1 (the LLM checkpoint that produced the candidate resolution). ⚠ Cycle 493 honest-disclosure: the platform does NOT verify parent-existence at issuance. Consumers walking the chain MUST resolve parentSha256 against their own attestation registry; see /docs/verification-recipe.md.

# properties.chain.properties.parentKind.description
Kind identifier of the parent attestation. support.resolution typically points at retrieval-citation (the KB-article anchoring the resolution — dominant for Intercom Fin / Zendesk Answer Bot / Decagon / Sierra workflows that resolve customer questions by citing internal documentation) or experiment-receipt (the LLM checkpoint that drafted the resolution).

# properties.chain.properties.parentAttestationId.description
Optional UUID of the parent attestation — convenience for consumers that index by id rather than by sha256.

# properties.chain.description
Cycle 781 (sc-772-P0-1 partial close, continuing the cycle 778-780 sweep): uniform upward chain link per the cycle-484 substrate. ip.support.resolution.attestation.v1 is the cycle-769 ip-support-attested killer-feature anchor at /docs/wedge.md L77. Pre-cycle-781 a verifier could read the signed resolution but had no way to mechanically prove the cited KB article had its own provenance attestation. Block is OPTIONAL (not in required[]) so back-compat preserved.

# allOf[].$comment
Cycle 538 (RC-480-F9 fan-out): when affectsIdentifiableIndividual=true (the typical customer-facing case) GDPR Art 22 + EU AI Act Art 50 attach. dataSubjectSafeguards becomes REQUIRED. Back-compat: pre-cycle-538 records (no flag) continue to validate.