{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://fingertrackid.dev/schemas/event-assessment-request.v1.1.schema.json",
  "title": "EventAssessmentRequestV1_1",
  "description": "Request server-to-server fechado do pedido com tag (D174): os campos comuns do v1 mais uma tag livre. Não existem journey, action nem journey_context; o cliente não escolhe tipo, e todo pedido v1.1 roda na classe interna de login, com o prazo, a policy, o fallback e o protocolo dela. Este perfil é aditivo e não altera event-assessment-request.v1.",
  "$defs": {
    "external_event_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 255,
      "pattern": "^[\\x21-\\x7e]+$"
    },
    "instant": {
      "type": "string",
      "format": "date-time",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,3})?(?:Z|[+-]\\d{2}:\\d{2})$"
    },
    "opaque_ref": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
      "description": "Pseudônimo opaco e estável no escopo do tenant, apresentado por um integration client autenticado. Não envie CPF, e-mail, telefone, nome, segredo nem identificador diretamente reversível."
    },
    "nullable_opaque_ref": {
      "anyOf": [
        {
          "$ref": "#/$defs/opaque_ref"
        },
        {
          "type": "null"
        }
      ]
    },
    "event_context_token": {
      "description": "Campo obrigatório e nullable. null significa ausência de coleta e produz fallback inconclusivo; token presente mas inválido é rejeitado.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1,
          "maxLength": 4096,
          "pattern": "^[\\x21-\\x7e]+$"
        },
        {
          "type": "null"
        }
      ]
    },
    "tag": {
      "description": "Tag livre do ponto de chamada, escolhida pela integração (D174). Slug ASCII minúsculo, 1..64, começando por letra ou dígito; sem normalização silenciosa (maiúscula, espaço e hífen são recusados). Nunca seleciona policy, detector, provider, nota, prazo, quota ou fila, e não pode conter PII, segredo, documento, telefone, e-mail nem nome de pessoa. No máximo dez dígitos no total, em qualquer posição: a recusa de onze ou mais dígitos (juntos ou separados, como em `cpf_123_456_789_01`) é estrutural e não comprova ausência de PII.",
      "type": "string",
      "allOf": [
        {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9_]{0,63}$"
        },
        {
          "not": {
            "type": "string",
            "pattern": "^(?:[^0-9]*[0-9]){11}"
          }
        }
      ]
    }
  },
  "type": "object",
  "properties": {
    "schema_version": {
      "const": "event-assessment-request.v1.1"
    },
    "external_event_id": {
      "$ref": "#/$defs/external_event_id"
    },
    "idempotency_key": {
      "$ref": "#/$defs/idempotency_key"
    },
    "occurred_at": {
      "$ref": "#/$defs/instant"
    },
    "subject_ref": {
      "$ref": "#/$defs/nullable_opaque_ref"
    },
    "account_ref": {
      "$ref": "#/$defs/nullable_opaque_ref"
    },
    "event_context_token": {
      "$ref": "#/$defs/event_context_token"
    },
    "tag": {
      "$ref": "#/$defs/tag"
    },
    "deadline_ms": {
      "description": "Budget técnico contado desde received_at. null seleciona 5000 ms; não é SLA comercial.",
      "anyOf": [
        {
          "type": "integer",
          "minimum": 250,
          "maximum": 5000
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "schema_version",
    "external_event_id",
    "idempotency_key",
    "occurred_at",
    "subject_ref",
    "account_ref",
    "event_context_token",
    "tag",
    "deadline_ms"
  ],
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "type": "object",
        "properties": {
          "account_ref": {
            "$ref": "#/$defs/opaque_ref"
          }
        },
        "required": ["account_ref"]
      },
      "then": {
        "type": "object",
        "properties": {
          "subject_ref": {
            "$ref": "#/$defs/opaque_ref"
          }
        },
        "required": ["subject_ref"]
      }
    }
  ],
  "x-ftid-runtime-invariants": [
    "every v1.1 request runs in the internal LOGIN class: its deadline range, policy, fallback and protocol; the class never appears to the customer",
    "tag never selects policy, detector, provider, score, coverage, recommendation, applicability, fallback, usage unit, quota, deadline or queue, and is never a metric, log or trace label",
    "tag is inside both the semantic idempotency digest and the authorization effect digest: the same event with another tag is an idempotency conflict",
    "only a NEW logical operation requires occurred_at within plus or minus 300 seconds of server received_at; an idempotent SAME hit is resolved first",
    "event_context_token is authenticated, single-scope and consumed atomically after idempotent replay lookup",
    "deadline_ms is authenticated by the raw-body HMAC but excluded from the semantic idempotency digest because it only budgets the transport attempt",
    "same idempotency_key and semantic request digest return the persisted assessment; divergent reuse is conflict, including reuse across event-assessment-request.v1 and v1.1",
    "idempotency_key and external_event_id are never reused during the resolved integration_client lifetime, including after payload retention; tenant erasure ends the namespace"
  ]
}
