# Milestone: Platform Runtime 2 — Vault Core Capability
Фиксирует состояние plugin runtime после добавления vault layer как core capability.
## Что реализовано
- **Vault Layer** — полноценный vault service (`internal/core/vault/vault.go`) с созданием, открытием, закрытием и валидацией.
- **Vault Capability** — `verstak/core/vault/v1` регистрируется в `main.go` и доступен плагинам через capability registry.
- **Vault Events** — `vault.created`, `vault.opened`, `vault.closed` публикуются в event bus.
- **Vault Tests** — `internal/core/vault/vault_test.go` покрывает layout creation, open/close cycle, corrupt JSON, path traversal, plugin namespace paths, status transitions, event publishing.
- **platform-test plugin** — статус обновлён: был `degraded` из-за отсутствия vault, теперь `degraded` только из-за отсутствия `verstak/core/sync/v1`.
## Vault Layout
```
/
VerstakVault/ ← vault root (создаётся CreateVault)
.verstak/
vault.json ← VaultMeta: schemaVersion=1, vaultId (UUID), createdAt, updatedAt, app="verstak"
plugin-data/ ← per-plugin data namespaces
/
plugin-settings/ ← per-plugin settings namespaces
/
plugin-cache/ ← per-plugin cache namespaces
/
trash/ ← soft-deleted items
logs/ ← vault-scoped logs
```
`EnsureVaultLayout()` создаёт `.verstak/` и все стандартные поддиректории. Идемпотентен — безопасно вызывать повторно.
## Vault API
| Метод | Описание |
|---|---|
| `NewVault(bus)` | Создаёт Vault instance. Начальный статус: `not-created`. |
| `CreateVault(path)` | Создаёт `VerstakVault/` на указанном пути. Генерирует `vault.json` с UUID. Публикует `vault.created`. Статус → `open`. |
| `OpenVault(path)` | Открывает существующий vault. Валидирует `vault.json` (schemaVersion, vaultId). Публикует `vault.opened`. Статус → `open`. |
| `CloseVault()` | Закрывает vault. Сбрасывает path и meta. Публикует `vault.closed`. Статус → `closed`. |
| `GetVaultStatus()` | Текущий статус: `not-created`, `closed`, `open`, `error`. |
| `GetVaultPath()` | Путь к vault root. |
| `GetVaultMeta()` | Указатель на `VaultMeta` (vaultId, timestamps, app). |
| `ResolveSafePath(rel)` | Резолвит относительный путь внутри vault. Блокирует `../` traversal. Требует `open` vault. |
| `GetPluginDataPath(id)` | Возвращает (и создаёт) `.verstak/plugin-data//`. |
| `GetPluginSettingsPath(id)` | Возвращает (и создаёт) `.verstak/plugin-settings//`. |
| `GetPluginCachePath(id)` | Возвращает (и создаёт) `.verstak/plugin-cache//`. |
## Vault Events
| Event | Когда | Payload |
|---|---|---|
| `vault.created` | Успешный `CreateVault` | `path`, `vaultId` |
| `vault.opened` | Успешный `OpenVault` | `path`, `vaultId` |
| `vault.closed` | `CloseVault` | `vaultId` |
| `vault.error` | Ошибки операций | `error` |
## Vault Status Flow
```
not-created ──CreateVault──▶ open ──CloseVault──▶ closed
│ │
└──OpenVault─────────┘
```
## Core Capabilities (зарегистрированы)
| Capability | Описание |
|---|---|
| `verstak/core/plugin-manager/v1` | Управление плагинами: discovery, enable/disable, reload |
| `verstak/core/capability-registry/v1` | Реестр возможностей: регистрация, запрос, проверка зависимостей |
| `verstak/core/contribution-registry/v1` | Реестр контрибуций: views, commands, sidebar items, actions |
| `verstak/core/permissions/v1` | Реестр разрешений: проверка dangerous, запрос пользователю |
| `verstak/core/events/v1` | In-process event bus: publish/subscribe |
| `verstak/core/vault/v1` | Vault service: создание/открытие/закрытие vault, plugin namespace paths, safe path resolution |
Все 6 capabilities регистрируются в `main.go` до plugin discovery.
## platform-test: текущий статус
| Аспект | Статус |
|---|---|
| Discovery | ✅ |
| Capability resolution (required) | ✅ |
| Capability resolution (optional: vault) | ✅ |
| Capability resolution (optional: sync) | ❌ `verstak/core/sync/v1` отсутствует |
| **Итоговый статус** | **degraded** (только из-за missing sync optional) |
## Команды для проверки
```bash
# 1. Собрать официальные плагины
cd ~/git/verstak2/verstak-official-plugins
./scripts/build.sh
# 2. Установить platform-test как dev plugin
cd ~/git/verstak2/verstak-desktop
./scripts/install-dev-plugins.sh
# 3. Smoke-проверка (headless)
./scripts/smoke-platform.sh
# 4. Запуск приложения
cd ~/git/verstak2/verstak-desktop
go run -mod=mod .
# 5. Vault unit tests
go test ./internal/core/vault/ -v
```
## Что НЕ сделано (намеренно)
- **Sync** (`verstak/core/sync/v1`) — sync boundary существует как заглушка, полная реализация позже.
- **Notes** — плагин для заметок не входит в core.
- **Files** — плагин для файлового менеджера не входит в core.
- **Editor** — markdown editor не входит в core.
Vault — фундамент для всех этих будущих плагинов, но сам по себе не зависит от них.
## Файлы реализации
| Файл | Назначение |
|---|---|
| `verstak-desktop/main.go` | Инициализация core, регистрация 6 capabilities (включая vault), plugin lifecycle |
| `verstak-desktop/internal/core/vault/vault.go` | Vault service: CreateVault, OpenVault, CloseVault, ResolveSafePath, plugin namespace paths |
| `verstak-desktop/internal/core/vault/vault_test.go` | Vault tests: layout, lifecycle, path traversal, events |
| `verstak-desktop/internal/core/capability/registry.go` | CapabilityRegistry |
| `verstak-desktop/internal/core/events/bus.go` | EventBus |
| `verstak-desktop/internal/api/app.go` | Wails API, ReloadPlugins |