Reliability / correctness:
- Always arm the graceful-shutdown safety timeout. Previously
`shutdown(force=true)` (called from uncaughtException) skipped the
timeout entirely, so a hung `framework.stop()` after a crash would
wedge the process until Docker's SIGKILL. Now uses 3s when forced,
8s otherwise, and .unref()s so it never blocks a clean exit.
- Attach a `.catch()` to `framework.start()` so a bad Webex token or
WebSocket handshake failure produces a clear "Webex framework failed
to start" error line instead of a bare Unhandled Rejection while the
bot silently stays dead.
- Rename MDM timestamp labels from "(EDT)" to "(ET)" since the
formatter uses DST-aware America/New_York (half the year it's EST).
Cleanup:
- Drop `body-parser` in favor of the built-in `express.json()`
(Express 4.16+). Removes one direct dep; still present as a
transitive dep of express itself.
- Remove orphaned JSDoc block referring to a helper that no longer
exists.
- Delete legacy `query-offline.js` (marked deprecated since the bot
`offline` command shipped) and remove its `APPSPACE_API_TOKEN` /
`APPSPACE_BASE_URL` env vars from `.env.example` and the
`offline:legacy` npm script from `package.json`.
Config / metadata:
- Add `"engines": { "node": ">=20" }` to package.json so npm warns on
the wrong Node version instead of just the README saying so.
- Document `SMOKE_TEST=true` in `.env.example`.
Docs:
- Rewrite README to document the `restart-offline` command (iOS
Supervised requirement, 50-device cap, concurrency, audit log
fields, fresh-at-execute semantics), the ET-not-EDT labeling,
structured error logging, character-budget rendering, and the
new CI workflow. Refresh the TODO section to reflect what has
actually shipped.
CI:
- Add `.gitea/workflows/ci.yml` with two jobs: syntax check
(`node --check` on index.js and mdm.js) and a Docker smoke test
that builds the production image, boots it with dummy credentials
+ SMOKE_TEST=true, and waits up to 30s for the container's
built-in healthcheck to reach `healthy`. Dumps container logs
on failure.
Co-authored-by: Cursor <cursoragent@cursor.com>
40 lines
2.2 KiB
Text
40 lines
2.2 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
|
|
|
|
# ---- 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.)
|
|
|
|
# ---- CI / test-only ----
|
|
# SMOKE_TEST=true # when set, skips Webex bot framework startup so the container can boot to a healthy /health
|
|
# with dummy credentials. Used by `npm run docker:smoke` and the CI workflow. Do NOT set in prod.
|