@sixb/pg 0.1.7 → 0.1.9
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/agents/rows.d.ts +0 -1
- package/dist/agents/rows.d.ts.map +1 -1
- package/dist/agents/runs.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7596 -6416
- package/dist/index.js.map +25 -19
- package/dist/migrations.d.ts.map +1 -1
- package/dist/objects/index.d.ts +2 -0
- package/dist/objects/index.d.ts.map +1 -0
- package/dist/{pg-object-query-compiler.d.ts → objects/query-compiler.d.ts} +25 -4
- package/dist/objects/query-compiler.d.ts.map +1 -0
- package/dist/objects/read-scope.d.ts +17 -0
- package/dist/objects/read-scope.d.ts.map +1 -0
- package/dist/objects/reader.d.ts +50 -0
- package/dist/objects/reader.d.ts.map +1 -0
- package/dist/objects/rows.d.ts +47 -0
- package/dist/objects/rows.d.ts.map +1 -0
- package/dist/objects/selected-reader.d.ts +8 -0
- package/dist/objects/selected-reader.d.ts.map +1 -0
- package/dist/{pg-object-storage.d.ts → objects/storage.d.ts} +12 -20
- package/dist/objects/storage.d.ts.map +1 -0
- package/dist/pg-action-run-storage.d.ts.map +1 -1
- package/dist/pg-ai-cost-storage.d.ts.map +1 -1
- package/dist/pg-ai-usage-storage.d.ts.map +1 -1
- package/dist/pg-execution-storage.d.ts +3 -2
- package/dist/pg-execution-storage.d.ts.map +1 -1
- package/dist/pg-pipeline-run-storage.d.ts.map +1 -1
- package/dist/pg-sync-run-storage.d.ts.map +1 -1
- package/dist/pg-workflow-run-storage.d.ts.map +1 -1
- package/dist/share-grant-storage.d.ts +11 -0
- package/dist/share-grant-storage.d.ts.map +1 -0
- package/dist/share-session-storage.d.ts +11 -0
- package/dist/share-session-storage.d.ts.map +1 -0
- package/dist/storage-errors.d.ts +2 -0
- package/dist/storage-errors.d.ts.map +1 -1
- package/dist/transactions.d.ts +9 -2
- package/dist/transactions.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/agents/rows.ts +0 -5
- package/src/agents/runs.ts +1 -6
- package/src/ai-cost-groups.ts +3 -0
- package/src/index.ts +20 -5
- package/src/migrations/035-share-grants.sql +57 -0
- package/src/migrations/036-share-sessions.sql +173 -0
- package/src/migrations/037-execution-requester-groups.sql +21 -0
- package/src/migrations.ts +9 -0
- package/src/objects/index.ts +1 -0
- package/src/{pg-object-query-compiler.ts → objects/query-compiler.ts} +185 -100
- package/src/objects/read-scope.ts +324 -0
- package/src/objects/reader.ts +604 -0
- package/src/objects/rows.ts +146 -0
- package/src/objects/selected-reader.ts +118 -0
- package/src/objects/storage.ts +305 -0
- package/src/pg-action-run-storage.ts +6 -7
- package/src/pg-ai-cost-storage.ts +11 -2
- package/src/pg-ai-usage-storage.ts +1 -2
- package/src/pg-execution-storage.ts +27 -6
- package/src/pg-pipeline-run-storage.ts +2 -5
- package/src/pg-sync-run-storage.ts +2 -5
- package/src/pg-workflow-run-storage.ts +0 -5
- package/src/share-grant-storage.ts +236 -0
- package/src/share-session-storage.ts +127 -0
- package/src/storage-errors.ts +6 -0
- package/src/transactions.ts +46 -5
- package/dist/pg-object-query-compiler.d.ts.map +0 -1
- package/dist/pg-object-storage.d.ts.map +0 -1
- package/src/pg-object-storage.ts +0 -734
package/src/index.ts
CHANGED
|
@@ -10,9 +10,14 @@ import type {
|
|
|
10
10
|
StorageTransactionOptions,
|
|
11
11
|
} from "@sixb/core"
|
|
12
12
|
import { ProviderMaterializationTransactionLifecycle } from "@sixb/core/internal/ontology-storage-provider"
|
|
13
|
+
import {
|
|
14
|
+
createTransactionStorageProxy,
|
|
15
|
+
throwNestedStorageTransaction,
|
|
16
|
+
} from "@sixb/core/internal/storage"
|
|
13
17
|
import {
|
|
14
18
|
createAgentOperationScope,
|
|
15
19
|
createAuthOperationScope,
|
|
20
|
+
createObjectOperationScope,
|
|
16
21
|
createOntologyOperationScope,
|
|
17
22
|
createOperationScopedFacade,
|
|
18
23
|
createStorageOperationScope,
|
|
@@ -22,15 +27,14 @@ import {
|
|
|
22
27
|
type AiCostStorage,
|
|
23
28
|
type AiLimitStorage,
|
|
24
29
|
type AiUsageStorage,
|
|
25
|
-
createTransactionStorageProxy,
|
|
26
30
|
type ObjectStorage,
|
|
27
31
|
StorageTransactionError,
|
|
28
|
-
throwNestedStorageTransaction,
|
|
29
32
|
} from "@sixb/core/storage"
|
|
30
33
|
import { PgAgentStorage } from "./agents"
|
|
31
34
|
import { PgAuthStorage } from "./auth-storage"
|
|
32
35
|
import { PgConnectorConnectionStorage } from "./connector-connection-storage"
|
|
33
36
|
import { createPostgresStorageMigrators, dropSchema } from "./migrations"
|
|
37
|
+
import { PgObjectStorage } from "./objects"
|
|
34
38
|
import { PgOntologyStorage, type PgOntologyTransactionContext } from "./ontology-storage"
|
|
35
39
|
import { PgActionRunStorage } from "./pg-action-run-storage"
|
|
36
40
|
import { PgAiCostStorage } from "./pg-ai-cost-storage"
|
|
@@ -38,7 +42,6 @@ import { PgAiLimitStorage } from "./pg-ai-limit-storage"
|
|
|
38
42
|
import { PgAiUsageStorage } from "./pg-ai-usage-storage"
|
|
39
43
|
import { createPgClient, type SQL, type SQLClient } from "./pg-client"
|
|
40
44
|
import { PgExecutionStorage } from "./pg-execution-storage"
|
|
41
|
-
import { PgObjectStorage } from "./pg-object-storage"
|
|
42
45
|
import { PgPipelineRunStorage } from "./pg-pipeline-run-storage"
|
|
43
46
|
import { PgProjectionRunStorage } from "./pg-projection-run-storage"
|
|
44
47
|
import { PgRulesStorage } from "./pg-rules-storage"
|
|
@@ -47,6 +50,8 @@ import { PgTimeseriesStorage } from "./pg-timeseries-storage"
|
|
|
47
50
|
import { PgWebhookRunStorage } from "./pg-webhook-run-storage"
|
|
48
51
|
import { PgWorkflowInterventionStorage } from "./pg-workflow-intervention-storage"
|
|
49
52
|
import { PgWorkflowRunStorage } from "./pg-workflow-run-storage"
|
|
53
|
+
import { PgShareGrantStorage } from "./share-grant-storage"
|
|
54
|
+
import { PgShareSessionStorage } from "./share-session-storage"
|
|
50
55
|
import { isRetryableTransactionConflict } from "./storage-errors"
|
|
51
56
|
import { registerPostgresStorageTestingAdapter } from "./testing"
|
|
52
57
|
import { type PgStoreClient, runPgTransaction } from "./transactions"
|
|
@@ -151,6 +156,8 @@ export class PostgresStorage implements MigrationCapableStorage {
|
|
|
151
156
|
readonly webhookRuns: PgWebhookRunStorage
|
|
152
157
|
readonly rules: PgRulesStorage
|
|
153
158
|
readonly connectorConnections: PgConnectorConnectionStorage
|
|
159
|
+
readonly shareGrants: PgShareGrantStorage
|
|
160
|
+
readonly shareSessions: PgShareSessionStorage
|
|
154
161
|
readonly migrators: readonly StorageMigrator[]
|
|
155
162
|
|
|
156
163
|
private readonly sql: SQL
|
|
@@ -208,7 +215,7 @@ export class PostgresStorage implements MigrationCapableStorage {
|
|
|
208
215
|
},
|
|
209
216
|
() => this.assertRootOperationAvailable()
|
|
210
217
|
)
|
|
211
|
-
this.objects =
|
|
218
|
+
this.objects = createObjectOperationScope(stores.objects, scope)
|
|
212
219
|
this.ontology = createOntologyOperationScope(stores.ontology, scope)
|
|
213
220
|
this.auth = createAuthOperationScope(stores.auth, scope)
|
|
214
221
|
this.executions = createOperationScopedFacade(stores.executions, scope)
|
|
@@ -226,6 +233,8 @@ export class PostgresStorage implements MigrationCapableStorage {
|
|
|
226
233
|
this.webhookRuns = createOperationScopedFacade(stores.webhookRuns, scope)
|
|
227
234
|
this.rules = createOperationScopedFacade(stores.rules, scope)
|
|
228
235
|
this.connectorConnections = createOperationScopedFacade(stores.connectorConnections, scope)
|
|
236
|
+
this.shareGrants = createOperationScopedFacade(stores.shareGrants, scope)
|
|
237
|
+
this.shareSessions = createOperationScopedFacade(stores.shareSessions, scope)
|
|
229
238
|
registerPostgresStorageTestingAdapter(this, (durationMs) =>
|
|
230
239
|
stores.connectorConnections.advanceTimeForTesting(durationMs)
|
|
231
240
|
)
|
|
@@ -334,7 +343,9 @@ function createPostgresStores(
|
|
|
334
343
|
}
|
|
335
344
|
): PostgresStoreSet {
|
|
336
345
|
const auth = new PgAuthStorage({ sql })
|
|
337
|
-
const
|
|
346
|
+
const shareGrants = new PgShareGrantStorage(sql)
|
|
347
|
+
const shareSessions = new PgShareSessionStorage(sql)
|
|
348
|
+
const executions = new PgExecutionStorage(sql, auth, shareSessions)
|
|
338
349
|
return {
|
|
339
350
|
objects: new PgObjectStorage(sql),
|
|
340
351
|
ontology: new PgOntologyStorage({
|
|
@@ -358,6 +369,8 @@ function createPostgresStores(
|
|
|
358
369
|
webhookRuns: new PgWebhookRunStorage(sql, executions),
|
|
359
370
|
rules: new PgRulesStorage(sql),
|
|
360
371
|
connectorConnections: new PgConnectorConnectionStorage(sql),
|
|
372
|
+
shareGrants,
|
|
373
|
+
shareSessions,
|
|
361
374
|
}
|
|
362
375
|
}
|
|
363
376
|
|
|
@@ -380,6 +393,8 @@ interface PostgresStoreSet {
|
|
|
380
393
|
readonly webhookRuns: PgWebhookRunStorage
|
|
381
394
|
readonly rules: PgRulesStorage
|
|
382
395
|
readonly connectorConnections: PgConnectorConnectionStorage
|
|
396
|
+
readonly shareGrants: PgShareGrantStorage
|
|
397
|
+
readonly shareSessions: PgShareSessionStorage
|
|
383
398
|
}
|
|
384
399
|
|
|
385
400
|
function resolveTimeoutMillis(value: number | undefined, label: string): number | undefined {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
CREATE TABLE share_grants (
|
|
2
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
3
|
+
id TEXT NOT NULL CHECK (length(trim(id)) > 0),
|
|
4
|
+
definition_id TEXT NOT NULL CHECK (length(trim(definition_id)) > 0),
|
|
5
|
+
target_object_type_id TEXT NOT NULL CHECK (length(trim(target_object_type_id)) > 0),
|
|
6
|
+
target_primary_id TEXT NOT NULL CHECK (length(trim(target_primary_id)) > 0),
|
|
7
|
+
issued_by_type TEXT NOT NULL CHECK (issued_by_type IN ('user', 'serviceAccount')),
|
|
8
|
+
issued_by_id TEXT NOT NULL CHECK (length(trim(issued_by_id)) > 0),
|
|
9
|
+
authority_version INTEGER NOT NULL CHECK (authority_version > 0),
|
|
10
|
+
authority_snapshot JSONB NOT NULL CHECK (
|
|
11
|
+
jsonb_typeof(authority_snapshot) = 'object'
|
|
12
|
+
AND jsonb_typeof(authority_snapshot -> 'version') = 'number'
|
|
13
|
+
AND (authority_snapshot ->> 'version')::integer = authority_version
|
|
14
|
+
AND jsonb_typeof(authority_snapshot -> 'access') = 'object'
|
|
15
|
+
),
|
|
16
|
+
authority_digest TEXT NOT NULL CHECK (authority_digest ~ '^[0-9a-f]{64}$'),
|
|
17
|
+
token_hash TEXT NOT NULL CHECK (token_hash ~ '^[0-9a-f]{64}$'),
|
|
18
|
+
destination_path TEXT NOT NULL CHECK (
|
|
19
|
+
left(destination_path, 1) = '/'
|
|
20
|
+
AND position('?' IN destination_path) = 0
|
|
21
|
+
AND position('#' IN destination_path) = 0
|
|
22
|
+
AND position(chr(92) IN destination_path) = 0
|
|
23
|
+
),
|
|
24
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
25
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
26
|
+
revoked_at TIMESTAMPTZ,
|
|
27
|
+
revoked_by_type TEXT CHECK (
|
|
28
|
+
revoked_by_type IS NULL OR revoked_by_type IN ('user', 'serviceAccount', 'system')
|
|
29
|
+
),
|
|
30
|
+
revoked_by_id TEXT CHECK (
|
|
31
|
+
revoked_by_id IS NULL OR length(trim(revoked_by_id)) > 0
|
|
32
|
+
),
|
|
33
|
+
PRIMARY KEY (project_id, id),
|
|
34
|
+
UNIQUE (project_id, token_hash),
|
|
35
|
+
CHECK (expires_at > created_at),
|
|
36
|
+
CHECK (revoked_at IS NULL OR revoked_at >= created_at),
|
|
37
|
+
CHECK (
|
|
38
|
+
(revoked_at IS NULL AND revoked_by_type IS NULL AND revoked_by_id IS NULL)
|
|
39
|
+
OR
|
|
40
|
+
(revoked_at IS NOT NULL AND revoked_by_type IS NOT NULL AND revoked_by_id IS NOT NULL)
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE INDEX idx_share_grants_project_created
|
|
45
|
+
ON share_grants (project_id, created_at DESC, id DESC);
|
|
46
|
+
CREATE INDEX idx_share_grants_definition_target
|
|
47
|
+
ON share_grants (
|
|
48
|
+
project_id,
|
|
49
|
+
definition_id,
|
|
50
|
+
target_object_type_id,
|
|
51
|
+
target_primary_id,
|
|
52
|
+
created_at DESC,
|
|
53
|
+
id DESC
|
|
54
|
+
);
|
|
55
|
+
CREATE INDEX idx_share_grants_expiry
|
|
56
|
+
ON share_grants (project_id, expires_at)
|
|
57
|
+
WHERE revoked_at IS NULL;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
-- Shared sessions and their execution provenance.
|
|
2
|
+
CREATE TABLE share_sessions (
|
|
3
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
4
|
+
id TEXT NOT NULL CHECK (length(trim(id)) > 0),
|
|
5
|
+
grant_id TEXT NOT NULL CHECK (length(trim(grant_id)) > 0),
|
|
6
|
+
token_hash TEXT NOT NULL CHECK (token_hash ~ '^[0-9a-f]{64}$'),
|
|
7
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
8
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
9
|
+
absolute_expires_at TIMESTAMPTZ NOT NULL,
|
|
10
|
+
revoked_at TIMESTAMPTZ,
|
|
11
|
+
PRIMARY KEY (project_id, id),
|
|
12
|
+
UNIQUE (project_id, id, grant_id),
|
|
13
|
+
UNIQUE (project_id, token_hash),
|
|
14
|
+
FOREIGN KEY (project_id, grant_id)
|
|
15
|
+
REFERENCES share_grants (project_id, id),
|
|
16
|
+
CHECK (expires_at > created_at),
|
|
17
|
+
CHECK (absolute_expires_at > created_at),
|
|
18
|
+
CHECK (expires_at <= absolute_expires_at),
|
|
19
|
+
CHECK (revoked_at IS NULL OR revoked_at >= created_at)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
CREATE INDEX idx_share_sessions_grant
|
|
23
|
+
ON share_sessions (project_id, grant_id, created_at DESC, id DESC);
|
|
24
|
+
|
|
25
|
+
CREATE INDEX idx_share_sessions_expiry
|
|
26
|
+
ON share_sessions (project_id, expires_at)
|
|
27
|
+
WHERE revoked_at IS NULL;
|
|
28
|
+
|
|
29
|
+
ALTER TABLE executions
|
|
30
|
+
ADD COLUMN authority_delegation_kind TEXT,
|
|
31
|
+
ADD COLUMN authority_delegation_id TEXT,
|
|
32
|
+
ADD COLUMN authority_delegation_session_id TEXT;
|
|
33
|
+
|
|
34
|
+
-- The original authority checks were unnamed. Drop exactly the checks that mention
|
|
35
|
+
-- authority_kind, then replace them with stable names and the delegated variant below.
|
|
36
|
+
DO $$
|
|
37
|
+
DECLARE authority_constraint RECORD;
|
|
38
|
+
BEGIN
|
|
39
|
+
FOR authority_constraint IN
|
|
40
|
+
SELECT conname
|
|
41
|
+
FROM pg_constraint
|
|
42
|
+
WHERE conrelid = 'executions'::regclass
|
|
43
|
+
AND contype = 'c'
|
|
44
|
+
AND pg_get_constraintdef(oid) LIKE '%authority_kind%'
|
|
45
|
+
LOOP
|
|
46
|
+
EXECUTE format('ALTER TABLE executions DROP CONSTRAINT %I', authority_constraint.conname);
|
|
47
|
+
END LOOP;
|
|
48
|
+
END $$;
|
|
49
|
+
|
|
50
|
+
ALTER TABLE executions
|
|
51
|
+
ADD CONSTRAINT executions_authority_kind_check CHECK (
|
|
52
|
+
authority_kind IN ('principal', 'trustedPrimitive', 'delegated', 'kernel', 'disabled')
|
|
53
|
+
),
|
|
54
|
+
ADD CONSTRAINT executions_authority_delegation_kind_check CHECK (
|
|
55
|
+
authority_delegation_kind IS NULL OR authority_delegation_kind = 'share'
|
|
56
|
+
),
|
|
57
|
+
ADD CONSTRAINT executions_authority_shape_check CHECK (
|
|
58
|
+
(
|
|
59
|
+
authority_kind = 'principal'
|
|
60
|
+
AND num_nonnulls(authority_user_id, authority_service_account_id) = 1
|
|
61
|
+
AND num_nonnulls(authority_session_id, authority_access_token_id) <= 1
|
|
62
|
+
AND (authority_session_id IS NULL OR authority_user_id IS NOT NULL)
|
|
63
|
+
AND authority_primitive_kind IS NULL
|
|
64
|
+
AND authority_primitive_id IS NULL
|
|
65
|
+
AND authority_kernel_operation IS NULL
|
|
66
|
+
AND authority_delegation_kind IS NULL
|
|
67
|
+
AND authority_delegation_id IS NULL
|
|
68
|
+
AND authority_delegation_session_id IS NULL
|
|
69
|
+
)
|
|
70
|
+
OR (
|
|
71
|
+
authority_kind = 'trustedPrimitive'
|
|
72
|
+
AND authority_user_id IS NULL
|
|
73
|
+
AND authority_service_account_id IS NULL
|
|
74
|
+
AND authority_session_id IS NULL
|
|
75
|
+
AND authority_access_token_id IS NULL
|
|
76
|
+
AND authority_primitive_kind IS NOT NULL
|
|
77
|
+
AND authority_primitive_id IS NOT NULL
|
|
78
|
+
AND length(trim(authority_primitive_id)) > 0
|
|
79
|
+
AND authority_kernel_operation IS NULL
|
|
80
|
+
AND authority_delegation_kind IS NULL
|
|
81
|
+
AND authority_delegation_id IS NULL
|
|
82
|
+
AND authority_delegation_session_id IS NULL
|
|
83
|
+
)
|
|
84
|
+
OR (
|
|
85
|
+
authority_kind = 'delegated'
|
|
86
|
+
AND authority_user_id IS NULL
|
|
87
|
+
AND authority_service_account_id IS NULL
|
|
88
|
+
AND authority_session_id IS NULL
|
|
89
|
+
AND authority_access_token_id IS NULL
|
|
90
|
+
AND authority_primitive_kind IS NULL
|
|
91
|
+
AND authority_primitive_id IS NULL
|
|
92
|
+
AND authority_kernel_operation IS NULL
|
|
93
|
+
AND authority_delegation_kind IS NOT NULL
|
|
94
|
+
AND authority_delegation_kind = 'share'
|
|
95
|
+
AND authority_delegation_id IS NOT NULL
|
|
96
|
+
AND length(trim(authority_delegation_id)) > 0
|
|
97
|
+
AND authority_delegation_session_id IS NOT NULL
|
|
98
|
+
AND length(trim(authority_delegation_session_id)) > 0
|
|
99
|
+
)
|
|
100
|
+
OR (
|
|
101
|
+
authority_kind = 'kernel'
|
|
102
|
+
AND authority_user_id IS NULL
|
|
103
|
+
AND authority_service_account_id IS NULL
|
|
104
|
+
AND authority_session_id IS NULL
|
|
105
|
+
AND authority_access_token_id IS NULL
|
|
106
|
+
AND authority_primitive_kind IS NULL
|
|
107
|
+
AND authority_primitive_id IS NULL
|
|
108
|
+
AND authority_kernel_operation IS NOT NULL
|
|
109
|
+
AND authority_delegation_kind IS NULL
|
|
110
|
+
AND authority_delegation_id IS NULL
|
|
111
|
+
AND authority_delegation_session_id IS NULL
|
|
112
|
+
)
|
|
113
|
+
OR (
|
|
114
|
+
authority_kind = 'disabled'
|
|
115
|
+
AND authority_user_id IS NULL
|
|
116
|
+
AND authority_service_account_id IS NULL
|
|
117
|
+
AND authority_session_id IS NULL
|
|
118
|
+
AND authority_access_token_id IS NULL
|
|
119
|
+
AND authority_primitive_kind IS NULL
|
|
120
|
+
AND authority_primitive_id IS NULL
|
|
121
|
+
AND authority_kernel_operation IS NULL
|
|
122
|
+
AND authority_delegation_kind IS NULL
|
|
123
|
+
AND authority_delegation_id IS NULL
|
|
124
|
+
AND authority_delegation_session_id IS NULL
|
|
125
|
+
)
|
|
126
|
+
),
|
|
127
|
+
ADD CONSTRAINT executions_executor_authority_check CHECK (
|
|
128
|
+
(
|
|
129
|
+
executor_kind = 'request'
|
|
130
|
+
AND source_kind = 'http'
|
|
131
|
+
AND executor_id = source_id
|
|
132
|
+
AND (
|
|
133
|
+
(
|
|
134
|
+
authority_kind = 'principal'
|
|
135
|
+
AND requested_by_user_id IS NOT DISTINCT FROM authority_user_id
|
|
136
|
+
AND requested_by_service_account_id IS NOT DISTINCT FROM authority_service_account_id
|
|
137
|
+
)
|
|
138
|
+
OR (
|
|
139
|
+
authority_kind IN ('delegated', 'disabled')
|
|
140
|
+
AND requested_by_user_id IS NULL
|
|
141
|
+
AND requested_by_service_account_id IS NULL
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
)
|
|
145
|
+
OR (
|
|
146
|
+
executor_kind IN ('action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow')
|
|
147
|
+
AND authority_kind = 'trustedPrimitive'
|
|
148
|
+
AND executor_kind = authority_primitive_kind
|
|
149
|
+
)
|
|
150
|
+
OR (
|
|
151
|
+
executor_kind = 'agent'
|
|
152
|
+
AND source_kind = 'execution'
|
|
153
|
+
AND (
|
|
154
|
+
(
|
|
155
|
+
authority_kind = 'principal'
|
|
156
|
+
AND authority_service_account_id IS NOT NULL
|
|
157
|
+
AND authority_session_id IS NULL
|
|
158
|
+
AND authority_access_token_id IS NULL
|
|
159
|
+
)
|
|
160
|
+
OR (
|
|
161
|
+
authority_kind = 'principal'
|
|
162
|
+
AND authority_user_id IS NOT NULL
|
|
163
|
+
AND num_nonnulls(authority_session_id, authority_access_token_id) = 1
|
|
164
|
+
)
|
|
165
|
+
OR authority_kind = 'disabled'
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
OR (executor_kind = 'kernel' AND authority_kind = 'kernel')
|
|
169
|
+
),
|
|
170
|
+
ADD CONSTRAINT fk_executions_share_session
|
|
171
|
+
FOREIGN KEY (project_id, authority_delegation_session_id, authority_delegation_id)
|
|
172
|
+
REFERENCES share_sessions (project_id, id, grant_id)
|
|
173
|
+
ON DELETE RESTRICT;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
ALTER TABLE executions ADD COLUMN requester_group_ids JSONB NOT NULL DEFAULT '[]'::jsonb;
|
|
2
|
+
|
|
3
|
+
-- Keep historical admission snapshots; never reconstruct them from current memberships.
|
|
4
|
+
WITH RECURSIVE attribution(project_id, id, groups) AS (
|
|
5
|
+
SELECT e.project_id, e.id, COALESCE(w.requester_group_ids, a.requester_group_ids, '[]'::jsonb)
|
|
6
|
+
FROM executions e
|
|
7
|
+
LEFT JOIN workflow_runs w ON w.project_id = e.project_id AND w.execution_id = e.id
|
|
8
|
+
LEFT JOIN agent_runs a ON a.project_id = e.project_id AND a.execution_id = e.id
|
|
9
|
+
WHERE e.parent_execution_id IS NULL
|
|
10
|
+
UNION ALL
|
|
11
|
+
SELECT e.project_id, e.id, COALESCE(w.requester_group_ids, a.requester_group_ids, p.groups)
|
|
12
|
+
FROM executions e
|
|
13
|
+
JOIN attribution p ON p.project_id = e.project_id AND p.id = e.parent_execution_id
|
|
14
|
+
LEFT JOIN workflow_runs w ON w.project_id = e.project_id AND w.execution_id = e.id
|
|
15
|
+
LEFT JOIN agent_runs a ON a.project_id = e.project_id AND a.execution_id = e.id
|
|
16
|
+
)
|
|
17
|
+
UPDATE executions e SET requester_group_ids = a.groups
|
|
18
|
+
FROM attribution a WHERE a.project_id = e.project_id AND a.id = e.id;
|
|
19
|
+
|
|
20
|
+
ALTER TABLE workflow_runs DROP COLUMN requester_group_ids;
|
|
21
|
+
ALTER TABLE agent_runs DROP COLUMN requester_group_ids;
|
package/src/migrations.ts
CHANGED
|
@@ -85,6 +85,8 @@ import retireAgentDefinitionsSql from "./migrations/033-retire-agent-definitions
|
|
|
85
85
|
import deviceAuthorizationsSql from "./migrations/034-device-authorizations.sql" with {
|
|
86
86
|
type: "text",
|
|
87
87
|
}
|
|
88
|
+
import shareGrantsSql from "./migrations/035-share-grants.sql" with { type: "text" }
|
|
89
|
+
import shareSessionsSql from "./migrations/036-share-sessions.sql" with { type: "text" }
|
|
88
90
|
import type { SQL, SQLClient } from "./pg-client"
|
|
89
91
|
|
|
90
92
|
export interface PostgresMigrationContext {
|
|
@@ -372,6 +374,9 @@ export const postgresStorageMigrations = defineMigrations<PostgresMigrationConte
|
|
|
372
374
|
pgSql("032-conversation-run-spec", conversationRunSpecSql),
|
|
373
375
|
pgSql("033-retire-agent-definitions", retireAgentDefinitionsSql),
|
|
374
376
|
pgSql("034-device-authorizations", deviceAuthorizationsSql),
|
|
377
|
+
pgSql("035-share-grants", shareGrantsSql),
|
|
378
|
+
pgSql("036-share-sessions", shareSessionsSql),
|
|
379
|
+
pgSql("037-execution-requester-groups", executionRequesterGroupsSql),
|
|
375
380
|
],
|
|
376
381
|
})
|
|
377
382
|
|
|
@@ -384,3 +389,7 @@ interface PostgresMigrationRow {
|
|
|
384
389
|
readonly started_at: Date | string
|
|
385
390
|
readonly finished_at: Date | string | null
|
|
386
391
|
}
|
|
392
|
+
|
|
393
|
+
import executionRequesterGroupsSql from "./migrations/037-execution-requester-groups.sql" with {
|
|
394
|
+
type: "text",
|
|
395
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PgObjectStorage } from "./storage"
|