# Device Link Architecture

Device Link connects a user's own ZoneGaze devices without a ZoneGaze-hosted device directory or traffic relay. The default product is direct-first and falls back only to infrastructure the user owns or configures.

## Product Rule
ZoneGaze does not host user traffic, device directories, public relays, TURN services, Firebase coordination, or default cloud rendezvous for Device Link. Worldwide access after setup requires at least one reachable user-owned relay or gateway.

## Connectivity
- Same-network direct path is preferred for latency and battery use.
- Direct internet path is planned through native Iroh NAT traversal and IPv6 when available.
- Relay fallback uses a ZoneGaze Relay service deployed by the user on their own Mac, NAS, router, home server, or VPS.
- Relays forward encrypted packets only. Application payloads stay end-to-end encrypted between paired device keys.

## Trust Model
- Each device owns a long-lived cryptographic identity.
- macOS stores the private identity material under Electron `safeStorage` in app user data.
- Android creates a Keystore-backed identity and stores only public metadata in app preferences.
- Pairing is explicit, short-lived, and verified with a matching code.
- Device groups are allow-lists of public keys. Unknown keys are not discoverable or accepted.
- Sensitive capabilities such as command execution stay disabled unless a future explicit approval flow enables them.

## Shared Contracts
The shared contract lives in `flow/contracts/src/device-link.ts`.

Important types:
- `DeviceLinkIdentity`
- `DeviceLinkPairingSession`
- `DeviceLinkPairedDevice`
- `DeviceLinkRelayConfig`
- `DeviceLinkRouteProbe`
- `DeviceLinkMessageEnvelope`
- `DeviceLinkSnapshot`
- `DeviceLinkRelayAccessClaims`

Important helpers:
- `selectDeviceLinkRoute`
- `validateDeviceLinkMessageEnvelope`

The Matrix shell talks to platform adapters through optional methods on `MatrixPlatformBridge`, so web, desktop, Android, and future relay transports can evolve without plugin-specific rewrites.

## Current Implementation Slice
- Matrix web has a Devices surface for pairing, route status, relay configuration, and paired-device capability controls.
- Desktop exposes Device Link state through IPC, persists identity/pairing/relay settings locally, handles `zonegaze-matrix://device-link/pair` invites, and signs relay route probes with its local identity.
- Desktop snapshots include a relay allow-list config for the current paired device group, and the Matrix Devices screen can copy that config for a self-hosted `zonegaze-relay`.
- Android exposes a native Devices surface and WebView bridge methods backed by the same local state.
- Android handles `zonegaze-matrix://device-link/pair` invite links natively, persists paired-device records, and implements capability updates plus device revocation behind the same `deviceLink.*` bridge methods used by the Mac Matrix surface.
- Android has an NSD-backed local discovery adapter for same-network route probes. It scans for `_zonegaze-device-link._tcp.` services during pairing and route tests, reports resolved local peers in the shared snapshot, and stops discovery after a bounded window.
- Route cards are truthful: they do not claim active Iroh NAT traversal, desktop LAN discovery, or relay packet forwarding until those transports are implemented and verified.
- `platforms/device-link-relay` contains the self-hostable relay scaffold. It validates signed device tokens against a user-provided group allow-list and forwards only opaque encrypted packet payloads.

## Self-Hosted Relay
The relay package is private to the repo today while the product packaging is finalized:

```bash
npm --prefix platforms/device-link-relay run build
node platforms/device-link-relay/dist/cli.js --host 0.0.0.0 --port 8098 --groups groups.json
```

After pairing at least one other device, open Matrix Devices and copy the relay allow-list. Save it as `groups.json` on the user-owned Mac, NAS, router, home server, or VPS that will run the relay. The relay does not discover devices globally and does not accept unsigned traffic:

```json
{
  "groups": [
    {
      "groupId": "group-example",
      "devices": [
        { "deviceId": "mac-device-id", "publicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n" },
        { "deviceId": "android-device-id", "publicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n" }
      ]
    }
  ]
}
```

The relay exposes:
- `HEAD /` or `GET /.well-known/zonegaze-device-link-relay` for authenticated health checks.
- `POST /v1/packets` for authenticated opaque packet enqueue.
- `GET /v1/packets` for authenticated packet polling by the receiving device.

## Next Transport Slice
1. Add native Iroh endpoint adapters for desktop and Android behind the existing bridge contracts.
2. Add desktop local discovery matching Android NSD.
3. Add encrypted application message streams over direct Iroh and relay packet routes.
4. Add Android native relay allow-list export/signing parity.
5. Add physical QA across same Wi-Fi, hotspot, different networks, relay online/offline, revoked devices, and separate users on the same relay.

## Android Follow-Up
The Android app already has the Devices surface, local identity state, native invite handling, paired-device persistence, capability/revoke controls, relay setup controls, WebView bridge methods, and lifecycle-bound NSD discovery for same-network peer detection. The Android transport slice still needs to add:

- Kotlin Iroh FFI endpoint binding behind the existing `deviceLink.*` bridge methods.
- Android Keystore-backed signing for device-group relay tokens.
- Android-native relay allow-list export matching the Mac Devices copy action.
- Foreground/background behavior that respects Android battery and network limits, with visible unavailable states when background access is restricted.
- Android-to-Mac physical QA for local Wi-Fi, hotspot, different networks with a user-owned relay, relay offline/online failover, and device revocation.

## License Constraint
Device Link dependencies must be free for commercial closed-source use. MIT, Apache-2.0, BSD, and similarly permissive licenses are acceptable when notices are preserved. GPL, AGPL, SSPL, paid-only relay services, and default company-hosted coordination are not acceptable for the product default.

## Research Basis
- Iroh language support: https://docs.iroh.computer/languages
- Iroh relays: https://docs.iroh.computer/concepts/relays
- Iroh NAT traversal: https://docs.iroh.computer/concepts/nat-traversal
- Iroh source and license: https://github.com/n0-computer/iroh
- Iroh FFI bindings: https://github.com/n0-computer/iroh-ffi
- Android NSD: https://developer.android.com/develop/connectivity/wifi/use-nsd
