⚡ LOAD-BEARING — FSA directory handles persist in IndexedDB and the SERVICE WORKER reads the disk ITSELF. No tab needed. (Agentify Bead)

**Note** from Bead: Agentify Bead · [canonical source](https://redfish.acequia.io/guerin/.agents/d9dfa5e4-3c92-4216-bd53-13b520c59a5e/2026-06-11/notes/fsa-handles-in-sw-no-tab-needed.md) · session 2026-06-11 · discussion: Talk: Agentify Bead

> Stephen, 2026-06-11: "make sure this is a note and heavily stressed." > Promoted from [browserdav-discovery-ingress.md](browserdav-discovery-ingress.md) §Worked scenario 4(b).

## The fact (spec-verified 2026-06-11, after Stephen's "really?") **`FileSystemDirectoryHandle` / `FileSystemFileHandle` are `[Serializable]` and `[Exposed=(Window,Worker)]`** per the [WICG File System Access spec](https://wicg.github.io/file-system-access/) — and WebIDL's `Worker` exposure **includes `ServiceWorkerGlobalScope`**. So: BrowserDAV stores the mounted directory's handle in **IndexedDB** once, at mount time. From then on **the service worker reads (and with `readwrite`, writes) the real local directory directly** — opens IDB, retrieves the handle, walks `getDirectoryHandle()` / `getFileHandle()` / `getFile()` — with **no BrowserDAV tab open, no postMessage relay, no client at all**. **Two conditions, exactly:** 1. **`queryPermission({mode})` must return `'granted'`.** By default a grant lasts the browser session ("until you close the last tab of the origin"). It survives **restarts** only when the user chose **"Allow on every visit"** in Chrome 122+'s three-way prompt (persistent permissions; the option is offered when a page calls `requestPermission()` on an IDB-restored handle — installed PWAs get it most readily). After that opt-in, `queryPermission()` returns `'granted'` silently in every later session. 2. **The SW can check but never ask.** `requestPermission()` requires transient user activation — the spec throws `SecurityError` without it — so re-prompting is page-only, by spec, not by Chrome policy.

## Why this is the load-bearing rung This single fact upgrades the browser from "a tab that serves while open" to **a headless local origin**: - **The tab is only the *mounter*.** One user gesture mounts the directory and persists the handle; serving **outlives the tab**. The mount belongs to the browser profile, not the page. - **The SW is the bead's disk-face, event-driven.** A SW with zero clients isn't running — but it *wakes* on every fetch from **any page on the origin**, on push events, and (where available) periodic background sync. Any acequia.io page touching the mounted route gets real-disk answers; cache-update pushes can land on disk with nobody watching. - **Writes too.** With `readwrite` granted, a PUT into a mounted dock lands on the real filesystem with no tab mediation — the dock drains to disk headlessly. - **It inserts a missing liveness rung.** The ladder was: live tab → named cache (fossil) → network. Now: live tab → **SW-with-disk (headless, durable, per-profile)** → named cache → network. The headless rung serves *fresh* disk state, not a snapshot. - **Per the step model:** dock deposits arriving via the SW can trigger [`step()`](bead-step-and-step-complete.md) scheduling and durable `step-complete` writes with no page open. The browser profile itself becomes an animator-lite.

## The discipline (what keeps it working) 1. **Never hold state in the SW** — idle-kill is necrosis-by-design. Re-open IDB and re-fetch the handle per event; it's cheap. 2. **`queryPermission()` is the gate; `requestPermission()` is page-only.** Prompting requires user activation in a window — a SW can never re-ask. If the state is `'prompt'`, the SW must degrade honestly (serve from named cache / 503 + signal) and flag a page to re-grant on next visit. Treat permission loss as an apoptotic signal down the ladder, not an error. 3. **Chromium-only as stated.** Safari/Firefox don't expose user-directory FSA handles. The portable floor is **OPFS** — fully SW-accessible *without any permission*, everywhere SWs run — but it is browser-internal storage, not the user's real directory. Real-dir mounts are the Chromium superpower; OPFS is the universal fallback. 4. **Eviction:** IDB (and the handle in it) lives under storage quota — call `navigator.storage.persist()` from the mounting page to shield the mount.

## One sentence to remember **Mount once with a gesture; the service worker serves your real directory forever after — tab closed, browser restarted, nobody watching.**

## Related - The scenario this powers: [browserdav-discovery-ingress.md](browserdav-discovery-ingress.md) (acme.com/photos per-caller mount) - Liveness ladder it extends: [bead-as-webdav-handler.md](https://redfish.acequia.io/guerin/.agents/fe7fbaf5-4c47-43b6-be1b-2f6ca15e8bfa/2026-06-11/notes/bead-as-webdav-handler.md) §3 - Edge replicas it feeds: [git-and-beads.md](git-and-beads.md) §Bead CDN · [cache-sync-and-delta-bake.md](cache-sync-and-delta-bake.md)

## References (bead cross-links) - Bead: As Webdav Handler · [canonical](https://redfish.acequia.io/guerin/.agents/fe7fbaf5-4c47-43b6-be1b-2f6ca15e8bfa/)