{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://corecore.local/schemas/module-manifest.schema.json",
  "title": "Module Manifest Schema",
  "description": "Declarative schema for module.php manifest files under modules/<id>/.",
  "type": "object",
  "required": ["id"],
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "pattern": "^[a-z][a-z0-9_-]*$",
      "description": "Module identifier — must match the directory name under modules/."
    },
    "version": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$",
      "description": "Semantic version (e.g. 1.0.0)."
    },
    "enabled_by_default": {
      "type": "boolean",
      "default": false
    },
    "load_order": {
      "type": "integer",
      "default": 100,
      "description": "Lower values load first. Deterministic tie-break by id ASC."
    },
    "requires": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "uniqueItems": true,
      "default": [],
      "description": "Module IDs that must be enabled for this module to function."
    },
    "routes": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["path", "target"],
        "properties": {
          "path": { "type": "string", "minLength": 1 },
          "target": { "type": "string", "minLength": 1 },
          "public": { "type": "boolean", "default": false }
        },
        "additionalProperties": false
      },
      "default": []
    },
    "public_paths": {
      "type": "array",
      "items": { "type": "string" },
      "default": []
    },
    "container_registrars": {
      "type": "array",
      "items": { "type": "string", "minLength": 1, "description": "FQCN of a ContainerRegistrar." },
      "default": []
    },
    "ui_slots": {
      "description": "Keyed by slot name (e.g. 'aside.tab_panel'). Values are arrays of contribution objects.",
      "anyOf": [
        {
          "type": "object",
          "patternProperties": {
            "^.+$": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["key"],
                "properties": {
                  "key": { "type": "string", "minLength": 1 },
                  "label": { "type": "string" },
                  "icon": { "type": "string" },
                  "href": { "type": "string" },
                  "permission": { "type": "string" },
                  "panel_template": { "type": "string" },
                  "template": { "type": "string" },
                  "path": { "type": "string" },
                  "script": { "type": "string" },
                  "export": { "type": "string" },
                  "selector": { "type": "string" },
                  "scope": { "type": "string" },
                  "config_path": { "type": "string" },
                  "default_config": {
                    "anyOf": [
                      { "type": "object" },
                      { "type": "array", "maxItems": 0 }
                    ]
                  },
                  "phase": { "type": "string", "enum": ["early", "default", "late"] },
                  "type": { "type": "string" },
                  "order": { "type": "integer", "default": 100 },
                  "details_storage": { "type": "string" },
                  "details_open_active": { "type": "boolean" },
                  "base_url": { "type": "string" },
                  "group": { "type": "string", "description": "Sidebar nav group key for grouping related items under a details/summary section." }
                }
              }
            }
          }
        },
        {
          "type": "array",
          "maxItems": 0
        }
      ],
      "default": {}
    },
    "search_resources": {
      "type": "array",
      "items": { "type": "string", "minLength": 1, "description": "FQCN of a SearchResourceProvider." },
      "default": []
    },
    "asset_groups": {
      "description": "Asset group name → file list.",
      "anyOf": [
        {
          "type": "object",
          "patternProperties": {
            "^.+$": {
              "type": "array",
              "items": { "type": "string" }
            }
          }
        },
        {
          "type": "array",
          "maxItems": 0
        }
      ],
      "default": {}
    },
    "layout_context_providers": {
      "type": "array",
      "items": { "type": "string", "minLength": 1, "description": "FQCN of a LayoutContextProvider." },
      "default": []
    },
    "session_providers": {
      "type": "array",
      "items": { "type": "string", "minLength": 1, "description": "FQCN of a SessionProvider." },
      "default": []
    },
    "authorization_policies": {
      "type": "array",
      "items": { "type": "string", "minLength": 1, "description": "FQCN of an AuthorizationPolicyInterface." },
      "default": []
    },
    "permissions": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["key", "description"],
        "properties": {
          "key": { "type": "string", "minLength": 1 },
          "description": { "type": "string", "minLength": 1 },
          "active": { "type": ["boolean", "integer"], "default": true },
          "is_system": { "type": ["boolean", "integer"], "default": true }
        },
        "additionalProperties": false
      },
      "default": []
    },
    "scheduler_jobs": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "job_key", "handler", "label", "description",
          "default_enabled", "default_timezone", "default_schedule_type",
          "default_schedule_interval", "default_schedule_time",
          "default_schedule_weekdays_csv", "default_catchup_once",
          "allowed_schedule_types"
        ],
        "properties": {
          "job_key": { "type": "string", "minLength": 1 },
          "handler": { "type": "string", "minLength": 1 },
          "label": { "type": "string", "minLength": 1 },
          "description": { "type": "string", "minLength": 1 },
          "default_enabled": { "type": ["boolean", "integer"] },
          "default_timezone": { "type": "string", "minLength": 1 },
          "default_schedule_type": { "type": "string", "enum": ["hourly", "daily", "weekly"] },
          "default_schedule_interval": { "type": "integer" },
          "default_schedule_time": { "type": ["string", "null"] },
          "default_schedule_weekdays_csv": { "type": ["string", "null"] },
          "default_catchup_once": { "type": ["boolean", "integer"] },
          "allowed_schedule_types": {
            "type": "array",
            "items": { "type": "string", "enum": ["hourly", "daily", "weekly"] },
            "minItems": 1
          }
        },
        "additionalProperties": false
      },
      "default": []
    },
    "event_listeners": {
      "description": "Event name → list of listener descriptors.",
      "anyOf": [
        {
          "type": "object",
          "patternProperties": {
            "^.+$": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["class", "method"],
                "properties": {
                  "class": { "type": "string", "minLength": 1, "description": "FQCN implementing EventListener." },
                  "method": { "type": "string", "minLength": 1 }
                },
                "additionalProperties": false
              }
            }
          }
        },
        {
          "type": "array",
          "maxItems": 0
        }
      ],
      "default": {}
    },
    "deactivation_handler": {
      "type": ["string", "null"],
      "description": "FQCN of a ModuleDeactivationHandler. Null if no cleanup needed.",
      "default": null
    },
    "migrations_path": {
      "type": ["string", "null"],
      "description": "Relative path to SQL migration scripts. Resolved against module basePath.",
      "default": null
    },
    "i18n_path": {
      "type": ["string", "null"],
      "description": "Relative path to i18n translation files. Resolved against module basePath.",
      "default": null
    }
  },
  "additionalProperties": false
}
