Skip to content

Persist cookies and localStorage in host-partitioned browser profiles #437

Description

@danwalmsley

Outcome

WebScene currently keeps its HTTP cookie jar, localStorage, and sessionStorage in memory. A successful Spotify login therefore survives same-engine navigation but is lost when the application exits. Add a host-controlled, origin-partitioned browser profile that persists the state browsers are required to retain across process restarts.

This issue owns durable HTTP cookies and localStorage. IndexedDB persistence remains owned by #56 and must be reused or composed with rather than duplicated here.

Current behavior and reproduction

The unchanged Spotify login flow now completes in samples/SpotifyCatalog, including email OTP verification and the authenticated status handoff. After destroying and recreating the WebScene engine:

  • all cookies are gone, including unexpired cookies carrying Expires or Max-Age;
  • localStorage is empty;
  • sessionStorage is empty, which is correct for a fresh browsing session.

The existing storage_directory and storage_partition_key engine options configure IndexedDB only. The cookie jar and Web Storage maps are process-local runtime state, and samples/SpotifyCatalog does not configure a durable profile.

Required design

Host-owned profile identity and location

  • Define one stable host-owned profile/partition identity and a host-selected storage directory. Do not infer identity from a mutable URL, random loopback port, working directory, or executable path.
  • Keep application/profile partitions isolated. A second partition using the same web origin must not read the first partition's state.
  • Specify multi-process locking or rejection behavior, schema versioning/migration, corruption recovery, and explicit clear-data semantics.
  • Reuse the durable backend/lifecycle abstractions from [Frameforge 3] Implement durable IndexedDB project and Blob storage with stable app origins #56 where appropriate, without coupling cookie or Web Storage semantics to IndexedDB transactions.

Cookies

  • Persist only cookies with a valid future Expires or positive Max-Age. Session cookies remain memory-only and disappear after engine/application shutdown.
  • Preserve domain, host-only, path, creation order, expiry, Secure, HttpOnly, and SameSite metadata and continue enforcing those attributes on reload.
  • Apply replacement, deletion, expiry pruning, maximum-count/size limits, and document.cookie visibility consistently before and after restart.
  • Write updates atomically and never emit cookie names, values, authentication tokens, or serialized profile contents in diagnostics or traces.
  • Use restrictive file permissions and document the local-data threat model and any platform credential/encryption integration.

Web Storage

  • Persist localStorage per origin and profile across engine destruction and process restart.
  • Keep sessionStorage scoped to the browsing session while preserving its existing same-session navigation/reload behavior.
  • Implement quota accounting, atomic mutation, deterministic key ordering, and correct SecurityError/quota failure behavior. Disk I/O must not block the UI/runtime thread.
  • Define and test storage event delivery between eligible same-profile, same-origin live contexts. Do not expose cross-profile state.

Lifecycle and API

  • Flush or checkpoint bounded pending writes during orderly shutdown without an unbounded close delay; interruption must leave the last committed state readable.
  • Provide explicit host APIs for profile initialization and clearing cookies, local storage, or all site data. Clearing must be bounded, partition-scoped, and safe against path traversal or broad deletion.
  • Make ephemeral/no-profile operation explicit and retain it for tests and privacy-sensitive applications.
  • Update SDK documentation and samples/SpotifyCatalog to use a stable durable profile so a successful Spotify login survives a normal restart. The sample must remain safe to run from a host-selected SSD location.

Tests and evidence

  • Add a deterministic two-process native contract: process A sets persistent and session cookies plus localStorage and sessionStorage; process B reopens the same profile and observes only the persistent cookie and localStorage.
  • Verify expired/deleted cookies, HttpOnly, Secure, domain/path matching, SameSite, origin separation, profile separation, quota failure, corrupted/truncated storage, interrupted writes, and concurrent-open policy.
  • Add selected WPT coverage for cookies and Web Storage where the native harness can represent the behavior, plus project-owned restart contracts for cross-process durability.
  • Run repeated open/mutate/close cycles and report close latency, pending-write high-water mark, file-descriptor/task cleanup, retained RSS, and on-disk growth bounds.
  • Qualify macOS arm64, Linux x64, and Windows x64, including Native AOT consumers and an installed/relocated SDK.
  • Retain a manual unchanged-Spotify confirmation without recording credentials, OTPs, cookie values, or tokens: login once, quit normally, relaunch, and reach the authenticated catalog without logging in again.

Acceptance

  • An unexpired persistent cookie survives engine destruction and a new application process using the same profile; a session cookie does not.
  • localStorage survives restart for the same origin/profile; sessionStorage does not survive a new browsing session.
  • Origin and host profile partitions cannot read one another's state.
  • Expiry, security attributes, quotas, clear-data, corruption, crash recovery, and concurrent-open behavior are specified and covered by deterministic tests.
  • Persistence never performs unbounded disk I/O on the UI/runtime thread and shutdown remains within a documented numeric budget.
  • The installed Spotify catalog sample remains logged in after a normal quit and relaunch, with secrets absent from logs and retained evidence.
  • SDK/profile documentation explains durable versus ephemeral operation and the relationship to IndexedDB issue [Frameforge 3] Implement durable IndexedDB project and Blob storage with stable app origins #56.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions