aeStatusPage/README.md
jmcqueen 007086caf6 Initial commit: status-page bridge with Webex bot management
Bridges third-party status pages into Webex spaces via RSS polling and
inbound webhooks (Statuspage / Status.io / Uptime Kuma / generic).

Includes an interactive Webex bot (websocket transport) that lets space
members register sources with an Adaptive Card instead of hand-editing
config/feeds.json: help, add, list, webhook <key>, remove <key>.

Ships with an atomic JSON store (per-file mutex, tmp+rename), parallel
RSS polling, and unit tests via node:test. All secrets are sourced from
environment variables (see .env.example); no credentials in the repo.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 16:08:34 -04:00

110 lines
4 KiB
Markdown

# aeStatusPage
Small Node.js service that bridges third-party status pages into Webex spaces.
It can consume:
- RSS / Atom feeds (polled every 5 minutes)
- Inbound webhooks in Atlassian Statuspage, Status.io, or Uptime Kuma format
- Anything else you point at it (raw dump)
It also runs a Webex bot so you can register new sources from inside a space
with a card-based UI instead of hand-editing `config/feeds.json`.
## Configure
Copy `.env.example` to `.env` and set the values, at minimum:
| Variable | Purpose |
| --- | --- |
| `WEBEX_BOT_TOKEN` | Bearer token for the Webex bot user (required) |
| `PUBLIC_BASE_URL` | Public https URL where this service is reachable; used to show users the correct webhook URL |
| `SERVER_PORT` | Override the port from `config/config.json` (default 1449) |
| `SERVER_NAME` | Cosmetic name used in log lines |
| `BOT_ENABLED` | Set to `false` to disable the interactive chat bot |
`config/config.json` should now only contain non-secret configuration.
## Run
**Node version.** The Docker image runs on Node 20 (`node:20`). For local
development, use Node 20.x — Node 21+ breaks `webex-node-bot-framework`'s
transitive `webex` dep, which tries to write to the now read-only global
`navigator`. The app will still start on newer Node hosts, but the interactive
chat bot will be disabled with a warning logged. Set `BOT_ENABLED=false` to
suppress the warning if you don't want the bot in dev.
```bash
npm install
npm start
```
or Docker:
```bash
docker build -t aestatuspage .
docker run --env-file .env -p 1449:1449 \
-v $(pwd)/config:/usr/src/app/config \
-v $(pwd)/logs:/usr/src/app/logs \
aestatuspage
```
## Register a source from Webex
1. Invite the bot user to the space.
2. Type `help` — you'll see the available commands.
3. Type `add` — the bot posts an Adaptive Card. Fill in:
- a short key (used as the webhook URL slug)
- a friendly name
- source type: `RSS`, `Webhook`, or `Both`
- the RSS URL and/or the webhook payload format
4. On submit the bot saves the entry to `config/feeds.json` atomically and
posts back the exact webhook URL you should configure in your upstream
status provider (Statuspage, Status.io, Uptime Kuma, ...).
Other commands:
- `list` — show sources currently posting to this space
- `webhook <key>` — echo back the inbound webhook URL for a provider
- `remove <key>` — stop posting a provider to this space
The bot uses Webex's websocket transport, so it does not require an inbound
webhook URL to work as a chat bot. `PUBLIC_BASE_URL` is only used to show
users the correct URL for **status page** webhooks.
## HTTP endpoints
| Method + path | Purpose |
| --- | --- |
| `GET /healthCheck` | Liveness probe |
| `GET /feeds` | Dumps the current `feeds.json` |
| `GET /webhookEvents` | Dumps recent webhook events (in-memory) |
| `GET /refreshFeeds` | Re-reads `feeds.json` from disk without restarting |
| `GET /checkRSSFeed?site=<url>` | Debug: fetch + parse a feed and return it |
| `GET /cleanOldFiles` | Manually trigger old-log cleanup |
| `GET /:provider/go` | Redirect to the provider's `siteUrl` |
| `POST /:provider` | Inbound status webhook (Statuspage / Status.io / Uptime Kuma / generic) |
| `POST /rssTest?provider=<key>` | Debug: send a fake RSS item as if it had come through the feed |
## Tests
```bash
npm test
```
Runs `node --test` against `test/**/*.test.js`. No test framework
dependencies — everything is Node built-ins.
## Layout
```
index.js HTTP server, cron loop, webhook processors
src/atomicJson.js Atomic JSON read/write with per-file mutex
src/providerStore.js Typed wrapper around feeds.json (add/remove/list)
src/cards.js Adaptive Card templates used by the bot
src/webexBot.js webex-node-bot-framework wiring (websocket mode)
config/config.json Non-secret configuration
config/feeds.json Registered providers (mutated at runtime)
config/rssFeedCache.json Dedup cache for RSS items already posted
logs/ Rolling per-day log files
test/ Unit tests
```