-
Notifications
You must be signed in to change notification settings - Fork 0
Relay Trust UI
Relay Trust UI is the renderer-side gate between a relay peer key becoming visible and the app treating that peer as trusted. The reusable core in this slice is the pure helper relay-trust.ts, which converts the persisted trust value plus the current peer fingerprint into a TrustState. That state drives the Settings → Relay confirmation card, while persistence remains in settings.relay.trustedFingerprint.
- Encode the pairing-trust decision: show nothing, ask for confirmation, trust silently, or warn about a changed key.
- Keep the trust rule independent from the settings sheet, Electron APIs, and WebSocket/relay transport.
- Persist a user’s trust choice across sessions in
settings.relay.trustedFingerprint. - Ensure a changed peer key is never auto-trusted; it requires an explicit re-trust.
relay-trust.ts exports:
export type TrustState = 'none' | 'confirm' | 'trusted' | 'mismatch'
export function trustState(
trusted: string | undefined,
peerFingerprint: string | null
): TrustState| State | Condition | UI behavior |
|---|---|---|
none |
peerFingerprint is absent/null |
Show no card; not yet paired with a peer. |
confirm |
A peer fingerprint exists, but no persisted trust exists | Ask the user to confirm this fingerprint. |
trusted |
Persisted trust exactly matches the current peer fingerprint | Connect silently; no card. |
mismatch |
Current peer fingerprint differs from persisted trust | Hard warning; require explicit re-trust, never auto-trust. |
flowchart TD
A["trustState(trusted, peerFingerprint)"] --> B{"peerFingerprint present?"}
B -- "no / null" --> C["'none'<br/>no card"]
B -- "yes" --> D{"trusted present?"}
D -- "no / undefined" --> E["'confirm'<br/>first-pairing confirmation"]
D -- "yes" --> F{"trusted === peerFingerprint?"}
F -- "yes" --> G["'trusted'<br/>silent connect, no card"]
F -- "no" --> H["'mismatch'<br/>hard warning, explicit re-trust"]
The first branch checks whether a peer key exists at all. If there is no peer fingerprint, the helper returns none even when this machine previously trusted a fingerprint. The second branch treats missing persisted trust as a first pairing and returns confirm. Only an exact string match produces trusted; any non-matching persisted value produces mismatch.
- The relay client exposes pairing data through
RelayPairing:peerPub,peerLogin, andselfId.connect()returns this pairing. - The peer’s display fingerprint comes from
relayFingerprint(peerPubB64). It validates the peer public key, takes the first 16 bytes of SHA-256, and renders them as 8 space-separated lowercase hex pairs for human eyeballing. - The renderer-side Settings → Relay surface reads
settings.relay.trustedFingerprint. - It calls
trustState(trustedFingerprint, peerFingerprint)to derive the UI state. - The view maps the result:
-
none: render no trust card. -
confirm: render the first-pairing confirmation card. -
trusted: render nothing and connect silently. -
mismatch: render a hard warning and require explicit re-trust.
-
- When the user confirms or re-trusts, the hosting UI/persistence layer is responsible for writing the fingerprint into
settings.relay.trustedFingerprint. The helper itself does not persist anything.
- Input
trusted: string | undefinedis the persisted trust value.undefinedmeans “never trusted on this machine.” - Input
peerFingerprint: string | nullis the fingerprint reported by the current connect.nullmeans “no peer key yet.” - Output
TrustStateis derived, not stored by this module. - Persisted state lives under
settings.relay.trustedFingerprint. - UI state such as card visibility and warning severity should be derived from
TrustStaterather than duplicated as separate booleans.
-
src/renderer/src/components/relay-trust.ts— pure trust-state type and decision function. -
src/renderer/src/components/relay-trust.test.ts— unit coverage for the four outcomes without browser orwindow.termsprawlmocks. -
src/renderer/src/components/AppSettingsPanel.tsx— the app-wide settings sheet; its Connections navigation group contains the Relay surface. -
src/core/relay-client.ts— relay pairing data, fingerprint formatting, and the relay transport seam that feeds the peer key into the UI. -
src/renderer/src/components/AGENTS.md— component conventions, including the in-app confirmation overlay rule.
-
trustStateis pure and Electron-free. It does not read settings, open sockets, format fingerprints, or render JSX. - If
peerFingerprintis falsy, includingnullor an empty string, the result isnone. - If
trustedis falsy, includingundefinedor an empty string, the result isconfirmwhen a peer fingerprint exists. - Trust comparison is exact string equality. Any fingerprint formatting change must be coordinated with persisted values or treated as a migration/reset case.
- A
mismatchmust never silently update the persisted fingerprint. The user must explicitly re-trust the new key. - Fingerprint validation belongs to
relayFingerprint, nottrustState. That formatter rejects invalid base64-looking input and decoded keys that are not 32 bytes. - New confirmation UI must follow the
.confirm-overlayin-app pattern;window.confirmmust not be used because Electron silently no-ops it.
- Add or restyle the Settings → Relay card by switching on
TrustStatewithout changing the decision helper. - Wire “trust” and “re-trust” actions to the settings persistence layer so they update
settings.relay.trustedFingerprint. - Add a “forget trust” or reset action by clearing the persisted fingerprint, which naturally returns the next pairing to
confirm. - Support key rotation by treating
mismatchas an explicit user decision that overwrites the old fingerprint only after confirmation. - If new trust states are introduced, update the
TrustStateunion, the decision function, the renderer branch table, and the unit tests together. - If fingerprint formatting changes, consider a migration or compatibility layer because
trustStatecompares raw strings.
relay-trust.test.ts verifies the core safety rules:
- No peer fingerprint produces
none, even with a previously trusted key. - First pairing with no persisted trust produces
confirm. - A matching persisted fingerprint produces
trusted. - A changed peer fingerprint produces
mismatch.
Sources: src/renderer/src/components/relay-trust.ts; src/renderer/src/components/relay-trust.test.ts; src/core/relay-client.ts; src/core/relay-client.ts; src/renderer/src/components/AGENTS.md; src/renderer/src/components/AGENTS.md; src/renderer/src/components/AGENTS.md.
Generated from termsprawl at 0d4393be54c6200beedd91bb636e5296c30472c5.
App Shell & Platform Foundations
- Electron Main Process & Window Lifecycle
- Preload Bridge & IPC Contract
- Shared Domain Types and File/URL Helpers
- Renderer Bootstrap & App Composition
- Build Targets & TypeScript Configuration
Canvas, Nodes & Renderer State
- Infinite Canvas Surface & Viewport Interaction
- Workspace, Project & Tab State
- Node Links, Edges & Link Inspector
- Sticky, Group, Editor & Diff Nodes
- Keyboard Canvas Navigation & Cross-Panel Requests
- Theme, Accent & Visual Language
- Boot Overlay, Onboarding & Shared UI Kit
Terminals & Session Continuity
- PTY Lifecycle & Terminal Sessions
- tmux Session Naming & Reattach
- Scrollback Snapshots & Cold Replay
- Terminal Node Rendering (xterm.js)
- SSH Remote Projects, Terminals & Files
Persistence, Projects & Files
- Workspace Store & Project File Layout
- Project Scope, Deletion & Worktree Registry
- Workspace Bundle Export/Import
- File Service & File Tree UI
Agent Runtime & Tooling
- Agent Status Model & Hook Normalization
- Hook Server & CLI Hook Installers
- Agent Launch, CLI Probing & Managed Accounts
- Agent Tool Protocol & In-Process Server
- Agent Tool Client, CLI & MCP Entry
- Transcripts, Context Discovery & Context CLI
- Agent Canvas State & Status Badges
Chat Nodes & Model Providers
- Chat Runtime, Conversation & Cost
- Model Provider Adapters & Streaming
- Chat Tool Calling & Project Tools
- Chat Node UI
Git & Source Control
Embedded Browser Nodes
- Browser Manager & Guest Runtime
- CDP Facade & Browser Agent Server
- Browser Navigation Policy & Node UI
Server Edition
- Server Bootstrap & HTTP/WebSocket Entry
- RPC Dispatch, Handlers & Service Bridges
- Renderer Shim & Server Boundary
- Server Auth & Security Boundary
Relay & Remote Access
- Relay Hub & WebSocket Frame Routing
- Relay End-to-End Cryptography
- Relay Auth, Invites, Store & Admin API
- Relay Client, Pairing & Terminal Tunneling
- Relay Trust UI
Integrations & Secondary Surfaces
- Telegram Bot, Commands & Pairing
- A2A Peers: Protocol, Client & Server
- Node Link Engine, Registry & Scheduler
- Cloud Spaces, Snapshots & Sync
Settings, Updates & Maintenance