@axiom-lattice/pg-stores 3.1.5 → 3.1.8

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.mjs CHANGED
@@ -2016,6 +2016,18 @@ var PostgreSQLMcpServerConfigStore = class {
2016
2016
  throw new Error("Failed to decrypt MCP server configuration");
2017
2017
  }
2018
2018
  }
2019
+ if (config.headers && row.is_env_encrypted) {
2020
+ try {
2021
+ const decryptedHeaders = {};
2022
+ for (const [key, value] of Object.entries(config.headers)) {
2023
+ decryptedHeaders[key] = decrypt3(value);
2024
+ }
2025
+ config.headers = decryptedHeaders;
2026
+ } catch (error) {
2027
+ console.error("Failed to decrypt MCP server headers:", error);
2028
+ throw new Error("Failed to decrypt MCP server configuration");
2029
+ }
2030
+ }
2019
2031
  return {
2020
2032
  id: row.id,
2021
2033
  tenantId: row.tenant_id,
@@ -2044,6 +2056,14 @@ var PostgreSQLMcpServerConfigStore = class {
2044
2056
  configCopy.env = encryptedEnv;
2045
2057
  isEnvEncrypted = true;
2046
2058
  }
2059
+ if (configCopy.headers && Object.keys(configCopy.headers).length > 0) {
2060
+ const encryptedHeaders = {};
2061
+ for (const [key, value] of Object.entries(configCopy.headers)) {
2062
+ encryptedHeaders[key] = encrypt3(value);
2063
+ }
2064
+ configCopy.headers = encryptedHeaders;
2065
+ isEnvEncrypted = true;
2066
+ }
2047
2067
  return { config: configCopy, isEnvEncrypted };
2048
2068
  }
2049
2069
  };
@@ -6320,6 +6340,22 @@ var createAgentWebAppsTable = {
6320
6340
  }
6321
6341
  };
6322
6342
 
6343
+ // src/migrations/add_agent_web_apps_identity_migration.ts
6344
+ var addAgentWebAppsIdentity = {
6345
+ version: 176,
6346
+ name: "add_agent_web_apps_identity",
6347
+ up: async (client) => {
6348
+ await client.query(
6349
+ "ALTER TABLE lattice_agent_web_apps ADD COLUMN IF NOT EXISTS identity JSONB"
6350
+ );
6351
+ },
6352
+ down: async (client) => {
6353
+ await client.query(
6354
+ "ALTER TABLE lattice_agent_web_apps DROP COLUMN IF EXISTS identity"
6355
+ );
6356
+ }
6357
+ };
6358
+
6323
6359
  // src/stores/PostgreSQLAgentWebAppStore.ts
6324
6360
  function isRecord(value) {
6325
6361
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -6334,16 +6370,23 @@ function isScope(value) {
6334
6370
  return isRecord(value) && typeof value.defaultProjectId === "string" && isStringArray(value.allowedProjectIds) && (value.defaultModelKey === void 0 || typeof value.defaultModelKey === "string") && (value.allowedModelKeys === void 0 || isStringArray(value.allowedModelKeys));
6335
6371
  }
6336
6372
  function isFeatures(value) {
6337
- return isRecord(value) && typeof value.projectSelector === "boolean" && typeof value.modelSelector === "boolean" && typeof value.threadManagement === "boolean" && typeof value.attachments === "boolean" && typeof value.hitl === "boolean" && typeof value.genUI === "boolean";
6373
+ return isRecord(value) && typeof value.projectSelector === "boolean" && typeof value.modelSelector === "boolean" && typeof value.threadManagement === "boolean" && typeof value.attachments === "boolean" && typeof value.hitl === "boolean" && typeof value.genUI === "boolean" && (value.files === void 0 || typeof value.files === "boolean");
6338
6374
  }
6339
6375
  function isAppearance(value) {
6340
6376
  return isRecord(value) && (value.title === void 0 || typeof value.title === "string") && (value.welcomeMessage === void 0 || typeof value.welcomeMessage === "string") && (value.primaryColor === void 0 || typeof value.primaryColor === "string");
6341
6377
  }
6378
+ function isIdentity(value) {
6379
+ if (value === null || value === void 0) return true;
6380
+ if (!isRecord(value)) return false;
6381
+ const policyOk = value.policy === "unverified" || value.policy === "verified" || value.policy === "both";
6382
+ const issuersOk = Array.isArray(value.issuers) && value.issuers.every((issuer) => isRecord(issuer) && typeof issuer.iss === "string" && typeof issuer.aud === "string" && (issuer.alg === "HS256" || issuer.alg === "RS256"));
6383
+ return policyOk && issuersOk;
6384
+ }
6342
6385
  function isStatus(value) {
6343
6386
  return value === "draft" || value === "active" || value === "disabled";
6344
6387
  }
6345
6388
  function mapRow(row) {
6346
- if (!isStatus(row.status) || !isIntegration(row.integration) || !isScope(row.scope) || !isFeatures(row.features) || !isAppearance(row.appearance)) {
6389
+ if (!isStatus(row.status) || !isIntegration(row.integration) || !isScope(row.scope) || !isFeatures(row.features) || !isAppearance(row.appearance) || !isIdentity(row.identity)) {
6347
6390
  throw new Error(`Invalid agent web app row: ${row.id}`);
6348
6391
  }
6349
6392
  return {
@@ -6357,6 +6400,7 @@ function mapRow(row) {
6357
6400
  scope: row.scope,
6358
6401
  features: row.features,
6359
6402
  appearance: row.appearance,
6403
+ identity: row.identity === null ? void 0 : row.identity,
6360
6404
  createdAt: row.created_at,
6361
6405
  updatedAt: row.updated_at
6362
6406
  };
@@ -6377,6 +6421,7 @@ var PostgreSQLAgentWebAppStore = class {
6377
6421
  })();
6378
6422
  this.migrationManager = new MigrationManager(this.pool);
6379
6423
  this.migrationManager.register(createAgentWebAppsTable);
6424
+ this.migrationManager.register(addAgentWebAppsIdentity);
6380
6425
  if (options.autoMigrate !== false) {
6381
6426
  this.startInitialization();
6382
6427
  }
@@ -6437,8 +6482,8 @@ var PostgreSQLAgentWebAppStore = class {
6437
6482
  const id = `webapp_${randomUUID2().replace(/-/g, "")}`;
6438
6483
  const result = await this.pool.query(
6439
6484
  `INSERT INTO lattice_agent_web_apps
6440
- (id, tenant_id, assistant_id, name, description, status, integration, scope, features, appearance)
6441
- VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8::jsonb, $9::jsonb, $10::jsonb)
6485
+ (id, tenant_id, assistant_id, name, description, status, integration, scope, features, appearance, identity)
6486
+ VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8::jsonb, $9::jsonb, $10::jsonb, $11::jsonb)
6442
6487
  RETURNING *`,
6443
6488
  [
6444
6489
  id,
@@ -6450,7 +6495,8 @@ var PostgreSQLAgentWebAppStore = class {
6450
6495
  JSON.stringify(input.integration),
6451
6496
  JSON.stringify(input.scope),
6452
6497
  JSON.stringify(input.features),
6453
- JSON.stringify(input.appearance)
6498
+ JSON.stringify(input.appearance),
6499
+ input.identity ? JSON.stringify(input.identity) : null
6454
6500
  ]
6455
6501
  );
6456
6502
  return mapRow(result.rows[0]);
@@ -6476,6 +6522,9 @@ var PostgreSQLAgentWebAppStore = class {
6476
6522
  if (patch.appearance !== void 0) {
6477
6523
  add("appearance", JSON.stringify(patch.appearance));
6478
6524
  }
6525
+ if (patch.identity !== void 0) {
6526
+ add("identity", JSON.stringify(patch.identity));
6527
+ }
6479
6528
  if (patch.status !== void 0) add("status", patch.status);
6480
6529
  if (assignments.length === 0) return this.getById(tenantId, webAppId);
6481
6530
  values.push(tenantId, webAppId);
@@ -9557,6 +9606,30 @@ var createProjectRoomTables = {
9557
9606
  await client.query("DROP TABLE IF EXISTS lattice_project_rooms");
9558
9607
  }
9559
9608
  };
9609
+ var createProjectRoomReadStates = {
9610
+ version: 177,
9611
+ name: "create_project_room_read_states",
9612
+ up: async (client) => {
9613
+ await client.query(`
9614
+ CREATE TABLE IF NOT EXISTS lattice_project_room_read_states (
9615
+ tenant_id VARCHAR(255) NOT NULL,
9616
+ room_id VARCHAR(255) NOT NULL,
9617
+ user_id VARCHAR(255) NOT NULL,
9618
+ last_read_at TIMESTAMPTZ NOT NULL,
9619
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
9620
+ PRIMARY KEY (tenant_id, room_id, user_id)
9621
+ )
9622
+ `);
9623
+ await client.query(`
9624
+ CREATE INDEX IF NOT EXISTS idx_lattice_project_room_read_states_user
9625
+ ON lattice_project_room_read_states (tenant_id, user_id)
9626
+ `);
9627
+ },
9628
+ down: async (client) => {
9629
+ await client.query("DROP INDEX IF EXISTS idx_lattice_project_room_read_states_user");
9630
+ await client.query("DROP TABLE IF EXISTS lattice_project_room_read_states");
9631
+ }
9632
+ };
9560
9633
 
9561
9634
  // src/stores/PostgreSQLCapabilityBundleStore.ts
9562
9635
  import { randomUUID as randomUUID3 } from "crypto";
@@ -10344,6 +10417,19 @@ var PostgreSQLProjectRoomMessageStore = class {
10344
10417
  );
10345
10418
  return result.rows[0] ? mapRow5(result.rows[0]) : null;
10346
10419
  }
10420
+ /** Counts messages created strictly after a horizon, optionally excluding one human author. */
10421
+ async countAfter(input) {
10422
+ if (!(input.after instanceof Date) || Number.isNaN(input.after.getTime())) {
10423
+ throw new RangeError("Project room message count horizon date is invalid");
10424
+ }
10425
+ const result = await this.pool.query(
10426
+ `SELECT COUNT(*)::int AS count FROM lattice_project_room_messages
10427
+ WHERE tenant_id = $1 AND room_id = $2 AND created_at > $3
10428
+ AND ($4::text IS NULL OR author->>'type' <> 'human' OR author->>'userId' <> $4)`,
10429
+ [input.tenantId, input.roomId, input.after, input.excludeAuthorUserId ?? null]
10430
+ );
10431
+ return result.rows[0]?.count ?? 0;
10432
+ }
10347
10433
  parameters(input) {
10348
10434
  return [
10349
10435
  input.id,
@@ -10362,6 +10448,45 @@ var PostgreSQLProjectRoomMessageStore = class {
10362
10448
  }
10363
10449
  };
10364
10450
 
10451
+ // src/stores/PostgreSQLProjectRoomReadStateStore.ts
10452
+ function mapRow6(row) {
10453
+ if (typeof row.tenant_id !== "string" || typeof row.room_id !== "string" || typeof row.user_id !== "string" || !(row.last_read_at instanceof Date) || Number.isNaN(row.last_read_at.getTime()) || !(row.updated_at instanceof Date) || Number.isNaN(row.updated_at.getTime())) {
10454
+ throw new Error("Invalid project room read state row");
10455
+ }
10456
+ return { tenantId: row.tenant_id, roomId: row.room_id, userId: row.user_id, lastReadAt: row.last_read_at, updatedAt: row.updated_at };
10457
+ }
10458
+ var PostgreSQLProjectRoomReadStateStore = class {
10459
+ /** Creates a store using an externally managed shared pool. */
10460
+ constructor(options) {
10461
+ this.pool = options.pool;
10462
+ }
10463
+ /** Returns the user's read marker for a room, or null when never reported. */
10464
+ async get(tenantId, roomId, userId) {
10465
+ const result = await this.pool.query(
10466
+ `SELECT tenant_id, room_id, user_id, last_read_at, updated_at
10467
+ FROM lattice_project_room_read_states WHERE tenant_id = $1 AND room_id = $2 AND user_id = $3`,
10468
+ [tenantId, roomId, userId]
10469
+ );
10470
+ return result.rows[0] ? mapRow6(result.rows[0]) : null;
10471
+ }
10472
+ /** Upserts the marker monotonically using GREATEST so older reports never regress it. */
10473
+ async markRead(input) {
10474
+ if (!(input.lastReadAt instanceof Date) || Number.isNaN(input.lastReadAt.getTime())) {
10475
+ throw new RangeError("Project room read state lastReadAt is invalid");
10476
+ }
10477
+ const result = await this.pool.query(
10478
+ `INSERT INTO lattice_project_room_read_states (tenant_id, room_id, user_id, last_read_at, updated_at)
10479
+ VALUES ($1, $2, $3, $4, NOW())
10480
+ ON CONFLICT (tenant_id, room_id, user_id) DO UPDATE
10481
+ SET last_read_at = GREATEST(lattice_project_room_read_states.last_read_at, EXCLUDED.last_read_at),
10482
+ updated_at = NOW()
10483
+ RETURNING tenant_id, room_id, user_id, last_read_at, updated_at`,
10484
+ [input.tenantId, input.roomId, input.userId, input.lastReadAt]
10485
+ );
10486
+ return mapRow6(result.rows[0]);
10487
+ }
10488
+ };
10489
+
10365
10490
  // src/createPgStoreConfig.ts
10366
10491
  async function createPgStoreConfig(connectionString) {
10367
10492
  const pool = new Pool26({ connectionString });
@@ -10424,6 +10549,8 @@ async function createPgStoreConfig(connectionString) {
10424
10549
  mm.register(createProjectRoomTables);
10425
10550
  mm.register(addTrustedRunContextColumn);
10426
10551
  mm.register(addProjectLifecycleEventIndex);
10552
+ mm.register(addAgentWebAppsIdentity);
10553
+ mm.register(createProjectRoomReadStates);
10427
10554
  await mm.migrate();
10428
10555
  const checkpoint = PostgresSaver.fromConnString(connectionString);
10429
10556
  checkpoint.setup().catch((err) => {
@@ -10461,6 +10588,7 @@ async function createPgStoreConfig(connectionString) {
10461
10588
  projectMembership: new PostgreSQLProjectMembershipStore(opts),
10462
10589
  projectBotMembership: new PostgreSQLProjectBotMembershipStore(opts),
10463
10590
  projectRoomMessage: new PostgreSQLProjectRoomMessageStore(opts),
10591
+ projectRoomReadState: new PostgreSQLProjectRoomReadStateStore(opts),
10464
10592
  vectorStoreProvider: new PGVectorStoreProvider(pool, connectionString),
10465
10593
  checkpoint
10466
10594
  };
@@ -11036,6 +11164,7 @@ export {
11036
11164
  PostgreSQLProjectBotMembershipStore,
11037
11165
  PostgreSQLProjectMembershipStore,
11038
11166
  PostgreSQLProjectRoomMessageStore,
11167
+ PostgreSQLProjectRoomReadStateStore,
11039
11168
  PostgreSQLProjectRoomStore,
11040
11169
  PostgreSQLProjectStore,
11041
11170
  PostgreSQLScheduleStorage,
@@ -11088,6 +11217,7 @@ export {
11088
11217
  createMetricsConfigsTable,
11089
11218
  createPGVectorStoreProvider,
11090
11219
  createPgStoreConfig,
11220
+ createProjectRoomReadStates,
11091
11221
  createProjectRoomTables,
11092
11222
  createProjectsTable,
11093
11223
  createScheduledTasksTable,