# Deployment V1 Target control plane: Portainer at `https://docker.cin.su`. Recommended V1 deployment topology: - `assistant-core-runtime` - `assistant-continuity-runtime` - `assistant-commit-runtime` (isolated privileged runtime) - `assistant-cognitive-worker` (replaceable, no canonical ownership) - PostgreSQL 18.6 - NATS as replaceable integration transport Temporal is intentionally **not** the canonical owner of future obligations. If/when Temporal is added, loss of Temporal must be recoverable from canonical continuity state. The initial stack definition is `deploy/docker-compose.prod.yml`. Portainer may deploy it from Git after the repository has been pushed. Project-built production images receive `org.opencontainers.image.revision` and `org.opencontainers.image.source` OCI labels. Promotion must set `ASSISTANT_SOURCE_REVISION` to the full merged `origin/main` SHA before `docker compose build/up`; the default `unknown` is intentionally rejected by artifact confirmation. After all project containers are running, execute: ```powershell $revision = git rev-parse origin/main powershell -ExecutionPolicy Bypass -File .\deploy\windows\Confirm-DomovoyProductionArtifact.ps1 -Revision $revision -DockerContext docker-prod ``` The confirmation script accepts the promotion only when every project-built container has that revision label, then atomically records its exact Docker image ID in `%LOCALAPPDATA%\Domovoy\monitoring\deployment-manifest.json` and the private NAS monitoring directory. Production health compares every running label and image ID to this manifest and becomes degraded on drift. The manifest is non-secret operational evidence; it is not canonical Assistant state. The first external operation adds `assistant-notification-receiver-1` on production host port `18081`. Caddy applies `deploy/caddy/assistent.caddy`, routing only `https://assistent.cin.su/delivery/*` to that port and all other paths to Creator Web on `18080`. The receiver has an isolated durable volume and no Assistant database access. Commit success means an immutable receiver receipt exists; Windows display and human reading are not Commit outcomes. Migrations `010_capability_notification_binding.sql` and `011_commit_notification_envelope.sql` must be applied before the new runtimes start. The initial Capability binding is owner-local for `domovoy-creator-principal`, revision 1, capability `prospective-notification-delivery`, origin `https://assistent.cin.su`, delivery path `/delivery/v1/deliveries`, receipt path `/delivery/v1/receipts`, protocol `IDEMPOTENT_RECEIPT_V1`, and secret reference `domovoy-notification-write-v1`. `deploy/windows/Invoke-DomovoyNotificationReceiver.ps1` polls the receipt list with the read-only credential, displays up to three unseen local notifications, and records only rebuildable receipt IDs under `%LOCALAPPDATA%\Domovoy`. `Register-DomovoyNotificationTask.ps1` registers the current-user task every two minutes and at logon. It requires an interactive session for display and never uses `docker-test`. Credentials/API deployment automation is deliberately not embedded. Use `PORTAINER_API_KEY` from an external secret source or deploy through Portainer UI/API after authenticating. The single Creator login is configured with external `CREATOR_USERNAME` and `CREATOR_PASSWORD` values. They issue the same bounded Creator session and never select Actor, Principal, Scope or Authority. Keep `CREATOR_BOOTSTRAP_TOKEN` as a separate recovery/automation credential; none of these values belongs in Git, compose defaults for production, image layers or logs. In production, `CREATOR_PASSWORD`, `CREATOR_BOOTSTRAP_TOKEN`, and `CREATOR_SESSION_SIGNING_KEY` are materialized as files in the external `assistant_core_secrets` Docker volume. `core-runtime` receives only the corresponding `_FILE` paths and mounts that volume read-only. Direct environment values remain a development compatibility path and fail closed if combined with `_FILE`. ## PostgreSQL recovery Production backups run only on `docker.cin.su`; this project must not use the shared `docker-test` host. `deploy/backup-postgres.sh` creates an atomic, mode-0600 logical backup under `/home/m/assistant-backups/postgres`. Each completed directory contains the application database, cluster roles without role passwords, database/owner metadata, and `SHA256SUMS`. Partial output is never promoted to a completed backup directory, and no automatic retention deletion is performed. `deploy/verify-postgres-restore.sh ` verifies all hashes and restores into an isolated PostgreSQL 18.6 container backed by tmpfs. It never mounts or writes `assistant_assistant_pg`, and removes its temporary container on exit. A backup is operationally accepted only after this restore check passes. The production user crontab installs the single entry from `deploy/cron/assistant-postgres-backup.crontab`. It runs the backup and restore check daily at 00:15 UTC (03:15 Europe/Moscow), survives host reboot without a persistent login session, and writes a private operational log beside the backups. ## Encrypted off-host backup `deploy/windows/Sync-PostgresBackupToNas.ps1` copies only a completed, hash-verified production backup over SSH, archives it locally, encrypts it with GnuPG AES-256, verifies an immediate decrypt round trip, and atomically publishes ciphertext plus a non-secret manifest under `\\nas\MST\codex\_backups\domovoy\postgres`. Temporary plaintext is removed on exit. The script is idempotent and never deletes existing backups. `deploy/windows/Test-PostgresBackupFromNas.ps1 -VerifyRemoteRestore` verifies the NAS ciphertext hash, decrypts it with the DPAPI-protected recovery key, checks every source hash, and performs a full isolated PostgreSQL restore on `docker.cin.su`. `deploy/windows/Register-PostgresBackupNasTask.ps1` generates the key when absent, atomically backs up only its DPAPI ciphertext to the NAS, and registers current-user daily and logon triggers. The task intentionally does not use `docker-test`. ## Production health monitoring `deploy/windows/Test-DomovoyProductionHealth.ps1` is an external, rebuildable operational projection; it is not a canonical Core `Monitor`. It checks all expected production containers, HTTPS health, TLS expiry, public DNS agreement, production backup age and hashes, NAS backup age and ciphertext hash, cron, and the off-host backup task. Thresholds are 30 hours for the production backup, 36 hours for the NAS copy, and 21 remaining certificate days. The script atomically writes the latest JSON snapshot to `%LOCALAPPDATA%\Domovoy\monitoring\status.json` and `\\nas\MST\codex\_monitoring\domovoy\status.json`, then exits nonzero when any check is degraded. `deploy/windows/Register-DomovoyProductionHealthTask.ps1` registers a current-user execution every 15 minutes and at logon. Monitoring never uses `docker-test` and never mutates product state. `deploy/windows/Invoke-DomovoyProductionMonitoring.ps1` runs health collection in a child process and then evaluates `deploy/windows/Send-DomovoyHealthNotification.ps1`, including when health is degraded. The notifier shows a local Windows notification on the first degraded observation, recovery, and no more than one continuing-failure reminder per six hours. Its suppression state is an external, non-canonical JSON file at `%LOCALAPPDATA%\Domovoy\monitoring\notification-state.json` and may be regenerated. Notifications require the registered user to have an interactive Windows session; no external notification service or credential is used.