release(v4.3.0): browser persistence via @shade/storage-indexeddb

Ship an official IndexedDB-backed StorageProvider so browser-based Shade
consumers persist identity, prekeys, sessions, retired identities,
peer-verification state and stream-resume rows across tab refresh and
browser restart. Closes the gap that forced browser apps onto
storage:"memory" (regenerated identity each load, orphaned device
records server-side).

- New package @shade/storage-indexeddb (4.3.0): full StorageProvider
  conformance, schema v1, idb-backed; bumpPeerIdentityVersion is wrapped
  in a single readwrite IDB transaction (atomic, vs SQLite's
  read-then-upsert race).
- @shade/sdk resolveStorage() accepts { type: 'indexeddb', dbName? } via
  dynamic import (lazy, optional dep — same pattern as
  @shade/storage-postgres). Named StorageSpec type now reused by
  ResolvedConfig.
- Tests: 16 new tests in shade-storage-indexeddb (StorageProvider
  surface + peer-verifications + full E2EE conversation surviving a
  simulated tab reload). Run on fake-indexeddb.
- Lockstep version bump 4.2.1 → 4.3.0 across all 25 packages.
- Publish scripts updated to include the new package.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-05 17:35:02 +02:00
parent b77b7e771c
commit f5f42fe557
37 changed files with 1167 additions and 54 deletions

View File

@@ -17,7 +17,7 @@
},
"packages/shade-cli": {
"name": "@shade/cli",
"version": "0.4.0",
"version": "4.2.1",
"bin": {
"shade": "src/cli.ts",
},
@@ -36,7 +36,7 @@
},
"packages/shade-core": {
"name": "@shade/core",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/observability": "workspace:*",
},
@@ -49,7 +49,7 @@
},
"packages/shade-crypto-web": {
"name": "@shade/crypto-web",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@noble/curves": "^2.0.1",
"@noble/hashes": "^2.0.1",
@@ -59,7 +59,7 @@
},
"packages/shade-dashboard": {
"name": "@shade/dashboard",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/widgets": "workspace:*",
"react": "^19.0.0",
@@ -74,7 +74,7 @@
},
"packages/shade-files": {
"name": "@shade/files",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/crypto-web": "workspace:*",
@@ -101,7 +101,7 @@
},
"packages/shade-inbox": {
"name": "@shade/inbox",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/proto": "workspace:*",
@@ -114,7 +114,7 @@
},
"packages/shade-inbox-server": {
"name": "@shade/inbox-server",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/observability": "workspace:*",
@@ -132,7 +132,7 @@
},
"packages/shade-key-transparency": {
"name": "@shade/key-transparency",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@noble/hashes": "^2.0.1",
"@shade/core": "workspace:*",
@@ -144,11 +144,11 @@
},
"packages/shade-keychain": {
"name": "@shade/keychain",
"version": "0.4.0",
"version": "4.2.1",
},
"packages/shade-observability": {
"name": "@shade/observability",
"version": "0.1.0",
"version": "4.2.1",
"dependencies": {
"@noble/hashes": "^2.0.1",
},
@@ -166,7 +166,7 @@
},
"packages/shade-observer": {
"name": "@shade/observer",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/server": "workspace:*",
@@ -178,14 +178,14 @@
},
"packages/shade-proto": {
"name": "@shade/proto",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
},
},
"packages/shade-recovery": {
"name": "@shade/recovery",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/crypto-web": "workspace:*",
@@ -198,7 +198,7 @@
},
"packages/shade-sdk": {
"name": "@shade/sdk",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/crypto-web": "workspace:*",
@@ -225,7 +225,7 @@
},
"packages/shade-server": {
"name": "@shade/server",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/inbox-server": "workspace:*",
@@ -245,7 +245,7 @@
},
"packages/shade-storage-encrypted": {
"name": "@shade/storage-encrypted",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@noble/hashes": "^2.0.1",
"@shade/core": "workspace:*",
@@ -261,9 +261,21 @@
"@shade/keychain",
],
},
"packages/shade-storage-indexeddb": {
"name": "@shade/storage-indexeddb",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"idb": "^8.0.3",
},
"devDependencies": {
"@shade/crypto-web": "workspace:*",
"fake-indexeddb": "^6.0.0",
},
},
"packages/shade-storage-postgres": {
"name": "@shade/storage-postgres",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/inbox-server": "workspace:*",
@@ -278,7 +290,7 @@
},
"packages/shade-storage-sqlite": {
"name": "@shade/storage-sqlite",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/crypto-web": "workspace:*",
@@ -288,7 +300,7 @@
},
"packages/shade-streams": {
"name": "@shade/streams",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@noble/hashes": "^2.0.1",
"@shade/core": "workspace:*",
@@ -300,7 +312,7 @@
},
"packages/shade-transfer": {
"name": "@shade/transfer",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/crypto-web": "workspace:*",
@@ -317,7 +329,7 @@
},
"packages/shade-transport": {
"name": "@shade/transport",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/crypto-web": "workspace:*",
@@ -328,7 +340,7 @@
},
"packages/shade-transport-bridge": {
"name": "@shade/transport-bridge",
"version": "0.1.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/server": "workspace:*",
@@ -350,7 +362,7 @@
},
"packages/shade-transport-webrtc": {
"name": "@shade/transport-webrtc",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/core": "workspace:*",
"@shade/streams": "workspace:*",
@@ -359,7 +371,7 @@
},
"packages/shade-widgets": {
"name": "@shade/widgets",
"version": "0.4.0",
"version": "4.2.1",
"dependencies": {
"@shade/recovery": "workspace:*",
"@shade/sdk": "workspace:*",
@@ -568,6 +580,8 @@
"@shade/storage-encrypted": ["@shade/storage-encrypted@workspace:packages/shade-storage-encrypted"],
"@shade/storage-indexeddb": ["@shade/storage-indexeddb@workspace:packages/shade-storage-indexeddb"],
"@shade/storage-postgres": ["@shade/storage-postgres@workspace:packages/shade-storage-postgres"],
"@shade/storage-sqlite": ["@shade/storage-sqlite@workspace:packages/shade-storage-sqlite"],
@@ -626,6 +640,8 @@
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
"fake-indexeddb": ["fake-indexeddb@6.2.5", "", {}, "sha512-CGnyrvbhPlWYMngksqrSSUT1BAVP49dZocrHuK0SvtR0D5TMs5wP0o3j7jexDJW01KSadjBp1M/71o/KR3nD1w=="],
"fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
@@ -638,6 +654,8 @@
"hono": ["hono@4.12.12", "", {}, "sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q=="],
"idb": ["idb@8.0.3", "", {}, "sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],