* feat(sshid) - sshid.io equivalent for termix (#919) * feat(ssh-id): database schema, migrations and field encryption Adds ssh_identities, ssh_identity_keys and ssh_identity_ca tables (public keys stored plaintext for the unauthenticated resolver; CA private key registered for per-user field encryption), with UNIQUE(user_id), an index on ssh_identity_keys(identity_id), and idempotent CREATE TABLE migrations. * feat(ssh-id): backend API — resolver, key management, CA and certificates Mounts /sshid (nginx route added). Public text/plain authorized_keys resolver (+ exact /:algo filter, HTML viewer) and CA public-key endpoint; no-store + noindex headers on every resolver response including early 404s. Authenticated management: claim/rename/delete handle, add/import/generate/enable/delete keys, and a per-user CA (create/rotate/delete) with pure-Node OpenSSH certificate issuance. Audit logging on all mutations; UNIQUE races map to a precise 409. Unit tests for key parsing and certificate signing (ssh-keygen-validated). * feat(ssh-id): frontend panel, API client and i18n SSH ID panel wired into the app rail and AppShell: claim handle, resolver URL + curl one-liner, key list, generate, paste/import, CA enable/rotate/remove with server trust command, and per-key certificate issuance. API client re-exported through main-axios.ts; all strings i18n'd. * style(ssh-id): align panel and resolver page with Termix theme - Rebuild the SSH ID sidebar panel with the theme's square components (SectionCard / SettingRow / FakeSwitch) instead of rounded ad-hoc cards; use accent-brand and destructive tokens rather than raw red/green. - Fix panel scrolling: move overflow to a block scroll container so the cards keep their natural height instead of being clipped. - Restyle the public resolver HTML page (/sshid/u/:handle) to the Termix dark theme: square corners, #18181b/#303032 palette, #f59145 accent, uppercase section labels. - Tidy copy: 'Save To Credentials' label, drop the redundant generate intro, and correct the generate tooltip (the key is stored when saving to vault). * feat: rename to Termix ID, improve UI, backend inconsistencies, and general bug fixes --------- Co-authored-by: LukeGus <bugattiguy527@gmail.com> * ci(deps): bump actions/checkout from 6 to 7 in the github-actions group (#922) Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 6 to 7 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump the dev-patch-updates group with 11 updates (#923) Bumps the dev-patch-updates group with 11 updates: | Package | From | To | | --- | --- | --- | | [@codemirror/search](https://github.com/codemirror/search) | `6.7.0` | `6.7.1` | | [@codemirror/view](https://github.com/codemirror/view) | `6.43.0` | `6.43.1` | | [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.3.0` | `4.3.1` | | [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.8` | `4.1.9` | | [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) | `4.1.8` | `4.1.9` | | [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh) | `0.5.2` | `0.5.3` | | [lint-staged](https://github.com/lint-staged/lint-staged) | `17.0.7` | `17.0.8` | | [prettier](https://github.com/prettier/prettier) | `3.8.3` | `3.8.4` | | [sharp](https://github.com/lovell/sharp) | `0.35.1` | `0.35.2` | | [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.3.0` | `4.3.1` | | [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.1.8` | `4.1.9` | Updates `@codemirror/search` from 6.7.0 to 6.7.1 - [Changelog](https://github.com/codemirror/search/blob/main/CHANGELOG.md) - [Commits](https://github.com/codemirror/search/commits) Updates `@codemirror/view` from 6.43.0 to 6.43.1 - [Changelog](https://github.com/codemirror/view/blob/main/CHANGELOG.md) - [Commits](https://github.com/codemirror/view/commits) Updates `@tailwindcss/vite` from 4.3.0 to 4.3.1 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.1/packages/@tailwindcss-vite) Updates `@vitest/coverage-v8` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/coverage-v8) Updates `@vitest/ui` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/ui) Updates `eslint-plugin-react-refresh` from 0.5.2 to 0.5.3 - [Release notes](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/releases) - [Changelog](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/blob/main/CHANGELOG.md) - [Commits](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/compare/v0.5.2...v0.5.3) Updates `lint-staged` from 17.0.7 to 17.0.8 - [Release notes](https://github.com/lint-staged/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md) - [Commits](https://github.com/lint-staged/lint-staged/compare/v17.0.7...v17.0.8) Updates `prettier` from 3.8.3 to 3.8.4 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.8.3...3.8.4) Updates `sharp` from 0.35.1 to 0.35.2 - [Release notes](https://github.com/lovell/sharp/releases) - [Commits](https://github.com/lovell/sharp/compare/v0.35.1...v0.35.2) Updates `tailwindcss` from 4.3.0 to 4.3.1 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.1/packages/tailwindcss) Updates `vitest` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/vitest) --- updated-dependencies: - dependency-name: "@codemirror/search" dependency-version: 6.7.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: "@codemirror/view" dependency-version: 6.43.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: "@tailwindcss/vite" dependency-version: 4.3.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: "@vitest/ui" dependency-version: 4.1.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: eslint-plugin-react-refresh dependency-version: 0.5.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: lint-staged dependency-version: 17.0.8 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: prettier dependency-version: 3.8.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: sharp dependency-version: 0.35.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: tailwindcss dependency-version: 4.3.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates - dependency-name: vitest dependency-version: 4.1.9 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-patch-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump nanoid in the prod-patch-updates group (#925) Bumps the prod-patch-updates group with 1 update: [nanoid](https://github.com/ai/nanoid). Updates `nanoid` from 5.1.11 to 5.1.15 - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/5.1.11...5.1.15) --- updated-dependencies: - dependency-name: nanoid dependency-version: 5.1.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-patch-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump the major-updates group with 5 updates (#926) Bumps the major-updates group with 5 updates: | Package | From | To | | --- | --- | --- | | [js-yaml](https://github.com/nodeca/js-yaml) | `4.2.0` | `5.0.0` | | [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.39.4` | `10.0.1` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.9.2` | `26.0.0` | | [concurrently](https://github.com/open-cli-tools/concurrently) | `9.2.1` | `10.0.3` | | [eslint](https://github.com/eslint/eslint) | `9.39.4` | `10.5.0` | Updates `js-yaml` from 4.2.0 to 5.0.0 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.2.0...5.0.0) Updates `@eslint/js` from 9.39.4 to 10.0.1 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/commits/v10.0.1/packages/js) Updates `@types/node` from 25.9.2 to 26.0.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `concurrently` from 9.2.1 to 10.0.3 - [Release notes](https://github.com/open-cli-tools/concurrently/releases) - [Commits](https://github.com/open-cli-tools/concurrently/compare/v9.2.1...v10.0.3) Updates `eslint` from 9.39.4 to 10.5.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v9.39.4...v10.5.0) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: major-updates - dependency-name: "@eslint/js" dependency-version: 10.0.1 dependency-type: direct:development update-type: version-update:semver-major dependency-group: major-updates - dependency-name: "@types/node" dependency-version: 26.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: major-updates - dependency-name: concurrently dependency-version: 10.0.3 dependency-type: direct:development update-type: version-update:semver-major dependency-group: major-updates - dependency-name: eslint dependency-version: 10.5.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: major-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(ssh): add HashiCorp Vault SSH signer authentication * fix: small fixes to vault feature to align with Termix codebase * chore: add view docs links for vault/termix id * fix: file upload fails with 400 and missing schema migrations on upgrade (#929) Two bugs introduced in v2.4.1: 1. uploadFileStream uses fileManagerApi.post() which triggers axios's transformRequest to JSON-serialize the FormData because the instance default Content-Type is application/json. Change to postForm() which sets Content-Type: multipart/form-data so the browser XHR sends the correct multipart body with boundary. 2. Two schema items added to schema.ts were not included in migrateSchema() in db/index.ts, causing 500 errors on existing installations upgrading from v2.4.0: - user_preferences.status_color_scheme (no such column) - dashboard_service_links table (no such table) Fixes #928 Co-authored-by: sash <sash@fominykh.io> * fix: support PuTTY PPK ssh keys (#930) * fix: chunk large file manager uploads (#932) * fix: route dashboard hosts by protocol (#934) * fix: resolve tunnel endpoints reliably (#935) * Fix Electron OIDC browser auth failures (#936) * Allow RDP connections without stored credentials (#937) * Sync role credential shares for OIDC users (#938) * Fix terminal link dialog layering (#940) * Confirm large files before opening editor (#942) * Confirm closing active host connections (#943) * Preserve file path case in file manager UI (#941) * fix: preserve unicode guacamole tokens (#933) * Persist VNC authentication settings (#944) * Fix Guacamole websocket base path (#946) * Promote file manager terminals to tabs (#939) * Guard Guacamole disconnect during startup (#945) * chore: increment ver * feat: bitwarden ssh agent integration * feat: serial connections support * fix: various small bug fixes * feat: open all sessions in a folder and terminal custom theme color support * feat: cross host file manager clipboard and several small bug fixes * feat: tailscale/wireguard support and added a new status state for when backend is checking status * feat: grafana like server stats history, new alert system, ntfy/webhook support * feat: new grid and widget based homepage function * feat: new donate button in dashboard * fix: alert ui incorrectly using termix css and fixed issue with alert system not loading * chore: start database layer refactor * docs: plan database layer refactor * docs: audit database layer refactor phase zero * chore: add database runtime adapter skeleton * chore: add settings repository skeleton * chore: add user session repository skeleton * chore: add host credential repository skeleton * chore: add field encryption boundary * chore: migrate settings route slice * chore: migrate user settings routes * chore: migrate host metrics settings routes * chore: migrate acme settings route * chore: migrate terminal settings route * chore: migrate tailscale settings read * chore: migrate guacamole settings reads * chore: migrate session timeout settings reads * chore: migrate auth route settings reads * chore: migrate host metrics settings reads * chore: migrate startup settings reads * chore: migrate user settings cleanup * chore: migrate password reset settings * chore: migrate oidc legacy settings read * chore: migrate user route settings slice * chore: migrate oidc state settings * chore: migrate user login settings reads * chore: migrate user crypto settings * chore: consolidate startup settings defaults * chore: consolidate database settings import export * chore: migrate core session auth paths * chore: migrate remaining session auth paths * chore: migrate admin user routes * chore: migrate user route admin checks * chore: migrate user lifecycle routes * chore: migrate auth user lookups * chore: migrate oidc user routes * chore: migrate api key repository paths * docs: add database gray rollout guide * chore: migrate trusted device paths * chore: migrate user session route user lookups * chore: add database repository rollout guard * chore: expose repository rollout status * chore: warn on repository rollout misconfiguration * chore: migrate remaining user lookup helpers * chore: migrate ssh user lookups * chore: migrate user settings admin lookups * chore: migrate acme ssl user lookups * chore: migrate audit log admin checks * chore: migrate oidc account user updates * chore: migrate password reset user updates * chore: migrate user deletion core records * chore: migrate snippet audit user lookups * chore: migrate ldap user sync paths * chore: migrate totp user updates * chore: migrate rbac user checks * chore: migrate rbac role paths * chore: migrate permission role lookups * chore: migrate rbac access list reads * chore: migrate shared rbac reads * chore: migrate rbac access writes * chore: migrate permission host access * chore: migrate role host access lookup * chore: migrate snippet access lookup * chore: migrate shared credential access lookups * chore: migrate host access cleanup writes * chore: migrate host list access checks * chore: migrate host access cleanup routes * chore: migrate shared credential role lookups * chore: migrate user role cleanup * chore: migrate admin role sync * chore: migrate ldap role sync * chore: migrate user role assignment * chore: migrate sso provider access * chore: migrate audit log access * chore: migrate user preference access * chore: migrate open tab access * chore: migrate dismissed alert access * chore: migrate homepage layout access * chore: migrate network topology access * chore: migrate dashboard service link access * chore: migrate command history access * chore: migrate recent activity cleanup * chore: migrate ssh credential usage access * chore: migrate transfer recent access * chore: migrate file manager bookmark access * chore: migrate c2s tunnel preset access * chore: migrate homepage item access * chore: migrate session recording access * chore: migrate tmux session tag access * chore: migrate opkssh token access * chore: migrate vault token access * chore: migrate vault profile access * chore: migrate host metrics preference access * chore: migrate host health access * chore: migrate host metrics history access * chore: migrate alert persistence access * chore: route alert host lookup through repository * chore: migrate user data export reads * chore: route host metrics stats sync through repository * chore: migrate host folder persistence * chore: migrate host resolution reads * chore: route jump host resolution reads * chore: route docker console jump host reads * chore: route docker ssh resolution reads * chore: route proxmox discovery resolution reads * chore: route file manager activity host reads * chore: route host metrics resolution reads * chore: route ssh auth credential reads * chore: route tunnel endpoint credential reads * chore: route credential deployment resolution reads * chore: route command history host flag reads * chore: route snippet execution resolution reads * chore: route terminal host resolution reads * chore: route vault oidc host resolution reads * chore: route wake on lan host reads * chore: route internal host list reads * chore: route host key verification persistence * chore: route credential read paths * chore: route credential host usage reads * chore: route credential folder rename * chore: route host owner access checks * chore: route shared credential source reads * chore: route user host credential cleanup * chore: route credential delete reads * chore: route credential update reads * chore: route host credential reads * chore: route host read paths * chore: route host projection reads * chore: route host list reads * chore: route snippet read paths * chore: route snippet folder writes * chore: route snippet crud paths * chore: route snippet bulk import * chore: route rbac ownership reads * chore: route user count reads * chore: route cleanup snippets folders * chore: route shared credential persistence * chore: route dashboard activity * chore: route guacamole host reads * chore: route host bulk lookups * chore: remove unlock-only simple db ops * chore: route host autostart persistence * chore: route ldap provisioning through users * chore: route credential encrypted writes * chore: route host encrypted writes * chore: route bulk host encrypted writes * chore: route termix id credentials * chore: route termix id ca persistence * chore: route termix identity persistence * chore: route credential system migration * chore: isolate user encryption migration storage * chore: remove legacy simple db ops * chore: isolate legacy sqlite migration copy * chore: route database settings import export * chore: route database host credential export * chore: route database host credential import * chore: route database file-manager import export * chore: route database alert usage import export * chore: route database user checks * chore: isolate auth lazy migration storage * chore: route explicit database saves * chore: initialize database save boundary * chore: route migration snapshot saves * chore: isolate sqlite import constraints * chore: route import sqlite boundary * chore: route user encryption migration store * chore: centralize current repository runtime * chore: route more current repositories * chore: route activity repository runtimes * chore: route token repository runtimes * chore: route health repository runtimes * chore: route identity repository runtimes * chore: route rbac repository runtime * chore: centralize current sqlite runtime access * chore: route user deletion key cleanup * chore: route user deletion vault cleanup * chore: route user deletion homepage cleanup * chore: route user deletion health cleanup * chore: route user deletion alert cleanup * chore: route user deletion identity cleanup * chore: add database layer preupgrade backup * Fix database repository type errors * fix: complete post-merge compile fixes for database refactor Restore missing DatabaseSaveTrigger/getDb imports, session log format fallback, OIDC provider resolution, guacamole recording insert, and passwordFallbackOnly typing after merging current dev. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: DivByZero <mr.oplus@yahoo.fr> Co-authored-by: LukeGus <bugattiguy527@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: devdanetra <46488477+devdanetra@users.noreply.github.com> Co-authored-by: Aleksandr Fominykh <neoformalex@users.noreply.github.com> Co-authored-by: sash <sash@fominykh.io>
34 KiB
Database Layer Gray Rollout Guide
Status: Draft branch gray-rollout guide
Branch: feature/database-layer-refactor
Scope: repository-boundary migration for current SQLite snapshot runtime
This branch is not the full multi-database refactor. Gray rollout is only for the already-migrated repository boundary paths while the production runtime still uses the existing encrypted SQLite snapshot model.
1. Gray Scope
Allowed in gray rollout:
- Existing encrypted SQLite snapshot runtime.
- Existing database file format.
- Existing schema and migration flow.
- Settings, user, host, API key, session, trusted device, audit log, user
preference, open tab, dismissed alert, homepage layout/item, and network
topology, dashboard service link, session recording, command history, recent
activity, transfer recent, and file-manager bookmark current repository
plus C2S tunnel preset, tmux session tag, OPKSSH token, Vault token/profile,
SSH credential usage, role, SSO provider, host folder, alert, host health,
host metrics preference/history, credential, host resolution, snippet,
RBAC access, shared credential, Termix ID identity/CA, and user data export
current repository factories share
current-repository-runtimefor SQLite context and write-save hooks. - Settings reads and writes migrated behind
SettingsRepository. - Database import/export settings reads and admin upserts migrated behind
SettingsRepository. - Session create/read/update/revoke/list paths migrated behind
SessionRepository. - User create/read/update/delete/auth paths migrated behind
UserRepository. - User setup/count/db-health, password-login TOTP guard, and last-admin delete
guard reads migrated behind
UserRepository. - Database import/export user unlock/admin checks migrated behind
UserRepository. - LDAP first-user provisioning and admin-group user creation migrated behind
UserRepository. - API key create/list/delete and authentication last-used updates migrated behind
ApiKeyRepository. - Trusted device check/add/remove and TOTP trusted-device cleanup migrated
behind
TrustedDeviceRepository. - Credential list, folder list, detail reads, update lookup/readback, host route
credential resolution reads, folder rename writes, apply usage writes, shared
credential source row reads, credential delete lookup/delete, and
credential-host list reads migrated behind
CredentialRepositoryandHostResolutionRepository. - Database export host and credential read/decryption paths migrated behind
HostRepositoryandCredentialRepository. - Database import host and credential duplicate checks plus encrypted creates
migrated behind
HostRepositoryandCredentialRepository. - Credential create/update encrypted writes migrated behind
CredentialRepository, including system-key copies for shared credentials. - Credential delete host cleanup and apply-to-host writes migrated behind
HostRepository. - Credential system-key copy backfill migration migrated behind
CredentialRepositoryandSharedCredentialRepository. - Legacy user field-encryption migration SQL centralized behind
RawSqliteUserEncryptionMigrationStore. - Auth login lazy user-field encryption migration now calls the
DataCryptocurrent-runtime migration boundary instead of opening SQLite inauth-manager.ts. - Current user-field encryption migration now resolves SQLite through
createCurrentUserEncryptionMigrationStoreand the shared current runtime helper, keepingDataCryptoon the migration-store interface. - User, admin, TOTP, OIDC account, and credential migration explicit saves now
use
DatabaseSaveTriggerinstead of importing the SQLite snapshot save function from routes. - Current SQLite snapshot save trigger now initializes after database startup regardless of file-encryption mode, and backend shutdown uses that save boundary.
- Direct SQLite snapshot save-function imports are now isolated inside
database/db/index.ts; current user-field migration saves throughDatabaseSaveTrigger. - Database import SQLite foreign-key toggling is isolated behind the
withSqliteForeignKeysDisabledruntime boundary and restores constraints in afinallypath; the current variant resolves SQLite through the shared current runtime helper. - Database import now uses the current SQLite foreign-key boundary without
importing
getDb()in the route handler. - Legacy unencrypted SQLite copy/verification path centralized behind
LegacySqliteDatabaseCopyStore. - Termix ID credential lookup, generated credential persistence, and generated
credential cleanup migrated behind
CredentialRepository. - Host route update readback, single-host fetch, password-field fetch, and host
export reads migrated behind
HostResolutionRepository. - Host route create/update encrypted writes migrated behind
HostRepository. - Host route update-state and delete-audit host reads migrated behind
HostResolutionRepository. - Host route delete final host-row writes and audit actor username lookups
migrated behind
HostRepositoryandUserRepository. - Host route own/shared list assembly reads migrated behind
HostResolutionRepositorywhile preserving route-level own-host decryption. - Host bulk-update state reads and non-sensitive bulk flag/config writes
migrated behind
HostRepository. - Host bulk import overwrite lookup and credential fallback reads migrated behind current host resolution and credential repository boundaries.
- Host bulk JSON and SSH-config import encrypted create/update writes migrated
behind
HostRepository. - Host autostart enable, disable, status, and endpoint-host resolution paths
migrated behind
HostRepository. - Guacamole host token host and protocol credential reads migrated behind
HostResolutionRepository. - Host user-cleanup delete paths migrated behind
HostRepository. - Snippet folder list/create/metadata/rename/delete, owned lookup, visible-list
owned reads, reorder, create/update/delete, export reads, and bulk import
plus user/password-reset cleanup migrated behind
SnippetRepository. - Host folder metadata user cleanup migrated behind
HostFolderRepository. - SSO provider listing, management, OIDC config loading, and LDAP provider
validation migrated behind
SsoProviderRepository. - Audit log writes, filtered reads, action lists, and user cleanup migrated
behind
AuditLogRepository. - User preferences read/write and user cleanup migrated behind
UserPreferenceRepository. - Open tab restore/upsert/sync/update/delete and user cleanup migrated behind
OpenTabRepository. - Dismissed alert read/dismiss/undismiss/export and user cleanup migrated behind
DismissedAlertRepository. - Database import/export dismissed alert reads and writes migrated behind
DismissedAlertRepository. - Homepage layout read/write paths migrated behind
HomepageLayoutRepository. - Homepage item list/create/update/delete migrated behind
HomepageItemRepository. - Network topology read/write and user cleanup migrated behind
NetworkTopologyRepository. - Dashboard service link list/create/update/delete migrated behind
DashboardServiceLinkRepository. - Session recording create/list/read/content/delete/prune and host/folder/user
cleanup migrated behind
SessionRecordingRepository. - Command history save/list/delete and host/user cleanup migrated behind
CommandHistoryRepository. - Dashboard recent activity list/log/trim/reset and host/user cleanup migrated
behind
RecentActivityRepository. - SSH credential usage writes and host/user cleanup migrated behind
SshCredentialUsageRepository. - Database export SSH credential usage reads migrated behind
SshCredentialUsageRepository. - Transfer recent list/upsert/prune/export and host/folder/user cleanup migrated
behind
TransferRecentRepository. - File manager recent/pinned/shortcut list/create/delete/export and
host/folder/user/password-reset cleanup migrated behind
FileManagerBookmarkRepository. - Database import/export file-manager recent/pinned/shortcut target reads and
writes migrated behind
FileManagerBookmarkRepository. - C2S tunnel preset list/create/update/delete migrated behind
C2sTunnelPresetRepository. - Tmux session tag list/rename/delete/replace migrated behind
TmuxSessionTagRepository. - OPKSSH token upsert/read/touch/delete and user cleanup migrated behind
OpksshTokenRepository. - Vault token upsert/read/touch/delete migrated behind
VaultTokenRepository. - Vault profile list/create/update/delete and profile lookup migrated behind
VaultProfileRepository. - Host metrics layout preference read/upsert and statsConfig widget sync migrated behind
HostMetricsPreferenceRepository. - Host health check config and history read/write migrated behind
HostHealthRepository. - Host metrics history record/prune/query migrated behind
HostMetricsHistoryRepository. - Alert notification channels, rules, linked channels, firings, and alert
engine persistence reads/writes migrated behind
AlertRepository. - User data export host and credential read models migrated behind
UserDataExportRepository. - SSH folder list, metadata upsert, rename, and folder host deletion writes
migrated behind
HostFolderRepository. - Host, jump-host, Docker SSH, Proxmox discovery, Docker console jump-host,
file-manager activity, host metrics, terminal SSH auth, and tunnel endpoint
credential plus credential deployment and command history host-flag resolution
plus snippet execution, terminal OPKSSH/activity, Vault OIDC profile, and
Wake-on-LAN host, internal host list, host-key verification metadata,
credential, permission-manager owner checks, and shared override read/write
models migrated behind
HostResolutionRepository. - Host metrics, host metrics viewer, tmux monitor, Docker, tunnel, and Proxmox
unlock gates now use
DataCryptodirectly instead ofSimpleDBOps. - Legacy
SimpleDBOpscompatibility helper removed after migrated route and utility paths stopped importing it. - RBAC role management and user-role assignment/listing paths migrated behind
RoleRepository. - Permission manager role permission aggregation and admin-role checks migrated
behind
RoleRepository. - User deletion role-assignment cleanup migrated behind
RoleRepository. - User deletion API key, trusted device, dashboard link, homepage layout/item, host health, host metrics preference, C2S preset, Vault token/profile, audit, alert, Termix ID identity/CA, tmux session tag, encrypted-data, UI state, and related per-user cleanup now uses current repository boundaries before the final user row delete.
- User admin route role sync and admin-created default role assignment migrated
behind
RoleRepository. - LDAP login default role assignment and admin-role sync migrated behind
RoleRepository. - Local, GitHub OIDC, and standard OIDC user default role assignment plus OIDC
admin-group role sync migrated behind
RoleRepository. - RBAC host/snippet access-list read models migrated behind
RbacAccessRepository. - RBAC shared host/shared snippet read models migrated behind
RbacAccessRepository. - RBAC route host/snippet owner checks and direct host-access credential existence reads migrated behind current host, snippet, and credential repository boundaries.
- RBAC host/snippet access grant, revoke, and direct host-access credential
override writes migrated behind
RbacAccessRepository. - Shared credential material create/update/delete, pending re-encryption, and
user cleanup persistence migrated behind
SharedCredentialRepository. - Permission manager host-access cleanup, shared-access lookup, and last-access
touch migrated behind
RbacAccessRepository. - Termix ID identity handle CRUD/resolution, public key publish/list/update/delete,
linked credential lookup, and certificate target key lookup migrated behind
TermixIdentityRepository. - Termix ID CA public lookup, encrypted private-key create/rotate/delete, and
certificate signing reads migrated behind
TermixIdentityCaRepository. - Current field encryption behavior.
Not included in gray rollout:
- PostgreSQL or MySQL/MariaDB runtime.
- New external database configuration UI.
- New schema migration strategy.
- Host and credential route migration beyond existing repository skeletons.
- Remaining audit, preferences, file manager, and metrics repository migration.
- Multi-instance backend deployment.
2. Required Preflight
Before enabling this branch for any gray target:
- Confirm the target is running from a full backup of the data directory.
- Confirm the app can write to the data directory so the automatic pre-upgrade backup can be created before first database startup.
- Record the exact source commit and container/image tag currently serving traffic.
- Confirm the gray build commit is known.
- Run the validation commands from this branch.
- Use a target with a small, known user set first.
- Keep an operator available for rollback during the first login/API-key smoke tests.
Repository rollout is controlled by DATABASE_LAYER_REPOSITORY_ROLLOUT.
Recommended gray value:
DATABASE_LAYER_REPOSITORY_ROLLOUT=settings,users,sessions,api_keys,trusted_devices,credentials,termix_identity,termix_identity_ca,hosts,snippets,sso_providers,audit_logs,user_preferences,open_tabs,dismissed_alerts,homepage_layouts,homepage_items,network_topology,dashboard_service_links,session_recordings,command_history,recent_activity,ssh_credential_usage,transfer_recent,file_manager_bookmarks,c2s_tunnel_presets,tmux_session_tags,opkssh_tokens,vault_tokens,vault_profiles,host_metrics_preferences,host_health,host_metrics_history,alerts,user_data_exports,host_folders,host_resolution,roles,rbac_access,shared_credentials
Accepted values:
| Value | Behavior |
|---|---|
| unset | current migrated slice enabled; logs implicit |
all, true, 1, on, enabled |
all current migrated repository domains |
off, false, 0, none, disabled |
no migrated repository domains; fail closed |
comma list, for example settings,users |
only listed repository domains enabled |
aliases such as user, api-key, apikey |
normalized to the supported domain names |
Supported domains:
settingsuserssessionsapi_keystrusted_devicescredentialstermix_identitytermix_identity_cahostssnippetssso_providersaudit_logsuser_preferencesopen_tabsdismissed_alertshomepage_layoutshomepage_itemsnetwork_topologydashboard_service_linkssession_recordingscommand_historyrecent_activityssh_credential_usagetransfer_recentfile_manager_bookmarksc2s_tunnel_presetstmux_session_tagsopkssh_tokensvault_tokensvault_profileshost_metrics_preferenceshost_healthhost_metrics_historyalertsuser_data_exportshost_foldershost_resolutionrolesrbac_accessshared_credentials
The backend logs the parsed rollout mode at startup with operation
repository_rollout_config. Use an explicit value in any staging or production
gray target so logs show the intended rollout state.
Admin users can also verify the active rollout state through
GET /database/migration/status. The response includes repositoryRollout
with the parsed mode, enabled domains, supported domains, env key, and whether
the value was explicitly configured. Startup logs and this endpoint also expose
rollout warnings for implicit, disabled, or partial configurations.
Minimum backup artifacts:
- encrypted SQLite snapshot file
- environment configuration
- application version or image tag
- logs from the last healthy startup on the previous version
This branch also creates one automatic pre-upgrade backup before opening the
database for the first time. If db.sqlite.encrypted, db.sqlite.encrypted.meta,
or db.sqlite exists and .database-layer-preupgrade-backup.json is absent, the
backend copies the database file(s) plus .env into:
<DATA_DIR>/backups/pre-database-layer-refactor-<timestamp>/
The backup directory and marker both include a manifest.json payload with the
app version, rollout config, source files, copied files, and backup reason. A
successful marker prevents repeat backups on every restart. If the backup cannot
be created, startup fails closed. Operators may bypass only when an external
backup has already been verified:
DATABASE_LAYER_SKIP_PREUPGRADE_BACKUP=1
The app keeps the latest three automatic pre-upgrade backups by default. Override
with DATABASE_LAYER_PREUPGRADE_BACKUP_KEEP=<count>.
3. Required Validation Commands
Run before deployment:
npm run type-check
npx eslint src/backend/database/repositories/repository-rollout.ts src/backend/database/repositories/repository-rollout.test.ts src/backend/database/repositories/current-settings-repository.ts src/backend/database/repositories/current-user-repository.ts src/backend/database/repositories/current-session-repository.ts src/backend/database/repositories/current-api-key-repository.ts src/backend/database/repositories/current-trusted-device-repository.ts src/backend/database/repositories/current-credential-repository.ts src/backend/database/repositories/credential-repository.ts src/backend/database/repositories/current-host-repository.ts src/backend/database/repositories/host-repository.ts src/backend/database/repositories/host-credential-repositories.test.ts src/backend/database/repositories/current-sso-provider-repository.ts src/backend/database/repositories/sso-provider-repository.ts src/backend/database/repositories/sso-provider-repository.test.ts src/backend/database/repositories/current-audit-log-repository.ts src/backend/database/repositories/audit-log-repository.ts src/backend/database/repositories/audit-log-repository.test.ts src/backend/database/repositories/current-user-preference-repository.ts src/backend/database/repositories/user-preference-repository.ts src/backend/database/repositories/user-preference-repository.test.ts src/backend/database/repositories/current-open-tab-repository.ts src/backend/database/repositories/open-tab-repository.ts src/backend/database/repositories/open-tab-repository.test.ts src/backend/database/repositories/current-dismissed-alert-repository.ts src/backend/database/repositories/dismissed-alert-repository.ts src/backend/database/repositories/dismissed-alert-repository.test.ts src/backend/database/repositories/current-homepage-layout-repository.ts src/backend/database/repositories/homepage-layout-repository.ts src/backend/database/repositories/homepage-layout-repository.test.ts src/backend/database/repositories/current-homepage-item-repository.ts src/backend/database/repositories/homepage-item-repository.ts src/backend/database/repositories/homepage-item-repository.test.ts src/backend/database/repositories/current-network-topology-repository.ts src/backend/database/repositories/network-topology-repository.ts src/backend/database/repositories/network-topology-repository.test.ts src/backend/database/repositories/current-dashboard-service-link-repository.ts src/backend/database/repositories/dashboard-service-link-repository.ts src/backend/database/repositories/dashboard-service-link-repository.test.ts src/backend/database/repositories/current-session-recording-repository.ts src/backend/database/repositories/session-recording-repository.ts src/backend/database/repositories/session-recording-repository.test.ts src/backend/database/repositories/current-command-history-repository.ts src/backend/database/repositories/command-history-repository.ts src/backend/database/repositories/command-history-repository.test.ts src/backend/database/repositories/current-recent-activity-repository.ts src/backend/database/repositories/recent-activity-repository.ts src/backend/database/repositories/recent-activity-repository.test.ts src/backend/database/repositories/current-ssh-credential-usage-repository.ts src/backend/database/repositories/ssh-credential-usage-repository.ts src/backend/database/repositories/ssh-credential-usage-repository.test.ts src/backend/database/repositories/current-transfer-recent-repository.ts src/backend/database/repositories/transfer-recent-repository.ts src/backend/database/repositories/transfer-recent-repository.test.ts src/backend/database/repositories/current-file-manager-bookmark-repository.ts src/backend/database/repositories/file-manager-bookmark-repository.ts src/backend/database/repositories/file-manager-bookmark-repository.test.ts src/backend/database/repositories/current-c2s-tunnel-preset-repository.ts src/backend/database/repositories/c2s-tunnel-preset-repository.ts src/backend/database/repositories/c2s-tunnel-preset-repository.test.ts src/backend/database/repositories/current-tmux-session-tag-repository.ts src/backend/database/repositories/tmux-session-tag-repository.ts src/backend/database/repositories/tmux-session-tag-repository.test.ts src/backend/database/repositories/current-opkssh-token-repository.ts src/backend/database/repositories/opkssh-token-repository.ts src/backend/database/repositories/opkssh-token-repository.test.ts src/backend/database/repositories/current-vault-token-repository.ts src/backend/database/repositories/vault-token-repository.ts src/backend/database/repositories/vault-token-repository.test.ts src/backend/database/repositories/current-vault-profile-repository.ts src/backend/database/repositories/vault-profile-repository.ts src/backend/database/repositories/vault-profile-repository.test.ts src/backend/database/repositories/current-host-metrics-preference-repository.ts src/backend/database/repositories/host-metrics-preference-repository.ts src/backend/database/repositories/host-metrics-preference-repository.test.ts src/backend/database/repositories/current-host-health-repository.ts src/backend/database/repositories/host-health-repository.ts src/backend/database/repositories/host-health-repository.test.ts src/backend/database/repositories/current-host-metrics-history-repository.ts src/backend/database/repositories/host-metrics-history-repository.ts src/backend/database/repositories/host-metrics-history-repository.test.ts src/backend/database/repositories/current-alert-repository.ts src/backend/database/repositories/alert-repository.ts src/backend/database/repositories/alert-repository.test.ts src/backend/database/repositories/current-user-data-export-repository.ts src/backend/database/repositories/user-data-export-repository.ts src/backend/database/repositories/user-data-export-repository.test.ts src/backend/database/repositories/current-host-folder-repository.ts src/backend/database/repositories/host-folder-repository.ts src/backend/database/repositories/host-folder-repository.test.ts src/backend/database/repositories/current-host-resolution-repository.ts src/backend/database/repositories/host-resolution-repository.ts src/backend/database/repositories/host-resolution-repository.test.ts src/backend/database/repositories/current-snippet-repository.ts src/backend/database/repositories/snippet-repository.ts src/backend/database/repositories/snippet-repository.test.ts src/backend/database/repositories/current-role-repository.ts src/backend/database/repositories/role-repository.ts src/backend/database/repositories/role-repository.test.ts src/backend/database/repositories/current-rbac-access-repository.ts src/backend/database/repositories/rbac-access-repository.ts src/backend/database/repositories/rbac-access-repository.test.ts src/backend/database/routes/rbac.ts src/backend/database/routes/snippets.ts src/backend/database/routes/host.ts src/backend/database/routes/credentials.ts src/backend/database/routes/delete-user-data.ts src/backend/database/routes/open-tabs.ts src/backend/database/routes/user-preferences.ts src/backend/database/routes/user-admin-routes.ts src/backend/database/routes/ldap-auth-routes.ts src/backend/database/routes/users.ts src/backend/database/routes/user-oidc-utils.ts src/backend/database/routes/sso-provider-routes.ts src/backend/database/routes/audit-log-routes.ts src/backend/database/routes/host-folder-routes.ts src/backend/database/routes/host-file-manager-bookmark-routes.ts src/backend/database/routes/c2s-tunnel-presets.ts src/backend/database/routes/alerts.ts src/backend/database/routes/alert-rules-routes.ts src/backend/database/routes/homepage-layout-routes.ts src/backend/database/routes/homepage-items-routes.ts src/backend/database/routes/network-topology.ts src/backend/database/routes/dashboard-service-links-routes.ts src/backend/database/routes/session-log-routes.ts src/backend/database/routes/host-command-history-routes.ts src/backend/database/routes/terminal.ts src/backend/database/routes/user-password-reset-routes.ts src/backend/ssh/terminal-session-manager.ts src/backend/ssh/tmux-monitor.ts src/backend/ssh/opkssh-auth.ts src/backend/ssh/vault-signer-auth.ts src/backend/ssh/vault-oidc-auth.ts src/backend/ssh/host-resolver.ts src/backend/ssh/host-metrics-preferences-routes.ts src/backend/ssh/managers/health.ts src/backend/ssh/host-metrics.ts src/backend/ssh/host-metrics-history-routes.ts src/backend/ssh/alert-engine.ts src/backend/utils/user-data-export.ts src/backend/utils/audit-logger.ts src/backend/utils/audit-logger.test.ts src/backend/utils/permission-manager.ts src/backend/utils/shared-credential-manager.ts src/backend/starter.ts
npm run test -- src/backend/database/runtime/config.test.ts src/backend/database/runtime/sqlite-adapter.test.ts src/backend/database/repositories/repository-rollout.test.ts src/backend/database/repositories/settings-repository.test.ts src/backend/database/repositories/user-session-repositories.test.ts src/backend/database/repositories/api-key-repository.test.ts src/backend/database/repositories/trusted-device-repository.test.ts src/backend/database/repositories/sso-provider-repository.test.ts src/backend/database/repositories/audit-log-repository.test.ts src/backend/database/repositories/user-preference-repository.test.ts src/backend/database/repositories/open-tab-repository.test.ts src/backend/database/repositories/dismissed-alert-repository.test.ts src/backend/database/repositories/homepage-layout-repository.test.ts src/backend/database/repositories/homepage-item-repository.test.ts src/backend/database/repositories/network-topology-repository.test.ts src/backend/database/repositories/dashboard-service-link-repository.test.ts src/backend/database/repositories/session-recording-repository.test.ts src/backend/database/repositories/command-history-repository.test.ts src/backend/database/repositories/recent-activity-repository.test.ts src/backend/database/repositories/ssh-credential-usage-repository.test.ts src/backend/database/repositories/transfer-recent-repository.test.ts src/backend/database/repositories/file-manager-bookmark-repository.test.ts src/backend/database/repositories/c2s-tunnel-preset-repository.test.ts src/backend/database/repositories/tmux-session-tag-repository.test.ts src/backend/database/repositories/opkssh-token-repository.test.ts src/backend/database/repositories/vault-token-repository.test.ts src/backend/database/repositories/vault-profile-repository.test.ts src/backend/database/repositories/host-metrics-preference-repository.test.ts src/backend/database/repositories/host-health-repository.test.ts src/backend/database/repositories/host-metrics-history-repository.test.ts src/backend/database/repositories/alert-repository.test.ts src/backend/database/repositories/user-data-export-repository.test.ts src/backend/database/repositories/host-folder-repository.test.ts src/backend/database/repositories/host-resolution-repository.test.ts src/backend/database/repositories/snippet-repository.test.ts src/backend/database/repositories/role-repository.test.ts src/backend/database/repositories/rbac-access-repository.test.ts src/backend/database/repositories/host-credential-repositories.test.ts src/backend/database/repositories/field-encryption-boundary.test.ts src/backend/utils/field-crypto.test.ts src/backend/utils/audit-logger.test.ts src/backend/guacamole/token-service.test.ts src/backend/database/routes/user-oidc-utils.test.ts src/backend/database/routes/termix-id.test.ts src/backend/database/routes/user-totp-routes.test.ts src/backend/utils/permission-manager.test.ts src/backend/ssh/credential-username.test.ts src/backend/ssh/tmux-monitor-helpers.test.ts
git diff --check
4. Smoke Test Matrix
Run these against the gray target:
| Area | Required check |
|---|---|
| Startup | App starts from existing encrypted snapshot without schema errors |
| Login | Password login succeeds for an existing local user |
| Sessions | Refresh, logout, and session list/revoke still work |
| Users | /users/me, user list, admin create, make/remove admin still work |
| Registration | New local user registration works when registration is enabled |
| Password | Change password, logout, and login with the new password |
| OIDC | Existing OIDC login works; auto-provision check only if enabled |
| API keys | Admin create/list/delete API key; API key authentication updates usage |
| Settings | Read/write user settings and global auth settings |
| Preferences | Read/write user preferences and user cleanup still work |
| Open tabs | Tab restore, single upsert, bulk sync, update/delete, active session list, and user cleanup work |
| Alerts | Active alert filtering, dismiss/undismiss, dismissed list, export, and user cleanup work |
| Homepage | Homepage layout read/write still works |
| Topology | Network topology read/write and user cleanup still work |
| Dashboard | Dashboard service link list/create/update/delete still works |
| Command log | Terminal and host command history save/list/delete and cleanup still work |
| Activity | Recent activity cleanup for host, folder, password reset, and user deletion still works |
| Usage | SSH credential usage tracking and host/folder/user cleanup still work |
| SSO providers | Login provider list, admin provider list/create/update/delete, and OIDC/LDAP login config loading work |
| Audit logs | Audit write, audit list filters, action filter list, and user cleanup still work |
| Roles | Admin list/create/update/delete role and assign/remove a user role |
| RBAC access | Host/snippet share/revoke/list and shared host/snippet endpoints work |
| Security | Non-admin user is rejected from admin-only endpoints |
Do not continue gray rollout if any check fails.
Also verify these startup log cases before production gray:
| Environment value | Expected startup behavior |
|---|---|
DATABASE_LAYER_REPOSITORY_ROLLOUT=all |
startup logs mode: all and all supported domains |
DATABASE_LAYER_REPOSITORY_ROLLOUT=off |
migrated repository use fails closed |
DATABASE_LAYER_REPOSITORY_ROLLOUT=settings |
only settings repository boundary is allowed |
Then check /database/migration/status as an admin and confirm
repositoryRollout.mode, repositoryRollout.enabledDomains, and
repositoryRollout.explicit match the intended gray target.
repositoryRollout.warnings should be empty for the recommended full gray
slice.
5. Rollout Stages
Recommended stages:
- Local fixture run with copied production-like data.
- Internal staging with one admin and one normal user.
- Internal gray target with real integrations enabled.
- Small production gray group.
Do not run multiple backend instances from this branch. The current runtime still uses the encrypted SQLite snapshot model and is not safe for multi-writer deployment.
6. Rollback
Rollback should be operationally simple because this gray scope does not change the data format or require an external database.
Rollback steps:
- Stop the gray build.
- Restore the pre-gray encrypted database snapshot if any write-path smoke test failed.
- Deploy the previous known-good commit or image tag.
- Start the previous version.
- Verify startup, login, settings read, and one admin endpoint.
If the gray build only served read paths and no smoke test failed, restoring the snapshot may not be necessary. If there is any doubt, restore the snapshot.
7. Stop Conditions
Stop gray rollout immediately if any of these happen:
- Login failure spike.
- API key authentication failure for known-good keys.
- Admin authorization mismatch.
- OIDC callback failure for existing users.
- Missing or stale settings after write.
- Data snapshot save errors.
- Any database error mentioning missing tables, unknown columns, or failed serialization.
- Any user encryption or data unlock failure.
- Any unexpected
Repository domain ... is disablederror for a domain that was intended to be enabled.
8. Current Gray Readiness
Current branch can be considered gray-candidate only after all validation commands and smoke checks above pass on staging.
The branch should remain draft until gray evidence is attached to the PR.