@bevel-software/platform-core-backend 0.23.0 → 0.25.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/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +17 -3
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +3 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +25 -1
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +12 -0
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +10 -0
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core-config.d.ts +16 -0
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +17 -0
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +4 -1
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/directory-sync-bot.d.ts.map +1 -1
- package/dist/modules/access/directory-sync-bot.js +7 -3
- package/dist/modules/access/directory-sync-bot.js.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +8 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.js +8 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +38 -6
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +39 -6
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/index.d.ts +2 -1
- package/dist/modules/agent-instructions/index.d.ts.map +1 -1
- package/dist/modules/agent-instructions/index.js +2 -1
- package/dist/modules/agent-instructions/index.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +115 -0
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -0
- package/dist/modules/agent-instructions/shared-file-rules.js +272 -0
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -0
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
- package/dist/modules/audit/agent-audit.service.js +4 -2
- package/dist/modules/audit/agent-audit.service.js.map +1 -1
- package/dist/modules/auth/account-erasure.service.d.ts.map +1 -1
- package/dist/modules/auth/account-erasure.service.js +57 -16
- package/dist/modules/auth/account-erasure.service.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +25 -15
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.d.ts +20 -2
- package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.js +66 -35
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
- package/dist/modules/database/connection.d.ts +16 -0
- package/dist/modules/database/connection.d.ts.map +1 -1
- package/dist/modules/database/connection.js +117 -0
- package/dist/modules/database/connection.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +296 -96
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +81 -31
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/database/migrate.d.ts +95 -1
- package/dist/modules/database/migrate.d.ts.map +1 -1
- package/dist/modules/database/migrate.js +390 -2
- package/dist/modules/database/migrate.js.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.d.ts +17 -0
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.js +29 -0
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +8 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +38 -8
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/plugins/join-request-records.store.d.ts.map +1 -1
- package/dist/modules/plugins/join-request-records.store.js +7 -4
- package/dist/modules/plugins/join-request-records.store.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +8 -2
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +30 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +42 -31
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/description-length.d.ts +80 -0
- package/dist/modules/tool-registry/description-length.d.ts.map +1 -0
- package/dist/modules/tool-registry/description-length.js +108 -0
- package/dist/modules/tool-registry/description-length.js.map +1 -0
- package/dist/modules/workflow/git/git.service.d.ts +25 -0
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +40 -1
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.service.js +5 -1
- package/dist/modules/workflow/pending-commits.service.js.map +1 -1
- package/dist/modules/workflow/recovery-bot.d.ts.map +1 -1
- package/dist/modules/workflow/recovery-bot.js +7 -3
- package/dist/modules/workflow/recovery-bot.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +12 -3
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +4 -1
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-upload.routes.d.ts +77 -0
- package/dist/modules/workspace/agent-upload.routes.d.ts.map +1 -0
- package/dist/modules/workspace/agent-upload.routes.js +210 -0
- package/dist/modules/workspace/agent-upload.routes.js.map +1 -0
- package/dist/modules/workspace/agent-upload.store.d.ts +284 -0
- package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -0
- package/dist/modules/workspace/agent-upload.store.js +553 -0
- package/dist/modules/workspace/agent-upload.store.js.map +1 -0
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +3 -3
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +40 -0
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +46 -4
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/upload-limits.d.ts +13 -0
- package/dist/modules/workspace/upload-limits.d.ts.map +1 -0
- package/dist/modules/workspace/upload-limits.js +13 -0
- package/dist/modules/workspace/upload-limits.js.map +1 -0
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +1 -1
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +13 -0
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +61 -33
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +11 -9
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +570 -134
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/modules/workspace/write-denial.d.ts +0 -6
- package/dist/modules/workspace/write-denial.d.ts.map +1 -1
- package/dist/modules/workspace/write-denial.js +0 -6
- package/dist/modules/workspace/write-denial.js.map +1 -1
- package/dist/modules/workspace/zip-entry-rules.d.ts +114 -0
- package/dist/modules/workspace/zip-entry-rules.d.ts.map +1 -0
- package/dist/modules/workspace/zip-entry-rules.js +154 -0
- package/dist/modules/workspace/zip-entry-rules.js.map +1 -0
- package/dist/shared/column-crypto.d.ts +194 -0
- package/dist/shared/column-crypto.d.ts.map +1 -0
- package/dist/shared/column-crypto.js +144 -0
- package/dist/shared/column-crypto.js.map +1 -0
- package/dist/shared/token-crypto.d.ts.map +1 -1
- package/dist/shared/token-crypto.js +25 -1
- package/dist/shared/token-crypto.js.map +1 -1
- package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
- package/dist/tenancy/static-tenant-source.js +1 -0
- package/dist/tenancy/static-tenant-source.js.map +1 -1
- package/dist/tenancy/tenant-secrets.d.ts +5 -1
- package/dist/tenancy/tenant-secrets.d.ts.map +1 -1
- package/dist/tenancy/tenant-secrets.js +4 -0
- package/dist/tenancy/tenant-secrets.js.map +1 -1
- package/kb-template/AGENTS.md +42 -0
- package/migrations/0016_pii_encryption.sql +20 -0
- package/migrations/meta/0016_snapshot.json +2327 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +3 -3
- package/src/core/__tests__/lifecycle.test.ts +71 -4
- package/src/core/create-core-server.ts +21 -3
- package/src/core/create-core-services.ts +27 -1
- package/src/core/lifecycle.ts +19 -0
- package/src/core-config.ts +18 -0
- package/src/index.ts +25 -0
- package/src/modules/access/__tests__/users-db-double.ts +21 -12
- package/src/modules/access/access.routes.ts +4 -1
- package/src/modules/access/directory-sync-bot.ts +7 -3
- package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +8 -4
- package/src/modules/agent-instructions/__tests__/compose.test.ts +19 -10
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +238 -0
- package/src/modules/agent-instructions/agent-instructions.routes.ts +12 -2
- package/src/modules/agent-instructions/compose.ts +50 -7
- package/src/modules/agent-instructions/index.ts +12 -0
- package/src/modules/agent-instructions/shared-file-rules.ts +314 -0
- package/src/modules/audit/agent-audit.service.ts +4 -2
- package/src/modules/auth/__tests__/account-deactivation.test.ts +2 -1
- package/src/modules/auth/__tests__/account-erasure.approval-gate.test.ts +6 -2
- package/src/modules/auth/__tests__/account.routes.test.ts +6 -3
- package/src/modules/auth/__tests__/auth.service.test.ts +3 -1
- package/src/modules/auth/account-erasure.service.ts +69 -18
- package/src/modules/auth/auth.service.ts +33 -23
- package/src/modules/code-mode/__tests__/chain-runtime.e2e.test.ts +335 -0
- package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +46 -2
- package/src/modules/code-mode/code-mode.tool.ts +80 -34
- package/src/modules/database/__tests__/connection.test.ts +12 -0
- package/src/modules/database/__tests__/pii-backfill.pg.test.ts +780 -0
- package/src/modules/database/connection.ts +117 -0
- package/src/modules/database/core-schema.ts +81 -31
- package/src/modules/database/migrate.ts +540 -2
- package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +93 -0
- package/src/modules/kb-fs/locking-filesystem.ts +37 -0
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +4 -3
- package/src/modules/mcp/__tests__/mcp.service.test.ts +47 -7
- package/src/modules/mcp/mcp.service.ts +46 -7
- package/src/modules/plugins/join-request-records.store.ts +7 -4
- package/src/modules/tool-auth/external-api-key.service.ts +8 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +151 -0
- package/src/modules/tool-manuals/tool-manuals.service.ts +37 -0
- package/src/modules/tool-manuals/tool-manuals.tools.ts +44 -31
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +378 -0
- package/src/modules/tool-registry/description-length.ts +111 -0
- package/src/modules/workflow/git/__tests__/git.service.prFetchFailure.test.ts +170 -0
- package/src/modules/workflow/git/git.service.ts +47 -1
- package/src/modules/workflow/pending-commits.service.ts +5 -1
- package/src/modules/workflow/recovery-bot.ts +7 -3
- package/src/modules/workflow/review-workflow/__tests__/carry-approvals-forward.test.ts +4 -0
- package/src/modules/workflow/review-workflow/__tests__/erase-approver.test.ts +25 -3
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +12 -3
- package/src/modules/workflow/workflow.service.ts +4 -1
- package/src/modules/workspace/__tests__/agent-uploads.test.ts +1604 -0
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +24 -14
- package/src/modules/workspace/__tests__/workspace.service.any-workspace-credentials.test.ts +156 -0
- package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +77 -1
- package/src/modules/workspace/__tests__/workspace.service.test.ts +57 -0
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +39 -36
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +196 -46
- package/src/modules/workspace/agent-upload.routes.ts +214 -0
- package/src/modules/workspace/agent-upload.store.ts +668 -0
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +9 -9
- package/src/modules/workspace/startup/steps/seed-tree.ts +3 -6
- package/src/modules/workspace/startup/steps/template-source.ts +53 -5
- package/src/modules/workspace/upload-limits.ts +12 -0
- package/src/modules/workspace/workspace.routes.ts +1 -2
- package/src/modules/workspace/workspace.service.ts +63 -37
- package/src/modules/workspace/workspace.tools.ts +647 -148
- package/src/modules/workspace/write-denial.ts +0 -8
- package/src/modules/workspace/zip-entry-rules.ts +173 -0
- package/src/shared/__tests__/column-crypto.test.ts +217 -0
- package/src/shared/column-crypto.ts +218 -0
- package/src/shared/token-crypto.ts +28 -1
- package/src/tenancy/__tests__/static-tenant-source.test.ts +4 -0
- package/src/tenancy/static-tenant-source.ts +1 -0
- package/src/tenancy/tenant-secrets.ts +5 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as schema from './schema.js';
|
|
2
|
+
import { type PiiKeys } from '../../shared/column-crypto.js';
|
|
2
3
|
/**
|
|
3
4
|
* One database, one schema per knowledge base.
|
|
4
5
|
*
|
|
@@ -43,6 +44,14 @@ export interface DbOptions {
|
|
|
43
44
|
max?: number;
|
|
44
45
|
/** How long an idle connection is kept before the pool closes it. Default: `pg`'s. */
|
|
45
46
|
idleTimeoutMillis?: number;
|
|
47
|
+
/**
|
|
48
|
+
* The key this handle seals personal data with: the `SECRETS_ENC_KEY` of
|
|
49
|
+
* the knowledge base whose rows it holds (its own derived one, for a
|
|
50
|
+
* tenant). Without it the handle reads sealed values as their blobs and
|
|
51
|
+
* refuses to write one — right for a handle that only touches tables with
|
|
52
|
+
* no personal data, and a loud failure for one that was meant to have it.
|
|
53
|
+
*/
|
|
54
|
+
piiKey?: string;
|
|
46
55
|
}
|
|
47
56
|
/**
|
|
48
57
|
* A NEW pool on `databaseUrl`, searching `opts.schema` first. Not cached:
|
|
@@ -56,6 +65,13 @@ export declare function createDb(databaseUrl: string, opts?: DbOptions): import(
|
|
|
56
65
|
export type Database = ReturnType<typeof createDb>;
|
|
57
66
|
/** The schema a database handle searches first — for the callers that name it in DDL. */
|
|
58
67
|
export declare function dbSchemaOf(db: Pick<Database, '$client'>): string;
|
|
68
|
+
/**
|
|
69
|
+
* The keys a handle seals personal data with — for the few callers that
|
|
70
|
+
* handle the stored form themselves (the backfill at start; an overlay's own
|
|
71
|
+
* SQL). Everything else never sees a key: the column types and the handle's
|
|
72
|
+
* connection do the work. Throws for a handle built without one.
|
|
73
|
+
*/
|
|
74
|
+
export declare function piiKeysOf(db: Pick<Database, '$client'>): PiiKeys;
|
|
59
75
|
/**
|
|
60
76
|
* The process's pool on `databaseUrl` for `opts.schema`, created on first
|
|
61
77
|
* use and shared afterwards. One per (url, schema): two handles on the same
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/modules/database/connection.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/modules/database/connection.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAkD,KAAK,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAE7G;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcrD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnG;AAED,MAAM,WAAW,SAAS;IACxB,yFAAyF;IACzF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAmFD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,SAAc;;EAqBjE;AAED,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEnD,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,MAAM,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,OAAO,CAMhE;AAQD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,SAAc,GAAG,QAAQ,CAazE;AAiBD;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1E"}
|
|
@@ -2,6 +2,7 @@ import { sql } from 'drizzle-orm';
|
|
|
2
2
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
3
3
|
import pg from 'pg';
|
|
4
4
|
import * as schema from './schema.js';
|
|
5
|
+
import { PII_CIPHERTEXT_PREFIX, PiiParam, derivePiiKeys } from '../../shared/column-crypto.js';
|
|
5
6
|
/**
|
|
6
7
|
* One database, one schema per knowledge base.
|
|
7
8
|
*
|
|
@@ -55,6 +56,81 @@ export async function assertSearchPath(db, schema) {
|
|
|
55
56
|
'use session pooling, or connect directly.');
|
|
56
57
|
}
|
|
57
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* The `pg` client of a handle that holds `keys`: the one place personal data
|
|
61
|
+
* changes form. Going in, every value a personal-data column marked (see
|
|
62
|
+
* `column-crypto.ts`) is replaced by its ciphertext or its blind index.
|
|
63
|
+
* Coming out, every sealed value of a result is opened — by its prefix, not
|
|
64
|
+
* by its column, so raw SQL through the handle reads plaintext too; a
|
|
65
|
+
* statement that needs what is STORED asks for it as bytes
|
|
66
|
+
* (`convert_to(col, 'UTF8')`).
|
|
67
|
+
*
|
|
68
|
+
* At the client, because that is what the handle owns: the pool builds every
|
|
69
|
+
* connection from this class, a transaction's included, so there is no path
|
|
70
|
+
* from this handle to the database that goes round it. Results that are
|
|
71
|
+
* streamed to a `Submittable` (a cursor) are not opened; nothing here uses one.
|
|
72
|
+
*/
|
|
73
|
+
function keyedClient(keys) {
|
|
74
|
+
const stored = (value) => {
|
|
75
|
+
if (!(value instanceof PiiParam))
|
|
76
|
+
return value;
|
|
77
|
+
return keys ? value.stored(keys) : value.toPostgres();
|
|
78
|
+
};
|
|
79
|
+
const openCell = (value) => typeof value === 'string' && value.startsWith(PII_CIPHERTEXT_PREFIX) ? keys.read(value) : value;
|
|
80
|
+
const openOne = (result) => {
|
|
81
|
+
const rows = result?.rows;
|
|
82
|
+
if (!Array.isArray(rows))
|
|
83
|
+
return;
|
|
84
|
+
for (const row of rows) {
|
|
85
|
+
if (Array.isArray(row)) {
|
|
86
|
+
for (let i = 0; i < row.length; i++)
|
|
87
|
+
row[i] = openCell(row[i]);
|
|
88
|
+
}
|
|
89
|
+
else if (row && typeof row === 'object') {
|
|
90
|
+
const record = row;
|
|
91
|
+
for (const column of Object.keys(record))
|
|
92
|
+
record[column] = openCell(record[column]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const open = (result) => {
|
|
97
|
+
if (!keys)
|
|
98
|
+
return result;
|
|
99
|
+
// Several statements in one query string come back as several results.
|
|
100
|
+
if (Array.isArray(result))
|
|
101
|
+
result.forEach(openOne);
|
|
102
|
+
else
|
|
103
|
+
openOne(result);
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
106
|
+
const base = pg.Client.prototype.query;
|
|
107
|
+
class KeyedClient extends pg.Client {
|
|
108
|
+
}
|
|
109
|
+
const query = function (config, values, callback) {
|
|
110
|
+
if (typeof values === 'function') {
|
|
111
|
+
callback = values;
|
|
112
|
+
values = undefined;
|
|
113
|
+
}
|
|
114
|
+
if (Array.isArray(values)) {
|
|
115
|
+
values = values.map(stored);
|
|
116
|
+
}
|
|
117
|
+
else if (config && typeof config === 'object' && Array.isArray(config.values)) {
|
|
118
|
+
const withValues = config;
|
|
119
|
+
if (typeof withValues.submit === 'function')
|
|
120
|
+
withValues.values = withValues.values.map(stored);
|
|
121
|
+
else
|
|
122
|
+
config = { ...withValues, values: withValues.values.map(stored) };
|
|
123
|
+
}
|
|
124
|
+
if (typeof callback === 'function') {
|
|
125
|
+
const done = callback;
|
|
126
|
+
return base.call(this, config, values, (err, result) => done(err, err ? result : open(result)));
|
|
127
|
+
}
|
|
128
|
+
const pending = base.call(this, config, values);
|
|
129
|
+
return pending instanceof Promise ? pending.then(open) : pending;
|
|
130
|
+
};
|
|
131
|
+
Object.defineProperty(KeyedClient.prototype, 'query', { value: query, writable: true, configurable: true });
|
|
132
|
+
return KeyedClient;
|
|
133
|
+
}
|
|
58
134
|
/**
|
|
59
135
|
* A bounded handshake: `pg` waits forever by default for a NEW connection to
|
|
60
136
|
* come up, so a database that accepts the socket and never finishes the
|
|
@@ -74,7 +150,11 @@ const CONNECT_TIMEOUT_MS = 30_000;
|
|
|
74
150
|
*/
|
|
75
151
|
export function createDb(databaseUrl, opts = {}) {
|
|
76
152
|
const dbSchema = assertSchemaName(opts.schema ?? DEFAULT_DB_SCHEMA);
|
|
153
|
+
// Only an ABSENT key means "this handle holds none". A blank or malformed
|
|
154
|
+
// one was meant to be a key, and is refused here rather than read as none.
|
|
155
|
+
const keys = opts.piiKey === undefined ? null : derivePiiKeys(opts.piiKey);
|
|
77
156
|
const pool = new pg.Pool({
|
|
157
|
+
Client: keyedClient(keys),
|
|
78
158
|
connectionString: databaseUrl,
|
|
79
159
|
connectionTimeoutMillis: CONNECT_TIMEOUT_MS,
|
|
80
160
|
max: opts.max,
|
|
@@ -87,13 +167,29 @@ export function createDb(databaseUrl, opts = {}) {
|
|
|
87
167
|
});
|
|
88
168
|
const db = drizzle(pool, { schema });
|
|
89
169
|
schemas.set(db, dbSchema);
|
|
170
|
+
if (keys)
|
|
171
|
+
piiKeys.set(db, { keys, of: opts.piiKey });
|
|
90
172
|
return db;
|
|
91
173
|
}
|
|
92
174
|
/** The schema a database handle searches first — for the callers that name it in DDL. */
|
|
93
175
|
export function dbSchemaOf(db) {
|
|
94
176
|
return schemas.get(db) ?? DEFAULT_DB_SCHEMA;
|
|
95
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* The keys a handle seals personal data with — for the few callers that
|
|
180
|
+
* handle the stored form themselves (the backfill at start; an overlay's own
|
|
181
|
+
* SQL). Everything else never sees a key: the column types and the handle's
|
|
182
|
+
* connection do the work. Throws for a handle built without one.
|
|
183
|
+
*/
|
|
184
|
+
export function piiKeysOf(db) {
|
|
185
|
+
const held = piiKeys.get(db);
|
|
186
|
+
if (!held) {
|
|
187
|
+
throw new Error('This database handle holds no personal-data key: build it with createDb/getDb and its piiKey.');
|
|
188
|
+
}
|
|
189
|
+
return held.keys;
|
|
190
|
+
}
|
|
96
191
|
const schemas = new WeakMap();
|
|
192
|
+
const piiKeys = new WeakMap();
|
|
97
193
|
const cache = new Map();
|
|
98
194
|
const cacheKey = (databaseUrl, dbSchema) => `${dbSchema}\u0000${databaseUrl}`;
|
|
99
195
|
/**
|
|
@@ -109,8 +205,29 @@ export function getDb(databaseUrl, opts = {}) {
|
|
|
109
205
|
db = createDb(databaseUrl, opts);
|
|
110
206
|
cache.set(key, db);
|
|
111
207
|
}
|
|
208
|
+
else if (opts.piiKey !== undefined && !holdsKey(db, opts.piiKey)) {
|
|
209
|
+
// One schema is one knowledge base and one key. Handing back the cached
|
|
210
|
+
// pool would seal this caller's rows under the other caller's key.
|
|
211
|
+
throw new Error(`The database handle for schema "${dbSchema}" is already open with a different personal-data key.`);
|
|
212
|
+
}
|
|
112
213
|
return db;
|
|
113
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Whether `db` was opened with the key `piiKey` spells. The KEY, not its
|
|
217
|
+
* spelling: `SECRETS_ENC_KEY` may be written as hex or as base64, and one
|
|
218
|
+
* process can be handed the same 32 bytes both ways — refusing the second as
|
|
219
|
+
* "a different key" would refuse a caller that holds the right one. Compared
|
|
220
|
+
* through what the two derive, so no key material is held here to compare.
|
|
221
|
+
*/
|
|
222
|
+
function holdsKey(db, piiKey) {
|
|
223
|
+
const held = piiKeys.get(db);
|
|
224
|
+
if (!held)
|
|
225
|
+
return false;
|
|
226
|
+
if (held.of === piiKey)
|
|
227
|
+
return true;
|
|
228
|
+
const probe = 'same-key?';
|
|
229
|
+
return held.keys.index(probe) === derivePiiKeys(piiKey).index(probe);
|
|
230
|
+
}
|
|
114
231
|
/**
|
|
115
232
|
* End a handle's pool and forget it, so a later {@link getDb} for the same
|
|
116
233
|
* schema opens a fresh one rather than handing out a pool that was ended.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/modules/database/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/modules/database/connection.ts"],"names":[],"mappings":"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"}
|