@axiom-lattice/pg-stores 5.1.1 → 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/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 import_protocols2 = require("@axiom-lattice/protocols");
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 import_protocols2.ExternalIdentityPersistError(
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 import_protocols2.ExternalIdentityConflictError(
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 import_protocols3 = require("@axiom-lattice/protocols");
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 import_protocols3.OidcProviderConfigConflictError(id);
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 import_protocols4 = require("@axiom-lattice/protocols");
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, import_protocols4.normalizePlatformInvitationEmail)(email)]
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, import_protocols4.normalizePlatformInvitationEmail)(invitation.email),
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, import_protocols4.normalizePlatformInvitationEmail)(email)]
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, import_protocols4.normalizePlatformInvitationEmail)(email)]
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 import_protocols5 = require("@axiom-lattice/protocols");
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, import_protocols5.normalizeOidcIdentityEmail)(input.email),
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 import_protocols5.OidcIdentityClaimConflictError(
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, import_protocols5.normalizeOidcIdentityEmail)(updates.email));
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 import_protocols6 = require("@axiom-lattice/protocols");
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, import_protocols6.normalizeInviteLinkEmail)(input.email) : null,
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 import_protocols7 = require("@axiom-lattice/protocols");
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, import_protocols7.parseTrustedRunContext)(typeof row.trusted_run_context === "string" ? JSON.parse(row.trusted_run_context) : row.trusted_run_context) : void 0,
6437
- execution_mode: row.execution_mode == null ? void 0 : (0, import_protocols7.parseQueuedExecutionMode)(row.execution_mode)
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, import_protocols7.parseTrustedRunContext)(params.trusted_run_context),
6444
- executionMode: params.execution_mode === void 0 ? void 0 : (0, import_protocols7.parseQueuedExecutionMode)(params.execution_mode)
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 import_protocols8 = require("@axiom-lattice/protocols");
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 import_protocols8.DuplicateChannelBindingSubjectError();
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 import_protocols9 = require("@axiom-lattice/protocols");
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
- import_protocols9.ScheduledTaskStatus.RUNNING,
8440
+ import_protocols10.ScheduledTaskStatus.RUNNING,
8164
8441
  /* @__PURE__ */ new Date(),
8165
8442
  taskId,
8166
- import_protocols9.ScheduledTaskStatus.PENDING
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
- import_protocols9.ScheduledTaskStatus.PENDING,
8187
- import_protocols9.ScheduledTaskStatus.RUNNING,
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
- [import_protocols9.ScheduledTaskStatus.PENDING, import_protocols9.ScheduledTaskStatus.PAUSED]
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
- import_protocols9.ScheduledTaskStatus.COMPLETED,
8370
- import_protocols9.ScheduledTaskStatus.CANCELLED,
8371
- import_protocols9.ScheduledTaskStatus.FAILED,
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 import_protocols10 = require("@axiom-lattice/protocols");
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 > import_protocols10.MAX_PENDING_EXECUTION_RESULTS_LIMIT) {
9678
- const error = new RangeError(`limit must be a safe integer between 0 and ${import_protocols10.MAX_PENDING_EXECUTION_RESULTS_LIMIT}`);
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 import_protocols11 = require("@axiom-lattice/protocols");
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 || import_protocols11.EMBEDDING_DEFAULT_KEY;
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 === import_protocols11.EMBEDDING_DEFAULT_KEY ? void 0 : await import_core9.embeddingsLatticeManager.getEmbeddingsClientWithTenant(
10828
+ ) ?? (requestedKey === import_protocols12.EMBEDDING_DEFAULT_KEY ? void 0 : await import_core9.embeddingsLatticeManager.getEmbeddingsClientWithTenant(
10552
10829
  tenantId,
10553
- import_protocols11.EMBEDDING_DEFAULT_KEY
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 import_protocols12 = require("@axiom-lattice/protocols");
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 import_protocols12.PlatformSettingsVersionConflictError(
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 import_protocols13 = require("@axiom-lattice/protocols");
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 mapRow16(row) {
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, import_protocols13.assertValidCreateChannelReplyJobInput)(input);
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 mapRow16(result.rows[0]);
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 : mapRow16(result.rows[0]);
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, import_protocols13.normalizeChannelReplyJobListLimit)(limit)]
15475
+ [now, (0, import_protocols14.normalizeChannelReplyJobListLimit)(limit)]
15016
15476
  );
15017
- return result.rows.map(mapRow16);
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 : mapRow16(result.rows[0]);
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 : mapRow16(result.rows[0]);
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 : mapRow16(result.rows[0]);
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 : mapRow16(result.rows[0]);
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, import_protocols13.normalizeChannelReplyJobListLimit)(limit)]
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 import_protocols14 = require("@axiom-lattice/protocols");
15596
- function mapRow17(row) {
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, import_protocols14.assertStoreIdentity)(input.namespace, input.key);
16074
+ (0, import_protocols15.assertStoreIdentity)(input.namespace, input.key);
15615
16075
  const now = /* @__PURE__ */ new Date();
15616
- const expiresAt = (0, import_protocols14.storeExpiresAt)(input.ttlMinutes, now) ?? null;
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 mapRow17(result.rows[0]);
16088
+ return mapRow18(result.rows[0]);
15629
16089
  }
15630
16090
  async get(tenantId, namespace, key) {
15631
- (0, import_protocols14.assertStoreIdentity)(namespace, key);
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] ? mapRow17(result.rows[0]) : null;
16099
+ return result.rows[0] ? mapRow18(result.rows[0]) : null;
15640
16100
  }
15641
16101
  async delete(tenantId, namespace, key) {
15642
- (0, import_protocols14.assertStoreIdentity)(namespace, key);
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, import_protocols14.assertStoreNamespacePrefix)(input.namespacePrefix);
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, import_protocols14.storePaginationValue)(input.limit, 10));
16131
+ params.push((0, import_protocols15.storePaginationValue)(input.limit, 10));
15672
16132
  const limitParam = params.length;
15673
- params.push((0, import_protocols14.storePaginationValue)(input.offset, 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(mapRow17);
16143
+ return result.rows.map(mapRow18);
15684
16144
  }
15685
16145
  async listNamespaces(tenantId, prefix = [], limit = 100) {
15686
- (0, import_protocols14.assertStoreNamespacePrefix)(prefix);
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, import_protocols14.storePaginationValue)(limit, 100));
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, import_protocols14.storePaginationValue)(limit, 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,