commit 982f3064ac09f1baf1900a1d0a4f3cb7b8d0e3a8 Author: mirivlad Date: Sat May 30 18:42:19 2026 +0800 step 1: skeleton - go module, CLI stub with --version, structure diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6181e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Binaries +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary +*.test + +# Output of go build +*.out +*.o + +# Dependency directories +vendor/ + +# Go workspace +go.work + +# Wails +frontend/dist/ +frontend/node_modules/ + +# VS Code +.vscode/ +.idea/ + +# OS +.DS_Store +Thumbs.db + +# Vault test data +test-vault/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ff2761 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Верстак + +**Верстак** — local-first рабочий vault для дел, клиентов, проектов, +документов, заметок, файлов, действий запуска, журнала работ +и синхронизации между машинами. + +Это не просто заметочник и не CRM. Главная сущность — **дело**. + +Дело может быть: клиентом, сайтом клиента, личным проектом, +Godot-проектом, набором документов, рецептом/инструкцией, +архивом, разовой помощью человеку, рабочей областью. + +Стек: Go + SQLite + Wails + Bubble Tea. + +Документация: [docs/](docs/) +План разработки: [docs/PLAN.md](docs/PLAN.md) + +## Сборка + +```bash +go build ./cmd/verstak +``` + +## Разработка + +Разработка ведётся пошагово. Каждый шаг — отдельный commit. +Подробнее в [docs/PLAN.md](docs/PLAN.md). diff --git a/cmd/verstak/main.go b/cmd/verstak/main.go new file mode 100644 index 0000000..1e6a43a --- /dev/null +++ b/cmd/verstak/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "os" +) + +const version = "0.1.0-dev" + +func main() { + if len(os.Args) < 2 { + fmt.Println("Verstak", version) + os.Exit(0) + } + + switch os.Args[1] { + case "--version", "-v": + fmt.Println("Verstak", version) + case "--help", "-h": + fmt.Println("Verstak — local-first working vault") + fmt.Println() + fmt.Println("Usage: verstak [flags]") + fmt.Println() + fmt.Println("Commands:") + fmt.Println(" init Initialize a new vault") + fmt.Println(" --version Show version") + fmt.Println(" --help Show this help") + case "init": + fmt.Println("TODO: init command (step 2)") + default: + fmt.Fprintf(os.Stderr, "Unknown command: %s\n", os.Args[1]) + os.Exit(1) + } +} diff --git a/docs/00_README.md b/docs/00_README.md new file mode 100644 index 0000000..6233016 --- /dev/null +++ b/docs/00_README.md @@ -0,0 +1,69 @@ +# Верстак — индекс документации + +**Верстак** — local-first рабочий vault для дел, клиентов, проектов, документов, заметок, файлов, скриптов, действий запуска, журнала работ и синхронизации между машинами. + +Это не просто заметочник и не CRM. Главная сущность — **дело**. + +Дело может быть: + +- клиентом; +- сайтом клиента; +- личным проектом; +- Godot-проектом; +- набором документов; +- рецептом/инструкцией; +- архивом; +- разовой помощью человеку; +- рабочей областью вроде `Рецепты / MySQL / Backup сайта`. + +Внутри дела живут: + +- вложенные папки; +- Markdown-заметки; +- документы `docx/pdf/xlsx/odt`; +- скриншоты; +- архивы; +- исходники; +- скрипты; +- SQL-фрагменты; +- ссылки; +- запускаемые действия; +- журнал работ; +- примерное время; +- история активности; +- связанные дела. + +## Файлы пакета + +1. [[01_Product_Spec]] — полное описание продукта и сценариев. +2. [[02_Architecture]] — архитектура core/GUI/TUI/CLI/server. +3. [[03_Data_Model_Storage]] — модель данных, SQLite, vault, files, notes, actions. +4. [[04_Sync_Backup_Activity]] — синхронизация, восстановление, backup, activity/time tracking. +5. [[05_UI_UX]] — экраны GUI/TUI, дерево, дело, поиск, документы, действия. +6. [[06_Roadmap]] — план разработки по этапам. +7. [[07_AI_Coder_Prompts]] — промпты для ИИ-кодера. +8. [[08_MVP_Checklist]] — чеклист первого MVP. + +## Главные принципы + +1. **Local-first.** + Рабочая копия всегда локальная. Сервер нужен для sync/backup/restore, но программа не должна зависеть от сервера каждый день. + +2. **Данные принадлежат пользователю.** + Заметки и файлы физически лежат обычными файлами в vault. SQLite хранит индекс, связи, метаданные, FTS и sync state. + +3. **Дерево дел важнее тегов.** + Теги полезны, но основная навигация — вложенное дерево: `Клиенты / Ромашка / Сайт / Документы`. + +4. **Не таймтрекер, а восстановитель следов.** + Верстак не требует постоянно нажимать Start/Stop. Он собирает следы работы и предлагает записать их в журнал. + +5. **GUI основной, TUI быстрый, CLI служебный.** + GUI — основная рабочая среда. TUI — быстрый доступ из терминала. CLI — sync, import, scripts, rescue mode. + +6. **Sync не должен уничтожать данные.** + Нужны trash, conflict copies, versions, snapshots и retention. + +## Короткая формула + +> Верстак — это локальный рабочий кабинет для людей, у которых жизнь состоит из проектов, клиентов, документов, заметок, скриптов, файлов, репозиториев и вечного “где я это сохранил?”. diff --git a/docs/01_Product_Spec.md b/docs/01_Product_Spec.md new file mode 100644 index 0000000..341dedc --- /dev/null +++ b/docs/01_Product_Spec.md @@ -0,0 +1,243 @@ +# Верстак — описание продукта + +## 1. Проблема + +У пользователя есть много разнородной рабочей информации: + +- папка `work` и подпапки; +- архивы нужных файлов; +- служебки; +- договоры; +- письма; +- скриншоты; +- файлы с серийными номерами; +- инструкции; +- статьи по установке; +- скрипты; +- SQL-фрагменты; +- заметки в DokuWiki; +- доступы к серверам и сервисам клиентов; +- записи о нестандартных действиях; +- репозитории личных проектов; +- Godot-проекты; +- локальные утилиты вроде sshkeeper. + +Проблема не только в хранении. Проблема в **контексте**: + +- что к чему относится; +- где лежит актуальная версия; +- где заметка по клиенту; +- где договор; +- где скрипт; +- что было сделано в прошлый раз; +- сколько примерно времени ушло; +- что можно сказать человеку, когда он спрашивает “сколько должен?”. + +Обычные инструменты закрывают только кусок: + +- Obsidian — заметки, но не рабочий кабинет с документами, действиями и журналом работ; +- DokuWiki — заметки, но не локальная рабочая оболочка над файлами и программами; +- CRM — клиенты и продажи, но не личная техническая память; +- файловый менеджер — файлы, но без смысла; +- таймтрекер — время, но требует дисциплины; +- лаунчер — запуск, но не память; +- Nextcloud — файлы, но не дела. + +## 2. Что такое Верстак + +**Верстак** — local-first рабочий vault, где всё организовано вокруг “дел”. + +Дело — это контекст, в который складываются заметки, документы, файлы, действия и история работы. + +Примеры дерева: + +```text +Клиенты + ООО Ромашка + Сайт + Обзор.md + Документы + Скрипты + Скриншоты + Журнал работ + Почта + Договоры + +Личные проекты + sshkeeper + Roadmap.md + Releases + dist + Действия + Tyaplyapiya + Godot project + Design notes + Assets + +Рецепты + MySQL + Очистка таблиц + Backup dump + Сайты + Backup сайта одной строкой + Очистка кеша WordPress + +Документы + Служебки + Договоры + Серийники +``` + +## 3. Основные сущности + +### Дело + +Главный рабочий контекст. + +Поля: + +- название; +- тип: клиент / проект / рецепт / документальная область / архив / личное; +- родитель; +- описание; +- статус: active / sleeping / archived; +- теги; +- связанные ссылки; +- связанные actions; +- журнал работ. + +### Заметка + +Обычный Markdown-файл внутри vault. + +Примеры: + +- `overview.md`; +- `nginx.md`; +- `mysql-cleanup.md`; +- `roadmap.md`; +- `access.secret.md`. + +### Документ + +Файл внутри дела: + +- `docx`; +- `xlsx`; +- `pdf`; +- `odt`; +- `png/jpg`; +- `zip`; +- любые другие файлы. + +В MVP документы открываются системным приложением. Встроенный preview можно добавить позже. + +### Действие + +Кнопка, которую можно запустить из дела: + +- открыть URL; +- открыть папку; +- открыть файл; +- запустить Godot; +- открыть IDE; +- запустить sshkeeper; +- выполнить скрипт; +- открыть терминал; +- собрать проект. + +### Журнал работ + +Записи вида: + +```text +2026-05-30 +Дело: ООО Ромашка / Сайт +Время: примерно 3ч +Описание: обновил витрину сайта, товары, баннеры, проверил отображение. +``` + +### Активность + +Сырые следы: + +- открыто дело; +- открыта заметка; +- изменён файл; +- запущено действие; +- открыта папка; +- later: активное окно; +- later: browser URL; +- later: sshkeeper session. + +## 4. Основные сценарии + +### Клиентская работа + +1. Открыть дело клиента. +2. Посмотреть заметки и документы. +3. Открыть админку сайта. +4. Запустить sshkeeper или скрипт. +5. Добавить скриншоты. +6. Записать работу. +7. Сформировать текст отчёта. + +### Личный проект + +1. Открыть проект `sshkeeper`. +2. Нажать “Открыть IDE”. +3. Нажать “Собрать”. +4. Посмотреть roadmap. +5. Добавить заметку “на чём остановился”. + +### Импорт DokuWiki + +1. Выбрать `data/pages`. +2. Выбрать `data/media`. +3. Импортировать namespaces как дерево. +4. Сохранить оригиналы. +5. Постепенно разобрать по делам. + +### Восстановление времени + +Пользователь не нажимал таймер, но вечером видит: + +```text +Похоже, ты работал по делу “ООО Ромашка / Сайт”: +14:05–17:12, примерно 3ч. + +Основания: +- открывалась админка сайта; +- менялся catalog.xlsx; +- запускался sshkeeper profile; +- создавались скриншоты. + +[Записать 3ч] [Исправить] [Игнорировать] +``` + +## 5. Что точно не делать в начале + +- не делать SaaS; +- не делать multi-user CRM; +- не делать встроенный офисный пакет; +- не делать полноценный password manager; +- не делать ИИ; +- не делать мобильное приложение; +- не делать сложные права пользователей; +- не делать бухгалтерию; +- не пытаться автоматически понимать всё. + +## 6. Уникальность + +Верстак отличается тем, что объединяет: + +- заметочник; +- файловый кабинет; +- project launcher; +- журнал работ; +- рабочий контекст; +- sync/backup; +- TUI/GUI; +- миграцию из DokuWiki. + +Но всё это не как отдельные модули, а вокруг одного понятия: **дело**. diff --git a/docs/02_Architecture.md b/docs/02_Architecture.md new file mode 100644 index 0000000..ff3e261 --- /dev/null +++ b/docs/02_Architecture.md @@ -0,0 +1,333 @@ +# Верстак — архитектура + +## 1. Архитектурная схема + +```text + ┌────────────────────┐ + │ GUI/Wails │ + └─────────┬──────────┘ + │ +┌─────────────┐ ┌───────▼────────┐ ┌─────────────┐ +│ TUI/Bubble │───▶│ Core Library │◀───│ CLI Commands │ +└─────────────┘ └───────┬────────┘ └─────────────┘ + │ + ┌─────────▼──────────┐ + │ Local Vault+SQLite │ + └─────────┬──────────┘ + │ + ┌─────────▼──────────┐ + │ Sync Client │ + └─────────┬──────────┘ + │ + ┌─────────▼──────────┐ + │ Sync Server │ + └────────────────────┘ +``` + +## 2. Компоненты + +### Core Library + +Общее ядро, которое не зависит от GUI/TUI. + +Отвечает за: + +- nodes tree; +- vault; +- notes; +- files; +- documents; +- actions; +- worklog; +- activity; +- search; +- import; +- sync client; +- security; +- config. + +### GUI + +Основной интерфейс. + +Рекомендуемый стек: + +- Go backend; +- Wails; +- Svelte или Vue; +- TypeScript; +- CSS без перегруза. + +Функции GUI: + +- дерево дел; +- экран “Сегодня”; +- карточка дела; +- Markdown editor; +- файловый список; +- actions buttons; +- worklog; +- поиск; +- sync status; +- импорт DokuWiki; +- разбор конфликтов. + +### TUI + +Быстрый интерфейс из терминала. + +Рекомендуемый стек: + +- Bubble Tea; +- Bubbles; +- Lip Gloss. + +TUI не обязан повторять весь GUI. + +Функции: + +- найти дело; +- открыть заметку; +- добавить worklog; +- запустить action; +- запустить sync; +- посмотреть “Сегодня”. + +### CLI + +CLI нужен не как главный интерфейс, а как служебный вход. + +Команды: + +```bash +verstak init --vault ~/VerstakVault +verstak sync +verstak index rebuild +verstak import-dokuwiki --pages /path/data/pages +verstak log "Клиенты/Ромашка" --time 3h --text "Обновил витрину" +verstak open "Личные проекты/sshkeeper" +verstak vault check +``` + +CLI нужен для: + +- автоматизации; +- интеграции с sshkeeper; +- shell scripts; +- импорта; +- восстановления; +- диагностики; +- rescue mode. + +### Sync Server + +Отдельный Go HTTP server. + +Функции: + +- API key auth; +- push/pull operations; +- upload/download blobs; +- restore manifest; +- snapshots; +- retention deleted files. + +## 3. Структура репозитория + +```text +verstak/ + go.mod + README.md + + cmd/ + verstak/ + main.go + verstak-gui/ + main.go + verstak-tui/ + main.go + verstak-server/ + main.go + + internal/ + core/ + nodes/ + vault/ + storage/ + notes/ + files/ + actions/ + worklog/ + activity/ + search/ + importers/ + sync/ + security/ + config/ + + gui/ + tui/ + server/ + + frontend/ + src/ + App.svelte + components/ + routes/ + stores/ + + migrations/ + 001_init.sql + 002_fts.sql + 003_sync.sql +``` + +## 4. Core modules + +### nodes + +Универсальное дерево. + +Типы: + +```text +space +case +folder +note +document +file +action +recipe +secret +worklog +link +``` + +### vault + +Работа с локальной папкой: + +- init; +- safe paths; +- copy/move/link files; +- trash; +- history; +- integrity check. + +### storage + +SQLite: + +- migrations; +- repositories; +- transactions; +- FTS; +- backup db. + +### notes + +Markdown notes: + +- create; +- read; +- save; +- version backup; +- import from DokuWiki. + +### files + +- add file; +- link external file; +- open system app; +- detect changes; +- hash; +- MIME; +- missing files. + +### actions + +- open_url; +- open_file; +- open_folder; +- run_command; +- run_script; +- open_terminal; +- launch_app; +- sshkeeper_profile. + +### worklog + +- manual entries; +- approximate time; +- billable flag; +- report generation. + +### activity + +- events; +- suggestions; +- grouping; +- confidence. + +### search + +- SQLite FTS5; +- index notes, files, worklog, actions. + +### importers + +- DokuWiki; +- work folder; +- plain folder; +- maybe Obsidian later. + +### sync + +- device id; +- operations log; +- push/pull; +- blobs; +- conflicts; +- restore. + +## 5. File watching + +Не строить систему только на watcher. + +Правильно: + +```text +snapshot scanner — источник правды +fsnotify watcher — ускоритель +manual scan — fallback +``` + +Scanner сравнивает реальность с SQLite: + +- new file; +- changed file; +- missing file; +- moved file later; +- hash mismatch. + +## 6. Внешние приложения + +Верстак не пишет свой офисный пакет. + +MVP: + +- Markdown/txt/sh/sql/json/yml — встроенный редактор; +- docx/xlsx/odt/pdf/images — открыть системным приложением; +- после закрытия/сохранения watcher/scanner видит изменение. + +## 7. Безопасность запуска actions + +Правила: + +- dangerous action требует confirm; +- команды запускать через `exec.Command`, не через shell, если shell не нужен; +- показывать command, args, working_dir; +- логировать запуск; +- не подставлять пользовательский ввод без escaping; +- не хранить секреты в action logs. diff --git a/docs/03_Data_Model_Storage.md b/docs/03_Data_Model_Storage.md new file mode 100644 index 0000000..6194aa1 --- /dev/null +++ b/docs/03_Data_Model_Storage.md @@ -0,0 +1,276 @@ +# Верстак — модель данных и хранилище + +## 1. Vault + +Пример структуры: + +```text +~/VerstakVault/ + .verstak/ + index.db + config.yml + device.yml + sync_state.db + trash/ + history/ + originals/ + thumbnails/ + + spaces/ + clients/ + romashka/ + case.yml + overview.md + notes/ + nginx.md + mysql-cleanup.md + access.secret.md.enc + documents/ + dogovor-2026.docx + sluzhebka.pdf + screenshots/ + error-form.png + scripts/ + backup-site.sh + cleanup.sql + actions/ + open-admin.yml + worklog/ + 2026-05.md +``` + +## 2. SQLite schema MVP + +### nodes + +```sql +CREATE TABLE nodes ( + id TEXT PRIMARY KEY, + parent_id TEXT NULL REFERENCES nodes(id), + type TEXT NOT NULL, + title TEXT NOT NULL, + slug TEXT NOT NULL, + path TEXT NULL, + sort_order INTEGER NOT NULL DEFAULT 0, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL, + deleted_at TEXT NULL, + revision INTEGER NOT NULL DEFAULT 1, + device_id TEXT NULL +); +``` + +### node_meta + +```sql +CREATE TABLE node_meta ( + node_id TEXT NOT NULL REFERENCES nodes(id), + key TEXT NOT NULL, + value TEXT NOT NULL, + PRIMARY KEY (node_id, key) +); +``` + +### files + +```sql +CREATE TABLE files ( + id TEXT PRIMARY KEY, + node_id TEXT NOT NULL REFERENCES nodes(id), + filename TEXT NOT NULL, + path TEXT NOT NULL, + storage_mode TEXT NOT NULL, -- vault | external + size INTEGER NOT NULL DEFAULT 0, + sha256 TEXT NULL, + mime TEXT NULL, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL, + last_seen_at TEXT NULL, + missing INTEGER NOT NULL DEFAULT 0 +); +``` + +### notes + +```sql +CREATE TABLE notes ( + node_id TEXT PRIMARY KEY REFERENCES nodes(id), + file_id TEXT NOT NULL REFERENCES files(id), + format TEXT NOT NULL DEFAULT 'markdown', + original_format TEXT NULL, + encrypted INTEGER NOT NULL DEFAULT 0 +); +``` + +### actions + +```sql +CREATE TABLE actions ( + id TEXT PRIMARY KEY, + node_id TEXT NOT NULL REFERENCES nodes(id), + title TEXT NOT NULL, + kind TEXT NOT NULL, + command TEXT NULL, + args_json TEXT NULL, + working_dir TEXT NULL, + url TEXT NULL, + confirm_required INTEGER NOT NULL DEFAULT 0, + capture_output INTEGER NOT NULL DEFAULT 0, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); +``` + +### worklog_entries + +```sql +CREATE TABLE worklog_entries ( + id TEXT PRIMARY KEY, + node_id TEXT NOT NULL REFERENCES nodes(id), + started_at TEXT NULL, + ended_at TEXT NULL, + date TEXT NOT NULL, + minutes INTEGER NULL, + approximate INTEGER NOT NULL DEFAULT 1, + billable INTEGER NOT NULL DEFAULT 0, + summary TEXT NOT NULL, + details TEXT NULL, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); +``` + +### activity_events + +```sql +CREATE TABLE activity_events ( + id TEXT PRIMARY KEY, + node_id TEXT NULL REFERENCES nodes(id), + source TEXT NOT NULL, + event_type TEXT NOT NULL, + title TEXT NULL, + path TEXT NULL, + url TEXT NULL, + app_name TEXT NULL, + process_name TEXT NULL, + started_at TEXT NOT NULL, + ended_at TEXT NULL, + duration_seconds INTEGER NULL, + metadata_json TEXT NULL, + confidence INTEGER NOT NULL DEFAULT 100, + created_at TEXT NOT NULL +); +``` + +### worklog_suggestions + +```sql +CREATE TABLE worklog_suggestions ( + id TEXT PRIMARY KEY, + node_id TEXT NOT NULL REFERENCES nodes(id), + date TEXT NOT NULL, + started_at TEXT NULL, + ended_at TEXT NULL, + suggested_minutes INTEGER NULL, + summary TEXT NOT NULL, + evidence_json TEXT NOT NULL, + status TEXT NOT NULL DEFAULT 'pending', + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); +``` + +### search_index + +```sql +CREATE VIRTUAL TABLE search_index USING fts5( + node_id UNINDEXED, + title, + content, + path, + tags, + type +); +``` + +### sync_ops + +```sql +CREATE TABLE sync_ops ( + id TEXT PRIMARY KEY, + op_id TEXT NOT NULL UNIQUE, + device_id TEXT NOT NULL, + entity_type TEXT NOT NULL, + entity_id TEXT NOT NULL, + op_type TEXT NOT NULL, + payload_json TEXT NOT NULL, + created_at TEXT NOT NULL, + pushed_at TEXT NULL, + applied_at TEXT NULL +); +``` + +## 3. Правила хранения + +### Заметки + +- physical `.md` file; +- metadata in SQLite; +- backup old version before overwrite. + +### Документы + +- physical file; +- open with system app; +- metadata in SQLite. + +### Secret notes + +- encrypted file, e.g. `access.secret.md.enc`; +- no FTS indexing; +- no logs with plaintext; +- master password later. + +### Удаление + +- soft delete node; +- file to `.verstak/trash`; +- sync tombstone; +- physical cleanup only after retention. + +## 4. Sync operations + +Каждое изменение должно создавать operation: + +- node_create; +- node_update; +- node_move; +- node_delete; +- file_add; +- file_update; +- file_delete; +- note_update; +- action_update; +- worklog_create; +- worklog_update. + +Даже если sync ещё не реализован, operation log лучше заложить рано. + +## 5. Индексация + +Индексировать: + +- node titles; +- note content; +- filenames; +- paths; +- worklog summaries/details; +- action titles; +- links. + +Не индексировать: + +- secret notes; +- private keys; +- token-like values; +- binary content in MVP. diff --git a/docs/04_Sync_Backup_Activity.md b/docs/04_Sync_Backup_Activity.md new file mode 100644 index 0000000..52dda15 --- /dev/null +++ b/docs/04_Sync_Backup_Activity.md @@ -0,0 +1,242 @@ +# Верстак — синхронизация, backup и активность + +## 1. Синхронизация + +Цель: + +- рабочая машина и домашняя машина имеют один vault; +- обе работают offline; +- сервер используется для обмена и восстановления; +- при потере локальных файлов можно восстановиться с сервера. + +## 2. Sync server + +`verstak-server` — простой Go HTTP server. + +Функции: + +- API key auth; +- device registry; +- operation log; +- blob storage by sha256; +- snapshots; +- restore manifest; +- deleted item retention. + +Пример server storage: + +```text +server-data/ + db.sqlite + blobs/ + ab/ + cd/ + abcdef...blob + snapshots/ +``` + +## 3. API MVP + +```http +GET /api/v1/health +POST /api/v1/device/register +POST /api/v1/sync/push +POST /api/v1/sync/pull +POST /api/v1/blobs/upload +GET /api/v1/blobs/{sha256} +GET /api/v1/restore/manifest +``` + +Auth: + +```http +Authorization: Bearer +``` + +## 4. Push/pull + +Client push: + +```json +{ + "device_id": "device-uuid", + "ops": [], + "blobs": ["sha256..."] +} +``` + +Server response: + +```json +{ + "accepted": true, + "missing_blobs": ["sha256..."] +} +``` + +Client pull: + +```json +{ + "device_id": "device-uuid", + "since_revision": 42 +} +``` + +Response: + +```json +{ + "server_revision": 50, + "ops": [] +} +``` + +## 5. Восстановление + +Сценарий: + +1. Установить Верстак. +2. Ввести server URL. +3. Ввести API key/recovery key. +4. Нажать Restore. +5. Скачать manifest. +6. Скачать blobs. +7. Применить ops. +8. Пересобрать SQLite/FTS. +9. Проверить целостность. + +## 6. Конфликты + +Не пытаться магически мержить всё. + +Если заметка изменилась на двух устройствах: + +```text +nginx.md +nginx.conflict-home-2026-05-30.md +``` + +Если docx изменился на двух устройствах: + +```text +dogovor.docx +dogovor.conflict-work-2026-05-30.docx +``` + +UI: + +```text +Конфликт: nginx.md +[Открыть обе версии] [Оставить локальную] [Оставить серверную] [Склеить вручную] +``` + +## 7. Sync не равен backup + +Если удалить файл на одной машине, sync может удалить везде. + +Поэтому сервер должен иметь: + +- tombstones; +- trash retention; +- note versions; +- daily snapshots; +- integrity check; +- manual export. + +Retention example: + +```yaml +retention: + deleted_items_days: 90 + note_versions_days: 180 + daily_snapshots_days: 30 +``` + +## 8. Activity tracking + +Верстак не должен быть шпионской программой. Activity tracking должен быть явным и настраиваемым. + +### Источники MVP + +- opened node; +- edited note; +- added file; +- changed file through app; +- launched action. + +### Источники later + +- file watcher/scanner; +- active window title; +- browser URL extension; +- sshkeeper integration; +- idle detection. + +## 9. Как понять, что пользователь работал 3 часа + +Верстак не “знает точно”. Он предлагает версию. + +Пример: + +```text +Похоже, ты работал по делу “ООО Ромашка / Сайт”: +14:05–17:12, примерно 3ч. + +Основания: +- открывалась админка сайта; +- изменялся catalog.xlsx; +- запускался sshkeeper profile romashka-vps; +- создавался screenshot-result.png; +- открывалась заметка “Витрина”. + +[Записать 3ч] [Исправить] [Игнорировать] +``` + +## 10. Группировка активности + +Правило MVP: + +- события одного дела; +- разрыв меньше 20 минут — один интервал; +- разрыв больше 20 минут — новый интервал; +- итог округлить до 5/10/15 минут; +- показать evidence. + +## 11. Privacy modes + +### Minimal + +- only inside Verstak; +- actions; +- manual worklog. + +### Work + +- + file scanner/watcher; +- + files opened from Verstak; +- + sshkeeper events. + +### Full + +- + active windows; +- + browser URLs; +- + idle detection. + +По умолчанию не включать Full. + +## 12. Client report + +Из журнала работ можно собрать отчёт: + +```text +По сайту ООО “Ромашка” было сделано: +- обновлена витрина сайта; +- внесены изменения в каталог товаров; +- обновлены баннеры; +- проверено отображение результата. + +Ориентировочное время: 3 часа. +``` + +MVP — шаблонный отчёт без ИИ. diff --git a/docs/05_UI_UX.md b/docs/05_UI_UX.md new file mode 100644 index 0000000..c6327c3 --- /dev/null +++ b/docs/05_UI_UX.md @@ -0,0 +1,245 @@ +# Верстак — UI/UX + +## 1. Главный экран — Сегодня + +```text +Сегодня +────────────────────────────── + +Активные дела: +[ООО Ромашка / Сайт] примерно 3ч 12 следов [подтвердить] +[sshkeeper] 42м 5 следов [открыть] +[Документы / Договоры] 3 новых файла разобрать [разобрать] + +Неразобранное: +- screenshot_2026-05-30.png +- dogovor-final2.docx +- backup-site-old.zip +- import/dokuwiki/mysql-cleanup.txt + +Быстрые действия: +[Новое дело] [Быстрая заметка] [Добавить файл] [Импорт DokuWiki] [Sync] +``` + +## 2. Общий layout + +```text +┌────────────────────────────────────────────────────┐ +│ Search | Quick Add | Sync Status | Settings │ +├───────────────┬────────────────────────────────────┤ +│ Tree sidebar │ Main content │ +│ │ │ +│ Сегодня │ Case / Note / File / Search │ +│ Клиенты │ │ +│ Проекты │ │ +│ Рецепты │ │ +│ Документы │ │ +└───────────────┴────────────────────────────────────┘ +``` + +## 3. Sidebar tree + +```text +Сегодня +Неразобранное + +Клиенты + ООО Ромашка + Сайт + Почта + Договоры + +Личные проекты + sshkeeper + Tyaplyapiya + +Рецепты + MySQL + Сайты + +Документы + Служебки + Договоры + Серийники + +Архив +``` + +## 4. Экран дела + +```text +ООО Ромашка / Сайт +────────────────────────────── + +Описание: +Сайт клиента. WordPress/nginx. Иногда обновление витрины, формы, почта. + +Быстрые действия: +[Открыть сайт] [Открыть админку] [Открыть sshkeeper] [Открыть папку] [Добавить работу] + +Последнее: +2026-05-30 — обновление витрины, баннеры, проверка — примерно 3ч +2026-05-12 — чистка кеша и проверка формы — 40м + +Вкладки: +Обзор | Заметки | Файлы | Документы | Скрипты | Действия | Журнал | Активность +``` + +## 5. Заметки + +- список заметок; +- Markdown editor; +- preview; +- save; +- move; +- rename; +- search within note later. + +## 6. Файлы и документы + +Actions: + +- add file; +- drag & drop; +- copy into vault; +- link external; +- open with system app; +- show in folder; +- delete to trash; +- rename; +- move. + +MVP: + +- preview только для markdown; +- системное открытие для office/pdf/images. + +Later: + +- image preview; +- PDF preview; +- thumbnails; +- document metadata. + +## 7. Действия + +Вкладка Actions: + +```text +Открыть сайт open_url +Открыть админку open_url +Открыть sshkeeper run_command +Открыть папку open_folder +Backup сайта run_script, confirm required +``` + +При опасном action: + +```text +Команда: +./backup-site.sh + +Рабочая папка: +.../clients/romashka/scripts + +[Запустить] [Отмена] +``` + +## 8. Журнал работ + +```text +2026-05-30 +3ч, примерно +Обновил витрину сайта, товары, баннеры, проверил отображение. + +2026-05-12 +40м +Почистил кеш и проверил форму обратной связи. +``` + +Кнопки: + +- add entry; +- edit; +- copy report; +- mark billable; +- approximate/exact. + +## 9. Активность + +```text +14:05 opened admin.romashka.ru +14:18 opened catalog.xlsx +14:44 changed price-list.csv +15:58 sshkeeper profile romashka-vps +16:40 opened romashka.ru/catalog +``` + +Suggestion: + +```text +Похоже, работа по Ромашка / Сайт: +14:05–17:12, примерно 3ч. + +[Записать] [Изменить] [Игнорировать] +``` + +## 10. Поиск + +Search results: + +```text +[Recipe] Рецепты / MySQL / Очистка таблиц +[Note] Клиенты / Ромашка / mysql-cleanup.md +[Script] Клиенты / Петров / scripts/cleanup.sql +[Worklog] 2026-04-28 — удалял старые записи из таблиц +``` + +## 11. Неразобранное + +Туда попадают: + +- импортированные DokuWiki pages; +- файлы без дела; +- папки из scan work; +- конфликты sync; +- activity suggestions без уверенного дела. + +Actions: + +- создать дело; +- привязать к делу; +- переместить; +- архивировать; +- игнорировать; +- удалить в trash. + +## 12. TUI UX + +TUI нужен для быстрого: + +- fuzzy search; +- открыть дело; +- добавить worklog; +- запустить action; +- sync now. + +Не нужно делать в TUI: + +- импорт DokuWiki; +- сложный conflict resolver; +- preview документов; +- настройки sync. + +## 13. CLI UX + +CLI команды: + +```bash +verstak sync +verstak index rebuild +verstak import-dokuwiki --pages /path/data/pages +verstak log "Ромашка" --time 3h --text "Обновил витрину" +verstak open "sshkeeper" +verstak action run "Ромашка/Открыть сайт" +``` diff --git a/docs/06_Roadmap.md b/docs/06_Roadmap.md new file mode 100644 index 0000000..0f4f976 --- /dev/null +++ b/docs/06_Roadmap.md @@ -0,0 +1,215 @@ +# Верстак — roadmap + +## Milestone 0 — Skeleton + +- Go module; +- cmd/verstak; +- cmd/verstak-gui stub; +- cmd/verstak-server stub; +- internal/core; +- SQLite connection; +- migrations; +- config; +- `verstak --version`; +- `verstak init --vault ./test-vault`. + +Acceptance: + +- `go test ./...` проходит; +- vault создаётся; +- повторный init безопасен. + +## Milestone 1 — Nodes + +- table nodes; +- node_meta; +- UUID; +- Create/Get/ListChildren/Update/Move/SoftDelete; +- CLI node commands; +- tests. + +Acceptance: + +- можно создать дерево дел; +- можно переместить узел; +- delete soft. + +## Milestone 2 — Vault files + +- `.verstak/`; +- config.yml; +- files table; +- copy/link file; +- open file; +- trash. + +Acceptance: + +- файл добавляется в дело; +- открывается системным приложением; +- delete moves to trash. + +## Milestone 3 — Markdown notes + +- notes table; +- create/read/save note; +- `.md` files; +- version backup; +- CLI note commands. + +Acceptance: + +- заметка редактируется; +- файл физически лежит в vault; +- старая версия сохраняется. + +## Milestone 4 — GUI MVP + +- Wails app; +- sidebar tree; +- create node/note; +- edit note; +- add/open file; +- basic settings. + +Acceptance: + +- можно пользоваться как маленьким заметочником+файловым кабинетом. + +## Milestone 5 — Actions + +- actions table; +- open_url; +- open_file; +- open_folder; +- run_command; +- confirmation; +- action log; +- GUI Actions tab. + +Acceptance: + +- можно запускать Godot/sshkeeper/сайт/папку. + +## Milestone 6 — Worklog + +- worklog table; +- manual entries; +- minutes; +- approximate; +- billable; +- report copy. + +Acceptance: + +- можно записать “3ч обновлял витрину”; +- можно скопировать отчёт клиенту. + +## Milestone 7 — Search + +- FTS5; +- index nodes/notes/files/worklog/actions; +- search UI; +- reindex command. + +Acceptance: + +- поиск находит старую инструкцию, файл или запись работ. + +## Milestone 8 — DokuWiki import + +- read `data/pages`; +- read `data/media`; +- namespaces to folders; +- pages to notes; +- originals saved; +- optional conversion to markdown. + +Acceptance: + +- старые заметки переезжают в Верстак. + +## Milestone 9 — Work folder intake + +- scan folder; +- show unassigned folders/files; +- create case from folder; +- copy/move/link into vault. + +Acceptance: + +- можно постепенно разобрать папку `work`. + +## Milestone 10 — Sync server MVP + +- HTTP server; +- API key; +- server db; +- push/pull ops; +- blob upload/download; +- restore manifest. + +Acceptance: + +- две машины обмениваются изменениями через сервер. + +## Milestone 11 — Conflicts and restore + +- conflict copy; +- conflict UI; +- restore from server; +- retention deleted files; +- integrity check. + +Acceptance: + +- конфликт не теряет данные; +- можно восстановить vault на новой машине. + +## Milestone 12 — Activity MVP + +- activity events; +- opened nodes; +- launched actions; +- changed files through app; +- suggestions; +- evidence. + +Acceptance: + +- Верстак предлагает worklog на основе следов. + +## Milestone 13 — File scanner/watcher + +- snapshot scanner; +- fsnotify watcher; +- manual scan; +- changed/missing files; +- activity events. + +Acceptance: + +- изменения файлов снаружи приложения обнаруживаются. + +## Milestone 14 — TUI MVP + +- Bubble Tea; +- tree/search; +- add worklog; +- run action; +- sync. + +Acceptance: + +- можно из терминала быстро работать с Верстаком. + +## Milestone 15 — 1.0 polish + +- installers; +- backup export; +- docs; +- keyboard shortcuts; +- UI polish; +- migration safety; +- crash recovery; +- tests. diff --git a/docs/07_AI_Coder_Prompts.md b/docs/07_AI_Coder_Prompts.md new file mode 100644 index 0000000..ea3e176 --- /dev/null +++ b/docs/07_AI_Coder_Prompts.md @@ -0,0 +1,304 @@ +# Верстак — промпты для ИИ-кодера + +## Постоянный контекст для ИИ-кодера + +```markdown +Ты работаешь над проектом “Верстак”. + +Верстак — local-first рабочий vault для дел, клиентов, проектов, документов, заметок, файлов, действий запуска, журнала работ и синхронизации. + +Главные принципы: +- данные принадлежат пользователю; +- заметки и файлы физически лежат обычными файлами в vault; +- SQLite хранит индекс, связи, метаданные, FTS и sync state; +- основная сущность — вложенное дерево nodes; +- GUI, TUI и CLI должны использовать общий core; +- бизнес-логику нельзя завязывать на UI; +- не делать SaaS; +- не делать ИИ; +- не делать password manager в MVP; +- не удалять файлы физически без trash; +- опасные действия требуют подтверждения; +- изменения делать маленькими проверяемыми шагами. + +Стек: +- Go; +- SQLite; +- Wails для GUI; +- Bubble Tea для TUI позже; +- fsnotify + snapshot scanner позже; +- sync server позже. + +После каждого шага дай: +1. что изменено; +2. как запустить; +3. как проверить; +4. какие файлы затронуты; +5. какие риски остались. +``` + +## Prompt 01 — Skeleton + +```markdown +Создай skeleton проекта “Верстак”. + +Нужно: +- Go module `verstak`; +- структура cmd/internal/migrations; +- CLI `verstak --version`; +- команда `verstak init --vault ./test-vault`; +- SQLite connection; +- migration runner; +- первая миграция. + +Acceptance: +- `go test ./...` проходит; +- init создаёт vault и `.verstak/index.db`; +- повторный init безопасен. +``` + +## Prompt 02 — Nodes + +```markdown +Реализуй универсальное дерево nodes. + +Нужно: +- tables nodes, node_meta; +- struct Node; +- repository: Create/Get/ListChildren/UpdateTitle/Move/SoftDelete; +- CLI node create/list/move/delete; +- unit tests. + +Правила: +- UUID; +- deleted_at вместо физического удаления; +- безопасный slug. +``` + +## Prompt 03 — Vault files + +```markdown +Добавь работу с файлами vault. + +Нужно: +- `.verstak/trash`; +- files table; +- VaultService; +- copy file into vault; +- link external file; +- open with system app; +- delete-to-trash; +- CLI file add/list/open. +``` + +## Prompt 04 — Markdown notes + +```markdown +Добавь Markdown-заметки. + +Нужно: +- notes table; +- note node type; +- create/read/save note; +- `.md` file inside vault; +- backup previous version before overwrite; +- CLI note create/read/write. +``` + +## Prompt 05 — Wails GUI MVP + +```markdown +Добавь первый Wails GUI. + +Нужно: +- sidebar tree; +- main panel; +- create node; +- create note; +- markdown textarea editor; +- save note; +- file list; +- add file; +- open file. + +Главный пользовательский поток: +1. создать дело; +2. создать заметку; +3. сохранить заметку; +4. добавить файл; +5. открыть файл системным приложением. +``` + +## Prompt 06 — Actions + +```markdown +Добавь actions-кнопки. + +Типы: +- open_url; +- open_file; +- open_folder; +- run_command. + +Нужно: +- actions table; +- action runner; +- confirm_required; +- action log; +- GUI вкладка “Действия”. + +Команды запускать через exec.Command с аргументами. Опасные действия — только после confirm. +``` + +## Prompt 07 — Worklog + +```markdown +Добавь журнал работ. + +Нужно: +- worklog_entries table; +- add/edit/delete entry; +- minutes; +- approximate; +- billable; +- GUI вкладка “Журнал”; +- copy report. + +Acceptance: +- можно записать “3ч, обновил витрину”; +- можно скопировать отчёт. +``` + +## Prompt 08 — Search + +```markdown +Добавь SQLite FTS5 поиск. + +Индексировать: +- node titles; +- note content; +- filenames; +- worklog summaries; +- action titles. + +Нужно: +- `verstak index rebuild`; +- GUI search bar; +- search results with type/path. +``` + +## Prompt 09 — DokuWiki import + +```markdown +Добавь импорт из DokuWiki. + +Вход: +- path to `data/pages`; +- optional path to `data/media`; +- target node id. + +Нужно: +- namespaces as folders; +- pages as notes; +- originals saved in `.verstak/originals/dokuwiki`; +- basic conversion or raw import. +``` + +## Prompt 10 — Sync server skeleton + +```markdown +Создай `verstak-server`. + +Нужно: +- HTTP server; +- API key auth; +- SQLite server db; +- GET /health; +- POST /sync/push; +- POST /sync/pull; +- POST /blobs/upload; +- GET /blobs/{sha256}; +- blob storage by sha256. +``` + +## Prompt 11 — Sync client MVP + +```markdown +Добавь sync client. + +Нужно: +- sync_ops local table; +- операции при изменениях; +- config server URL + API key; +- command `verstak sync`; +- push local ops; +- pull remote ops; +- upload/download blobs; +- conflict copy if unsure. +``` + +## Prompt 12 — Activity MVP + +```markdown +Добавь минимальный activity tracking. + +Источники: +- opened node; +- edited note; +- added file; +- launched action. + +Нужно: +- activity_events table; +- экран “Активность”; +- группировка по делу; +- возможность создать worklog из выбранных событий. +``` + +## Prompt 13 — File scanner/watcher + +```markdown +Добавь file scanner и fsnotify watcher. + +Важно: +- scanner — источник правды; +- watcher — ускоритель. + +Нужно: +- scan vault tree; +- detect new/changed/missing files; +- update index; +- create activity events; +- manual command `verstak scan`. +``` + +## Prompt 14 — TUI MVP + +```markdown +Добавь TUI на Bubble Tea. + +Функции: +- tree/search; +- open node; +- add worklog; +- run action; +- sync now. + +TUI не должен повторять весь GUI. +``` + +## Prompt 15 — Integrity/restore + +```markdown +Добавь команды: +- `verstak vault check`; +- `verstak vault repair`; +- `verstak restore --server --api-key --target `. + +Проверять: +- missing files; +- orphan files; +- SQLite references; +- hash mismatch; +- sync state. +``` diff --git a/docs/08_MVP_Checklist.md b/docs/08_MVP_Checklist.md new file mode 100644 index 0000000..6ecbc6f --- /dev/null +++ b/docs/08_MVP_Checklist.md @@ -0,0 +1,73 @@ +# Верстак — MVP checklist + +## MVP цель + +Первая версия должна позволять реально начать пользоваться Верстаком как заменой части DokuWiki и папочного хаоса. + +## Обязательные функции + +- [ ] Создать vault. +- [ ] Создать дерево дел. +- [ ] Создать Markdown-заметку. +- [ ] Редактировать Markdown-заметку. +- [ ] Добавить файл в дело. +- [ ] Открыть файл системным приложением. +- [ ] Создать action “Открыть URL”. +- [ ] Создать action “Открыть папку”. +- [ ] Создать action “Запустить команду”. +- [ ] Добавить запись работы. +- [ ] Скопировать отчёт по работам. +- [ ] Поиск по заметкам. +- [ ] Поиск по именам файлов. +- [ ] Поиск по журналу работ. +- [ ] Базовый импорт DokuWiki. + +## Необязательные, но желательные + +- [ ] Неразобранное. +- [ ] Скан папки work. +- [ ] Внешние linked files. +- [ ] Action log. +- [ ] Activity events MVP. +- [ ] TUI MVP. + +## Не входит в первый MVP + +- [ ] Полная синхронизация. +- [ ] Активные окна. +- [ ] Browser tracking. +- [ ] Encrypted secret notes. +- [ ] PDF preview. +- [ ] Office preview. +- [ ] Мобильное приложение. +- [ ] Multi-user. +- [ ] ИИ. + +## Проверка MVP руками + +1. Создать vault `~/VerstakVault`. +2. Создать `Клиенты / ООО Ромашка / Сайт`. +3. Создать `overview.md`. +4. Добавить `dogovor.docx`. +5. Открыть `dogovor.docx`. +6. Создать action “Открыть сайт”. +7. Создать action “Открыть папку”. +8. Добавить worklog “3ч, обновил витрину”. +9. Найти “витрину” через поиск. +10. Закрыть и открыть приложение. +11. Убедиться, что всё осталось на месте. + +## Первый demo-сценарий + +```text +Верстак запускается. +Пользователь видит экран “Сегодня”. +Создаёт дело клиента. +Добавляет заметку. +Перетаскивает договор. +Создаёт кнопку открытия сайта. +Записывает работу. +Поиском находит старую заметку. +``` + +Если это работает — проект уже живой. diff --git a/docs/PLAN.md b/docs/PLAN.md new file mode 100644 index 0000000..8f586d6 --- /dev/null +++ b/docs/PLAN.md @@ -0,0 +1,387 @@ +# Верстак — Пошаговый план реализации + +## Принципы работы + +1. После каждого шага — **СТОП**. Влад проверяет, даёт обратную связь. +2. Следующий шаг начинается **ТОЛЬКО** после одобрения. +3. Каждый шаг — отдельный git commit. +4. Периодически сверяться с этим планом и документацией в docs/. + +## Статус шагов + +| # | Шаг | Статус | +|---|-----|--------| +| 1 | Git init + Skeleton | ⬜ не начат | +| 2 | Init + SQLite + First Migration | ⬜ не начат | +| 3 | Nodes Repository + CRUD + CLI Node | ⬜ не начат | +| 4 | Vault Files: Trash + File Service + CLI File | ⬜ не начат | +| 5 | Markdown Notes: Create/Read/Save + CLI Note | ⬜ не начат | +| 6 | Wails GUI MVP: Sidebar + Main Panel | ⬜ не начат | +| 7 | Actions: Run URL/File/Command + GUI Tab | ⬜ не начат | +| 8 | Worklog: Entries + Report + GUI Tab | ⬜ не начат | +| 9 | FTS5 Search: Rebuild Index + GUI Search Bar | ⬜ не начат | +| 10 | DokuWiki Importer | ⬜ не начат | +| 11 | Sync Server Skeleton | ⬜ не начат | +| 12 | Sync Client MVP | ⬜ не начат | +| 13 | Activity + File Scanner/Watcher | ⬜ не начат | +| 14 | TUI MVP (Bubble Tea) | ⬜ не начат | +| 15 | Integrity Check + Repair + Vault Restore | ⬜ не начат | + +--- + +## ШАГ 1 — Git Init + Skeleton + +**Цель:** репозиторий создан, пустая структура, "hello world" билдится. + +**Acceptance:** +- `go build ./...` проходит +- `go test ./...` проходит +- `verstak --version` выводит версию +- Повторный init безопасен + +**Действия:** +- git init, .gitignore (Go, Wails) +- `go mod init verstak` +- Структура: `cmd/verstak/`, `internal/core/`, `migrations/` +- `cmd/verstak/main.go`: --version flag +- README.md + +**Commit:** `step 1: skeleton` + +--- + +## ШАГ 2 — Init + SQLite + First Migration + +**Цель:** `verstak init --vault ./test` создаёт vault с index.db. + +**Acceptance:** +- `go test ./...` проходит +- init создаёт `.verstak/index.db` +- повторный init безопасен + +**Действия:** +- migration runner (cmd + SQL migrations/) +- миграция 001_init.sql (таблица nodes) +- `_ "github.com/mattn/go-sqlite3"` или modernc driver +- CLI `init`: vault dir + `.verstak/` + `index.db` + +**Commit:** `step 2: init + sqlite + first migration` + +--- + +## ШАГ 3 — Nodes Repository + CRUD + CLI Node + +**Цель:** можно создать/прочитать/переместить/удалить дело через CLI. + +**Acceptance:** +- nodes + node_meta таблицы +- NodeRepository: Create, Get, ListChildren, UpdateTitle, Move, SoftDelete +- CLI: `node create`, `node list`, `node move`, `node delete` +- unit tests проходят + +**Действия:** +- Полная схема nodes (id, parent_id, type, title, slug, path, sort_order, created_at, updated_at, deleted_at, revision, device_id) +- node_meta (node_id, key, value) +- Node struct + Repository +- UUID вместо auto-increment +- Soft delete (deleted_at) +- безопасный slug для path +- Tests: in-memory SQLite + +**Commit:** `step 3: nodes repository + CRUD` + +--- + +## ШАГ 4 — Vault Files: Trash + File Service + CLI File + +**Цель:** можно добавить файл в дело, открыть системным приложением, удалить в trash. + +**Acceptance:** +- `.verstak/trash/` создаётся при init +- copy file into vault работает +- open with system app работает +- delete-to-trash работает +- тесты проходят + +**Действия:** +- Таблица files (id, node_id, filename, path, storage_mode, size, sha256, mime, ...) +- VaultService: CopyFile, LinkExternal, OpenFile, DeleteToTrash, RestoreFromTrash +- CLI: `file add`, `file list`, `file open`, `file trash` + +**Commit:** `step 4: vault files + trash + CLI` + +--- + +## ШАГ 5 — Markdown Notes: Create/Read/Save + CLI Note + +**Цель:** можно создать заметку, писать в неё, читать обратно. + +**Acceptance:** +- type "note" для nodes +- создать .md файл в vault +- save делает backup старой версии +- тесты проходят + +**Действия:** +- Таблица notes (node_id, file_id, format, original_format, encrypted) +- NoteService: CreateNote, ReadNote, SaveNote (с backup) +- CLI: `note create`, `note read`, `note write` +- Backup старой версии перед перезаписью + +**Commit:** `step 5: markdown notes` + +--- + +## ШАГ 6 — Wails GUI MVP + +**Цель:** GUI запускается, видно дерево дел, можно создать дело и заметку. + +**Acceptance:** +- sidebar tree показывает дела +- create node работает +- markdown textarea editor с save +- file list + add file + open file +- главный пользовательский поток работает + +**Действия:** +- Wails app init (Go backend + Svelte/Vue) +- Backend bindings: NodeService, VaultService, NoteService +- Frontend: sidebar tree, main panel, modals, markdown editor +- Поток: дело → заметка → файл → открыть файл + +**Commit:** `step 6: Wails GUI MVP` + +--- + +## ШАГ 7 — Actions + +**Цель:** можно создать кнопку "Открыть сайт", нажать, сайт открылся. + +**Acceptance:** +- open_url, open_file, open_folder, run_command +- confirm_required диалог +- action log +- GUI вкладка "Действия" + +**Действия:** +- Таблица actions +- ActionService: Run с confirm, exec.Command БЕЗ shell, args массивом +- CLI: `action add`, `action list`, `action run` +- GUI: вкладка с кнопками + +**Commit:** `step 7: actions` + +--- + +## ШАГ 8 — Worklog + +**Цель:** можно записать "3ч обновил витрину", скопировать отчёт. + +**Acceptance:** +- add/edit/delete entry +- approximate minutes + billable flag +- copy report копирует в буфер +- GUI вкладка "Журнал" + +**Действия:** +- Таблица worklog_entries +- WorklogService: Add, Edit, Delete, CopyReport +- CLI: `worklog add`, `worklog list`, `worklog report` +- GUI: вкладка журнал + кнопка copy report + +**Commit:** `step 8: worklog` + +--- + +## ШАГ 9 — FTS5 Search + +**Цель:** можно найти "витрину" по заметкам, файлам, журналу. + +**Acceptance:** +- `verstak index rebuild` перестраивает индекс +- поиск по node titles, note content, filenames, worklog summaries +- GUI search bar + результаты с type/path + +**Действия:** +- Таблица search_index (FTS5): node_id, title, content, path, tags, type +- Триггеры для автоматического обновления или manual rebuild +- SearchService: RebuildIndex, Search(query) +- CLI: `index rebuild` +- GUI: search bar в header + +**Commit:** `step 9: FTS5 search` + +--- + +## ШАГ 10 — DokuWiki Importer + +**Цель:** можно импортировать страницы DokuWiki как дерево дел. + +**Acceptance:** +- namespaces → folders +- pages → notes +- оригиналы сохранены в `.verstak/originals/dokuwiki/` + +**Действия:** +- DokuWiki парсер: namespaces как nodes tree +- страницы как note nodes с .md файлами +- CLI: `import-dokuwiki --pages /path --media /path --target-node ...` +- Originals сохраняются без изменений + +**Commit:** `step 10: DokuWiki importer` + +--- + +## ШАГ 11 — Sync Server Skeleton + +**Цель:** verstak-server отвечает на /health, /sync/push, /sync/pull, /blobs. + +**Acceptance:** +- HTTP server на отдельном порту +- API key auth +- blob storage by sha256 +- GET /health, POST /sync/push, POST /sync/pull, POST /blobs/upload, GET /blobs/{sha256} + +**Действия:** +- `cmd/verstak-server/main.go` +- SQLite server db +- Push/pull operations endpoints +- Blob upload/download with sha256 naming + +**Commit:** `step 11: sync server skeleton` + +--- + +## ШАГ 12 — Sync Client MVP + +**Цель:** `verstak sync` отправляет локальные операции на сервер и получает обратно. + +**Acceptance:** +- sync_ops таблица +- операции создаются при каждом изменении +- push local ops + pull remote ops +- upload/download blobs +- conflict copy при неуверенности + +**Действия:** +- Таблица sync_ops (опционально добавить триггеры в repository) +- SyncClient: Push, Pull, UploadBlob, DownloadBlob +- CLI: `verstak sync` +- Server URL + API key в .verstak/config + +**Commit:** `step 12: sync client MVP` + +--- + +## ШАГ 13 — Activity + File Scanner/Watcher + +**Цель:** фиксируется открытие/редактирование, scanner видит новые файлы. + +**Acceptance:** +- activity_events таблица +- scanner сравнивает реальность с SQLite +- watcher (fsnotify) ускоряет обнаружение +- экран "Активность" с группировкой по делу +- можно создать worklog из events + +**Действия:** +- Таблица activity_events +- Запись событий из nodes/notes/files/actions +- Snapshot scanner (источник правды) +- fsnotify watcher (ускоритель) +- CLI: `scan`, `activity list` +- GUI: экран "Активность" + +**Commit:** `step 13: activity + scanner/watcher` + +--- + +## ШАГ 14 — TUI MVP (Bubble Tea) + +**Цель:** быстрый поиск дела, добавление worklog, запуск action. + +**Acceptance:** +- fuzzy search tree +- open node +- add worklog +- run action +- sync now + +**Действия:** +- `cmd/verstak-tui/main.go` с Bubble Tea +- Модели: search, node view, worklog form, action runner +- Не повторяет весь GUI — только быстрые действия + +**Commit:** `step 14: TUI MVP` + +--- + +## ШАГ 15 — Integrity Check + Repair + Vault Restore + +**Цель:** `verstak vault check` находит проблемы, repair чинит, restore восстанавливает. + +**Acceptance:** +- check: missing files, orphan files, SQLite references, hash mismatch +- repair: устраняет найденные проблемы +- restore с сервера восстанавливает vault + +**Действия:** +- CLI: `vault check` — сканирует и отчитывается +- CLI: `vault repair` — чинит найденное +- CLI: `restore --server --api-key --target ` + +**Commit:** `step 15: integrity + restore` + +--- + +## Сводка структуры репозитория + +``` +verstak/ + go.mod + README.md + PLAN.md + + cmd/ + verstak/ # CLI + verstak-gui/ # Wails GUI + verstak-tui/ # Bubble Tea TUI + verstak-server/ # Sync server + + internal/ + core/ + nodes/ + vault/ + storage/ + notes/ + files/ + actions/ + worklog/ + activity/ + search/ + importers/ + sync/ + security/ + config/ + + frontend/ # Wails frontend (Svelte/Vue) + + migrations/ + 001_init.sql + 002_add_meta.sql + 003_add_files.sql + 004_add_notes.sql + 005_add_actions.sql + 006_add_worklog.sql + 007_add_activity.sql + 008_add_fts.sql + 009_add_sync.sql +``` + +## RAID (Risks, Assumptions, Issues, Dependencies) + +- **Критично:** Wails v3 может быть нестабилен — проверить перед шагом 6 +- **Критично:** go-sqlite3 нужен cgo; modernc — чистый Go, выбрать до шага 2 +- **Зависимость:** Шаги 12 (sync client) зависят от 11 (server) +- **Зависимость:** Шаг 6 (GUI) лучше откладывать до стабильности core +- **Риск:** Svelte/Vue фронтенд потребует node/npm — подготовить diff --git a/docs/verstak_browser_extension_prompts.md b/docs/verstak_browser_extension_prompts.md new file mode 100644 index 0000000..f5058f7 --- /dev/null +++ b/docs/verstak_browser_extension_prompts.md @@ -0,0 +1,1045 @@ +# Верстак — браузерное дополнение Firefox / Chrome / Yandex Browser + +## 1. Назначение + +Браузерное дополнение нужно потому, что большая часть работы может происходить не в локальных файлах, а в браузере: + +- админки сайтов; +- CMS; +- панели клиентов; +- GitHub/Gitea/GitLab; +- webmail; +- личные кабинеты; +- документация; +- витрины сайтов; +- CRM/ERP клиентов; +- облачные панели. + +Если пользователь три часа обновлял витрину сайта через web-админку, локальный Верстак может почти ничего не увидеть. +Расширение даёт Верстаку браузерные следы: + +```text +Похоже, пользователь работал с admin.romashka.ru с 14:05 до 17:12. +Домен связан с делом “Клиенты / ООО Ромашка / Сайт”. +Можно предложить запись в журнал: “обновление витрины сайта, примерно 3 часа”. +``` + +## 2. Главный принцип + +Расширение — не шпион и не самостоятельный таймтрекер. + +Оно должно: + +- работать локально; +- передавать события только в локальный Верстак; +- не отправлять данные в облако; +- не читать DOM страниц; +- не читать формы; +- не читать cookies; +- не перехватывать сетевые запросы; +- не делать скриншоты; +- не сохранять полную историю браузера; +- уважать allowlist/blocklist; +- иметь pause; +- показывать пользователю, что отслеживается; +- не трекать private windows по умолчанию. + +## 3. Что собирать + +MVP-событие активности активной вкладки: + +```json +{ + "type": "active_tab_interval", + "browser": "firefox|chrome|yandex", + "window_id": 1, + "tab_id": 123, + "domain": "admin.romashka.ru", + "origin": "https://admin.romashka.ru", + "url": "https://admin.romashka.ru/catalog/products", + "title": "Каталог товаров — Админка", + "started_at": "2026-05-30T14:05:00+03:00", + "ended_at": "2026-05-30T14:18:00+03:00", + "duration_seconds": 780, + "source": "browser_extension", + "private_window": false +} +``` + +Отправлять батчами: + +```json +{ + "browser": "firefox", + "device_id": "browser-extension-device-id", + "events": [ + { + "type": "active_tab_interval", + "domain": "admin.romashka.ru", + "origin": "https://admin.romashka.ru", + "url": "https://admin.romashka.ru/catalog", + "title": "Каталог товаров", + "started_at": "2026-05-30T14:05:00+03:00", + "ended_at": "2026-05-30T14:18:00+03:00", + "duration_seconds": 780 + } + ] +} +``` + +## 4. Что не собирать + +В MVP запрещено: + +- DOM; +- содержимое страниц; +- значения input/textarea; +- cookies; +- localStorage/sessionStorage страниц; +- POST bodies; +- webRequest details; +- screenshot; +- пароли; +- приватные окна без явного включения; +- полную историю браузера; +- query string с токенами. + +## 5. Очистка URL + +По умолчанию: + +- query string удалять; +- fragment удалять; +- full URL хранить только если пользователь включил; +- для чувствительных доменов хранить только domain/origin. + +Пример: + +```text +https://client.example.com/admin/orders?token=abc&session=123#x +``` + +Безопасный вариант: + +```text +https://client.example.com/admin/orders +``` + +Приватный вариант: + +```text +client.example.com +``` + +## 6. Архитектура расширения + +```text +browser-extension/ + src/ + background.js + popup.html + popup.js + options.html + options.js + shared/ + browser-api.js + activity.js + storage.js + transport.js + url.js + manifests/ + manifest.chrome.json + manifest.firefox.json + package.json + build.js + dist/ + chrome/ + firefox/ +``` + +Yandex Browser использовать Chrome-compatible build. + +## 7. Транспорт в Верстак + +### Вариант MVP: Local HTTP endpoint + +Верстак поднимает локальный endpoint: + +```text +http://127.0.0.1:47731/api/browser/events +``` + +Расширение шлёт туда события через `fetch`. + +Auth: + +```http +Authorization: Bearer +``` + +Плюсы: + +- проще отлаживать; +- одинаково для Firefox/Chrome/Yandex; +- не надо регистрировать native host; +- быстрее сделать MVP. + +Минусы: + +- endpoint надо защищать токеном; +- bind только на 127.0.0.1; +- нужен pairing flow. + +### Вариант позже: Native Messaging + +Плюсы: + +- более официальный канал extension ↔ native app; +- не нужен HTTP endpoint. + +Минусы: + +- сложнее установка; +- нужно регистрировать native messaging host отдельно для Chrome/Firefox; +- тяжелее для MVP. + +Решение: **в MVP Local HTTP**, Native Messaging оставить на будущее. + +## 8. Pairing flow + +1. Пользователь открывает Верстак. +2. Нажимает “Подключить браузер”. +3. Верстак показывает одноразовый pairing token. +4. Пользователь вводит token в extension options. +5. Extension вызывает: + +```http +POST /api/browser/pair +``` + +Body: + +```json +{ + "pairing_token": "123456", + "extension_id": "...", + "browser": "firefox|chrome|yandex", + "device_name": "Firefox on Work PC" +} +``` + +Response: + +```json +{ + "ok": true, + "local_token": "...", + "device_id": "..." +} +``` + +6. Extension сохраняет `local_token` в local storage. +7. Token больше не показывается пользователю. + +## 9. Local Browser API в Верстаке + +```http +GET /api/browser/health +POST /api/browser/pair +POST /api/browser/events +GET /api/browser/bindings +POST /api/browser/link-domain-request +POST /api/browser/pause +``` + +### Health + +```json +{ + "ok": true, + "app": "Verstak", + "version": "0.1.0" +} +``` + +### Events + +```http +POST /api/browser/events +Authorization: Bearer +Content-Type: application/json +``` + +### Bindings + +Ответ: + +```json +{ + "domains": { + "admin.romashka.ru": { + "node_id": "uuid", + "title": "Клиенты / ООО Ромашка / Сайт" + } + } +} +``` + +## 10. Permissions + +Стараться держать permissions минимальными. + +Возможные: + +```json +{ + "permissions": [ + "tabs", + "storage", + "idle" + ] +} +``` + +Host permissions: + +- не начинать с агрессивного ``, если можно; +- по умолчанию режим `allowlist_only`; +- пользователь явно добавляет домены. + +Режимы: + +```text +allowlist_only +all_except_blocked +disabled +``` + +Default: `allowlist_only`. + +## 11. Popup UI + +Popup: + +```text +Верстак + +Status: connected / not connected / paused +Current site: admin.romashka.ru + +[Track this site] +[Stop tracking this site] +[Link this site to case] +[Pause 1 hour] +[Open settings] + +Today: +admin.romashka.ru — 1h 20m +git.mirv.top — 35m +``` + +## 12. Options UI + +Настройки: + +- endpoint URL; +- pairing token; +- test connection; +- tracking enabled; +- tracking mode: + - allowlist only; + - all except blocked; + - disabled; +- allowlist domains; +- blocklist domains; +- send full URL: yes/no; +- strip query string: yes/no; +- include private windows: no by default; +- idle timeout minutes; +- batch interval seconds; +- max pending events; +- debug mode; +- clear pending events; +- reset pairing. + +## 13. Activity collector + +Логика: + +1. Следить за active tab. +2. При смене active tab закрывать текущий interval. +3. При смене URL активной вкладки закрывать текущий interval и открывать новый. +4. При смене active window закрывать/переключать interval. +5. Если tab URL не trackable — не создавать interval. +6. Если domain не в allowlist при режиме allowlist_only — не создавать interval. +7. Если domain в blocklist — не создавать interval. +8. Если пользователь idle — закрыть interval. +9. Раз в N секунд отправить pending events в Верстак. +10. Если Верстак недоступен — хранить pending events локально. + +## 14. Idle detection + +Если пользователь idle дольше заданного времени: + +- закрыть текущий interval; +- не считать idle time как работу; +- при возвращении открыть новый interval для текущей вкладки. + +## 15. Domain bindings в Верстаке + +Таблица: + +```sql +CREATE TABLE domain_bindings ( + id TEXT PRIMARY KEY, + node_id TEXT NOT NULL REFERENCES nodes(id), + domain TEXT NOT NULL, + match_type TEXT NOT NULL DEFAULT 'exact', -- exact | suffix + created_at TEXT NOT NULL +); +``` + +Примеры: + +```text +admin.romashka.ru → Клиенты / ООО Ромашка / Сайт +*.romashka.ru → Клиенты / ООО Ромашка / Сайт +git.mirv.top/mirivlad/sshkeeper → Личные проекты / sshkeeper +``` + +MVP: + +- exact domain; +- suffix match позже. + +## 16. Worklog suggestions + +Верстак группирует browser events: + +- по node_id; +- по domain; +- по дню; +- intervals with gap <= 20 minutes объединяются. + +Suggestion: + +```text +Похоже, работа по “ООО Ромашка / Сайт”: +admin.romashka.ru — 2ч 48м +romashka.ru/catalog — 12м + +Предлагаемое время: 3ч + +Основания: +- 14:05–15:30 admin.romashka.ru/catalog +- 15:40–16:55 admin.romashka.ru/products +- 17:00–17:12 romashka.ru/catalog + +[Записать 3ч] [Изменить] [Игнорировать] +``` + +## 17. Safety requirements + +1. Не использовать content scripts в MVP, если не нужны. +2. Не читать DOM. +3. Не читать cookies. +4. Не читать forms. +5. Не использовать `webRequest`. +6. Не использовать `history`. +7. Query strip по умолчанию. +8. Private windows ignore по умолчанию. +9. Pause в popup. +10. Allowlist mode по умолчанию. +11. Blocklist есть всегда. +12. Pending events ограничены. +13. Endpoint только 127.0.0.1. +14. Pairing token одноразовый. +15. Local token не логировать. +16. No external network requests. + +--- + +# Промпты для ИИ-кодера + +## Prompt 01 — Browser extension skeleton + +```markdown +Создай отдельный модуль `browser-extension` для проекта Верстак. + +Цель: +браузерное расширение для Firefox / Chrome / Yandex Browser, которое собирает локальную активность активной вкладки и отправляет её в локальный Верстак. + +Важно: +- не собирать DOM; +- не читать формы; +- не читать cookies; +- не делать screenshots; +- не использовать webRequest/history; +- не отправлять данные в интернет; +- только local endpoint `http://127.0.0.1:47731`; +- query string удалять по умолчанию; +- private windows игнорировать по умолчанию. + +Структура: +- `browser-extension/src/background.js` +- `browser-extension/src/shared/browser-api.js` +- `browser-extension/src/shared/url.js` +- `browser-extension/src/shared/storage.js` +- `browser-extension/src/shared/transport.js` +- `browser-extension/src/popup.html` +- `browser-extension/src/popup.js` +- `browser-extension/src/options.html` +- `browser-extension/src/options.js` +- `browser-extension/manifests/manifest.chrome.json` +- `browser-extension/manifests/manifest.firefox.json` +- `browser-extension/package.json` +- `browser-extension/build.js` + +Сделай manifests для Chrome MV3 и Firefox WebExtension. +Для Yandex Browser использовать Chrome build. + +MVP skeleton должен: +- загружаться как unpacked extension в Chrome/Chromium; +- загружаться временно в Firefox через about:debugging; +- показывать popup; +- иметь options page; +- хранить настройки в browser/chrome storage local; +- иметь build script для `dist/chrome` и `dist/firefox`. + +Не реализуй пока отправку активности, только skeleton и настройки. +После выполнения дай инструкции запуска. +``` + +## Prompt 02 — Cross-browser API layer + +```markdown +Добавь compatibility layer для Chrome/Firefox. + +Файл: +`src/shared/browser-api.js` + +Нужно: +- использовать `globalThis.browser`, если есть; +- fallback на `globalThis.chrome`; +- promisify callback APIs, где нужно; +- методы: + - getActiveTab() + - getCurrentWindow() + - onTabActivated(handler) + - onTabUpdated(handler) + - onWindowFocusChanged(handler) + - storageGet(keys) + - storageSet(values) + - idleQueryState(minutes) + - onIdleStateChanged(handler) + +Правила: +- popup/options/background не должны напрямую использовать chrome/browser; +- весь доступ к browser APIs через browserApi; +- не добавлять тяжёлые зависимости без необходимости. + +Acceptance criteria: +- работает в Chrome; +- работает в Firefox; +- storage работает; +- active tab можно получить. +``` + +## Prompt 03 — URL sanitizer + +```markdown +Реализуй URL sanitizer. + +Файл: +`src/shared/url.js` + +Функции: +- parseUrl(rawUrl) +- sanitizeUrl(rawUrl, options) +- getDomain(rawUrl) +- getOrigin(rawUrl) +- isTrackableUrl(rawUrl) +- isBlockedUrl(rawUrl, settings) +- isAllowedUrl(rawUrl, settings) + +Правила: +- не трекать chrome://, about:, moz-extension:, chrome-extension:, edge:, opera:, file:// по умолчанию; +- query string удалять по умолчанию; +- hash удалять по умолчанию; +- full URL хранить только если setting `sendFullUrl=true`; +- режимы: + - allowlist_only; + - all_except_blocked; + - disabled. + +Добавь простые unit tests. +Покажи примеры sanitize для URL с token/session/query. +``` + +## Prompt 04 — Settings storage + +```markdown +Реализуй настройки расширения. + +Файл: +`src/shared/storage.js` + +Настройки: +- endpointUrl default `http://127.0.0.1:47731`; +- localToken; +- deviceId; +- pairedAt; +- trackingEnabled; +- trackingMode: allowlist_only | all_except_blocked | disabled; +- allowlistDomains; +- blocklistDomains; +- sendFullUrl default false; +- stripQueryString default true; +- includePrivateWindows default false; +- idleTimeoutMinutes default 5; +- batchIntervalSeconds default 30; +- maxPendingEvents default 1000; +- debugMode default false; +- pendingEvents array. + +Нужно: +- getSettings() +- saveSettings(partial) +- addPendingEvent(event) +- getPendingEvents() +- removePendingEvents(ids) +- clearPendingEvents() + +Acceptance criteria: +- options page может менять настройки; +- pending events переживают перезапуск браузера; +- maxPendingEvents соблюдается. +``` + +## Prompt 05 — Active tab interval collector + +```markdown +Реализуй сбор интервалов активности активной вкладки. + +Файлы: +- `src/background.js` +- `src/shared/activity.js` + +Логика: +- при старте background получить active tab; +- при tabs.onActivated закрыть старый interval и открыть новый; +- при tabs.onUpdated для активной вкладки, если URL изменился, закрыть старый interval и открыть новый; +- при windows.onFocusChanged закрывать/переключать interval; +- если URL не trackable — interval не создавать; +- если домен не проходит allowlist/blocklist — interval не создавать; +- interval хранить: + - id + - domain + - origin + - sanitized URL + - title + - started_at + - ended_at + - duration_seconds + - private_window false/true if available + +Пока не отправляй на сервер, складывай pending events в storage. + +Popup должен в debug mode показывать последние 10 pending events. +``` + +## Prompt 06 — Local HTTP transport + +```markdown +Добавь отправку событий в локальный Верстак. + +Файл: +`src/shared/transport.js` + +Endpoint: +`POST http://127.0.0.1:47731/api/browser/events` + +Header: +`Authorization: Bearer ` + +Логика: +- раз в batchIntervalSeconds отправлять pending events; +- если нет localToken — не отправлять; +- если endpoint недоступен — оставить pending; +- если 401 — status auth_failed; +- если success — удалить отправленные events; +- body: + { + browser, + device_id, + events + } + +Popup должен показывать: +- connected / disconnected / auth failed; +- pending count; +- last successful send. + +Acceptance criteria: +- с mock server events отправляются; +- при server down events остаются pending; +- query string не отправляется. +``` + +## Prompt 07 — Pairing flow + +```markdown +Добавь pairing flow. + +Options page: +- endpoint URL; +- pairing token; +- button “Pair with Verstak”; +- button “Test connection”; +- status area. + +API: +GET /api/browser/health +POST /api/browser/pair + +Pair request: +{ + "pairing_token": "...", + "extension_id": "...", + "browser": "chrome|firefox|yandex", + "device_name": "..." +} + +Pair response: +{ + "ok": true, + "local_token": "...", + "device_id": "..." +} + +После pairing: +- сохранить localToken; +- сохранить deviceId; +- сохранить pairedAt; +- очистить pairingToken из UI; +- popup показывает connected. + +Не логировать токены. +``` + +## Prompt 08 — Popup UI + +```markdown +Сделай popup UI. + +Показывать: +- статус подключения; +- текущий сайт; +- текущий режим tracking; +- pending events count; +- today summary по доменам. + +Кнопки: +- Track this site; +- Stop tracking this site; +- Link this site to case; +- Pause 1 hour; +- Resume; +- Open settings. + +Track this site: +- добавляет текущий domain в allowlist. + +Stop tracking this site: +- добавляет domain в blocklist или удаляет из allowlist. + +Link this site to case: +- отправляет в Верстак: + POST /api/browser/link-domain-request + { + "domain": "...", + "url": "...", + "title": "..." + } + +Если Верстак недоступен, показать понятную ошибку. +``` + +## Prompt 09 — Options UI + +```markdown +Сделай options page. + +Настройки: +- endpoint URL; +- pairing/test connection; +- tracking enabled; +- tracking mode: + - allowlist_only + - all_except_blocked + - disabled +- allowlist domains; +- blocklist domains; +- send full URL yes/no; +- strip query string yes/no; +- include private windows yes/no, default false; +- idle timeout minutes; +- batch interval seconds; +- max pending events; +- debug mode. + +Функции: +- validate domain; +- import/export settings JSON; +- clear pending events; +- reset pairing; +- show current extension version. + +Сделай простой чистый UI без framework. +``` + +## Prompt 10 — Idle detection + +```markdown +Добавь idle detection. + +Использовать browser/chrome idle API через compatibility layer. + +Логика: +- если пользователь idle больше idleTimeoutMinutes, закрыть текущий interval; +- пока idle, новые intervals не создавать; +- при возвращении active открыть interval для текущей вкладки; +- idle time не должен попадать в duration. + +Popup debug показывает current idle state. + +Acceptance criteria: +- idle event закрывает interval; +- duration не растёт во время idle. +``` + +## Prompt 11 — Verstak desktop receiver + +```markdown +В основном приложении Верстак добавь local browser activity receiver. + +Нужно: +- локальный HTTP server на 127.0.0.1:47731; +- endpoints: + - GET /api/browser/health + - POST /api/browser/pair + - POST /api/browser/events + - POST /api/browser/link-domain-request +- local pairing tokens; +- local browser tokens; +- таблица browser_devices; +- сохранение browser events в activity_events. + +Безопасность: +- bind только на 127.0.0.1; +- Bearer token required после pairing; +- pairing token одноразовый; +- не логировать token; +- ограничить body size; +- reject requests from non-loopback interface. + +Acceptance criteria: +- extension может pair; +- extension может отправить events; +- events появляются в activity_events; +- invalid token rejected. +``` + +## Prompt 12 — Domain bindings in Verstak + +```markdown +Добавь привязку доменов к делам в Верстаке. + +Нужно: +- таблица domain_bindings: + - id + - node_id + - domain + - match_type exact|suffix + - created_at +- UI в карточке дела: + - список связанных доменов; + - добавить домен; + - удалить домен. +- обработка link-domain-request: + - показать запрос в Неразобранном; + - пользователь выбирает дело; + - создаётся binding. + +Matching: +- exact first; +- suffix for *.example.com later; +- unmatched browser events попадают в unresolved activity. + +Acceptance criteria: +- admin.romashka.ru привязан к делу; +- события этого домена видны в активности дела; +- неизвестные домены попадают в Неразобранное. +``` + +## Prompt 13 — Browser activity worklog suggestions + +```markdown +Добавь построение worklog suggestions из browser activity. + +Логика: +- брать browser activity events за день; +- группировать по node_id/domain; +- объединять интервалы с gap <= 20 минут; +- суммировать duration; +- создавать suggestion: + - node_id + - date + - started_at + - ended_at + - suggested_minutes + - evidence_json + - summary template. + +Summary template: +“Работа в браузере по связанному сайту: {domains}.” + +UI: +- Today показывает suggestions; +- Case Activity tab показывает suggestions; +- кнопки: + - Записать; + - Изменить; + - Игнорировать. + +Acceptance criteria: +- 3 часа активности admin.romashka.ru создают suggestion; +- пользователь может записать suggestion в worklog; +- evidence показывает домены, titles, intervals. +``` + +## Prompt 14 — Firefox packaging + +```markdown +Подготовь Firefox build. + +Нужно: +- npm run build:firefox; +- использовать manifests/manifest.firefox.json; +- output dist/firefox; +- инструкция: + 1. открыть about:debugging; + 2. This Firefox; + 3. Load Temporary Add-on; + 4. выбрать manifest.json. + +Проверить: +- popup работает; +- options page работает; +- active tab tracking работает; +- local HTTP events отправляются. + +Не публиковать в AMO на этом этапе. +``` + +## Prompt 15 — Chrome/Yandex packaging + +```markdown +Подготовь Chrome/Yandex build. + +Нужно: +- npm run build:chrome; +- output dist/chrome; +- инструкция для Chrome: + 1. открыть chrome://extensions; + 2. включить Developer mode; + 3. Load unpacked; + 4. выбрать dist/chrome. +- инструкция для Yandex Browser: + - использовать Chrome-compatible build; + - проверить установку как unpacked, если доступно в dev mode; + - иначе оставить ручную инструкцию для совместимой установки. + +Проверить: +- popup работает; +- options page работает; +- active tab tracking работает; +- local HTTP events отправляются. + +Не публиковать в Chrome Web Store на этом этапе. +``` + +## Prompt 16 — Privacy/security audit + +```markdown +Проведи privacy/security audit расширения. + +Проверь: +- нет сбора DOM; +- нет content scripts без необходимости; +- нет cookies permission; +- нет webRequest permission; +- нет history permission; +- query string strip по умолчанию; +- private windows ignore по умолчанию; +- pause работает; +- allowlist mode работает; +- blocklist работает; +- local token не логируется; +- pending events ограничены; +- endpoint только 127.0.0.1; +- pairing token одноразовый; +- нет external network requests; +- errors не содержат секретов. + +Выдай список найденных проблем и исправь критичные. +``` + +## MVP scope + +### Входит + +- Chrome-compatible build; +- Firefox build; +- Yandex via Chrome-compatible build; +- popup; +- options; +- pairing; +- active tab intervals; +- allowlist/blocklist; +- query stripping; +- local HTTP transport; +- pending queue; +- idle detection; +- domain linking request. + +### Не входит + +- content scripts; +- DOM reading; +- form tracking; +- network request tracking; +- screenshots; +- cloud sync from extension; +- AI summaries; +- password detection; +- automatic client detection by page content; +- browser history import. + +## Первый полезный сценарий + +1. Пользователь создаёт дело “ООО Ромашка / Сайт”. +2. Добавляет домен `admin.romashka.ru`. +3. Устанавливает extension. +4. Pair extension with Verstak. +5. Работает в админке сайта. +6. Extension отправляет intervals. +7. Верстак показывает: + +```text +Похоже, работа по “ООО Ромашка / Сайт”: +admin.romashka.ru — 2ч 48м +romashka.ru/catalog — 12м + +[Записать 3ч] [Изменить] [Игнорировать] +``` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..357c8f5 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module verstak + +go 1.22 diff --git a/internal/core/doc.go b/internal/core/doc.go new file mode 100644 index 0000000..9a8bc95 --- /dev/null +++ b/internal/core/doc.go @@ -0,0 +1 @@ +package core diff --git a/migrations/.gitkeep b/migrations/.gitkeep new file mode 100644 index 0000000..e69de29