Files
Termix/readme/DATABASE-LAYER-GRAY-ROLLOUT.md
T
ZacharyZcR 1e7c9ea53c draft: database layer refactor (#1054)
* 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>
2026-07-15 23:28:10 -05:00

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-runtime for 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 CredentialRepository and HostResolutionRepository.
  • Database export host and credential read/decryption paths migrated behind HostRepository and CredentialRepository.
  • Database import host and credential duplicate checks plus encrypted creates migrated behind HostRepository and CredentialRepository.
  • 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 CredentialRepository and SharedCredentialRepository.
  • Legacy user field-encryption migration SQL centralized behind RawSqliteUserEncryptionMigrationStore.
  • Auth login lazy user-field encryption migration now calls the DataCrypto current-runtime migration boundary instead of opening SQLite in auth-manager.ts.
  • Current user-field encryption migration now resolves SQLite through createCurrentUserEncryptionMigrationStore and the shared current runtime helper, keeping DataCrypto on the migration-store interface.
  • User, admin, TOTP, OIDC account, and credential migration explicit saves now use DatabaseSaveTrigger instead 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 through DatabaseSaveTrigger.
  • Database import SQLite foreign-key toggling is isolated behind the withSqliteForeignKeysDisabled runtime boundary and restores constraints in a finally path; 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 HostRepository and UserRepository.
  • Host route own/shared list assembly reads migrated behind HostResolutionRepository while 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 DataCrypto directly instead of SimpleDBOps.
  • Legacy SimpleDBOps compatibility 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:

  1. Confirm the target is running from a full backup of the data directory.
  2. Confirm the app can write to the data directory so the automatic pre-upgrade backup can be created before first database startup.
  3. Record the exact source commit and container/image tag currently serving traffic.
  4. Confirm the gray build commit is known.
  5. Run the validation commands from this branch.
  6. Use a target with a small, known user set first.
  7. 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:

  • 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

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:

  1. Local fixture run with copied production-like data.
  2. Internal staging with one admin and one normal user.
  3. Internal gray target with real integrations enabled.
  4. 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:

  1. Stop the gray build.
  2. Restore the pre-gray encrypted database snapshot if any write-path smoke test failed.
  3. Deploy the previous known-good commit or image tag.
  4. Start the previous version.
  5. 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 disabled error 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.