@opengeni/db 0.31.1 → 0.36.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 (122) hide show
  1. package/dist/browser-auth.d.ts +209 -1
  2. package/dist/browser-downloads.d.ts +51 -0
  3. package/dist/browser-identities.d.ts +11 -2
  4. package/dist/browser-sessions.d.ts +83 -1
  5. package/dist/browser-state-artifacts.d.ts +75 -1
  6. package/dist/canonical-human-identities.d.ts +48 -0
  7. package/dist/canonical-human-identities.js +28 -0
  8. package/dist/canonical-human-identities.js.map +1 -0
  9. package/dist/capability-integrations.d.ts +8 -6
  10. package/dist/{chunk-MWDVXQOL.js → chunk-5KTIEDX7.js} +5773 -4212
  11. package/dist/chunk-5KTIEDX7.js.map +1 -0
  12. package/dist/{chunk-NBE6CHRI.js → chunk-CQZ4QSP5.js} +49 -9
  13. package/dist/chunk-CQZ4QSP5.js.map +1 -0
  14. package/dist/chunk-F32YT7MP.js +117 -0
  15. package/dist/chunk-F32YT7MP.js.map +1 -0
  16. package/dist/{chunk-ISI2TIUG.js → chunk-JC5QPLUM.js} +30 -3
  17. package/dist/chunk-JC5QPLUM.js.map +1 -0
  18. package/dist/{chunk-F5FT7BEZ.js → chunk-P3RE4D2B.js} +2 -2
  19. package/dist/chunk-TAUTWOS5.js +259 -0
  20. package/dist/chunk-TAUTWOS5.js.map +1 -0
  21. package/dist/{chunk-YHZXQ7HP.js → chunk-VKLB2ZGI.js} +446 -19
  22. package/dist/chunk-VKLB2ZGI.js.map +1 -0
  23. package/dist/database.d.ts +5 -0
  24. package/dist/editable-artifact-durable-export.js +2 -2
  25. package/dist/editable-artifacts.js +3 -3
  26. package/dist/index.d.ts +438 -29
  27. package/dist/index.js +35640 -28969
  28. package/dist/index.js.map +1 -1
  29. package/dist/insights.d.ts +23 -7
  30. package/dist/integration-bindings.d.ts +24 -24
  31. package/dist/integration-facets.d.ts +99 -0
  32. package/dist/interaction-revisions.d.ts +11 -0
  33. package/dist/interaction-schema.d.ts +698 -34
  34. package/dist/provision-roles.js +1 -1
  35. package/dist/runtime-posture.d.ts +8 -7
  36. package/dist/schema.d.ts +9464 -5412
  37. package/dist/schema.js +51 -9
  38. package/dist/session-control.d.ts +29 -3
  39. package/dist/session-tenancy.d.ts +44 -0
  40. package/dist/session-tenancy.js +16 -0
  41. package/dist/session-tenancy.js.map +1 -0
  42. package/dist/slack-task-policy-schema.d.ts +847 -0
  43. package/dist/slack-task-policy.d.ts +65 -0
  44. package/dist/task-notes-schema.d.ts +924 -0
  45. package/dist/task-notes.d.ts +85 -0
  46. package/dist/video-generation.d.ts +9 -0
  47. package/dist/video-generation.js +5 -3
  48. package/dist/xai-subscription.d.ts +326 -0
  49. package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
  50. package/drizzle/0213_browser_interaction_authority.sql +67 -0
  51. package/drizzle/0214_browser_download_saves.sql +34 -0
  52. package/drizzle/0215_browser_controller_host.sql +385 -0
  53. package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
  54. package/drizzle/0217_external_browser_auth_operations.sql +22 -0
  55. package/drizzle/0218_organization_tenancy_foundation.sql +299 -0
  56. package/drizzle/0219_organization_tenancy_managed_human_provisioning.sql +317 -0
  57. package/drizzle/0219_site_auth_maintenance_sessions.sql +234 -0
  58. package/drizzle/0220_memory_slack_append_only_cascade.sql +38 -0
  59. package/drizzle/0220_session_channels.sql +54 -0
  60. package/drizzle/0221_sessions_channel_index.sql +5 -0
  61. package/drizzle/0222_session_visibility_authority_epochs.sql +158 -0
  62. package/drizzle/0222_sessions_channel_fk.sql +89 -0
  63. package/drizzle/0223_pending_tool_event_output.sql +55 -0
  64. package/drizzle/0223_sessions_channel_fk_validate.sql +118 -0
  65. package/drizzle/0224_slack_post_outcome_reconciliation.sql +123 -0
  66. package/drizzle/0225_session_visibility_fork_activation.sql +1363 -0
  67. package/drizzle/0226_personal_codex_authority_foundation.sql +365 -0
  68. package/drizzle/0227_slack_native_actions.sql +145 -0
  69. package/drizzle/0228_interaction_controller_data_plane.sql +14 -0
  70. package/drizzle/0228_slack_task_policy.sql +400 -0
  71. package/drizzle/0229_slack_inbox_file_fact.sql +10 -0
  72. package/drizzle/0230_user_scoped_variable_sets_rigs.sql +84 -0
  73. package/drizzle/0231_integration_definition_identity_cutover.sql +271 -0
  74. package/drizzle/0232_integration_facet_authority_cutover.sql +610 -0
  75. package/drizzle/0233_skill_and_integration_authority_cutover.sql +1162 -0
  76. package/drizzle/0234_xai_subscription_authority.sql +1139 -0
  77. package/drizzle/0235_canonical_human_login_bindings.sql +920 -0
  78. package/drizzle/0236_browser_identity_lifecycle.sql +39 -0
  79. package/drizzle/0236_session_visibility_slack_policy.sql +72 -0
  80. package/drizzle/0237_interaction_transition_reaper.sql +263 -0
  81. package/drizzle/0238_goal_persistence_policy.sql +471 -0
  82. package/drizzle/0238_supergrok_realtime_model.sql +29 -0
  83. package/drizzle/0239_supergrok_video_funding.sql +50 -0
  84. package/drizzle/0239_task_tree_notes.sql +990 -0
  85. package/package.json +13 -5
  86. package/src/browser-auth.ts +2600 -123
  87. package/src/browser-downloads.ts +517 -0
  88. package/src/browser-identities.ts +220 -3
  89. package/src/browser-sessions.ts +334 -45
  90. package/src/browser-state-artifacts.ts +402 -12
  91. package/src/canonical-human-identities.ts +317 -0
  92. package/src/capability-integrations.ts +121 -213
  93. package/src/database.ts +41 -1
  94. package/src/index.ts +4157 -394
  95. package/src/insights.ts +109 -28
  96. package/src/integration-bindings.ts +101 -101
  97. package/src/{integration-features.ts → integration-facets.ts} +187 -184
  98. package/src/interaction-revisions.ts +33 -3
  99. package/src/interaction-schema.ts +311 -8
  100. package/src/pack-components.ts +43 -43
  101. package/src/pack-installations.ts +0 -43
  102. package/src/plugin-packages.ts +9 -9
  103. package/src/provision-roles.ts +232 -0
  104. package/src/runtime-posture.ts +227 -14
  105. package/src/schema.ts +1188 -75
  106. package/src/session-control.ts +122 -37
  107. package/src/session-queue-commands.ts +78 -1
  108. package/src/session-tenancy.ts +188 -0
  109. package/src/session-tool-call-settlement.ts +9 -3
  110. package/src/slack-task-policy-schema.ts +130 -0
  111. package/src/slack-task-policy.ts +341 -0
  112. package/src/task-notes-schema.ts +135 -0
  113. package/src/task-notes.ts +178 -0
  114. package/src/video-generation.ts +90 -12
  115. package/src/workspace-artifacts.ts +1 -1
  116. package/src/xai-subscription.ts +1887 -0
  117. package/dist/chunk-ISI2TIUG.js.map +0 -1
  118. package/dist/chunk-MWDVXQOL.js.map +0 -1
  119. package/dist/chunk-NBE6CHRI.js.map +0 -1
  120. package/dist/chunk-YHZXQ7HP.js.map +0 -1
  121. package/dist/integration-features.d.ts +0 -99
  122. /package/dist/{chunk-F5FT7BEZ.js.map → chunk-P3RE4D2B.js.map} +0 -0
package/src/schema.ts CHANGED
@@ -7,9 +7,14 @@ import type {
7
7
  McpServerConnectionRef,
8
8
  RigProviderImages,
9
9
  SessionMcpApprovalPolicy,
10
+ SessionGoalChangeKind,
11
+ SessionGoalMutationPolicy,
12
+ SessionGoalSnapshot,
10
13
  SlackUserLinkAccessRequest,
11
14
  TimelineAnnotation,
15
+ XaiProviderAccountAuthoritySnapshotV1,
12
16
  } from "@opengeni/contracts";
17
+ import { WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1 } from "@opengeni/contracts";
13
18
  import { sql } from "drizzle-orm";
14
19
  import type { SessionToolPolicy } from "@opengeni/contracts";
15
20
  import type { HumanInputQuestion, HumanInputResponse } from "@opengeni/contracts";
@@ -420,6 +425,165 @@ export const workspaceMemberships = pgTable(
420
425
  }),
421
426
  );
422
427
 
428
+ // Organization membership is distinct from workspace access. `account_id` is
429
+ // the physical organization identifier; `personal_workspace_id` is lifecycle
430
+ // metadata only and never the ownership anchor for user resources.
431
+ export const organizationMemberships = pgTable(
432
+ "organization_memberships",
433
+ {
434
+ id: uuid("id").primaryKey().defaultRandom(),
435
+ accountId: uuid("account_id")
436
+ .notNull()
437
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
438
+ subjectId: text("subject_id").notNull(),
439
+ status: text("status").notNull().default("provisioning"),
440
+ personalWorkspaceId: uuid("personal_workspace_id"),
441
+ authorizationRevision: bigint("authorization_revision", { mode: "number" })
442
+ .notNull()
443
+ .default(1),
444
+ revokedAt: timestamp("revoked_at", { withTimezone: true }),
445
+ personalRetentionUntil: timestamp("personal_retention_until", {
446
+ withTimezone: true,
447
+ }),
448
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
449
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
450
+ },
451
+ (table) => ({
452
+ accountIdentity: uniqueIndex("organization_memberships_id_account_idx").on(
453
+ table.id,
454
+ table.accountId,
455
+ ),
456
+ accountSubject: uniqueIndex("organization_memberships_account_subject_idx").on(
457
+ table.accountId,
458
+ table.subjectId,
459
+ ),
460
+ personalWorkspace: uniqueIndex("organization_memberships_personal_workspace_idx")
461
+ .on(table.accountId, table.personalWorkspaceId)
462
+ .where(sql`${table.personalWorkspaceId} is not null`),
463
+ personalWorkspaceAccount: foreignKey({
464
+ name: "organization_memberships_personal_workspace_account_fk",
465
+ columns: [table.personalWorkspaceId, table.accountId],
466
+ foreignColumns: [workspaces.id, workspaces.accountId],
467
+ }).onDelete("restrict"),
468
+ statusValid: check(
469
+ "organization_memberships_status_check",
470
+ sql`${table.status} in ('provisioning', 'active', 'suspended', 'revoked')`,
471
+ ),
472
+ activePersonalWorkspace: check(
473
+ "organization_memberships_active_personal_workspace_check",
474
+ sql`${table.status} <> 'active' or ${table.personalWorkspaceId} is not null`,
475
+ ),
476
+ subjectValid: check(
477
+ "organization_memberships_subject_check",
478
+ sql`length(btrim(${table.subjectId})) between 1 and 1024`,
479
+ ),
480
+ revisionValid: check(
481
+ "organization_memberships_revision_check",
482
+ sql`${table.authorizationRevision} > 0`,
483
+ ),
484
+ revocationValid: check(
485
+ "organization_memberships_revocation_check",
486
+ sql`(${table.status} = 'revoked' and ${table.revokedAt} is not null)
487
+ or (${table.status} <> 'revoked' and ${table.revokedAt} is null)`,
488
+ ),
489
+ }),
490
+ );
491
+
492
+ export const organizationUserRetentionPolicies = pgTable(
493
+ "organization_user_retention_policies",
494
+ {
495
+ accountId: uuid("account_id")
496
+ .primaryKey()
497
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
498
+ mode: text("mode").notNull().default("retain"),
499
+ retentionDays: integer("retention_days"),
500
+ version: bigint("version", { mode: "number" }).notNull().default(1),
501
+ updatedByMembershipId: uuid("updated_by_membership_id"),
502
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
503
+ },
504
+ (table) => ({
505
+ updater: foreignKey({
506
+ name: "organization_user_retention_policies_updater_fk",
507
+ columns: [table.updatedByMembershipId, table.accountId],
508
+ foreignColumns: [organizationMemberships.id, organizationMemberships.accountId],
509
+ }).onDelete("restrict"),
510
+ modeValid: check(
511
+ "organization_user_retention_policies_mode_check",
512
+ sql`${table.mode} in ('retain', 'delete_after')`,
513
+ ),
514
+ durationValid: check(
515
+ "organization_user_retention_policies_duration_check",
516
+ sql`(${table.mode} = 'retain' and ${table.retentionDays} is null)
517
+ or (
518
+ ${table.mode} = 'delete_after'
519
+ and ${table.retentionDays} is not null
520
+ and ${table.retentionDays} between 1 and 3650
521
+ )`,
522
+ ),
523
+ versionValid: check(
524
+ "organization_user_retention_policies_version_check",
525
+ sql`${table.version} > 0`,
526
+ ),
527
+ }),
528
+ );
529
+
530
+ export const organizationUserResourceAuthorities = pgTable(
531
+ "organization_user_resource_authorities",
532
+ {
533
+ id: uuid("id").primaryKey().defaultRandom(),
534
+ accountId: uuid("account_id")
535
+ .notNull()
536
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
537
+ organizationMembershipId: uuid("organization_membership_id").notNull(),
538
+ resourceKind: text("resource_kind").notNull(),
539
+ resourceId: uuid("resource_id").notNull(),
540
+ // Provenance only. The migration owns a composite same-organization FK
541
+ // whose delete action clears only this column, never account_id.
542
+ originWorkspaceId: uuid("origin_workspace_id"),
543
+ generation: bigint("generation", { mode: "number" }).notNull().default(1),
544
+ status: text("status").notNull().default("active"),
545
+ revokedAt: timestamp("revoked_at", { withTimezone: true }),
546
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
547
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
548
+ },
549
+ (table) => ({
550
+ accountIdentity: uniqueIndex("organization_user_resource_authorities_id_account_idx").on(
551
+ table.id,
552
+ table.accountId,
553
+ ),
554
+ accountMembershipIdentity: uniqueIndex(
555
+ "organization_user_resource_authorities_id_account_membership_idx",
556
+ ).on(table.id, table.accountId, table.organizationMembershipId),
557
+ resourceIdentity: uniqueIndex(
558
+ "organization_user_resource_authorities_resource_identity_idx",
559
+ ).on(table.accountId, table.organizationMembershipId, table.resourceKind, table.resourceId),
560
+ membership: foreignKey({
561
+ name: "organization_user_resource_authorities_membership_fk",
562
+ columns: [table.organizationMembershipId, table.accountId],
563
+ foreignColumns: [organizationMemberships.id, organizationMemberships.accountId],
564
+ }).onDelete("restrict"),
565
+ resourceKindValid: check(
566
+ "organization_user_resource_authorities_kind_check",
567
+ sql`${table.resourceKind} = lower(btrim(${table.resourceKind}))
568
+ and length(${table.resourceKind}) between 1 and 64
569
+ and ${table.resourceKind} ~ '^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$'`,
570
+ ),
571
+ generationValid: check(
572
+ "organization_user_resource_authorities_generation_check",
573
+ sql`${table.generation} > 0`,
574
+ ),
575
+ statusValid: check(
576
+ "organization_user_resource_authorities_status_check",
577
+ sql`${table.status} in ('active', 'retained', 'revoked')`,
578
+ ),
579
+ revocationValid: check(
580
+ "organization_user_resource_authorities_revocation_check",
581
+ sql`(${table.status} = 'revoked' and ${table.revokedAt} is not null)
582
+ or (${table.status} <> 'revoked' and ${table.revokedAt} is null)`,
583
+ ),
584
+ }),
585
+ );
586
+
423
587
  export const apiKeys = pgTable(
424
588
  "api_keys",
425
589
  {
@@ -460,6 +624,13 @@ export const workspaceVariableSets = pgTable(
460
624
  .references(() => workspaces.id, { onDelete: "cascade" }),
461
625
  name: text("name").notNull(),
462
626
  description: text("description"),
627
+ // Migration 0230 is schema-only: all shipped CRUD continues to omit these
628
+ // fields and therefore remains workspace-scoped. A later activation slice
629
+ // must provide the complete owner authority and runtime protocol.
630
+ authorityScope: text("authority_scope").notNull().default("workspace"),
631
+ authorityId: uuid("authority_id"),
632
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
633
+ originWorkspaceId: uuid("origin_workspace_id"),
463
634
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
464
635
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
465
636
  },
@@ -472,6 +643,33 @@ export const workspaceVariableSets = pgTable(
472
643
  table.workspaceId,
473
644
  table.createdAt,
474
645
  ),
646
+ authorityShape: check(
647
+ "workspace_variable_sets_authority_shape_check",
648
+ sql`(
649
+ ${table.authorityScope} = 'workspace'
650
+ and ${table.authorityId} is null
651
+ and ${table.ownerOrganizationMembershipId} is null
652
+ ) or (
653
+ ${table.authorityScope} = 'user'
654
+ and ${table.authorityId} is not null
655
+ and ${table.ownerOrganizationMembershipId} is not null
656
+ )`,
657
+ ),
658
+ authorityScopeValid: check(
659
+ "workspace_variable_sets_authority_scope_check",
660
+ sql`${table.authorityScope} in ('workspace', 'user')`,
661
+ ),
662
+ authority: foreignKey({
663
+ name: "workspace_variable_sets_authority_fk",
664
+ columns: [table.authorityId, table.accountId, table.ownerOrganizationMembershipId],
665
+ foreignColumns: [
666
+ organizationUserResourceAuthorities.id,
667
+ organizationUserResourceAuthorities.accountId,
668
+ organizationUserResourceAuthorities.organizationMembershipId,
669
+ ],
670
+ }).onDelete("restrict"),
671
+ // PostgreSQL's column-subset SET NULL action preserves account_id; Drizzle
672
+ // cannot represent that action, so migration 0230 owns the origin FK.
475
673
  }),
476
674
  );
477
675
 
@@ -559,12 +757,16 @@ export const codexSubscriptionCredentials = pgTable(
559
757
  // continues to own `version`; quota/cache writes own neither counter.
560
758
  allocatorVersion: integer("allocator_version").notNull().default(1),
561
759
  allocatorUpdatedBySubjectId: text("allocator_updated_by_subject_id"),
562
- allocatorUpdatedAt: timestamp("allocator_updated_at", { withTimezone: true }),
760
+ allocatorUpdatedAt: timestamp("allocator_updated_at", {
761
+ withTimezone: true,
762
+ }),
563
763
  // Authoritative count-only summary cached from /wham/usage. Detailed rows
564
764
  // are never persisted as redemption authority; every first POST preflights
565
765
  // the provider's fresh detail endpoint.
566
766
  resetCreditAvailableCount: integer("reset_credit_available_count"),
567
- resetCreditsCheckedAt: timestamp("reset_credits_checked_at", { withTimezone: true }),
767
+ resetCreditsCheckedAt: timestamp("reset_credits_checked_at", {
768
+ withTimezone: true,
769
+ }),
568
770
  // Set only by a direct Better Auth cookie connection/reconnection. Legacy,
569
771
  // configured, delegated, API-key, and agent-created rows remain view-only.
570
772
  connectedBySubjectId: text("connected_by_subject_id"),
@@ -662,7 +864,9 @@ export const codexResetRedemptionAttempts = pgTable(
662
864
  outcome: text("outcome"),
663
865
  claimHolderId: uuid("claim_holder_id"),
664
866
  claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
665
- confirmationExpiresAt: timestamp("confirmation_expires_at", { withTimezone: true }).notNull(),
867
+ confirmationExpiresAt: timestamp("confirmation_expires_at", {
868
+ withTimezone: true,
869
+ }).notNull(),
666
870
  providerStartedAt: timestamp("provider_started_at", { withTimezone: true }),
667
871
  completedAt: timestamp("completed_at", { withTimezone: true }),
668
872
  lastFailureKind: text("last_failure_kind"),
@@ -1143,10 +1347,17 @@ export const slackInteractionInbox = pgTable(
1143
1347
  slackThreadTs: text("slack_thread_ts"),
1144
1348
  triggerKind: text("trigger_kind")
1145
1349
  .$type<
1146
- "app_mention" | "dm" | "reaction" | "slash_command" | "message_shortcut" | "thread_reply"
1350
+ | "app_mention"
1351
+ | "dm"
1352
+ | "reaction"
1353
+ | "slash_command"
1354
+ | "message_shortcut"
1355
+ | "thread_reply"
1356
+ | "block_action"
1147
1357
  >()
1148
1358
  .notNull(),
1149
1359
  text: text("text").notNull(),
1360
+ hasFiles: boolean("has_files").notNull().default(false),
1150
1361
  status: text("status")
1151
1362
  .$type<"pending" | "processing" | "processed" | "failed">()
1152
1363
  .notNull()
@@ -1197,6 +1408,7 @@ export const slackInteractions = pgTable(
1197
1408
  slackThreadTs: text("slack_thread_ts").notNull(),
1198
1409
  routeKey: text("route_key").notNull(),
1199
1410
  triggeringProviderEventId: text("triggering_provider_event_id").notNull(),
1411
+ initiatingSlackUserId: text("initiating_slack_user_id"),
1200
1412
  owningSubjectId: text("owning_subject_id").notNull(),
1201
1413
  visibility: text("visibility").$type<"private" | "workspace">().notNull(),
1202
1414
  sessionReservationId: uuid("session_reservation_id").notNull().defaultRandom(),
@@ -1245,6 +1457,73 @@ export const slackInteractions = pgTable(
1245
1457
  }),
1246
1458
  );
1247
1459
 
1460
+ export const slackInteractionActionHandles = pgTable(
1461
+ "slack_interaction_action_handles",
1462
+ {
1463
+ id: uuid("id").primaryKey().defaultRandom(),
1464
+ accountId: uuid("account_id")
1465
+ .notNull()
1466
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
1467
+ workspaceId: uuid("workspace_id")
1468
+ .notNull()
1469
+ .references(() => workspaces.id, { onDelete: "cascade" }),
1470
+ connectionId: uuid("connection_id")
1471
+ .notNull()
1472
+ .references(() => connections.id, { onDelete: "cascade" }),
1473
+ interactionId: uuid("interaction_id").notNull(),
1474
+ sessionId: uuid("session_id")
1475
+ .notNull()
1476
+ .references(() => sessions.id, { onDelete: "cascade" }),
1477
+ sessionEventSequence: integer("session_event_sequence").notNull(),
1478
+ actionKind: text("action_kind")
1479
+ .$type<
1480
+ | "approval_approve"
1481
+ | "approval_reject"
1482
+ | "human_input_select"
1483
+ | "human_input_skip"
1484
+ | "session_status"
1485
+ | "session_pause"
1486
+ | "session_resume"
1487
+ | "shared_result_publish"
1488
+ >()
1489
+ .notNull(),
1490
+ actionKey: text("action_key").notNull(),
1491
+ targetId: text("target_id"),
1492
+ targetValue: text("target_value"),
1493
+ authorizedSubjectId: text("authorized_subject_id").notNull(),
1494
+ authorizedSlackUserId: text("authorized_slack_user_id").notNull(),
1495
+ messageOperationId: uuid("message_operation_id").notNull(),
1496
+ status: text("status").$type<"pending" | "completed" | "stale">().notNull().default("pending"),
1497
+ result: text("result"),
1498
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
1499
+ completedAt: timestamp("completed_at", { withTimezone: true }),
1500
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1501
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
1502
+ },
1503
+ (table) => ({
1504
+ interactionIdentity: foreignKey({
1505
+ columns: [table.accountId, table.workspaceId, table.interactionId],
1506
+ foreignColumns: [
1507
+ slackInteractions.accountId,
1508
+ slackInteractions.workspaceId,
1509
+ slackInteractions.id,
1510
+ ],
1511
+ name: "slack_interaction_action_handles_interaction_fk",
1512
+ }).onDelete("cascade"),
1513
+ identity: uniqueIndex("slack_interaction_action_handles_identity_uq").on(
1514
+ table.interactionId,
1515
+ table.sessionEventSequence,
1516
+ table.actionKey,
1517
+ ),
1518
+ pending: index("slack_interaction_action_handles_pending_idx").on(
1519
+ table.workspaceId,
1520
+ table.status,
1521
+ table.expiresAt,
1522
+ table.id,
1523
+ ),
1524
+ }),
1525
+ );
1526
+
1248
1527
  export const slackInteractionProgressDeliveries = pgTable(
1249
1528
  "slack_interaction_progress_deliveries",
1250
1529
  {
@@ -1287,9 +1566,9 @@ export const slackInteractionProgressDeliveries = pgTable(
1287
1566
  );
1288
1567
 
1289
1568
  // Durable provider-operation identity for OpenGeni Slack bot posts. The
1290
- // caller-supplied operation UUID is also Slack's client_msg_id; a bounded claim
1291
- // serializes live attempts while an expired/released claim can safely retry the
1292
- // same provider identity after response loss or process death.
1569
+ // server-owned durable operation UUID is also Slack's client_msg_id. `pending` is
1570
+ // safe to send, `provider_started` and `outcome_unknown` require provider read
1571
+ // reconciliation, and only `completed` may expose the provider result.
1293
1572
  export const slackBotPostOperations = pgTable(
1294
1573
  "slack_bot_post_operations",
1295
1574
  {
@@ -1308,9 +1587,12 @@ export const slackBotPostOperations = pgTable(
1308
1587
  targetKind: text("target_kind").$type<"channel" | "user">().notNull(),
1309
1588
  targetId: text("target_id").notNull(),
1310
1589
  requestDigest: text("request_digest").notNull(),
1311
- status: text("status").$type<"provider_started" | "completed">().notNull(),
1590
+ status: text("status")
1591
+ .$type<"pending" | "provider_started" | "outcome_unknown" | "completed">()
1592
+ .notNull(),
1312
1593
  claimHolderId: uuid("claim_holder_id"),
1313
1594
  claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
1595
+ claimMode: text("claim_mode").$type<"send" | "reconcile">(),
1314
1596
  attemptCount: integer("attempt_count").notNull().default(0),
1315
1597
  lastFailureCode: text("last_failure_code"),
1316
1598
  slackChannelId: text("slack_channel_id"),
@@ -1336,7 +1618,7 @@ export const slackBotPostOperations = pgTable(
1336
1618
  ),
1337
1619
  statusValid: check(
1338
1620
  "slack_bot_post_operations_status_check",
1339
- sql`${table.status} in ('provider_started', 'completed')`,
1621
+ sql`${table.status} in ('pending', 'provider_started', 'outcome_unknown', 'completed')`,
1340
1622
  ),
1341
1623
  identityValid: check(
1342
1624
  "slack_bot_post_operations_identity_check",
@@ -1344,12 +1626,26 @@ export const slackBotPostOperations = pgTable(
1344
1626
  and length(${table.targetId}) between 1 and 64
1345
1627
  and ${table.requestDigest} ~ '^[0-9a-f]{64}$'
1346
1628
  and ${table.attemptCount} > 0
1347
- and ((${table.claimHolderId} is null) = (${table.claimExpiresAt} is null))`,
1629
+ and (
1630
+ (
1631
+ ${table.claimHolderId} is null
1632
+ and ${table.claimExpiresAt} is null
1633
+ and ${table.claimMode} is null
1634
+ )
1635
+ or (
1636
+ ${table.claimHolderId} is not null
1637
+ and ${table.claimExpiresAt} is not null
1638
+ and (
1639
+ (${table.claimMode} = 'send' and ${table.status} in ('pending', 'provider_started'))
1640
+ or (${table.claimMode} = 'reconcile' and ${table.status} = 'outcome_unknown')
1641
+ )
1642
+ )
1643
+ )`,
1348
1644
  ),
1349
1645
  completionValid: check(
1350
1646
  "slack_bot_post_operations_completion_check",
1351
1647
  sql`(
1352
- ${table.status} = 'provider_started'
1648
+ ${table.status} <> 'completed'
1353
1649
  and ${table.slackChannelId} is null
1354
1650
  and ${table.slackMessageTimestamp} is null
1355
1651
  and ${table.completedAt} is null
@@ -1365,6 +1661,46 @@ export const slackBotPostOperations = pgTable(
1365
1661
  }),
1366
1662
  );
1367
1663
 
1664
+ export const slackBotUpdateOperations = pgTable(
1665
+ "slack_bot_update_operations",
1666
+ {
1667
+ id: uuid("id").primaryKey().defaultRandom(),
1668
+ accountId: uuid("account_id")
1669
+ .notNull()
1670
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
1671
+ workspaceId: uuid("workspace_id")
1672
+ .notNull()
1673
+ .references(() => workspaces.id, { onDelete: "cascade" }),
1674
+ connectionId: uuid("connection_id")
1675
+ .notNull()
1676
+ .references(() => connections.id, { onDelete: "cascade" }),
1677
+ operationId: uuid("operation_id").notNull(),
1678
+ slackChannelId: text("slack_channel_id").notNull(),
1679
+ slackMessageTimestamp: text("slack_message_timestamp").notNull(),
1680
+ requestDigest: text("request_digest").notNull(),
1681
+ status: text("status").$type<"provider_started" | "completed">().notNull(),
1682
+ claimHolderId: uuid("claim_holder_id"),
1683
+ claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
1684
+ attemptCount: integer("attempt_count").notNull().default(0),
1685
+ lastFailureCode: text("last_failure_code"),
1686
+ completedAt: timestamp("completed_at", { withTimezone: true }),
1687
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
1688
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
1689
+ },
1690
+ (table) => ({
1691
+ workspaceOperation: uniqueIndex("slack_bot_update_operations_workspace_operation_uq").on(
1692
+ table.workspaceId,
1693
+ table.connectionId,
1694
+ table.operationId,
1695
+ ),
1696
+ workspaceStatus: index("slack_bot_update_operations_workspace_status_idx").on(
1697
+ table.workspaceId,
1698
+ table.status,
1699
+ table.updatedAt,
1700
+ ),
1701
+ }),
1702
+ );
1703
+
1368
1704
  export const memorySlackPublicationConfigurations = pgTable(
1369
1705
  "memory_slack_publication_configurations",
1370
1706
  {
@@ -1438,7 +1774,9 @@ export const memorySlackPublications = pgTable(
1438
1774
  .references(() => workspaces.id, { onDelete: "cascade" }),
1439
1775
  configurationId: uuid("configuration_id")
1440
1776
  .notNull()
1441
- .references(() => memorySlackPublicationConfigurations.id, { onDelete: "restrict" }),
1777
+ .references(() => memorySlackPublicationConfigurations.id, {
1778
+ onDelete: "restrict",
1779
+ }),
1442
1780
  configurationRevision: integer("configuration_revision").notNull(),
1443
1781
  connectionId: uuid("connection_id").notNull(),
1444
1782
  slackTeamId: text("slack_team_id").notNull(),
@@ -1901,6 +2239,218 @@ export const codexCredentialLeases = pgTable(
1901
2239
  }),
1902
2240
  );
1903
2241
 
2242
+ // Encrypted multi-account xAI/SuperGrok credentials. Provider tokens and
2243
+ // cookies live only inside credential_encrypted; every other column is bounded
2244
+ // allocation/health metadata. User-scoped rows are created only by the
2245
+ // migration-owned lifecycle function that also creates their exact generic
2246
+ // organization_user_resource_authorities row.
2247
+ export const xaiSubscriptionCredentials = pgTable(
2248
+ "xai_subscription_credentials",
2249
+ {
2250
+ id: uuid("id").primaryKey().defaultRandom(),
2251
+ accountId: uuid("account_id")
2252
+ .notNull()
2253
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2254
+ workspaceId: uuid("workspace_id")
2255
+ .notNull()
2256
+ .references(() => workspaces.id, { onDelete: "cascade" }),
2257
+ credentialEncrypted: text("credential_encrypted").notNull(),
2258
+ providerAccountId: text("provider_account_id"),
2259
+ label: text("label"),
2260
+ accountEmail: text("account_email"),
2261
+ planType: text("plan_type"),
2262
+ status: text("status").notNull().default("active"),
2263
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
2264
+ lastRefreshAt: timestamp("last_refresh_at", { withTimezone: true }),
2265
+ lastError: text("last_error"),
2266
+ version: integer("version").notNull().default(1),
2267
+ allocatorEnabled: boolean("allocator_enabled").notNull().default(true),
2268
+ allocatorVersion: integer("allocator_version").notNull().default(1),
2269
+ allocatorUpdatedAt: timestamp("allocator_updated_at", {
2270
+ withTimezone: true,
2271
+ }),
2272
+ quotaUsedPercent: integer("quota_used_percent"),
2273
+ quotaResetAt: timestamp("quota_reset_at", { withTimezone: true }),
2274
+ quotaCheckedAt: timestamp("quota_checked_at", { withTimezone: true }),
2275
+ exhaustedUntil: timestamp("exhausted_until", { withTimezone: true }),
2276
+ selectionCount: integer("selection_count").notNull().default(0),
2277
+ lastSelectedAt: timestamp("last_selected_at", { withTimezone: true }),
2278
+ authorityScope: text("authority_scope").notNull().default("workspace"),
2279
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
2280
+ organizationUserResourceAuthorityId: uuid("organization_user_resource_authority_id"),
2281
+ organizationUserResourceKind: text("organization_user_resource_kind"),
2282
+ organizationUserResourceAuthorityGeneration: bigint(
2283
+ "organization_user_resource_authority_generation",
2284
+ { mode: "number" },
2285
+ ),
2286
+ // Connection attribution only. Ownership/execution authority comes from
2287
+ // the explicit authority tuple above and the frozen acceptance snapshot.
2288
+ connectedBySubjectId: text("connected_by_subject_id"),
2289
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2290
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2291
+ },
2292
+ (table) => ({
2293
+ workspaceIdentity: uniqueIndex("xai_subscription_credentials_workspace_id_uq").on(
2294
+ table.workspaceId,
2295
+ table.id,
2296
+ ),
2297
+ workspaceAccountIdentity: uniqueIndex(
2298
+ "xai_subscription_credentials_workspace_account_id_uq",
2299
+ ).on(table.workspaceId, table.accountId, table.id),
2300
+ providerIdentity: uniqueIndex("xai_subscription_credentials_provider_identity_uq")
2301
+ .on(
2302
+ table.workspaceId,
2303
+ table.authorityScope,
2304
+ table.ownerOrganizationMembershipId,
2305
+ table.providerAccountId,
2306
+ )
2307
+ .where(sql`${table.providerAccountId} is not null`),
2308
+ workspaceStatus: index("xai_subscription_credentials_workspace_status_idx").on(
2309
+ table.workspaceId,
2310
+ table.status,
2311
+ table.allocatorEnabled,
2312
+ ),
2313
+ scopeValid: check(
2314
+ "xai_subscription_credentials_authority_scope_chk",
2315
+ sql`${table.authorityScope} in ('workspace', 'user')`,
2316
+ ),
2317
+ authorityShapeValid: check(
2318
+ "xai_subscription_credentials_authority_shape_chk",
2319
+ sql`(
2320
+ ${table.authorityScope} = 'workspace'
2321
+ and ${table.ownerOrganizationMembershipId} is null
2322
+ and ${table.organizationUserResourceAuthorityId} is null
2323
+ and ${table.organizationUserResourceKind} is null
2324
+ and ${table.organizationUserResourceAuthorityGeneration} is null
2325
+ ) or (
2326
+ ${table.authorityScope} = 'user'
2327
+ and ${table.ownerOrganizationMembershipId} is not null
2328
+ and ${table.organizationUserResourceAuthorityId} is not null
2329
+ and ${table.organizationUserResourceKind} = 'xai_subscription'
2330
+ and ${table.organizationUserResourceAuthorityGeneration} > 0
2331
+ )`,
2332
+ ),
2333
+ statusValid: check(
2334
+ "xai_subscription_credentials_status_chk",
2335
+ sql`${table.status} in ('active', 'needs_relogin', 'error', 'disabled')`,
2336
+ ),
2337
+ versionValid: check(
2338
+ "xai_subscription_credentials_version_chk",
2339
+ sql`${table.version} > 0 and ${table.allocatorVersion} > 0`,
2340
+ ),
2341
+ quotaValid: check(
2342
+ "xai_subscription_credentials_quota_chk",
2343
+ sql`${table.quotaUsedPercent} is null or ${table.quotaUsedPercent} between 0 and 100`,
2344
+ ),
2345
+ }),
2346
+ );
2347
+
2348
+ // One fair-allocation serialization row per workspace or exact user pool.
2349
+ export const xaiRotationSettings = pgTable(
2350
+ "xai_rotation_settings",
2351
+ {
2352
+ id: uuid("id").primaryKey().defaultRandom(),
2353
+ accountId: uuid("account_id")
2354
+ .notNull()
2355
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2356
+ workspaceId: uuid("workspace_id")
2357
+ .notNull()
2358
+ .references(() => workspaces.id, { onDelete: "cascade" }),
2359
+ authorityScope: text("authority_scope").notNull().default("workspace"),
2360
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
2361
+ activeCredentialId: uuid("active_credential_id"),
2362
+ rotationEnabled: boolean("rotation_enabled").notNull().default(true),
2363
+ fairnessCursor: bigint("fairness_cursor", { mode: "number" }).notNull().default(0),
2364
+ version: integer("version").notNull().default(1),
2365
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2366
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2367
+ },
2368
+ (table) => ({
2369
+ workspacePool: uniqueIndex("xai_rotation_settings_workspace_pool_uq").on(
2370
+ table.workspaceId,
2371
+ table.authorityScope,
2372
+ table.ownerOrganizationMembershipId,
2373
+ ),
2374
+ scopeValid: check(
2375
+ "xai_rotation_settings_authority_scope_chk",
2376
+ sql`(${table.authorityScope} = 'workspace' and ${table.ownerOrganizationMembershipId} is null)
2377
+ or (${table.authorityScope} = 'user' and ${table.ownerOrganizationMembershipId} is not null)`,
2378
+ ),
2379
+ countersValid: check(
2380
+ "xai_rotation_settings_counters_chk",
2381
+ sql`${table.fairnessCursor} >= 0 and ${table.version} > 0`,
2382
+ ),
2383
+ }),
2384
+ );
2385
+
2386
+ // Exact logical-turn lease. A replacement holder for the same turn preserves
2387
+ // the credential and advances generation; stale holders must match both.
2388
+ export const xaiCredentialLeases = pgTable(
2389
+ "xai_credential_leases",
2390
+ {
2391
+ id: uuid("id").primaryKey().defaultRandom(),
2392
+ accountId: uuid("account_id")
2393
+ .notNull()
2394
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2395
+ workspaceId: uuid("workspace_id")
2396
+ .notNull()
2397
+ .references(() => workspaces.id, { onDelete: "cascade" }),
2398
+ authorityScope: text("authority_scope").notNull(),
2399
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
2400
+ credentialId: uuid("credential_id").notNull(),
2401
+ turnId: uuid("turn_id").notNull(),
2402
+ holderId: text("holder_id").notNull(),
2403
+ generation: integer("generation").notNull().default(1),
2404
+ leasedUntil: timestamp("leased_until", { withTimezone: true }).notNull(),
2405
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2406
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2407
+ },
2408
+ (table) => ({
2409
+ workspaceTurn: uniqueIndex("xai_credential_leases_workspace_turn_uq").on(
2410
+ table.workspaceId,
2411
+ table.turnId,
2412
+ ),
2413
+ activeCredential: index("xai_credential_leases_active_credential_idx").on(
2414
+ table.workspaceId,
2415
+ table.credentialId,
2416
+ table.leasedUntil,
2417
+ ),
2418
+ expiry: index("xai_credential_leases_expiry_idx").on(table.leasedUntil),
2419
+ scopeValid: check(
2420
+ "xai_credential_leases_authority_scope_chk",
2421
+ sql`(${table.authorityScope} = 'workspace' and ${table.ownerOrganizationMembershipId} is null)
2422
+ or (${table.authorityScope} = 'user' and ${table.ownerOrganizationMembershipId} is not null)`,
2423
+ ),
2424
+ generationValid: check("xai_credential_leases_generation_chk", sql`${table.generation} > 0`),
2425
+ }),
2426
+ );
2427
+
2428
+ // Workspace-shared channels organize root sessions ("workstreams") by work
2429
+ // type in the rail. Pure organizational metadata: filing a session into a
2430
+ // channel never affects execution, authority, memory, or history.
2431
+ export const channels = pgTable(
2432
+ "channels",
2433
+ {
2434
+ id: uuid("id").primaryKey().defaultRandom(),
2435
+ accountId: uuid("account_id")
2436
+ .notNull()
2437
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2438
+ workspaceId: uuid("workspace_id")
2439
+ .notNull()
2440
+ .references(() => workspaces.id, { onDelete: "cascade" }),
2441
+ name: text("name").notNull(),
2442
+ description: text("description"),
2443
+ // Attribution string: 'user:<subject>' | 'session:<id>' | 'system'.
2444
+ createdBy: text("created_by"),
2445
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2446
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2447
+ },
2448
+ (table) => ({
2449
+ // The migration owns the case-insensitive lower(name) uniqueness.
2450
+ workspaceIdentity: uniqueIndex("channels_workspace_id_uq").on(table.workspaceId, table.id),
2451
+ }),
2452
+ );
2453
+
1904
2454
  export const sessions = pgTable(
1905
2455
  "sessions",
1906
2456
  {
@@ -1944,6 +2494,21 @@ export const sessions = pgTable(
1944
2494
  .$type<Record<string, unknown>>()
1945
2495
  .notNull()
1946
2496
  .default({ backfill: true }),
2497
+ // Generic tenancy metadata is additive foundation only. Existing rows are
2498
+ // explicitly workspace-shared and have no owner membership, so absent
2499
+ // fields can never manufacture user authority.
2500
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
2501
+ ownerSubjectId: text("owner_subject_id"),
2502
+ visibility: text("visibility").notNull().default("workspace_shared"),
2503
+ authorityEpoch: integer("authority_epoch").notNull().default(1),
2504
+ // Independent-copy provenance. A destination may use either visibility and
2505
+ // may live in another workspace in the same organization; no live process,
2506
+ // credential, grant, or delegation is represented by these facts.
2507
+ forkedFromSessionId: uuid("forked_from_session_id"),
2508
+ forkedFromAuthorityEpoch: integer("forked_from_authority_epoch"),
2509
+ forkedFromVisibility: text("forked_from_visibility"),
2510
+ forkedAt: timestamp("forked_at", { withTimezone: true }),
2511
+ forkedByOrganizationMembershipId: uuid("forked_by_organization_membership_id"),
1947
2512
  model: text("model").notNull(),
1948
2513
  sandboxBackend: text("sandbox_backend").notNull(),
1949
2514
  // The OS this session's box runs. Defaults to 'linux' (today's only OS, so
@@ -1992,6 +2557,12 @@ export const sessions = pgTable(
1992
2557
  // file (forward-reference pattern, same as activeSandboxId). Consumed in M3.
1993
2558
  rigId: uuid("rig_id"),
1994
2559
  rigVersionId: uuid("rig_version_id"),
2560
+ // Workspace channel this session is filed under (rail organization only;
2561
+ // the rail groups a tree by its ROOT session's channel). Null = unfiled
2562
+ // (inbox). ON DELETE SET NULL detaches sessions when a channel is removed.
2563
+ channelId: uuid("channel_id").references(() => channels.id, {
2564
+ onDelete: "set null",
2565
+ }),
1995
2566
  // Non-default first-party MCP token permissions (manager-style sessions);
1996
2567
  // null means the fixed worker default set in @opengeni/runtime.
1997
2568
  firstPartyMcpPermissions: jsonb("first_party_mcp_permissions").$type<string[]>(),
@@ -2006,6 +2577,12 @@ export const sessions = pgTable(
2006
2577
  .$type<McpPersonalConnectionDelegation[]>()
2007
2578
  .notNull()
2008
2579
  .default([]),
2580
+ initialXaiProviderAccountAuthoritySnapshot: jsonb(
2581
+ "initial_xai_provider_account_authority_snapshot",
2582
+ )
2583
+ .$type<XaiProviderAccountAuthoritySnapshotV1>()
2584
+ .notNull()
2585
+ .default(WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1),
2009
2586
  // Durable tool-policy origin. Migration 0136 removes the old null/legacy
2010
2587
  // representation so every session has one explicit policy mode.
2011
2588
  toolPolicy: jsonb("tool_policy").$type<SessionToolPolicy>().notNull(),
@@ -2094,9 +2671,12 @@ export const sessions = pgTable(
2094
2671
  activityRevision: bigint("activity_revision", { mode: "number" }).notNull().default(0),
2095
2672
  // Transaction ownership marker between the cheap row trigger and the
2096
2673
  // once-per-transaction commit gate. Committed rows must always be null.
2097
- activityRevisionPendingXid: bigint("activity_revision_pending_xid", { mode: "bigint" }),
2674
+ activityRevisionPendingXid: bigint("activity_revision_pending_xid", {
2675
+ mode: "bigint",
2676
+ }),
2098
2677
  },
2099
2678
  (table) => ({
2679
+ accountIdentity: uniqueIndex("sessions_id_account_idx").on(table.id, table.accountId),
2100
2680
  workspaceIdentity: uniqueIndex("sessions_workspace_id_idx").on(table.workspaceId, table.id),
2101
2681
  workspaceCreated: index("sessions_workspace_created_idx").on(
2102
2682
  table.workspaceId,
@@ -2124,6 +2704,47 @@ export const sessions = pgTable(
2124
2704
  workspaceActivityPending: index("sessions_workspace_activity_pending_idx")
2125
2705
  .on(table.workspaceId, table.activityRevisionPendingXid, table.id)
2126
2706
  .where(sql`${table.activityRevisionPendingXid} is not null`),
2707
+ ownerOrganizationMembership: foreignKey({
2708
+ name: "sessions_owner_organization_membership_fk",
2709
+ columns: [table.ownerOrganizationMembershipId, table.accountId],
2710
+ foreignColumns: [organizationMemberships.id, organizationMemberships.accountId],
2711
+ }).onDelete("restrict"),
2712
+ forkedFromSession: foreignKey({
2713
+ name: "sessions_forked_from_session_account_fk",
2714
+ columns: [table.forkedFromSessionId, table.accountId],
2715
+ foreignColumns: [table.id, table.accountId],
2716
+ }).onDelete("restrict"),
2717
+ forkedByOrganizationMembership: foreignKey({
2718
+ name: "sessions_forked_by_organization_membership_fk",
2719
+ columns: [table.forkedByOrganizationMembershipId, table.accountId],
2720
+ foreignColumns: [organizationMemberships.id, organizationMemberships.accountId],
2721
+ }).onDelete("restrict"),
2722
+ visibilityValid: check(
2723
+ "sessions_visibility_check",
2724
+ sql`${table.visibility} in ('user_private', 'workspace_shared')`,
2725
+ ),
2726
+ privateOwnerValid: check(
2727
+ "sessions_private_owner_check",
2728
+ sql`${table.visibility} <> 'user_private' or ${table.ownerOrganizationMembershipId} is not null`,
2729
+ ),
2730
+ authorityEpochValid: check("sessions_authority_epoch_check", sql`${table.authorityEpoch} > 0`),
2731
+ forkProvenanceValid: check(
2732
+ "sessions_fork_provenance_check",
2733
+ sql`(
2734
+ ${table.forkedFromSessionId} is null
2735
+ and ${table.forkedFromAuthorityEpoch} is null
2736
+ and ${table.forkedFromVisibility} is null
2737
+ and ${table.forkedAt} is null
2738
+ and ${table.forkedByOrganizationMembershipId} is null
2739
+ ) or (
2740
+ ${table.forkedFromSessionId} is not null
2741
+ and ${table.forkedFromAuthorityEpoch} is not null
2742
+ and ${table.forkedFromAuthorityEpoch} > 0
2743
+ and ${table.forkedFromVisibility} in ('user_private', 'workspace_shared')
2744
+ and ${table.forkedAt} is not null
2745
+ and ${table.forkedByOrganizationMembershipId} is not null
2746
+ )`,
2747
+ ),
2127
2748
  variableSet: index("sessions_variable_set_idx").on(table.workspaceId, table.variableSetId),
2128
2749
  parent: index("sessions_parent_idx").on(table.workspaceId, table.parentSessionId),
2129
2750
  // Routing index: resolve session_id -> sandbox_group_id at every lease entry
@@ -2144,6 +2765,114 @@ export const sessions = pgTable(
2144
2765
  }),
2145
2766
  );
2146
2767
 
2768
+ export const organizationUserResourceGrants = pgTable(
2769
+ "organization_user_resource_grants",
2770
+ {
2771
+ id: uuid("id").primaryKey().defaultRandom(),
2772
+ accountId: uuid("account_id")
2773
+ .notNull()
2774
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
2775
+ authorityId: uuid("authority_id").notNull(),
2776
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id").notNull(),
2777
+ workspaceId: uuid("workspace_id").notNull(),
2778
+ sessionId: uuid("session_id"),
2779
+ action: text("action").notNull(),
2780
+ mode: text("mode").notNull(),
2781
+ context: text("context").notNull(),
2782
+ authorityEpoch: integer("authority_epoch"),
2783
+ generation: bigint("generation", { mode: "number" }).notNull().default(1),
2784
+ status: text("status").notNull().default("active"),
2785
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
2786
+ revokedAt: timestamp("revoked_at", { withTimezone: true }),
2787
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2788
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2789
+ },
2790
+ (table) => ({
2791
+ accountIdentity: uniqueIndex("organization_user_resource_grants_id_account_idx").on(
2792
+ table.id,
2793
+ table.accountId,
2794
+ ),
2795
+ authorityWorkspace: index("organization_user_resource_grants_authority_workspace_idx").on(
2796
+ table.authorityId,
2797
+ table.workspaceId,
2798
+ table.status,
2799
+ ),
2800
+ authority: foreignKey({
2801
+ name: "organization_user_resource_grants_authority_fk",
2802
+ columns: [table.authorityId, table.accountId],
2803
+ foreignColumns: [
2804
+ organizationUserResourceAuthorities.id,
2805
+ organizationUserResourceAuthorities.accountId,
2806
+ ],
2807
+ }).onDelete("restrict"),
2808
+ ownerMembership: foreignKey({
2809
+ name: "organization_user_resource_grants_owner_membership_fk",
2810
+ columns: [table.ownerOrganizationMembershipId, table.accountId],
2811
+ foreignColumns: [organizationMemberships.id, organizationMemberships.accountId],
2812
+ }).onDelete("restrict"),
2813
+ authorityOwner: foreignKey({
2814
+ name: "organization_user_resource_grants_authority_owner_fk",
2815
+ columns: [table.authorityId, table.accountId, table.ownerOrganizationMembershipId],
2816
+ foreignColumns: [
2817
+ organizationUserResourceAuthorities.id,
2818
+ organizationUserResourceAuthorities.accountId,
2819
+ organizationUserResourceAuthorities.organizationMembershipId,
2820
+ ],
2821
+ }).onDelete("restrict"),
2822
+ workspaceAccount: foreignKey({
2823
+ name: "organization_user_resource_grants_workspace_account_fk",
2824
+ columns: [table.workspaceId, table.accountId],
2825
+ foreignColumns: [workspaces.id, workspaces.accountId],
2826
+ }).onDelete("cascade"),
2827
+ sessionWorkspace: foreignKey({
2828
+ name: "organization_user_resource_grants_session_workspace_fk",
2829
+ columns: [table.workspaceId, table.sessionId],
2830
+ foreignColumns: [sessions.workspaceId, sessions.id],
2831
+ }).onDelete("restrict"),
2832
+ actionValid: check(
2833
+ "organization_user_resource_grants_action_check",
2834
+ sql`${table.action} = lower(btrim(${table.action}))
2835
+ and length(${table.action}) between 1 and 64
2836
+ and ${table.action} ~ '^[a-z0-9](?:[a-z0-9._:-]*[a-z0-9])?$'`,
2837
+ ),
2838
+ modeValid: check(
2839
+ "organization_user_resource_grants_mode_check",
2840
+ sql`${table.mode} in ('once', 'session', 'always')`,
2841
+ ),
2842
+ contextValid: check(
2843
+ "organization_user_resource_grants_context_check",
2844
+ sql`${table.context} in ('user_private', 'workspace_shared')`,
2845
+ ),
2846
+ sessionFenceValid: check(
2847
+ "organization_user_resource_grants_session_fence_check",
2848
+ sql`(
2849
+ ${table.mode} = 'always'
2850
+ and ${table.sessionId} is null
2851
+ and ${table.authorityEpoch} is null
2852
+ ) or (
2853
+ ${table.mode} in ('once', 'session')
2854
+ and
2855
+ ${table.sessionId} is not null
2856
+ and ${table.authorityEpoch} is not null
2857
+ and ${table.authorityEpoch} > 0
2858
+ )`,
2859
+ ),
2860
+ generationValid: check(
2861
+ "organization_user_resource_grants_generation_check",
2862
+ sql`${table.generation} > 0`,
2863
+ ),
2864
+ statusValid: check(
2865
+ "organization_user_resource_grants_status_check",
2866
+ sql`${table.status} in ('active', 'consumed', 'revoked', 'expired')`,
2867
+ ),
2868
+ revocationValid: check(
2869
+ "organization_user_resource_grants_revocation_check",
2870
+ sql`(${table.status} = 'revoked' and ${table.revokedAt} is not null)
2871
+ or (${table.status} <> 'revoked' and ${table.revokedAt} is null)`,
2872
+ ),
2873
+ }),
2874
+ );
2875
+
2147
2876
  // One temporary realtime owner for an ordinary session. Terminal rows remain
2148
2877
  // as lifecycle evidence; the partial unique index admits only one active owner.
2149
2878
  export const sessionRealtimeModes = pgTable(
@@ -2161,15 +2890,21 @@ export const sessionRealtimeModes = pgTable(
2161
2890
  state: text("state").notNull().default("active"),
2162
2891
  version: integer("version").notNull().default(1),
2163
2892
  connectionEpoch: integer("connection_epoch").notNull().default(1),
2164
- leaseExpiresAt: timestamp("lease_expires_at", { withTimezone: true }).notNull(),
2165
- lastHeartbeatAt: timestamp("last_heartbeat_at", { withTimezone: true }).notNull(),
2893
+ leaseExpiresAt: timestamp("lease_expires_at", {
2894
+ withTimezone: true,
2895
+ }).notNull(),
2896
+ lastHeartbeatAt: timestamp("last_heartbeat_at", {
2897
+ withTimezone: true,
2898
+ }).notNull(),
2166
2899
  startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
2167
2900
  endedAt: timestamp("ended_at", { withTimezone: true }),
2168
2901
  endReason: text("end_reason"),
2169
2902
  // The rolling migration owns this forward reference. End commits at most
2170
2903
  // one canonical transcript-tail Steer and binds its audit projection here.
2171
2904
  contextProjectionId: uuid("context_projection_id"),
2172
- contextProjectedAt: timestamp("context_projected_at", { withTimezone: true }),
2905
+ contextProjectedAt: timestamp("context_projected_at", {
2906
+ withTimezone: true,
2907
+ }),
2173
2908
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
2174
2909
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
2175
2910
  },
@@ -2203,6 +2938,7 @@ export const sessionRealtimeModes = pgTable(
2203
2938
  "session_realtime_modes_model_check",
2204
2939
  sql`${table.model} in (
2205
2940
  'gpt-live-1-boulder-alpha',
2941
+ 'supergrok/grok-voice-think-fast-2.0',
2206
2942
  'opengeni-gateway/openai/gpt-realtime-2.1',
2207
2943
  'opengeni-gateway/openai/gpt-realtime-mini',
2208
2944
  'opengeni-gateway/xai/grok-voice-think-fast-2.0',
@@ -2260,7 +2996,9 @@ export const sessionRealtimeConnections = pgTable(
2260
2996
  failureCode: text("failure_code"),
2261
2997
  providerSessionId: text("provider_session_id"),
2262
2998
  startupEventId: text("startup_event_id"),
2263
- startupAcknowledgedAt: timestamp("startup_acknowledged_at", { withTimezone: true }),
2999
+ startupAcknowledgedAt: timestamp("startup_acknowledged_at", {
3000
+ withTimezone: true,
3001
+ }),
2264
3002
  negotiatedAt: timestamp("negotiated_at", { withTimezone: true }),
2265
3003
  closedAt: timestamp("closed_at", { withTimezone: true }),
2266
3004
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
@@ -2729,7 +3467,9 @@ export const generatedImageArtifacts = pgTable(
2729
3467
  workspaceId: uuid("workspace_id")
2730
3468
  .notNull()
2731
3469
  .references(() => workspaces.id, { onDelete: "cascade" }),
2732
- sessionId: uuid("session_id").references(() => sessions.id, { onDelete: "set null" }),
3470
+ sessionId: uuid("session_id").references(() => sessions.id, {
3471
+ onDelete: "set null",
3472
+ }),
2733
3473
  // Turn/attempt foreign keys are installed by the migration; those tables
2734
3474
  // are declared later in this monolithic schema module.
2735
3475
  turnId: uuid("turn_id"),
@@ -2944,7 +3684,7 @@ export const workspaceVideoGenerationPolicies = pgTable(
2944
3684
  ),
2945
3685
  fundingSourceValid: check(
2946
3686
  "workspace_video_generation_policies_funding_source_chk",
2947
- sql`${table.fundingSource} in ('opengeni_credits', 'workspace_gateway')`,
3687
+ sql`${table.fundingSource} in ('opengeni_credits', 'workspace_gateway', 'supergrok_subscription')`,
2948
3688
  ),
2949
3689
  }),
2950
3690
  );
@@ -2990,7 +3730,9 @@ export const videoGenerationOperations = pgTable(
2990
3730
  workspaceId: uuid("workspace_id")
2991
3731
  .notNull()
2992
3732
  .references(() => workspaces.id, { onDelete: "cascade" }),
2993
- sessionId: uuid("session_id").references(() => sessions.id, { onDelete: "set null" }),
3733
+ sessionId: uuid("session_id").references(() => sessions.id, {
3734
+ onDelete: "set null",
3735
+ }),
2994
3736
  turnId: uuid("turn_id"),
2995
3737
  attemptId: uuid("attempt_id"),
2996
3738
  toolCallId: text("tool_call_id").notNull(),
@@ -3012,7 +3754,9 @@ export const videoGenerationOperations = pgTable(
3012
3754
  /** Exact provider start body, encrypted before the first network byte. */
3013
3755
  providerRequestEncrypted: text("provider_request_encrypted"),
3014
3756
  /** Bearer URLs inside the frozen body are unusable after this instant. */
3015
- providerRequestExpiresAt: timestamp("provider_request_expires_at", { withTimezone: true }),
3757
+ providerRequestExpiresAt: timestamp("provider_request_expires_at", {
3758
+ withTimezone: true,
3759
+ }),
3016
3760
  expectedArtifactId: uuid("expected_artifact_id").notNull(),
3017
3761
  expectedFileId: uuid("expected_file_id").notNull(),
3018
3762
  reservedBytes: bigint("reserved_bytes", { mode: "number" }).notNull(),
@@ -3023,13 +3767,21 @@ export const videoGenerationOperations = pgTable(
3023
3767
  terminalUpdateId: uuid("terminal_update_id"),
3024
3768
  reconcileRevision: bigint("reconcile_revision", { mode: "number" }).notNull().default(0),
3025
3769
  reconcileLeaseOwner: text("reconcile_lease_owner"),
3026
- reconcileLeaseExpiresAt: timestamp("reconcile_lease_expires_at", { withTimezone: true }),
3770
+ reconcileLeaseExpiresAt: timestamp("reconcile_lease_expires_at", {
3771
+ withTimezone: true,
3772
+ }),
3027
3773
  nextReconcileAt: timestamp("next_reconcile_at", { withTimezone: true }),
3028
- providerRequestSentAt: timestamp("provider_request_sent_at", { withTimezone: true }),
3774
+ providerRequestSentAt: timestamp("provider_request_sent_at", {
3775
+ withTimezone: true,
3776
+ }),
3029
3777
  providerStartedAt: timestamp("provider_started_at", { withTimezone: true }),
3030
- recoveryDeadlineAt: timestamp("recovery_deadline_at", { withTimezone: true }).notNull(),
3778
+ recoveryDeadlineAt: timestamp("recovery_deadline_at", {
3779
+ withTimezone: true,
3780
+ }).notNull(),
3031
3781
  terminalAt: timestamp("terminal_at", { withTimezone: true }),
3032
- privateDataEraseAfter: timestamp("private_data_erase_after", { withTimezone: true }),
3782
+ privateDataEraseAfter: timestamp("private_data_erase_after", {
3783
+ withTimezone: true,
3784
+ }),
3033
3785
  boundedPublicReason: text("bounded_public_reason"),
3034
3786
  lastError: text("last_error"),
3035
3787
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
@@ -3105,11 +3857,15 @@ export const videoGenerationOperations = pgTable(
3105
3857
  and ((${table.status} in ('provider_failed','cancelled_before_submit','outcome_unknown','retention_failed')
3106
3858
  and ${table.creditState} = 'refunded')
3107
3859
  or (${table.status} not in ('provider_failed','cancelled_before_submit','outcome_unknown','retention_failed')
3108
- and ${table.creditState} = 'debited')))))`,
3860
+ and ${table.creditState} = 'debited'))))
3861
+ or (${table.fundingSource} = 'supergrok_subscription'
3862
+ and ${table.connectionId} is null
3863
+ and ${table.pricedCostMicros} = 0
3864
+ and ${table.creditState} = 'not_applicable'))`,
3109
3865
  ),
3110
3866
  fundingValuesValid: check(
3111
3867
  "video_generation_operations_funding_values_chk",
3112
- sql`${table.fundingSource} in ('opengeni_credits','workspace_gateway')
3868
+ sql`${table.fundingSource} in ('opengeni_credits','workspace_gateway','supergrok_subscription')
3113
3869
  and ${table.pricedCostMicros} between 0 and 1000000000
3114
3870
  and ${table.creditState} in ('not_applicable','debited','refunded')`,
3115
3871
  ),
@@ -3181,7 +3937,9 @@ export const generatedVideoArtifacts = pgTable(
3181
3937
  operationId: uuid("operation_id")
3182
3938
  .notNull()
3183
3939
  .references(() => videoGenerationOperations.id, { onDelete: "restrict" }),
3184
- sessionId: uuid("session_id").references(() => sessions.id, { onDelete: "set null" }),
3940
+ sessionId: uuid("session_id").references(() => sessions.id, {
3941
+ onDelete: "set null",
3942
+ }),
3185
3943
  turnId: uuid("turn_id"),
3186
3944
  attemptId: uuid("attempt_id"),
3187
3945
  modelId: text("model_id").notNull(),
@@ -3317,12 +4075,16 @@ export const retainedScreenshotArtifacts = pgTable(
3317
4075
  sha256: text("sha256").notNull(),
3318
4076
  width: integer("width").notNull(),
3319
4077
  height: integer("height").notNull(),
3320
- retentionExpiresAt: timestamp("retention_expires_at", { withTimezone: true }).notNull(),
4078
+ retentionExpiresAt: timestamp("retention_expires_at", {
4079
+ withTimezone: true,
4080
+ }).notNull(),
3321
4081
  readyAt: timestamp("ready_at", { withTimezone: true }),
3322
4082
  cleanupReason: text("cleanup_reason"),
3323
4083
  lastError: text("last_error"),
3324
4084
  maintenanceClaimId: uuid("maintenance_claim_id"),
3325
- maintenanceClaimedAt: timestamp("maintenance_claimed_at", { withTimezone: true }),
4085
+ maintenanceClaimedAt: timestamp("maintenance_claimed_at", {
4086
+ withTimezone: true,
4087
+ }),
3326
4088
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
3327
4089
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
3328
4090
  },
@@ -3773,6 +4535,10 @@ export const sessionTurns = pgTable(
3773
4535
  // causal turn's value while retaining a service initiator. Null means the
3774
4536
  // turn has no human preference authority.
3775
4537
  initiatingHumanSubjectId: text("initiating_human_subject_id"),
4538
+ // Exact goal authority frozen when the logical turn is accepted. The
4539
+ // migration trigger fills this for old and rolling writers; claim only
4540
+ // reconstructs legacy nulls from events as-of created_at.
4541
+ goalSnapshot: jsonb("goal_snapshot").$type<SessionGoalSnapshot>(),
3776
4542
  // Immutable exact personal MCP authority for this logical turn. Recovery,
3777
4543
  // approval, retries, and Codemode reuse this row; no runtime may infer
3778
4544
  // broader authority from the session creator or mutable session state.
@@ -3780,6 +4546,10 @@ export const sessionTurns = pgTable(
3780
4546
  .$type<McpPersonalConnectionDelegation[]>()
3781
4547
  .notNull()
3782
4548
  .default([]),
4549
+ xaiProviderAccountAuthoritySnapshot: jsonb("xai_provider_account_authority_snapshot")
4550
+ .$type<XaiProviderAccountAuthoritySnapshotV1>()
4551
+ .notNull()
4552
+ .default(WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1),
3783
4553
  cancelledBy: text("cancelled_by"),
3784
4554
  cancelReason: text("cancel_reason"),
3785
4555
  // Atomic per-turn codemode call budget counter (migration 0043). Incremented
@@ -3890,6 +4660,16 @@ export const sessionTurnAttempts = pgTable(
3890
4660
  verifiedControlRevision: bigint("verified_control_revision", {
3891
4661
  mode: "number",
3892
4662
  }).notNull(),
4663
+ // Immutable generic session-tenancy authority admitted with this exact
4664
+ // attempt. A later visibility/ownership epoch change fences the attempt;
4665
+ // these are snapshots, never live lookups or mutable metadata.
4666
+ // Pre-0222 SQL writers may omit these columns; the migration-owned BEFORE
4667
+ // INSERT trigger fills them from the exact session row. Current claim
4668
+ // writers pass both explicitly, so no client-side default may bypass the
4669
+ // trigger and manufacture stale authority.
4670
+ authorityEpoch: integer("authority_epoch").notNull(),
4671
+ authorityVisibility: text("authority_visibility").notNull(),
4672
+ authorityOwnerOrganizationMembershipId: uuid("authority_owner_organization_membership_id"),
3893
4673
  // Immutable policy snapshot captured under the session lock at claim.
3894
4674
  mcpApprovalPolicies: jsonb("mcp_approval_policies")
3895
4675
  .$type<Record<string, SessionMcpApprovalPolicy>>()
@@ -3947,6 +4727,11 @@ export const sessionTurnAttempts = pgTable(
3947
4727
  table.startedAt.desc(),
3948
4728
  table.id.desc(),
3949
4729
  ),
4730
+ authorityEpoch: index("session_turn_attempts_authority_epoch_idx").on(
4731
+ table.workspaceId,
4732
+ table.sessionId,
4733
+ table.authorityEpoch,
4734
+ ),
3950
4735
  dispatch: uniqueIndex("session_turn_attempts_dispatch_uq").on(
3951
4736
  table.workspaceId,
3952
4737
  table.temporalWorkflowRunId,
@@ -3972,6 +4757,28 @@ export const sessionTurnAttempts = pgTable(
3972
4757
  sql`(${table.state} = 'closed' and ${table.outcome} is not null and ${table.closedAt} is not null)
3973
4758
  or (${table.state} <> 'closed' and ${table.outcome} is null and ${table.closedAt} is null)`,
3974
4759
  ),
4760
+ authorityEpochValid: check(
4761
+ "session_turn_attempts_authority_epoch_check",
4762
+ sql`${table.authorityEpoch} is not null
4763
+ and ${table.authorityVisibility} is not null
4764
+ and ${table.authorityEpoch} > 0`,
4765
+ ),
4766
+ authorityVisibilityValid: check(
4767
+ "session_turn_attempts_authority_visibility_check",
4768
+ sql`${table.authorityEpoch} is not null
4769
+ and ${table.authorityVisibility} is not null
4770
+ and ${table.authorityVisibility} in ('user_private', 'workspace_shared')`,
4771
+ ),
4772
+ authorityOwnerShape: check(
4773
+ "session_turn_attempts_authority_owner_shape_check",
4774
+ sql`${table.authorityVisibility} <> 'user_private'
4775
+ or ${table.authorityOwnerOrganizationMembershipId} is not null`,
4776
+ ),
4777
+ authorityOwner: foreignKey({
4778
+ name: "session_turn_attempts_authority_owner_fk",
4779
+ columns: [table.authorityOwnerOrganizationMembershipId, table.accountId],
4780
+ foreignColumns: [organizationMemberships.id, organizationMemberships.accountId],
4781
+ }).onDelete("restrict"),
3975
4782
  }),
3976
4783
  );
3977
4784
 
@@ -4085,7 +4892,9 @@ export const sessionAttemptCodemodeCalls = pgTable(
4085
4892
  errorMessage: text("error_message"),
4086
4893
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4087
4894
  claimedAt: timestamp("claimed_at", { withTimezone: true }),
4088
- executionStartedAt: timestamp("execution_started_at", { withTimezone: true }),
4895
+ executionStartedAt: timestamp("execution_started_at", {
4896
+ withTimezone: true,
4897
+ }),
4089
4898
  claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
4090
4899
  completedAt: timestamp("completed_at", { withTimezone: true }),
4091
4900
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
@@ -4258,8 +5067,12 @@ export const connectorActionRequests = pgTable(
4258
5067
  decisionBySubjectId: text("decision_by_subject_id"),
4259
5068
  decisionEventId: uuid("decision_event_id"),
4260
5069
  decidedAt: timestamp("decided_at", { withTimezone: true }),
4261
- executionStartedAt: timestamp("execution_started_at", { withTimezone: true }),
4262
- executionFinishedAt: timestamp("execution_finished_at", { withTimezone: true }),
5070
+ executionStartedAt: timestamp("execution_started_at", {
5071
+ withTimezone: true,
5072
+ }),
5073
+ executionFinishedAt: timestamp("execution_finished_at", {
5074
+ withTimezone: true,
5075
+ }),
4263
5076
  outcome: text("outcome"),
4264
5077
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4265
5078
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
@@ -4642,6 +5455,10 @@ export const sessionSystemUpdates = pgTable(
4642
5455
  .$type<McpPersonalConnectionDelegation[]>()
4643
5456
  .notNull()
4644
5457
  .default([]),
5458
+ xaiProviderAccountAuthoritySnapshot: jsonb("xai_provider_account_authority_snapshot")
5459
+ .$type<XaiProviderAccountAuthoritySnapshotV1>()
5460
+ .notNull()
5461
+ .default(WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1),
4645
5462
  // pending is visible queue truth; delivered means its exact model-memory
4646
5463
  // batch was durably claimed. Terminal cancellation/supersession is explicit.
4647
5464
  state: text("state").notNull().default("pending"),
@@ -4729,6 +5546,10 @@ export const sessionSystemUpdateOutbox = pgTable(
4729
5546
  .$type<McpPersonalConnectionDelegation[]>()
4730
5547
  .notNull()
4731
5548
  .default([]),
5549
+ xaiProviderAccountAuthoritySnapshot: jsonb("xai_provider_account_authority_snapshot")
5550
+ .$type<XaiProviderAccountAuthoritySnapshotV1>()
5551
+ .notNull()
5552
+ .default(WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1),
4732
5553
  status: text("status").notNull().default("pending"),
4733
5554
  attempts: integer("attempts").notNull().default(0),
4734
5555
  updateId: uuid("update_id"),
@@ -4831,6 +5652,13 @@ export const sessionGoals = pgTable(
4831
5652
  pausedReason: text("paused_reason"), // agent | user_pause | api | no_progress | max_auto_continuations | limits
4832
5653
  createdBy: text("created_by").notNull().default("api"), // api | agent | scheduled_task
4833
5654
  version: integer("version").notNull().default(1), // bumped on every set/update; progress signal
5655
+ // Semantic objective changes use a separate fence. `version` remains the
5656
+ // established lifecycle/wake identity for continuation compatibility.
5657
+ objectiveRevision: integer("objective_revision").notNull().default(1),
5658
+ mutationPolicy: text("mutation_policy")
5659
+ .$type<SessionGoalMutationPolicy>()
5660
+ .notNull()
5661
+ .default("preserve_intent"),
4834
5662
  autoContinuations: integer("auto_continuations").notNull().default(0),
4835
5663
  noProgressStreak: integer("no_progress_streak").notNull().default(0),
4836
5664
  maxAutoContinuations: integer("max_auto_continuations"), // per-goal override; a configured settings cap (if any) remains the hard ceiling
@@ -4842,10 +5670,14 @@ export const sessionGoals = pgTable(
4842
5670
  // update, timeline events, usage row, and workflow-wake outbox row.
4843
5671
  // Temporal signals and workflow history are replaceable nudges over these
4844
5672
  // monotonic revisions.
4845
- continuationWakeRevision: bigint("continuation_wake_revision", { mode: "number" })
5673
+ continuationWakeRevision: bigint("continuation_wake_revision", {
5674
+ mode: "number",
5675
+ })
4846
5676
  .notNull()
4847
5677
  .default(0),
4848
- continuationObservedRevision: bigint("continuation_observed_revision", { mode: "number" })
5678
+ continuationObservedRevision: bigint("continuation_observed_revision", {
5679
+ mode: "number",
5680
+ })
4849
5681
  .notNull()
4850
5682
  .default(0),
4851
5683
  metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
@@ -4869,6 +5701,88 @@ export const sessionGoals = pgTable(
4869
5701
  }),
4870
5702
  );
4871
5703
 
5704
+ /**
5705
+ * Immutable semantic goal history. A proposal is never model-visible until a
5706
+ * later applied row references it; rejection is another immutable decision
5707
+ * row rather than mutation of the original proposal.
5708
+ */
5709
+ export const sessionGoalRevisions = pgTable(
5710
+ "session_goal_revisions",
5711
+ {
5712
+ id: uuid("id").primaryKey().defaultRandom(),
5713
+ accountId: uuid("account_id").notNull(),
5714
+ workspaceId: uuid("workspace_id").notNull(),
5715
+ sessionId: uuid("session_id").notNull(),
5716
+ goalId: uuid("goal_id").notNull(),
5717
+ disposition: text("disposition").$type<"applied" | "proposed" | "rejected">().notNull(),
5718
+ changeKind: text("change_kind").$type<SessionGoalChangeKind>().notNull(),
5719
+ baseObjectiveRevision: integer("base_objective_revision").notNull(),
5720
+ resultObjectiveRevision: integer("result_objective_revision"),
5721
+ text: text("text").notNull(),
5722
+ successCriteria: text("success_criteria"),
5723
+ mutationPolicy: text("mutation_policy").$type<SessionGoalMutationPolicy>().notNull(),
5724
+ rationale: text("rationale").notNull(),
5725
+ actor: text("actor").$type<"agent" | "api" | "scheduled_task">().notNull(),
5726
+ actorTurnId: uuid("actor_turn_id"),
5727
+ actorAttemptId: uuid("actor_attempt_id"),
5728
+ proposalId: uuid("proposal_id"),
5729
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5730
+ },
5731
+ (table) => ({
5732
+ workspaceAccount: foreignKey({
5733
+ name: "session_goal_revisions_workspace_account_fk",
5734
+ columns: [table.workspaceId, table.accountId],
5735
+ foreignColumns: [workspaces.id, workspaces.accountId],
5736
+ }).onDelete("cascade"),
5737
+ workspaceSession: foreignKey({
5738
+ name: "session_goal_revisions_workspace_session_fk",
5739
+ columns: [table.workspaceId, table.sessionId],
5740
+ foreignColumns: [sessions.workspaceId, sessions.id],
5741
+ }).onDelete("cascade"),
5742
+ actorTurn: foreignKey({
5743
+ name: "session_goal_revisions_actor_turn_fk",
5744
+ columns: [table.workspaceId, table.actorTurnId],
5745
+ foreignColumns: [sessionTurns.workspaceId, sessionTurns.id],
5746
+ }).onDelete("restrict"),
5747
+ actorAttempt: foreignKey({
5748
+ name: "session_goal_revisions_actor_attempt_fk",
5749
+ columns: [table.workspaceId, table.actorAttemptId],
5750
+ foreignColumns: [sessionTurnAttempts.workspaceId, sessionTurnAttempts.id],
5751
+ }).onDelete("restrict"),
5752
+ proposal: foreignKey({
5753
+ name: "session_goal_revisions_proposal_fk",
5754
+ columns: [table.workspaceId, table.proposalId],
5755
+ foreignColumns: [table.workspaceId, table.id],
5756
+ }).onDelete("restrict"),
5757
+ appliedRevision: uniqueIndex("session_goal_revisions_applied_revision_uq")
5758
+ .on(table.workspaceId, table.goalId, table.resultObjectiveRevision)
5759
+ .where(sql`${table.disposition} = 'applied'`),
5760
+ goalTimeline: index("session_goal_revisions_goal_timeline_idx").on(
5761
+ table.workspaceId,
5762
+ table.goalId,
5763
+ table.createdAt,
5764
+ table.id,
5765
+ ),
5766
+ dispositionValid: check(
5767
+ "session_goal_revisions_disposition_chk",
5768
+ sql`${table.disposition} in ('applied', 'proposed', 'rejected')`,
5769
+ ),
5770
+ changeKindValid: check(
5771
+ "session_goal_revisions_change_kind_chk",
5772
+ sql`${table.changeKind} in ('refinement', 'adaptation', 'replacement')`,
5773
+ ),
5774
+ policyValid: check(
5775
+ "session_goal_revisions_policy_chk",
5776
+ sql`${table.mutationPolicy} in ('review_changes', 'preserve_intent', 'autonomous_adaptation')`,
5777
+ ),
5778
+ revisionShape: check(
5779
+ "session_goal_revisions_revision_shape_chk",
5780
+ sql`(${table.disposition} = 'applied' and ${table.resultObjectiveRevision} = ${table.baseObjectiveRevision} + 1)
5781
+ or (${table.disposition} in ('proposed', 'rejected') and ${table.resultObjectiveRevision} is null)`,
5782
+ ),
5783
+ }),
5784
+ );
5785
+
4872
5786
  // credential allocator: one durable, coalescing capacity waiter per session. The row is both
4873
5787
  // the wait state and the commit->signal outbox: capacity mutations increment
4874
5788
  // wakeRevision in the SAME transaction as the mutation, while the session
@@ -4936,6 +5850,126 @@ export const codexCapacityWaiters = pgTable(
4936
5850
  }),
4937
5851
  );
4938
5852
 
5853
+ // Per-session pin and last-account state is kept outside the shared session row
5854
+ // so user-scoped account identifiers remain behind the same exact-subject RLS
5855
+ // policy as every other xAI persistence table.
5856
+ export const xaiSessionAccountPins = pgTable(
5857
+ "xai_session_account_pins",
5858
+ {
5859
+ id: uuid("id").primaryKey().defaultRandom(),
5860
+ accountId: uuid("account_id")
5861
+ .notNull()
5862
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
5863
+ workspaceId: uuid("workspace_id")
5864
+ .notNull()
5865
+ .references(() => workspaces.id, { onDelete: "cascade" }),
5866
+ sessionId: uuid("session_id").notNull(),
5867
+ authorityScope: text("authority_scope").notNull().default("workspace"),
5868
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
5869
+ pinnedCredentialId: uuid("pinned_credential_id"),
5870
+ pinSource: text("pin_source"),
5871
+ lastCredentialId: uuid("last_credential_id"),
5872
+ version: integer("version").notNull().default(1),
5873
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5874
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
5875
+ },
5876
+ (table) => ({
5877
+ // Migration 0231 adds NULLS NOT DISTINCT so workspace scope is also a
5878
+ // singleton; Drizzle 0.45 cannot encode that PostgreSQL index modifier.
5879
+ workspaceSessionPool: uniqueIndex("xai_session_account_pins_workspace_session_uq").on(
5880
+ table.workspaceId,
5881
+ table.sessionId,
5882
+ table.authorityScope,
5883
+ table.ownerOrganizationMembershipId,
5884
+ ),
5885
+ scopeValid: check(
5886
+ "xai_session_account_pins_authority_scope_chk",
5887
+ sql`(${table.authorityScope} = 'workspace' and ${table.ownerOrganizationMembershipId} is null)
5888
+ or (${table.authorityScope} = 'user' and ${table.ownerOrganizationMembershipId} is not null)`,
5889
+ ),
5890
+ pinValid: check(
5891
+ "xai_session_account_pins_pin_chk",
5892
+ sql`(${table.pinnedCredentialId} is null and ${table.pinSource} is null)
5893
+ or (${table.pinnedCredentialId} is not null and ${table.pinSource} in ('manual', 'policy'))`,
5894
+ ),
5895
+ versionValid: check("xai_session_account_pins_version_chk", sql`${table.version} > 0`),
5896
+ }),
5897
+ );
5898
+
5899
+ // Durable same-turn capacity wait. The blocked turn owns the immutable xAI
5900
+ // authority snapshot; this row carries only pool scope and wake/retry metadata.
5901
+ export const xaiCapacityWaiters = pgTable(
5902
+ "xai_capacity_waiters",
5903
+ {
5904
+ id: uuid("id").primaryKey().defaultRandom(),
5905
+ accountId: uuid("account_id")
5906
+ .notNull()
5907
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
5908
+ workspaceId: uuid("workspace_id")
5909
+ .notNull()
5910
+ .references(() => workspaces.id, { onDelete: "cascade" }),
5911
+ sessionId: uuid("session_id").notNull(),
5912
+ goalId: uuid("goal_id"),
5913
+ goalVersion: integer("goal_version"),
5914
+ blockedTurnId: uuid("blocked_turn_id").notNull(),
5915
+ blockedTurnGeneration: integer("blocked_turn_generation").notNull(),
5916
+ workflowId: text("workflow_id").notNull(),
5917
+ authorityScope: text("authority_scope").notNull(),
5918
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
5919
+ status: text("status").notNull().default("waiting"),
5920
+ generation: integer("generation").notNull().default(1),
5921
+ earliestResetAt: timestamp("earliest_reset_at", { withTimezone: true }),
5922
+ nextCheckAt: timestamp("next_check_at", { withTimezone: true }).notNull(),
5923
+ wakeRevision: integer("wake_revision").notNull().default(1),
5924
+ observedWakeRevision: integer("observed_wake_revision").notNull().default(0),
5925
+ lastWakeReason: text("last_wake_reason").notNull().default("capacity_wait_armed"),
5926
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5927
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
5928
+ },
5929
+ (table) => ({
5930
+ // Migration 0234 uses NULLS NOT DISTINCT so workspace scope is also a
5931
+ // singleton; Drizzle 0.45 cannot encode that PostgreSQL index modifier.
5932
+ workspaceSessionPool: uniqueIndex("xai_capacity_waiters_workspace_session_uq").on(
5933
+ table.workspaceId,
5934
+ table.sessionId,
5935
+ table.authorityScope,
5936
+ table.ownerOrganizationMembershipId,
5937
+ ),
5938
+ pending: index("xai_capacity_waiters_pending_idx").on(
5939
+ table.workspaceId,
5940
+ table.status,
5941
+ table.nextCheckAt,
5942
+ ),
5943
+ wakeRepair: index("xai_capacity_waiters_wake_repair_idx").on(
5944
+ table.status,
5945
+ table.wakeRevision,
5946
+ table.observedWakeRevision,
5947
+ ),
5948
+ scopeValid: check(
5949
+ "xai_capacity_waiters_authority_scope_chk",
5950
+ sql`(${table.authorityScope} = 'workspace' and ${table.ownerOrganizationMembershipId} is null)
5951
+ or (${table.authorityScope} = 'user' and ${table.ownerOrganizationMembershipId} is not null)`,
5952
+ ),
5953
+ statusValid: check(
5954
+ "xai_capacity_waiters_status_chk",
5955
+ sql`${table.status} in ('waiting', 'resumed', 'superseded')`,
5956
+ ),
5957
+ countersValid: check(
5958
+ "xai_capacity_waiters_counters_chk",
5959
+ sql`${table.blockedTurnGeneration} >= 0
5960
+ and ${table.generation} > 0
5961
+ and ${table.wakeRevision} > 0
5962
+ and ${table.observedWakeRevision} >= 0
5963
+ and ${table.observedWakeRevision} <= ${table.wakeRevision}`,
5964
+ ),
5965
+ goalFenceValid: check(
5966
+ "xai_capacity_waiters_goal_fence_chk",
5967
+ sql`(${table.goalId} is null and ${table.goalVersion} is null)
5968
+ or (${table.goalId} is not null and ${table.goalVersion} > 0)`,
5969
+ ),
5970
+ }),
5971
+ );
5972
+
4939
5973
  export const sessionEvents = pgTable(
4940
5974
  "session_events",
4941
5975
  {
@@ -5225,6 +6259,8 @@ export const sessionPendingToolCalls = pgTable(
5225
6259
  modelToolOutputTruncationTokens: integer("model_tool_output_truncation_tokens"),
5226
6260
  resultItem: losslessJsonb("result_item").$type<Record<string, unknown>>(),
5227
6261
  resultItemCodecVersion: losslessCodecVersion("result_item_codec_version"),
6262
+ eventOutput: losslessJsonb("event_output").$type<{ value: unknown }>(),
6263
+ eventOutputCodecVersion: losslessCodecVersion("event_output_codec_version"),
5228
6264
  resultRecordedAt: timestamp("result_recorded_at", { withTimezone: true }),
5229
6265
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
5230
6266
  },
@@ -5459,6 +6495,11 @@ export const sandboxLeases = pgTable(
5459
6495
  // data_plane_url.
5460
6496
  terminalDataPlaneUrl: text("terminal_data_plane_url"),
5461
6497
 
6498
+ // Cached browserd HTTP/WebSocket tunnel (7682). Controller requests use
6499
+ // this epoch-fenced endpoint directly after the first provider resolution;
6500
+ // provider-handle coordination remains limited to lifecycle/provisioning.
6501
+ controllerDataPlaneUrl: text("controller_data_plane_url"),
6502
+
5462
6503
  // integer (NOT bigint): the lease-epoch spike proved a raw int8 read returns a
5463
6504
  // JS STRING from postgres-js, breaking the strict epoch-fence comparison (it
5464
6505
  // was always-true → every turn fenced); int4 returns a JS number, the fix.
@@ -5718,7 +6759,9 @@ export const sandboxWorkspaceMutationAdmissions = pgTable(
5718
6759
  .references(() => sandboxLeases.id, { onDelete: "cascade" }),
5719
6760
  sandboxGroupId: uuid("sandbox_group_id").notNull(),
5720
6761
  sessionId: uuid("session_id").notNull(),
5721
- actorKind: text("actor_kind", { enum: sandboxWorkspaceMutationActorKindValues }).notNull(),
6762
+ actorKind: text("actor_kind", {
6763
+ enum: sandboxWorkspaceMutationActorKindValues,
6764
+ }).notNull(),
5722
6765
  actorId: uuid("actor_id").notNull(),
5723
6766
  // Exact turn authority is present only for actor_kind='turn'. Direct HTTP
5724
6767
  // requests and retained processes never invent a turn or quiescence owner.
@@ -5865,7 +6908,9 @@ export const sandboxRetainedProcesses = pgTable(
5865
6908
  sandboxGroupId: uuid("sandbox_group_id").notNull(),
5866
6909
  parentAdmissionId: uuid("parent_admission_id").notNull(),
5867
6910
  holderId: text("holder_id").notNull(),
5868
- ownerActorKind: text("owner_actor_kind", { enum: ["turn", "direct"] }).notNull(),
6911
+ ownerActorKind: text("owner_actor_kind", {
6912
+ enum: ["turn", "direct"],
6913
+ }).notNull(),
5869
6914
  ownerActorId: uuid("owner_actor_id").notNull(),
5870
6915
  ownerTurnId: uuid("owner_turn_id"),
5871
6916
  ownerAttemptId: uuid("owner_attempt_id"),
@@ -5893,13 +6938,19 @@ export const sandboxRetainedProcesses = pgTable(
5893
6938
  // never exit/loss proof.
5894
6939
  reconcileAfter: timestamp("reconcile_after", { withTimezone: true }).notNull().defaultNow(),
5895
6940
  reconcileClaimId: uuid("reconcile_claim_id"),
5896
- reconcileClaimedAt: timestamp("reconcile_claimed_at", { withTimezone: true }),
6941
+ reconcileClaimedAt: timestamp("reconcile_claimed_at", {
6942
+ withTimezone: true,
6943
+ }),
5897
6944
  reconcileAttempts: integer("reconcile_attempts").notNull().default(0),
5898
6945
  lastReconcileOutcome: text("last_reconcile_outcome"),
5899
- reconcileProofOutcome: text("reconcile_proof_outcome", { enum: ["exited", "lost"] }),
6946
+ reconcileProofOutcome: text("reconcile_proof_outcome", {
6947
+ enum: ["exited", "lost"],
6948
+ }),
5900
6949
  reconcileProofExitCode: integer("reconcile_proof_exit_code"),
5901
6950
  reconcileProofReason: text("reconcile_proof_reason"),
5902
- reconcileProofObservedAt: timestamp("reconcile_proof_observed_at", { withTimezone: true }),
6951
+ reconcileProofObservedAt: timestamp("reconcile_proof_observed_at", {
6952
+ withTimezone: true,
6953
+ }),
5903
6954
  },
5904
6955
  (table) => ({
5905
6956
  workspaceAccount: foreignKey({
@@ -6373,7 +7424,9 @@ export const machineRemovalOperations = pgTable(
6373
7424
  .references(() => enrollments.id, { onDelete: "restrict" }),
6374
7425
  operationKey: text("operation_key").notNull(),
6375
7426
  requestFingerprint: text("request_fingerprint").notNull(),
6376
- outcome: text("outcome", { enum: machineRemovalOperationOutcomeValues }).notNull(),
7427
+ outcome: text("outcome", {
7428
+ enum: machineRemovalOperationOutcomeValues,
7429
+ }).notNull(),
6377
7430
  result: jsonb("result").$type<Record<string, unknown>>().notNull().default({}),
6378
7431
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
6379
7432
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
@@ -6639,6 +7692,10 @@ export const scheduledTasks = pgTable(
6639
7692
  .$type<McpPersonalConnectionDelegation[]>()
6640
7693
  .notNull()
6641
7694
  .default([]),
7695
+ xaiProviderAccountAuthoritySnapshot: jsonb("xai_provider_account_authority_snapshot")
7696
+ .$type<XaiProviderAccountAuthoritySnapshotV1>()
7697
+ .notNull()
7698
+ .default(WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1),
6642
7699
  reusableSessionId: uuid("reusable_session_id").references(() => sessions.id, {
6643
7700
  onDelete: "set null",
6644
7701
  }),
@@ -6776,8 +7833,12 @@ export const githubInstallations = pgTable(
6776
7833
  githubActorId: bigint("github_actor_id", { mode: "number" }),
6777
7834
  githubActorLogin: text("github_actor_login"),
6778
7835
  authorityKind: text("authority_kind"),
6779
- authorityCheckedAt: timestamp("authority_checked_at", { withTimezone: true }),
6780
- authorityExpiresAt: timestamp("authority_expires_at", { withTimezone: true }),
7836
+ authorityCheckedAt: timestamp("authority_checked_at", {
7837
+ withTimezone: true,
7838
+ }),
7839
+ authorityExpiresAt: timestamp("authority_expires_at", {
7840
+ withTimezone: true,
7841
+ }),
6781
7842
  authorityNonce: text("authority_nonce"),
6782
7843
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
6783
7844
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
@@ -6995,7 +8056,9 @@ export const modelCallFacts = pgTable(
6995
8056
  reasoningTokens: bigint("reasoning_tokens", { mode: "number" }),
6996
8057
  totalTokens: bigint("total_tokens", { mode: "number" }),
6997
8058
  pricedCostMicros: bigint("priced_cost_micros", { mode: "number" }).notNull().default(0),
6998
- estimatedProviderCostMicros: bigint("estimated_provider_cost_micros", { mode: "number" }),
8059
+ estimatedProviderCostMicros: bigint("estimated_provider_cost_micros", {
8060
+ mode: "number",
8061
+ }),
6999
8062
  pricingSource: text("pricing_source"),
7000
8063
  occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull(),
7001
8064
  recordedAt: timestamp("recorded_at", { withTimezone: true }).notNull().defaultNow(),
@@ -7121,7 +8184,9 @@ export const hostExportOutbox = pgTable(
7121
8184
  payloadCodecVersion: losslessCodecVersion("payload_codec_version"),
7122
8185
  envelopeBytes: integer("envelope_bytes").notNull(),
7123
8186
  occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull(),
7124
- sourceRecordedAt: timestamp("source_recorded_at", { withTimezone: true }).notNull(),
8187
+ sourceRecordedAt: timestamp("source_recorded_at", {
8188
+ withTimezone: true,
8189
+ }).notNull(),
7125
8190
  enqueuedAt: timestamp("enqueued_at", { withTimezone: true }).notNull(),
7126
8191
  },
7127
8192
  (table) => ({
@@ -7505,6 +8570,7 @@ export const capabilityCatalogItems = pgTable(
7505
8570
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
7506
8571
  },
7507
8572
  (table) => ({
8573
+ kindAuthority: check("capability_catalog_items_kind_authority_chk", sql`${table.kind} = 'mcp'`),
7508
8574
  workspaceCapability: uniqueIndex("capability_catalog_items_workspace_capability_idx").on(
7509
8575
  table.workspaceId,
7510
8576
  table.id,
@@ -7551,6 +8617,7 @@ export const capabilityInstallations = pgTable(
7551
8617
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
7552
8618
  },
7553
8619
  (table) => ({
8620
+ kindAuthority: check("capability_installations_kind_authority_chk", sql`${table.kind} = 'mcp'`),
7554
8621
  workspaceCapability: uniqueIndex("capability_installations_workspace_capability_idx").on(
7555
8622
  table.workspaceId,
7556
8623
  table.capabilityId,
@@ -7563,17 +8630,21 @@ export const capabilityInstallations = pgTable(
7563
8630
  }),
7564
8631
  );
7565
8632
 
7566
- // --- Capabilities platform v2 ------------------------------------------------
7567
- // Expand-only normalized state. The v1 catalog/installations remain intact
7568
- // while adapters shadow-read and migrate exact owners into this model.
8633
+ // --- Capabilities platform ---------------------------------------------------
8634
+ // Authoritative Plugin, immutable Version, Facet, installation, and ownership
8635
+ // state. The generic catalog/installations ledger is reserved for MCP.
7569
8636
 
7570
8637
  export const capabilityPlugins = pgTable(
7571
8638
  "capability_plugins",
7572
8639
  {
7573
8640
  id: uuid("id").primaryKey().defaultRandom(),
7574
8641
  pluginKey: text("plugin_key").notNull(),
7575
- accountId: uuid("account_id").references(() => managedAccounts.id, { onDelete: "cascade" }),
7576
- workspaceId: uuid("workspace_id").references(() => workspaces.id, { onDelete: "cascade" }),
8642
+ accountId: uuid("account_id").references(() => managedAccounts.id, {
8643
+ onDelete: "cascade",
8644
+ }),
8645
+ workspaceId: uuid("workspace_id").references(() => workspaces.id, {
8646
+ onDelete: "cascade",
8647
+ }),
7577
8648
  name: text("name").notNull(),
7578
8649
  description: text("description"),
7579
8650
  category: text("category").notNull(),
@@ -7785,7 +8856,9 @@ export const capabilityFacetInstallations = pgTable(
7785
8856
  .references(() => workspaces.id, { onDelete: "cascade" }),
7786
8857
  pluginInstallationId: uuid("plugin_installation_id")
7787
8858
  .notNull()
7788
- .references(() => capabilityPluginInstallations.id, { onDelete: "cascade" }),
8859
+ .references(() => capabilityPluginInstallations.id, {
8860
+ onDelete: "cascade",
8861
+ }),
7789
8862
  facetId: uuid("facet_id")
7790
8863
  .notNull()
7791
8864
  .references(() => capabilityFacets.id, { onDelete: "restrict" }),
@@ -7823,7 +8896,9 @@ export const capabilityComponentOwners = pgTable(
7823
8896
  .references(() => workspaces.id, { onDelete: "cascade" }),
7824
8897
  facetInstallationId: uuid("facet_installation_id")
7825
8898
  .notNull()
7826
- .references(() => capabilityFacetInstallations.id, { onDelete: "cascade" }),
8899
+ .references(() => capabilityFacetInstallations.id, {
8900
+ onDelete: "cascade",
8901
+ }),
7827
8902
  ownerKind: text("owner_kind").notNull(),
7828
8903
  ownerId: text("owner_id").notNull(),
7829
8904
  removable: boolean("removable").notNull().default(true),
@@ -7892,33 +8967,35 @@ export const integrationTools = pgTable(
7892
8967
  }),
7893
8968
  );
7894
8969
 
7895
- export const integrationFeatureFacets = pgTable(
7896
- "integration_feature_facets",
8970
+ export const integrationFacetDefinitions = pgTable(
8971
+ "integration_facet_definitions",
7897
8972
  {
7898
8973
  id: uuid("id").primaryKey().defaultRandom(),
7899
8974
  integrationFacetId: uuid("integration_facet_id")
7900
8975
  .notNull()
7901
- .references(() => capabilityIntegrationFacets.facetId, { onDelete: "cascade" }),
7902
- featureKey: text("feature_key").notNull(),
8976
+ .references(() => capabilityIntegrationFacets.facetId, {
8977
+ onDelete: "cascade",
8978
+ }),
8979
+ facetKey: text("facet_key").notNull(),
7903
8980
  kind: text("kind").notNull(),
7904
8981
  configSchema: jsonb("config_schema").$type<Record<string, unknown>>().notNull().default({}),
7905
8982
  capabilities: jsonb("capabilities").$type<Record<string, unknown>>().notNull().default({}),
7906
8983
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
7907
8984
  },
7908
8985
  (table) => ({
7909
- integrationFeature: uniqueIndex("integration_feature_facets_integration_feature_idx").on(
8986
+ integrationFacet: uniqueIndex("integration_facet_definitions_integration_facet_idx").on(
7910
8987
  table.integrationFacetId,
7911
- table.featureKey,
8988
+ table.facetKey,
7912
8989
  ),
7913
- integrationKind: index("integration_feature_facets_integration_kind_idx").on(
8990
+ integrationKind: index("integration_facet_definitions_integration_kind_idx").on(
7914
8991
  table.integrationFacetId,
7915
8992
  table.kind,
7916
8993
  ),
7917
8994
  }),
7918
8995
  );
7919
8996
 
7920
- export const integrationFeatureBindings = pgTable(
7921
- "integration_feature_bindings",
8997
+ export const integrationFacetBindings = pgTable(
8998
+ "integration_facet_bindings",
7922
8999
  {
7923
9000
  id: uuid("id").primaryKey().defaultRandom(),
7924
9001
  accountId: uuid("account_id")
@@ -7927,12 +9004,16 @@ export const integrationFeatureBindings = pgTable(
7927
9004
  workspaceId: uuid("workspace_id")
7928
9005
  .notNull()
7929
9006
  .references(() => workspaces.id, { onDelete: "cascade" }),
7930
- featureFacetId: uuid("feature_facet_id")
9007
+ facetDefinitionId: uuid("facet_definition_id")
7931
9008
  .notNull()
7932
- .references(() => integrationFeatureFacets.id, { onDelete: "restrict" }),
9009
+ .references(() => integrationFacetDefinitions.id, {
9010
+ onDelete: "restrict",
9011
+ }),
7933
9012
  integrationFacetInstallationId: uuid("integration_facet_installation_id")
7934
9013
  .notNull()
7935
- .references(() => capabilityFacetInstallations.id, { onDelete: "cascade" }),
9014
+ .references(() => capabilityFacetInstallations.id, {
9015
+ onDelete: "cascade",
9016
+ }),
7936
9017
  bindingKey: text("binding_key").notNull(),
7937
9018
  displayName: text("display_name").notNull(),
7938
9019
  runtimeKey: text("runtime_key"),
@@ -7950,26 +9031,24 @@ export const integrationFeatureBindings = pgTable(
7950
9031
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
7951
9032
  },
7952
9033
  (table) => ({
7953
- installationFeatureKey: uniqueIndex(
7954
- "integration_feature_bindings_installation_feature_key_idx",
7955
- ).on(
9034
+ installationFacetKey: uniqueIndex("integration_facet_bindings_installation_facet_key_idx").on(
7956
9035
  table.workspaceId,
7957
9036
  table.integrationFacetInstallationId,
7958
- table.featureFacetId,
9037
+ table.facetDefinitionId,
7959
9038
  table.bindingKey,
7960
9039
  ),
7961
- workspaceRuntime: uniqueIndex("integration_feature_bindings_workspace_runtime_idx")
9040
+ workspaceRuntime: uniqueIndex("integration_facet_bindings_workspace_runtime_idx")
7962
9041
  .on(table.workspaceId, table.runtimeKey)
7963
9042
  .where(sql`${table.runtimeKey} is not null`),
7964
- workspaceStatus: index("integration_feature_bindings_workspace_status_idx").on(
9043
+ workspaceStatus: index("integration_facet_bindings_workspace_status_idx").on(
7965
9044
  table.workspaceId,
7966
9045
  table.status,
7967
9046
  ),
7968
9047
  }),
7969
9048
  );
7970
9049
 
7971
- export const integrationFeatureBindingOwners = pgTable(
7972
- "integration_feature_binding_owners",
9050
+ export const integrationFacetBindingOwners = pgTable(
9051
+ "integration_facet_binding_owners",
7973
9052
  {
7974
9053
  id: uuid("id").primaryKey().defaultRandom(),
7975
9054
  accountId: uuid("account_id")
@@ -7980,19 +9059,19 @@ export const integrationFeatureBindingOwners = pgTable(
7980
9059
  .references(() => workspaces.id, { onDelete: "cascade" }),
7981
9060
  bindingId: uuid("binding_id")
7982
9061
  .notNull()
7983
- .references(() => integrationFeatureBindings.id, { onDelete: "cascade" }),
9062
+ .references(() => integrationFacetBindings.id, { onDelete: "cascade" }),
7984
9063
  ownerKind: text("owner_kind").notNull(),
7985
9064
  ownerId: text("owner_id").notNull(),
7986
9065
  removable: boolean("removable").notNull().default(true),
7987
9066
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
7988
9067
  },
7989
9068
  (table) => ({
7990
- uniqueOwner: uniqueIndex("integration_feature_binding_owners_unique_idx").on(
9069
+ uniqueOwner: uniqueIndex("integration_facet_binding_owners_unique_idx").on(
7991
9070
  table.bindingId,
7992
9071
  table.ownerKind,
7993
9072
  table.ownerId,
7994
9073
  ),
7995
- workspaceOwner: index("integration_feature_binding_owners_workspace_owner_idx").on(
9074
+ workspaceOwner: index("integration_facet_binding_owners_workspace_owner_idx").on(
7996
9075
  table.workspaceId,
7997
9076
  table.ownerKind,
7998
9077
  table.ownerId,
@@ -8144,12 +9223,44 @@ export const rigs = pgTable(
8144
9223
  description: text("description"),
8145
9224
  // Attribution string: 'user:<subject>' | 'session:<id>' | 'system'.
8146
9225
  createdBy: text("created_by"),
9226
+ // Inert migration-0230 identity foundation. Existing DAO/API/runtime paths
9227
+ // omit these fields and keep their historical workspace authority.
9228
+ authorityScope: text("authority_scope").notNull().default("workspace"),
9229
+ authorityId: uuid("authority_id"),
9230
+ ownerOrganizationMembershipId: uuid("owner_organization_membership_id"),
9231
+ originWorkspaceId: uuid("origin_workspace_id"),
8147
9232
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
8148
9233
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
8149
9234
  },
8150
9235
  (table) => ({
8151
9236
  workspaceName: uniqueIndex("rigs_workspace_name_idx").on(table.workspaceId, table.name),
8152
9237
  workspaceCreated: index("rigs_workspace_created_idx").on(table.workspaceId, table.createdAt),
9238
+ authorityShape: check(
9239
+ "rigs_authority_shape_check",
9240
+ sql`(
9241
+ ${table.authorityScope} = 'workspace'
9242
+ and ${table.authorityId} is null
9243
+ and ${table.ownerOrganizationMembershipId} is null
9244
+ ) or (
9245
+ ${table.authorityScope} = 'user'
9246
+ and ${table.authorityId} is not null
9247
+ and ${table.ownerOrganizationMembershipId} is not null
9248
+ )`,
9249
+ ),
9250
+ authorityScopeValid: check(
9251
+ "rigs_authority_scope_check",
9252
+ sql`${table.authorityScope} in ('workspace', 'user')`,
9253
+ ),
9254
+ authority: foreignKey({
9255
+ name: "rigs_authority_fk",
9256
+ columns: [table.authorityId, table.accountId, table.ownerOrganizationMembershipId],
9257
+ foreignColumns: [
9258
+ organizationUserResourceAuthorities.id,
9259
+ organizationUserResourceAuthorities.accountId,
9260
+ organizationUserResourceAuthorities.organizationMembershipId,
9261
+ ],
9262
+ }).onDelete("restrict"),
9263
+ // Migration 0230 owns the origin-workspace FK's column-subset SET NULL.
8153
9264
  }),
8154
9265
  );
8155
9266
 
@@ -8251,9 +9362,11 @@ export const rigChanges = pgTable(
8251
9362
  export * from "./workspace-instruction-policies-schema";
8252
9363
  export * from "./company-profile-schema";
8253
9364
  export * from "./workspace-learning-policy-schema";
9365
+ export * from "./slack-task-policy-schema";
8254
9366
  export * from "./preference-registry-schema";
8255
9367
  export * from "./memory-governance-schema";
8256
9368
  export * from "./scoped-knowledge-schema";
9369
+ export * from "./task-notes-schema";
8257
9370
  export * from "./knowledge-source-sync-schema";
8258
9371
  export * from "./transcription-recordings-schema";
8259
9372
  export * from "./interaction-schema";