Distribution
Web is canonical. PWA, Tauri and Electron are the same contract with capabilities added.
Capabilities by target
Produced by building each adapter and asking it — not a written-down claim.
| Target | Secure storage | Native notifications | File system | Updater | Deep-link scheme | Auth transport |
|---|---|---|---|---|---|---|
| Web | no | no | no | no | — | same-origin-redirect |
| PWA | no | no | no | no | — | same-origin-redirect |
| Tauri (packaged) | yes | yes | yes | yes | ottili-coder | system-browser-deeplink |
| Tauri (no host bridge) | no | no | no | no | ottili-coder | system-browser-deeplink |
| Electron (packaged) | yes | yes | yes | yes | ottili-coder | system-browser-deeplink |
Why the two Tauri rows differ
The same bundle is served to a packaged app and to a browser tab.
- Foundation is a browser bundle and must not carry a desktop SDK, so both desktop adapters talk to whatever the host injected as
window.ottiliDesktop. - With no bridge, every native capability reports unsupported and every native call refuses with a reason — rather than throwing an undefined-property error on first use.
secureStorageis the one that matters most. On web it reports unavailable and refuses to write, instead of falling back tolocalStorageand quietly turning an OS-keychain guarantee into a value any script on the page can read.- Desktop detection runs before PWA detection: a Tauri window also reports
display-mode: standalone, and mistaking it for an installed PWA would leave it with no keychain, no updater and no deep links.
Offline cache policy
SoT §29.6. Caching company data on a device is a decision a product makes deliberately.
| Route | Cached |
|---|---|
/ | yes |
/signin | yes |
/assets/app.css | yes |
/c/acme/dashboard | no |
/c/acme/settings/branding | no |
/api/v1/foundation/bootstrap | no |
A /c/ route carries tenant data by construction, so it never qualifies as safe metadata — only an explicit approved-cache reaches it. An /api/path is refused under every policy: a cached API response is an authorization decision frozen at fetch time, and §12 makes the server the only authority on those.
The Lab is itself a PWA
Both artefacts below are generated from one PwaProductConfig, so they cannot disagree.
This browser, right now
Not what an adapter would answer — what actually happened when the Lab registered its worker.
| Service worker | pending Registering… |
|---|---|
| Offline policy | safe-metadata |
| Installability | unsupported This browser does not offer installation |
| Manifest | /manifest.webmanifest · /sw.js |