netanalyzer/docker/remote-agent/deploy/README.md
Joseph McQueen b3c37bd7df feat: st command suite, Webex phone + Atlas AV integrations, dockerized remote agent
Rebrand NetAnalyzer -> StoreHealthAnalyzer and consolidate the store
reporting surface into a single `st [number]` command with focused
sub-modes.

Commands
- st [number]                - general info (SIW + brands + Meraki net link)
- st [number] network        - switches, APs, store server
- st [number] pos            - registers, payment terminals, customer display
- st [number] ios            - MDM-tracked iOS hardware
- st [number] phone          - wired 78xx + DECT basestations/handsets with
                               registration state, extensions and main DID
- st [number] av             - Atlas AMPs + MDM-tracked Apple TVs, video
                               walls, music players, LED displays
- Removed `analyze` in favor of the unified `st` surface

Integrations
- integrations/webex: Service App OAuth with rotating refresh tokens,
  seed + cleanup scripts, tokens/ storage (git-ignored)
- integrations/atlas: Xyte client + cached device discovery keyed on
  zero-padded 6-digit store numbers, cold-cache failure -> unavailable
  banner instead of a misleading empty result
- services/webexPhone, services/webexService, services/avService: shape
  raw upstream data into the report layer's contract
- utils/merakiMatcher: FQDN hostname extraction so payment terminals
  match Meraki descriptions; case-insensitive lookup
- utils/chunkReport: split long markdown replies at 7000-char boundaries

Reliability / ops
- server.js: awaited framework.stop() + 8s hard-kill timer so nodemon /
  Docker restarts don't leak WDM device registrations ("excessive device
  registrations")
- nodemon.json: SIGINT so the graceful path always runs
- scripts/cleanupWebexDevices.js: one-shot WDM cleanup utility
- Group-space routing: hears() regexes tolerate the leading @BotName
  prefix Webex prepends to mentions
- Replaced HTML-unsafe <number> placeholders with [number] in all help
  strings

Remote agent containerization
- docker/remote-agent/: multi-stage node:22-alpine image, non-root user,
  tini for signal handling, minimal deps (ws/axios/dotenv)
- docker/remote-agent/package.sh: docker buildx build defaulting to
  linux/amd64 (with override), saves image + assembles deploy/ + writes
  SHA256 + zips for offline transfer
- docker/remote-agent/deploy/: runtime docker-compose.yml, install.sh
  with platform sanity check, remote-host README
- .dockerignore + .gitignore updates for build artifacts and dist bundles
- npm run agent:package convenience script

Cleanup
- Dropped storeHealth.js / HealthReport.js and their tests/mocks in favor
  of the shared storeDetail pipeline
- Store model handles null SIW records gracefully; toSummary always
  ends with a newline so the Meraki link sits on its own line

Tests
- 144 tests across 14 suites passing; new coverage for atlasClient,
  atlasDevices, avService, avCategory classification, webexPhone,
  webexServiceAppAuth, storeDetail integration, siw, chunkReport and
  the updated meraki matcher

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 09:54:41 -04:00

119 lines
4 KiB
Markdown

# StoreHealthAnalyzer Remote Agent — Deploy Bundle
This ZIP is a self-contained deployment bundle for the StoreHealthAnalyzer
remote agent. Extract it, run `install.sh`, fill in your `.env`, and the
agent will start as a Docker container.
## What's in the bundle
| File | Purpose |
| --- | --- |
| `sha-remote-agent-<version>.tar.gz` | The Docker image, saved via `docker save`. |
| `docker-compose.yml` | Runtime-only compose file (no build step; references the loaded image). |
| `install.sh` | Verifies checksum, loads the image, seeds `.env`, starts the container. |
| `.env.example` | Template — copied to `.env` on first run for you to fill in. |
| `SHA256SUMS` | Integrity check for the image tarball. |
| `VERSION` | Plain-text version marker used by `install.sh` and `docker-compose.yml`. |
| `README.md` | This file. |
## Prerequisites (on the remote host)
- Docker 20.10+ with the daemon running.
- Docker Compose — either the modern `docker compose` plugin (v2) or the
legacy `docker-compose` binary. `install.sh` auto-detects.
- Whichever user runs `install.sh` needs permission to talk to the Docker
daemon (member of the `docker` group, or run under `sudo`).
- Outbound network access from the host to:
- The main StoreHealthAnalyzer server (`WS_URL`).
- The internal APIs the agent proxies for (SIW, MDM, etc.).
## Install / start
```bash
unzip sha-remote-agent-<version>.zip
cd sha-remote-agent-<version>
./install.sh
```
On the first run `install.sh` will:
1. Verify the SHA-256 of the image tarball against `SHA256SUMS`.
2. Load the image into Docker (skipped on subsequent runs if the image is
already present).
3. Copy `.env.example``.env` and stop, asking you to fill it in.
Fill in `.env`:
```bash
vi .env # set WS_URL and WS_TOKEN
```
Then re-run:
```bash
./install.sh
```
That last run will start the container (`docker compose up -d`) and print
the log-tail command.
## Day-to-day operations
```bash
docker compose logs -f # tail the agent logs
docker compose ps # show container status
docker compose restart # cycle it
docker compose down # stop and remove the container
docker compose up -d # bring it back up
```
Healthy startup looks like:
```
🔄 Connecting to wss://.../ws...
✅ Remote Agent connected to StoreHealthAnalyzer
```
## Upgrading
When you receive a newer ZIP:
```bash
# Optional: back up your existing config
cp -a <old-version-folder>/.env ./sha-remote-agent-<new-version>-env.bak
# Stop the old container
cd <old-version-folder> && docker compose down && cd ..
# Extract and start the new one
unzip sha-remote-agent-<new-version>.zip
cp <old-version-folder>/.env sha-remote-agent-<new-version>/.env
cd sha-remote-agent-<new-version>
./install.sh
```
The old image stays in Docker's local cache until you `docker image prune`
it — handy if you need to roll back quickly.
## Troubleshooting
- **"Cannot talk to the Docker daemon"** — either Docker isn't running or
your user isn't in the `docker` group. Try `sudo ./install.sh` or add
yourself to the group: `sudo usermod -aG docker $USER` and log back in.
- **"Checksum verification FAILED"** — the ZIP was corrupted in transit.
Re-transfer.
- **"exec /sbin/tini: exec format error"** or **"Image architecture
does not match this host"** — the ZIP was built for the wrong CPU
architecture (typically an Apple Silicon Mac produced an `arm64` image
for an `x86_64` Linux host). `install.sh` catches this and prints the
exact rebuild command; ask your build operator to run:
```
./docker/remote-agent/package.sh --platform linux/amd64
```
(or `linux/arm64` if this host is ARM — run `uname -m` to check:
`x86_64``linux/amd64`, `aarch64``linux/arm64`.)
- **Agent connects, then disconnects immediately** — `WS_TOKEN` doesn't
match the server. Fix in `.env`, then `docker compose restart`.
- **Agent never connects** — check `WS_URL` (correct hostname, correct
scheme `ws://` vs `wss://`) and that there's no firewall between this
host and the server.