Repository navigation
LocalSpace 3.0.1
A patch release that fixes data-loss and hang bugs in 3.0.0, hardens the encryption plugin, and speeds up IndexedDB transactions. Stored data formats are unchanged: 3.0.1 reads everything 3.0.0 and 2.x wrote, and the pinned 2.1.1 rollback bridge still reads what 3.0.1 writes (unless you opt into the new bindStorageKey option).
Upgrade notes
Most apps can upgrade without changes. Review these items first:
- Encrypted stores containing plaintext: reading a value that is not an encrypted payload through
encryptionPluginnow rejects withDESERIALIZATION_FAILED(details.reason: 'unencrypted-value') instead of returning it. If a store still holds values written before encryption was enabled, read them through an instance created withallowPlaintext: trueand rewrite them. - Encryption configuration:
ivLengthbelow 12 bytes and an AES-GCMtagLengthoutside 96, 104, 112, 120, or 128 bits now throwINVALID_CONFIG. key(index): indexes that are not safe integers (NaN,Infinity, fractions) now reject withINVALID_ARGUMENT. Negative or out-of-range integers still returnnull.TTLPluginOptions.cleanupBatchSizeis deprecated and has no effect.
Security
- Encrypted instances now reject stored values that are not encrypted payloads instead of returning them unchanged, so values injected by anyone with storage access are no longer accepted as authentic. Use
allowPlaintext: trueonly on a migration instance. encryptionPluginnow enforces an IV of at least 96 bits and an authentication tag of at least 96 bits.- Serialization failures no longer log the value to the console, which could expose plaintext that the encryption plugin was about to protect.
Added
bindStorageKeyencryption option (opt-in). Each ciphertext is authenticated against its database name, store name, and key as AES-GCM additional data, so a payload copied to another key or store fails to decrypt. Values written before enabling it stay readable until rewritten. Bound values cannot be read by 3.0.0 or the 2.1.x rollback bridge, and the option cannot be combined withalgorithm.additionalData.
Fixed
- localStorage / React Native store isolation: a default store no longer reads, counts, clears, or drops the keys of named stores that share its database name. Previously
clear()on{ name: 'app' }also deleted the data of{ name: 'app', storeName: 'users' }. Named stores now register underlocalspace:stores:<name>on their first write; existing key prefixes are unchanged. - localStorage removal:
clear()anddropInstance()could leave entries behind in Chromium, which reorders native keys after a removal. Keys are now snapshotted before removal. - localStorage iteration: removing entries during
iterate()(including TTL expiry) no longer skips live entries. With TTL, live entries that followed expired ones could be skipped entirely. - React Native iteration: keys removed during
iterate()are now skipped instead of being passed to the iterator asnull. - TTL concurrent writes: TTL removes an expired key only while it still holds the value that was read, so a fresh value written concurrently by the application, another tab, or the background sweep is no longer deleted. Drivers with native transactions perform the check and removal atomically; while a transaction is active on the same instance, removal is deferred to a later read or sweep.
- IndexedDB
key()hang:key(NaN),key(Infinity), and fractional indexes previously returned a promise that never settled. IndexedDBgetItem,keys,key, andlengthnow also reject when their transaction aborts. dropInstance(options)now validates and normalizes options when no plugins are registered, matching instances with plugins.- TTL cleanup timer is unref'd so it no longer keeps a Node.js process alive.
- Removed the stale console warning about using the lenient error policy with compression; compression failures already propagate under every policy.
Performance
- IndexedDB transactions: keep-alive requests now count a single probe key instead of the whole object store, so their cost no longer grows with store size. In the release benchmark, transactions went from 4.17x to 2.65x of the 2.1.0 baseline.
- TTL background sweep: performs one logical scan per interval instead of reading and decrypting every live entry twice.
Full Changelog: v3.0.0...v3.0.1