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 }
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? Yes — activePlatforms 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.
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.
Summary
/api/healthnow returns anactivePlatformsarray populated live as each adapter'sstart()resolves. The live reference is passed intoregisterApiRoutesbecause Telegram starts after the HTTP listener is already accepting requests, so a snapshot would miss it.SettingsPage.PlatformConnectionsSectionreadsactivePlatformsand looks each platform up in aSet. Also adds Gitea and GitLab to the list (they already ship as adapters).devmigrated to grammY and now uses theonStartcallback inpackages/adapters/src/chat/telegram/adapter.ts. That portion of the original PR has been dropped on rebase.UX Journey
Before
After
Architecture Diagram
Before
After
Connection inventory:
startServerregisterApiRoutes(activePlatforms)start()activePlatforms.push(...)GET /api/healthHealthResponse.activePlatforms['Web']SettingsPagehealth.activePlatformsfalse)Label Snapshot
risk: lowsize: Sserver,webserver:index,server:routes/api,web:SettingsPageChange Metadata
fixmulti(server + web)Linked Issue
Validation Evidence (required)
Security Impact (required)
NoNoNoNoactivePlatformsexposes only platform names (e.g."Slack") — no tokens or config values.Compatibility / Migration
Yes—activePlatformsis an optional field; clients that ignore it see no change.NoNoHuman Verification (required)
@archon/servertest suite pass locally.registerApiRoutesruns — the live array reference ensures/api/healthreflects its state once it pushes.getHealth()without platforms configured returns['Web']as before.Side Effects / Blast Radius (required)
/api/health, Settings page.*.bot_started,github_webhook_registered, etc.) remain the source of truth for startup observability.Rollback Plan (required)
git revert <commit>— single commit, 4 files, contained.Risks and Mitigations
'Telegram'to the array.tryblock afterawait telegramAdapter.start(); failure skips the push (matches pre-existingtelegram = nullhandling).Rebased from @liorfranko's original PR onto current
dev. The adapter changes were dropped because dev migrated from telegraf to grammY and already resolves thebot.launch()never-resolves issue via theonStartcallback — so that fix is no longer needed. The server + web portions remain and are credited to @liorfranko.Summary by CodeRabbit
New Features
Bug Fixes