hermes-agent/web/src/components
Ben c93b9f9057
Some checks are pending
CI / detect (push) Waiting to run
CI / tests (push) Blocked by required conditions
CI / lint (push) Blocked by required conditions
CI / typecheck (push) Blocked by required conditions
CI / docs-site (push) Blocked by required conditions
CI / history-check (push) Blocked by required conditions
CI / contributor-check (push) Blocked by required conditions
CI / uv-lockfile (push) Blocked by required conditions
CI / docker-lint (push) Blocked by required conditions
CI / supply-chain (push) Blocked by required conditions
CI / osv-scanner (push) Blocked by required conditions
CI / All required checks pass (push) Blocked by required conditions
Deploy Site / deploy-vercel (push) Waiting to run
Deploy Site / deploy-docs (push) Waiting to run
Docker Build and Publish / build-amd64 (push) Waiting to run
Docker Build and Publish / build-arm64 (push) Waiting to run
Docker Build and Publish / merge (push) Blocked by required conditions
feat(relay): terminal 4401 (opt-out) → clean "Relay disabled" state
Phase 7 Unit 7d-B. When an operator opts an instance OUT of the Team Gateway
relay (Unit 7b deprovision), the connector revokes the per-gateway secret and
closes the gateway's WS with 4401. The reconnect supervisor previously treated
EVERY close as retryable, so the live process spun "retrying 4401" forever and
the dashboard showed a red error — opt-out looked like a failure.

Now a 4401 close that arrives AFTER a successful handshake is recognized as a
terminal credential revocation:

- ws_transport.py: track `_handshake_succeeded` (set when a descriptor is
  received); on a 4401 close after a prior success, latch `auth_revoked` and do
  NOT spawn the reconnect supervisor. A 4401 BEFORE any successful handshake
  stays retryable (cold-start / not-yet-provisioned race, not a revocation).
  New `auth_revoked` property + a websockets-version-safe close-code reader
  (prefers `.rcvd`/`.sent` Close frames; `.code` is deprecated in websockets 13+).
- adapter.py: a revocation monitor turns `transport.auth_revoked` into a clean,
  NON-retryable `relay_disabled` fatal and notifies the gateway's fatal-error
  handler (so the adapter is removed and NOT queued for reconnection — the
  credential is dead until the instance is recreated). Monitor is cancelled on
  disconnect; only started when the transport exposes `auth_revoked` (prod WS).
- run.py: `_handle_adapter_fatal_error` maps the `relay_disabled` code to a
  `disabled` platform_state (not `fatal`/`retrying`).
- web: PlatformsCard renders the `disabled` state with a neutral outline badge,
  a PowerOff icon, and muted (not destructive-red) text + message. New optional
  `status.disabled` i18n string ("Disabled").

Also bundles the Phase 7 contract-doc update (this doc is authoritative in
hermes-agent): docs/relay-connector-contract.md gains an "Author-first
resolution + the account-link (DM) path" section documenting the
multi-tenant-guild rule (D-7.2 — route by authenticated author binding, never by
guild; unlinked → fail-closed), the `/link <code>` DM flow, and the
connector-authoritative opt-out + terminal-4401 behavior this PR implements.

Tests: +2 ws_transport (4401-after-handshake terminal / no-reconnect;
4401-before-handshake stays retryable) and +2 adapter (revocation → non-retryable
relay_disabled fatal + handler fired; no-revocation → no fatal). 138 relay tests
pass (incl. the contract-doc conformance test); ruff clean; web tsc clean.

Phase 7 Unit 7d-B (relay-adapter solo lane). Q17 → Option 2; Option 3 (live
de-register, no recreate) + the restart-re-provision hole deferred post-alpha.
2026-06-24 18:43:01 +10:00
..
AuthWidget.tsx feat(dashboard-auth): Phase 7 — SPA AuthWidget + /api/status auth fields 2026-05-27 02:12:27 -07:00
AutoField.tsx Merge remote-tracking branch 'origin/main' into refactor/use-ds-primitives 2026-05-28 14:20:49 -04:00
AutomationBlueprints.tsx fix(dashboard): use DS Button prefix/size API instead of inline icons 2026-06-18 16:00:26 -04:00
Backdrop.tsx feat(dashboard): nous-blue theme, bulk sessions, schedule picker (#37383) 2026-06-02 12:37:40 -04:00
ChatSessionList.tsx fix(dashboard): sort chat session switcher by most-recent activity (#49104) 2026-06-19 07:58:56 -07:00
ChatSidebar.tsx refactor(dashboard): remove the dead tools box from the chat sidebar (#51737) 2026-06-23 23:59:55 -07:00
ConfirmDialog.tsx fix(model): require confirmation for expensive model selections 2026-06-10 00:24:06 -07:00
DeleteConfirmDialog.tsx refactor(web): consume DS primitives, remove local component copies 2026-05-22 21:57:59 -04:00
LanguageSwitcher.tsx Merge remote-tracking branch 'origin/main' into refactor/use-ds-primitives 2026-05-28 14:20:49 -04:00
Markdown.tsx harden: restrict markdown link schemes; parse untrusted XML with defusedxml 2026-05-25 23:30:43 -07:00
ModelInfoCard.tsx feat(dashboard): nous-blue theme, bulk sessions, schedule picker (#37383) 2026-06-02 12:37:40 -04:00
ModelPickerDialog.tsx fix(model): require confirmation for expensive model selections 2026-06-10 00:24:06 -07:00
ModelReloadConfirm.tsx Fix model picker and autorefresh on change 2026-06-19 07:25:35 -07:00
OAuthLoginModal.tsx Merge remote-tracking branch 'origin/main' into refactor/use-ds-primitives 2026-05-28 14:20:49 -04:00
OAuthProvidersCard.tsx Merge remote-tracking branch 'origin/main' into refactor/use-ds-primitives 2026-05-28 14:20:49 -04:00
PlatformsCard.tsx feat(relay): terminal 4401 (opt-out) → clean "Relay disabled" state 2026-06-24 18:43:01 +10:00
ProfileScopeBanner.tsx feat(dashboard): unify multi-profile management — one machine dashboard, global profile switcher (#44007) 2026-06-11 03:29:33 -07:00
ProfileSwitcher.tsx feat(dashboard): unify multi-profile management — one machine dashboard, global profile switcher (#44007) 2026-06-11 03:29:33 -07:00
ReasoningPicker.tsx feat(dashboard): add a reasoning-effort picker to the chat sidebar (#49141) 2026-06-19 11:37:40 -07:00
ScheduleBuilder.tsx feat(dashboard): nous-blue theme, bulk sessions, schedule picker (#37383) 2026-06-02 12:37:40 -04:00
SidebarFooter.tsx Merge remote-tracking branch 'origin/main' into refactor/use-ds-primitives 2026-05-28 14:20:49 -04:00
SidebarStatusStrip.tsx feat(web): add collapsible sidebar for the dashboard (#33421) 2026-05-27 23:58:41 -04:00
SkillEditorDialog.tsx feat(dashboard): SKILL.md editor on Skills page + attach-skill selector in cron modals (#44231) 2026-06-11 06:10:27 -07:00
SlashPopover.tsx refactor(web): dashboard typography & contrast pass 2026-05-22 19:50:32 -07:00
ThemeSwitcher.tsx feat(dashboard): change UI font from the theme picker, independent of theme (#41145) 2026-06-07 03:39:01 -07:00
ToolsetConfigDrawer.tsx fix(dashboard): use DS Button prefix/size API instead of inline icons 2026-06-18 16:00:26 -04:00