# AiMe Deployment and Automatic Update Plan

Status: Draft plan; offline MSIX feasibility proven, deployment not started  
Last updated: 2026-08-15  
Initial target: NAS `kksm2`, public dashboard `https://aime.kks.homes`

## Purpose

This document defines the first self-hosted deployment target for the AiMe web
control plane and the security contract for automatically updating installed
Windows clients. It authorizes planning only. Inspecting or changing `kksm2`,
Cloudflare, DNS, certificates, databases, backups, or production data requires a
separate deployment task with current-state inspection and explicit approval.

## Prerequisite Go/No-Go gate

Phase 1 in [the delivery roadmap](ROADMAP.md) recorded a scoped `GO` after a
real ChatGPT Chat conversation called AiMe on the Windows VM. The investment
hold is therefore removed, but no `kksm2`, Cloudflare/DNS, database, update
hosting, production signing automation, package installation, or Windows
auto-update deployment has started. Offline staging and unsigned MakeAppx
verification now exist without changing host trust or installed-package state.
The remaining mutations still require Phase 3 readiness, current-state
inspection, and separate explicit approval.

## Deployment decision

The initial managed control plane will be designed to run in containers on NAS
`kksm2` and be published through Cloudflare Tunnel. The main user-facing origin
is:

```text
https://aime.kks.homes
```

As observed on 2026-08-13, `aime.kks.homes` had no public DNS answer. The DNS
route must therefore be created during deployment after zone and tunnel
ownership are verified.

Cloudflare Tunnel is an outbound-only publication path, not an authentication
or application-authorization boundary. AiMe still requires its own login,
tenant isolation, RBAC, rate limiting, CSRF protection, device authentication,
and audit.

Official references:

- [Cloudflare Tunnel published-application configuration](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/configuration-file/)
- [Cloudflare Tunnel DNS route commands](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/tunnel-useful-commands/)
- [Cloudflare Tunnel connectivity model](https://developers.cloudflare.com/cloudflare-one/networks/connectivity-options/)
- [Microsoft MSIX auto-update and repair](https://learn.microsoft.com/en-us/windows/msix/app-installer/auto-update-and-repair--overview)
- [Microsoft Windows app distribution and update options](https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/publish-first-app)

## Recommended hostnames

| Hostname | Purpose | Additional boundary |
| --- | --- | --- |
| `aime.kks.homes` | User web app and public account/OAuth endpoints. | Application login, CSRF, RBAC, rate limits. |
| `admin.aime.kks.homes` | Platform-admin UI/API. | Application platform role plus Cloudflare Access as defense in depth. |
| `devices.aime.kks.homes` | Device polling, policy lease, presence, and revoke API. | Device-bound authentication; no browser session auth. |
| `updates.aime.kks.homes` | Signed release index, packages, release notes, and update health. | Public read or scoped rollout; immutable cache policy and signature verification. |

All hostnames may route through one Cloudflare Tunnel to one internal reverse
proxy while retaining separate application routes and policies. If only
`aime.kks.homes` is available for the first alpha, `/admin`, `/api/device`, and
`/updates` may be used temporarily, but the same authorization separation and
cache/header rules still apply.

Cloudflare Access is an extra gate for the platform-admin hostname; it must not
replace application-level platform-admin authentication or audit. Interactive
Access must not be placed in front of device or update endpoints that cannot
complete its browser login.

## Proposed NAS topology

```text
Cloudflare edge
      |
      | outbound Cloudflare Tunnel connections
      v
cloudflared container on kksm2
      |
      v
internal reverse proxy
  |-- web frontend
  |-- application/API service
  |-- device API service or isolated routes
  |-- background worker
  |-- signed update repository (read-only to serving processes)
  `-- PostgreSQL on an internal-only network
```

The exact services and technology stack remain architecture decisions. The
first sufficient implementation should avoid adding a cache, queue, object
store, or additional database until measured requirements justify it.

OAuth authorization-code state must use a transactional PostgreSQL store, not
the device-local authenticated JSONL authority journal. The production store
must atomically burn a known code before evaluating a redemption binding, keep
approval replay fences for the defined retention horizon, and prove one winner
across independent connections and process restart. An unwired adapter,
migration, deterministic transaction suite, and opt-in two-pool integration
test now cover the intended boundary; the real PostgreSQL test is skipped when
`AIME_TEST_POSTGRES_URL` is absent and deployment wiring remains blocked. The existing filesystem
journal remains a single-process local durability proof; its HMAC chain neither
provides confidentiality nor prevents rollback to an older valid prefix.

The managed consumer gateway runtime is now the lifecycle boundary that owns
the unbound OAuth/MCP/WSS composition and its authority owners. Deployment must
still provide the transactional PostgreSQL pool, durable signing keys, tenant
and route resolvers, public HTTPS/WSS termination, canonical external origins,
and explicit listener/readiness/signal policy. The runtime intentionally does
not call `listen()` or infer those deployment decisions.

## Required `kksm2` preflight

Before any deployment mutation, record:

- NAS make/model, operating system, CPU architecture, memory, and free space;
- supported container runtime/Compose version and current workloads;
- existing reverse proxy, Cloudflare Tunnel, DNS, certificates, and ports;
- storage volumes, filesystem, snapshots, backup destinations, and restore test;
- outbound connectivity required by Cloudflare and update publication;
- time synchronization, timezone, DNS resolver, and certificate trust;
- user/group ownership, ACL behavior, secret-storage options, and log location;
- resource limits and coexistence risk for existing NAS services; and
- current monitoring, notification, UPS/shutdown, and recovery capabilities.

The resulting deployment must not reuse or overwrite another service's tunnel,
database, volumes, proxy routes, certificates, ports, or secrets without an
explicit migration plan.

## Container and origin hardening

- Pin production images by immutable digest and record an SBOM.
- Run as non-root where possible, drop unused Linux capabilities, disallow
  privileged mode, and use read-only root filesystems with explicit writable
  volumes.
- Keep the database and internal services off published NAS ports; only
  `cloudflared` reaches the Cloudflare edge.
- Separate web/device/admin/update routes and service credentials by purpose.
- Do not store secrets in the repository, image layers, Compose file, command
  history, logs, or frontend bundles. Use protected secret files or the selected
  runtime's secret mechanism.
- Keep Cloudflare tunnel credentials independently revocable and least scoped.
- Apply strict security headers, origin checks, cookie attributes, request/body
  limits, timeouts, rate limits, and denial logging at the application boundary.
- Trust Cloudflare forwarding headers only from the controlled tunnel/proxy
  path; never treat a caller-supplied copy as authoritative.
- Make update packages and versioned assets immutable after publication.

## Data, backup, and recovery

- Encrypt backups and keep at least one tested copy outside `kksm2`.
- Back up database state, application configuration, release metadata, and the
  information needed to reconstruct DNS/tunnel routes; do not back up private
  device keys that never belong on the server.
- Use migration backups and backward-compatible schema changes whenever a
  running client may still use the previous API version.
- Define recovery-point and recovery-time targets before external users depend
  on the service.
- Test restore into an isolated environment and re-run tenant-isolation and
  revoke-state checks before declaring recovery successful.
- A restored database must not resurrect expired/revoked sessions, invitations,
  shares, device credentials, or releases.

## Availability and fail-closed behavior

- NAS/tunnel outage prevents new managed sessions, sharing changes, pairing,
  and lease renewal after the documented grace window.
- Local emergency stop, local revoke, uninstall, and safe diagnostics do not
  depend on the NAS.
- The UI distinguishes web health, control-plane lease, device presence, tunnel
  readiness, and actual callable state.
- A single-NAS deployment is an accepted alpha availability limitation, not a
  high-availability claim.
- If external use grows, measure NAS bandwidth, update download size, database
  load, tunnel availability, and backup/restore time before choosing replicas,
  load balancing, external object storage, or managed database services.

## Deployment workflow

1. Inspect and document `kksm2`, Cloudflare zone, and current services.
2. Create isolated directories/volumes, service users, networks, and protected
   secrets without changing existing workloads.
3. Build and scan versioned images in CI; do not build production releases from
   an unreviewed NAS working directory.
4. Back up and verify restore prerequisites.
5. Deploy database and services internally with health checks.
6. Run migrations as a bounded, logged one-shot operation.
7. Deploy `cloudflared`, create the exact DNS routes, and verify origin ports are
   not publicly reachable.
8. Validate login/RBAC/tenant isolation, pairing, revoke, security headers,
   rate limits, audit, and backup before inviting a second user.
9. Publish only signed client update artifacts.
10. Record versions, image digests, migrations, DNS/tunnel IDs, verification
    results, rollback point, and remaining risks.

Production rollback restores application images/configuration and a compatible
database state. Destructive schema rollback is never improvised after release.

## Windows update goals

- Security fixes reach installed computers without requiring terminal commands.
- Every installed binary and native helper has an authenticated publisher and
  version.
- A compromised NAS, Cloudflare account, DNS route, or update endpoint cannot
  produce an accepted unsigned update.
- Updates do not interrupt active tool operations or leave partial process
  trees, profiles, credentials, or incompatible local state.
- Users can choose Stable or opt-in Beta; organization policy may set a maximum
  deferral or minimum supported version.
- Failed updates recover to a known-good version or a safe repair state.

## Preferred packaging path

Evaluate signed MSIX/MSIXBundle with a downloaded `.appinstaller` file first.
Windows App Installer can perform scheduled/on-launch update checks and repair
for packages installed through that path. The package publisher identity and
version rules become part of Windows deployment enforcement.

This option is accepted only if it supports AiMe's desktop shell, native
helpers, process lifecycle, secure storage, and any future separately installed
privileged broker without weakening their boundaries.

Current offline evidence narrows that evaluation without accepting deployment:

- deterministic native-helper and unmanaged-launcher builds publish versioned,
  hash-bound outputs under serialized build locks;
- an exact staging allowlist includes only the local Modify runtime graph,
  pinned runtime packages, Node executable and license, required helpers,
  launcher, manifest assets, and generated notices/metadata;
- the manifest uses the unmanaged launcher as a packaged classic medium-
  integrity application with `runFullTrust`, package content enforcement, and a
  single visible app-list entry while actual shell activation remains unverified;
- the launcher constructs a two-variable child environment, derives Local App
  Data through the Known Folder API, retains stdin, enforces one session-local
  process tree, validates the Node leaf and signature, owns descendants with a
  kill-on-close Job Object, maps exact redacted lifecycle frames to a local
  status/tray surface, keeps terminal failure/setup status dismissible for a
  bounded ten seconds, and stops cooperatively before a bounded forced tree kill;
- the staged payload includes a separate zero-argument Personal Connect setup
  helper and the existing secret-store helper. The setup flow collects only a
  Tunnel ID and paths to an existing profile, DPAPI blob, and tunnel client;
  native fixed-state preparation creates the private Local App Data chain and a
  successful no-replace finalization permits one bounded tunnel retry; and
- a real Windows SDK test imports the staged dependency graph, creates an
  unsigned SHA-256 MSIX, inspects its block map/archive, and unpacks it without
  installing, signing, trusting, or registering the package.

This evidence does not prove that the app-list entry appears or activates through
the real installed shell, production publisher signing, App Installer update
semantics, upgrade/uninstall recovery, or accepted tunnel-client redistribution.
It also does not prove creation of the prerequisite OpenAI tunnel, protected
runtime-key blob, profile, or private ChatGPT app, and the setup slice cannot
replace a different existing `tunnel.json`.
The launcher relies on installed-MSIX integrity for ancestor namespace
protection. The Node stager is a release-build tool for an exclusive trusted
workspace, not a hostile same-user runtime boundary.

A separate temp-only feasibility probe on the current development host also
confirmed that the SDK SignTool can add a CMS package signature matching the
manifest publisher, that the signature can be inspected independently, and that
tampering breaks package integrity. It did not install or trust the throwaway
certificate. This is not part of the default suite: SignTool PFX use may create a
current-user CNG key container outside the temporary directory, so repeatable
developer-signing automation must run only by explicit opt-in in a disposable
Windows profile/VM with exact key-identity cleanup. That probe does not close the
production signing, timestamping, protected-key, or publisher-trust gates.

If MSIX is insufficient, use a separately signed, minimal updater/bootstrapper.
It must implement the same manifest, signature, staging, shutdown, health, and
rollback contract below. Pipe-to-shell installation and an unsigned self-update
mechanism are prohibited.

## Release and signing trust

- Sign Windows packages/executables with an appropriate trusted code-signing
  identity.
- Keep the release-signing private key outside `kksm2`, the running control
  plane, and ordinary developer workstations. Use an approved protected CI or
  offline signing workflow with auditable authorization.
- Embed the allowed publisher identity and update-metadata public key/root in
  the installed client.
- Sign update metadata independently of HTTPS hosting. A hash stored on the same
  mutable origin without an independent signature is insufficient.
- Rotate signing keys through a threshold/transition process accepted by an
  already trusted version; emergency revocation has a documented recovery path.
- Generate and retain SBOM, hashes, signatures, provenance, source revision,
  build environment, tests, and security-scan results for every release.

## Update feed contract

The conceptual signed release record contains at least:

- schema version and signed-metadata expiry;
- channel and monotonically increasing application version;
- minimum supported/blocked versions and protocol compatibility;
- publication time and release identifier;
- deterministic staged-rollout rule;
- per-architecture package URL, size, SHA-256, publisher/signature expectation,
  and package format;
- critical/mandatory flag and maximum deferral when policy permits it;
- release notes and known rollback limitations; and
- signature key ID and signature over canonical metadata.

Clients reject unknown critical fields, expired/replayed metadata, downgrade,
unexpected publisher, invalid signature/hash, wrong architecture, incompatible
protocol/database state, mutable-version mismatch, and oversized responses.

## Client update lifecycle

1. Check a bounded signed release record over HTTPS without sending local
   secrets or inventory beyond the required alias/version/channel.
2. Apply deterministic rollout and organization policy locally.
3. Download to a private staging directory with size/time limits.
4. Verify metadata signature, package hash, publisher signature, architecture,
   version monotonicity, and compatibility before shutdown.
5. Wait for active tasks to finish or ask the user; critical policy may block
   new tasks but must not corrupt an active operation.
6. Stop the tunnel and the full supervised process tree.
7. Install atomically through Windows/package-manager semantics or the signed
   updater.
8. Start the new version and run local startup, profile, native-helper, audit,
   and control-plane compatibility health checks.
9. Mark healthy only after a bounded stabilization period and control-plane
   acknowledgement.
10. On failure, restore the supported known-good version or enter an explicit
    safe repair state with remote execution disabled.

Profiles, user data, and credentials use versioned migrations with backups and
must never be deleted merely because an update failed.

## Rollout and version policy

- `Beta` is explicit opt-in per user/organization and receives releases first.
- `Stable` begins with internal/canary devices, then expands deterministically
  by stable device ID after health thresholds pass.
- Rollout pause and release revoke are immediate control-plane actions, but an
  already downloaded client still verifies the signed metadata and package.
- Minimum-version enforcement is used only for demonstrated security/protocol
  incompatibility and includes a recovery/update path.
- The control plane and client negotiate supported protocol ranges so a web
  deployment does not silently strand older clients.

## Update privacy and administration

The update service stores only the device/account aliases and metadata needed
for version compliance and rollout. It does not receive local roots, file data,
prompts, command output, or screen/clipboard content. Platform Operations may
publish/pause/revoke a release but cannot sign one unless the separate signing
authorization succeeds. Release actions are immutable audited events.

## Deployment acceptance gate

The `kksm2` alpha is accepted only when:

1. origin services are unreachable from the public Internet except through the
   intended Cloudflare hostnames;
2. login, admin, device, and update endpoints have separate authentication and
   policy boundaries;
3. NAS compromise without the signing key cannot create an accepted client
   update;
4. database restore, tunnel/DNS recreation, credential rotation, and application
   rollback are successfully rehearsed;
5. secrets are absent from repository, images, logs, frontend, command lines,
   and support artifacts;
6. container breakout/resource/health failures do not affect unrelated NAS
   services in the tested threat model;
7. update success, interruption, corrupt download, wrong signer, downgrade,
   replay, staging failure, health failure, and rollback tests pass on Windows;
8. client and control-plane version skew follows the documented compatibility
   contract; and
9. no Critical or High finding remains for the deployed alpha capabilities.

## Open deployment decisions

- Actual `kksm2` runtime, reverse proxy, database, backup, and secret mechanism
  after preflight inspection.
- Whether release binaries remain on NAS or move to external immutable object
  storage/CDN when size, bandwidth, or availability requires it.
- MSIX/App Installer compatibility versus a signed updater/bootstrapper.
- Code-signing provider and protected signing workflow.
- Monitoring/alert delivery and operational on-call expectations.
- Recovery-point, recovery-time, retention, and maximum managed-session lease
  values.
