> For the complete documentation index, see [llms.txt](https://docs.we360.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.we360.ai/deployment-and-it-ops/deployment/agent-deployment-hub/installation-and-update-architecture.md).

# Installation & Update Architecture

This page explains **how the desktop agent installs and updates itself** on Windows and macOS — what runs, in what order, where files land, and how updates are triggered and applied. It is a reference for IT/security teams who need to understand the moving parts behind the step-by-step deployment guides.

There are two flavours of the agent:

* **Standard** (`MyZenV2`) — visible, interactive app.
* **Stealth** (`zs`) — headless. A background **service monitor** (`svcmonitor`) supervises the tracker, applies admin commands, and performs updates.

Both flavours share the same Go tooling and the same per-tenant key configuration (`zs.json`, the tenant id + key the installer is bound to).

***

## Windows — installation

### Primary path: self-contained installer (`zs-setup.exe`)

The recommended installer is a single self-contained executable with the entire application payload embedded inside it, so it installs **fully offline** with no download step.

1. **Resolve the tenant key config.** The installer determines which tenant it belongs to from (in order) an `installer-sources.json` beside it, an installer text marker, the executable's own (encoded) filename, or an existing `C:\Windows\System32\zs.json`.
2. **Elevate to administrator** (UAC prompt if not already elevated).
3. **Write the key config** to the canonical path `C:\Windows\System32\zs.json` so the agent and service always read the current tenant binding (this happens on update/repair too, replacing a stale config).
4. **Extract & validate the payload**, with a short settle delay so antivirus can inspect files before they're used.
5. **Place files atomically with rollback** (stage `.new`, move current to `.old`, rename into place; restore on failure) — resilient to AV locks/quarantine.
6. **Register and start the Windows service** (`svcmonitor`) with crash-recovery, write install registry keys, and add outbound firewall rules.

### Legacy path: MSI (Advanced Installer)

An MSI (`zs.msi` / `MyZenV2.msi`) is still produced for enterprise deployment via Group Policy / SCCM / Intune. It lays down the same file layout and service. New deployments should prefer the self-contained `zs-setup.exe` for offline/air-gapped scenarios. (The `configure_user.exe` helper is **no longer shipped** in either path — onboarding now runs in-process in the app.)

### Windows services

| Service                                      | Role                                                                                                                                                |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **svcmonitor** (`C:\Windows\svcmonitor.exe`) | Supervises the tracker, polls the server for admin commands, performs updates, ships logs on request. Auto-start, with `sc failure` crash recovery. |
| **svcrunner** (`C:\Windows\svcrunner.exe`)   | Companion that keeps svcmonitor alive across sessions/crashes.                                                                                      |

***

## macOS — installation

The agent ships as a signed, **notarized** `.pkg`, built per architecture (`amd64` and `arm64` — no universal binary, intentionally). Gatekeeper acceptance, stapling, and signature integrity are verified at build time.

The package installs the app bundle and runs a **postinstall** script that:

1. Stops any existing app/processes.
2. Resolves and writes the tenant key config to `/Library/Preferences/zs.json` (stealth uses a `keyconfig_check` helper that reads the tenant from the package's own name).
3. Renders **launchd** job definitions from templates and bootstraps them for the system and logged-in GUI users.

### launchd jobs

| Job                        | Flavour  | Type                   | Purpose                                          |
| -------------------------- | -------- | ---------------------- | ------------------------------------------------ |
| `ai.we360.MyZenV2`         | Standard | LaunchAgent (per user) | Starts the interactive app at login              |
| `ai.we360.MyZenV2-updater` | Standard | LaunchDaemon (system)  | Hourly update check                              |
| `ai.zs.zs`                 | Stealth  | LaunchAgent/Daemon     | Starts/keeps `svcmonitor` running                |
| `ai.zs.zs-updater`         | Stealth  | LaunchDaemon (system)  | Runs `svcmonitor updater` to check/apply updates |

***

## File locations

|                              | Windows                                                           | macOS                                                                  |
| ---------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------- |
| **Stealth app**              | `C:\Program Files\zs\zs\`                                         | `/usr/local/zs/zs.app`                                                 |
| **Standard app**             | `C:\Program Files\…` (MSI)                                        | `/Applications/MyZenV2.app`                                            |
| **Service binaries**         | `C:\Windows\svcmonitor.exe`, `svcrunner.exe`                      | inside the app bundle (`…/Contents/MacOS/svcmonitor`), run via launchd |
| **Tenant key config**        | `C:\Windows\System32\zs.json` (fallback `…\zs\zs\keyconfig.json`) | `/Library/Preferences/zs.json` (fallback `/etc/zs.json`)               |
| **Version file**             | `…\zs\zs\version.txt`                                             | `…/Contents/MacOS/version.txt`                                         |
| **Per-user config (tokens)** | `%APPDATA%\ai.zs\zs.ini`                                          | `~/.config/ai.zs/zs.ini`                                               |
| **App data / logs**          | `%APPDATA%\ai.zs\zs\`                                             | `~/Library/Application Support/ai.zs/zs`                               |

> A custom key-config path can be supplied via the `ZS_KEY_CONFIG` environment variable (used by always-on mode); it overrides the platform default path.

***

## Updates

Updates are **server-led and per-tenant**, with a build-time fallback URL. The agent never auto-downgrades by accident.

### How an update is decided

1. **Resolve the installer URL** for this tenant: `GET https://origin.in.we360.ai/discover/v1/tenant/<id>/download-urls/` (cached in-process). If unavailable, fall back to the per-brand build-time base URL.
2. **Check the auto-update gate** (`auto_update` per tenant). If disabled, the updater no-ops.
3. **Compare versions** with a strict semver gate — an update installs only when the published version is **higher** than the installed one. (Intentional rollbacks require publishing a new build with the older bits.)
4. **Verify integrity** — the download's MD5 is checked against the published `.version` sidecar; a mismatch aborts the install.

### How an update is applied

* **Windows:** `svcmonitor` re-runs the self-contained `zs-setup.exe` (downloaded for this tenant), which stops the service, performs the same atomic file swap as a fresh install, and recreates/starts the service. MSI assets are applied via `msiexec /i … /qn /norestart`.
* **macOS:** the `*-updater` launchd job runs the updater, which downloads the per-arch `.pkg` and installs it system-wide via `/usr/sbin/installer -pkg … -target /`. The stealth updater encodes the tenant key config into the package path so postinstall can re-bind the tenant.

### Cadence & triggers

* **Standard (macOS):** hourly via the updater LaunchDaemon.
* **Stealth (both OS):** `svcmonitor` checks on a timer (only while a user session is active) and also honours an on-demand **`UPDATE`** admin command delivered through the service-state channel.
* **Skip markers:** developer/opt-out markers on disk cause the updater to no-op (used for dev machines and temporary holds).

***

## Related

* Step-by-step install guides: **Manual Installation** (Windows/macOS, standard/stealth).
* Mass deployment: **Mass Deployment** (GPO, Intune, MDM, command-line MSI).
* Network behaviour & endpoints: **Network & Security Hardening → Stealth App — Server Communication (v4.13+)**.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.we360.ai/deployment-and-it-ops/deployment/agent-deployment-hub/installation-and-update-architecture.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
