{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://law.arxo.io/schema/profile.schema.json",
  "title": "Arxo canon profile 0.1",
  "description": "A named, dated, and hashed composition of the norm library: the boundary of permitted dependencies for a build. Not a package and not a case — it holds no nodes and no facts, only names with versions and hashes, itself pinned by contentHash (sha256 of the canonical bytes excluding that field). Empty arrays are omitted; a composition with neither packages nor profiles is refused.",
  "$comment": "SPEC §170.1; DECISION-0170",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "schemaVersion": {
      "const": "law.profile/0.1"
    },
    "id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9_]*(?:\\.[a-z][a-z0-9_]*)*$",
      "description": "Profile name; follows the package-name grammar.",
      "$comment": "SPEC §10"
    },
    "version": {
      "type": "string",
      "minLength": 1,
      "pattern": "^[0-9A-Za-z][0-9A-Za-z._+-]*$"
    },
    "kind": {
      "enum": [
        "jurisdiction",
        "discipline",
        "tradition",
        "custom"
      ],
      "description": "Profile kind; descriptive, not part of the computation, but part of the contentHash."
    },
    "title": {
      "type": "string",
      "minLength": 1
    },
    "asOf": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
      "description": "Composition date. It does not replace the legal time of a case or the dated editions of an act.",
      "$comment": "SPEC §48"
    },
    "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"
    },
    "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"
    },
    "contentHash": {
      "type": "string",
      "pattern": "^sha256:[0-9a-f]{64}$"
    }
  },
  "required": [
    "schemaVersion",
    "id",
    "version",
    "kind",
    "title",
    "asOf",
    "language",
    "semanticsRevision",
    "contentHash"
  ],
  "anyOf": [
    {
      "required": [
        "packages"
      ]
    },
    {
      "required": [
        "profiles"
      ]
    }
  ]
}
