{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://stackrivet.zkthink.com/schemas/module-manifest-v1.schema.json",
  "title": "StackRivet module manifest v1",
  "type": "object",
  "additionalProperties": false,
  "required": ["$schema", "schemaVersion", "id", "name", "version"],
  "properties": {
    "$schema": {
      "const": "https://stackrivet.zkthink.com/schemas/module-manifest-v1.schema.json"
    },
    "schemaVersion": { "const": 1 },
    "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]{0,127}$" },
    "name": { "type": "string", "minLength": 1, "maxLength": 256 },
    "version": { "type": "string", "minLength": 1, "maxLength": 64 },
    "description": { "type": ["string", "null"], "maxLength": 2048 },
    "dependsOn": { "$ref": "#/$defs/stringSet" },
    "capabilities": { "$ref": "#/$defs/stringSet" },
    "permissions": {
      "type": "array",
      "uniqueItems": true,
      "items": { "$ref": "#/$defs/permission" }
    },
    "menus": {
      "type": "array",
      "uniqueItems": true,
      "items": { "$ref": "#/$defs/menu" }
    },
    "migrations": { "$ref": "#/$defs/stringSet" },
    "publicApis": { "$ref": "#/$defs/stringSet" },
    "spi": { "$ref": "#/$defs/stringSet" },
    "spec": { "type": ["string", "null"], "maxLength": 512 },
    "aiRules": { "type": ["string", "null"], "maxLength": 512 },
    "generation": {
      "oneOf": [
        { "type": "null" },
        { "$ref": "#/$defs/generation" }
      ]
    }
  },
  "$defs": {
    "stringSet": {
      "type": "array",
      "uniqueItems": true,
      "items": { "type": "string", "minLength": 1 }
    },
    "permission": {
      "type": "object",
      "additionalProperties": false,
      "required": ["code", "name", "scope", "owner"],
      "properties": {
        "code": {
          "type": "string",
          "pattern": "^[A-Za-z][A-Za-z0-9_-]*:[A-Za-z][A-Za-z0-9_-]*:[A-Za-z][A-Za-z0-9_-]*$"
        },
        "name": { "type": "string", "minLength": 1, "maxLength": 256 },
        "scope": { "enum": ["global", "tenant", "row"] },
        "owner": { "type": "string", "pattern": "^[a-z][a-z0-9-]{0,127}$" }
      }
    },
    "menu": {
      "type": "object",
      "additionalProperties": false,
      "required": ["title", "path", "component", "permission"],
      "properties": {
        "title": { "type": "string", "minLength": 1, "maxLength": 256 },
        "path": {
          "type": "string",
          "pattern": "^/[^\\\\]*$",
          "maxLength": 256,
          "not": { "pattern": "\\.\\." }
        },
        "component": { "type": "string", "minLength": 1, "maxLength": 512 },
        "permission": {
          "type": "string",
          "pattern": "^[A-Za-z][A-Za-z0-9_-]*:[A-Za-z][A-Za-z0-9_-]*:[A-Za-z][A-Za-z0-9_-]*$"
        }
      }
    },
    "generation": {
      "type": "object",
      "additionalProperties": false,
      "required": ["templateId", "templateVersion", "sourceTable", "className", "resourcePath", "routeModule"],
      "properties": {
        "templateId": { "type": "string", "minLength": 1, "maxLength": 64 },
        "templateVersion": { "type": "string", "minLength": 1, "maxLength": 64 },
        "sourceTable": { "type": "string", "minLength": 1, "maxLength": 128 },
        "className": {
          "type": "string",
          "pattern": "^[A-Za-z][A-Za-z0-9]*$",
          "maxLength": 128
        },
        "resourcePath": {
          "type": "string",
          "pattern": "^/[^\\\\]*$",
          "maxLength": 256,
          "not": { "pattern": "\\.\\." }
        },
        "routeModule": { "type": "string", "minLength": 1, "maxLength": 512 }
      }
    }
  }
}
