fix(ui): actually call refreshSignInPanel — VERIFIED IN A REAL BROWSER

`refreshSignInPanel` was exported and never invoked. The Cognitum Account panel
would have rendered "Checking…" forever and the Sign in button would never have
reflected a completed sign-in.

That is the FOURTH defect of this exact shape today — implemented, unit-tested,
and never called. The others: the refresh path no command invoked, scope
resolved only at write time, and a WebSocket listener with no auth layer. The
pattern is consistent: the logic was fine, the caller was missing, and a green
suite could not see it.

Now refreshed on every panel open — not once at construction — because the
session may have been established in another tab or expired since page load.
Buttons are also bound at construction so a click works before the first status
fetch resolves.

VERIFIED END TO END IN A REAL BROWSER (Chrome, http://127.0.0.1:8099/ui/), which
is the gap that has been open all session:

  1. panel showed "This server requires sign-in." + Sign in with Cognitum
  2. clicked -> auth.cognitum.one -> approved
  3. server: "browser sign-in complete" sub=ed3efb51-…
  4. DevTools: ruview_session cookie on 127.0.0.1, Path=/, HttpOnly, SameSite=Lax
  5. after reload the panel reads:
       "Signed in as UyShaIh1B1gL7km9Xli9kCDSdRT2 — sensing:read"  + Sign out

So the browser half of gate G-3 is now proven, not argued: PKCE, consent, the
server-side code exchange, ES256 verification with audience and scope checks,
the signed session cookie, and the UI reading it back.

Diagnosis note worth keeping: the first attempt appeared to fail because the
browser tab had been open since BEFORE the fix — an already-loaded ES module
stays in memory regardless of `Cache-Control: no-store`. The cookie had been
stored correctly the whole time; the panel simply never re-queried. The server
log showed zero /oauth/status probes, which is what distinguished "fetch never
fired" from "fetch got the wrong answer". Temporary cookie diagnostics added to
find that are removed here.

Tests: 547 sensing-server lib, unchanged.

Co-Authored-By: Ruflo & AQE
This commit is contained in:
Dragan Spiridonov
2026-07-23 10:41:11 +02:00
parent 9299a3b137
commit 4a704acc02
+12
View File
@@ -113,6 +113,13 @@ export class QuickSettings {
// Bind events
this.panel.querySelector('.qs-close').addEventListener('click', () => this.close());
// ADR-271 sign-in. Bound here as well as in refreshSignInPanel so a click
// works even if the status fetch has not resolved yet.
this.panel.querySelector('#qs-signin')
.addEventListener('click', () => { window.location.href = '/oauth/start'; });
this.panel.querySelector('#qs-signout')
.addEventListener('click', () => { window.location.href = '/oauth/logout'; });
this.panel.querySelector('#qs-reduced-motion').addEventListener('change', (e) => {
document.body.classList.toggle('reduced-motion', e.target.checked);
this.saveSetting('reduced-motion', e.target.checked);
@@ -221,6 +228,11 @@ export class QuickSettings {
open() {
this.isOpen = true;
this.panel.classList.add('open');
// Refresh on every open, not once at construction: the session may have
// been established in another tab, or expired since the page loaded.
// Fire-and-forget — a failure renders as a message in the panel, and must
// not stop the panel opening.
void refreshSignInPanel(this.panel);
}
close() {