{
  "openapi": "3.1.0",
  "info": {
    "title": "Thetanuts Wallet Vault API",
    "version": "1.0.0",
    "description": "Exact registered HTTPS origins only. API bodies are JSON, at most 128 KiB. Binary fields are canonical unpadded base64url. Do not send PRF output or plaintext keys. OPTIONS preflights are handled for every documented route and return 204 without a body. API responses, including errors, use Cache-Control: no-store. See /integration-notes and /security."
  },
  "servers": [
    {
      "url": "https://wallet.thetanuts.finance"
    }
  ],
  "security": [],
  "externalDocs": {
    "url": "https://wallet.thetanuts.finance/api"
  },
  "paths": {
    "/v1/config": {
      "get": {
        "operationId": "get_v1_config",
        "summary": "Read protocol capabilities",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Read protocol capabilities.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConfigResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/registration/options": {
      "post": {
        "operationId": "post_v1_registration_options",
        "summary": "Start new-account or add-passkey registration",
        "security": [
          {},
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Start new-account or add-passkey registration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistrationOptionsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyRequest"
              }
            }
          }
        },
        "description": "Omit Authorization to create a new account when enrollment is enabled. Supply an active bearer session to add a passkey to that existing account. An invalid supplied token is rejected; it is not treated as anonymous. Bootstrap sessions cannot add another passkey before the initial vault commits."
      }
    },
    "/v1/registration/verify": {
      "post": {
        "operationId": "post_v1_registration_verify",
        "summary": "Verify a provisional passkey",
        "security": [
          {},
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Verify a provisional passkey.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistrationVerifyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegistrationVerifyRequest"
              }
            }
          }
        },
        "description": "For a new-account challenge, no bearer token is required and success returns accountId, credentialId, token and expires. For an add-passkey challenge, send the same active bearer session used for registration/options; success returns accountId and credentialId without a new token. A later signed mutation must commit the tested root-key wrap before the credential can log in."
      }
    },
    "/v1/authentication/options": {
      "post": {
        "operationId": "post_v1_authentication_options",
        "summary": "Start discoverable login",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Start discoverable login.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationOptionsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyRequest"
              }
            }
          }
        },
        "description": "Returns allowCredentials: [] for discoverable login. No account identifier or bearer session is required."
      }
    },
    "/v1/authentication/verify": {
      "post": {
        "operationId": "post_v1_authentication_verify",
        "summary": "Authenticate and read the encrypted vault",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticate and read the encrypted vault.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthenticationVerifyRequest"
              }
            }
          }
        },
        "description": "The discoverable assertion must contain the registered userHandle. Success returns a ten-minute session and the current encrypted envelope."
      }
    },
    "/v1/vault": {
      "get": {
        "operationId": "get_v1_vault",
        "summary": "Read the current encrypted snapshot",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Read the current encrypted snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/mutations/options": {
      "post": {
        "operationId": "post_v1_mutations_options",
        "summary": "Authorize an encrypted mutation",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Authorize an encrypted mutation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MutationOptionsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MutationOptionsRequest"
              }
            }
          }
        },
        "description": "revision is the current revision (0 for a bootstrap vault). digest is SHA-256 over the exact JSON.stringify(envelope) bytes; operationId is a new random identifier. The returned credential allowlist belongs to the authenticated account."
      }
    },
    "/v1/mutations/commit": {
      "post": {
        "operationId": "post_v1_mutations_commit",
        "summary": "Commit an encrypted revision",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Commit an encrypted revision.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationReceipt"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MutationCommitRequest"
              }
            }
          }
        },
        "description": "Consumes the one-time challenge even if verification fails. A fresh assertion must bind the exact payload digest and previous revision. Success atomically advances revision by one and returns its receipt."
      }
    },
    "/v1/operations/{id}": {
      "get": {
        "operationId": "get_v1_operations__id",
        "summary": "Read a committed-operation receipt",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/OpaqueId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read a committed-operation receipt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationReceipt"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "200 means the mutation committed and returns its digest and revision. 404 OPERATION_UNKNOWN means no retained receipt was found, not proof of non-commit. Read the vault before deciding how to recover an uncertain write."
      }
    },
    "/v1/session/revoke": {
      "post": {
        "operationId": "post_v1_session_revoke",
        "summary": "Revoke the current session",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "Revoke the current session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "415": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmptyRequest"
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "session": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque base64url",
        "description": "Short-lived account/origin-scoped token. Omit cookies; keep the token only in memory."
      }
    },
    "parameters": {
      "Origin": {
        "name": "Origin",
        "in": "header",
        "required": true,
        "description": "Set automatically by browsers. Other HTTP clients must send the exact registered origin. CORS is not authentication.",
        "schema": {
          "type": "string",
          "enum": [
            "https://ranger.thetanuts.finance"
          ]
        }
      }
    },
    "responses": {
      "Error": {
        "description": "Request rejected. See the error code; failed verification requires fresh challenge options.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "OpaqueId": {
        "type": "string",
        "pattern": "^[A-Za-z0-9_-]+$",
        "minLength": 43,
        "maxLength": 43,
        "description": "32 random bytes encoded as canonical unpadded base64url."
      },
      "CredentialId": {
        "type": "string",
        "pattern": "^[A-Za-z0-9_-]+$",
        "minLength": 2,
        "maxLength": 1366
      },
      "ExpiresAt": {
        "type": "integer",
        "minimum": 0,
        "maximum": 9007199254740991,
        "description": "Session expiry as Unix epoch milliseconds. Sessions last ten minutes."
      },
      "EmptyRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [],
        "properties": {}
      },
      "Tenant": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "origin",
          "rpId",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "origin": {
            "type": "string",
            "format": "uri"
          },
          "rpId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "ConfigResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "version",
          "tenant",
          "enrollmentEnabled",
          "maxWallets",
          "maxPasskeys"
        ],
        "properties": {
          "version": {
            "const": 1
          },
          "tenant": {
            "$ref": "#/components/schemas/Tenant"
          },
          "enrollmentEnabled": {
            "type": "boolean"
          },
          "maxWallets": {
            "const": 32
          },
          "maxPasskeys": {
            "const": 8
          }
        }
      },
      "Ciphertext": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "iv",
          "ct"
        ],
        "properties": {
          "iv": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+$",
            "minLength": 16,
            "maxLength": 16
          },
          "ct": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+$",
            "minLength": 23,
            "maxLength": 174763
          }
        }
      },
      "KeyWrap": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "credentialId",
          "salt",
          "iv",
          "ct"
        ],
        "properties": {
          "credentialId": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "salt": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "iv": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+$",
            "minLength": 16,
            "maxLength": 16
          },
          "ct": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+$",
            "minLength": 64,
            "maxLength": 64
          }
        }
      },
      "Envelope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "v",
          "accountId",
          "revision",
          "payload",
          "wraps"
        ],
        "properties": {
          "v": {
            "const": 2
          },
          "accountId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "revision": {
            "type": "integer",
            "minimum": 1
          },
          "payload": {
            "$ref": "#/components/schemas/Ciphertext"
          },
          "wraps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KeyWrap"
            },
            "minItems": 1,
            "maxItems": 8
          }
        }
      },
      "CredentialDescriptor": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "type"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "type": {
            "const": "public-key"
          },
          "transports": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 32
            },
            "minItems": 0,
            "maxItems": 8
          }
        }
      },
      "RegistrationOptions": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challenge",
          "rp",
          "user",
          "pubKeyCredParams",
          "timeout",
          "attestation",
          "excludeCredentials",
          "authenticatorSelection",
          "extensions",
          "hints"
        ],
        "properties": {
          "challenge": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "rp": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "name",
              "id"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "id": {
                "type": "string"
              }
            }
          },
          "user": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "displayName"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/OpaqueId"
              },
              "name": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              }
            }
          },
          "pubKeyCredParams": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "type",
                "alg"
              ],
              "properties": {
                "type": {
                  "const": "public-key"
                },
                "alg": {
                  "type": "integer",
                  "enum": [
                    -7,
                    -257
                  ]
                }
              }
            },
            "minItems": 2,
            "maxItems": 2
          },
          "timeout": {
            "const": 60000
          },
          "attestation": {
            "const": "none"
          },
          "excludeCredentials": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CredentialDescriptor"
            },
            "minItems": 0,
            "maxItems": 8
          },
          "authenticatorSelection": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "residentKey",
              "userVerification",
              "requireResidentKey"
            ],
            "properties": {
              "residentKey": {
                "const": "required"
              },
              "userVerification": {
                "const": "required"
              },
              "requireResidentKey": {
                "const": true
              }
            }
          },
          "extensions": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "credProps"
            ],
            "properties": {
              "credProps": {
                "const": true
              }
            }
          },
          "hints": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 0,
            "maxItems": 0
          }
        }
      },
      "AssertionOptions": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challenge",
          "rpId",
          "userVerification",
          "timeout",
          "allowCredentials"
        ],
        "properties": {
          "challenge": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "rpId": {
            "type": "string"
          },
          "userVerification": {
            "const": "required"
          },
          "timeout": {
            "const": 60000
          },
          "allowCredentials": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CredentialDescriptor"
            },
            "minItems": 0,
            "maxItems": 8
          }
        }
      },
      "RegistrationOptionsResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challengeId",
          "accountId",
          "options"
        ],
        "properties": {
          "challengeId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "accountId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "options": {
            "$ref": "#/components/schemas/RegistrationOptions"
          }
        }
      },
      "AuthenticationOptionsResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challengeId",
          "options"
        ],
        "properties": {
          "challengeId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "options": {
            "$ref": "#/components/schemas/AssertionOptions"
          }
        }
      },
      "MutationOptionsResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challengeId",
          "options"
        ],
        "properties": {
          "challengeId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "options": {
            "$ref": "#/components/schemas/AssertionOptions"
          }
        }
      },
      "NewRegistrationResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "accountId",
          "credentialId",
          "token",
          "expires"
        ],
        "properties": {
          "accountId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "credentialId": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "token": {
            "$ref": "#/components/schemas/OpaqueId",
            "description": "Bootstrap bearer token. Keep only in memory; never log or persist it."
          },
          "expires": {
            "$ref": "#/components/schemas/ExpiresAt"
          }
        }
      },
      "AddedPasskeyResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "accountId",
          "credentialId"
        ],
        "properties": {
          "accountId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "credentialId": {
            "$ref": "#/components/schemas/CredentialId"
          }
        }
      },
      "RegistrationVerifyResponse": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/NewRegistrationResponse"
          },
          {
            "$ref": "#/components/schemas/AddedPasskeyResponse"
          }
        ],
        "description": "New accounts receive a bootstrap token and expiry. Adding a passkey returns only the account and credential IDs; the existing session continues."
      },
      "AuthenticationResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "token",
          "expires",
          "accountId",
          "envelope"
        ],
        "properties": {
          "token": {
            "$ref": "#/components/schemas/OpaqueId",
            "description": "Bearer token scoped to this account and origin. Keep only in memory."
          },
          "expires": {
            "$ref": "#/components/schemas/ExpiresAt"
          },
          "accountId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "envelope": {
            "$ref": "#/components/schemas/Envelope"
          }
        }
      },
      "VaultResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "envelope"
        ],
        "properties": {
          "envelope": {
            "$ref": "#/components/schemas/Envelope"
          }
        }
      },
      "OperationReceipt": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "revision",
          "digest"
        ],
        "properties": {
          "revision": {
            "type": "integer",
            "minimum": 1
          },
          "digest": {
            "$ref": "#/components/schemas/OpaqueId"
          }
        },
        "description": "A 200 receipt confirms that the encrypted mutation committed at this revision. A 404 OPERATION_UNKNOWN does not prove it never committed; receipts can expire."
      },
      "RevokeResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "revoked"
        ],
        "properties": {
          "revoked": {
            "const": true
          }
        }
      },
      "RegistrationCredential": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "rawId",
          "type",
          "clientExtensionResults",
          "response"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "rawId": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "type": {
            "const": "public-key"
          },
          "clientExtensionResults": {
            "type": "object",
            "additionalProperties": false,
            "required": [],
            "properties": {}
          },
          "response": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "clientDataJSON",
              "attestationObject",
              "transports"
            ],
            "properties": {
              "clientDataJSON": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 2,
                "maxLength": 5462
              },
              "attestationObject": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 2,
                "maxLength": 21846
              },
              "transports": {
                "type": "array",
                "items": {
                  "type": "string",
                  "maxLength": 32
                },
                "minItems": 0,
                "maxItems": 8
              }
            }
          }
        }
      },
      "AssertionCredential": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "rawId",
          "type",
          "clientExtensionResults",
          "response"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "rawId": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "type": {
            "const": "public-key"
          },
          "clientExtensionResults": {
            "type": "object",
            "additionalProperties": false,
            "required": [],
            "properties": {}
          },
          "response": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "clientDataJSON",
              "authenticatorData",
              "signature",
              "userHandle"
            ],
            "properties": {
              "clientDataJSON": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 2,
                "maxLength": 5462
              },
              "authenticatorData": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 50,
                "maxLength": 5462
              },
              "signature": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 2,
                "maxLength": 2731
              },
              "userHandle": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/OpaqueId"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        }
      },
      "DiscoverableAssertionCredential": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "rawId",
          "type",
          "clientExtensionResults",
          "response"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "rawId": {
            "$ref": "#/components/schemas/CredentialId"
          },
          "type": {
            "const": "public-key"
          },
          "clientExtensionResults": {
            "type": "object",
            "additionalProperties": false,
            "required": [],
            "properties": {}
          },
          "response": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "clientDataJSON",
              "authenticatorData",
              "signature",
              "userHandle"
            ],
            "properties": {
              "clientDataJSON": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 2,
                "maxLength": 5462
              },
              "authenticatorData": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 50,
                "maxLength": 5462
              },
              "signature": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]+$",
                "minLength": 2,
                "maxLength": 2731
              },
              "userHandle": {
                "$ref": "#/components/schemas/OpaqueId"
              }
            }
          }
        }
      },
      "RegistrationVerifyRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challengeId",
          "credential"
        ],
        "properties": {
          "challengeId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "credential": {
            "$ref": "#/components/schemas/RegistrationCredential"
          }
        }
      },
      "AuthenticationVerifyRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challengeId",
          "credential"
        ],
        "properties": {
          "challengeId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "credential": {
            "$ref": "#/components/schemas/DiscoverableAssertionCredential"
          }
        }
      },
      "MutationOptionsRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "revision",
          "digest",
          "operationId"
        ],
        "properties": {
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "digest": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "operationId": {
            "$ref": "#/components/schemas/OpaqueId"
          }
        }
      },
      "MutationCommitRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "challengeId",
          "credential",
          "envelope"
        ],
        "properties": {
          "challengeId": {
            "$ref": "#/components/schemas/OpaqueId"
          },
          "credential": {
            "$ref": "#/components/schemas/AssertionCredential"
          },
          "envelope": {
            "$ref": "#/components/schemas/Envelope"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "AUTH_FAILED",
              "AUTH_REQUIRED",
              "AUTH_RETRY",
              "BODY_TOO_LARGE",
              "CHALLENGE_EXPIRED",
              "CHALLENGE_MISMATCH",
              "CREDENTIAL_EXISTS",
              "DIGEST_MISMATCH",
              "ENROLLMENT_DISABLED",
              "FINISH_REGISTRATION",
              "INVALID_REQUEST",
              "JSON_REQUIRED",
              "KEEP_EXISTING_PASSKEYS",
              "METHOD_NOT_ALLOWED",
              "NOT_FOUND",
              "OPERATION_EXISTS",
              "OPERATION_UNKNOWN",
              "ORIGIN_DENIED",
              "PASSKEY_LIMIT",
              "PREFLIGHT_DENIED",
              "QUERY_NOT_SUPPORTED",
              "REVISION_CONFLICT",
              "SERVICE_UNAVAILABLE",
              "SESSION_EXPIRED",
              "SIGNING_PASSKEY_MISSING",
              "TENANT_MISMATCH",
              "TRY_LATER",
              "UNKNOWN_PASSKEY",
              "VAULT_PENDING"
            ],
            "description": "Stable short error code. No credential material or parser details."
          }
        }
      }
    }
  }
}
