@stigmer/server 3.25.0 → 3.27.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/authorization/evaluator.d.ts +4 -1
- package/dist/authorization/evaluator.d.ts.map +1 -1
- package/dist/authorization/evaluator.js +8 -0
- package/dist/authorization/evaluator.js.map +1 -1
- package/dist/authorization/model/agent.d.ts.map +1 -1
- package/dist/authorization/model/agent.js +4 -2
- package/dist/authorization/model/agent.js.map +1 -1
- package/dist/authorization/model/agent_channel.d.ts.map +1 -1
- package/dist/authorization/model/agent_channel.js +5 -4
- package/dist/authorization/model/agent_channel.js.map +1 -1
- package/dist/authorization/model/agent_instance.d.ts.map +1 -1
- package/dist/authorization/model/agent_instance.js +3 -2
- package/dist/authorization/model/agent_instance.js.map +1 -1
- package/dist/authorization/model/mcp_server.d.ts.map +1 -1
- package/dist/authorization/model/mcp_server.js +3 -2
- package/dist/authorization/model/mcp_server.js.map +1 -1
- package/dist/authorization/model/organization.d.ts.map +1 -1
- package/dist/authorization/model/organization.js +3 -0
- package/dist/authorization/model/organization.js.map +1 -1
- package/dist/authorization/model/plugin.d.ts.map +1 -1
- package/dist/authorization/model/plugin.js +4 -2
- package/dist/authorization/model/plugin.js.map +1 -1
- package/dist/authorization/model/rewrite.d.ts +25 -7
- package/dist/authorization/model/rewrite.d.ts.map +1 -1
- package/dist/authorization/model/rewrite.js +40 -1
- package/dist/authorization/model/rewrite.js.map +1 -1
- package/dist/authorization/model/schedule.d.ts.map +1 -1
- package/dist/authorization/model/schedule.js +8 -3
- package/dist/authorization/model/schedule.js.map +1 -1
- package/dist/authorization/model/skill.d.ts.map +1 -1
- package/dist/authorization/model/skill.js +3 -2
- package/dist/authorization/model/skill.js.map +1 -1
- package/dist/authorization/model/workflow.d.ts.map +1 -1
- package/dist/authorization/model/workflow.js +3 -2
- package/dist/authorization/model/workflow.js.map +1 -1
- package/dist/authorization/model/workflow_execution.d.ts.map +1 -1
- package/dist/authorization/model/workflow_execution.js +4 -3
- package/dist/authorization/model/workflow_execution.js.map +1 -1
- package/dist/authorization/model/workflow_instance.d.ts.map +1 -1
- package/dist/authorization/model/workflow_instance.js +5 -1
- package/dist/authorization/model/workflow_instance.js.map +1 -1
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +13 -8
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/list-indexes.d.ts +3 -0
- package/dist/boot/list-indexes.d.ts.map +1 -0
- package/dist/boot/list-indexes.js +24 -0
- package/dist/boot/list-indexes.js.map +1 -0
- package/dist/domain/agentexecution/controller.d.ts.map +1 -1
- package/dist/domain/agentexecution/controller.js +6 -8
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentexecution/list-index.d.ts +2 -0
- package/dist/domain/agentexecution/list-index.d.ts.map +1 -0
- package/dist/domain/agentexecution/list-index.js +23 -0
- package/dist/domain/agentexecution/list-index.js.map +1 -0
- package/dist/domain/agentexecution/steps.d.ts +17 -33
- package/dist/domain/agentexecution/steps.d.ts.map +1 -1
- package/dist/domain/agentexecution/steps.js +94 -95
- package/dist/domain/agentexecution/steps.js.map +1 -1
- package/dist/domain/agentexecution/usage.d.ts.map +1 -1
- package/dist/domain/agentexecution/usage.js +37 -14
- package/dist/domain/agentexecution/usage.js.map +1 -1
- package/dist/domain/artifact/controller.d.ts.map +1 -1
- package/dist/domain/artifact/controller.js +27 -15
- package/dist/domain/artifact/controller.js.map +1 -1
- package/dist/domain/artifact/list-index.d.ts +2 -0
- package/dist/domain/artifact/list-index.d.ts.map +1 -0
- package/dist/domain/artifact/list-index.js +21 -0
- package/dist/domain/artifact/list-index.js.map +1 -0
- package/dist/domain/iampolicy/access-lists.d.ts +5 -3
- package/dist/domain/iampolicy/access-lists.d.ts.map +1 -1
- package/dist/domain/iampolicy/access-lists.js +72 -19
- package/dist/domain/iampolicy/access-lists.js.map +1 -1
- package/dist/domain/iampolicy/constants.d.ts +32 -6
- package/dist/domain/iampolicy/constants.d.ts.map +1 -1
- package/dist/domain/iampolicy/constants.js +41 -6
- package/dist/domain/iampolicy/constants.js.map +1 -1
- package/dist/domain/iampolicy/controller.d.ts +6 -0
- package/dist/domain/iampolicy/controller.d.ts.map +1 -1
- package/dist/domain/iampolicy/controller.js +16 -7
- package/dist/domain/iampolicy/controller.js.map +1 -1
- package/dist/domain/iampolicy/resource-store.d.ts.map +1 -1
- package/dist/domain/iampolicy/resource-store.js +2 -6
- package/dist/domain/iampolicy/resource-store.js.map +1 -1
- package/dist/domain/iampolicy/steps.d.ts.map +1 -1
- package/dist/domain/iampolicy/steps.js +49 -7
- package/dist/domain/iampolicy/steps.js.map +1 -1
- package/dist/domain/session/list-index.d.ts +4 -0
- package/dist/domain/session/list-index.d.ts.map +1 -0
- package/dist/domain/session/list-index.js +26 -0
- package/dist/domain/session/list-index.js.map +1 -0
- package/dist/domain/session/steps.d.ts +7 -8
- package/dist/domain/session/steps.d.ts.map +1 -1
- package/dist/domain/session/steps.js +76 -78
- package/dist/domain/session/steps.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -0
- package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
- package/dist/domain/workflowexecution/controller.js +53 -55
- package/dist/domain/workflowexecution/controller.js.map +1 -1
- package/dist/domain/workflowexecution/execution-filter.d.ts +4 -0
- package/dist/domain/workflowexecution/execution-filter.d.ts.map +1 -1
- package/dist/domain/workflowexecution/execution-filter.js +11 -5
- package/dist/domain/workflowexecution/execution-filter.js.map +1 -1
- package/dist/domain/workflowexecution/get-execution-summary.d.ts.map +1 -1
- package/dist/domain/workflowexecution/get-execution-summary.js +23 -17
- package/dist/domain/workflowexecution/get-execution-summary.js.map +1 -1
- package/dist/domain/workflowexecution/list-index.d.ts +2 -0
- package/dist/domain/workflowexecution/list-index.d.ts.map +1 -0
- package/dist/domain/workflowexecution/list-index.js +21 -0
- package/dist/domain/workflowexecution/list-index.js.map +1 -0
- package/dist/domain/workflowexecution/list-pending-approvals.d.ts.map +1 -1
- package/dist/domain/workflowexecution/list-pending-approvals.js +69 -32
- package/dist/domain/workflowexecution/list-pending-approvals.js.map +1 -1
- package/dist/domain/workflowexecution/queries.d.ts +30 -4
- package/dist/domain/workflowexecution/queries.d.ts.map +1 -1
- package/dist/domain/workflowexecution/queries.js +76 -22
- package/dist/domain/workflowexecution/queries.js.map +1 -1
- package/dist/extensions/drivers.d.ts +12 -0
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/gate-slots.d.ts +10 -1
- package/dist/extensions/gate-slots.d.ts.map +1 -1
- package/dist/extensions/gate-slots.js +1 -0
- package/dist/extensions/gate-slots.js.map +1 -1
- package/dist/extensions/list-read-scope.d.ts +9 -12
- package/dist/extensions/list-read-scope.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.js.map +1 -1
- package/dist/extensions/principal-display.d.ts +34 -0
- package/dist/extensions/principal-display.d.ts.map +1 -0
- package/dist/extensions/principal-display.js +2 -0
- package/dist/extensions/principal-display.js.map +1 -0
- package/dist/extensions/registry.d.ts +6 -0
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/registry.js +10 -0
- package/dist/extensions/registry.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline/apiresource-meta.d.ts +10 -0
- package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
- package/dist/pipeline/apiresource-meta.js +16 -0
- package/dist/pipeline/apiresource-meta.js.map +1 -1
- package/dist/pipeline/steps/list-page.d.ts +63 -0
- package/dist/pipeline/steps/list-page.d.ts.map +1 -0
- package/dist/pipeline/steps/list-page.js +187 -0
- package/dist/pipeline/steps/list-page.js.map +1 -0
- package/dist/query/activity/handler.d.ts +6 -7
- package/dist/query/activity/handler.d.ts.map +1 -1
- package/dist/query/activity/handler.js +42 -59
- package/dist/query/activity/handler.js.map +1 -1
- package/dist/store/interface.d.ts +29 -0
- package/dist/store/interface.d.ts.map +1 -1
- package/dist/store/interface.js.map +1 -1
- package/dist/store/list-index.d.ts +123 -0
- package/dist/store/list-index.d.ts.map +1 -0
- package/dist/store/list-index.js +277 -0
- package/dist/store/list-index.js.map +1 -0
- package/dist/store/logger.d.ts +3 -0
- package/dist/store/logger.d.ts.map +1 -1
- package/dist/store/logger.js +5 -1
- package/dist/store/logger.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +10 -6
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +64 -6
- package/dist/store/postgres/migrations.js.map +1 -1
- package/dist/store/postgres/store.d.ts +26 -5
- package/dist/store/postgres/store.d.ts.map +1 -1
- package/dist/store/postgres/store.js +377 -22
- package/dist/store/postgres/store.js.map +1 -1
- package/dist/store/sqlite/migrations.d.ts +11 -5
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +50 -4
- package/dist/store/sqlite/migrations.js.map +1 -1
- package/dist/store/sqlite/store.d.ts +18 -3
- package/dist/store/sqlite/store.d.ts.map +1 -1
- package/dist/store/sqlite/store.js +321 -15
- package/dist/store/sqlite/store.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/__tests__/drivers.ts +6 -1
- package/src/authorization/__tests__/evaluator.test.ts +127 -2
- package/src/authorization/evaluator.ts +12 -1
- package/src/authorization/model/__tests__/registry.test.ts +64 -2
- package/src/authorization/model/agent.ts +4 -1
- package/src/authorization/model/agent_channel.ts +11 -3
- package/src/authorization/model/agent_instance.ts +3 -1
- package/src/authorization/model/mcp_server.ts +3 -1
- package/src/authorization/model/organization.ts +3 -0
- package/src/authorization/model/plugin.ts +4 -1
- package/src/authorization/model/rewrite.ts +65 -8
- package/src/authorization/model/schedule.ts +11 -2
- package/src/authorization/model/skill.ts +3 -1
- package/src/authorization/model/workflow.ts +3 -1
- package/src/authorization/model/workflow_execution.ts +4 -2
- package/src/authorization/model/workflow_instance.ts +5 -0
- package/src/boot/__tests__/list-indexes.test.ts +65 -0
- package/src/boot/compose.ts +25 -13
- package/src/boot/list-indexes.ts +25 -0
- package/src/domain/agentexecution/__tests__/agentexecution.test.ts +85 -3
- package/src/domain/agentexecution/controller.ts +8 -10
- package/src/domain/agentexecution/list-index.ts +24 -0
- package/src/domain/agentexecution/steps.ts +118 -115
- package/src/domain/agentexecution/usage.ts +38 -17
- package/src/domain/artifact/controller.ts +28 -18
- package/src/domain/artifact/list-index.ts +22 -0
- package/src/domain/iampolicy/__tests__/access-lists.test.ts +120 -6
- package/src/domain/iampolicy/__tests__/constants.test.ts +26 -4
- package/src/domain/iampolicy/__tests__/controller.test.ts +55 -1
- package/src/domain/iampolicy/__tests__/grant-path.test.ts +3 -3
- package/src/domain/iampolicy/__tests__/steps.test.ts +123 -1
- package/src/domain/iampolicy/access-lists.ts +98 -23
- package/src/domain/iampolicy/constants.ts +50 -6
- package/src/domain/iampolicy/controller.ts +30 -7
- package/src/domain/iampolicy/resource-store.ts +3 -6
- package/src/domain/iampolicy/steps.ts +89 -7
- package/src/domain/session/list-index.ts +28 -0
- package/src/domain/session/steps.ts +108 -123
- package/src/domain/workflow/registry/data/task-kind-registry.json +1 -0
- package/src/domain/workflowexecution/__tests__/list-read-scope-summaries.test.ts +155 -99
- package/src/domain/workflowexecution/__tests__/workflowexecution.test.ts +193 -31
- package/src/domain/workflowexecution/controller.ts +54 -82
- package/src/domain/workflowexecution/execution-filter.ts +20 -7
- package/src/domain/workflowexecution/get-execution-summary.ts +31 -24
- package/src/domain/workflowexecution/list-index.ts +22 -0
- package/src/domain/workflowexecution/list-pending-approvals.ts +82 -25
- package/src/domain/workflowexecution/queries.ts +134 -23
- package/src/extensions/__tests__/iam-policy-points.test.ts +30 -0
- package/src/extensions/__tests__/registry.test.ts +3 -0
- package/src/extensions/drivers.ts +12 -0
- package/src/extensions/gate-slots.ts +10 -0
- package/src/extensions/list-read-scope.ts +9 -12
- package/src/extensions/principal-display.ts +37 -0
- package/src/extensions/registry.ts +19 -0
- package/src/index.ts +19 -1
- package/src/pipeline/apiresource-meta.ts +21 -0
- package/src/pipeline/steps/__tests__/list-page.test.ts +186 -0
- package/src/pipeline/steps/list-page.ts +284 -0
- package/src/query/activity/handler.ts +57 -78
- package/src/store/README.md +51 -32
- package/src/store/__tests__/list-index.measure.test.ts +293 -0
- package/src/store/__tests__/list-index.test.ts +328 -0
- package/src/store/__tests__/store-contract.ts +346 -3
- package/src/store/interface.ts +39 -0
- package/src/store/list-index.ts +465 -0
- package/src/store/logger.ts +8 -1
- package/src/store/postgres/__tests__/list-index-repair.test.ts +133 -0
- package/src/store/postgres/__tests__/migrations.test.ts +27 -19
- package/src/store/postgres/__tests__/store-contract.test.ts +50 -3
- package/src/store/postgres/migrations.ts +69 -7
- package/src/store/postgres/store.ts +485 -29
- package/src/store/sqlite/__tests__/migrations.test.ts +51 -7
- package/src/store/sqlite/__tests__/store-contract.test.ts +70 -16
- package/src/store/sqlite/__tests__/support.ts +12 -3
- package/src/store/sqlite/migrations.ts +57 -6
- package/src/store/sqlite/store.ts +462 -21
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* single-file lock never had. v5, the chain's first row-decoding step,
|
|
8
8
|
* moves every row of the seven kinds that held the retired public level to
|
|
9
9
|
* org and leaves every other row's bytes as they were; a row it cannot
|
|
10
|
-
* decode fails the step and leaves the database at v4.
|
|
10
|
+
* decode fails the step and leaves the database at v4. v6 adds the list
|
|
11
|
+
* index's table (its behaviour is the store contract's). A step's starting
|
|
12
|
+
* database is built by running the chain up to the step before it.
|
|
11
13
|
*
|
|
12
14
|
* Gated on TEST_DATABASE_URL (see support.ts): visible skips without a
|
|
13
15
|
* database, always exercised in CI via the ci.stigmer-server service
|
|
@@ -24,7 +26,12 @@ import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb"
|
|
|
24
26
|
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
25
27
|
|
|
26
28
|
import { PUBLIC_ROW_KINDS_AT_RETIREMENT } from "../../public-visibility-retired.js";
|
|
27
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
CURRENT_SCHEMA_VERSION,
|
|
31
|
+
SCHEMA_VERSION_1,
|
|
32
|
+
SCHEMA_VERSION_5,
|
|
33
|
+
runMigrations,
|
|
34
|
+
} from "../migrations.js";
|
|
28
35
|
import { PostgresStore } from "../store.js";
|
|
29
36
|
import {
|
|
30
37
|
createTestDatabase,
|
|
@@ -32,6 +39,18 @@ import {
|
|
|
32
39
|
type TestDatabase,
|
|
33
40
|
} from "./support.js";
|
|
34
41
|
|
|
42
|
+
/** Builds the database a step starts from: the chain run up to `version`. */
|
|
43
|
+
async function migrateTo(databaseUrl: string, version: number): Promise<void> {
|
|
44
|
+
const pool = new pg.Pool({ connectionString: databaseUrl, max: 1 });
|
|
45
|
+
const client = await pool.connect();
|
|
46
|
+
try {
|
|
47
|
+
await runMigrations(client, version);
|
|
48
|
+
} finally {
|
|
49
|
+
client.release();
|
|
50
|
+
await pool.end();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
35
54
|
describe.skipIf(testDatabaseAdminUrl() === undefined)(
|
|
36
55
|
"postgres migrations",
|
|
37
56
|
() => {
|
|
@@ -71,6 +90,7 @@ describe.skipIf(testDatabaseAdminUrl() === undefined)(
|
|
|
71
90
|
"oauth_grant",
|
|
72
91
|
"pending_oauth_state",
|
|
73
92
|
"resource_audit",
|
|
93
|
+
"resource_list_keys",
|
|
74
94
|
"resources",
|
|
75
95
|
"schedule_runs",
|
|
76
96
|
"schema_version",
|
|
@@ -102,21 +122,13 @@ describe.skipIf(testDatabaseAdminUrl() === undefined)(
|
|
|
102
122
|
});
|
|
103
123
|
|
|
104
124
|
it("a v1 database resumes the chain on reopen: the v2/v3 indexes arrive and v4 removes the Project rows", async () => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// Rewind to a v1 database: drop exactly what v2+v4 created and their
|
|
109
|
-
// version rows — the state any pre-v2 deployment is actually in —
|
|
110
|
-
// and seed one row of the Project kind an earlier release wrote
|
|
125
|
+
// A v1 database — the state any pre-v2 deployment is actually in —
|
|
126
|
+
// seeded with one row of the Project kind an earlier release wrote
|
|
111
127
|
// (the kind column holds the enum NAME) beside a row v4 must keep.
|
|
128
|
+
await migrateTo(db.databaseUrl, SCHEMA_VERSION_1);
|
|
112
129
|
const client = new pg.Client({ connectionString: db.databaseUrl });
|
|
113
130
|
await client.connect();
|
|
114
131
|
try {
|
|
115
|
-
await client.query(`DROP INDEX idx_wfee_created_at`);
|
|
116
|
-
await client.query(`DROP INDEX idx_oauth_grant_resource`);
|
|
117
|
-
await client.query(
|
|
118
|
-
`DELETE FROM schema_version WHERE version IN (2, 3, 4, 5)`,
|
|
119
|
-
);
|
|
120
132
|
await client.query(
|
|
121
133
|
`INSERT INTO resources (kind, id, data) VALUES ('project', 'prj_seeded', '\\x00'), ('organization', 'acme', '\\x00')`,
|
|
122
134
|
);
|
|
@@ -242,15 +254,11 @@ describe.skipIf(testDatabaseAdminUrl() === undefined)(
|
|
|
242
254
|
);
|
|
243
255
|
}
|
|
244
256
|
|
|
245
|
-
/**
|
|
257
|
+
/** A v4 database, the one v5 starts from, and a client on it for the seeding. */
|
|
246
258
|
async function v4Client(): Promise<pg.Client> {
|
|
247
|
-
|
|
248
|
-
await store.close();
|
|
259
|
+
await migrateTo(db.databaseUrl, SCHEMA_VERSION_5 - 1);
|
|
249
260
|
const client = new pg.Client({ connectionString: db.databaseUrl });
|
|
250
261
|
await client.connect();
|
|
251
|
-
await client.query(`DELETE FROM schema_version WHERE version = $1`, [
|
|
252
|
-
SCHEMA_VERSION_5,
|
|
253
|
-
]);
|
|
254
262
|
return client;
|
|
255
263
|
}
|
|
256
264
|
|
|
@@ -15,8 +15,13 @@ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/
|
|
|
15
15
|
|
|
16
16
|
import pg from "pg";
|
|
17
17
|
|
|
18
|
+
import type { Store } from "../../interface.js";
|
|
19
|
+
import { apiResourceKindName } from "../../proto-fields.js";
|
|
18
20
|
import type { StoreContractFixture } from "../../__tests__/store-contract.js";
|
|
19
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
CONTRACT_STORE_OPTIONS,
|
|
23
|
+
describeStoreContract,
|
|
24
|
+
} from "../../__tests__/store-contract.js";
|
|
20
25
|
import { PostgresStore } from "../store.js";
|
|
21
26
|
import {
|
|
22
27
|
createTestDatabase,
|
|
@@ -26,6 +31,7 @@ import {
|
|
|
26
31
|
|
|
27
32
|
const ALL_TABLES = [
|
|
28
33
|
"resources",
|
|
34
|
+
"resource_list_keys",
|
|
29
35
|
"resource_audit",
|
|
30
36
|
"search_index",
|
|
31
37
|
"bootstrap_state",
|
|
@@ -64,7 +70,12 @@ describe.skipIf(testDatabaseAdminUrl() === undefined)(
|
|
|
64
70
|
await hooks.query(
|
|
65
71
|
`TRUNCATE ${ALL_TABLES.join(", ")} RESTART IDENTITY CASCADE`,
|
|
66
72
|
);
|
|
67
|
-
const store = await PostgresStore.open(
|
|
73
|
+
const store = await PostgresStore.open(
|
|
74
|
+
db.databaseUrl,
|
|
75
|
+
undefined,
|
|
76
|
+
CONTRACT_STORE_OPTIONS,
|
|
77
|
+
);
|
|
78
|
+
const others: Store[] = [];
|
|
68
79
|
return {
|
|
69
80
|
store,
|
|
70
81
|
async forceDedupeExpiry(id, expiresAtIso) {
|
|
@@ -79,7 +90,43 @@ describe.skipIf(testDatabaseAdminUrl() === undefined)(
|
|
|
79
90
|
);
|
|
80
91
|
return Number((result.rows[0] as { count: string }).count);
|
|
81
92
|
},
|
|
82
|
-
|
|
93
|
+
async writeAsOlderBinary(kind, id, data) {
|
|
94
|
+
// The statement this driver ran before the list index existed.
|
|
95
|
+
await hooks.query(
|
|
96
|
+
`INSERT INTO resources (kind, id, data, updated_at) VALUES ($1, $2, $3, now())
|
|
97
|
+
ON CONFLICT (kind, id) DO UPDATE SET data = excluded.data, updated_at = now()`,
|
|
98
|
+
[apiResourceKindName(kind), id, Buffer.from(data)],
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
async countUnproven(kind, revision) {
|
|
102
|
+
const revisionArm =
|
|
103
|
+
revision === undefined
|
|
104
|
+
? ""
|
|
105
|
+
: ` OR list_index_revision IS NULL OR list_index_revision <> $2`;
|
|
106
|
+
const result = await hooks.query(
|
|
107
|
+
`SELECT COUNT(*) AS count FROM resources
|
|
108
|
+
WHERE kind = $1 AND (list_indexed_at IS DISTINCT FROM updated_at${revisionArm})`,
|
|
109
|
+
revision === undefined
|
|
110
|
+
? [apiResourceKindName(kind)]
|
|
111
|
+
: [apiResourceKindName(kind), revision],
|
|
112
|
+
);
|
|
113
|
+
return Number((result.rows[0] as { count: string }).count);
|
|
114
|
+
},
|
|
115
|
+
async openAnother(options) {
|
|
116
|
+
const other = await PostgresStore.open(
|
|
117
|
+
db.databaseUrl,
|
|
118
|
+
undefined,
|
|
119
|
+
options,
|
|
120
|
+
);
|
|
121
|
+
others.push(other);
|
|
122
|
+
return other;
|
|
123
|
+
},
|
|
124
|
+
async cleanup() {
|
|
125
|
+
for (const other of others) {
|
|
126
|
+
await other.close();
|
|
127
|
+
}
|
|
128
|
+
await store.close();
|
|
129
|
+
},
|
|
83
130
|
};
|
|
84
131
|
});
|
|
85
132
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Versioned schema migrations for the Postgres driver — an INDEPENDENT
|
|
3
3
|
* chain starting at its own v1 (DD-010 §3). It deliberately does NOT
|
|
4
|
-
* mirror sqlite's
|
|
4
|
+
* mirror sqlite's chain: that chain's value is Go-DDL fidelity for adopted
|
|
5
5
|
* laptop databases, a concern Postgres cannot have (no Postgres database
|
|
6
6
|
* predates this driver). Same runner discipline as sqlite/migrations.ts —
|
|
7
7
|
* deliberate, versioned, each step in its own transaction, `schema_version`
|
|
@@ -50,9 +50,11 @@ export const SCHEMA_VERSION_3 = 3;
|
|
|
50
50
|
export const SCHEMA_VERSION_4 = 4;
|
|
51
51
|
/** v5: every row holding the retired public visibility level moved to org. */
|
|
52
52
|
export const SCHEMA_VERSION_5 = 5;
|
|
53
|
+
/** v6: the list index's columns, key table and indexes (DDL only). */
|
|
54
|
+
export const SCHEMA_VERSION_6 = 6;
|
|
53
55
|
|
|
54
56
|
/** Target version for new databases. */
|
|
55
|
-
export const CURRENT_SCHEMA_VERSION =
|
|
57
|
+
export const CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_6;
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
60
|
* Advisory lock key for the migration chain. Arbitrary but stable 64-bit
|
|
@@ -63,11 +65,16 @@ export const CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_5;
|
|
|
63
65
|
export const MIGRATION_LOCK_KEY = 0x5354474d5231n;
|
|
64
66
|
|
|
65
67
|
/**
|
|
66
|
-
* Applies
|
|
67
|
-
*
|
|
68
|
-
*
|
|
68
|
+
* Applies every pending migration up to `targetVersion` in order — all of
|
|
69
|
+
* them unless a test builds the database a given step starts from —
|
|
70
|
+
* serialized across instances by the advisory lock. Runs on a dedicated
|
|
71
|
+
* client (locks are session-scoped; a pool query could release on a
|
|
72
|
+
* different session).
|
|
69
73
|
*/
|
|
70
|
-
export async function runMigrations(
|
|
74
|
+
export async function runMigrations(
|
|
75
|
+
client: PoolClient,
|
|
76
|
+
targetVersion: number = CURRENT_SCHEMA_VERSION,
|
|
77
|
+
): Promise<void> {
|
|
71
78
|
await client.query("SELECT pg_advisory_lock($1)", [MIGRATION_LOCK_KEY]);
|
|
72
79
|
try {
|
|
73
80
|
await client.query(`
|
|
@@ -87,10 +94,11 @@ export async function runMigrations(client: PoolClient): Promise<void> {
|
|
|
87
94
|
[SCHEMA_VERSION_3, migrateToV3],
|
|
88
95
|
[SCHEMA_VERSION_4, migrateToV4],
|
|
89
96
|
[SCHEMA_VERSION_5, migrateToV5],
|
|
97
|
+
[SCHEMA_VERSION_6, migrateToV6],
|
|
90
98
|
];
|
|
91
99
|
|
|
92
100
|
for (const [version, migrate] of chain) {
|
|
93
|
-
if (currentVersion < version) {
|
|
101
|
+
if (currentVersion < version && version <= targetVersion) {
|
|
94
102
|
await applyInTransaction(client, version, migrate);
|
|
95
103
|
}
|
|
96
104
|
}
|
|
@@ -362,3 +370,57 @@ async function migrateToV5(client: PoolClient): Promise<void> {
|
|
|
362
370
|
}
|
|
363
371
|
}
|
|
364
372
|
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* v6: the list index (../list-index.ts) — schema only. Every existing row
|
|
376
|
+
* arrives with its stamp NULL, which makes it unproven, so the store's
|
|
377
|
+
* reconciliation at open derives its facts with the code that runs and
|
|
378
|
+
* reads stay exact until it has; a migration that decoded rows here would
|
|
379
|
+
* freeze today's declarations into the chain (the v5 step freezes its
|
|
380
|
+
* kind table for the same reason, public-visibility-retired.ts).
|
|
381
|
+
*
|
|
382
|
+
* - `list_org` and `list_created_at` are the order's inputs, byte-collated
|
|
383
|
+
* (`COLLATE "C"`) so the database sorts them the way list-index.ts
|
|
384
|
+
* compares them when it merges unproven rows in; `id` is compared under
|
|
385
|
+
* the same collation in the index expressions and the queries.
|
|
386
|
+
* - `list_index_revision` is the declaration revision the facts were
|
|
387
|
+
* derived under; `list_indexed_at` is the `updated_at` they were derived
|
|
388
|
+
* from. A writer that does not know these columns leaves them behind as
|
|
389
|
+
* it bumps `updated_at`, which is exactly what marks its row unproven.
|
|
390
|
+
* - `resource_list_keys` holds one row per (resource, key) with the
|
|
391
|
+
* creation instant copied in, so a parent's rows are one range of one
|
|
392
|
+
* index. It carries no foreign key: every indexed read joins
|
|
393
|
+
* `resources`, so a key row whose resource is gone matches nothing.
|
|
394
|
+
* - The partial index holds only unproven rows (none in steady state), so
|
|
395
|
+
* finding them is never a scan of the kind.
|
|
396
|
+
*/
|
|
397
|
+
async function migrateToV6(client: PoolClient): Promise<void> {
|
|
398
|
+
await client.query(`
|
|
399
|
+
ALTER TABLE resources
|
|
400
|
+
ADD COLUMN list_org TEXT COLLATE "C",
|
|
401
|
+
ADD COLUMN list_created_at TEXT COLLATE "C",
|
|
402
|
+
ADD COLUMN list_index_revision INTEGER,
|
|
403
|
+
ADD COLUMN list_indexed_at timestamptz;
|
|
404
|
+
|
|
405
|
+
CREATE INDEX idx_resources_list_org
|
|
406
|
+
ON resources (kind, list_org, list_created_at, (id COLLATE "C"));
|
|
407
|
+
CREATE INDEX idx_resources_list_created
|
|
408
|
+
ON resources (kind, list_created_at, (id COLLATE "C"));
|
|
409
|
+
CREATE INDEX idx_resources_list_revision
|
|
410
|
+
ON resources (kind, list_index_revision);
|
|
411
|
+
CREATE INDEX idx_resources_list_unproven
|
|
412
|
+
ON resources (kind, id) WHERE list_indexed_at IS DISTINCT FROM updated_at;
|
|
413
|
+
|
|
414
|
+
CREATE TABLE resource_list_keys (
|
|
415
|
+
kind TEXT NOT NULL,
|
|
416
|
+
id TEXT NOT NULL,
|
|
417
|
+
key TEXT NOT NULL,
|
|
418
|
+
value TEXT NOT NULL,
|
|
419
|
+
created_at TEXT COLLATE "C" NOT NULL,
|
|
420
|
+
PRIMARY KEY (kind, id, key)
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
CREATE INDEX idx_resource_list_keys_lookup
|
|
424
|
+
ON resource_list_keys (kind, key, value, created_at, (id COLLATE "C"));
|
|
425
|
+
`);
|
|
426
|
+
}
|