@opengeni/db 1.0.1 → 3.2.0-canary.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.
- package/dist/attached-browser-devices.d.ts +7 -0
- package/dist/automations.d.ts +154 -0
- package/dist/canonical-human-identities.js +3 -3
- package/dist/capability-integrations.d.ts +13 -0
- package/dist/child-lifecycle-notices.d.ts +68 -0
- package/dist/{chunk-4SR4HKKA.js → chunk-2EH4WRHL.js} +19 -11
- package/dist/chunk-2EH4WRHL.js.map +1 -0
- package/dist/{chunk-CUPM3FGB.js → chunk-2PRS4J5Q.js} +3 -3
- package/dist/chunk-6HMM2R5T.js +390 -0
- package/dist/chunk-6HMM2R5T.js.map +1 -0
- package/dist/{chunk-ZWREYEWA.js → chunk-AZHW7R5V.js} +56 -11
- package/dist/chunk-AZHW7R5V.js.map +1 -0
- package/dist/{chunk-LTG3S6ZY.js → chunk-E6CLMKEE.js} +2 -2
- package/dist/{chunk-6ZYKCRFO.js → chunk-KRLPEMLH.js} +7591 -4417
- package/dist/chunk-KRLPEMLH.js.map +1 -0
- package/dist/chunk-NAB6FKFN.js +516 -0
- package/dist/chunk-NAB6FKFN.js.map +1 -0
- package/dist/{chunk-SK7YYHBI.js → chunk-SIBYBA2D.js} +46 -1
- package/dist/chunk-SIBYBA2D.js.map +1 -0
- package/dist/chunk-UZNXG44K.js +4508 -0
- package/dist/chunk-UZNXG44K.js.map +1 -0
- package/dist/codemode-operations.d.ts +1 -6
- package/dist/company-brain-context-selection-schema.d.ts +705 -0
- package/dist/company-brain-context-selection.d.ts +94 -0
- package/dist/company-brain-governed-writes.d.ts +24 -0
- package/dist/company-brain.d.ts +55 -0
- package/dist/company-profile-agent-admin.d.ts +15 -0
- package/dist/company-profile-schema.d.ts +619 -2
- package/dist/company-profile.d.ts +9 -4
- package/dist/connection-authority.d.ts +95 -0
- package/dist/connection-scopes.d.ts +8 -0
- package/dist/connection-tenancy-backfill.d.ts +85 -0
- package/dist/connection-token-resolver.d.ts +30 -1
- package/dist/database.d.ts +23 -4
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.d.ts +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation-schema.d.ts +984 -0
- package/dist/governed-learning-activation.d.ts +98 -0
- package/dist/governed-learning-evaluator-schema.d.ts +633 -0
- package/dist/governed-learning-evaluator.d.ts +28 -0
- package/dist/index.d.ts +1606 -81
- package/dist/index.js +21898 -8147
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +18 -0
- package/dist/integration-bindings.d.ts +1 -0
- package/dist/integration-facets.d.ts +30 -0
- package/dist/interaction-placement-loss.d.ts +22 -0
- package/dist/managed-human-provisioning.d.ts +25 -0
- package/dist/memory-domain.d.ts +3 -3
- package/dist/migrate.d.ts +11 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +43 -5
- package/dist/organization-membership-backfill.d.ts +174 -0
- package/dist/organization-membership-lifecycle.d.ts +162 -0
- package/dist/pr-review.d.ts +107 -0
- package/dist/preference-registry-schema.d.ts +2 -0
- package/dist/preference-registry.d.ts +2 -0
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +29 -8
- package/dist/schema.d.ts +24914 -13703
- package/dist/schema.js +99 -1
- package/dist/scoped-knowledge-schema.d.ts +52 -1
- package/dist/session-background-commands.d.ts +125 -0
- package/dist/session-background-commands.js +34 -0
- package/dist/session-background-commands.js.map +1 -0
- package/dist/session-control.d.ts +156 -3
- package/dist/session-goal-pacing.d.ts +68 -0
- package/dist/session-queue-commands.d.ts +43 -4
- package/dist/session-realtime-ledger.d.ts +2 -0
- package/dist/session-tenancy.d.ts +71 -1
- package/dist/session-tenancy.js +25 -3
- package/dist/session-tool-call-settlement.d.ts +9 -4
- package/dist/slack-routing-personal-workspace.d.ts +23 -0
- package/dist/slack-routing.d.ts +268 -0
- package/dist/slack-task-policy-schema.d.ts +34 -0
- package/dist/slack-task-policy.d.ts +8 -0
- package/dist/slack-user-link-access.d.ts +28 -0
- package/dist/task-notes-schema.d.ts +594 -0
- package/dist/task-notes.d.ts +39 -0
- package/dist/turn-initiator.d.ts +2 -0
- package/dist/user-resource-authority.d.ts +109 -0
- package/dist/video-generation.js +3 -3
- package/dist/workspace-authority.d.ts +81 -0
- package/dist/workspace-instruction-policies-schema.d.ts +279 -0
- package/dist/workspace-instruction-policies.d.ts +62 -0
- package/dist/workspace-learning-policy.d.ts +1 -0
- package/dist/workspace-membership-permissions.d.ts +2 -0
- package/drizzle/0240_enrollment_connection_authority.sql +39 -0
- package/drizzle/0241_atomic_personal_resource_delegation.sql +1000 -0
- package/drizzle/0241_enrollment_agent_runtime.sql +70 -0
- package/drizzle/0244_slack_app_home_refresh_queue.sql +120 -0
- package/drizzle/0245_model_context_contribution_facts.sql +88 -0
- package/drizzle/0246_integration_personal_instance_authority.sql +70 -0
- package/drizzle/0247_terraform_stacks_provenance_repair.sql +428 -0
- package/drizzle/0248_terraform_stacks_component_resolution_fence.sql +83 -0
- package/drizzle/0249_personal_resource_delegation_authority_correction.sql +662 -0
- package/drizzle/0250_direct_retained_process_owner_liveness.sql +199 -0
- package/drizzle/0251_connected_machine_operation_policy.sql +45 -0
- package/drizzle/0252_scheduled_personal_resource_delegation.sql +1867 -0
- package/drizzle/0253_common_user_resource_authority_lifecycle.sql +1555 -0
- package/drizzle/0254_scoped_variable_set_authority.sql +1255 -0
- package/drizzle/0255_company_brain_governed_write_proposals.sql +524 -0
- package/drizzle/0256_connection_authority_delegation.sql +703 -0
- package/drizzle/0257_goal_revision_decisions_and_root_constraints.sql +436 -0
- package/drizzle/0258_three_scope_document_knowledge_authority.sql +1273 -0
- package/drizzle/0259_company_brain_context_selection_receipts.sql +869 -0
- package/drizzle/0260_task_note_knowledge_promotion.sql +820 -0
- package/drizzle/0261_preference_knowledge_proposal_actor_binding.sql +471 -0
- package/drizzle/0262_scoped_connected_machines_and_rigs.sql +1700 -0
- package/drizzle/0263_organization_membership_lifecycle.sql +3284 -0
- package/drizzle/0264_connection_authority_runtime_activation.sql +1084 -0
- package/drizzle/0266_company_brain_context_receipt_inspection.sql +156 -0
- package/drizzle/0268_governed_learning_decision_receipts.sql +825 -0
- package/drizzle/0269_governed_learning_activation_controller.sql +1874 -0
- package/drizzle/0270_governed_learning_history_inspection.sql +170 -0
- package/drizzle/0271_company_brain_retrieval_only_default.sql +524 -0
- package/drizzle/0272_human_confirmed_learning_activation.sql +591 -0
- package/drizzle/0273_scheduled_variable_set_materialization.sql +268 -0
- package/drizzle/0274_human_confirmed_knowledge_review.sql +310 -0
- package/drizzle/0275_scheduled_connection_authority.sql +5527 -0
- package/drizzle/0276_onboarding_proposal_initiating_human_guc.sql +198 -0
- package/drizzle/0277_workspace_writer_authority_attribution.sql +393 -0
- package/drizzle/0278_workspace_membership_removal_fencing.sql +1174 -0
- package/drizzle/0279_workspace_connection_use_lane.sql +343 -0
- package/drizzle/0280_connection_and_variable_set_audit_attribution.sql +773 -0
- package/drizzle/0281_viewer_holder_authority_claims.sql +52 -0
- package/drizzle/0282_variable_set_session_attach_attribution.sql +178 -0
- package/drizzle/0283_editable_spreadsheet_authored_state.sql +82 -0
- package/drizzle/0284_truthful_human_confirmed_review_reason.sql +930 -0
- package/drizzle/0285_organization_tenancy_inventory.sql +329 -0
- package/drizzle/0286_widen_task_note_expiry_ceiling.sql +391 -0
- package/drizzle/0287_open_suffix_pending_tool_calls.sql +18 -0
- package/drizzle/0288_attached_browser_reenrollment.sql +64 -0
- package/drizzle/0289_session_composer_policy_authority.sql +597 -0
- package/drizzle/0290_organization_membership_backfill.sql +268 -0
- package/drizzle/0291_resource_authority_classification_assertion.sql +371 -0
- package/drizzle/0292_truthful_tenancy_inventory_counters.sql +291 -0
- package/drizzle/0293_confirm_time_rule_rebaseline.sql +615 -0
- package/drizzle/0294_preference_activation_authority.sql +237 -0
- package/drizzle/0295_retire_legacy_standing_memory_mode.sql +476 -0
- package/drizzle/0296_force_rls_backfill_noop_repair.sql +215 -0
- package/drizzle/0297_session_ownership_classification_and_backfill.sql +752 -0
- package/drizzle/0298_organization_tenancy_parity.sql +609 -0
- package/drizzle/0299_organization_membership_lock_order.sql +291 -0
- package/drizzle/0300_tenancy_backfill_ledger.sql +459 -0
- package/drizzle/0301_session_snapshot_and_pin_visibility.sql +181 -0
- package/drizzle/0302_personal_workspace_session_ownership.sql +303 -0
- package/drizzle/0303_session_tenancy_product_activation.sql +919 -0
- package/drizzle/0304_personal_workspace_private_session_reads.sql +97 -0
- package/drizzle/0305_personal_resource_grant_management.sql +584 -0
- package/drizzle/0306_atomic_personal_resource_attachments.sql +1374 -0
- package/drizzle/0307_session_attention_state.sql +51 -0
- package/drizzle/0308_session_archives.sql +35 -0
- package/drizzle/0309_channel_project_pins.sql +6 -0
- package/drizzle/0310_channel_project_order.sql +27 -0
- package/drizzle/0311_company_scope_and_private_session_create.sql +656 -0
- package/drizzle/0312_quiescent_session_tree_deletion.sql +39 -0
- package/drizzle/0313_private_child_session_authority.sql +365 -0
- package/drizzle/0314_unregistered_organization_invitations.sql +606 -0
- package/drizzle/0315_personal_github_repository_selection.sql +624 -0
- package/drizzle/0316_human_confirmed_activation_resumed_generation.sql +869 -0
- package/drizzle/0317_session_goal_continuation_hold.sql +64 -0
- package/drizzle/0318_session_turn_startup_milestones.sql +115 -0
- package/drizzle/0319_event_triggered_automations.sql +254 -0
- package/drizzle/0320_pr_review_pack.sql +113 -0
- package/drizzle/0321_slack_bot_environment_display_name.sql +15 -0
- package/drizzle/0322_session_turns_unclaimed_prompt_trigger_index.sql +5 -0
- package/drizzle/0323_organization_private_session_enablement.sql +489 -0
- package/drizzle/0324_human_confirmed_company_profile_agent_admin.sql +856 -0
- package/drizzle/0325_child_lifecycle_notices.sql +44 -0
- package/drizzle/0326_interaction_operation_error_codes.sql +62 -0
- package/drizzle/0327_slack_first_task_hint.sql +29 -0
- package/drizzle/0328_session_background_commands.sql +590 -0
- package/drizzle/0329_slack_orchestration_delivery_events.sql +91 -0
- package/drizzle/0330_api_key_descriptions.sql +20 -0
- package/drizzle/0331_managed_organization_creation.sql +163 -0
- package/drizzle/0332_organization_shared_workspace_control_plane.sql +539 -0
- package/drizzle/0333_session_turn_prompt_routing.sql +45 -0
- package/drizzle/0334_connected_machine_workspace_root.sql +99 -0
- package/drizzle/0335_slack_workspace_routing.sql +460 -0
- package/drizzle/0336_atomic_session_fork_visibility.sql +667 -0
- package/drizzle/0337_slack_routed_action_handles.sql +189 -0
- package/drizzle/0338_atomic_connected_machine_attachments.sql +410 -0
- package/drizzle/0339_document_authority_reclassification.sql +1153 -0
- package/drizzle/0340_tenancy_backfill_activation_evidence.sql +1347 -0
- package/drizzle/0341_slack_routing_probe_organization_fence.sql +109 -0
- package/drizzle/0342_slack_route_prompt_single_pending.sql +32 -0
- package/drizzle/0343_personal_document_force_rls_lock_repair.sql +146 -0
- package/drizzle/0344_private_session_visibility_transition_gate.sql +85 -0
- package/drizzle/0345_tenant_scoped_session_tenancy_fence.sql +2839 -0
- package/drizzle/0346_document_migration_audit_surface.sql +454 -0
- package/drizzle/0347_connection_authority_convergence_evidence.sql +396 -0
- package/package.json +10 -6
- package/src/attached-browser-devices.ts +233 -5
- package/src/automations.ts +911 -0
- package/src/browser-sessions.ts +10 -0
- package/src/capability-integrations.ts +175 -1
- package/src/child-lifecycle-notices.ts +241 -0
- package/src/codemode-operations.ts +1 -35
- package/src/company-brain-context-selection-schema.ts +100 -0
- package/src/company-brain-context-selection.ts +359 -0
- package/src/company-brain-governed-writes.ts +1170 -0
- package/src/company-brain.ts +309 -0
- package/src/company-profile-agent-admin.ts +225 -0
- package/src/company-profile-schema.ts +121 -1
- package/src/company-profile.ts +21 -0
- package/src/computer-sessions.ts +10 -1
- package/src/connection-authority.ts +290 -0
- package/src/connection-scopes.ts +20 -0
- package/src/connection-tenancy-backfill.ts +167 -0
- package/src/connection-token-resolver.ts +263 -31
- package/src/database.ts +87 -2
- package/src/editable-artifacts-schema.ts +10 -5
- package/src/editable-artifacts.ts +21 -11
- package/src/governed-learning-activation-schema.ts +121 -0
- package/src/governed-learning-activation.ts +588 -0
- package/src/governed-learning-evaluator-schema.ts +72 -0
- package/src/governed-learning-evaluator.ts +217 -0
- package/src/index.ts +11676 -1550
- package/src/insights.ts +107 -0
- package/src/integration-bindings.ts +88 -6
- package/src/integration-facets.ts +287 -84
- package/src/interaction-placement-loss.ts +234 -0
- package/src/managed-human-provisioning.ts +116 -0
- package/src/memory-domain.ts +27 -32
- package/src/migrate.ts +77 -1
- package/src/new-session-drafts.ts +229 -35
- package/src/organization-membership-backfill.ts +735 -0
- package/src/organization-membership-lifecycle.ts +995 -0
- package/src/pr-review.ts +890 -0
- package/src/preference-registry.ts +31 -1
- package/src/provision-roles.ts +905 -6
- package/src/runtime-posture-cli.ts +2 -0
- package/src/runtime-posture.ts +1317 -72
- package/src/schema.ts +3316 -428
- package/src/scoped-knowledge-schema.ts +16 -8
- package/src/scoped-knowledge.ts +1 -1
- package/src/session-background-commands.ts +759 -0
- package/src/session-control.ts +640 -74
- package/src/session-goal-pacing.ts +126 -0
- package/src/session-queue-commands.ts +441 -85
- package/src/session-realtime-context.ts +4 -6
- package/src/session-realtime-ledger.ts +28 -14
- package/src/session-realtime-mirror.ts +1 -1
- package/src/session-tenancy.ts +410 -49
- package/src/session-tool-call-settlement.ts +38 -29
- package/src/slack-routing-personal-workspace.ts +67 -0
- package/src/slack-routing.ts +867 -0
- package/src/slack-task-policy-schema.ts +5 -0
- package/src/slack-task-policy.ts +18 -0
- package/src/slack-user-link-access.ts +138 -11
- package/src/task-notes-schema.ts +74 -0
- package/src/task-notes.ts +124 -2
- package/src/turn-initiator.ts +8 -0
- package/src/user-resource-authority.ts +377 -0
- package/src/workspace-authority.ts +160 -0
- package/src/workspace-instruction-policies-schema.ts +53 -1
- package/src/workspace-instruction-policies.ts +528 -77
- package/src/workspace-learning-policy.ts +21 -5
- package/src/workspace-membership-permissions.ts +9 -0
- package/dist/chunk-4SR4HKKA.js.map +0 -1
- package/dist/chunk-6ZYKCRFO.js.map +0 -1
- package/dist/chunk-NXAFLCQX.js +0 -2468
- package/dist/chunk-NXAFLCQX.js.map +0 -1
- package/dist/chunk-SK7YYHBI.js.map +0 -1
- package/dist/chunk-WD5ROSLL.js +0 -117
- package/dist/chunk-WD5ROSLL.js.map +0 -1
- package/dist/chunk-ZWREYEWA.js.map +0 -1
- /package/dist/{chunk-CUPM3FGB.js.map → chunk-2PRS4J5Q.js.map} +0 -0
- /package/dist/{chunk-LTG3S6ZY.js.map → chunk-E6CLMKEE.js.map} +0 -0
package/src/database.ts
CHANGED
|
@@ -115,6 +115,18 @@ export type RlsStrategy = "force" | "scoped";
|
|
|
115
115
|
*/
|
|
116
116
|
export type UserLookup = (db: Database, email: string) => Promise<string | null>;
|
|
117
117
|
|
|
118
|
+
export type ManagedUserProfile = {
|
|
119
|
+
id: string;
|
|
120
|
+
name: string | null;
|
|
121
|
+
email: string;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/** Host identity projection used by organization administration rosters. */
|
|
125
|
+
export type UserProfileLookup = (
|
|
126
|
+
db: Database,
|
|
127
|
+
userIds: readonly string[],
|
|
128
|
+
) => Promise<ManagedUserProfile[]>;
|
|
129
|
+
|
|
118
130
|
export type CreateDbOptions = {
|
|
119
131
|
/**
|
|
120
132
|
* The Postgres `search_path` for this connection (Step I, §7.8 runtime half).
|
|
@@ -132,6 +144,8 @@ export type CreateDbOptions = {
|
|
|
132
144
|
rlsStrategy?: RlsStrategy;
|
|
133
145
|
/** Host-provided user-by-email resolver; unset → today's raw `auth_users` query. */
|
|
134
146
|
userLookup?: UserLookup;
|
|
147
|
+
/** Host-provided user profile projection; unset → standalone `auth_users`. */
|
|
148
|
+
userProfileLookup?: UserProfileLookup;
|
|
135
149
|
/** postgres-js pool size; defaults to today's `10`. */
|
|
136
150
|
max?: number;
|
|
137
151
|
/**
|
|
@@ -150,7 +164,11 @@ export type CreateDbOptions = {
|
|
|
150
164
|
* config (e.g. one built outside `createDb`, or in a test) falls back to the
|
|
151
165
|
* standalone defaults: `rlsStrategy: "force"`, raw `auth_users` lookup.
|
|
152
166
|
*/
|
|
153
|
-
type DbBinding = {
|
|
167
|
+
type DbBinding = {
|
|
168
|
+
rlsStrategy: RlsStrategy;
|
|
169
|
+
userLookup?: UserLookup;
|
|
170
|
+
userProfileLookup?: UserProfileLookup;
|
|
171
|
+
};
|
|
154
172
|
|
|
155
173
|
const dbBindings = new WeakMap<object, DbBinding>();
|
|
156
174
|
|
|
@@ -314,6 +332,7 @@ export function createDb(databaseUrl: string, options: CreateDbOptions = {}): Db
|
|
|
314
332
|
dbBindings.set(db as unknown as object, {
|
|
315
333
|
rlsStrategy: options.rlsStrategy ?? "force",
|
|
316
334
|
...(options.userLookup ? { userLookup: options.userLookup } : {}),
|
|
335
|
+
...(options.userProfileLookup ? { userProfileLookup: options.userProfileLookup } : {}),
|
|
317
336
|
});
|
|
318
337
|
return {
|
|
319
338
|
db,
|
|
@@ -331,11 +350,16 @@ export function createDb(databaseUrl: string, options: CreateDbOptions = {}): Db
|
|
|
331
350
|
*/
|
|
332
351
|
export function registerDbBinding(
|
|
333
352
|
db: Database,
|
|
334
|
-
binding: {
|
|
353
|
+
binding: {
|
|
354
|
+
rlsStrategy?: RlsStrategy;
|
|
355
|
+
userLookup?: UserLookup;
|
|
356
|
+
userProfileLookup?: UserProfileLookup;
|
|
357
|
+
},
|
|
335
358
|
): void {
|
|
336
359
|
dbBindings.set(db as unknown as object, {
|
|
337
360
|
rlsStrategy: binding.rlsStrategy ?? "force",
|
|
338
361
|
...(binding.userLookup ? { userLookup: binding.userLookup } : {}),
|
|
362
|
+
...(binding.userProfileLookup ? { userProfileLookup: binding.userProfileLookup } : {}),
|
|
339
363
|
});
|
|
340
364
|
}
|
|
341
365
|
|
|
@@ -429,12 +453,18 @@ export async function withRlsContext<T>(
|
|
|
429
453
|
context: RlsContext,
|
|
430
454
|
fn: (db: Database) => Promise<T>,
|
|
431
455
|
transactionConfig?: PgTransactionConfig,
|
|
456
|
+
sessionTenancyFence: "shared" | "none" = "shared",
|
|
432
457
|
): Promise<T> {
|
|
433
458
|
const restoreParentScope = isTransactionHandle(db);
|
|
434
459
|
return await db.transaction(async (tx) => {
|
|
435
460
|
const scoped = tx as unknown as Database;
|
|
436
461
|
const parentScope = restoreParentScope ? await readRlsContextSettings(scoped) : null;
|
|
437
462
|
await setRlsContext(scoped, context);
|
|
463
|
+
if (context.workspaceId && sessionTenancyFence === "shared") {
|
|
464
|
+
await scoped.execute(
|
|
465
|
+
sql`select pg_advisory_xact_lock_shared(hashtextextended(${`session-tenancy:${context.workspaceId}`}, 0))`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
438
468
|
// Defense-in-depth: read the LOCAL GUC back on THIS backend BEFORE running
|
|
439
469
|
// the scoped query. The set_config and this read share one db.transaction,
|
|
440
470
|
// which a transaction pooler pins to a single backend — so a mismatch here
|
|
@@ -662,6 +692,14 @@ async function finalizeSessionActivityGate(
|
|
|
662
692
|
await db.execute(
|
|
663
693
|
sql`set constraints sessions_activity_insert_commit_guard, sessions_activity_update_commit_guard immediate`,
|
|
664
694
|
);
|
|
695
|
+
// A restored activity scope can be followed by another workspace scope, or
|
|
696
|
+
// by a SECURITY DEFINER lifecycle that opens and finalizes its own gate in
|
|
697
|
+
// the same outer transaction. Keep the guards deferred after proving this
|
|
698
|
+
// scope's final state so those later writes reach their own finalizer instead
|
|
699
|
+
// of firing the commit guard at the first session update.
|
|
700
|
+
await db.execute(
|
|
701
|
+
sql`set constraints sessions_activity_insert_commit_guard, sessions_activity_update_commit_guard deferred`,
|
|
702
|
+
);
|
|
665
703
|
}
|
|
666
704
|
|
|
667
705
|
/**
|
|
@@ -674,6 +712,7 @@ export async function withSessionActivityRlsContext<T>(
|
|
|
674
712
|
context: RlsContext & { workspaceId: string },
|
|
675
713
|
fn: (db: SessionActivityDatabase) => Promise<T>,
|
|
676
714
|
transactionConfig?: PgTransactionConfig,
|
|
715
|
+
fenceMode: "shared" | "none" = "shared",
|
|
677
716
|
): Promise<T> {
|
|
678
717
|
await assertSessionActivityGateEntry(db);
|
|
679
718
|
return await withRlsContext(
|
|
@@ -692,6 +731,7 @@ export async function withSessionActivityRlsContext<T>(
|
|
|
692
731
|
return value;
|
|
693
732
|
},
|
|
694
733
|
transactionConfig,
|
|
734
|
+
fenceMode,
|
|
695
735
|
);
|
|
696
736
|
}
|
|
697
737
|
|
|
@@ -709,6 +749,47 @@ export async function withWorkspaceSessionActivityRls<T>(
|
|
|
709
749
|
);
|
|
710
750
|
}
|
|
711
751
|
|
|
752
|
+
/**
|
|
753
|
+
* Run one of several ordered workspace activity scopes inside a caller-owned
|
|
754
|
+
* transaction. Each scope is fully finalized before restoring the caller's
|
|
755
|
+
* gate GUCs, so the next workspace can reuse the same outer transaction.
|
|
756
|
+
*/
|
|
757
|
+
export async function withRestoredSessionActivityRlsContext<T>(
|
|
758
|
+
db: Database,
|
|
759
|
+
context: RlsContext & { workspaceId: string },
|
|
760
|
+
fn: (db: SessionActivityDatabase) => Promise<T>,
|
|
761
|
+
): Promise<T> {
|
|
762
|
+
if (!isTransactionHandle(db)) {
|
|
763
|
+
throw new Error("Sequential workspace activity scopes require a caller-owned transaction");
|
|
764
|
+
}
|
|
765
|
+
const [prior] = await rawRows<{ state: string; workspace_id: string }>(
|
|
766
|
+
db,
|
|
767
|
+
sql`select
|
|
768
|
+
coalesce(current_setting('opengeni.session_activity_gate_state', true), '') as state,
|
|
769
|
+
coalesce(
|
|
770
|
+
current_setting('opengeni.session_activity_gate_workspace_id', true), ''
|
|
771
|
+
) as workspace_id`,
|
|
772
|
+
);
|
|
773
|
+
try {
|
|
774
|
+
return await withRlsContext(db, context, async (scopedDb) => {
|
|
775
|
+
const gate = await beginSessionActivityGate(scopedDb, context.workspaceId);
|
|
776
|
+
if (!gate.owner) {
|
|
777
|
+
throw new Error("Sequential workspace activity scope unexpectedly reused an open gate");
|
|
778
|
+
}
|
|
779
|
+
const value = await fn(gate.db);
|
|
780
|
+
await assertRlsContextApplied(gate.db, context);
|
|
781
|
+
await finalizeSessionActivityGate(gate.db, context.workspaceId);
|
|
782
|
+
return value;
|
|
783
|
+
});
|
|
784
|
+
} finally {
|
|
785
|
+
await db.execute(sql`select
|
|
786
|
+
set_config('opengeni.session_activity_gate_state', ${prior?.state ?? ""}, true),
|
|
787
|
+
set_config(
|
|
788
|
+
'opengeni.session_activity_gate_workspace_id', ${prior?.workspace_id ?? ""}, true
|
|
789
|
+
)`);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
712
793
|
/**
|
|
713
794
|
* Open one nested savepoint without losing the gate brand. Drizzle correctly
|
|
714
795
|
* preserves the backend-local gate GUCs, but its structural transaction type
|
|
@@ -765,6 +846,7 @@ export async function withWorkspaceSubjectRls<T>(
|
|
|
765
846
|
subjectId: string,
|
|
766
847
|
fn: (db: Database) => Promise<T>,
|
|
767
848
|
transactionConfig?: PgTransactionConfig,
|
|
849
|
+
sessionTenancyFence: "shared" | "none" = "shared",
|
|
768
850
|
): Promise<T> {
|
|
769
851
|
if (!subjectId.trim()) {
|
|
770
852
|
throw new Error("withWorkspaceSubjectRls: a non-empty subjectId is required");
|
|
@@ -778,6 +860,7 @@ export async function withWorkspaceSubjectRls<T>(
|
|
|
778
860
|
return await fn(scopedDb);
|
|
779
861
|
},
|
|
780
862
|
transactionConfig,
|
|
863
|
+
sessionTenancyFence,
|
|
781
864
|
);
|
|
782
865
|
}
|
|
783
866
|
|
|
@@ -787,6 +870,7 @@ export async function withWorkspaceSubjectSessionActivityRls<T>(
|
|
|
787
870
|
subjectId: string,
|
|
788
871
|
fn: (db: SessionActivityDatabase) => Promise<T>,
|
|
789
872
|
transactionConfig?: PgTransactionConfig,
|
|
873
|
+
fenceMode: "shared" | "none" = "shared",
|
|
790
874
|
): Promise<T> {
|
|
791
875
|
if (!subjectId.trim()) {
|
|
792
876
|
throw new Error("withWorkspaceSubjectSessionActivityRls: a non-empty subjectId is required");
|
|
@@ -800,6 +884,7 @@ export async function withWorkspaceSubjectSessionActivityRls<T>(
|
|
|
800
884
|
return await fn(scopedDb);
|
|
801
885
|
},
|
|
802
886
|
transactionConfig,
|
|
887
|
+
fenceMode,
|
|
803
888
|
);
|
|
804
889
|
}
|
|
805
890
|
|
|
@@ -272,7 +272,6 @@ export const editableArtifactTransactions = pgTable(
|
|
|
272
272
|
and ${table.intentHash} = ${table.requestHash}
|
|
273
273
|
and ${table.intentEnvelopeVersion} = 1
|
|
274
274
|
and ${table.intentProtocolVersion} = 1
|
|
275
|
-
and ${table.commandProtocolVersion} > 0
|
|
276
275
|
and ${table.intentByteSize} between 8 and 5242880
|
|
277
276
|
and octet_length(${table.intentBytes}) = ${table.intentByteSize}
|
|
278
277
|
and substring(${table.intentBytes} from 1 for 8) = convert_to('OGATX001', 'UTF8')
|
|
@@ -288,6 +287,8 @@ export const editableArtifactTransactions = pgTable(
|
|
|
288
287
|
'sha256:' || encode(sha256(${table.committedTransactionBytes}), 'hex')
|
|
289
288
|
and (
|
|
290
289
|
(${table.modality} = 'spreadsheet'
|
|
290
|
+
and ${table.modelSchemaVersion} = 2
|
|
291
|
+
and ${table.commandProtocolVersion} = 2
|
|
291
292
|
and ${table.operationCount} between 1 and 4096
|
|
292
293
|
and ${table.sequenceEnd} = ${table.sequenceStart} + ${table.operationCount} - 1
|
|
293
294
|
and jsonb_typeof(${table.causalBase}) = 'array'
|
|
@@ -296,7 +297,7 @@ export const editableArtifactTransactions = pgTable(
|
|
|
296
297
|
and jsonb_typeof(${table.selectiveUndoTargets}) = 'array'
|
|
297
298
|
and jsonb_typeof(${table.operationIds}) = 'array'
|
|
298
299
|
and jsonb_array_length(${table.operationIds}) = ${table.operationCount}
|
|
299
|
-
and ${table.operationProtocolVersion} =
|
|
300
|
+
and ${table.operationProtocolVersion} = 2
|
|
300
301
|
and ${table.commitProtocolVersion} is null
|
|
301
302
|
and ${table.priorNativeRevision} is null
|
|
302
303
|
and ${table.nativeRevision} is null
|
|
@@ -304,9 +305,11 @@ export const editableArtifactTransactions = pgTable(
|
|
|
304
305
|
and ${table.nativeReceiptByteSize} is null
|
|
305
306
|
and ${table.nativeReceiptHash} is null
|
|
306
307
|
and ${table.nativeReceiptBytes} is null
|
|
307
|
-
and substring(${table.committedTransactionBytes} from 1 for 8) = convert_to('
|
|
308
|
+
and substring(${table.committedTransactionBytes} from 1 for 8) = convert_to('OGACO002', 'UTF8'))
|
|
308
309
|
or
|
|
309
310
|
(${table.modality} in ('document', 'presentation')
|
|
311
|
+
and ${table.modelSchemaVersion} = 1
|
|
312
|
+
and ${table.commandProtocolVersion} = 1
|
|
310
313
|
and ${table.sequenceEnd} = ${table.sequenceStart}
|
|
311
314
|
and ${table.causalBase} is null
|
|
312
315
|
and ${table.resolvedCausalBase} is null
|
|
@@ -635,11 +638,13 @@ export const editableArtifactSnapshots = pgTable(
|
|
|
635
638
|
sql`${stableIdSql(table.id)} and ${sha256Sql(table.contentHash)} and ${sha256Sql(table.stateHash)}
|
|
636
639
|
and (
|
|
637
640
|
(${table.modality} = 'spreadsheet'
|
|
641
|
+
and ${table.modelSchemaVersion} = 2
|
|
638
642
|
and jsonb_typeof(${table.coveredCausalFrontier}) = 'array'
|
|
639
|
-
and ${table.operationProtocolVersion} =
|
|
640
|
-
and ${table.crdtStateVersion}
|
|
643
|
+
and ${table.operationProtocolVersion} = 2
|
|
644
|
+
and ${table.crdtStateVersion} = 2
|
|
641
645
|
and ${table.nativeRevision} is null)
|
|
642
646
|
or (${table.modality} in ('document', 'presentation')
|
|
647
|
+
and ${table.modelSchemaVersion} = 1
|
|
643
648
|
and ${table.coveredCausalFrontier} is null
|
|
644
649
|
and ${table.operationProtocolVersion} is null
|
|
645
650
|
and ${table.crdtStateVersion} is null
|
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
decodeEditableArtifactSerializedCommit,
|
|
12
12
|
} from "@opengeni/contracts/editable-artifact-serialized-commit";
|
|
13
13
|
import {
|
|
14
|
+
EDITABLE_ARTIFACT_INTENT_PROTOCOL_VERSION,
|
|
14
15
|
EDITABLE_ARTIFACT_KERNEL_VERSION_MAX_BYTES,
|
|
15
16
|
EDITABLE_ARTIFACT_PRODUCT_MAX_SNAPSHOT_BYTES,
|
|
16
17
|
} from "@opengeni/contracts/editable-artifacts";
|
|
18
|
+
import { EDITABLE_ARTIFACT_LIVE_WIRE_VERSION } from "@opengeni/contracts/editable-artifact-versions";
|
|
17
19
|
import { sql } from "drizzle-orm";
|
|
18
20
|
|
|
19
21
|
import { rawRows, type Database, withRlsContext } from "./database";
|
|
@@ -331,7 +333,7 @@ export type PersistedEditableArtifactLiveHead =
|
|
|
331
333
|
|
|
332
334
|
export type PersistedEditableArtifactLiveResume =
|
|
333
335
|
| Readonly<{
|
|
334
|
-
modality
|
|
336
|
+
modality: "spreadsheet";
|
|
335
337
|
localCursor: number | null;
|
|
336
338
|
localStateHash: string | null;
|
|
337
339
|
localCausalFrontier: PersistedEditableArtifactCausalFrontier;
|
|
@@ -354,6 +356,7 @@ export type PersistedEditableArtifactLiveSnapshot =
|
|
|
354
356
|
causalFrontier: PersistedEditableArtifactCausalFrontier;
|
|
355
357
|
digest: string;
|
|
356
358
|
operationProtocolVersion: number;
|
|
359
|
+
snapshotVersion: number;
|
|
357
360
|
kernelVersion: string;
|
|
358
361
|
modelSchemaVersion: number;
|
|
359
362
|
bytes: Uint8Array;
|
|
@@ -1841,11 +1844,9 @@ export class PostgresEditableArtifactLiveReadStore {
|
|
|
1841
1844
|
scope: PersistedEditableArtifactScope;
|
|
1842
1845
|
artifactId: string;
|
|
1843
1846
|
resume: PersistedEditableArtifactLiveResume;
|
|
1844
|
-
protocolVersion: number;
|
|
1845
1847
|
}): Promise<PersistedEditableArtifactLiveBootstrap> {
|
|
1846
1848
|
const scope = validateScope(input.scope);
|
|
1847
1849
|
const artifactId = validateStableId(input.artifactId, "artifact id");
|
|
1848
|
-
validateInteger(input.protocolVersion, "live protocol version", 1);
|
|
1849
1850
|
const resume = validateLiveResume(input.resume);
|
|
1850
1851
|
const authority = await withRlsContext(
|
|
1851
1852
|
this.db,
|
|
@@ -2103,6 +2104,7 @@ export class PostgresEditableArtifactLiveReadStore {
|
|
|
2103
2104
|
modality: snapshot.modality,
|
|
2104
2105
|
causalFrontier: snapshot.coveredCausalFrontier,
|
|
2105
2106
|
operationProtocolVersion: snapshot.operationProtocolVersion,
|
|
2107
|
+
snapshotVersion: snapshot.crdtStateVersion,
|
|
2106
2108
|
})
|
|
2107
2109
|
: Object.freeze({
|
|
2108
2110
|
...common,
|
|
@@ -2872,7 +2874,7 @@ function validateLiveResume(
|
|
|
2872
2874
|
input: PersistedEditableArtifactLiveResume,
|
|
2873
2875
|
): NormalizedPersistedEditableArtifactLiveResume {
|
|
2874
2876
|
if (!isPlainRecord(input)) throw new TypeError("Editable artifact live resume is invalid");
|
|
2875
|
-
const modality = input.modality
|
|
2877
|
+
const modality = input.modality;
|
|
2876
2878
|
if (modality !== "spreadsheet" && modality !== "document" && modality !== "presentation") {
|
|
2877
2879
|
throw new TypeError("Editable artifact live resume modality is invalid");
|
|
2878
2880
|
}
|
|
@@ -3443,7 +3445,7 @@ function committedTransactionFromRow(
|
|
|
3443
3445
|
} catch (error) {
|
|
3444
3446
|
throw new EditableArtifactPersistenceError(
|
|
3445
3447
|
"corrupt_history",
|
|
3446
|
-
"Stored canonical committed transaction is not a valid
|
|
3448
|
+
"Stored canonical committed transaction is not a valid OGACO002 envelope",
|
|
3447
3449
|
{ cause: error },
|
|
3448
3450
|
);
|
|
3449
3451
|
}
|
|
@@ -4144,7 +4146,7 @@ function validateCommittedTransactionProjection(
|
|
|
4144
4146
|
try {
|
|
4145
4147
|
summary = decodeCommittedTransactionSummary(transaction.committedTransactionBytes);
|
|
4146
4148
|
} catch (error) {
|
|
4147
|
-
throw new TypeError("Canonical committed transaction is not a valid
|
|
4149
|
+
throw new TypeError("Canonical committed transaction is not a valid OGACO002 envelope", {
|
|
4148
4150
|
cause: error,
|
|
4149
4151
|
});
|
|
4150
4152
|
}
|
|
@@ -4159,7 +4161,7 @@ function validateCommittedTransactionProjection(
|
|
|
4159
4161
|
!sameFrontier(summary.resolvedCausalBase, resolvedCausalBase) ||
|
|
4160
4162
|
!sameFrontier(summary.resultingCausalFrontier, resultingCausalFrontier)
|
|
4161
4163
|
) {
|
|
4162
|
-
throw new TypeError("Canonical
|
|
4164
|
+
throw new TypeError("Canonical OGACO002 bytes disagree with their durable projection");
|
|
4163
4165
|
}
|
|
4164
4166
|
return;
|
|
4165
4167
|
}
|
|
@@ -4681,6 +4683,10 @@ function validateLiveTicketRecord(
|
|
|
4681
4683
|
throw new TypeError("Live ticket lifetime must be 1-60 seconds");
|
|
4682
4684
|
}
|
|
4683
4685
|
const modality = validateLiveTicketModality(input.modality);
|
|
4686
|
+
const protocolVersion = validateInteger(input.protocolVersion, "live protocol version", 1);
|
|
4687
|
+
if (protocolVersion !== EDITABLE_ARTIFACT_LIVE_WIRE_VERSION) {
|
|
4688
|
+
throw new TypeError("Live ticket protocol version is unsupported");
|
|
4689
|
+
}
|
|
4684
4690
|
return Object.freeze({
|
|
4685
4691
|
tokenDigest: validateHash(input.tokenDigest, "live ticket digest"),
|
|
4686
4692
|
scope: validateScope(input.scope),
|
|
@@ -4688,7 +4694,7 @@ function validateLiveTicketRecord(
|
|
|
4688
4694
|
modality,
|
|
4689
4695
|
actor: validateLiveTicketActor(input.actor),
|
|
4690
4696
|
allowEdit: validateBoolean(input.allowEdit, "live ticket allowEdit"),
|
|
4691
|
-
protocolVersion
|
|
4697
|
+
protocolVersion,
|
|
4692
4698
|
issuedAt,
|
|
4693
4699
|
expiresAt,
|
|
4694
4700
|
});
|
|
@@ -4984,9 +4990,13 @@ function validateCanonicalIntentBytes(value: unknown, requestHashInput: unknown)
|
|
|
4984
4990
|
return bytes;
|
|
4985
4991
|
}
|
|
4986
4992
|
|
|
4987
|
-
function validateIntentProtocolVersion(
|
|
4988
|
-
|
|
4989
|
-
|
|
4993
|
+
function validateIntentProtocolVersion(
|
|
4994
|
+
value: unknown,
|
|
4995
|
+
): typeof EDITABLE_ARTIFACT_INTENT_PROTOCOL_VERSION {
|
|
4996
|
+
if (value !== EDITABLE_ARTIFACT_INTENT_PROTOCOL_VERSION) {
|
|
4997
|
+
throw new TypeError("Intent protocol version is unsupported for current OGATX001");
|
|
4998
|
+
}
|
|
4999
|
+
return EDITABLE_ARTIFACT_INTENT_PROTOCOL_VERSION;
|
|
4990
5000
|
}
|
|
4991
5001
|
|
|
4992
5002
|
function validateClientTransactionId(value: unknown): string {
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bigint,
|
|
3
|
+
check,
|
|
4
|
+
index,
|
|
5
|
+
pgTable,
|
|
6
|
+
text,
|
|
7
|
+
timestamp,
|
|
8
|
+
uniqueIndex,
|
|
9
|
+
uuid,
|
|
10
|
+
} from "drizzle-orm/pg-core";
|
|
11
|
+
import { sql } from "drizzle-orm";
|
|
12
|
+
|
|
13
|
+
/** Migration 0269 owns exact foreign keys, RLS, immutability and lifecycle checks. */
|
|
14
|
+
export const governedLearningActivationReceipts = pgTable(
|
|
15
|
+
"governed_learning_activation_receipts",
|
|
16
|
+
{
|
|
17
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
18
|
+
accountId: uuid("account_id").notNull(),
|
|
19
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
20
|
+
operationId: uuid("operation_id").notNull(),
|
|
21
|
+
inputHash: text("input_hash").notNull(),
|
|
22
|
+
decisionReceiptId: uuid("decision_receipt_id").notNull(),
|
|
23
|
+
initiatingHumanSubjectId: text("initiating_human_subject_id").notNull(),
|
|
24
|
+
serviceActorSubjectId: text("service_actor_subject_id").notNull(),
|
|
25
|
+
policyRevisionId: uuid("policy_revision_id").notNull(),
|
|
26
|
+
policyHash: text("policy_hash").notNull(),
|
|
27
|
+
policyActivationVersion: bigint("policy_activation_version", { mode: "number" }).notNull(),
|
|
28
|
+
sourceKind: text("source_kind").notNull(),
|
|
29
|
+
sourceId: uuid("source_id").notNull(),
|
|
30
|
+
sourceAuthorityHash: text("source_authority_hash").notNull(),
|
|
31
|
+
proposalId: uuid("proposal_id").notNull(),
|
|
32
|
+
claimId: uuid("claim_id").notNull(),
|
|
33
|
+
evidenceId: uuid("evidence_id").notNull(),
|
|
34
|
+
knowledgePreviousReviewId: uuid("knowledge_previous_review_id").notNull(),
|
|
35
|
+
knowledgePreviousReviewRevision: bigint("knowledge_previous_review_revision", {
|
|
36
|
+
mode: "number",
|
|
37
|
+
}).notNull(),
|
|
38
|
+
knowledgeApprovalReviewId: uuid("knowledge_approval_review_id").notNull(),
|
|
39
|
+
knowledgeApprovalReviewRevision: bigint("knowledge_approval_review_revision", {
|
|
40
|
+
mode: "number",
|
|
41
|
+
}).notNull(),
|
|
42
|
+
knowledgeApprovalInputHash: text("knowledge_approval_input_hash").notNull(),
|
|
43
|
+
destination: text("destination").notNull(),
|
|
44
|
+
destinationProposalId: uuid("destination_proposal_id").notNull(),
|
|
45
|
+
destinationRevisionId: uuid("destination_revision_id").notNull(),
|
|
46
|
+
destinationOldRevisionId: uuid("destination_old_revision_id"),
|
|
47
|
+
destinationOldContentHash: text("destination_old_content_hash"),
|
|
48
|
+
destinationOldVersion: bigint("destination_old_version", { mode: "number" }).notNull(),
|
|
49
|
+
destinationNewContentHash: text("destination_new_content_hash").notNull(),
|
|
50
|
+
destinationNewVersion: bigint("destination_new_version", { mode: "number" }).notNull(),
|
|
51
|
+
destinationEventId: uuid("destination_event_id").notNull(),
|
|
52
|
+
// Added by migration 0272 alongside human-confirmed activation; the schema
|
|
53
|
+
// file had not caught up.
|
|
54
|
+
authorityKind: text("authority_kind").notNull().default("automatic"),
|
|
55
|
+
humanInputRequestId: uuid("human_input_request_id"),
|
|
56
|
+
effectiveAt: timestamp("effective_at", { withTimezone: true }).notNull(),
|
|
57
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
58
|
+
},
|
|
59
|
+
(table) => ({
|
|
60
|
+
operation: uniqueIndex("governed_learning_activation_receipts_operation_uq").on(
|
|
61
|
+
table.workspaceId,
|
|
62
|
+
table.operationId,
|
|
63
|
+
),
|
|
64
|
+
decision: uniqueIndex("governed_learning_activation_receipts_decision_uq").on(
|
|
65
|
+
table.decisionReceiptId,
|
|
66
|
+
),
|
|
67
|
+
timeline: index("governed_learning_activation_receipts_workspace_time_idx").on(
|
|
68
|
+
table.workspaceId,
|
|
69
|
+
table.createdAt,
|
|
70
|
+
table.id,
|
|
71
|
+
),
|
|
72
|
+
hash: check(
|
|
73
|
+
"governed_learning_activation_receipts_hash_chk",
|
|
74
|
+
sql`${table.inputHash} ~ '^[0-9a-f]{64}$'`,
|
|
75
|
+
),
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
export const governedLearningActivationUndoReceipts = pgTable(
|
|
80
|
+
"governed_learning_activation_undo_receipts",
|
|
81
|
+
{
|
|
82
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
83
|
+
accountId: uuid("account_id").notNull(),
|
|
84
|
+
workspaceId: uuid("workspace_id").notNull(),
|
|
85
|
+
operationId: uuid("operation_id").notNull(),
|
|
86
|
+
inputHash: text("input_hash").notNull(),
|
|
87
|
+
activationReceiptId: uuid("activation_receipt_id").notNull(),
|
|
88
|
+
initiatingHumanSubjectId: text("initiating_human_subject_id").notNull(),
|
|
89
|
+
serviceActorSubjectId: text("service_actor_subject_id").notNull(),
|
|
90
|
+
destination: text("destination").notNull(),
|
|
91
|
+
knowledgeApprovalReviewId: uuid("knowledge_approval_review_id").notNull(),
|
|
92
|
+
knowledgeRevocationReviewId: uuid("knowledge_revocation_review_id").notNull(),
|
|
93
|
+
knowledgeRevocationReviewRevision: bigint("knowledge_revocation_review_revision", {
|
|
94
|
+
mode: "number",
|
|
95
|
+
}).notNull(),
|
|
96
|
+
knowledgeRevocationInputHash: text("knowledge_revocation_input_hash").notNull(),
|
|
97
|
+
destinationActivatedRevisionId: uuid("destination_activated_revision_id").notNull(),
|
|
98
|
+
destinationRestoredRevisionId: uuid("destination_restored_revision_id"),
|
|
99
|
+
destinationActivatedContentHash: text("destination_activated_content_hash").notNull(),
|
|
100
|
+
destinationRestoredContentHash: text("destination_restored_content_hash"),
|
|
101
|
+
destinationOldVersion: bigint("destination_old_version", { mode: "number" }).notNull(),
|
|
102
|
+
destinationNewVersion: bigint("destination_new_version", { mode: "number" }).notNull(),
|
|
103
|
+
destinationEventId: uuid("destination_event_id").notNull(),
|
|
104
|
+
effectiveAt: timestamp("effective_at", { withTimezone: true }).notNull(),
|
|
105
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
106
|
+
},
|
|
107
|
+
(table) => ({
|
|
108
|
+
operation: uniqueIndex("governed_learning_activation_undo_receipts_operation_uq").on(
|
|
109
|
+
table.workspaceId,
|
|
110
|
+
table.operationId,
|
|
111
|
+
),
|
|
112
|
+
activation: uniqueIndex("governed_learning_activation_undo_receipts_activation_uq").on(
|
|
113
|
+
table.activationReceiptId,
|
|
114
|
+
),
|
|
115
|
+
timeline: index("governed_learning_activation_undo_receipts_workspace_time_idx").on(
|
|
116
|
+
table.workspaceId,
|
|
117
|
+
table.createdAt,
|
|
118
|
+
table.id,
|
|
119
|
+
),
|
|
120
|
+
}),
|
|
121
|
+
);
|