memorio 5.0.0 → 5.1.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 +80 -449
- package/SECURITY.md +152 -42
- package/SUMMARY.md +1 -1
- package/adr/001-state-proxy-model.md +95 -96
- package/adr/002-observer-semantics.md +179 -180
- package/adr/003-deep-mutation-semantics.md +7 -8
- package/adr/004-array-mutation-semantics.md +127 -128
- package/adr/005-scheduler-contract.md +148 -149
- package/adr/006-context-isolation.md +91 -92
- package/adr/007-mutation-records.md +5 -6
- package/adr/008-transactions.md +6 -7
- package/adr/009-history-model.md +6 -7
- package/adr/README.md +46 -46
- package/adr/template.md +48 -49
- package/bin/cli.js +68 -0
- package/global.cjs +1462 -323
- package/global.js +1459 -324
- package/index.cjs +1462 -323
- package/index.d.ts +1 -0
- package/index.js +1459 -324
- package/llms.txt +42 -5
- package/markdown/AUDIT-REPORT.md +7 -8
- package/markdown/CACHE.md +190 -99
- package/markdown/DEVTOOLS.md +0 -1
- package/markdown/DISPATCH.md +0 -1
- package/markdown/HISTORY.md +0 -1
- package/markdown/IDB.md +0 -1
- package/markdown/IMPORT.md +0 -1
- package/markdown/INSPECT.md +0 -1
- package/markdown/LOGGER.md +0 -1
- package/markdown/MEMORY-ATTACHMENT.md +0 -1
- package/markdown/MEMORY.md +0 -1
- package/markdown/OBSERVER.md +0 -1
- package/markdown/PLATFORM.md +277 -271
- package/markdown/REDUX.md +54 -0
- package/markdown/SCHEMA.md +0 -1
- package/markdown/SESSION.md +0 -1
- package/markdown/SQLITE.md +0 -1
- package/markdown/STATE.md +0 -1
- package/markdown/STORE.md +0 -1
- package/markdown/SYNC.md +0 -1
- package/markdown/TYPED.md +0 -1
- package/markdown/USEOBSERVER.md +0 -1
- package/modules/redux.cjs +381 -10
- package/modules/redux.cjs.map +1 -1
- package/modules/redux.js +381 -10
- package/modules/redux.js.map +1 -1
- package/package.json +14 -2
- package/types/broadcast.d.ts +61 -0
- package/types/computed.d.ts +96 -0
- package/types/encryption.d.ts +129 -0
- package/types/exports.d.ts +9 -0
- package/types/memorio.d.ts +19 -12
- package/types/security.d.ts +67 -0
- package/types/session.d.ts +23 -5
- package/types/store.d.ts +19 -3
- package/vsix/memorio.vsix +0 -0
- package/markdown/CHANGELOG.md +0 -243
- package/markdown/PROJECT.md +0 -311
- package/markdown/SECURITY.md +0 -330
package/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# 🧠 memorio
|
|
2
2
|
|
|
3
|
-
**
|
|
4
|
-
|
|
5
|
-
Use it like an object.
|
|
3
|
+
**The memory layer for AI agents and apps — owned by the user, not the vendor.**
|
|
6
4
|
|
|
7
5
|
```ts
|
|
8
6
|
import 'memorio/global'
|
|
@@ -19,18 +17,20 @@ Just data, available where your application needs it.
|
|
|
19
17
|
|
|
20
18
|
---
|
|
21
19
|
|
|
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.
|
|
20
|
+
## Why memorio
|
|
25
21
|
|
|
26
|
-
|
|
22
|
+
Most AI-powered apps (and most apps in general) eventually need more than "just state": reactive values, persistent data, session data, caches, structured browser storage, local SQL, application memory, history, and optional sync.
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
Usually that means a different library — and a different mental model — for each. Memorio gives them one consistent runtime, without making the simple case complicated:
|
|
29
25
|
|
|
30
26
|
```ts
|
|
31
27
|
state.value = 42
|
|
32
28
|
```
|
|
33
29
|
|
|
30
|
+
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.
|
|
31
|
+
|
|
32
|
+
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).
|
|
33
|
+
|
|
34
34
|
Add persistence, memory, history, or sync only when your application actually needs them. The common case stays tiny; the runtime grows with you.
|
|
35
35
|
|
|
36
36
|
---
|
|
@@ -45,110 +45,23 @@ Zero production dependencies in core. Optional integrations (`react`, `sql.js`,
|
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
-
##
|
|
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
|
-
---
|
|
48
|
+
## Start here
|
|
88
49
|
|
|
89
|
-
|
|
50
|
+
Three things cover most apps - reactive state, persistence, and observation:
|
|
90
51
|
|
|
91
52
|
```ts
|
|
92
|
-
|
|
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
|
|
111
|
-
|
|
112
|
-
```ts
|
|
113
|
-
import { state, persist } from 'memorio'
|
|
53
|
+
import { state, persist, observer } from 'memorio'
|
|
114
54
|
|
|
115
55
|
state.user = { name: 'Sara' }
|
|
116
|
-
const off = persist('state.user')
|
|
117
|
-
|
|
118
|
-
// later
|
|
119
|
-
off()
|
|
120
|
-
```
|
|
121
56
|
|
|
122
|
-
|
|
123
|
-
Without `localStorage` (e.g. Node), `store` falls back to memory.
|
|
57
|
+
persist('state.user')
|
|
124
58
|
|
|
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)
|
|
59
|
+
observer('state.user', user => {
|
|
60
|
+
console.log(user)
|
|
134
61
|
})
|
|
135
|
-
|
|
136
|
-
off() // unsubscribe
|
|
137
62
|
```
|
|
138
63
|
|
|
139
|
-
|
|
140
|
-
The alternatives remove listeners by path name:
|
|
141
|
-
|
|
142
|
-
```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**.
|
|
64
|
+
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:
|
|
152
65
|
|
|
153
66
|
```ts
|
|
154
67
|
import { memorio } from 'memorio'
|
|
@@ -156,317 +69,77 @@ import { memorio } from 'memorio'
|
|
|
156
69
|
await memorio.memory.remember('user.language', 'Italian', {
|
|
157
70
|
type: 'preference',
|
|
158
71
|
confidence: 0.92,
|
|
159
|
-
scope: 'local',
|
|
160
|
-
tags: ['user', 'ui'],
|
|
161
72
|
source: 'conversation'
|
|
162
73
|
})
|
|
163
74
|
|
|
164
75
|
const language = await memorio.memory.recall('user.language')
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
|
310
|
-
```
|
|
311
|
-
|
|
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.
|
|
341
|
-
|
|
342
|
-
---
|
|
343
|
-
|
|
344
|
-
## Redux and other state managers
|
|
345
|
-
|
|
346
|
-
> **Your state manager owns application state. Memorio owns memory.**
|
|
347
|
-
|
|
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
|
-
})
|
|
364
|
-
|
|
365
|
-
const store = createStore(reducer, applyMiddleware(memorioRedux.middleware))
|
|
366
|
-
|
|
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.
|
|
378
|
-
|
|
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 |
|
|
388
|
-
|
|
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.
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
## Local-first sync
|
|
394
|
-
|
|
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.
|
|
396
|
-
|
|
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`.
|
|
76
|
+
// { value: 'Italian', confidence: 0.92, source: 'conversation', ... }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
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.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Where to go next
|
|
84
|
+
|
|
85
|
+
### Core
|
|
86
|
+
| Topic | Reference |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| Reactive state | [`markdown/STATE.md`](./markdown/STATE.md) |
|
|
89
|
+
| Persistent key/value store | [`markdown/STORE.md`](./markdown/STORE.md) |
|
|
90
|
+
| Observing changes | [`markdown/OBSERVER.md`](./markdown/OBSERVER.md) |
|
|
91
|
+
| Structured application memory | [`markdown/MEMORY.md`](./markdown/MEMORY.md) |
|
|
92
|
+
|
|
93
|
+
### Storage
|
|
94
|
+
| Topic | Reference |
|
|
95
|
+
| --- | --- |
|
|
96
|
+
| Session storage (tab-scoped) | [`markdown/SESSION.md`](./markdown/SESSION.md) |
|
|
97
|
+
| In-memory cache | [`markdown/CACHE.md`](./markdown/CACHE.md) |
|
|
98
|
+
| IndexedDB | [`markdown/IDB.md`](./markdown/IDB.md) |
|
|
99
|
+
| SQLite (`sql.js` / `bun:sqlite`) | [`markdown/SQLITE.md`](./markdown/SQLITE.md) |
|
|
100
|
+
|
|
101
|
+
### Sync & history
|
|
102
|
+
| Topic | Reference |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| Local-first sync & cloud | [`markdown/SYNC.md`](./markdown/SYNC.md) |
|
|
105
|
+
| Memory attachments (linking memory entries) | [`markdown/MEMORY-ATTACHMENT.md`](./markdown/MEMORY-ATTACHMENT.md) |
|
|
106
|
+
| History, undo/redo, snapshot, diff, trace | [`markdown/HISTORY.md`](./markdown/HISTORY.md) |
|
|
107
|
+
|
|
108
|
+
### Integrations
|
|
109
|
+
| Topic | Reference |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| React (`useObserver`) | [`markdown/USEOBSERVER.md`](./markdown/USEOBSERVER.md) |
|
|
112
|
+
| Redux bridge | [`markdown/REDUX.md`](./markdown/REDUX.md) |
|
|
113
|
+
| Typed state | [`markdown/TYPED.md`](./markdown/TYPED.md) |
|
|
114
|
+
| Schema validation | [`markdown/SCHEMA.md`](./markdown/SCHEMA.md) |
|
|
115
|
+
| Pub/sub events outside React | [`markdown/DISPATCH.md`](./markdown/DISPATCH.md) |
|
|
116
|
+
| Console logging middleware | [`markdown/LOGGER.md`](./markdown/LOGGER.md) |
|
|
117
|
+
|
|
118
|
+
### Ops & security
|
|
119
|
+
| Topic | Reference |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| Platform detection & multi-tenant context isolation | [`markdown/PLATFORM.md`](./markdown/PLATFORM.md) |
|
|
122
|
+
| Classic `import` vs `memorio/global` | [`markdown/IMPORT.md`](./markdown/IMPORT.md) |
|
|
123
|
+
| Runtime introspection | [`markdown/INSPECT.md`](./markdown/INSPECT.md) |
|
|
124
|
+
| Browser DevTools | [`markdown/DEVTOOLS.md`](./markdown/DEVTOOLS.md) |
|
|
125
|
+
| Security, encryption, threat model | [`SECURITY.md`](./SECURITY.md) |
|
|
126
|
+
| Internal self-assessment *(not a third-party audit)* | [`markdown/SELF-ASSESSMENT.md`](./markdown/SELF-ASSESSMENT.md) |
|
|
127
|
+
|
|
128
|
+
### Other
|
|
129
|
+
| Topic | Reference |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| Version history | [`CHANGELOG.md`](./CHANGELOG.md) |
|
|
132
|
+
| 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/) |
|
|
133
|
+
| Architecture decisions | [`adr/`](./adr/) |
|
|
460
134
|
|
|
461
135
|
---
|
|
462
136
|
|
|
463
137
|
## When to use something else
|
|
464
138
|
|
|
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.
|
|
139
|
+
- **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
140
|
- **A server database** - for authoritative persistence, multi-user authorization, or server-side transactions.
|
|
467
|
-
- **A dedicated
|
|
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.
|
|
141
|
+
- **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).
|
|
142
|
+
- **A dedicated vector database** - for true embedding similarity search. Memorio manages structured memory (preferences, decisions, facts), not embeddings.
|
|
470
143
|
|
|
471
144
|
---
|
|
472
145
|
|
|
@@ -477,52 +150,10 @@ Memorio occupies a distinct space: **application state + history + causality + r
|
|
|
477
150
|
3. **The cloud is optional** - sync extends the local app; it doesn't define it.
|
|
478
151
|
4. **Use the right primitive** - relational data belongs in SQL, not a kv store; memory isn't the same as ordinary state.
|
|
479
152
|
5. **Memory has meaning** - confidence, source, type, scope, TTL, tags, history, status: more than "just a value."
|
|
480
|
-
6. **
|
|
481
|
-
7. **
|
|
482
|
-
8. **
|
|
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
|
-
```
|
|
153
|
+
6. **Memory belongs to whoever it's about** - structured and inspectable by default, encryptable with a key the vendor doesn't have to hold.
|
|
154
|
+
7. **Global access is explicit** - opt in with `import 'memorio/global'`, or keep it explicit with named imports.
|
|
155
|
+
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.
|
|
156
|
+
9. **Keep the common case tiny** - `state.value = 42` is a complete, valid program.
|
|
526
157
|
|
|
527
158
|
---
|
|
528
159
|
|