@opengeni/db 0.21.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.
- package/dist/{chunk-OTJHD33E.js → chunk-BNGEN5QZ.js} +5 -1
- package/dist/chunk-BNGEN5QZ.js.map +1 -0
- package/dist/{chunk-NK2A36KP.js → chunk-CYGFLLMN.js} +150 -1
- package/dist/chunk-CYGFLLMN.js.map +1 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +565 -4
- package/dist/index.js.map +1 -1
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +2 -2
- package/dist/schema.d.ts +820 -0
- package/dist/schema.js +5 -1
- package/dist/session-control.d.ts +1 -0
- package/drizzle/0155_connector_action_policies.sql +218 -0
- package/package.json +3 -3
- package/src/index.ts +870 -0
- package/src/runtime-posture.ts +4 -0
- package/src/schema.ts +181 -0
- package/src/session-control.ts +3 -0
- package/dist/chunk-NK2A36KP.js.map +0 -1
- package/dist/chunk-OTJHD33E.js.map +0 -1
package/src/runtime-posture.ts
CHANGED
|
@@ -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",
|
|
@@ -170,6 +172,8 @@ export const RUNTIME_FULL_DML_TABLES = [
|
|
|
170
172
|
"codex_subscription_credentials",
|
|
171
173
|
"composer_drafts",
|
|
172
174
|
"connections",
|
|
175
|
+
"connector_action_policies",
|
|
176
|
+
"connector_action_requests",
|
|
173
177
|
"credit_ledger_entries",
|
|
174
178
|
"device_enrollment_requests",
|
|
175
179
|
"document_bases",
|
package/src/schema.ts
CHANGED
|
@@ -33,6 +33,18 @@ const vector = customType<{ data: number[]; driverData: string }>({
|
|
|
33
33
|
},
|
|
34
34
|
});
|
|
35
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
|
+
|
|
36
48
|
export const managedAccounts = pgTable(
|
|
37
49
|
"managed_accounts",
|
|
38
50
|
{
|
|
@@ -714,6 +726,53 @@ export const connections = pgTable(
|
|
|
714
726
|
}),
|
|
715
727
|
);
|
|
716
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
|
+
|
|
717
776
|
export const slackBotUserLinks = pgTable(
|
|
718
777
|
"slack_bot_user_links",
|
|
719
778
|
{
|
|
@@ -2089,6 +2148,10 @@ export const sessionTurnAttempts = pgTable(
|
|
|
2089
2148
|
mcpApprovalPolicies: jsonb("mcp_approval_policies")
|
|
2090
2149
|
.$type<Record<string, SessionMcpApprovalPolicy>>()
|
|
2091
2150
|
.notNull(),
|
|
2151
|
+
connectorActionPolicies: jsonb("connector_action_policies")
|
|
2152
|
+
.$type<ConnectorActionPolicySnapshotEntry[]>()
|
|
2153
|
+
.notNull()
|
|
2154
|
+
.default([]),
|
|
2092
2155
|
startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2093
2156
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2094
2157
|
closedAt: timestamp("closed_at", { withTimezone: true }),
|
|
@@ -2166,6 +2229,124 @@ export const sessionTurnAttempts = pgTable(
|
|
|
2166
2229
|
}),
|
|
2167
2230
|
);
|
|
2168
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
|
+
|
|
2169
2350
|
// One durable idempotency/operation record for every queue, control,
|
|
2170
2351
|
// foreground Send/Steer, and Agent MCP mutation. The database migration owns
|
|
2171
2352
|
// the NULLS NOT DISTINCT uniqueness form because Drizzle does not model it.
|
package/src/session-control.ts
CHANGED
|
@@ -519,6 +519,7 @@ export async function registerSessionTurnAttemptClaim(
|
|
|
519
519
|
temporalActivityId: string;
|
|
520
520
|
verifiedControlRevision: number;
|
|
521
521
|
mcpApprovalPolicies: Record<string, SessionMcpApprovalPolicy>;
|
|
522
|
+
connectorActionPolicies: schema.ConnectorActionPolicySnapshotEntry[];
|
|
522
523
|
},
|
|
523
524
|
): Promise<typeof schema.sessionTurnAttempts.$inferSelect> {
|
|
524
525
|
const [inserted] = await db
|
|
@@ -554,6 +555,8 @@ export async function registerSessionTurnAttemptClaim(
|
|
|
554
555
|
existing.temporalWorkflowId !== input.temporalWorkflowId ||
|
|
555
556
|
existing.temporalWorkflowRunId !== input.temporalWorkflowRunId ||
|
|
556
557
|
existing.temporalActivityId !== input.temporalActivityId ||
|
|
558
|
+
JSON.stringify(existing.connectorActionPolicies) !==
|
|
559
|
+
JSON.stringify(input.connectorActionPolicies) ||
|
|
557
560
|
existing.state === "closed"
|
|
558
561
|
) {
|
|
559
562
|
throw new SessionControlInvariantError(
|