{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://docs.qauth.dev/interaction/v1-rc.0/steps/new_password.json",
  "title": "urn:qauth:ia:new_password:v1-rc.0",
  "description": "Sets a password through the one password policy (ADR-017 Decision 8): at registration, at the end of a reset, or when an admin or a breach-list match requires a new one (ADR-020 §3). The reasons of a refusal are returned, never prose. The page marks the field for password managers, with the identifier from the personal data as the username. Works without JavaScript.",
  "x-qauth-transports": [
    "interaction",
    "fipa"
  ],
  "type": "object",
  "properties": {
    "type": {
      "const": "urn:qauth:ia:new_password:v1-rc.0",
      "description": "The step name."
    },
    "params": {
      "$ref": "#/$defs/params"
    },
    "answer": {
      "$ref": "#/$defs/answer"
    },
    "personal": {
      "$ref": "#/$defs/personal"
    },
    "error": {
      "$ref": "#/$defs/error"
    },
    "amr": {
      "$ref": "#/$defs/amr"
    }
  },
  "required": [
    "type",
    "params",
    "answer",
    "personal",
    "amr"
  ],
  "examples": [
    {
      "type": "urn:qauth:ia:new_password:v1-rc.0",
      "params": {
        "purpose": "reset",
        "min_length": 15,
        "max_length": 256,
        "reasons": [
          "too_short"
        ]
      },
      "answer": {
        "new_password": "a much longer passphrase than before"
      },
      "personal": {
        "identifier": "alice@example.com"
      },
      "error": "password_rejected",
      "amr": []
    }
  ],
  "$defs": {
    "params": {
      "type": "object",
      "properties": {
        "purpose": {
          "type": "string",
          "enum": [
            "register",
            "reset",
            "update_required"
          ],
          "description": "Why a new password is asked for, so one screen can say so: a new account, a reset, or a required update."
        },
        "min_length": {
          "type": "integer",
          "minimum": 8,
          "maximum": 256,
          "description": "The shortest password the policy accepts, in code points."
        },
        "max_length": {
          "type": "integer",
          "minimum": 8,
          "maximum": 256,
          "description": "The longest password the policy accepts."
        },
        "reasons": {
          "type": "array",
          "description": "After a refused answer: why the policy refused it.",
          "minItems": 1,
          "maxItems": 4,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "enum": [
              "too_short",
              "too_long",
              "blocklisted",
              "too_weak"
            ],
            "description": "One reason."
          }
        }
      },
      "required": [
        "purpose",
        "min_length",
        "max_length"
      ],
      "additionalProperties": false,
      "examples": [
        {
          "purpose": "reset",
          "min_length": 15,
          "max_length": 256,
          "reasons": [
            "too_short"
          ]
        }
      ]
    },
    "answer": {
      "type": "object",
      "properties": {
        "new_password": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "The new password."
        }
      },
      "required": [
        "new_password"
      ],
      "additionalProperties": false,
      "examples": [
        {
          "new_password": "a much longer passphrase than before"
        }
      ]
    },
    "personal": {
      "type": "object",
      "description": "Who the transaction is for, so the screen can show it with a way to switch accounts. Absent until the transaction has an identifier.",
      "properties": {
        "identifier": {
          "type": "string",
          "minLength": 1,
          "maxLength": 254,
          "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": "account",
          "description": "The identifier of the account this transaction is for. Before a first factor succeeds it is the identifier exactly as the person gave it, after the one normalisation every input gets, whether or not an account holds it, so it tells nothing about which accounts exist; the form the account holds appears only after authentication. Personal data: only the personal-data read returns it."
        }
      },
      "additionalProperties": false,
      "examples": [
        {
          "identifier": "alice@example.com"
        }
      ]
    },
    "error": {
      "type": "string",
      "enum": [
        "password_rejected"
      ],
      "description": "Why the last answer was refused. A closed set."
    },
    "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."
    }
  }
}
