docs: release notes and version bump for v1.10.0

Document the command palette, reorganized instance menu/tabs, global
minimized-operations tray, owner-scoped live Proxmox resources, and the
React Query cache clear on login/logout; bump VERSION and README badges.
This commit is contained in:
markmorado
2026-07-23 21:59:24 +05:00
parent 0b0b11c689
commit d0824df0f5
6 changed files with 164 additions and 9 deletions

View File

@@ -4,6 +4,45 @@ All notable changes to PVEmanager will be documented in this file.
---
## [v1.10.0] - 2026-07-22
### 🧭 Navigation & Instances
- **Command palette (Ctrl+K)** — searchable palette over a shared registry of navigation items (its own store), for jumping to any page from the keyboard
- **Unified navigation** — the sidebar and command palette are driven by one shared nav-item registry
- **Expanded instance menu** — the per-instance row menu gains **Options**, **Migrate**, **Change resources**, **Create backup** (new `BackupDialog`) and **Delete**; the menu no longer closes on every live list refresh (stable `columns` + `getRowId`)
- **Instance tab reorganization** — for VMs, *Compute resources*, *CPU options*, *Disk management* and *Disk resize* moved from **Settings** to **Hardware**; LXC (which has no Hardware tab) keeps them in **Settings**. Shared cards extracted into `ResourceCards.tsx`
- **New shared UI primitives** — `alert`, `breadcrumb`, `checkbox`, `progress`, `switch`, `textarea`; RU/EN locale keys for the new menu items and backup
### 🛒 App Store
- **Global minimized-operations tray** — minimized long-running operations (app install, golden-template build) now live in a global zustand store (persisted to `localStorage`) and are rendered by a `MinimizedOpsTray` in the app layout instead of by the dialog itself:
- the chip **survives page navigation and a tab reload**; the tray polls progress on its own (REST, every 3 s) independently of the dialog
- clicking a chip returns to the operation's page and reopens the dialog — install resumes in `InstallWizard` (resume mode via navigation state), template reopens the golden dialog with the server preselected
- **Minimize** adds the operation to the tray and closes the dialog; the chip's ✕ only removes the chip (the operation keeps running on the server); chips for operations that no longer exist (404 after reload) are cleared automatically
- **App data files** — files bundled with a catalog app (`data_files`) are delivered before `compose up`; Umbrel `APP_PASSWORD` / `default_credentials` are honored
- **Minimizable install/build dialogs** — long operations can be collapsed via `MinimizableDialog`
- **Install/uninstall reliability**:
- **teardown** — a CT that no longer exists in Proxmox is treated as removed, so an `orphaned` app can finally be deleted from the DB
- **install** — the VMID search skips already-occupied records (`nextid` does not reserve the number, so a retry could grab another container)
- **retry** — install parameters (`cores/memory/disk/storage/bridge/ip_config/port`) are saved to `installed_apps.install_params` (JSONB, new migration) and reused on retry instead of falling back to hard-coded defaults
- **reconcile** — an unreachable server no longer flags all of its apps as `orphaned`
- **update** — the actually-published port is recorded in the DB (`url`/health)
- **.env** — values containing `#` are quoted (the dotenv parser was trimming them as an inline comment)
- port `80`, when chosen explicitly in the wizard, is published as-is
- `useCatalog` — `available_only` is part of the query key (fixes a cache collision)
### 🔒 Owner Isolation
- **Live Proxmox resources are now owner-scoped** — the instance list (`/api/virtual-machines`) was already filtered by `owner_id`, but the live-resource endpoints `/api/resources/all` (dashboard) and `/api/{server_id}/resources` (node/server page) returned **all** VMs/LXC. A regular user (`proxmox.view`) could see other owners' instances through the node page. Both endpoints now filter VM/LXC by owner for non-privileged users (matching `vmid` against the `vm_instances` cache); admins and roles with `vm:manage` still see everything
- **`assign_instances_owner.py`** — script to bulk-assign an owner to existing instances whose `owner_id` is `NULL` (instances synced from Proxmox before ownership existed)
### 🐛 Fixes
- **React Query cache cleared on login/logout** — logging in as a different user in the same tab no longer serves the previous user's cached data (instance list, etc.) until a hard reload. `queryClient` was moved out of `App.tsx` into `lib/query-client.ts` so it is reachable outside React, and `auth-store` calls `queryClient.clear()` on successful login and on logout
---
## [v1.9.1] - 2026-07-17
### 🛒 App Store

View File

@@ -4,6 +4,89 @@
---
## [v1.10.0] - 2026-07-22
### 🧭 Навигация и инстансы
- **Командная палитра (Ctrl+K)** — палитра с поиском поверх общего реестра пунктов навигации (со своим store), позволяет перейти на любую страницу с клавиатуры
- **Единая навигация** — боковое меню и командная палитра работают от одного общего реестра nav-элементов
- **Расширенное меню инстанса** — в меню строки инстанса добавлены **Параметры**, **Мигрировать**, **Изменить ресурсы**, **Создать резервную копию** (новый `BackupDialog`) и **Удалить**; меню больше не закрывается при каждом живом обновлении списка (стабильные `columns` + `getRowId`)
- **Реорганизация вкладок инстанса** — для VM «Вычислительные ресурсы», «Опции CPU», «Управление дисками» и «Изменение размера диска» перенесены со вкладки **Настройки** на **Оборудование**; у LXC (где вкладки «Оборудование» нет) они остаются в **Настройках**. Общие карточки вынесены в `ResourceCards.tsx`
- **Новые общие UI-примитивы** — `alert`, `breadcrumb`, `checkbox`, `progress`, `switch`, `textarea`; ключи локализации RU/EN для новых пунктов меню и бэкапа
### 🛒 App Store
- **Глобальный трей свёрнутых операций** — свёрнутые долгие операции (установка приложения, сборка золотого шаблона) теперь живут в глобальном zustand-сторе (persist в `localStorage`) и рендерятся треем `MinimizedOpsTray` в layout приложения, а не самим диалогом:
- плашка **переживает навигацию между страницами и перезагрузку вкладки**; трей опрашивает прогресс сам (REST, каждые 3 с) независимо от диалога
- клик по плашке возвращает на страницу операции и разворачивает диалог — установка продолжается в `InstallWizard` (resume-режим через navigation state), шаблон открывает диалог золотого шаблона с предвыбранным сервером
- «Свернуть» добавляет операцию в трей и закрывает диалог; крестик на плашке только убирает плашку (операция продолжается на сервере); плашки несуществующих операций (404 после перезагрузки) трей убирает сам
- **Файлы данных приложения** — файлы, поставляемые вместе с приложением каталога (`data_files`), доставляются до `compose up`; учитываются `APP_PASSWORD` / `default_credentials` для Umbrel
- **Сворачиваемые диалоги установки/сборки** — долгие операции можно свернуть через `MinimizableDialog`
- **Надёжность установки/удаления**:
- **teardown** — отсутствующий в Proxmox CT считается удалённым, поэтому `orphaned`-приложение теперь можно удалить из БД
- **install** — поиск VMID сдвигается мимо занятых записей (`nextid` не резервирует номер, из-за чего retry мог подхватить чужой контейнер)
- **retry** — параметры установки (`cores/memory/disk/storage/bridge/ip_config/port`) сохраняются в `installed_apps.install_params` (JSONB, новая миграция) и переиспользуются при повторе вместо жёстких дефолтов
- **reconcile** — недоступный сервер больше не помечает все свои приложения `orphaned`
- **update** — реально опубликованный порт фиксируется в БД (`url`/health)
- **.env** — значения с `#` кавычатся (dotenv-парсер обрезал их как inline-комментарий)
- порт `80`, выбранный явно в мастере, публикуется как есть
- `useCatalog` — `available_only` включён в query key (устранена коллизия кэша)
### 🔒 Изоляция по владельцу
- **Живые ресурсы Proxmox теперь фильтруются по владельцу** — список инстансов (`/api/virtual-machines`) уже фильтровался по `owner_id`, но эндпоинты живых ресурсов `/api/resources/all` (дашборд) и `/api/{server_id}/resources` (страница ноды/сервера) отдавали **все** VM/LXC. Обычный пользователь (`proxmox.view`) через страницу ноды видел чужие инстансы. Оба эндпоинта теперь фильтруют VM/LXC по владельцу для непривилегированных (сверка `vmid` с кэшем `vm_instances`); админы и роли с `vm:manage` по-прежнему видят всё
- **`assign_instances_owner.py`** — скрипт массового назначения владельца существующим инстансам с `owner_id = NULL` (синхронизированным из Proxmox до появления владения)
### 🐛 Исправления
- **Очистка кэша React Query при login/logout** — при входе под другим пользователем в той же вкладке React Query больше не отдаёт закэшированные данные предыдущего пользователя (список инстансов и др.) до жёсткой перезагрузки. `queryClient` вынесен из `App.tsx` в `lib/query-client.ts` (доступен вне React), а `auth-store` вызывает `queryClient.clear()` при успешном входе и при выходе
---
## [v1.9.1] - 2026-07-17
### 🛒 App Store
- **Золотой шаблон отдельно на каждый сервер** — золотой vztmpl теперь хранится и разрешается по `server_id` Proxmox, а не одним глобальным указателем; сборка на одном сервере больше не перезаписывает/ломает шаблон, настроенный для другого. `APPSTORE_GOLDEN_TEMPLATE` теперь только последний запасной вариант для серверов без собственной сборки. Миграция 37 добавляет `app_operations.server_id`
- **Исправление сборки золотого шаблона** — автоматическая сборка (**App Store → золотой шаблон**) больше не падает на финальном шаге экспорта `vzdump` (`unable to parse directory volume name 'vztmpl/probe'`)
- **Надёжность DNS** — LXC приложений App Store (и CT сборки золотого шаблона) теперь получают явный `nameserver` (`APPSTORE_NAMESERVER`, по умолчанию `1.1.1.1 8.8.8.8`) вместо наследования резолвера ноды — это устранило таймауты при загрузке образов на нодах, чей DNS доступен только с хоста (например, через Tailscale)
- **Права bind-mount** — директории данных из `volumes:` приложения (`${APP_DATA_DIR}/...` или относительные пути) заранее создаются перед `up`, что устраняет `Permission denied` для контейнеров, пишущих под non-root пользователем (например, MariaDB)
- **Устранена гонка удаления/переустановки** — удаление приложения теперь ждёт фактического подтверждения Proxmox, что контейнер удалён (до 30 мин, покрывает медленную очистку диска), прежде чем освободить VMID, вместо предположения об успехе после короткого таймаута
- **Retry блокировки `pct create`** — временные ошибки «can't lock file ... got lock» сразу после удаления теперь повторяются несколько раз, а не роняют установку
- **Полный вывод ошибки** — упавшие шаги пайплайна теперь показывают последние 4000 символов вывода команды (раньше первые 2000), так что реальная причина не теряется под шумом прогресса `docker compose pull`
- **UI ошибки установки** — блок ошибки в диалоге установки теперь переносит длинный неразрывный текст (дайджесты образов, пути) и скроллится в своих границах вместо растягивания диалога
---
## [v1.9.0] - 2026-07-09
### 🌐 IPAM
- **Сети привязаны к серверу/ноде и рабочему пространству** — сеть IPAM теперь можно привязать к конкретному серверу/ноде Proxmox и к рабочему пространству; каждое пространство использует одну подсеть, а сеть автоматически выбирается активным пространством в мастерах создания инстанса и установки App Store, так что в типичном случае пользователю больше не нужно выбирать сеть вручную
- **Автовыбор в мастерах** — мастера развёртывания определяют целевую сеть/пул из текущего контекста и подставляют их; отсутствие привязки откатывается к ручному выбору
- Миграция: столбцы привязки сети IPAM к рабочему пространству + флаг «по умолчанию» через `backend/migrations/migrations.py`
### 🔧 Ноды
- **Домен/FQDN в поле хоста Proxmox** — форма добавления/редактирования сервера Proxmox теперь принимает доменное имя или FQDN (не только IP), которое резолвится при подключении
---
## [v1.8.1] - 2026-07-09
### 🛒 App Store
- **Umbrel как второй источник каталога** — каталог теперь мультиисточниковый: наряду с `runtipi/runtipi-appstore` можно включить `getumbrel/umbrel-apps` (~380 приложений). Источники настраиваются через `APPSTORE_SOURCES` (через запятую, по умолчанию `runtipi`); id приложений Umbrel неймспейсятся (`umbrel-<id>`), чтобы каталоги не конфликтовали
- **Compose-адаптер Umbrel** — установка понимает манифесты Umbrel: порт контейнера берётся из сервиса `app_proxy` (`APP_PORT`), runtime-сервисы Umbrel (`app_proxy`, `tor`) вырезаются, повисшие `depends_on` очищаются, а порт основного сервиса публикуется на хосте LXC, чтобы health-check прошёл; поведение Runtipi не меняется
- **Иконки Umbrel** — иконки берутся из отдельного репозитория `getumbrel/umbrel-apps-gallery` (`<app-id>/icon.svg`) при синке и кэшируются как логотипы Runtipi; сбой загрузки галереи никогда не роняет синк каталога
- **Мультиисточниковый синк** — каждый источник синкается независимо (сетевой сбой одного не отменяет другие), а проход *исчез → недоступен* ограничен своим источником, так что синк Runtipi никогда не трогает строки Umbrel
- **Фильтр источника и бейдж (UI)** — App Store получает фильтр по источнику и бейдж источника на карточке, показываемые только когда включено больше одного источника; метаданные каталога теперь отдают доступные `sources`
- **Кастомный порт установки** — мастер установки принимает произвольный порт хоста (валидация 1..65535), переопределяющий дефолт каталога
- **Мгновенная чистка инстанса** — удаление приложения сразу мягко удаляет связанный VM-инстанс для отзывчивости UI
- **Модель данных и настройки** — столбец `catalog_apps.source` (миграция 34); новые env-настройки `APPSTORE_SOURCES`, `UMBREL_APPSTORE_REPO`, `UMBREL_APPSTORE_REF`, `UMBREL_APPSTORE_GALLERY_REPO`
---
## [v1.8.0] - 2026-07-07
### 🛒 App Store

View File

@@ -4,7 +4,7 @@
**Modern web panel for managing Proxmox servers, virtual machines and LXC containers**
[![Version](https://img.shields.io/badge/version-1.8.0-blue?style=flat-square)](CHANGELOG.md)
[![Version](https://img.shields.io/badge/version-1.10.0-blue?style=flat-square)](CHANGELOG.md)
[![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)
[![Docker](https://img.shields.io/badge/docker-ready-2496ED?style=flat-square&logo=docker&logoColor=white)](compose.yml)
[![Python](https://img.shields.io/badge/python-3.12-3776AB?style=flat-square&logo=python&logoColor=white)](backend/)
@@ -39,6 +39,7 @@ PVEmanager is a self-hosted web panel that provides a unified interface for mana
- **Install wizard** — dynamic app parameters (form fields), advanced LXC resources, auto-generated secrets, live install progress over WebSocket, and one-time credential display
- **My Apps lifecycle** — start / stop / restart / logs / delete, with background reconciliation (orphan detection) and per-app status
- **Update & Rollback** — snapshot-backed updates (`docker compose pull`) with health-check and one-click rollback to the pre-update snapshot
- **Global operations tray** — minimize a running install or golden-template build into a global tray that survives page navigation and tab reload; click a chip to resume the dialog where you left off
- **Secure by design** — unprivileged LXC only, Fernet-encrypted secrets, injection-safe `pct exec`/`pct push`, RBAC `app:view` / `app:install` / `app:manage`
### Access & Console
@@ -48,7 +49,7 @@ PVEmanager is a self-hosted web panel that provides a unified interface for mana
- **SSH Keys Management** — personal SSH key library per user; keys selectable when deploying VMs/LXC; admin can manage keys for any user
- **RBAC v2** — granular role-based access control with per-resource permissions
- **Server assignment** — directly assign specific Proxmox servers to users with workspace-conflict validation
- **VM/LXC ownership** — assign an owner user to any VM or LXC container
- **VM/LXC ownership** — assign an owner user to any VM or LXC container; non-privileged users see only their own instances everywhere, including the dashboard and per-node resource views
- **Per-user quotas** — limit each user's number of instances and total vCPU, RAM and disk; enforced at deploy time (HTTP 429), with admin management and self-service usage view
- **Session management** — active session list, remote session revocation, login protection
- **Smart login redirect** — users are automatically routed to the first page they have access to
@@ -60,6 +61,7 @@ PVEmanager is a self-hosted web panel that provides a unified interface for mana
- **Audit log** — full action log with user, timestamp, and details
### Other
- **Command palette** — `Ctrl+K` palette with search over a unified navigation registry for keyboard-driven jumps to any page
- **IPAM** — IP Address Management with allocation history and orphan detection
- **Multilingual** — Russian and English interface; language preference is per-user account
- **Encrypted credentials** — sensitive fields stored encrypted in the database

View File

@@ -4,7 +4,7 @@
**Современная веб-панель для управления серверами Proxmox, виртуальными машинами и контейнерами LXC**
[![Версия](https://img.shields.io/badge/версия-1.8.0-blue?style=flat-square)](CHANGELOG.md)
[![Версия](https://img.shields.io/badge/версия-1.10.0-blue?style=flat-square)](CHANGELOG.md)
[![Лицензия](https://img.shields.io/badge/лицензия-MIT-green?style=flat-square)](LICENSE)
[![Docker](https://img.shields.io/badge/docker-готов-2496ED?style=flat-square&logo=docker&logoColor=white)](compose.yml)
[![Python](https://img.shields.io/badge/python-3.12-3776AB?style=flat-square&logo=python&logoColor=white)](backend/)
@@ -39,6 +39,7 @@ PVEmanager — это самостоятельно размещаемая веб
- **Мастер установки** — динамические параметры приложения (form_fields), расширенные ресурсы LXC, автогенерация секретов, живой прогресс установки по WebSocket и показ учётных данных один раз
- **Жизненный цикл в «Мои приложения»** — start / stop / restart / логи / удаление, с фоновой реконсиляцией (детект orphaned) и статусом по каждому приложению
- **Обновление и откат** — обновления на основе снапшотов (`docker compose pull`) с health-check и откатом в один клик к pre-update снапшоту
- **Глобальный трей операций** — сверните идущую установку или сборку золотого шаблона в глобальный трей, который переживает навигацию между страницами и перезагрузку вкладки; клик по плашке разворачивает диалог с того места, где вы остановились
- **Безопасность by design** — только unprivileged LXC, шифрование секретов (Fernet), защита `pct exec`/`pct push` от инъекций, RBAC `app:view` / `app:install` / `app:manage`
### Доступ и консоль
@@ -46,7 +47,7 @@ PVEmanager — это самостоятельно размещаемая веб
- **Терминал xterm.js** — полностью интерактивный shell непосредственно в браузере для контейнеров LXC
- **Удаленные команды** — выполняйте команды bash через QEMU Guest Agent- **Управление SSH-ключами** — личная библиотека SSH-ключей для каждого пользователя; ключи можно выбирать при развёртывании VM/LXC; админ может управлять ключами любого пользователя- **RBAC v2** — детальный контроль доступа на основе ролей с разрешениями для каждого ресурса
- **Назначение серверов** — напрямую назначайте конкретные серверы Proxmox пользователям с проверкой конфликтов рабочих областей
- **Владелец ВМ/LXC** — назначайте пользователя-владельца любой ВМ или контейнеру LXC
- **Владелец ВМ/LXC** — назначайте пользователя-владельца любой ВМ или контейнеру LXC; непривилегированные пользователи везде видят только свои инстансы, включая дашборд и ресурсы по ноде
- **Квоты на пользователя** — ограничение количества инстансов и суммарных vCPU, RAM и диска для каждого пользователя; проверка при развёртывании (HTTP 429), управление администратором и просмотр собственного использования
- **Управление сессиями** — список активных сессий, отзыв удаленных сессий, защита входа
- **Умное перенаправление входа** — пользователи автоматически маршрутизируются на первую страницу, к которой у них есть доступ
@@ -58,6 +59,7 @@ PVEmanager — это самостоятельно размещаемая веб
- **Журнал аудита** — полный журнал действий с пользователем, временем и деталями
### Прочее
- **Командная палитра** — палитра по `Ctrl+K` с поиском по единому реестру навигации для перехода на любую страницу с клавиатуры
- **IPAM** — управление IP-адресами с историей выделения и обнаружением сиротских адресов
- **Многоязычность** — интерфейс на русском и английском языках; язык задаётся отдельно для каждого аккаунта в профиле
- **Зашифрованные учетные данные** — чувствительные поля хранятся зашифрованными в базе данных

View File

@@ -1 +1 @@
1.9.1
1.10.0

37
WIKI.md
View File

@@ -476,8 +476,14 @@ Automatically tracks:
## 🖥️ VM and Container Management
### Command palette (Ctrl+K)
Press **Ctrl+K** (⌘K on macOS) anywhere in the app to open the **command palette** — a searchable list of every navigation destination. Start typing to filter, then <kbd>Enter</kbd> to jump. The palette and the sidebar are driven by the same unified navigation registry, so they always stay in sync.
### VM Actions
The per-instance row menu (⋯) exposes **Options**, **Migrate**, **Change resources**, **Create backup** and **Delete** alongside the power actions below. The menu stays open across live list refreshes.
| Action | Description | Hotkey |
|--------|-------------|--------|
| Start | Start VM | - |
@@ -486,6 +492,8 @@ Automatically tracks:
| Force Stop | Force stop | - |
| Delete | Delete VM | - |
> **Instance tabs:** for **VMs**, *Compute resources*, *CPU options*, *Disk management* and *Disk resize* live on the **Hardware** tab; **LXC** containers (which have no Hardware tab) keep those cards on the **Settings** tab.
### Bulk Operations
Select multiple VMs/containers and perform mass actions:
@@ -807,17 +815,28 @@ Pipeline (each step is journaled and streamed over WebSocket):
1. Clone the golden LXC template (default 2 vCPU / 2048 MB / 8 GB, DHCP or advanced overrides).
2. Start and wait for IP.
3. `pct push` `docker-compose.yml` + `.env` (form answers + generated `random` secrets).
3. `pct push` `docker-compose.yml` + `.env` (form answers + generated `random` secrets) + any bundled `data_files`.
4. `docker compose up -d`.
5. HTTP health-check.
6. Show the app URL and one-time credentials.
A failed step sets status `error` with a step log; **Retry** does not recreate the LXC (idempotent by VMID), **Delete** removes the container and the record.
A failed step sets status `error` with a step log; **Retry** does not recreate the LXC (idempotent by VMID) and reuses the original install parameters (saved in `installed_apps.install_params`), **Delete** removes the container and the record.
**Reliability notes:**
- Files bundled with a catalog app (`data_files`) are delivered to the container before `docker compose up`; Umbrel `APP_PASSWORD` / `default_credentials` are honored.
- Bind-mount host directories (`volumes:` in the app's compose, both `${APP_DATA_DIR}/...` and relative paths) are pre-created with permissive ownership before `up` — otherwise Docker auto-creates them as root and non-root container users (e.g. mariadb's `mysql`) get `Permission denied`.
- The VMID search skips already-occupied records — `nextid` does not reserve the number, so a retry could otherwise grab another container.
- `pct create` retries a few times on a transient config-lock error (common right after deleting the same VMID, while the node is still wiping the old disk).
- **Delete** now waits for Proxmox to actually confirm the destroy task finished (up to 30 min, covers slow disk wipes) before marking the app removed — otherwise a VMID could be reused while still busy on the node.
- `.env` values containing `#` are quoted (the dotenv parser would otherwise trim them as an inline comment); a port chosen explicitly in the wizard (including `80`) is published as-is.
### Minimized operations tray
Long-running App Store operations — an app **install** and a **golden-template build** — can be minimized instead of keeping the dialog open:
- Minimized operations live in a **global store** (persisted to `localStorage`) and are rendered as a **tray** in the app layout, so a chip **survives page navigation and a full tab reload**. The tray polls each operation's progress itself (REST, every 3 s), independently of the dialog.
- **Clicking a chip** returns to the operation's page and reopens the dialog — an install resumes in the wizard, a template build reopens the golden-template dialog with the server preselected.
- **Minimize** adds the operation to the tray and closes the dialog; the chip's ✕ only removes the chip (the operation keeps running on the server). Chips for operations that no longer exist (a `404` after reload) are cleared automatically.
### My Apps
@@ -1965,6 +1984,16 @@ Returns `409 workspace_conflict` if any server shares no workspace with the user
Any VM or LXC container can have an **owner** — a regular user responsible for that instance. The owner is displayed in the VM list.
### Isolation
Ownership is enforced everywhere a non-privileged user sees instances, not just the instance list. The live-resource endpoints — `/api/resources/all` (dashboard) and `/api/{server_id}/resources` (node/server page) — filter VMs/LXC by owner (matching each `vmid` against the `vm_instances` cache), so a user with only `proxmox.view` cannot see other owners' instances through the node page. **Admins** and roles with **`vm:manage`** are exempt and see everything.
Instances synced from Proxmox before ownership existed have `owner_id = NULL`. To bulk-assign an owner to them, run the helper script shipped in the backend image:
```bash
docker compose exec app python assign_instances_owner.py
```
### Assigning an owner (Admin)
Open the VM detail page → **Owner** button → select user → Save.
@@ -2253,5 +2282,5 @@ A: Not yet, but planned for future versions.
---
*Last updated: June 20, 2026*
*Version: 1.5.2-1*
*Last updated: July 22, 2026*
*Version: 1.10.0*