@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.
- package/dist/{chunk-4RUK5CON.js → chunk-T6RSJT6C.js} +20 -2
- package/dist/chunk-T6RSJT6C.js.map +1 -0
- package/dist/{chunk-HZD7KVAR.js → chunk-YKWJ7QJ2.js} +369 -17
- package/dist/chunk-YKWJ7QJ2.js.map +1 -0
- package/dist/index.d.ts +225 -0
- package/dist/index.js +3735 -2488
- package/dist/index.js.map +1 -1
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +3 -3
- package/dist/schema.d.ts +2631 -749
- package/dist/schema.js +15 -1
- package/dist/workspace-artifacts.d.ts +62 -0
- package/drizzle/0141_social_connection_credentials.sql +8 -0
- package/drizzle/0149_workspace_artifacts.sql +348 -0
- package/drizzle/0150_slack_task_interactions.sql +344 -0
- package/drizzle/0151_slack_delivery_backoff.sql +134 -0
- package/package.json +3 -3
- package/src/index.ts +1217 -12
- package/src/runtime-posture.ts +19 -1
- package/src/schema.ts +409 -16
- package/src/workspace-artifacts.ts +751 -0
- package/dist/chunk-4RUK5CON.js.map +0 -1
- package/dist/chunk-HZD7KVAR.js.map +0 -1
package/dist/schema.js
CHANGED
|
@@ -88,10 +88,17 @@ import {
|
|
|
88
88
|
sessions,
|
|
89
89
|
slackBotDeleteOperations,
|
|
90
90
|
slackBotPostOperations,
|
|
91
|
+
slackBotUserLinks,
|
|
92
|
+
slackInteractionInbox,
|
|
93
|
+
slackInteractionProgressDeliveries,
|
|
94
|
+
slackInteractions,
|
|
91
95
|
socialConnections,
|
|
92
96
|
socialPosts,
|
|
93
97
|
stripeWebhookEvents,
|
|
94
98
|
usageEvents,
|
|
99
|
+
workspaceArtifactEvents,
|
|
100
|
+
workspaceArtifactVersions,
|
|
101
|
+
workspaceArtifacts,
|
|
95
102
|
workspaceCaptures,
|
|
96
103
|
workspaceControlEvents,
|
|
97
104
|
workspaceInferenceControls,
|
|
@@ -105,7 +112,7 @@ import {
|
|
|
105
112
|
workspaceVariableSetVariables,
|
|
106
113
|
workspaceVariableSets,
|
|
107
114
|
workspaces
|
|
108
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-YKWJ7QJ2.js";
|
|
109
116
|
import "./chunk-PZ5AY32C.js";
|
|
110
117
|
export {
|
|
111
118
|
agentRunStates,
|
|
@@ -197,10 +204,17 @@ export {
|
|
|
197
204
|
sessions,
|
|
198
205
|
slackBotDeleteOperations,
|
|
199
206
|
slackBotPostOperations,
|
|
207
|
+
slackBotUserLinks,
|
|
208
|
+
slackInteractionInbox,
|
|
209
|
+
slackInteractionProgressDeliveries,
|
|
210
|
+
slackInteractions,
|
|
200
211
|
socialConnections,
|
|
201
212
|
socialPosts,
|
|
202
213
|
stripeWebhookEvents,
|
|
203
214
|
usageEvents,
|
|
215
|
+
workspaceArtifactEvents,
|
|
216
|
+
workspaceArtifactVersions,
|
|
217
|
+
workspaceArtifacts,
|
|
204
218
|
workspaceCaptures,
|
|
205
219
|
workspaceControlEvents,
|
|
206
220
|
workspaceInferenceControls,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { WorkspaceArtifact, WorkspaceArtifactDetailResponse, WorkspaceArtifactMutationResponse, WorkspaceArtifactVersion } from "@opengeni/contracts";
|
|
2
|
+
import type { Database } from "./index";
|
|
3
|
+
type ArtifactMutationToolName = "artifacts_create" | "artifacts_publish" | "artifacts_rollback";
|
|
4
|
+
export declare class WorkspaceArtifactNotFoundError extends Error {
|
|
5
|
+
readonly name = "WorkspaceArtifactNotFoundError";
|
|
6
|
+
}
|
|
7
|
+
export declare class WorkspaceArtifactConflictError extends Error {
|
|
8
|
+
readonly currentVersionId: string | null;
|
|
9
|
+
readonly name = "WorkspaceArtifactConflictError";
|
|
10
|
+
constructor(message: string, currentVersionId?: string | null);
|
|
11
|
+
}
|
|
12
|
+
export declare class WorkspaceArtifactOperationError extends Error {
|
|
13
|
+
readonly name = "WorkspaceArtifactOperationError";
|
|
14
|
+
}
|
|
15
|
+
export declare function listWorkspaceArtifacts(db: Database, workspaceId: string, options?: {
|
|
16
|
+
limit?: number;
|
|
17
|
+
cursor?: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
artifacts: WorkspaceArtifact[];
|
|
20
|
+
nextCursor: string | null;
|
|
21
|
+
truncated: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function getWorkspaceArtifact(db: Database, workspaceId: string, artifactId: string): Promise<WorkspaceArtifactDetailResponse>;
|
|
24
|
+
export declare function getWorkspaceArtifactContentRef(db: Database, workspaceId: string, artifactId: string, versionId?: string): Promise<{
|
|
25
|
+
artifactId: string;
|
|
26
|
+
version: WorkspaceArtifactVersion;
|
|
27
|
+
contentKey: string;
|
|
28
|
+
}>;
|
|
29
|
+
type PublishMetadata = {
|
|
30
|
+
accountId: string;
|
|
31
|
+
workspaceId: string;
|
|
32
|
+
contentKey: string;
|
|
33
|
+
contentSha256: string;
|
|
34
|
+
sizeBytes: number;
|
|
35
|
+
operationKey: string;
|
|
36
|
+
actorSubjectId: string;
|
|
37
|
+
sourceSessionId: string | null;
|
|
38
|
+
sourceTurnId: string | null;
|
|
39
|
+
sourceAttemptId: string | null;
|
|
40
|
+
sourceExecutionGeneration: number | null;
|
|
41
|
+
sourceToolName: ArtifactMutationToolName | null;
|
|
42
|
+
persistContent: () => Promise<void>;
|
|
43
|
+
};
|
|
44
|
+
export declare function createWorkspaceArtifact(db: Database, input: PublishMetadata & {
|
|
45
|
+
artifactId: string;
|
|
46
|
+
slug: string;
|
|
47
|
+
title: string;
|
|
48
|
+
description: string | null;
|
|
49
|
+
}): Promise<WorkspaceArtifactMutationResponse>;
|
|
50
|
+
export declare function publishWorkspaceArtifactVersion(db: Database, input: PublishMetadata & {
|
|
51
|
+
artifactId: string;
|
|
52
|
+
expectedCurrentVersionId: string;
|
|
53
|
+
title?: string;
|
|
54
|
+
description?: string | null;
|
|
55
|
+
}): Promise<WorkspaceArtifactMutationResponse>;
|
|
56
|
+
export declare function rollbackWorkspaceArtifact(db: Database, input: Omit<PublishMetadata, "contentKey" | "contentSha256" | "sizeBytes" | "persistContent"> & {
|
|
57
|
+
artifactId: string;
|
|
58
|
+
versionId: string;
|
|
59
|
+
expectedCurrentVersionId: string;
|
|
60
|
+
reason: string;
|
|
61
|
+
}): Promise<WorkspaceArtifactMutationResponse>;
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- First-party social connectors (X / Reddit): OAuth token storage.
|
|
3
|
+
-- credential_encrypted holds the AES-256-GCM envelope (environment-crypto v1
|
|
4
|
+
-- format) with the provider token bundle {access_token, refresh_token, ...}.
|
|
5
|
+
-- It is deliberately separate from credential_ref (a free-text external
|
|
6
|
+
-- reference) and never surfaced by the SocialConnection contract mapper.
|
|
7
|
+
|
|
8
|
+
ALTER TABLE "social_connections" ADD COLUMN IF NOT EXISTS "credential_encrypted" text;
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
-- deployment-mode: maintenance
|
|
2
|
+
-- Generic, versioned workspace-published HTML artifacts. Existing sessions
|
|
3
|
+
-- retain their immutable capability policy; only newly created sessions use
|
|
4
|
+
-- the artifact tools added to the application default catalog.
|
|
5
|
+
|
|
6
|
+
-- NULL meant "the then-current worker default" before artifact permissions
|
|
7
|
+
-- existed. Freeze that exact historical default before the application default
|
|
8
|
+
-- widens. Explicit [] and every explicit narrow array remain byte-for-byte
|
|
9
|
+
-- unchanged. first_party_mcp_tools has been explicit and NOT NULL since 0136;
|
|
10
|
+
-- do not append the new artifact tools to any historical selection.
|
|
11
|
+
UPDATE "sessions"
|
|
12
|
+
SET "first_party_mcp_permissions" = '[
|
|
13
|
+
"workspace:read",
|
|
14
|
+
"files:read",
|
|
15
|
+
"documents:search",
|
|
16
|
+
"scheduled_tasks:manage",
|
|
17
|
+
"scheduled_tasks:run",
|
|
18
|
+
"goals:manage",
|
|
19
|
+
"sessions:read",
|
|
20
|
+
"sessions:create",
|
|
21
|
+
"sessions:control",
|
|
22
|
+
"variable-sets:use",
|
|
23
|
+
"variable-sets:manage",
|
|
24
|
+
"rigs:use",
|
|
25
|
+
"github:use"
|
|
26
|
+
]'::jsonb
|
|
27
|
+
WHERE "first_party_mcp_permissions" IS NULL;
|
|
28
|
+
|
|
29
|
+
ALTER TABLE "sessions"
|
|
30
|
+
ALTER COLUMN "first_party_mcp_tools"
|
|
31
|
+
SET DEFAULT '[
|
|
32
|
+
"set_session_title",
|
|
33
|
+
"goal_set",
|
|
34
|
+
"goal_update",
|
|
35
|
+
"goal_complete",
|
|
36
|
+
"goal_pause",
|
|
37
|
+
"memory_search",
|
|
38
|
+
"memory_save",
|
|
39
|
+
"memory_correct",
|
|
40
|
+
"preference_registry_summary",
|
|
41
|
+
"preference_registry_get",
|
|
42
|
+
"sandboxes_list",
|
|
43
|
+
"sandbox_attach",
|
|
44
|
+
"sandbox_swap",
|
|
45
|
+
"run_on",
|
|
46
|
+
"sandbox_provision",
|
|
47
|
+
"rig_list",
|
|
48
|
+
"rig_get",
|
|
49
|
+
"rig_propose_change",
|
|
50
|
+
"rig_verify",
|
|
51
|
+
"rig_promote",
|
|
52
|
+
"sessions_list",
|
|
53
|
+
"session_get",
|
|
54
|
+
"session_events",
|
|
55
|
+
"session_create",
|
|
56
|
+
"session_send_message",
|
|
57
|
+
"session_pause",
|
|
58
|
+
"session_resume",
|
|
59
|
+
"session_steer",
|
|
60
|
+
"set_other_session_title",
|
|
61
|
+
"variable_set_list",
|
|
62
|
+
"environment_list",
|
|
63
|
+
"variable_set_set_variable",
|
|
64
|
+
"environment_set_variable",
|
|
65
|
+
"github_connect_link",
|
|
66
|
+
"github_token",
|
|
67
|
+
"github_repositories_list",
|
|
68
|
+
"social_connections_list",
|
|
69
|
+
"social_posts_recent",
|
|
70
|
+
"social_daily_analysis_context",
|
|
71
|
+
"scheduled_tasks_list",
|
|
72
|
+
"scheduled_tasks_get",
|
|
73
|
+
"scheduled_tasks_create",
|
|
74
|
+
"scheduled_tasks_update",
|
|
75
|
+
"scheduled_tasks_pause",
|
|
76
|
+
"scheduled_tasks_resume",
|
|
77
|
+
"scheduled_tasks_trigger",
|
|
78
|
+
"scheduled_tasks_delete",
|
|
79
|
+
"scheduled_task_runs_list",
|
|
80
|
+
"slack_bot_list_channels",
|
|
81
|
+
"slack_bot_channel_history",
|
|
82
|
+
"slack_bot_thread_replies",
|
|
83
|
+
"slack_bot_list_users",
|
|
84
|
+
"slack_bot_list_files",
|
|
85
|
+
"slack_bot_file_info",
|
|
86
|
+
"slack_bot_file_content",
|
|
87
|
+
"slack_bot_post_message",
|
|
88
|
+
"slack_bot_delete_message",
|
|
89
|
+
"artifacts_list",
|
|
90
|
+
"artifacts_get_source",
|
|
91
|
+
"artifacts_create",
|
|
92
|
+
"artifacts_publish",
|
|
93
|
+
"artifacts_rollback"
|
|
94
|
+
]'::jsonb;
|
|
95
|
+
|
|
96
|
+
CREATE TABLE "workspace_artifacts" (
|
|
97
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
98
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
99
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
100
|
+
"slug" text NOT NULL,
|
|
101
|
+
"title" text NOT NULL,
|
|
102
|
+
"description" text,
|
|
103
|
+
"status" text NOT NULL DEFAULT 'active',
|
|
104
|
+
"current_version_id" uuid,
|
|
105
|
+
"created_by_subject_id" text NOT NULL,
|
|
106
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
107
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
108
|
+
CONSTRAINT "workspace_artifacts_status_chk" CHECK ("status" IN ('active', 'archived')),
|
|
109
|
+
CONSTRAINT "workspace_artifacts_slug_chk" CHECK (
|
|
110
|
+
length("slug") BETWEEN 1 AND 96
|
|
111
|
+
AND "slug" ~ '^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$'
|
|
112
|
+
),
|
|
113
|
+
CONSTRAINT "workspace_artifacts_title_chk" CHECK (length(btrim("title")) BETWEEN 1 AND 120),
|
|
114
|
+
CONSTRAINT "workspace_artifacts_description_chk" CHECK (
|
|
115
|
+
"description" IS NULL OR length("description") <= 2000
|
|
116
|
+
),
|
|
117
|
+
CONSTRAINT "workspace_artifacts_actor_chk" CHECK (
|
|
118
|
+
length(btrim("created_by_subject_id")) BETWEEN 1 AND 1024
|
|
119
|
+
),
|
|
120
|
+
CONSTRAINT "workspace_artifacts_workspace_account_fk"
|
|
121
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
122
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
123
|
+
CONSTRAINT "workspace_artifacts_workspace_id_uq" UNIQUE ("workspace_id", "id"),
|
|
124
|
+
CONSTRAINT "workspace_artifacts_workspace_slug_uq" UNIQUE ("workspace_id", "slug")
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
CREATE INDEX "workspace_artifacts_list_idx"
|
|
128
|
+
ON "workspace_artifacts" ("workspace_id", "updated_at" DESC);
|
|
129
|
+
|
|
130
|
+
CREATE TABLE "workspace_artifact_versions" (
|
|
131
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
132
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
133
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
134
|
+
"artifact_id" uuid NOT NULL,
|
|
135
|
+
"revision" integer NOT NULL,
|
|
136
|
+
"content_key" text NOT NULL,
|
|
137
|
+
"content_type" text NOT NULL DEFAULT 'text/html',
|
|
138
|
+
"content_sha256" text NOT NULL,
|
|
139
|
+
"size_bytes" integer NOT NULL,
|
|
140
|
+
"operation_key" text NOT NULL,
|
|
141
|
+
"source_session_id" uuid,
|
|
142
|
+
"source_turn_id" uuid,
|
|
143
|
+
"source_attempt_id" uuid,
|
|
144
|
+
"source_execution_generation" integer,
|
|
145
|
+
"created_by_subject_id" text NOT NULL,
|
|
146
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
147
|
+
CONSTRAINT "workspace_artifact_versions_artifact_fk"
|
|
148
|
+
FOREIGN KEY ("workspace_id", "artifact_id")
|
|
149
|
+
REFERENCES "workspace_artifacts"("workspace_id", "id") ON DELETE CASCADE,
|
|
150
|
+
CONSTRAINT "workspace_artifact_versions_workspace_account_fk"
|
|
151
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
152
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
153
|
+
CONSTRAINT "workspace_artifact_versions_workspace_id_uq" UNIQUE ("workspace_id", "id"),
|
|
154
|
+
CONSTRAINT "workspace_artifact_versions_revision_uq"
|
|
155
|
+
UNIQUE ("workspace_id", "artifact_id", "revision"),
|
|
156
|
+
CONSTRAINT "workspace_artifact_versions_operation_uq" UNIQUE ("workspace_id", "operation_key"),
|
|
157
|
+
CONSTRAINT "workspace_artifact_versions_revision_chk" CHECK ("revision" > 0),
|
|
158
|
+
CONSTRAINT "workspace_artifact_versions_content_chk" CHECK (
|
|
159
|
+
"content_type" = 'text/html'
|
|
160
|
+
AND "content_sha256" ~ '^[0-9a-f]{64}$'
|
|
161
|
+
AND "size_bytes" BETWEEN 1 AND 524288
|
|
162
|
+
AND length("content_key") BETWEEN 1 AND 1024
|
|
163
|
+
),
|
|
164
|
+
CONSTRAINT "workspace_artifact_versions_operation_chk" CHECK (
|
|
165
|
+
length("operation_key") BETWEEN 1 AND 512
|
|
166
|
+
),
|
|
167
|
+
CONSTRAINT "workspace_artifact_versions_actor_chk" CHECK (
|
|
168
|
+
length(btrim("created_by_subject_id")) BETWEEN 1 AND 1024
|
|
169
|
+
),
|
|
170
|
+
CONSTRAINT "workspace_artifact_versions_provenance_chk" CHECK (
|
|
171
|
+
(
|
|
172
|
+
"source_session_id" IS NULL
|
|
173
|
+
AND "source_turn_id" IS NULL
|
|
174
|
+
AND "source_attempt_id" IS NULL
|
|
175
|
+
AND "source_execution_generation" IS NULL
|
|
176
|
+
) OR (
|
|
177
|
+
"source_session_id" IS NOT NULL
|
|
178
|
+
AND "source_turn_id" IS NOT NULL
|
|
179
|
+
AND "source_attempt_id" IS NOT NULL
|
|
180
|
+
AND "source_execution_generation" > 0
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
ALTER TABLE "workspace_artifacts"
|
|
186
|
+
ADD CONSTRAINT "workspace_artifacts_current_version_fk"
|
|
187
|
+
FOREIGN KEY ("workspace_id", "current_version_id")
|
|
188
|
+
REFERENCES "workspace_artifact_versions"("workspace_id", "id")
|
|
189
|
+
DEFERRABLE INITIALLY DEFERRED;
|
|
190
|
+
|
|
191
|
+
CREATE TABLE "workspace_artifact_events" (
|
|
192
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
193
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
194
|
+
"workspace_id" uuid NOT NULL REFERENCES "workspaces"("id") ON DELETE CASCADE,
|
|
195
|
+
"artifact_id" uuid NOT NULL,
|
|
196
|
+
"type" text NOT NULL,
|
|
197
|
+
"from_version_id" uuid,
|
|
198
|
+
"to_version_id" uuid NOT NULL,
|
|
199
|
+
"operation_key" text NOT NULL,
|
|
200
|
+
"source_session_id" uuid,
|
|
201
|
+
"source_turn_id" uuid,
|
|
202
|
+
"source_attempt_id" uuid,
|
|
203
|
+
"source_execution_generation" integer,
|
|
204
|
+
"actor_subject_id" text NOT NULL,
|
|
205
|
+
"reason" text NOT NULL,
|
|
206
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
207
|
+
CONSTRAINT "workspace_artifact_events_artifact_fk"
|
|
208
|
+
FOREIGN KEY ("workspace_id", "artifact_id")
|
|
209
|
+
REFERENCES "workspace_artifacts"("workspace_id", "id") ON DELETE CASCADE,
|
|
210
|
+
CONSTRAINT "workspace_artifact_events_workspace_account_fk"
|
|
211
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
212
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
213
|
+
CONSTRAINT "workspace_artifact_events_operation_uq" UNIQUE ("workspace_id", "operation_key"),
|
|
214
|
+
CONSTRAINT "workspace_artifact_events_type_chk" CHECK ("type" IN ('published', 'rolled_back')),
|
|
215
|
+
CONSTRAINT "workspace_artifact_events_operation_chk" CHECK (length("operation_key") BETWEEN 1 AND 512),
|
|
216
|
+
CONSTRAINT "workspace_artifact_events_audit_chk" CHECK (
|
|
217
|
+
length(btrim("actor_subject_id")) BETWEEN 1 AND 1024
|
|
218
|
+
AND length(btrim("reason")) BETWEEN 1 AND 4096
|
|
219
|
+
),
|
|
220
|
+
CONSTRAINT "workspace_artifact_events_provenance_chk" CHECK (
|
|
221
|
+
(
|
|
222
|
+
"source_session_id" IS NULL
|
|
223
|
+
AND "source_turn_id" IS NULL
|
|
224
|
+
AND "source_attempt_id" IS NULL
|
|
225
|
+
AND "source_execution_generation" IS NULL
|
|
226
|
+
) OR (
|
|
227
|
+
"source_session_id" IS NOT NULL
|
|
228
|
+
AND "source_turn_id" IS NOT NULL
|
|
229
|
+
AND "source_attempt_id" IS NOT NULL
|
|
230
|
+
AND "source_execution_generation" > 0
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
CREATE INDEX "workspace_artifact_events_list_idx"
|
|
236
|
+
ON "workspace_artifact_events" ("workspace_id", "artifact_id", "created_at" DESC);
|
|
237
|
+
|
|
238
|
+
ALTER TABLE "workspace_artifact_versions"
|
|
239
|
+
ADD CONSTRAINT "workspace_artifact_versions_source_session_fk"
|
|
240
|
+
FOREIGN KEY ("workspace_id", "source_session_id")
|
|
241
|
+
REFERENCES "sessions"("workspace_id", "id") ON DELETE RESTRICT,
|
|
242
|
+
ADD CONSTRAINT "workspace_artifact_versions_source_turn_fk"
|
|
243
|
+
FOREIGN KEY ("workspace_id", "source_turn_id")
|
|
244
|
+
REFERENCES "session_turns"("workspace_id", "id") ON DELETE RESTRICT,
|
|
245
|
+
ADD CONSTRAINT "workspace_artifact_versions_source_attempt_fk"
|
|
246
|
+
FOREIGN KEY ("workspace_id", "source_attempt_id")
|
|
247
|
+
REFERENCES "session_turn_attempts"("workspace_id", "id") ON DELETE RESTRICT;
|
|
248
|
+
|
|
249
|
+
ALTER TABLE "workspace_artifact_events"
|
|
250
|
+
ADD CONSTRAINT "workspace_artifact_events_source_session_fk"
|
|
251
|
+
FOREIGN KEY ("workspace_id", "source_session_id")
|
|
252
|
+
REFERENCES "sessions"("workspace_id", "id") ON DELETE RESTRICT,
|
|
253
|
+
ADD CONSTRAINT "workspace_artifact_events_source_turn_fk"
|
|
254
|
+
FOREIGN KEY ("workspace_id", "source_turn_id")
|
|
255
|
+
REFERENCES "session_turns"("workspace_id", "id") ON DELETE RESTRICT,
|
|
256
|
+
ADD CONSTRAINT "workspace_artifact_events_source_attempt_fk"
|
|
257
|
+
FOREIGN KEY ("workspace_id", "source_attempt_id")
|
|
258
|
+
REFERENCES "session_turn_attempts"("workspace_id", "id") ON DELETE RESTRICT;
|
|
259
|
+
|
|
260
|
+
CREATE OR REPLACE FUNCTION workspace_artifact_validate_current()
|
|
261
|
+
RETURNS trigger LANGUAGE plpgsql AS $$
|
|
262
|
+
BEGIN
|
|
263
|
+
IF NEW."current_version_id" IS NOT NULL THEN
|
|
264
|
+
IF NOT EXISTS (
|
|
265
|
+
SELECT 1 FROM "workspace_artifact_versions" version
|
|
266
|
+
WHERE version."workspace_id" = NEW."workspace_id"
|
|
267
|
+
AND version."artifact_id" = NEW."id"
|
|
268
|
+
AND version."id" = NEW."current_version_id"
|
|
269
|
+
) THEN
|
|
270
|
+
RAISE EXCEPTION 'artifact current version must belong to the artifact' USING ERRCODE = '23514';
|
|
271
|
+
END IF;
|
|
272
|
+
END IF;
|
|
273
|
+
RETURN NEW;
|
|
274
|
+
END;
|
|
275
|
+
$$;
|
|
276
|
+
|
|
277
|
+
CREATE OR REPLACE FUNCTION workspace_artifact_validate_event_links()
|
|
278
|
+
RETURNS trigger LANGUAGE plpgsql AS $$
|
|
279
|
+
BEGIN
|
|
280
|
+
IF NOT EXISTS (
|
|
281
|
+
SELECT 1 FROM "workspace_artifact_versions" version
|
|
282
|
+
WHERE version."workspace_id" = NEW."workspace_id"
|
|
283
|
+
AND version."artifact_id" = NEW."artifact_id"
|
|
284
|
+
AND version."id" = NEW."to_version_id"
|
|
285
|
+
) OR (NEW."from_version_id" IS NOT NULL AND NOT EXISTS (
|
|
286
|
+
SELECT 1 FROM "workspace_artifact_versions" version
|
|
287
|
+
WHERE version."workspace_id" = NEW."workspace_id"
|
|
288
|
+
AND version."artifact_id" = NEW."artifact_id"
|
|
289
|
+
AND version."id" = NEW."from_version_id"
|
|
290
|
+
)) THEN
|
|
291
|
+
RAISE EXCEPTION 'artifact event versions must belong to the artifact' USING ERRCODE = '23514';
|
|
292
|
+
END IF;
|
|
293
|
+
RETURN NEW;
|
|
294
|
+
END;
|
|
295
|
+
$$;
|
|
296
|
+
|
|
297
|
+
CREATE CONSTRAINT TRIGGER workspace_artifacts_validate_current
|
|
298
|
+
AFTER INSERT OR UPDATE ON "workspace_artifacts"
|
|
299
|
+
DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION workspace_artifact_validate_current();
|
|
300
|
+
CREATE TRIGGER workspace_artifact_events_validate_links
|
|
301
|
+
BEFORE INSERT OR UPDATE ON "workspace_artifact_events"
|
|
302
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_artifact_validate_event_links();
|
|
303
|
+
|
|
304
|
+
CREATE OR REPLACE FUNCTION workspace_artifact_reject_history_mutation()
|
|
305
|
+
RETURNS trigger LANGUAGE plpgsql AS $$
|
|
306
|
+
BEGIN
|
|
307
|
+
IF TG_OP = 'DELETE' AND pg_trigger_depth() > 1 AND NOT EXISTS (
|
|
308
|
+
SELECT 1 FROM "workspaces" workspace WHERE workspace."id" = OLD."workspace_id"
|
|
309
|
+
) THEN
|
|
310
|
+
RETURN OLD;
|
|
311
|
+
END IF;
|
|
312
|
+
RAISE EXCEPTION 'workspace artifact history is immutable' USING ERRCODE = '55000';
|
|
313
|
+
END;
|
|
314
|
+
$$;
|
|
315
|
+
|
|
316
|
+
CREATE TRIGGER workspace_artifact_versions_immutable
|
|
317
|
+
BEFORE UPDATE OR DELETE ON "workspace_artifact_versions"
|
|
318
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_artifact_reject_history_mutation();
|
|
319
|
+
CREATE TRIGGER workspace_artifact_events_immutable
|
|
320
|
+
BEFORE UPDATE OR DELETE ON "workspace_artifact_events"
|
|
321
|
+
FOR EACH ROW EXECUTE FUNCTION workspace_artifact_reject_history_mutation();
|
|
322
|
+
|
|
323
|
+
ALTER TABLE "workspace_artifacts" ENABLE ROW LEVEL SECURITY;
|
|
324
|
+
ALTER TABLE "workspace_artifacts" FORCE ROW LEVEL SECURITY;
|
|
325
|
+
ALTER TABLE "workspace_artifact_versions" ENABLE ROW LEVEL SECURITY;
|
|
326
|
+
ALTER TABLE "workspace_artifact_versions" FORCE ROW LEVEL SECURITY;
|
|
327
|
+
ALTER TABLE "workspace_artifact_events" ENABLE ROW LEVEL SECURITY;
|
|
328
|
+
ALTER TABLE "workspace_artifact_events" FORCE ROW LEVEL SECURITY;
|
|
329
|
+
|
|
330
|
+
CREATE POLICY workspace_isolation ON "workspace_artifacts"
|
|
331
|
+
USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
|
|
332
|
+
WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
|
|
333
|
+
CREATE POLICY workspace_isolation ON "workspace_artifact_versions"
|
|
334
|
+
USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
|
|
335
|
+
WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
|
|
336
|
+
CREATE POLICY workspace_isolation ON "workspace_artifact_events"
|
|
337
|
+
USING (opengeni_private.workspace_rls_visible("account_id", "workspace_id"))
|
|
338
|
+
WITH CHECK (opengeni_private.workspace_rls_visible("account_id", "workspace_id"));
|
|
339
|
+
|
|
340
|
+
DO $$
|
|
341
|
+
BEGIN
|
|
342
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
343
|
+
REVOKE ALL PRIVILEGES ON TABLE "workspace_artifacts", "workspace_artifact_versions", "workspace_artifact_events" FROM opengeni_app;
|
|
344
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE "workspace_artifacts" TO opengeni_app;
|
|
345
|
+
GRANT SELECT, INSERT ON TABLE "workspace_artifact_versions", "workspace_artifact_events" TO opengeni_app;
|
|
346
|
+
END IF;
|
|
347
|
+
END;
|
|
348
|
+
$$;
|