@intx/db 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/approval-store.d.ts +7 -0
- package/dist/approval-store.js +13 -0
- package/dist/backfill-principal-keys.d.ts +9 -0
- package/dist/backfill-principal-keys.js +51 -0
- package/dist/client.d.ts +27 -2
- package/dist/client.js +6 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -0
- package/dist/connection.js +1 -0
- package/dist/credential-resolution.d.ts +54 -5
- package/dist/credential-resolution.js +109 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.js +10 -4
- package/dist/model-source-resolution.d.ts +6 -5
- package/dist/model-source-resolution.js +42 -13
- package/dist/parse-row.d.ts +39 -8
- package/dist/parse-row.js +8 -0
- package/dist/principal-key-store.d.ts +51 -0
- package/dist/principal-key-store.js +82 -0
- package/dist/principal-store.d.ts +44 -0
- package/dist/principal-store.js +67 -0
- package/dist/schema/approvals.js +5 -0
- package/dist/schema/git-tokens.js +1 -1
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/principal-keys.d.ts +126 -0
- package/dist/schema/principal-keys.js +28 -0
- package/dist/schema/sidecar-allocation.d.ts +19 -40
- package/dist/schema/sidecar-allocation.js +4 -8
- package/dist/schema/sidecar.d.ts +0 -17
- package/dist/schema/sidecar.js +4 -12
- package/dist/schema/tenants.js +13 -3
- package/dist/schema/workflow-probe.d.ts +358 -0
- package/dist/schema/workflow-probe.js +51 -0
- package/dist/schema/workflow-run-dispatch.d.ts +17 -0
- package/dist/schema/workflow-run-dispatch.js +7 -0
- package/dist/schema/workflow-run.d.ts +27 -0
- package/dist/schema/workflow-run.js +8 -0
- package/dist/sender-key-resolver.d.ts +91 -0
- package/dist/sender-key-resolver.js +184 -0
- package/dist/sidecar-allocation-store.d.ts +38 -3
- package/dist/sidecar-allocation-store.js +224 -22
- package/dist/signer-identity.d.ts +12 -0
- package/dist/signer-identity.js +15 -0
- package/dist/tenant-hierarchy.d.ts +2 -0
- package/dist/tenant-hierarchy.js +27 -0
- package/dist/workflow-probe-store.d.ts +47 -0
- package/dist/workflow-probe-store.js +124 -0
- package/dist/workflow-run-dispatch-store.d.ts +3 -0
- package/dist/workflow-run-dispatch-store.js +12 -2
- package/migrations/0085_add_approval_run_idx.sql +1 -0
- package/migrations/0086_cool_human_cannonball.sql +1 -0
- package/migrations/0087_drop_sidecar_placement.sql +3 -0
- package/migrations/0088_thick_sprite.sql +32 -0
- package/migrations/0089_tense_selene.sql +13 -0
- package/migrations/0090_tenant_domain_lower_unique.sql +2 -0
- package/migrations/0091_workflow_run_dispatch_sender_address.sql +21 -0
- package/migrations/0092_sidecar_destroy_failed.sql +4 -0
- package/migrations/0093_sidecar_initialization.sql +2 -0
- package/migrations/meta/0085_snapshot.json +4111 -0
- package/migrations/meta/0086_snapshot.json +4117 -0
- package/migrations/meta/0087_snapshot.json +4100 -0
- package/migrations/meta/0088_snapshot.json +4286 -0
- package/migrations/meta/0089_snapshot.json +4376 -0
- package/migrations/meta/0090_snapshot.json +4387 -0
- package/migrations/meta/0091_snapshot.json +4397 -0
- package/migrations/meta/0092_snapshot.json +4397 -0
- package/migrations/meta/0093_snapshot.json +4407 -0
- package/migrations/meta/_journal.json +63 -0
- package/package.json +6 -5
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import type { WorkflowProbeResultFrame } from "@intx/types/sidecar";
|
|
2
|
+
type WorkflowProbeResult = Omit<WorkflowProbeResultFrame, "type" | "requestId">;
|
|
3
|
+
export type WorkflowProbeStatus = "pending" | "provisioning" | "probing" | "releasing" | "succeeded" | "failed";
|
|
4
|
+
/**
|
|
5
|
+
* A workflow probe and the temporary provisioned capacity executing it.
|
|
6
|
+
*
|
|
7
|
+
* Deployment intent deliberately does not live here. The source and entry are
|
|
8
|
+
* the probe input; the result is the probe output. The provisioner binding is
|
|
9
|
+
* retained only so uncertain or abandoned capacity can be destroyed safely.
|
|
10
|
+
*/
|
|
11
|
+
export declare const workflowProbe: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
12
|
+
name: "workflow_probe";
|
|
13
|
+
schema: undefined;
|
|
14
|
+
columns: {
|
|
15
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
16
|
+
name: "id";
|
|
17
|
+
tableName: "workflow_probe";
|
|
18
|
+
dataType: "string";
|
|
19
|
+
columnType: "PgText";
|
|
20
|
+
data: string;
|
|
21
|
+
driverParam: string;
|
|
22
|
+
notNull: true;
|
|
23
|
+
hasDefault: false;
|
|
24
|
+
isPrimaryKey: true;
|
|
25
|
+
isAutoincrement: false;
|
|
26
|
+
hasRuntimeDefault: false;
|
|
27
|
+
enumValues: [string, ...string[]];
|
|
28
|
+
baseColumn: never;
|
|
29
|
+
identity: undefined;
|
|
30
|
+
generated: undefined;
|
|
31
|
+
}, {}, {}>;
|
|
32
|
+
tenantId: import("drizzle-orm/pg-core").PgColumn<{
|
|
33
|
+
name: "tenant_id";
|
|
34
|
+
tableName: "workflow_probe";
|
|
35
|
+
dataType: "string";
|
|
36
|
+
columnType: "PgText";
|
|
37
|
+
data: string;
|
|
38
|
+
driverParam: string;
|
|
39
|
+
notNull: true;
|
|
40
|
+
hasDefault: false;
|
|
41
|
+
isPrimaryKey: false;
|
|
42
|
+
isAutoincrement: false;
|
|
43
|
+
hasRuntimeDefault: false;
|
|
44
|
+
enumValues: [string, ...string[]];
|
|
45
|
+
baseColumn: never;
|
|
46
|
+
identity: undefined;
|
|
47
|
+
generated: undefined;
|
|
48
|
+
}, {}, {}>;
|
|
49
|
+
definitionAssetId: import("drizzle-orm/pg-core").PgColumn<{
|
|
50
|
+
name: "definition_asset_id";
|
|
51
|
+
tableName: "workflow_probe";
|
|
52
|
+
dataType: "string";
|
|
53
|
+
columnType: "PgText";
|
|
54
|
+
data: string;
|
|
55
|
+
driverParam: string;
|
|
56
|
+
notNull: true;
|
|
57
|
+
hasDefault: false;
|
|
58
|
+
isPrimaryKey: false;
|
|
59
|
+
isAutoincrement: false;
|
|
60
|
+
hasRuntimeDefault: false;
|
|
61
|
+
enumValues: [string, ...string[]];
|
|
62
|
+
baseColumn: never;
|
|
63
|
+
identity: undefined;
|
|
64
|
+
generated: undefined;
|
|
65
|
+
}, {}, {}>;
|
|
66
|
+
source: import("drizzle-orm/pg-core").PgColumn<{
|
|
67
|
+
name: "source";
|
|
68
|
+
tableName: "workflow_probe";
|
|
69
|
+
dataType: "json";
|
|
70
|
+
columnType: "PgJsonb";
|
|
71
|
+
data: {
|
|
72
|
+
kind: "registry";
|
|
73
|
+
registry: string;
|
|
74
|
+
} | {
|
|
75
|
+
kind: "asset";
|
|
76
|
+
assetId: string;
|
|
77
|
+
package: {
|
|
78
|
+
format: "tarball";
|
|
79
|
+
} | {
|
|
80
|
+
format: "source";
|
|
81
|
+
commitSha: string;
|
|
82
|
+
packageName?: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
driverParam: unknown;
|
|
86
|
+
notNull: true;
|
|
87
|
+
hasDefault: false;
|
|
88
|
+
isPrimaryKey: false;
|
|
89
|
+
isAutoincrement: false;
|
|
90
|
+
hasRuntimeDefault: false;
|
|
91
|
+
enumValues: undefined;
|
|
92
|
+
baseColumn: never;
|
|
93
|
+
identity: undefined;
|
|
94
|
+
generated: undefined;
|
|
95
|
+
}, {}, {
|
|
96
|
+
$type: {
|
|
97
|
+
kind: "registry";
|
|
98
|
+
registry: string;
|
|
99
|
+
} | {
|
|
100
|
+
kind: "asset";
|
|
101
|
+
assetId: string;
|
|
102
|
+
package: {
|
|
103
|
+
format: "tarball";
|
|
104
|
+
} | {
|
|
105
|
+
format: "source";
|
|
106
|
+
commitSha: string;
|
|
107
|
+
packageName?: string;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
}>;
|
|
111
|
+
entry: import("drizzle-orm/pg-core").PgColumn<{
|
|
112
|
+
name: "entry";
|
|
113
|
+
tableName: "workflow_probe";
|
|
114
|
+
dataType: "string";
|
|
115
|
+
columnType: "PgText";
|
|
116
|
+
data: string;
|
|
117
|
+
driverParam: string;
|
|
118
|
+
notNull: true;
|
|
119
|
+
hasDefault: false;
|
|
120
|
+
isPrimaryKey: false;
|
|
121
|
+
isAutoincrement: false;
|
|
122
|
+
hasRuntimeDefault: false;
|
|
123
|
+
enumValues: [string, ...string[]];
|
|
124
|
+
baseColumn: never;
|
|
125
|
+
identity: undefined;
|
|
126
|
+
generated: undefined;
|
|
127
|
+
}, {}, {}>;
|
|
128
|
+
pin: import("drizzle-orm/pg-core").PgColumn<{
|
|
129
|
+
name: "pin";
|
|
130
|
+
tableName: "workflow_probe";
|
|
131
|
+
dataType: "string";
|
|
132
|
+
columnType: "PgText";
|
|
133
|
+
data: string;
|
|
134
|
+
driverParam: string;
|
|
135
|
+
notNull: false;
|
|
136
|
+
hasDefault: false;
|
|
137
|
+
isPrimaryKey: false;
|
|
138
|
+
isAutoincrement: false;
|
|
139
|
+
hasRuntimeDefault: false;
|
|
140
|
+
enumValues: [string, ...string[]];
|
|
141
|
+
baseColumn: never;
|
|
142
|
+
identity: undefined;
|
|
143
|
+
generated: undefined;
|
|
144
|
+
}, {}, {}>;
|
|
145
|
+
status: import("drizzle-orm/pg-core").PgColumn<{
|
|
146
|
+
name: "status";
|
|
147
|
+
tableName: "workflow_probe";
|
|
148
|
+
dataType: "string";
|
|
149
|
+
columnType: "PgText";
|
|
150
|
+
data: WorkflowProbeStatus;
|
|
151
|
+
driverParam: string;
|
|
152
|
+
notNull: true;
|
|
153
|
+
hasDefault: true;
|
|
154
|
+
isPrimaryKey: false;
|
|
155
|
+
isAutoincrement: false;
|
|
156
|
+
hasRuntimeDefault: false;
|
|
157
|
+
enumValues: [string, ...string[]];
|
|
158
|
+
baseColumn: never;
|
|
159
|
+
identity: undefined;
|
|
160
|
+
generated: undefined;
|
|
161
|
+
}, {}, {
|
|
162
|
+
$type: WorkflowProbeStatus;
|
|
163
|
+
}>;
|
|
164
|
+
provisionerId: import("drizzle-orm/pg-core").PgColumn<{
|
|
165
|
+
name: "provisioner_id";
|
|
166
|
+
tableName: "workflow_probe";
|
|
167
|
+
dataType: "string";
|
|
168
|
+
columnType: "PgText";
|
|
169
|
+
data: string;
|
|
170
|
+
driverParam: string;
|
|
171
|
+
notNull: true;
|
|
172
|
+
hasDefault: false;
|
|
173
|
+
isPrimaryKey: false;
|
|
174
|
+
isAutoincrement: false;
|
|
175
|
+
hasRuntimeDefault: false;
|
|
176
|
+
enumValues: [string, ...string[]];
|
|
177
|
+
baseColumn: never;
|
|
178
|
+
identity: undefined;
|
|
179
|
+
generated: undefined;
|
|
180
|
+
}, {}, {}>;
|
|
181
|
+
provisionerApiVersion: import("drizzle-orm/pg-core").PgColumn<{
|
|
182
|
+
name: "provisioner_api_version";
|
|
183
|
+
tableName: "workflow_probe";
|
|
184
|
+
dataType: "number";
|
|
185
|
+
columnType: "PgInteger";
|
|
186
|
+
data: 1;
|
|
187
|
+
driverParam: string | number;
|
|
188
|
+
notNull: true;
|
|
189
|
+
hasDefault: false;
|
|
190
|
+
isPrimaryKey: false;
|
|
191
|
+
isAutoincrement: false;
|
|
192
|
+
hasRuntimeDefault: false;
|
|
193
|
+
enumValues: undefined;
|
|
194
|
+
baseColumn: never;
|
|
195
|
+
identity: undefined;
|
|
196
|
+
generated: undefined;
|
|
197
|
+
}, {}, {
|
|
198
|
+
$type: 1;
|
|
199
|
+
}>;
|
|
200
|
+
provisionerBindingFingerprint: import("drizzle-orm/pg-core").PgColumn<{
|
|
201
|
+
name: "provisioner_binding_fingerprint";
|
|
202
|
+
tableName: "workflow_probe";
|
|
203
|
+
dataType: "string";
|
|
204
|
+
columnType: "PgText";
|
|
205
|
+
data: string;
|
|
206
|
+
driverParam: string;
|
|
207
|
+
notNull: true;
|
|
208
|
+
hasDefault: false;
|
|
209
|
+
isPrimaryKey: false;
|
|
210
|
+
isAutoincrement: false;
|
|
211
|
+
hasRuntimeDefault: false;
|
|
212
|
+
enumValues: [string, ...string[]];
|
|
213
|
+
baseColumn: never;
|
|
214
|
+
identity: undefined;
|
|
215
|
+
generated: undefined;
|
|
216
|
+
}, {}, {}>;
|
|
217
|
+
sidecarId: import("drizzle-orm/pg-core").PgColumn<{
|
|
218
|
+
name: "sidecar_id";
|
|
219
|
+
tableName: "workflow_probe";
|
|
220
|
+
dataType: "string";
|
|
221
|
+
columnType: "PgText";
|
|
222
|
+
data: string;
|
|
223
|
+
driverParam: string;
|
|
224
|
+
notNull: false;
|
|
225
|
+
hasDefault: false;
|
|
226
|
+
isPrimaryKey: false;
|
|
227
|
+
isAutoincrement: false;
|
|
228
|
+
hasRuntimeDefault: false;
|
|
229
|
+
enumValues: [string, ...string[]];
|
|
230
|
+
baseColumn: never;
|
|
231
|
+
identity: undefined;
|
|
232
|
+
generated: undefined;
|
|
233
|
+
}, {}, {}>;
|
|
234
|
+
generation: import("drizzle-orm/pg-core").PgColumn<{
|
|
235
|
+
name: "generation";
|
|
236
|
+
tableName: "workflow_probe";
|
|
237
|
+
dataType: "number";
|
|
238
|
+
columnType: "PgInteger";
|
|
239
|
+
data: number;
|
|
240
|
+
driverParam: string | number;
|
|
241
|
+
notNull: true;
|
|
242
|
+
hasDefault: true;
|
|
243
|
+
isPrimaryKey: false;
|
|
244
|
+
isAutoincrement: false;
|
|
245
|
+
hasRuntimeDefault: false;
|
|
246
|
+
enumValues: undefined;
|
|
247
|
+
baseColumn: never;
|
|
248
|
+
identity: undefined;
|
|
249
|
+
generated: undefined;
|
|
250
|
+
}, {}, {}>;
|
|
251
|
+
externalRef: import("drizzle-orm/pg-core").PgColumn<{
|
|
252
|
+
name: "external_ref";
|
|
253
|
+
tableName: "workflow_probe";
|
|
254
|
+
dataType: "string";
|
|
255
|
+
columnType: "PgText";
|
|
256
|
+
data: string;
|
|
257
|
+
driverParam: string;
|
|
258
|
+
notNull: false;
|
|
259
|
+
hasDefault: false;
|
|
260
|
+
isPrimaryKey: false;
|
|
261
|
+
isAutoincrement: false;
|
|
262
|
+
hasRuntimeDefault: false;
|
|
263
|
+
enumValues: [string, ...string[]];
|
|
264
|
+
baseColumn: never;
|
|
265
|
+
identity: undefined;
|
|
266
|
+
generated: undefined;
|
|
267
|
+
}, {}, {}>;
|
|
268
|
+
result: import("drizzle-orm/pg-core").PgColumn<{
|
|
269
|
+
name: "result";
|
|
270
|
+
tableName: "workflow_probe";
|
|
271
|
+
dataType: "json";
|
|
272
|
+
columnType: "PgJsonb";
|
|
273
|
+
data: WorkflowProbeResult;
|
|
274
|
+
driverParam: unknown;
|
|
275
|
+
notNull: false;
|
|
276
|
+
hasDefault: false;
|
|
277
|
+
isPrimaryKey: false;
|
|
278
|
+
isAutoincrement: false;
|
|
279
|
+
hasRuntimeDefault: false;
|
|
280
|
+
enumValues: undefined;
|
|
281
|
+
baseColumn: never;
|
|
282
|
+
identity: undefined;
|
|
283
|
+
generated: undefined;
|
|
284
|
+
}, {}, {
|
|
285
|
+
$type: WorkflowProbeResult;
|
|
286
|
+
}>;
|
|
287
|
+
failureCode: import("drizzle-orm/pg-core").PgColumn<{
|
|
288
|
+
name: "failure_code";
|
|
289
|
+
tableName: "workflow_probe";
|
|
290
|
+
dataType: "string";
|
|
291
|
+
columnType: "PgText";
|
|
292
|
+
data: string;
|
|
293
|
+
driverParam: string;
|
|
294
|
+
notNull: false;
|
|
295
|
+
hasDefault: false;
|
|
296
|
+
isPrimaryKey: false;
|
|
297
|
+
isAutoincrement: false;
|
|
298
|
+
hasRuntimeDefault: false;
|
|
299
|
+
enumValues: [string, ...string[]];
|
|
300
|
+
baseColumn: never;
|
|
301
|
+
identity: undefined;
|
|
302
|
+
generated: undefined;
|
|
303
|
+
}, {}, {}>;
|
|
304
|
+
failureMessage: import("drizzle-orm/pg-core").PgColumn<{
|
|
305
|
+
name: "failure_message";
|
|
306
|
+
tableName: "workflow_probe";
|
|
307
|
+
dataType: "string";
|
|
308
|
+
columnType: "PgText";
|
|
309
|
+
data: string;
|
|
310
|
+
driverParam: string;
|
|
311
|
+
notNull: false;
|
|
312
|
+
hasDefault: false;
|
|
313
|
+
isPrimaryKey: false;
|
|
314
|
+
isAutoincrement: false;
|
|
315
|
+
hasRuntimeDefault: false;
|
|
316
|
+
enumValues: [string, ...string[]];
|
|
317
|
+
baseColumn: never;
|
|
318
|
+
identity: undefined;
|
|
319
|
+
generated: undefined;
|
|
320
|
+
}, {}, {}>;
|
|
321
|
+
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
322
|
+
name: "created_at";
|
|
323
|
+
tableName: "workflow_probe";
|
|
324
|
+
dataType: "date";
|
|
325
|
+
columnType: "PgTimestamp";
|
|
326
|
+
data: Date;
|
|
327
|
+
driverParam: string;
|
|
328
|
+
notNull: true;
|
|
329
|
+
hasDefault: true;
|
|
330
|
+
isPrimaryKey: false;
|
|
331
|
+
isAutoincrement: false;
|
|
332
|
+
hasRuntimeDefault: false;
|
|
333
|
+
enumValues: undefined;
|
|
334
|
+
baseColumn: never;
|
|
335
|
+
identity: undefined;
|
|
336
|
+
generated: undefined;
|
|
337
|
+
}, {}, {}>;
|
|
338
|
+
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
339
|
+
name: "updated_at";
|
|
340
|
+
tableName: "workflow_probe";
|
|
341
|
+
dataType: "date";
|
|
342
|
+
columnType: "PgTimestamp";
|
|
343
|
+
data: Date;
|
|
344
|
+
driverParam: string;
|
|
345
|
+
notNull: true;
|
|
346
|
+
hasDefault: true;
|
|
347
|
+
isPrimaryKey: false;
|
|
348
|
+
isAutoincrement: false;
|
|
349
|
+
hasRuntimeDefault: false;
|
|
350
|
+
enumValues: undefined;
|
|
351
|
+
baseColumn: never;
|
|
352
|
+
identity: undefined;
|
|
353
|
+
generated: undefined;
|
|
354
|
+
}, {}, {}>;
|
|
355
|
+
};
|
|
356
|
+
dialect: "pg";
|
|
357
|
+
}>;
|
|
358
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
import { check, index, integer, jsonb, pgTable, text, timestamp, } from "drizzle-orm/pg-core";
|
|
3
|
+
import { asset } from "./assets.js";
|
|
4
|
+
import { sidecar } from "./sidecar.js";
|
|
5
|
+
import { tenant } from "./tenants.js";
|
|
6
|
+
/**
|
|
7
|
+
* A workflow probe and the temporary provisioned capacity executing it.
|
|
8
|
+
*
|
|
9
|
+
* Deployment intent deliberately does not live here. The source and entry are
|
|
10
|
+
* the probe input; the result is the probe output. The provisioner binding is
|
|
11
|
+
* retained only so uncertain or abandoned capacity can be destroyed safely.
|
|
12
|
+
*/
|
|
13
|
+
export const workflowProbe = pgTable("workflow_probe", {
|
|
14
|
+
id: text("id").primaryKey(),
|
|
15
|
+
tenantId: text("tenant_id")
|
|
16
|
+
.notNull()
|
|
17
|
+
.references(() => tenant.id, { onDelete: "restrict" }),
|
|
18
|
+
definitionAssetId: text("definition_asset_id")
|
|
19
|
+
.notNull()
|
|
20
|
+
.references(() => asset.id, { onDelete: "restrict" }),
|
|
21
|
+
source: jsonb("source").$type().notNull(),
|
|
22
|
+
entry: text("entry").notNull(),
|
|
23
|
+
pin: text("pin"),
|
|
24
|
+
status: text("status")
|
|
25
|
+
.$type()
|
|
26
|
+
.notNull()
|
|
27
|
+
.default("pending"),
|
|
28
|
+
provisionerId: text("provisioner_id").notNull(),
|
|
29
|
+
provisionerApiVersion: integer("provisioner_api_version")
|
|
30
|
+
.$type()
|
|
31
|
+
.notNull(),
|
|
32
|
+
provisionerBindingFingerprint: text("provisioner_binding_fingerprint").notNull(),
|
|
33
|
+
sidecarId: text("sidecar_id").references(() => sidecar.id, {
|
|
34
|
+
onDelete: "restrict",
|
|
35
|
+
}),
|
|
36
|
+
generation: integer("generation").notNull().default(0),
|
|
37
|
+
externalRef: text("external_ref"),
|
|
38
|
+
result: jsonb("result").$type(),
|
|
39
|
+
failureCode: text("failure_code"),
|
|
40
|
+
failureMessage: text("failure_message"),
|
|
41
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
42
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
43
|
+
}, (t) => [
|
|
44
|
+
index("workflow_probe_active_idx")
|
|
45
|
+
.on(t.createdAt)
|
|
46
|
+
.where(sql `${t.status} in ('pending', 'provisioning', 'probing', 'releasing')`),
|
|
47
|
+
index("workflow_probe_sidecar_idx").on(t.sidecarId),
|
|
48
|
+
check("workflow_probe_status_check", sql `${t.status} in ('pending', 'provisioning', 'probing', 'releasing', 'succeeded', 'failed')`),
|
|
49
|
+
check("workflow_probe_succeeded_result_check", sql `${t.status} <> 'succeeded' or ${t.result} is not null`),
|
|
50
|
+
check("workflow_probe_generation_check", sql `${t.generation} >= 0`),
|
|
51
|
+
]);
|
|
@@ -81,6 +81,23 @@ export declare const workflowRunDispatch: import("drizzle-orm/pg-core").PgTableW
|
|
|
81
81
|
}, {}, {
|
|
82
82
|
$type: "signal" | "mail";
|
|
83
83
|
}>;
|
|
84
|
+
senderAddress: import("drizzle-orm/pg-core").PgColumn<{
|
|
85
|
+
name: "sender_address";
|
|
86
|
+
tableName: "workflow_run_dispatch";
|
|
87
|
+
dataType: "string";
|
|
88
|
+
columnType: "PgText";
|
|
89
|
+
data: string;
|
|
90
|
+
driverParam: string;
|
|
91
|
+
notNull: false;
|
|
92
|
+
hasDefault: false;
|
|
93
|
+
isPrimaryKey: false;
|
|
94
|
+
isAutoincrement: false;
|
|
95
|
+
hasRuntimeDefault: false;
|
|
96
|
+
enumValues: [string, ...string[]];
|
|
97
|
+
baseColumn: never;
|
|
98
|
+
identity: undefined;
|
|
99
|
+
generated: undefined;
|
|
100
|
+
}, {}, {}>;
|
|
84
101
|
rawMessage: import("drizzle-orm/pg-core").PgColumn<{
|
|
85
102
|
name: "raw_message";
|
|
86
103
|
tableName: "workflow_run_dispatch";
|
|
@@ -24,6 +24,7 @@ export const workflowRunDispatch = pgTable("workflow_run_dispatch", {
|
|
|
24
24
|
.$type()
|
|
25
25
|
.notNull()
|
|
26
26
|
.default("mail"),
|
|
27
|
+
senderAddress: text("sender_address"),
|
|
27
28
|
rawMessage: bytea("raw_message").notNull(),
|
|
28
29
|
stepGrants: jsonb("step_grants").notNull(),
|
|
29
30
|
status: text("status")
|
|
@@ -53,4 +54,10 @@ export const workflowRunDispatch = pgTable("workflow_run_dispatch", {
|
|
|
53
54
|
check("workflow_run_dispatch_acknowledged_generation_check", sql `${t.acknowledgedGeneration} is null or ${t.acknowledgedGeneration} >= 0`),
|
|
54
55
|
check("workflow_run_dispatch_acknowledged_state_check", sql `${t.status} <> 'acknowledged' or ${t.acknowledgedGeneration} is not null`),
|
|
55
56
|
check("workflow_run_dispatch_pending_schedule_check", sql `${t.status} <> 'pending' or ${t.nextAttemptAt} is not null`),
|
|
57
|
+
// A deliverable mail dispatch must carry the hub-verified sender that
|
|
58
|
+
// its inbound frame is stamped with; signals have no sender. Terminal
|
|
59
|
+
// (settled/failed) mail rows are exempt because they are never
|
|
60
|
+
// re-dispatched and so never reconstruct a frame -- this is what lets a
|
|
61
|
+
// migration fail legacy in-flight mail in place rather than delete it.
|
|
62
|
+
check("workflow_run_dispatch_mail_sender_check", sql `${t.kind} <> 'mail' or ${t.status} in ('settled', 'failed') or ${t.senderAddress} is not null`),
|
|
56
63
|
]);
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export type WorkflowRunCredentialRefs = {
|
|
2
|
+
credentialIds: string[];
|
|
3
|
+
bindings: {
|
|
4
|
+
handle: string;
|
|
5
|
+
credentialId: string;
|
|
6
|
+
consumer: string;
|
|
7
|
+
}[];
|
|
8
|
+
};
|
|
1
9
|
export declare const workflowRun: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
2
10
|
name: "workflow_run";
|
|
3
11
|
schema: undefined;
|
|
@@ -189,6 +197,25 @@ export declare const workflowRun: import("drizzle-orm/pg-core").PgTableWithColum
|
|
|
189
197
|
identity: undefined;
|
|
190
198
|
generated: undefined;
|
|
191
199
|
}, {}, {}>;
|
|
200
|
+
credentialRefs: import("drizzle-orm/pg-core").PgColumn<{
|
|
201
|
+
name: "credential_refs";
|
|
202
|
+
tableName: "workflow_run";
|
|
203
|
+
dataType: "json";
|
|
204
|
+
columnType: "PgJsonb";
|
|
205
|
+
data: WorkflowRunCredentialRefs;
|
|
206
|
+
driverParam: unknown;
|
|
207
|
+
notNull: false;
|
|
208
|
+
hasDefault: false;
|
|
209
|
+
isPrimaryKey: false;
|
|
210
|
+
isAutoincrement: false;
|
|
211
|
+
hasRuntimeDefault: false;
|
|
212
|
+
enumValues: undefined;
|
|
213
|
+
baseColumn: never;
|
|
214
|
+
identity: undefined;
|
|
215
|
+
generated: undefined;
|
|
216
|
+
}, {}, {
|
|
217
|
+
$type: WorkflowRunCredentialRefs;
|
|
218
|
+
}>;
|
|
192
219
|
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
193
220
|
name: "created_at";
|
|
194
221
|
tableName: "workflow_run";
|
|
@@ -71,6 +71,14 @@ export const workflowRun = pgTable("workflow_run", {
|
|
|
71
71
|
}),
|
|
72
72
|
kernelId: text("kernel_id"),
|
|
73
73
|
modelPreferences: jsonb("model_preferences"),
|
|
74
|
+
// The non-secret shape of the credential delivery this deployment resolved
|
|
75
|
+
// at deploy: the credentialIds it references and the tool binding
|
|
76
|
+
// descriptors. Set on a deployment anchor run; null for runs that carry no
|
|
77
|
+
// credential delivery. Secrets are NEVER stored here -- only ids and
|
|
78
|
+
// descriptors -- so the reconnect resync can re-resolve each id's CURRENT
|
|
79
|
+
// material from the credential table (dropping a revoked or deleted id,
|
|
80
|
+
// picking up a rotated secret) and reconcile the reconnecting child.
|
|
81
|
+
credentialRefs: jsonb("credential_refs").$type(),
|
|
74
82
|
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
75
83
|
// Nullable: a run has no end time until it reaches a terminal state.
|
|
76
84
|
endedAt: timestamp("ended_at"),
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { DBExecutor } from "./client.js";
|
|
2
|
+
import type { PrincipalKeyStore } from "./principal-key-store.js";
|
|
3
|
+
/**
|
|
4
|
+
* The durable public key that authenticates a signed mail sender, resolved from
|
|
5
|
+
* the hub's own storage. `source` records which store the key came from -- a
|
|
6
|
+
* run sender's key is the sidecar-minted key recorded on the deployment anchor,
|
|
7
|
+
* a user sender's key is the hub-custodied principal key -- so a consumer can
|
|
8
|
+
* bucket a resolution without re-parsing the address.
|
|
9
|
+
*/
|
|
10
|
+
export type SenderKeyResolution = {
|
|
11
|
+
source: "run";
|
|
12
|
+
publicKey: string;
|
|
13
|
+
} | {
|
|
14
|
+
source: "user";
|
|
15
|
+
publicKey: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the durable public key a signed mail sender must verify against,
|
|
19
|
+
* unioning the two existing durable-key sources: a run address
|
|
20
|
+
* (`run_<id>@<domain>`) resolves to the run's `workflow_run.public_key`; any
|
|
21
|
+
* other address (`<refId>@<domain>`) is treated as a user sender and resolves
|
|
22
|
+
* to that principal's hub-custodied key.
|
|
23
|
+
*
|
|
24
|
+
* Read-only. Returns `null` when the sender has no durable key to resolve -- a
|
|
25
|
+
* malformed address, an unknown run, a run whose deploy has not been acked yet,
|
|
26
|
+
* or an address that matches no user principal. A `null` is a legitimate
|
|
27
|
+
* "unresolvable sender" answer the caller acts on; it is NOT an error.
|
|
28
|
+
*
|
|
29
|
+
* Addresses are matched case-insensitively. Inbound `From` addresses are
|
|
30
|
+
* lowercased when parsed (see `@intx/mime` `extractAddrSpec`), so the address is
|
|
31
|
+
* normalized here and stored values are compared under `lower(...)`. Tenant
|
|
32
|
+
* domains are `lower(domain)`-unique (`tenant_domain_lower_idx`), so a
|
|
33
|
+
* normalized domain matches at most one tenant. A user `refId` is a
|
|
34
|
+
* case-sensitively-unique betterAuth id that can carry uppercase; lowercasing it
|
|
35
|
+
* to reconcile with the parser is lossy, so the resolver prefers the exact
|
|
36
|
+
* (already-lowercase) row and falls back to a case-insensitive match to find a
|
|
37
|
+
* mixed-case-stored refId. When two principals in one tenant hold case-variant
|
|
38
|
+
* refIds the case-insensitive match is not unique and no exact row disambiguates
|
|
39
|
+
* it: the resolver throws rather than silently return one, which would attribute
|
|
40
|
+
* the sender to the wrong principal.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveSenderKey(db: DBExecutor, principalKeyStore: PrincipalKeyStore, address: string): Promise<SenderKeyResolution | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the hex-encoded public key to stamp on an outbound mail frame, as a
|
|
45
|
+
* BEST-EFFORT value that never blocks delivery. Returns the key, or `null` when
|
|
46
|
+
* the sender has no resolvable key -- OR when resolution FAILS.
|
|
47
|
+
*
|
|
48
|
+
* {@link resolveSenderKey} throws on a genuine fault (an ambiguous user address,
|
|
49
|
+
* or a principal with no active key -- an INTR-164 invariant break). Those
|
|
50
|
+
* throws must fail loud for {@link auditSenderKeys}, but they must not break
|
|
51
|
+
* the send path: the frame key is nullable, so a recipient with no co-delivered
|
|
52
|
+
* key resolves the sender as `unknown`, which its admission policy rejects by
|
|
53
|
+
* default (a workflow may relax `unknown` to admit).
|
|
54
|
+
* Coupling delivery to key resolution would let a data-integrity fault strand a
|
|
55
|
+
* run or drop mail. So a throw here degrades to `null` and is logged at ERROR
|
|
56
|
+
* with its cause -- a degraded fault, kept distinct from the ordinary
|
|
57
|
+
* unresolvable-sender `null`, which stays silent.
|
|
58
|
+
*
|
|
59
|
+
* The principal key store is real in production (INTR-164 mints every principal
|
|
60
|
+
* a key), so the throw path is a defensive safety net, not the common case: the
|
|
61
|
+
* normal outcome is a resolved, populated key.
|
|
62
|
+
*/
|
|
63
|
+
export declare function resolveFrameSenderKey(db: DBExecutor, principalKeyStore: PrincipalKeyStore, address: string): Promise<string | null>;
|
|
64
|
+
/**
|
|
65
|
+
* The outcome of sweeping every sender that could sign a piece of mail: how many
|
|
66
|
+
* of each kind were checked, and any whose address did not resolve to a durable
|
|
67
|
+
* key. An empty `unresolved` is the "no unresolvable signed senders" state a
|
|
68
|
+
* durable-signature verifier depends on.
|
|
69
|
+
*/
|
|
70
|
+
export type SenderKeyAuditReport = {
|
|
71
|
+
runsChecked: number;
|
|
72
|
+
usersChecked: number;
|
|
73
|
+
unresolved: {
|
|
74
|
+
address: string;
|
|
75
|
+
kind: "run" | "user";
|
|
76
|
+
}[];
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Sweep every mail sender that could sign and confirm each resolves to a durable
|
|
80
|
+
* public key via {@link resolveSenderKey}. Read-only.
|
|
81
|
+
*
|
|
82
|
+
* The senders that can sign are every workflow run that holds a signing key or
|
|
83
|
+
* is live ("running") and carries a sending address, plus every active user
|
|
84
|
+
* principal. A never-signed run -- deployed-but-not-yet-acked, or failed or
|
|
85
|
+
* cancelled before ack (address set, key null) -- is excluded. Any checked
|
|
86
|
+
* sender that does not resolve is collected in `unresolved`. A keyless user
|
|
87
|
+
* principal is an INTR-164 invariant break, so `resolveSenderKey` throws and the
|
|
88
|
+
* sweep fails loudly rather than folding it into `unresolved` -- it is a
|
|
89
|
+
* different, more serious fault than an unresolvable address.
|
|
90
|
+
*/
|
|
91
|
+
export declare function auditSenderKeys(db: DBExecutor, principalKeyStore: PrincipalKeyStore): Promise<SenderKeyAuditReport>;
|