{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.orbiplex.org/inac-control.v1.schema.json",
  "title": "INAC control frame",
  "description": "Control-plane frame for Inter-Node Artifact Channel offer/request/push/response exchanges. The frame is transport-neutral; concrete transports must preserve the byte identity of inline artifact bytes.",
  "type": "object",
  "required": ["schema", "operation"],
  "properties": {
    "schema": {
      "const": "inac-control.v1"
    },
    "operation": {
      "type": "string",
      "enum": [
        "offer",
        "request",
        "push",
        "accept",
        "decline",
        "defer",
        "ingested",
        "already-present",
        "refused",
        "partial"
      ]
    },
    "correlation/id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256,
      "pattern": "^[A-Za-z0-9:_./-]+$"
    },
    "idempotency/key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256,
      "pattern": "^[A-Za-z0-9:_./-]+$"
    },
    "artifact": {
      "$ref": "#/$defs/artifact"
    },
    "request": {
      "$ref": "#/$defs/request"
    },
    "transfer": {
      "$ref": "#/$defs/transfer"
    },
    "authorization": {
      "$ref": "#/$defs/authorization"
    },
    "response": {
      "$ref": "#/$defs/response"
    },
    "meta": {
      "type": "object",
      "maxProperties": 16,
      "propertyNames": {
        "minLength": 1,
        "maxLength": 64,
        "pattern": "^[A-Za-z0-9:_./-]+$"
      },
      "additionalProperties": {
        "type": "string",
        "maxLength": 512
      }
    }
  },
  "allOf": [
    {
      "if": {
        "properties": { "operation": { "const": "offer" } },
        "required": ["operation"]
      },
      "then": {
        "required": ["artifact"],
        "properties": {
          "artifact": {
            "oneOf": [
              { "required": ["bytes/base64url"], "not": { "anyOf": [{ "required": ["artifact/ref"] }, { "required": ["artifact/href"] }] } },
              { "required": ["artifact/ref"], "not": { "anyOf": [{ "required": ["bytes/base64url"] }, { "required": ["artifact/href"] }] } },
              { "required": ["artifact/href"], "not": { "anyOf": [{ "required": ["bytes/base64url"] }, { "required": ["artifact/ref"] }] } }
            ]
          }
        }
      }
    },
    {
      "if": {
        "properties": { "operation": { "const": "push" } },
        "required": ["operation"]
      },
      "then": {
        "required": ["artifact"]
      }
    },
    {
      "if": {
        "properties": { "operation": { "const": "request" } },
        "required": ["operation"]
      },
      "then": {
        "required": ["request"]
      }
    },
    {
      "if": {
        "properties": {
          "operation": {
            "enum": ["accept", "decline", "defer", "ingested", "already-present", "refused", "partial"]
          }
        },
        "required": ["operation"]
      },
      "then": {
        "required": ["response"]
      }
    }
  ],
  "$defs": {
    "artifact": {
      "type": "object",
      "required": ["schema", "content/type", "artifact/id", "digest", "size/bytes"],
      "properties": {
        "schema": {
          "type": "string",
          "minLength": 1
        },
        "content/type": {
          "type": "string",
          "minLength": 1
        },
        "artifact/id": {
          "type": "string",
          "minLength": 1
        },
        "digest": {
          "type": "string",
          "pattern": "^sha256:[A-Za-z0-9_-]+$"
        },
        "size/bytes": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1073741824
        },
        "bytes/base64url": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_-]+$"
        },
        "artifact/ref": {
          "type": "string",
          "minLength": 1
        },
        "artifact/href": {
          "type": "string",
          "format": "uri"
        }
      },
      "additionalProperties": false
    },
    "request": {
      "type": "object",
      "required": ["schema", "content/type"],
      "properties": {
        "schema": {
          "type": "string",
          "minLength": 1
        },
        "content/type": {
          "type": "string",
          "minLength": 1
        },
        "artifact/id": {
          "type": "string",
          "minLength": 1
        },
        "digest": {
          "type": "string",
          "pattern": "^sha256:[A-Za-z0-9_-]+$"
        }
      },
      "additionalProperties": false
    },
    "transfer": {
      "type": "object",
      "properties": {
        "mode": {
          "type": "string",
          "enum": ["inline", "stream", "out-of-band"]
        },
        "stream/id": {
          "type": "string",
          "minLength": 1
        },
        "chunk/size-bytes": {
          "type": "integer",
          "minimum": 1
        }
      },
      "additionalProperties": false
    },
    "authorization": {
      "type": "object",
      "required": ["mode", "passport"],
      "properties": {
        "mode": {
          "type": "string",
          "enum": ["invitation-passport"]
        },
        "passport": {
          "type": "object",
          "required": ["schema"],
          "properties": {
            "schema": {
              "const": "capability-passport.v1"
            }
          },
          "additionalProperties": true
        }
      },
      "additionalProperties": false
    },
    "response": {
      "type": "object",
      "required": ["status"],
      "properties": {
        "status": {
          "type": "string",
          "enum": ["accepted", "declined", "deferred", "ingested", "already-present", "refused", "partial"]
        },
        "refusal/code": {
          "type": "string",
          "enum": [
            "kind-not-supported",
            "kind-conflict",
            "not-authorized",
            "invitation-unknown",
            "invitation-expired",
            "invitation-revoked",
            "invitation-scope-mismatch",
            "payload-too-large",
            "digest-mismatch",
            "malformed",
            "handler-unavailable",
            "already-present",
            "operation-not-supported",
            "policy-denied",
            "transport-unavailable",
            "rate-limited",
            "quota-exceeded"
          ]
        },
        "retryable": {
          "type": "boolean"
        },
        "retry/after-ms": {
          "type": "integer",
          "minimum": 0
        },
        "message": {
          "type": "string",
          "maxLength": 1024
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
