{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:certarail:schema:event:certarail.trade.order.v1",
  "title": "CertaRail legacy durable sandbox trading order event v1",
  "description": "Frozen legacy PostgreSQL transactional-outbox contract emitted before subject binding, the BUY-only gate, the current RUB/USD/EUR quote set and explicit order provenance. V1 may omit subject_ref, may contain BUY or SELL, and accepts any uppercase three-letter quote. Existing rows are assigned immutable event_contract v1 and retain v1 for subsequent lifecycle facts; historical v1 payloads may omit event_contract. A legacy SELL can only be locally cancelled and cannot receive a fill. V1 never authorizes a new legacy order or asserts a live venue call, market price, settlement, custody balance, ledger posting, asset movement, or legal permission to trade.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "event_id",
    "event_type",
    "action",
    "occurred_at",
    "tenant_id",
    "order_id",
    "decision_id",
    "order",
    "evidence_digest",
    "safety",
    "external_calls"
  ],
  "properties": {
    "event_id": {
      "type": "string",
      "pattern": "^evt-trade_[0-9a-f]{32}$"
    },
    "event_type": {
      "const": "certarail.trade.order.v1"
    },
    "action": {
      "enum": ["ORDER_OPENED", "SYNTHETIC_FILL_RECORDED", "ORDER_CANCELLED"]
    },
    "occurred_at": {
      "type": "string",
      "format": "date-time"
    },
    "tenant_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128
    },
    "order_id": {
      "type": "string",
      "pattern": "^ord_[0-9a-f]{32}$"
    },
    "decision_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 160
    },
    "order": {
      "$ref": "#/$defs/order"
    },
    "fill": {
      "$ref": "#/$defs/fill"
    },
    "evidence_digest": {
      "$ref": "#/$defs/digest"
    },
    "safety": {
      "$ref": "#/$defs/safety"
    },
    "external_calls": {
      "const": 0
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "action": { "const": "SYNTHETIC_FILL_RECORDED" }
        },
        "required": ["action"]
      },
      "then": {
        "properties": {
          "fill": { "$ref": "#/$defs/fill" }
        },
        "required": ["fill"]
      },
      "else": {
        "properties": {
          "fill": false
        }
      }
    }
  ],
  "$defs": {
    "digest": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    },
    "safety": {
      "type": "object",
      "additionalProperties": false,
      "required": ["environment", "production_enforceable", "monetary"],
      "properties": {
        "environment": { "const": "sandbox" },
        "production_enforceable": { "const": false },
        "monetary": { "const": false }
      }
    },
    "instrument": {
      "type": "object",
      "additionalProperties": false,
      "required": ["base_asset", "quote_currency"],
      "properties": {
        "base_asset": { "type": "string", "minLength": 1, "maxLength": 64 },
        "quote_currency": { "type": "string", "pattern": "^[A-Z]{3}$" }
      }
    },
    "positiveQuantity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["atomic_units", "decimals"],
      "properties": {
        "atomic_units": { "type": "string", "pattern": "^[1-9][0-9]{0,77}$" },
        "decimals": { "type": "integer", "minimum": 0, "maximum": 38 }
      }
    },
    "nonNegativeQuantity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["atomic_units", "decimals"],
      "properties": {
        "atomic_units": { "type": "string", "pattern": "^(0|[1-9][0-9]{0,77})$" },
        "decimals": { "type": "integer", "minimum": 0, "maximum": 38 }
      }
    },
    "decimal": {
      "type": "object",
      "additionalProperties": false,
      "required": ["value", "scale"],
      "properties": {
        "value": { "type": "string", "pattern": "^[1-9][0-9]{0,77}$" },
        "scale": { "type": "integer", "minimum": 0, "maximum": 38 }
      }
    },
    "money": {
      "type": "object",
      "additionalProperties": false,
      "required": ["currency", "minor_units"],
      "properties": {
        "currency": { "type": "string", "pattern": "^[A-Z]{3}$" },
        "minor_units": { "type": "integer", "minimum": 1, "maximum": 9223372036854775807 }
      }
    },
    "order": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "order_id",
        "request_id",
        "tenant_id",
        "decision_id",
        "portfolio_ref",
        "approval_ref",
        "connection_id",
        "account_ref",
        "client_order_id",
        "instrument",
        "side",
        "order_type",
        "base_quantity",
        "time_in_force",
        "max_notional",
        "command_id",
        "provider_order_ref",
        "status",
        "submit_disposition",
        "venue_state",
        "filled_quantity",
        "version",
        "created_at",
        "updated_at",
        "evidence_digest",
        "safety",
        "external_calls"
      ],
      "properties": {
        "order_id": { "type": "string", "pattern": "^ord_[0-9a-f]{32}$" },
        "request_id": { "type": "string", "minLength": 1, "maxLength": 128 },
        "tenant_id": { "type": "string", "minLength": 1, "maxLength": 128 },
        "decision_id": { "type": "string", "minLength": 1, "maxLength": 160 },
        "event_contract": {
          "const": "certarail.trade.order.v1",
          "description": "Immutable order event-schema provenance. Optional because historical v1 payloads predate the field."
        },
        "subject_ref": {
          "type": "string",
          "minLength": 0,
          "maxLength": 256,
          "description": "Optional legacy field. It may be absent or empty because v1 predates mandatory eligibility subject binding."
        },
        "portfolio_ref": { "type": "string", "minLength": 1, "maxLength": 256 },
        "approval_ref": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Correlation only; not evidence that CertaRail performed maker-checker approval."
        },
        "connection_id": { "type": "string", "minLength": 1, "maxLength": 128 },
        "account_ref": { "type": "string", "minLength": 1, "maxLength": 256 },
        "client_order_id": { "type": "string", "minLength": 1, "maxLength": 128 },
        "instrument": { "$ref": "#/$defs/instrument" },
        "side": {
          "enum": ["BUY", "SELL"],
          "description": "Legacy v1 facts may contain SELL. This does not make SELL executable in the current runtime."
        },
        "order_type": { "const": "MARKET" },
        "base_quantity": { "$ref": "#/$defs/positiveQuantity" },
        "limit_price": { "$ref": "#/$defs/decimal" },
        "time_in_force": { "const": "IOC" },
        "max_notional": { "$ref": "#/$defs/money" },
        "command_id": { "type": "string", "pattern": "^cmd_[0-9a-f]{32}$" },
        "provider_order_ref": {
          "type": "string",
          "pattern": "^syn-order_[0-9a-f]{32}$",
          "description": "Deterministic local reference, never a provider receipt."
        },
        "status": { "enum": ["OPEN", "PARTIALLY_FILLED", "FILLED", "CANCELLED"] },
        "submit_disposition": {
          "const": "ACKNOWLEDGED",
          "description": "Local PostgreSQL acknowledgement only."
        },
        "venue_state": { "enum": ["OPEN", "PARTIALLY_FILLED", "FILLED", "CANCELLED"] },
        "filled_quantity": { "$ref": "#/$defs/nonNegativeQuantity" },
        "version": { "type": "integer", "minimum": 1 },
        "created_at": { "type": "string", "format": "date-time" },
        "updated_at": { "type": "string", "format": "date-time" },
        "evidence_digest": { "$ref": "#/$defs/digest" },
        "safety": { "$ref": "#/$defs/safety" },
        "external_calls": { "const": 0 }
      }
    },
    "fill": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "fill_id",
        "order_id",
        "tenant_id",
        "fill_ref",
        "quantity",
        "price",
        "observed_at",
        "recorded_at",
        "evidence_digest",
        "safety"
      ],
      "properties": {
        "fill_id": { "type": "string", "pattern": "^fill_[0-9a-f]{32}$" },
        "order_id": { "type": "string", "pattern": "^ord_[0-9a-f]{32}$" },
        "tenant_id": { "type": "string", "minLength": 1, "maxLength": 128 },
        "fill_ref": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Synthetic deduplication reference, not a live venue fill ID."
        },
        "quantity": { "$ref": "#/$defs/positiveQuantity" },
        "price": {
          "allOf": [{ "$ref": "#/$defs/decimal" }],
          "description": "Caller-supplied local fixture, not real-time market data."
        },
        "observed_at": { "type": "string", "format": "date-time" },
        "recorded_at": { "type": "string", "format": "date-time" },
        "evidence_digest": {
          "allOf": [{ "$ref": "#/$defs/digest" }],
          "description": "Legacy lowercase SHA-256 evidence digest. Consumers must not assume v2 fill-preimage semantics for already published v1 payloads."
        },
        "evidence_format": {
          "enum": ["SYNTHETIC_FILL_EVIDENCE_V1", "LEGACY_COMMAND_PREIMAGE_V1"],
          "description": "Optional compatibility tag. Historical v1 payloads may omit it; LEGACY_COMMAND_PREIMAGE_V1 identifies a repaired row whose digest is bound to the original immutable command preimage."
        },
        "safety": { "$ref": "#/$defs/safety" }
      }
    }
  }
}
