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

4 KiB

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

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:

vi .env    # set WS_URL and WS_TOKEN

Then re-run:

./install.sh

That last run will start the container (docker compose up -d) and print the log-tail command.

Day-to-day operations

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:

# 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_64linux/amd64, aarch64linux/arm64.)
  • Agent connects, then disconnects immediatelyWS_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.