@opengeni/db 0.16.2 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -86,9 +86,16 @@ export const FORCE_RLS_TABLES = [
86
86
  "sessions",
87
87
  "slack_bot_delete_operations",
88
88
  "slack_bot_post_operations",
89
+ "slack_bot_user_links",
90
+ "slack_interaction_inbox",
91
+ "slack_interaction_progress_deliveries",
92
+ "slack_interactions",
89
93
  "social_connections",
90
94
  "social_posts",
91
95
  "usage_events",
96
+ "workspace_artifact_events",
97
+ "workspace_artifact_versions",
98
+ "workspace_artifacts",
92
99
  "workspace_captures",
93
100
  "workspace_control_events",
94
101
  "workspace_inference_controls",
@@ -198,10 +205,15 @@ export const RUNTIME_FULL_DML_TABLES = [
198
205
  "sessions",
199
206
  "slack_bot_delete_operations",
200
207
  "slack_bot_post_operations",
208
+ "slack_bot_user_links",
209
+ "slack_interaction_inbox",
210
+ "slack_interaction_progress_deliveries",
211
+ "slack_interactions",
201
212
  "social_connections",
202
213
  "social_posts",
203
214
  "stripe_webhook_events",
204
215
  "usage_events",
216
+ "workspace_artifacts",
205
217
  "workspace_captures",
206
218
  "workspace_control_events",
207
219
  "workspace_inference_controls",
@@ -227,6 +239,8 @@ export const RUNTIME_READ_INSERT_TABLES = [
227
239
  "preference_registry_preferences",
228
240
  "preference_registry_revisions",
229
241
  "session_spawn_denials",
242
+ "workspace_artifact_events",
243
+ "workspace_artifact_versions",
230
244
  "workspace_instruction_policy_activation_events",
231
245
  "workspace_instruction_policy_revisions",
232
246
  ] as const;
@@ -557,7 +571,11 @@ export async function inspectRuntimeDatabasePosture(
557
571
  and p.prokind in ('f', 'p')
558
572
  order by p.proname, pg_get_function_identity_arguments(p.oid)
559
573
  `),
560
- ).map((row) => ({ name: row.name, owner: row.owner, execute: row.can_execute }));
574
+ ).map((row) => ({
575
+ name: row.name,
576
+ owner: row.owner,
577
+ execute: row.can_execute,
578
+ }));
561
579
 
562
580
  return {
563
581
  identity: mappedIdentity,
package/src/schema.ts CHANGED
@@ -109,6 +109,169 @@ export const workspaces = pgTable(
109
109
  }),
110
110
  );
111
111
 
112
+ // A single generic workspace-published surface. Presentation labels such as
113
+ // app, page, gallery, or document are intentionally not persisted as types.
114
+ export const workspaceArtifacts = pgTable(
115
+ "workspace_artifacts",
116
+ {
117
+ id: uuid("id").primaryKey().defaultRandom(),
118
+ accountId: uuid("account_id")
119
+ .notNull()
120
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
121
+ workspaceId: uuid("workspace_id")
122
+ .notNull()
123
+ .references(() => workspaces.id, { onDelete: "cascade" }),
124
+ slug: text("slug").notNull(),
125
+ title: text("title").notNull(),
126
+ description: text("description"),
127
+ status: text("status").$type<"active" | "archived">().notNull().default("active"),
128
+ // The FK to workspace_artifact_versions is installed by migration after
129
+ // that table exists. Keeping this pointer here makes reads inexpensive.
130
+ currentVersionId: uuid("current_version_id"),
131
+ createdBySubjectId: text("created_by_subject_id").notNull(),
132
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
133
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
134
+ },
135
+ (table) => ({
136
+ workspaceAccount: foreignKey({
137
+ name: "workspace_artifacts_workspace_account_fk",
138
+ columns: [table.workspaceId, table.accountId],
139
+ foreignColumns: [workspaces.id, workspaces.accountId],
140
+ }).onDelete("cascade"),
141
+ workspaceSlug: uniqueIndex("workspace_artifacts_workspace_slug_uq").on(
142
+ table.workspaceId,
143
+ table.slug,
144
+ ),
145
+ workspaceId: uniqueIndex("workspace_artifacts_workspace_id_uq").on(table.workspaceId, table.id),
146
+ list: index("workspace_artifacts_list_idx").on(table.workspaceId, table.updatedAt),
147
+ }),
148
+ );
149
+
150
+ export const workspaceArtifactVersions = pgTable(
151
+ "workspace_artifact_versions",
152
+ {
153
+ id: uuid("id").primaryKey().defaultRandom(),
154
+ accountId: uuid("account_id")
155
+ .notNull()
156
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
157
+ workspaceId: uuid("workspace_id")
158
+ .notNull()
159
+ .references(() => workspaces.id, { onDelete: "cascade" }),
160
+ artifactId: uuid("artifact_id").notNull(),
161
+ revision: integer("revision").notNull(),
162
+ contentKey: text("content_key").notNull(),
163
+ contentType: text("content_type").$type<"text/html">().notNull().default("text/html"),
164
+ contentSha256: text("content_sha256").notNull(),
165
+ sizeBytes: integer("size_bytes").notNull(),
166
+ operationKey: text("operation_key").notNull(),
167
+ sourceSessionId: uuid("source_session_id"),
168
+ sourceTurnId: uuid("source_turn_id"),
169
+ sourceAttemptId: uuid("source_attempt_id"),
170
+ sourceExecutionGeneration: integer("source_execution_generation"),
171
+ createdBySubjectId: text("created_by_subject_id").notNull(),
172
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
173
+ },
174
+ (table) => ({
175
+ workspaceAccount: foreignKey({
176
+ name: "workspace_artifact_versions_workspace_account_fk",
177
+ columns: [table.workspaceId, table.accountId],
178
+ foreignColumns: [workspaces.id, workspaces.accountId],
179
+ }).onDelete("cascade"),
180
+ artifact: foreignKey({
181
+ name: "workspace_artifact_versions_artifact_fk",
182
+ columns: [table.workspaceId, table.artifactId],
183
+ foreignColumns: [workspaceArtifacts.workspaceId, workspaceArtifacts.id],
184
+ }).onDelete("cascade"),
185
+ workspaceId: uniqueIndex("workspace_artifact_versions_workspace_id_uq").on(
186
+ table.workspaceId,
187
+ table.id,
188
+ ),
189
+ revision: uniqueIndex("workspace_artifact_versions_revision_uq").on(
190
+ table.workspaceId,
191
+ table.artifactId,
192
+ table.revision,
193
+ ),
194
+ operation: uniqueIndex("workspace_artifact_versions_operation_uq").on(
195
+ table.workspaceId,
196
+ table.operationKey,
197
+ ),
198
+ provenance: check(
199
+ "workspace_artifact_versions_provenance_chk",
200
+ sql`(
201
+ ${table.sourceSessionId} is null
202
+ and ${table.sourceTurnId} is null
203
+ and ${table.sourceAttemptId} is null
204
+ and ${table.sourceExecutionGeneration} is null
205
+ ) or (
206
+ ${table.sourceSessionId} is not null
207
+ and ${table.sourceTurnId} is not null
208
+ and ${table.sourceAttemptId} is not null
209
+ and ${table.sourceExecutionGeneration} > 0
210
+ )`,
211
+ ),
212
+ }),
213
+ );
214
+
215
+ export const workspaceArtifactEvents = pgTable(
216
+ "workspace_artifact_events",
217
+ {
218
+ id: uuid("id").primaryKey().defaultRandom(),
219
+ accountId: uuid("account_id")
220
+ .notNull()
221
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
222
+ workspaceId: uuid("workspace_id")
223
+ .notNull()
224
+ .references(() => workspaces.id, { onDelete: "cascade" }),
225
+ artifactId: uuid("artifact_id").notNull(),
226
+ type: text("type").$type<"published" | "rolled_back">().notNull(),
227
+ fromVersionId: uuid("from_version_id"),
228
+ toVersionId: uuid("to_version_id").notNull(),
229
+ operationKey: text("operation_key").notNull(),
230
+ sourceSessionId: uuid("source_session_id"),
231
+ sourceTurnId: uuid("source_turn_id"),
232
+ sourceAttemptId: uuid("source_attempt_id"),
233
+ sourceExecutionGeneration: integer("source_execution_generation"),
234
+ actorSubjectId: text("actor_subject_id").notNull(),
235
+ reason: text("reason").notNull(),
236
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
237
+ },
238
+ (table) => ({
239
+ workspaceAccount: foreignKey({
240
+ name: "workspace_artifact_events_workspace_account_fk",
241
+ columns: [table.workspaceId, table.accountId],
242
+ foreignColumns: [workspaces.id, workspaces.accountId],
243
+ }).onDelete("cascade"),
244
+ artifact: foreignKey({
245
+ name: "workspace_artifact_events_artifact_fk",
246
+ columns: [table.workspaceId, table.artifactId],
247
+ foreignColumns: [workspaceArtifacts.workspaceId, workspaceArtifacts.id],
248
+ }).onDelete("cascade"),
249
+ operation: uniqueIndex("workspace_artifact_events_operation_uq").on(
250
+ table.workspaceId,
251
+ table.operationKey,
252
+ ),
253
+ list: index("workspace_artifact_events_list_idx").on(
254
+ table.workspaceId,
255
+ table.artifactId,
256
+ table.createdAt,
257
+ ),
258
+ provenance: check(
259
+ "workspace_artifact_events_provenance_chk",
260
+ sql`(
261
+ ${table.sourceSessionId} is null
262
+ and ${table.sourceTurnId} is null
263
+ and ${table.sourceAttemptId} is null
264
+ and ${table.sourceExecutionGeneration} is null
265
+ ) or (
266
+ ${table.sourceSessionId} is not null
267
+ and ${table.sourceTurnId} is not null
268
+ and ${table.sourceAttemptId} is not null
269
+ and ${table.sourceExecutionGeneration} > 0
270
+ )`,
271
+ ),
272
+ }),
273
+ );
274
+
112
275
  // One target-schema-local deployment fallback. The migration runner reconciles
113
276
  // this singleton from OPENGENI_MAX_NESTED_AGENT_DEPTH; session admission locks
114
277
  // and reads it through the SECURITY DEFINER capability installed by the
@@ -381,12 +544,16 @@ export const codexSubscriptionCredentials = pgTable(
381
544
  // continues to own `version`; quota/cache writes own neither counter.
382
545
  allocatorVersion: integer("allocator_version").notNull().default(1),
383
546
  allocatorUpdatedBySubjectId: text("allocator_updated_by_subject_id"),
384
- allocatorUpdatedAt: timestamp("allocator_updated_at", { withTimezone: true }),
547
+ allocatorUpdatedAt: timestamp("allocator_updated_at", {
548
+ withTimezone: true,
549
+ }),
385
550
  // Authoritative count-only summary cached from /wham/usage. Detailed rows
386
551
  // are never persisted as redemption authority; every first POST preflights
387
552
  // the provider's fresh detail endpoint.
388
553
  resetCreditAvailableCount: integer("reset_credit_available_count"),
389
- resetCreditsCheckedAt: timestamp("reset_credits_checked_at", { withTimezone: true }),
554
+ resetCreditsCheckedAt: timestamp("reset_credits_checked_at", {
555
+ withTimezone: true,
556
+ }),
390
557
  // Set only by a direct Better Auth cookie connection/reconnection. Legacy,
391
558
  // configured, delegated, API-key, and agent-created rows remain view-only.
392
559
  connectedBySubjectId: text("connected_by_subject_id"),
@@ -436,7 +603,9 @@ export const codexResetRedemptionAttempts = pgTable(
436
603
  outcome: text("outcome"),
437
604
  claimHolderId: uuid("claim_holder_id"),
438
605
  claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
439
- confirmationExpiresAt: timestamp("confirmation_expires_at", { withTimezone: true }).notNull(),
606
+ confirmationExpiresAt: timestamp("confirmation_expires_at", {
607
+ withTimezone: true,
608
+ }).notNull(),
440
609
  providerStartedAt: timestamp("provider_started_at", { withTimezone: true }),
441
610
  completedAt: timestamp("completed_at", { withTimezone: true }),
442
611
  lastFailureKind: text("last_failure_kind"),
@@ -544,6 +713,200 @@ export const connections = pgTable(
544
713
  }),
545
714
  );
546
715
 
716
+ export const slackBotUserLinks = pgTable(
717
+ "slack_bot_user_links",
718
+ {
719
+ id: uuid("id").primaryKey().defaultRandom(),
720
+ accountId: uuid("account_id")
721
+ .notNull()
722
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
723
+ workspaceId: uuid("workspace_id")
724
+ .notNull()
725
+ .references(() => workspaces.id, { onDelete: "cascade" }),
726
+ connectionId: uuid("connection_id")
727
+ .notNull()
728
+ .references(() => connections.id, { onDelete: "cascade" }),
729
+ slackTeamId: text("slack_team_id").notNull(),
730
+ slackUserId: text("slack_user_id").notNull(),
731
+ subjectId: text("subject_id").notNull(),
732
+ linkedBySubjectId: text("linked_by_subject_id").notNull(),
733
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
734
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
735
+ },
736
+ (table) => ({
737
+ connectionUser: uniqueIndex("slack_bot_user_links_connection_user_uq").on(
738
+ table.connectionId,
739
+ table.slackUserId,
740
+ ),
741
+ workspaceSubject: index("slack_bot_user_links_workspace_subject_idx").on(
742
+ table.workspaceId,
743
+ table.subjectId,
744
+ ),
745
+ }),
746
+ );
747
+
748
+ export const slackInteractionInbox = pgTable(
749
+ "slack_interaction_inbox",
750
+ {
751
+ id: uuid("id").primaryKey().defaultRandom(),
752
+ accountId: uuid("account_id")
753
+ .notNull()
754
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
755
+ workspaceId: uuid("workspace_id")
756
+ .notNull()
757
+ .references(() => workspaces.id, { onDelete: "cascade" }),
758
+ connectionId: uuid("connection_id")
759
+ .notNull()
760
+ .references(() => connections.id, { onDelete: "cascade" }),
761
+ providerEventId: text("provider_event_id").notNull(),
762
+ providerMessageId: text("provider_message_id").notNull(),
763
+ slackTeamId: text("slack_team_id").notNull(),
764
+ slackUserId: text("slack_user_id").notNull(),
765
+ slackChannelId: text("slack_channel_id").notNull(),
766
+ slackMessageTs: text("slack_message_ts").notNull(),
767
+ slackThreadTs: text("slack_thread_ts"),
768
+ triggerKind: text("trigger_kind")
769
+ .$type<"app_mention" | "dm" | "slash_command" | "message_shortcut" | "thread_reply">()
770
+ .notNull(),
771
+ text: text("text").notNull(),
772
+ status: text("status")
773
+ .$type<"pending" | "processing" | "processed" | "failed">()
774
+ .notNull()
775
+ .default("pending"),
776
+ claimHolderId: uuid("claim_holder_id"),
777
+ claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
778
+ attemptCount: integer("attempt_count").notNull().default(0),
779
+ retryAt: timestamp("retry_at", { withTimezone: true }),
780
+ lastErrorCode: text("last_error_code"),
781
+ processedAt: timestamp("processed_at", { withTimezone: true }),
782
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
783
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
784
+ },
785
+ (table) => ({
786
+ providerEvent: uniqueIndex("slack_interaction_inbox_provider_event_uq").on(
787
+ table.connectionId,
788
+ table.providerEventId,
789
+ ),
790
+ providerMessage: uniqueIndex("slack_interaction_inbox_provider_message_uq").on(
791
+ table.connectionId,
792
+ table.providerMessageId,
793
+ ),
794
+ pending: index("slack_interaction_inbox_pending_idx").on(
795
+ table.status,
796
+ table.retryAt,
797
+ table.createdAt,
798
+ table.id,
799
+ ),
800
+ }),
801
+ );
802
+
803
+ export const slackInteractions = pgTable(
804
+ "slack_interactions",
805
+ {
806
+ id: uuid("id").primaryKey().defaultRandom(),
807
+ accountId: uuid("account_id")
808
+ .notNull()
809
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
810
+ workspaceId: uuid("workspace_id")
811
+ .notNull()
812
+ .references(() => workspaces.id, { onDelete: "cascade" }),
813
+ connectionId: uuid("connection_id")
814
+ .notNull()
815
+ .references(() => connections.id, { onDelete: "cascade" }),
816
+ slackTeamId: text("slack_team_id").notNull(),
817
+ slackChannelId: text("slack_channel_id").notNull(),
818
+ slackThreadTs: text("slack_thread_ts").notNull(),
819
+ routeKey: text("route_key").notNull(),
820
+ triggeringProviderEventId: text("triggering_provider_event_id").notNull(),
821
+ owningSubjectId: text("owning_subject_id").notNull(),
822
+ visibility: text("visibility").$type<"private" | "workspace">().notNull(),
823
+ sessionReservationId: uuid("session_reservation_id").notNull().defaultRandom(),
824
+ sessionId: uuid("session_id").references(() => sessions.id, {
825
+ onDelete: "cascade",
826
+ }),
827
+ lastDeliveredSessionEventSequence: integer("last_delivered_session_event_sequence")
828
+ .notNull()
829
+ .default(0),
830
+ deliveryClaimHolderId: uuid("delivery_claim_holder_id"),
831
+ deliveryClaimExpiresAt: timestamp("delivery_claim_expires_at", {
832
+ withTimezone: true,
833
+ }),
834
+ deliveryAttemptCount: integer("delivery_attempt_count").notNull().default(0),
835
+ deliveryRetryAt: timestamp("delivery_retry_at", { withTimezone: true }),
836
+ deliveryLastErrorCode: text("delivery_last_error_code"),
837
+ ackSlackMessageTs: text("ack_slack_message_ts"),
838
+ progressCount: integer("progress_count").notNull().default(0),
839
+ terminalDeliveryState: text("terminal_delivery_state")
840
+ .$type<"open" | "completed" | "failed" | "cancelled" | "blocked">()
841
+ .notNull()
842
+ .default("open"),
843
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
844
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
845
+ },
846
+ (table) => ({
847
+ route: uniqueIndex("slack_interactions_route_uq").on(table.connectionId, table.routeKey),
848
+ identity: uniqueIndex("slack_interactions_identity_uq").on(
849
+ table.accountId,
850
+ table.workspaceId,
851
+ table.id,
852
+ ),
853
+ workspaceReservation: uniqueIndex("slack_interactions_workspace_reservation_uq").on(
854
+ table.workspaceId,
855
+ table.sessionReservationId,
856
+ ),
857
+ workspaceSession: uniqueIndex("slack_interactions_workspace_session_uq")
858
+ .on(table.workspaceId, table.sessionId)
859
+ .where(sql`${table.sessionId} is not null`),
860
+ delivery: index("slack_interactions_delivery_idx").on(
861
+ table.terminalDeliveryState,
862
+ table.deliveryRetryAt,
863
+ table.updatedAt,
864
+ table.id,
865
+ ),
866
+ }),
867
+ );
868
+
869
+ export const slackInteractionProgressDeliveries = pgTable(
870
+ "slack_interaction_progress_deliveries",
871
+ {
872
+ id: uuid("id").primaryKey().defaultRandom(),
873
+ accountId: uuid("account_id")
874
+ .notNull()
875
+ .references(() => managedAccounts.id, { onDelete: "cascade" }),
876
+ workspaceId: uuid("workspace_id")
877
+ .notNull()
878
+ .references(() => workspaces.id, { onDelete: "cascade" }),
879
+ interactionId: uuid("interaction_id").notNull(),
880
+ sessionEventSequence: integer("session_event_sequence").notNull(),
881
+ slot: integer("slot").notNull(),
882
+ operationId: uuid("operation_id").notNull(),
883
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
884
+ },
885
+ (table) => ({
886
+ interactionIdentity: foreignKey({
887
+ columns: [table.accountId, table.workspaceId, table.interactionId],
888
+ foreignColumns: [
889
+ slackInteractions.accountId,
890
+ slackInteractions.workspaceId,
891
+ slackInteractions.id,
892
+ ],
893
+ name: "slack_interaction_progress_deliveries_interaction_fk",
894
+ }).onDelete("cascade"),
895
+ event: uniqueIndex("slack_interaction_progress_deliveries_event_uq").on(
896
+ table.interactionId,
897
+ table.sessionEventSequence,
898
+ ),
899
+ slot: uniqueIndex("slack_interaction_progress_deliveries_slot_uq").on(
900
+ table.interactionId,
901
+ table.slot,
902
+ ),
903
+ operation: uniqueIndex("slack_interaction_progress_deliveries_operation_uq").on(
904
+ table.workspaceId,
905
+ table.operationId,
906
+ ),
907
+ }),
908
+ );
909
+
547
910
  // Durable provider-operation identity for OpenGeni Slack bot posts. The
548
911
  // caller-supplied operation UUID is also Slack's client_msg_id; a bounded claim
549
912
  // serializes live attempts while an expired/released claim can safely retry the
@@ -2234,10 +2597,14 @@ export const sessionGoals = pgTable(
2234
2597
  // update, timeline events, usage row, and workflow-wake outbox row.
2235
2598
  // Temporal signals and workflow history are replaceable nudges over these
2236
2599
  // monotonic revisions.
2237
- continuationWakeRevision: bigint("continuation_wake_revision", { mode: "number" })
2600
+ continuationWakeRevision: bigint("continuation_wake_revision", {
2601
+ mode: "number",
2602
+ })
2238
2603
  .notNull()
2239
2604
  .default(0),
2240
- continuationObservedRevision: bigint("continuation_observed_revision", { mode: "number" })
2605
+ continuationObservedRevision: bigint("continuation_observed_revision", {
2606
+ mode: "number",
2607
+ })
2241
2608
  .notNull()
2242
2609
  .default(0),
2243
2610
  metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
@@ -2911,8 +3278,12 @@ export const sandboxLeases = pgTable(
2911
3278
  lastMeterTick: integer("last_meter_tick").notNull().default(0),
2912
3279
 
2913
3280
  providerCreatedAt: timestamp("provider_created_at", { withTimezone: true }),
2914
- providerDeadlineAt: timestamp("provider_deadline_at", { withTimezone: true }),
2915
- rotationRequestedAt: timestamp("rotation_requested_at", { withTimezone: true }),
3281
+ providerDeadlineAt: timestamp("provider_deadline_at", {
3282
+ withTimezone: true,
3283
+ }),
3284
+ rotationRequestedAt: timestamp("rotation_requested_at", {
3285
+ withTimezone: true,
3286
+ }),
2916
3287
  rotationReason: text("rotation_reason", {
2917
3288
  enum: ["provider_deadline", "operator"],
2918
3289
  }),
@@ -3017,7 +3388,9 @@ export const sandboxLeaseHolders = pgTable(
3017
3388
  leaseId: uuid("lease_id")
3018
3389
  .notNull()
3019
3390
  .references(() => sandboxLeases.id, { onDelete: "cascade" }),
3020
- kind: text("kind", { enum: ["turn", "viewer", "direct", "process"] }).notNull(),
3391
+ kind: text("kind", {
3392
+ enum: ["turn", "viewer", "direct", "process"],
3393
+ }).notNull(),
3021
3394
  holderId: text("holder_id").notNull(),
3022
3395
  // The attributing session within the (possibly shared) group.
3023
3396
  subjectId: uuid("subject_id"),
@@ -3062,7 +3435,9 @@ export const sandboxWorkspaceMutationAdmissions = pgTable(
3062
3435
  .references(() => sandboxLeases.id, { onDelete: "cascade" }),
3063
3436
  sandboxGroupId: uuid("sandbox_group_id").notNull(),
3064
3437
  sessionId: uuid("session_id").notNull(),
3065
- actorKind: text("actor_kind", { enum: sandboxWorkspaceMutationActorKindValues }).notNull(),
3438
+ actorKind: text("actor_kind", {
3439
+ enum: sandboxWorkspaceMutationActorKindValues,
3440
+ }).notNull(),
3066
3441
  actorId: uuid("actor_id").notNull(),
3067
3442
  // Exact turn authority is present only for actor_kind='turn'. Direct HTTP
3068
3443
  // requests and retained processes never invent a turn or quiescence owner.
@@ -3209,7 +3584,9 @@ export const sandboxRetainedProcesses = pgTable(
3209
3584
  sandboxGroupId: uuid("sandbox_group_id").notNull(),
3210
3585
  parentAdmissionId: uuid("parent_admission_id").notNull(),
3211
3586
  holderId: text("holder_id").notNull(),
3212
- ownerActorKind: text("owner_actor_kind", { enum: ["turn", "direct"] }).notNull(),
3587
+ ownerActorKind: text("owner_actor_kind", {
3588
+ enum: ["turn", "direct"],
3589
+ }).notNull(),
3213
3590
  ownerActorId: uuid("owner_actor_id").notNull(),
3214
3591
  ownerTurnId: uuid("owner_turn_id"),
3215
3592
  ownerAttemptId: uuid("owner_attempt_id"),
@@ -3237,13 +3614,19 @@ export const sandboxRetainedProcesses = pgTable(
3237
3614
  // never exit/loss proof.
3238
3615
  reconcileAfter: timestamp("reconcile_after", { withTimezone: true }).notNull().defaultNow(),
3239
3616
  reconcileClaimId: uuid("reconcile_claim_id"),
3240
- reconcileClaimedAt: timestamp("reconcile_claimed_at", { withTimezone: true }),
3617
+ reconcileClaimedAt: timestamp("reconcile_claimed_at", {
3618
+ withTimezone: true,
3619
+ }),
3241
3620
  reconcileAttempts: integer("reconcile_attempts").notNull().default(0),
3242
3621
  lastReconcileOutcome: text("last_reconcile_outcome"),
3243
- reconcileProofOutcome: text("reconcile_proof_outcome", { enum: ["exited", "lost"] }),
3622
+ reconcileProofOutcome: text("reconcile_proof_outcome", {
3623
+ enum: ["exited", "lost"],
3624
+ }),
3244
3625
  reconcileProofExitCode: integer("reconcile_proof_exit_code"),
3245
3626
  reconcileProofReason: text("reconcile_proof_reason"),
3246
- reconcileProofObservedAt: timestamp("reconcile_proof_observed_at", { withTimezone: true }),
3627
+ reconcileProofObservedAt: timestamp("reconcile_proof_observed_at", {
3628
+ withTimezone: true,
3629
+ }),
3247
3630
  },
3248
3631
  (table) => ({
3249
3632
  workspaceAccount: foreignKey({
@@ -3995,8 +4378,12 @@ export const githubInstallations = pgTable(
3995
4378
  githubActorId: bigint("github_actor_id", { mode: "number" }),
3996
4379
  githubActorLogin: text("github_actor_login"),
3997
4380
  authorityKind: text("authority_kind"),
3998
- authorityCheckedAt: timestamp("authority_checked_at", { withTimezone: true }),
3999
- authorityExpiresAt: timestamp("authority_expires_at", { withTimezone: true }),
4381
+ authorityCheckedAt: timestamp("authority_checked_at", {
4382
+ withTimezone: true,
4383
+ }),
4384
+ authorityExpiresAt: timestamp("authority_expires_at", {
4385
+ withTimezone: true,
4386
+ }),
4000
4387
  authorityNonce: text("authority_nonce"),
4001
4388
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4002
4389
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
@@ -4326,7 +4713,9 @@ export const hostExportOutbox = pgTable(
4326
4713
  payload: jsonb("payload").$type<unknown>().notNull(),
4327
4714
  envelopeBytes: integer("envelope_bytes").notNull(),
4328
4715
  occurredAt: timestamp("occurred_at", { withTimezone: true }).notNull(),
4329
- sourceRecordedAt: timestamp("source_recorded_at", { withTimezone: true }).notNull(),
4716
+ sourceRecordedAt: timestamp("source_recorded_at", {
4717
+ withTimezone: true,
4718
+ }).notNull(),
4330
4719
  enqueuedAt: timestamp("enqueued_at", { withTimezone: true }).notNull(),
4331
4720
  },
4332
4721
  (table) => ({
@@ -4736,6 +5125,10 @@ export const socialConnections = pgTable(
4736
5125
  status: text("status").notNull().default("connected"),
4737
5126
  scopes: jsonb("scopes").$type<string[]>().notNull().default([]),
4738
5127
  credentialRef: text("credential_ref"),
5128
+ // AES-256-GCM envelope (environment-crypto v1 format) holding the OAuth
5129
+ // token bundle. Never exposed through contracts or MCP tools; only the
5130
+ // host-side social API client decrypts it.
5131
+ credentialEncrypted: text("credential_encrypted"),
4739
5132
  tokenMetadata: jsonb("token_metadata").$type<Record<string, unknown>>().notNull().default({}),
4740
5133
  metadata: jsonb("metadata").$type<Record<string, unknown>>().notNull().default({}),
4741
5134
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),