You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Connections Registry: Formalized Panel with Logos + Custom Connections
Important
Decision Surface
Problem: The Connections panel is hardcoded to two entries (Company Compute, Pasqal Cloud), renders only colored dots (no brand identity), and provides no mechanism for users to add their own connections. New services (Slack, GitHub, Linear) need homes, and the system needs to be open to user-defined connections.
Approach: Introduce a ConnectionRegistry pattern. Built-in connections (5 total) ship with inline SVG logos and specific validators. Custom connections are user-created with optimistic storage (no server-side probe). Only configured connections appear in the panel; an "Add" picker surfaces unconfigured built-ins and a custom entry point.
Approaches Considered:
(A) Registry pattern (chosen): ConnectionRegistry holds built-in catalog + user entries. Validators are per-entry. ConnectionType loosens to string. Clean extension point, single-object additions for future built-ins.
(B) Additive (extend hardcoded): Keep CONNECTION_IDS, add a parallel custom array. Minimal change but two data paths, growing if/else chains.
(C) Configuration-driven: All connections in an external config file. Overengineered — built-in validators aren't user-configurable.
Scope: Panel infrastructure only (credential home + status + logos + custom connections). Gate wiring (features checking connection status before acting) is a follow-up per-service.
Assumptions:
Slack, GitHub, and Linear each take a single token (no OAuth flows in this pass)
Custom connections store optimistically — no validation probe
Existing Company Compute and Pasqal credential files are untouched
No auto-detection of existing credentials (gh CLI auth, env-var tokens)
Acceptance Criteria
Built-in catalog expanded: 5 connections ship: Harmoniqs Cloud, Pasqal Cloud, Slack, GitHub, Linear — each with an inline SVG brand icon and a specific validator
Logo rendering: Each connection card shows an 18px logo icon (SVG for built-ins, letter-avatar for custom) with a 6px state-dot badge on the bottom-right corner
Only configured connections visible: The panel shows only connections that have been configured (connected or previously attempted). Empty state shows "No connections yet" + Add button
Add picker: An "Add connection" button at the bottom of the list opens a picker. Custom entry at the top, then unconfigured built-ins with their logos. Selecting one opens the appropriate inline form
Custom connections: User provides name + token + optional URL. Stored in ~/.amico/custom-connections.json (0600). Render as "connected" immediately on save (optimistic). "Remove" action deletes entirely
Built-in disconnect hides card: "Disconnect" on a built-in clears the credential and removes the card from the panel. The connection reappears in the Add picker
New validators probe correctly: Slack validates against auth.test, GitHub against /user, Linear against the GraphQL endpoint. Probe failures classify as invalid/unreachable per existing discipline
Backward-compatible wire shape: GET /amicode/connections response keeps its shape. New icon field is optional (older UIs fall back to dots). New /catalog and /add-custom and /remove routes are additive
Custom connections file at 0600: Born atomic with restrictive permissions (ADR 0001 discipline)
Key Decisions
Registry architecture
A ConnectionRegistry replaces the hardcoded CONNECTION_IDS array. It holds:
A static built-in catalog (5 entries, each with id, name, icon, validator reference, authShape)
A dynamic custom-connections list loaded from ~/.amico/custom-connections.json
allConnections() merges both; configuredConnections() filters to those with stored credentials
The ConnectionType union type loosens to string across server and UI. Type guards remain for built-in-specific logic (HP flip on Company Compute connect, keychain for Pasqal).
Available (unconfigured) built-in connections for the picker
POST
/amicode/connections/add-custom
Create a custom connection
POST
/amicode/connections/remove
Remove a custom connection
Validator specs
Connection
Probe
Valid
Invalid
Unreachable
Slack
GET https://slack.com/api/auth.test with Bearer token
JSON body ok: true
JSON body ok: false
Network failure / non-JSON
GitHub
GET https://api.github.com/user with Bearer token
200
401/403
Other status / network failure
Linear
POST https://api.linear.app/graphql with Bearer, body {query:"{ viewer { id } }"}
200 + data present
401/403
Other / network failure
UI component map
Component
Location
Purpose
ConnectionIcon (new)
packages/ui/src/amicode/connection-icon.tsx
18px logo + 6px state badge
ConnectionPicker (new)
packages/ui/src/amicode/connection-picker.tsx
Add-flow picker list + inline forms
ConnectionCard (modified)
packages/ui/src/amicode/connections-tab.tsx
Replace dot with ConnectionIcon; add "Remove" action for custom
AmicodeConnectionsTab (modified)
same file
Add picker trigger; handle empty state
Icon assets
All SVGs are monochrome, currentColor fill, 18px viewBox. Built-ins: Harmoniqs logomark, Pasqal "P" mark, Slack hashtag, GitHub octocat silhouette, Linear angled-L. Custom: circle with background fill and first-letter initial.
Constraints & Invariants
Secrets never appear in status responses, error messages, or logs (existing discipline, extended to custom connections)
Loopback guard applies to all new mutation routes (add-custom, remove)
Custom connections file is born atomic at 0600 (ADR 0001)
The existing Company Compute and Pasqal credential files are never moved or reformatted
Custom connection IDs are prefixed custom- to avoid collisions with future built-in IDs
Prior Art
ADR 0002 (connections-server-route-seam): the server owns credentials and validation — this design extends that pattern
Resolved in design session 2026-08-10. CONTEXT.md updated with broadened Connection definition.
Notes
Gate wiring (Slack posts checking connection status, GitHub operations checking, Linear checking) is intentionally out of scope — tracked as per-service follow-ups once the panel infrastructure lands
OAuth flows for Slack/GitHub/Linear are a future enhancement (this pass is token-paste only)
The connectionTitle() function is subsumed by the registry's name field but kept as a backward-compat shim until all call sites migrate
type: spec
date: 2026-08-10
status: draft
priority: p2
platform: amicode
tags: [spec, connections, ui, architecture]
linked_plan: null
Connections Registry: Formalized Panel with Logos + Custom Connections
Important
Decision Surface
Problem: The Connections panel is hardcoded to two entries (Company Compute, Pasqal Cloud), renders only colored dots (no brand identity), and provides no mechanism for users to add their own connections. New services (Slack, GitHub, Linear) need homes, and the system needs to be open to user-defined connections.
Approach: Introduce a ConnectionRegistry pattern. Built-in connections (5 total) ship with inline SVG logos and specific validators. Custom connections are user-created with optimistic storage (no server-side probe). Only configured connections appear in the panel; an "Add" picker surfaces unconfigured built-ins and a custom entry point.
Approaches Considered:
Scope: Panel infrastructure only (credential home + status + logos + custom connections). Gate wiring (features checking connection status before acting) is a follow-up per-service.
Assumptions:
Acceptance Criteria
~/.amico/custom-connections.json(0600). Render as "connected" immediately on save (optimistic). "Remove" action deletes entirelyauth.test, GitHub against/user, Linear against the GraphQL endpoint. Probe failures classify as invalid/unreachable per existing discipline/amicode/connectionsresponse keeps its shape. Newiconfield is optional (older UIs fall back to dots). New/catalogand/add-customand/removeroutes are additiveKey Decisions
Registry architecture
A
ConnectionRegistryreplaces the hardcodedCONNECTION_IDSarray. It holds:~/.amico/custom-connections.jsonallConnections()merges both;configuredConnections()filters to those with stored credentialsThe
ConnectionTypeunion type loosens tostringacross server and UI. Type guards remain for built-in-specific logic (HP flip on Company Compute connect, keychain for Pasqal).Data contracts
ConnectionEntry (registry unit):
Custom connections file (
~/.amico/custom-connections.json):[ { "id": "custom-<uuid>", "name": "My Lab Server", "url": "https://...", "token": "<encrypted>" } ]New routes:
/amicode/connections/catalog/amicode/connections/add-custom/amicode/connections/removeValidator specs
https://slack.com/api/auth.testwith Bearer tokenok: trueok: falsehttps://api.github.com/userwith Bearer tokenhttps://api.linear.app/graphqlwith Bearer, body{query:"{ viewer { id } }"}UI component map
ConnectionIcon(new)packages/ui/src/amicode/connection-icon.tsxConnectionPicker(new)packages/ui/src/amicode/connection-picker.tsxConnectionCard(modified)packages/ui/src/amicode/connections-tab.tsxAmicodeConnectionsTab(modified)Icon assets
All SVGs are monochrome,
currentColorfill, 18px viewBox. Built-ins: Harmoniqs logomark, Pasqal "P" mark, Slack hashtag, GitHub octocat silhouette, Linear angled-L. Custom: circle with background fill and first-letter initial.Constraints & Invariants
custom-to avoid collisions with future built-in IDsPrior Art
connections.tswire-state contract (159/S3 — Connections routes: Company Compute connect path (probe-first, one round trip) #165): the tolerant parser + card model — extended withiconfield, backward-compatibleSource
Resolved in design session 2026-08-10. CONTEXT.md updated with broadened Connection definition.
Notes
connectionTitle()function is subsumed by the registry'snamefield but kept as a backward-compat shim until all call sites migrate