@keystrokehq/hosting 0.1.9 → 0.1.11
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/index.cjs +336 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +27 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +335 -99
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
+
let node_crypto = require("node:crypto");
|
|
24
25
|
let dockerode = require("dockerode");
|
|
25
26
|
dockerode = __toESM(dockerode, 1);
|
|
26
27
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -645,6 +646,7 @@ const string$1 = (params) => {
|
|
|
645
646
|
const integer = /^-?\d+$/;
|
|
646
647
|
const number$2 = /^-?\d+(?:\.\d+)?$/;
|
|
647
648
|
const boolean$1 = /^(?:true|false)$/i;
|
|
649
|
+
const _null$2 = /^null$/i;
|
|
648
650
|
const lowercase = /^[^A-Z]*$/;
|
|
649
651
|
const uppercase = /^[^a-z]*$/;
|
|
650
652
|
//#endregion
|
|
@@ -1457,6 +1459,22 @@ const $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
|
1457
1459
|
return payload;
|
|
1458
1460
|
};
|
|
1459
1461
|
});
|
|
1462
|
+
const $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
1463
|
+
$ZodType.init(inst, def);
|
|
1464
|
+
inst._zod.pattern = _null$2;
|
|
1465
|
+
inst._zod.values = new Set([null]);
|
|
1466
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1467
|
+
const input = payload.value;
|
|
1468
|
+
if (input === null) return payload;
|
|
1469
|
+
payload.issues.push({
|
|
1470
|
+
expected: "null",
|
|
1471
|
+
code: "invalid_type",
|
|
1472
|
+
input,
|
|
1473
|
+
inst
|
|
1474
|
+
});
|
|
1475
|
+
return payload;
|
|
1476
|
+
};
|
|
1477
|
+
});
|
|
1460
1478
|
const $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
1461
1479
|
$ZodType.init(inst, def);
|
|
1462
1480
|
inst._zod.parse = (payload) => payload;
|
|
@@ -2703,6 +2721,13 @@ function _boolean(Class, params) {
|
|
|
2703
2721
|
});
|
|
2704
2722
|
}
|
|
2705
2723
|
/* @__NO_SIDE_EFFECTS__ */
|
|
2724
|
+
function _null$1(Class, params) {
|
|
2725
|
+
return new Class({
|
|
2726
|
+
type: "null",
|
|
2727
|
+
...normalizeParams(params)
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2730
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
2706
2731
|
function _unknown(Class) {
|
|
2707
2732
|
return new Class({ type: "unknown" });
|
|
2708
2733
|
}
|
|
@@ -3251,6 +3276,13 @@ const numberProcessor = (schema, ctx, _json, _params) => {
|
|
|
3251
3276
|
const booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
3252
3277
|
json.type = "boolean";
|
|
3253
3278
|
};
|
|
3279
|
+
const nullProcessor = (_schema, ctx, json, _params) => {
|
|
3280
|
+
if (ctx.target === "openapi-3.0") {
|
|
3281
|
+
json.type = "string";
|
|
3282
|
+
json.nullable = true;
|
|
3283
|
+
json.enum = [null];
|
|
3284
|
+
} else json.type = "null";
|
|
3285
|
+
};
|
|
3254
3286
|
const neverProcessor = (_schema, _ctx, json, _params) => {
|
|
3255
3287
|
json.not = {};
|
|
3256
3288
|
};
|
|
@@ -3950,6 +3982,14 @@ const ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
|
3950
3982
|
function boolean(params) {
|
|
3951
3983
|
return /* @__PURE__ */ _boolean(ZodBoolean, params);
|
|
3952
3984
|
}
|
|
3985
|
+
const ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
3986
|
+
$ZodNull.init(inst, def);
|
|
3987
|
+
ZodType.init(inst, def);
|
|
3988
|
+
inst._zod.processJSONSchema = (ctx, json, params) => nullProcessor(inst, ctx, json, params);
|
|
3989
|
+
});
|
|
3990
|
+
function _null(params) {
|
|
3991
|
+
return /* @__PURE__ */ _null$1(ZodNull, params);
|
|
3992
|
+
}
|
|
3953
3993
|
const ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
3954
3994
|
$ZodUnknown.init(inst, def);
|
|
3955
3995
|
ZodType.init(inst, def);
|
|
@@ -4792,6 +4832,7 @@ const INFRA_SYSTEM_SLUGS = [
|
|
|
4792
4832
|
"health",
|
|
4793
4833
|
"healthcheck",
|
|
4794
4834
|
"healthz",
|
|
4835
|
+
"hook-resume",
|
|
4795
4836
|
"hooks",
|
|
4796
4837
|
"internal",
|
|
4797
4838
|
"item",
|
|
@@ -4957,14 +4998,14 @@ const OrganizationUserRoleSchema = _enum([
|
|
|
4957
4998
|
"admin",
|
|
4958
4999
|
"builder"
|
|
4959
5000
|
]);
|
|
4960
|
-
const isoDateTime$
|
|
5001
|
+
const isoDateTime$7 = string().datetime();
|
|
4961
5002
|
const OrganizationSchema = object({
|
|
4962
5003
|
id: string(),
|
|
4963
5004
|
name: string(),
|
|
4964
5005
|
slug: OrganizationSlugSchema,
|
|
4965
5006
|
verified: boolean(),
|
|
4966
|
-
createdAt: isoDateTime$
|
|
4967
|
-
updatedAt: isoDateTime$
|
|
5007
|
+
createdAt: isoDateTime$7,
|
|
5008
|
+
updatedAt: isoDateTime$7
|
|
4968
5009
|
});
|
|
4969
5010
|
const ProjectSchema = object({
|
|
4970
5011
|
id: string(),
|
|
@@ -4976,8 +5017,8 @@ const ProjectSchema = object({
|
|
|
4976
5017
|
baseUrl: string().nullable(),
|
|
4977
5018
|
runtimeId: string().nullable(),
|
|
4978
5019
|
lastError: string().nullable(),
|
|
4979
|
-
createdAt: isoDateTime$
|
|
4980
|
-
updatedAt: isoDateTime$
|
|
5020
|
+
createdAt: isoDateTime$7,
|
|
5021
|
+
updatedAt: isoDateTime$7
|
|
4981
5022
|
});
|
|
4982
5023
|
object({
|
|
4983
5024
|
organization: OrganizationSchema,
|
|
@@ -4997,7 +5038,7 @@ const ProjectListMetricsSchema = object({
|
|
|
4997
5038
|
workflowCount: number$1(),
|
|
4998
5039
|
skillCount: number$1(),
|
|
4999
5040
|
credentialCount: number$1(),
|
|
5000
|
-
lastDeploymentAt: isoDateTime$
|
|
5041
|
+
lastDeploymentAt: isoDateTime$7.nullable()
|
|
5001
5042
|
});
|
|
5002
5043
|
record(string(), ProjectListMetricsSchema);
|
|
5003
5044
|
object({
|
|
@@ -5352,6 +5393,130 @@ object({
|
|
|
5352
5393
|
skills: array(StoredRouteManifestSkillSchema).default([]),
|
|
5353
5394
|
integrations: array(string()).optional()
|
|
5354
5395
|
});
|
|
5396
|
+
const isoDateTime$6 = string().datetime();
|
|
5397
|
+
const subscriptionStatusSchema = _enum([
|
|
5398
|
+
"none",
|
|
5399
|
+
"trialing",
|
|
5400
|
+
"active",
|
|
5401
|
+
"past_due",
|
|
5402
|
+
"canceled"
|
|
5403
|
+
]);
|
|
5404
|
+
const CreditPackSchema = object({
|
|
5405
|
+
id: string(),
|
|
5406
|
+
usd: number$1(),
|
|
5407
|
+
microCredits: number$1(),
|
|
5408
|
+
label: string()
|
|
5409
|
+
});
|
|
5410
|
+
const AutoTopupSummarySchema = object({
|
|
5411
|
+
enabled: boolean(),
|
|
5412
|
+
thresholdMicroCredits: number$1().nullable(),
|
|
5413
|
+
amountMicroCredits: number$1().nullable(),
|
|
5414
|
+
/** A saved payment method exists to charge off-session. */
|
|
5415
|
+
hasPaymentMethod: boolean(),
|
|
5416
|
+
/** A top-up invoice payment is in flight. */
|
|
5417
|
+
pending: boolean()
|
|
5418
|
+
});
|
|
5419
|
+
/**
|
|
5420
|
+
* The plan's resolved limits. Storage overage is billed from the wallet's
|
|
5421
|
+
* pushed-down `includedStorageGb`; concurrency, per-pass run timeouts, and
|
|
5422
|
+
* API/MCP rate limits are enforced from the wallet (timeouts/concurrency) or
|
|
5423
|
+
* plan preset (rate limits). Log retention is configured but not pruned yet.
|
|
5424
|
+
*/
|
|
5425
|
+
const PlanLimitsSchema = object({
|
|
5426
|
+
includedStorageGb: number$1(),
|
|
5427
|
+
concurrencyLimit: number$1(),
|
|
5428
|
+
agentTimeoutMs: number$1(),
|
|
5429
|
+
workflowTimeoutMs: number$1(),
|
|
5430
|
+
pollTimeoutMs: number$1(),
|
|
5431
|
+
/** Configured retention window; pruning not implemented yet. */
|
|
5432
|
+
logRetentionDays: number$1(),
|
|
5433
|
+
apiRateLimitCapacity: number$1(),
|
|
5434
|
+
apiRateLimitRefillPerSec: number$1(),
|
|
5435
|
+
mcpRateLimitCapacity: number$1(),
|
|
5436
|
+
mcpRateLimitRefillPerSec: number$1()
|
|
5437
|
+
});
|
|
5438
|
+
object({
|
|
5439
|
+
planKey: string(),
|
|
5440
|
+
subscriptionStatus: subscriptionStatusSchema,
|
|
5441
|
+
planCreditMicroCredits: number$1(),
|
|
5442
|
+
prepaidCreditMicroCredits: number$1(),
|
|
5443
|
+
periodStart: isoDateTime$6.nullable(),
|
|
5444
|
+
periodEnd: isoDateTime$6.nullable(),
|
|
5445
|
+
autoTopup: AutoTopupSummarySchema,
|
|
5446
|
+
creditPacks: array(CreditPackSchema),
|
|
5447
|
+
limits: PlanLimitsSchema
|
|
5448
|
+
});
|
|
5449
|
+
const BillingUsageMeterSchema = object({
|
|
5450
|
+
/** Meter key (`llm`, `vm_second`, …); null groups uncategorized rows. */
|
|
5451
|
+
meterKey: string().nullable(),
|
|
5452
|
+
/** Charged this period, µc. */
|
|
5453
|
+
microCredits: number$1(),
|
|
5454
|
+
/** Tracked-but-not-charged usage (e.g. BYOK LLM calls), display USD. */
|
|
5455
|
+
unchargedUsd: number$1()
|
|
5456
|
+
});
|
|
5457
|
+
object({
|
|
5458
|
+
periodStart: isoDateTime$6.nullable(),
|
|
5459
|
+
periodEnd: isoDateTime$6.nullable(),
|
|
5460
|
+
totalMicroCredits: number$1(),
|
|
5461
|
+
byMeter: array(BillingUsageMeterSchema)
|
|
5462
|
+
});
|
|
5463
|
+
const billingLedgerEntryTypeSchema = _enum([
|
|
5464
|
+
"grant_plan",
|
|
5465
|
+
"grant_prepaid",
|
|
5466
|
+
"expire_plan",
|
|
5467
|
+
"adjustment"
|
|
5468
|
+
]);
|
|
5469
|
+
object({
|
|
5470
|
+
entries: array(object({
|
|
5471
|
+
id: string(),
|
|
5472
|
+
entryType: billingLedgerEntryTypeSchema,
|
|
5473
|
+
label: string(),
|
|
5474
|
+
/** Signed: positive grants, negative expirations/adjustments. */
|
|
5475
|
+
microCredits: number$1(),
|
|
5476
|
+
bucket: _enum(["plan", "prepaid"]).nullable(),
|
|
5477
|
+
/** Stripe invoice behind the entry, when there is one — powers "View invoice". */
|
|
5478
|
+
stripeInvoiceId: string().nullable(),
|
|
5479
|
+
createdAt: isoDateTime$6
|
|
5480
|
+
})),
|
|
5481
|
+
/** Set only when the latest payment failure is newer than the latest successful payment. */
|
|
5482
|
+
lastPaymentFailureAt: isoDateTime$6.nullable()
|
|
5483
|
+
});
|
|
5484
|
+
object({
|
|
5485
|
+
/** Web-app path to land on after Checkout (must be a path, not a URL). */
|
|
5486
|
+
returnPath: string().startsWith("/").max(512).optional() });
|
|
5487
|
+
object({
|
|
5488
|
+
packId: string(),
|
|
5489
|
+
returnPath: string().startsWith("/").max(512).optional()
|
|
5490
|
+
});
|
|
5491
|
+
object({ returnPath: string().startsWith("/").max(512).optional() });
|
|
5492
|
+
object({ url: string().url() });
|
|
5493
|
+
object({
|
|
5494
|
+
/** Hosted invoice page (view, download, receipt). */
|
|
5495
|
+
url: string().url(),
|
|
5496
|
+
/** Direct PDF download when Stripe provides one. */
|
|
5497
|
+
pdf: string().url().nullable()
|
|
5498
|
+
});
|
|
5499
|
+
object({
|
|
5500
|
+
/** Stripe Checkout Session id from the `session_id` success-URL param. */
|
|
5501
|
+
sessionId: string().min(1).max(255) });
|
|
5502
|
+
object({
|
|
5503
|
+
/**
|
|
5504
|
+
* `granted` — credits are in the wallet now; `processing` — payment not
|
|
5505
|
+
* complete yet, the webhook will finish it; `ignored` — not a confirmable
|
|
5506
|
+
* session for this org.
|
|
5507
|
+
*/
|
|
5508
|
+
status: _enum([
|
|
5509
|
+
"granted",
|
|
5510
|
+
"processing",
|
|
5511
|
+
"ignored"
|
|
5512
|
+
]),
|
|
5513
|
+
reason: string().optional()
|
|
5514
|
+
});
|
|
5515
|
+
object({
|
|
5516
|
+
enabled: boolean(),
|
|
5517
|
+
thresholdMicroCredits: number$1().int().positive().optional(),
|
|
5518
|
+
packId: string().optional()
|
|
5519
|
+
});
|
|
5355
5520
|
/** Messaging platforms that support agent gateway bindings. */
|
|
5356
5521
|
const ChannelPlatformKeySchema = _enum(["slack"]);
|
|
5357
5522
|
const ChannelReactionSupportSchema = _enum([
|
|
@@ -5872,7 +6037,11 @@ object({
|
|
|
5872
6037
|
isDefault: boolean().optional(),
|
|
5873
6038
|
value: credentialSecretValueSchema.optional()
|
|
5874
6039
|
}).refine((input) => input.label !== void 0 || input.isDefault !== void 0 || input.value !== void 0, { message: "At least one field is required" });
|
|
5875
|
-
const CredentialAssignmentTargetTypeSchema = _enum([
|
|
6040
|
+
const CredentialAssignmentTargetTypeSchema = _enum([
|
|
6041
|
+
"workflow",
|
|
6042
|
+
"agent",
|
|
6043
|
+
"poll"
|
|
6044
|
+
]);
|
|
5876
6045
|
object({ assignments: array(object({
|
|
5877
6046
|
id: string(),
|
|
5878
6047
|
targetType: CredentialAssignmentTargetTypeSchema,
|
|
@@ -5987,7 +6156,11 @@ const ValidationErrorDetailSchema = object({
|
|
|
5987
6156
|
message: string()
|
|
5988
6157
|
});
|
|
5989
6158
|
/** Machine-readable codes returned in standard API error bodies. */
|
|
5990
|
-
const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum([
|
|
6159
|
+
const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum([
|
|
6160
|
+
"needs_org_selection",
|
|
6161
|
+
"org_unverified",
|
|
6162
|
+
"connector_unavailable"
|
|
6163
|
+
]));
|
|
5991
6164
|
object({
|
|
5992
6165
|
error: string(),
|
|
5993
6166
|
code: ErrorResponseCodeSchema.optional(),
|
|
@@ -6098,6 +6271,17 @@ union([
|
|
|
6098
6271
|
SkipResponseSchema,
|
|
6099
6272
|
object({ runId: string() })
|
|
6100
6273
|
]);
|
|
6274
|
+
object({
|
|
6275
|
+
sql: string().min(1),
|
|
6276
|
+
params: array(unknown()).default([]),
|
|
6277
|
+
method: string().min(1).optional()
|
|
6278
|
+
});
|
|
6279
|
+
object({ migrations: array(object({
|
|
6280
|
+
sql: array(string().min(1)),
|
|
6281
|
+
hash: string().min(1),
|
|
6282
|
+
folderMillis: number$1()
|
|
6283
|
+
})) });
|
|
6284
|
+
object({ results: array(object({ rows: array(unknown()) })) });
|
|
6101
6285
|
const RunSourceKindSchema = _enum([
|
|
6102
6286
|
"api",
|
|
6103
6287
|
"trigger",
|
|
@@ -6418,12 +6602,19 @@ const HistoryRunActorSchema = object({
|
|
|
6418
6602
|
const HistoryRunUsageLineItemSchema = object({
|
|
6419
6603
|
id: string(),
|
|
6420
6604
|
label: string(),
|
|
6421
|
-
|
|
6605
|
+
/** Amount debited from the org's Keystroke balance for this line. */
|
|
6606
|
+
billedUsd: number$1(),
|
|
6607
|
+
/** Provider cost for LLM usage on the org's API key (informational; not billed by Keystroke). */
|
|
6608
|
+
providerCostUsd: number$1().nullable().optional(),
|
|
6609
|
+
keySource: _enum(["byok", "platform"]).nullable().optional()
|
|
6422
6610
|
});
|
|
6423
6611
|
const HistoryRunUsageSchema = object({
|
|
6424
6612
|
runDurationMs: number$1().nullable(),
|
|
6425
6613
|
lineItems: array(HistoryRunUsageLineItemSchema),
|
|
6426
|
-
|
|
6614
|
+
/** Sum of `billedUsd` — what Keystroke charged for this run. */
|
|
6615
|
+
totalBilledUsd: number$1().nullable(),
|
|
6616
|
+
/** Sum of BYOK LLM provider costs (billed externally by the org's provider). */
|
|
6617
|
+
externalProviderCostUsd: number$1().nullable().optional()
|
|
6427
6618
|
});
|
|
6428
6619
|
const HistoryRunSchema = object({
|
|
6429
6620
|
id: string(),
|
|
@@ -6554,6 +6745,7 @@ const HistoryRunDetailSchema = discriminatedUnion("kind", [object({
|
|
|
6554
6745
|
attachmentSlug: string().nullable()
|
|
6555
6746
|
}).nullable(),
|
|
6556
6747
|
messages: array(record(string(), unknown())),
|
|
6748
|
+
live: record(string(), unknown()).nullable().default(null),
|
|
6557
6749
|
trace: HistoryTraceSchema.nullable(),
|
|
6558
6750
|
ranAs: HistoryRunActorSchema.nullable().optional(),
|
|
6559
6751
|
usage: HistoryRunUsageSchema.nullable().optional()
|
|
@@ -6843,7 +7035,7 @@ const OrganizationMemberStatusSchema = _enum([
|
|
|
6843
7035
|
"suspended"
|
|
6844
7036
|
]);
|
|
6845
7037
|
const InvitableOrganizationMemberRoleSchema = _enum(["admin", "builder"]);
|
|
6846
|
-
const isoDateTime$
|
|
7038
|
+
const isoDateTime$5 = string().datetime();
|
|
6847
7039
|
object({
|
|
6848
7040
|
id: string(),
|
|
6849
7041
|
name: string(),
|
|
@@ -6851,8 +7043,8 @@ object({
|
|
|
6851
7043
|
role: OrganizationMemberRoleSchema,
|
|
6852
7044
|
status: OrganizationMemberStatusSchema,
|
|
6853
7045
|
avatarUrl: string().optional(),
|
|
6854
|
-
joinedAt: isoDateTime$
|
|
6855
|
-
lastActiveAt: isoDateTime$
|
|
7046
|
+
joinedAt: isoDateTime$5.optional(),
|
|
7047
|
+
lastActiveAt: isoDateTime$5.nullable().optional()
|
|
6856
7048
|
});
|
|
6857
7049
|
object({
|
|
6858
7050
|
emails: array(string().trim().email()).min(1),
|
|
@@ -6879,7 +7071,7 @@ object({
|
|
|
6879
7071
|
role: OrganizationMemberRoleSchema
|
|
6880
7072
|
});
|
|
6881
7073
|
object({ success: literal(true) });
|
|
6882
|
-
const isoDateTime$
|
|
7074
|
+
const isoDateTime$4 = string().datetime();
|
|
6883
7075
|
const ApiKeyCreatorSchema = object({
|
|
6884
7076
|
id: string(),
|
|
6885
7077
|
name: string(),
|
|
@@ -6892,12 +7084,37 @@ const ApiKeySummarySchema = object({
|
|
|
6892
7084
|
id: string(),
|
|
6893
7085
|
name: string(),
|
|
6894
7086
|
keyPreview: string(),
|
|
6895
|
-
createdAt: isoDateTime$
|
|
7087
|
+
createdAt: isoDateTime$4,
|
|
6896
7088
|
createdBy: ApiKeyCreatorSchema,
|
|
6897
7089
|
isCreatedByCurrentUser: boolean()
|
|
6898
7090
|
});
|
|
6899
7091
|
object({ name: string().trim().min(1).max(128) });
|
|
6900
7092
|
ApiKeySummarySchema.extend({ secret: string() });
|
|
7093
|
+
const isoDateTime$3 = string().datetime();
|
|
7094
|
+
const ManagedServiceKindSchema = _enum(["llm"]);
|
|
7095
|
+
_enum([
|
|
7096
|
+
"openai",
|
|
7097
|
+
"anthropic",
|
|
7098
|
+
"google",
|
|
7099
|
+
"groq",
|
|
7100
|
+
"xai"
|
|
7101
|
+
]);
|
|
7102
|
+
object({
|
|
7103
|
+
id: string(),
|
|
7104
|
+
kind: ManagedServiceKindSchema,
|
|
7105
|
+
provider: string(),
|
|
7106
|
+
keyPreview: string(),
|
|
7107
|
+
createdAt: isoDateTime$3,
|
|
7108
|
+
updatedAt: isoDateTime$3,
|
|
7109
|
+
createdBy: ApiKeyCreatorSchema,
|
|
7110
|
+
isCreatedByCurrentUser: boolean()
|
|
7111
|
+
});
|
|
7112
|
+
object({
|
|
7113
|
+
kind: ManagedServiceKindSchema.default("llm"),
|
|
7114
|
+
provider: string().trim().min(1),
|
|
7115
|
+
apiKey: string().trim().min(1)
|
|
7116
|
+
});
|
|
7117
|
+
object({ apiKey: string().trim().min(1) });
|
|
6901
7118
|
const ProjectUserRoleSchema = _enum(["admin", "builder"]);
|
|
6902
7119
|
const ProjectInvitePermissionSchema = _enum(["admin", "all"]);
|
|
6903
7120
|
const ProjectMemberStatusSchema = _enum(["active", "invited"]);
|
|
@@ -6947,6 +7164,14 @@ object({
|
|
|
6947
7164
|
uploadUrl: url(),
|
|
6948
7165
|
storageKey: string().min(1)
|
|
6949
7166
|
});
|
|
7167
|
+
function isValidIanaTimezone(value) {
|
|
7168
|
+
try {
|
|
7169
|
+
Intl.DateTimeFormat(void 0, { timeZone: value });
|
|
7170
|
+
return true;
|
|
7171
|
+
} catch {
|
|
7172
|
+
return false;
|
|
7173
|
+
}
|
|
7174
|
+
}
|
|
6950
7175
|
const UserInterfaceThemeSchema = _enum([
|
|
6951
7176
|
"system",
|
|
6952
7177
|
"light",
|
|
@@ -6966,22 +7191,25 @@ const UserWorkspaceFavoriteSchema = object({
|
|
|
6966
7191
|
]),
|
|
6967
7192
|
resourceId: string().min(1)
|
|
6968
7193
|
});
|
|
7194
|
+
const UserSidebarPreferencesSchema = object({
|
|
7195
|
+
navIconVisibility: UserSidebarNavIconVisibilitySchema,
|
|
7196
|
+
footerChatRowVisibility: UserSidebarFooterChatRowVisibilitySchema,
|
|
7197
|
+
hiddenNavItemIds: array(string()),
|
|
7198
|
+
topNavItemOrderIds: array(string()),
|
|
7199
|
+
workspaceNavItemOrderIds: array(string())
|
|
7200
|
+
});
|
|
7201
|
+
const UserTimezoneSchema = string().refine(isValidIanaTimezone, { message: "Invalid IANA timezone" });
|
|
6969
7202
|
object({
|
|
6970
7203
|
interfaceTheme: UserInterfaceThemeSchema,
|
|
6971
7204
|
surfaceContrast: UserSurfaceContrastSchema,
|
|
6972
7205
|
layoutMode: UserWorkspaceLayoutModeSchema,
|
|
6973
7206
|
fontSize: UserWorkspaceFontSizeSchema,
|
|
6974
|
-
sidebar:
|
|
6975
|
-
navIconVisibility: UserSidebarNavIconVisibilitySchema,
|
|
6976
|
-
footerChatRowVisibility: UserSidebarFooterChatRowVisibilitySchema,
|
|
6977
|
-
hiddenNavItemIds: array(string()),
|
|
6978
|
-
topNavItemOrderIds: array(string()),
|
|
6979
|
-
workspaceNavItemOrderIds: array(string())
|
|
6980
|
-
}),
|
|
7207
|
+
sidebar: UserSidebarPreferencesSchema,
|
|
6981
7208
|
favorites: array(UserWorkspaceFavoriteSchema),
|
|
6982
7209
|
projectOrderIds: array(string()),
|
|
6983
7210
|
projectDotColors: record(string(), string()),
|
|
6984
|
-
onboardingTabVisible: boolean()
|
|
7211
|
+
onboardingTabVisible: boolean(),
|
|
7212
|
+
timezone: union([UserTimezoneSchema, _null()])
|
|
6985
7213
|
});
|
|
6986
7214
|
const UserSidebarPreferencesPatchSchema = object({
|
|
6987
7215
|
navIconVisibility: UserSidebarNavIconVisibilitySchema.optional(),
|
|
@@ -6999,8 +7227,9 @@ object({
|
|
|
6999
7227
|
favorites: array(UserWorkspaceFavoriteSchema).optional(),
|
|
7000
7228
|
projectOrderIds: array(string()).optional(),
|
|
7001
7229
|
projectDotColors: record(string(), string()).optional(),
|
|
7002
|
-
onboardingTabVisible: boolean().optional()
|
|
7003
|
-
|
|
7230
|
+
onboardingTabVisible: boolean().optional(),
|
|
7231
|
+
timezone: union([UserTimezoneSchema, _null()]).optional()
|
|
7232
|
+
}).refine((value) => value.interfaceTheme !== void 0 || value.surfaceContrast !== void 0 || value.layoutMode !== void 0 || value.fontSize !== void 0 || value.sidebar !== void 0 || value.favorites !== void 0 || value.projectOrderIds !== void 0 || value.projectDotColors !== void 0 || value.onboardingTabVisible !== void 0 || value.timezone !== void 0, { message: "At least one preference field is required" });
|
|
7004
7233
|
const OrganizationLogoVariantSchema = _enum(["light", "dark"]);
|
|
7005
7234
|
object({
|
|
7006
7235
|
customLogoEnabled: boolean(),
|
|
@@ -7463,13 +7692,35 @@ function parseOrgArtifactsFromEnv(env = process.env) {
|
|
|
7463
7692
|
});
|
|
7464
7693
|
}
|
|
7465
7694
|
//#endregion
|
|
7695
|
+
//#region src/org-worker-token.ts
|
|
7696
|
+
function sign(secret, organizationId) {
|
|
7697
|
+
return (0, node_crypto.createHmac)("sha256", secret).update(`org-worker:${organizationId}`).digest("base64url");
|
|
7698
|
+
}
|
|
7699
|
+
/**
|
|
7700
|
+
* Per-org worker token: `{organizationId}.{hmac}`. Self-describing so the
|
|
7701
|
+
* platform can tell which org a machine is calling as, and stateless — verified
|
|
7702
|
+
* by re-signing with the shared `PLATFORM_WORKER_TOKEN` secret.
|
|
7703
|
+
*/
|
|
7704
|
+
function mintOrgWorkerToken(secret, organizationId) {
|
|
7705
|
+
return `${organizationId}.${sign(secret, organizationId)}`;
|
|
7706
|
+
}
|
|
7707
|
+
function verifyOrgWorkerToken(secret, token) {
|
|
7708
|
+
if (!secret || !token) return;
|
|
7709
|
+
const separator = token.lastIndexOf(".");
|
|
7710
|
+
if (separator <= 0) return;
|
|
7711
|
+
const organizationId = token.slice(0, separator);
|
|
7712
|
+
const signature = Buffer.from(token.slice(separator + 1));
|
|
7713
|
+
const expected = Buffer.from(sign(secret, organizationId));
|
|
7714
|
+
if (signature.length !== expected.length || !(0, node_crypto.timingSafeEqual)(signature, expected)) return;
|
|
7715
|
+
return { organizationId };
|
|
7716
|
+
}
|
|
7717
|
+
//#endregion
|
|
7466
7718
|
//#region src/runtime-env.ts
|
|
7467
7719
|
const RUNTIME_ENV_KEYS = [
|
|
7468
7720
|
"BETTER_AUTH_SECRET",
|
|
7469
7721
|
"PUBLIC_PLATFORM_URL",
|
|
7470
7722
|
"PUBLIC_PLATFORM_PROXY_URL",
|
|
7471
7723
|
"PUBLIC_WEB_URL",
|
|
7472
|
-
"POSTGRES_SSL",
|
|
7473
7724
|
"UPSTASH_REDIS_URL",
|
|
7474
7725
|
"REDIS_URL",
|
|
7475
7726
|
"KEYSTROKE_QUEUE_PREFIX"
|
|
@@ -7483,25 +7734,6 @@ const PROVIDER_ENV_KEYS = [
|
|
|
7483
7734
|
];
|
|
7484
7735
|
/** Shared dev token when `PLATFORM_WORKER_TOKEN` is unset (non-production only). */
|
|
7485
7736
|
const DEV_PLATFORM_WORKER_TOKEN = "dev-platform-worker-token";
|
|
7486
|
-
const PROJECT_DATABASE_ENV_KEYS = [
|
|
7487
|
-
"POSTGRES_HOST",
|
|
7488
|
-
"POSTGRES_PORT",
|
|
7489
|
-
"POSTGRES_DB",
|
|
7490
|
-
"POSTGRES_USER",
|
|
7491
|
-
"POSTGRES_PASSWORD",
|
|
7492
|
-
"DATABASE_SEARCH_PATH"
|
|
7493
|
-
];
|
|
7494
|
-
/** Per-project postgres env injected into every project server container/machine. */
|
|
7495
|
-
function projectDatabaseRuntimeEnv(database) {
|
|
7496
|
-
return {
|
|
7497
|
-
POSTGRES_HOST: rewriteLoopbackHost(database.host),
|
|
7498
|
-
POSTGRES_PORT: String(database.port),
|
|
7499
|
-
POSTGRES_DB: database.database,
|
|
7500
|
-
POSTGRES_USER: database.user,
|
|
7501
|
-
POSTGRES_PASSWORD: database.password,
|
|
7502
|
-
DATABASE_SEARCH_PATH: database.searchPath
|
|
7503
|
-
};
|
|
7504
|
-
}
|
|
7505
7737
|
/**
|
|
7506
7738
|
* Builds the launch spec for an org worker. Each deploy artifact is encoded in
|
|
7507
7739
|
* `KEYSTROKE_ORG_ARTIFACTS` — there is no base image, so at least one artifact is required.
|
|
@@ -7528,10 +7760,7 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
|
|
|
7528
7760
|
]);
|
|
7529
7761
|
for (const key of RUNTIME_ENV_KEYS) {
|
|
7530
7762
|
const value = source[key]?.trim();
|
|
7531
|
-
if (!value)
|
|
7532
|
-
if (key === "POSTGRES_SSL") throw new Error("POSTGRES_SSL is required");
|
|
7533
|
-
continue;
|
|
7534
|
-
}
|
|
7763
|
+
if (!value) continue;
|
|
7535
7764
|
entries.set(key, value);
|
|
7536
7765
|
}
|
|
7537
7766
|
if (!extraEnv) for (const key of PROVIDER_ENV_KEYS) {
|
|
@@ -7540,8 +7769,7 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
|
|
|
7540
7769
|
}
|
|
7541
7770
|
const worker = resolveWorkerRuntimeConfig(source);
|
|
7542
7771
|
entries.set("PLATFORM_URL", worker.platformUrl);
|
|
7543
|
-
entries.set("WORKER_INTERNAL_TOKEN", worker.workerToken);
|
|
7544
|
-
for (const [key, value] of Object.entries(projectDatabaseRuntimeEnv(database))) entries.set(key, value);
|
|
7772
|
+
entries.set("WORKER_INTERNAL_TOKEN", mintOrgWorkerToken(worker.workerToken, database.organizationId));
|
|
7545
7773
|
if (extraEnv) for (const [key, value] of Object.entries(extraEnv)) entries.set(key, value);
|
|
7546
7774
|
return Object.fromEntries(entries);
|
|
7547
7775
|
}
|
|
@@ -7629,55 +7857,63 @@ function sleep(ms) {
|
|
|
7629
7857
|
const MINIO_DOCKER_NETWORK = process.env.MINIO_DOCKER_NETWORK ?? "keystroke";
|
|
7630
7858
|
function createDockerRuntime(options = {}) {
|
|
7631
7859
|
const docker = options.docker ?? new dockerode.default();
|
|
7632
|
-
return {
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7860
|
+
return {
|
|
7861
|
+
async start(input) {
|
|
7862
|
+
if (input.projects.length === 0) throw new Error("Docker org runtime requires at least one project deploy");
|
|
7863
|
+
let launch = resolveRuntimeLaunch(options, input.projects.map((project) => ({
|
|
7864
|
+
projectId: project.projectId,
|
|
7865
|
+
artifactStorageKey: project.artifactStorageKey
|
|
7866
|
+
})), input.database, input.env);
|
|
7867
|
+
if (options.workspacesMount) {
|
|
7868
|
+
const { hostPath, containerPath } = options.workspacesMount;
|
|
7869
|
+
await (0, node_fs_promises.mkdir)(hostPath, { recursive: true });
|
|
7870
|
+
launch = {
|
|
7871
|
+
...launch,
|
|
7872
|
+
env: {
|
|
7873
|
+
...launch.env,
|
|
7874
|
+
KEYSTROKE_WORKSPACES_ROOT: containerPath
|
|
7875
|
+
}
|
|
7876
|
+
};
|
|
7877
|
+
}
|
|
7878
|
+
await ensureImage(docker, launch.image);
|
|
7879
|
+
await removeExistingContainer(docker, input.organizationId);
|
|
7880
|
+
const binds = [...options.workspacesMount ? [`${options.workspacesMount.hostPath}:${options.workspacesMount.containerPath}`] : [], ...options.extraBinds ?? []];
|
|
7881
|
+
const container = await docker.createContainer({
|
|
7882
|
+
Image: launch.image,
|
|
7883
|
+
name: containerName(input.organizationId),
|
|
7884
|
+
Labels: {
|
|
7885
|
+
"keystroke.organization.id": input.organizationId,
|
|
7886
|
+
"keystroke.project.ids": input.projects.map((project) => project.projectId).join(",")
|
|
7887
|
+
},
|
|
7888
|
+
ExposedPorts: { [`${launch.port}/tcp`]: {} },
|
|
7889
|
+
HostConfig: {
|
|
7890
|
+
ExtraHosts: ["host.docker.internal:host-gateway"],
|
|
7891
|
+
PortBindings: { [`${launch.port}/tcp`]: [{ HostPort: "0" }] },
|
|
7892
|
+
...binds.length > 0 ? { Binds: binds } : {}
|
|
7893
|
+
},
|
|
7894
|
+
NetworkingConfig: { EndpointsConfig: { [MINIO_DOCKER_NETWORK]: {} } },
|
|
7895
|
+
Env: formatDockerEnv(launch.env)
|
|
7896
|
+
});
|
|
7897
|
+
await container.start();
|
|
7898
|
+
const inspect = await container.inspect();
|
|
7899
|
+
const binding = inspect.NetworkSettings.Ports?.[`${launch.port}/tcp`]?.[0];
|
|
7900
|
+
if (!binding?.HostPort) throw new Error("Failed to resolve org container host port");
|
|
7901
|
+
const baseUrl = `http://127.0.0.1:${binding.HostPort}`;
|
|
7902
|
+
await waitForHealth(baseUrl, {
|
|
7903
|
+
fetchImpl: options.fetchImpl,
|
|
7904
|
+
timeoutMs: options.healthTimeoutMs
|
|
7905
|
+
});
|
|
7906
|
+
return {
|
|
7907
|
+
runtimeId: inspect.Id,
|
|
7908
|
+
baseUrl
|
|
7647
7909
|
};
|
|
7910
|
+
},
|
|
7911
|
+
async destroy(input) {
|
|
7912
|
+
try {
|
|
7913
|
+
await docker.getContainer(input.runtimeId).remove({ force: true });
|
|
7914
|
+
} catch {}
|
|
7648
7915
|
}
|
|
7649
|
-
|
|
7650
|
-
await removeExistingContainer(docker, input.organizationId);
|
|
7651
|
-
const container = await docker.createContainer({
|
|
7652
|
-
Image: launch.image,
|
|
7653
|
-
name: containerName(input.organizationId),
|
|
7654
|
-
Labels: {
|
|
7655
|
-
"keystroke.organization.id": input.organizationId,
|
|
7656
|
-
"keystroke.project.ids": input.projects.map((project) => project.projectId).join(",")
|
|
7657
|
-
},
|
|
7658
|
-
ExposedPorts: { [`${launch.port}/tcp`]: {} },
|
|
7659
|
-
HostConfig: {
|
|
7660
|
-
ExtraHosts: ["host.docker.internal:host-gateway"],
|
|
7661
|
-
PortBindings: { [`${launch.port}/tcp`]: [{ HostPort: "0" }] },
|
|
7662
|
-
...options.workspacesMount ? { Binds: [`${options.workspacesMount.hostPath}:${options.workspacesMount.containerPath}`] } : {}
|
|
7663
|
-
},
|
|
7664
|
-
NetworkingConfig: { EndpointsConfig: { [MINIO_DOCKER_NETWORK]: {} } },
|
|
7665
|
-
Env: formatDockerEnv(launch.env)
|
|
7666
|
-
});
|
|
7667
|
-
await container.start();
|
|
7668
|
-
const inspect = await container.inspect();
|
|
7669
|
-
const binding = inspect.NetworkSettings.Ports?.[`${launch.port}/tcp`]?.[0];
|
|
7670
|
-
if (!binding?.HostPort) throw new Error("Failed to resolve org container host port");
|
|
7671
|
-
const baseUrl = `http://127.0.0.1:${binding.HostPort}`;
|
|
7672
|
-
await waitForHealth(baseUrl, {
|
|
7673
|
-
fetchImpl: options.fetchImpl,
|
|
7674
|
-
timeoutMs: options.healthTimeoutMs
|
|
7675
|
-
});
|
|
7676
|
-
return {
|
|
7677
|
-
runtimeId: inspect.Id,
|
|
7678
|
-
baseUrl
|
|
7679
|
-
};
|
|
7680
|
-
} };
|
|
7916
|
+
};
|
|
7681
7917
|
}
|
|
7682
7918
|
function containerName(organizationId) {
|
|
7683
7919
|
return `keystroke-org-${organizationId}`;
|
|
@@ -7786,7 +8022,6 @@ async function fetchDeployStatus(baseUrl, options = {}) {
|
|
|
7786
8022
|
}
|
|
7787
8023
|
//#endregion
|
|
7788
8024
|
exports.DEV_PLATFORM_WORKER_TOKEN = DEV_PLATFORM_WORKER_TOKEN;
|
|
7789
|
-
exports.PROJECT_DATABASE_ENV_KEYS = PROJECT_DATABASE_ENV_KEYS;
|
|
7790
8025
|
exports.PROJECT_SERVER_DEPLOY_STATUS = PROJECT_SERVER_DEPLOY_STATUS;
|
|
7791
8026
|
exports.PROJECT_SERVER_FRAMEWORK_NODE_MODULES = PROJECT_SERVER_FRAMEWORK_NODE_MODULES;
|
|
7792
8027
|
exports.PROJECT_SERVER_FRAMEWORK_ROOT = PROJECT_SERVER_FRAMEWORK_ROOT;
|
|
@@ -7803,10 +8038,10 @@ exports.dockerPlugin = dockerPlugin;
|
|
|
7803
8038
|
exports.encodeOrgArtifacts = encodeOrgArtifacts;
|
|
7804
8039
|
exports.fetchDeployStatus = fetchDeployStatus;
|
|
7805
8040
|
exports.formatDockerEnv = formatDockerEnv;
|
|
8041
|
+
exports.mintOrgWorkerToken = mintOrgWorkerToken;
|
|
7806
8042
|
exports.parseOrgArtifactsFromEnv = parseOrgArtifactsFromEnv;
|
|
7807
8043
|
exports.pingProject = pingProject;
|
|
7808
8044
|
exports.pingProjectTarget = pingProjectTarget;
|
|
7809
|
-
exports.projectDatabaseRuntimeEnv = projectDatabaseRuntimeEnv;
|
|
7810
8045
|
exports.resolvePlatformWorkerToken = resolvePlatformWorkerToken;
|
|
7811
8046
|
exports.resolveProjectServerImage = resolveProjectServerImage;
|
|
7812
8047
|
exports.resolveRuntimeLaunch = resolveRuntimeLaunch;
|
|
@@ -7814,6 +8049,7 @@ exports.resolveWorkerPlatformUrl = resolveWorkerPlatformUrl;
|
|
|
7814
8049
|
exports.resolveWorkerRuntimeConfig = resolveWorkerRuntimeConfig;
|
|
7815
8050
|
exports.rewriteLoopbackHost = rewriteLoopbackHost;
|
|
7816
8051
|
exports.rewriteLoopbackUrl = rewriteLoopbackUrl;
|
|
8052
|
+
exports.verifyOrgWorkerToken = verifyOrgWorkerToken;
|
|
7817
8053
|
exports.waitForHealth = waitForHealth;
|
|
7818
8054
|
|
|
7819
8055
|
//# sourceMappingURL=index.cjs.map
|