@oscharko-dev/keiko-memory-vault 0.2.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.
Files changed (59) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/access.d.ts +12 -0
  3. package/dist/access.d.ts.map +1 -0
  4. package/dist/access.js +79 -0
  5. package/dist/cipher.d.ts +17 -0
  6. package/dist/cipher.d.ts.map +1 -0
  7. package/dist/cipher.js +95 -0
  8. package/dist/db.d.ts +12 -0
  9. package/dist/db.d.ts.map +1 -0
  10. package/dist/db.js +80 -0
  11. package/dist/edges.d.ts +8 -0
  12. package/dist/edges.d.ts.map +1 -0
  13. package/dist/edges.js +47 -0
  14. package/dist/embeddings.d.ts +10 -0
  15. package/dist/embeddings.d.ts.map +1 -0
  16. package/dist/embeddings.js +116 -0
  17. package/dist/errors.d.ts +14 -0
  18. package/dist/errors.d.ts.map +1 -0
  19. package/dist/errors.js +20 -0
  20. package/dist/index.d.ts +7 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +9 -0
  23. package/dist/memories.d.ts +11 -0
  24. package/dist/memories.d.ts.map +1 -0
  25. package/dist/memories.js +195 -0
  26. package/dist/migrate-encrypt.d.ts +4 -0
  27. package/dist/migrate-encrypt.d.ts.map +1 -0
  28. package/dist/migrate-encrypt.js +69 -0
  29. package/dist/paths.d.ts +6 -0
  30. package/dist/paths.d.ts.map +1 -0
  31. package/dist/paths.js +82 -0
  32. package/dist/redact-record.d.ts +8 -0
  33. package/dist/redact-record.d.ts.map +1 -0
  34. package/dist/redact-record.js +67 -0
  35. package/dist/schema.d.ts +5 -0
  36. package/dist/schema.d.ts.map +1 -0
  37. package/dist/schema.js +206 -0
  38. package/dist/scope-key.d.ts +4 -0
  39. package/dist/scope-key.d.ts.map +1 -0
  40. package/dist/scope-key.js +27 -0
  41. package/dist/serialize.d.ts +67 -0
  42. package/dist/serialize.d.ts.map +1 -0
  43. package/dist/serialize.js +213 -0
  44. package/dist/tombstones.d.ts +8 -0
  45. package/dist/tombstones.d.ts.map +1 -0
  46. package/dist/tombstones.js +57 -0
  47. package/dist/types.d.ts +127 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +4 -0
  50. package/dist/validate.d.ts +8 -0
  51. package/dist/validate.d.ts.map +1 -0
  52. package/dist/validate.js +71 -0
  53. package/dist/vault.d.ts +3 -0
  54. package/dist/vault.d.ts.map +1 -0
  55. package/dist/vault.js +301 -0
  56. package/dist/version.d.ts +2 -0
  57. package/dist/version.d.ts.map +1 -0
  58. package/dist/version.js +1 -0
  59. package/package.json +31 -0
@@ -0,0 +1,127 @@
1
+ import type { MemoryEdge, MemoryEdgeId, MemoryId, MemoryRecord, MemoryReviewerId, MemoryScope, MemoryScopeKind, MemoryStatus, MemoryType } from "@oscharko-dev/keiko-contracts/memory";
2
+ import type { MemoryContentCipher } from "./cipher.js";
3
+ import type { MemoryAccessStat } from "./access.js";
4
+ export type { MemoryAccessStat } from "./access.js";
5
+ export type MemoryEmbeddingMetric = "cosine" | "euclidean" | "dot";
6
+ export interface MemoryEmbeddingInput {
7
+ readonly provider: string;
8
+ readonly modelId: string;
9
+ readonly modelRevision?: string;
10
+ readonly metric: MemoryEmbeddingMetric;
11
+ readonly vector: Float32Array;
12
+ }
13
+ export interface MemoryEmbeddingRow {
14
+ readonly memoryId: MemoryId;
15
+ readonly provider: string;
16
+ readonly modelId: string;
17
+ readonly modelRevision?: string;
18
+ readonly dimensions: number;
19
+ readonly metric: MemoryEmbeddingMetric;
20
+ readonly vector: Float32Array;
21
+ readonly createdAt: number;
22
+ }
23
+ export interface MemoryTombstone {
24
+ readonly id: string;
25
+ readonly memoryId: MemoryId;
26
+ readonly scopeKind: MemoryScopeKind;
27
+ readonly scopeCoordinate: string;
28
+ readonly type: MemoryType;
29
+ readonly forgottenAt: number;
30
+ readonly forgetterSurface: string;
31
+ readonly reviewerId?: MemoryReviewerId;
32
+ readonly originalStatus?: MemoryStatus;
33
+ readonly reason?: string;
34
+ }
35
+ export type MemoryEvent = {
36
+ readonly kind: "memory:inserted";
37
+ readonly record: MemoryRecord;
38
+ } | {
39
+ readonly kind: "memory:updated";
40
+ readonly record: MemoryRecord;
41
+ } | {
42
+ readonly kind: "memory:deleted";
43
+ readonly memoryId: MemoryId;
44
+ readonly scope: MemoryScope;
45
+ readonly tombstoned: boolean;
46
+ } | {
47
+ readonly kind: "memory:tombstoned";
48
+ readonly tombstone: MemoryTombstone;
49
+ } | {
50
+ readonly kind: "edge:inserted";
51
+ readonly edge: MemoryEdge;
52
+ } | {
53
+ readonly kind: "edge:deleted";
54
+ readonly edgeId: MemoryEdgeId;
55
+ } | {
56
+ readonly kind: "embedding:upserted";
57
+ readonly memoryId: MemoryId;
58
+ readonly provider: string;
59
+ readonly modelId: string;
60
+ };
61
+ export type MemoryUpdatePatch = Partial<Omit<MemoryRecord, "id" | "schemaVersion" | "scope" | "createdAt">>;
62
+ export interface MemoryBatchUpdate {
63
+ readonly id: MemoryId;
64
+ readonly patch: MemoryUpdatePatch;
65
+ readonly nowMs: number;
66
+ }
67
+ export interface MemoryBatchDelete {
68
+ readonly id: MemoryId;
69
+ readonly options: DeleteMemoryOptions;
70
+ }
71
+ export interface MemoryDeleteResult {
72
+ readonly memoryId: MemoryId;
73
+ readonly scope: MemoryScope;
74
+ readonly tombstone: MemoryTombstone | undefined;
75
+ }
76
+ export interface ListMemoriesOptions {
77
+ readonly type?: readonly MemoryType[];
78
+ readonly status?: readonly MemoryStatus[];
79
+ readonly pinned?: boolean;
80
+ readonly includeExpired?: boolean;
81
+ readonly limit?: number;
82
+ readonly offset?: number;
83
+ readonly orderBy?: "createdAt" | "updatedAt" | "validFrom";
84
+ readonly orderDir?: "asc" | "desc";
85
+ readonly nowMs?: number;
86
+ }
87
+ export interface DeleteMemoryOptions {
88
+ readonly tombstone: boolean;
89
+ readonly forgetterSurface: string;
90
+ readonly reviewerId?: MemoryReviewerId;
91
+ readonly reason?: string;
92
+ readonly nowMs: number;
93
+ }
94
+ export interface MemoryVaultStore {
95
+ readonly insertMemory: (record: MemoryRecord) => MemoryRecord;
96
+ readonly updateMemory: (id: MemoryId, patch: MemoryUpdatePatch, nowMs: number) => MemoryRecord;
97
+ readonly updateMemories: (updates: readonly MemoryBatchUpdate[]) => readonly MemoryRecord[];
98
+ readonly getMemory: (id: MemoryId) => MemoryRecord | undefined;
99
+ readonly deleteMemory: (id: MemoryId, options: DeleteMemoryOptions) => void;
100
+ readonly deleteMemories: (deletes: readonly MemoryBatchDelete[]) => readonly MemoryDeleteResult[];
101
+ readonly listMemories: (options?: ListMemoriesOptions) => readonly MemoryRecord[];
102
+ readonly listMemoriesByScope: (scope: MemoryScope, options?: ListMemoriesOptions) => readonly MemoryRecord[];
103
+ readonly insertEdge: (edge: MemoryEdge) => MemoryEdge;
104
+ readonly listOutgoingEdges: (memoryId: MemoryId) => readonly MemoryEdge[];
105
+ readonly listIncomingEdges: (memoryId: MemoryId) => readonly MemoryEdge[];
106
+ readonly deleteEdge: (edgeId: MemoryEdgeId) => void;
107
+ readonly upsertEmbedding: (memoryId: MemoryId, embedding: MemoryEmbeddingInput) => void;
108
+ readonly getEmbedding: (memoryId: MemoryId) => MemoryEmbeddingRow | undefined;
109
+ readonly getEmbeddings: (memoryIds: readonly MemoryId[]) => ReadonlyMap<MemoryId, MemoryEmbeddingRow>;
110
+ readonly listTombstonesByScope: (scope: MemoryScope) => readonly MemoryTombstone[];
111
+ readonly purgeTombstonesByScopeBefore: (scope: MemoryScope, forgottenBeforeMs: number) => number;
112
+ readonly recordAccess: (ids: readonly MemoryId[], nowMs: number) => void;
113
+ readonly recordOutcome: (ids: readonly MemoryId[], utility: number, nowMs: number) => void;
114
+ readonly getAccessStats: (ids?: readonly MemoryId[]) => ReadonlyMap<MemoryId, MemoryAccessStat>;
115
+ readonly close: () => void;
116
+ }
117
+ export interface MemoryVaultFactoryOptions {
118
+ readonly memoryDir?: string;
119
+ readonly env?: Readonly<Record<string, string | undefined>>;
120
+ readonly now?: () => number;
121
+ readonly newTombstoneId?: () => string;
122
+ readonly redactString?: (input: string) => string;
123
+ readonly onMemoryEvent?: (event: MemoryEvent) => void;
124
+ readonly cipher?: MemoryContentCipher;
125
+ readonly vaultKey?: Buffer;
126
+ }
127
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ // Public port + supporting types for the memory vault. Package-local types (tombstone, embedding
2
+ // I/O, event union) live here so downstream packages compose them through the barrel without
3
+ // having to know the SQLite encoding.
4
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { MemoryEdge, MemoryRecord, MemoryScope } from "@oscharko-dev/keiko-contracts/memory";
2
+ import type { DeleteMemoryOptions, MemoryEmbeddingInput } from "./types.js";
3
+ export declare function gateMemoryRecord(record: MemoryRecord): MemoryRecord;
4
+ export declare function gateMemoryEdge(edge: MemoryEdge): MemoryEdge;
5
+ export declare function gateMemoryScope(scope: MemoryScope): MemoryScope;
6
+ export declare function gateEmbeddingInput(input: MemoryEmbeddingInput): MemoryEmbeddingInput;
7
+ export declare function gateDeleteOptions(options: DeleteMemoryOptions): DeleteMemoryOptions;
8
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAGlG,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAM5E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAMnE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAM3D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAQ/D;AAkBD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG,oBAAoB,CAMpF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAenF"}
@@ -0,0 +1,71 @@
1
+ // Validator-gate helpers. Wraps the contract validators from @oscharko-dev/keiko-contracts/memory
2
+ // in throw-on-failure form so the vault factory stays imperative. The structured failure list is
3
+ // preserved on the thrown MemoryStorageValidationError so the caller can branch on `.failures`.
4
+ import { validateMemoryEdge, validateMemoryRecord, validateMemoryScope, } from "@oscharko-dev/keiko-contracts/memory";
5
+ import { MemoryStorageValidationError } from "./errors.js";
6
+ import { ALLOWED_EMBEDDING_METRICS, MAX_EMBEDDING_DIMENSIONS } from "./embeddings.js";
7
+ function toFailures(errors) {
8
+ return errors.map((message) => ({ path: [], message }));
9
+ }
10
+ export function gateMemoryRecord(record) {
11
+ const result = validateMemoryRecord(record);
12
+ if (!result.ok) {
13
+ throw new MemoryStorageValidationError("Invalid memory record.", toFailures(result.errors));
14
+ }
15
+ return result.value;
16
+ }
17
+ export function gateMemoryEdge(edge) {
18
+ const result = validateMemoryEdge(edge);
19
+ if (!result.ok) {
20
+ throw new MemoryStorageValidationError("Invalid memory edge.", toFailures(result.errors));
21
+ }
22
+ return result.value;
23
+ }
24
+ export function gateMemoryScope(scope) {
25
+ const result = validateMemoryScope(scope);
26
+ if (!result.ok) {
27
+ throw new MemoryStorageValidationError("Invalid memory scope.", toFailures(result.errors));
28
+ }
29
+ // validateMemoryScope's signature returns `MemoryValidation<undefined>` — it asserts shape but
30
+ // does not narrow. The input has the type we promised so we return it directly.
31
+ return scope;
32
+ }
33
+ function collectEmbeddingErrors(input) {
34
+ const errors = [];
35
+ if (input.provider.length === 0)
36
+ errors.push("embedding.provider must be non-empty");
37
+ if (input.modelId.length === 0)
38
+ errors.push("embedding.modelId must be non-empty");
39
+ if (input.vector.length === 0)
40
+ errors.push("embedding.vector must have at least one dimension");
41
+ if (input.vector.length > MAX_EMBEDDING_DIMENSIONS) {
42
+ errors.push(`embedding.vector length ${String(input.vector.length)} exceeds maximum ${String(MAX_EMBEDDING_DIMENSIONS)}`);
43
+ }
44
+ if (!ALLOWED_EMBEDDING_METRICS.includes(input.metric)) {
45
+ errors.push(`embedding.metric must be one of ${ALLOWED_EMBEDDING_METRICS.join("|")}`);
46
+ }
47
+ return errors;
48
+ }
49
+ export function gateEmbeddingInput(input) {
50
+ const errors = collectEmbeddingErrors(input);
51
+ if (errors.length > 0) {
52
+ throw new MemoryStorageValidationError("Invalid embedding input.", toFailures(errors));
53
+ }
54
+ return input;
55
+ }
56
+ export function gateDeleteOptions(options) {
57
+ const errors = [];
58
+ if (options.forgetterSurface.length === 0) {
59
+ errors.push("deleteOptions.forgetterSurface must be non-empty");
60
+ }
61
+ if (options.reviewerId?.length === 0) {
62
+ errors.push("deleteOptions.reviewerId must be non-empty when provided");
63
+ }
64
+ if (!Number.isFinite(options.nowMs) || options.nowMs < 0) {
65
+ errors.push("deleteOptions.nowMs must be a finite non-negative number");
66
+ }
67
+ if (errors.length > 0) {
68
+ throw new MemoryStorageValidationError("Invalid delete options.", toFailures(errors));
69
+ }
70
+ return options;
71
+ }
@@ -0,0 +1,3 @@
1
+ import type { MemoryVaultFactoryOptions, MemoryVaultStore } from "./types.js";
2
+ export declare function createMemoryVault(options?: MemoryVaultFactoryOptions): MemoryVaultStore;
3
+ //# sourceMappingURL=vault.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AA4DA,OAAO,KAAK,EAWV,yBAAyB,EACzB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAgYpB,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,gBAAgB,CAMvF"}
package/dist/vault.js ADDED
@@ -0,0 +1,301 @@
1
+ // createMemoryVault — the integration layer. Composes path resolution, DB lifecycle, validator
2
+ // gate, boundary redaction, prepared-SQL adapters, and the optional onMemoryEvent callback into
3
+ // a single MemoryVaultStore port. Every public method follows the same order:
4
+ //
5
+ // 1. validate (throws MemoryStorageValidationError before any SQL touches)
6
+ // 2. redact at the boundary (applies the factory redactString to free-text fields)
7
+ // 3. execute the prepared SQL (transactional when the method writes more than one row)
8
+ // 4. fire onMemoryEvent (AFTER commit, never on rollback)
9
+ //
10
+ // Steps 1-3 are pure-functional in TS-space until the SQL prepare() runs, so a thrown validator
11
+ // or redact exception leaves the database untouched. Step 4 sees only the post-commit truth.
12
+ import { DatabaseSync } from "node:sqlite";
13
+ import { randomUUID } from "node:crypto";
14
+ import { openMemoryDatabase } from "./db.js";
15
+ import { resolveMemoryDir, resolveMemoryDbPath } from "./paths.js";
16
+ import { createMemoryContentCipher, resolveVaultKey } from "./cipher.js";
17
+ import { scopeCoordinateOf, scopeKindOf } from "./scope-key.js";
18
+ import { deleteMemoryRow, getMemoryRow, insertMemoryRow, listMemoriesRows, listMemoriesByScopeRows, updateMemoryRow, } from "./memories.js";
19
+ import { deleteEdgeRow, insertEdgeRow, listIncomingEdgeRows, listOutgoingEdgeRows, } from "./edges.js";
20
+ import { getEmbeddingRow, getEmbeddingRows, upsertEmbeddingRow } from "./embeddings.js";
21
+ import { getAccessStatsRows, recordAccessRows, recordOutcomeRows, } from "./access.js";
22
+ import { deleteTombstonesByScopeBeforeRows, insertTombstoneRow, listTombstonesByScopeRows, } from "./tombstones.js";
23
+ import { gateDeleteOptions, gateEmbeddingInput, gateMemoryEdge, gateMemoryRecord, gateMemoryScope, } from "./validate.js";
24
+ import { redactMemoryEdge, redactMemoryRecord, redactTombstone } from "./redact-record.js";
25
+ import { MemoryStorageError } from "./errors.js";
26
+ const IDENTITY = (s) => s;
27
+ const NOOP_EMIT = () => undefined;
28
+ // Single named entry point for the default environment read so the literal `process.env`
29
+ // reference does not appear inline in business logic (audit AC19).
30
+ function defaultEnv() {
31
+ return process.env;
32
+ }
33
+ function resolveOptions(opts, cipher) {
34
+ return {
35
+ now: opts?.now ?? (() => Date.now()),
36
+ newTombstoneId: opts?.newTombstoneId ?? (() => randomUUID()),
37
+ redactString: opts?.redactString ?? IDENTITY,
38
+ emit: opts?.onMemoryEvent ?? NOOP_EMIT,
39
+ cipher,
40
+ };
41
+ }
42
+ // Resolve the content cipher. Precedence: an explicitly injected cipher (tests), then an injected
43
+ // raw key (tests/CI), then the real tiered resolver (KEIKO_MEMORY_KEY > keychain > keyfile). The
44
+ // public factory never requires any of these — production callers get the tiered resolver.
45
+ function resolveCipher(opts, env) {
46
+ if (opts?.cipher !== undefined)
47
+ return opts.cipher;
48
+ if (opts?.vaultKey !== undefined)
49
+ return createMemoryContentCipher(opts.vaultKey);
50
+ const memoryDir = resolveMemoryDir(opts?.memoryDir, env);
51
+ return createMemoryContentCipher(resolveVaultKey(env, memoryDir).key);
52
+ }
53
+ // Validate-then-redact for inserts. The validator runs on the CALLER-SUPPLIED record so a
54
+ // validation failure carries the caller's exact failure list. Redaction runs SECOND so the SQL
55
+ // row is the redacted form — a secret-shaped string that slipped past the capture-layer gate
56
+ // in #207 is scrubbed before persistence.
57
+ function preparedForWrite(record, opts) {
58
+ const validated = gateMemoryRecord(record);
59
+ return redactMemoryRecord(validated, opts.redactString);
60
+ }
61
+ function preparedEdgeForWrite(edge, opts) {
62
+ const validated = gateMemoryEdge(edge);
63
+ return redactMemoryEdge(validated, opts.redactString);
64
+ }
65
+ function mergePatch(existing, patch, nowMs) {
66
+ // updatedAt is owned by the vault, not the patch, so the caller cannot regress it. createdAt
67
+ // and the scope coordinate are immutable on update (scope changes require supersession +
68
+ // re-insert by design — moving a record across scopes is an audit event, not a field write).
69
+ const next = {
70
+ ...existing,
71
+ ...patch,
72
+ id: existing.id,
73
+ schemaVersion: existing.schemaVersion,
74
+ scope: existing.scope,
75
+ createdAt: existing.createdAt,
76
+ updatedAt: nowMs,
77
+ };
78
+ return next;
79
+ }
80
+ function existingMemoryOrThrow(db, id, cipher) {
81
+ const existing = getMemoryRow(db, id, cipher);
82
+ if (existing === undefined) {
83
+ throw new MemoryStorageError("not-found", "Memory not found.");
84
+ }
85
+ return existing;
86
+ }
87
+ function buildTombstone(record, options, opts) {
88
+ const base = {
89
+ id: opts.newTombstoneId(),
90
+ memoryId: record.id,
91
+ scopeKind: scopeKindOf(record.scope),
92
+ scopeCoordinate: scopeCoordinateOf(record.scope),
93
+ type: record.type,
94
+ forgottenAt: options.nowMs,
95
+ forgetterSurface: options.forgetterSurface,
96
+ originalStatus: record.status,
97
+ };
98
+ return {
99
+ ...base,
100
+ ...(options.reviewerId === undefined ? {} : { reviewerId: options.reviewerId }),
101
+ ...(options.reason === undefined ? {} : { reason: options.reason }),
102
+ };
103
+ }
104
+ function prepareDelete(db, id, options, opts) {
105
+ gateDeleteOptions(options);
106
+ const existing = existingMemoryOrThrow(db, id, opts.cipher);
107
+ const tombstone = options.tombstone
108
+ ? redactTombstone(buildTombstone(existing, options, opts), opts.redactString)
109
+ : undefined;
110
+ return { memoryId: id, scope: existing.scope, tombstone };
111
+ }
112
+ function applyPreparedDelete(db, result, opts) {
113
+ if (!deleteMemoryRow(db, result.memoryId)) {
114
+ throw new MemoryStorageError("not-found", "Memory not found.");
115
+ }
116
+ if (result.tombstone !== undefined) {
117
+ insertTombstoneRow(db, result.tombstone, opts.cipher);
118
+ }
119
+ }
120
+ function runDelete(db, id, options, opts) {
121
+ const ready = prepareDelete(db, id, options, opts);
122
+ db.exec("BEGIN");
123
+ try {
124
+ applyPreparedDelete(db, ready, opts);
125
+ db.exec("COMMIT");
126
+ }
127
+ catch (error) {
128
+ db.exec("ROLLBACK");
129
+ throw error;
130
+ }
131
+ return ready;
132
+ }
133
+ function runBatchDeleteMemories(db, deletes, opts) {
134
+ const ready = deletes.map((entry) => prepareDelete(db, entry.id, entry.options, opts));
135
+ db.exec("BEGIN");
136
+ try {
137
+ for (const result of ready) {
138
+ applyPreparedDelete(db, result, opts);
139
+ }
140
+ db.exec("COMMIT");
141
+ }
142
+ catch (error) {
143
+ db.exec("ROLLBACK");
144
+ throw error;
145
+ }
146
+ return ready;
147
+ }
148
+ function updateMemoryInPlace(db, update, opts) {
149
+ const existing = existingMemoryOrThrow(db, update.id, opts.cipher);
150
+ const merged = mergePatch(existing, update.patch, update.nowMs);
151
+ const ready = preparedForWrite(merged, opts);
152
+ updateMemoryRow(db, ready, opts.cipher);
153
+ return ready;
154
+ }
155
+ function runBatchUpdateMemories(db, updates, opts) {
156
+ const ready = [];
157
+ db.exec("BEGIN");
158
+ try {
159
+ for (const update of updates) {
160
+ ready.push(updateMemoryInPlace(db, update, opts));
161
+ }
162
+ db.exec("COMMIT");
163
+ }
164
+ catch (error) {
165
+ db.exec("ROLLBACK");
166
+ throw error;
167
+ }
168
+ return ready;
169
+ }
170
+ function emitUpdatedRecords(records, opts) {
171
+ for (const record of records) {
172
+ opts.emit({ kind: "memory:updated", record });
173
+ }
174
+ }
175
+ function emitDeletedRecords(results, opts) {
176
+ for (const result of results) {
177
+ opts.emit({
178
+ kind: "memory:deleted",
179
+ memoryId: result.memoryId,
180
+ scope: result.scope,
181
+ tombstoned: result.tombstone !== undefined,
182
+ });
183
+ if (result.tombstone !== undefined) {
184
+ opts.emit({ kind: "memory:tombstoned", tombstone: result.tombstone });
185
+ }
186
+ }
187
+ }
188
+ function deleteMemoryWithEvents(db, id, options, opts) {
189
+ const result = runDelete(db, id, options, opts);
190
+ emitDeletedRecords([result], opts);
191
+ }
192
+ function buildMemoryMutators(db, opts) {
193
+ return {
194
+ insertMemory: (record) => {
195
+ const ready = preparedForWrite(record, opts);
196
+ insertMemoryRow(db, ready, opts.cipher);
197
+ opts.emit({ kind: "memory:inserted", record: ready });
198
+ return ready;
199
+ },
200
+ updateMemory: (id, patch, nowMs) => {
201
+ const ready = updateMemoryInPlace(db, { id, patch, nowMs }, opts);
202
+ opts.emit({ kind: "memory:updated", record: ready });
203
+ return ready;
204
+ },
205
+ updateMemories: (updates) => {
206
+ const ready = runBatchUpdateMemories(db, updates, opts);
207
+ emitUpdatedRecords(ready, opts);
208
+ return ready;
209
+ },
210
+ deleteMemory: (id, options) => {
211
+ deleteMemoryWithEvents(db, id, options, opts);
212
+ },
213
+ deleteMemories: (deletes) => {
214
+ const ready = runBatchDeleteMemories(db, deletes, opts);
215
+ emitDeletedRecords(ready, opts);
216
+ return ready;
217
+ },
218
+ getMemory: (id) => getMemoryRow(db, id, opts.cipher),
219
+ listMemories: (options) => {
220
+ const effective = options ?? {};
221
+ const nowMs = effective.nowMs ?? opts.now();
222
+ return listMemoriesRows(db, effective, nowMs, opts.cipher);
223
+ },
224
+ listMemoriesByScope: (scope, options) => {
225
+ gateMemoryScope(scope);
226
+ const effective = options ?? {};
227
+ const nowMs = effective.nowMs ?? opts.now();
228
+ return listMemoriesByScopeRows(db, scope, effective, nowMs, opts.cipher);
229
+ },
230
+ };
231
+ }
232
+ function buildEdgeAndEmbeddingOps(db, opts) {
233
+ return {
234
+ insertEdge: (edge) => {
235
+ const ready = preparedEdgeForWrite(edge, opts);
236
+ insertEdgeRow(db, ready, opts.cipher);
237
+ opts.emit({ kind: "edge:inserted", edge: ready });
238
+ return ready;
239
+ },
240
+ listOutgoingEdges: (memoryId) => listOutgoingEdgeRows(db, memoryId, opts.cipher),
241
+ listIncomingEdges: (memoryId) => listIncomingEdgeRows(db, memoryId, opts.cipher),
242
+ deleteEdge: (edgeId) => {
243
+ const removed = deleteEdgeRow(db, edgeId);
244
+ if (!removed) {
245
+ throw new MemoryStorageError("not-found", "Edge not found.");
246
+ }
247
+ opts.emit({ kind: "edge:deleted", edgeId });
248
+ },
249
+ upsertEmbedding: (memoryId, embedding) => {
250
+ gateEmbeddingInput(embedding);
251
+ if (getMemoryRow(db, memoryId, opts.cipher) === undefined) {
252
+ throw new MemoryStorageError("not-found", "Memory not found.");
253
+ }
254
+ upsertEmbeddingRow(db, memoryId, embedding, opts.now(), opts.cipher);
255
+ opts.emit({
256
+ kind: "embedding:upserted",
257
+ memoryId,
258
+ provider: embedding.provider,
259
+ modelId: embedding.modelId,
260
+ });
261
+ },
262
+ getEmbedding: (memoryId) => getEmbeddingRow(db, memoryId, opts.cipher),
263
+ getEmbeddings: (memoryIds) => getEmbeddingRows(db, memoryIds, opts.cipher),
264
+ };
265
+ }
266
+ function buildTombstoneAndAccessOps(db, opts) {
267
+ return {
268
+ listTombstonesByScope: (scope) => {
269
+ gateMemoryScope(scope);
270
+ return listTombstonesByScopeRows(db, scope, opts.cipher);
271
+ },
272
+ purgeTombstonesByScopeBefore: (scope, forgottenBeforeMs) => {
273
+ gateMemoryScope(scope);
274
+ return deleteTombstonesByScopeBeforeRows(db, scope, forgottenBeforeMs);
275
+ },
276
+ recordAccess: (ids, nowMs) => {
277
+ recordAccessRows(db, ids, nowMs);
278
+ },
279
+ recordOutcome: (ids, utility, nowMs) => {
280
+ recordOutcomeRows(db, ids, utility, nowMs);
281
+ },
282
+ getAccessStats: (ids) => getAccessStatsRows(db, ids),
283
+ };
284
+ }
285
+ function buildStore(db, opts) {
286
+ return {
287
+ ...buildMemoryMutators(db, opts),
288
+ ...buildEdgeAndEmbeddingOps(db, opts),
289
+ ...buildTombstoneAndAccessOps(db, opts),
290
+ close: () => {
291
+ db.close();
292
+ },
293
+ };
294
+ }
295
+ export function createMemoryVault(options) {
296
+ const env = options?.env ?? defaultEnv();
297
+ const dbPath = resolveMemoryDbPath(options?.memoryDir, env);
298
+ const cipher = resolveCipher(options, env);
299
+ const db = openMemoryDatabase(dbPath, cipher);
300
+ return buildStore(db, resolveOptions(options, cipher));
301
+ }
@@ -0,0 +1,2 @@
1
+ export declare const KEIKO_MEMORY_VAULT_VERSION: "0.1.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B,EAAG,OAAgB,CAAC"}
@@ -0,0 +1 @@
1
+ export const KEIKO_MEMORY_VAULT_VERSION = "0.1.0";
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@oscharko-dev/keiko-memory-vault",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "license": "Apache-2.0",
6
+ "description": "MemoriaViva — Internal memory-vault package: governed enterprise memory storage (node:sqlite). Scope-isolated CRUD, edges, embeddings, tombstones, validator-gated boundary, redaction-aware writes (ADR-0019 + Epic #204). Not published independently.",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc -b tsconfig.json",
17
+ "typecheck": "tsc -b tsconfig.json",
18
+ "test": "vitest run"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "sideEffects": false,
24
+ "engines": {
25
+ "node": ">=22"
26
+ },
27
+ "dependencies": {
28
+ "@oscharko-dev/keiko-contracts": "0.2.0",
29
+ "@oscharko-dev/keiko-security": "0.2.0"
30
+ }
31
+ }