{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://security-intelligence.invalid/contracts/feed-manifest/1.0",
  "title": "Public feed manifest payload 1.0",
  "$comment": "This is a TUF target payload, never a trust anchor. The wire preflight rejects duplicate keys, invalid UTF-8, unpaired surrogates, depth over 32, documents over 1 MiB, and numeric tokens other than bounded plain integers. Authentication, rollback and expiry relative to a trusted clock are separate consumer gates.",
  "type": "object",
  "additionalProperties": false,
  "required": ["feed_contract_version", "service_id", "feed_id", "channel", "scope_digest", "dataset_epoch", "sequence", "created_at", "expires_at", "export_policy_revision", "source_watermark", "previous_manifest_digest", "base_snapshot_digest", "objects", "source_coverage", "key_id"],
  "properties": {
    "feed_contract_version": { "const": "1.0" },
    "service_id": { "$ref": "#/$defs/identifier" },
    "feed_id": { "$ref": "#/$defs/identifier" },
    "channel": { "const": "public-all" },
    "scope_digest": { "$ref": "#/$defs/digest" },
    "dataset_epoch": { "$ref": "#/$defs/identifier" },
    "sequence": { "$ref": "#/$defs/positiveInteger" },
    "created_at": { "$ref": "#/$defs/utcTime" },
    "expires_at": { "$ref": "#/$defs/utcTime" },
    "export_policy_revision": { "$ref": "#/$defs/identifier" },
    "source_watermark": { "$ref": "#/$defs/identifier" },
    "previous_manifest_digest": { "type": ["string", "null"], "minLength": 71, "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}$" },
    "base_snapshot_digest": { "$ref": "#/$defs/digest" },
    "key_id": { "$ref": "#/$defs/identifier" },
    "objects": {
      "type": "array", "minItems": 1, "maxItems": 1024,
      "items": {
        "type": "object", "additionalProperties": false,
        "required": ["digest", "bytes", "uncompressed_bytes", "media_type", "kind", "from_sequence", "to_sequence"],
        "properties": {
          "digest": { "$ref": "#/$defs/digest" },
          "bytes": { "$ref": "#/$defs/positiveInteger" },
          "uncompressed_bytes": { "$ref": "#/$defs/positiveInteger" },
          "media_type": { "const": "application/x-ndjson" },
          "kind": { "enum": ["snapshot", "delta"] },
          "from_sequence": { "$ref": "#/$defs/nonnegativeInteger" },
          "to_sequence": { "$ref": "#/$defs/positiveInteger" }
        }
      }
    },
    "source_coverage": {
      "type": "array", "minItems": 1, "maxItems": 1024,
      "items": {
        "type": "object", "additionalProperties": false,
        "required": ["source_id", "stream", "last_success_at", "state"],
        "properties": {
          "source_id": { "$ref": "#/$defs/identifier" },
          "stream": { "type": "string", "minLength": 1, "maxLength": 128 },
          "last_success_at": { "anyOf": [{ "$ref": "#/$defs/utcTime" }, { "type": "null" }] },
          "state": { "enum": ["current", "stale", "partial", "failed", "unknown"] }
        }
      }
    }
  },
  "$defs": {
    "identifier": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$", "not": { "pattern": "[^A-Za-z0-9._:-]" } },
    "digest": { "type": "string", "minLength": 71, "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}$" },
    "nonnegativeInteger": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
    "positiveInteger": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 },
    "utcTime": { "type": "string", "minLength": 20, "maxLength": 20, "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$" }
  }
}
