Node/Express service that:
- Receives Appspace outbound webhooks, enriches with Workspace ONE MDM
data (matched by serial), and posts Adaptive Card alerts to Webex.
- Runs a Webex bot in WebSocket mode with two commands:
* `offline [filter]` - lists currently offline / lost / failed
Appspace devices, enriched with per-device MDM facts + console links.
* `restart-offline [filter]` - sends WS1 SoftReset (reboot) to every
currently-offline device that has a WS1 record. Capped at 50 per
invocation with bounded concurrency to protect the WS1 API.
Notes on hardening already applied:
- In-flight promise coalescing in mdm.js and index.js so burst webhook
traffic can't stampede the WS1 token / device-cache refresh or the
Appspace token refresh.
- Structured logger that serializes Error instances (message, stack,
code, axios response.status/data) instead of stringifying to "{}".
- Webex 7439-char message-limit handling: `offline` builds its body
incrementally against a character budget and reports accurate
"N more not shown" truncation.
- Uses string phrases for `framework.hears(...)` so the framework's
`(^| )phrase($| )` wrapper handles group-space @mentions correctly,
and a shared `extractFilterArg()` helper so filter parsing works
identically in DMs and mentioned messages.
Config, Docker, smoke-test profile, and healthcheck included.
Secrets are managed via `.env` (gitignored); see `.env.example`.
Co-authored-by: Cursor <cursoragent@cursor.com>
40 lines
2.1 KiB
Text
40 lines
2.1 KiB
Text
# ============================================
|
|
# Appspace + Webex Alerts Service
|
|
# Copy this file to .env (prod) or .env.dev and fill in real values.
|
|
# Never commit real secrets.
|
|
# ============================================
|
|
|
|
# ---- Server ----
|
|
PORT=3000
|
|
NODE_ENV=production # or development
|
|
PUBLIC_HOST=https://your-public-host.example.com # used in logs only
|
|
|
|
# ---- Webex Bot (required) ----
|
|
WEBEX_BOT_TOKEN=your-webex-bot-access-token
|
|
WEBEX_ROOM_ID=your-webex-room-id
|
|
|
|
# ---- Appspace Webhook (from Appspace Outbound Webhooks) ----
|
|
WEBHOOK_SECRET=your-shared-secret-for-appspace-webhooks # optional but recommended; checked via x-webhook-secret or x-secret header
|
|
|
|
# ---- Appspace API (refresh token flow) ----
|
|
APPSPACE_INSTANCE_URL=https://your-instance.cloud.appspace.com
|
|
APPSPACE_SUBJECT_ID=your-application-subject-id
|
|
APPSPACE_REFRESH_TOKEN=your-long-lived-refresh-token
|
|
APPSPACE_API_BASE_URL=https://api.cloud.appspace.com # or your regional API base
|
|
APPSPACE_CONSOLE_BASE_URL=https://app3.cloud.appspace.com
|
|
|
|
# (Legacy / query-offline.js still references this static token style)
|
|
APPSPACE_API_TOKEN=your-static-token-if-needed
|
|
APPSPACE_BASE_URL=https://api.cloud.appspace.com
|
|
|
|
# ---- Workspace ONE MDM (for enrichment) ----
|
|
WS1_BASE_URL=https://as1991.awmdm.com # your WS1 server URL (used for API calls in mdm.js)
|
|
WS1_CONSOLE_BASE_URL=https://cn1896.awmdm.com # console base for per-device links (MUST be the console hostname like cn1896, NOT the API hostname like as1896 — links will be broken otherwise)
|
|
WS1_CLIENT_ID=your-oauth-client-id
|
|
WS1_CLIENT_SECRET=your-oauth-client-secret
|
|
WS1_TENANT_CODE=your-tenant-code
|
|
|
|
# ---- Debugging (optional) ----
|
|
DEBUG=false # enables verbose per-request / per-lookup logs (mdm lookups, ignores, command receipts, etc.)
|
|
DEBUG_WEBHOOK=false # set to "true" to log *full* Appspace webhook JSON payloads (avoid in prod - may contain sensitive data)
|
|
LOG_FORMAT=json # set to "json" (or NODE_ENV=production) for structured JSON logs suitable for Docker log aggregation (Loki, CloudWatch, etc.)
|