# Верстак — модель данных и хранилище ## 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. ## 6. Расширяемость через плагины Базовая схема фиксирована и поддерживает плагины: - Новые типы нод регистрируются плагинами через Lua API (`verstak.node.register_type()`) — схема таблицы `nodes` не меняется, `type` принимает любое строковое значение. - Мета-поля (`node_meta`) хранят произвольные key-value пары, зарегистрированные плагинами. - Плагины могут создавать собственные таблицы через SQL-миграции в своей директории `.verstak/plugins//migrations/`. - `device_id` на уровне nodes позволяет плагинам синхронизировать свои данные через sync_ops.