From 714dae9a2cd779d801f377a9a7cdd2ba9f1b6885 Mon Sep 17 00:00:00 2001 From: Dragan Spiridonov Date: Wed, 22 Jul 2026 17:54:13 +0200 Subject: [PATCH] =?UTF-8?q?docs(adr):=20amend=20ADR-271=20=E2=80=94=20the?= =?UTF-8?q?=20login=20flow=20lives=20in=20ruview-auth=20behind=20a=20featu?= =?UTF-8?q?re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ADR said the login flow was "not in this crate". It is now, gated behind a non-default `login` feature. The original line existed to keep the sensing server lean; a feature gate achieves that without forcing the Tauri desktop app to grow a second copy of a PKCE + rotating-refresh implementation — the kind of duplication that drifts and then disagrees about something subtle. Recording the change rather than letting the ADR quietly go stale, which is the exact failure this session hit twice in other repos' ADRs. Co-Authored-By: Ruflo & AQE --- .../ADR-271-cognitum-oauth-resource-server.md | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/adr/ADR-271-cognitum-oauth-resource-server.md b/docs/adr/ADR-271-cognitum-oauth-resource-server.md index e63972b8..a243fdf8 100644 --- a/docs/adr/ADR-271-cognitum-oauth-resource-server.md +++ b/docs/adr/ADR-271-cognitum-oauth-resource-server.md @@ -204,6 +204,30 @@ signature or identity claims distinguishes it — only scope does. A naive verifier accepts it, and an `inference` token becomes a key to someone's home sensor. -**Not in this crate**: the login flow (PKCE, loopback, OOB paste), wiring into -`bearer_auth.rs`, WebSocket authentication (ADR-272), and any outbound Cognitum -call. This is verification only. +**Not in this crate**: WebSocket authentication (ADR-272) and any outbound +Cognitum call. + +### Amendment, 2026-07-22 — the login flow lives here after all, behind a feature + +The paragraph above originally also excluded the login flow. That was written +to keep the sensing server lean, which is the right goal but not a reason to put +the code somewhere else: the Tauri desktop app needs the same flow, and a second +copy of a PKCE + rotating-refresh implementation is exactly the kind of +duplication that drifts apart and then disagrees about something subtle. + +So `login` is a **non-default feature** of this crate. A server built with +default features gets the verifier and nothing more — no `reqwest`, no tokio +networking, no browser launcher. The CLI opts in with +`features = ["login"]`, and the desktop app can do the same. + +Shipped as `wifi-densepose login` / `logout` / `whoami`. Two properties worth +restating because they are easy to get wrong: + +* **Refresh is serialised and never retried.** Identity rotates refresh tokens + with reuse detection, so a concurrent refresh looks like replay and a retry + *is* replay — either revokes the session family. `Session::ensure_fresh` + holds an async mutex across the network call, re-checks expiry after + acquiring it, and persists the rotated token before returning it. +* **Least scope by default.** `login` requests `sensing:read`; `--admin` is an + explicit escalation and requests both scopes, since there is no hierarchy + server-side.