Skip to content

Web sessions should survive a daemon restart #16

Description

@whaclaw-bot

Goal

A browser that was logged in should stay logged in after the daemon restarts or
is re-launched. Today every restart sends every viewer back to the password
prompt.

Why it is not simply a bug

The cookie is fine — it is issued with Max-Age=86400 and the browser still
holds it. What is gone is the server's memory of it:

// src/web/common/auth.rs
pub struct SessionStore {
    tokens: Mutex<HashSet<String>>,
}

and that is documented as deliberate:

Tokens are opaque 256-bit random strings and stay valid until the process
exits (a fresh launch invalidates all sessions, which is the desired
behaviour for a dev tool).

So this issue asks to change a recorded decision, not to fix a defect. Moving
the credential to localStorage is not the answer either: the cookie is
HttpOnly on purpose, docs/architecture/web.md confines localStorage to
first-paint caches, and the server would still not recognise the token after a
restart.

What the change has to carry with it

Process exit is currently the backstop that makes two other accepted risks
tolerable. Removing it means picking up both:

  • No absolute TTL (docs/architecture/web.md, listed under accepted residual risks). Sessions
    live until the process ends. If a restart no longer clears them and nothing
    expires them, tokens become valid indefinitely. A persistent session needs an
    expiry.
  • Logout must stay a revocation, not a suggestionSessionStore::revoke
    exists precisely so that clearing the cookie is not the only defence. A purely
    stateless signed cookie (HMAC over an expiry, no server state) cannot revoke,
    so it does not satisfy this on its own; it needs a deny list, which puts the
    state back.

Two more constraints, if tokens land on disk:

  • They are credentials, so the file wants owner-only permissions. PermissionsExt
    is Unix-only, so per .agents/rules/guardrails.md the mode belongs behind the
    src/platform/ seam, with whatever Windows cannot enforce written down.
  • docs/web-viewer.md already steers operators away from a plaintext secret on
    disk (hashed_password over password). Long-lived tokens in a file push the
    other way and should be a conscious trade, not a side effect.

Worth noting for anyone weighing the exposure: the viewer has no TLS and the
cookie carries no Secure flag, both recorded. On a non-loopback bind the
token already crosses the network in plaintext; persisting it widens the window
from "until this process exits" to "until it expires".

Not proposing an implementation here

Ways this could go — persisted store with a TTL, signed cookie plus a deny list,
or leaving the model alone and letting a reverse proxy / SSH tunnel own
authentication — differ in what they give up. Since the current behaviour is a
documented decision, the decision should be settled (and
docs/architecture/web.md updated) before code moves.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions