diff --git a/docs/superpowers/specs/2026-07-29-device-uuid-pairing-design.md b/docs/superpowers/specs/2026-07-29-device-uuid-pairing-design.md new file mode 100644 index 0000000..a22ee4c --- /dev/null +++ b/docs/superpowers/specs/2026-07-29-device-uuid-pairing-design.md @@ -0,0 +1,68 @@ +# Device UUID Pairing — Design + +**Datum:** 2026-07-29 +**Status:** goedgekeurd + +## Doel + +Voorkomen dat twee ESP-telefoon paren in dezelfde ruimte met elkaars ESP verbinden. Elk ESP-telefoon paar deelt een unieke UUID die tijdens key exchange wordt uitgewisseld. + +## Flow + +### Verse ESP (geen UUID, geen HMAC key) + +1. ESP boot, genereert random UUID (16 bytes via `esp_random()`), slaat op in NVS +2. ESP start BLE advertising als `"SylDa_Server"` (UUID nog onbekend bij app) +3. App opent Settings → Key Exchange +4. App stuurt `KEY?` over USB CDC, ESP antwoordt `NO_KEY` +5. App genereert random 32-byte HMAC key + 16-byte UUID +6. App stuurt `SET_KEY:<64 hex>` → ESP slaat op → `OK` +7. App stuurt `SET_ID:<32 hex>` → ESP slaat op → `OK` +8. App slaat beide op in EncryptedSharedPreferences +9. App keert terug naar main, start scan + +### Bestaand paar (beide hebben UUID + HMAC key) + +1. App stuurt `KEY?`, ESP antwoordt `DEVICE_ID:<32 hex>\nHMAC_KEY:<64 hex>` +2. App slaat beide op +3. Klaar + +### BLE connectie + +1. App scant op BLE service UUID `4fafc201-...` (niet op naam) +2. Bij elke gevonden device: connect, discover services +3. Lees UUID characteristic (READ-only) +4. UUID match → zet relay knoppen actief +5. UUID mismatch → disconnect, voeg address toe aan `triedAddresses`, herstart scan +6. Relay commands blijven HMAC-beveiligd zoals voorheen + +## Componenten + +### Firmware (`src/main.cpp`) + +| Item | Details | +|------|---------| +| NVS key `"uuid"` | 16 bytes, namespace `"hmac"` | +| UUID generatie | `esp_random()` per byte, alleen bij eerste boot | +| BLE naam | `"SylDa_Server"` | +| UUID characteristic | Nieuwe READ-only characteristic, los UUID | +| `KEY?` response | `DEVICE_ID:32HEX\nHMAC_KEY:64HEX` of `NO_KEY` | +| `SET_ID:32HEX` | Nieuw commando, slaat UUID in NVS | + +### Android — PrefsHelper + +- `PREF_UUID = "device_uuid"` (EncryptedSharedPreferences) + +### Android — SettingsActivity + +- `readKeyFromEsp()`: parse `DEVICE_ID:` lijn +- `KeyResult.Success` krijgt `deviceUuid` veld +- Bij `NO_KEY`: app genereert UUID + stuurt `SET_KEY` en `SET_ID` + +### Android — MainActivity + +- `loadState()`: laadt UUID +- `startScan()`: `ScanFilter` op service UUID +- `onScanResult`: connect bij elke match (naam genegeerd) +- `gattCallback.onMtuChanged`: lees UUID characteristic, verify +- UUID mismatch: disconnect, `triedAddresses.add(address)`, herstart scan