Skip to content

fix(web): clear form drafts even when you sign out before the page loads - #346

Merged
botandbang merged 2 commits into
mainfrom
bnb/signout-drafts
Oct 31, 2026
Merged

botandbang merged 2 commits into
mainfrom
bnb/signout-drafts

Conversation

@botandbang

Copy link
Copy Markdown
Contributor

What and why

Form drafts kept in localStorage were dropped by a submit handler in the root layout, which only exists once the page has hydrated. Pressing Sign out before the dashboard hydrated posted the form natively, the handler never ran, and the account's drafts stayed in the browser for whoever used it next. This also made the e2e test "an inquiry from a planner show ... keeps an unsent message" fail about 1 run in 6.

Added: POST /logout sets an ln_signed_out cookie naming the account that signed out, adding to any DIDs already in it. Every sign-out ends in a full page load, so on that load the root layout drops those accounts' drafts and then deletes the cookie. This works whether or not the page signed out from had hydrated, and the cookie also survives a tab closed before the next page loads. It isn't HttpOnly because the page's scripts read and delete it; it holds only DIDs, is SameSite=Lax and Secure on HTTPS, and lives until the next page load (a year at most).

Changed: clearDrafts(did) in form-draft.svelte.ts became clearSignedOutDrafts(), which reads the cookie. The README describes the new behaviour and lists the cookie in the security notes.

Removed: the root layout's submit handler for the sign-out form, which the cookie makes redundant (it also cleared drafts when the logout request failed).

Drafts of accounts that didn't sign out are kept, so a session that lapses mid-form and is sent back through sign-in still finds its draft. Clear-Site-Data: "storage" wasn't used because it clears all of the origin's storage, including the keyboard-shortcuts preference and other accounts' drafts.

How it was tested

  • The inquiry e2e now loads the dashboard with its scripts blocked, checks the page hasn't hydrated, presses Sign out, and checks the draft is gone once / hydrates. It failed on main before this change.
  • Two new client tests in layout.svelte.test.ts cover the startup clearing: only the named accounts' drafts and the cookie go, and nothing is dropped without the cookie.
  • format:check, lint, check, knip, test, test:storybook, test:build, test:coverage (lines 95.46%) and test:e2e --project chromium pass locally.

Checklist

  • Tests cover the change
  • The READMEs, docs/ and --help still say what the code does

The root layout dropped an account's drafts from a submit handler on the
sign-out form, which only exists once the page hydrates. Pressing Sign
out before that posted the form natively, the handler never ran, and the
drafts stayed in localStorage for whoever used the browser next.

/logout now sets an ln_signed_out cookie naming the account, and the
root layout drops that account's drafts and the cookie on the next page
load, which every sign-out ends in. The submit handler is gone, since
this covers it. Drafts of accounts that didn't sign out stay, so a
session that lapses mid-form still gets its draft back after signing in
again.

The inquiry e2e now signs out with the dashboard's scripts held back and
checks the draft is gone on the page it lands on.
@botandbang
botandbang requested a review from bnb as a code owner October 31, 2026 13:52
bnb
bnb previously approved these changes Oct 31, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation web The Local Network website (apps/web) web: accounts Signing in, sessions and the account pages web: ui Shared components, design tokens, layout and the static pages tests Tests, fixtures and test harnesses labels Oct 31, 2026
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Coverage Report for apps/web

Status Category Percentage Covered / Total
🟢 Lines 95.43% (🎯 93%)
⬆️ +0.01 pp
7916 / 8295
🟢 Statements 94.09% (🎯 91%)
⬆️ +0.01 pp
12053 / 12810
🟢 Functions 94.21% (🎯 92%)
🟰 ±0 pp
3126 / 3318
🟢 Branches 84.71% (🎯 80%)
🟰 ±0 pp
5621 / 6635
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/web/src/lib/form-draft.svelte.ts 89.28%
⬆️ +0.82 pp
82.75%
⬆️ +1.27 pp
95.45%
⬆️ +0.22 pp
89.85%
⬆️ +0.79 pp
28, 172-179, 127, 173-178
Generated in workflow #13 for commit b07634e by the Vitest Coverage Report Action

Size

Compared with main. KiB are 1,024 bytes.

This pull request main Change
Client JavaScript 680.7 KiB 680.3 KiB +380 B (+0.1%)
Client JavaScript, brotli 226.8 KiB 225.8 KiB +946 B (+0.4%)
Client CSS 89.6 KiB 89.6 KiB 0 B (0%)
Client CSS, brotli 12.9 KiB 12.9 KiB 0 B (0%)

@botandbang
botandbang added this pull request to the merge queue Oct 31, 2026
Merged via the queue into main with commit 5c74019 Oct 31, 2026
25 checks passed
@botandbang
botandbang deleted the bnb/signout-drafts branch October 31, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation tests Tests, fixtures and test harnesses web: accounts Signing in, sessions and the account pages web: ui Shared components, design tokens, layout and the static pages web The Local Network website (apps/web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants