memorio 5.0.0 โ†’ 5.1.1

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.
Files changed (60) hide show
  1. package/README.md +98 -435
  2. package/SECURITY.md +152 -42
  3. package/SUMMARY.md +1 -1
  4. package/adr/001-state-proxy-model.md +95 -96
  5. package/adr/002-observer-semantics.md +179 -180
  6. package/adr/003-deep-mutation-semantics.md +7 -8
  7. package/adr/004-array-mutation-semantics.md +127 -128
  8. package/adr/005-scheduler-contract.md +148 -149
  9. package/adr/006-context-isolation.md +91 -92
  10. package/adr/007-mutation-records.md +5 -6
  11. package/adr/008-transactions.md +6 -7
  12. package/adr/009-history-model.md +6 -7
  13. package/adr/README.md +46 -46
  14. package/adr/template.md +48 -49
  15. package/bin/cli.js +68 -0
  16. package/global.cjs +1462 -323
  17. package/global.js +1459 -324
  18. package/index.cjs +1462 -323
  19. package/index.d.ts +1 -0
  20. package/index.js +1459 -324
  21. package/llms.txt +42 -5
  22. package/markdown/AUDIT-REPORT.md +7 -8
  23. package/markdown/CACHE.md +190 -99
  24. package/markdown/DEVTOOLS.md +0 -1
  25. package/markdown/DISPATCH.md +0 -1
  26. package/markdown/HISTORY.md +0 -1
  27. package/markdown/IDB.md +0 -1
  28. package/markdown/IMPORT.md +0 -1
  29. package/markdown/INSPECT.md +0 -1
  30. package/markdown/LOGGER.md +0 -1
  31. package/markdown/MEMORY-ATTACHMENT.md +0 -1
  32. package/markdown/MEMORY.md +0 -1
  33. package/markdown/OBSERVER.md +0 -1
  34. package/markdown/PLATFORM.md +277 -271
  35. package/markdown/REDUX.md +54 -0
  36. package/markdown/SCHEMA.md +0 -1
  37. package/markdown/SESSION.md +0 -1
  38. package/markdown/SQLITE.md +0 -1
  39. package/markdown/STATE.md +0 -1
  40. package/markdown/STORE.md +0 -1
  41. package/markdown/SYNC.md +0 -1
  42. package/markdown/TYPED.md +0 -1
  43. package/markdown/USEOBSERVER.md +0 -1
  44. package/modules/redux.cjs +381 -10
  45. package/modules/redux.cjs.map +1 -1
  46. package/modules/redux.js +381 -10
  47. package/modules/redux.js.map +1 -1
  48. package/package.json +14 -2
  49. package/types/broadcast.d.ts +61 -0
  50. package/types/computed.d.ts +96 -0
  51. package/types/encryption.d.ts +129 -0
  52. package/types/exports.d.ts +9 -0
  53. package/types/memorio.d.ts +19 -12
  54. package/types/security.d.ts +67 -0
  55. package/types/session.d.ts +23 -5
  56. package/types/store.d.ts +19 -3
  57. package/vsix/memorio.vsix +0 -0
  58. package/markdown/CHANGELOG.md +0 -243
  59. package/markdown/PROJECT.md +0 -311
  60. package/markdown/SECURITY.md +0 -330
package/README.md CHANGED
@@ -1,8 +1,26 @@
1
1
  # ๐Ÿง  memorio
2
2
 
3
- **Application state intelligence runtime.**
3
+ ![banner](https://raw.githubusercontent.com/passariello/container/refs/heads/main/memorio/banner.svg)
4
4
 
5
- Use it like an object.
5
+ [![npm version](https://img.shields.io/npm/v/memorio)](https://www.npmjs.com/package/memorio)
6
+ [![license](https://img.shields.io/npm/l/memorio)](./LICENSE)
7
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/memorio)](https://bundlephobia.com/package/memorio)
8
+ [![Socket Badge](https://socket.dev/api/badge/npm/package/memorio)](https://socket.dev/npm/package/memorio)
9
+ [![Known Vulnerabilities](https://snyk.io/test/npm/memorio/badge.svg)](https://snyk.io/test/npm/memorio)
10
+ [![zero deps](https://img.shields.io/badge/dependencies-0-brightgreen)](#security)
11
+ ![Browser](https://img.shields.io/badge/Browser-Chrome%20/%20Firefox%20/%20Safari-gray?logo=google-chrome)
12
+ ![Deno](https://img.shields.io/badge/Deno-compatible-gray?logo=deno)
13
+ ![Edge Workers](https://img.shields.io/badge/Edge%20Workers-compatible-gray)
14
+ ![TypeScript](https://img.shields.io/badge/TypeScript-native-gray?logo=typescript)
15
+ ![React](https://img.shields.io/badge/React-compatible-gray?logo=react)
16
+ ![Tests](https://img.shields.io/badge/tests-500+%20passed-green)
17
+ [![license](https://img.shields.io/npm/l/memorio.svg)](#license)
18
+
19
+ <!--
20
+ [![CI](https://img.shields.io/github/actions/workflow/status/GITHUB_ORG/GITHUB_REPO/ci.yml?branch=main)](https://github.com/GITHUB_ORG/GITHUB_REPO/actions)
21
+ -->
22
+
23
+ **The memory layer for AI agents and apps โ€” owned by the user, not the vendor.**
6
24
 
7
25
  ```ts
8
26
  import 'memorio/global'
@@ -19,18 +37,20 @@ Just data, available where your application needs it.
19
37
 
20
38
  ---
21
39
 
22
- ## Why memorio?
23
-
24
- Most applications eventually need more than one kind of data: reactive state, persistent values, session data, caches, structured browser storage, local SQL, application memory, history, and optional sync.
40
+ ## Why memorio
25
41
 
26
- Usually that means a different library - and a different mental model - for each.
42
+ That's the whole API for the simple case. No provider tree, no boilerplate.
27
43
 
28
- **Memorio gives them one consistent runtime, without making the simple case complicated.**
44
+ But real apps grow. Most AI-powered apps (and most apps in general) eventually need more than "just state" โ€” persistence, session data, caches, structured browser storage, local SQL, application memory, history, optional sync. Usually that means pulling in a different library โ€” and a different mental model โ€” for each. Memorio gives them one consistent runtime, without making the simple case complicated:
29
45
 
30
46
  ```ts
31
47
  state.value = 42
32
48
  ```
33
49
 
50
+ But the reason memorio exists isn't just "fewer dependencies." It's this: **the memory an AI agent builds about a user shouldn't be locked inside a vendor's server, opaque, and impossible to inspect or move.** Memorio's memory layer is structured, inspectable, editable, and โ€” when you turn on encryption โ€” readable only with a key the vendor doesn't hold. It runs client-side, in the browser, on the edge, or in Node.
51
+
52
+ That said, this covers *structured* memory - preferences, decisions, facts with confidence and provenance - not semantic similarity search. If your agent needs "find things like this conversation," pair memorio with a dedicated vector store; see [`markdown/MEMORY.md`](./markdown/MEMORY.md).
53
+
34
54
  Add persistence, memory, history, or sync only when your application actually needs them. The common case stays tiny; the runtime grows with you.
35
55
 
36
56
  ---
@@ -45,428 +65,113 @@ Zero production dependencies in core. Optional integrations (`react`, `sql.js`,
45
65
 
46
66
  ---
47
67
 
48
- ## Global or explicit
49
-
50
- ```ts
51
- // Opt-in global access
52
- import 'memorio/global'
53
- state.user = { name: 'Sara' }
54
-
55
- // Or explicit imports
56
- import { state, store, memory } from 'memorio'
57
- ```
58
-
59
- Memorio never puts APIs on `globalThis` automatically and never infers dev mode from `NODE_ENV` or your bundler - global access is always something you choose.
60
-
61
- ---
62
-
63
- ## The layers
64
-
65
- | Layer | Purpose | Persistence | Reactive |
66
- | --------- | --------------------------------- | :---------: | :------: |
67
- | `state` | application state | No | Yes |
68
- | `cache` | transient runtime data | No | No |
69
- | `session` | tab/session data | Yes | No |
70
- | `store` | persistent key/value data | Yes | No |
71
- | `idb` | durable structured browser data | Yes | No |
72
- | `sqlite` | relational local SQL | Optional | No |
73
- | `memory` | structured application memory | Yes | Optional |
74
- | `journal` | local-first operation history | Yes | No |
75
-
76
- You don't have to use all of them - start with `state`.
77
-
78
- **Which one do I need?**
79
-
80
- ```text
81
- Does the UI need to react automatically to changes?
82
- yes โ†’ state
83
- no โ†’ cache (runtime only) ยท session (this tab) ยท store (small persistent kv)
84
- idb (structured browser data) ยท sqlite (relations/SQL) ยท memory (what the app should remember)
85
- ```
86
-
87
- ---
88
-
89
- ## Before / after
68
+ ## Start here
90
69
 
91
- ```ts
92
- // Without memorio
93
- const [user, setUser] = useState(null)
94
- useEffect(() => {
95
- const saved = localStorage.getItem('user')
96
- if (saved) setUser(JSON.parse(saved))
97
- }, [])
98
- useEffect(() => {
99
- localStorage.setItem('user', JSON.stringify(user))
100
- }, [user])
101
-
102
- // With memorio
103
- import { state, persist } from 'memorio'
104
- state.user = { name: 'Sara' }
105
- const off = persist('state.user') // restores + keeps in sync
106
- ```
107
-
108
- ---
109
-
110
- ## Persistent state
70
+ Three things cover most apps - reactive state, persistence, and observation:
111
71
 
112
72
  ```ts
113
- import { state, persist } from 'memorio'
73
+ import { state, persist, observer } from 'memorio'
114
74
 
115
75
  state.user = { name: 'Sara' }
116
- const off = persist('state.user')
117
76
 
118
- // later
119
- off()
120
- ```
77
+ persist('state.user')
121
78
 
122
- Nested paths work when the intermediate objects already exist: `persist('state.user.preferences.theme')`.
123
- Without `localStorage` (e.g. Node), `store` falls back to memory.
124
-
125
- ---
126
-
127
- ## Observing changes
128
-
129
- ```ts
130
- import { observer } from 'memorio'
131
-
132
- const off = observer('state.user', (next, previous) => {
133
- console.log('user changed:', next, previous)
79
+ observer('state.user', user => {
80
+ console.log(user)
134
81
  })
135
-
136
- off() // unsubscribe
137
82
  ```
138
83
 
139
- Prefer the returned `off()` for targeted teardown (it unsubscribes only *this* callback).
140
- The alternatives remove listeners by path name:
84
+ And this is what makes memorio a *memory* layer, not just a state manager - structured, inspectable facts about a user or agent, not just ephemeral UI state:
141
85
 
142
86
  ```ts
143
- observer.remove('state.user') // removes ALL callbacks for this path
144
- observer.removeAll() // removes every observer at once
145
- ```
146
-
147
- ---
148
-
149
- ## Application memory
150
-
151
- State stores what the application **has**. Memory stores what it **remembers**.
87
+ import { memory } from 'memorio'
152
88
 
153
- ```ts
154
- import { memorio } from 'memorio'
155
-
156
- await memorio.memory.remember('user.language', 'Italian', {
89
+ await memory.remember('user.language', 'Italian', {
157
90
  type: 'preference',
158
91
  confidence: 0.92,
159
- scope: 'local',
160
- tags: ['user', 'ui'],
161
92
  source: 'conversation'
162
93
  })
163
94
 
164
- const language = await memorio.memory.recall('user.language')
165
- ```
166
-
167
- Updating an entry doesn't overwrite it - the previous entry becomes `superseded`, the new one `active`:
168
-
169
- ```ts
170
- await memorio.memory.update('user.language', 'English', { confidence: 0.95 })
171
- ```
172
-
173
- Retrieve relevant memory instead of loading everything:
174
-
175
- ```ts
176
- const context = await memorio.memory.context({
177
- tags: 'user',
178
- types: ['preference', 'decision'],
179
- minConfidence: 0.7,
180
- maxEntries: 10
181
- })
182
- ```
183
-
184
- > **Note:** "structured memory" here means metadata-based ranking (tags, type, confidence, recency) - not embedding similarity search. Pair `memorio.memory` with a dedicated vector store if you need that.
185
-
186
- ```text
187
- sqlite โ†’ what data do I have?
188
- memory โ†’ what does my application remember?
189
- ```
190
-
191
- ---
192
-
193
- ## The other layers, briefly
194
-
195
- **`store`** - persistent key/value, backed by `localStorage` in browsers, memory elsewhere.
196
- ```ts
197
- store.set('preferences', { theme: 'dark' })
198
- const preferences = store.get('preferences')
199
- ```
200
-
201
- **`session`** - scoped to the current browser session (`sessionStorage`). Good for wizard steps and tab-local state.
202
-
203
- **`cache`** - volatile, in-memory, disappears when the runtime disappears.
204
-
205
- **`idb`** - durable structured browser data:
206
- ```ts
207
- await idb.db.create('app')
208
- await idb.table.create('app', 'users')
209
- await idb.data.set('app', 'users', { id: 1, name: 'Sara' })
210
- ```
211
-
212
- **`sqlite`** - relational local SQL, in-memory by default via `sql.js`:
213
- ```ts
214
- await sqlite.ready
215
- await sqlite.db.create('app', { persistence: true })
216
- await sqlite.query.run('app', `CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, role TEXT)`)
217
- await sqlite.query.select('app', `SELECT * FROM users WHERE role = ?`, ['admin'])
218
- ```
219
- > โš ๏ธ Persistence serializes the **entire database** on flush - fine for small/medium datasets, but large ones need deliberate batching.
220
-
221
- Check what's actually available at runtime before depending on a backend: `memorio.getCapabilities()`.
222
-
223
- ---
224
-
225
- ## State Intelligence
226
-
227
- With history tracking enabled, mutations are recorded with a unique ID, HLC timestamp, source, and causal context - the foundation for undo/redo, diff, trace, and (planned) replay.
228
-
229
- ```ts
230
- import { memorio } from 'memorio'
231
-
232
- memorio.enableHistory(true)
233
-
234
- state.user = { name: 'John' }
235
- state.user.name = 'Maria'
236
- state.user.name = 'Pedro'
237
-
238
- const history = memorio.trace()
239
- memorio.undo()
240
- memorio.redo()
241
-
242
- memorio.canUndo()
243
- memorio.canRedo()
244
- ```
245
-
246
- **Explicit mutations & transactions:**
247
-
248
- ```ts
249
- const mutation = memorio.mutate('state.user.role', 'admin', { source: 'permissions.enableAdmin' })
250
- // mutation.id ยท mutation.hlc ยท mutation.source
251
-
252
- const tx = memorio.transaction('user.migration', 'Migrate to v2 schema')
253
- state.user.role = 'admin'
254
- state.user.permissions = ['read', 'write']
255
- memorio.commitTransaction()
256
-
257
- // or abort and roll back
258
- memorio.transaction('failed-op')
259
- state.user.name = 'Maria'
260
- memorio.abortTransaction()
261
- ```
262
-
263
- **Roadmap:**
264
-
265
- | Phase | Capability | Status |
266
- | ----- | ---------------------------- | --------------------------------------------------- |
267
- | 1 | Mutation Engine | โœ… Active |
268
- | 2 | Undo / Redo / Diff / Revert | โœ… Partial (basic trace + undo/redo shipped above) |
269
- | 3 | History Engine (persisted, queryable history) | Planned |
270
- | 4 | Replay / Time Machine | Planned |
271
- | 5 | Causal Graph | Planned |
272
- | 6 | Explain / Trace / Impact | Planned |
273
- | 7 | What-if Simulation | Planned |
274
-
275
- ---
276
-
277
- ## Typed state & validation
278
-
279
- ```ts
280
- import { memorio } from 'memorio'
281
-
282
- interface AppState {
283
- user: { name: string; age: number; email: string }
284
- theme: 'light' | 'dark'
285
- }
286
-
287
- const app = memorio.typed<AppState>()
288
- app.theme = 'dark' // โœ…
289
- app.theme = 'purple' // โŒ TypeScript error
290
-
291
- app === state // same proxy, typed
292
- ```
293
-
294
- Runtime schemas validate values crossing trust boundaries:
295
-
296
- ```ts
297
- memorio.registerSchema('user', {
298
- type: 'object',
299
- required: ['name', 'email'],
300
- properties: {
301
- name: { type: 'string', min: 1 },
302
- email: { type: 'string', pattern: /^[^@]+@[^@]+$/ }
303
- }
304
- })
305
-
306
- memorio.registerSchema('tags', { type: 'array', items: { type: 'string' } })
307
-
308
- state.tags = ['a', 'b'] // accepted
309
- state.tags = [1, 2, 3] // rejected
95
+ const language = await memory.recall('user.language')
96
+ // { value: 'Italian', confidence: 0.92, source: 'conversation', ... }
310
97
  ```
311
98
 
312
- ---
313
-
314
- ## React integration
315
-
316
- `useObserver` is a thin bridge over the observer engine. For the common React case,
317
- wrap it in a tiny helper so components read state like any other value:
318
-
319
- ```tsx
320
- import { useReducer } from 'react'
321
- import { useObserver, state } from 'memorio'
322
-
323
- // Subscribe to one or more state paths and re-render on change.
324
- function useMemorioValue(path: any) {
325
- const [, update] = useReducer((n: number) => n + 1, 0)
326
- useObserver(update, path)
327
- return path
328
- }
329
-
330
- function Counter() {
331
- const counter = useMemorioValue(state.counter)
332
- return <div>{counter}</div>
333
- }
334
- ```
335
-
336
- `useObserver` can also auto-discover dependencies โ€” pass a callback with no explicit
337
- deps and it tracks every state path read inside it โ€” but the explicit-deps form above
338
- is cheaper and easier to reason about at scale.
339
-
340
- Memorio itself stays framework-independent - React is an integration, not a requirement.
99
+ For most apps, that's enough. Everything below is an optional capability you can add when your application needs it - each one documented in its own reference file.
341
100
 
342
101
  ---
343
102
 
344
- ## Redux and other state managers
103
+ ## Where to go next
345
104
 
346
- > **Your state manager owns application state. Memorio owns memory.**
105
+ ### Core
106
+ | Topic | Reference |
107
+ | --- | --- |
108
+ | Reactive state | [`markdown/STATE.md`](./markdown/STATE.md) |
109
+ | Persistent key/value store | [`markdown/STORE.md`](./markdown/STORE.md) |
110
+ | Observing changes | [`markdown/OBSERVER.md`](./markdown/OBSERVER.md) |
111
+ | Structured application memory | [`markdown/MEMORY.md`](./markdown/MEMORY.md) |
347
112
 
348
- ```ts
349
- import { createMemorioReduxBridge } from 'memorio/redux'
350
-
351
- const memorioRedux = createMemorioReduxBridge<AppState>({
352
- mappings: {
353
- 'user.preferences': {
354
- selector: state => state.user.preferences,
355
- type: 'preference',
356
- scope: 'local',
357
- tags: ['app', 'user']
358
- },
359
- 'user.name': state => state.user.name
360
- },
361
- whitelist: ['user/preferencesChanged', 'user/nameChanged'],
362
- debug: true
363
- })
113
+ ### Storage
114
+ | Topic | Reference |
115
+ | --- | --- |
116
+ | Session storage (tab-scoped) | [`markdown/SESSION.md`](./markdown/SESSION.md) |
117
+ | In-memory cache | [`markdown/CACHE.md`](./markdown/CACHE.md) |
118
+ | IndexedDB | [`markdown/IDB.md`](./markdown/IDB.md) |
119
+ | SQLite (`sql.js` / `bun:sqlite`) | [`markdown/SQLITE.md`](./markdown/SQLITE.md) |
364
120
 
365
- const store = createStore(reducer, applyMiddleware(memorioRedux.middleware))
121
+ ### Sync & history
122
+ | Topic | Reference |
123
+ | --- | --- |
124
+ | Local-first sync & cloud | [`markdown/SYNC.md`](./markdown/SYNC.md) |
125
+ | Memory attachments (linking memory entries) | [`markdown/MEMORY-ATTACHMENT.md`](./markdown/MEMORY-ATTACHMENT.md) |
126
+ | History, undo/redo, snapshot, diff, trace | [`markdown/HISTORY.md`](./markdown/HISTORY.md) |
366
127
 
367
- await memorioRedux.hydrate(store, {
368
- onHydration(values) { store.dispatch(restorePreferences(values)) }
369
- })
370
- ```
371
-
372
- ```text
373
- Redux โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’ memorio memorio โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’ Redux
374
- application state durable memory bootstrap hydration (one-shot)
375
- ```
376
-
377
- The bridge persists only mapped selectors, never mirrors the full tree, coalesces bursts, and never breaks Redux dispatch if Memorio fails.
128
+ ### Integrations
129
+ | Topic | Reference |
130
+ | --- | --- |
131
+ | React (`useObserver`) | [`markdown/USEOBSERVER.md`](./markdown/USEOBSERVER.md) |
132
+ | Redux bridge | [`markdown/REDUX.md`](./markdown/REDUX.md) |
133
+ | Typed state | [`markdown/TYPED.md`](./markdown/TYPED.md) |
134
+ | Schema validation | [`markdown/SCHEMA.md`](./markdown/SCHEMA.md) |
135
+ | Pub/sub events outside React | [`markdown/DISPATCH.md`](./markdown/DISPATCH.md) |
136
+ | Console logging middleware | [`markdown/LOGGER.md`](./markdown/LOGGER.md) |
378
137
 
379
- | | Redux | Memorio |
380
- |---|---|---|
381
- | Core model | single store | independent runtime layers |
382
- | State changes | actions + reducers | direct reactive mutation |
383
- | Persistence | external integration | built in |
384
- | Structured memory | - | native |
385
- | Offline memory sync | - | supported |
386
- | Time-travel debugging | mature | State Intelligence (in progress) |
387
- | Production dependencies | ecosystem-dependent | zero in core |
138
+ ### Ops & security
139
+ | Topic | Reference |
140
+ | --- | --- |
141
+ | Platform detection & multi-tenant context isolation | [`markdown/PLATFORM.md`](./markdown/PLATFORM.md) |
142
+ | Classic `import` vs `memorio/global` | [`markdown/IMPORT.md`](./markdown/IMPORT.md) |
143
+ | Runtime introspection | [`markdown/INSPECT.md`](./markdown/INSPECT.md) |
144
+ | Browser DevTools | [`markdown/DEVTOOLS.md`](./markdown/DEVTOOLS.md) |
145
+ | Security, encryption, threat model | [`SECURITY.md`](./SECURITY.md) |
146
+ | Internal self-assessment *(not a third-party audit)* | [`markdown/SELF-ASSESSMENT.md`](./markdown/SELF-ASSESSMENT.md) |
388
147
 
389
- Use Redux when you need its action-pipeline discipline and ecosystem. Use Memorio when you want state, persistence, and structured memory under one runtime. You can use both.
148
+ ### Other
149
+ | Topic | Reference |
150
+ | --- | --- |
151
+ | Version history | [`CHANGELOG.md`](./CHANGELOG.md) |
152
+ | Working examples - each file has a `Run:` comment at the top (typically `npx ts-node examples/<name>.ts`, or `npx ts-node --esm examples/<name>.tsx` for React examples) | [`examples/`](./examples/) |
153
+ | Architecture decisions | [`adr/`](./adr/) |
390
154
 
391
155
  ---
392
156
 
393
- ## Local-first sync
157
+ ## Honest limitations
394
158
 
395
- Memorio synchronizes **operations** (`remember`, `update`, `forget`, `expire`, `confirm`, `supersede`), not database dumps. A local journal keeps the app working through network failures; the cloud is optional transport, not a prerequisite.
159
+ Memorio is upfront about what it doesn't do, so you don't find out the hard way:
396
160
 
397
- ```ts
398
- memorio.memory.configure({
399
- namespace: 'user:123:device:abc',
400
- provider: {
401
- push: ops => fetch('/api/sync', { method: 'POST', body: JSON.stringify(ops) }),
402
- pull: since => fetch(`/api/sync?since=${since}`).then(r => r.json())
403
- },
404
- auto: true
405
- })
406
- ```
407
-
408
- Concurrent operations use HLC ordering by default; override with a custom resolver:
409
-
410
- ```ts
411
- memorio.memory.configure({
412
- resolveConflict(local, remote) {
413
- if (remote.source === 'user-correction') return remote
414
- return local.confidence >= remote.confidence ? local : remote
415
- }
416
- })
417
- ```
418
-
419
- The sync provider is still responsible for the final server-side conflict policy.
420
-
421
- ---
422
-
423
- ## Cross-platform support
424
-
425
- | API | Browser | Node.js | Deno | Edge / Workers |
426
- | -------------------------------- | :--------: | :---------------: | :----------------: | :---------------------: |
427
- | `state` / `observer` / `cache` | โœ… | โœ… | โœ… | โœ… |
428
- | `store` / `session` | persistent | memory fallback | memory fallback | capability-dependent |
429
- | `idb` | โœ… | โŒ | โŒ | capability-dependent |
430
- | `sqlite` | โœ… | โŒ | โŒ | capability-dependent |
431
- | `memory` / `journal` | โœ… | โœ… | โœ… | โœ… |
432
- | `devtools` | dev-only | โŒ | โŒ | capability-dependent |
433
-
434
- ```ts
435
- memorio.getCapabilities()
436
- memorio.isBrowser() // .isNode() ยท .isDeno() ยท .isEdge()
437
- ```
438
-
439
- Don't assume every persistence backend exists in every runtime - check first.
440
-
441
- > **SQLite on Node.js / Deno:** Memorio's `sqlite` is backed by `sql.js` (SQLite compiled to WebAssembly), which requires browser APIs (`window`, `document`, `WebAssembly`). It is not available in Node.js or Deno. For server-side SQL, pair Memorio with a native SQLite package directly; use `store` or `idb` for in-process persistence from Memorio.
442
-
443
- ---
444
-
445
- ## Security
446
-
447
- Core has zero production dependencies. No `eval`, no dynamic code execution, no bundled telemetry, sanitized keys, validated inputs, bounded journal entries, UUID-based session identifiers. Independently checkable via Socket.dev / Snyk.
448
-
449
- > โš ๏ธ **Memorio does not encrypt data by default** - this applies to every layer (`state`, `store`, `session`, `idb`, `memory`, `sqlite`). Treat browser storage as client-controlled. Use proper encryption and backend authorization for credentials or regulated data.
450
-
451
- **Contexts are not authorization:**
452
-
453
- ```ts
454
- memorio.createContext('tenant-123')
455
- ```
456
-
457
- Contexts organize and isolate application concerns - they're not a security boundary. Code in the same JS runtime can potentially reach other contexts. Real tenant isolation belongs at the auth/backend layer.
458
-
459
- DevTools expose data for development only, and only when you opt into `memorio/global`.
161
+ - **No encryption by default.** Data is stored in plain text unless you explicitly turn on `memorio.encryption` or pass an `encryptionKey`. See [`SECURITY.md`](./SECURITY.md).
162
+ - **Namespaces/contexts aren't a security boundary.** `memorio.isolate()` gives you logical separation between tenants or sessions, not authorization or access control โ€” enforce that at your application layer.
163
+ - **SQLite persistence (`sql.js` backend) isn't incremental.** Each write exports and re-saves the whole database, which gets costly as data grows. The `bun:sqlite` backend avoids this cost but doesn't support `export()` at all โ€” see [`markdown/SQLITE.md`](./markdown/SQLITE.md).
164
+ - **`memory.context()` is rule-based, not embedding-based.** It ranks structured entries by recency, confidence, and type โ€” it does not do semantic similarity search. Pair it with a vector store if your agent needs "find things like this."
165
+ - **Key management is your responsibility.** Memorio's encryption is client-side; it doesn't manage, rotate, or store keys for you.
460
166
 
461
167
  ---
462
168
 
463
169
  ## When to use something else
464
170
 
465
- - **A strict Redux-style architecture** - when you need action pipelines, extensive middleware, event-sourcing, or mature time-travel tooling. Memorio can integrate rather than replace.
171
+ - **A strict Redux-style architecture** - when you need action pipelines, extensive middleware, event-sourcing, or mature time-travel tooling. Memorio can integrate rather than replace - see [`markdown/REDUX.md`](./markdown/REDUX.md).
466
172
  - **A server database** - for authoritative persistence, multi-user authorization, or server-side transactions.
467
- - **A dedicated vector database** - for true embedding similarity search. Memorio can still manage the lifecycle/metadata of what you retrieve from it.
468
-
469
- Memorio occupies a distinct space: **application state + history + causality + replay + impact analysis + simulation**. If you need to know *why* state changed, *who* changed it, or *what would happen* if it changed, Memorio is the tool - not just a state container.
173
+ - **A dedicated secrets manager** - for high-privilege credentials, encryption key management, or regulated data at rest. Memorio's encryption is client-side and key-management is your responsibility - see [`SECURITY.md`](./SECURITY.md).
174
+ - **A dedicated vector database** - for true embedding similarity search. Memorio manages structured memory (preferences, decisions, facts), not embeddings.
470
175
 
471
176
  ---
472
177
 
@@ -477,52 +182,10 @@ Memorio occupies a distinct space: **application state + history + causality + r
477
182
  3. **The cloud is optional** - sync extends the local app; it doesn't define it.
478
183
  4. **Use the right primitive** - relational data belongs in SQL, not a kv store; memory isn't the same as ordinary state.
479
184
  5. **Memory has meaning** - confidence, source, type, scope, TTL, tags, history, status: more than "just a value."
480
- 6. **Global access is explicit** - opt in with `import 'memorio/global'`, or keep it explicit with named imports.
481
- 7. **Tell the truth about boundaries** - not encrypted, not authorization, not embedding search unless paired with one.
482
- 8. **Keep the common case tiny** - `state.value = 42` is a complete, valid program.
483
-
484
- ---
485
-
486
- ## Quick recipes
487
-
488
- ```ts
489
- // Global state
490
- import 'memorio/global'
491
- state.user = { name: 'Sara', role: 'admin' }
492
-
493
- // Explicit state
494
- import { state } from 'memorio'
495
- state.counter++
496
-
497
- // Persistent kv
498
- import { store } from 'memorio'
499
- store.set('preferences', { theme: 'dark' })
500
-
501
- // Persistent reactive state
502
- import { state, persist } from 'memorio'
503
- state.user = { name: 'Sara' }
504
- const off = persist('state.user')
505
-
506
- // Application memory
507
- import { memorio } from 'memorio'
508
- await memorio.memory.remember('user.language', 'Italian', {
509
- type: 'preference', confidence: 0.92, source: 'conversation'
510
- })
511
-
512
- // Observe a value
513
- import { observer } from 'memorio'
514
- const off = observer('state.user', (next, previous) => console.log(next, previous))
515
-
516
- // Track mutations, undo, and trace history
517
- import { memorio } from 'memorio'
518
- memorio.enableHistory(true)
519
- memorio.mutate('state.user.role', 'admin', { source: 'permissions.save' })
520
- const tx = memorio.transaction('migration', 'v2 schema migration')
521
- state.user.v2 = true
522
- memorio.commitTransaction()
523
- memorio.undo()
524
- console.debug(memorio.trace())
525
- ```
185
+ 6. **Memory belongs to whoever it's about** - structured and inspectable by default, encryptable with a key the vendor doesn't have to hold.
186
+ 7. **Global access is explicit** - opt in with `import 'memorio/global'`, or keep it explicit with named imports.
187
+ 8. **Tell the truth about boundaries** - encryption is opt-in (not default), contexts aren't authorization, and there's no embedding search unless paired with one. (See [Honest limitations](#honest-limitations) above.)
188
+ 9. **Keep the common case tiny** - `state.value = 42` is a complete, valid program.
526
189
 
527
190
  ---
528
191