selfstore 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/advanced.d.ts +7 -7
- package/dist/advanced.js +1 -1
- package/dist/backups.d.ts +2 -2
- package/dist/{cache-De5_sALA.d.ts → cache-ilsK3Tki.d.ts} +11 -0
- package/dist/{chunk-XI3MGK4M.js → chunk-FL66ACWR.js} +36 -2
- package/dist/chunk-FL66ACWR.js.map +1 -0
- package/dist/{chunk-3XR3GLR2.js → chunk-I243KZMZ.js} +2 -2
- package/dist/chunk-I243KZMZ.js.map +1 -0
- package/dist/{drive-DNiDXBDe.d.ts → drive-BhiTdk-Q.d.ts} +2 -2
- package/dist/flows-BBMVdP1S.d.ts +325 -0
- package/dist/flows.d.ts +5 -325
- package/dist/flows.js +1 -1
- package/dist/flows.js.map +1 -1
- package/dist/groups.d.ts +2 -2
- package/dist/households.d.ts +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/{local-DsXG7QW7.d.ts → local-6OALceUy.d.ts} +2 -2
- package/dist/{store-2RnED1Vq.d.ts → store-C20_6JBo.d.ts} +1 -1
- package/dist/widgets.d.ts +106 -20
- package/dist/widgets.js +299 -2
- package/dist/widgets.js.map +1 -1
- package/llms.txt +8 -3
- package/package.json +2 -1
- package/dist/chunk-3XR3GLR2.js.map +0 -1
- package/dist/chunk-XI3MGK4M.js.map +0 -1
package/README.md
CHANGED
|
@@ -134,7 +134,7 @@ too, as subpaths of the same install:
|
|
|
134
134
|
|---|---|---|
|
|
135
135
|
| `selfstore` | the simple store + backup files | almost always: start here |
|
|
136
136
|
| `selfstore/flows` | the user journeys (connect a destination, share panel, join an invitation) as headless, tested state machines | you are building the connect/share/join UI and want the ordering and failure rules - one popup per gesture, password proven before attach, merge by default - already right |
|
|
137
|
-
| `selfstore/widgets` | the same journeys as drop-in web components (`<selfstore-connect>`, `<selfstore-share>`, `<selfstore-join>`) - framework-free, themable via CSS custom properties and `::part()`, reworded/localized via a `labels` map | you want the screens ready-made and your app's look on top |
|
|
137
|
+
| `selfstore/widgets` | the same journeys as drop-in web components (`<selfstore-connect>`, `<selfstore-gate>`, `<selfstore-share>`, `<selfstore-join>`) - framework-free, themable via CSS custom properties and `::part()`, reworded/localized via a `labels` map | you want the screens ready-made and your app's look on top |
|
|
138
138
|
| `selfstore/advanced` | the pull-model store (`createLocalStore`), custom `BackupTarget`s, caches, headless status derivation, functional codec | your state lives in its own reactive model (Svelte runes, Redux), or you are writing a destination (S3, your KV...) |
|
|
139
139
|
| `selfstore/groups` | passwordless group encryption: per-member identities, sealed envelopes, signed membership manifests | several PEOPLE share one encrypted store without a shared password ([PEERS.md](./PEERS.md)) |
|
|
140
140
|
| `selfstore/sync` | the bare merge engine (HLC + per-collection strategies, no CRDT runtime) | you only want the algorithm inside your own persistence ([SYNC docs in SPEC.md](./SPEC.md)) |
|
|
@@ -306,6 +306,12 @@ const persistence = {
|
|
|
306
306
|
full-profile copy cannot read it. One unlock per session - `cacheLock` on the
|
|
307
307
|
simple facade, or `indexedDbCache(name, { lock: true })` at the store layer.
|
|
308
308
|
Still bounded by the origin (unlocked, code in the page decrypts).
|
|
309
|
+
A forgotten secret is unrecoverable by design, so give your users a way
|
|
310
|
+
out rather than a dead-end prompt: `indexedDbCache(name, { lock: true })
|
|
311
|
+
.clear()` needs no key and abandons the sealed cache, after which they can
|
|
312
|
+
start again from a backup file or from scratch. Throwing from the
|
|
313
|
+
`cacheLock` callback aborts the boot and hands control back to you, which
|
|
314
|
+
is where that offer belongs.
|
|
309
315
|
- Opt-in hardening for sensitive deployments: `requireEncryption` refuses to
|
|
310
316
|
write or export a plaintext backup, and `passwordPolicy` refuses a password
|
|
311
317
|
weaker than a length / character-class rule - both enforced at the store, so
|
package/dist/advanced.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { B as BackupTarget } from './store-
|
|
2
|
-
export { A as AuthExpiredError, a as BuiltinTargetKind, E as EncodeOptions, H as Header, K as KdfParams, L as LocalStore, b as LocalStoreOptions, c as LocalStoreState, M as MirrorState, d as Mode, P as PasswordCheck, e as PasswordPolicy, f as PasswordRequirement, g as PeerSource, h as PeerState, R as RESERVED_COLLECTION_PREFIX, i as RESERVED_STORE_MODES, j as RecipientStanza, k as ReplicaState, S as SelfstoreError, l as SelfstoreErrorCode, m as Severity, n as Snapshot, o as SnapshotFile, p as StatusAction, q as StatusDescriptor, r as StatusInput, s as StorageState, t as StoreError, u as StoreGroupConfig, v as SyncJournalEntry, w as SyncSource, T as TargetKind, x as checkPasswordPolicy, y as createLocalStore, z as deriveStatus, C as errorLabelKey, D as isAuthExpired, F as isReservedStoreMode, G as isSelfstoreError } from './store-
|
|
3
|
-
import { K as KV } from './cache-
|
|
4
|
-
export { C as CachedFile, L as LocalCache, e as LockableCache, i as indexedDbCache, f as isLockableCache, m as memoryCache } from './cache-
|
|
5
|
-
export { e as exportSnapshot, g as gisDriveAuth, i as importSnapshot, a as inspect, b as isEncrypted, p as pickFromDisk, s as saveToDisk } from './local-
|
|
6
|
-
import { c as connect$1, f as fromSession$1, p as preview, a as adopt, b as findOrCreateOwnFile, l as listBackups, d as createBackup, e as deleteBackup, r as renameBackup, g as connect$2, h as fromSession$2, i as connect$3, j as fromSession$3, k as peer } from './drive-
|
|
7
|
-
export { D as DriveAuth, m as DriveBackupInfo, n as DriveOptions, S as S3Config, o as S3ConnectOptions, W as WebdavConfig, q as WebdavConnectOptions, s as WebdavPeerOptions } from './drive-
|
|
1
|
+
import { B as BackupTarget } from './store-C20_6JBo.js';
|
|
2
|
+
export { A as AuthExpiredError, a as BuiltinTargetKind, E as EncodeOptions, H as Header, K as KdfParams, L as LocalStore, b as LocalStoreOptions, c as LocalStoreState, M as MirrorState, d as Mode, P as PasswordCheck, e as PasswordPolicy, f as PasswordRequirement, g as PeerSource, h as PeerState, R as RESERVED_COLLECTION_PREFIX, i as RESERVED_STORE_MODES, j as RecipientStanza, k as ReplicaState, S as SelfstoreError, l as SelfstoreErrorCode, m as Severity, n as Snapshot, o as SnapshotFile, p as StatusAction, q as StatusDescriptor, r as StatusInput, s as StorageState, t as StoreError, u as StoreGroupConfig, v as SyncJournalEntry, w as SyncSource, T as TargetKind, x as checkPasswordPolicy, y as createLocalStore, z as deriveStatus, C as errorLabelKey, D as isAuthExpired, F as isReservedStoreMode, G as isSelfstoreError } from './store-C20_6JBo.js';
|
|
3
|
+
import { K as KV } from './cache-ilsK3Tki.js';
|
|
4
|
+
export { C as CachedFile, L as LocalCache, e as LockableCache, i as indexedDbCache, f as isLockableCache, m as memoryCache } from './cache-ilsK3Tki.js';
|
|
5
|
+
export { e as exportSnapshot, g as gisDriveAuth, i as importSnapshot, a as inspect, b as isEncrypted, p as pickFromDisk, s as saveToDisk } from './local-6OALceUy.js';
|
|
6
|
+
import { c as connect$1, f as fromSession$1, p as preview, a as adopt, b as findOrCreateOwnFile, l as listBackups, d as createBackup, e as deleteBackup, r as renameBackup, g as connect$2, h as fromSession$2, i as connect$3, j as fromSession$3, k as peer } from './drive-BhiTdk-Q.js';
|
|
7
|
+
export { D as DriveAuth, m as DriveBackupInfo, n as DriveOptions, S as S3Config, o as S3ConnectOptions, W as WebdavConfig, q as WebdavConnectOptions, s as WebdavPeerOptions } from './drive-BhiTdk-Q.js';
|
|
8
8
|
import './sync.js';
|
|
9
9
|
|
|
10
10
|
/**
|
package/dist/advanced.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { RESERVED_STORE_MODES, createLocalStore, deriveStatus, gisDriveAuth, indexedDbCache, isLockableCache, isReservedStoreMode, memoryCache } from './chunk-
|
|
1
|
+
export { RESERVED_STORE_MODES, createLocalStore, deriveStatus, gisDriveAuth, indexedDbCache, isLockableCache, isReservedStoreMode, memoryCache } from './chunk-FL66ACWR.js';
|
|
2
2
|
export { pickFromDisk, saveToDisk } from './chunk-UWVAKBU4.js';
|
|
3
3
|
import './chunk-SKWHKM25.js';
|
|
4
4
|
import { FILE_ID_KEY, renameBackup, deleteBackup, createBackup, listBackups, findOrCreateOwnFile, adopt, preview, fromSession, connect, isSupported, fromSession2, connect2, fromSession4, connect4, peer, fromSession3, connect3 } from './chunk-TEIAFKFS.js';
|
package/dist/backups.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { K as KV } from './cache-
|
|
2
|
-
import { B as BackupTarget, L as LocalStore } from './store-
|
|
1
|
+
import { K as KV } from './cache-ilsK3Tki.js';
|
|
2
|
+
import { B as BackupTarget, L as LocalStore } from './store-C20_6JBo.js';
|
|
3
3
|
import { F as FlowStore } from './machine-ALMkT3mk.js';
|
|
4
4
|
import './sync.js';
|
|
5
5
|
|
|
@@ -107,6 +107,17 @@ interface LockableCache extends LocalCache {
|
|
|
107
107
|
* does not open existing data - the cache stays locked. The first secret on
|
|
108
108
|
* an empty cache sets the lock. */
|
|
109
109
|
unlock(secret: string | CryptoKey): Promise<boolean>;
|
|
110
|
+
/**
|
|
111
|
+
* Change the secret that seals this cache, in place: re-derive the key (a
|
|
112
|
+
* fresh salt for a password) and rewrite every sealed record under it.
|
|
113
|
+
*
|
|
114
|
+
* Without this, "change my password" has no honest implementation for a
|
|
115
|
+
* locked cache - the app has to wipe and rebuild, which also throws away
|
|
116
|
+
* the durable destination's session, and a half-finished wipe leaves data
|
|
117
|
+
* no key can open. Requires the cache to be unlocked: what cannot be read
|
|
118
|
+
* cannot be re-sealed.
|
|
119
|
+
*/
|
|
120
|
+
reseal(secret: string | CryptoKey): Promise<void>;
|
|
110
121
|
/** Drop the in-memory key: reads and writes lock until unlock() is called. */
|
|
111
122
|
lockNow(): void;
|
|
112
123
|
/** Whether no seal key is currently held. */
|
|
@@ -1886,6 +1886,40 @@ function indexedDbCache(name, opts) {
|
|
|
1886
1886
|
lockNow() {
|
|
1887
1887
|
sealKey = null;
|
|
1888
1888
|
},
|
|
1889
|
+
async reseal(secret) {
|
|
1890
|
+
const { keyFromPassword, freshCacheKdf } = await import('./cache-lock-NXIR6JRB.js');
|
|
1891
|
+
const previous = sealKey;
|
|
1892
|
+
if (previous === null) {
|
|
1893
|
+
throw new SelfstoreError(
|
|
1894
|
+
"PASSWORD_REQUIRED",
|
|
1895
|
+
"reseal(): the local cache is locked - unlock() it first."
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
const d = await db();
|
|
1899
|
+
const kdf = typeof secret === "string" ? freshCacheKdf() : null;
|
|
1900
|
+
const next = kdf ? await keyFromPassword(secret, kdf) : secret;
|
|
1901
|
+
const rawCollections = await d.get("kv", COLLECTIONS_KEY);
|
|
1902
|
+
const collections = isEnvelope(rawCollections) ? await seal(next, await unseal(previous, rawCollections)) : null;
|
|
1903
|
+
const files = [];
|
|
1904
|
+
for (const fileKey of await d.getAllKeys("files")) {
|
|
1905
|
+
const v = await d.get("files", fileKey);
|
|
1906
|
+
if (!v) continue;
|
|
1907
|
+
const bytes = await unseal(previous, v);
|
|
1908
|
+
files.push({
|
|
1909
|
+
id: fileKey,
|
|
1910
|
+
rec: { name: v.name, mime: v.mime, ...await seal(next, bytes) }
|
|
1911
|
+
});
|
|
1912
|
+
}
|
|
1913
|
+
const tx = d.transaction(["kv", "files"], "readwrite");
|
|
1914
|
+
const store = tx.objectStore("kv");
|
|
1915
|
+
if (kdf) store.put(kdf, CACHE_KDF);
|
|
1916
|
+
else store.delete(CACHE_KDF);
|
|
1917
|
+
if (collections) store.put(collections, COLLECTIONS_KEY);
|
|
1918
|
+
const fileStore = tx.objectStore("files");
|
|
1919
|
+
for (const { id, rec } of files) fileStore.put(rec, id);
|
|
1920
|
+
await tx.done;
|
|
1921
|
+
sealKey = next;
|
|
1922
|
+
},
|
|
1889
1923
|
async unlock(secret) {
|
|
1890
1924
|
const { keyFromPassword, freshCacheKdf, opens } = await import('./cache-lock-NXIR6JRB.js');
|
|
1891
1925
|
const d = await db();
|
|
@@ -1994,5 +2028,5 @@ function gisDriveAuth(opts) {
|
|
|
1994
2028
|
}
|
|
1995
2029
|
|
|
1996
2030
|
export { RESERVED_STORE_MODES, createLocalStore, deriveStatus, gisDriveAuth, indexedDbCache, isLockableCache, isReservedStoreMode, memoryCache };
|
|
1997
|
-
//# sourceMappingURL=chunk-
|
|
1998
|
-
//# sourceMappingURL=chunk-
|
|
2031
|
+
//# sourceMappingURL=chunk-FL66ACWR.js.map
|
|
2032
|
+
//# sourceMappingURL=chunk-FL66ACWR.js.map
|