# Verstak Plugin System ## 1. Цель Плагины превращают Верстак из монолитного приложения в платформу. Любая пользовательская функция должна быть реализуема как плагин: - заметки; - файловый менеджер; - редактор; - просмотрщик; - журнал; - активность; - браузерный inbox; - поиск; - секреты; - импорт; - шаблоны дел. ## 2. Структура плагина ```text official.notes/ plugin.json frontend/ index.js style.css backend/ plugin-linux-amd64 plugin-windows-amd64.exe migrations/ 001_init.sql assets/ README.md ``` Не каждый плагин обязан иметь frontend/backend/migrations. Manifest обязателен. ## 3. Manifest ```json { "schemaVersion": 1, "id": "official.notes", "name": "Notes", "version": "0.1.0", "apiVersion": "1", "description": "Markdown notes inside Verstak cases.", "source": "official", "provides": [ "workspace.notes", "entity.note" ], "requires": [ "vault.files" ], "optionalRequires": [ "editor.text.markdown", "preview.markdown", "search.provider" ], "permissions": [ "vault.read", "vault.write", "storage.namespace", "ui.register", "events.publish", "events.subscribe" ], "frontend": { "entry": "frontend/index.js", "style": "frontend/style.css" }, "backend": { "type": "sidecar", "entry": { "linux-amd64": "backend/plugin-linux-amd64", "windows-amd64": "backend/plugin-windows-amd64.exe" } }, "contributes": { "views": [], "commands": [], "settingsPanels": [] } } ``` ## 4. Capabilities Instead Of Plugin Names Плагины не должны требовать конкретный плагин, если им нужна способность. Плохо: ```json { "requires": ["official.markdown-editor"] } ``` Хорошо: ```json { "optionalRequires": ["editor.text.markdown"] } ``` Так можно заменить редактор, поставить два редактора или временно выключить предпросмотр без поломки файлового плагина. ## 5. Required And Optional Capabilities `requires` - без этих capabilities плагин не может работать. `optionalRequires` - без них плагин работает в degraded mode. Пример: ```text official.notes requires: vault.files optionalRequires: editor.text.markdown preview.markdown search.provider ``` Если нет `preview.markdown`, заметки работают, но кнопка предпросмотра не появляется. ## 6. Plugin States Core должен различать состояния: - `discovered` - manifest найден; - `disabled` - пользователь выключил; - `loading` - идет загрузка; - `loaded` - успешно загружен; - `degraded` - работает без optional capabilities; - `failed` - ошибка загрузки/запуска; - `incompatible` - неподдерживаемый apiVersion/schemaVersion; - `missing-required-capability` - не хватает обязательной capability. Состояние видно в Plugin Manager UI. ## 7. Lifecycle ```text discover validate manifest check compatibility check enabled state resolve required capabilities request permissions run migrations start backend sidecar load frontend bundle register capabilities register contributions activate deactivate shutdown ``` Lifecycle hooks: - `onInstall`; - `onEnable`; - `onVaultOpen`; - `onActivate`; - `onDeactivate`; - `onDisable`; - `onUninstall`; - `onShutdown`. ## 8. Contribution Points Плагин может регистрировать: - sidebar item; - main view; - case tab; - file action; - note action; - context menu item; - command palette command; - settings panel; - search provider; - activity provider; - importer; - exporter; - vault scanner; - protocol receiver. Contribution должен быть декларативным, где возможно. Runtime callbacks нужны только для поведения. ## 9. Plugin Settings Окно настроек плагинов - обязательная часть core. Плагин объявляет settings panels: ```json { "contributes": { "settingsPanels": [ { "id": "official.markdown-editor.general", "title": "Markdown Editor", "component": "settings.general" } ] } } ``` Plugin Manager показывает кнопку настроек только если у плагина есть settings panels. Настройки хранятся в namespace плагина: ```text plugin_settings.official.markdown-editor ``` Плагин не должен читать/писать настройки другого плагина без разрешения. ## 10. Enable/Disable Rules Выключение плагина: - убирает его UI contributions; - убирает commands/actions; - отзывает provided capabilities; - останавливает sidecar; - сохраняет данные плагина; - не удаляет пользовательские файлы; - публикует событие `plugin.disabled`. Включение плагина: - повторно проверяет совместимость; - выполняет pending migrations; - регистрирует contributions; - публикует событие `plugin.enabled`. Если другой плагин использовал optional capability выключенного плагина, он переходит в degraded mode. Если required capability исчезла, зависимый плагин должен быть деактивирован или переведен в failed/missing-required state. ## 11. Permissions Минимальный набор permissions: ```text vault.read vault.write vault.watch storage.namespace storage.migrations events.publish events.subscribe ui.register commands.register network.local network.remote process.spawn secrets.read secrets.write sync.participate ``` Опасные разрешения должны быть видны пользователю до включения плагина: - `network.remote`; - `process.spawn`; - `secrets.read`; - `vault.write`; - `sync.participate`. ## 12. Data Ownership Каждый плагин имеет namespace: ```text plugin_data// plugin_settings// plugin_cache// ``` Пользовательские данные должны отделяться от cache. Uninstall не должен автоматически удалять пользовательские данные без явного подтверждения. ## 13. Packaging Плагин распространяется как zip/tar package: ```text official.notes-0.1.0.vpkg ``` Пакет содержит: - `plugin.json`; - frontend bundle; - backend binaries if any; - migrations; - README; - checksums/signature later. На первом этапе допустима ручная установка папкой в plugin directory.