@axiom-lattice/pg-stores 5.1.2 → 5.2.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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +69 -0
- package/dist/index.d.mts +87 -3
- package/dist/index.d.ts +87 -3
- package/dist/index.js +534 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +477 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/PostgreSQLMcpServerConfigStore.integration.test.ts +122 -0
- package/src/__tests__/PostgreSQLMcpServerConfigStore.test.ts +81 -0
- package/src/__tests__/PostgreSQLPlatformAuditStore.test.ts +446 -0
- package/src/__tests__/PostgreSQLUserTenantLinkStore.test.ts +62 -0
- package/src/createPgStoreConfig.ts +6 -1
- package/src/index.ts +2 -0
- package/src/migrations/mcp_server_config_migrations.ts +47 -0
- package/src/migrations/platform_audit_migration.ts +45 -0
- package/src/stores/PostgreSQLMcpServerConfigStore.ts +343 -15
- package/src/stores/PostgreSQLPlatformAuditStore.ts +209 -0
- package/src/stores/PostgreSQLUserTenantLinkStore.ts +2 -0
package/dist/index.js
CHANGED
|
@@ -63,6 +63,7 @@ __export(index_exports, {
|
|
|
63
63
|
PostgreSQLOidcIdentityClaimStore: () => PostgreSQLOidcIdentityClaimStore,
|
|
64
64
|
PostgreSQLOidcProviderConfigStore: () => PostgreSQLOidcProviderConfigStore,
|
|
65
65
|
PostgreSQLOpenAuditStore: () => PostgreSQLOpenAuditStore,
|
|
66
|
+
PostgreSQLPlatformAuditStore: () => PostgreSQLPlatformAuditStore,
|
|
66
67
|
PostgreSQLPlatformInvitationStore: () => PostgreSQLPlatformInvitationStore,
|
|
67
68
|
PostgreSQLPlatformMemberStore: () => PostgreSQLPlatformMemberStore,
|
|
68
69
|
PostgreSQLPlatformSettingsStore: () => PostgreSQLPlatformSettingsStore,
|
|
@@ -134,7 +135,9 @@ __export(index_exports, {
|
|
|
134
135
|
createOidcIdentityClaimsTable: () => createOidcIdentityClaimsTable,
|
|
135
136
|
createOidcProviderConfigsTable: () => createOidcProviderConfigsTable,
|
|
136
137
|
createPGVectorStoreProvider: () => createPGVectorStoreProvider,
|
|
138
|
+
createPersonalMcpServerConfigsTable: () => createPersonalMcpServerConfigsTable,
|
|
137
139
|
createPgStoreConfig: () => createPgStoreConfig,
|
|
140
|
+
createPlatformAuditTable: () => createPlatformAuditTable,
|
|
138
141
|
createPlatformInvitationsTable: () => createPlatformInvitationsTable,
|
|
139
142
|
createPlatformMembersTable: () => createPlatformMembersTable,
|
|
140
143
|
createPlatformSettingsTable: () => createPlatformSettingsTable,
|
|
@@ -1932,6 +1935,43 @@ var createMcpServerConfigsTable = {
|
|
|
1932
1935
|
await client.query("DROP TABLE IF EXISTS lattice_mcp_server_configs");
|
|
1933
1936
|
}
|
|
1934
1937
|
};
|
|
1938
|
+
var createPersonalMcpServerConfigsTable = {
|
|
1939
|
+
version: 220,
|
|
1940
|
+
name: "create_personal_mcp_server_configs_table",
|
|
1941
|
+
up: async (client) => {
|
|
1942
|
+
await client.query(`
|
|
1943
|
+
CREATE TABLE IF NOT EXISTS lattice_personal_mcp_server_configs (
|
|
1944
|
+
id VARCHAR(255) NOT NULL,
|
|
1945
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
1946
|
+
owner_assistant_id VARCHAR(255) NOT NULL,
|
|
1947
|
+
key VARCHAR(255) NOT NULL,
|
|
1948
|
+
name VARCHAR(255),
|
|
1949
|
+
description TEXT,
|
|
1950
|
+
config JSONB NOT NULL,
|
|
1951
|
+
selected_tools JSONB NOT NULL DEFAULT '[]',
|
|
1952
|
+
is_env_encrypted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
1953
|
+
status VARCHAR(50) NOT NULL DEFAULT 'disconnected',
|
|
1954
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1955
|
+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1956
|
+
|
|
1957
|
+
PRIMARY KEY (tenant_id, owner_assistant_id, id)
|
|
1958
|
+
)
|
|
1959
|
+
`);
|
|
1960
|
+
await client.query(`
|
|
1961
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_lattice_personal_mcp_assistant_key
|
|
1962
|
+
ON lattice_personal_mcp_server_configs(tenant_id, owner_assistant_id, key)
|
|
1963
|
+
`);
|
|
1964
|
+
await client.query(`
|
|
1965
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_personal_mcp_assistant
|
|
1966
|
+
ON lattice_personal_mcp_server_configs(tenant_id, owner_assistant_id)
|
|
1967
|
+
`);
|
|
1968
|
+
},
|
|
1969
|
+
down: async (client) => {
|
|
1970
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_personal_mcp_assistant_key");
|
|
1971
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_personal_mcp_assistant");
|
|
1972
|
+
await client.query("DROP TABLE IF EXISTS lattice_personal_mcp_server_configs");
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1935
1975
|
|
|
1936
1976
|
// src/stores/PostgreSQLMcpServerConfigStore.ts
|
|
1937
1977
|
var import_core4 = require("@axiom-lattice/core");
|
|
@@ -1955,6 +1995,7 @@ var PostgreSQLMcpServerConfigStore = class {
|
|
|
1955
1995
|
}
|
|
1956
1996
|
this.migrationManager = new MigrationManager(this.pool);
|
|
1957
1997
|
this.migrationManager.register(createMcpServerConfigsTable);
|
|
1998
|
+
this.migrationManager.register(createPersonalMcpServerConfigsTable);
|
|
1958
1999
|
if (options.autoMigrate !== false) {
|
|
1959
2000
|
this.initialize().catch((error) => {
|
|
1960
2001
|
console.error("Failed to initialize PostgreSQLMcpServerConfigStore:", error);
|
|
@@ -2182,6 +2223,231 @@ var PostgreSQLMcpServerConfigStore = class {
|
|
|
2182
2223
|
);
|
|
2183
2224
|
return result.rows.length > 0;
|
|
2184
2225
|
}
|
|
2226
|
+
/**
|
|
2227
|
+
* Get all personal MCP server configurations owned by one assistant.
|
|
2228
|
+
*/
|
|
2229
|
+
async getAllConfigsForAssistant(tenantId, ownerAssistantId) {
|
|
2230
|
+
await this.ensureInitialized();
|
|
2231
|
+
const result = await this.pool.query(
|
|
2232
|
+
`
|
|
2233
|
+
SELECT id, tenant_id, owner_assistant_id, key, name, description, config, selected_tools, is_env_encrypted, status, created_at, updated_at
|
|
2234
|
+
FROM lattice_personal_mcp_server_configs
|
|
2235
|
+
WHERE tenant_id = $1 AND owner_assistant_id = $2
|
|
2236
|
+
ORDER BY created_at DESC
|
|
2237
|
+
`,
|
|
2238
|
+
[tenantId, ownerAssistantId]
|
|
2239
|
+
);
|
|
2240
|
+
return result.rows.map((row) => this.mapPersonalRowToEntry(row));
|
|
2241
|
+
}
|
|
2242
|
+
/**
|
|
2243
|
+
* Get every personal MCP server configuration across tenants.
|
|
2244
|
+
*
|
|
2245
|
+
* Operations/tests only; startup restoration must not call this.
|
|
2246
|
+
*/
|
|
2247
|
+
async getAllPersonalConfigsWithoutTenant() {
|
|
2248
|
+
await this.ensureInitialized();
|
|
2249
|
+
const result = await this.pool.query(
|
|
2250
|
+
`
|
|
2251
|
+
SELECT id, tenant_id, owner_assistant_id, key, name, description, config, selected_tools, is_env_encrypted, status, created_at, updated_at
|
|
2252
|
+
FROM lattice_personal_mcp_server_configs
|
|
2253
|
+
ORDER BY created_at DESC
|
|
2254
|
+
`
|
|
2255
|
+
);
|
|
2256
|
+
return result.rows.map((row) => this.mapPersonalRowToEntry(row));
|
|
2257
|
+
}
|
|
2258
|
+
/**
|
|
2259
|
+
* Get one personal MCP server configuration by id.
|
|
2260
|
+
*/
|
|
2261
|
+
async getConfigByIdForAssistant(tenantId, ownerAssistantId, id) {
|
|
2262
|
+
await this.ensureInitialized();
|
|
2263
|
+
const result = await this.pool.query(
|
|
2264
|
+
`
|
|
2265
|
+
SELECT id, tenant_id, owner_assistant_id, key, name, description, config, selected_tools, is_env_encrypted, status, created_at, updated_at
|
|
2266
|
+
FROM lattice_personal_mcp_server_configs
|
|
2267
|
+
WHERE tenant_id = $1 AND owner_assistant_id = $2 AND id = $3
|
|
2268
|
+
`,
|
|
2269
|
+
[tenantId, ownerAssistantId, id]
|
|
2270
|
+
);
|
|
2271
|
+
if (result.rows.length === 0) {
|
|
2272
|
+
return null;
|
|
2273
|
+
}
|
|
2274
|
+
return this.mapPersonalRowToEntry(result.rows[0]);
|
|
2275
|
+
}
|
|
2276
|
+
/**
|
|
2277
|
+
* Get one personal MCP server configuration by business key.
|
|
2278
|
+
*/
|
|
2279
|
+
async getConfigByKeyForAssistant(tenantId, ownerAssistantId, key) {
|
|
2280
|
+
await this.ensureInitialized();
|
|
2281
|
+
const result = await this.pool.query(
|
|
2282
|
+
`
|
|
2283
|
+
SELECT id, tenant_id, owner_assistant_id, key, name, description, config, selected_tools, is_env_encrypted, status, created_at, updated_at
|
|
2284
|
+
FROM lattice_personal_mcp_server_configs
|
|
2285
|
+
WHERE tenant_id = $1 AND owner_assistant_id = $2 AND key = $3
|
|
2286
|
+
`,
|
|
2287
|
+
[tenantId, ownerAssistantId, key]
|
|
2288
|
+
);
|
|
2289
|
+
if (result.rows.length === 0) {
|
|
2290
|
+
return null;
|
|
2291
|
+
}
|
|
2292
|
+
return this.mapPersonalRowToEntry(result.rows[0]);
|
|
2293
|
+
}
|
|
2294
|
+
/**
|
|
2295
|
+
* Create a personal MCP server configuration.
|
|
2296
|
+
*/
|
|
2297
|
+
async createConfigForAssistant(tenantId, ownerAssistantId, id, data) {
|
|
2298
|
+
await this.ensureInitialized();
|
|
2299
|
+
const now = /* @__PURE__ */ new Date();
|
|
2300
|
+
const nowString = now.toISOString();
|
|
2301
|
+
const { config: configWithEncryptedEnv, isEnvEncrypted } = this.encryptEnvInConfig(data.config);
|
|
2302
|
+
await this.pool.query(
|
|
2303
|
+
`
|
|
2304
|
+
INSERT INTO lattice_personal_mcp_server_configs (id, tenant_id, owner_assistant_id, key, name, description, config, selected_tools, is_env_encrypted, status, created_at, updated_at)
|
|
2305
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11::timestamp, $12::timestamp)
|
|
2306
|
+
ON CONFLICT (tenant_id, owner_assistant_id, id) DO UPDATE SET
|
|
2307
|
+
key = EXCLUDED.key,
|
|
2308
|
+
name = EXCLUDED.name,
|
|
2309
|
+
description = EXCLUDED.description,
|
|
2310
|
+
config = EXCLUDED.config,
|
|
2311
|
+
selected_tools = EXCLUDED.selected_tools,
|
|
2312
|
+
is_env_encrypted = EXCLUDED.is_env_encrypted,
|
|
2313
|
+
status = EXCLUDED.status,
|
|
2314
|
+
updated_at = EXCLUDED.updated_at
|
|
2315
|
+
`,
|
|
2316
|
+
[
|
|
2317
|
+
id,
|
|
2318
|
+
tenantId,
|
|
2319
|
+
ownerAssistantId,
|
|
2320
|
+
data.key,
|
|
2321
|
+
data.name || null,
|
|
2322
|
+
data.description || null,
|
|
2323
|
+
JSON.stringify(configWithEncryptedEnv),
|
|
2324
|
+
JSON.stringify(data.selectedTools || []),
|
|
2325
|
+
isEnvEncrypted,
|
|
2326
|
+
"disconnected",
|
|
2327
|
+
nowString,
|
|
2328
|
+
nowString
|
|
2329
|
+
]
|
|
2330
|
+
);
|
|
2331
|
+
return {
|
|
2332
|
+
id,
|
|
2333
|
+
tenantId,
|
|
2334
|
+
ownerAssistantId,
|
|
2335
|
+
key: data.key,
|
|
2336
|
+
config: data.config,
|
|
2337
|
+
selectedTools: data.selectedTools || [],
|
|
2338
|
+
isEnvEncrypted,
|
|
2339
|
+
status: "disconnected",
|
|
2340
|
+
name: data.name,
|
|
2341
|
+
description: data.description,
|
|
2342
|
+
createdAt: now,
|
|
2343
|
+
updatedAt: now
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
/**
|
|
2347
|
+
* Update a personal MCP server configuration.
|
|
2348
|
+
*/
|
|
2349
|
+
async updateConfigForAssistant(tenantId, ownerAssistantId, id, updates) {
|
|
2350
|
+
await this.ensureInitialized();
|
|
2351
|
+
const existing = await this.getConfigByIdForAssistant(
|
|
2352
|
+
tenantId,
|
|
2353
|
+
ownerAssistantId,
|
|
2354
|
+
id
|
|
2355
|
+
);
|
|
2356
|
+
if (!existing) {
|
|
2357
|
+
return null;
|
|
2358
|
+
}
|
|
2359
|
+
const updateData = {};
|
|
2360
|
+
if (updates.key !== void 0) {
|
|
2361
|
+
updateData.key = updates.key;
|
|
2362
|
+
}
|
|
2363
|
+
if (updates.name !== void 0) {
|
|
2364
|
+
updateData.name = updates.name || null;
|
|
2365
|
+
}
|
|
2366
|
+
if (updates.description !== void 0) {
|
|
2367
|
+
updateData.description = updates.description || null;
|
|
2368
|
+
}
|
|
2369
|
+
if (updates.config !== void 0) {
|
|
2370
|
+
const { config: configWithEncryptedEnv, isEnvEncrypted } = this.encryptEnvInConfig(updates.config);
|
|
2371
|
+
updateData.config = JSON.stringify(configWithEncryptedEnv);
|
|
2372
|
+
updateData.is_env_encrypted = isEnvEncrypted;
|
|
2373
|
+
}
|
|
2374
|
+
if (updates.selectedTools !== void 0) {
|
|
2375
|
+
updateData.selected_tools = JSON.stringify(updates.selectedTools);
|
|
2376
|
+
}
|
|
2377
|
+
if (updates.status !== void 0) {
|
|
2378
|
+
updateData.status = updates.status;
|
|
2379
|
+
}
|
|
2380
|
+
if (Object.keys(updateData).length === 0) {
|
|
2381
|
+
return existing;
|
|
2382
|
+
}
|
|
2383
|
+
updateData.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2384
|
+
const fields = Object.keys(updateData);
|
|
2385
|
+
const values = Object.values(updateData);
|
|
2386
|
+
values.push(tenantId);
|
|
2387
|
+
values.push(ownerAssistantId);
|
|
2388
|
+
values.push(id);
|
|
2389
|
+
const setClauses = fields.map((field, index) => {
|
|
2390
|
+
if (field === "updated_at") {
|
|
2391
|
+
return `${field} = $${index + 1}::timestamp`;
|
|
2392
|
+
}
|
|
2393
|
+
return `${field} = $${index + 1}`;
|
|
2394
|
+
});
|
|
2395
|
+
const whereTenantIndex = fields.length + 1;
|
|
2396
|
+
const whereOwnerIndex = fields.length + 2;
|
|
2397
|
+
const whereIdIndex = fields.length + 3;
|
|
2398
|
+
const sql = `
|
|
2399
|
+
UPDATE lattice_personal_mcp_server_configs
|
|
2400
|
+
SET ${setClauses.join(", ")}
|
|
2401
|
+
WHERE tenant_id = $${whereTenantIndex}
|
|
2402
|
+
AND owner_assistant_id = $${whereOwnerIndex}
|
|
2403
|
+
AND id = $${whereIdIndex}
|
|
2404
|
+
`;
|
|
2405
|
+
await this.pool.query(sql, values);
|
|
2406
|
+
return this.getConfigByIdForAssistant(tenantId, ownerAssistantId, id);
|
|
2407
|
+
}
|
|
2408
|
+
/**
|
|
2409
|
+
* Delete one personal MCP server configuration by id.
|
|
2410
|
+
*/
|
|
2411
|
+
async deleteConfigForAssistant(tenantId, ownerAssistantId, id) {
|
|
2412
|
+
await this.ensureInitialized();
|
|
2413
|
+
const result = await this.pool.query(
|
|
2414
|
+
`
|
|
2415
|
+
DELETE FROM lattice_personal_mcp_server_configs
|
|
2416
|
+
WHERE tenant_id = $1 AND owner_assistant_id = $2 AND id = $3
|
|
2417
|
+
`,
|
|
2418
|
+
[tenantId, ownerAssistantId, id]
|
|
2419
|
+
);
|
|
2420
|
+
return result.rowCount !== null && result.rowCount > 0;
|
|
2421
|
+
}
|
|
2422
|
+
/**
|
|
2423
|
+
* Delete every personal MCP server configuration owned by one assistant.
|
|
2424
|
+
*/
|
|
2425
|
+
async deleteConfigsForAssistant(tenantId, ownerAssistantId) {
|
|
2426
|
+
await this.ensureInitialized();
|
|
2427
|
+
const result = await this.pool.query(
|
|
2428
|
+
`
|
|
2429
|
+
DELETE FROM lattice_personal_mcp_server_configs
|
|
2430
|
+
WHERE tenant_id = $1 AND owner_assistant_id = $2
|
|
2431
|
+
`,
|
|
2432
|
+
[tenantId, ownerAssistantId]
|
|
2433
|
+
);
|
|
2434
|
+
return result.rowCount ?? 0;
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Check whether a personal MCP server configuration exists.
|
|
2438
|
+
*/
|
|
2439
|
+
async hasConfigForAssistant(tenantId, ownerAssistantId, id) {
|
|
2440
|
+
await this.ensureInitialized();
|
|
2441
|
+
const result = await this.pool.query(
|
|
2442
|
+
`
|
|
2443
|
+
SELECT 1 FROM lattice_personal_mcp_server_configs
|
|
2444
|
+
WHERE tenant_id = $1 AND owner_assistant_id = $2 AND id = $3
|
|
2445
|
+
LIMIT 1
|
|
2446
|
+
`,
|
|
2447
|
+
[tenantId, ownerAssistantId, id]
|
|
2448
|
+
);
|
|
2449
|
+
return result.rows.length > 0;
|
|
2450
|
+
}
|
|
2185
2451
|
/**
|
|
2186
2452
|
* Dispose resources and close the connection pool
|
|
2187
2453
|
*/
|
|
@@ -2232,6 +2498,15 @@ var PostgreSQLMcpServerConfigStore = class {
|
|
|
2232
2498
|
updatedAt: row.updated_at
|
|
2233
2499
|
};
|
|
2234
2500
|
}
|
|
2501
|
+
/**
|
|
2502
|
+
* Map a personal table row, tagging the owning assistant.
|
|
2503
|
+
*/
|
|
2504
|
+
mapPersonalRowToEntry(row) {
|
|
2505
|
+
return {
|
|
2506
|
+
...this.mapRowToEntry(row),
|
|
2507
|
+
ownerAssistantId: row.owner_assistant_id
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2235
2510
|
/**
|
|
2236
2511
|
* Encrypt env values in config before storing
|
|
2237
2512
|
*/
|
|
@@ -3423,6 +3698,7 @@ var PostgreSQLTenantStore = class {
|
|
|
3423
3698
|
|
|
3424
3699
|
// src/stores/PostgreSQLUserTenantLinkStore.ts
|
|
3425
3700
|
var import_pg10 = require("pg");
|
|
3701
|
+
var import_protocols2 = require("@axiom-lattice/protocols");
|
|
3426
3702
|
|
|
3427
3703
|
// src/migrations/user_tenant_link_migrations.ts
|
|
3428
3704
|
var createUserTenantLinkTable = {
|
|
@@ -3581,6 +3857,7 @@ var PostgreSQLUserTenantLinkStore = class {
|
|
|
3581
3857
|
return this.mapRowToLink(result.rows[0]);
|
|
3582
3858
|
}
|
|
3583
3859
|
async createLink(data) {
|
|
3860
|
+
(0, import_protocols2.assertNotPlatformTenant)(data.tenantId);
|
|
3584
3861
|
await this.ensureInitialized();
|
|
3585
3862
|
const now = /* @__PURE__ */ new Date();
|
|
3586
3863
|
const role = data.role || "member";
|
|
@@ -3656,7 +3933,7 @@ var PostgreSQLUserTenantLinkStore = class {
|
|
|
3656
3933
|
};
|
|
3657
3934
|
|
|
3658
3935
|
// src/stores/PostgreSQLUserExternalIdentityStore.ts
|
|
3659
|
-
var
|
|
3936
|
+
var import_protocols3 = require("@axiom-lattice/protocols");
|
|
3660
3937
|
var InvalidUserExternalIdentityRowError = class extends Error {
|
|
3661
3938
|
constructor() {
|
|
3662
3939
|
super("Invalid user external identity row");
|
|
@@ -3719,14 +3996,14 @@ var PostgreSQLUserExternalIdentityStore = class {
|
|
|
3719
3996
|
identity.subject
|
|
3720
3997
|
);
|
|
3721
3998
|
if (!existing) {
|
|
3722
|
-
throw new
|
|
3999
|
+
throw new import_protocols3.ExternalIdentityPersistError(
|
|
3723
4000
|
identity.providerId,
|
|
3724
4001
|
identity.issuer,
|
|
3725
4002
|
identity.subject
|
|
3726
4003
|
);
|
|
3727
4004
|
}
|
|
3728
4005
|
if (existing.userId !== identity.userId) {
|
|
3729
|
-
throw new
|
|
4006
|
+
throw new import_protocols3.ExternalIdentityConflictError(
|
|
3730
4007
|
identity.providerId,
|
|
3731
4008
|
identity.issuer,
|
|
3732
4009
|
identity.subject
|
|
@@ -3751,7 +4028,7 @@ var PostgreSQLUserExternalIdentityStore = class {
|
|
|
3751
4028
|
|
|
3752
4029
|
// src/stores/PostgreSQLOidcProviderConfigStore.ts
|
|
3753
4030
|
var import_core5 = require("@axiom-lattice/core");
|
|
3754
|
-
var
|
|
4031
|
+
var import_protocols4 = require("@axiom-lattice/protocols");
|
|
3755
4032
|
var TABLE2 = "lattice_oidc_provider_configs";
|
|
3756
4033
|
function parseAllowedPrivateHosts(value) {
|
|
3757
4034
|
if (!Array.isArray(value)) return void 0;
|
|
@@ -3836,7 +4113,7 @@ var PostgreSQLOidcProviderConfigStore = class {
|
|
|
3836
4113
|
);
|
|
3837
4114
|
} catch (error) {
|
|
3838
4115
|
if (isUniqueViolation(error)) {
|
|
3839
|
-
throw new
|
|
4116
|
+
throw new import_protocols4.OidcProviderConfigConflictError(id);
|
|
3840
4117
|
}
|
|
3841
4118
|
throw error;
|
|
3842
4119
|
}
|
|
@@ -3967,7 +4244,7 @@ var PostgreSQLPlatformMemberStore = class {
|
|
|
3967
4244
|
};
|
|
3968
4245
|
|
|
3969
4246
|
// src/stores/PostgreSQLPlatformInvitationStore.ts
|
|
3970
|
-
var
|
|
4247
|
+
var import_protocols5 = require("@axiom-lattice/protocols");
|
|
3971
4248
|
var TABLE4 = "lattice_platform_invitations";
|
|
3972
4249
|
var ROLES2 = ["owner", "admin", "auditor"];
|
|
3973
4250
|
function isPlatformRole2(value) {
|
|
@@ -4001,7 +4278,7 @@ var PostgreSQLPlatformInvitationStore = class {
|
|
|
4001
4278
|
async get(email) {
|
|
4002
4279
|
const result = await this.pool.query(
|
|
4003
4280
|
`SELECT * FROM ${TABLE4} WHERE email = $1`,
|
|
4004
|
-
[(0,
|
|
4281
|
+
[(0, import_protocols5.normalizePlatformInvitationEmail)(email)]
|
|
4005
4282
|
);
|
|
4006
4283
|
return result.rows[0] ? mapRow4(result.rows[0]) : null;
|
|
4007
4284
|
}
|
|
@@ -4024,7 +4301,7 @@ var PostgreSQLPlatformInvitationStore = class {
|
|
|
4024
4301
|
consumed_at = EXCLUDED.consumed_at
|
|
4025
4302
|
RETURNING *`,
|
|
4026
4303
|
[
|
|
4027
|
-
(0,
|
|
4304
|
+
(0, import_protocols5.normalizePlatformInvitationEmail)(invitation.email),
|
|
4028
4305
|
invitation.role,
|
|
4029
4306
|
invitation.invitedBy ?? null,
|
|
4030
4307
|
invitation.createdAt,
|
|
@@ -4038,7 +4315,7 @@ var PostgreSQLPlatformInvitationStore = class {
|
|
|
4038
4315
|
async delete(email) {
|
|
4039
4316
|
const result = await this.pool.query(
|
|
4040
4317
|
`DELETE FROM ${TABLE4} WHERE email = $1`,
|
|
4041
|
-
[(0,
|
|
4318
|
+
[(0, import_protocols5.normalizePlatformInvitationEmail)(email)]
|
|
4042
4319
|
);
|
|
4043
4320
|
return (result.rowCount ?? 0) > 0;
|
|
4044
4321
|
}
|
|
@@ -4056,14 +4333,14 @@ var PostgreSQLPlatformInvitationStore = class {
|
|
|
4056
4333
|
AND consumed_at IS NULL
|
|
4057
4334
|
AND (expires_at IS NULL OR expires_at > $1)
|
|
4058
4335
|
RETURNING *`,
|
|
4059
|
-
[at, (0,
|
|
4336
|
+
[at, (0, import_protocols5.normalizePlatformInvitationEmail)(email)]
|
|
4060
4337
|
);
|
|
4061
4338
|
return result.rows[0] ? mapRow4(result.rows[0]) : null;
|
|
4062
4339
|
}
|
|
4063
4340
|
};
|
|
4064
4341
|
|
|
4065
4342
|
// src/stores/PostgreSQLOidcIdentityClaimStore.ts
|
|
4066
|
-
var
|
|
4343
|
+
var import_protocols6 = require("@axiom-lattice/protocols");
|
|
4067
4344
|
var TABLE5 = "lattice_oidc_identity_claims";
|
|
4068
4345
|
function mapRow5(row) {
|
|
4069
4346
|
return {
|
|
@@ -4146,7 +4423,7 @@ var PostgreSQLOidcIdentityClaimStore = class {
|
|
|
4146
4423
|
input.providerId,
|
|
4147
4424
|
input.issuer,
|
|
4148
4425
|
input.subject,
|
|
4149
|
-
(0,
|
|
4426
|
+
(0, import_protocols6.normalizeOidcIdentityEmail)(input.email),
|
|
4150
4427
|
input.name ?? null,
|
|
4151
4428
|
input.picture ?? null,
|
|
4152
4429
|
now,
|
|
@@ -4162,7 +4439,7 @@ var PostgreSQLOidcIdentityClaimStore = class {
|
|
|
4162
4439
|
return mapRow5(result.rows[0]);
|
|
4163
4440
|
} catch (error) {
|
|
4164
4441
|
if (isUniqueViolation2(error)) {
|
|
4165
|
-
throw new
|
|
4442
|
+
throw new import_protocols6.OidcIdentityClaimConflictError(
|
|
4166
4443
|
input.providerId,
|
|
4167
4444
|
input.issuer,
|
|
4168
4445
|
input.subject
|
|
@@ -4175,7 +4452,7 @@ var PostgreSQLOidcIdentityClaimStore = class {
|
|
|
4175
4452
|
const sets = [];
|
|
4176
4453
|
const params = [];
|
|
4177
4454
|
if (updates.email !== void 0) {
|
|
4178
|
-
params.push((0,
|
|
4455
|
+
params.push((0, import_protocols6.normalizeOidcIdentityEmail)(updates.email));
|
|
4179
4456
|
sets.push(`email = $${params.length}`);
|
|
4180
4457
|
}
|
|
4181
4458
|
if (updates.name !== void 0) {
|
|
@@ -4231,7 +4508,7 @@ var PostgreSQLOidcIdentityClaimStore = class {
|
|
|
4231
4508
|
|
|
4232
4509
|
// src/stores/PostgreSQLInviteLinkStore.ts
|
|
4233
4510
|
var import_core6 = require("@axiom-lattice/core");
|
|
4234
|
-
var
|
|
4511
|
+
var import_protocols7 = require("@axiom-lattice/protocols");
|
|
4235
4512
|
var TABLE6 = "lattice_invite_links";
|
|
4236
4513
|
function mapRow6(row) {
|
|
4237
4514
|
return {
|
|
@@ -4293,7 +4570,7 @@ var PostgreSQLInviteLinkStore = class {
|
|
|
4293
4570
|
input.scope,
|
|
4294
4571
|
input.tokenHash,
|
|
4295
4572
|
(0, import_core6.encrypt)(input.token),
|
|
4296
|
-
input.email ? (0,
|
|
4573
|
+
input.email ? (0, import_protocols7.normalizeInviteLinkEmail)(input.email) : null,
|
|
4297
4574
|
input.platformRole ?? null,
|
|
4298
4575
|
input.tenantId ?? null,
|
|
4299
4576
|
input.tenantRole ?? null,
|
|
@@ -5946,7 +6223,7 @@ var PostgreSQLEvalStore = class {
|
|
|
5946
6223
|
// src/stores/ThreadMessageQueueStore.ts
|
|
5947
6224
|
var import_pg13 = require("pg");
|
|
5948
6225
|
var import_crypto = __toESM(require("crypto"));
|
|
5949
|
-
var
|
|
6226
|
+
var import_protocols8 = require("@axiom-lattice/protocols");
|
|
5950
6227
|
|
|
5951
6228
|
// src/migrations/thread_message_queue_migrations.ts
|
|
5952
6229
|
var createThreadMessageQueueTable = {
|
|
@@ -6433,15 +6710,15 @@ var ThreadMessageQueueStore = class {
|
|
|
6433
6710
|
priority: row.priority || 0,
|
|
6434
6711
|
command: row.command ? typeof row.command === "string" ? JSON.parse(row.command) : row.command : void 0,
|
|
6435
6712
|
custom_run_config: row.custom_run_config ? typeof row.custom_run_config === "string" ? JSON.parse(row.custom_run_config) : row.custom_run_config : void 0,
|
|
6436
|
-
trusted_run_context: row.trusted_run_context ? (0,
|
|
6437
|
-
execution_mode: row.execution_mode == null ? void 0 : (0,
|
|
6713
|
+
trusted_run_context: row.trusted_run_context ? (0, import_protocols8.parseTrustedRunContext)(typeof row.trusted_run_context === "string" ? JSON.parse(row.trusted_run_context) : row.trusted_run_context) : void 0,
|
|
6714
|
+
execution_mode: row.execution_mode == null ? void 0 : (0, import_protocols8.parseQueuedExecutionMode)(row.execution_mode)
|
|
6438
6715
|
};
|
|
6439
6716
|
}
|
|
6440
6717
|
};
|
|
6441
6718
|
function validateQueueTrust(params) {
|
|
6442
6719
|
return {
|
|
6443
|
-
trustedRunContext: params.trusted_run_context === void 0 ? void 0 : (0,
|
|
6444
|
-
executionMode: params.execution_mode === void 0 ? void 0 : (0,
|
|
6720
|
+
trustedRunContext: params.trusted_run_context === void 0 ? void 0 : (0, import_protocols8.parseTrustedRunContext)(params.trusted_run_context),
|
|
6721
|
+
executionMode: params.execution_mode === void 0 ? void 0 : (0, import_protocols8.parseQueuedExecutionMode)(params.execution_mode)
|
|
6445
6722
|
};
|
|
6446
6723
|
}
|
|
6447
6724
|
function scopeClause(scope, start) {
|
|
@@ -6459,7 +6736,7 @@ function scopeClause(scope, start) {
|
|
|
6459
6736
|
|
|
6460
6737
|
// src/stores/ChannelBindingStore.ts
|
|
6461
6738
|
var import_pg14 = require("pg");
|
|
6462
|
-
var
|
|
6739
|
+
var import_protocols9 = require("@axiom-lattice/protocols");
|
|
6463
6740
|
|
|
6464
6741
|
// src/migrations/channel_bindings_migration.ts
|
|
6465
6742
|
var createChannelBindingsTable = {
|
|
@@ -6608,7 +6885,7 @@ var ChannelBindingStore = class {
|
|
|
6608
6885
|
return this.mapRowToBinding(result.rows[0]);
|
|
6609
6886
|
} catch (error) {
|
|
6610
6887
|
if (isBindingSubjectConflict(error)) {
|
|
6611
|
-
throw new
|
|
6888
|
+
throw new import_protocols9.DuplicateChannelBindingSubjectError();
|
|
6612
6889
|
}
|
|
6613
6890
|
throw error;
|
|
6614
6891
|
}
|
|
@@ -7745,7 +8022,7 @@ var PostgreSQLAgentWebAppStore = class {
|
|
|
7745
8022
|
|
|
7746
8023
|
// src/stores/PostgreSQLScheduleStorage.ts
|
|
7747
8024
|
var import_pg19 = require("pg");
|
|
7748
|
-
var
|
|
8025
|
+
var import_protocols10 = require("@axiom-lattice/protocols");
|
|
7749
8026
|
|
|
7750
8027
|
// src/migrations/schedule_migrations.ts
|
|
7751
8028
|
var createScheduledTasksTable = {
|
|
@@ -8160,10 +8437,10 @@ var PostgreSQLScheduleStorage = class {
|
|
|
8160
8437
|
WHERE task_id = $3 AND status = $4
|
|
8161
8438
|
RETURNING task_id`,
|
|
8162
8439
|
[
|
|
8163
|
-
|
|
8440
|
+
import_protocols10.ScheduledTaskStatus.RUNNING,
|
|
8164
8441
|
/* @__PURE__ */ new Date(),
|
|
8165
8442
|
taskId,
|
|
8166
|
-
|
|
8443
|
+
import_protocols10.ScheduledTaskStatus.PENDING
|
|
8167
8444
|
]
|
|
8168
8445
|
);
|
|
8169
8446
|
return (result.rowCount ?? 0) > 0;
|
|
@@ -8183,8 +8460,8 @@ var PostgreSQLScheduleStorage = class {
|
|
|
8183
8460
|
WHERE status = $2 AND updated_at < now() - ($3::bigint || ' milliseconds')::interval
|
|
8184
8461
|
RETURNING task_id`,
|
|
8185
8462
|
[
|
|
8186
|
-
|
|
8187
|
-
|
|
8463
|
+
import_protocols10.ScheduledTaskStatus.PENDING,
|
|
8464
|
+
import_protocols10.ScheduledTaskStatus.RUNNING,
|
|
8188
8465
|
olderThanMs
|
|
8189
8466
|
]
|
|
8190
8467
|
);
|
|
@@ -8207,7 +8484,7 @@ var PostgreSQLScheduleStorage = class {
|
|
|
8207
8484
|
await this.ensureInitialized();
|
|
8208
8485
|
const result = await this.pool.query(
|
|
8209
8486
|
`SELECT * FROM lattice_scheduled_tasks WHERE status IN ($1, $2) ORDER BY created_at ASC`,
|
|
8210
|
-
[
|
|
8487
|
+
[import_protocols10.ScheduledTaskStatus.PENDING, import_protocols10.ScheduledTaskStatus.PAUSED]
|
|
8211
8488
|
);
|
|
8212
8489
|
return result.rows.map((row) => this.mapRowToTask(row));
|
|
8213
8490
|
}
|
|
@@ -8366,9 +8643,9 @@ var PostgreSQLScheduleStorage = class {
|
|
|
8366
8643
|
AND updated_at < $4
|
|
8367
8644
|
`,
|
|
8368
8645
|
[
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8646
|
+
import_protocols10.ScheduledTaskStatus.COMPLETED,
|
|
8647
|
+
import_protocols10.ScheduledTaskStatus.CANCELLED,
|
|
8648
|
+
import_protocols10.ScheduledTaskStatus.FAILED,
|
|
8372
8649
|
cutoff
|
|
8373
8650
|
]
|
|
8374
8651
|
);
|
|
@@ -9384,7 +9661,7 @@ var PostgreSQLTaskStore = class {
|
|
|
9384
9661
|
|
|
9385
9662
|
// src/stores/PostgreSQLTaskWorkItemStore.ts
|
|
9386
9663
|
var import_pg21 = require("pg");
|
|
9387
|
-
var
|
|
9664
|
+
var import_protocols11 = require("@axiom-lattice/protocols");
|
|
9388
9665
|
var import_uuid4 = require("uuid");
|
|
9389
9666
|
|
|
9390
9667
|
// src/migrations/task_work_items_migration.ts
|
|
@@ -9674,8 +9951,8 @@ var PostgreSQLTaskWorkItemStore = class {
|
|
|
9674
9951
|
}
|
|
9675
9952
|
/** List pending execution results using one bounded PostgreSQL anti-join query. */
|
|
9676
9953
|
async listPendingExecutionResults(params) {
|
|
9677
|
-
if (!Number.isSafeInteger(params.limit) || params.limit < 0 || params.limit >
|
|
9678
|
-
const error = new RangeError(`limit must be a safe integer between 0 and ${
|
|
9954
|
+
if (!Number.isSafeInteger(params.limit) || params.limit < 0 || params.limit > import_protocols11.MAX_PENDING_EXECUTION_RESULTS_LIMIT) {
|
|
9955
|
+
const error = new RangeError(`limit must be a safe integer between 0 and ${import_protocols11.MAX_PENDING_EXECUTION_RESULTS_LIMIT}`);
|
|
9679
9956
|
error.code = "INVALID_LIMIT";
|
|
9680
9957
|
throw error;
|
|
9681
9958
|
}
|
|
@@ -10529,7 +10806,7 @@ var import_pg25 = require("pg");
|
|
|
10529
10806
|
var import_pgvector = require("@langchain/community/vectorstores/pgvector");
|
|
10530
10807
|
var import_documents = require("@langchain/core/documents");
|
|
10531
10808
|
var import_core9 = require("@axiom-lattice/core");
|
|
10532
|
-
var
|
|
10809
|
+
var import_protocols12 = require("@axiom-lattice/protocols");
|
|
10533
10810
|
function safeTableName(name) {
|
|
10534
10811
|
if (!/^[a-z][a-z0-9_-]*$/.test(name)) {
|
|
10535
10812
|
throw new Error(`Invalid table name: ${name}`);
|
|
@@ -10544,13 +10821,13 @@ var PGVectorStoreProvider = class {
|
|
|
10544
10821
|
async create(params) {
|
|
10545
10822
|
const { tableName, embeddingKey } = params;
|
|
10546
10823
|
const tenantId = params.tenantId ?? "default";
|
|
10547
|
-
const requestedKey = embeddingKey ||
|
|
10824
|
+
const requestedKey = embeddingKey || import_protocols12.EMBEDDING_DEFAULT_KEY;
|
|
10548
10825
|
const embeddings = await import_core9.embeddingsLatticeManager.getEmbeddingsClientWithTenant(
|
|
10549
10826
|
tenantId,
|
|
10550
10827
|
requestedKey
|
|
10551
|
-
) ?? (requestedKey ===
|
|
10828
|
+
) ?? (requestedKey === import_protocols12.EMBEDDING_DEFAULT_KEY ? void 0 : await import_core9.embeddingsLatticeManager.getEmbeddingsClientWithTenant(
|
|
10552
10829
|
tenantId,
|
|
10553
|
-
|
|
10830
|
+
import_protocols12.EMBEDDING_DEFAULT_KEY
|
|
10554
10831
|
)) ?? await import_core9.embeddingsLatticeManager.getEmbeddingsClientWithTenant(
|
|
10555
10832
|
tenantId,
|
|
10556
10833
|
"default"
|
|
@@ -11155,6 +11432,49 @@ var addOidcProviderAllowedHosts = {
|
|
|
11155
11432
|
}
|
|
11156
11433
|
};
|
|
11157
11434
|
|
|
11435
|
+
// src/migrations/platform_audit_migration.ts
|
|
11436
|
+
var createPlatformAuditTable = {
|
|
11437
|
+
version: 219,
|
|
11438
|
+
name: "create_platform_audit_table",
|
|
11439
|
+
up: async (client) => {
|
|
11440
|
+
await client.query(`
|
|
11441
|
+
CREATE TABLE IF NOT EXISTS lattice_platform_audit (
|
|
11442
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
11443
|
+
initiator_user_id VARCHAR(255),
|
|
11444
|
+
initiator_role VARCHAR(16),
|
|
11445
|
+
initiator JSONB NOT NULL,
|
|
11446
|
+
source VARCHAR(32) NOT NULL,
|
|
11447
|
+
executor JSONB NOT NULL,
|
|
11448
|
+
tenant_id VARCHAR(255),
|
|
11449
|
+
action VARCHAR(16) NOT NULL,
|
|
11450
|
+
status VARCHAR(16) NOT NULL,
|
|
11451
|
+
summary JSONB NOT NULL,
|
|
11452
|
+
before JSONB,
|
|
11453
|
+
after JSONB,
|
|
11454
|
+
error_code VARCHAR(64),
|
|
11455
|
+
duration_ms INTEGER NOT NULL,
|
|
11456
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
11457
|
+
)
|
|
11458
|
+
`);
|
|
11459
|
+
await client.query(`
|
|
11460
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_platform_audit_created
|
|
11461
|
+
ON lattice_platform_audit(created_at DESC, id DESC)
|
|
11462
|
+
`);
|
|
11463
|
+
await client.query(`
|
|
11464
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_platform_audit_initiator
|
|
11465
|
+
ON lattice_platform_audit(initiator_user_id, created_at DESC)
|
|
11466
|
+
`);
|
|
11467
|
+
await client.query(`
|
|
11468
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_platform_audit_tenant
|
|
11469
|
+
ON lattice_platform_audit(tenant_id, created_at DESC)
|
|
11470
|
+
WHERE tenant_id IS NOT NULL
|
|
11471
|
+
`);
|
|
11472
|
+
},
|
|
11473
|
+
down: async (client) => {
|
|
11474
|
+
await client.query("DROP TABLE IF EXISTS lattice_platform_audit");
|
|
11475
|
+
}
|
|
11476
|
+
};
|
|
11477
|
+
|
|
11158
11478
|
// src/migrations/collection_migrations.ts
|
|
11159
11479
|
var createCollectionsTable = {
|
|
11160
11480
|
version: 137,
|
|
@@ -14798,7 +15118,7 @@ function isActiveRunViolation(error) {
|
|
|
14798
15118
|
}
|
|
14799
15119
|
|
|
14800
15120
|
// src/stores/PostgreSQLPlatformSettingsStore.ts
|
|
14801
|
-
var
|
|
15121
|
+
var import_protocols13 = require("@axiom-lattice/protocols");
|
|
14802
15122
|
var TABLE7 = "lattice_platform_settings";
|
|
14803
15123
|
var SETTINGS_ID = "default";
|
|
14804
15124
|
var COLUMNS = "id, document, version, updated_by, updated_at";
|
|
@@ -14861,16 +15181,156 @@ var PostgreSQLPlatformSettingsStore = class {
|
|
|
14861
15181
|
`SELECT version FROM ${TABLE7} WHERE id = $1`,
|
|
14862
15182
|
[SETTINGS_ID]
|
|
14863
15183
|
);
|
|
14864
|
-
throw new
|
|
15184
|
+
throw new import_protocols13.PlatformSettingsVersionConflictError(
|
|
14865
15185
|
expectedVersion,
|
|
14866
15186
|
actual.rows[0] ? Number(actual.rows[0].version) : 0
|
|
14867
15187
|
);
|
|
14868
15188
|
}
|
|
14869
15189
|
};
|
|
14870
15190
|
|
|
15191
|
+
// src/stores/PostgreSQLPlatformAuditStore.ts
|
|
15192
|
+
var TABLE8 = "lattice_platform_audit";
|
|
15193
|
+
function parseJson(value) {
|
|
15194
|
+
return typeof value === "string" ? JSON.parse(value) : value;
|
|
15195
|
+
}
|
|
15196
|
+
function normalizeBoundary(value) {
|
|
15197
|
+
if (value === void 0) return void 0;
|
|
15198
|
+
const trimmed = value.trim();
|
|
15199
|
+
if (trimmed === "") return void 0;
|
|
15200
|
+
const parsed = new Date(trimmed);
|
|
15201
|
+
if (Number.isNaN(parsed.getTime())) return void 0;
|
|
15202
|
+
return parsed.toISOString();
|
|
15203
|
+
}
|
|
15204
|
+
function normalizePagination(value, fallback) {
|
|
15205
|
+
if (value === void 0 || !Number.isFinite(value)) return fallback;
|
|
15206
|
+
return Math.max(0, Math.trunc(value));
|
|
15207
|
+
}
|
|
15208
|
+
function mapRow16(row) {
|
|
15209
|
+
return {
|
|
15210
|
+
id: row.id,
|
|
15211
|
+
initiator: parseJson(row.initiator),
|
|
15212
|
+
source: row.source,
|
|
15213
|
+
executor: parseJson(row.executor),
|
|
15214
|
+
...row.tenant_id !== null ? { tenantId: row.tenant_id } : {},
|
|
15215
|
+
action: row.action,
|
|
15216
|
+
status: row.status,
|
|
15217
|
+
summary: parseJson(row.summary),
|
|
15218
|
+
...row.before !== null ? { before: parseJson(row.before) } : {},
|
|
15219
|
+
...row.after !== null ? { after: parseJson(row.after) } : {},
|
|
15220
|
+
...row.error_code !== null ? { errorCode: row.error_code } : {},
|
|
15221
|
+
durationMs: Number(row.duration_ms),
|
|
15222
|
+
createdAt: row.created_at
|
|
15223
|
+
};
|
|
15224
|
+
}
|
|
15225
|
+
var PostgreSQLPlatformAuditStore = class {
|
|
15226
|
+
constructor(options) {
|
|
15227
|
+
this.options = options;
|
|
15228
|
+
}
|
|
15229
|
+
get pool() {
|
|
15230
|
+
return this.options.pool;
|
|
15231
|
+
}
|
|
15232
|
+
/** Appends a record, assigning a fresh id and creation timestamp. */
|
|
15233
|
+
async append(record) {
|
|
15234
|
+
const initiator = record.initiator;
|
|
15235
|
+
const initiatorUserId = initiator.type === "human" ? initiator.userId : null;
|
|
15236
|
+
const initiatorRole = initiator.type === "human" ? initiator.role : null;
|
|
15237
|
+
const durationMs = Number.isFinite(record.durationMs) ? Math.max(0, Math.round(record.durationMs)) : 0;
|
|
15238
|
+
const result = await this.pool.query(
|
|
15239
|
+
`INSERT INTO ${TABLE8}
|
|
15240
|
+
(initiator_user_id, initiator_role, initiator, source, executor,
|
|
15241
|
+
tenant_id, action, status, summary, before, after, error_code,
|
|
15242
|
+
duration_ms)
|
|
15243
|
+
VALUES ($1,$2,$3::jsonb,$4,$5::jsonb,$6,$7,$8,$9::jsonb,$10::jsonb,
|
|
15244
|
+
$11::jsonb,$12,$13)
|
|
15245
|
+
RETURNING *`,
|
|
15246
|
+
[
|
|
15247
|
+
initiatorUserId,
|
|
15248
|
+
initiatorRole,
|
|
15249
|
+
JSON.stringify(initiator),
|
|
15250
|
+
record.source,
|
|
15251
|
+
JSON.stringify(record.executor),
|
|
15252
|
+
record.tenantId ?? null,
|
|
15253
|
+
record.action,
|
|
15254
|
+
record.status,
|
|
15255
|
+
JSON.stringify(record.summary),
|
|
15256
|
+
record.before === void 0 ? null : JSON.stringify(record.before),
|
|
15257
|
+
record.after === void 0 ? null : JSON.stringify(record.after),
|
|
15258
|
+
record.errorCode ?? null,
|
|
15259
|
+
durationMs
|
|
15260
|
+
]
|
|
15261
|
+
);
|
|
15262
|
+
const row = result.rows[0];
|
|
15263
|
+
if (!row) throw new Error("Platform audit record was not persisted");
|
|
15264
|
+
return mapRow16(row);
|
|
15265
|
+
}
|
|
15266
|
+
/** Returns a record by id, or null when it does not exist. */
|
|
15267
|
+
async get(id) {
|
|
15268
|
+
const result = await this.pool.query(
|
|
15269
|
+
`SELECT * FROM ${TABLE8} WHERE id = $1`,
|
|
15270
|
+
[id]
|
|
15271
|
+
);
|
|
15272
|
+
return result.rows[0] ? mapRow16(result.rows[0]) : null;
|
|
15273
|
+
}
|
|
15274
|
+
/**
|
|
15275
|
+
* Returns matching records newest-first.
|
|
15276
|
+
*
|
|
15277
|
+
* `initiatorUserId` only matches human initiators. `from` is inclusive and
|
|
15278
|
+
* `to` is exclusive after both are normalized to instants; invalid or empty
|
|
15279
|
+
* boundaries are ignored. Records are ordered by `createdAt` descending,
|
|
15280
|
+
* then by `id` descending. Results are paginated with a default limit of 100;
|
|
15281
|
+
* non-finite `offset`/`limit` fall back to defaults, finite values are
|
|
15282
|
+
* truncated to integers, and negatives are clamped to 0.
|
|
15283
|
+
*/
|
|
15284
|
+
async query(params) {
|
|
15285
|
+
const clauses = [];
|
|
15286
|
+
const values = [];
|
|
15287
|
+
if (params.initiatorUserId !== void 0) {
|
|
15288
|
+
values.push(params.initiatorUserId);
|
|
15289
|
+
clauses.push(`initiator_user_id = $${values.length}`);
|
|
15290
|
+
}
|
|
15291
|
+
if (params.source !== void 0) {
|
|
15292
|
+
values.push(params.source);
|
|
15293
|
+
clauses.push(`source = $${values.length}`);
|
|
15294
|
+
}
|
|
15295
|
+
if (params.tenantId !== void 0) {
|
|
15296
|
+
values.push(params.tenantId);
|
|
15297
|
+
clauses.push(`tenant_id = $${values.length}`);
|
|
15298
|
+
}
|
|
15299
|
+
if (params.action !== void 0) {
|
|
15300
|
+
values.push(params.action);
|
|
15301
|
+
clauses.push(`action = $${values.length}`);
|
|
15302
|
+
}
|
|
15303
|
+
if (params.status !== void 0) {
|
|
15304
|
+
values.push(params.status);
|
|
15305
|
+
clauses.push(`status = $${values.length}`);
|
|
15306
|
+
}
|
|
15307
|
+
const from = normalizeBoundary(params.from);
|
|
15308
|
+
if (from !== void 0) {
|
|
15309
|
+
values.push(from);
|
|
15310
|
+
clauses.push(`created_at >= $${values.length}`);
|
|
15311
|
+
}
|
|
15312
|
+
const to = normalizeBoundary(params.to);
|
|
15313
|
+
if (to !== void 0) {
|
|
15314
|
+
values.push(to);
|
|
15315
|
+
clauses.push(`created_at < $${values.length}`);
|
|
15316
|
+
}
|
|
15317
|
+
const limit = normalizePagination(params.limit, 100);
|
|
15318
|
+
const offset = normalizePagination(params.offset, 0);
|
|
15319
|
+
values.push(limit, offset);
|
|
15320
|
+
const where = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
|
|
15321
|
+
const { rows } = await this.pool.query(
|
|
15322
|
+
`SELECT * FROM ${TABLE8}${where}
|
|
15323
|
+
ORDER BY created_at DESC, id DESC
|
|
15324
|
+
LIMIT $${values.length - 1} OFFSET $${values.length}`,
|
|
15325
|
+
values
|
|
15326
|
+
);
|
|
15327
|
+
return rows.map(mapRow16);
|
|
15328
|
+
}
|
|
15329
|
+
};
|
|
15330
|
+
|
|
14871
15331
|
// src/stores/PostgreSQLChannelReplyJobStore.ts
|
|
14872
15332
|
var import_pg31 = require("pg");
|
|
14873
|
-
var
|
|
15333
|
+
var import_protocols14 = require("@axiom-lattice/protocols");
|
|
14874
15334
|
var DB_CLOCK_MS2 = "FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint";
|
|
14875
15335
|
var COLUMNS2 = `run_id, tenant_id, assistant_id, thread_id, adapter_channel,
|
|
14876
15336
|
channel_installation_id, reply_target, input_message_id, stream_cursor, status,
|
|
@@ -14890,7 +15350,7 @@ function toStatus(value) {
|
|
|
14890
15350
|
}
|
|
14891
15351
|
throw new Error(`Invalid channel reply job status: ${value}`);
|
|
14892
15352
|
}
|
|
14893
|
-
function
|
|
15353
|
+
function mapRow17(row) {
|
|
14894
15354
|
return {
|
|
14895
15355
|
runId: row.run_id,
|
|
14896
15356
|
tenantId: row.tenant_id,
|
|
@@ -14961,7 +15421,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
14961
15421
|
}
|
|
14962
15422
|
/** Creates a pending job with database-clock created/updated timestamps. */
|
|
14963
15423
|
async create(input) {
|
|
14964
|
-
(0,
|
|
15424
|
+
(0, import_protocols14.assertValidCreateChannelReplyJobInput)(input);
|
|
14965
15425
|
const result = await this.pool.query(
|
|
14966
15426
|
`WITH clock AS (SELECT ${DB_CLOCK_MS2} AS now_ms)
|
|
14967
15427
|
INSERT INTO lattice_channel_reply_jobs (
|
|
@@ -14990,7 +15450,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
14990
15450
|
input.availableAt
|
|
14991
15451
|
]
|
|
14992
15452
|
);
|
|
14993
|
-
return
|
|
15453
|
+
return mapRow17(result.rows[0]);
|
|
14994
15454
|
}
|
|
14995
15455
|
/** Reads one job within a tenant scope. */
|
|
14996
15456
|
async get(tenantId, runId) {
|
|
@@ -15000,7 +15460,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
15000
15460
|
WHERE tenant_id = $1 AND run_id = $2`,
|
|
15001
15461
|
[tenantId, runId]
|
|
15002
15462
|
);
|
|
15003
|
-
return result.rowCount === 0 ? null :
|
|
15463
|
+
return result.rowCount === 0 ? null : mapRow17(result.rows[0]);
|
|
15004
15464
|
}
|
|
15005
15465
|
/** Lists claimable pending jobs that are due at `now`, oldest first. */
|
|
15006
15466
|
async listPending(now, limit) {
|
|
@@ -15012,9 +15472,9 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
15012
15472
|
AND (lease_owner IS NULL OR lease_expires_at IS NULL OR lease_expires_at <= $1)
|
|
15013
15473
|
ORDER BY available_at ASC, created_at ASC, run_id ASC
|
|
15014
15474
|
LIMIT $2`,
|
|
15015
|
-
[now, (0,
|
|
15475
|
+
[now, (0, import_protocols14.normalizeChannelReplyJobListLimit)(limit)]
|
|
15016
15476
|
);
|
|
15017
|
-
return result.rows.map(
|
|
15477
|
+
return result.rows.map(mapRow17);
|
|
15018
15478
|
}
|
|
15019
15479
|
/**
|
|
15020
15480
|
* Atomically leases a claimable job.
|
|
@@ -15038,7 +15498,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
15038
15498
|
RETURNING ${COLUMNS2}`,
|
|
15039
15499
|
[tenantId, runId, owner, leaseMs]
|
|
15040
15500
|
);
|
|
15041
|
-
return result.rowCount === 0 ? null :
|
|
15501
|
+
return result.rowCount === 0 ? null : mapRow17(result.rows[0]);
|
|
15042
15502
|
}
|
|
15043
15503
|
/**
|
|
15044
15504
|
* Marks a job delivered when `owner` still holds the lease.
|
|
@@ -15064,7 +15524,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
15064
15524
|
RETURNING ${COLUMNS2}`,
|
|
15065
15525
|
[tenantId, runId, owner, outputMessageId]
|
|
15066
15526
|
);
|
|
15067
|
-
return result.rowCount === 0 ? null :
|
|
15527
|
+
return result.rowCount === 0 ? null : mapRow17(result.rows[0]);
|
|
15068
15528
|
}
|
|
15069
15529
|
/**
|
|
15070
15530
|
* Returns a job to pending with an incremented attempt count.
|
|
@@ -15091,7 +15551,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
15091
15551
|
RETURNING ${COLUMNS2}`,
|
|
15092
15552
|
[tenantId, runId, owner, error, availableAt]
|
|
15093
15553
|
);
|
|
15094
|
-
return result.rowCount === 0 ? null :
|
|
15554
|
+
return result.rowCount === 0 ? null : mapRow17(result.rows[0]);
|
|
15095
15555
|
}
|
|
15096
15556
|
/**
|
|
15097
15557
|
* Marks a job terminally failed when `owner` still holds the lease.
|
|
@@ -15116,7 +15576,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
15116
15576
|
RETURNING ${COLUMNS2}`,
|
|
15117
15577
|
[tenantId, runId, owner, error]
|
|
15118
15578
|
);
|
|
15119
|
-
return result.rowCount === 0 ? null :
|
|
15579
|
+
return result.rowCount === 0 ? null : mapRow17(result.rows[0]);
|
|
15120
15580
|
}
|
|
15121
15581
|
/** Deletes one job. Returns whether a row was removed. */
|
|
15122
15582
|
async delete(tenantId, runId) {
|
|
@@ -15138,7 +15598,7 @@ var PostgreSQLChannelReplyJobStore = class {
|
|
|
15138
15598
|
ORDER BY updated_at ASC, run_id ASC
|
|
15139
15599
|
LIMIT $2
|
|
15140
15600
|
)`,
|
|
15141
|
-
[before, (0,
|
|
15601
|
+
[before, (0, import_protocols14.normalizeChannelReplyJobListLimit)(limit)]
|
|
15142
15602
|
);
|
|
15143
15603
|
return result.rowCount ?? 0;
|
|
15144
15604
|
}
|
|
@@ -15592,8 +16052,8 @@ var PostgreSQLCheckpointStorage = class {
|
|
|
15592
16052
|
};
|
|
15593
16053
|
|
|
15594
16054
|
// src/stores/PostgreSQLStore.ts
|
|
15595
|
-
var
|
|
15596
|
-
function
|
|
16055
|
+
var import_protocols15 = require("@axiom-lattice/protocols");
|
|
16056
|
+
function mapRow18(row) {
|
|
15597
16057
|
return {
|
|
15598
16058
|
namespace: row.namespace,
|
|
15599
16059
|
key: row.key,
|
|
@@ -15611,9 +16071,9 @@ var PostgreSQLStore = class {
|
|
|
15611
16071
|
this.pool = pool;
|
|
15612
16072
|
}
|
|
15613
16073
|
async put(tenantId, input) {
|
|
15614
|
-
(0,
|
|
16074
|
+
(0, import_protocols15.assertStoreIdentity)(input.namespace, input.key);
|
|
15615
16075
|
const now = /* @__PURE__ */ new Date();
|
|
15616
|
-
const expiresAt = (0,
|
|
16076
|
+
const expiresAt = (0, import_protocols15.storeExpiresAt)(input.ttlMinutes, now) ?? null;
|
|
15617
16077
|
const result = await this.pool.query(
|
|
15618
16078
|
`INSERT INTO lattice_store_items
|
|
15619
16079
|
(tenant_id, namespace, key, value, created_at, updated_at, expires_at)
|
|
@@ -15625,10 +16085,10 @@ var PostgreSQLStore = class {
|
|
|
15625
16085
|
RETURNING tenant_id, namespace, key, value, created_at, updated_at, expires_at`,
|
|
15626
16086
|
[tenantId, input.namespace, input.key, JSON.stringify(input.value), now, expiresAt]
|
|
15627
16087
|
);
|
|
15628
|
-
return
|
|
16088
|
+
return mapRow18(result.rows[0]);
|
|
15629
16089
|
}
|
|
15630
16090
|
async get(tenantId, namespace, key) {
|
|
15631
|
-
(0,
|
|
16091
|
+
(0, import_protocols15.assertStoreIdentity)(namespace, key);
|
|
15632
16092
|
const result = await this.pool.query(
|
|
15633
16093
|
`SELECT tenant_id, namespace, key, value, created_at, updated_at, expires_at
|
|
15634
16094
|
FROM lattice_store_items
|
|
@@ -15636,10 +16096,10 @@ var PostgreSQLStore = class {
|
|
|
15636
16096
|
AND (expires_at IS NULL OR expires_at > $4)`,
|
|
15637
16097
|
[tenantId, namespace, key, /* @__PURE__ */ new Date()]
|
|
15638
16098
|
);
|
|
15639
|
-
return result.rows[0] ?
|
|
16099
|
+
return result.rows[0] ? mapRow18(result.rows[0]) : null;
|
|
15640
16100
|
}
|
|
15641
16101
|
async delete(tenantId, namespace, key) {
|
|
15642
|
-
(0,
|
|
16102
|
+
(0, import_protocols15.assertStoreIdentity)(namespace, key);
|
|
15643
16103
|
const result = await this.pool.query(
|
|
15644
16104
|
`DELETE FROM lattice_store_items
|
|
15645
16105
|
WHERE tenant_id = $1 AND namespace = $2 AND key = $3`,
|
|
@@ -15654,7 +16114,7 @@ var PostgreSQLStore = class {
|
|
|
15654
16114
|
];
|
|
15655
16115
|
const params = [tenantId, /* @__PURE__ */ new Date()];
|
|
15656
16116
|
if (input.namespacePrefix) {
|
|
15657
|
-
(0,
|
|
16117
|
+
(0, import_protocols15.assertStoreNamespacePrefix)(input.namespacePrefix);
|
|
15658
16118
|
}
|
|
15659
16119
|
if (input.namespacePrefix && input.namespacePrefix.length > 0) {
|
|
15660
16120
|
params.push(input.namespacePrefix);
|
|
@@ -15668,9 +16128,9 @@ var PostgreSQLStore = class {
|
|
|
15668
16128
|
params.push(input.query.replace(/[\\%_]/g, "\\$&"));
|
|
15669
16129
|
conditions.push(`value::text ILIKE '%' || $${params.length} || '%' ESCAPE '\\'`);
|
|
15670
16130
|
}
|
|
15671
|
-
params.push((0,
|
|
16131
|
+
params.push((0, import_protocols15.storePaginationValue)(input.limit, 10));
|
|
15672
16132
|
const limitParam = params.length;
|
|
15673
|
-
params.push((0,
|
|
16133
|
+
params.push((0, import_protocols15.storePaginationValue)(input.offset, 0));
|
|
15674
16134
|
const offsetParam = params.length;
|
|
15675
16135
|
const result = await this.pool.query(
|
|
15676
16136
|
`SELECT tenant_id, namespace, key, value, created_at, updated_at, expires_at
|
|
@@ -15680,10 +16140,10 @@ var PostgreSQLStore = class {
|
|
|
15680
16140
|
LIMIT $${limitParam} OFFSET $${offsetParam}`,
|
|
15681
16141
|
params
|
|
15682
16142
|
);
|
|
15683
|
-
return result.rows.map(
|
|
16143
|
+
return result.rows.map(mapRow18);
|
|
15684
16144
|
}
|
|
15685
16145
|
async listNamespaces(tenantId, prefix = [], limit = 100) {
|
|
15686
|
-
(0,
|
|
16146
|
+
(0, import_protocols15.assertStoreNamespacePrefix)(prefix);
|
|
15687
16147
|
const conditions = [
|
|
15688
16148
|
"tenant_id = $1",
|
|
15689
16149
|
"(expires_at IS NULL OR expires_at > $2)"
|
|
@@ -15693,7 +16153,7 @@ var PostgreSQLStore = class {
|
|
|
15693
16153
|
params.push(prefix);
|
|
15694
16154
|
conditions.push(`namespace[1:array_length($${params.length}::text[], 1)] = $${params.length}`);
|
|
15695
16155
|
}
|
|
15696
|
-
params.push((0,
|
|
16156
|
+
params.push((0, import_protocols15.storePaginationValue)(limit, 100));
|
|
15697
16157
|
const result = await this.pool.query(
|
|
15698
16158
|
`SELECT DISTINCT namespace
|
|
15699
16159
|
FROM lattice_store_items
|
|
@@ -15705,7 +16165,7 @@ var PostgreSQLStore = class {
|
|
|
15705
16165
|
return result.rows.map((row) => row.namespace);
|
|
15706
16166
|
}
|
|
15707
16167
|
async deleteExpired(now, limit) {
|
|
15708
|
-
const bounded = (0,
|
|
16168
|
+
const bounded = (0, import_protocols15.storePaginationValue)(limit, 0);
|
|
15709
16169
|
const result = await this.pool.query(
|
|
15710
16170
|
`WITH expired AS (
|
|
15711
16171
|
SELECT ctid FROM lattice_store_items
|
|
@@ -15861,6 +16321,8 @@ async function createPgStoreConfig(connectionString) {
|
|
|
15861
16321
|
mm.register(addOidcIdentityClaimInviteFields);
|
|
15862
16322
|
mm.register(createPlatformSettingsTable);
|
|
15863
16323
|
mm.register(addOidcProviderAllowedHosts);
|
|
16324
|
+
mm.register(createPlatformAuditTable);
|
|
16325
|
+
mm.register(createPersonalMcpServerConfigsTable);
|
|
15864
16326
|
await mm.migrate();
|
|
15865
16327
|
const checkpoint = import_langgraph_checkpoint_postgres.PostgresSaver.fromConnString(connectionString);
|
|
15866
16328
|
try {
|
|
@@ -15884,6 +16346,7 @@ async function createPgStoreConfig(connectionString) {
|
|
|
15884
16346
|
oidcIdentityClaim: new PostgreSQLOidcIdentityClaimStore(opts),
|
|
15885
16347
|
inviteLink: new PostgreSQLInviteLinkStore(opts),
|
|
15886
16348
|
platformSettings: new PostgreSQLPlatformSettingsStore(opts),
|
|
16349
|
+
platformAudit: new PostgreSQLPlatformAuditStore(opts),
|
|
15887
16350
|
channelBinding: new ChannelBindingStore(opts),
|
|
15888
16351
|
channelInstallation: new PostgreSQLChannelInstallationStore(opts),
|
|
15889
16352
|
thread: new PostgreSQLThreadStore(opts),
|
|
@@ -16505,6 +16968,7 @@ function mapRowToChannelIdentityMapping(row) {
|
|
|
16505
16968
|
PostgreSQLOidcIdentityClaimStore,
|
|
16506
16969
|
PostgreSQLOidcProviderConfigStore,
|
|
16507
16970
|
PostgreSQLOpenAuditStore,
|
|
16971
|
+
PostgreSQLPlatformAuditStore,
|
|
16508
16972
|
PostgreSQLPlatformInvitationStore,
|
|
16509
16973
|
PostgreSQLPlatformMemberStore,
|
|
16510
16974
|
PostgreSQLPlatformSettingsStore,
|
|
@@ -16576,7 +17040,9 @@ function mapRowToChannelIdentityMapping(row) {
|
|
|
16576
17040
|
createOidcIdentityClaimsTable,
|
|
16577
17041
|
createOidcProviderConfigsTable,
|
|
16578
17042
|
createPGVectorStoreProvider,
|
|
17043
|
+
createPersonalMcpServerConfigsTable,
|
|
16579
17044
|
createPgStoreConfig,
|
|
17045
|
+
createPlatformAuditTable,
|
|
16580
17046
|
createPlatformInvitationsTable,
|
|
16581
17047
|
createPlatformMembersTable,
|
|
16582
17048
|
createPlatformSettingsTable,
|