@kybernesis/brain-storage-sqlite 0.8.4 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hash.d.ts +9 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +12 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations/backup.d.ts +14 -0
- package/dist/migrations/backup.d.ts.map +1 -0
- package/dist/migrations/backup.js +20 -0
- package/dist/migrations/backup.js.map +1 -0
- package/dist/migrations/config.d.ts +14 -0
- package/dist/migrations/config.d.ts.map +1 -0
- package/dist/migrations/config.js +24 -0
- package/dist/migrations/config.js.map +1 -0
- package/dist/migrations/errors.d.ts +24 -0
- package/dist/migrations/errors.d.ts.map +1 -0
- package/dist/migrations/errors.js +45 -0
- package/dist/migrations/errors.js.map +1 -0
- package/dist/migrations/registry.d.ts +15 -0
- package/dist/migrations/registry.d.ts.map +1 -0
- package/dist/migrations/registry.js +34 -0
- package/dist/migrations/registry.js.map +1 -0
- package/dist/migrations/runner.d.ts +57 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +141 -0
- package/dist/migrations/runner.js.map +1 -0
- package/dist/migrations/timeline/002-file-provenance.d.ts +24 -0
- package/dist/migrations/timeline/002-file-provenance.d.ts.map +1 -0
- package/dist/migrations/timeline/002-file-provenance.js +43 -0
- package/dist/migrations/timeline/002-file-provenance.js.map +1 -0
- package/dist/migrations/timeline/002-proof.d.ts +13 -0
- package/dist/migrations/timeline/002-proof.d.ts.map +1 -0
- package/dist/migrations/timeline/002-proof.js +16 -0
- package/dist/migrations/timeline/002-proof.js.map +1 -0
- package/dist/migrations/types.d.ts +52 -0
- package/dist/migrations/types.d.ts.map +1 -0
- package/dist/migrations/types.js +15 -0
- package/dist/migrations/types.js.map +1 -0
- package/dist/provider.d.ts +13 -3
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +9 -57
- package/dist/provider.js.map +1 -1
- package/dist/reconcile.d.ts +76 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +120 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/timeline.d.ts.map +1 -1
- package/dist/timeline.js +67 -10
- package/dist/timeline.js.map +1 -1
- package/dist/vec-lazy.d.ts +19 -0
- package/dist/vec-lazy.d.ts.map +1 -0
- package/dist/vec-lazy.js +76 -0
- package/dist/vec-lazy.js.map +1 -0
- package/package.json +5 -4
package/dist/hash.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content fingerprint (Spec B): sha256 over RAW FILE BYTES — deliberately not
|
|
3
|
+
* normalized/extracted text, so the hash is simple, stable, decoupled from
|
|
4
|
+
* extraction, and fails safe. The same function serves both sides of the
|
|
5
|
+
* contract: consumers compute it at file-read for ingest; reconcile recomputes
|
|
6
|
+
* it from disk for comparison.
|
|
7
|
+
*/
|
|
8
|
+
export declare function contentHash(rawBytes: Uint8Array | string): string;
|
|
9
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAEjE"}
|
package/dist/hash.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content fingerprint (Spec B): sha256 over RAW FILE BYTES — deliberately not
|
|
3
|
+
* normalized/extracted text, so the hash is simple, stable, decoupled from
|
|
4
|
+
* extraction, and fails safe. The same function serves both sides of the
|
|
5
|
+
* contract: consumers compute it at file-read for ingest; reconcile recomputes
|
|
6
|
+
* it from disk for comparison.
|
|
7
|
+
*/
|
|
8
|
+
import { createHash } from 'node:crypto';
|
|
9
|
+
export function contentHash(rawBytes) {
|
|
10
|
+
return createHash('sha256').update(rawBytes).digest('hex');
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=hash.js.map
|
package/dist/hash.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,WAAW,CAAC,QAA6B;IACvD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,15 @@ 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';
|
|
13
|
+
export { reconcile } from './reconcile.js';
|
|
14
|
+
export type { ReconcileOptions, ReconcileReport, ReconcileDiskFile } from './reconcile.js';
|
|
15
|
+
export { contentHash } from './hash.js';
|
|
7
16
|
import type { TenantContext } from '@kybernesis/brain-contracts';
|
|
8
17
|
export type DbKind = 'timeline' | 'entityGraph' | 'vectors' | 'sleep' | 'idempotency';
|
|
9
18
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAIxC,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,24 @@ 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
|
+
// File provenance + reconcile (Spec B). reconcile() is report-only by default;
|
|
29
|
+
// repair/removeOrphaned are explicit opt-ins. Consumers wire storeConversation
|
|
30
|
+
// into opts.reingest (the library never ingests on its own).
|
|
31
|
+
export { reconcile } from './reconcile.js';
|
|
32
|
+
export { contentHash } from './hash.js';
|
|
33
|
+
import { runMigrations } from './migrations/runner.js';
|
|
34
|
+
import { getAutoMigrate } from './migrations/config.js';
|
|
19
35
|
const pool = new Map();
|
|
36
|
+
const MIGRATABLE_KINDS = ['timeline', 'entityGraph', 'sleep', 'vectors'];
|
|
20
37
|
function resolveDbPath(t, kind) {
|
|
21
38
|
switch (kind) {
|
|
22
39
|
case 'timeline': return t.paths.timelineDbPath;
|
|
@@ -45,6 +62,21 @@ export function getDb(t, kind) {
|
|
|
45
62
|
db.pragma('journal_mode = WAL');
|
|
46
63
|
db.pragma('synchronous = NORMAL');
|
|
47
64
|
db.pragma('foreign_keys = ON');
|
|
65
|
+
// After PRAGMAs, before first use — and before pooling, so a refused DB
|
|
66
|
+
// (SchemaAheadError / SchemaBehindError) is closed, not cached half-open.
|
|
67
|
+
const autoMigrate = getAutoMigrate();
|
|
68
|
+
if (autoMigrate && MIGRATABLE_KINDS.includes(kind)) {
|
|
69
|
+
try {
|
|
70
|
+
runMigrations(db, kind, autoMigrate);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
try {
|
|
74
|
+
db.close();
|
|
75
|
+
}
|
|
76
|
+
catch { /* ignore */ }
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
48
80
|
pool.set(key, db);
|
|
49
81
|
return db;
|
|
50
82
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,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;AAChE,8EAA8E;AAC9E,4EAA4E;AAC5E,eAAe;AACf,EAAE;AACF,kFAAkF;AAClF,4EAA4E;AAC5E,kFAAkF;AAClF,gFAAgF;AAChF,8DAA8D;AAC9D,iDAAiD;AACjD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;
|
|
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;AAG3D;;;;;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,34 @@
|
|
|
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 { migration as fileProvenance } from './timeline/002-file-provenance.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 const sentinelTables = {
|
|
14
|
+
timeline: 'timeline_events',
|
|
15
|
+
entityGraph: 'entities',
|
|
16
|
+
sleep: 'sleep_runs',
|
|
17
|
+
vectors: 'chunk_meta',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* `001-baseline` is a MARKER, not DDL: table creation stays owned by the lazy
|
|
21
|
+
* `ensure*Schema` paths (CREATE TABLE IF NOT EXISTS with current bodies).
|
|
22
|
+
* Discipline that follows: every real migration must ALSO update the matching
|
|
23
|
+
* CREATE body, so fresh DBs are born current (and get stamped as such).
|
|
24
|
+
*/
|
|
25
|
+
function baseline(db) {
|
|
26
|
+
return { id: '001-baseline', db, statements: [], baseline: true };
|
|
27
|
+
}
|
|
28
|
+
export const registry = {
|
|
29
|
+
timeline: [baseline('timeline'), fileProvenance],
|
|
30
|
+
entityGraph: [baseline('entityGraph')],
|
|
31
|
+
sleep: [baseline('sleep')],
|
|
32
|
+
vectors: [baseline('vectors')],
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/migrations/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEhF;;;;;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,EAAE,cAAc,CAAC;IAChD,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,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec B (docs/specs/file-provenance-and-reconcile.md): file provenance.
|
|
3
|
+
*
|
|
4
|
+
* Adds the mutable LOCATOR (`file_path`, relative path, type='file' rows only)
|
|
5
|
+
* and the VERSION fingerprint (`content_hash` = sha256 of raw file bytes) to
|
|
6
|
+
* timeline_events. Stable identity (random source_path / chunk origin_id) is
|
|
7
|
+
* deliberately untouched — separating identity from locator is what makes a
|
|
8
|
+
* rename a one-row UPDATE.
|
|
9
|
+
*
|
|
10
|
+
* The unique index is PARTIAL: conversation rows keep file_path NULL in any
|
|
11
|
+
* number; non-NULL paths are unique (the dual-key upsert rides on it — proven
|
|
12
|
+
* in partial-upsert.spike.test.ts on better-sqlite3 + libsql).
|
|
13
|
+
*
|
|
14
|
+
* Backfill stamps file_path from the legacy `title` ("… File: <relpath>") —
|
|
15
|
+
* in-DB only, no file reads; content_hash stays NULL on legacy rows (the first
|
|
16
|
+
* reconcile run stamps it lazily). DEDUPE-AWARE: legacy brains can hold
|
|
17
|
+
* duplicate rows for the same file (the pile-up bug Spec B fixes) — stamping
|
|
18
|
+
* all of them would violate the new unique index and roll back the whole
|
|
19
|
+
* migration, so only the NEWEST row (MAX(id)) per title gets the locator;
|
|
20
|
+
* older duplicates stay NULL and remain reachable by source_path.
|
|
21
|
+
*/
|
|
22
|
+
import type { Migration } from '../types.js';
|
|
23
|
+
export declare const migration: Migration;
|
|
24
|
+
//# sourceMappingURL=002-file-provenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"002-file-provenance.d.ts","sourceRoot":"","sources":["../../../src/migrations/timeline/002-file-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,eAAO,MAAM,SAAS,EAAE,SAoBvB,CAAC"}
|