@sixb/sqlite 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/action-run-storage.d.ts.map +1 -1
- 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/ai-cost-storage.d.ts.map +1 -1
- package/dist/ai-usage-storage.d.ts.map +1 -1
- package/dist/execution-storage.d.ts +3 -2
- package/dist/execution-storage.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1567 -430
- package/dist/index.js.map +25 -19
- package/dist/migrations.d.ts.map +1 -1
- package/dist/objects/index.d.ts +3 -0
- package/dist/objects/index.d.ts.map +1 -0
- package/dist/{object-query-compiler.d.ts → objects/query-compiler.d.ts} +16 -1
- 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 +51 -0
- package/dist/objects/reader.d.ts.map +1 -0
- package/dist/objects/rows.d.ts +33 -0
- package/dist/objects/rows.d.ts.map +1 -0
- package/dist/objects/selected-reader.d.ts +9 -0
- package/dist/objects/selected-reader.d.ts.map +1 -0
- package/dist/{object-storage.d.ts → objects/storage.d.ts} +12 -9
- package/dist/objects/storage.d.ts.map +1 -0
- package/dist/pipeline-run-storage.d.ts.map +1 -1
- package/dist/share-grant-storage.d.ts +20 -0
- package/dist/share-grant-storage.d.ts.map +1 -0
- package/dist/share-session-storage.d.ts +19 -0
- package/dist/share-session-storage.d.ts.map +1 -0
- package/dist/storage-errors.d.ts +1 -0
- package/dist/storage-errors.d.ts.map +1 -1
- package/dist/sync-run-storage.d.ts.map +1 -1
- package/dist/transactions.d.ts +8 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/workflow-run-storage.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/action-run-storage.ts +6 -7
- package/src/agents/rows.ts +0 -2
- package/src/agents/runs.ts +3 -7
- package/src/ai-cost-groups.ts +3 -0
- package/src/ai-cost-storage.ts +11 -2
- package/src/ai-usage-storage.ts +1 -2
- package/src/execution-storage.ts +28 -7
- package/src/index.ts +22 -5
- package/src/migrations/035-share-grants.sql +66 -0
- package/src/migrations/036-share-sessions.sql +226 -0
- package/src/migrations/037-execution-requester-groups.sql +24 -0
- package/src/migrations.ts +9 -0
- package/src/objects/index.ts +2 -0
- package/src/{object-query-compiler.ts → objects/query-compiler.ts} +104 -54
- package/src/objects/read-scope.ts +316 -0
- package/src/objects/reader.ts +526 -0
- package/src/objects/rows.ts +123 -0
- package/src/objects/selected-reader.ts +119 -0
- package/src/objects/storage.ts +296 -0
- package/src/pipeline-run-storage.ts +2 -5
- package/src/share-grant-storage.ts +252 -0
- package/src/share-session-storage.ts +189 -0
- package/src/storage-errors.ts +4 -0
- package/src/sync-run-storage.ts +2 -5
- package/src/transactions.ts +32 -0
- package/src/workflow-run-storage.ts +1 -6
- package/dist/object-query-compiler.d.ts.map +0 -1
- package/dist/object-storage.d.ts.map +0 -1
- package/src/object-storage.ts +0 -709
package/src/execution-storage.ts
CHANGED
|
@@ -3,24 +3,29 @@ import {
|
|
|
3
3
|
type ExecutionStorageRow,
|
|
4
4
|
executionRecordFromStorageRow,
|
|
5
5
|
executionRecordToStorageRow,
|
|
6
|
-
|
|
7
|
-
validateExecutionRecordReferences,
|
|
6
|
+
prepareExecutionRecord,
|
|
8
7
|
} from "@sixb/core/internal/execution-storage"
|
|
9
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
CreateExecutionInput,
|
|
10
|
+
ExecutionRecord,
|
|
11
|
+
ExecutionStorage,
|
|
12
|
+
ShareSessionStorage,
|
|
13
|
+
} from "@sixb/core/storage"
|
|
10
14
|
import { ExecutionStorageError } from "@sixb/core/storage"
|
|
11
15
|
import type { SqliteAuthStorage } from "./auth-storage"
|
|
12
16
|
|
|
13
17
|
export class SqliteExecutionStorage implements ExecutionStorage {
|
|
14
18
|
constructor(
|
|
15
19
|
private readonly db: Database,
|
|
16
|
-
private readonly auth: SqliteAuthStorage
|
|
20
|
+
private readonly auth: SqliteAuthStorage,
|
|
21
|
+
private readonly shareSessions: Pick<ShareSessionStorage, "getById">
|
|
17
22
|
) {}
|
|
18
23
|
|
|
19
24
|
async create(input: CreateExecutionInput): Promise<ExecutionRecord> {
|
|
20
|
-
const record =
|
|
21
|
-
await validateExecutionRecordReferences(record, {
|
|
25
|
+
const record = await prepareExecutionRecord(input, {
|
|
22
26
|
auth: this.auth,
|
|
23
27
|
getExecution: (params) => this.getById(params),
|
|
28
|
+
getShareSession: (params) => this.shareSessions.getById(params),
|
|
24
29
|
})
|
|
25
30
|
const row = executionRecordToStorageRow(record)
|
|
26
31
|
|
|
@@ -37,6 +42,7 @@ export class SqliteExecutionStorage implements ExecutionStorage {
|
|
|
37
42
|
source_id,
|
|
38
43
|
requested_by_user_id,
|
|
39
44
|
requested_by_service_account_id,
|
|
45
|
+
requester_group_ids,
|
|
40
46
|
correlation_id,
|
|
41
47
|
parent_execution_id,
|
|
42
48
|
authority_kind,
|
|
@@ -47,8 +53,11 @@ export class SqliteExecutionStorage implements ExecutionStorage {
|
|
|
47
53
|
authority_primitive_kind,
|
|
48
54
|
authority_primitive_id,
|
|
49
55
|
authority_kernel_operation,
|
|
56
|
+
authority_delegation_kind,
|
|
57
|
+
authority_delegation_id,
|
|
58
|
+
authority_delegation_session_id,
|
|
50
59
|
created_at
|
|
51
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
60
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
52
61
|
`
|
|
53
62
|
)
|
|
54
63
|
.run(
|
|
@@ -60,6 +69,7 @@ export class SqliteExecutionStorage implements ExecutionStorage {
|
|
|
60
69
|
row.sourceId,
|
|
61
70
|
row.requestedByUserId,
|
|
62
71
|
row.requestedByServiceAccountId,
|
|
72
|
+
JSON.stringify(row.requesterGroupIds),
|
|
63
73
|
row.correlationId,
|
|
64
74
|
row.parentExecutionId,
|
|
65
75
|
row.authorityKind,
|
|
@@ -70,6 +80,9 @@ export class SqliteExecutionStorage implements ExecutionStorage {
|
|
|
70
80
|
row.authorityPrimitiveKind,
|
|
71
81
|
row.authorityPrimitiveId,
|
|
72
82
|
row.authorityKernelOperation,
|
|
83
|
+
row.authorityDelegationKind,
|
|
84
|
+
row.authorityDelegationId,
|
|
85
|
+
row.authorityDelegationSessionId,
|
|
73
86
|
row.createdAt.toISOString()
|
|
74
87
|
)
|
|
75
88
|
} catch (error) {
|
|
@@ -114,6 +127,7 @@ function toStorageRow(row: SqliteExecutionRow): ExecutionStorageRow {
|
|
|
114
127
|
sourceId: row.source_id,
|
|
115
128
|
requestedByUserId: row.requested_by_user_id,
|
|
116
129
|
requestedByServiceAccountId: row.requested_by_service_account_id,
|
|
130
|
+
requesterGroupIds: JSON.parse(row.requester_group_ids),
|
|
117
131
|
correlationId: row.correlation_id,
|
|
118
132
|
parentExecutionId: row.parent_execution_id,
|
|
119
133
|
authorityKind: row.authority_kind,
|
|
@@ -124,6 +138,9 @@ function toStorageRow(row: SqliteExecutionRow): ExecutionStorageRow {
|
|
|
124
138
|
authorityPrimitiveKind: row.authority_primitive_kind,
|
|
125
139
|
authorityPrimitiveId: row.authority_primitive_id,
|
|
126
140
|
authorityKernelOperation: row.authority_kernel_operation,
|
|
141
|
+
authorityDelegationKind: row.authority_delegation_kind,
|
|
142
|
+
authorityDelegationId: row.authority_delegation_id,
|
|
143
|
+
authorityDelegationSessionId: row.authority_delegation_session_id,
|
|
127
144
|
createdAt: new Date(row.created_at),
|
|
128
145
|
}
|
|
129
146
|
}
|
|
@@ -144,6 +161,7 @@ interface SqliteExecutionRow {
|
|
|
144
161
|
readonly source_id: string
|
|
145
162
|
readonly requested_by_user_id: string | null
|
|
146
163
|
readonly requested_by_service_account_id: string | null
|
|
164
|
+
readonly requester_group_ids: string
|
|
147
165
|
readonly correlation_id: string
|
|
148
166
|
readonly parent_execution_id: string | null
|
|
149
167
|
readonly authority_kind: ExecutionStorageRow["authorityKind"]
|
|
@@ -154,5 +172,8 @@ interface SqliteExecutionRow {
|
|
|
154
172
|
readonly authority_primitive_kind: ExecutionStorageRow["authorityPrimitiveKind"]
|
|
155
173
|
readonly authority_primitive_id: string | null
|
|
156
174
|
readonly authority_kernel_operation: ExecutionStorageRow["authorityKernelOperation"]
|
|
175
|
+
readonly authority_delegation_kind: ExecutionStorageRow["authorityDelegationKind"]
|
|
176
|
+
readonly authority_delegation_id: string | null
|
|
177
|
+
readonly authority_delegation_session_id: string | null
|
|
157
178
|
readonly created_at: string
|
|
158
179
|
}
|
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,9 +27,9 @@ import {
|
|
|
22
27
|
type AiCostStorage,
|
|
23
28
|
type AiLimitStorage,
|
|
24
29
|
type AiUsageStorage,
|
|
25
|
-
|
|
30
|
+
type ShareGrantStorage,
|
|
31
|
+
type ShareSessionStorage,
|
|
26
32
|
StorageTransactionError,
|
|
27
|
-
throwNestedStorageTransaction,
|
|
28
33
|
} from "@sixb/core/storage"
|
|
29
34
|
import { SqliteActionRunStorage } from "./action-run-storage"
|
|
30
35
|
import { SqliteAgentStorage } from "./agents"
|
|
@@ -39,11 +44,13 @@ import {
|
|
|
39
44
|
installFreshSqliteSchema,
|
|
40
45
|
sqliteStoragePath,
|
|
41
46
|
} from "./migrations"
|
|
42
|
-
import { SqliteObjectStorage } from "./
|
|
47
|
+
import { SqliteObjectStorage } from "./objects"
|
|
43
48
|
import { SqliteOntologyStorage, type SqliteOntologyTransactionContext } from "./ontology-storage"
|
|
44
49
|
import { SqlitePipelineRunStorage } from "./pipeline-run-storage"
|
|
45
50
|
import { SqliteProjectionRunStorage } from "./projection-run-storage"
|
|
46
51
|
import { SqliteRulesStorage } from "./rules-storage"
|
|
52
|
+
import { SqliteShareGrantStorage } from "./share-grant-storage"
|
|
53
|
+
import { SqliteShareSessionStorage } from "./share-session-storage"
|
|
47
54
|
import { SqliteSyncRunStorage } from "./sync-run-storage"
|
|
48
55
|
import { registerSqliteStorageTestingAdapter } from "./testing"
|
|
49
56
|
import { SqliteTimeseriesStorage } from "./timeseries-storage"
|
|
@@ -96,6 +103,8 @@ export class SqliteStorage implements MigrationCapableStorage {
|
|
|
96
103
|
readonly timeseries: Storage["timeseries"]
|
|
97
104
|
readonly webhookRuns: SqliteWebhookRunStorage
|
|
98
105
|
readonly rules: SqliteRulesStorage
|
|
106
|
+
readonly shareGrants: ShareGrantStorage
|
|
107
|
+
readonly shareSessions: ShareSessionStorage
|
|
99
108
|
readonly connectorConnections: SqliteConnectorConnectionStorage
|
|
100
109
|
readonly migrators: readonly StorageMigrator[]
|
|
101
110
|
|
|
@@ -143,7 +152,7 @@ export class SqliteStorage implements MigrationCapableStorage {
|
|
|
143
152
|
const readTimeseries = path
|
|
144
153
|
? new SqliteTimeseriesStorage({ connection: this.readConnection })
|
|
145
154
|
: stores.timeseries
|
|
146
|
-
this.objects =
|
|
155
|
+
this.objects = createObjectOperationScope(readObjects, readScope)
|
|
147
156
|
this.ontology = createOntologyOperationScope(stores.ontology, ontologyScope)
|
|
148
157
|
this.auth = createAuthOperationScope(stores.auth, scope)
|
|
149
158
|
this.executions = createOperationScopedFacade(stores.executions, scope)
|
|
@@ -160,6 +169,8 @@ export class SqliteStorage implements MigrationCapableStorage {
|
|
|
160
169
|
this.workflowInterventions = createOperationScopedFacade(stores.workflowInterventions, scope)
|
|
161
170
|
this.webhookRuns = createOperationScopedFacade(stores.webhookRuns, scope)
|
|
162
171
|
this.rules = createOperationScopedFacade(stores.rules, scope)
|
|
172
|
+
this.shareGrants = createOperationScopedFacade(stores.shareGrants, scope)
|
|
173
|
+
this.shareSessions = createOperationScopedFacade(stores.shareSessions, scope)
|
|
163
174
|
this.connectorConnections = createOperationScopedFacade(stores.connectorConnections, scope)
|
|
164
175
|
this.migrators = options.path ? createSqliteStorageMigrators(options.path) : []
|
|
165
176
|
registerSqliteStorageTestingAdapter(this, (durationMs) =>
|
|
@@ -294,7 +305,9 @@ function createSqliteStores(
|
|
|
294
305
|
}
|
|
295
306
|
): SqliteStoreSet {
|
|
296
307
|
const auth = new SqliteAuthStorage({ connection })
|
|
297
|
-
const
|
|
308
|
+
const shareGrants = new SqliteShareGrantStorage({ connection })
|
|
309
|
+
const shareSessions = new SqliteShareSessionStorage({ connection })
|
|
310
|
+
const executions = new SqliteExecutionStorage(connection.db, auth, shareSessions)
|
|
298
311
|
return {
|
|
299
312
|
objects: new SqliteObjectStorage({ connection }),
|
|
300
313
|
ontology: new SqliteOntologyStorage({
|
|
@@ -317,6 +330,8 @@ function createSqliteStores(
|
|
|
317
330
|
workflowInterventions: new SqliteWorkflowInterventionStorage({ connection }),
|
|
318
331
|
webhookRuns: new SqliteWebhookRunStorage({ connection, executions }),
|
|
319
332
|
rules: new SqliteRulesStorage({ connection }),
|
|
333
|
+
shareGrants,
|
|
334
|
+
shareSessions,
|
|
320
335
|
connectorConnections: new SqliteConnectorConnectionStorage(connection),
|
|
321
336
|
}
|
|
322
337
|
}
|
|
@@ -339,6 +354,8 @@ interface SqliteStoreSet {
|
|
|
339
354
|
readonly timeseries: SqliteTimeseriesStorage
|
|
340
355
|
readonly webhookRuns: SqliteWebhookRunStorage
|
|
341
356
|
readonly rules: SqliteRulesStorage
|
|
357
|
+
readonly shareGrants: SqliteShareGrantStorage
|
|
358
|
+
readonly shareSessions: SqliteShareSessionStorage
|
|
342
359
|
readonly connectorConnections: SqliteConnectorConnectionStorage
|
|
343
360
|
}
|
|
344
361
|
|
|
@@ -0,0 +1,66 @@
|
|
|
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 TEXT NOT NULL CHECK (
|
|
11
|
+
json_valid(authority_snapshot)
|
|
12
|
+
AND json_type(authority_snapshot) = 'object'
|
|
13
|
+
AND json_type(authority_snapshot, '$.version') = 'integer'
|
|
14
|
+
AND json_extract(authority_snapshot, '$.version') = authority_version
|
|
15
|
+
AND json_type(authority_snapshot, '$.access') = 'object'
|
|
16
|
+
),
|
|
17
|
+
authority_digest TEXT NOT NULL CHECK (
|
|
18
|
+
length(authority_digest) = 64
|
|
19
|
+
AND authority_digest = lower(authority_digest)
|
|
20
|
+
AND authority_digest NOT GLOB '*[^0-9a-f]*'
|
|
21
|
+
),
|
|
22
|
+
token_hash TEXT NOT NULL CHECK (
|
|
23
|
+
length(token_hash) = 64
|
|
24
|
+
AND token_hash = lower(token_hash)
|
|
25
|
+
AND token_hash NOT GLOB '*[^0-9a-f]*'
|
|
26
|
+
),
|
|
27
|
+
destination_path TEXT NOT NULL CHECK (
|
|
28
|
+
substr(destination_path, 1, 1) = '/'
|
|
29
|
+
AND instr(destination_path, '?') = 0
|
|
30
|
+
AND instr(destination_path, '#') = 0
|
|
31
|
+
AND instr(destination_path, char(92)) = 0
|
|
32
|
+
),
|
|
33
|
+
created_at TEXT NOT NULL,
|
|
34
|
+
expires_at TEXT NOT NULL,
|
|
35
|
+
revoked_at TEXT,
|
|
36
|
+
revoked_by_type TEXT CHECK (
|
|
37
|
+
revoked_by_type IS NULL OR revoked_by_type IN ('user', 'serviceAccount', 'system')
|
|
38
|
+
),
|
|
39
|
+
revoked_by_id TEXT CHECK (revoked_by_id IS NULL OR length(trim(revoked_by_id)) > 0),
|
|
40
|
+
PRIMARY KEY (project_id, id),
|
|
41
|
+
UNIQUE (project_id, token_hash),
|
|
42
|
+
CHECK (expires_at > created_at),
|
|
43
|
+
CHECK (revoked_at IS NULL OR revoked_at >= created_at),
|
|
44
|
+
CHECK (
|
|
45
|
+
(revoked_at IS NULL AND revoked_by_type IS NULL AND revoked_by_id IS NULL)
|
|
46
|
+
OR
|
|
47
|
+
(revoked_at IS NOT NULL AND revoked_by_type IS NOT NULL AND revoked_by_id IS NOT NULL)
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE INDEX idx_share_grants_target
|
|
52
|
+
ON share_grants (
|
|
53
|
+
project_id,
|
|
54
|
+
definition_id,
|
|
55
|
+
target_object_type_id,
|
|
56
|
+
target_primary_id,
|
|
57
|
+
created_at DESC,
|
|
58
|
+
id DESC
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE INDEX idx_share_grants_project_created
|
|
62
|
+
ON share_grants (project_id, created_at DESC, id DESC);
|
|
63
|
+
|
|
64
|
+
CREATE INDEX idx_share_grants_expiry
|
|
65
|
+
ON share_grants (project_id, expires_at)
|
|
66
|
+
WHERE revoked_at IS NULL;
|
|
@@ -0,0 +1,226 @@
|
|
|
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 (
|
|
7
|
+
length(token_hash) = 64
|
|
8
|
+
AND token_hash = lower(token_hash)
|
|
9
|
+
AND token_hash NOT GLOB '*[^0-9a-f]*'
|
|
10
|
+
),
|
|
11
|
+
created_at TEXT NOT NULL,
|
|
12
|
+
expires_at TEXT NOT NULL,
|
|
13
|
+
absolute_expires_at TEXT NOT NULL,
|
|
14
|
+
revoked_at TEXT,
|
|
15
|
+
PRIMARY KEY (project_id, id),
|
|
16
|
+
UNIQUE (project_id, id, grant_id),
|
|
17
|
+
UNIQUE (project_id, token_hash),
|
|
18
|
+
FOREIGN KEY (project_id, grant_id)
|
|
19
|
+
REFERENCES share_grants (project_id, id),
|
|
20
|
+
CHECK (expires_at > created_at),
|
|
21
|
+
CHECK (absolute_expires_at > created_at),
|
|
22
|
+
CHECK (expires_at <= absolute_expires_at),
|
|
23
|
+
CHECK (revoked_at IS NULL OR revoked_at >= created_at)
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
CREATE INDEX idx_share_sessions_grant
|
|
27
|
+
ON share_sessions (project_id, grant_id, created_at DESC, id DESC);
|
|
28
|
+
|
|
29
|
+
CREATE INDEX idx_share_sessions_expiry
|
|
30
|
+
ON share_sessions (project_id, expires_at)
|
|
31
|
+
WHERE revoked_at IS NULL;
|
|
32
|
+
|
|
33
|
+
-- Persist shared-session provenance on request executions without fabricating a principal.
|
|
34
|
+
CREATE TABLE executions_v2 (
|
|
35
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
36
|
+
id TEXT NOT NULL CHECK (length(trim(id)) > 0),
|
|
37
|
+
executor_kind TEXT NOT NULL CHECK (
|
|
38
|
+
executor_kind IN (
|
|
39
|
+
'request', 'action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow',
|
|
40
|
+
'agent', 'kernel'
|
|
41
|
+
)
|
|
42
|
+
),
|
|
43
|
+
executor_id TEXT NOT NULL CHECK (length(trim(executor_id)) > 0),
|
|
44
|
+
source_kind TEXT NOT NULL CHECK (
|
|
45
|
+
source_kind IN ('http', 'webhook', 'schedule', 'event', 'datasetVersion', 'execution')
|
|
46
|
+
),
|
|
47
|
+
source_id TEXT NOT NULL CHECK (length(trim(source_id)) > 0),
|
|
48
|
+
requested_by_user_id TEXT,
|
|
49
|
+
requested_by_service_account_id TEXT,
|
|
50
|
+
correlation_id TEXT NOT NULL CHECK (length(trim(correlation_id)) > 0),
|
|
51
|
+
parent_execution_id TEXT,
|
|
52
|
+
authority_kind TEXT NOT NULL CHECK (
|
|
53
|
+
authority_kind IN ('principal', 'trustedPrimitive', 'delegated', 'kernel', 'disabled')
|
|
54
|
+
),
|
|
55
|
+
authority_user_id TEXT,
|
|
56
|
+
authority_service_account_id TEXT,
|
|
57
|
+
authority_session_id TEXT,
|
|
58
|
+
authority_access_token_id TEXT,
|
|
59
|
+
authority_primitive_kind TEXT CHECK (
|
|
60
|
+
authority_primitive_kind IS NULL
|
|
61
|
+
OR authority_primitive_kind IN (
|
|
62
|
+
'action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow'
|
|
63
|
+
)
|
|
64
|
+
),
|
|
65
|
+
authority_primitive_id TEXT,
|
|
66
|
+
authority_kernel_operation TEXT CHECK (
|
|
67
|
+
authority_kernel_operation IS NULL OR authority_kernel_operation = 'ontology.recover'
|
|
68
|
+
),
|
|
69
|
+
authority_delegation_kind TEXT CHECK (
|
|
70
|
+
authority_delegation_kind IS NULL OR authority_delegation_kind = 'share'
|
|
71
|
+
),
|
|
72
|
+
authority_delegation_id TEXT,
|
|
73
|
+
authority_delegation_session_id TEXT,
|
|
74
|
+
created_at TEXT NOT NULL,
|
|
75
|
+
PRIMARY KEY (project_id, id),
|
|
76
|
+
FOREIGN KEY (project_id, parent_execution_id) REFERENCES executions (project_id, id),
|
|
77
|
+
FOREIGN KEY (project_id, requested_by_user_id) REFERENCES auth_users (project_id, id),
|
|
78
|
+
FOREIGN KEY (project_id, requested_by_service_account_id)
|
|
79
|
+
REFERENCES auth_service_accounts (project_id, id),
|
|
80
|
+
FOREIGN KEY (project_id, authority_user_id) REFERENCES auth_users (project_id, id),
|
|
81
|
+
FOREIGN KEY (project_id, authority_service_account_id)
|
|
82
|
+
REFERENCES auth_service_accounts (project_id, id),
|
|
83
|
+
FOREIGN KEY (project_id, authority_session_id) REFERENCES auth_sessions (project_id, id),
|
|
84
|
+
FOREIGN KEY (project_id, authority_access_token_id)
|
|
85
|
+
REFERENCES auth_access_tokens (project_id, id),
|
|
86
|
+
FOREIGN KEY (
|
|
87
|
+
project_id, authority_delegation_session_id, authority_delegation_id
|
|
88
|
+
) REFERENCES share_sessions (project_id, id, grant_id),
|
|
89
|
+
CHECK ((requested_by_user_id IS NOT NULL) + (requested_by_service_account_id IS NOT NULL) <= 1),
|
|
90
|
+
CHECK (
|
|
91
|
+
(source_kind = 'execution' AND parent_execution_id = source_id)
|
|
92
|
+
OR (source_kind <> 'execution' AND parent_execution_id IS NULL)
|
|
93
|
+
),
|
|
94
|
+
CHECK (
|
|
95
|
+
(
|
|
96
|
+
authority_kind = 'principal'
|
|
97
|
+
AND (authority_user_id IS NOT NULL) + (authority_service_account_id IS NOT NULL) = 1
|
|
98
|
+
AND (authority_session_id IS NOT NULL) + (authority_access_token_id IS NOT NULL) <= 1
|
|
99
|
+
AND (authority_session_id IS NULL OR authority_user_id IS NOT NULL)
|
|
100
|
+
AND authority_primitive_kind IS NULL
|
|
101
|
+
AND authority_primitive_id IS NULL
|
|
102
|
+
AND authority_kernel_operation IS NULL
|
|
103
|
+
AND authority_delegation_kind IS NULL
|
|
104
|
+
AND authority_delegation_id IS NULL
|
|
105
|
+
AND authority_delegation_session_id IS NULL
|
|
106
|
+
)
|
|
107
|
+
OR (
|
|
108
|
+
authority_kind = 'trustedPrimitive'
|
|
109
|
+
AND authority_user_id IS NULL
|
|
110
|
+
AND authority_service_account_id IS NULL
|
|
111
|
+
AND authority_session_id IS NULL
|
|
112
|
+
AND authority_access_token_id IS NULL
|
|
113
|
+
AND authority_primitive_kind IS NOT NULL
|
|
114
|
+
AND authority_primitive_id IS NOT NULL
|
|
115
|
+
AND length(trim(authority_primitive_id)) > 0
|
|
116
|
+
AND authority_kernel_operation IS NULL
|
|
117
|
+
AND authority_delegation_kind IS NULL
|
|
118
|
+
AND authority_delegation_id IS NULL
|
|
119
|
+
AND authority_delegation_session_id IS NULL
|
|
120
|
+
)
|
|
121
|
+
OR (
|
|
122
|
+
authority_kind = 'delegated'
|
|
123
|
+
AND authority_user_id IS NULL
|
|
124
|
+
AND authority_service_account_id IS NULL
|
|
125
|
+
AND authority_session_id IS NULL
|
|
126
|
+
AND authority_access_token_id IS NULL
|
|
127
|
+
AND authority_primitive_kind IS NULL
|
|
128
|
+
AND authority_primitive_id IS NULL
|
|
129
|
+
AND authority_kernel_operation IS NULL
|
|
130
|
+
AND authority_delegation_kind IS NOT NULL
|
|
131
|
+
AND authority_delegation_kind = 'share'
|
|
132
|
+
AND authority_delegation_id IS NOT NULL
|
|
133
|
+
AND length(trim(authority_delegation_id)) > 0
|
|
134
|
+
AND authority_delegation_session_id IS NOT NULL
|
|
135
|
+
AND length(trim(authority_delegation_session_id)) > 0
|
|
136
|
+
)
|
|
137
|
+
OR (
|
|
138
|
+
authority_kind = 'kernel'
|
|
139
|
+
AND authority_user_id IS NULL
|
|
140
|
+
AND authority_service_account_id IS NULL
|
|
141
|
+
AND authority_session_id IS NULL
|
|
142
|
+
AND authority_access_token_id IS NULL
|
|
143
|
+
AND authority_primitive_kind IS NULL
|
|
144
|
+
AND authority_primitive_id IS NULL
|
|
145
|
+
AND authority_kernel_operation IS NOT NULL
|
|
146
|
+
AND authority_delegation_kind IS NULL
|
|
147
|
+
AND authority_delegation_id IS NULL
|
|
148
|
+
AND authority_delegation_session_id IS NULL
|
|
149
|
+
)
|
|
150
|
+
OR (
|
|
151
|
+
authority_kind = 'disabled'
|
|
152
|
+
AND authority_user_id IS NULL
|
|
153
|
+
AND authority_service_account_id IS NULL
|
|
154
|
+
AND authority_session_id IS NULL
|
|
155
|
+
AND authority_access_token_id IS NULL
|
|
156
|
+
AND authority_primitive_kind IS NULL
|
|
157
|
+
AND authority_primitive_id IS NULL
|
|
158
|
+
AND authority_kernel_operation IS NULL
|
|
159
|
+
AND authority_delegation_kind IS NULL
|
|
160
|
+
AND authority_delegation_id IS NULL
|
|
161
|
+
AND authority_delegation_session_id IS NULL
|
|
162
|
+
)
|
|
163
|
+
),
|
|
164
|
+
CHECK (
|
|
165
|
+
(
|
|
166
|
+
executor_kind = 'request'
|
|
167
|
+
AND source_kind = 'http'
|
|
168
|
+
AND executor_id = source_id
|
|
169
|
+
AND (
|
|
170
|
+
(
|
|
171
|
+
authority_kind = 'principal'
|
|
172
|
+
AND requested_by_user_id IS authority_user_id
|
|
173
|
+
AND requested_by_service_account_id IS authority_service_account_id
|
|
174
|
+
)
|
|
175
|
+
OR (
|
|
176
|
+
authority_kind IN ('delegated', 'disabled')
|
|
177
|
+
AND requested_by_user_id IS NULL
|
|
178
|
+
AND requested_by_service_account_id IS NULL
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
OR (
|
|
183
|
+
executor_kind IN ('action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow')
|
|
184
|
+
AND authority_kind = 'trustedPrimitive'
|
|
185
|
+
AND executor_kind = authority_primitive_kind
|
|
186
|
+
)
|
|
187
|
+
OR (
|
|
188
|
+
executor_kind = 'agent'
|
|
189
|
+
AND source_kind = 'execution'
|
|
190
|
+
AND (
|
|
191
|
+
(
|
|
192
|
+
authority_kind = 'principal'
|
|
193
|
+
AND authority_service_account_id IS NOT NULL
|
|
194
|
+
AND authority_session_id IS NULL
|
|
195
|
+
AND authority_access_token_id IS NULL
|
|
196
|
+
)
|
|
197
|
+
OR (
|
|
198
|
+
authority_kind = 'principal'
|
|
199
|
+
AND authority_user_id IS NOT NULL
|
|
200
|
+
AND (authority_session_id IS NOT NULL) + (authority_access_token_id IS NOT NULL) = 1
|
|
201
|
+
)
|
|
202
|
+
OR authority_kind = 'disabled'
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
OR (executor_kind = 'kernel' AND authority_kind = 'kernel')
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
INSERT INTO executions_v2 (
|
|
210
|
+
project_id, id, executor_kind, executor_id, source_kind, source_id,
|
|
211
|
+
requested_by_user_id, requested_by_service_account_id, correlation_id, parent_execution_id,
|
|
212
|
+
authority_kind, authority_user_id, authority_service_account_id, authority_session_id,
|
|
213
|
+
authority_access_token_id, authority_primitive_kind, authority_primitive_id,
|
|
214
|
+
authority_kernel_operation, authority_delegation_kind, authority_delegation_id,
|
|
215
|
+
authority_delegation_session_id, created_at
|
|
216
|
+
)
|
|
217
|
+
SELECT
|
|
218
|
+
project_id, id, executor_kind, executor_id, source_kind, source_id,
|
|
219
|
+
requested_by_user_id, requested_by_service_account_id, correlation_id, parent_execution_id,
|
|
220
|
+
authority_kind, authority_user_id, authority_service_account_id, authority_session_id,
|
|
221
|
+
authority_access_token_id, authority_primitive_kind, authority_primitive_id,
|
|
222
|
+
authority_kernel_operation, NULL, NULL, NULL, created_at
|
|
223
|
+
FROM executions;
|
|
224
|
+
|
|
225
|
+
DROP TABLE executions;
|
|
226
|
+
ALTER TABLE executions_v2 RENAME TO executions;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
ALTER TABLE executions ADD COLUMN requester_group_ids TEXT NOT NULL DEFAULT '[]';
|
|
2
|
+
|
|
3
|
+
-- Preserve each admitted snapshot, including an intentionally empty one. Executions without
|
|
4
|
+
-- their own historical snapshot inherit from their parent; historical roots remain unknown/empty.
|
|
5
|
+
WITH RECURSIVE attribution(project_id, id, groups) AS (
|
|
6
|
+
SELECT e.project_id, e.id, COALESCE(w.requester_group_ids, a.requester_group_ids, '[]')
|
|
7
|
+
FROM executions e
|
|
8
|
+
LEFT JOIN workflow_runs w ON w.project_id = e.project_id AND w.execution_id = e.id
|
|
9
|
+
LEFT JOIN agent_runs a ON a.project_id = e.project_id AND a.execution_id = e.id
|
|
10
|
+
WHERE e.parent_execution_id IS NULL
|
|
11
|
+
UNION ALL
|
|
12
|
+
SELECT e.project_id, e.id, COALESCE(w.requester_group_ids, a.requester_group_ids, p.groups)
|
|
13
|
+
FROM executions e
|
|
14
|
+
JOIN attribution p ON p.project_id = e.project_id AND p.id = e.parent_execution_id
|
|
15
|
+
LEFT JOIN workflow_runs w ON w.project_id = e.project_id AND w.execution_id = e.id
|
|
16
|
+
LEFT JOIN agent_runs a ON a.project_id = e.project_id AND a.execution_id = e.id
|
|
17
|
+
)
|
|
18
|
+
UPDATE executions SET requester_group_ids = (
|
|
19
|
+
SELECT groups FROM attribution
|
|
20
|
+
WHERE attribution.project_id = executions.project_id AND attribution.id = executions.id
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
ALTER TABLE workflow_runs DROP COLUMN requester_group_ids;
|
|
24
|
+
ALTER TABLE agent_runs DROP COLUMN requester_group_ids;
|
package/src/migrations.ts
CHANGED
|
@@ -88,6 +88,8 @@ import retireAgentDefinitionsSql from "./migrations/033-retire-agent-definitions
|
|
|
88
88
|
import deviceAuthorizationsSql from "./migrations/034-device-authorizations.sql" with {
|
|
89
89
|
type: "text",
|
|
90
90
|
}
|
|
91
|
+
import shareGrantsSql from "./migrations/035-share-grants.sql" with { type: "text" }
|
|
92
|
+
import shareSessionsSql from "./migrations/036-share-sessions.sql" with { type: "text" }
|
|
91
93
|
|
|
92
94
|
const MIGRATIONS_TABLE_SQL = `
|
|
93
95
|
CREATE TABLE IF NOT EXISTS sixb_migrations (
|
|
@@ -177,6 +179,9 @@ export const sqliteStorageMigrations = defineMigrations({
|
|
|
177
179
|
sqliteSql("032-conversation-run-spec", conversationRunSpecSql),
|
|
178
180
|
sqliteSql("033-retire-agent-definitions", retireAgentDefinitionsSql),
|
|
179
181
|
sqliteSql("034-device-authorizations", deviceAuthorizationsSql),
|
|
182
|
+
sqliteSql("035-share-grants", shareGrantsSql),
|
|
183
|
+
sqliteSql("036-share-sessions", shareSessionsSql),
|
|
184
|
+
sqliteSql("037-execution-requester-groups", executionRequesterGroupsSql),
|
|
180
185
|
],
|
|
181
186
|
})
|
|
182
187
|
|
|
@@ -392,3 +397,7 @@ function rollbackQuietly(db: Database): void {
|
|
|
392
397
|
// Ignore rollback errors so the original migration failure is preserved.
|
|
393
398
|
}
|
|
394
399
|
}
|
|
400
|
+
|
|
401
|
+
import executionRequesterGroupsSql from "./migrations/037-execution-requester-groups.sql" with {
|
|
402
|
+
type: "text",
|
|
403
|
+
}
|