memorio 4.7.1 → 4.7.3
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 +241 -34
- package/SECURITY.md +10 -10
- package/SUMMARY.md +14 -0
- package/index.cjs +160 -29
- package/index.d.ts +3 -0
- package/index.js +115 -7
- package/llms.txt +119 -28
- package/markdown/CHANGELOG.md +8 -8
- package/markdown/HISTORY.md +192 -0
- package/markdown/INSPECT.md +116 -0
- package/markdown/MEMORY.md +155 -0
- package/markdown/SCHEMA.md +169 -0
- package/markdown/SECURITY.md +1 -1
- package/markdown/TYPED.md +158 -0
- package/package.json +7 -7
- package/types/exports.d.ts +25 -0
- package/types/history.d.ts +27 -0
- package/types/inspect.d.ts +14 -0
- package/types/memorio.d.ts +48 -2
- package/types/memory.d.ts +70 -0
- package/types/schema.d.ts +53 -0
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|

|
|
14
14
|

|
|
15
15
|
|
|
16
|
-
### One import. Global state, persistence, and a IndexedDB layer
|
|
16
|
+
### One import. Global state, persistence, and a IndexedDB layer - done.
|
|
17
17
|
|
|
18
18
|
```javascript
|
|
19
19
|
import 'memorio'
|
|
@@ -21,7 +21,7 @@ import 'memorio'
|
|
|
21
21
|
state.user = { name: 'Sara' } // reactive, everywhere, instantly
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
No provider tree. No reducers. No actions to dispatch before you can change a number. If you've ever set up a global store for an app that just needed *"a value, shared, that updates the UI when it changes,"* memorio is the toolkit for that thirty-second job
|
|
24
|
+
No provider tree. No reducers. No actions to dispatch before you can change a number. If you've ever set up a global store for an app that just needed *"a value, shared, that updates the UI when it changes,"* memorio is the toolkit for that thirty-second job - and it keeps growing with you: session storage, a cache, typed IndexedDB tables, an observer system, a React hook, devtools, and a change logger, all sharing one mental model.
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
@@ -31,26 +31,28 @@ No provider tree. No reducers. No actions to dispatch before you can change a nu
|
|
|
31
31
|
2. [Installation](#installation)
|
|
32
32
|
3. [Quick Start](#quick-start)
|
|
33
33
|
4. [API Reference](#api-reference)
|
|
34
|
-
5. [
|
|
35
|
-
6. [
|
|
36
|
-
7. [
|
|
37
|
-
8. [
|
|
34
|
+
5. [Typed Stores](#typed-stores)
|
|
35
|
+
6. [Schema Validation](#schema-validation)
|
|
36
|
+
7. [Cross-Platform Behavior](#cross-platform-behavior)
|
|
37
|
+
8. [Context Isolation (multi-tenant)](#context-isolation-multi-tenant)
|
|
38
|
+
9. [Security](#security)
|
|
39
|
+
10. [License](#license)
|
|
38
40
|
|
|
39
41
|
---
|
|
40
42
|
|
|
41
43
|
## Is this for you?
|
|
42
44
|
|
|
43
|
-
memorio is built for speed of thought: you think "I need this value everywhere," you write one line, it works. That's the entire pitch
|
|
45
|
+
memorio is built for speed of thought: you think "I need this value everywhere," you write one line, it works. That's the entire pitch - and it's a real one, not a rewritten complaint about how much Redux boilerplate you've had to write.
|
|
44
46
|
|
|
45
47
|
**Reach for memorio when:**
|
|
46
|
-
- You want state that's simply *there*
|
|
48
|
+
- You want state that's simply *there* - no store setup, no provider wrapping your app.
|
|
47
49
|
- You want `localStorage`, `sessionStorage`, and `IndexedDB` behind one consistent API instead of learning three.
|
|
48
50
|
- You're prototyping, building an internal tool, or shipping something small-to-medium where iteration speed matters more than architectural ceremony.
|
|
49
51
|
|
|
50
52
|
**Reach for something else when:**
|
|
51
|
-
- You need every state path statically type-checked against every observer
|
|
52
|
-
- You need Redux-style middleware, action logs, or time-travel debugging as a hard requirement for a large team
|
|
53
|
-
- Your isolation requirements are a security boundary, not a convenience
|
|
53
|
+
- You need every state path statically type-checked against every observer - memorio's `state.foo.bar` and `observer('state.foo.bar', ...)` are connected by a string, not by the compiler, so a rename won't be caught for you. However, if you want compiler-checked state access, use `memorio.typed<T>()` (see [Typed Stores](#typed-stores)) which gives you full static types on the global `state` proxy. For runtime validation as well, combine with `memorio.registerSchema()` (see [Schema Validation](#schema-validation)).
|
|
54
|
+
- You need Redux-style middleware, action logs, or time-travel debugging as a hard requirement for a large team - those tools exist because that discipline solves real problems at scale, not because their authors enjoy boilerplate. Memorio logs through `memorio.logger` and inspects via `memorio.devtools`, but doesn't have Redux DevTools time-travel.
|
|
55
|
+
- Your isolation requirements are a security boundary, not a convenience - see [Context Isolation](#context-isolation-multi-tenant) before you rely on it for that.
|
|
54
56
|
|
|
55
57
|
Pick the right tool. memorio is at its best when the answer to "how much state architecture do I need here?" is genuinely "not much."
|
|
56
58
|
|
|
@@ -63,7 +65,7 @@ npm i memorio
|
|
|
63
65
|
# pnpm add memorio
|
|
64
66
|
# yarn add memorio
|
|
65
67
|
|
|
66
|
-
# Optional
|
|
68
|
+
# Optional - only if you use the React hook
|
|
67
69
|
npm i react react-dom
|
|
68
70
|
```
|
|
69
71
|
|
|
@@ -71,7 +73,7 @@ npm i react react-dom
|
|
|
71
73
|
|
|
72
74
|
## Quick Start
|
|
73
75
|
|
|
74
|
-
### Global style
|
|
76
|
+
### Global style - the whole point of memorio
|
|
75
77
|
|
|
76
78
|
```typescript
|
|
77
79
|
import 'memorio' // once, at your entry point
|
|
@@ -85,7 +87,7 @@ useObserver(
|
|
|
85
87
|
)
|
|
86
88
|
```
|
|
87
89
|
|
|
88
|
-
### Named imports
|
|
90
|
+
### Named imports - same instances, explicit about it
|
|
89
91
|
|
|
90
92
|
```typescript
|
|
91
93
|
import { state, store, session, cache, idb, observer, useObserver, dispatch, memorio } from 'memorio'
|
|
@@ -102,13 +104,13 @@ function Counter() {
|
|
|
102
104
|
}
|
|
103
105
|
```
|
|
104
106
|
|
|
105
|
-
Two styles, one engine underneath
|
|
107
|
+
Two styles, one engine underneath - use whichever reads better in your codebase.
|
|
106
108
|
|
|
107
109
|
---
|
|
108
110
|
|
|
109
111
|
## API Reference
|
|
110
112
|
|
|
111
|
-
### `state`
|
|
113
|
+
### `state` - reactive, volatile, Proxy-based
|
|
112
114
|
|
|
113
115
|
```javascript
|
|
114
116
|
state.user = { name: 'Sara', role: 'admin' }
|
|
@@ -125,7 +127,7 @@ state.config.maxUsers = 200 // throws: state 'config' is locked
|
|
|
125
127
|
state.config.unlock()
|
|
126
128
|
```
|
|
127
129
|
|
|
128
|
-
### `store`
|
|
130
|
+
### `store` - the value that survives a refresh
|
|
129
131
|
|
|
130
132
|
```javascript
|
|
131
133
|
store.set('preferences', { theme: 'dark' })
|
|
@@ -133,21 +135,21 @@ store.get('preferences') // { theme: 'dark' } or null
|
|
|
133
135
|
store.isPersistent // true when backed by real localStorage
|
|
134
136
|
```
|
|
135
137
|
|
|
136
|
-
### `session`
|
|
138
|
+
### `session` - lives as long as the tab does
|
|
137
139
|
|
|
138
140
|
```javascript
|
|
139
141
|
session.set('token', 'user-abc-123')
|
|
140
142
|
session.get('token')
|
|
141
143
|
```
|
|
142
144
|
|
|
143
|
-
### `cache`
|
|
145
|
+
### `cache` - the fastest thing you own, gone on refresh
|
|
144
146
|
|
|
145
147
|
```javascript
|
|
146
148
|
cache.set('temp', computeExpensiveResult())
|
|
147
149
|
cache.get('temp')
|
|
148
150
|
```
|
|
149
151
|
|
|
150
|
-
### `idb`
|
|
152
|
+
### `idb` - typed, async, structured tables without the ceremony
|
|
151
153
|
|
|
152
154
|
```javascript
|
|
153
155
|
await idb.db.create('my-db')
|
|
@@ -156,9 +158,9 @@ await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
|
|
|
156
158
|
const user = await idb.data.get('my-db', 'users', 1)
|
|
157
159
|
```
|
|
158
160
|
|
|
159
|
-
> IndexedDB is a browser-only primitive
|
|
161
|
+
> IndexedDB is a browser-only primitive - see [Cross-Platform Behavior](#cross-platform-behavior) for what happens off the browser.
|
|
160
162
|
|
|
161
|
-
### `observer` / `useObserver`
|
|
163
|
+
### `observer` / `useObserver` - watch a path, react to it
|
|
162
164
|
|
|
163
165
|
```javascript
|
|
164
166
|
observer('state.user', (newVal, oldVal) => {
|
|
@@ -168,14 +170,14 @@ observer('state.user', (newVal, oldVal) => {
|
|
|
168
170
|
|
|
169
171
|
> Keys here are plain strings, not statically checked against `state`'s shape. Keep the observer near the code that shapes that state, and grep before you rename.
|
|
170
172
|
|
|
171
|
-
### `dispatch`
|
|
173
|
+
### `dispatch` - the event bus underneath it all
|
|
172
174
|
|
|
173
175
|
```javascript
|
|
174
176
|
memorio.dispatch.listen('state.user', (event) => console.debug(event.detail))
|
|
175
177
|
memorio.dispatch.set('state.user', { detail: { name: 'Sara' } })
|
|
176
178
|
```
|
|
177
179
|
|
|
178
|
-
### `devtools`
|
|
180
|
+
### `devtools` - see everything, instantly
|
|
179
181
|
|
|
180
182
|
```javascript
|
|
181
183
|
memorio.devtools.inspect()
|
|
@@ -185,32 +187,237 @@ memorio.devtools.exportData()
|
|
|
185
187
|
|
|
186
188
|
Pairs with [dphelper-manager](https://chrome.google.com/webstore/detail/dphelper-manager-dev-tool/oppppldaoknfddeikfloonnialijngbk) for visual, time-travel inspection of your global state straight from devtools.
|
|
187
189
|
|
|
188
|
-
### `logger`
|
|
190
|
+
### `logger` - a black box for every change
|
|
189
191
|
|
|
190
192
|
```javascript
|
|
191
193
|
memorio.logger.configure({ enabled: true, logToConsole: true })
|
|
192
194
|
memorio.logger.getHistory()
|
|
193
195
|
```
|
|
194
196
|
|
|
195
|
-
> It logs *everything* written to `state`/`store`/`session`
|
|
197
|
+
> It logs *everything* written to `state`/`store`/`session` - including anything sensitive you put there. Great for debugging, but don't leave it on unconditionally in production if secrets or PII pass through your state. See [Security](#security).
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Typed Stores
|
|
202
|
+
|
|
203
|
+
`memorio.typed<T>()` returns the global `state` proxy cast to a TypeScript type `T`, giving you **compile-time** type safety on every access and mutation. The returned object is the *exact same* Proxy as `globalThis.state` — no duplication, no overhead.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import 'memorio'
|
|
207
|
+
|
|
208
|
+
interface AppState {
|
|
209
|
+
user: { name: string; age: number; email: string }
|
|
210
|
+
theme: 'light' | 'dark'
|
|
211
|
+
items: string[]
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const app = memorio.typed<AppState>()
|
|
215
|
+
|
|
216
|
+
// Type-checked at compile time:
|
|
217
|
+
app.user = { name: 'Sara', age: 30, email: 'sara@test.com' }
|
|
218
|
+
app.theme = 'dark'
|
|
219
|
+
|
|
220
|
+
// TypeScript errors:
|
|
221
|
+
// app.user = { name: 42 } // age missing, name wrong type
|
|
222
|
+
// app.theme = 'purple' // not a valid literal
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The same data is accessible via the global `state` proxy — `app` and `state` are identical instances:
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
state.user = { name: 'Sara', age: 30, email: 'sara@test.com' }
|
|
229
|
+
app.user.name // 'Sara' — same Proxy
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
For runtime safety (rejecting invalid values even when TypeScript isn't checking), combine with [Schema Validation](#schema-validation) below.
|
|
233
|
+
|
|
234
|
+
See [Typed Stores docs](markdown/TYPED.md) for full examples.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Schema Validation
|
|
239
|
+
|
|
240
|
+
`memorio.registerSchema(path, schema)` lets you register runtime validators for state paths. When a write to `state.somePath = value` violates a registered schema, the write is **rejected** before the value is stored.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import 'memorio'
|
|
244
|
+
|
|
245
|
+
memorio.registerSchema('user', {
|
|
246
|
+
type: 'object',
|
|
247
|
+
required: ['name', 'email'],
|
|
248
|
+
properties: {
|
|
249
|
+
name: { type: 'string', min: 1 },
|
|
250
|
+
email: { type: 'string', pattern: /^[^@]+@[^@]+$/ },
|
|
251
|
+
age: { type: 'number', min: 0, max: 150 }
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
state.user = { name: 'Sara', email: 'sara@test.com', age: 30 } // accepted
|
|
256
|
+
state.user = { name: 'Sara' } // rejected: missing 'email'
|
|
257
|
+
state.user = { name: 42 } // rejected: wrong type
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Custom validator functions are also supported:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
memorio.registerSchema('theme', (val) => {
|
|
264
|
+
return val === 'light' || val === 'dark'
|
|
265
|
+
? true
|
|
266
|
+
: 'theme must be "light" or "dark"'
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
state.theme = 'purple' // rejected: "theme must be light or dark"
|
|
270
|
+
state.theme = 'dark' // accepted
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Manual validation without writing:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
memorio.validate('user', { name: 'Sara', email: 'sara@test.com' })
|
|
277
|
+
// { valid: true }
|
|
278
|
+
|
|
279
|
+
memorio.validate('user', { name: 'Sara' })
|
|
280
|
+
// { valid: false, errors: ["user: missing required property 'email'"] }
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Manage registered schemas:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
memorio.listSchemas() // ['user', 'theme']
|
|
287
|
+
memorio.unregisterSchema('theme') // removes the validator
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Typed + Schema** — combine both for full safety:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
interface AppState {
|
|
294
|
+
user: { name: string; email: string }
|
|
295
|
+
theme: 'light' | 'dark'
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const app = memorio.typed<AppState>()
|
|
299
|
+
|
|
300
|
+
memorio.registerSchema('user', {
|
|
301
|
+
type: 'object',
|
|
302
|
+
required: ['name', 'email'],
|
|
303
|
+
properties: {
|
|
304
|
+
name: { type: 'string', min: 1 },
|
|
305
|
+
email: { type: 'string', pattern: /^[^@]+@[^@]+$/ }
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
app.user = { names: 'Sara' } // ❌ TS: wrong shape
|
|
310
|
+
app.user = { name: '', email: '' } // ❌ TS passes, ❌ runtime: name too short
|
|
311
|
+
app.user = { name: 'Sara', email: 'sara@test.com' } // ✅ both pass
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
See [Schema Validation docs](markdown/SCHEMA.md) for the full schema definition reference.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Memory System
|
|
319
|
+
|
|
320
|
+
`memorio.memory` provides a semantic memory layer — a key/value store with **type safety**, **TTL**, **confidence scoring**, **tagging**, and **scope-based persistence**. It's designed for AI agents and applications that need structured, queryable memory with lifecycle management.
|
|
321
|
+
|
|
322
|
+
### Core API
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
// remember(key, value, options)
|
|
326
|
+
await memorio.memory.remember('user.language', 'Italian', {
|
|
327
|
+
type: 'preference',
|
|
328
|
+
confidence: 0.92,
|
|
329
|
+
scope: 'local',
|
|
330
|
+
ttl: null, // never expires
|
|
331
|
+
tags: ['ui', 'user'],
|
|
332
|
+
source: 'conversation'
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
// recall(key, options)
|
|
336
|
+
const lang = await memorio.memory.recall('user.language')
|
|
337
|
+
// → 'Italian'
|
|
338
|
+
|
|
339
|
+
// update(key, value, options) — creates a superseded version of the old entry
|
|
340
|
+
await memorio.memory.update('user.language', 'English', { confidence: 0.95 })
|
|
341
|
+
|
|
342
|
+
// forget(key) — permanently deletes
|
|
343
|
+
await memorio.memory.forget('user.language')
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Scopes
|
|
347
|
+
|
|
348
|
+
| Scope | Storage | TTL | Cross-session | Size limit |
|
|
349
|
+
|---|---|---|---|---|
|
|
350
|
+
| `hot` | `state` proxy | ✅ | ❌ | ~5MB (RAM) |
|
|
351
|
+
| `session` | `sessionStorage` | ✅ | Tab only | ~5MB |
|
|
352
|
+
| `local` | `localStorage` | ✅ | ✅ | ~10MB |
|
|
353
|
+
| `durable` | `IndexedDB` | ✅ | ✅ | ~1GB+ |
|
|
354
|
+
|
|
355
|
+
Default scope is `local` for values ≤100KB, `durable` for larger values.
|
|
356
|
+
|
|
357
|
+
### Context API
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
// context() — returns ranked, relevant memories
|
|
361
|
+
const context = await memorio.memory.context({
|
|
362
|
+
tags: 'user',
|
|
363
|
+
types: ['preference', 'decision'],
|
|
364
|
+
minConfidence: 0.7,
|
|
365
|
+
maxEntries: 10
|
|
366
|
+
})
|
|
367
|
+
// → [{ key, value, relevance, age, confidence, ... }]
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Memory Entry Model
|
|
371
|
+
|
|
372
|
+
Each memory is stored as a structured entry:
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
{
|
|
376
|
+
id: string // unique identifier
|
|
377
|
+
key: string // path-like key (e.g. "user.preference.theme")
|
|
378
|
+
value: any // the stored data
|
|
379
|
+
type: MemoryType // 'fact' | 'preference' | 'decision' | 'task' | 'context'
|
|
380
|
+
confidence: number // 0.0–1.0
|
|
381
|
+
scope: MemoryScope // 'hot' | 'session' | 'local' | 'durable'
|
|
382
|
+
ttl?: number | null // milliseconds (null = never expires)
|
|
383
|
+
tags: string[] // for filtering
|
|
384
|
+
source?: string // where this memory came from
|
|
385
|
+
status: MemoryStatus // 'active' | 'obsolete' | 'superseded'
|
|
386
|
+
createdAt: number // timestamp
|
|
387
|
+
lastConfirmedAt: number
|
|
388
|
+
supersededId?: string | null
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Memory Lifecycle
|
|
393
|
+
|
|
394
|
+
| Operation | Behavior |
|
|
395
|
+
|---|---|
|
|
396
|
+
| `remember(key, newValue)` when entry exists | Old entry → `superseded` status, new entry → `active` |
|
|
397
|
+
| `recall(key)` | Returns active value; expired entries return `null` unless `includeObsolete: true` |
|
|
398
|
+
| `update(key, value)` | Creates superseded copy + updated active entry |
|
|
399
|
+
| Entry with `ttl` expires | Status → `obsolete` (via `forgetExpired()`) |
|
|
400
|
+
| `clear()` | Wipes all memories + index |
|
|
401
|
+
|
|
402
|
+
See [Memory docs](markdown/MEMORY.md) for full reference.
|
|
196
403
|
|
|
197
404
|
---
|
|
198
405
|
|
|
199
406
|
## Cross-Platform Behavior
|
|
200
407
|
|
|
201
|
-
memorio runs everywhere JavaScript does
|
|
408
|
+
memorio runs everywhere JavaScript does - but "everywhere" means different guarantees in different places, and we'd rather tell you now than have you find out at 2am:
|
|
202
409
|
|
|
203
410
|
| API | Browser | Node.js | Deno | Edge / Workers |
|
|
204
411
|
|---|---|---|---|---|
|
|
205
412
|
| `state` | Proxy in memory | Proxy in memory | Proxy in memory | Proxy in memory |
|
|
206
413
|
| `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
|
|
207
414
|
| `cache` | ✅ in memory | ✅ in memory | ✅ in memory | ✅ in memory |
|
|
208
|
-
| `store` | `localStorage` | `Map` fallback
|
|
209
|
-
| `session` | `sessionStorage` | `Map` fallback
|
|
415
|
+
| `store` | `localStorage` | `Map` fallback - **not durable across restarts** | `Map` fallback - not durable | `localStorage` where available, else `Map` |
|
|
416
|
+
| `session` | `sessionStorage` | `Map` fallback - not durable | `Map` fallback - not durable | `sessionStorage` where available, else `Map` |
|
|
210
417
|
| `idb` | ✅ `IndexedDB` | ❌ not available | ❌ not available | ⚠️ check `getCapabilities()` |
|
|
211
418
|
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
212
419
|
|
|
213
|
-
Same API top to bottom
|
|
420
|
+
Same API top to bottom - that's the promise. But if your server code leans on `store.get(...)` surviving a redeploy, know that on Node/Deno it won't; the fallback is an in-memory cache with the same shape, not durable storage.
|
|
214
421
|
|
|
215
422
|
```javascript
|
|
216
423
|
memorio.isBrowser()
|
|
@@ -234,10 +441,10 @@ const ctx = memorio.createContext('tenant-123')
|
|
|
234
441
|
ctx.state.user = { name: 'Isolated' }
|
|
235
442
|
ctx.store.set('settings', { theme: 'dark' })
|
|
236
443
|
|
|
237
|
-
console.debug(state.user) // undefined
|
|
444
|
+
console.debug(state.user) // undefined - separate namespace
|
|
238
445
|
```
|
|
239
446
|
|
|
240
|
-
Handy for keeping per-tenant or per-request state from colliding in the same process. Under the hood it's a key prefix (`tenant-123-key`) inside the same storage
|
|
447
|
+
Handy for keeping per-tenant or per-request state from colliding in the same process. Under the hood it's a key prefix (`tenant-123-key`) inside the same storage - a naming convention, not a hard memory boundary. Great for a browser tab; if you're running this in a shared Node.js process or an edge isolate that might be reused across requests, make sure tenant IDs can't collide or be forged, and don't treat this as your only isolation layer if the stakes are real.
|
|
241
448
|
|
|
242
449
|
---
|
|
243
450
|
|
|
@@ -248,9 +455,9 @@ Handy for keeping per-tenant or per-request state from colliding in the same pro
|
|
|
248
455
|
- Session IDs generated via `crypto.randomUUID`.
|
|
249
456
|
- Inputs validated, keys sanitized, errors caught at module boundaries.
|
|
250
457
|
|
|
251
|
-
memorio does **not** encrypt what you put into `store`, `session`, or `idb`
|
|
458
|
+
memorio does **not** encrypt what you put into `store`, `session`, or `idb` - they're thin, fast wrappers over `localStorage`/`sessionStorage`/`IndexedDB`, which store data in the clear on the user's device. Bring your own encryption layer for tokens, secrets, or regulated personal data.
|
|
252
459
|
|
|
253
|
-
We build with recognized engineering guidance (NIST SP 800-53 practices) as an input to how we write code
|
|
460
|
+
We build with recognized engineering guidance (NIST SP 800-53 practices) as an input to how we write code - that's a design discipline, not a compliance certificate, and no third-party audit has been performed. Found an issue? Report it privately - see `SECURITY.md` - rather than opening a public issue.
|
|
254
461
|
|
|
255
462
|
---
|
|
256
463
|
|
package/SECURITY.md
CHANGED
|
@@ -24,15 +24,15 @@ Memorio follows NIST and NSA security standards at the enterprise level.
|
|
|
24
24
|
## OWASP Compliance
|
|
25
25
|
|
|
26
26
|
Addresses OWASP Top 10 (2021):
|
|
27
|
-
- A01:2021
|
|
28
|
-
- A02:2021
|
|
29
|
-
- A03:2021
|
|
30
|
-
- A05:2021
|
|
31
|
-
- A06:2021
|
|
32
|
-
- A07:2021
|
|
33
|
-
- A08:2021
|
|
34
|
-
- A09:2021
|
|
35
|
-
- A10:2021
|
|
27
|
+
- A01:2021 - Broken Access Control (global object protection, property locks)
|
|
28
|
+
- A02:2021 - Cryptographic Failures (crypto.randomUUID for session IDs)
|
|
29
|
+
- A03:2021 - Injection (CSS sanitization in devtools)
|
|
30
|
+
- A05:2021 - Security Misconfiguration (minimal surface area, no bundled secrets)
|
|
31
|
+
- A06:2021 - Vulnerable and Outdated Components (regular npm audit, Socket.dev)
|
|
32
|
+
- A07:2021 - Identification and Authentication Failures (N/A - library, no auth)
|
|
33
|
+
- A08:2021 - Software and Data Integrity Failures (strict tsconfig, lock files)
|
|
34
|
+
- A09:2021 - Security Logging and Monitoring Failures (DevTools inspect, Logger module)
|
|
35
|
+
- A10:2021 - Server-Side Request Forgery (N/A - no network requests)
|
|
36
36
|
|
|
37
37
|
## Reporting Security Issues
|
|
38
38
|
|
|
@@ -44,5 +44,5 @@ If you find a security vulnerability:
|
|
|
44
44
|
Do not open public issues for security vulnerabilities.
|
|
45
45
|
|
|
46
46
|
---
|
|
47
|
-
*Document version: 2.0
|
|
47
|
+
*Document version: 2.0 - Last updated: 2026-05-19*
|
|
48
48
|
*Owner: BigLogic Security Team*
|
package/SUMMARY.md
CHANGED
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
* [Session](markdown/SESSION.md) - Temporary sessionStorage management
|
|
14
14
|
* [IDB](markdown/IDB.md) - IndexedDB for large data storage
|
|
15
15
|
|
|
16
|
+
## Typed & Validated
|
|
17
|
+
|
|
18
|
+
* [Typed Stores](markdown/TYPED.md) - Compile-time type safety for state access
|
|
19
|
+
* [Schema Validation](markdown/SCHEMA.md) - Runtime validation of state mutations
|
|
20
|
+
|
|
21
|
+
## History & Introspection
|
|
22
|
+
|
|
23
|
+
* [History](markdown/HISTORY.md) - Snapshot, diff, undo/redo, trace
|
|
24
|
+
* [Introspection](markdown/INSPECT.md) - stateKeys, pathExists, stateType, stateSchema
|
|
25
|
+
|
|
26
|
+
## Memory System
|
|
27
|
+
|
|
28
|
+
* [Memory](markdown/MEMORY.md) - Semantic memory layer with TTL, confidence, scopes
|
|
29
|
+
|
|
16
30
|
## Platform & Compatibility
|
|
17
31
|
|
|
18
32
|
* [Platform & Context Isolation](markdown/PLATFORM.md) - Cross-platform support, session isolation
|