# `manifest.json`-Schema *(Quelle: `docs/core/module-requirements.md` §2/§3/§7, interne Details entfernt)* Jedes Modul-Paket enthält genau eine `manifest.json` im Wurzelverzeichnis. Vollständiges Beispiel (am Beispiel eines fiktiven SPAM-Filter-Moduls): ```json { "module_key": "spam_filter", "module_name": "SPAM-Filter", "version": "1.0.0", "requires_core": ">=2.0", "api_contract": "v1", "description": "KI-gestützte E-Mail-Klassifizierung für IMAP-Postfächer", "author": { "name": "Deine Firma", "contact": "dev@example.com" }, "db_schema": "mod_spam_filter", "roles": { "sa_features": ["global_prompts", "system_limits", "module_stats"], "ma_features": ["tenant_config", "llm_override", "email_templates", "user_permissions"], "user_permission": "write", "optional_user_gates": [ { "key": "can_override_classification", "label": "Darf KI-Klassifizierungen manuell überschreiben", "default": true } ] }, "llm_capable": true, "llm_prompt_keys": ["classify_email", "classify_batch"], "email_templates": ["spam_daily_digest", "spam_stuck_alert"], "widgets": [ { "id": "spam_pending_count", "type": "metric", "label": "Offene Klassifizierungen", "default_size": { "w": 1, "h": 1 }, "min_size": { "w": 1, "h": 1 }, "max_size": { "w": 2, "h": 2 }, "roles": ["superadmin", "tenant_admin", "user"], "refresh_interval_seconds": 60, "click_navigates_to": "spam-filter", "entry": "moduls/spam-filter/widgets/pending-count.js" } ], "frontend": { "pages": { "superadmin": "moduls/spam-filter/pages/sa-config.html", "tenant_admin": "moduls/spam-filter/pages/ma-config.html", "user": "moduls/spam-filter/pages/user-view.html" }, "nav_key": "spam-filter", "nav_label": "SPAM-Filter", "nav_icon": "🛡" }, "api_scopes": ["spam_filter.read", "spam_filter.write", "spam_filter.admin"], "external_hosts": [], "n8n": { "topology": "dispatcher-worker", "workflows": [ { "id": "spam-filter-api", "type": "api", "file": "workflows/hubrobotix-spam-filter-api.json", "schedule": null }, { "id": "spam-filter-dispatcher", "type": "scheduler", "file": "workflows/hubrobotix-spam-filter-dispatcher.json", "schedule": "*/10 * * * *" }, { "id": "spam-filter-worker", "type": "worker", "file": "workflows/hubrobotix-spam-filter-worker.json", "schedule": null } ] }, "install": { "migrations": ["db/schema.sql"], "seed_fake": "db/seed-fake.sql" }, "test_cases": [ { "id": "tc_pending_count", "description": "Widget pending-count gibt positive Integer zurück", "endpoint": "/spam-filter/stats/pending-count", "method": "GET", "scope": "spam_filter.read", "expect": { "status": 200, "body.count": ">= 0" } } ] } ``` ## Wichtigste Felder im Detail - **`module_key`**: eindeutig, muss vor Einreichung im Developer-Portal reserviert werden. - **`api_scopes`**: die **vollständige** Liste der Core-API-Scopes, die dein Modul je nutzt — die Prüf-Pipeline testet, dass du nie mehr nutzt als hier deklariert (Scope-Enforcement-Test). - **`external_hosts`**: jeder externe Host (Drittanbieter-API), den dein Modul-Code je aufruft, muss hier stehen — deine Modul-Instanz darf sonst netzwerkseitig nichts außer die Core-API erreichen. - **`n8n.topology`**: `single` (ein Workflow), `dispatcher-worker` (zwei gekoppelte Workflows) oder `queue` (echter n8n-Queue-Mode, braucht besondere Sandbox-Konfiguration — vorher anfragen). - **`test_cases[]`**: Pflicht, mindestens ein Testfall — läuft automatisch in Prüf-Stufe 4. Weiter mit [02-core-api-reference.md](02-core-api-reference.md).