fix(session): snapshot seed + appended data at the boundary (review #31)
The source-level JSON-serializability invariant was only a preflight: the Session constructor copied the seed array but shared every event/data object with the caller, and append() stored the caller's `data` reference verbatim. A post-create/post-append mutation could rewrite the durable log or reintroduce a non-JSON-serializable value AFTER validation, so session.events could diverge from what was validated / what a backend can persist. - ctor deep-clones each seed event after validation (not just the array). - append() stores structuredClone(data) (serializability already checked, so the clone is safe); the returned event carries the same snapshot. Regression tests: mutating the original seed / the passed append object after the call leaves session.events unchanged. Adapted the dev-freeze invariants test to assert on the logged clone (append no longer freezes the caller's input). Documented isJsonValue's exact scope (own enumerable string keys, matching JSON.stringify) and synced the README create() signature with meta.createdAt.
This commit is contained in:
@@ -8,7 +8,7 @@ Creates and holds event-sourced `Session` instances. Persistence is intentionall
|
||||
|
||||
### Public API
|
||||
|
||||
- `ctx.sessions.create(id?: string, options?: { seed?: SessionEvent[]; meta?: { cwd?: string; parentSession?: SessionId } }): Session` — Create a session. `options.seed` replays/forks an existing event log; `options.meta` attaches creation metadata (validated absolute `cwd`, `parentSession` lineage) as the immutable `SessionHeader` (the store fills `version`/`id`/`createdAt`). Disposed with the calling fiber.
|
||||
- `ctx.sessions.create(id?: string, options?: { seed?: SessionEvent[]; meta?: { cwd?: string; parentSession?: SessionId; createdAt?: number } }): Session` — Create a session. `options.seed` replays/forks an existing event log; `options.meta` attaches creation metadata (validated absolute `cwd`, `parentSession` lineage) as the immutable `SessionHeader`. The store fills `version`/`id` and defaults `createdAt` to now; a caller reconstructing a persisted session passes the original `createdAt` to preserve it. Disposed with the calling fiber.
|
||||
- `ctx.sessions.get(id: string): Session | undefined`
|
||||
- `ctx.sessions.list(): Session[]`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user