{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://docs.qauth.dev/interaction/v1-rc.0/steps/device_confirm.json",
  "title": "urn:qauth:ia:device_confirm:v1-rc.0",
  "description": "The explicit confirmation of a device authorization, always asked, also after `verification_uri_complete` (ADR-020 §3). The screen warns that nobody else should have given the person the code, and shows where the request came from: the requesting device’s approximate location, network and user agent, which are personal data, and its start time. The consent step always follows, even for a client that may skip consent elsewhere. The device details come with the personal data, so this step needs JavaScript: a page shows them before it offers `confirm`.",
  "x-qauth-transports": [
    "interaction"
  ],
  "type": "object",
  "properties": {
    "type": {
      "const": "urn:qauth:ia:device_confirm:v1-rc.0",
      "description": "The step name."
    },
    "params": {
      "$ref": "#/$defs/params"
    },
    "answer": {
      "$ref": "#/$defs/answer"
    },
    "personal": {
      "$ref": "#/$defs/personal"
    },
    "amr": {
      "$ref": "#/$defs/amr"
    }
  },
  "required": [
    "type",
    "params",
    "answer",
    "personal",
    "amr"
  ],
  "examples": [
    {
      "type": "urn:qauth:ia:device_confirm:v1-rc.0",
      "params": {
        "user_code": "WDJB-MJHT",
        "requested_at": "2026-10-26T09:29:12Z"
      },
      "answer": {
        "decision": "confirm"
      },
      "personal": {
        "location": {
          "country": "DE",
          "region": "Bavaria"
        },
        "network": {
          "asn": 64500,
          "name": "Example Broadband"
        },
        "user_agent": "ExampleTV/4.2 (Linux; Android 14)"
      },
      "amr": []
    }
  ],
  "$defs": {
    "params": {
      "type": "object",
      "properties": {
        "user_code": {
          "type": "string",
          "minLength": 9,
          "maxLength": 9,
          "pattern": "^[BCDFGHJKLMNPQRSTVWXZ]{4}-[BCDFGHJKLMNPQRSTVWXZ]{4}$",
          "description": "The code being confirmed, so the person can compare it with the device."
        },
        "requested_at": {
          "type": "string",
          "format": "date-time",
          "maxLength": 30,
          "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\\.[0-9]{1,9})?Z$",
          "description": "When the device started the request."
        }
      },
      "required": [
        "user_code",
        "requested_at"
      ],
      "additionalProperties": false,
      "examples": [
        {
          "user_code": "WDJB-MJHT",
          "requested_at": "2026-10-26T09:29:12Z"
        }
      ]
    },
    "answer": {
      "type": "object",
      "properties": {
        "decision": {
          "type": "string",
          "enum": [
            "confirm",
            "deny"
          ],
          "description": "The decision."
        }
      },
      "required": [
        "decision"
      ],
      "additionalProperties": false,
      "examples": [
        {
          "decision": "confirm"
        }
      ]
    },
    "personal": {
      "type": "object",
      "properties": {
        "location": {
          "type": "object",
          "description": "Where the requesting address is, approximately. Absent when the lookup knows nothing.",
          "properties": {
            "country": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2,
              "pattern": "^[A-Z]{2}$",
              "description": "The ISO 3166-1 alpha-2 country of the requesting address."
            },
            "region": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0](?:[^<>\\p{C}\\p{Zl}\\p{Zp}\\u115F\\u1160\\u3164\\uFFA0]*[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0])?$",
              "x-qauth-display": "server",
              "description": "The region of the requesting address."
            }
          },
          "additionalProperties": false
        },
        "network": {
          "type": "object",
          "description": "The network the request came from.",
          "properties": {
            "asn": {
              "type": "integer",
              "minimum": 1,
              "maximum": 4294967295,
              "description": "The autonomous system number of the requesting address."
            },
            "name": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0](?:[^<>\\p{C}\\p{Zl}\\p{Zp}\\u115F\\u1160\\u3164\\uFFA0]*[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0])?$",
              "x-qauth-display": "declared",
              "description": "The name of that network, as its registrant declared it in the address registry. The registrant chose it, so the screen marks it as declared."
            }
          },
          "additionalProperties": false
        },
        "user_agent": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "pattern": "^[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0](?:[^<>\\p{C}\\p{Zl}\\p{Zp}\\u115F\\u1160\\u3164\\uFFA0]*[^<>\\p{C}\\p{Z}\\u115F\\u1160\\u3164\\uFFA0])?$",
          "x-qauth-display": "declared",
          "description": "The user agent the device declared, cut and stripped. The device chose it, so the screen marks it as declared."
        }
      },
      "additionalProperties": false,
      "examples": [
        {
          "location": {
            "country": "DE",
            "region": "Bavaria"
          },
          "network": {
            "asn": 64500,
            "name": "Example Broadband"
          },
          "user_agent": "ExampleTV/4.2 (Linux; Android 14)"
        }
      ]
    },
    "amr": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "const": [],
      "description": "The RFC 8176 `amr` values a successful answer adds to the transaction: none, because the step proves no authenticator."
    }
  }
}
