{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://aidid.im/schemas/delegation/delegation-error.schema.json",
  "title": "AIDID Delegation Failure",
  "description": "The fail-closed failure body produced by the delegation layer. It is the `{ ok: false, ... }` branch of the RP-side `verifyDelegation` result and of the `evaluateDelegation` / `parseDelegationPayload` decision helpers (`packages/aidid-login-sdk/src/delegation.js`). Every rejection yields this shape with a stable `DELEGATION_ERROR_CODES` value — never a silent success. This is an in-process result contract, not an HTTP contract: an RP picks its own status code and transport.",
  "type": "object",
  "additionalProperties": false,
  "required": ["ok", "error", "message"],
  "properties": {
    "ok": {
      "const": false,
      "description": "Always `false` for a failure."
    },
    "error": {
      "enum": [
        "delegation_invalid_payload",
        "delegation_not_found",
        "delegation_revoked",
        "delegation_deactivated",
        "delegation_expired",
        "delegation_scope_denied",
        "delegation_sub_did_mismatch",
        "delegation_parent_did_mismatch",
        "delegation_not_authorized",
        "delegation_signature_required",
        "delegation_signature_invalid",
        "delegation_parent_key_unavailable",
        "delegation_agent_not_bound",
        "delegation_own_key_not_accepted",
        "delegation_agent_key_mismatch",
        "delegation_agent_key_unverified"
      ],
      "description": "Stable machine-readable rejection code (SPEC-DELEGATION-v1 §3.3 + §9.1). Every code means 'deny'; a verifier must not downgrade any of them to an allow."
    },
    "message": {
      "type": "string",
      "description": "Human-readable diagnostic. NOT stable — never branch on it; branch on `error`."
    }
  },
  "examples": [
    {
      "ok": false,
      "error": "delegation_revoked",
      "message": "delegation for did:msg:Q3kR2sVn0pLxWmYtZbA1c was revoked at 2026-10-11T09:00:00.000Z"
    },
    {
      "ok": false,
      "error": "delegation_signature_required",
      "message": "provide either the on-chain sub-DID document (authoritative) or the parent signature over the canonical delegation text"
    }
  ],
  "x-aidid": {
    "spec": {
      "doc": "AIDID_母子DID与授权规范_v1.md",
      "section": "§3.3",
      "version": "v1.14"
    },
    "status": "implemented",
    "source": [
      "frontend/packages/aidid-login-sdk/src/delegation.js#DELEGATION_ERROR_CODES",
      "frontend/packages/aidid-login-sdk/src/delegation.js#verifyDelegation",
      "frontend/packages/aidid-login-sdk/src/delegation.js#evaluateDelegation",
      "frontend/lib/subDid.ts#parseDelegationPayload"
    ],
    "enumBindings": [
      {
        "pointer": "/properties/error/enum",
        "source": "DELEGATION_ERROR_CODES"
      }
    ],
    "note": "Two classes of code share this shape. 判定类 (decision, produced by `evaluateDelegation`/`parseDelegationPayload`, SPEC §3.3): `delegation_invalid_payload`, `delegation_not_found`, `delegation_revoked`, `delegation_deactivated`, `delegation_expired`, `delegation_scope_denied`. 验证类 (RP \"one-click verify\", produced by `verifyDelegation`, SPEC §9.1): `delegation_sub_did_mismatch`, `delegation_parent_did_mismatch`, `delegation_not_authorized`, `delegation_signature_required`, `delegation_signature_invalid`, `delegation_parent_key_unavailable`, `delegation_agent_not_bound`, `delegation_own_key_not_accepted`, `delegation_agent_key_mismatch`, `delegation_agent_key_unverified`. Trust for a delegation must come from ONE of two sources — the on-chain sub-DID document (authoritative in stage A) OR the parent DID's signature over the canonical delegation text; when NEITHER is provided the result is `delegation_signature_required` (fail-closed). `verifyDelegation` never throws: an internal exception is mapped to `delegation_invalid_payload`. own-key 验证类的 3 个码：`delegation_own_key_not_accepted`（`keyMode='own-key'` 而调用方未显式 `allowOwnKey=true`，默认 fail-closed）、`delegation_agent_key_mismatch`（实际验签公钥 ≠ 母 DID 绑定的 Agent 公钥）、`delegation_agent_key_unverified`（既无 `signerPublicKeyMultibase` 也无法从文档确定 Agent 公钥）。",
    "honestLimit": "These codes describe why the authorization layer denied; they do not cover the S1 sign-in layer's own errors (see the login schemas). Nothing counts or enforces `scope.maxUsesPerDay`: quota exhaustion is intentionally NOT a delegation error code — an RP that enforces a quota must invent its own signal."
  }
}
