@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.
- package/dist/browser-auth.d.ts +209 -1
- package/dist/browser-downloads.d.ts +51 -0
- package/dist/browser-identities.d.ts +11 -2
- package/dist/browser-sessions.d.ts +83 -1
- package/dist/browser-state-artifacts.d.ts +75 -1
- package/dist/canonical-human-identities.d.ts +48 -0
- package/dist/canonical-human-identities.js +28 -0
- package/dist/canonical-human-identities.js.map +1 -0
- package/dist/capability-integrations.d.ts +8 -6
- package/dist/{chunk-MWDVXQOL.js → chunk-5KTIEDX7.js} +5773 -4212
- package/dist/chunk-5KTIEDX7.js.map +1 -0
- package/dist/{chunk-NBE6CHRI.js → chunk-CQZ4QSP5.js} +49 -9
- package/dist/chunk-CQZ4QSP5.js.map +1 -0
- package/dist/chunk-F32YT7MP.js +117 -0
- package/dist/chunk-F32YT7MP.js.map +1 -0
- package/dist/{chunk-ISI2TIUG.js → chunk-JC5QPLUM.js} +30 -3
- package/dist/chunk-JC5QPLUM.js.map +1 -0
- package/dist/{chunk-F5FT7BEZ.js → chunk-P3RE4D2B.js} +2 -2
- package/dist/chunk-TAUTWOS5.js +259 -0
- package/dist/chunk-TAUTWOS5.js.map +1 -0
- package/dist/{chunk-YHZXQ7HP.js → chunk-VKLB2ZGI.js} +446 -19
- package/dist/chunk-VKLB2ZGI.js.map +1 -0
- package/dist/database.d.ts +5 -0
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/index.d.ts +438 -29
- package/dist/index.js +35640 -28969
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +23 -7
- package/dist/integration-bindings.d.ts +24 -24
- package/dist/integration-facets.d.ts +99 -0
- package/dist/interaction-revisions.d.ts +11 -0
- package/dist/interaction-schema.d.ts +698 -34
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +8 -7
- package/dist/schema.d.ts +9464 -5412
- package/dist/schema.js +51 -9
- package/dist/session-control.d.ts +29 -3
- package/dist/session-tenancy.d.ts +44 -0
- package/dist/session-tenancy.js +16 -0
- package/dist/session-tenancy.js.map +1 -0
- package/dist/slack-task-policy-schema.d.ts +847 -0
- package/dist/slack-task-policy.d.ts +65 -0
- package/dist/task-notes-schema.d.ts +924 -0
- package/dist/task-notes.d.ts +85 -0
- package/dist/video-generation.d.ts +9 -0
- package/dist/video-generation.js +5 -3
- package/dist/xai-subscription.d.ts +326 -0
- package/drizzle/0212_browser_state_transfer_hardening.sql +560 -0
- package/drizzle/0213_browser_interaction_authority.sql +67 -0
- package/drizzle/0214_browser_download_saves.sql +34 -0
- package/drizzle/0215_browser_controller_host.sql +385 -0
- package/drizzle/0216_browser_auth_health_evidence.sql +137 -0
- package/drizzle/0217_external_browser_auth_operations.sql +22 -0
- package/drizzle/0218_organization_tenancy_foundation.sql +299 -0
- package/drizzle/0219_organization_tenancy_managed_human_provisioning.sql +317 -0
- package/drizzle/0219_site_auth_maintenance_sessions.sql +234 -0
- package/drizzle/0220_memory_slack_append_only_cascade.sql +38 -0
- package/drizzle/0220_session_channels.sql +54 -0
- package/drizzle/0221_sessions_channel_index.sql +5 -0
- package/drizzle/0222_session_visibility_authority_epochs.sql +158 -0
- package/drizzle/0222_sessions_channel_fk.sql +89 -0
- package/drizzle/0223_pending_tool_event_output.sql +55 -0
- package/drizzle/0223_sessions_channel_fk_validate.sql +118 -0
- package/drizzle/0224_slack_post_outcome_reconciliation.sql +123 -0
- package/drizzle/0225_session_visibility_fork_activation.sql +1363 -0
- package/drizzle/0226_personal_codex_authority_foundation.sql +365 -0
- package/drizzle/0227_slack_native_actions.sql +145 -0
- package/drizzle/0228_interaction_controller_data_plane.sql +14 -0
- package/drizzle/0228_slack_task_policy.sql +400 -0
- package/drizzle/0229_slack_inbox_file_fact.sql +10 -0
- package/drizzle/0230_user_scoped_variable_sets_rigs.sql +84 -0
- package/drizzle/0231_integration_definition_identity_cutover.sql +271 -0
- package/drizzle/0232_integration_facet_authority_cutover.sql +610 -0
- package/drizzle/0233_skill_and_integration_authority_cutover.sql +1162 -0
- package/drizzle/0234_xai_subscription_authority.sql +1139 -0
- package/drizzle/0235_canonical_human_login_bindings.sql +920 -0
- package/drizzle/0236_browser_identity_lifecycle.sql +39 -0
- package/drizzle/0236_session_visibility_slack_policy.sql +72 -0
- package/drizzle/0237_interaction_transition_reaper.sql +263 -0
- package/drizzle/0238_goal_persistence_policy.sql +471 -0
- package/drizzle/0238_supergrok_realtime_model.sql +29 -0
- package/drizzle/0239_supergrok_video_funding.sql +50 -0
- package/drizzle/0239_task_tree_notes.sql +990 -0
- package/package.json +13 -5
- package/src/browser-auth.ts +2600 -123
- package/src/browser-downloads.ts +517 -0
- package/src/browser-identities.ts +220 -3
- package/src/browser-sessions.ts +334 -45
- package/src/browser-state-artifacts.ts +402 -12
- package/src/canonical-human-identities.ts +317 -0
- package/src/capability-integrations.ts +121 -213
- package/src/database.ts +41 -1
- package/src/index.ts +4157 -394
- package/src/insights.ts +109 -28
- package/src/integration-bindings.ts +101 -101
- package/src/{integration-features.ts → integration-facets.ts} +187 -184
- package/src/interaction-revisions.ts +33 -3
- package/src/interaction-schema.ts +311 -8
- package/src/pack-components.ts +43 -43
- package/src/pack-installations.ts +0 -43
- package/src/plugin-packages.ts +9 -9
- package/src/provision-roles.ts +232 -0
- package/src/runtime-posture.ts +227 -14
- package/src/schema.ts +1188 -75
- package/src/session-control.ts +122 -37
- package/src/session-queue-commands.ts +78 -1
- package/src/session-tenancy.ts +188 -0
- package/src/session-tool-call-settlement.ts +9 -3
- package/src/slack-task-policy-schema.ts +130 -0
- package/src/slack-task-policy.ts +341 -0
- package/src/task-notes-schema.ts +135 -0
- package/src/task-notes.ts +178 -0
- package/src/video-generation.ts +90 -12
- package/src/workspace-artifacts.ts +1 -1
- package/src/xai-subscription.ts +1887 -0
- package/dist/chunk-ISI2TIUG.js.map +0 -1
- package/dist/chunk-MWDVXQOL.js.map +0 -1
- package/dist/chunk-NBE6CHRI.js.map +0 -1
- package/dist/chunk-YHZXQ7HP.js.map +0 -1
- package/dist/integration-features.d.ts +0 -99
- /package/dist/{chunk-F5FT7BEZ.js.map → chunk-P3RE4D2B.js.map} +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Additive organization-tenancy Slice A foundation only. This migration names
|
|
3
|
+
-- durable organization membership, user-resource authority/grant identity,
|
|
4
|
+
-- retention policy, and generic session visibility/fork provenance. It does
|
|
5
|
+
-- not move an existing resource, grant runtime access, or activate sharing.
|
|
6
|
+
|
|
7
|
+
SET LOCAL lock_timeout = '5s';
|
|
8
|
+
SET LOCAL statement_timeout = '10min';
|
|
9
|
+
|
|
10
|
+
CREATE TABLE "organization_memberships" (
|
|
11
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
12
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
13
|
+
"subject_id" text NOT NULL,
|
|
14
|
+
"status" text NOT NULL DEFAULT 'provisioning',
|
|
15
|
+
"personal_workspace_id" uuid,
|
|
16
|
+
"authorization_revision" bigint NOT NULL DEFAULT 1,
|
|
17
|
+
"revoked_at" timestamptz,
|
|
18
|
+
"personal_retention_until" timestamptz,
|
|
19
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
20
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
21
|
+
CONSTRAINT "organization_memberships_status_check" CHECK (
|
|
22
|
+
"status" IN ('provisioning', 'active', 'suspended', 'revoked')
|
|
23
|
+
),
|
|
24
|
+
CONSTRAINT "organization_memberships_active_personal_workspace_check" CHECK (
|
|
25
|
+
"status" <> 'active' OR "personal_workspace_id" IS NOT NULL
|
|
26
|
+
),
|
|
27
|
+
CONSTRAINT "organization_memberships_subject_check" CHECK (
|
|
28
|
+
length(btrim("subject_id")) BETWEEN 1 AND 1024
|
|
29
|
+
),
|
|
30
|
+
CONSTRAINT "organization_memberships_revision_check" CHECK (
|
|
31
|
+
"authorization_revision" > 0
|
|
32
|
+
),
|
|
33
|
+
CONSTRAINT "organization_memberships_revocation_check" CHECK (
|
|
34
|
+
("status" = 'revoked' AND "revoked_at" IS NOT NULL)
|
|
35
|
+
OR ("status" <> 'revoked' AND "revoked_at" IS NULL)
|
|
36
|
+
),
|
|
37
|
+
CONSTRAINT "organization_memberships_personal_workspace_account_fk"
|
|
38
|
+
FOREIGN KEY ("personal_workspace_id", "account_id")
|
|
39
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE RESTRICT
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
CREATE UNIQUE INDEX "organization_memberships_id_account_idx"
|
|
43
|
+
ON "organization_memberships" ("id", "account_id");
|
|
44
|
+
CREATE UNIQUE INDEX "organization_memberships_account_subject_idx"
|
|
45
|
+
ON "organization_memberships" ("account_id", "subject_id");
|
|
46
|
+
CREATE UNIQUE INDEX "organization_memberships_personal_workspace_idx"
|
|
47
|
+
ON "organization_memberships" ("account_id", "personal_workspace_id")
|
|
48
|
+
WHERE "personal_workspace_id" IS NOT NULL;
|
|
49
|
+
|
|
50
|
+
CREATE TABLE "organization_user_retention_policies" (
|
|
51
|
+
"account_id" uuid PRIMARY KEY REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
52
|
+
"mode" text NOT NULL DEFAULT 'retain',
|
|
53
|
+
"retention_days" integer,
|
|
54
|
+
"version" bigint NOT NULL DEFAULT 1,
|
|
55
|
+
"updated_by_membership_id" uuid,
|
|
56
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
57
|
+
CONSTRAINT "organization_user_retention_policies_updater_fk"
|
|
58
|
+
FOREIGN KEY ("updated_by_membership_id", "account_id")
|
|
59
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
60
|
+
CONSTRAINT "organization_user_retention_policies_mode_check" CHECK (
|
|
61
|
+
"mode" IN ('retain', 'delete_after')
|
|
62
|
+
),
|
|
63
|
+
CONSTRAINT "organization_user_retention_policies_duration_check" CHECK (
|
|
64
|
+
("mode" = 'retain' AND "retention_days" IS NULL)
|
|
65
|
+
OR (
|
|
66
|
+
"mode" = 'delete_after'
|
|
67
|
+
AND "retention_days" IS NOT NULL
|
|
68
|
+
AND "retention_days" BETWEEN 1 AND 3650
|
|
69
|
+
)
|
|
70
|
+
),
|
|
71
|
+
CONSTRAINT "organization_user_retention_policies_version_check" CHECK (
|
|
72
|
+
"version" > 0
|
|
73
|
+
)
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
CREATE TABLE "organization_user_resource_authorities" (
|
|
77
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
78
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
79
|
+
"organization_membership_id" uuid NOT NULL,
|
|
80
|
+
"resource_kind" text NOT NULL,
|
|
81
|
+
"resource_id" uuid NOT NULL,
|
|
82
|
+
"origin_workspace_id" uuid,
|
|
83
|
+
"generation" bigint NOT NULL DEFAULT 1,
|
|
84
|
+
"status" text NOT NULL DEFAULT 'active',
|
|
85
|
+
"revoked_at" timestamptz,
|
|
86
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
87
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
88
|
+
CONSTRAINT "organization_user_resource_authorities_membership_fk"
|
|
89
|
+
FOREIGN KEY ("organization_membership_id", "account_id")
|
|
90
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
91
|
+
CONSTRAINT "organization_user_resource_authorities_origin_workspace_fk"
|
|
92
|
+
FOREIGN KEY ("origin_workspace_id", "account_id")
|
|
93
|
+
REFERENCES "workspaces"("id", "account_id")
|
|
94
|
+
ON DELETE SET NULL ("origin_workspace_id"),
|
|
95
|
+
CONSTRAINT "organization_user_resource_authorities_kind_check" CHECK (
|
|
96
|
+
"resource_kind" = lower(btrim("resource_kind"))
|
|
97
|
+
AND length("resource_kind") BETWEEN 1 AND 64
|
|
98
|
+
AND "resource_kind" ~ '^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$'
|
|
99
|
+
),
|
|
100
|
+
CONSTRAINT "organization_user_resource_authorities_generation_check" CHECK (
|
|
101
|
+
"generation" > 0
|
|
102
|
+
),
|
|
103
|
+
CONSTRAINT "organization_user_resource_authorities_status_check" CHECK (
|
|
104
|
+
"status" IN ('active', 'retained', 'revoked')
|
|
105
|
+
),
|
|
106
|
+
CONSTRAINT "organization_user_resource_authorities_revocation_check" CHECK (
|
|
107
|
+
("status" = 'revoked' AND "revoked_at" IS NOT NULL)
|
|
108
|
+
OR ("status" <> 'revoked' AND "revoked_at" IS NULL)
|
|
109
|
+
)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
CREATE UNIQUE INDEX "organization_user_resource_authorities_id_account_idx"
|
|
113
|
+
ON "organization_user_resource_authorities" ("id", "account_id");
|
|
114
|
+
CREATE UNIQUE INDEX "organization_user_resource_authorities_id_account_membership_idx"
|
|
115
|
+
ON "organization_user_resource_authorities" ("id", "account_id", "organization_membership_id");
|
|
116
|
+
CREATE UNIQUE INDEX "organization_user_resource_authorities_resource_identity_idx"
|
|
117
|
+
ON "organization_user_resource_authorities" (
|
|
118
|
+
"account_id",
|
|
119
|
+
"organization_membership_id",
|
|
120
|
+
"resource_kind",
|
|
121
|
+
"resource_id"
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
-- Existing sessions remain explicitly workspace-owned/workspace-visible. Null
|
|
125
|
+
-- owner and fork facts are non-authority; epoch 1 is the legacy baseline.
|
|
126
|
+
ALTER TABLE "sessions"
|
|
127
|
+
ADD COLUMN IF NOT EXISTS "owner_organization_membership_id" uuid,
|
|
128
|
+
ADD COLUMN IF NOT EXISTS "visibility" text NOT NULL DEFAULT 'workspace_shared',
|
|
129
|
+
ADD COLUMN IF NOT EXISTS "authority_epoch" integer NOT NULL DEFAULT 1,
|
|
130
|
+
ADD COLUMN IF NOT EXISTS "forked_from_session_id" uuid,
|
|
131
|
+
ADD COLUMN IF NOT EXISTS "forked_from_authority_epoch" integer,
|
|
132
|
+
ADD COLUMN IF NOT EXISTS "forked_from_visibility" text,
|
|
133
|
+
ADD COLUMN IF NOT EXISTS "forked_at" timestamptz,
|
|
134
|
+
ADD COLUMN IF NOT EXISTS "forked_by_organization_membership_id" uuid;
|
|
135
|
+
|
|
136
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "sessions_id_account_idx"
|
|
137
|
+
ON "sessions" ("id", "account_id");
|
|
138
|
+
|
|
139
|
+
ALTER TABLE "sessions"
|
|
140
|
+
ADD CONSTRAINT "sessions_owner_organization_membership_fk"
|
|
141
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
142
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT NOT VALID,
|
|
143
|
+
ADD CONSTRAINT "sessions_forked_from_session_account_fk"
|
|
144
|
+
FOREIGN KEY ("forked_from_session_id", "account_id")
|
|
145
|
+
REFERENCES "sessions"("id", "account_id") ON DELETE RESTRICT NOT VALID,
|
|
146
|
+
ADD CONSTRAINT "sessions_forked_by_organization_membership_fk"
|
|
147
|
+
FOREIGN KEY ("forked_by_organization_membership_id", "account_id")
|
|
148
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT NOT VALID,
|
|
149
|
+
ADD CONSTRAINT "sessions_visibility_check" CHECK (
|
|
150
|
+
"visibility" IN ('user_private', 'workspace_shared')
|
|
151
|
+
) NOT VALID,
|
|
152
|
+
ADD CONSTRAINT "sessions_private_owner_check" CHECK (
|
|
153
|
+
"visibility" <> 'user_private' OR "owner_organization_membership_id" IS NOT NULL
|
|
154
|
+
) NOT VALID,
|
|
155
|
+
ADD CONSTRAINT "sessions_authority_epoch_check" CHECK (
|
|
156
|
+
"authority_epoch" > 0
|
|
157
|
+
) NOT VALID,
|
|
158
|
+
ADD CONSTRAINT "sessions_fork_provenance_check" CHECK (
|
|
159
|
+
(
|
|
160
|
+
"forked_from_session_id" IS NULL
|
|
161
|
+
AND "forked_from_authority_epoch" IS NULL
|
|
162
|
+
AND "forked_from_visibility" IS NULL
|
|
163
|
+
AND "forked_at" IS NULL
|
|
164
|
+
AND "forked_by_organization_membership_id" IS NULL
|
|
165
|
+
) OR (
|
|
166
|
+
"forked_from_session_id" IS NOT NULL
|
|
167
|
+
AND "forked_from_authority_epoch" IS NOT NULL
|
|
168
|
+
AND "forked_from_authority_epoch" > 0
|
|
169
|
+
AND "forked_from_visibility" IN ('user_private', 'workspace_shared')
|
|
170
|
+
AND "forked_at" IS NOT NULL
|
|
171
|
+
AND "forked_by_organization_membership_id" IS NOT NULL
|
|
172
|
+
)
|
|
173
|
+
) NOT VALID;
|
|
174
|
+
|
|
175
|
+
ALTER TABLE "sessions"
|
|
176
|
+
VALIDATE CONSTRAINT "sessions_owner_organization_membership_fk",
|
|
177
|
+
VALIDATE CONSTRAINT "sessions_forked_from_session_account_fk",
|
|
178
|
+
VALIDATE CONSTRAINT "sessions_forked_by_organization_membership_fk",
|
|
179
|
+
VALIDATE CONSTRAINT "sessions_visibility_check",
|
|
180
|
+
VALIDATE CONSTRAINT "sessions_private_owner_check",
|
|
181
|
+
VALIDATE CONSTRAINT "sessions_authority_epoch_check",
|
|
182
|
+
VALIDATE CONSTRAINT "sessions_fork_provenance_check";
|
|
183
|
+
|
|
184
|
+
CREATE TABLE "organization_user_resource_grants" (
|
|
185
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
186
|
+
"account_id" uuid NOT NULL REFERENCES "managed_accounts"("id") ON DELETE CASCADE,
|
|
187
|
+
"authority_id" uuid NOT NULL,
|
|
188
|
+
"owner_organization_membership_id" uuid NOT NULL,
|
|
189
|
+
"workspace_id" uuid NOT NULL,
|
|
190
|
+
"session_id" uuid,
|
|
191
|
+
"action" text NOT NULL,
|
|
192
|
+
"mode" text NOT NULL,
|
|
193
|
+
"context" text NOT NULL,
|
|
194
|
+
"authority_epoch" integer,
|
|
195
|
+
"generation" bigint NOT NULL DEFAULT 1,
|
|
196
|
+
"status" text NOT NULL DEFAULT 'active',
|
|
197
|
+
"expires_at" timestamptz,
|
|
198
|
+
"revoked_at" timestamptz,
|
|
199
|
+
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
200
|
+
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
201
|
+
CONSTRAINT "organization_user_resource_grants_authority_fk"
|
|
202
|
+
FOREIGN KEY ("authority_id", "account_id")
|
|
203
|
+
REFERENCES "organization_user_resource_authorities"("id", "account_id")
|
|
204
|
+
ON DELETE RESTRICT,
|
|
205
|
+
CONSTRAINT "organization_user_resource_grants_owner_membership_fk"
|
|
206
|
+
FOREIGN KEY ("owner_organization_membership_id", "account_id")
|
|
207
|
+
REFERENCES "organization_memberships"("id", "account_id") ON DELETE RESTRICT,
|
|
208
|
+
CONSTRAINT "organization_user_resource_grants_authority_owner_fk"
|
|
209
|
+
FOREIGN KEY ("authority_id", "account_id", "owner_organization_membership_id")
|
|
210
|
+
REFERENCES "organization_user_resource_authorities"(
|
|
211
|
+
"id", "account_id", "organization_membership_id"
|
|
212
|
+
) ON DELETE RESTRICT,
|
|
213
|
+
CONSTRAINT "organization_user_resource_grants_workspace_account_fk"
|
|
214
|
+
FOREIGN KEY ("workspace_id", "account_id")
|
|
215
|
+
REFERENCES "workspaces"("id", "account_id") ON DELETE CASCADE,
|
|
216
|
+
CONSTRAINT "organization_user_resource_grants_session_workspace_fk"
|
|
217
|
+
FOREIGN KEY ("workspace_id", "session_id")
|
|
218
|
+
REFERENCES "sessions"("workspace_id", "id") ON DELETE RESTRICT,
|
|
219
|
+
CONSTRAINT "organization_user_resource_grants_action_check" CHECK (
|
|
220
|
+
"action" = lower(btrim("action"))
|
|
221
|
+
AND length("action") BETWEEN 1 AND 64
|
|
222
|
+
AND "action" ~ '^[a-z0-9](?:[a-z0-9._:-]*[a-z0-9])?$'
|
|
223
|
+
),
|
|
224
|
+
CONSTRAINT "organization_user_resource_grants_mode_check" CHECK (
|
|
225
|
+
"mode" IN ('once', 'session', 'always')
|
|
226
|
+
),
|
|
227
|
+
CONSTRAINT "organization_user_resource_grants_context_check" CHECK (
|
|
228
|
+
"context" IN ('user_private', 'workspace_shared')
|
|
229
|
+
),
|
|
230
|
+
CONSTRAINT "organization_user_resource_grants_session_fence_check" CHECK (
|
|
231
|
+
(
|
|
232
|
+
"mode" = 'always'
|
|
233
|
+
AND "session_id" IS NULL
|
|
234
|
+
AND "authority_epoch" IS NULL
|
|
235
|
+
) OR (
|
|
236
|
+
"mode" IN ('once', 'session')
|
|
237
|
+
AND
|
|
238
|
+
"session_id" IS NOT NULL
|
|
239
|
+
AND "authority_epoch" IS NOT NULL
|
|
240
|
+
AND "authority_epoch" > 0
|
|
241
|
+
)
|
|
242
|
+
),
|
|
243
|
+
CONSTRAINT "organization_user_resource_grants_generation_check" CHECK (
|
|
244
|
+
"generation" > 0
|
|
245
|
+
),
|
|
246
|
+
CONSTRAINT "organization_user_resource_grants_status_check" CHECK (
|
|
247
|
+
"status" IN ('active', 'consumed', 'revoked', 'expired')
|
|
248
|
+
),
|
|
249
|
+
CONSTRAINT "organization_user_resource_grants_revocation_check" CHECK (
|
|
250
|
+
("status" = 'revoked' AND "revoked_at" IS NOT NULL)
|
|
251
|
+
OR ("status" <> 'revoked' AND "revoked_at" IS NULL)
|
|
252
|
+
)
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
CREATE UNIQUE INDEX "organization_user_resource_grants_id_account_idx"
|
|
256
|
+
ON "organization_user_resource_grants" ("id", "account_id");
|
|
257
|
+
CREATE INDEX "organization_user_resource_grants_authority_workspace_idx"
|
|
258
|
+
ON "organization_user_resource_grants" ("authority_id", "workspace_id", "status");
|
|
259
|
+
|
|
260
|
+
-- Slice A is intentionally inert. Each table has one explicit system-only
|
|
261
|
+
-- deny-all policy and no direct opengeni_app privileges, so the runtime role
|
|
262
|
+
-- remains denied until a later reviewed dual-write/backfill/validate/activate
|
|
263
|
+
-- slice installs exact behavior.
|
|
264
|
+
ALTER TABLE "organization_memberships" ENABLE ROW LEVEL SECURITY;
|
|
265
|
+
ALTER TABLE "organization_memberships" FORCE ROW LEVEL SECURITY;
|
|
266
|
+
ALTER TABLE "organization_user_retention_policies" ENABLE ROW LEVEL SECURITY;
|
|
267
|
+
ALTER TABLE "organization_user_retention_policies" FORCE ROW LEVEL SECURITY;
|
|
268
|
+
ALTER TABLE "organization_user_resource_authorities" ENABLE ROW LEVEL SECURITY;
|
|
269
|
+
ALTER TABLE "organization_user_resource_authorities" FORCE ROW LEVEL SECURITY;
|
|
270
|
+
ALTER TABLE "organization_user_resource_grants" ENABLE ROW LEVEL SECURITY;
|
|
271
|
+
ALTER TABLE "organization_user_resource_grants" FORCE ROW LEVEL SECURITY;
|
|
272
|
+
|
|
273
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_memberships";
|
|
274
|
+
CREATE POLICY organization_tenancy_system_only ON "organization_memberships"
|
|
275
|
+
USING (false) WITH CHECK (false);
|
|
276
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_user_retention_policies";
|
|
277
|
+
CREATE POLICY organization_tenancy_system_only ON "organization_user_retention_policies"
|
|
278
|
+
USING (false) WITH CHECK (false);
|
|
279
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_user_resource_authorities";
|
|
280
|
+
CREATE POLICY organization_tenancy_system_only ON "organization_user_resource_authorities"
|
|
281
|
+
USING (false) WITH CHECK (false);
|
|
282
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_user_resource_grants";
|
|
283
|
+
CREATE POLICY organization_tenancy_system_only ON "organization_user_resource_grants"
|
|
284
|
+
USING (false) WITH CHECK (false);
|
|
285
|
+
|
|
286
|
+
COMMENT ON TABLE "organization_memberships" IS
|
|
287
|
+
'Organization membership and personal-workspace lifecycle metadata; not workspace content access.';
|
|
288
|
+
COMMENT ON COLUMN "organization_memberships"."personal_workspace_id" IS
|
|
289
|
+
'One personal workspace per membership; lifecycle metadata, never user-resource ownership.';
|
|
290
|
+
COMMENT ON TABLE "organization_user_resource_authorities" IS
|
|
291
|
+
'Stable organization+membership user-resource authority identity; inert in Slice A.';
|
|
292
|
+
COMMENT ON COLUMN "organization_user_resource_authorities"."origin_workspace_id" IS
|
|
293
|
+
'Non-authoritative provenance only; deletion clears this fact without transferring authority.';
|
|
294
|
+
COMMENT ON TABLE "organization_user_resource_grants" IS
|
|
295
|
+
'Opaque once/session/always user-resource grant identities; inert in Slice A.';
|
|
296
|
+
COMMENT ON COLUMN "sessions"."visibility" IS
|
|
297
|
+
'Generic user_private/workspace_shared tenancy visibility; Slice A adds storage only.';
|
|
298
|
+
COMMENT ON COLUMN "sessions"."authority_epoch" IS
|
|
299
|
+
'Monotonic execution-authority fence for later sharing/fork runtime; Slice A baseline is 1.';
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- Activate only the managed-human provisioning seam for organization tenancy.
|
|
3
|
+
-- This migration does not expose organization/member CRUD, resource authority or
|
|
4
|
+
-- grant writes, session sharing, or personal-workspace runtime access.
|
|
5
|
+
|
|
6
|
+
SET LOCAL lock_timeout = '5s';
|
|
7
|
+
SET LOCAL statement_timeout = '10min';
|
|
8
|
+
|
|
9
|
+
-- Keep all four Slice A tables FORCE-RLS and replace the inert deny-all policy
|
|
10
|
+
-- with one transaction-local capability marker. The marker is set only inside
|
|
11
|
+
-- the exact SECURITY DEFINER lifecycle routine below; opengeni_app still has
|
|
12
|
+
-- no direct table privileges on any of these tables.
|
|
13
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_memberships";
|
|
14
|
+
CREATE POLICY organization_tenancy_lifecycle ON "organization_memberships"
|
|
15
|
+
USING (
|
|
16
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
17
|
+
= 'managed_human_provisioning'
|
|
18
|
+
)
|
|
19
|
+
WITH CHECK (
|
|
20
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
21
|
+
= 'managed_human_provisioning'
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_user_retention_policies";
|
|
25
|
+
CREATE POLICY organization_tenancy_lifecycle ON "organization_user_retention_policies"
|
|
26
|
+
USING (
|
|
27
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
28
|
+
= 'managed_human_provisioning'
|
|
29
|
+
)
|
|
30
|
+
WITH CHECK (
|
|
31
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
32
|
+
= 'managed_human_provisioning'
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_user_resource_authorities";
|
|
36
|
+
CREATE POLICY organization_tenancy_lifecycle ON "organization_user_resource_authorities"
|
|
37
|
+
USING (
|
|
38
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
39
|
+
= 'managed_human_provisioning'
|
|
40
|
+
)
|
|
41
|
+
WITH CHECK (
|
|
42
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
43
|
+
= 'managed_human_provisioning'
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
DROP POLICY IF EXISTS organization_tenancy_system_only ON "organization_user_resource_grants";
|
|
47
|
+
CREATE POLICY organization_tenancy_lifecycle ON "organization_user_resource_grants"
|
|
48
|
+
USING (
|
|
49
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
50
|
+
= 'managed_human_provisioning'
|
|
51
|
+
)
|
|
52
|
+
WITH CHECK (
|
|
53
|
+
current_setting('opengeni.organization_tenancy_lifecycle', true)
|
|
54
|
+
= 'managed_human_provisioning'
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
DO $organization_tenancy_managed_human_provisioning$
|
|
58
|
+
DECLARE
|
|
59
|
+
data_schema text := current_schema();
|
|
60
|
+
BEGIN
|
|
61
|
+
EXECUTE format($ddl$
|
|
62
|
+
CREATE OR REPLACE FUNCTION %1$I.ensure_managed_human_personal_workspace(
|
|
63
|
+
p_account_id uuid,
|
|
64
|
+
p_subject_id text,
|
|
65
|
+
p_personal_workspace_id uuid
|
|
66
|
+
)
|
|
67
|
+
RETURNS TABLE (
|
|
68
|
+
organization_membership_id uuid,
|
|
69
|
+
personal_workspace_id uuid
|
|
70
|
+
)
|
|
71
|
+
LANGUAGE plpgsql
|
|
72
|
+
SECURITY DEFINER
|
|
73
|
+
SET search_path = %1$I, pg_catalog
|
|
74
|
+
AS $body$
|
|
75
|
+
DECLARE
|
|
76
|
+
expected_external_id text;
|
|
77
|
+
membership_row organization_memberships%%ROWTYPE;
|
|
78
|
+
workspace_row workspaces%%ROWTYPE;
|
|
79
|
+
previous_workspace_id text := pg_catalog.current_setting(
|
|
80
|
+
'opengeni.workspace_id',
|
|
81
|
+
true
|
|
82
|
+
);
|
|
83
|
+
previous_lifecycle_marker text := pg_catalog.current_setting(
|
|
84
|
+
'opengeni.organization_tenancy_lifecycle',
|
|
85
|
+
true
|
|
86
|
+
);
|
|
87
|
+
BEGIN
|
|
88
|
+
IF p_account_id IS NULL
|
|
89
|
+
OR p_subject_id IS NULL
|
|
90
|
+
OR p_personal_workspace_id IS NULL
|
|
91
|
+
THEN
|
|
92
|
+
RAISE EXCEPTION 'managed-human provisioning requires complete identity'
|
|
93
|
+
USING ERRCODE = '42501';
|
|
94
|
+
END IF;
|
|
95
|
+
|
|
96
|
+
IF p_subject_id <> pg_catalog.btrim(p_subject_id)
|
|
97
|
+
OR pg_catalog.length(p_subject_id) NOT BETWEEN 1 AND 1024
|
|
98
|
+
OR p_subject_id NOT LIKE 'user:%%'
|
|
99
|
+
THEN
|
|
100
|
+
RAISE EXCEPTION 'managed-human provisioning subject is invalid'
|
|
101
|
+
USING ERRCODE = '42501';
|
|
102
|
+
END IF;
|
|
103
|
+
|
|
104
|
+
expected_external_id := pg_catalog.substr(p_subject_id, 6);
|
|
105
|
+
IF expected_external_id IS NULL OR pg_catalog.length(expected_external_id) < 1 THEN
|
|
106
|
+
RAISE EXCEPTION 'managed-human provisioning subject is invalid'
|
|
107
|
+
USING ERRCODE = '42501';
|
|
108
|
+
END IF;
|
|
109
|
+
|
|
110
|
+
IF p_account_id IS DISTINCT FROM opengeni_private.current_account_id() THEN
|
|
111
|
+
RAISE EXCEPTION 'managed-human provisioning account authority is invalid'
|
|
112
|
+
USING ERRCODE = '42501';
|
|
113
|
+
END IF;
|
|
114
|
+
|
|
115
|
+
IF NOT EXISTS (
|
|
116
|
+
SELECT 1
|
|
117
|
+
FROM managed_accounts account_row
|
|
118
|
+
WHERE account_row.id = p_account_id
|
|
119
|
+
AND account_row.external_source = 'better-auth:user'
|
|
120
|
+
AND account_row.external_id = expected_external_id
|
|
121
|
+
) THEN
|
|
122
|
+
RAISE EXCEPTION 'managed-human provisioning account identity is invalid'
|
|
123
|
+
USING ERRCODE = '42501';
|
|
124
|
+
END IF;
|
|
125
|
+
|
|
126
|
+
IF NOT EXISTS (
|
|
127
|
+
SELECT 1
|
|
128
|
+
FROM workspace_memberships owner_membership
|
|
129
|
+
INNER JOIN workspaces owner_workspace
|
|
130
|
+
ON owner_workspace.id = owner_membership.workspace_id
|
|
131
|
+
AND owner_workspace.account_id = owner_membership.account_id
|
|
132
|
+
WHERE owner_membership.account_id = p_account_id
|
|
133
|
+
AND owner_membership.subject_id = p_subject_id
|
|
134
|
+
AND owner_membership.role = 'owner'
|
|
135
|
+
) THEN
|
|
136
|
+
RAISE EXCEPTION 'managed-human provisioning owner membership is invalid'
|
|
137
|
+
USING ERRCODE = '42501';
|
|
138
|
+
END IF;
|
|
139
|
+
|
|
140
|
+
SELECT *
|
|
141
|
+
INTO workspace_row
|
|
142
|
+
FROM workspaces candidate_workspace
|
|
143
|
+
WHERE candidate_workspace.id = p_personal_workspace_id
|
|
144
|
+
FOR UPDATE;
|
|
145
|
+
IF NOT FOUND
|
|
146
|
+
OR workspace_row.account_id IS DISTINCT FROM p_account_id
|
|
147
|
+
OR workspace_row.external_source IS DISTINCT FROM 'opengeni:organization-membership'
|
|
148
|
+
OR workspace_row.external_id IS DISTINCT FROM (
|
|
149
|
+
p_account_id::text || ':' || p_subject_id
|
|
150
|
+
)
|
|
151
|
+
THEN
|
|
152
|
+
RAISE EXCEPTION 'managed-human provisioning personal workspace identity is invalid'
|
|
153
|
+
USING ERRCODE = '42501';
|
|
154
|
+
END IF;
|
|
155
|
+
|
|
156
|
+
IF EXISTS (
|
|
157
|
+
SELECT 1
|
|
158
|
+
FROM workspaces conflicting_workspace
|
|
159
|
+
WHERE conflicting_workspace.external_source = 'opengeni:organization-membership'
|
|
160
|
+
AND conflicting_workspace.external_id = (
|
|
161
|
+
p_account_id::text || ':' || p_subject_id
|
|
162
|
+
)
|
|
163
|
+
AND conflicting_workspace.id <> p_personal_workspace_id
|
|
164
|
+
) THEN
|
|
165
|
+
RAISE EXCEPTION 'managed-human provisioning personal workspace identity conflicts'
|
|
166
|
+
USING ERRCODE = '23505';
|
|
167
|
+
END IF;
|
|
168
|
+
|
|
169
|
+
IF EXISTS (
|
|
170
|
+
SELECT 1
|
|
171
|
+
FROM workspace_memberships personal_access
|
|
172
|
+
WHERE personal_access.workspace_id = p_personal_workspace_id
|
|
173
|
+
) THEN
|
|
174
|
+
RAISE EXCEPTION 'managed-human personal workspace already has runtime access'
|
|
175
|
+
USING ERRCODE = '42501';
|
|
176
|
+
END IF;
|
|
177
|
+
|
|
178
|
+
-- workspace_inference_controls is FORCE-RLS and needs the exact workspace
|
|
179
|
+
-- context for this structural validation. Restore the caller context on
|
|
180
|
+
-- both success and error before returning from this capability.
|
|
181
|
+
PERFORM pg_catalog.set_config(
|
|
182
|
+
'opengeni.workspace_id',
|
|
183
|
+
p_personal_workspace_id::text,
|
|
184
|
+
true
|
|
185
|
+
);
|
|
186
|
+
IF NOT EXISTS (
|
|
187
|
+
SELECT 1
|
|
188
|
+
FROM workspace_inference_controls control_row
|
|
189
|
+
WHERE control_row.workspace_id = p_personal_workspace_id
|
|
190
|
+
AND control_row.account_id = p_account_id
|
|
191
|
+
) THEN
|
|
192
|
+
RAISE EXCEPTION 'managed-human personal workspace control is missing'
|
|
193
|
+
USING ERRCODE = '42501';
|
|
194
|
+
END IF;
|
|
195
|
+
|
|
196
|
+
PERFORM pg_catalog.set_config(
|
|
197
|
+
'opengeni.organization_tenancy_lifecycle',
|
|
198
|
+
'managed_human_provisioning',
|
|
199
|
+
true
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
INSERT INTO organization_memberships (
|
|
203
|
+
account_id,
|
|
204
|
+
subject_id,
|
|
205
|
+
status,
|
|
206
|
+
personal_workspace_id
|
|
207
|
+
) VALUES (
|
|
208
|
+
p_account_id,
|
|
209
|
+
p_subject_id,
|
|
210
|
+
'active',
|
|
211
|
+
p_personal_workspace_id
|
|
212
|
+
)
|
|
213
|
+
ON CONFLICT (account_id, subject_id) DO NOTHING;
|
|
214
|
+
|
|
215
|
+
SELECT *
|
|
216
|
+
INTO membership_row
|
|
217
|
+
FROM organization_memberships candidate_membership
|
|
218
|
+
WHERE candidate_membership.account_id = p_account_id
|
|
219
|
+
AND candidate_membership.subject_id = p_subject_id
|
|
220
|
+
FOR UPDATE;
|
|
221
|
+
IF NOT FOUND THEN
|
|
222
|
+
RAISE EXCEPTION 'managed-human organization membership was not created'
|
|
223
|
+
USING ERRCODE = 'P0002';
|
|
224
|
+
END IF;
|
|
225
|
+
|
|
226
|
+
IF membership_row.status IN ('suspended', 'revoked') THEN
|
|
227
|
+
RAISE EXCEPTION 'managed-human organization membership is not active'
|
|
228
|
+
USING ERRCODE = '42501';
|
|
229
|
+
END IF;
|
|
230
|
+
IF membership_row.status = 'active'
|
|
231
|
+
AND membership_row.personal_workspace_id IS DISTINCT FROM p_personal_workspace_id
|
|
232
|
+
THEN
|
|
233
|
+
RAISE EXCEPTION 'managed-human organization membership personal workspace conflicts'
|
|
234
|
+
USING ERRCODE = '23505';
|
|
235
|
+
END IF;
|
|
236
|
+
IF membership_row.status = 'provisioning'
|
|
237
|
+
AND membership_row.personal_workspace_id IS NOT NULL
|
|
238
|
+
AND membership_row.personal_workspace_id IS DISTINCT FROM p_personal_workspace_id
|
|
239
|
+
THEN
|
|
240
|
+
RAISE EXCEPTION 'managed-human organization membership personal workspace conflicts'
|
|
241
|
+
USING ERRCODE = '23505';
|
|
242
|
+
END IF;
|
|
243
|
+
|
|
244
|
+
IF membership_row.status = 'provisioning' THEN
|
|
245
|
+
UPDATE organization_memberships
|
|
246
|
+
SET status = 'active',
|
|
247
|
+
personal_workspace_id = p_personal_workspace_id,
|
|
248
|
+
updated_at = pg_catalog.clock_timestamp()
|
|
249
|
+
WHERE id = membership_row.id;
|
|
250
|
+
membership_row.status := 'active';
|
|
251
|
+
membership_row.personal_workspace_id := p_personal_workspace_id;
|
|
252
|
+
END IF;
|
|
253
|
+
|
|
254
|
+
IF membership_row.status <> 'active'
|
|
255
|
+
OR membership_row.personal_workspace_id IS DISTINCT FROM p_personal_workspace_id
|
|
256
|
+
THEN
|
|
257
|
+
RAISE EXCEPTION 'managed-human organization membership did not converge'
|
|
258
|
+
USING ERRCODE = '42501';
|
|
259
|
+
END IF;
|
|
260
|
+
|
|
261
|
+
PERFORM pg_catalog.set_config(
|
|
262
|
+
'opengeni.workspace_id',
|
|
263
|
+
CASE
|
|
264
|
+
WHEN previous_workspace_id IS NULL THEN ''
|
|
265
|
+
ELSE previous_workspace_id
|
|
266
|
+
END,
|
|
267
|
+
true
|
|
268
|
+
);
|
|
269
|
+
PERFORM pg_catalog.set_config(
|
|
270
|
+
'opengeni.organization_tenancy_lifecycle',
|
|
271
|
+
CASE
|
|
272
|
+
WHEN previous_lifecycle_marker IS NULL THEN ''
|
|
273
|
+
ELSE previous_lifecycle_marker
|
|
274
|
+
END,
|
|
275
|
+
true
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
organization_membership_id := membership_row.id;
|
|
279
|
+
personal_workspace_id := membership_row.personal_workspace_id;
|
|
280
|
+
RETURN NEXT;
|
|
281
|
+
EXCEPTION WHEN OTHERS THEN
|
|
282
|
+
PERFORM pg_catalog.set_config(
|
|
283
|
+
'opengeni.workspace_id',
|
|
284
|
+
CASE
|
|
285
|
+
WHEN previous_workspace_id IS NULL THEN ''
|
|
286
|
+
ELSE previous_workspace_id
|
|
287
|
+
END,
|
|
288
|
+
true
|
|
289
|
+
);
|
|
290
|
+
PERFORM pg_catalog.set_config(
|
|
291
|
+
'opengeni.organization_tenancy_lifecycle',
|
|
292
|
+
CASE
|
|
293
|
+
WHEN previous_lifecycle_marker IS NULL THEN ''
|
|
294
|
+
ELSE previous_lifecycle_marker
|
|
295
|
+
END,
|
|
296
|
+
true
|
|
297
|
+
);
|
|
298
|
+
RAISE;
|
|
299
|
+
END;
|
|
300
|
+
$body$;
|
|
301
|
+
$ddl$, data_schema);
|
|
302
|
+
|
|
303
|
+
EXECUTE format(
|
|
304
|
+
'REVOKE ALL ON FUNCTION %I.ensure_managed_human_personal_workspace(uuid,text,uuid) FROM PUBLIC',
|
|
305
|
+
data_schema
|
|
306
|
+
);
|
|
307
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
308
|
+
EXECUTE format(
|
|
309
|
+
'GRANT EXECUTE ON FUNCTION %I.ensure_managed_human_personal_workspace(uuid,text,uuid) TO opengeni_app',
|
|
310
|
+
data_schema
|
|
311
|
+
);
|
|
312
|
+
END IF;
|
|
313
|
+
END
|
|
314
|
+
$organization_tenancy_managed_human_provisioning$;
|
|
315
|
+
|
|
316
|
+
COMMENT ON FUNCTION ensure_managed_human_personal_workspace(uuid, text, uuid) IS
|
|
317
|
+
'Lifecycle-only managed-human organization membership and personal-workspace provisioning; no workspace access grant.';
|