@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/migrations.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAoG3B,OAAO,KAAK,EAAE,GAAG,EAAa,MAAM,aAAa,CAAA;AAEjD,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC;AAED,eAAO,MAAM,2BAA2B,wBAAwB,CAAA;AAEhE,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,wBAAwB,CAAC,CAE1F;AAED,wBAAgB,MAAM,CACpB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC/D,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAAC,wBAAwB,CAAC,CAEzC;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,GACjB,SAAS,eAAe,EAAE,CAQ5B;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,wBAAwB,CAAC,CAAA;CAC5D,GAAG,eAAe,CAqBlB;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxF;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrD;AA6KD,eAAO,MAAM,yBAAyB,wCAqDpC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/objects/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,KAAK,aAAa,EAAkC,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/objects/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,KAAK,aAAa,EAAkC,MAAM,iBAAiB,CAAA;AAiFpF,mFAAmF;AACnF,qBAAa,eAAgB,YAAW,aAAa;IAGvC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAEV,GAAG,EAAE,aAAa;IAI/C,iBAAiB,IAAI,uBAAuB;IAI5C,uBAAuB,CAAC,MAAM,EAAE;QAC9B,SAAS,EAAE,MAAM,CAAA;QACjB,KAAK,EAAE,+BAA+B,CAAA;QACtC,MAAM,EAAE,yBAAyB,CAAA;KAClC,GAAG,iBAAiB;IAIf,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAQpE,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAQpE,aAAa,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQvE,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAQpE,cAAc,CAAC,MAAM,EAAE;QAC3B,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,EAAE,MAAM,CAAA;QACpB,SAAS,EAAE,MAAM,CAAA;KAClB,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAIvB,uBAAuB,CAC3B,MAAM,EAAE,UAAU,CAAC,iBAAiB,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,GAClE,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC;IAIxB,SAAS,CAAC,MAAM,EAAE;QACtB,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,SAAS,CAAC,EAAE,aAAa,CAAA;KAC1B,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC;IAI/B,mBAAmB,CAAC,MAAM,EAAE;QAChC,SAAS,EAAE,MAAM,CAAA;QACjB,KAAK,EAAE,SAAS;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAC9D,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IAIrC,cAAc,CAAC,MAAM,EAAE;QAC3B,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,CAAC,EAAE,aAAa,CAAA;QACzB,KAAK,EAAE,SAAS;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAC7E,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC;IAIzC,UAAU,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAK1E,sBAAsB,CAAC,MAAM,EAAE;QACnC,SAAS,EAAE,MAAM,CAAA;QACjB,KAAK,EAAE,SAAS;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAC7D,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC;IAkC/B,mBAAmB,CAAC,MAAM,EAAE;QAChC,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,EAAE,MAAM,CAAA;QACpB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,KAAK,EAAE,MAAM,CAAA;KACd,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAmBhE,IAAI,CAAC,MAAM,EAAE;QACjB,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;QACzC,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,YAAY,CAAC,EAAE,IAAI,CAAA;QACnB,aAAa,CAAC,EAAE,IAAI,CAAA;QACpB,YAAY,CAAC,EAAE,IAAI,CAAA;QACnB,aAAa,CAAC,EAAE,IAAI,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,WAAW,CAAA;QACjD,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;KACvB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAGhF"}
|
|
@@ -20,8 +20,6 @@ export declare class PgOntologyMaterializationStorage implements OntologyMateria
|
|
|
20
20
|
private assertCommitAbsent;
|
|
21
21
|
private assertSources;
|
|
22
22
|
private assertSourceRow;
|
|
23
|
-
private assertObject;
|
|
24
|
-
private assertLink;
|
|
25
23
|
private assertFinalization;
|
|
26
24
|
private assertFinalCardinality;
|
|
27
25
|
private projectionCounts;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materializations.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/materializations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"materializations.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/materializations.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC1B,4BAA4B,EAC5B,8BAA8B,EAC9B,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EAEvB,8BAA8B,EAC9B,uCAAuC,EAEvC,0BAA0B,EAC1B,6BAA6B,EAC7B,+BAA+B,EAC/B,8BAA8B,EAC9B,iCAAiC,EAClC,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAG7C,OAAO,EAGL,KAAK,4BAA4B,EAClC,MAAM,2BAA2B,CAAA;AAqClC,qBAAa,gCAAiC,YAAW,8BAA8B;IAKnF,OAAO,CAAC,QAAQ,CAAC,GAAG;IAJtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAG7B,GAAG,EAAE,SAAS,EAC/B,OAAO,EAAE,4BAA4B,GAAG,IAAI;IAM9C,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAY1F,KAAK,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAqDvE,WAAW,CAChB,KAAK,EAAE,+BAA+B,GACrC,aAAa,CAAC,wBAAwB,CAAC;IAqDnC,4BAA4B,CACjC,KAAK,EAAE,iCAAiC,GACvC,aAAa,CAAC,0BAA0B,CAAC;IA6FtC,SAAS,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,UAAU,CAAC,KAAK,EAAE,8BAA8B,GAAG,aAAa,CAAC,uBAAuB,CAAC;IAKnF,mBAAmB,CACvB,KAAK,EAAE,uCAAuC,GAC7C,OAAO,CAAC,SAAS,8BAA8B,EAAE,CAAC;IAK/C,UAAU,CAAC,KAAK,EAAE,8BAA8B,GAAG,OAAO,CAAC,IAAI,CAAC;IAahE,QAAQ,CAAC,KAAK,EAAE,4BAA4B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAgBxF,kBAAkB,IAAI,IAAI;YAIZ,kBAAkB;YA6DlB,kBAAkB;YAmDlB,aAAa;IAoB3B,OAAO,CAAC,eAAe;YAeT,kBAAkB;YAqDlB,sBAAsB;YAyDtB,gBAAgB;YA2DhB,gBAAgB;YAiChB,cAAc;YA6Gd,YAAY;YAqCZ,eAAe;YAcf,SAAS;CAgBxB"}
|
|
@@ -12,7 +12,8 @@ export interface PgOntologyCommitRow {
|
|
|
12
12
|
readonly origin_run_id: string | null;
|
|
13
13
|
readonly origin_batch_ordinal: number | string | null;
|
|
14
14
|
readonly origin: unknown;
|
|
15
|
-
readonly
|
|
15
|
+
readonly requested_by: unknown | null;
|
|
16
|
+
readonly executor: unknown;
|
|
16
17
|
readonly ontology_revision: string;
|
|
17
18
|
readonly projection_revision: string | null;
|
|
18
19
|
readonly ownership_hash: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/shared.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,yCAAyC,EACzC,oBAAoB,EAEpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,eAAe,GAChB,MAAM,+CAA+C,CAAA;AAEtD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAIpF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACrD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/ontology-storage/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DurableFileUploadSessions } from "@sixb/core/internal/file-upload-session-storage-provider";
|
|
2
|
+
import { type PgStoreClient } from "./transactions";
|
|
3
|
+
export declare class PgFileUploadSessionStorage extends DurableFileUploadSessions {
|
|
4
|
+
constructor(sql: PgStoreClient);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=pg-file-upload-session-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-file-upload-session-storage.d.ts","sourceRoot":"","sources":["../src/pg-file-upload-session-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAK1B,MAAM,0DAA0D,CAAA;AAEjE,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,gBAAgB,CAAA;AAErE,qBAAa,0BAA2B,SAAQ,yBAAyB;gBAC3D,GAAG,EAAE,aAAa;CAG/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-workflow-intervention-storage.d.ts","sourceRoot":"","sources":["../src/pg-workflow-intervention-storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,+BAA+B,EAC/B,+BAA+B,EAC/B,8BAA8B,EAC9B,+BAA+B,
|
|
1
|
+
{"version":3,"file":"pg-workflow-intervention-storage.d.ts","sourceRoot":"","sources":["../src/pg-workflow-intervention-storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+BAA+B,EAC/B,+BAA+B,EAC/B,+BAA+B,EAC/B,8BAA8B,EAC9B,+BAA+B,EAE/B,+BAA+B,EAC/B,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,oBAAoB,CAAA;AAI3B,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,gBAAgB,CAAA;AAErE,qBAAa,6BAA8B,YAAW,2BAA2B;IACnE,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAEzC,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmDnF,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmBnF,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAkBnF,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAiBnF,OAAO,CAAC,MAAM,EAAE;QACpB,SAAS,EAAE,MAAM,CAAA;QACjB,EAAE,EAAE,MAAM,CAAA;KACX,GAAG,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC;IASxC,IAAI,CAAC,KAAK,EAAE,8BAA8B,GAAG,OAAO,CAAC,+BAA+B,CAAC;CAiG5F"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sixb/pg",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "PostgreSQL storage provider for Sixb",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sixb",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"postgres": "^3.4.5"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@sixb/core": "0.1.
|
|
43
|
+
"@sixb/core": "0.1.13"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@sixb/core": "0.1.
|
|
46
|
+
"@sixb/core": "0.1.13",
|
|
47
47
|
"@types/bun": "latest",
|
|
48
48
|
"typescript": "^5.7.0"
|
|
49
49
|
},
|
|
@@ -24,10 +24,10 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
24
24
|
const id = assertNonEmpty(input.id, "Access token id")
|
|
25
25
|
const projectId = assertNonEmpty(input.projectId, "Project id")
|
|
26
26
|
const name = assertNonEmpty(input.name, "Access token name")
|
|
27
|
-
const subjectId = assertNonEmpty(input.
|
|
27
|
+
const subjectId = assertNonEmpty(input.subject.id, "Access token subject id")
|
|
28
28
|
const tokenHash = assertNonEmpty(input.tokenHash, "Access token hash")
|
|
29
29
|
assertKindMatchesSubject(input)
|
|
30
|
-
await this.assertSubjectExists(projectId, input.
|
|
30
|
+
await this.assertSubjectExists(projectId, input.subject.type, subjectId)
|
|
31
31
|
const groupIds = input.groupIds === undefined ? undefined : normalizeGroupIds(input.groupIds)
|
|
32
32
|
|
|
33
33
|
try {
|
|
@@ -52,7 +52,7 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
52
52
|
${id},
|
|
53
53
|
${name},
|
|
54
54
|
${input.kind},
|
|
55
|
-
${input.
|
|
55
|
+
${input.subject.type},
|
|
56
56
|
${subjectId},
|
|
57
57
|
${tokenHash},
|
|
58
58
|
${serializeOptionalStringArray(groupIds)},
|
|
@@ -99,13 +99,9 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
99
99
|
whereClauses.push(`kind = $${nextIndex++}`)
|
|
100
100
|
params.push(input.kind)
|
|
101
101
|
}
|
|
102
|
-
if (input.
|
|
103
|
-
whereClauses.push(`subject_type = $${nextIndex++}`)
|
|
104
|
-
params.push(input.
|
|
105
|
-
}
|
|
106
|
-
if (input.subjectId) {
|
|
107
|
-
whereClauses.push(`subject_id = $${nextIndex++}`)
|
|
108
|
-
params.push(input.subjectId)
|
|
102
|
+
if (input.subject) {
|
|
103
|
+
whereClauses.push(`subject_type = $${nextIndex++}`, `subject_id = $${nextIndex++}`)
|
|
104
|
+
params.push(input.subject.type, input.subject.id)
|
|
109
105
|
}
|
|
110
106
|
if (!input.includeRevoked) {
|
|
111
107
|
whereClauses.push("revoked_at IS NULL")
|
|
@@ -208,7 +204,7 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
208
204
|
|
|
209
205
|
private async assertSubjectExists(
|
|
210
206
|
projectId: string,
|
|
211
|
-
subjectType: CreateAuthAccessTokenInput["
|
|
207
|
+
subjectType: CreateAuthAccessTokenInput["subject"]["type"],
|
|
212
208
|
subjectId: string
|
|
213
209
|
): Promise<void> {
|
|
214
210
|
if (subjectType === "user") {
|
|
@@ -241,14 +237,14 @@ export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
|
241
237
|
|
|
242
238
|
function assertKindMatchesSubject(input: CreateAuthAccessTokenInput): void {
|
|
243
239
|
if (
|
|
244
|
-
(input.kind === "personal" && input.
|
|
245
|
-
(input.kind === "serviceAccount" && input.
|
|
240
|
+
(input.kind === "personal" && input.subject.type === "user") ||
|
|
241
|
+
(input.kind === "serviceAccount" && input.subject.type === "serviceAccount")
|
|
246
242
|
) {
|
|
247
243
|
return
|
|
248
244
|
}
|
|
249
245
|
|
|
250
246
|
throw new AuthStorageError(
|
|
251
247
|
"invalid_input",
|
|
252
|
-
`[Sixb] Access token kind '${input.kind}' cannot target subject type '${input.
|
|
248
|
+
`[Sixb] Access token kind '${input.kind}' cannot target subject type '${input.subject.type}'.`
|
|
253
249
|
)
|
|
254
250
|
}
|
|
@@ -113,7 +113,7 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
113
113
|
)
|
|
114
114
|
}
|
|
115
115
|
assertCompletableDeviceAuthorization(authorization, input)
|
|
116
|
-
const
|
|
116
|
+
const session = await createSession(tx, input.session)
|
|
117
117
|
const [consumed] = await tx`
|
|
118
118
|
UPDATE auth_device_authorizations
|
|
119
119
|
SET status = 'consumed', consumed_at = ${input.completedAt}
|
|
@@ -132,7 +132,7 @@ export class PgAuthStorage implements AuthStorage {
|
|
|
132
132
|
status: "consumed" as const,
|
|
133
133
|
consumedAt: new Date(input.completedAt),
|
|
134
134
|
},
|
|
135
|
-
|
|
135
|
+
session,
|
|
136
136
|
}
|
|
137
137
|
})
|
|
138
138
|
}
|
|
@@ -869,10 +869,8 @@ function assertCompletableDeviceAuthorization(
|
|
|
869
869
|
authorization.expiresAt <= input.completedAt ||
|
|
870
870
|
!authorization.approvedUserId ||
|
|
871
871
|
!authorization.approvedSessionId ||
|
|
872
|
-
input.
|
|
873
|
-
input.
|
|
874
|
-
input.accessToken.subjectId !== authorization.approvedUserId ||
|
|
875
|
-
input.accessToken.createdBySessionId !== authorization.approvedSessionId
|
|
872
|
+
input.session.projectId !== input.projectId ||
|
|
873
|
+
input.session.userId !== authorization.approvedUserId
|
|
876
874
|
) {
|
|
877
875
|
throw new AuthStorageError(
|
|
878
876
|
"invalid_device_authorization",
|
|
@@ -37,16 +37,15 @@ export class PgAuthDeviceAuthorizationStore implements AuthDeviceAuthorizationSt
|
|
|
37
37
|
try {
|
|
38
38
|
const [row] = await tx<PgAuthDeviceAuthorizationRow[]>`
|
|
39
39
|
INSERT INTO auth_device_authorizations (
|
|
40
|
-
project_id, id, device_code_hash, user_code, client_name,
|
|
41
|
-
|
|
40
|
+
project_id, id, device_code_hash, user_code, client_name, status, created_at,
|
|
41
|
+
expires_at
|
|
42
42
|
) VALUES (
|
|
43
43
|
${assertNonEmpty(input.projectId, "Project id")},
|
|
44
44
|
${assertNonEmpty(input.id, "Device authorization id")},
|
|
45
45
|
${assertNonEmpty(input.deviceCodeHash, "Device code hash")},
|
|
46
46
|
${assertNonEmpty(input.userCode, "User code")},
|
|
47
47
|
${assertNonEmpty(input.clientName, "Client name")},
|
|
48
|
-
${
|
|
49
|
-
${input.tokenExpiresAt}, 'pending', ${input.createdAt}, ${input.expiresAt}
|
|
48
|
+
'pending', ${input.createdAt}, ${input.expiresAt}
|
|
50
49
|
) RETURNING *
|
|
51
50
|
`
|
|
52
51
|
return rowToDeviceAuthorizationRecord(row)
|
package/src/auth-storage/rows.ts
CHANGED
|
@@ -76,6 +76,11 @@ export interface PgAuthSessionRow {
|
|
|
76
76
|
readonly last_seen_at: PgDate | null
|
|
77
77
|
readonly user_agent: string | null
|
|
78
78
|
readonly ip_address: string | null
|
|
79
|
+
readonly client_name: string | null
|
|
80
|
+
readonly access_expires_at: PgDate | null
|
|
81
|
+
readonly refresh_token_hash: string | null
|
|
82
|
+
readonly previous_refresh_token_hash: string | null
|
|
83
|
+
readonly refreshed_at: PgDate | null
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
export interface PgAuthAccessTokenRow {
|
|
@@ -83,7 +88,7 @@ export interface PgAuthAccessTokenRow {
|
|
|
83
88
|
readonly id: string
|
|
84
89
|
readonly name: string
|
|
85
90
|
readonly kind: AccessTokenRecord["kind"]
|
|
86
|
-
readonly subject_type: AccessTokenRecord["
|
|
91
|
+
readonly subject_type: AccessTokenRecord["subject"]["type"]
|
|
87
92
|
readonly subject_id: string
|
|
88
93
|
readonly token_hash: string
|
|
89
94
|
readonly group_ids: readonly string[] | string | null
|
|
@@ -157,8 +162,6 @@ export interface PgAuthDeviceAuthorizationRow {
|
|
|
157
162
|
readonly device_code_hash: string
|
|
158
163
|
readonly user_code: string
|
|
159
164
|
readonly client_name: string
|
|
160
|
-
readonly token_name: string
|
|
161
|
-
readonly token_expires_at: PgDate
|
|
162
165
|
readonly status: DeviceAuthorizationRecord["status"]
|
|
163
166
|
readonly approved_user_id: string | null
|
|
164
167
|
readonly approved_session_id: string | null
|
|
@@ -235,6 +238,16 @@ export function rowToSessionRecord(row: PgAuthSessionRow): SessionRecord {
|
|
|
235
238
|
lastSeenAt: row.last_seen_at ? toDate(row.last_seen_at) : undefined,
|
|
236
239
|
userAgent: row.user_agent ?? undefined,
|
|
237
240
|
ipAddress: row.ip_address ?? undefined,
|
|
241
|
+
bearer:
|
|
242
|
+
row.refresh_token_hash !== null && row.client_name !== null && row.access_expires_at !== null
|
|
243
|
+
? {
|
|
244
|
+
clientName: row.client_name,
|
|
245
|
+
accessExpiresAt: toDate(row.access_expires_at),
|
|
246
|
+
refreshTokenHash: row.refresh_token_hash,
|
|
247
|
+
previousRefreshTokenHash: row.previous_refresh_token_hash ?? undefined,
|
|
248
|
+
refreshedAt: row.refreshed_at ? toDate(row.refreshed_at) : undefined,
|
|
249
|
+
}
|
|
250
|
+
: undefined,
|
|
238
251
|
}
|
|
239
252
|
}
|
|
240
253
|
|
|
@@ -244,8 +257,7 @@ export function rowToAccessTokenRecord(row: PgAuthAccessTokenRow): AccessTokenRe
|
|
|
244
257
|
projectId: row.project_id,
|
|
245
258
|
name: row.name,
|
|
246
259
|
kind: row.kind,
|
|
247
|
-
|
|
248
|
-
subjectId: row.subject_id,
|
|
260
|
+
subject: { type: row.subject_type, id: row.subject_id },
|
|
249
261
|
tokenHash: row.token_hash,
|
|
250
262
|
groupIds: parseOptionalStringArray(row.group_ids),
|
|
251
263
|
createdByPrincipal: principalFromColumns(row),
|
|
@@ -332,8 +344,6 @@ export function rowToDeviceAuthorizationRecord(
|
|
|
332
344
|
deviceCodeHash: row.device_code_hash,
|
|
333
345
|
userCode: row.user_code,
|
|
334
346
|
clientName: row.client_name,
|
|
335
|
-
tokenName: row.token_name,
|
|
336
|
-
tokenExpiresAt: toDate(row.token_expires_at),
|
|
337
347
|
status: row.status,
|
|
338
348
|
approvedUserId: row.approved_user_id ?? undefined,
|
|
339
349
|
approvedSessionId: row.approved_session_id ?? undefined,
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { AuthSessionAudience } from "@sixb/core"
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AuthSessionStore,
|
|
4
|
+
CreateAuthSessionInput,
|
|
5
|
+
RotateSessionRefreshTokenResult,
|
|
6
|
+
SessionRecord,
|
|
7
|
+
} from "@sixb/core/storage"
|
|
3
8
|
import { AuthStorageError } from "@sixb/core/storage"
|
|
4
9
|
import {
|
|
5
10
|
authLockKey,
|
|
@@ -85,11 +90,10 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
85
90
|
|
|
86
91
|
if (
|
|
87
92
|
!row ||
|
|
93
|
+
row.refresh_token_hash !== null ||
|
|
88
94
|
row.audience !== params.audience ||
|
|
89
95
|
row.token_hash !== params.tokenHash ||
|
|
90
|
-
row.
|
|
91
|
-
new Date(row.expires_at) <= params.now ||
|
|
92
|
-
(row.absolute_expires_at !== null && new Date(row.absolute_expires_at) <= params.now)
|
|
96
|
+
!isLiveSessionRow(row, params.now)
|
|
93
97
|
) {
|
|
94
98
|
return null
|
|
95
99
|
}
|
|
@@ -97,6 +101,71 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
97
101
|
return rowToSessionRecord(row)
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
async findValidByAccessTokenHash(params: {
|
|
105
|
+
readonly projectId: string
|
|
106
|
+
readonly id: string
|
|
107
|
+
readonly tokenHash: string
|
|
108
|
+
readonly now: Date
|
|
109
|
+
}): Promise<SessionRecord | null> {
|
|
110
|
+
const row = await getSessionRowById(this.sql, params)
|
|
111
|
+
if (
|
|
112
|
+
!row ||
|
|
113
|
+
row.access_expires_at === null ||
|
|
114
|
+
row.token_hash !== params.tokenHash ||
|
|
115
|
+
new Date(row.access_expires_at) <= params.now ||
|
|
116
|
+
!isLiveSessionRow(row, params.now)
|
|
117
|
+
) {
|
|
118
|
+
return null
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return rowToSessionRecord(row)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async rotateRefreshToken(
|
|
125
|
+
params: Parameters<AuthSessionStore["rotateRefreshToken"]>[0]
|
|
126
|
+
): Promise<RotateSessionRefreshTokenResult> {
|
|
127
|
+
return runPgTransaction(this.sql, async (tx): Promise<RotateSessionRefreshTokenResult> => {
|
|
128
|
+
const row = await getSessionRowById(tx, params, { forUpdate: true })
|
|
129
|
+
if (!row?.refresh_token_hash || !isLiveSessionRow(row, params.now)) {
|
|
130
|
+
return { status: "invalid" }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const replacedRecently =
|
|
134
|
+
row.previous_refresh_token_hash === params.refreshTokenHash &&
|
|
135
|
+
row.refreshed_at !== null &&
|
|
136
|
+
params.now.getTime() - new Date(row.refreshed_at).getTime() <= params.reuseGraceMs
|
|
137
|
+
if (row.refresh_token_hash !== params.refreshTokenHash && !replacedRecently) {
|
|
138
|
+
if (row.previous_refresh_token_hash !== params.refreshTokenHash) {
|
|
139
|
+
return { status: "invalid" }
|
|
140
|
+
}
|
|
141
|
+
await tx`
|
|
142
|
+
UPDATE auth_sessions SET revoked_at = ${params.now}
|
|
143
|
+
WHERE project_id = ${params.projectId} AND id = ${params.id}
|
|
144
|
+
`
|
|
145
|
+
return { status: "reused" }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const [rotated] = await tx<PgAuthSessionRow[]>`
|
|
149
|
+
UPDATE auth_sessions
|
|
150
|
+
SET token_hash = ${params.next.tokenHash},
|
|
151
|
+
access_expires_at = ${params.next.accessExpiresAt},
|
|
152
|
+
previous_refresh_token_hash = refresh_token_hash,
|
|
153
|
+
refresh_token_hash = ${params.next.refreshTokenHash},
|
|
154
|
+
refreshed_at = ${params.now},
|
|
155
|
+
last_seen_at = ${params.now},
|
|
156
|
+
expires_at = GREATEST(
|
|
157
|
+
expires_at,
|
|
158
|
+
LEAST(${params.next.expiresAt}, COALESCE(absolute_expires_at, ${params.next.expiresAt}))
|
|
159
|
+
)
|
|
160
|
+
WHERE project_id = ${params.projectId} AND id = ${params.id}
|
|
161
|
+
RETURNING *
|
|
162
|
+
`
|
|
163
|
+
return rotated
|
|
164
|
+
? { status: "rotated", session: rowToSessionRecord(rotated) }
|
|
165
|
+
: { status: "invalid" }
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
100
169
|
async renewIfValid(params: {
|
|
101
170
|
readonly projectId: string
|
|
102
171
|
readonly id: string
|
|
@@ -119,6 +188,7 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
119
188
|
AND id = ${params.id}
|
|
120
189
|
AND audience = ${params.audience}
|
|
121
190
|
AND token_hash = ${params.tokenHash}
|
|
191
|
+
AND refresh_token_hash IS NULL
|
|
122
192
|
AND revoked_at IS NULL
|
|
123
193
|
AND expires_at > ${params.now}
|
|
124
194
|
AND (absolute_expires_at IS NULL OR absolute_expires_at > ${params.now})
|
|
@@ -191,3 +261,11 @@ export class PgAuthSessionStore implements AuthSessionStore {
|
|
|
191
261
|
})
|
|
192
262
|
}
|
|
193
263
|
}
|
|
264
|
+
|
|
265
|
+
function isLiveSessionRow(row: PgAuthSessionRow, now: Date): boolean {
|
|
266
|
+
return (
|
|
267
|
+
row.revoked_at === null &&
|
|
268
|
+
new Date(row.expires_at) > now &&
|
|
269
|
+
(row.absolute_expires_at === null || new Date(row.absolute_expires_at) > now)
|
|
270
|
+
)
|
|
271
|
+
}
|
|
@@ -487,7 +487,10 @@ export async function createSession(
|
|
|
487
487
|
expires_at,
|
|
488
488
|
absolute_expires_at,
|
|
489
489
|
user_agent,
|
|
490
|
-
ip_address
|
|
490
|
+
ip_address,
|
|
491
|
+
client_name,
|
|
492
|
+
access_expires_at,
|
|
493
|
+
refresh_token_hash
|
|
491
494
|
) VALUES (
|
|
492
495
|
${projectId},
|
|
493
496
|
${id},
|
|
@@ -499,7 +502,10 @@ export async function createSession(
|
|
|
499
502
|
${input.expiresAt},
|
|
500
503
|
${input.absoluteExpiresAt ?? null},
|
|
501
504
|
${input.userAgent ?? null},
|
|
502
|
-
${input.ipAddress ?? null}
|
|
505
|
+
${input.ipAddress ?? null},
|
|
506
|
+
${input.bearer ? assertNonEmpty(input.bearer.clientName, "Session client name") : null},
|
|
507
|
+
${input.bearer?.accessExpiresAt ?? null},
|
|
508
|
+
${input.bearer ? assertNonEmpty(input.bearer.refreshTokenHash, "Refresh token hash") : null}
|
|
503
509
|
)
|
|
504
510
|
RETURNING *
|
|
505
511
|
`
|
package/src/index.ts
CHANGED
|
@@ -42,6 +42,7 @@ import { PgAiLimitStorage } from "./pg-ai-limit-storage"
|
|
|
42
42
|
import { PgAiUsageStorage } from "./pg-ai-usage-storage"
|
|
43
43
|
import { createPgClient, type SQL, type SQLClient } from "./pg-client"
|
|
44
44
|
import { PgExecutionStorage } from "./pg-execution-storage"
|
|
45
|
+
import { PgFileUploadSessionStorage } from "./pg-file-upload-session-storage"
|
|
45
46
|
import { PgPipelineRunStorage } from "./pg-pipeline-run-storage"
|
|
46
47
|
import { PgProjectionRunStorage } from "./pg-projection-run-storage"
|
|
47
48
|
import { PgRulesStorage } from "./pg-rules-storage"
|
|
@@ -158,6 +159,7 @@ export class PostgresStorage implements MigrationCapableStorage {
|
|
|
158
159
|
readonly connectorConnections: PgConnectorConnectionStorage
|
|
159
160
|
readonly shareGrants: PgShareGrantStorage
|
|
160
161
|
readonly shareSessions: PgShareSessionStorage
|
|
162
|
+
readonly fileUploadSessions: PgFileUploadSessionStorage
|
|
161
163
|
readonly migrators: readonly StorageMigrator[]
|
|
162
164
|
|
|
163
165
|
private readonly sql: SQL
|
|
@@ -235,6 +237,7 @@ export class PostgresStorage implements MigrationCapableStorage {
|
|
|
235
237
|
this.connectorConnections = createOperationScopedFacade(stores.connectorConnections, scope)
|
|
236
238
|
this.shareGrants = createOperationScopedFacade(stores.shareGrants, scope)
|
|
237
239
|
this.shareSessions = createOperationScopedFacade(stores.shareSessions, scope)
|
|
240
|
+
this.fileUploadSessions = createOperationScopedFacade(stores.fileUploadSessions, scope)
|
|
238
241
|
registerPostgresStorageTestingAdapter(this, (durationMs) =>
|
|
239
242
|
stores.connectorConnections.advanceTimeForTesting(durationMs)
|
|
240
243
|
)
|
|
@@ -371,6 +374,7 @@ function createPostgresStores(
|
|
|
371
374
|
connectorConnections: new PgConnectorConnectionStorage(sql),
|
|
372
375
|
shareGrants,
|
|
373
376
|
shareSessions,
|
|
377
|
+
fileUploadSessions: new PgFileUploadSessionStorage(sql),
|
|
374
378
|
}
|
|
375
379
|
}
|
|
376
380
|
|
|
@@ -395,6 +399,7 @@ interface PostgresStoreSet {
|
|
|
395
399
|
readonly connectorConnections: PgConnectorConnectionStorage
|
|
396
400
|
readonly shareGrants: PgShareGrantStorage
|
|
397
401
|
readonly shareSessions: PgShareSessionStorage
|
|
402
|
+
readonly fileUploadSessions: PgFileUploadSessionStorage
|
|
398
403
|
}
|
|
399
404
|
|
|
400
405
|
function resolveTimeoutMillis(value: number | undefined, label: string): number | undefined {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Intervention actors were stored as { principalType, principalId }. Rewrite them to the
|
|
2
|
+
-- canonical Principal shape { type, id } used by every other stored principal.
|
|
3
|
+
UPDATE workflow_interventions
|
|
4
|
+
SET submitted_by = jsonb_build_object(
|
|
5
|
+
'type', submitted_by->>'principalType',
|
|
6
|
+
'id', submitted_by->>'principalId'
|
|
7
|
+
)
|
|
8
|
+
WHERE submitted_by->>'principalType' IS NOT NULL;
|
|
9
|
+
|
|
10
|
+
UPDATE workflow_interventions
|
|
11
|
+
SET cancelled_by = jsonb_build_object(
|
|
12
|
+
'type', cancelled_by->>'principalType',
|
|
13
|
+
'id', cancelled_by->>'principalId'
|
|
14
|
+
)
|
|
15
|
+
WHERE cancelled_by->>'principalType' IS NOT NULL;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
-- Commits and their events name who requested the write and what ran it, replacing the
|
|
2
|
+
-- authority-only `actor`. Both are copied from the commit's execution, which stays canonical and
|
|
3
|
+
-- is immutable, so the backfill is exact.
|
|
4
|
+
ALTER TABLE ontology_commits
|
|
5
|
+
ADD COLUMN requested_by JSONB,
|
|
6
|
+
ADD COLUMN executor JSONB;
|
|
7
|
+
|
|
8
|
+
UPDATE ontology_commits c SET
|
|
9
|
+
requested_by = CASE
|
|
10
|
+
WHEN e.requested_by_user_id IS NOT NULL
|
|
11
|
+
THEN jsonb_build_object('type', 'user', 'id', e.requested_by_user_id)
|
|
12
|
+
WHEN e.requested_by_service_account_id IS NOT NULL
|
|
13
|
+
THEN jsonb_build_object('type', 'serviceAccount', 'id', e.requested_by_service_account_id)
|
|
14
|
+
END,
|
|
15
|
+
executor = CASE e.executor_kind
|
|
16
|
+
WHEN 'request' THEN jsonb_build_object('type', 'request', 'requestId', e.executor_id)
|
|
17
|
+
WHEN 'agent' THEN jsonb_build_object('type', 'agent', 'runId', e.executor_id)
|
|
18
|
+
WHEN 'kernel' THEN jsonb_build_object(
|
|
19
|
+
'type', 'kernel',
|
|
20
|
+
'operation',
|
|
21
|
+
CASE e.authority_kernel_operation
|
|
22
|
+
WHEN 'ontology.recover'
|
|
23
|
+
THEN jsonb_build_object('type', 'ontology.recover', 'recoveryId', e.executor_id)
|
|
24
|
+
ELSE jsonb_build_object('type', 'ontology.indexVectors', 'indexingId', e.executor_id)
|
|
25
|
+
END
|
|
26
|
+
)
|
|
27
|
+
ELSE jsonb_build_object(
|
|
28
|
+
'type', 'primitive',
|
|
29
|
+
'kind', e.executor_kind,
|
|
30
|
+
'id', e.authority_primitive_id,
|
|
31
|
+
'runId', e.executor_id
|
|
32
|
+
)
|
|
33
|
+
END
|
|
34
|
+
FROM executions e
|
|
35
|
+
WHERE e.project_id = c.project_id AND e.id = c.execution_id;
|
|
36
|
+
|
|
37
|
+
ALTER TABLE ontology_commits ALTER COLUMN executor SET NOT NULL;
|
|
38
|
+
|
|
39
|
+
-- Events not yet published would otherwise reach consumers in the retired shape.
|
|
40
|
+
UPDATE ontology_outbox o SET envelope =
|
|
41
|
+
(o.envelope - 'actor')
|
|
42
|
+
|| jsonb_build_object('executor', c.executor)
|
|
43
|
+
|| CASE
|
|
44
|
+
WHEN c.requested_by IS NULL THEN '{}'::jsonb
|
|
45
|
+
ELSE jsonb_build_object('requestedBy', c.requested_by)
|
|
46
|
+
END
|
|
47
|
+
FROM ontology_commits c
|
|
48
|
+
WHERE c.project_id = o.project_id AND c.id = o.commit_id;
|
|
49
|
+
|
|
50
|
+
ALTER TABLE ontology_commits DROP COLUMN actor;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
-- Durable staged-upload sessions, so an upload survives restarts and spans API replicas.
|
|
2
|
+
CREATE TABLE file_upload_sessions (
|
|
3
|
+
id TEXT PRIMARY KEY CHECK (length(trim(id)) > 0),
|
|
4
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
5
|
+
owner_principal_type TEXT NOT NULL
|
|
6
|
+
CHECK (owner_principal_type IN ('user', 'serviceAccount', 'system')),
|
|
7
|
+
owner_principal_id TEXT NOT NULL CHECK (length(owner_principal_id) > 0),
|
|
8
|
+
strategy TEXT NOT NULL CHECK (strategy IN ('server', 'direct-put', 'multipart')),
|
|
9
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'completed', 'aborted')),
|
|
10
|
+
file_name TEXT,
|
|
11
|
+
media_type TEXT,
|
|
12
|
+
logical_path TEXT,
|
|
13
|
+
expected_size_bytes BIGINT CHECK (expected_size_bytes IS NULL OR expected_size_bytes >= 0),
|
|
14
|
+
expected_digest TEXT,
|
|
15
|
+
provider_upload JSONB CHECK (provider_upload IS NULL OR jsonb_typeof(provider_upload) = 'object'),
|
|
16
|
+
signed_parts JSONB NOT NULL CHECK (jsonb_typeof(signed_parts) = 'array'),
|
|
17
|
+
file_ref JSONB CHECK (file_ref IS NULL OR jsonb_typeof(file_ref) = 'object'),
|
|
18
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
19
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
20
|
+
completed_at TIMESTAMPTZ,
|
|
21
|
+
aborted_at TIMESTAMPTZ,
|
|
22
|
+
-- Derived by core (fileUploadSessionReapAt); NULL while an abandoned upload awaits its abort.
|
|
23
|
+
reap_at TIMESTAMPTZ,
|
|
24
|
+
CHECK ((status = 'completed') = (completed_at IS NOT NULL)),
|
|
25
|
+
CHECK ((status = 'aborted') = (aborted_at IS NOT NULL))
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
CREATE INDEX idx_file_upload_sessions_reap
|
|
29
|
+
ON file_upload_sessions (reap_at)
|
|
30
|
+
WHERE reap_at IS NOT NULL;
|
|
31
|
+
|
|
32
|
+
CREATE INDEX idx_file_upload_sessions_abandoned
|
|
33
|
+
ON file_upload_sessions (project_id, expires_at)
|
|
34
|
+
WHERE status = 'pending' AND provider_upload IS NOT NULL;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Native clients, such as the CLI, hold their session as bearer tokens: a
|
|
2
|
+
-- short-lived access token, whose hash is `token_hash`, and a rotating refresh token. Browser
|
|
3
|
+
-- sessions leave these columns NULL; `refresh_token_hash IS NULL` is what marks a cookie session.
|
|
4
|
+
ALTER TABLE auth_sessions
|
|
5
|
+
ADD COLUMN client_name TEXT,
|
|
6
|
+
ADD COLUMN access_expires_at TIMESTAMPTZ,
|
|
7
|
+
ADD COLUMN refresh_token_hash TEXT,
|
|
8
|
+
ADD COLUMN previous_refresh_token_hash TEXT,
|
|
9
|
+
ADD COLUMN refreshed_at TIMESTAMPTZ,
|
|
10
|
+
ADD CONSTRAINT auth_sessions_bearer_state CHECK (
|
|
11
|
+
(refresh_token_hash IS NULL) = (client_name IS NULL)
|
|
12
|
+
AND (refresh_token_hash IS NULL) = (access_expires_at IS NULL)
|
|
13
|
+
AND (refresh_token_hash IS NOT NULL OR previous_refresh_token_hash IS NULL)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
-- The device flow now starts a session instead of issuing a personal access token.
|
|
17
|
+
ALTER TABLE auth_device_authorizations
|
|
18
|
+
DROP COLUMN token_name,
|
|
19
|
+
DROP COLUMN token_expires_at;
|
package/src/migrations.ts
CHANGED
|
@@ -99,6 +99,13 @@ import vectorBatchingSql from "./migrations/044-vector-batching.sql" with { type
|
|
|
99
99
|
import agentThreadSandboxStateSql from "./migrations/045-agent-thread-sandbox-state.sql" with {
|
|
100
100
|
type: "text",
|
|
101
101
|
}
|
|
102
|
+
import workflowInterventionPrincipalsSql from "./migrations/046-workflow-intervention-principals.sql" with {
|
|
103
|
+
type: "text",
|
|
104
|
+
}
|
|
105
|
+
import ontologyCommitAttributionSql from "./migrations/047-ontology-commit-attribution.sql" with {
|
|
106
|
+
type: "text",
|
|
107
|
+
}
|
|
108
|
+
import nativeSessionsSql from "./migrations/049-native-sessions.sql" with { type: "text" }
|
|
102
109
|
import type { SQL, SQLClient } from "./pg-client"
|
|
103
110
|
|
|
104
111
|
export interface PostgresMigrationContext {
|
|
@@ -397,6 +404,10 @@ export const postgresStorageMigrations = defineMigrations<PostgresMigrationConte
|
|
|
397
404
|
pgSql("043-vector-indexing", vectorIndexingSql),
|
|
398
405
|
pgSql("044-vector-batching", vectorBatchingSql),
|
|
399
406
|
pgSql("045-agent-thread-sandbox-state", agentThreadSandboxStateSql),
|
|
407
|
+
pgSql("046-workflow-intervention-principals", workflowInterventionPrincipalsSql),
|
|
408
|
+
pgSql("047-ontology-commit-attribution", ontologyCommitAttributionSql),
|
|
409
|
+
pgSql("048-file-upload-sessions", fileUploadSessionsSql),
|
|
410
|
+
pgSql("049-native-sessions", nativeSessionsSql),
|
|
400
411
|
],
|
|
401
412
|
})
|
|
402
413
|
|
|
@@ -420,3 +431,4 @@ import outboxPublicationOrderSql from "./migrations/038-outbox-publication-order
|
|
|
420
431
|
import connectorOptionalPkceSql from "./migrations/040-connector-optional-pkce.sql" with {
|
|
421
432
|
type: "text",
|
|
422
433
|
}
|
|
434
|
+
import fileUploadSessionsSql from "./migrations/048-file-upload-sessions.sql" with { type: "text" }
|
package/src/objects/storage.ts
CHANGED
|
@@ -88,6 +88,8 @@ const PG_OBJECT_QUERY_CAPABILITIES: ObjectQueryCapabilities = {
|
|
|
88
88
|
decimal: { equality: true, ordering: true },
|
|
89
89
|
date: { equality: true, ordering: true },
|
|
90
90
|
timestamp: { equality: true, ordering: true },
|
|
91
|
+
// jsonb equality and containment compare both fields of `{ type, id }`, whatever key order.
|
|
92
|
+
userRef: { equality: true },
|
|
91
93
|
},
|
|
92
94
|
limits: {
|
|
93
95
|
totalCount: true,
|