# Plugin architecture Extends ADR 0008 with the concrete contracts implementers need. ## Package format A plugin is a ZIP archive: ``` my-plugin.zip ├── manifest.json (required) ├── plugin.js (required for kind=code; single ES module bundle) ├── styles.css (optional; required for kind=section_style) ├── i18n/de.json (optional UI strings) ├── i18n/en.json └── assets/… (optional images etc.) ``` ### `manifest.json` ```json { "id": "toc", "name": "Table of Contents", "version": "1.2.0", "apiVersion": "1", "kind": "code", "extensionPoints": [ { "type": "pageTool", "id": "toc", "title": { "de": "Inhaltsverzeichnis", "en": "Table of contents" } } ], "permissions": ["readCurrentPage"], "fallback": { "type": "text", "value": "[Table of contents]" }, "license": "MIT", "homepage": "https://…" } ``` - `apiVersion`: host checks against its supported range at install time. - `permissions`: the capabilities the plugin may call (see API below); shown to the Site Admin at install time. Requests outside the declared set are rejected at runtime. - `fallback`: static representation used in Word/PDF exports and when the plugin is disabled but its blocks still exist in documents. ## Kinds and extension points | Kind | Extension point | What it does | Sandbox | | --- | --- | --- | --- | | `section_style` | `sectionStyle` | declares named styles (name, i18n label, CSS class body) applicable to container blocks — e.g. colored background boxes | none needed: CSS is sanitized (no `@import`, no `url()` to external hosts) and scoped under `.dt-style--` | | `code` | `block` | a custom editor block (diagram, embed, …); host registers a ProseMirror node `plugin_block` instance with `pluginId`, `blockType`, `data` attrs | sandboxed iframe per block | | `code` | `pageTool` | read-only widget rendered in the page tools panel or embedded as a block (TOC, page index, cross-page block embed) | sandboxed iframe | ## Sandbox runtime - Each code-plugin surface runs in `