fix: второй стабилизационный проход Lua plugin lifecycle

1. Enabled/Active state separation:
   - Enable() sets Enabled=true (persisted in config), does NOT create runtime
   - ActivatePlugin() checks Enabled && !Active, creates VM + scheduler
   - DeactivatePlugin() stops runtime, keeps Enabled=true
   - InitRuntimes() iterates Enabled plugins, sets Active=true after creation
   - SyncConfig() restores Enabled from config, does NOT touch Active

2. ActivatePlugin: добавлен vm.SetServices(m.Services)

3. Discover: атомарная замена списка (newPlugins slice), нет дублирования

4. CallPluginFunction: thread-safe через LuaVM.CallFunction (vm.mu + callWithTimeout)

5. Uninstall активного плагина: полная деактивация (StopScheduler → on_shutdown → CloseVM → Active=false)

6. GetPluginPanelHTML: валидация panel path (no absolute, no .., must be .html, must be within plugin dir)

7. PluginPage: убран hardcoded 'calendar-plugin', используется funcPrefix из pluginName

Тесты:
- security_test.go: +8 тестов (FullLifecycle, ActivatePlugin_Services, Discover_Idempotent,
  ReloadPlugins_NoDuplicates, CallPluginFunction_Timeout, Uninstall_ActivePlugin,
  GetPluginPanelHTML_PathTraversal, FullLifecycle_EndToEnd)
- manager_test.go: обновлены тесты под новую семантику Enabled/Active
This commit is contained in:
2026-06-07 20:49:43 +08:00
parent 4df83cd361
commit d83c8c80e1
10 changed files with 654 additions and 107 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -19,7 +19,7 @@
background: #13131f;
}
</style>
<script type="module" crossorigin src="/assets/main-9sLWbwBV.js"></script>
<script type="module" crossorigin src="/assets/main-8qmy5tDO.js"></script>
<link rel="stylesheet" crossorigin href="/assets/main-Cjkp2F09.css">
</head>
<body>