@opengeni/db 1.3.0 → 1.4.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.
Files changed (70) hide show
  1. package/dist/canonical-human-identities.js +3 -3
  2. package/dist/capability-reconciliation.js +2 -2
  3. package/dist/{chunk-LRSIODCQ.js → chunk-27T4AP25.js} +2 -2
  4. package/dist/{chunk-VQX54TK3.js → chunk-3WUCM7YF.js} +3 -3
  5. package/dist/{chunk-BRVBLQAL.js → chunk-AMK3FNOW.js} +4 -4
  6. package/dist/{chunk-AQMH2ZEH.js → chunk-BA52ITIY.js} +2 -2
  7. package/dist/{chunk-6S5T6FSP.js → chunk-CKDHKQS4.js} +5 -5
  8. package/dist/{chunk-HYBQABBJ.js → chunk-EFANLEWI.js} +2 -2
  9. package/dist/{chunk-PNWWNEDM.js → chunk-EMYA6XNE.js} +2 -2
  10. package/dist/{chunk-6UKNJ43T.js → chunk-GC5GUTV3.js} +2 -2
  11. package/dist/{chunk-DSNEIW5E.js → chunk-JL6TBB76.js} +2 -1
  12. package/dist/chunk-JL6TBB76.js.map +1 -0
  13. package/dist/{chunk-OEFNTGR3.js → chunk-NT7OGKYX.js} +4 -4
  14. package/dist/{chunk-BID3CNN3.js → chunk-T3CYF3DH.js} +3 -3
  15. package/dist/{chunk-3XHC5KC5.js → chunk-TRUEH4I2.js} +2 -2
  16. package/dist/{chunk-7S3O33NM.js → chunk-UQELJ6OM.js} +2 -2
  17. package/dist/{chunk-OI6YZXTU.js → chunk-VCHK4D6S.js} +2 -2
  18. package/dist/connect-attempts.js +3 -3
  19. package/dist/connection-metadata.d.ts +416 -0
  20. package/dist/editable-artifact-durable-export.js +2 -2
  21. package/dist/editable-artifacts.js +3 -3
  22. package/dist/index.d.ts +28 -7
  23. package/dist/index.js +10304 -9877
  24. package/dist/index.js.map +1 -1
  25. package/dist/legacy-tool-action-reviews.d.ts +75 -0
  26. package/dist/managed-auth-session-sets.js +3 -3
  27. package/dist/mcp-operations.js +2 -2
  28. package/dist/organization-integration-policy.js +3 -3
  29. package/dist/organization-slack-bots.d.ts +1 -1
  30. package/dist/retained-provider-commands.js +6 -6
  31. package/dist/schema.js +1 -1
  32. package/dist/session-background-commands.js +4 -4
  33. package/dist/session-command-output.js +5 -5
  34. package/dist/session-event-slices.js +3 -3
  35. package/dist/session-mcp-credential-rotation.js +5 -5
  36. package/dist/session-realtime-billing.d.ts +48 -0
  37. package/dist/session-realtime.d.ts +8 -2
  38. package/dist/session-tenancy.js +3 -3
  39. package/dist/video-generation.js +3 -3
  40. package/dist/voice-transcription-settlement.d.ts +36 -0
  41. package/dist/workspace-tool-defaults.js +4 -4
  42. package/drizzle/0623_voice_transcription_attribution.sql +128 -0
  43. package/drizzle/0624_azure_live_realtime_model.sql +30 -0
  44. package/drizzle/0625_transcription_billing_refusal_codes.sql +29 -0
  45. package/package.json +7 -7
  46. package/src/connection-metadata.ts +166 -0
  47. package/src/index.ts +98 -165
  48. package/src/insights-unified.ts +2 -1
  49. package/src/legacy-tool-action-reviews.ts +242 -0
  50. package/src/organization-slack-bots.ts +1 -1
  51. package/src/schema.ts +1 -0
  52. package/src/session-realtime-billing.ts +135 -0
  53. package/src/session-realtime-ledger.ts +9 -4
  54. package/src/session-realtime.ts +20 -2
  55. package/src/tool-action-reviews.ts +129 -18
  56. package/src/voice-transcription-settlement.ts +94 -0
  57. package/dist/chunk-DSNEIW5E.js.map +0 -1
  58. /package/dist/{chunk-LRSIODCQ.js.map → chunk-27T4AP25.js.map} +0 -0
  59. /package/dist/{chunk-VQX54TK3.js.map → chunk-3WUCM7YF.js.map} +0 -0
  60. /package/dist/{chunk-BRVBLQAL.js.map → chunk-AMK3FNOW.js.map} +0 -0
  61. /package/dist/{chunk-AQMH2ZEH.js.map → chunk-BA52ITIY.js.map} +0 -0
  62. /package/dist/{chunk-6S5T6FSP.js.map → chunk-CKDHKQS4.js.map} +0 -0
  63. /package/dist/{chunk-HYBQABBJ.js.map → chunk-EFANLEWI.js.map} +0 -0
  64. /package/dist/{chunk-PNWWNEDM.js.map → chunk-EMYA6XNE.js.map} +0 -0
  65. /package/dist/{chunk-6UKNJ43T.js.map → chunk-GC5GUTV3.js.map} +0 -0
  66. /package/dist/{chunk-OEFNTGR3.js.map → chunk-NT7OGKYX.js.map} +0 -0
  67. /package/dist/{chunk-BID3CNN3.js.map → chunk-T3CYF3DH.js.map} +0 -0
  68. /package/dist/{chunk-3XHC5KC5.js.map → chunk-TRUEH4I2.js.map} +0 -0
  69. /package/dist/{chunk-7S3O33NM.js.map → chunk-UQELJ6OM.js.map} +0 -0
  70. /package/dist/{chunk-OI6YZXTU.js.map → chunk-VCHK4D6S.js.map} +0 -0
@@ -0,0 +1,166 @@
1
+ import {
2
+ type ConnectionKind,
3
+ type ConnectionMetadata,
4
+ type ConnectionStatus,
5
+ OPENROUTER_CREDENTIAL_OPERATION_DIGEST_METADATA_KEY,
6
+ OPENROUTER_CREDENTIAL_OPERATION_ID_METADATA_KEY,
7
+ VERCEL_AI_GATEWAY_CREDENTIAL_OPERATION_DIGEST_METADATA_KEY,
8
+ VERCEL_AI_GATEWAY_CREDENTIAL_OPERATION_ID_METADATA_KEY,
9
+ } from "@opengeni/contracts";
10
+ import { and, desc, eq, isNull, or, type SQL } from "drizzle-orm";
11
+ import { withWorkspaceRls, withWorkspaceSubjectRls, type Database } from "./database";
12
+ import * as schema from "./schema";
13
+
14
+ /** Server-owned verification facts; public schemas expose them read-only and nullable. */
15
+ export type ConnectionMetadataWithVerification = ConnectionMetadata & {
16
+ verifiedInstallAt: string | null;
17
+ verifiedInstallVersion: number | null;
18
+ };
19
+
20
+ export const connectionMetadataColumns = {
21
+ id: schema.connections.id,
22
+ authorityId: schema.connections.authorityId,
23
+ authorityGeneration: schema.connections.authorityGeneration,
24
+ accountId: schema.connections.accountId,
25
+ workspaceId: schema.connections.workspaceId,
26
+ subjectId: schema.connections.subjectId,
27
+ providerDomain: schema.connections.providerDomain,
28
+ kind: schema.connections.kind,
29
+ status: schema.connections.status,
30
+ grantedScopes: schema.connections.grantedScopes,
31
+ expiresAt: schema.connections.expiresAt,
32
+ lastRefreshAt: schema.connections.lastRefreshAt,
33
+ lastUsedAt: schema.connections.lastUsedAt,
34
+ lastError: schema.connections.lastError,
35
+ version: schema.connections.version,
36
+ verifiedInstallAt: schema.connections.verifiedInstallAt,
37
+ verifiedInstallVersion: schema.connections.verifiedInstallVersion,
38
+ metadata: schema.connections.metadata,
39
+ createdBySubjectId: schema.connections.createdBySubjectId,
40
+ updatedBySubjectId: schema.connections.updatedBySubjectId,
41
+ createdAt: schema.connections.createdAt,
42
+ updatedAt: schema.connections.updatedAt,
43
+ };
44
+
45
+ export function connectionSubjectVisibility(subjectId?: string | null): SQL {
46
+ return subjectId
47
+ ? or(isNull(schema.connections.subjectId), eq(schema.connections.subjectId, subjectId))!
48
+ : isNull(schema.connections.subjectId);
49
+ }
50
+
51
+ export async function withConnectionSubjectRls<T>(
52
+ db: Database,
53
+ workspaceId: string,
54
+ subjectId: string | null | undefined,
55
+ fn: (db: Database) => Promise<T>,
56
+ ): Promise<T> {
57
+ return subjectId
58
+ ? await withWorkspaceSubjectRls(db, workspaceId, subjectId, fn)
59
+ : await withWorkspaceRls(db, workspaceId, fn);
60
+ }
61
+
62
+ export async function listConnectionsMetadata(
63
+ db: Database,
64
+ workspaceId: string,
65
+ subjectId?: string | null,
66
+ ): Promise<ConnectionMetadataWithVerification[]> {
67
+ return await withConnectionSubjectRls(db, workspaceId, subjectId, async (scopedDb) => {
68
+ const rows = await scopedDb
69
+ .select(connectionMetadataColumns)
70
+ .from(schema.connections)
71
+ .where(
72
+ and(
73
+ eq(schema.connections.workspaceId, workspaceId),
74
+ connectionSubjectVisibility(subjectId),
75
+ ),
76
+ )
77
+ // Legacy rows can share created_at. UUID DESC is the immutable stable
78
+ // tie-breaker, so every caller that intentionally selects the first row
79
+ // collapses duplicates in the same documented direction.
80
+ .orderBy(desc(schema.connections.createdAt), desc(schema.connections.id));
81
+ return rows.map(mapConnectionMetadata);
82
+ });
83
+ }
84
+
85
+ export async function getConnectionMetadata(
86
+ db: Database,
87
+ workspaceId: string,
88
+ connectionId: string,
89
+ subjectId?: string | null,
90
+ ): Promise<ConnectionMetadataWithVerification | null> {
91
+ return await withConnectionSubjectRls(db, workspaceId, subjectId, async (scopedDb) => {
92
+ const [row] = await scopedDb
93
+ .select(connectionMetadataColumns)
94
+ .from(schema.connections)
95
+ .where(
96
+ and(
97
+ eq(schema.connections.workspaceId, workspaceId),
98
+ eq(schema.connections.id, connectionId),
99
+ connectionSubjectVisibility(subjectId),
100
+ ),
101
+ )
102
+ .limit(1);
103
+ return row ? mapConnectionMetadata(row) : null;
104
+ });
105
+ }
106
+
107
+ export function mapConnectionMetadata(row: {
108
+ id: string;
109
+ authorityId?: string | null;
110
+ authorityGeneration: number;
111
+ accountId: string;
112
+ workspaceId: string;
113
+ subjectId: string | null;
114
+ providerDomain: string;
115
+ kind: string;
116
+ status: string;
117
+ grantedScopes: string[];
118
+ expiresAt: Date | null;
119
+ lastRefreshAt: Date | null;
120
+ lastUsedAt: Date | null;
121
+ lastError: string | null;
122
+ version: number;
123
+ verifiedInstallAt: Date | null;
124
+ verifiedInstallVersion: number | null;
125
+ metadata: Record<string, unknown>;
126
+ createdBySubjectId: string | null;
127
+ updatedBySubjectId: string | null;
128
+ createdAt: Date;
129
+ updatedAt: Date;
130
+ }): ConnectionMetadataWithVerification {
131
+ const {
132
+ [OPENROUTER_CREDENTIAL_OPERATION_ID_METADATA_KEY]: _openRouterOperationId,
133
+ [OPENROUTER_CREDENTIAL_OPERATION_DIGEST_METADATA_KEY]: _openRouterOperationDigest,
134
+ [VERCEL_AI_GATEWAY_CREDENTIAL_OPERATION_ID_METADATA_KEY]: _operationId,
135
+ [VERCEL_AI_GATEWAY_CREDENTIAL_OPERATION_DIGEST_METADATA_KEY]: _operationDigest,
136
+ anthropicCredentialOperationId: _anthropicOperationId,
137
+ anthropicCredentialOperationDigest: _anthropicOperationDigest,
138
+ claude_subscriptionCredentialOperationId: _claudeOperationId,
139
+ claude_subscriptionCredentialOperationDigest: _claudeOperationDigest,
140
+ ...publicMetadata
141
+ } = row.metadata;
142
+ return {
143
+ id: row.id,
144
+ ...(row.subjectId !== null && row.authorityId ? { authorityId: row.authorityId } : {}),
145
+ connectionAuthorityGeneration: row.authorityGeneration,
146
+ accountId: row.accountId,
147
+ workspaceId: row.workspaceId,
148
+ subjectId: row.subjectId,
149
+ providerDomain: row.providerDomain,
150
+ kind: row.kind as ConnectionKind,
151
+ status: row.status as ConnectionStatus,
152
+ grantedScopes: row.grantedScopes,
153
+ expiresAt: row.expiresAt?.toISOString() ?? null,
154
+ lastRefreshAt: row.lastRefreshAt?.toISOString() ?? null,
155
+ lastUsedAt: row.lastUsedAt?.toISOString() ?? null,
156
+ lastError: row.lastError,
157
+ version: row.version,
158
+ verifiedInstallAt: row.verifiedInstallAt?.toISOString() ?? null,
159
+ verifiedInstallVersion: row.verifiedInstallVersion,
160
+ metadata: publicMetadata,
161
+ createdBySubjectId: row.createdBySubjectId,
162
+ updatedBySubjectId: row.updatedBySubjectId,
163
+ createdAt: row.createdAt.toISOString(),
164
+ updatedAt: row.updatedAt.toISOString(),
165
+ };
166
+ }
package/src/index.ts CHANGED
@@ -1,4 +1,19 @@
1
1
  export * from "./organization-slack-bots";
2
+ export * from "./voice-transcription-settlement";
3
+ import {
4
+ connectionMetadataColumns,
5
+ connectionSubjectVisibility,
6
+ getConnectionMetadata,
7
+ listConnectionsMetadata,
8
+ mapConnectionMetadata,
9
+ withConnectionSubjectRls,
10
+ type ConnectionMetadataWithVerification,
11
+ } from "./connection-metadata";
12
+ export {
13
+ getConnectionMetadata,
14
+ listConnectionsMetadata,
15
+ type ConnectionMetadataWithVerification,
16
+ } from "./connection-metadata";
2
17
  export { readCreditPromotionPolicy } from "./credit-promotion-policy";
3
18
  import { getBillingBalance, getSpendableCreditBalance, planCreditDebit } from "./credit-balances";
4
19
  export {
@@ -802,6 +817,7 @@ export * from "./session-queue-commands";
802
817
  export * from "./session-realtime";
803
818
  export * from "./session-realtime-context";
804
819
  export * from "./session-realtime-ledger";
820
+ export * from "./session-realtime-billing";
805
821
  export * from "./new-session-drafts";
806
822
  export * from "./workspace-instruction-policies";
807
823
  export * from "./company-profile";
@@ -6545,12 +6561,6 @@ export class PersonalGitHubRepositorySelectionUnavailableError extends Error {
6545
6561
  }
6546
6562
  }
6547
6563
 
6548
- /** Server-owned verification facts; public schemas expose them read-only and nullable. */
6549
- export type ConnectionMetadataWithVerification = ConnectionMetadata & {
6550
- verifiedInstallAt: string | null;
6551
- verifiedInstallVersion: number | null;
6552
- };
6553
-
6554
6564
  export type SlackBotPostOperation = {
6555
6565
  id: string;
6556
6566
  accountId: string;
@@ -10631,37 +10641,6 @@ export function mcpServerIdForCapability(
10631
10641
  return `cap-${body}-${shortHash(capabilityId)}`;
10632
10642
  }
10633
10643
 
10634
- const connectionMetadataColumns = {
10635
- id: schema.connections.id,
10636
- authorityId: schema.connections.authorityId,
10637
- authorityGeneration: schema.connections.authorityGeneration,
10638
- accountId: schema.connections.accountId,
10639
- workspaceId: schema.connections.workspaceId,
10640
- subjectId: schema.connections.subjectId,
10641
- providerDomain: schema.connections.providerDomain,
10642
- kind: schema.connections.kind,
10643
- status: schema.connections.status,
10644
- grantedScopes: schema.connections.grantedScopes,
10645
- expiresAt: schema.connections.expiresAt,
10646
- lastRefreshAt: schema.connections.lastRefreshAt,
10647
- lastUsedAt: schema.connections.lastUsedAt,
10648
- lastError: schema.connections.lastError,
10649
- version: schema.connections.version,
10650
- verifiedInstallAt: schema.connections.verifiedInstallAt,
10651
- verifiedInstallVersion: schema.connections.verifiedInstallVersion,
10652
- metadata: schema.connections.metadata,
10653
- createdBySubjectId: schema.connections.createdBySubjectId,
10654
- updatedBySubjectId: schema.connections.updatedBySubjectId,
10655
- createdAt: schema.connections.createdAt,
10656
- updatedAt: schema.connections.updatedAt,
10657
- };
10658
-
10659
- function connectionSubjectVisibility(subjectId?: string | null): SQL {
10660
- return subjectId
10661
- ? or(isNull(schema.connections.subjectId), eq(schema.connections.subjectId, subjectId))!
10662
- : isNull(schema.connections.subjectId);
10663
- }
10664
-
10665
10644
  function connectionExactSubject(subjectId?: string | null): SQL {
10666
10645
  return subjectId
10667
10646
  ? eq(schema.connections.subjectId, subjectId)
@@ -10683,17 +10662,6 @@ function personalSlackCanonicalConnectionOrder(): SQL[] {
10683
10662
  ];
10684
10663
  }
10685
10664
 
10686
- async function withConnectionSubjectRls<T>(
10687
- db: Database,
10688
- workspaceId: string,
10689
- subjectId: string | null | undefined,
10690
- fn: (db: Database) => Promise<T>,
10691
- ): Promise<T> {
10692
- return subjectId
10693
- ? await withWorkspaceSubjectRls(db, workspaceId, subjectId, fn)
10694
- : await withWorkspaceRls(db, workspaceId, fn);
10695
- }
10696
-
10697
10665
  const connectionAccessPolicyColumns = {
10698
10666
  allowedModelIds: schema.connections.allowedModelIds,
10699
10667
  allowedWorkspaceIds: schema.connections.allowedWorkspaceIds,
@@ -11414,51 +11382,6 @@ export async function persistProviderOAuthConnection(
11414
11382
  );
11415
11383
  }
11416
11384
 
11417
- export async function listConnectionsMetadata(
11418
- db: Database,
11419
- workspaceId: string,
11420
- subjectId?: string | null,
11421
- ): Promise<ConnectionMetadataWithVerification[]> {
11422
- return await withConnectionSubjectRls(db, workspaceId, subjectId, async (scopedDb) => {
11423
- const rows = await scopedDb
11424
- .select(connectionMetadataColumns)
11425
- .from(schema.connections)
11426
- .where(
11427
- and(
11428
- eq(schema.connections.workspaceId, workspaceId),
11429
- connectionSubjectVisibility(subjectId),
11430
- ),
11431
- )
11432
- // Legacy rows can share created_at. UUID DESC is the immutable stable
11433
- // tie-breaker, so every caller that intentionally selects the first row
11434
- // collapses duplicates in the same documented direction.
11435
- .orderBy(desc(schema.connections.createdAt), desc(schema.connections.id));
11436
- return rows.map(mapConnectionMetadata);
11437
- });
11438
- }
11439
-
11440
- export async function getConnectionMetadata(
11441
- db: Database,
11442
- workspaceId: string,
11443
- connectionId: string,
11444
- subjectId?: string | null,
11445
- ): Promise<ConnectionMetadataWithVerification | null> {
11446
- return await withConnectionSubjectRls(db, workspaceId, subjectId, async (scopedDb) => {
11447
- const [row] = await scopedDb
11448
- .select(connectionMetadataColumns)
11449
- .from(schema.connections)
11450
- .where(
11451
- and(
11452
- eq(schema.connections.workspaceId, workspaceId),
11453
- eq(schema.connections.id, connectionId),
11454
- connectionSubjectVisibility(subjectId),
11455
- ),
11456
- )
11457
- .limit(1);
11458
- return row ? mapConnectionMetadata(row) : null;
11459
- });
11460
- }
11461
-
11462
11385
  function personalGitHubRepositorySelectionStateFromDatabase(
11463
11386
  value: unknown,
11464
11387
  ): PersonalGitHubRepositorySelectionState | null {
@@ -55775,6 +55698,46 @@ export type SandboxWorkspaceMutationAdmission = {
55775
55698
 
55776
55699
  export type SandboxWorkspaceMutationProviderOutcome = "resolved" | "rejected";
55777
55700
 
55701
+ /** Evidence from a committed exact admission settlement. It establishes the
55702
+ * physical provider outcome only; mutable output authority remains rejected. */
55703
+ export type SandboxWorkspaceMutationPhysicalSettlement = Readonly<{
55704
+ accountId: string;
55705
+ workspaceId: string;
55706
+ admission: Readonly<SandboxWorkspaceMutationAdmission>;
55707
+ operation: string;
55708
+ outcome: "resolved";
55709
+ }>;
55710
+
55711
+ /** The exact provider outcome committed before its output failed an acceptance
55712
+ * fence. A generic admission fence or failed transaction carries no receipt.
55713
+ * This error never authorizes accepting output or replaying provider work. */
55714
+ export class SandboxWorkspaceMutationOutputRejectedError extends SandboxWorkspaceMutationFencedError {
55715
+ readonly name = "SandboxWorkspaceMutationOutputRejectedError";
55716
+ readonly physicalSettlement: SandboxWorkspaceMutationPhysicalSettlement;
55717
+
55718
+ constructor(
55719
+ code: SandboxWorkspaceMutationFencedError["code"],
55720
+ message: string,
55721
+ physicalSettlement: SandboxWorkspaceMutationPhysicalSettlement,
55722
+ ) {
55723
+ super(code, message);
55724
+ this.physicalSettlement = Object.freeze({
55725
+ ...physicalSettlement,
55726
+ admission: Object.freeze({ ...physicalSettlement.admission }),
55727
+ });
55728
+ }
55729
+
55730
+ matchesPhysicalSettlement(input: {
55731
+ accountId: string;
55732
+ workspaceId: string;
55733
+ admission: SandboxWorkspaceMutationAdmission;
55734
+ operation: string;
55735
+ outcome: SandboxWorkspaceMutationProviderOutcome;
55736
+ }): boolean {
55737
+ return isDeepStrictEqual(this.physicalSettlement, input);
55738
+ }
55739
+ }
55740
+
55778
55741
  export type SandboxRetainedProcessState = "active" | "exited" | "lost";
55779
55742
 
55780
55743
  export type SandboxRetainedProcess = {
@@ -55953,6 +55916,7 @@ type SandboxWorkspaceMutationSettlementResult =
55953
55916
  | "authority_unattributed"
55954
55917
  | "authority_revoked";
55955
55918
  detail: string;
55919
+ physicallySettled?: true;
55956
55920
  };
55957
55921
 
55958
55922
  type TurnWorkspaceMutationAuthority = {
@@ -57308,6 +57272,10 @@ async function verifyWorkspaceMutationSettlementForAuthority(
57308
57272
  },
57309
57273
  ): Promise<void> {
57310
57274
  const operation = normalizeWorkspaceMutationOperation(input.operation);
57275
+ const admissionSnapshot = { ...input.admission };
57276
+ const outcome = input.outcome;
57277
+ // Savepoint release cannot prove an outer caller-owned transaction committed.
57278
+ const ownsCommit = typeof (db as Database & { rollback?: unknown }).rollback !== "function";
57311
57279
  const settleOnce = async (): Promise<SandboxWorkspaceMutationSettlementResult> =>
57312
57280
  await withRlsContext(
57313
57281
  db,
@@ -57349,19 +57317,20 @@ async function verifyWorkspaceMutationSettlementForAuthority(
57349
57317
  const admission = await selectExactAdmissionForUpdate(tx, {
57350
57318
  accountId: authorityInput.accountId,
57351
57319
  workspaceId: authorityInput.workspaceId,
57352
- admissionId: input.admission.id,
57320
+ admissionId: admissionSnapshot.id,
57353
57321
  actorKind,
57354
57322
  actorId,
57355
57323
  sessionId: authorityInput.sessionId,
57356
- admittedWorkspaceGeneration: input.admission.workspaceGeneration,
57324
+ admittedWorkspaceGeneration: admissionSnapshot.workspaceGeneration,
57357
57325
  operation,
57358
57326
  });
57359
57327
  if (
57360
57328
  !admission ||
57361
- !admissionMatchesSnapshot(admission, input.admission) ||
57362
- !admissionSnapshotMatchesAuthorityInput(input.admission, authorityInput) ||
57329
+ !admissionMatchesSnapshot(admission, admissionSnapshot) ||
57330
+ !admissionMatchesAuthorityInput(admission, authorityInput) ||
57363
57331
  admission.provider_outcome === "retained" ||
57364
- (admission.provider_outcome && admission.provider_outcome !== input.outcome)
57332
+ (admission.provider_outcome && admission.provider_outcome !== outcome) ||
57333
+ (admission.settled_at && admission.provider_outcome !== outcome)
57365
57334
  ) {
57366
57335
  return {
57367
57336
  failure: "admission_fenced" as const,
@@ -57374,11 +57343,21 @@ async function verifyWorkspaceMutationSettlementForAuthority(
57374
57343
  authorityInput.workspaceId,
57375
57344
  authorityInput.sessionId,
57376
57345
  );
57377
- await tx.execute(sql`
57346
+ const [physical] = await tx.execute<{
57347
+ provider_outcome: string;
57348
+ settled_at: Date;
57349
+ }>(sql`
57378
57350
  update sandbox_workspace_mutation_admissions set
57379
- provider_outcome = ${input.outcome}, settled_at = now()
57380
- where id = ${input.admission.id} and settled_at is null
57351
+ provider_outcome = ${outcome}, settled_at = now()
57352
+ where id = ${admissionSnapshot.id} and settled_at is null
57353
+ returning provider_outcome, settled_at
57381
57354
  `);
57355
+ if (physical?.provider_outcome !== outcome || !physical.settled_at) {
57356
+ return {
57357
+ failure: "admission_fenced" as const,
57358
+ detail: "Workspace mutation settlement did not commit its exact provider outcome",
57359
+ };
57360
+ }
57382
57361
  if (
57383
57362
  pendingAttempt ||
57384
57363
  (authorityInput.kind !== "direct" &&
@@ -57410,12 +57389,15 @@ async function verifyWorkspaceMutationSettlementForAuthority(
57410
57389
  });
57411
57390
  }
57412
57391
  }
57413
- if (input.outcome === "rejected") return { failure: null };
57414
- if (authorityFailure) return authorityFailure;
57392
+ if (outcome === "rejected") return { failure: null };
57393
+ if (authorityFailure) return { ...authorityFailure, physicallySettled: true };
57415
57394
  if (!authority) {
57416
57395
  throw new Error("Workspace mutation settlement lost its locked authority");
57417
57396
  }
57418
- return await verifyResolvedAdmissionAuthority(tx, authority, admission);
57397
+ const acceptance = await verifyResolvedAdmissionAuthority(tx, authority, admission);
57398
+ return acceptance.failure === null
57399
+ ? acceptance
57400
+ : { ...acceptance, physicallySettled: true };
57419
57401
  }),
57420
57402
  );
57421
57403
  const settlement = await runIdempotentPersistenceTransaction(
@@ -57426,6 +57408,18 @@ async function verifyWorkspaceMutationSettlementForAuthority(
57426
57408
  settleOnce,
57427
57409
  );
57428
57410
  if (settlement.failure !== null) {
57411
+ if (settlement.physicallySettled && ownsCommit) {
57412
+ // This branch is reached only after the transaction committed a matching
57413
+ // terminal admission. A failed commit or contradictory receipt never
57414
+ // reaches it, even when the provider returned successfully.
57415
+ throw new SandboxWorkspaceMutationOutputRejectedError(settlement.failure, settlement.detail, {
57416
+ accountId: authorityInput.accountId,
57417
+ workspaceId: authorityInput.workspaceId,
57418
+ admission: admissionSnapshot,
57419
+ operation,
57420
+ outcome: "resolved",
57421
+ });
57422
+ }
57429
57423
  throw new SandboxWorkspaceMutationFencedError(settlement.failure, settlement.detail);
57430
57424
  }
57431
57425
  }
@@ -87622,67 +87616,6 @@ function projectInstallationConfig(config: Record<string, unknown>): Record<stri
87622
87616
  return { ...rest, headerNames: Object.keys(headersEncrypted).sort() };
87623
87617
  }
87624
87618
 
87625
- function mapConnectionMetadata(row: {
87626
- id: string;
87627
- authorityId?: string | null;
87628
- authorityGeneration: number;
87629
- accountId: string;
87630
- workspaceId: string;
87631
- subjectId: string | null;
87632
- providerDomain: string;
87633
- kind: string;
87634
- status: string;
87635
- grantedScopes: string[];
87636
- expiresAt: Date | null;
87637
- lastRefreshAt: Date | null;
87638
- lastUsedAt: Date | null;
87639
- lastError: string | null;
87640
- version: number;
87641
- verifiedInstallAt: Date | null;
87642
- verifiedInstallVersion: number | null;
87643
- metadata: Record<string, unknown>;
87644
- createdBySubjectId: string | null;
87645
- updatedBySubjectId: string | null;
87646
- createdAt: Date;
87647
- updatedAt: Date;
87648
- }): ConnectionMetadataWithVerification {
87649
- const {
87650
- [OPENROUTER_CREDENTIAL_OPERATION_ID_METADATA_KEY]: _openRouterOperationId,
87651
- [OPENROUTER_CREDENTIAL_OPERATION_DIGEST_METADATA_KEY]: _openRouterOperationDigest,
87652
- [VERCEL_AI_GATEWAY_CREDENTIAL_OPERATION_ID_METADATA_KEY]: _operationId,
87653
- [VERCEL_AI_GATEWAY_CREDENTIAL_OPERATION_DIGEST_METADATA_KEY]: _operationDigest,
87654
- anthropicCredentialOperationId: _anthropicOperationId,
87655
- anthropicCredentialOperationDigest: _anthropicOperationDigest,
87656
- claude_subscriptionCredentialOperationId: _claudeOperationId,
87657
- claude_subscriptionCredentialOperationDigest: _claudeOperationDigest,
87658
- ...publicMetadata
87659
- } = row.metadata;
87660
- return {
87661
- id: row.id,
87662
- ...(row.subjectId !== null && row.authorityId ? { authorityId: row.authorityId } : {}),
87663
- connectionAuthorityGeneration: row.authorityGeneration,
87664
- accountId: row.accountId,
87665
- workspaceId: row.workspaceId,
87666
- subjectId: row.subjectId,
87667
- providerDomain: row.providerDomain,
87668
- kind: row.kind as ConnectionKind,
87669
- status: row.status as ConnectionStatus,
87670
- grantedScopes: row.grantedScopes,
87671
- expiresAt: row.expiresAt?.toISOString() ?? null,
87672
- lastRefreshAt: row.lastRefreshAt?.toISOString() ?? null,
87673
- lastUsedAt: row.lastUsedAt?.toISOString() ?? null,
87674
- lastError: row.lastError,
87675
- version: row.version,
87676
- verifiedInstallAt: row.verifiedInstallAt?.toISOString() ?? null,
87677
- verifiedInstallVersion: row.verifiedInstallVersion,
87678
- metadata: publicMetadata,
87679
- createdBySubjectId: row.createdBySubjectId,
87680
- updatedBySubjectId: row.updatedBySubjectId,
87681
- createdAt: row.createdAt.toISOString(),
87682
- updatedAt: row.updatedAt.toISOString(),
87683
- };
87684
- }
87685
-
87686
87619
  function mapSlackBotPostOperation(
87687
87620
  row: typeof schema.slackBotPostOperations.$inferSelect,
87688
87621
  ): SlackBotPostOperation {
@@ -331,7 +331,8 @@ export async function readInsightsUsage(
331
331
  ||jsonb_strip_nulls(jsonb_build_object(
332
332
  'provider',case when ${query.groupBy} in ('model','provider') then provider end,
333
333
  'model',case when ${query.groupBy}='model' then model end,
334
- 'workspaceId',case when ${query.groupBy}='workspace' then workspace_id end,
334
+ 'workspaceId',case when ${query.groupBy}='workspace'
335
+ or (${query.groupBy}='rootSession' and kind='item') then workspace_id end,
335
336
  'you',case when ${query.groupBy}='person' or kind='personal' then you end))
336
337
  order by (measures->>'chargedMicros')::bigint+(measures->>'listMicros')::bigint desc,key) from selected_groups),'[]'::jsonb),
337
338
  'series',coalesce((select jsonb_agg(jsonb_build_object('start',points.start,'measures',coalesce(buckets.measures,zero.measures))