Context
Clients need local storage for preferences, sessions, caches, the offline queue, secrets and files. An earlier plan proposed a separate@stackra/local-store package. The owner decided on 2026-10-20 night (“Client storage FINAL”) that one package covers all of it, with SQLite read models as one of its entries.
Decision
- One package.
@stackra/storageis the only client storage package. There is no@stackra/local-store. - Injected service. A
Storageservice is injected, with named stores:prefs,session,cache,outbox(the offline queue),secretsandfiles. - Drivers per platform. Web:
local,session,indexeddb,opfsandwebcrypto. Native:mmkv,sqlite,secure-storeandexpo-fs. Desktop:safe-storageandfs. - Behaviour. Optional encryption and a time-to-live per store. Values are typed with Zod.
- SQL entry. The Phase 2 SQLite read models are the
./sqlentry of@stackra/storage. - No ORM on clients. MikroORM and any other ORM never run on a client (ADR 0014 applies to the server).
- Sync engine. Still Deferred (ADR 0011), with the revival triggers of the plan.
Consequences
- One API covers every client store, so an agent learns one storage surface.
- Read models on a client are disposable and regenerated, never the source of truth.
Enforcement
planned — the validator rejects an ORM import in a client app; each driver has a contract test against theStorage interface.
Owner defaults recorded here
- Web offline encryption. The web offline store is encrypted with a non-extractable WebCrypto key: the page can use the key to encrypt and decrypt, but cannot read its raw bytes.
Supersedes and sources
Supersedes: none (replaces the earlier draft@stackra/local-store, which is not written). Restates: 0011, 0014.
Sources: owner decision “Client storage FINAL” (stackra-decisions-2026-10-19.md L957, 2026-10-20 night); plan stackra-notes/desktop-pwa-offline-plan.md sections 4 and 8.