Commit Graph

107 Commits (c1434a0b61a20772dc47bd9a4bda2aae668e4cea)

Author SHA1 Message Date
mirivlad 21130c6f1e debug: log typeof events and JSON.stringify in both parent and iframe 2026-06-08 13:57:45 +08:00
mirivlad 4a5dab49b5 debug: add try-catch around iframe render() to catch any JS errors 2026-06-08 13:43:13 +08:00
mirivlad c03e2e2961 debug: add WriteDebugLog after postToIframe to confirm delivery 2026-06-08 12:31:45 +08:00
mirivlad 35e23d75fa debug: add step-by-step logging in loadCalendarData to trace where error occurs 2026-06-08 12:23:51 +08:00
mirivlad 5069472e19 debug: add logging to get_categories + better error details in CalendarPluginPage 2026-06-08 12:01:29 +08:00
mirivlad f769daa617 fix(plugins): JSON-serialize CallFunctionJSON return values + backward compat Lua args
Root cause: CallFunctionJSON used .String() on Lua return values, which
for tables produces 'table: 0x...' — not valid JSON. Frontend does
JSON.parse() on the result and silently caught the parse error.

Fix:
- runtime.go: convert Lua return value to JSON via luaValueToGo +
  json.Marshal so tables become proper JSON arrays/objects
- main.lua: add backward compat in get_events() and update_event()
  to accept both positional args (start, end) and table params
- CalendarPluginPage.svelte: show errors in UI instead of silent catch;
  restructure template to always show iframe + error overlay
2026-06-08 11:31:18 +08:00
mirivlad fddbd3a98a fix calendar: table params for Lua functions + remove duplicate header
- CalendarPluginPage.svelte: removed <h2>pluginName — pageLabel</h2> (AppHeader already shows title)
- main.lua: all API functions now accept a single table parameter:
  - get_events(params) — reads params.start_date or params.start
  - get_event(params) — reads params.id
  - update_event(params) — reads params.id + mutable fields
  - delete_event(params) — reads params.id
  - get_expanded_events(params), get_calendar_events(params) — same
  - get_events_day(params) — reads params.date
  - create_event(opts) — already worked, no change
- Backward compatible: get_events accepts both start/start_date and end/end_date keys
2026-06-08 11:18:28 +08:00
mirivlad b1d1defebe release infra: build scripts, Firefox signing, plugin fixes
- .gitignore: release/, .env, *.xpi, node_modules/
- .env.example: template for AMO credentials
- extension-firefox/package.json: web-ext scripts (lint, sign)
- extension-firefox/manifest.json: gecko.id + update_url + data_collection_permissions
- scripts/build.sh: renamed binaries (verstak, verstak-server), release target
- scripts/sign-firefox-xpi.sh: AMO signing with --self-hosted
- scripts/release-firefox-xpi.sh: signed XPI + updates.json generation
- scripts/release.sh: full release pipeline (DEB/RPM/checksums/git tag)
- VERSION: 0.1.0
- README.md: Firefox extension & release sections

Plugin fixes:
- internal/core/plugins/manager.go: auto-create .verstak/plugins/ dir
- frontend/src/lib/SettingsSidebar.svelte: remove 'plugins' from disabled + active left border
- frontend/src/lib/SettingsPlugins.svelte: force ListPlugins refresh on toggle
- frontend/src/lib/SettingsWindow.svelte: onPluginToggle callback
- frontend/src/App.svelte: refreshSystemViews on plugin toggle
- frontend/src/lib/CalendarPluginPage.svelte: visible error icon
2026-06-08 11:07:29 +08:00
mirivlad 45cfe1b0a6 fix: финальный cleanup Lua plugin lifecycle
1. ActivatePlugin → error return:
   - Возвращает ошибки при создании VM, загрузке main.lua, scheduler setup
   - on_init failure = non-fatal (logged, activation continues)
   - SetPluginEnabled сохраняет EnabledPlugins в config ТОЛЬКО после успешной активации
   - При ошибке активации — rollback (deactivate + не сохраняем в config)

2. CallPluginFunction fully thread-safe:
   - Новый метод LuaVM.CallFunctionJSON(segments, paramsJSON)
   - JSON→Lua conversion происходит под vm.mu (внутри lock)
   - Убраны parseParamsToLua/goToLua из bindings_plugins.go
   - goToLua перенесён в runtime.go (под lock)

3. PluginPage → CalendarPluginPage:
   - Компонент явно календарный (get-events/create-event/update-event/delete-event)
   - Переименован для ясности
   - Console log префиксы обновлены

4. Тесты:
   - TestSetPluginEnabled_ActivateFails_NoConfigSave: проверяет что при ошибке
     активации плагин НЕ сохраняется в EnabledPlugins
   - TestActivatePlugin_ErrorReturn: проверяет все режимы ошибок
   - TestCallFunctionJSON_ThreadSafe: JSON object/array/empty params
   - TestDeactivatePlugin_Idempotent: двойная деактивация = no-op
   - TestInitRuntimes_SkipsDisabled: только Enabled плагины активируются
2026-06-07 22:58:26 +08:00
mirivlad d83c8c80e1 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
2026-06-07 20:49:43 +08:00
mirivlad 4df83cd361 security: стабилизационный аудит Lua plugin system
Исправления:
- Install: идемпотентность (no duplicates in InstalledPlugins)
- ReloadPlugins: StopSchedulers + CallShutdownHooks перед CloseRuntimes
- StopSchedulers: обнуление scheduler=nil после остановки
- Scheduler.Stop: обнуление tasks после wg.Wait
- Lua sandbox: блокировка package.loadlib/seeall/preload/loaders/loaded/path/cpath/config/searchpath
- Lua sandbox: блокировка load (глобальная функция)
- CallPluginFunction: валидация funcName (regex [a-zA-Z_][a-zA-Z0-9_]*, max 3 segments)
- CallPluginFunction: убрана строковая сборка Lua-кодa, вызов через PCall напрямую
- PluginPage.svelte: проверка e.source === iframeEl.contentWindow
- PluginPage.svelte: type checking для msg.source, msg.action

Тесты:
- security_test.go: 18 новых тестов (sandbox, lifecycle, validation)
- Все существующие тесты проходят

Документация:
- docs/plugins-security.md: модель безопасности, sandbox, протокол, lifecycle
2026-06-07 19:19:44 +08:00
mirivlad c443ca23c5 fix: PluginPage.svelte — замена CallPluginAction на CallPluginFunction с dotted path
PluginPage.svelte использовал несуществующий Wails binding CallPluginAction.
Заменён на CallPluginFunction с правильным dotted path (calendar.get_events и т.д.),
что соответствует сигнатуре bindings_plugins.go.

Frontend пересобран, go build + go test ./... — всё зелёное.
2026-06-07 16:56:28 +08:00
mirivlad a1d7c7b88b feat: PluginPage iframe bridge + CallPluginFunction binding
- PluginPage.svelte: bidirectional postMessage bridge with iframe
  - Handles: ready, get-events, create-event, update-event, delete-event
  - Queues messages until iframe is ready
  - Exports handleDrop() for drag-and-drop from parent
- CallPluginFunction binding: calls arbitrary Lua functions on active plugins
  - Supports dotted paths: 'calendar.create_event' → _G.calendar.create_event
  - JSON params → Lua table conversion
- LuaVM: added DoString(), LState(), VM() public methods
- Plugin: added VM() getter for external access
2026-06-07 16:37:32 +08:00
mirivlad 3f787ec66d fix: only plugins with on_install are managed - skip others entirely
- Discover(): skip plugins without on_install hook (not shown in UI)
- Enable(): simplified - just check Installed flag
- SyncConfig(): simplified - no HasInstall special case
- Frontend: simplified toggle logic (only installed/uninstalled states)
- Tests: updated all test fixtures to include on_install hook
2026-06-07 15:55:04 +08:00
mirivlad e99ff984b1 feat: plugin install/uninstall lifecycle + UI buttons
- AppConfig: add InstalledPlugins []string
- Manager.Discover(): no config dependency, all plugins start inactive
- Manager.SyncConfig(): apply installed/enabled state from AppConfig
- Manager.Enable(): works for plugins without on_install hook
- Manager.Install/Uninstall(): run on_install/on_uninstall hooks
- ActivatePlugin: skip if HasInstall && !Installed
- ReloadPlugins: Discover → SyncConfig → InitRuntimes
- Bindings: InstallPlugin, UninstallPlugin
- SettingsPlugins: install/uninstall buttons, toggle only after install
- Calendar: migration moved from on_init to on_install, on_uninstall drops tables
- Tests: all 12 pass (manager + runtime + calendar)
2026-06-07 15:28:37 +08:00
mirivlad b80941f908 feat: плагин-система Lua + Calendar reference plugin
- Lua VM runtime: gopher-lua с песочницей, хуки on_init/on_tick/on_shutdown
- API: verstak.node.* / verstak.db.* / verstak.config.* / verstak.state.*
- API: verstak.worklog.* / verstak.activity.* / verstak.file.*
- API: verstak.schedule.* / verstak.http.* / verstak.ui.*
- Менеджер плагинов: жизненный цикл, инициализация, шаблоны
- Scheduler: фоновые задачи с интервалами
- PluginPage.svelte: контейнер для iframe-панелей плагинов
- Calendar plugin: миграция, категории CRUD, события CRUD
- Calendar: расширенный рекарренс (daily/weekly/monthly/yearly)
- Calendar: связь с узлами Верстака, напоминания, HTTP-праздники
- Calendar: Lua-тест-сьют (15 тестов), Go-интеграционный тест
- fix: query_row использует реальные Column() вместо guessColumns
2026-06-07 14:59:46 +08:00
mirivlad 8cbc87cdad feat: настройки Browser Bridge в Verstak и extension
Verstak (GUI):
- SettingsBrowserBridge.svelte — новая секция в Settings:
  toggle вкл/выкл сервера, поле порта (default 9786),
  статус (Запущен/Остановлен), кнопки Сохранить/Перезапустить
- SettingsWindow + SettingsSidebar — подключена секция browserBridge
- BridgeConfig: добавлено поле Enabled (default true)
- RestartBridge() — новый биндинг для перезапуска сервера
- initVault: проверяет bc.Enabled перед запуском bridge

Extension (Chrome + Firefox):
- popup: панель настроек с полем порта (default 9786)
- кнопка «Проверить» — fetch /api/ping с таймаутом 3с
- кнопка «Сохранить» — сохраняет port в chrome.storage.local
- статус соединения: ✓ Сервер отвечает / ✗ Недоступен / ✗ Таймаут
- оба расширения работают только с 127.0.0.1
2026-06-07 01:03:35 +08:00
mirivlad 1cc0c407b1 fix: исправление 6 пунктов из ревью
Critical:
- bridge: AutoGenPort=false по умолчанию, не генерируем secret если пустой
  → extension и bridge совпадают на port 9786 и empty secret
- bridgeConfig: убрана авто-генерация secret, убран secret из BridgeInfo

High:
- extension/background.js + extension-firefox/background.js:
  все chrome.* listeners вынесены в global scope (не внутри onInstalled/onStartup)
  → MV3 service worker корректно перезапускается
- UI: acceptBrowserEvent вызывает AcceptBrowserEvent, attachBrowserEvent вызывает
  AttachBrowserEventToNode (к текущему selectedNode), а не DismissBrowserEvent
- watcher: при Create проверяется isUnderVault(absPath, vaultRoot) —
  если файл уже в vault, используется AddExternal вместо CopyIntoVault
  → нет дублирования файлов с timestamp-суффиксом

Medium:
- bridge.Event: добавлено поле DeviceID, handleEvents обогащает events из batch.DeviceID
  → device_id сохраняется в DB как chrome-*/firefox-*, а не evt_*
- config: FileWatcher изменён на *bool — nil означает default true,
  false = явно выключено → старые config.json без поля file_watcher получают true
2026-06-07 00:15:34 +08:00
mirivlad fc429ac26e feat: ШАГ 4 — UI для browser events в TodayScreen
Go bindings:
- bindings_browser.go: ListBrowserEvents, CountPendingBrowserEvents,
  AcceptBrowserEvent, DismissBrowserEvent, AttachBrowserEventToNode

Frontend:
- BrowserEvents.svelte — компонент списка событий с действиями
  (принять/прикрепить/удалить), статусы, домены, длительность
- TodayScreen.svelte — новая вкладка «Браузер» с badge
- App.svelte — loadBrowserEvents, acceptBrowserEvent,
  dismissBrowserEvent, attachBrowserEvent handlers
2026-06-06 18:58:39 +08:00
mirivlad f88376264d fix: reorder journal worklog sections 2026-06-06 02:53:36 +08:00
mirivlad 40c0953904 fix: skip deleted entries in navigation history 2026-06-06 02:42:20 +08:00
mirivlad 0cd8a79049 feat: restore global search in app header 2026-06-06 02:39:29 +08:00
mirivlad cf770262e5 fix: reset capture drag state reliably 2026-06-06 02:30:54 +08:00
mirivlad a37afd3b67 fix: trash integrity for TypeFile nodes — file record soft-delete, correct preview/restore 2026-06-05 17:31:18 +08:00
mirivlad 64e6c6f735 fix: trash file preview, visual CSS, virtual folder model
- Added resolveTrashPath() backend function: walks ancestor chain to find
  files inside deleted/moved folders (flat trash directory)
- Added TrashFsPath to TrashNodeDTO, computed during ListTrash via
  parent-to-child propagation of physical trash path
- Fixed visual CSS for trash rows: button reset (no white bg, transparent,
  inherit font/color), hover styles match app dark theme
- Root view filters out descendant nodes (only shows top-level items)
2026-06-05 17:05:35 +08:00
mirivlad 5257789a4d fix: trash duplicate path, journal tabs, today undefined, mouse back, inbox search
- Trash: removed duplicate fsPath display, folders/files open by clicking icon/name
- Trash: removed separate 'Open' button, only restore/delete right-aligned
- Trash: added ReadTrashFileContent binding + preview for files
- Trash: breadcrumb path under title, compact date display
- Journal: split into 'Предложения' + 'Журнал работы' tabs
- Journal: suggestions tab opens by default
- Today: fixed undefined in feed (null-guard on eventType/title)
- Today: improved event type label readability (blue badge style)
- Today: folder_deleted clicks navigate to trash
- Mouse Back: added mouseup fallback for Wails compat, handle button 3/4
- SearchNodes: case-insensitive with LOWER()
- Inbox assign: added search hint placeholder
2026-06-05 16:49:00 +08:00
mirivlad c512ada386 cleanup: remove stale frontend-dist assets, fix warnings 2026-06-05 16:21:21 +08:00
mirivlad 2ed2ecf77a Today screen: tabs (feed, suggestions, in-progress, captured) + inbox sort/group
- Новый экран 'Сегодня' разбит на 4 вкладки: Лента, Предложения,
  В работе, Захвачено
- Лента отображает события за сегодня с кликабельными сущностями
- Предложения вынесены в отдельную вкладку (только предложения)
- В работе: изменённые файлы/заметки/действия за сегодня с сортировками
- Захвачено: захваченные элементы за сегодня с сортировками
- Неразобранное: сортировка по дате/имени/типу с направлением
- Неразобранное: переключатель 'Группировать по месту захвата'
- TodayScreen.svelte: новый компонент с 4 вкладками
- Новые i18n ключи для вкладок и сортировок
- Backend: ListTodayInProgress, ListTodayCaptures bindings
- Все переходы из вкладок ведут в соответствующее место программы
2026-06-05 16:17:22 +08:00
mirivlad c8aaf36533 fix: stabilize trash navigation and action icons 2026-06-05 14:41:40 +08:00
mirivlad 1fa009b1e2 feat: complete trash restore and batch actions 2026-06-05 12:43:30 +08:00
mirivlad 10b287de7b feat: aggregate journals across node subtrees 2026-06-05 12:37:25 +08:00
mirivlad 23f517dee3 feat: simplify inbox actions and group task tabs 2026-06-05 12:32:36 +08:00
mirivlad 6d15639b41 fix: normalize bare URLs in capture flow 2026-06-05 12:29:19 +08:00
mirivlad 56ef211418 chore: move app icons into frontend assets 2026-06-05 12:25:47 +08:00
mirivlad 22b05f57b4 fix: show inbox capture target context 2026-06-05 08:10:33 +08:00
mirivlad a8df9d118c fix: hide explorer action for inbox links 2026-06-05 08:07:39 +08:00
mirivlad 91b5629e01 fix: open inbox artifacts by type 2026-06-05 08:06:06 +08:00
mirivlad 0e5d13ff01 fix: ignore global hotkeys in editable fields 2026-06-05 07:47:07 +08:00
mirivlad f112e9a2d0 feat: add local inbox and links tabs 2026-06-05 07:44:38 +08:00
mirivlad c1dfc456ec feat: unify frontend capture pipeline 2026-06-05 07:41:15 +08:00
mirivlad 9e70e36f7f feat: add native clipboard capture bridge 2026-06-05 07:34:45 +08:00
mirivlad 6eaa4cda49 feat: assign and delete inbox artifacts 2026-06-05 02:15:27 +08:00
mirivlad a96a316883 feat: capture files and images in inbox 2026-06-05 02:06:21 +08:00
mirivlad 326f6f283d feat: capture clipboard links in inbox gui 2026-06-05 01:55:38 +08:00
mirivlad 44d0be2649 feat: add text and url inbox capture 2026-06-05 01:46:22 +08:00
mirivlad d6ef3a973a feat: model inbox capture artifacts 2026-06-05 01:40:08 +08:00
mirivlad 2e86229350 fix: restrict inbox to captured artifacts 2026-06-05 01:35:27 +08:00
mirivlad cc83cd3476 feat: expose trash in gui 2026-06-05 01:05:57 +08:00
mirivlad 035f877280 feat: add interactive inbox view 2026-06-05 00:59:57 +08:00
mirivlad 02d68ca3f4 feat: edit suggestions before accepting worklog 2026-06-05 00:53:13 +08:00