# Relay-Level Success Criteria

Source: `docs/architecture/adr-009-relay-tunnel.md`, GitHub issue #438

## Core Criteria (from #438)

- [ ] `llmhosts up` establishes relay connection with zero user config
- [ ] `curl https://device.llmhosts.com/v1/models` returns models from the device
- [ ] Works behind NAT, corporate firewall, hotel WiFi
- [ ] Reconnects automatically on network interruption
- [ ] Binary ships inside pip wheel (no separate install)
- [ ] <50ms latency overhead for relay (excluding network RTT)
- [ ] Works on Windows, Linux, macOS (all architectures)

## Journey-Aligned Criteria

| Journey | Criterion |
|---------|-----------|
| Journey 4 (Multi-Machine) | Set `OPENAI_BASE_URL=https://device.llmhosts.com/v1`, any OpenAI-compatible tool works |
| Journey 5 (Team) | All team members' GPUs accessible via relay for Hive pooling |
| Journey 6 (Graceful Degradation) | Local proxy continues working when relay is disconnected |
| Journey 7 (Marketplace Operator) | Operators maintain persistent relay connections for buyer traffic |

## Security Criteria

- [ ] Noise NK encryption: relay server provably cannot read HTTP payloads
- [ ] Wrong server pubkey → clean error, no crash or data leak
- [ ] Relay token expires after 24h, auto-refreshes via control stream
- [ ] Rate limiting: per-device request + bandwidth limits

## Multiplexing Criteria

- [ ] 10 concurrent streaming requests through relay, all complete independently
- [ ] No head-of-line blocking: fast request finishes while slow request is in-flight
- [ ] yamux overhead: <2ms per frame
- [ ] Max 256 concurrent streams per device (configurable)

## Resilience Criteria

- [ ] Reconnection within 5s (p95) after network interruption
- [ ] Exponential backoff: 1s → 2s → 4s → ... → 60s cap, with ±50% jitter
- [ ] Never stop reconnecting (device should always be reachable)
- [ ] Server restart → connections drain gracefully (30s timeout)
- [ ] Token refresh at 23h (before 24h expiry), transparent to user
