Auth nutzt ein Shared Token (IRIS_TOKEN) als Security-Principal. Bei Rotation müssen alle Devices neu pairn; per-Device-Revocation steht nur als "stretch" in docs/09 §9.3.
Problem: Ein geleaktes Token = Zugriff auf alle Devices; ein kompromittiertes Device lässt sich nicht isolieren. Relevant, wenn die App mehreren Leuten zur Verfügung gestellt wird.
Vorschlag: Beim Pairing ein einzigartiges, revocables Token pro Device ausstellen (in devices.db). Shared Token bleibt als Setup/Bootstrap-Fallback.
Akzeptanz:
Per-Device-Token beim Pairing generiert + gespeichert
Einzelnes Device revocable ohne die anderen zu betreffen
Shared Token bleibt als Bootstrap-Path
docs/09 §9.3 von "stretch" auf "implemented"
Auth nutzt ein Shared Token (IRIS_TOKEN) als Security-Principal. Bei Rotation müssen alle Devices neu pairn; per-Device-Revocation steht nur als "stretch" in docs/09 §9.3.
Problem: Ein geleaktes Token = Zugriff auf alle Devices; ein kompromittiertes Device lässt sich nicht isolieren. Relevant, wenn die App mehreren Leuten zur Verfügung gestellt wird.
Vorschlag: Beim Pairing ein einzigartiges, revocables Token pro Device ausstellen (in devices.db). Shared Token bleibt als Setup/Bootstrap-Fallback.
Akzeptanz:
- Per-Device-Token beim Pairing generiert + gespeichert
- Einzelnes Device revocable ohne die anderen zu betreffen
- Shared Token bleibt als Bootstrap-Path
- docs/09 §9.3 von "stretch" auf "implemented"
Implementiert (Working Tree, noch nicht committet):
Gateway
pairing.py: devices.token-Spalte (Migration) + revoked-Denylist; issue_token (idempotent, 64 hex), token_for, reissue_token, revoke/unrevoke/is_revoked/list_revoked. Token wird nie in Device-Dicts geleakt.
http_server.py: Auth akzeptiert Shared Token (Bootstrap/Legacy) ODER das Device-Token (beide constant-time); revoked device_ids werden vor dem Token-Vergleich mit 401 abgewiesen. Beim SSE-Open (Pairing) wird das Device-Token gemintet und in hello.ack.device_token zurückgegeben.
HelloAckPayload.deviceToken; GatewayClient speichert es beim hello und präsentiert es fortan statt des Shared Tokens (Live-Provider in HttpGateway); savePairing/clear wischen es (Re-Pair auf anderes Gateway).
Akzeptanz
✅ Per-Device-Token beim Pairing generiert + gespeichert (devices.db)
✅ Einzelnes Device revocable ohne die anderen zu betreffen (Denylist schlägt auch den Shared Token)
✅ Shared Token bleibt Bootstrap-Path (Legacy-Devices ohne Device-Token funktionieren weiter; Rotation bricht Pairings nicht mehr)
✅ docs/09 §9.3 von "stretch" auf implemented (+ docs/04, frames.schema.json, M7-Tabelle Zeile 13)
Tests: 7 neue Python-Tests (Issuance, Acceptance, Revocation, Isolation, Unrevoke, 2 Registry-Unit) — 93/93 grün; 2 neue Kotlin-Wire-Tests — grün. Live-Verifiziert gegen laufendes Gateway: hello.ack trägt das Token (matcht devices.db), revoke → 401 auch mit Shared Token, unrevoke → 200.
Implementiert (Working Tree, noch nicht committet):
**Gateway**
- `pairing.py`: `devices.token`-Spalte (Migration) + `revoked`-Denylist; `issue_token` (idempotent, 64 hex), `token_for`, `reissue_token`, `revoke`/`unrevoke`/`is_revoked`/`list_revoked`. Token wird nie in Device-Dicts geleakt.
- `http_server.py`: Auth akzeptiert Shared Token (Bootstrap/Legacy) ODER das Device-Token (beide constant-time); revoked device_ids werden vor dem Token-Vergleich mit 401 abgewiesen. Beim SSE-Open (Pairing) wird das Device-Token gemintet und in `hello.ack.device_token` zurückgegeben.
- `protocol.py`: `hello_ack(..., device_token)`.
- Neues CLI `gateway-plugin/tools/iris_devices.py`: `list` / `revoke <id>` / `unrevoke <id>` / `reissue <id>`.
**App**
- `SecureStore.deviceToken` (Android: EncryptedSharedPreferences; Desktop: zweiter Keyring-/Encrypted-File-Slot `iris-device-token`/`device_token.enc`).
- `HelloAckPayload.deviceToken`; `GatewayClient` speichert es beim hello und präsentiert es fortan statt des Shared Tokens (Live-Provider in `HttpGateway`); `savePairing`/`clear` wischen es (Re-Pair auf anderes Gateway).
**Akzeptanz**
- ✅ Per-Device-Token beim Pairing generiert + gespeichert (devices.db)
- ✅ Einzelnes Device revocable ohne die anderen zu betreffen (Denylist schlägt auch den Shared Token)
- ✅ Shared Token bleibt Bootstrap-Path (Legacy-Devices ohne Device-Token funktionieren weiter; Rotation bricht Pairings nicht mehr)
- ✅ docs/09 §9.3 von "stretch" auf implemented (+ docs/04, frames.schema.json, M7-Tabelle Zeile 13)
**Tests**: 7 neue Python-Tests (Issuance, Acceptance, Revocation, Isolation, Unrevoke, 2 Registry-Unit) — 93/93 grün; 2 neue Kotlin-Wire-Tests — grün. Live-Verifiziert gegen laufendes Gateway: hello.ack trägt das Token (matcht devices.db), `revoke` → 401 auch mit Shared Token, `unrevoke` → 200.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Auth nutzt ein Shared Token (IRIS_TOKEN) als Security-Principal. Bei Rotation müssen alle Devices neu pairn; per-Device-Revocation steht nur als "stretch" in docs/09 §9.3.
Problem: Ein geleaktes Token = Zugriff auf alle Devices; ein kompromittiertes Device lässt sich nicht isolieren. Relevant, wenn die App mehreren Leuten zur Verfügung gestellt wird.
Vorschlag: Beim Pairing ein einzigartiges, revocables Token pro Device ausstellen (in devices.db). Shared Token bleibt als Setup/Bootstrap-Fallback.
Akzeptanz:
Implementiert (Working Tree, noch nicht committet):
Gateway
pairing.py:devices.token-Spalte (Migration) +revoked-Denylist;issue_token(idempotent, 64 hex),token_for,reissue_token,revoke/unrevoke/is_revoked/list_revoked. Token wird nie in Device-Dicts geleakt.http_server.py: Auth akzeptiert Shared Token (Bootstrap/Legacy) ODER das Device-Token (beide constant-time); revoked device_ids werden vor dem Token-Vergleich mit 401 abgewiesen. Beim SSE-Open (Pairing) wird das Device-Token gemintet und inhello.ack.device_tokenzurückgegeben.protocol.py:hello_ack(..., device_token).gateway-plugin/tools/iris_devices.py:list/revoke <id>/unrevoke <id>/reissue <id>.App
SecureStore.deviceToken(Android: EncryptedSharedPreferences; Desktop: zweiter Keyring-/Encrypted-File-Slotiris-device-token/device_token.enc).HelloAckPayload.deviceToken;GatewayClientspeichert es beim hello und präsentiert es fortan statt des Shared Tokens (Live-Provider inHttpGateway);savePairing/clearwischen es (Re-Pair auf anderes Gateway).Akzeptanz
Tests: 7 neue Python-Tests (Issuance, Acceptance, Revocation, Isolation, Unrevoke, 2 Registry-Unit) — 93/93 grün; 2 neue Kotlin-Wire-Tests — grün. Live-Verifiziert gegen laufendes Gateway: hello.ack trägt das Token (matcht devices.db),
revoke→ 401 auch mit Shared Token,unrevoke→ 200.