fix(web,server): show real platform connection status in Settings (closes #1031) #1061

PR
PR description

Summary

  • Problem: The Settings page's "Platform Connections" section hardcoded every platform except Web to "Not configured", so users couldn't tell whether their Slack/Telegram/Discord/GitHub/Gitea/GitLab adapters had actually started.
  • Why it matters: Health/UX — config errors go undetected until a message arrives (or doesn't).
  • What changed:
    • Server: /api/health now returns an activePlatforms array populated live as each adapter's start() resolves. The live reference is passed into registerApiRoutes because Telegram starts after the HTTP listener is already accepting requests, so a snapshot would miss it.
    • Web: SettingsPage.PlatformConnectionsSection reads activePlatforms and looks each platform up in a Set. Also adds Gitea and GitLab to the list (they already ship as adapters).
  • What did not change (scope boundary): No changes to the Telegram adapter — the telegraf/grammY startup semantics fix that was part of the original PR is no longer needed since dev migrated to grammY and now uses the onStart callback in packages/adapters/src/chat/telegram/adapter.ts. That portion of the original PR has been dropped on rebase.

UX Journey

Before

  User                 Server                   Web UI (Settings)
  ────                 ──────                   ─────────────────
  opens Settings ────▶ GET /api/health
                       returns { adapter } ────▶ shows only Web
                                                 others hardcoded 'Not configured' ❌

After

  User                 Server                   Web UI (Settings)
  ────                 ──────                   ─────────────────
  opens Settings ────▶ GET /api/health
                       returns { adapter,
                              *activePlatforms*: ['Web','Slack',...] } ────▶ reflects real state ✅

Architecture Diagram

Before

startServer
├─ adapter.start() (each platform)
└─ (log-only) activePlatforms computed at end       registerApiRoutes
                                                    └─ GET /api/health → { adapter }

After

startServer
├─ [+] const activePlatforms: string[] = ['Web']
├─ adapter.start(); [+] activePlatforms.push(name)   registerApiRoutes(..., [+] activePlatforms)
└─ log activePlatforms (reuses the live array)       └─ GET /api/health → { adapter, [+] activePlatforms }

Connection inventory:

From To Status Notes
startServer registerApiRoutes(activePlatforms) modified Live array reference
each adapter start() activePlatforms.push(...) new Populated as they start
GET /api/health HealthResponse.activePlatforms new Optional field, defaults to ['Web']
SettingsPage health.activePlatforms modified Reads real data (was hardcoded false)

Label Snapshot

  • Risk: risk: low
  • Size: size: S
  • Scope: server, web
  • Module: server:index, server:routes/api, web:SettingsPage

Change Metadata

  • Change type: fix
  • Primary scope: multi (server + web)

Linked Issue

  • Closes #1031

Validation Evidence (required)

bun run type-check              # ✅ 10 packages
bun run lint                    # ✅ 0 errors, 0 warnings
bun --filter @archon/server test  # ✅ 46 tests pass

Security Impact (required)

  • New permissions/capabilities? No
  • New external network calls? No
  • Secrets/tokens handling changed? No
  • File system access scope changed? No

activePlatforms exposes only platform names (e.g. "Slack") — no tokens or config values.

Compatibility / Migration

  • Backward compatible? YesactivePlatforms is an optional field; clients that ignore it see no change.
  • Config/env changes? No
  • Database migration needed? No

Human Verification (required)

  • Verified scenarios: type-check / lint / @archon/server test suite pass locally.
  • Edge cases checked: Telegram starts after registerApiRoutes runs — the live array reference ensures /api/health reflects its state once it pushes. getHealth() without platforms configured returns ['Web'] as before.
  • What was not verified: Live browser check of the Settings page rendering against a running server.

Side Effects / Blast Radius (required)

  • Affected subsystems: /api/health, Settings page.
  • Potential unintended effects: None. The array is read-only from the handler's perspective; a copy is emitted each response.
  • Guardrails: Existing adapter-start logs (*.bot_started, github_webhook_registered, etc.) remain the source of truth for startup observability.

Rollback Plan (required)

  • Fast rollback: git revert <commit> — single commit, 4 files, contained.
  • Feature flags or config toggles: N/A.
  • Observable failure symptoms: Settings page returns to showing everything as "Not configured".

Risks and Mitigations

  • Risk: Telegram adapter fails to start but earlier code path already pushes 'Telegram' to the array.
    • Mitigation: Push is inside the try block after await telegramAdapter.start(); failure skips the push (matches pre-existing telegram = null handling).

Rebased from @liorfranko's original PR onto current dev. The adapter changes were dropped because dev migrated from telegraf to grammY and already resolves the bot.launch() never-resolves issue via the onStart callback — so that fix is no longer needed. The server + web portions remain and are credited to @liorfranko.

Summary by CodeRabbit

  • New Features

    • Settings panel now displays real-time connection status for all active platforms, including Gitea and GitLab.
    • Health check endpoint reports which platforms are currently active.
  • Bug Fixes

    • Platform connection status now reflects actual running platforms instead of hardcoded defaults.
CUT
cutter bot commented just now

Cutter Summary

The Platform Connections list now includes Gitea and GitLab rows alongside the existing platforms, and each row's connected/not-configured state is rendered from the health response rather than hardcoded.