@opengeni/db 0.19.0 → 0.22.1

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.
@@ -469,6 +469,54 @@ BEGIN
469
469
  ${literal(role)}
470
470
  );
471
471
  END IF;
472
+ IF to_regprocedure(
473
+ format(
474
+ '%I.scoped_knowledge_apply_lifecycle(uuid,text,uuid,text,bigint,text,text,text,text,text,text)',
475
+ ${literal(schema)}
476
+ )
477
+ ) IS NOT NULL THEN
478
+ EXECUTE format(
479
+ 'GRANT EXECUTE ON FUNCTION %I.scoped_knowledge_apply_lifecycle(uuid, text, uuid, text, bigint, text, text, text, text, text, text) TO %I',
480
+ ${literal(schema)},
481
+ ${literal(role)}
482
+ );
483
+ END IF;
484
+ IF to_regprocedure(
485
+ format(
486
+ '%I.scoped_knowledge_advance_source_acl(uuid,uuid,bigint,bigint,uuid,text,text,text,text,text,text)',
487
+ ${literal(schema)}
488
+ )
489
+ ) IS NOT NULL THEN
490
+ EXECUTE format(
491
+ 'GRANT EXECUTE ON FUNCTION %I.scoped_knowledge_advance_source_acl(uuid, uuid, bigint, bigint, uuid, text, text, text, text, text, text) TO %I',
492
+ ${literal(schema)},
493
+ ${literal(role)}
494
+ );
495
+ END IF;
496
+ IF to_regprocedure(
497
+ format(
498
+ '%I.scoped_knowledge_complete_sync(uuid,uuid,text,text,timestamptz,jsonb,text,text,text)',
499
+ ${literal(schema)}
500
+ )
501
+ ) IS NOT NULL THEN
502
+ EXECUTE format(
503
+ 'GRANT EXECUTE ON FUNCTION %I.scoped_knowledge_complete_sync(uuid, uuid, text, text, timestamptz, jsonb, text, text, text) TO %I',
504
+ ${literal(schema)},
505
+ ${literal(role)}
506
+ );
507
+ END IF;
508
+ IF to_regprocedure(
509
+ format(
510
+ '%I.scoped_knowledge_advance_object_version(uuid,uuid,bigint,bigint,uuid,text,text,text,text,text,text)',
511
+ ${literal(schema)}
512
+ )
513
+ ) IS NOT NULL THEN
514
+ EXECUTE format(
515
+ 'GRANT EXECUTE ON FUNCTION %I.scoped_knowledge_advance_object_version(uuid, uuid, bigint, bigint, uuid, text, text, text, text, text, text) TO %I',
516
+ ${literal(schema)},
517
+ ${literal(role)}
518
+ );
519
+ END IF;
472
520
  EXECUTE format('GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA %I TO %I', ${literal(schema)}, ${literal(role)});
473
521
  EXECUTE format(
474
522
  'ALTER DEFAULT PRIVILEGES FOR ROLE %I IN SCHEMA %I REVOKE ALL PRIVILEGES ON TABLES FROM %I',
@@ -25,6 +25,8 @@ export const FORCE_RLS_TABLES = [
25
25
  "codex_subscription_credentials",
26
26
  "composer_drafts",
27
27
  "connections",
28
+ "connector_action_policies",
29
+ "connector_action_requests",
28
30
  "credit_ledger_entries",
29
31
  "device_enrollment_requests",
30
32
  "document_bases",
@@ -42,9 +44,25 @@ export const FORCE_RLS_TABLES = [
42
44
  "host_export_outbox",
43
45
  "import_batches",
44
46
  "integration_oauth_state_nonces",
47
+ "knowledge_change_proposals",
48
+ "knowledge_claim_evidence",
49
+ "knowledge_claim_relations",
50
+ "knowledge_claim_reviews",
51
+ "knowledge_claims",
52
+ "knowledge_document_versions",
53
+ "knowledge_entities",
54
+ "knowledge_entity_aliases",
55
+ "knowledge_facts",
56
+ "knowledge_lifecycle_events",
45
57
  "knowledge_memories",
46
58
  "knowledge_memory_lifecycle_events",
47
59
  "knowledge_memory_relationships",
60
+ "knowledge_operation_receipts",
61
+ "knowledge_providers",
62
+ "knowledge_source_acl_versions",
63
+ "knowledge_source_objects",
64
+ "knowledge_sources",
65
+ "knowledge_sync_runs",
48
66
  "machine_metrics_latest",
49
67
  "machine_metrics_series",
50
68
  "model_call_facts",
@@ -154,6 +172,8 @@ export const RUNTIME_FULL_DML_TABLES = [
154
172
  "codex_subscription_credentials",
155
173
  "composer_drafts",
156
174
  "connections",
175
+ "connector_action_policies",
176
+ "connector_action_requests",
157
177
  "credit_ledger_entries",
158
178
  "device_enrollment_requests",
159
179
  "document_bases",
@@ -231,6 +251,7 @@ export const RUNTIME_FULL_DML_TABLES = [
231
251
 
232
252
  /** Configuration and lifecycle-owned audit rows are read-only at runtime. */
233
253
  export const RUNTIME_READ_ONLY_TABLES = [
254
+ "knowledge_lifecycle_events",
234
255
  "knowledge_memory_lifecycle_events",
235
256
  "knowledge_memory_relationships",
236
257
  "nested_agent_depth_configuration",
@@ -240,6 +261,21 @@ export const RUNTIME_READ_ONLY_TABLES = [
240
261
 
241
262
  /** Append-only evidence/revision tables are insertable and queryable, never mutable. */
242
263
  export const RUNTIME_READ_INSERT_TABLES = [
264
+ "knowledge_change_proposals",
265
+ "knowledge_claim_evidence",
266
+ "knowledge_claim_relations",
267
+ "knowledge_claim_reviews",
268
+ "knowledge_claims",
269
+ "knowledge_document_versions",
270
+ "knowledge_entities",
271
+ "knowledge_entity_aliases",
272
+ "knowledge_facts",
273
+ "knowledge_operation_receipts",
274
+ "knowledge_providers",
275
+ "knowledge_source_acl_versions",
276
+ "knowledge_source_objects",
277
+ "knowledge_sources",
278
+ "knowledge_sync_runs",
243
279
  "preference_registry_preferences",
244
280
  "preference_registry_revisions",
245
281
  "session_spawn_denials",
package/src/schema.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  FirstPartyMcpToolName,
3
+ McpPersonalConnectionDelegation,
3
4
  McpServerConnectionRef,
4
5
  SessionMcpApprovalPolicy,
5
6
  } from "@opengeni/contracts";
@@ -32,6 +33,18 @@ const vector = customType<{ data: number[]; driverData: string }>({
32
33
  },
33
34
  });
34
35
 
36
+ export type ConnectorActionPolicyDecision = "allow" | "ask" | "block";
37
+
38
+ export type ConnectorActionPolicySnapshotEntry = {
39
+ id: string;
40
+ connectionId: string;
41
+ serverId: string;
42
+ toolName: string;
43
+ actionName: string;
44
+ policy: ConnectorActionPolicyDecision;
45
+ version: number;
46
+ };
47
+
35
48
  export const managedAccounts = pgTable(
36
49
  "managed_accounts",
37
50
  {
@@ -713,6 +726,53 @@ export const connections = pgTable(
713
726
  }),
714
727
  );
715
728
 
729
+ export const connectorActionPolicies = pgTable(
730
+ "connector_action_policies",
731
+ {
732
+ id: uuid("id").primaryKey().defaultRandom(),
733
+ accountId: uuid("account_id")
734
+ .notNull()
735
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
736
+ workspaceId: uuid("workspace_id")
737
+ .notNull()
738
+ .references(() => workspaces.id, { onDelete: "cascade" }),
739
+ connectionId: text("connection_id").notNull(),
740
+ serverId: text("server_id").notNull(),
741
+ toolName: text("tool_name").notNull(),
742
+ actionName: text("action_name").notNull(),
743
+ policy: text("policy").$type<ConnectorActionPolicyDecision>().notNull(),
744
+ version: integer("version").notNull().default(1),
745
+ createdBySubjectId: text("created_by_subject_id").notNull(),
746
+ updatedBySubjectId: text("updated_by_subject_id").notNull(),
747
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
748
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
749
+ },
750
+ (table) => ({
751
+ workspaceAccount: foreignKey({
752
+ name: "connector_action_policies_workspace_account_fk",
753
+ columns: [table.workspaceId, table.accountId],
754
+ foreignColumns: [workspaces.id, workspaces.accountId],
755
+ }).onDelete("cascade"),
756
+ scope: uniqueIndex("connector_action_policies_scope_uq").on(
757
+ table.workspaceId,
758
+ table.connectionId,
759
+ table.serverId,
760
+ table.toolName,
761
+ table.actionName,
762
+ ),
763
+ workspaceConnection: index("connector_action_policies_workspace_connection_idx").on(
764
+ table.workspaceId,
765
+ table.connectionId,
766
+ table.serverId,
767
+ ),
768
+ policyValid: check(
769
+ "connector_action_policies_policy_chk",
770
+ sql`${table.policy} in ('allow', 'ask', 'block')`,
771
+ ),
772
+ versionValid: check("connector_action_policies_version_chk", sql`${table.version} > 0`),
773
+ }),
774
+ );
775
+
716
776
  export const slackBotUserLinks = pgTable(
717
777
  "slack_bot_user_links",
718
778
  {
@@ -1316,6 +1376,14 @@ export const sessions = pgTable(
1316
1376
  // Exact model-visible first-party tool selection. All catalogued tools are
1317
1377
  // selected by default; [] intentionally selects no broad-server tools.
1318
1378
  firstPartyMcpTools: jsonb("first_party_mcp_tools").$type<FirstPartyMcpToolName[]>().notNull(),
1379
+ // Initial-command staging only. initializeSessionStartAtomically copies
1380
+ // this immutable snapshot onto the first turn so create repair survives a
1381
+ // crash between the session insert and first-turn transaction. Runtime
1382
+ // credential authority must never read this session field.
1383
+ initialPersonalConnectionDelegations: jsonb("initial_personal_connection_delegations")
1384
+ .$type<McpPersonalConnectionDelegation[]>()
1385
+ .notNull()
1386
+ .default([]),
1319
1387
  // Durable tool-policy origin. Migration 0136 removes the old null/legacy
1320
1388
  // representation so every session has one explicit policy mode.
1321
1389
  toolPolicy: jsonb("tool_policy").$type<SessionToolPolicy>().notNull(),
@@ -1325,9 +1393,15 @@ export const sessions = pgTable(
1325
1393
  // when the creating grant carried a worker-signed sessionId claim (a session
1326
1394
  // spawning a worker); null for direct API creates and scheduled-task runs.
1327
1395
  // When set, this worker's terminal-for-now transitions wake the parent so a
1328
- // manager can orchestrate workers without busy-polling. Self-referencing FK,
1329
- // ON DELETE SET NULL so deleting a manager never cascades into its workers.
1396
+ // manager can orchestrate workers without busy-polling. The migration-owned
1397
+ // self-reference uses ON DELETE RESTRICT so immutable hierarchy and
1398
+ // authority lineage cannot be silently orphaned by a parent hard delete.
1330
1399
  parentSessionId: uuid("parent_session_id"),
1400
+ // Exact parent turn whose worker-signed attempt created this child. This is
1401
+ // private immutable authority lineage: child completion copies personal MCP
1402
+ // authority from that turn, never from whichever parent turn ran most
1403
+ // recently. Null for top-level and legacy child sessions.
1404
+ parentTurnId: uuid("parent_turn_id"),
1331
1405
  // Workspace-scoped CREATE idempotency key. NULL means the create carried no
1332
1406
  // key (each such create is independent). When set, the partial unique index
1333
1407
  // below collapses concurrent/retried creates with the same key in the same
@@ -2008,6 +2082,13 @@ export const sessionTurns = pgTable(
2008
2082
  .$type<Record<string, unknown>>()
2009
2083
  .notNull()
2010
2084
  .default({ backfill: true }),
2085
+ // Immutable exact personal MCP authority for this logical turn. Recovery,
2086
+ // approval, retries, and Toolspace reuse this row; no runtime may infer
2087
+ // broader authority from the session creator or mutable session state.
2088
+ personalConnectionDelegations: jsonb("personal_connection_delegations")
2089
+ .$type<McpPersonalConnectionDelegation[]>()
2090
+ .notNull()
2091
+ .default([]),
2011
2092
  cancelledBy: text("cancelled_by"),
2012
2093
  cancelReason: text("cancel_reason"),
2013
2094
  // Atomic per-turn toolspace call budget counter (migration 0043). Incremented
@@ -2067,6 +2148,10 @@ export const sessionTurnAttempts = pgTable(
2067
2148
  mcpApprovalPolicies: jsonb("mcp_approval_policies")
2068
2149
  .$type<Record<string, SessionMcpApprovalPolicy>>()
2069
2150
  .notNull(),
2151
+ connectorActionPolicies: jsonb("connector_action_policies")
2152
+ .$type<ConnectorActionPolicySnapshotEntry[]>()
2153
+ .notNull()
2154
+ .default([]),
2070
2155
  startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
2071
2156
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2072
2157
  closedAt: timestamp("closed_at", { withTimezone: true }),
@@ -2144,6 +2229,124 @@ export const sessionTurnAttempts = pgTable(
2144
2229
  }),
2145
2230
  );
2146
2231
 
2232
+ export const connectorActionRequests = pgTable(
2233
+ "connector_action_requests",
2234
+ {
2235
+ id: uuid("id").primaryKey().defaultRandom(),
2236
+ accountId: uuid("account_id")
2237
+ .notNull()
2238
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2239
+ workspaceId: uuid("workspace_id")
2240
+ .notNull()
2241
+ .references(() => workspaces.id, { onDelete: "cascade" }),
2242
+ sessionId: uuid("session_id").notNull(),
2243
+ turnId: uuid("turn_id").notNull(),
2244
+ creationAttemptId: uuid("creation_attempt_id").notNull(),
2245
+ creationExecutionGeneration: integer("creation_execution_generation").notNull(),
2246
+ executionAttemptId: uuid("execution_attempt_id"),
2247
+ executionAttemptGeneration: integer("execution_attempt_generation"),
2248
+ approvalId: text("approval_id").notNull(),
2249
+ initiatorKind: text("initiator_kind").$type<"subject" | "service">().notNull(),
2250
+ initiatorSubjectId: text("initiator_subject_id").notNull(),
2251
+ connectionId: text("connection_id").notNull(),
2252
+ connectionVersion: integer("connection_version"),
2253
+ serverId: text("server_id").notNull(),
2254
+ toolName: text("tool_name").notNull(),
2255
+ actionName: text("action_name").notNull(),
2256
+ // Attempt-frozen provenance intentionally survives policy deletion.
2257
+ policyId: uuid("policy_id"),
2258
+ policyVersion: integer("policy_version"),
2259
+ policySource: text("policy_source").$type<"explicit" | "ambiguous">().notNull(),
2260
+ policyDecision: text("policy_decision").$type<ConnectorActionPolicyDecision>().notNull(),
2261
+ actionFingerprint: text("action_fingerprint").notNull(),
2262
+ status: text("status")
2263
+ .$type<
2264
+ | "pending"
2265
+ | "approved"
2266
+ | "rejected"
2267
+ | "blocked"
2268
+ | "executing"
2269
+ | "completed"
2270
+ | "failed"
2271
+ | "uncertain"
2272
+ >()
2273
+ .notNull(),
2274
+ decision: text("decision").$type<"approve" | "reject">(),
2275
+ decisionBySubjectId: text("decision_by_subject_id"),
2276
+ decisionEventId: uuid("decision_event_id"),
2277
+ decidedAt: timestamp("decided_at", { withTimezone: true }),
2278
+ executionStartedAt: timestamp("execution_started_at", { withTimezone: true }),
2279
+ executionFinishedAt: timestamp("execution_finished_at", { withTimezone: true }),
2280
+ outcome: text("outcome"),
2281
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2282
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2283
+ },
2284
+ (table) => ({
2285
+ creationAttempt: foreignKey({
2286
+ name: "connector_action_requests_creation_attempt_fk",
2287
+ columns: [
2288
+ table.accountId,
2289
+ table.workspaceId,
2290
+ table.sessionId,
2291
+ table.turnId,
2292
+ table.creationAttemptId,
2293
+ ],
2294
+ foreignColumns: [
2295
+ sessionTurnAttempts.accountId,
2296
+ sessionTurnAttempts.workspaceId,
2297
+ sessionTurnAttempts.sessionId,
2298
+ sessionTurnAttempts.turnId,
2299
+ sessionTurnAttempts.id,
2300
+ ],
2301
+ }).onDelete("cascade"),
2302
+ executionAttempt: foreignKey({
2303
+ name: "connector_action_requests_execution_attempt_fk",
2304
+ columns: [
2305
+ table.accountId,
2306
+ table.workspaceId,
2307
+ table.sessionId,
2308
+ table.turnId,
2309
+ table.executionAttemptId,
2310
+ ],
2311
+ foreignColumns: [
2312
+ sessionTurnAttempts.accountId,
2313
+ sessionTurnAttempts.workspaceId,
2314
+ sessionTurnAttempts.sessionId,
2315
+ sessionTurnAttempts.turnId,
2316
+ sessionTurnAttempts.id,
2317
+ ],
2318
+ }).onDelete("cascade"),
2319
+ identity: uniqueIndex("connector_action_requests_identity_uq").on(
2320
+ table.workspaceId,
2321
+ table.sessionId,
2322
+ table.turnId,
2323
+ table.approvalId,
2324
+ ),
2325
+ attemptStatus: index("connector_action_requests_attempt_status_idx").on(
2326
+ table.workspaceId,
2327
+ table.creationAttemptId,
2328
+ table.status,
2329
+ ),
2330
+ sessionCreated: index("connector_action_requests_session_created_idx").on(
2331
+ table.workspaceId,
2332
+ table.sessionId,
2333
+ table.createdAt.desc(),
2334
+ table.id.desc(),
2335
+ ),
2336
+ policyDecisionValid: check(
2337
+ "connector_action_requests_policy_decision_chk",
2338
+ sql`${table.policyDecision} in ('allow', 'ask', 'block')`,
2339
+ ),
2340
+ statusValid: check(
2341
+ "connector_action_requests_status_chk",
2342
+ sql`${table.status} in (
2343
+ 'pending', 'approved', 'rejected', 'blocked', 'executing',
2344
+ 'completed', 'failed', 'uncertain'
2345
+ )`,
2346
+ ),
2347
+ }),
2348
+ );
2349
+
2147
2350
  // One durable idempotency/operation record for every queue, control,
2148
2351
  // foreground Send/Steer, and Agent MCP mutation. The database migration owns
2149
2352
  // the NULLS NOT DISTINCT uniqueness form because Drizzle does not model it.
@@ -2447,6 +2650,12 @@ export const sessionSystemUpdates = pgTable(
2447
2650
  summary: text("summary").notNull(),
2448
2651
  payload: jsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
2449
2652
  lineage: jsonb("lineage").$type<Record<string, unknown>>().notNull().default({}),
2653
+ // Private immutable authority frozen when this machine input is accepted.
2654
+ // Public projections intentionally omit connection ids and owner subjects.
2655
+ personalConnectionDelegations: jsonb("personal_connection_delegations")
2656
+ .$type<McpPersonalConnectionDelegation[]>()
2657
+ .notNull()
2658
+ .default([]),
2450
2659
  // pending is visible queue truth; delivered means its exact model-memory
2451
2660
  // batch was durably claimed. Terminal cancellation/supersession is explicit.
2452
2661
  state: text("state").notNull().default("pending"),
@@ -2526,6 +2735,12 @@ export const sessionSystemUpdateOutbox = pgTable(
2526
2735
  summary: text("summary").notNull(),
2527
2736
  payload: jsonb("payload").$type<Record<string, unknown>>().notNull().default({}),
2528
2737
  lineage: jsonb("lineage").$type<Record<string, unknown>>().notNull().default({}),
2738
+ // Exact private authority copied from the causal parent turn in the source
2739
+ // terminal transaction. Delivery retries cannot replace this snapshot.
2740
+ personalConnectionDelegations: jsonb("personal_connection_delegations")
2741
+ .$type<McpPersonalConnectionDelegation[]>()
2742
+ .notNull()
2743
+ .default([]),
2529
2744
  status: text("status").notNull().default("pending"),
2530
2745
  attempts: integer("attempts").notNull().default(0),
2531
2746
  updateId: uuid("update_id"),
@@ -4325,6 +4540,16 @@ export const scheduledTasks = pgTable(
4325
4540
  runMode: text("run_mode").notNull().default("new_session_per_run"),
4326
4541
  overlapPolicy: text("overlap_policy").notNull().default("allow_concurrent"),
4327
4542
  agentConfig: jsonb("agent_config").$type<unknown>().notNull(),
4543
+ createdByKind: text("created_by_kind").notNull().default("service"),
4544
+ createdBySubjectId: text("created_by_subject_id").notNull().default("unattributed-legacy"),
4545
+ createdByContext: jsonb("created_by_context")
4546
+ .$type<Record<string, unknown>>()
4547
+ .notNull()
4548
+ .default({ backfill: true }),
4549
+ personalConnectionDelegations: jsonb("personal_connection_delegations")
4550
+ .$type<McpPersonalConnectionDelegation[]>()
4551
+ .notNull()
4552
+ .default([]),
4328
4553
  reusableSessionId: uuid("reusable_session_id").references(() => sessions.id, {
4329
4554
  onDelete: "set null",
4330
4555
  }),
@@ -5343,3 +5568,4 @@ export const rigChanges = pgTable(
5343
5568
  export * from "./workspace-instruction-policies-schema";
5344
5569
  export * from "./preference-registry-schema";
5345
5570
  export * from "./memory-governance-schema";
5571
+ export * from "./scoped-knowledge-schema";