@sixb/pg 0.1.12 → 0.1.13
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/auth-storage/access-tokens.d.ts.map +1 -1
- package/dist/auth-storage/device-authorizations.d.ts.map +1 -1
- package/dist/auth-storage/rows.d.ts +6 -3
- package/dist/auth-storage/rows.d.ts.map +1 -1
- package/dist/auth-storage/sessions.d.ts +8 -1
- package/dist/auth-storage/sessions.d.ts.map +1 -1
- package/dist/auth-storage/shared.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +366 -70
- package/dist/index.js.map +16 -15
- package/dist/migrations.d.ts.map +1 -1
- package/dist/objects/storage.d.ts.map +1 -1
- package/dist/ontology-storage/materializations.d.ts +0 -2
- package/dist/ontology-storage/materializations.d.ts.map +1 -1
- package/dist/ontology-storage/shared.d.ts +2 -1
- package/dist/ontology-storage/shared.d.ts.map +1 -1
- package/dist/pg-file-upload-session-storage.d.ts +6 -0
- package/dist/pg-file-upload-session-storage.d.ts.map +1 -0
- package/dist/pg-workflow-intervention-storage.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/auth-storage/access-tokens.ts +10 -14
- package/src/auth-storage/auth-storage.ts +4 -6
- package/src/auth-storage/device-authorizations.ts +3 -4
- package/src/auth-storage/rows.ts +17 -7
- package/src/auth-storage/sessions.ts +82 -4
- package/src/auth-storage/shared.ts +8 -2
- package/src/index.ts +5 -0
- package/src/migrations/046-workflow-intervention-principals.sql +15 -0
- package/src/migrations/047-ontology-commit-attribution.sql +50 -0
- package/src/migrations/048-file-upload-sessions.sql +34 -0
- package/src/migrations/049-native-sessions.sql +19 -0
- package/src/migrations.ts +12 -0
- package/src/objects/storage.ts +2 -0
- package/src/ontology-storage/materializations.ts +15 -58
- package/src/ontology-storage/shared.ts +7 -3
- package/src/pg-file-upload-session-storage.ts +143 -0
- package/src/pg-workflow-intervention-storage.ts +11 -15
package/dist/index.js
CHANGED
|
@@ -1162,7 +1162,14 @@ function rowToSessionRecord(row) {
|
|
|
1162
1162
|
revokedAt: row.revoked_at ? toDate(row.revoked_at) : undefined,
|
|
1163
1163
|
lastSeenAt: row.last_seen_at ? toDate(row.last_seen_at) : undefined,
|
|
1164
1164
|
userAgent: row.user_agent ?? undefined,
|
|
1165
|
-
ipAddress: row.ip_address ?? undefined
|
|
1165
|
+
ipAddress: row.ip_address ?? undefined,
|
|
1166
|
+
bearer: row.refresh_token_hash !== null && row.client_name !== null && row.access_expires_at !== null ? {
|
|
1167
|
+
clientName: row.client_name,
|
|
1168
|
+
accessExpiresAt: toDate(row.access_expires_at),
|
|
1169
|
+
refreshTokenHash: row.refresh_token_hash,
|
|
1170
|
+
previousRefreshTokenHash: row.previous_refresh_token_hash ?? undefined,
|
|
1171
|
+
refreshedAt: row.refreshed_at ? toDate(row.refreshed_at) : undefined
|
|
1172
|
+
} : undefined
|
|
1166
1173
|
};
|
|
1167
1174
|
}
|
|
1168
1175
|
function rowToAccessTokenRecord(row) {
|
|
@@ -1171,8 +1178,7 @@ function rowToAccessTokenRecord(row) {
|
|
|
1171
1178
|
projectId: row.project_id,
|
|
1172
1179
|
name: row.name,
|
|
1173
1180
|
kind: row.kind,
|
|
1174
|
-
|
|
1175
|
-
subjectId: row.subject_id,
|
|
1181
|
+
subject: { type: row.subject_type, id: row.subject_id },
|
|
1176
1182
|
tokenHash: row.token_hash,
|
|
1177
1183
|
groupIds: parseOptionalStringArray(row.group_ids),
|
|
1178
1184
|
createdByPrincipal: principalFromColumns2(row),
|
|
@@ -1247,8 +1253,6 @@ function rowToDeviceAuthorizationRecord(row) {
|
|
|
1247
1253
|
deviceCodeHash: row.device_code_hash,
|
|
1248
1254
|
userCode: row.user_code,
|
|
1249
1255
|
clientName: row.client_name,
|
|
1250
|
-
tokenName: row.token_name,
|
|
1251
|
-
tokenExpiresAt: toDate(row.token_expires_at),
|
|
1252
1256
|
status: row.status,
|
|
1253
1257
|
approvedUserId: row.approved_user_id ?? undefined,
|
|
1254
1258
|
approvedSessionId: row.approved_session_id ?? undefined,
|
|
@@ -1559,7 +1563,10 @@ async function createSession(sql, input) {
|
|
|
1559
1563
|
expires_at,
|
|
1560
1564
|
absolute_expires_at,
|
|
1561
1565
|
user_agent,
|
|
1562
|
-
ip_address
|
|
1566
|
+
ip_address,
|
|
1567
|
+
client_name,
|
|
1568
|
+
access_expires_at,
|
|
1569
|
+
refresh_token_hash
|
|
1563
1570
|
) VALUES (
|
|
1564
1571
|
${projectId},
|
|
1565
1572
|
${id},
|
|
@@ -1571,7 +1578,10 @@ async function createSession(sql, input) {
|
|
|
1571
1578
|
${input.expiresAt},
|
|
1572
1579
|
${input.absoluteExpiresAt ?? null},
|
|
1573
1580
|
${input.userAgent ?? null},
|
|
1574
|
-
${input.ipAddress ?? null}
|
|
1581
|
+
${input.ipAddress ?? null},
|
|
1582
|
+
${input.bearer ? assertNonEmpty(input.bearer.clientName, "Session client name") : null},
|
|
1583
|
+
${input.bearer?.accessExpiresAt ?? null},
|
|
1584
|
+
${input.bearer ? assertNonEmpty(input.bearer.refreshTokenHash, "Refresh token hash") : null}
|
|
1575
1585
|
)
|
|
1576
1586
|
RETURNING *
|
|
1577
1587
|
`;
|
|
@@ -1763,10 +1773,10 @@ class PgAuthAccessTokenStore {
|
|
|
1763
1773
|
const id = assertNonEmpty(input.id, "Access token id");
|
|
1764
1774
|
const projectId = assertNonEmpty(input.projectId, "Project id");
|
|
1765
1775
|
const name = assertNonEmpty(input.name, "Access token name");
|
|
1766
|
-
const subjectId = assertNonEmpty(input.
|
|
1776
|
+
const subjectId = assertNonEmpty(input.subject.id, "Access token subject id");
|
|
1767
1777
|
const tokenHash = assertNonEmpty(input.tokenHash, "Access token hash");
|
|
1768
1778
|
assertKindMatchesSubject(input);
|
|
1769
|
-
await this.assertSubjectExists(projectId, input.
|
|
1779
|
+
await this.assertSubjectExists(projectId, input.subject.type, subjectId);
|
|
1770
1780
|
const groupIds = input.groupIds === undefined ? undefined : normalizeGroupIds(input.groupIds);
|
|
1771
1781
|
try {
|
|
1772
1782
|
const [row] = await this.sql`
|
|
@@ -1790,7 +1800,7 @@ class PgAuthAccessTokenStore {
|
|
|
1790
1800
|
${id},
|
|
1791
1801
|
${name},
|
|
1792
1802
|
${input.kind},
|
|
1793
|
-
${input.
|
|
1803
|
+
${input.subject.type},
|
|
1794
1804
|
${subjectId},
|
|
1795
1805
|
${tokenHash},
|
|
1796
1806
|
${serializeOptionalStringArray(groupIds)},
|
|
@@ -1825,13 +1835,9 @@ class PgAuthAccessTokenStore {
|
|
|
1825
1835
|
whereClauses.push(`kind = $${nextIndex++}`);
|
|
1826
1836
|
params.push(input.kind);
|
|
1827
1837
|
}
|
|
1828
|
-
if (input.
|
|
1829
|
-
whereClauses.push(`subject_type = $${nextIndex++}`);
|
|
1830
|
-
params.push(input.
|
|
1831
|
-
}
|
|
1832
|
-
if (input.subjectId) {
|
|
1833
|
-
whereClauses.push(`subject_id = $${nextIndex++}`);
|
|
1834
|
-
params.push(input.subjectId);
|
|
1838
|
+
if (input.subject) {
|
|
1839
|
+
whereClauses.push(`subject_type = $${nextIndex++}`, `subject_id = $${nextIndex++}`);
|
|
1840
|
+
params.push(input.subject.type, input.subject.id);
|
|
1835
1841
|
}
|
|
1836
1842
|
if (!input.includeRevoked) {
|
|
1837
1843
|
whereClauses.push("revoked_at IS NULL");
|
|
@@ -1919,10 +1925,10 @@ class PgAuthAccessTokenStore {
|
|
|
1919
1925
|
}
|
|
1920
1926
|
}
|
|
1921
1927
|
function assertKindMatchesSubject(input) {
|
|
1922
|
-
if (input.kind === "personal" && input.
|
|
1928
|
+
if (input.kind === "personal" && input.subject.type === "user" || input.kind === "serviceAccount" && input.subject.type === "serviceAccount") {
|
|
1923
1929
|
return;
|
|
1924
1930
|
}
|
|
1925
|
-
throw new AuthStorageError2("invalid_input", `[Sixb] Access token kind '${input.kind}' cannot target subject type '${input.
|
|
1931
|
+
throw new AuthStorageError2("invalid_input", `[Sixb] Access token kind '${input.kind}' cannot target subject type '${input.subject.type}'.`);
|
|
1926
1932
|
}
|
|
1927
1933
|
|
|
1928
1934
|
// src/auth-storage/device-authorizations.ts
|
|
@@ -1949,16 +1955,15 @@ class PgAuthDeviceAuthorizationStore {
|
|
|
1949
1955
|
try {
|
|
1950
1956
|
const [row] = await tx`
|
|
1951
1957
|
INSERT INTO auth_device_authorizations (
|
|
1952
|
-
project_id, id, device_code_hash, user_code, client_name,
|
|
1953
|
-
|
|
1958
|
+
project_id, id, device_code_hash, user_code, client_name, status, created_at,
|
|
1959
|
+
expires_at
|
|
1954
1960
|
) VALUES (
|
|
1955
1961
|
${assertNonEmpty(input.projectId, "Project id")},
|
|
1956
1962
|
${assertNonEmpty(input.id, "Device authorization id")},
|
|
1957
1963
|
${assertNonEmpty(input.deviceCodeHash, "Device code hash")},
|
|
1958
1964
|
${assertNonEmpty(input.userCode, "User code")},
|
|
1959
1965
|
${assertNonEmpty(input.clientName, "Client name")},
|
|
1960
|
-
${
|
|
1961
|
-
${input.tokenExpiresAt}, 'pending', ${input.createdAt}, ${input.expiresAt}
|
|
1966
|
+
'pending', ${input.createdAt}, ${input.expiresAt}
|
|
1962
1967
|
) RETURNING *
|
|
1963
1968
|
`;
|
|
1964
1969
|
return rowToDeviceAuthorizationRecord(row);
|
|
@@ -2700,11 +2705,53 @@ class PgAuthSessionStore {
|
|
|
2700
2705
|
}
|
|
2701
2706
|
async findValidByTokenHash(params) {
|
|
2702
2707
|
const row = await getSessionRowById(this.sql, params);
|
|
2703
|
-
if (!row || row.
|
|
2708
|
+
if (!row || row.refresh_token_hash !== null || row.audience !== params.audience || row.token_hash !== params.tokenHash || !isLiveSessionRow(row, params.now)) {
|
|
2709
|
+
return null;
|
|
2710
|
+
}
|
|
2711
|
+
return rowToSessionRecord(row);
|
|
2712
|
+
}
|
|
2713
|
+
async findValidByAccessTokenHash(params) {
|
|
2714
|
+
const row = await getSessionRowById(this.sql, params);
|
|
2715
|
+
if (!row || row.access_expires_at === null || row.token_hash !== params.tokenHash || new Date(row.access_expires_at) <= params.now || !isLiveSessionRow(row, params.now)) {
|
|
2704
2716
|
return null;
|
|
2705
2717
|
}
|
|
2706
2718
|
return rowToSessionRecord(row);
|
|
2707
2719
|
}
|
|
2720
|
+
async rotateRefreshToken(params) {
|
|
2721
|
+
return runPgTransaction(this.sql, async (tx) => {
|
|
2722
|
+
const row = await getSessionRowById(tx, params, { forUpdate: true });
|
|
2723
|
+
if (!row?.refresh_token_hash || !isLiveSessionRow(row, params.now)) {
|
|
2724
|
+
return { status: "invalid" };
|
|
2725
|
+
}
|
|
2726
|
+
const replacedRecently = row.previous_refresh_token_hash === params.refreshTokenHash && row.refreshed_at !== null && params.now.getTime() - new Date(row.refreshed_at).getTime() <= params.reuseGraceMs;
|
|
2727
|
+
if (row.refresh_token_hash !== params.refreshTokenHash && !replacedRecently) {
|
|
2728
|
+
if (row.previous_refresh_token_hash !== params.refreshTokenHash) {
|
|
2729
|
+
return { status: "invalid" };
|
|
2730
|
+
}
|
|
2731
|
+
await tx`
|
|
2732
|
+
UPDATE auth_sessions SET revoked_at = ${params.now}
|
|
2733
|
+
WHERE project_id = ${params.projectId} AND id = ${params.id}
|
|
2734
|
+
`;
|
|
2735
|
+
return { status: "reused" };
|
|
2736
|
+
}
|
|
2737
|
+
const [rotated] = await tx`
|
|
2738
|
+
UPDATE auth_sessions
|
|
2739
|
+
SET token_hash = ${params.next.tokenHash},
|
|
2740
|
+
access_expires_at = ${params.next.accessExpiresAt},
|
|
2741
|
+
previous_refresh_token_hash = refresh_token_hash,
|
|
2742
|
+
refresh_token_hash = ${params.next.refreshTokenHash},
|
|
2743
|
+
refreshed_at = ${params.now},
|
|
2744
|
+
last_seen_at = ${params.now},
|
|
2745
|
+
expires_at = GREATEST(
|
|
2746
|
+
expires_at,
|
|
2747
|
+
LEAST(${params.next.expiresAt}, COALESCE(absolute_expires_at, ${params.next.expiresAt}))
|
|
2748
|
+
)
|
|
2749
|
+
WHERE project_id = ${params.projectId} AND id = ${params.id}
|
|
2750
|
+
RETURNING *
|
|
2751
|
+
`;
|
|
2752
|
+
return rotated ? { status: "rotated", session: rowToSessionRecord(rotated) } : { status: "invalid" };
|
|
2753
|
+
});
|
|
2754
|
+
}
|
|
2708
2755
|
async renewIfValid(params) {
|
|
2709
2756
|
const [row] = await this.sql`
|
|
2710
2757
|
UPDATE auth_sessions
|
|
@@ -2720,6 +2767,7 @@ class PgAuthSessionStore {
|
|
|
2720
2767
|
AND id = ${params.id}
|
|
2721
2768
|
AND audience = ${params.audience}
|
|
2722
2769
|
AND token_hash = ${params.tokenHash}
|
|
2770
|
+
AND refresh_token_hash IS NULL
|
|
2723
2771
|
AND revoked_at IS NULL
|
|
2724
2772
|
AND expires_at > ${params.now}
|
|
2725
2773
|
AND (absolute_expires_at IS NULL OR absolute_expires_at > ${params.now})
|
|
@@ -2767,6 +2815,9 @@ class PgAuthSessionStore {
|
|
|
2767
2815
|
});
|
|
2768
2816
|
}
|
|
2769
2817
|
}
|
|
2818
|
+
function isLiveSessionRow(row, now) {
|
|
2819
|
+
return row.revoked_at === null && new Date(row.expires_at) > now && (row.absolute_expires_at === null || new Date(row.absolute_expires_at) > now);
|
|
2820
|
+
}
|
|
2770
2821
|
|
|
2771
2822
|
// src/auth-storage/users.ts
|
|
2772
2823
|
import { AuthStorageError as AuthStorageError10 } from "@sixb/core/storage";
|
|
@@ -2928,7 +2979,7 @@ class PgAuthStorage {
|
|
|
2928
2979
|
throw new AuthStorageError11("missing_device_authorization", `[Sixb] Device authorization '${input.id}' not found for project '${input.projectId}'.`);
|
|
2929
2980
|
}
|
|
2930
2981
|
assertCompletableDeviceAuthorization(authorization, input);
|
|
2931
|
-
const
|
|
2982
|
+
const session = await createSession(tx, input.session);
|
|
2932
2983
|
const [consumed] = await tx`
|
|
2933
2984
|
UPDATE auth_device_authorizations
|
|
2934
2985
|
SET status = 'consumed', consumed_at = ${input.completedAt}
|
|
@@ -2944,7 +2995,7 @@ class PgAuthStorage {
|
|
|
2944
2995
|
status: "consumed",
|
|
2945
2996
|
consumedAt: new Date(input.completedAt)
|
|
2946
2997
|
},
|
|
2947
|
-
|
|
2998
|
+
session
|
|
2948
2999
|
};
|
|
2949
3000
|
});
|
|
2950
3001
|
}
|
|
@@ -3406,7 +3457,7 @@ function assertCompletableDeviceAuthorization(authorization, input) {
|
|
|
3406
3457
|
if (authorization.status === "denied") {
|
|
3407
3458
|
throw new AuthStorageError11("device_authorization_denied", "[Sixb] Device authorization was denied.");
|
|
3408
3459
|
}
|
|
3409
|
-
if (authorization.status !== "approved" || authorization.expiresAt <= input.completedAt || !authorization.approvedUserId || !authorization.approvedSessionId || input.
|
|
3460
|
+
if (authorization.status !== "approved" || authorization.expiresAt <= input.completedAt || !authorization.approvedUserId || !authorization.approvedSessionId || input.session.projectId !== input.projectId || input.session.userId !== authorization.approvedUserId) {
|
|
3410
3461
|
throw new AuthStorageError11("invalid_device_authorization", "[Sixb] Device authorization is invalid.");
|
|
3411
3462
|
}
|
|
3412
3463
|
}
|
|
@@ -7244,6 +7295,99 @@ var _045_agent_thread_sandbox_state_default = `ALTER TABLE agent_threads ADD COL
|
|
|
7244
7295
|
CHECK (sandbox_state IS NULL OR jsonb_typeof(sandbox_state) = 'object');
|
|
7245
7296
|
`;
|
|
7246
7297
|
|
|
7298
|
+
// src/migrations/046-workflow-intervention-principals.sql
|
|
7299
|
+
var _046_workflow_intervention_principals_default = `-- Intervention actors were stored as { principalType, principalId }. Rewrite them to the
|
|
7300
|
+
-- canonical Principal shape { type, id } used by every other stored principal.
|
|
7301
|
+
UPDATE workflow_interventions
|
|
7302
|
+
SET submitted_by = jsonb_build_object(
|
|
7303
|
+
'type', submitted_by->>'principalType',
|
|
7304
|
+
'id', submitted_by->>'principalId'
|
|
7305
|
+
)
|
|
7306
|
+
WHERE submitted_by->>'principalType' IS NOT NULL;
|
|
7307
|
+
|
|
7308
|
+
UPDATE workflow_interventions
|
|
7309
|
+
SET cancelled_by = jsonb_build_object(
|
|
7310
|
+
'type', cancelled_by->>'principalType',
|
|
7311
|
+
'id', cancelled_by->>'principalId'
|
|
7312
|
+
)
|
|
7313
|
+
WHERE cancelled_by->>'principalType' IS NOT NULL;
|
|
7314
|
+
`;
|
|
7315
|
+
|
|
7316
|
+
// src/migrations/047-ontology-commit-attribution.sql
|
|
7317
|
+
var _047_ontology_commit_attribution_default = `-- Commits and their events name who requested the write and what ran it, replacing the
|
|
7318
|
+
-- authority-only \`actor\`. Both are copied from the commit's execution, which stays canonical and
|
|
7319
|
+
-- is immutable, so the backfill is exact.
|
|
7320
|
+
ALTER TABLE ontology_commits
|
|
7321
|
+
ADD COLUMN requested_by JSONB,
|
|
7322
|
+
ADD COLUMN executor JSONB;
|
|
7323
|
+
|
|
7324
|
+
UPDATE ontology_commits c SET
|
|
7325
|
+
requested_by = CASE
|
|
7326
|
+
WHEN e.requested_by_user_id IS NOT NULL
|
|
7327
|
+
THEN jsonb_build_object('type', 'user', 'id', e.requested_by_user_id)
|
|
7328
|
+
WHEN e.requested_by_service_account_id IS NOT NULL
|
|
7329
|
+
THEN jsonb_build_object('type', 'serviceAccount', 'id', e.requested_by_service_account_id)
|
|
7330
|
+
END,
|
|
7331
|
+
executor = CASE e.executor_kind
|
|
7332
|
+
WHEN 'request' THEN jsonb_build_object('type', 'request', 'requestId', e.executor_id)
|
|
7333
|
+
WHEN 'agent' THEN jsonb_build_object('type', 'agent', 'runId', e.executor_id)
|
|
7334
|
+
WHEN 'kernel' THEN jsonb_build_object(
|
|
7335
|
+
'type', 'kernel',
|
|
7336
|
+
'operation',
|
|
7337
|
+
CASE e.authority_kernel_operation
|
|
7338
|
+
WHEN 'ontology.recover'
|
|
7339
|
+
THEN jsonb_build_object('type', 'ontology.recover', 'recoveryId', e.executor_id)
|
|
7340
|
+
ELSE jsonb_build_object('type', 'ontology.indexVectors', 'indexingId', e.executor_id)
|
|
7341
|
+
END
|
|
7342
|
+
)
|
|
7343
|
+
ELSE jsonb_build_object(
|
|
7344
|
+
'type', 'primitive',
|
|
7345
|
+
'kind', e.executor_kind,
|
|
7346
|
+
'id', e.authority_primitive_id,
|
|
7347
|
+
'runId', e.executor_id
|
|
7348
|
+
)
|
|
7349
|
+
END
|
|
7350
|
+
FROM executions e
|
|
7351
|
+
WHERE e.project_id = c.project_id AND e.id = c.execution_id;
|
|
7352
|
+
|
|
7353
|
+
ALTER TABLE ontology_commits ALTER COLUMN executor SET NOT NULL;
|
|
7354
|
+
|
|
7355
|
+
-- Events not yet published would otherwise reach consumers in the retired shape.
|
|
7356
|
+
UPDATE ontology_outbox o SET envelope =
|
|
7357
|
+
(o.envelope - 'actor')
|
|
7358
|
+
|| jsonb_build_object('executor', c.executor)
|
|
7359
|
+
|| CASE
|
|
7360
|
+
WHEN c.requested_by IS NULL THEN '{}'::jsonb
|
|
7361
|
+
ELSE jsonb_build_object('requestedBy', c.requested_by)
|
|
7362
|
+
END
|
|
7363
|
+
FROM ontology_commits c
|
|
7364
|
+
WHERE c.project_id = o.project_id AND c.id = o.commit_id;
|
|
7365
|
+
|
|
7366
|
+
ALTER TABLE ontology_commits DROP COLUMN actor;
|
|
7367
|
+
`;
|
|
7368
|
+
|
|
7369
|
+
// src/migrations/049-native-sessions.sql
|
|
7370
|
+
var _049_native_sessions_default = `-- Native clients, such as the CLI, hold their session as bearer tokens: a
|
|
7371
|
+
-- short-lived access token, whose hash is \`token_hash\`, and a rotating refresh token. Browser
|
|
7372
|
+
-- sessions leave these columns NULL; \`refresh_token_hash IS NULL\` is what marks a cookie session.
|
|
7373
|
+
ALTER TABLE auth_sessions
|
|
7374
|
+
ADD COLUMN client_name TEXT,
|
|
7375
|
+
ADD COLUMN access_expires_at TIMESTAMPTZ,
|
|
7376
|
+
ADD COLUMN refresh_token_hash TEXT,
|
|
7377
|
+
ADD COLUMN previous_refresh_token_hash TEXT,
|
|
7378
|
+
ADD COLUMN refreshed_at TIMESTAMPTZ,
|
|
7379
|
+
ADD CONSTRAINT auth_sessions_bearer_state CHECK (
|
|
7380
|
+
(refresh_token_hash IS NULL) = (client_name IS NULL)
|
|
7381
|
+
AND (refresh_token_hash IS NULL) = (access_expires_at IS NULL)
|
|
7382
|
+
AND (refresh_token_hash IS NOT NULL OR previous_refresh_token_hash IS NULL)
|
|
7383
|
+
);
|
|
7384
|
+
|
|
7385
|
+
-- The device flow now starts a session instead of issuing a personal access token.
|
|
7386
|
+
ALTER TABLE auth_device_authorizations
|
|
7387
|
+
DROP COLUMN token_name,
|
|
7388
|
+
DROP COLUMN token_expires_at;
|
|
7389
|
+
`;
|
|
7390
|
+
|
|
7247
7391
|
// src/migrations/037-execution-requester-groups.sql
|
|
7248
7392
|
var _037_execution_requester_groups_default = `ALTER TABLE executions ADD COLUMN requester_group_ids JSONB NOT NULL DEFAULT '[]'::jsonb;
|
|
7249
7393
|
|
|
@@ -7282,6 +7426,43 @@ ALTER TABLE connector_authorization_attempts
|
|
|
7282
7426
|
ALTER COLUMN code_verifier DROP NOT NULL;
|
|
7283
7427
|
`;
|
|
7284
7428
|
|
|
7429
|
+
// src/migrations/048-file-upload-sessions.sql
|
|
7430
|
+
var _048_file_upload_sessions_default = `-- Durable staged-upload sessions, so an upload survives restarts and spans API replicas.
|
|
7431
|
+
CREATE TABLE file_upload_sessions (
|
|
7432
|
+
id TEXT PRIMARY KEY CHECK (length(trim(id)) > 0),
|
|
7433
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
7434
|
+
owner_principal_type TEXT NOT NULL
|
|
7435
|
+
CHECK (owner_principal_type IN ('user', 'serviceAccount', 'system')),
|
|
7436
|
+
owner_principal_id TEXT NOT NULL CHECK (length(owner_principal_id) > 0),
|
|
7437
|
+
strategy TEXT NOT NULL CHECK (strategy IN ('server', 'direct-put', 'multipart')),
|
|
7438
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'completed', 'aborted')),
|
|
7439
|
+
file_name TEXT,
|
|
7440
|
+
media_type TEXT,
|
|
7441
|
+
logical_path TEXT,
|
|
7442
|
+
expected_size_bytes BIGINT CHECK (expected_size_bytes IS NULL OR expected_size_bytes >= 0),
|
|
7443
|
+
expected_digest TEXT,
|
|
7444
|
+
provider_upload JSONB CHECK (provider_upload IS NULL OR jsonb_typeof(provider_upload) = 'object'),
|
|
7445
|
+
signed_parts JSONB NOT NULL CHECK (jsonb_typeof(signed_parts) = 'array'),
|
|
7446
|
+
file_ref JSONB CHECK (file_ref IS NULL OR jsonb_typeof(file_ref) = 'object'),
|
|
7447
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
7448
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
7449
|
+
completed_at TIMESTAMPTZ,
|
|
7450
|
+
aborted_at TIMESTAMPTZ,
|
|
7451
|
+
-- Derived by core (fileUploadSessionReapAt); NULL while an abandoned upload awaits its abort.
|
|
7452
|
+
reap_at TIMESTAMPTZ,
|
|
7453
|
+
CHECK ((status = 'completed') = (completed_at IS NOT NULL)),
|
|
7454
|
+
CHECK ((status = 'aborted') = (aborted_at IS NOT NULL))
|
|
7455
|
+
);
|
|
7456
|
+
|
|
7457
|
+
CREATE INDEX idx_file_upload_sessions_reap
|
|
7458
|
+
ON file_upload_sessions (reap_at)
|
|
7459
|
+
WHERE reap_at IS NOT NULL;
|
|
7460
|
+
|
|
7461
|
+
CREATE INDEX idx_file_upload_sessions_abandoned
|
|
7462
|
+
ON file_upload_sessions (project_id, expires_at)
|
|
7463
|
+
WHERE status = 'pending' AND provider_upload IS NOT NULL;
|
|
7464
|
+
`;
|
|
7465
|
+
|
|
7285
7466
|
// src/migrations.ts
|
|
7286
7467
|
var POSTGRES_STORAGE_ADAPTER_ID = "SixbPostgresStorage";
|
|
7287
7468
|
function pgSql(id, sqlText) {
|
|
@@ -7501,7 +7682,11 @@ var postgresStorageMigrations = defineMigrations({
|
|
|
7501
7682
|
pgSql("042-vector-profiles", _042_vector_profiles_default),
|
|
7502
7683
|
pgSql("043-vector-indexing", _043_vector_indexing_default),
|
|
7503
7684
|
pgSql("044-vector-batching", _044_vector_batching_default),
|
|
7504
|
-
pgSql("045-agent-thread-sandbox-state", _045_agent_thread_sandbox_state_default)
|
|
7685
|
+
pgSql("045-agent-thread-sandbox-state", _045_agent_thread_sandbox_state_default),
|
|
7686
|
+
pgSql("046-workflow-intervention-principals", _046_workflow_intervention_principals_default),
|
|
7687
|
+
pgSql("047-ontology-commit-attribution", _047_ontology_commit_attribution_default),
|
|
7688
|
+
pgSql("048-file-upload-sessions", _048_file_upload_sessions_default),
|
|
7689
|
+
pgSql("049-native-sessions", _049_native_sessions_default)
|
|
7505
7690
|
]
|
|
7506
7691
|
});
|
|
7507
7692
|
|
|
@@ -9625,7 +9810,8 @@ var PG_OBJECT_QUERY_CAPABILITIES = {
|
|
|
9625
9810
|
double: { equality: true, ordering: true },
|
|
9626
9811
|
decimal: { equality: true, ordering: true },
|
|
9627
9812
|
date: { equality: true, ordering: true },
|
|
9628
|
-
timestamp: { equality: true, ordering: true }
|
|
9813
|
+
timestamp: { equality: true, ordering: true },
|
|
9814
|
+
userRef: { equality: true }
|
|
9629
9815
|
},
|
|
9630
9816
|
limits: {
|
|
9631
9817
|
totalCount: true,
|
|
@@ -9828,9 +10014,10 @@ function commitRecord(row) {
|
|
|
9828
10014
|
requestHash: row.request_hash,
|
|
9829
10015
|
executionId: row.execution_id,
|
|
9830
10016
|
origin: structuredClone(row.origin),
|
|
9831
|
-
...row.
|
|
9832
|
-
|
|
10017
|
+
...row.requested_by === null ? {} : {
|
|
10018
|
+
requestedBy: structuredClone(row.requested_by)
|
|
9833
10019
|
},
|
|
10020
|
+
executor: structuredClone(row.executor),
|
|
9834
10021
|
ontologyRevision: row.ontology_revision,
|
|
9835
10022
|
...row.projection_revision === null ? {} : { projectionRevision: row.projection_revision },
|
|
9836
10023
|
...row.ownership_hash === null ? {} : { ownershipHash: row.ownership_hash },
|
|
@@ -9979,6 +10166,9 @@ import {
|
|
|
9979
10166
|
telemetryPointSortKey as telemetryPointSortKey2
|
|
9980
10167
|
} from "@sixb/core/internal/materialization";
|
|
9981
10168
|
import {
|
|
10169
|
+
assertExpectedLinkRevision,
|
|
10170
|
+
assertExpectedLinkScopeRevision,
|
|
10171
|
+
assertExpectedObjectRevision,
|
|
9982
10172
|
assertMaterializationFinalizationCorrelation,
|
|
9983
10173
|
assertMaterializationHeader,
|
|
9984
10174
|
assertMaterializationLaneCompletion,
|
|
@@ -11915,17 +12105,15 @@ class PgOntologyMaterializationStorage {
|
|
|
11915
12105
|
await this.assertSources(input.expected.sources, input.commit.projectId);
|
|
11916
12106
|
const objectRevisions = await reader.effectiveObjectRevisions(input.expected.objects.map((expected) => expected.ref), true);
|
|
11917
12107
|
for (const expected of input.expected.objects) {
|
|
11918
|
-
|
|
12108
|
+
assertExpectedObjectRevision(objectRevisions.get(objectRefKey3(expected.ref)) ?? null, expected);
|
|
11919
12109
|
}
|
|
11920
12110
|
const linkRevisions = await reader.effectiveLinkLastCommits(input.expected.links.map((expected) => expected.ref), true);
|
|
11921
12111
|
for (const expected of input.expected.links) {
|
|
11922
|
-
|
|
12112
|
+
assertExpectedLinkRevision(linkRevisions.get(linkRefKey3(expected.ref)), expected);
|
|
11923
12113
|
}
|
|
11924
12114
|
const linkScopeRevisions = await reader.linkScopeRevisions(input.expected.linkScopes);
|
|
11925
12115
|
for (const [index, expected] of input.expected.linkScopes.entries()) {
|
|
11926
|
-
|
|
11927
|
-
throw new MaterializationConflictError6("effective-state", `Expected link scope changed for ${expected.source.objectTypeId}:${expected.source.primaryId}.${expected.linkId}.`);
|
|
11928
|
-
}
|
|
12116
|
+
assertExpectedLinkScopeRevision(linkScopeRevisions[index]?.fingerprint, expected);
|
|
11929
12117
|
}
|
|
11930
12118
|
const points = await reader.exactPoints(input.expected.points, true);
|
|
11931
12119
|
const pointRevisions = new Map(points.map((point) => [telemetryPointKey3(point.series, point.at), point.lastCommitId]));
|
|
@@ -12185,28 +12373,6 @@ class PgOntologyMaterializationStorage {
|
|
|
12185
12373
|
throw new MaterializationConflictError6("projection-fence", `Source '${expected.source.projectionId}' changed.`);
|
|
12186
12374
|
}
|
|
12187
12375
|
}
|
|
12188
|
-
assertObject(row, expected) {
|
|
12189
|
-
if (!expected.exists) {
|
|
12190
|
-
if (row) {
|
|
12191
|
-
throw new MaterializationConflictError6("effective-state", `Expected object ${objectRefKey3(expected.ref)} to be absent.`);
|
|
12192
|
-
}
|
|
12193
|
-
return;
|
|
12194
|
-
}
|
|
12195
|
-
if (!row || row.version !== expected.version || row.lastCommitId !== expected.lastCommitId) {
|
|
12196
|
-
throw new MaterializationConflictError6("effective-state", `Expected object ${objectRefKey3(expected.ref)} changed.`);
|
|
12197
|
-
}
|
|
12198
|
-
}
|
|
12199
|
-
assertLink(lastCommitId, expected) {
|
|
12200
|
-
if (!expected.exists) {
|
|
12201
|
-
if (lastCommitId !== undefined) {
|
|
12202
|
-
throw new MaterializationConflictError6("effective-state", `Expected link ${linkRefKey3(expected.ref)} to be absent.`);
|
|
12203
|
-
}
|
|
12204
|
-
return;
|
|
12205
|
-
}
|
|
12206
|
-
if (lastCommitId === undefined || lastCommitId !== expected.lastCommitId) {
|
|
12207
|
-
throw new MaterializationConflictError6("effective-state", `Expected link ${linkRefKey3(expected.ref)} changed.`);
|
|
12208
|
-
}
|
|
12209
|
-
}
|
|
12210
12376
|
async assertFinalization(session, input) {
|
|
12211
12377
|
const { commit } = session.header;
|
|
12212
12378
|
const { result } = input.finalization;
|
|
@@ -12442,18 +12608,19 @@ class PgOntologyMaterializationStorage {
|
|
|
12442
12608
|
async insertCommit(header, input) {
|
|
12443
12609
|
const { commit } = header;
|
|
12444
12610
|
const origin = originColumns(commit.origin);
|
|
12445
|
-
const
|
|
12611
|
+
const requestedBy = commit.requestedBy === undefined ? null : jsonParameter2(this.sql, commit.requestedBy);
|
|
12446
12612
|
const rows = await this.sql`
|
|
12447
12613
|
INSERT INTO ontology_commits (
|
|
12448
12614
|
project_id, id, idempotency_key, request_hash, execution_id,
|
|
12449
|
-
origin_kind, origin_run_id, origin_batch_ordinal, origin,
|
|
12615
|
+
origin_kind, origin_run_id, origin_batch_ordinal, origin, requested_by, executor,
|
|
12450
12616
|
ontology_revision, projection_revision, ownership_hash,
|
|
12451
12617
|
intent, result, committed_at
|
|
12452
12618
|
) VALUES (
|
|
12453
12619
|
${commit.projectId}, ${commit.id}, ${commit.idempotencyKey}, ${commit.requestHash},
|
|
12454
12620
|
${commit.executionId},
|
|
12455
12621
|
${origin.kind}, ${origin.runId}, ${origin.batchOrdinal},
|
|
12456
|
-
${jsonParameter2(this.sql, commit.origin)}, ${
|
|
12622
|
+
${jsonParameter2(this.sql, commit.origin)}, ${requestedBy},
|
|
12623
|
+
${jsonParameter2(this.sql, commit.executor)}, ${commit.ontologyRevision},
|
|
12457
12624
|
${commit.projectionRevision ?? null}, ${commit.ownershipHash ?? null},
|
|
12458
12625
|
${jsonParameter2(this.sql, commit.intent)},
|
|
12459
12626
|
${jsonParameter2(this.sql, input.finalization.result)}, ${commit.committedAt}
|
|
@@ -15547,6 +15714,132 @@ function toStorageRow(row) {
|
|
|
15547
15714
|
};
|
|
15548
15715
|
}
|
|
15549
15716
|
|
|
15717
|
+
// src/pg-file-upload-session-storage.ts
|
|
15718
|
+
import {
|
|
15719
|
+
DurableFileUploadSessions,
|
|
15720
|
+
fileUploadSessionReapAt,
|
|
15721
|
+
parseFileUploadSessionRow
|
|
15722
|
+
} from "@sixb/core/internal/file-upload-session-storage-provider";
|
|
15723
|
+
class PgFileUploadSessionStorage extends DurableFileUploadSessions {
|
|
15724
|
+
constructor(sql) {
|
|
15725
|
+
super(new PgFileUploadSessionBackend(sql));
|
|
15726
|
+
}
|
|
15727
|
+
}
|
|
15728
|
+
|
|
15729
|
+
class PgFileUploadSessionBackend {
|
|
15730
|
+
sql;
|
|
15731
|
+
constructor(sql) {
|
|
15732
|
+
this.sql = sql;
|
|
15733
|
+
}
|
|
15734
|
+
read(run) {
|
|
15735
|
+
return run(new PgFileUploadSessionPersistence(this.sql, false));
|
|
15736
|
+
}
|
|
15737
|
+
transaction(run) {
|
|
15738
|
+
return runPgTransaction(this.sql, (tx) => run(new PgFileUploadSessionPersistence(tx, true)));
|
|
15739
|
+
}
|
|
15740
|
+
}
|
|
15741
|
+
|
|
15742
|
+
class PgFileUploadSessionPersistence {
|
|
15743
|
+
sql;
|
|
15744
|
+
locking;
|
|
15745
|
+
constructor(sql, locking) {
|
|
15746
|
+
this.sql = sql;
|
|
15747
|
+
this.locking = locking;
|
|
15748
|
+
}
|
|
15749
|
+
async now() {
|
|
15750
|
+
const [row] = await this.sql`SELECT clock_timestamp() AS now`;
|
|
15751
|
+
if (!row)
|
|
15752
|
+
throw new Error("[SixbPg] Database clock returned no row.");
|
|
15753
|
+
return new Date(row.now);
|
|
15754
|
+
}
|
|
15755
|
+
async insert(session) {
|
|
15756
|
+
const rows = await this.sql`
|
|
15757
|
+
INSERT INTO file_upload_sessions (
|
|
15758
|
+
id, project_id, owner_principal_type, owner_principal_id, strategy, status, file_name,
|
|
15759
|
+
media_type, logical_path, expected_size_bytes, expected_digest, provider_upload,
|
|
15760
|
+
signed_parts, file_ref, created_at, expires_at, completed_at, aborted_at, reap_at
|
|
15761
|
+
) VALUES (
|
|
15762
|
+
${session.id}, ${session.projectId}, ${session.principal.type}, ${session.principal.id},
|
|
15763
|
+
${session.strategy}, ${session.status}, ${session.fileName ?? null}, ${session.mediaType ?? null},
|
|
15764
|
+
${session.logicalPath ?? null}, ${session.expectedSizeBytes ?? null},
|
|
15765
|
+
${session.expectedDigest ?? null}, ${jsonText(session.providerUpload)}::text::jsonb,
|
|
15766
|
+
${JSON.stringify(session.signedParts)}::text::jsonb, ${jsonText(session.fileRef)}::text::jsonb,
|
|
15767
|
+
${session.createdAt}, ${session.expiresAt}, ${session.completedAt ?? null},
|
|
15768
|
+
${session.abortedAt ?? null}, ${fileUploadSessionReapAt(session)}
|
|
15769
|
+
)
|
|
15770
|
+
ON CONFLICT (id) DO NOTHING
|
|
15771
|
+
RETURNING id
|
|
15772
|
+
`;
|
|
15773
|
+
return rows.length === 1;
|
|
15774
|
+
}
|
|
15775
|
+
async get(uploadId) {
|
|
15776
|
+
const [row] = this.locking ? await this.sql`
|
|
15777
|
+
SELECT * FROM file_upload_sessions WHERE id = ${uploadId} FOR UPDATE
|
|
15778
|
+
` : await this.sql`
|
|
15779
|
+
SELECT * FROM file_upload_sessions WHERE id = ${uploadId}
|
|
15780
|
+
`;
|
|
15781
|
+
return row ? sessionFromRow(row) : null;
|
|
15782
|
+
}
|
|
15783
|
+
async update(session) {
|
|
15784
|
+
await this.sql`
|
|
15785
|
+
UPDATE file_upload_sessions
|
|
15786
|
+
SET status = ${session.status},
|
|
15787
|
+
provider_upload = ${jsonText(session.providerUpload)}::text::jsonb,
|
|
15788
|
+
signed_parts = ${JSON.stringify(session.signedParts)}::text::jsonb,
|
|
15789
|
+
file_ref = ${jsonText(session.fileRef)}::text::jsonb,
|
|
15790
|
+
created_at = ${session.createdAt},
|
|
15791
|
+
expires_at = ${session.expiresAt},
|
|
15792
|
+
completed_at = ${session.completedAt ?? null},
|
|
15793
|
+
aborted_at = ${session.abortedAt ?? null},
|
|
15794
|
+
reap_at = ${fileUploadSessionReapAt(session)}
|
|
15795
|
+
WHERE id = ${session.id}
|
|
15796
|
+
`;
|
|
15797
|
+
}
|
|
15798
|
+
async listAbandoned(input) {
|
|
15799
|
+
const rows = await this.sql`
|
|
15800
|
+
SELECT * FROM file_upload_sessions
|
|
15801
|
+
WHERE project_id = ${input.projectId} AND status = 'pending'
|
|
15802
|
+
AND provider_upload IS NOT NULL AND expires_at <= ${input.now}
|
|
15803
|
+
ORDER BY expires_at, id COLLATE "C"
|
|
15804
|
+
LIMIT ${input.limit}
|
|
15805
|
+
`;
|
|
15806
|
+
return rows.map(sessionFromRow);
|
|
15807
|
+
}
|
|
15808
|
+
async deleteReapable(now) {
|
|
15809
|
+
const rows = await this.sql`
|
|
15810
|
+
DELETE FROM file_upload_sessions
|
|
15811
|
+
WHERE reap_at IS NOT NULL AND reap_at <= ${now}
|
|
15812
|
+
RETURNING id
|
|
15813
|
+
`;
|
|
15814
|
+
return rows.length;
|
|
15815
|
+
}
|
|
15816
|
+
}
|
|
15817
|
+
function sessionFromRow(row) {
|
|
15818
|
+
return parseFileUploadSessionRow({
|
|
15819
|
+
id: row.id,
|
|
15820
|
+
projectId: row.project_id,
|
|
15821
|
+
ownerPrincipalType: row.owner_principal_type,
|
|
15822
|
+
ownerPrincipalId: row.owner_principal_id,
|
|
15823
|
+
strategy: row.strategy,
|
|
15824
|
+
status: row.status,
|
|
15825
|
+
fileName: row.file_name,
|
|
15826
|
+
mediaType: row.media_type,
|
|
15827
|
+
logicalPath: row.logical_path,
|
|
15828
|
+
expectedSizeBytes: row.expected_size_bytes,
|
|
15829
|
+
expectedDigest: row.expected_digest,
|
|
15830
|
+
providerUpload: row.provider_upload,
|
|
15831
|
+
signedParts: row.signed_parts,
|
|
15832
|
+
fileRef: row.file_ref,
|
|
15833
|
+
createdAt: row.created_at,
|
|
15834
|
+
expiresAt: row.expires_at,
|
|
15835
|
+
completedAt: row.completed_at,
|
|
15836
|
+
abortedAt: row.aborted_at
|
|
15837
|
+
});
|
|
15838
|
+
}
|
|
15839
|
+
function jsonText(value) {
|
|
15840
|
+
return value === undefined ? null : JSON.stringify(value);
|
|
15841
|
+
}
|
|
15842
|
+
|
|
15550
15843
|
// src/pg-pipeline-run-storage.ts
|
|
15551
15844
|
import { parseSixbFailure as parseSixbFailure4, serializeSixbFailure as serializeSixbFailure3 } from "@sixb/core/internal/errors";
|
|
15552
15845
|
import { assertPipelineRunExecution } from "@sixb/core/internal/pipeline-run-storage-provider";
|
|
@@ -17218,7 +17511,7 @@ class PgWorkflowInterventionStorage {
|
|
|
17218
17511
|
SET
|
|
17219
17512
|
status = ${"submitted"},
|
|
17220
17513
|
submitted_at = ${input.submittedAt ?? new Date},
|
|
17221
|
-
submitted_by = ${
|
|
17514
|
+
submitted_by = ${serializePrincipal(input.submittedBy)}::text::jsonb,
|
|
17222
17515
|
response = ${serializeRecord(input.response)}::text::jsonb
|
|
17223
17516
|
WHERE project_id = ${input.projectId} AND id = ${input.id}
|
|
17224
17517
|
RETURNING *
|
|
@@ -17234,7 +17527,7 @@ class PgWorkflowInterventionStorage {
|
|
|
17234
17527
|
SET
|
|
17235
17528
|
status = ${"cancelled"},
|
|
17236
17529
|
cancelled_at = ${input.cancelledAt ?? new Date},
|
|
17237
|
-
cancelled_by = ${
|
|
17530
|
+
cancelled_by = ${serializePrincipal(input.cancelledBy)}::text::jsonb
|
|
17238
17531
|
WHERE project_id = ${input.projectId} AND id = ${input.id}
|
|
17239
17532
|
RETURNING *
|
|
17240
17533
|
`;
|
|
@@ -17361,10 +17654,10 @@ function serializeRecord(value) {
|
|
|
17361
17654
|
function parseRecord(value) {
|
|
17362
17655
|
return typeof value === "string" ? JSON.parse(value) : value;
|
|
17363
17656
|
}
|
|
17364
|
-
function
|
|
17365
|
-
return
|
|
17657
|
+
function serializePrincipal(principal) {
|
|
17658
|
+
return principal ? JSON.stringify(principal) : null;
|
|
17366
17659
|
}
|
|
17367
|
-
function
|
|
17660
|
+
function parsePrincipal(value) {
|
|
17368
17661
|
return typeof value === "string" ? JSON.parse(value) : value ?? undefined;
|
|
17369
17662
|
}
|
|
17370
17663
|
function rowToWorkflowInterventionRecord(row) {
|
|
@@ -17384,10 +17677,10 @@ function rowToWorkflowInterventionRecord(row) {
|
|
|
17384
17677
|
requestedAt: new Date(row.requested_at),
|
|
17385
17678
|
expiresAt: row.expires_at ? new Date(row.expires_at) : undefined,
|
|
17386
17679
|
submittedAt: row.submitted_at ? new Date(row.submitted_at) : undefined,
|
|
17387
|
-
submittedBy:
|
|
17680
|
+
submittedBy: parsePrincipal(row.submitted_by),
|
|
17388
17681
|
response: row.response ? parseRecord(row.response) : undefined,
|
|
17389
17682
|
cancelledAt: row.cancelled_at ? new Date(row.cancelled_at) : undefined,
|
|
17390
|
-
cancelledBy:
|
|
17683
|
+
cancelledBy: parsePrincipal(row.cancelled_by),
|
|
17391
17684
|
expiredAt: row.expired_at ? new Date(row.expired_at) : undefined
|
|
17392
17685
|
};
|
|
17393
17686
|
}
|
|
@@ -18455,6 +18748,7 @@ class PostgresStorage {
|
|
|
18455
18748
|
connectorConnections;
|
|
18456
18749
|
shareGrants;
|
|
18457
18750
|
shareSessions;
|
|
18751
|
+
fileUploadSessions;
|
|
18458
18752
|
migrators;
|
|
18459
18753
|
sql;
|
|
18460
18754
|
schemaName;
|
|
@@ -18508,6 +18802,7 @@ class PostgresStorage {
|
|
|
18508
18802
|
this.connectorConnections = createOperationScopedFacade(stores.connectorConnections, scope);
|
|
18509
18803
|
this.shareGrants = createOperationScopedFacade(stores.shareGrants, scope);
|
|
18510
18804
|
this.shareSessions = createOperationScopedFacade(stores.shareSessions, scope);
|
|
18805
|
+
this.fileUploadSessions = createOperationScopedFacade(stores.fileUploadSessions, scope);
|
|
18511
18806
|
registerPostgresStorageTestingAdapter(this, (durationMs) => stores.connectorConnections.advanceTimeForTesting(durationMs));
|
|
18512
18807
|
}
|
|
18513
18808
|
async ping() {
|
|
@@ -18602,7 +18897,8 @@ function createPostgresStores(sql, options) {
|
|
|
18602
18897
|
rules: new PgRulesStorage(sql),
|
|
18603
18898
|
connectorConnections: new PgConnectorConnectionStorage(sql),
|
|
18604
18899
|
shareGrants,
|
|
18605
|
-
shareSessions
|
|
18900
|
+
shareSessions,
|
|
18901
|
+
fileUploadSessions: new PgFileUploadSessionStorage(sql)
|
|
18606
18902
|
};
|
|
18607
18903
|
}
|
|
18608
18904
|
function resolveTimeoutMillis(value, label) {
|
|
@@ -18619,4 +18915,4 @@ export {
|
|
|
18619
18915
|
migratePostgresStorage
|
|
18620
18916
|
};
|
|
18621
18917
|
|
|
18622
|
-
//# debugId=
|
|
18918
|
+
//# debugId=F4D8409142F8F3AF64756E2164756E21
|