{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:certarail:schema:event:certarail.trade.order.v2",
  "title": "CertaRail durable sandbox trading order event v2",
  "description": "Current PostgreSQL transactional-outbox fact from the BUY-only non-monetary sandbox. V2 requires the eligibility-bound opaque subject_ref and never 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.v2"
    },
    "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": { "enum": ["RUB", "USD", "EUR"] }
      }
    },
    "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",
        "event_contract",
        "subject_ref",
        "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.v2",
          "description": "Immutable event-schema provenance assigned when a new order is created."
        },
        "subject_ref": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Opaque reference bound to client.subject_ref in the verified eligibility evidence."
        },
        "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": {
          "const": "BUY",
          "description": "Current v2 sandbox events are BUY-only; SELL is not executable."
        },
        "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",
        "evidence_format",
        "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": "SHA-256 of the persisted versioned canonical synthetic-fill evidence bytes."
        },
        "evidence_format": {
          "const": "SYNTHETIC_FILL_EVIDENCE_V1",
          "description": "Exact current canonical evidence format hashed by evidence_digest."
        },
        "safety": { "$ref": "#/$defs/safety" }
      }
    }
  }
}
