Auth previously used the shared IRIS_TOKEN as the security principal: a leaked token meant access to all devices, and a compromised device could not be isolated. Gateway: - pairing.py: devices.token column (in-place migration) + revoked denylist table; issue_token (idempotent, 64 hex), token_for, reissue_token, revoke/unrevoke/is_revoked/list_revoked. The token never leaks into device dicts (push fan-out / listings). - http_server.py: auth accepts the shared token (bootstrap/legacy) OR the device's own token (both constant-time); a revoked device_id is rejected with 401 before either comparison. On SSE open (pairing) the per-device token is minted and returned in hello.ack. - protocol.py: hello_ack(..., device_token). - adapter.py: setup flow (hermes gateway setup -> Iris) now offers 'Remove a paired device?' on an existing setup: numbered select menu (last option = exit the removal loop), confirmation, back to the menu for further removals. - tools/iris_devices.py: operator CLI (list / revoke / unrevoke / reissue), stdlib only. App: - SecureStore.deviceToken (Android: EncryptedSharedPreferences; Desktop: second keyring slot iris-device-token / device_token.enc). - HelloAckPayload.deviceToken; GatewayClient stores it on hello and presents it instead of the shared token from then on (live provider in HttpGateway); savePairing/clear wipe it for re-pairing. Docs: 09 §9.3 stretch -> implemented (revocation semantics, both control surfaces), 04 hello.ack example, frames.schema.json, M7 row 13. Tests: 8 new Python tests (issuance, acceptance, revocation, isolation, unrevoke, registry unit x2, setup-flow menu) - 94/94 pass; 2 new Kotlin wire tests - green. Live-verified against a running gateway (hello.ack token matches devices.db; revoke -> 401 even with shared token; unrevoke -> 200; setup TUI both paths).
Iris × Hermes — Implementation Reference Library
A coder-facing reference library for building a native Android + Desktop experience for hermes-agent, connected through a gateway platform plugin.
This folder is the single source of truth for what to build and why. Read it top-to-bottom once, then use the numbered docs as a lookup while implementing.
⚠️ READ FIRST — two hard rules
hermes-agent/(sibling of this folder) is a read-only research reference. It must NEVER be committed, pushed, or shipped. It is git-ignored at the repo root. We only install our plugin into a live hermes install (~/.hermes/plugins/); we never modify hermes core.- ADB is installed and a device is connected (
a5ca2a4b, Xiaomi MIX 2S, Android 10 / API 29). Use it to install/launch/debug the app on-device.
Reading order
| # | File | When to read |
|---|---|---|
| 0 | 00-overview.md |
Always first. Vision, scope, disclaimers, locked decisions. |
| 1 | 01-architecture.md |
Before touching code. System shape + rationale. |
| 2 | 02-monorepo.md |
When scaffolding the repo. |
| 3 | 03-gateway-plugin.md |
When building the Python plugin. |
| 4 | 04-wire-protocol.md |
When implementing either side of the WS. |
| 5 | 05-streaming.md |
Streaming / reasoning / tools / intermediate. |
| 6 | 06-channels-cron-search.md |
Channels, threads, cron delivery, search. |
| 7 | 07-media.md |
Media upload/download + playback. |
| 8 | 08-push.md |
Push (ntfy default + FCM optional), outbox, sync. |
| 9 | 09-pairing-security.md |
Pairing, auth, security model. |
| 10 | 10-android-app.md |
When building the Android app. |
| 11 | 11-desktop-app.md |
When building the Desktop app. |
| 12 | 12-toolchain.md |
First time on a machine (JDK/SDK/uv/Firebase). |
| 13 | 13-testing.md |
Writing tests + on-device ADB workflow. |
| 14 | 14-milestones.md |
Planning work / tracking progress. |
| 15 | 15-hermes-reference.md |
Cheat-sheet of hermes-agent source to read. |
| 16 | 16-open-questions.md |
Decisions made + open items. |
| 17 | 17-future-control-surface.md |
Backlog — what the app could control beyond chat (cron, kanban, models, …). |
| 19 | 19-http-fallback-transport.md |
Design — HTTP fallback leg (POST + SSE/long-poll) so the app can send/receive when the WS is down. |
| 20 | 20-qr-pairing.md |
Terminal QR at gateway setup + in-app QR scanner (Android) + iris://pair deep link. |
Machine-readable / diagrams:
protocol/frames.schema.json— wire-frame schema.diagrams/architecture.mmd— mermaid architecture.playstore-listing.md— Play Store listing text (incl. the FCM/ntfy privacy note).
The three deliverables (one monorepo)
gateway-plugin/— a Python hermes platform plugin namediris. Runs inside thehermes gatewayprocess. Opens a WebSocket server the apps connect to. Implements the fullBasePlatformAdaptercontract. Zero new Python dependencies, zero hermes-core changes.app/androidApp— native Kotlin + Jetpack Compose client.app/desktopApp— Kotlin + Compose Multiplatform client that shares the Android app's code and is "tweaked" for a big screen.
The Android and Desktop clients live in one Compose Multiplatform Gradle
project (app/) with a shared KMP module (app/shared).
Status
- Phase: M0–M6 complete; M7 (polish + E2E + docs) in progress.
- Owner decisions locked: see
16-open-questions.md. - Last updated: 2026-08-19.