@kybernesis/brain-storage-sqlite 0.8.3 → 0.9.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 (37) hide show
  1. package/dist/index.d.ts +6 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +27 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/migrations/backup.d.ts +14 -0
  6. package/dist/migrations/backup.d.ts.map +1 -0
  7. package/dist/migrations/backup.js +20 -0
  8. package/dist/migrations/backup.js.map +1 -0
  9. package/dist/migrations/config.d.ts +14 -0
  10. package/dist/migrations/config.d.ts.map +1 -0
  11. package/dist/migrations/config.js +24 -0
  12. package/dist/migrations/config.js.map +1 -0
  13. package/dist/migrations/errors.d.ts +24 -0
  14. package/dist/migrations/errors.d.ts.map +1 -0
  15. package/dist/migrations/errors.js +45 -0
  16. package/dist/migrations/errors.js.map +1 -0
  17. package/dist/migrations/registry.d.ts +15 -0
  18. package/dist/migrations/registry.d.ts.map +1 -0
  19. package/dist/migrations/registry.js +33 -0
  20. package/dist/migrations/registry.js.map +1 -0
  21. package/dist/migrations/runner.d.ts +57 -0
  22. package/dist/migrations/runner.d.ts.map +1 -0
  23. package/dist/migrations/runner.js +141 -0
  24. package/dist/migrations/runner.js.map +1 -0
  25. package/dist/migrations/timeline/002-proof.d.ts +13 -0
  26. package/dist/migrations/timeline/002-proof.d.ts.map +1 -0
  27. package/dist/migrations/timeline/002-proof.js +16 -0
  28. package/dist/migrations/timeline/002-proof.js.map +1 -0
  29. package/dist/migrations/types.d.ts +52 -0
  30. package/dist/migrations/types.d.ts.map +1 -0
  31. package/dist/migrations/types.js +15 -0
  32. package/dist/migrations/types.js.map +1 -0
  33. package/dist/provider.d.ts +12 -1
  34. package/dist/provider.d.ts.map +1 -1
  35. package/dist/provider.js +5 -1
  36. package/dist/provider.js.map +1 -1
  37. package/package.json +5 -4
package/dist/index.d.ts CHANGED
@@ -4,6 +4,12 @@ export { sanitizeFtsQuery } from './fts-sanitizer.js';
4
4
  export { resetTimelineSchemaCache } from './timeline.js';
5
5
  export { resetEntityGraphSchemaCache } from './entity-graph.js';
6
6
  export { ensureSleepSchema, recoverStaleSleepRuns, resetSleepSchemaCache } from './sleep-store.js';
7
+ export { runMigrations } from './migrations/runner.js';
8
+ export { copyFileBackup } from './migrations/backup.js';
9
+ export { setAutoMigrate } from './migrations/config.js';
10
+ export { registry as migrationRegistry, sentinelTables } from './migrations/registry.js';
11
+ export { SchemaAheadError, SchemaBehindError, ChecksumDriftError } from './migrations/errors.js';
12
+ export type { Migration, MigrationKind, MigrationOptions } from './migrations/types.js';
7
13
  import type { TenantContext } from '@kybernesis/brain-contracts';
8
14
  export type DbKind = 'timeline' | 'entityGraph' | 'vectors' | 'sleep' | 'idempotency';
9
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAWhE,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAgBtF;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAevE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAOjD;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAK/B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAWhE,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAKnG,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjG,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAIxF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAkBtF;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CA2BvE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAOjD;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAK/B"}
package/dist/index.js CHANGED
@@ -16,7 +16,19 @@ export { resetEntityGraphSchemaCache } from './entity-graph.js';
16
16
  // any module on this cycle — either would TDZ-throw on import
17
17
  // ('Cannot access getDb before initialization').
18
18
  export { ensureSleepSchema, recoverStaleSleepRuns, resetSleepSchemaCache } from './sleep-store.js';
19
+ // Migration surface (Spec A). runMigrations is a STANDALONE primitive — the
20
+ // trigger is consumer-chosen: local apps opt in via setAutoMigrate / the
21
+ // provider's autoMigrate option; Arcana serving runs mode:'check' and its
22
+ // migrator job drives mode:'apply' per tenant.
23
+ export { runMigrations } from './migrations/runner.js';
24
+ export { copyFileBackup } from './migrations/backup.js';
25
+ export { setAutoMigrate } from './migrations/config.js';
26
+ export { registry as migrationRegistry, sentinelTables } from './migrations/registry.js';
27
+ export { SchemaAheadError, SchemaBehindError, ChecksumDriftError } from './migrations/errors.js';
28
+ import { runMigrations } from './migrations/runner.js';
29
+ import { getAutoMigrate } from './migrations/config.js';
19
30
  const pool = new Map();
31
+ const MIGRATABLE_KINDS = ['timeline', 'entityGraph', 'sleep', 'vectors'];
20
32
  function resolveDbPath(t, kind) {
21
33
  switch (kind) {
22
34
  case 'timeline': return t.paths.timelineDbPath;
@@ -45,6 +57,21 @@ export function getDb(t, kind) {
45
57
  db.pragma('journal_mode = WAL');
46
58
  db.pragma('synchronous = NORMAL');
47
59
  db.pragma('foreign_keys = ON');
60
+ // After PRAGMAs, before first use — and before pooling, so a refused DB
61
+ // (SchemaAheadError / SchemaBehindError) is closed, not cached half-open.
62
+ const autoMigrate = getAutoMigrate();
63
+ if (autoMigrate && MIGRATABLE_KINDS.includes(kind)) {
64
+ try {
65
+ runMigrations(db, kind, autoMigrate);
66
+ }
67
+ catch (err) {
68
+ try {
69
+ db.close();
70
+ }
71
+ catch { /* ignore */ }
72
+ throw err;
73
+ }
74
+ }
48
75
  pool.set(key, db);
49
76
  return db;
50
77
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Local backup strategy: WAL-checkpoint then copy the DB file to
3
+ * `<name>.pre-<firstPendingId>.bak` beside it, BEFORE any migration applies.
4
+ *
5
+ * This is the default for local consumers (KBDE / KyberBot). Cloud (Arcana)
6
+ * injects its own hook — snapshot or no-op — via `MigrationOptions.backup`;
7
+ * per-file `.bak` copies don't fit N-tenant scale.
8
+ *
9
+ * Must run OUTSIDE the migration transaction: `wal_checkpoint` cannot execute
10
+ * while a transaction is open. The runner guarantees this ordering.
11
+ */
12
+ import type Database from 'better-sqlite3';
13
+ export declare function copyFileBackup(db: Database.Database, firstPendingId: string): void;
14
+ //# sourceMappingURL=backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/migrations/backup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAKlF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Local backup strategy: WAL-checkpoint then copy the DB file to
3
+ * `<name>.pre-<firstPendingId>.bak` beside it, BEFORE any migration applies.
4
+ *
5
+ * This is the default for local consumers (KBDE / KyberBot). Cloud (Arcana)
6
+ * injects its own hook — snapshot or no-op — via `MigrationOptions.backup`;
7
+ * per-file `.bak` copies don't fit N-tenant scale.
8
+ *
9
+ * Must run OUTSIDE the migration transaction: `wal_checkpoint` cannot execute
10
+ * while a transaction is open. The runner guarantees this ordering.
11
+ */
12
+ import { copyFileSync } from 'node:fs';
13
+ export function copyFileBackup(db, firstPendingId) {
14
+ if (db.memory)
15
+ return; // nothing on disk to back up (tests / ephemeral DBs)
16
+ // Fold the WAL into the main file so the copy is complete and self-contained.
17
+ db.pragma('wal_checkpoint(TRUNCATE)');
18
+ copyFileSync(db.name, `${db.name}.pre-${firstPendingId}.bak`);
19
+ }
20
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/migrations/backup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,MAAM,UAAU,cAAc,CAAC,EAAqB,EAAE,cAAsB;IAC1E,IAAI,EAAE,CAAC,MAAM;QAAE,OAAO,CAAC,qDAAqD;IAC5E,8EAA8E;IAC9E,EAAE,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,QAAQ,cAAc,MAAM,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Auto-migrate trigger config (Spec A) — consumer-chosen, OFF by default.
3
+ *
4
+ * Lives in its own module (not index.ts) so provider.ts can import it without
5
+ * joining the index ↔ sleep-store eval-order cycle documented in index.ts.
6
+ *
7
+ * `true` → the local default: { mode:'apply', backup: copyFileBackup }
8
+ * (KBDE / KyberBot self-heal on open). Cloud serving (Arcana) passes
9
+ * { mode:'check' } — refuse ahead AND behind, never write schema.
10
+ */
11
+ import type { MigrationOptions } from './types.js';
12
+ export declare function setAutoMigrate(config: MigrationOptions | boolean | null): void;
13
+ export declare function getAutoMigrate(): MigrationOptions | null;
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/migrations/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInD,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAI9E;AAED,wBAAgB,cAAc,IAAI,gBAAgB,GAAG,IAAI,CAExD"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Auto-migrate trigger config (Spec A) — consumer-chosen, OFF by default.
3
+ *
4
+ * Lives in its own module (not index.ts) so provider.ts can import it without
5
+ * joining the index ↔ sleep-store eval-order cycle documented in index.ts.
6
+ *
7
+ * `true` → the local default: { mode:'apply', backup: copyFileBackup }
8
+ * (KBDE / KyberBot self-heal on open). Cloud serving (Arcana) passes
9
+ * { mode:'check' } — refuse ahead AND behind, never write schema.
10
+ */
11
+ import { copyFileBackup } from './backup.js';
12
+ let autoMigrateConfig = null;
13
+ export function setAutoMigrate(config) {
14
+ if (config === true)
15
+ autoMigrateConfig = { mode: 'apply', backup: copyFileBackup };
16
+ else if (config === false || config === null)
17
+ autoMigrateConfig = null;
18
+ else
19
+ autoMigrateConfig = config;
20
+ }
21
+ export function getAutoMigrate() {
22
+ return autoMigrateConfig;
23
+ }
24
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/migrations/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,IAAI,iBAAiB,GAA4B,IAAI,CAAC;AAEtD,MAAM,UAAU,cAAc,CAAC,MAAyC;IACtE,IAAI,MAAM,KAAK,IAAI;QAAE,iBAAiB,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;SAC9E,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI;QAAE,iBAAiB,GAAG,IAAI,CAAC;;QAClE,iBAAiB,GAAG,MAAM,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,iBAAiB,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Migration refusal errors (Spec A). All three are LOUD refusals — callers must
3
+ * never swallow them; a brain DB in an unexpected schema state is unusable
4
+ * until a human (or the migrator) intervenes.
5
+ */
6
+ /** The DB has applied migration ids this build doesn't know — code is older than the schema. Refuse in BOTH modes. */
7
+ export declare class SchemaAheadError extends Error {
8
+ readonly kind: string;
9
+ readonly unknownIds: readonly string[];
10
+ constructor(kind: string, unknownIds: readonly string[]);
11
+ }
12
+ /** Pending migrations exist but mode is 'check' (serving path must never mutate schema). */
13
+ export declare class SchemaBehindError extends Error {
14
+ readonly kind: string;
15
+ readonly pendingIds: readonly string[];
16
+ constructor(kind: string, pendingIds: readonly string[]);
17
+ }
18
+ /** An applied migration's recorded checksum no longer matches this build's body — a shipped migration was edited. */
19
+ export declare class ChecksumDriftError extends Error {
20
+ readonly kind: string;
21
+ readonly id: string;
22
+ constructor(kind: string, id: string);
23
+ }
24
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/migrations/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,sHAAsH;AACtH,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,IAAI,EAAE,MAAM;aACZ,UAAU,EAAE,SAAS,MAAM,EAAE;gBAD7B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,MAAM,EAAE;CAShD;AAED,4FAA4F;AAC5F,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,IAAI,EAAE,MAAM;aACZ,UAAU,EAAE,SAAS,MAAM,EAAE;gBAD7B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,MAAM,EAAE;CAShD;AAED,qHAAqH;AACrH,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,IAAI,EAAE,MAAM;aACZ,EAAE,EAAE,MAAM;gBADV,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM;CAS7B"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Migration refusal errors (Spec A). All three are LOUD refusals — callers must
3
+ * never swallow them; a brain DB in an unexpected schema state is unusable
4
+ * until a human (or the migrator) intervenes.
5
+ */
6
+ /** The DB has applied migration ids this build doesn't know — code is older than the schema. Refuse in BOTH modes. */
7
+ export class SchemaAheadError extends Error {
8
+ kind;
9
+ unknownIds;
10
+ constructor(kind, unknownIds) {
11
+ super(`[brain-storage-sqlite] ${kind} DB schema is AHEAD of this build — ` +
12
+ `unknown applied migration(s): ${unknownIds.join(', ')}. ` +
13
+ `Upgrade the consumer; refusing to touch the DB.`);
14
+ this.kind = kind;
15
+ this.unknownIds = unknownIds;
16
+ this.name = 'SchemaAheadError';
17
+ }
18
+ }
19
+ /** Pending migrations exist but mode is 'check' (serving path must never mutate schema). */
20
+ export class SchemaBehindError extends Error {
21
+ kind;
22
+ pendingIds;
23
+ constructor(kind, pendingIds) {
24
+ super(`[brain-storage-sqlite] ${kind} DB schema is BEHIND this build — ` +
25
+ `pending migration(s): ${pendingIds.join(', ')}. ` +
26
+ `Run the migrator (mode:'apply'); serving refuses to migrate.`);
27
+ this.kind = kind;
28
+ this.pendingIds = pendingIds;
29
+ this.name = 'SchemaBehindError';
30
+ }
31
+ }
32
+ /** An applied migration's recorded checksum no longer matches this build's body — a shipped migration was edited. */
33
+ export class ChecksumDriftError extends Error {
34
+ kind;
35
+ id;
36
+ constructor(kind, id) {
37
+ super(`[brain-storage-sqlite] ${kind} migration '${id}' checksum mismatch — ` +
38
+ `a shipped migration was edited in place. Shipped migrations are immutable; ` +
39
+ `add a new migration instead.`);
40
+ this.kind = kind;
41
+ this.id = id;
42
+ this.name = 'ChecksumDriftError';
43
+ }
44
+ }
45
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/migrations/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,sHAAsH;AACtH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAEvB;IACA;IAFlB,YACkB,IAAY,EACZ,UAA6B;QAE7C,KAAK,CACH,0BAA0B,IAAI,sCAAsC;YAClE,iCAAiC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAC1D,iDAAiD,CACpD,CAAC;QAPc,SAAI,GAAJ,IAAI,CAAQ;QACZ,eAAU,GAAV,UAAU,CAAmB;QAO7C,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,4FAA4F;AAC5F,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAExB;IACA;IAFlB,YACkB,IAAY,EACZ,UAA6B;QAE7C,KAAK,CACH,0BAA0B,IAAI,oCAAoC;YAChE,yBAAyB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAClD,8DAA8D,CACjE,CAAC;QAPc,SAAI,GAAJ,IAAI,CAAQ;QACZ,eAAU,GAAV,UAAU,CAAmB;QAO7C,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,qHAAqH;AACrH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAEzB;IACA;IAFlB,YACkB,IAAY,EACZ,EAAU;QAE1B,KAAK,CACH,0BAA0B,IAAI,eAAe,EAAE,wBAAwB;YACrE,6EAA6E;YAC7E,8BAA8B,CACjC,CAAC;QAPc,SAAI,GAAJ,IAAI,CAAQ;QACZ,OAAE,GAAF,EAAE,CAAQ;QAO1B,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Ordered migration registry, one line per DB kind (each DB file has its own
3
+ * `_migrations` table and version line). Append-only: new migrations go at the
4
+ * END of a kind's list; shipped entries are immutable (checksum-guarded).
5
+ */
6
+ import type { Migration, MigrationKind } from './types.js';
7
+ /**
8
+ * Legacy-detection signal per DB (baseline decision, Spec A T6): if this table
9
+ * exists but `_migrations` doesn't, the DB predates the migration system —
10
+ * stamp the baseline without running it. Each name is the oldest table that
11
+ * has existed in that DB since v1.
12
+ */
13
+ export declare const sentinelTables: Readonly<Record<MigrationKind, string>>;
14
+ export declare const registry: Readonly<Record<MigrationKind, readonly Migration[]>>;
15
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/migrations/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAKlE,CAAC;AAYF,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAAC,CAK1E,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Ordered migration registry, one line per DB kind (each DB file has its own
3
+ * `_migrations` table and version line). Append-only: new migrations go at the
4
+ * END of a kind's list; shipped entries are immutable (checksum-guarded).
5
+ */
6
+ /**
7
+ * Legacy-detection signal per DB (baseline decision, Spec A T6): if this table
8
+ * exists but `_migrations` doesn't, the DB predates the migration system —
9
+ * stamp the baseline without running it. Each name is the oldest table that
10
+ * has existed in that DB since v1.
11
+ */
12
+ export const sentinelTables = {
13
+ timeline: 'timeline_events',
14
+ entityGraph: 'entities',
15
+ sleep: 'sleep_runs',
16
+ vectors: 'chunk_meta',
17
+ };
18
+ /**
19
+ * `001-baseline` is a MARKER, not DDL: table creation stays owned by the lazy
20
+ * `ensure*Schema` paths (CREATE TABLE IF NOT EXISTS with current bodies).
21
+ * Discipline that follows: every real migration must ALSO update the matching
22
+ * CREATE body, so fresh DBs are born current (and get stamped as such).
23
+ */
24
+ function baseline(db) {
25
+ return { id: '001-baseline', db, statements: [], baseline: true };
26
+ }
27
+ export const registry = {
28
+ timeline: [baseline('timeline')],
29
+ entityGraph: [baseline('entityGraph')],
30
+ sleep: [baseline('sleep')],
31
+ vectors: [baseline('vectors')],
32
+ };
33
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/migrations/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAA4C;IACrE,QAAQ,EAAE,iBAAiB;IAC3B,WAAW,EAAE,UAAU;IACvB,KAAK,EAAE,YAAY;IACnB,OAAO,EAAE,YAAY;CACtB,CAAC;AAEF;;;;;GAKG;AACH,SAAS,QAAQ,CAAC,EAAiB;IACjC,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAA0D;IAC7E,QAAQ,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAChC,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACtC,KAAK,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC1B,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;CAC/B,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Migration runner core (Spec A — docs/specs/migration-capability.md).
3
+ *
4
+ * Each of the four brain DB files carries its own `_migrations` table tracking
5
+ * only that DB's migrations. The runner is a STANDALONE primitive — consumers
6
+ * choose the trigger (local getDb autoMigrate vs Arcana's per-tenant migrator);
7
+ * it must never be buried inside getDb.
8
+ */
9
+ import type Database from 'better-sqlite3';
10
+ import type { Migration, MigrationKind, MigrationOptions } from './types.js';
11
+ type Registry = Partial<Record<MigrationKind, readonly Migration[]>>;
12
+ /**
13
+ * Run (or check) the migration line for one DB. STANDALONE primitive — the
14
+ * trigger is consumer-chosen: local getDb passes `mode:'apply'` when
15
+ * `autoMigrate` is set; Arcana serving passes `mode:'check'`; Arcana's
16
+ * migrator job drives `mode:'apply'` per tenant.
17
+ *
18
+ * Ordering (deliberate deviation from the spec pseudocode, which drew backup
19
+ * inside the txn): the backup hook runs BEFORE the write transaction opens —
20
+ * `PRAGMA wal_checkpoint` cannot execute inside an open transaction. The
21
+ * applies themselves are atomic: one IMMEDIATE transaction, with the applied
22
+ * set re-read under the write lock so a concurrent opener no-ops instead of
23
+ * double-applying.
24
+ */
25
+ export declare function runMigrations(db: Database.Database, kind: MigrationKind, opts: MigrationOptions & {
26
+ registry?: Registry;
27
+ }): void;
28
+ /** Create the `_migrations` ledger if absent. Idempotent. */
29
+ export declare function ensureMigrationsTable(db: Database.Database): void;
30
+ /** Applied migrations as id → checksum. */
31
+ export declare function readApplied(db: Database.Database): Map<string, string>;
32
+ /** Record a migration as applied. */
33
+ export declare function record(db: Database.Database, m: Migration): void;
34
+ /**
35
+ * Checksum of the migration's NORMALIZED SQL (whitespace-collapsed), not its
36
+ * JS source — formatting edits don't churn it; semantic edits do.
37
+ */
38
+ export declare function checksumOf(m: Migration): string;
39
+ /**
40
+ * Version a DB that has no `_migrations` table yet (baseline decision, T6):
41
+ *
42
+ * - LEGACY (sentinel table exists, no ledger): the DB was built by the old
43
+ * CREATE-IF-NOT-EXISTS path → stamp `001-baseline` as applied WITHOUT
44
+ * running it; later migrations stay pending and will apply normally.
45
+ * - FRESH (no sentinel, no ledger): the lazy `ensure*Schema` paths will create
46
+ * the CURRENT schema after open, so stamp ALL registry ids as applied —
47
+ * running an ALTER against tables that don't exist yet would crash, and the
48
+ * fresh CREATE bodies already include every shipped migration's columns.
49
+ * - VERSIONED (ledger exists): untouched.
50
+ */
51
+ export declare function baselineIfUnversioned(db: Database.Database, kind: MigrationKind, migrations: readonly Migration[]): void;
52
+ /** The DB must not hold applied ids this build doesn't know (code older than schema). */
53
+ export declare function assertNotAhead(kind: MigrationKind, applied: ReadonlyMap<string, string>, migrations: readonly Migration[]): void;
54
+ /** Every applied id this build knows must still checksum-match — shipped migrations are immutable. */
55
+ export declare function assertNoChecksumDrift(kind: MigrationKind, applied: ReadonlyMap<string, string>, migrations: readonly Migration[]): void;
56
+ export {};
57
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/migrations/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI7E,KAAK,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC,CAAC;AAErE;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,gBAAgB,GAAG;IAAE,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAAE,GAC/C,IAAI,CAkCN;AAED,6DAA6D;AAC7D,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAQjE;AAED,2CAA2C;AAC3C,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAKtE;AAED,qCAAqC;AACrC,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,SAAS,GAAG,IAAI,CAMhE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAG/C;AAYD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,SAAS,SAAS,EAAE,GAC/B,IAAI,CAUN;AAQD,yFAAyF;AACzF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,UAAU,EAAE,SAAS,SAAS,EAAE,GAC/B,IAAI,CAIN;AAED,sGAAsG;AACtG,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,UAAU,EAAE,SAAS,SAAS,EAAE,GAC/B,IAAI,CAON"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Migration runner core (Spec A — docs/specs/migration-capability.md).
3
+ *
4
+ * Each of the four brain DB files carries its own `_migrations` table tracking
5
+ * only that DB's migrations. The runner is a STANDALONE primitive — consumers
6
+ * choose the trigger (local getDb autoMigrate vs Arcana's per-tenant migrator);
7
+ * it must never be buried inside getDb.
8
+ */
9
+ import { createHash } from 'node:crypto';
10
+ import { registry as defaultRegistry, sentinelTables } from './registry.js';
11
+ import { SchemaAheadError, SchemaBehindError, ChecksumDriftError } from './errors.js';
12
+ /**
13
+ * Run (or check) the migration line for one DB. STANDALONE primitive — the
14
+ * trigger is consumer-chosen: local getDb passes `mode:'apply'` when
15
+ * `autoMigrate` is set; Arcana serving passes `mode:'check'`; Arcana's
16
+ * migrator job drives `mode:'apply'` per tenant.
17
+ *
18
+ * Ordering (deliberate deviation from the spec pseudocode, which drew backup
19
+ * inside the txn): the backup hook runs BEFORE the write transaction opens —
20
+ * `PRAGMA wal_checkpoint` cannot execute inside an open transaction. The
21
+ * applies themselves are atomic: one IMMEDIATE transaction, with the applied
22
+ * set re-read under the write lock so a concurrent opener no-ops instead of
23
+ * double-applying.
24
+ */
25
+ export function runMigrations(db, kind, opts) {
26
+ const migrations = (opts.registry ?? defaultRegistry)[kind] ?? [];
27
+ if (opts.mode === 'check') {
28
+ // Serving path: NEVER write — not even the ledger table. A DB with no
29
+ // ledger and a non-empty registry is behind (everything pending), which
30
+ // includes a fresh tenant DB: serving refuses until the migrator runs.
31
+ const applied = migrationsTableExists(db) ? readApplied(db) : new Map();
32
+ assertNotAhead(kind, applied, migrations);
33
+ assertNoChecksumDrift(kind, applied, migrations);
34
+ const pending = migrations.filter((m) => !applied.has(m.id));
35
+ if (pending.length)
36
+ throw new SchemaBehindError(kind, pending.map((m) => m.id));
37
+ return;
38
+ }
39
+ baselineIfUnversioned(db, kind, migrations);
40
+ ensureMigrationsTable(db);
41
+ const applied = readApplied(db);
42
+ assertNotAhead(kind, applied, migrations);
43
+ assertNoChecksumDrift(kind, applied, migrations);
44
+ const pending = migrations.filter((m) => !applied.has(m.id));
45
+ if (pending.length === 0)
46
+ return;
47
+ opts.backup?.(db, pending[0].id);
48
+ db.transaction(() => {
49
+ const appliedNow = readApplied(db); // re-check under the write lock (race loser no-ops)
50
+ for (const m of pending) {
51
+ if (appliedNow.has(m.id))
52
+ continue;
53
+ for (const sql of m.statements)
54
+ db.exec(sql);
55
+ m.backfill?.(db);
56
+ record(db, m);
57
+ }
58
+ }).immediate();
59
+ }
60
+ /** Create the `_migrations` ledger if absent. Idempotent. */
61
+ export function ensureMigrationsTable(db) {
62
+ db.exec(`CREATE TABLE IF NOT EXISTS _migrations (
63
+ id TEXT PRIMARY KEY,
64
+ applied_at TEXT NOT NULL,
65
+ checksum TEXT NOT NULL
66
+ )`);
67
+ }
68
+ /** Applied migrations as id → checksum. */
69
+ export function readApplied(db) {
70
+ const rows = db
71
+ .prepare(`SELECT id, checksum FROM _migrations`)
72
+ .all();
73
+ return new Map(rows.map((r) => [r.id, r.checksum]));
74
+ }
75
+ /** Record a migration as applied. */
76
+ export function record(db, m) {
77
+ db.prepare(`INSERT INTO _migrations (id, applied_at, checksum) VALUES (?, ?, ?)`).run(m.id, new Date().toISOString(), checksumOf(m));
78
+ }
79
+ /**
80
+ * Checksum of the migration's NORMALIZED SQL (whitespace-collapsed), not its
81
+ * JS source — formatting edits don't churn it; semantic edits do.
82
+ */
83
+ export function checksumOf(m) {
84
+ const normalized = m.statements.map(normalizeSql).join('\n');
85
+ return createHash('sha256').update(normalized).digest('hex');
86
+ }
87
+ function normalizeSql(sql) {
88
+ return sql.trim().replace(/\s+/g, ' ');
89
+ }
90
+ function migrationsTableExists(db) {
91
+ return !!db
92
+ .prepare(`SELECT 1 FROM sqlite_master WHERE type='table' AND name='_migrations'`)
93
+ .get();
94
+ }
95
+ /**
96
+ * Version a DB that has no `_migrations` table yet (baseline decision, T6):
97
+ *
98
+ * - LEGACY (sentinel table exists, no ledger): the DB was built by the old
99
+ * CREATE-IF-NOT-EXISTS path → stamp `001-baseline` as applied WITHOUT
100
+ * running it; later migrations stay pending and will apply normally.
101
+ * - FRESH (no sentinel, no ledger): the lazy `ensure*Schema` paths will create
102
+ * the CURRENT schema after open, so stamp ALL registry ids as applied —
103
+ * running an ALTER against tables that don't exist yet would crash, and the
104
+ * fresh CREATE bodies already include every shipped migration's columns.
105
+ * - VERSIONED (ledger exists): untouched.
106
+ */
107
+ export function baselineIfUnversioned(db, kind, migrations) {
108
+ if (migrations.length === 0)
109
+ return;
110
+ if (migrationsTableExists(db))
111
+ return;
112
+ const legacy = tableExists(db, sentinelTables[kind]);
113
+ db.transaction(() => {
114
+ ensureMigrationsTable(db);
115
+ const toStamp = legacy ? migrations.filter((m) => m.baseline) : migrations;
116
+ for (const m of toStamp)
117
+ record(db, m);
118
+ }).immediate();
119
+ }
120
+ function tableExists(db, name) {
121
+ return !!db
122
+ .prepare(`SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?`)
123
+ .get(name);
124
+ }
125
+ /** The DB must not hold applied ids this build doesn't know (code older than schema). */
126
+ export function assertNotAhead(kind, applied, migrations) {
127
+ const known = new Set(migrations.map((m) => m.id));
128
+ const unknown = [...applied.keys()].filter((id) => !known.has(id));
129
+ if (unknown.length)
130
+ throw new SchemaAheadError(kind, unknown);
131
+ }
132
+ /** Every applied id this build knows must still checksum-match — shipped migrations are immutable. */
133
+ export function assertNoChecksumDrift(kind, applied, migrations) {
134
+ for (const m of migrations) {
135
+ const recorded = applied.get(m.id);
136
+ if (recorded !== undefined && recorded !== checksumOf(m)) {
137
+ throw new ChecksumDriftError(kind, m.id);
138
+ }
139
+ }
140
+ }
141
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/migrations/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Proof migration (Spec A T8 / C9): a trivial additive column purely to
3
+ * exercise the runner end-to-end against a copy of a real brain.
4
+ *
5
+ * Deliberately NOT in the default registry — shipping a probe column to every
6
+ * consumer has no value. The real-brain regression test injects it via
7
+ * `opts.registry`; the first SHIPPED migration will be Spec B's provenance
8
+ * columns (which must also update the matching ensure*Schema CREATE body —
9
+ * see registry.ts).
10
+ */
11
+ import type { Migration } from '../types.js';
12
+ export declare const proofMigration: Migration;
13
+ //# sourceMappingURL=002-proof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002-proof.d.ts","sourceRoot":"","sources":["../../../src/migrations/timeline/002-proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,eAAO,MAAM,cAAc,EAAE,SAI5B,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Proof migration (Spec A T8 / C9): a trivial additive column purely to
3
+ * exercise the runner end-to-end against a copy of a real brain.
4
+ *
5
+ * Deliberately NOT in the default registry — shipping a probe column to every
6
+ * consumer has no value. The real-brain regression test injects it via
7
+ * `opts.registry`; the first SHIPPED migration will be Spec B's provenance
8
+ * columns (which must also update the matching ensure*Schema CREATE body —
9
+ * see registry.ts).
10
+ */
11
+ export const proofMigration = {
12
+ id: '002-proof',
13
+ db: 'timeline',
14
+ statements: ['ALTER TABLE timeline_events ADD COLUMN _migration_probe TEXT'],
15
+ };
16
+ //# sourceMappingURL=002-proof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002-proof.js","sourceRoot":"","sources":["../../../src/migrations/timeline/002-proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,UAAU;IACd,UAAU,EAAE,CAAC,8DAA8D,CAAC;CAC7E,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Schema migration types (Spec A — docs/specs/migration-capability.md).
3
+ *
4
+ * A migration is a small, named, immutable-once-shipped module. Its DDL is
5
+ * DECLARATIVE (`statements`), not an imperative `up(db)` — the runner executes
6
+ * the statements in order. Declarative SQL keeps the checksum honest (we hash
7
+ * the normalized SQL, not JS source) and stays dialect-portable for a future
8
+ * libsql/Turso backend (Arcana).
9
+ *
10
+ * MVP constraint: statements must be ADDITIVE (`ALTER TABLE ... ADD COLUMN`,
11
+ * `CREATE TABLE/INDEX IF NOT EXISTS`) — no drop/rewrite. Table-rebuild
12
+ * migrations are out of MVP scope.
13
+ */
14
+ import type Database from 'better-sqlite3';
15
+ /**
16
+ * The four brain DBs that carry migrations. Subset of `DbKind` in index.ts
17
+ * (same spelling — `entityGraph`, not `entity-graph`); `idempotency` is a
18
+ * cache-shaped DB with no migration line.
19
+ */
20
+ export type MigrationKind = 'timeline' | 'entityGraph' | 'sleep' | 'vectors';
21
+ export interface Migration {
22
+ /** Ordered + named, e.g. '002-add-file-provenance'. NEVER edit after release (checksum guards it). */
23
+ readonly id: string;
24
+ /** Which DB file this migration belongs to (each carries its own _migrations table). */
25
+ readonly db: MigrationKind;
26
+ /** Plain-SQLite DDL, executed in order inside the migration transaction. Checksummed. */
27
+ readonly statements: readonly string[];
28
+ /**
29
+ * Marks the no-op baseline marker (one per kind, by convention `001-baseline`).
30
+ * On a LEGACY unversioned DB (sentinel table present, no `_migrations`), only
31
+ * baseline-flagged entries are stamped as applied without running.
32
+ */
33
+ readonly baseline?: boolean;
34
+ /** Optional data backfill — idempotent, resumable; runs after `statements` in the same txn. */
35
+ backfill?(db: Database.Database): void;
36
+ }
37
+ export interface MigrationOptions {
38
+ /**
39
+ * 'apply' — advance schema (local consumers: KBDE / KyberBot via autoMigrate;
40
+ * Arcana's migrator job per-tenant).
41
+ * 'check' — never write; throw SchemaBehindError on pending (Arcana serving path).
42
+ * Refuse-when-ahead applies in BOTH modes.
43
+ */
44
+ mode: 'apply' | 'check';
45
+ /**
46
+ * Invoked once before the first pending migration applies (apply mode only).
47
+ * Local: copyFileBackup (WAL checkpoint + `<name>.pre-<firstPendingId>.bak`).
48
+ * Cloud: snapshot hook or no-op.
49
+ */
50
+ backup?: (db: Database.Database, firstPendingId: string) => void;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/migrations/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,SAAS;IACxB,sGAAsG;IACtG,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,+FAA+F;IAC/F,QAAQ,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;CAClE"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Schema migration types (Spec A — docs/specs/migration-capability.md).
3
+ *
4
+ * A migration is a small, named, immutable-once-shipped module. Its DDL is
5
+ * DECLARATIVE (`statements`), not an imperative `up(db)` — the runner executes
6
+ * the statements in order. Declarative SQL keeps the checksum honest (we hash
7
+ * the normalized SQL, not JS source) and stays dialect-portable for a future
8
+ * libsql/Turso backend (Arcana).
9
+ *
10
+ * MVP constraint: statements must be ADDITIVE (`ALTER TABLE ... ADD COLUMN`,
11
+ * `CREATE TABLE/INDEX IF NOT EXISTS`) — no drop/rewrite. Table-rebuild
12
+ * migrations are out of MVP scope.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/migrations/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -10,7 +10,18 @@
10
10
  * corresponding brain-core module; behaviour is held constant.
11
11
  */
12
12
  import type { StorageProvider } from '@kybernesis/brain-contracts';
13
+ import type { MigrationOptions } from './migrations/types.js';
13
14
  /** Reset the lazy vec-store cache (test/utility). */
14
15
  export declare function resetLazyVectorStore(): void;
15
- export declare function createSqliteStorageProvider(): StorageProvider;
16
+ export interface SqliteStorageProviderOptions {
17
+ /**
18
+ * Migration trigger (Spec A) — consumer-chosen, off when omitted.
19
+ * `true` → local default `{ mode:'apply', backup: copyFileBackup }` (KBDE /
20
+ * KyberBot: self-heal on open). Cloud serving (Arcana) passes
21
+ * `{ mode:'check' }` — refuse ahead AND behind, never write; its migrator
22
+ * job calls `runMigrations` standalone per tenant.
23
+ */
24
+ autoMigrate?: boolean | MigrationOptions;
25
+ }
26
+ export declare function createSqliteStorageProvider(options?: SqliteStorageProviderOptions): StorageProvider;
16
27
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAgCrC,qDAAqD;AACrD,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C;AA6BD,wBAAgB,2BAA2B,IAAI,eAAe,CAiB7D"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAgC9D,qDAAqD;AACrD,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C;AA6BD,MAAM,WAAW,4BAA4B;IAC3C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;CAC1C;AAED,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,4BAAiC,GACzC,eAAe,CAoBjB"}
package/dist/provider.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * The SQL that lands here is moved verbatim (port-faithful) from the
10
10
  * corresponding brain-core module; behaviour is held constant.
11
11
  */
12
+ import { setAutoMigrate } from './migrations/config.js';
12
13
  import { sqliteFactStore } from './fact-store.js';
13
14
  import { sqliteTimelineStore } from './timeline.js';
14
15
  import { sqliteEntityGraphStore } from './entity-graph.js';
@@ -73,7 +74,10 @@ const lazyVectorStore = {
73
74
  return s.stats(t);
74
75
  },
75
76
  };
76
- export function createSqliteStorageProvider() {
77
+ export function createSqliteStorageProvider(options = {}) {
78
+ if (options.autoMigrate !== undefined) {
79
+ setAutoMigrate(options.autoMigrate);
80
+ }
77
81
  return {
78
82
  repositories: {
79
83
  timeline: sqliteTimelineStore,
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kybernesis/brain-storage-sqlite",
3
- "version": "0.8.3",
3
+ "version": "0.9.0",
4
4
  "description": "better-sqlite3 StructuredStore implementation for brain-core",
5
5
  "license": "MIT",
6
6
  "author": "David Cruwys (AppyDave)",
@@ -27,18 +27,19 @@
27
27
  "README.md"
28
28
  ],
29
29
  "dependencies": {
30
- "@kybernesis/brain-contracts": "0.8.3"
30
+ "@kybernesis/brain-contracts": "0.9.0"
31
31
  },
32
32
  "optionalDependencies": {
33
- "@kybernesis/brain-storage-vec": "0.8.3"
33
+ "@kybernesis/brain-storage-vec": "0.9.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "better-sqlite3": ">=9.0.0"
37
37
  },
38
38
  "devDependencies": {
39
+ "@libsql/client": "^0.17.3",
39
40
  "@types/better-sqlite3": "^7.6.0",
40
41
  "better-sqlite3": "^12.0.0",
41
- "@kybernesis/brain-testkit": "0.8.3"
42
+ "@kybernesis/brain-testkit": "0.9.0"
42
43
  },
43
44
  "publishConfig": {
44
45
  "access": "public"