{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "v": {
      "type": "number",
      "const": 1,
      "description": "Protocol major version."
    },
    "type": {
      "type": "string",
      "const": "approval.resolved"
    },
    "id": {
      "type": "string",
      "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "The event's own id. Stable across a retry of the same event."
    },
    "ts": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "description": "When it happened, by Chips' clock. Stamped on the way in; a value the sender writes is replaced."
    },
    "workspace_id": {
      "type": "string",
      "pattern": "^ws_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "A workspace identifier: `ws_` followed by a ULID."
    },
    "space_id": {
      "description": "The space, when the event belongs to one.",
      "type": "string",
      "pattern": "^spc_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "run_id": {
      "description": "The run, when the event belongs to one.",
      "type": "string",
      "pattern": "^run_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "seq": {
      "description": "Assigned by the server on append, monotonic per workspace. Absent on the way in.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "idempotency_key": {
      "description": "Required on every client-originated write. Sending the same key twice is a no-op.",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "actor": {
      "type": "object",
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "person",
            "harness",
            "agent",
            "system"
          ],
          "description": "Whether a person, a harness, one of a harness's agents or Chips itself acted."
        },
        "id": {
          "type": "string",
          "minLength": 1,
          "description": "The participant id, or `system` for Chips."
        },
        "harness_id": {
          "description": "For an agent: the harness it speaks through, whose budget and runs are the agent's (ADR 0087). Filled in by Chips.",
          "type": "string",
          "pattern": "^hrn_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
        }
      },
      "required": [
        "kind",
        "id"
      ],
      "description": "The participant an event is attributed to."
    },
    "approval_id": {
      "type": "string",
      "pattern": "^apr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "A approval identifier: `apr_` followed by a ULID."
    },
    "decision": {
      "type": "string",
      "enum": [
        "approved",
        "edited",
        "denied",
        "expired"
      ],
      "description": "`expired` means nobody answered and the fallback applied."
    },
    "scope": {
      "default": "once",
      "description": "How far the answer reaches. `always` becomes a policy rule.",
      "type": "string",
      "enum": [
        "once",
        "session",
        "always"
      ]
    },
    "everywhere": {
      "description": "With `always`: the rule is the harness's in every space, not only this one (ADR 0239). An owner or an admin only.",
      "type": "boolean"
    },
    "updated_input": {
      "description": "The edited action input, when the decision is `edited`."
    },
    "reason": {
      "description": "Why. The harness gets to read this.",
      "type": "string",
      "maxLength": 4000
    },
    "resolved_by": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120,
      "description": "The participant who answered, or `system` on expiry — a harness when it settles its own ask, answered in its own tools. Filled in by Chips from the credential that sent it; a value the sender writes is replaced."
    },
    "resolved_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "description": "When it was answered. Stamped by Chips."
    },
    "resolved_elsewhere": {
      "default": false,
      "description": "True on the surfaces that did not answer first. First answer wins.",
      "type": "boolean"
    },
    "approvers": {
      "description": "Who could answer it, as ids, as they stood when it was decided. Written by Chips from the approval so that somebody named outside the room is sent the decision as well as the ask (ADR 0042); a value the sender writes is replaced.",
      "maxItems": 64,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 120
      }
    }
  },
  "required": [
    "v",
    "type",
    "id",
    "ts",
    "workspace_id",
    "actor",
    "approval_id",
    "decision",
    "resolved_by",
    "resolved_at"
  ],
  "description": "A decision came back. More than yes or no: it carries a scope, optional edited input, and a reason.",
  "$id": "https://chipschat.ai/schema/v1/approval.resolved.json",
  "title": "ApprovalResolved"
}
