The bot runs in the public cloud and can't reach the 10.x/8 network
where DBS-210 bases live. This phase adds a data-center-resident relay
agent that dials outbound over WSS to the bot, and lets /phonestatus
post a follow-up message with per-base health after its main output
has already shipped.
Bot side (services/):
- dectRelayHub.js: WebSocket upgrade handler on /dect-relay/ws with
bearer-token auth (constant-time compare, header + Sec-WebSocket-
Protocol fallback for header-stripping proxies). Promise-based RPC
API with per-call timeouts, mid-flight-disconnect rejection, and
clean replacement of a stale agent socket when a newer one connects.
- dectDiscovery.js: pure filter that turns a phoneService result into
a list of reachable bases. Enforces the "must be on 10.0.0.0/8"
guardrail per requirements, dedups by IP + MAC, prefers Meraki-live
IP over Webex-cached IP.
- dectCollectorService.js: fan-out layer over the hub. collectAll()
runs one RPC per base in parallel with per-base error isolation —
one bad base never fails the batch.
Phone-status integration:
- Renderer gets a dectFollowUpBaseCount opt that emits an italic
"diagnostics loading for N base(s)..." hint inside the DECT section
of the main message.
- New exported renderDectDiagnosticsMarkdown() renders the follow-up
message: healthy/warning icon per base, uptime + firmware summary,
structured Power Loss reboot line, and per-base failure hints (e.g.
"relay accepted the request but the base did not respond in time").
- commands/phoneStatus.js discovers reachable bases synchronously
(pure), sends the main message, then fires collectAll() and posts
the follow-up as a separate message. Failures logged, never thrown
back to the user.
- Chat only: HTTP callers keep their single-message contract.
Agent side (dect-relay-agent/):
- Standalone Node process with its own package.json (only ws, axios,
dotenv). Reuses the shared integrations/cisco-dect/{client,probes,
statusXml}.js modules from the parent workspace so there's no code
duplication.
- Auto-reconnect with exponential backoff + jitter.
- Dispatches collect / reboot / force-reboot / reboot-chain /
force-reboot-chain / factory-reset / reconfigure-tree.
- DECT admin credentials live ONLY on the agent (never on the bot).
Shared bearer token gates the WSS handshake.
- README.md covers install, config, wire protocol, and safety model.
Env / infra:
- .env.example: adds DECT_RELAY_AGENT_TOKEN + optional DECT_RELAY_PATH
and DECT_COLLECT_TIMEOUT_MS. Reframes DECT_TEST_* as the local-dev
test harness rather than the production path.
- index.js: captures the http.Server from app.listen() and attaches
the relay hub when DECT_RELAY_AGENT_TOKEN is set; graceful shutdown
now closes the hub so in-flight RPCs get rejected cleanly.
- Adds "ws" to bot dependencies.
Tests (99 -> 113):
- tests/dectDiscovery.test.js: 13 cases covering the 10.x guardrail,
MAC normalization, IP source preference, dedup, and warning shape.
- tests/dectRelayHub.test.js: 14 integration cases using a real
ws pair on an ephemeral 127.0.0.1 port — auth (missing / wrong /
correct via header / correct via protocol fallback), hello frame,
RPC round-trip with correlation, agent error surfacing, concurrent
out-of-order replies, timeout, mid-flight disconnect, replacement
of a stale socket, and execAction routing.
- tests/renderers.test.js: 8 new cases for the DECT-follow-up loading
hint (plural / singular / off) and the diagnostics renderer (empty,
healthy, warning, power-loss dedup, active RTP, error hint, footer).
48 lines
2.5 KiB
Text
48 lines
2.5 KiB
Text
# =============================================================================
|
|
# DECT Relay Agent — data-center-resident bridge to Cisco DBS-210 bases
|
|
# =============================================================================
|
|
#
|
|
# This agent runs INSIDE the corporate network (has route to 10.x/8)
|
|
# and dials outbound over WSS to the CollabSupport bot. The bot
|
|
# process itself runs in the public cloud and can't reach 10.x
|
|
# directly; this agent is the only thing that can talk to a DBS-210.
|
|
#
|
|
# See README.md in this folder for run instructions.
|
|
|
|
# ─── Where to dial the bot ───────────────────────────────────────────
|
|
#
|
|
# Full WSS URL to the bot's DECT relay endpoint. Must be wss:// (never
|
|
# ws:// — the bearer token would be visible in cleartext). The path
|
|
# defaults to /dect-relay/ws to match the bot's DECT_RELAY_PATH env
|
|
# on the other side; only change here if you've changed it there too.
|
|
DECT_RELAY_BOT_URL=wss://your-bot-host.example.com/dect-relay/ws
|
|
|
|
# Shared bearer token — MUST match the bot's DECT_RELAY_AGENT_TOKEN
|
|
# exactly. Rotate both sides at once to avoid a lockout window.
|
|
# Suggested generation: `openssl rand -hex 32`
|
|
DECT_RELAY_AGENT_TOKEN=replace-with-shared-secret
|
|
|
|
# Optional friendly identifier reported to the bot on hello.
|
|
# Shows up in the bot's logs and eventually /dectstatus admin views.
|
|
# Defaults to os.hostname() if unset.
|
|
# DECT_RELAY_AGENT_HOSTNAME=dc-dect-relay-01
|
|
|
|
# ─── DBS-210 admin credentials ───────────────────────────────────────
|
|
#
|
|
# Cisco tenants share ONE serviceability password across all bases
|
|
# in the fleet (configured in Control Hub → Calling → Features →
|
|
# DECT Networks → Manage → Manage DECT serviceability password), so
|
|
# a single credential works for every 10.x base this agent can reach.
|
|
DECT_ADMIN_USER=admin
|
|
DECT_ADMIN_PASSWORD=replace-with-dect-serviceability-password
|
|
|
|
# Per-request HTTPS timeout when talking to a DBS-210. Bases going
|
|
# through a corporate proxy can be slow — 30s is comfortable, 15s
|
|
# is aggressive.
|
|
DECT_ADMIN_TIMEOUT_MS=30000
|
|
|
|
# ─── Optional tuning ─────────────────────────────────────────────────
|
|
#
|
|
# How long to wait between reconnect attempts when the bot socket
|
|
# drops. Uses exponential backoff up to this cap.
|
|
# DECT_RELAY_RECONNECT_MAX_MS=30000
|