{
  "$id": "https://uape.dev/schemas/contract-manifest-1.0.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Contract Manifest",
  "description": "Signed declaration of a UAPE module's identity, capabilities, storage topology, gateway bindings, and audit obligations.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "manifest_version",
    "module",
    "runtime",
    "capabilities",
    "storage",
    "audit"
  ],
  "properties": {
    "manifest_version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+$",
      "description": "Semver MAJOR.MINOR of THIS document's schema. Current: 1.0."
    },
    "module": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name", "version", "description"],
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "description": "UUIDv4. Stable across versions of the same module."
        },
        "name": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9-]{1,62}[a-z0-9]$"
        },
        "version": {
          "type": "string",
          "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?$"
        },
        "description": {
          "$ref": "#/$defs/LocalizedString",
          "description": "Either a plain string (English) or an object keyed by BCP-47 locale tag. `en` is mandatory when the object form is used. ADR-0015 / LE-002."
        },
        "authors": {
          "type": "array",
          "items": { "type": "string", "maxLength": 256 },
          "maxItems": 32
        },
        "license": { "type": "string", "maxLength": 128 },
        "artifact_path": {
          "type": "string",
          "minLength": 1,
          "maxLength": 512,
          "description": "Workspace-relative path to the compiled WASM component artefact produced by `cargo xtask build-modules`. Optional: when absent the kernel falls back to its discovery rules (see docs/runbooks/wasm-build.md)."
        }
      }
    },
    "runtime": {
      "type": "object",
      "additionalProperties": false,
      "required": ["engine", "fuel_per_invocation", "epoch_deadline_ms", "memory_mb"],
      "properties": {
        "engine": { "type": "string", "enum": ["wasmtime"] },
        "host_abi": {
          "type": "string",
          "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
          "description": "Required host ABI version. Kernel refuses load if its host version is incompatible."
        },
        "fuel_per_invocation": { "type": "integer", "minimum": 1000, "maximum": 10000000000 },
        "epoch_deadline_ms": { "type": "integer", "minimum": 1, "maximum": 60000 },
        "memory_mb": { "type": "integer", "minimum": 1, "maximum": 4096 },
        "wasm_simd": { "type": "boolean", "default": true }
      }
    },
    "capabilities": {
      "type": "array",
      "minItems": 0,
      "maxItems": 256,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["namespace", "name", "scope"],
        "properties": {
          "namespace": {
            "type": "string",
            "enum": [
              "daimon:host/storage",
              "daimon:host/clock",
              "daimon:host/random",
              "daimon:host/audit",
              "daimon:host/yield",
              "daimon:host/log",
              "daimon:host/i18n",
              "daimon:host/projection"
            ]
          },
          "name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
          "scope": {
            "type": "string",
            "pattern": "^(module|shared:[0-9a-f-]{36}:[a-zA-Z0-9_-]+)$",
            "description": "'module' or 'shared:<module-uuid>:<entity-name>'. Wildcards forbidden."
          },
          "entities": {
            "type": "array",
            "description": "Optional per-entity grain for daimon:host/storage and daimon:host/projection capabilities (ADR-0010 §Per-entity grain, ADR-0016). Each entry expands to a host:storage:<entity> or host:projection:<entity> module-axis policy. Omit to keep wildcard :* behaviour.",
            "items": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_]*$" },
            "maxItems": 256
          }
        }
      }
    },
    "storage": {
      "type": "object",
      "additionalProperties": false,
      "required": ["topology"],
      "properties": {
        "topology": {
          "oneOf": [
            { "$ref": "storage-topology.schema.json" },
            { "type": "object", "required": ["$ref"], "properties": { "$ref": { "type": "string" } }, "additionalProperties": false }
          ]
        },
        "data_sharing": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["source_module_id", "entity", "access"],
            "properties": {
              "source_module_id": { "type": "string", "format": "uuid" },
              "entity": { "type": "string" },
              "access": { "type": "string", "enum": ["read"] }
            }
          }
        },
        "shared_scope": {
          "type": "string",
          "description": "Opt-in to a deterministic cross-module storage namespace (ADR-0010 §Shared storage scope). Modules declaring the same shared_scope share the same EntityKey::module_id derived as UUIDv5 of this label under the SHARED_STORAGE_SCOPE_NS namespace. Omit for full isolation.",
          "pattern": "^[a-z][a-z0-9_-]*$",
          "minLength": 1,
          "maxLength": 64
        },
        "projections": {
          "type": "array",
          "description": "Declarative DLF L1 projections (ADR-0016). Each entry asks the kernel to maintain an in-memory projection of the named entity, rebuilt from L0 at boot and updated on commit. The target entity must exist in storage.topology.entities.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["entity", "kind"],
            "properties": {
              "entity": { "type": "string", "pattern": "^[A-Z][A-Za-z0-9]+$" },
              "kind": { "type": "string", "enum": ["vector", "graph", "document", "columnar"] }
            }
          }
        }
      }
    },
    "gateways": {
      "type": "array",
      "items": { "$ref": "gateway.schema.json" }
    },
    "audit": {
      "type": "object",
      "additionalProperties": false,
      "required": ["required_events"],
      "properties": {
        "required_events": {
          "type": "array",
          "items": { "type": "string", "pattern": "^[A-Z][A-Za-z0-9]+$" },
          "minItems": 0,
          "maxItems": 256
        },
        "allowed_events": {
          "type": "array",
          "items": { "type": "string", "pattern": "^[A-Z][A-Za-z0-9]+$" },
          "maxItems": 1024
        }
      }
    },
    "autopoietic": {
      "$ref": "autopoietic-trigger.schema.json"
    },
    "migrations": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["from_version", "to_version", "adr_ref"],
        "properties": {
          "from_version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
          "to_version":   { "type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
          "adr_ref":      { "type": "string", "pattern": "^docs/adr/[0-9]{4}-[a-z0-9-]+\\.md$" },
          "ops": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "required": ["kind"],
              "properties": {
                "kind": { "type": "string", "enum": ["add_field", "remove_field", "rename_field", "widen_type", "backfill"] }
              }
            }
          }
        }
      }
    },
    "signer_pubkey": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "Hex Ed25519 public key. MUST be enrolled in infra/security/trusted-signers.toml."
    },
    "valid_until": {
      "type": ["string", "null"],
      "format": "date-time",
      "description": "RFC 3339 UTC expiry timestamp. Kernel rejects the manifest at load time when current time >= valid_until. Part of the signed surface (ADR-0012 §SLA)."
    },
    "signature": {
      "type": ["string", "null"],
      "pattern": "^[0-9a-f]{128}$",
      "description": "Hex Ed25519 signature over RFC-8785-canonical JSON of all fields except 'signature' itself."
    }
  },
  "$defs": {
    "LocalizedString": {
      "description": "Either a plain English string or an object keyed by BCP-47 locale tags. The `en` key is mandatory in the object form and serves as the fallback when the requested locale is missing. ADR-0015 / LE-002.",
      "oneOf": [
        { "type": "string", "minLength": 1, "maxLength": 2048 },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["en"],
          "patternProperties": {
            "^[a-z]{2}(-[A-Z]{2})?$": { "type": "string", "minLength": 1, "maxLength": 2048 }
          },
          "minProperties": 1
        }
      ]
    }
  }
}
