{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://law.arxo.io/schema/profile-descriptor.schema.json",
  "title": "Arxo registry profile descriptor 0.1",
  "description": "Registry descriptor of a PROFILE release: the profile artifact's arrays are repeated here as full elements so the dependency graph is available before anything is downloaded. On load, the artifact is checked against the descriptor by equality of the full elements (LDC-E1367). Address form: registry://<registryId>/profile/<id>/<version>.",
  "$comment": "DECISION-0170 §1.8; DECISION-0168 §6",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "descriptorFormat": {
      "const": "law.profile-descriptor/0.1"
    },
    "id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9_]*(?:\\.[a-z][a-z0-9_]*)*$"
    },
    "version": {
      "type": "string",
      "minLength": 1,
      "pattern": "^[0-9A-Za-z][0-9A-Za-z._+-]*$"
    },
    "registryId": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9._-]{0,63}$",
      "description": "Registry identifier of the publisher that issued the package.",
      "$comment": "DECISION-0168 §8"
    },
    "resolverUri": {
      "type": "string",
      "pattern": "^registry://[a-z][a-z0-9._-]{0,63}/profile/[a-z][a-z0-9_]*(?:\\.[a-z][a-z0-9_]*)*/[0-9A-Za-z][0-9A-Za-z._+-]*$"
    },
    "contentHash": {
      "type": "string",
      "pattern": "^sha256:[0-9a-f]{64}$",
      "description": "Content hash of the profile artifact, computed under the same rule as the profile contentHash field.",
      "$comment": "SPEC §170.1"
    },
    "language": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+$",
      "description": "Language line the profile belongs to, as a language name and version.",
      "$comment": "SPEC §22"
    },
    "semanticsRevision": {
      "type": "string",
      "minLength": 1,
      "description": "Exact semantics revision the composition was built against.",
      "$comment": "DECISION-0166 §4.5"
    },
    "signature": {
      "type": "object",
      "additionalProperties": false,
      "required": ["algorithm", "keyId", "value"],
      "properties": {
        "algorithm": {"const": "ed25519"},
        "keyId": {"type": "string", "pattern": "^ed25519:[0-9a-f]{64}$"},
        "value": {"type": "string", "minLength": 1}
      },
      "description": "Typed PAE signature over the canonical descriptor bytes excluding this field.",
      "$comment": "DECISION-0369 R7"
    },
    "packages": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]*(?:\\.[a-z][a-z0-9_]*)*$"
          },
          "version": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[0-9A-Za-z][0-9A-Za-z._+-]*$"
          },
          "namespace": {
            "type": "string",
            "format": "uri",
            "description": "Package namespace, a URN. The `format` keyword of Draft 2020-12 is only an annotation, so the shape is enforced by `pattern`.",
            "$comment": "SPEC §10; E-0060",
            "pattern": "^urn:[A-Za-z0-9][A-Za-z0-9-]{0,31}(?::[A-Za-z0-9._~%!$&'()*+,;=@-]+)+$"
          },
          "contentHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$"
          },
          "registryId": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9._-]{0,63}$",
            "description": "Registry identifier of the publisher that issued the package.",
            "$comment": "DECISION-0168 §8"
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_.-]+(?:/[0-9A-Za-z._+-]+)?$"
            },
            "uniqueItems": true,
            "description": "The set PROVIDED by the package; absence means the empty set."
          }
        },
        "required": [
          "name",
          "version",
          "namespace",
          "contentHash"
        ]
      },
      "description": "A set sorted by name; one version per name."
    },
    "profiles": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]*(?:\\.[a-z][a-z0-9_]*)*$"
          },
          "version": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[0-9A-Za-z][0-9A-Za-z._+-]*$"
          },
          "contentHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$"
          },
          "registryId": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9._-]{0,63}$",
            "description": "Registry identifier of the publisher that issued the package.",
            "$comment": "DECISION-0168 §8"
          }
        },
        "required": [
          "id",
          "version",
          "contentHash"
        ]
      },
      "description": "Included profiles; a set keyed by id; resolution is transitive."
    },
    "calendars": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "node": {
            "type": "string",
            "minLength": 1,
            "description": "Stable identifier of the calendar snapshot node used for business-day arithmetic.",
            "$comment": "SPEC §85"
          },
          "contentHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$"
          },
          "package": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]*(?:\\.[a-z][a-z0-9_]*)*$"
          }
        },
        "required": [
          "node",
          "contentHash",
          "package"
        ]
      },
      "description": "Pinned calendar datasets in the calendar-dataset resource form; a set keyed by node.",
      "$comment": "SPEC §85"
    },
    "expansions": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]*(?:\\.[a-z][a-z0-9_]*)*$"
          },
          "version": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[0-9A-Za-z][0-9A-Za-z._+-]*$"
          },
          "contentHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "Hash of the significant files of the expansion-definitions package, matching the lock entry.",
            "$comment": "SPEC §279.1.8"
          }
        },
        "required": [
          "name",
          "version",
          "contentHash"
        ]
      },
      "description": "Expansion-definitions packages available to the composition; a set keyed by name.",
      "$comment": "SPEC §279.1.8"
    }
  },
  "required": [
    "descriptorFormat",
    "id",
    "version",
    "registryId",
    "resolverUri",
    "contentHash",
    "language",
    "semanticsRevision",
    "signature"
  ],
  "anyOf": [
    {
      "required": [
        "packages"
      ]
    },
    {
      "required": [
        "profiles"
      ]
    }
  ]
}
