{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://glixo.dev/schemas/glixo.module.schema.json",
  "title": "Glixo Module Manifest",
  "description": "Module/host handshake contract (glixo.module.json). A module declares what it provides (capabilities), the platform services it requires, and how it is installed; the host validates and grants only what is declared.",
  "type": "object",
  "additionalProperties": true,
  "required": ["id", "name", "version", "protocolVersion", "runtime", "entry", "capabilities", "artifacts"],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9.-]{1,127}$",
      "description": "Stable module id, e.g. glixo.messaging.teams."
    },
    "name": { "type": "string", "minLength": 1 },
    "description": { "type": "string" },
    "icon": {
      "type": "string",
      "minLength": 1,
      "description": "Extension icon path, URL, data URL, or host icon id. Hosts may restrict which forms they render."
    },
    "version": { "type": "string", "minLength": 1 },
    "kind": {
      "type": "string",
      "enum": ["module", "service", "extension", "app", "theme"],
      "description": "Authoring role hint only. Runtime ownership is determined by components, requires, capabilities, and contributions."
    },
    "protocolVersion": { "type": "string", "description": "Host/module protocol version. Currently \"0\"." },
    "runtime": {
      "type": "object",
      "required": ["kind"],
      "properties": {
        "kind": {
          "type": "string",
          "enum": ["dotnet", "node", "python", "native", "http", "container", "go", "java", "ruby"]
        },
        "version": { "type": "string" }
      }
    },
    "entry": {
      "type": "object",
      "required": ["command"],
      "properties": {
        "command": { "type": "string", "minLength": 1 },
        "workingDirectory": { "type": "string" },
        "args": { "type": "array", "items": { "type": "string" } }
      }
    },
    "capabilities": {
      "type": "array",
      "minItems": 1,
      "items": { "type": "string", "minLength": 1 },
      "description": "Capabilities the module PROVIDES. Capabilities a module USES go in `requires` as capability.<id>."
    },
    "requires": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "not": {
          "anyOf": [
            { "pattern": "^relationalDb\\.(?!module$).+" },
            { "pattern": "sharedReadModel" },
            { "pattern": "[Ss]hared[ ._-]?([Ss][Qq][Ll]|[Tt]able|[Vv]iew|[Rr]ead|[Qq]uery|[Mm]odel)" },
            { "pattern": "hostInternalQuery" }
          ]
        }
      },
      "description": "Platform services and scoped requirements the module CONSUMES. Roots: logging, health, storage, relationalDb, config, secrets, notifications, jobs, ui, workers, capabilities, events. Allowed scoped forms: relationalDb.module (relationalDb is PRIVATE module persistence only), secrets.<scope>, capability.<id> (capability USES), events / events.<topic> (subscriptions), storage.<area>. Public modules MUST NOT request shared SQL or shared read models: relationalDb.shared (or relationalDb.<anything-but-module>), sharedReadModel, shared tables/views/queries, and hostInternalQuery are rejected. Shared data flows through events + host capabilities (e.g. capability.glixo.messages.get)."
    },
    "components": {
      "type": "array",
      "description": "Multi-component modules declare their components here; the Manager installs each into its cell (server | client | target), composed by Aspire. Omit for a single server-cell module that uses the top-level runtime/entry/requires/capabilities. Cross-component data flows through events + host capabilities, never a shared relationalDb.",
      "items": {
        "type": "object",
        "required": ["id", "cell"],
        "additionalProperties": true,
        "properties": {
          "id": { "type": "string", "minLength": 1, "description": "Component id within the module, e.g. server | relay | viewer | capture." },
          "cell": { "type": "string", "enum": ["server", "client", "target"], "description": "The Aspire cell the Manager installs this component into." },
          "scope": { "type": "string", "enum": ["server", "user", "machine", "project"], "description": "Execution/data scope; defaults from the cell (server->server, client->user, target->machine)." },
          "placement": {
            "type": "object",
            "description": "Install-time placement policy for this component. The manifest declares what is allowed; Manager stores the resolved install plan separately, e.g. selected machine IDs for target components.",
            "required": ["kind"],
            "additionalProperties": true,
            "properties": {
              "kind": {
                "type": "string",
                "enum": ["server", "user", "workspace", "session", "currentMachine", "selectedMachines", "allMachines"]
              },
              "required": { "type": "boolean" },
              "selector": { "type": "string", "description": "Optional machine/capability selector expression, e.g. os == 'windows'." },
              "prompt": { "type": "string" },
              "minTargets": { "type": "integer", "minimum": 0 },
              "maxTargets": { "type": "integer", "minimum": 1 },
              "defaultEnabled": { "type": "boolean" }
            }
          },
          "defaultEnabled": { "type": "boolean" },
          "runtime": { "type": "string", "enum": ["dotnet", "node", "python", "native", "http", "container", "go", "java", "ruby"], "description": "Runtime kind for this component." },
          "entry": {
            "type": "object",
            "properties": {
              "command": { "type": "string", "minLength": 1 },
              "workingDirectory": { "type": "string" },
              "args": { "type": "array", "items": { "type": "string" } }
            }
          },
          "requires": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "not": {
                "anyOf": [
                  { "pattern": "^relationalDb\\.(?!module$).+" },
                  { "pattern": "sharedReadModel" },
                  { "pattern": "[Ss]hared[ ._-]?([Ss][Qq][Ll]|[Tt]able|[Vv]iew|[Rr]ead|[Qq]uery|[Mm]odel)" },
                  { "pattern": "hostInternalQuery" }
                ]
              }
            },
            "description": "Platform services / scoped requirements this component CONSUMES. Same rules as the top-level `requires`: no shared SQL or shared read models; cross-component data flows via events + host capabilities."
          },
          "capabilities": {
            "type": "array",
            "items": { "type": "string", "minLength": 1 },
            "description": "Capabilities this component PROVIDES."
          }
        }
      }
    },
    "permissions": {
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "description": "Host/OS permissions the module needs (e.g. network.microsoft-graph, filesystem.workspace)."
    },
    "images": {
      "type": "array",
      "description": "Product screenshots or preview images shown by Manager, app hosts, and the dev portal.",
      "items": {
        "type": "object",
        "required": ["url"],
        "additionalProperties": true,
        "properties": {
          "url": { "type": "string", "minLength": 1 },
          "alt": { "type": "string" },
          "caption": { "type": "string" },
          "type": { "type": "string", "enum": ["screenshot", "logo", "hero", "thumbnail", "diagram"] }
        }
      }
    },
    "changelog": {
      "type": "object",
      "description": "Release notes shown before install or update.",
      "additionalProperties": true,
      "properties": {
        "url": { "type": "string" },
        "entries": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["version"],
            "additionalProperties": true,
            "properties": {
              "version": { "type": "string", "minLength": 1 },
              "date": { "type": "string" },
              "title": { "type": "string" },
              "description": { "type": "string" }
            }
          }
        }
      }
    },
    "health": {
      "type": "object",
      "properties": {
        "path": { "type": "string" },
        "intervalSeconds": { "type": "integer", "minimum": 5, "maximum": 3600 }
      }
    },
    "ui": {
      "type": "object",
      "properties": {
        "schema": { "type": "string" },
        "component": { "type": "string" }
      }
    },
    "contributes": {
      "type": "object",
      "additionalProperties": true,
      "description": "Declarative extension points consumed by apps and Manager: routes, actions, sidebars, context menus, view patches, data sources, AI context providers, settings panels, Agxos apps, agent skills, and agent tools.",
      "properties": {
        "capabilities": { "type": "array", "items": { "type": "string", "minLength": 1 } },
        "routes": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "actions": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "contextMenuItems": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "sidebarViews": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "viewPatches": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "settingsPanels": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "dataSources": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "aiContextProviders": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "llmProviders": {
          "type": "array",
          "description": "Installable LLM provider definitions. Requires capability.glixo.llmProviders.register.",
          "items": {
            "type": "object",
            "required": ["id", "label", "adapter", "credentialFields"],
            "additionalProperties": true,
            "properties": {
              "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9.-]{1,127}$" },
              "label": { "type": "string", "minLength": 1 },
              "description": { "type": "string" },
              "icon": { "type": "string" },
              "adapter": { "type": "string", "enum": ["openai-compatible", "openai", "openai-oauth", "anthropic"] },
              "credentialFields": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": ["id", "label", "type"],
                  "additionalProperties": true,
                  "properties": {
                    "id": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_.-]{0,127}$" },
                    "label": { "type": "string", "minLength": 1 },
                    "type": { "type": "string", "enum": ["url", "secret", "text", "oauth"] },
                    "required": { "type": "boolean" },
                    "secret": { "type": "boolean" },
                    "helpText": { "type": "string" },
                    "defaultValue": { "type": "string" }
                  }
                }
              },
              "modelDiscovery": {
                "type": "object",
                "required": ["kind"],
                "additionalProperties": true,
                "properties": {
                  "kind": { "type": "string", "enum": ["openai-compatible-models"] },
                  "path": { "type": "string" }
                }
              },
              "modelRouting": {
                "type": "object",
                "additionalProperties": true,
                "properties": {
                  "families": { "type": "array", "items": { "type": "string", "minLength": 1 } },
                  "patterns": { "type": "array", "items": { "type": "string", "minLength": 1 } },
                  "servesAllFamilies": { "type": "boolean" }
                }
              },
              "capabilities": {
                "type": "array",
                "items": { "type": "string", "enum": ["chat", "streaming", "tools", "images", "reasoning"] }
              }
            }
          }
        },
        "agxos": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "apps": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["id", "name", "template"],
                "additionalProperties": true,
                "properties": {
                  "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,79}$" },
                  "name": { "type": "string", "minLength": 1 },
                  "icon": { "type": "string" },
                  "accent": { "type": "string" },
                  "template": { "type": "string", "enum": ["chat", "note", "terminal", "list", "app"] },
                  "entry": { "type": "string", "minLength": 1, "description": "Client component entry for a real coded app (template 'app')." },
                  "mobileUi": {
                    "oneOf": [
                      { "type": "boolean" },
                      { "type": "string", "enum": ["adaptive", "dedicated"] }
                    ],
                    "description": "Mobile layout mode: true/adaptive (default reflow) or dedicated (separate mobile component)."
                  },
                  "mobileEntry": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Dedicated mobile component entry URL (template app only)."
                  },
                  "width": { "type": "integer", "minimum": 1 },
                  "height": { "type": "integer", "minimum": 1 },
                  "actions": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": ["id"],
                      "additionalProperties": true,
                      "properties": {
                        "id": { "type": "string", "pattern": "^[a-z0-9_]{1,40}$" },
                        "description": { "type": "string" }
                      }
                    }
                  },
                  "fileAssociations": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": ["extensions"],
                      "additionalProperties": true,
                      "properties": {
                        "extensions": { "type": "array", "minItems": 1, "items": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9.+-]*$" } },
                        "mimeTypes": { "type": "array", "items": { "type": "string", "minLength": 1 } },
                        "role": { "type": "string", "enum": ["default", "editor", "viewer"] }
                      }
                    }
                  },
                  "deepLinks": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": ["scheme"],
                      "additionalProperties": true,
                      "properties": {
                        "scheme": { "type": "string", "pattern": "^agxos-[a-z0-9-]+$" },
                        "description": { "type": "string" }
                      }
                    }
                  },
                  "permissions": { "type": "array", "items": { "type": "string" } }
                }
              }
            },
            "trayEntries": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["id", "title"],
                "additionalProperties": true,
                "properties": {
                  "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,79}$" },
                  "title": { "type": "string", "minLength": 1 },
                  "icon": { "type": "string" },
                  "command": { "type": "string" }
                }
              }
            },
            "windowActions": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["id", "appId", "command"],
                "additionalProperties": true,
                "properties": {
                  "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,79}$" },
                  "title": { "type": "string" },
                  "icon": { "type": "string" },
                  "appId": { "type": "string", "minLength": 1 },
                  "command": { "type": "string", "enum": ["show", "hide", "bringToFront", "close"] }
                }
              }
            },
            "themes": {
              "type": "array",
              "description": "Agxos themes contributed from agxos-scoped manifests.",
              "items": { "$ref": "#/$defs/themeContribution" }
            }
          }
        },
        "skills": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "tools": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
        "themes": {
          "type": "array",
          "description": "Theme modules: a token bundle (+ optional wallpaper) selectable in Settings → Themes.",
          "items": { "$ref": "#/$defs/themeContribution" }
        },
        "settingsTabs": {
          "type": "array",
          "description": "Settings tabs contributed via Settings.addTab (the app-API registry).",
          "items": {
            "type": "object",
            "required": ["id", "title"],
            "additionalProperties": true,
            "properties": {
              "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,79}$" },
              "title": { "type": "string", "minLength": 1 },
              "icon": { "type": "string" },
              "order": { "type": "integer" },
              "group": { "type": "string" },
              "component": { "type": "string", "minLength": 1 }
            }
          }
        },
        "fileTypes": {
          "type": "array",
          "description": "File-type → app defaults this extension provides (Default Apps registry).",
          "items": {
            "type": "object",
            "required": ["extensions", "appId"],
            "additionalProperties": true,
            "properties": {
              "extensions": { "type": "array", "minItems": 1, "items": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9.+-]*$" } },
              "mimeTypes": { "type": "array", "items": { "type": "string", "minLength": 1 } },
              "appId": { "type": "string", "minLength": 1 },
              "role": { "type": "string", "enum": ["default", "editor", "viewer"] }
            }
          }
        }
      }
    },
    "config": {
      "type": "object",
      "properties": {
        "fields": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["key", "label", "type"],
            "properties": {
              "key": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_.-]{0,127}$" },
              "label": { "type": "string" },
              "type": { "type": "string", "enum": ["text", "secret", "number", "checkbox", "select", "path"] },
              "required": { "type": "boolean" },
              "helpText": { "type": "string" },
              "defaultValue": { "type": "string" },
              "options": { "type": "array", "items": { "type": "string" } }
            }
          }
        }
      }
    },
    "artifacts": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["rid", "url", "sha256"],
        "properties": {
          "rid": { "type": "string", "minLength": 1 },
          "url": { "type": "string", "minLength": 1 },
          "sha256": { "type": "string", "minLength": 1 }
        }
      }
    },
    "updateChannels": {
      "type": "array",
      "items": { "type": "string", "enum": ["dev", "stable", "beta", "canary"] }
    }
  },
  "$defs": {
    "themeAssetLicense": {
      "type": "object",
      "required": ["spdx", "source", "attribution"],
      "additionalProperties": true,
      "properties": {
        "spdx": {
          "type": "string",
          "enum": ["Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "CC-BY-4.0", "CC0-1.0", "ISC", "MIT", "Unlicense"]
        },
        "source": { "type": "string", "minLength": 1 },
        "attribution": { "type": "string", "minLength": 1 }
      }
    },
    "themeContribution": {
      "type": "object",
      "required": ["id", "name", "tokens"],
      "additionalProperties": true,
      "properties": {
        "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,79}$" },
        "name": { "type": "string", "minLength": 1 },
        "tokens": { "type": "object", "description": "Theme color/spacing tokens keyed by slot." },
        "wallpaper": { "type": "string", "description": "Optional wallpaper asset (relative path, URL, color, or CSS gradient)." },
        "cursor": { "type": "string", "description": "Optional cursor asset path or URL." },
        "license": { "$ref": "#/$defs/themeAssetLicense" },
        "assets": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "wallpaper": {
              "type": "object",
              "additionalProperties": true,
              "properties": {
                "license": { "$ref": "#/$defs/themeAssetLicense" }
              }
            },
            "cursor": {
              "type": "object",
              "additionalProperties": true,
              "properties": {
                "license": { "$ref": "#/$defs/themeAssetLicense" }
              }
            }
          }
        }
      }
    }
  }
}
