@bevel-software/platform-core-backend 0.24.0 → 0.25.2

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 (35) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +4 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/modules/database/migrate.d.ts +87 -1
  6. package/dist/modules/database/migrate.d.ts.map +1 -1
  7. package/dist/modules/database/migrate.js +166 -48
  8. package/dist/modules/database/migrate.js.map +1 -1
  9. package/dist/modules/kb-fs/locking-filesystem.d.ts +17 -0
  10. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  11. package/dist/modules/kb-fs/locking-filesystem.js +29 -0
  12. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  13. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  14. package/dist/modules/tool-manuals/tool-manuals.service.js +30 -0
  15. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  16. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +70 -0
  17. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  18. package/dist/modules/workspace/startup/kb-startup-runner.js +213 -20
  19. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  20. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  21. package/dist/modules/workspace/workspace.tools.js +58 -21
  22. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  23. package/kb-template/AGENTS.md +40 -0
  24. package/package.json +3 -3
  25. package/src/index.ts +7 -0
  26. package/src/modules/database/__tests__/pii-backfill.pg.test.ts +223 -4
  27. package/src/modules/database/migrate.ts +238 -52
  28. package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +93 -0
  29. package/src/modules/kb-fs/locking-filesystem.ts +37 -0
  30. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +151 -0
  31. package/src/modules/tool-manuals/tool-manuals.service.ts +37 -0
  32. package/src/modules/workspace/__tests__/workspace.tools.test.ts +112 -1
  33. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +231 -1
  34. package/src/modules/workspace/startup/kb-startup-runner.ts +216 -19
  35. package/src/modules/workspace/workspace.tools.ts +59 -21
package/dist/index.d.ts CHANGED
@@ -25,7 +25,7 @@ export { setLogger, logger, createConsoleLogger } from './shared/logging.js';
25
25
  export type { ILogger, LogFields } from './shared/logger.contract.js';
26
26
  export { createShutdown, startCore, stopCore, withStartupTask, type BootableCore, type CoreStopDeps, type ShutdownDeps, type ShutdownOptions, type StopCoreOptions, type LeaseLoopHandle, type LeasedWorker, } from './core/lifecycle.js';
27
27
  export { coreMigrationsDir, defaultKbTemplateDir } from './assets.js';
28
- export { runCoreMigrations, runEnterpriseMigrations, runPiiEncryptionBackfill, } from './modules/database/migrate.js';
28
+ export { runCoreMigrations, runEnterpriseMigrations, runPiiEncryptionBackfill, runPiiBackfill, type PiiBackfillExecutor, type PiiBackfillSpec, type PiiBackfillTable, type PiiBlindIndex, } from './modules/database/migrate.js';
29
29
  export { getDb, createDb, closeDb, dbSchemaOf, piiKeysOf, assertSchemaName, DEFAULT_DB_SCHEMA, type Database, type DbOptions, } from './modules/database/connection.js';
30
30
  export { encryptedText, blindIndexText, derivePiiKeys, isEncryptedBlob, PII_CIPHERTEXT_PREFIX, type PiiKeys, } from './shared/column-crypto.js';
31
31
  export { GIT_SHA, resolveGitSha } from './version.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEzG,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,EACL,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGzE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAGtE,OAAO,EACL,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,QAAQ,EACb,KAAK,SAAS,GACf,MAAM,kCAAkC,CAAC;AAS1C,OAAO,EACL,aAAa,EACb,cAAc,EACd,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,KAAK,OAAO,GACb,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMtD,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,EACL,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,6CAA6C,CAAC;AACrD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,mDAAmD,CAAC;AAK3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAC9E,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,0CAA0C,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACxE,YAAY,EACV,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,8CAA8C,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAC7E,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EACL,cAAc,EACd,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,yBAAyB,EACzB,gBAAgB,EAChB,2BAA2B,EAC3B,aAAa,EACb,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,GACvB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,sCAAsC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -30,7 +30,10 @@ export { setLogger, logger, createConsoleLogger } from './shared/logging.js';
30
30
  export { createShutdown, startCore, stopCore, withStartupTask, } from './core/lifecycle.js';
31
31
  // Packaged assets (migrations/, kb-template/) + the migration runners.
32
32
  export { coreMigrationsDir, defaultKbTemplateDir } from './assets.js';
33
- export { runCoreMigrations, runEnterpriseMigrations, runPiiEncryptionBackfill, } from './modules/database/migrate.js';
33
+ export { runCoreMigrations, runEnterpriseMigrations, runPiiEncryptionBackfill,
34
+ // The same backfill for an overlay's own sealed columns: its spec goes to
35
+ // `runEnterpriseMigrations`, or to `runPiiBackfill` under a lock of its own.
36
+ runPiiBackfill, } from './modules/database/migrate.js';
34
37
  export { getDb, createDb, closeDb, dbSchemaOf, piiKeysOf, assertSchemaName, DEFAULT_DB_SCHEMA, } from './modules/database/connection.js';
35
38
  // PII column encryption (see shared/column-crypto.ts). The key belongs to the
36
39
  // database handle (`createDb(url, { piiKey })`), so an overlay seals its own
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAyC,MAAM,kBAAkB,CAAC;AACzG,+EAA+E;AAC/E,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAqB,MAAM,gCAAgC,CAAC;AACvF,OAAO,EACL,gBAAgB,GAGjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAkB,MAAM,sBAAsB,CAAC;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE7E,2EAA2E;AAC3E,mDAAmD;AACnD,OAAO,EACL,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,GAQhB,MAAM,qBAAqB,CAAC;AAE7B,uEAAuE;AACvE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAGlB,MAAM,kCAAkC,CAAC;AAE1C,8EAA8E;AAC9E,6EAA6E;AAC7E,4EAA4E;AAC5E,wEAAwE;AACxE,4EAA4E;AAC5E,8EAA8E;AAC9E,qBAAqB;AACrB,OAAO,EACL,aAAa,EACb,cAAc,EACd,aAAa,EACb,eAAe,EACf,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AAEnC,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEtD,+EAA+E;AAC/E,2EAA2E;AAC3E,0EAA0E;AAC1E,qBAAqB;AACrB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,EACL,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,6CAA6C,CAAC;AAOrD,6CAA6C;AAC7C,sEAAsE;AACtE,8EAA8E;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAgB9E,OAAO,EACL,cAAc,EACd,cAAc,GAGf,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,yBAAyB,EACzB,gBAAgB,EAChB,2BAA2B,EAC3B,aAAa,GAId,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,aAAa,GAMd,MAAM,sCAAsC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAyC,MAAM,kBAAkB,CAAC;AACzG,+EAA+E;AAC/E,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAqB,MAAM,gCAAgC,CAAC;AACvF,OAAO,EACL,gBAAgB,GAGjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAkB,MAAM,sBAAsB,CAAC;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE7E,2EAA2E;AAC3E,mDAAmD;AACnD,OAAO,EACL,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,GAQhB,MAAM,qBAAqB,CAAC;AAE7B,uEAAuE;AACvE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB;AACxB,0EAA0E;AAC1E,6EAA6E;AAC7E,cAAc,GAKf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAGlB,MAAM,kCAAkC,CAAC;AAE1C,8EAA8E;AAC9E,6EAA6E;AAC7E,4EAA4E;AAC5E,wEAAwE;AACxE,4EAA4E;AAC5E,8EAA8E;AAC9E,qBAAqB;AACrB,OAAO,EACL,aAAa,EACb,cAAc,EACd,aAAa,EACb,eAAe,EACf,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AAEnC,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEtD,+EAA+E;AAC/E,2EAA2E;AAC3E,0EAA0E;AAC1E,qBAAqB;AACrB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,EACL,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,6CAA6C,CAAC;AAOrD,6CAA6C;AAC7C,sEAAsE;AACtE,8EAA8E;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAgB9E,OAAO,EACL,cAAc,EACd,cAAc,GAGf,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,yBAAyB,EACzB,gBAAgB,EAChB,2BAA2B,EAC3B,aAAa,GAId,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,aAAa,GAMd,MAAM,sCAAsC,CAAC"}
@@ -5,8 +5,78 @@ export declare function runCoreMigrations(db: Database, folder: string): Promise
5
5
  * Apply the ENTERPRISE migration history from `folder`, tracked in
6
6
  * `__drizzle_migrations_enterprise`. Run AFTER {@link runCoreMigrations} —
7
7
  * enterprise tables FK into core tables.
8
+ *
9
+ * `piiBackfill` is the overlay's own personal data, for the overlay that has
10
+ * sealed columns of its own (`encryptedText` / `blindIndexText` in its
11
+ * schema): the rows written before those columns were sealed are sealed here,
12
+ * right after the history that adds the index columns and under the same
13
+ * lock, exactly as {@link runCoreMigrations} does for core's tables. See
14
+ * {@link runPiiBackfill}.
8
15
  */
9
- export declare function runEnterpriseMigrations(db: Database, folder: string): Promise<void>;
16
+ export declare function runEnterpriseMigrations(db: Database, folder: string, opts?: {
17
+ piiBackfill?: PiiBackfillSpec;
18
+ }): Promise<void>;
19
+ /** A blind-index column and the sealed column whose plaintext it is the index of. */
20
+ export interface PiiBlindIndex {
21
+ /** One of the table's `encrypted` columns. */
22
+ source: string;
23
+ column: string;
24
+ }
25
+ /** One table of personal data, as the backfill works on it: the columns `encryptedText` and `blindIndexText` are declared on. */
26
+ export interface PiiBackfillTable {
27
+ table: string;
28
+ /** Columns that uniquely identify a row for the write-back UPDATE. */
29
+ key: string[];
30
+ /** Columns whose plaintext values get rewritten as ciphertext. */
31
+ encrypted: string[];
32
+ /** Blind-index column(s) to fill, each from the plaintext of its `source`. */
33
+ bidx?: PiiBlindIndex | PiiBlindIndex[];
34
+ }
35
+ /**
36
+ * Whose rows a backfill seals, and what closes it. Core's own tables are one
37
+ * such spec ({@link runPiiEncryptionBackfill}); an overlay that seals columns
38
+ * of its own schema writes another and hands it to
39
+ * {@link runEnterpriseMigrations} (or to {@link runPiiBackfill}, for a
40
+ * database it migrates under a lock of its own).
41
+ */
42
+ export interface PiiBackfillSpec {
43
+ /** Whose tables these are, for the log and the refusals: `core`, `enterprise`, … */
44
+ name: string;
45
+ tables: PiiBackfillTable[];
46
+ /**
47
+ * A blind-index column of one of `tables` that the SQL history adds
48
+ * NULLABLE and `finalize` makes NOT NULL. Its nullability is how a start
49
+ * knows whether this backfill has ever committed here: the sealing, the
50
+ * indexing and `finalize` are one transaction, so nullable means nothing is
51
+ * sealed yet, whatever a value looks like (see `needsSealing`), and NOT
52
+ * NULL means everything is. A spec whose `finalize` leaves it nullable is
53
+ * refused: every later start would take sealed rows for plaintext and seal
54
+ * them again.
55
+ */
56
+ marker: {
57
+ table: string;
58
+ column: string;
59
+ };
60
+ /**
61
+ * Runs in the same transaction once every row is sealed and indexed, before
62
+ * `finalize`: what has to happen before the constraints can go up (core
63
+ * collapses rows that collide under the normalised index). `first` is true
64
+ * on the first backfill of this database.
65
+ */
66
+ afterSealing?: (tx: PiiBackfillExecutor, run: {
67
+ first: boolean;
68
+ }) => Promise<void>;
69
+ /**
70
+ * Statements applied last, on every start, in order: `SET NOT NULL` on the
71
+ * index columns, the unique indexes that move onto them. Each must be safe
72
+ * to run again (`IF EXISTS` / `IF NOT EXISTS`; `SET NOT NULL` is).
73
+ */
74
+ finalize: string[];
75
+ /** What the key is called where the operator sets it, for the refusals. Default: `SECRETS_ENC_KEY`, with its tenant note. */
76
+ keyName?: string;
77
+ }
78
+ /** What the backfill needs from a drizzle client — the db or a transaction. */
79
+ export type PiiBackfillExecutor = Pick<Database, 'execute'>;
10
80
  /**
11
81
  * Encrypt pre-existing plaintext PII rows, fill the blind-index columns, and
12
82
  * apply the constraints migration 0016 deferred. Idempotent; `runCoreMigrations`
@@ -15,4 +85,20 @@ export declare function runEnterpriseMigrations(db: Database, folder: string): P
15
85
  * root's does): one that holds none is refused before anything is read.
16
86
  */
17
87
  export declare function runPiiEncryptionBackfill(db: Database): Promise<void>;
88
+ /**
89
+ * Seal the rows `spec` names that were written before their columns were
90
+ * sealed, fill their blind indexes, and apply `spec.finalize` — the DATA half
91
+ * of a migration that adds `encryptedText` / `blindIndexText` columns, which
92
+ * SQL cannot do because it holds no key. ONE implementation for every schema
93
+ * on a handle: core's own tables ({@link runPiiEncryptionBackfill}) and an
94
+ * overlay's, so the rules above (one transaction, a first run that trusts no
95
+ * shape, a key that must open what is sealed, columns read as stored, writes
96
+ * that pin what they read) are not rewritten per schema and cannot drift.
97
+ *
98
+ * Idempotent, and to be run on every start under the lock that guards the
99
+ * schema's history: {@link runEnterpriseMigrations} does that for an overlay
100
+ * that passes its spec. The handle must hold the key the rows are sealed
101
+ * with; one that holds none is refused before anything is read.
102
+ */
103
+ export declare function runPiiBackfill(db: Database, spec: PiiBackfillSpec): Promise<void>;
18
104
  //# sourceMappingURL=migrate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/modules/database/migrate.ts"],"names":[],"mappings":"AAKA,OAAO,EAA4C,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AA0D1F,8FAA8F;AAC9F,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAenF;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBzF;AA0TD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B1E"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/modules/database/migrate.ts"],"names":[],"mappings":"AAKA,OAAO,EAA4C,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AA0D1F,8FAA8F;AAC9F,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAenF;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,eAAe,CAAA;CAAO,GAC3C,OAAO,CAAC,IAAI,CAAC,CAiBf;AA+CD,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iIAAiI;AACjI,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,kEAAkE;IAClE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE,CAAC;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B;;;;;;;;;OASG;IACH,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,mBAAmB,EAAE,GAAG,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF;;;;OAIG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6HAA6H;IAC7H,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAeD,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAsU5D;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BvF"}
@@ -73,8 +73,15 @@ export async function runCoreMigrations(db, folder) {
73
73
  * Apply the ENTERPRISE migration history from `folder`, tracked in
74
74
  * `__drizzle_migrations_enterprise`. Run AFTER {@link runCoreMigrations} —
75
75
  * enterprise tables FK into core tables.
76
+ *
77
+ * `piiBackfill` is the overlay's own personal data, for the overlay that has
78
+ * sealed columns of its own (`encryptedText` / `blindIndexText` in its
79
+ * schema): the rows written before those columns were sealed are sealed here,
80
+ * right after the history that adds the index columns and under the same
81
+ * lock, exactly as {@link runCoreMigrations} does for core's tables. See
82
+ * {@link runPiiBackfill}.
76
83
  */
77
- export async function runEnterpriseMigrations(db, folder) {
84
+ export async function runEnterpriseMigrations(db, folder, opts = {}) {
78
85
  const { migrationsSchema, tenantKey } = ledgerOptions(db);
79
86
  await withAdvisoryLock(db, AdvisoryLock.Migrations, async () => {
80
87
  log.info('Running enterprise database migrations...');
@@ -84,6 +91,8 @@ export async function runEnterpriseMigrations(db, folder) {
84
91
  migrationsSchema,
85
92
  });
86
93
  log.info('Enterprise migrations complete.');
94
+ if (opts.piiBackfill)
95
+ await runPiiBackfill(db, opts.piiBackfill);
87
96
  }, { tenantKey });
88
97
  }
89
98
  const PII_BACKFILL_TABLES = [
@@ -97,6 +106,10 @@ const PII_BACKFILL_TABLES = [
97
106
  { table: 'plugin_join_requests', key: ['id'], encrypted: ['requester_email', 'requester_name', 'failure_reason'], bidx: { source: 'requester_email', column: 'requester_email_bidx' } },
98
107
  ];
99
108
  const ident = (name) => sql.raw(`"${name}"`);
109
+ /** A table's blind indexes, however many it declares. */
110
+ const indexesOf = (t) => (t.bidx === undefined ? [] : Array.isArray(t.bidx) ? t.bidx : [t.bidx]);
111
+ /** The name the refusals call the key by: the operator's own, with core's tenant note when it is core's. */
112
+ const keyNameOf = (spec) => spec.keyName ?? 'SECRETS_ENC_KEY (for a tenant: the one derived from TENANT_MASTER_KEY)';
100
113
  /** A text column as it is stored: bytes, so the handle's connection does not open it. */
101
114
  const asStored = (col) => sql `convert_to(${ident(col)}, 'UTF8') AS ${ident(col)}`;
102
115
  /** What {@link asStored} selected, back as text; anything else as it came. */
@@ -119,11 +132,11 @@ function needsSealing(col, trustShape) {
119
132
  return sql `(${ident(col)} IS NOT NULL AND ${ident(col)} <> '' AND ${ident(col)} !~ ${PII_SEALED_SHAPE_SQL_REGEX})`;
120
133
  }
121
134
  /**
122
- * Whether this database has never been through the backfill: the blind-index
123
- * column of `users` is still nullable. The backfill, the duplicate collapse
124
- * and the constraints run in ONE transaction, so a nullable column means no
125
- * backfill has ever committed here — and therefore that nothing in it is
126
- * sealed, whatever it looks like.
135
+ * Whether this database has never been through the backfill: the spec's
136
+ * marker column (for core, the blind index of `users`) is still nullable.
137
+ * The backfill, the duplicate collapse and the constraints run in ONE
138
+ * transaction, so a nullable column means no backfill has ever committed
139
+ * here — and therefore that nothing in it is sealed, whatever it looks like.
127
140
  *
128
141
  * That is what lets a first backfill trust no shape at all. A blob is
129
142
  * recognised by its shape, and a title or a display name is text a person
@@ -132,13 +145,23 @@ function needsSealing(col, trustShape) {
132
145
  * {@link assertKeyOpensSealedRows}, would refuse the start for a key that is
133
146
  * perfectly right. Once the first backfill has committed, every write goes
134
147
  * through a handle that seals it, so no such value can arrive again.
148
+ *
149
+ * A marker that is not there at all is the SQL history not having run (or a
150
+ * spec naming a column it does not add): refused, rather than read as "not
151
+ * the first run", which would trust every shape in a database nobody sealed.
135
152
  */
136
- async function isFirstBackfill(tx) {
153
+ async function isFirstBackfill(tx, spec) {
154
+ const { table, column } = spec.marker;
137
155
  const result = await tx.execute(sql `
138
156
  SELECT is_nullable FROM information_schema.columns
139
- WHERE table_schema = current_schema() AND table_name = 'users' AND column_name = 'email_bidx'
157
+ WHERE table_schema = current_schema() AND table_name = ${table} AND column_name = ${column}
140
158
  `);
141
- return result.rows[0]?.is_nullable === 'YES';
159
+ const nullable = result.rows[0]?.is_nullable;
160
+ if (nullable === undefined) {
161
+ throw new Error(`PII encryption backfill (${spec.name}): the marker column ${table}.${column} does not exist. ` +
162
+ 'Apply the migration that adds the blind-index columns before the backfill runs.');
163
+ }
164
+ return nullable === 'YES';
142
165
  }
143
166
  /** How many rows one backfill query reads: a table is walked in batches, never loaded whole. */
144
167
  const BACKFILL_BATCH_ROWS = 500;
@@ -148,22 +171,38 @@ const BACKFILL_BATCH_ROWS = 500;
148
171
  * are exactly the ones the scan skips — and surface only as every login
149
172
  * failing and every lookup by email missing, because the blind indexes would
150
173
  * be computed under the new key. One sealed value per table is enough: all
151
- * rows of a deployment are sealed under one key. Refusing the start is the
152
- * loud failure; re-keying a database is a deliberate operation, not a boot.
174
+ * rows of a deployment are sealed under one key, so any one of them answers
175
+ * for the rest. Refusing the start is the loud failure; re-keying a database
176
+ * is a deliberate operation, not a boot.
177
+ *
178
+ * The sample is a sealed value from WHICHEVER column has one, not from a
179
+ * column chosen to stand for its table. A column may hold nothing in any
180
+ * row (an optional address nobody gave, an error text that never occurred),
181
+ * and a check that looked only there would find no sample, say nothing, and
182
+ * let a wrong key through to a table whose other columns are full of values
183
+ * it cannot open.
153
184
  */
154
- async function assertKeyOpensSealedRows(tx, keys) {
155
- for (const t of PII_BACKFILL_TABLES) {
156
- const col = t.bidx?.source ?? t.encrypted[0];
157
- const sample = await tx.execute(sql `SELECT ${asStored(col)} FROM ${ident(t.table)} WHERE ${ident(col)} ~ ${PII_SEALED_SHAPE_SQL_REGEX} LIMIT 1`);
158
- const value = storedText(sample.rows[0]?.[col]);
159
- if (typeof value === 'string' && !keys.open(value).ok) {
160
- throw new Error(`PII encryption: ${t.table}.${col} is sealed with a key the configured SECRETS_ENC_KEY ` +
161
- '(for a tenant: the one derived from TENANT_MASTER_KEY) does not open — refusing to start. ' +
162
- 'Restore the key that sealed it; changing the key is a re-keying of the database, not a configuration change.');
185
+ async function assertKeyOpensSealedRows(tx, keys, spec) {
186
+ for (const t of spec.tables) {
187
+ // ONE pass over the table, which ends at the first row that has a sealed
188
+ // value in ANY of its sealed columns: on a sealed database, the first
189
+ // row. Whatever that row holds sealed is tried. (A value in it that is
190
+ // not sealed opens as itself, so it is no evidence either way.)
191
+ const sealedSomewhere = sql.join(t.encrypted.map((col) => sql `${ident(col)} ~ ${PII_SEALED_SHAPE_SQL_REGEX}`), sql ` OR `);
192
+ const sample = await tx.execute(sql `SELECT ${sql.join(t.encrypted.map(asStored), sql `, `)} FROM ${ident(t.table)} WHERE ${sealedSomewhere} LIMIT 1`);
193
+ const row = (sample.rows[0] ?? {});
194
+ for (const col of t.encrypted) {
195
+ const value = storedText(row[col]);
196
+ if (typeof value === 'string' && !keys.open(value).ok) {
197
+ throw new Error(`PII encryption: ${t.table}.${col} is sealed with a key the configured ${keyNameOf(spec)} ` +
198
+ 'does not open — refusing to start. ' +
199
+ 'Restore the key that sealed it; changing the key is a re-keying of the database, not a configuration change.');
200
+ }
163
201
  }
164
202
  }
165
203
  }
166
- async function backfillTable(tx, keys, t, trustShape) {
204
+ async function backfillTable(tx, keys, t, trustShape, keyName) {
205
+ const indexes = indexesOf(t);
167
206
  // The key columns are read as text beside themselves, so the next batch can
168
207
  // be asked for by value whatever their type is (a uuid, a serial, a path).
169
208
  const keyText = (k) => `${k}__key`;
@@ -171,13 +210,19 @@ async function backfillTable(tx, keys, t, trustShape) {
171
210
  ...t.key.map(ident),
172
211
  ...t.key.map((k) => sql `${ident(k)}::text AS ${ident(keyText(k))}`),
173
212
  ...t.encrypted.map(asStored),
174
- ...(t.bidx ? [ident(t.bidx.column)] : []),
213
+ ...indexes.map((index) => ident(index.column)),
175
214
  ];
176
215
  // Only rows with work left: the ciphertext prefix makes "unsealed" a plain
177
216
  // SQL predicate, so a fully-sealed table costs one empty-result query.
217
+ // AN INDEX IS THERE EXACTLY WHERE ITS SOURCE IS. A row is owed work when
218
+ // the two disagree, either way: a source with no index beside it, and an
219
+ // index left beside a source that has since been emptied to NULL (which
220
+ // would go on answering for an address the row no longer holds). A source
221
+ // that is NULL with no index is how an optional address looks, and is not
222
+ // asked for: it would come back on every start for nothing.
178
223
  const pending = [
179
224
  ...t.encrypted.map((col) => needsSealing(col, trustShape)),
180
- ...(t.bidx ? [sql `${ident(t.bidx.column)} IS NULL`] : []),
225
+ ...indexes.map((index) => sql `((${ident(index.column)} IS NULL) <> (${ident(index.source)} IS NULL))`),
181
226
  ];
182
227
  const keyTuple = sql `(${sql.join(t.key.map((k) => sql `${ident(k)}::text`), sql `, `)})`;
183
228
  // A blob, as far as this pass may believe one. On a first backfill nothing
@@ -210,7 +255,7 @@ async function backfillTable(tx, keys, t, trustShape) {
210
255
  where.push(sql `${ident(col)} = ${value}`);
211
256
  }
212
257
  }
213
- if (t.bidx) {
258
+ for (const index of indexes) {
214
259
  // The blind index is derived from its source, so it is (re)computed
215
260
  // whenever the source is being sealed in this pass — a legacy writer
216
261
  // that put a NEW plaintext email on an already-indexed row left a stale
@@ -219,23 +264,41 @@ async function backfillTable(tx, keys, t, trustShape) {
219
264
  // ciphertext (an index that was never filled beside a sealed address);
220
265
  // the index is always computed over the plaintext, never over a blob
221
266
  // the key cannot open.
222
- const source = row[t.bidx.source];
223
- const stored = row[t.bidx.column];
224
- const text = typeof source === 'string' ? source : '';
267
+ const source = row[index.source];
268
+ const stored = row[index.column];
269
+ // NULL is "no value", and has no index: not the index of the empty
270
+ // string, which every row without an address would then share where
271
+ // a plain unique index let any number of NULLs stand. An index found
272
+ // beside a NULL source is taken away, pinned to what was read like
273
+ // every other write here.
274
+ //
275
+ // The EMPTY STRING is a value, and keeps its index: it is what the
276
+ // handle writes for one (`blindIndexText`), so a row is found by it
277
+ // whether the application wrote it or this did, and two empty
278
+ // strings are equal under a unique index, as they were in clear.
279
+ if (typeof source !== 'string') {
280
+ if (stored != null) {
281
+ sets.push(sql `${ident(index.column)} = NULL`);
282
+ where.push(sql `${ident(index.column)} = ${stored}`);
283
+ where.push(sql `${ident(index.source)} IS NULL`);
284
+ }
285
+ continue;
286
+ }
287
+ const text = source;
225
288
  const sealingSource = text !== '' && !sealedAlready(text);
226
289
  if (sealingSource || stored == null) {
227
290
  const opened = sealedAlready(text) ? keys.open(text) : { ok: true, plain: text };
228
291
  if (!opened.ok) {
229
- throw new Error(`PII encryption backfill: ${t.table}.${t.bidx.source} cannot be decrypted with the ` +
230
- 'configured SECRETS_ENC_KEY — refusing to derive a blind index from ciphertext. ' +
292
+ throw new Error(`PII encryption backfill: ${t.table}.${index.source} cannot be decrypted with the ` +
293
+ `configured ${keyName} — refusing to derive a blind index from ciphertext. ` +
231
294
  'Restore the key that sealed it, then restart.');
232
295
  }
233
- sets.push(sql `${ident(t.bidx.column)} = ${keys.index(opened.plain)}`);
296
+ sets.push(sql `${ident(index.column)} = ${keys.index(opened.plain)}`);
234
297
  // Pin the index AND its source: if a concurrent writer replaces the
235
298
  // email between scan and write, the CAS must not attach the OLD
236
299
  // email's blind index to the NEW value.
237
- where.push(sql `${ident(t.bidx.column)} IS NOT DISTINCT FROM ${stored ?? null}`);
238
- where.push(sql `${ident(t.bidx.source)} IS NOT DISTINCT FROM ${source ?? null}`);
300
+ where.push(sql `${ident(index.column)} IS NOT DISTINCT FROM ${stored ?? null}`);
301
+ where.push(sql `${ident(index.source)} IS NOT DISTINCT FROM ${source ?? null}`);
239
302
  }
240
303
  }
241
304
  if (sets.length === 0)
@@ -314,6 +377,25 @@ const PII_FINALIZE_STATEMENTS = [
314
377
  'CREATE UNIQUE INDEX IF NOT EXISTS "plugin_join_requests_requester_bidx_plugin_unq" ON "plugin_join_requests" ("requester_email_bidx","plugin_key")',
315
378
  'DROP INDEX IF EXISTS "plugin_join_requests_requester_plugin_unq"',
316
379
  ];
380
+ /** Core's own personal data: the tables above, and what migration 0016 deferred. */
381
+ const CORE_PII_BACKFILL = {
382
+ name: 'core',
383
+ tables: PII_BACKFILL_TABLES,
384
+ marker: { table: 'users', column: 'email_bidx' },
385
+ afterSealing: async (tx, { first }) => {
386
+ const cleared = await clearUnindexedRefusalNames(tx);
387
+ if (cleared > 0) {
388
+ log.info(`PII encryption backfill: took the name off ${cleared} refused apply(ies) recorded before this release.`);
389
+ }
390
+ // Only where the unique indexes are not up yet. Once they are, they are
391
+ // what keeps two rows from sharing an index, so there is nothing to
392
+ // collapse — and the collapse is two self-joins and an aggregate over
393
+ // whole tables, which every later start paid for nothing.
394
+ if (first)
395
+ await resolveBidxCollisions(tx);
396
+ },
397
+ finalize: PII_FINALIZE_STATEMENTS,
398
+ };
317
399
  /**
318
400
  * Encrypt pre-existing plaintext PII rows, fill the blind-index columns, and
319
401
  * apply the constraints migration 0016 deferred. Idempotent; `runCoreMigrations`
@@ -322,33 +404,69 @@ const PII_FINALIZE_STATEMENTS = [
322
404
  * root's does): one that holds none is refused before anything is read.
323
405
  */
324
406
  export async function runPiiEncryptionBackfill(db) {
407
+ await runPiiBackfill(db, CORE_PII_BACKFILL);
408
+ }
409
+ /**
410
+ * Seal the rows `spec` names that were written before their columns were
411
+ * sealed, fill their blind indexes, and apply `spec.finalize` — the DATA half
412
+ * of a migration that adds `encryptedText` / `blindIndexText` columns, which
413
+ * SQL cannot do because it holds no key. ONE implementation for every schema
414
+ * on a handle: core's own tables ({@link runPiiEncryptionBackfill}) and an
415
+ * overlay's, so the rules above (one transaction, a first run that trusts no
416
+ * shape, a key that must open what is sealed, columns read as stored, writes
417
+ * that pin what they read) are not rewritten per schema and cannot drift.
418
+ *
419
+ * Idempotent, and to be run on every start under the lock that guards the
420
+ * schema's history: {@link runEnterpriseMigrations} does that for an overlay
421
+ * that passes its spec. The handle must hold the key the rows are sealed
422
+ * with; one that holds none is refused before anything is read.
423
+ */
424
+ export async function runPiiBackfill(db, spec) {
325
425
  const keys = piiKeysOf(db);
426
+ assertSpecIsWhole(spec);
427
+ const label = spec.name === CORE_PII_BACKFILL.name ? 'PII encryption backfill' : `PII encryption backfill (${spec.name})`;
326
428
  await db.transaction(async (tx) => {
327
- const first = await isFirstBackfill(tx);
429
+ const first = await isFirstBackfill(tx, spec);
328
430
  // Nothing is sealed before the first backfill, so there is no sealed row
329
431
  // for the key to be checked against — and a value that only LOOKS sealed
330
432
  // must not be taken for one (see `isFirstBackfill`).
331
433
  if (!first)
332
- await assertKeyOpensSealedRows(tx, keys);
434
+ await assertKeyOpensSealedRows(tx, keys, spec);
333
435
  let rewritten = 0;
334
- for (const t of PII_BACKFILL_TABLES) {
335
- rewritten += await backfillTable(tx, keys, t, !first);
436
+ for (const t of spec.tables) {
437
+ rewritten += await backfillTable(tx, keys, t, !first, keyNameOf(spec));
336
438
  }
337
439
  if (rewritten > 0)
338
- log.info(`PII encryption backfill: rewrote ${rewritten} row(s).`);
339
- const cleared = await clearUnindexedRefusalNames(tx);
340
- if (cleared > 0) {
341
- log.info(`PII encryption backfill: took the name off ${cleared} refused apply(ies) recorded before this release.`);
342
- }
343
- // Only where the unique indexes are not up yet. Once they are, they are
344
- // what keeps two rows from sharing an index, so there is nothing to
345
- // collapse — and the collapse is two self-joins and an aggregate over
346
- // whole tables, which every later start paid for nothing.
347
- if (first)
348
- await resolveBidxCollisions(tx);
349
- for (const statement of PII_FINALIZE_STATEMENTS) {
440
+ log.info(`${label}: rewrote ${rewritten} row(s).`);
441
+ await spec.afterSealing?.(tx, { first });
442
+ for (const statement of spec.finalize) {
350
443
  await tx.execute(sql.raw(statement));
351
444
  }
445
+ // The marker is what the NEXT start reads. Left nullable, that start
446
+ // would be a "first" one again: it would believe no shape, take every
447
+ // sealed value for plaintext and seal it a second time, and nothing
448
+ // would open afterwards. So a spec that does not close its own marker
449
+ // does not commit.
450
+ if (await isFirstBackfill(tx, spec)) {
451
+ throw new Error(`${label}: finalize left the marker column ${spec.marker.table}.${spec.marker.column} nullable. ` +
452
+ 'It must set it NOT NULL, or the next start would seal the sealed rows again. Nothing was changed.');
453
+ }
352
454
  });
353
455
  }
456
+ /** A spec is refused for what would otherwise fail halfway: a marker that is no index of its tables, an index of a column that is not sealed. */
457
+ function assertSpecIsWhole(spec) {
458
+ let markerIsAnIndex = false;
459
+ for (const t of spec.tables) {
460
+ for (const index of indexesOf(t)) {
461
+ if (!t.encrypted.includes(index.source)) {
462
+ throw new Error(`PII encryption backfill (${spec.name}): ${t.table}.${index.column} indexes "${index.source}", which is not one of the table's encrypted columns.`);
463
+ }
464
+ if (t.table === spec.marker.table && index.column === spec.marker.column)
465
+ markerIsAnIndex = true;
466
+ }
467
+ }
468
+ if (!markerIsAnIndex) {
469
+ throw new Error(`PII encryption backfill (${spec.name}): the marker ${spec.marker.table}.${spec.marker.column} is not a blind-index column of the spec's tables.`);
470
+ }
471
+ }
354
472
  //# sourceMappingURL=migrate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/modules/database/migrate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/modules/database/migrate.ts"],"names":[],"mappings":"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"}
@@ -114,6 +114,23 @@ export declare class LockingFilesystem extends GitGuardedFilesystem {
114
114
  * the write and releases the lock untouched; the caller gets what it threw.
115
115
  */
116
116
  writeFile(inputPath: string, content: FileContent, options?: WriteOptions, check?: () => void | Promise<void>): Promise<void>;
117
+ /**
118
+ * Write a file whose new content DEPENDS on what it holds: the read, the
119
+ * computing of the new bytes and the write all happen with the path's lock
120
+ * held, so what lands is derived from the very bytes it replaces.
121
+ *
122
+ * `writeFile` cannot give that. Its content is fixed before the lock is
123
+ * taken, so a caller that read the file first is writing over a state
124
+ * anyone may have moved in between: an `edit_file` replacing an empty owner
125
+ * field with one name would silently overwrite another name written a
126
+ * moment earlier, and both callers would be told their edit landed.
127
+ *
128
+ * `rewrite` receives the file as it is under the lock (null when nothing is
129
+ * there) and answers the bytes to write. Throwing refuses: nothing is
130
+ * written, the lock is released untouched, and the caller gets what was
131
+ * thrown.
132
+ */
133
+ rewriteFile(inputPath: string, rewrite: (current: Buffer | null) => FileContent | Promise<FileContent>): Promise<void>;
117
134
  appendFile(inputPath: string, content: FileContent): Promise<void>;
118
135
  deleteFile(inputPath: string, options?: RemoveOptions): Promise<void>;
119
136
  copyFile(src: string, dest: string, options?: CopyOptions): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"locking-filesystem.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/locking-filesystem.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"locking-filesystem.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/locking-filesystem.ts"],"names":[],"mappings":"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"}
@@ -98,6 +98,35 @@ export class LockingFilesystem extends GitGuardedFilesystem {
98
98
  await validate?.(inputPath, toWrite);
99
99
  }));
100
100
  }
101
+ /**
102
+ * Write a file whose new content DEPENDS on what it holds: the read, the
103
+ * computing of the new bytes and the write all happen with the path's lock
104
+ * held, so what lands is derived from the very bytes it replaces.
105
+ *
106
+ * `writeFile` cannot give that. Its content is fixed before the lock is
107
+ * taken, so a caller that read the file first is writing over a state
108
+ * anyone may have moved in between: an `edit_file` replacing an empty owner
109
+ * field with one name would silently overwrite another name written a
110
+ * moment earlier, and both callers would be told their edit landed.
111
+ *
112
+ * `rewrite` receives the file as it is under the lock (null when nothing is
113
+ * there) and answers the bytes to write. Throwing refuses: nothing is
114
+ * written, the lock is released untouched, and the caller gets what was
115
+ * thrown.
116
+ */
117
+ async rewriteFile(inputPath, rewrite) {
118
+ await this.assertNotGitInternals(inputPath);
119
+ this.assertInsideRepo(inputPath);
120
+ const validate = this.lockContext.validateWrite;
121
+ let toWrite = null;
122
+ return this.withLock(inputPath, () => super.writeFile(inputPath, toWrite), async () => {
123
+ const next = await rewrite(await this.readIfExists(inputPath));
124
+ // The pre-disk gate judges the bytes that will land, as it does for
125
+ // every other write, and here those exist only now.
126
+ await validate?.(inputPath, next);
127
+ toWrite = next;
128
+ });
129
+ }
101
130
  async appendFile(inputPath, content) {
102
131
  await this.assertNotGitInternals(inputPath);
103
132
  this.assertInsideRepo(inputPath);