reference/link-handler-spec.md

/link Handler Spec

Back to DocStart

Status:

  • implemented
  • active in apps/web for test.mino.ink, mino.ink, and built-in UI

Last updated:

  • February 11, 2026

Goal

Support zero-manual onboarding from setup links generated by the server:

  • Relay mode:
    • https://test.mino.ink/link?relayCode=...&relayUrl=...
    • https://mino.ink/link?relayCode=...&relayUrl=...
  • Open-port mode:
    • https://test.mino.ink/link?serverUrl=...&apiKey=...
    • https://mino.ink/link?serverUrl=...&apiKey=...
  • http://localhost:3000/link?serverUrl=...&apiKey=... (built-in UI)
  • http://localhost:5173/link?serverUrl=...&apiKey=... (local dev)

The user should open the link and be connected automatically.

Required Query Params

  • Direct mode:
    • serverUrl
    • apiKey
  • Relay mode:
    • relayCode
    • optional relayUrl (defaults to configured relay base)

Optional (future):

  • workspace
  • returnTo

Required Behavior

  1. Parse query params on /link.
  2. If relayCode is present, exchange at relay:
    • POST {relayUrl}/api/v1/pair/exchange
    • response contains serverUrl + apiKey
  3. Validate presence of resolved serverUrl and apiKey.
  4. Normalize serverUrl:
    • trim whitespace
    • remove trailing slash (while preserving path segments)
  5. Verify key:
    • POST {serverUrl}/api/v1/auth/verify
    • header: X-Mino-Key: {apiKey}
  6. Mark setup complete:
    • POST {serverUrl}/api/v1/auth/link
    • header: X-Mino-Key: {apiKey}
  7. Persist linked server profile in localStorage (mino.linkedServers.v1).
  8. Redirect to /workspace?profile=<id>.

Error Handling Requirements

  • Missing params: show actionable error with retry link.
  • Auth failure (401): show invalid key error and manual form fallback.
  • Network/CORS failure: show diagnostics (serverUrl, endpoint attempted).
  • Any failure must keep manual link form available.

Security Requirements

  • Never log raw apiKey to console/analytics.
  • Redact key in UI logs and telemetry.
  • Remove sensitive params from URL after processing (replaceState):
    • apiKey
    • relayCode
    • relayUrl

Acceptance Criteria

  • Opening a valid relay or direct /link URL performs full linking without user typing.
  • Successful flow triggers POST /api/v1/auth/link exactly once.
  • URL is cleaned immediately (apiKey removed via history.replaceState).
  • Invalid links fail safely and present manual fallback.
  • Behavior is identical on:
    • https://mino.ink
    • https://test.mino.ink
    • built-in UI (http://localhost:3000)
    • local dev client (http://localhost:5173)