@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.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
1
2
|
import Docker from "dockerode";
|
|
2
3
|
import { mkdir } from "node:fs/promises";
|
|
3
4
|
//#region src/constants.ts
|
|
@@ -621,6 +622,7 @@ const string$1 = (params) => {
|
|
|
621
622
|
const integer = /^-?\d+$/;
|
|
622
623
|
const number$2 = /^-?\d+(?:\.\d+)?$/;
|
|
623
624
|
const boolean$1 = /^(?:true|false)$/i;
|
|
625
|
+
const _null$2 = /^null$/i;
|
|
624
626
|
const lowercase = /^[^A-Z]*$/;
|
|
625
627
|
const uppercase = /^[^a-z]*$/;
|
|
626
628
|
//#endregion
|
|
@@ -1433,6 +1435,22 @@ const $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
|
1433
1435
|
return payload;
|
|
1434
1436
|
};
|
|
1435
1437
|
});
|
|
1438
|
+
const $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
1439
|
+
$ZodType.init(inst, def);
|
|
1440
|
+
inst._zod.pattern = _null$2;
|
|
1441
|
+
inst._zod.values = new Set([null]);
|
|
1442
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1443
|
+
const input = payload.value;
|
|
1444
|
+
if (input === null) return payload;
|
|
1445
|
+
payload.issues.push({
|
|
1446
|
+
expected: "null",
|
|
1447
|
+
code: "invalid_type",
|
|
1448
|
+
input,
|
|
1449
|
+
inst
|
|
1450
|
+
});
|
|
1451
|
+
return payload;
|
|
1452
|
+
};
|
|
1453
|
+
});
|
|
1436
1454
|
const $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
1437
1455
|
$ZodType.init(inst, def);
|
|
1438
1456
|
inst._zod.parse = (payload) => payload;
|
|
@@ -2679,6 +2697,13 @@ function _boolean(Class, params) {
|
|
|
2679
2697
|
});
|
|
2680
2698
|
}
|
|
2681
2699
|
/* @__NO_SIDE_EFFECTS__ */
|
|
2700
|
+
function _null$1(Class, params) {
|
|
2701
|
+
return new Class({
|
|
2702
|
+
type: "null",
|
|
2703
|
+
...normalizeParams(params)
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
2682
2707
|
function _unknown(Class) {
|
|
2683
2708
|
return new Class({ type: "unknown" });
|
|
2684
2709
|
}
|
|
@@ -3227,6 +3252,13 @@ const numberProcessor = (schema, ctx, _json, _params) => {
|
|
|
3227
3252
|
const booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
3228
3253
|
json.type = "boolean";
|
|
3229
3254
|
};
|
|
3255
|
+
const nullProcessor = (_schema, ctx, json, _params) => {
|
|
3256
|
+
if (ctx.target === "openapi-3.0") {
|
|
3257
|
+
json.type = "string";
|
|
3258
|
+
json.nullable = true;
|
|
3259
|
+
json.enum = [null];
|
|
3260
|
+
} else json.type = "null";
|
|
3261
|
+
};
|
|
3230
3262
|
const neverProcessor = (_schema, _ctx, json, _params) => {
|
|
3231
3263
|
json.not = {};
|
|
3232
3264
|
};
|
|
@@ -3926,6 +3958,14 @@ const ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
|
3926
3958
|
function boolean(params) {
|
|
3927
3959
|
return /* @__PURE__ */ _boolean(ZodBoolean, params);
|
|
3928
3960
|
}
|
|
3961
|
+
const ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
3962
|
+
$ZodNull.init(inst, def);
|
|
3963
|
+
ZodType.init(inst, def);
|
|
3964
|
+
inst._zod.processJSONSchema = (ctx, json, params) => nullProcessor(inst, ctx, json, params);
|
|
3965
|
+
});
|
|
3966
|
+
function _null(params) {
|
|
3967
|
+
return /* @__PURE__ */ _null$1(ZodNull, params);
|
|
3968
|
+
}
|
|
3929
3969
|
const ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
3930
3970
|
$ZodUnknown.init(inst, def);
|
|
3931
3971
|
ZodType.init(inst, def);
|
|
@@ -4768,6 +4808,7 @@ const INFRA_SYSTEM_SLUGS = [
|
|
|
4768
4808
|
"health",
|
|
4769
4809
|
"healthcheck",
|
|
4770
4810
|
"healthz",
|
|
4811
|
+
"hook-resume",
|
|
4771
4812
|
"hooks",
|
|
4772
4813
|
"internal",
|
|
4773
4814
|
"item",
|
|
@@ -4933,14 +4974,14 @@ const OrganizationUserRoleSchema = _enum([
|
|
|
4933
4974
|
"admin",
|
|
4934
4975
|
"builder"
|
|
4935
4976
|
]);
|
|
4936
|
-
const isoDateTime$
|
|
4977
|
+
const isoDateTime$7 = string().datetime();
|
|
4937
4978
|
const OrganizationSchema = object({
|
|
4938
4979
|
id: string(),
|
|
4939
4980
|
name: string(),
|
|
4940
4981
|
slug: OrganizationSlugSchema,
|
|
4941
4982
|
verified: boolean(),
|
|
4942
|
-
createdAt: isoDateTime$
|
|
4943
|
-
updatedAt: isoDateTime$
|
|
4983
|
+
createdAt: isoDateTime$7,
|
|
4984
|
+
updatedAt: isoDateTime$7
|
|
4944
4985
|
});
|
|
4945
4986
|
const ProjectSchema = object({
|
|
4946
4987
|
id: string(),
|
|
@@ -4952,8 +4993,8 @@ const ProjectSchema = object({
|
|
|
4952
4993
|
baseUrl: string().nullable(),
|
|
4953
4994
|
runtimeId: string().nullable(),
|
|
4954
4995
|
lastError: string().nullable(),
|
|
4955
|
-
createdAt: isoDateTime$
|
|
4956
|
-
updatedAt: isoDateTime$
|
|
4996
|
+
createdAt: isoDateTime$7,
|
|
4997
|
+
updatedAt: isoDateTime$7
|
|
4957
4998
|
});
|
|
4958
4999
|
object({
|
|
4959
5000
|
organization: OrganizationSchema,
|
|
@@ -4973,7 +5014,7 @@ const ProjectListMetricsSchema = object({
|
|
|
4973
5014
|
workflowCount: number$1(),
|
|
4974
5015
|
skillCount: number$1(),
|
|
4975
5016
|
credentialCount: number$1(),
|
|
4976
|
-
lastDeploymentAt: isoDateTime$
|
|
5017
|
+
lastDeploymentAt: isoDateTime$7.nullable()
|
|
4977
5018
|
});
|
|
4978
5019
|
record(string(), ProjectListMetricsSchema);
|
|
4979
5020
|
object({
|
|
@@ -5328,6 +5369,130 @@ object({
|
|
|
5328
5369
|
skills: array(StoredRouteManifestSkillSchema).default([]),
|
|
5329
5370
|
integrations: array(string()).optional()
|
|
5330
5371
|
});
|
|
5372
|
+
const isoDateTime$6 = string().datetime();
|
|
5373
|
+
const subscriptionStatusSchema = _enum([
|
|
5374
|
+
"none",
|
|
5375
|
+
"trialing",
|
|
5376
|
+
"active",
|
|
5377
|
+
"past_due",
|
|
5378
|
+
"canceled"
|
|
5379
|
+
]);
|
|
5380
|
+
const CreditPackSchema = object({
|
|
5381
|
+
id: string(),
|
|
5382
|
+
usd: number$1(),
|
|
5383
|
+
microCredits: number$1(),
|
|
5384
|
+
label: string()
|
|
5385
|
+
});
|
|
5386
|
+
const AutoTopupSummarySchema = object({
|
|
5387
|
+
enabled: boolean(),
|
|
5388
|
+
thresholdMicroCredits: number$1().nullable(),
|
|
5389
|
+
amountMicroCredits: number$1().nullable(),
|
|
5390
|
+
/** A saved payment method exists to charge off-session. */
|
|
5391
|
+
hasPaymentMethod: boolean(),
|
|
5392
|
+
/** A top-up invoice payment is in flight. */
|
|
5393
|
+
pending: boolean()
|
|
5394
|
+
});
|
|
5395
|
+
/**
|
|
5396
|
+
* The plan's resolved limits. Storage overage is billed from the wallet's
|
|
5397
|
+
* pushed-down `includedStorageGb`; concurrency, per-pass run timeouts, and
|
|
5398
|
+
* API/MCP rate limits are enforced from the wallet (timeouts/concurrency) or
|
|
5399
|
+
* plan preset (rate limits). Log retention is configured but not pruned yet.
|
|
5400
|
+
*/
|
|
5401
|
+
const PlanLimitsSchema = object({
|
|
5402
|
+
includedStorageGb: number$1(),
|
|
5403
|
+
concurrencyLimit: number$1(),
|
|
5404
|
+
agentTimeoutMs: number$1(),
|
|
5405
|
+
workflowTimeoutMs: number$1(),
|
|
5406
|
+
pollTimeoutMs: number$1(),
|
|
5407
|
+
/** Configured retention window; pruning not implemented yet. */
|
|
5408
|
+
logRetentionDays: number$1(),
|
|
5409
|
+
apiRateLimitCapacity: number$1(),
|
|
5410
|
+
apiRateLimitRefillPerSec: number$1(),
|
|
5411
|
+
mcpRateLimitCapacity: number$1(),
|
|
5412
|
+
mcpRateLimitRefillPerSec: number$1()
|
|
5413
|
+
});
|
|
5414
|
+
object({
|
|
5415
|
+
planKey: string(),
|
|
5416
|
+
subscriptionStatus: subscriptionStatusSchema,
|
|
5417
|
+
planCreditMicroCredits: number$1(),
|
|
5418
|
+
prepaidCreditMicroCredits: number$1(),
|
|
5419
|
+
periodStart: isoDateTime$6.nullable(),
|
|
5420
|
+
periodEnd: isoDateTime$6.nullable(),
|
|
5421
|
+
autoTopup: AutoTopupSummarySchema,
|
|
5422
|
+
creditPacks: array(CreditPackSchema),
|
|
5423
|
+
limits: PlanLimitsSchema
|
|
5424
|
+
});
|
|
5425
|
+
const BillingUsageMeterSchema = object({
|
|
5426
|
+
/** Meter key (`llm`, `vm_second`, …); null groups uncategorized rows. */
|
|
5427
|
+
meterKey: string().nullable(),
|
|
5428
|
+
/** Charged this period, µc. */
|
|
5429
|
+
microCredits: number$1(),
|
|
5430
|
+
/** Tracked-but-not-charged usage (e.g. BYOK LLM calls), display USD. */
|
|
5431
|
+
unchargedUsd: number$1()
|
|
5432
|
+
});
|
|
5433
|
+
object({
|
|
5434
|
+
periodStart: isoDateTime$6.nullable(),
|
|
5435
|
+
periodEnd: isoDateTime$6.nullable(),
|
|
5436
|
+
totalMicroCredits: number$1(),
|
|
5437
|
+
byMeter: array(BillingUsageMeterSchema)
|
|
5438
|
+
});
|
|
5439
|
+
const billingLedgerEntryTypeSchema = _enum([
|
|
5440
|
+
"grant_plan",
|
|
5441
|
+
"grant_prepaid",
|
|
5442
|
+
"expire_plan",
|
|
5443
|
+
"adjustment"
|
|
5444
|
+
]);
|
|
5445
|
+
object({
|
|
5446
|
+
entries: array(object({
|
|
5447
|
+
id: string(),
|
|
5448
|
+
entryType: billingLedgerEntryTypeSchema,
|
|
5449
|
+
label: string(),
|
|
5450
|
+
/** Signed: positive grants, negative expirations/adjustments. */
|
|
5451
|
+
microCredits: number$1(),
|
|
5452
|
+
bucket: _enum(["plan", "prepaid"]).nullable(),
|
|
5453
|
+
/** Stripe invoice behind the entry, when there is one — powers "View invoice". */
|
|
5454
|
+
stripeInvoiceId: string().nullable(),
|
|
5455
|
+
createdAt: isoDateTime$6
|
|
5456
|
+
})),
|
|
5457
|
+
/** Set only when the latest payment failure is newer than the latest successful payment. */
|
|
5458
|
+
lastPaymentFailureAt: isoDateTime$6.nullable()
|
|
5459
|
+
});
|
|
5460
|
+
object({
|
|
5461
|
+
/** Web-app path to land on after Checkout (must be a path, not a URL). */
|
|
5462
|
+
returnPath: string().startsWith("/").max(512).optional() });
|
|
5463
|
+
object({
|
|
5464
|
+
packId: string(),
|
|
5465
|
+
returnPath: string().startsWith("/").max(512).optional()
|
|
5466
|
+
});
|
|
5467
|
+
object({ returnPath: string().startsWith("/").max(512).optional() });
|
|
5468
|
+
object({ url: string().url() });
|
|
5469
|
+
object({
|
|
5470
|
+
/** Hosted invoice page (view, download, receipt). */
|
|
5471
|
+
url: string().url(),
|
|
5472
|
+
/** Direct PDF download when Stripe provides one. */
|
|
5473
|
+
pdf: string().url().nullable()
|
|
5474
|
+
});
|
|
5475
|
+
object({
|
|
5476
|
+
/** Stripe Checkout Session id from the `session_id` success-URL param. */
|
|
5477
|
+
sessionId: string().min(1).max(255) });
|
|
5478
|
+
object({
|
|
5479
|
+
/**
|
|
5480
|
+
* `granted` — credits are in the wallet now; `processing` — payment not
|
|
5481
|
+
* complete yet, the webhook will finish it; `ignored` — not a confirmable
|
|
5482
|
+
* session for this org.
|
|
5483
|
+
*/
|
|
5484
|
+
status: _enum([
|
|
5485
|
+
"granted",
|
|
5486
|
+
"processing",
|
|
5487
|
+
"ignored"
|
|
5488
|
+
]),
|
|
5489
|
+
reason: string().optional()
|
|
5490
|
+
});
|
|
5491
|
+
object({
|
|
5492
|
+
enabled: boolean(),
|
|
5493
|
+
thresholdMicroCredits: number$1().int().positive().optional(),
|
|
5494
|
+
packId: string().optional()
|
|
5495
|
+
});
|
|
5331
5496
|
/** Messaging platforms that support agent gateway bindings. */
|
|
5332
5497
|
const ChannelPlatformKeySchema = _enum(["slack"]);
|
|
5333
5498
|
const ChannelReactionSupportSchema = _enum([
|
|
@@ -5848,7 +6013,11 @@ object({
|
|
|
5848
6013
|
isDefault: boolean().optional(),
|
|
5849
6014
|
value: credentialSecretValueSchema.optional()
|
|
5850
6015
|
}).refine((input) => input.label !== void 0 || input.isDefault !== void 0 || input.value !== void 0, { message: "At least one field is required" });
|
|
5851
|
-
const CredentialAssignmentTargetTypeSchema = _enum([
|
|
6016
|
+
const CredentialAssignmentTargetTypeSchema = _enum([
|
|
6017
|
+
"workflow",
|
|
6018
|
+
"agent",
|
|
6019
|
+
"poll"
|
|
6020
|
+
]);
|
|
5852
6021
|
object({ assignments: array(object({
|
|
5853
6022
|
id: string(),
|
|
5854
6023
|
targetType: CredentialAssignmentTargetTypeSchema,
|
|
@@ -5963,7 +6132,11 @@ const ValidationErrorDetailSchema = object({
|
|
|
5963
6132
|
message: string()
|
|
5964
6133
|
});
|
|
5965
6134
|
/** Machine-readable codes returned in standard API error bodies. */
|
|
5966
|
-
const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum([
|
|
6135
|
+
const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum([
|
|
6136
|
+
"needs_org_selection",
|
|
6137
|
+
"org_unverified",
|
|
6138
|
+
"connector_unavailable"
|
|
6139
|
+
]));
|
|
5967
6140
|
object({
|
|
5968
6141
|
error: string(),
|
|
5969
6142
|
code: ErrorResponseCodeSchema.optional(),
|
|
@@ -6074,6 +6247,17 @@ union([
|
|
|
6074
6247
|
SkipResponseSchema,
|
|
6075
6248
|
object({ runId: string() })
|
|
6076
6249
|
]);
|
|
6250
|
+
object({
|
|
6251
|
+
sql: string().min(1),
|
|
6252
|
+
params: array(unknown()).default([]),
|
|
6253
|
+
method: string().min(1).optional()
|
|
6254
|
+
});
|
|
6255
|
+
object({ migrations: array(object({
|
|
6256
|
+
sql: array(string().min(1)),
|
|
6257
|
+
hash: string().min(1),
|
|
6258
|
+
folderMillis: number$1()
|
|
6259
|
+
})) });
|
|
6260
|
+
object({ results: array(object({ rows: array(unknown()) })) });
|
|
6077
6261
|
const RunSourceKindSchema = _enum([
|
|
6078
6262
|
"api",
|
|
6079
6263
|
"trigger",
|
|
@@ -6394,12 +6578,19 @@ const HistoryRunActorSchema = object({
|
|
|
6394
6578
|
const HistoryRunUsageLineItemSchema = object({
|
|
6395
6579
|
id: string(),
|
|
6396
6580
|
label: string(),
|
|
6397
|
-
|
|
6581
|
+
/** Amount debited from the org's Keystroke balance for this line. */
|
|
6582
|
+
billedUsd: number$1(),
|
|
6583
|
+
/** Provider cost for LLM usage on the org's API key (informational; not billed by Keystroke). */
|
|
6584
|
+
providerCostUsd: number$1().nullable().optional(),
|
|
6585
|
+
keySource: _enum(["byok", "platform"]).nullable().optional()
|
|
6398
6586
|
});
|
|
6399
6587
|
const HistoryRunUsageSchema = object({
|
|
6400
6588
|
runDurationMs: number$1().nullable(),
|
|
6401
6589
|
lineItems: array(HistoryRunUsageLineItemSchema),
|
|
6402
|
-
|
|
6590
|
+
/** Sum of `billedUsd` — what Keystroke charged for this run. */
|
|
6591
|
+
totalBilledUsd: number$1().nullable(),
|
|
6592
|
+
/** Sum of BYOK LLM provider costs (billed externally by the org's provider). */
|
|
6593
|
+
externalProviderCostUsd: number$1().nullable().optional()
|
|
6403
6594
|
});
|
|
6404
6595
|
const HistoryRunSchema = object({
|
|
6405
6596
|
id: string(),
|
|
@@ -6530,6 +6721,7 @@ const HistoryRunDetailSchema = discriminatedUnion("kind", [object({
|
|
|
6530
6721
|
attachmentSlug: string().nullable()
|
|
6531
6722
|
}).nullable(),
|
|
6532
6723
|
messages: array(record(string(), unknown())),
|
|
6724
|
+
live: record(string(), unknown()).nullable().default(null),
|
|
6533
6725
|
trace: HistoryTraceSchema.nullable(),
|
|
6534
6726
|
ranAs: HistoryRunActorSchema.nullable().optional(),
|
|
6535
6727
|
usage: HistoryRunUsageSchema.nullable().optional()
|
|
@@ -6819,7 +7011,7 @@ const OrganizationMemberStatusSchema = _enum([
|
|
|
6819
7011
|
"suspended"
|
|
6820
7012
|
]);
|
|
6821
7013
|
const InvitableOrganizationMemberRoleSchema = _enum(["admin", "builder"]);
|
|
6822
|
-
const isoDateTime$
|
|
7014
|
+
const isoDateTime$5 = string().datetime();
|
|
6823
7015
|
object({
|
|
6824
7016
|
id: string(),
|
|
6825
7017
|
name: string(),
|
|
@@ -6827,8 +7019,8 @@ object({
|
|
|
6827
7019
|
role: OrganizationMemberRoleSchema,
|
|
6828
7020
|
status: OrganizationMemberStatusSchema,
|
|
6829
7021
|
avatarUrl: string().optional(),
|
|
6830
|
-
joinedAt: isoDateTime$
|
|
6831
|
-
lastActiveAt: isoDateTime$
|
|
7022
|
+
joinedAt: isoDateTime$5.optional(),
|
|
7023
|
+
lastActiveAt: isoDateTime$5.nullable().optional()
|
|
6832
7024
|
});
|
|
6833
7025
|
object({
|
|
6834
7026
|
emails: array(string().trim().email()).min(1),
|
|
@@ -6855,7 +7047,7 @@ object({
|
|
|
6855
7047
|
role: OrganizationMemberRoleSchema
|
|
6856
7048
|
});
|
|
6857
7049
|
object({ success: literal(true) });
|
|
6858
|
-
const isoDateTime$
|
|
7050
|
+
const isoDateTime$4 = string().datetime();
|
|
6859
7051
|
const ApiKeyCreatorSchema = object({
|
|
6860
7052
|
id: string(),
|
|
6861
7053
|
name: string(),
|
|
@@ -6868,12 +7060,37 @@ const ApiKeySummarySchema = object({
|
|
|
6868
7060
|
id: string(),
|
|
6869
7061
|
name: string(),
|
|
6870
7062
|
keyPreview: string(),
|
|
6871
|
-
createdAt: isoDateTime$
|
|
7063
|
+
createdAt: isoDateTime$4,
|
|
6872
7064
|
createdBy: ApiKeyCreatorSchema,
|
|
6873
7065
|
isCreatedByCurrentUser: boolean()
|
|
6874
7066
|
});
|
|
6875
7067
|
object({ name: string().trim().min(1).max(128) });
|
|
6876
7068
|
ApiKeySummarySchema.extend({ secret: string() });
|
|
7069
|
+
const isoDateTime$3 = string().datetime();
|
|
7070
|
+
const ManagedServiceKindSchema = _enum(["llm"]);
|
|
7071
|
+
_enum([
|
|
7072
|
+
"openai",
|
|
7073
|
+
"anthropic",
|
|
7074
|
+
"google",
|
|
7075
|
+
"groq",
|
|
7076
|
+
"xai"
|
|
7077
|
+
]);
|
|
7078
|
+
object({
|
|
7079
|
+
id: string(),
|
|
7080
|
+
kind: ManagedServiceKindSchema,
|
|
7081
|
+
provider: string(),
|
|
7082
|
+
keyPreview: string(),
|
|
7083
|
+
createdAt: isoDateTime$3,
|
|
7084
|
+
updatedAt: isoDateTime$3,
|
|
7085
|
+
createdBy: ApiKeyCreatorSchema,
|
|
7086
|
+
isCreatedByCurrentUser: boolean()
|
|
7087
|
+
});
|
|
7088
|
+
object({
|
|
7089
|
+
kind: ManagedServiceKindSchema.default("llm"),
|
|
7090
|
+
provider: string().trim().min(1),
|
|
7091
|
+
apiKey: string().trim().min(1)
|
|
7092
|
+
});
|
|
7093
|
+
object({ apiKey: string().trim().min(1) });
|
|
6877
7094
|
const ProjectUserRoleSchema = _enum(["admin", "builder"]);
|
|
6878
7095
|
const ProjectInvitePermissionSchema = _enum(["admin", "all"]);
|
|
6879
7096
|
const ProjectMemberStatusSchema = _enum(["active", "invited"]);
|
|
@@ -6923,6 +7140,14 @@ object({
|
|
|
6923
7140
|
uploadUrl: url(),
|
|
6924
7141
|
storageKey: string().min(1)
|
|
6925
7142
|
});
|
|
7143
|
+
function isValidIanaTimezone(value) {
|
|
7144
|
+
try {
|
|
7145
|
+
Intl.DateTimeFormat(void 0, { timeZone: value });
|
|
7146
|
+
return true;
|
|
7147
|
+
} catch {
|
|
7148
|
+
return false;
|
|
7149
|
+
}
|
|
7150
|
+
}
|
|
6926
7151
|
const UserInterfaceThemeSchema = _enum([
|
|
6927
7152
|
"system",
|
|
6928
7153
|
"light",
|
|
@@ -6942,22 +7167,25 @@ const UserWorkspaceFavoriteSchema = object({
|
|
|
6942
7167
|
]),
|
|
6943
7168
|
resourceId: string().min(1)
|
|
6944
7169
|
});
|
|
7170
|
+
const UserSidebarPreferencesSchema = object({
|
|
7171
|
+
navIconVisibility: UserSidebarNavIconVisibilitySchema,
|
|
7172
|
+
footerChatRowVisibility: UserSidebarFooterChatRowVisibilitySchema,
|
|
7173
|
+
hiddenNavItemIds: array(string()),
|
|
7174
|
+
topNavItemOrderIds: array(string()),
|
|
7175
|
+
workspaceNavItemOrderIds: array(string())
|
|
7176
|
+
});
|
|
7177
|
+
const UserTimezoneSchema = string().refine(isValidIanaTimezone, { message: "Invalid IANA timezone" });
|
|
6945
7178
|
object({
|
|
6946
7179
|
interfaceTheme: UserInterfaceThemeSchema,
|
|
6947
7180
|
surfaceContrast: UserSurfaceContrastSchema,
|
|
6948
7181
|
layoutMode: UserWorkspaceLayoutModeSchema,
|
|
6949
7182
|
fontSize: UserWorkspaceFontSizeSchema,
|
|
6950
|
-
sidebar:
|
|
6951
|
-
navIconVisibility: UserSidebarNavIconVisibilitySchema,
|
|
6952
|
-
footerChatRowVisibility: UserSidebarFooterChatRowVisibilitySchema,
|
|
6953
|
-
hiddenNavItemIds: array(string()),
|
|
6954
|
-
topNavItemOrderIds: array(string()),
|
|
6955
|
-
workspaceNavItemOrderIds: array(string())
|
|
6956
|
-
}),
|
|
7183
|
+
sidebar: UserSidebarPreferencesSchema,
|
|
6957
7184
|
favorites: array(UserWorkspaceFavoriteSchema),
|
|
6958
7185
|
projectOrderIds: array(string()),
|
|
6959
7186
|
projectDotColors: record(string(), string()),
|
|
6960
|
-
onboardingTabVisible: boolean()
|
|
7187
|
+
onboardingTabVisible: boolean(),
|
|
7188
|
+
timezone: union([UserTimezoneSchema, _null()])
|
|
6961
7189
|
});
|
|
6962
7190
|
const UserSidebarPreferencesPatchSchema = object({
|
|
6963
7191
|
navIconVisibility: UserSidebarNavIconVisibilitySchema.optional(),
|
|
@@ -6975,8 +7203,9 @@ object({
|
|
|
6975
7203
|
favorites: array(UserWorkspaceFavoriteSchema).optional(),
|
|
6976
7204
|
projectOrderIds: array(string()).optional(),
|
|
6977
7205
|
projectDotColors: record(string(), string()).optional(),
|
|
6978
|
-
onboardingTabVisible: boolean().optional()
|
|
6979
|
-
|
|
7206
|
+
onboardingTabVisible: boolean().optional(),
|
|
7207
|
+
timezone: union([UserTimezoneSchema, _null()]).optional()
|
|
7208
|
+
}).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" });
|
|
6980
7209
|
const OrganizationLogoVariantSchema = _enum(["light", "dark"]);
|
|
6981
7210
|
object({
|
|
6982
7211
|
customLogoEnabled: boolean(),
|
|
@@ -7439,13 +7668,35 @@ function parseOrgArtifactsFromEnv(env = process.env) {
|
|
|
7439
7668
|
});
|
|
7440
7669
|
}
|
|
7441
7670
|
//#endregion
|
|
7671
|
+
//#region src/org-worker-token.ts
|
|
7672
|
+
function sign(secret, organizationId) {
|
|
7673
|
+
return createHmac("sha256", secret).update(`org-worker:${organizationId}`).digest("base64url");
|
|
7674
|
+
}
|
|
7675
|
+
/**
|
|
7676
|
+
* Per-org worker token: `{organizationId}.{hmac}`. Self-describing so the
|
|
7677
|
+
* platform can tell which org a machine is calling as, and stateless — verified
|
|
7678
|
+
* by re-signing with the shared `PLATFORM_WORKER_TOKEN` secret.
|
|
7679
|
+
*/
|
|
7680
|
+
function mintOrgWorkerToken(secret, organizationId) {
|
|
7681
|
+
return `${organizationId}.${sign(secret, organizationId)}`;
|
|
7682
|
+
}
|
|
7683
|
+
function verifyOrgWorkerToken(secret, token) {
|
|
7684
|
+
if (!secret || !token) return;
|
|
7685
|
+
const separator = token.lastIndexOf(".");
|
|
7686
|
+
if (separator <= 0) return;
|
|
7687
|
+
const organizationId = token.slice(0, separator);
|
|
7688
|
+
const signature = Buffer.from(token.slice(separator + 1));
|
|
7689
|
+
const expected = Buffer.from(sign(secret, organizationId));
|
|
7690
|
+
if (signature.length !== expected.length || !timingSafeEqual(signature, expected)) return;
|
|
7691
|
+
return { organizationId };
|
|
7692
|
+
}
|
|
7693
|
+
//#endregion
|
|
7442
7694
|
//#region src/runtime-env.ts
|
|
7443
7695
|
const RUNTIME_ENV_KEYS = [
|
|
7444
7696
|
"BETTER_AUTH_SECRET",
|
|
7445
7697
|
"PUBLIC_PLATFORM_URL",
|
|
7446
7698
|
"PUBLIC_PLATFORM_PROXY_URL",
|
|
7447
7699
|
"PUBLIC_WEB_URL",
|
|
7448
|
-
"POSTGRES_SSL",
|
|
7449
7700
|
"UPSTASH_REDIS_URL",
|
|
7450
7701
|
"REDIS_URL",
|
|
7451
7702
|
"KEYSTROKE_QUEUE_PREFIX"
|
|
@@ -7459,25 +7710,6 @@ const PROVIDER_ENV_KEYS = [
|
|
|
7459
7710
|
];
|
|
7460
7711
|
/** Shared dev token when `PLATFORM_WORKER_TOKEN` is unset (non-production only). */
|
|
7461
7712
|
const DEV_PLATFORM_WORKER_TOKEN = "dev-platform-worker-token";
|
|
7462
|
-
const PROJECT_DATABASE_ENV_KEYS = [
|
|
7463
|
-
"POSTGRES_HOST",
|
|
7464
|
-
"POSTGRES_PORT",
|
|
7465
|
-
"POSTGRES_DB",
|
|
7466
|
-
"POSTGRES_USER",
|
|
7467
|
-
"POSTGRES_PASSWORD",
|
|
7468
|
-
"DATABASE_SEARCH_PATH"
|
|
7469
|
-
];
|
|
7470
|
-
/** Per-project postgres env injected into every project server container/machine. */
|
|
7471
|
-
function projectDatabaseRuntimeEnv(database) {
|
|
7472
|
-
return {
|
|
7473
|
-
POSTGRES_HOST: rewriteLoopbackHost(database.host),
|
|
7474
|
-
POSTGRES_PORT: String(database.port),
|
|
7475
|
-
POSTGRES_DB: database.database,
|
|
7476
|
-
POSTGRES_USER: database.user,
|
|
7477
|
-
POSTGRES_PASSWORD: database.password,
|
|
7478
|
-
DATABASE_SEARCH_PATH: database.searchPath
|
|
7479
|
-
};
|
|
7480
|
-
}
|
|
7481
7713
|
/**
|
|
7482
7714
|
* Builds the launch spec for an org worker. Each deploy artifact is encoded in
|
|
7483
7715
|
* `KEYSTROKE_ORG_ARTIFACTS` — there is no base image, so at least one artifact is required.
|
|
@@ -7504,10 +7736,7 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
|
|
|
7504
7736
|
]);
|
|
7505
7737
|
for (const key of RUNTIME_ENV_KEYS) {
|
|
7506
7738
|
const value = source[key]?.trim();
|
|
7507
|
-
if (!value)
|
|
7508
|
-
if (key === "POSTGRES_SSL") throw new Error("POSTGRES_SSL is required");
|
|
7509
|
-
continue;
|
|
7510
|
-
}
|
|
7739
|
+
if (!value) continue;
|
|
7511
7740
|
entries.set(key, value);
|
|
7512
7741
|
}
|
|
7513
7742
|
if (!extraEnv) for (const key of PROVIDER_ENV_KEYS) {
|
|
@@ -7516,8 +7745,7 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
|
|
|
7516
7745
|
}
|
|
7517
7746
|
const worker = resolveWorkerRuntimeConfig(source);
|
|
7518
7747
|
entries.set("PLATFORM_URL", worker.platformUrl);
|
|
7519
|
-
entries.set("WORKER_INTERNAL_TOKEN", worker.workerToken);
|
|
7520
|
-
for (const [key, value] of Object.entries(projectDatabaseRuntimeEnv(database))) entries.set(key, value);
|
|
7748
|
+
entries.set("WORKER_INTERNAL_TOKEN", mintOrgWorkerToken(worker.workerToken, database.organizationId));
|
|
7521
7749
|
if (extraEnv) for (const [key, value] of Object.entries(extraEnv)) entries.set(key, value);
|
|
7522
7750
|
return Object.fromEntries(entries);
|
|
7523
7751
|
}
|
|
@@ -7605,55 +7833,63 @@ function sleep(ms) {
|
|
|
7605
7833
|
const MINIO_DOCKER_NETWORK = process.env.MINIO_DOCKER_NETWORK ?? "keystroke";
|
|
7606
7834
|
function createDockerRuntime(options = {}) {
|
|
7607
7835
|
const docker = options.docker ?? new Docker();
|
|
7608
|
-
return {
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7836
|
+
return {
|
|
7837
|
+
async start(input) {
|
|
7838
|
+
if (input.projects.length === 0) throw new Error("Docker org runtime requires at least one project deploy");
|
|
7839
|
+
let launch = resolveRuntimeLaunch(options, input.projects.map((project) => ({
|
|
7840
|
+
projectId: project.projectId,
|
|
7841
|
+
artifactStorageKey: project.artifactStorageKey
|
|
7842
|
+
})), input.database, input.env);
|
|
7843
|
+
if (options.workspacesMount) {
|
|
7844
|
+
const { hostPath, containerPath } = options.workspacesMount;
|
|
7845
|
+
await mkdir(hostPath, { recursive: true });
|
|
7846
|
+
launch = {
|
|
7847
|
+
...launch,
|
|
7848
|
+
env: {
|
|
7849
|
+
...launch.env,
|
|
7850
|
+
KEYSTROKE_WORKSPACES_ROOT: containerPath
|
|
7851
|
+
}
|
|
7852
|
+
};
|
|
7853
|
+
}
|
|
7854
|
+
await ensureImage(docker, launch.image);
|
|
7855
|
+
await removeExistingContainer(docker, input.organizationId);
|
|
7856
|
+
const binds = [...options.workspacesMount ? [`${options.workspacesMount.hostPath}:${options.workspacesMount.containerPath}`] : [], ...options.extraBinds ?? []];
|
|
7857
|
+
const container = await docker.createContainer({
|
|
7858
|
+
Image: launch.image,
|
|
7859
|
+
name: containerName(input.organizationId),
|
|
7860
|
+
Labels: {
|
|
7861
|
+
"keystroke.organization.id": input.organizationId,
|
|
7862
|
+
"keystroke.project.ids": input.projects.map((project) => project.projectId).join(",")
|
|
7863
|
+
},
|
|
7864
|
+
ExposedPorts: { [`${launch.port}/tcp`]: {} },
|
|
7865
|
+
HostConfig: {
|
|
7866
|
+
ExtraHosts: ["host.docker.internal:host-gateway"],
|
|
7867
|
+
PortBindings: { [`${launch.port}/tcp`]: [{ HostPort: "0" }] },
|
|
7868
|
+
...binds.length > 0 ? { Binds: binds } : {}
|
|
7869
|
+
},
|
|
7870
|
+
NetworkingConfig: { EndpointsConfig: { [MINIO_DOCKER_NETWORK]: {} } },
|
|
7871
|
+
Env: formatDockerEnv(launch.env)
|
|
7872
|
+
});
|
|
7873
|
+
await container.start();
|
|
7874
|
+
const inspect = await container.inspect();
|
|
7875
|
+
const binding = inspect.NetworkSettings.Ports?.[`${launch.port}/tcp`]?.[0];
|
|
7876
|
+
if (!binding?.HostPort) throw new Error("Failed to resolve org container host port");
|
|
7877
|
+
const baseUrl = `http://127.0.0.1:${binding.HostPort}`;
|
|
7878
|
+
await waitForHealth(baseUrl, {
|
|
7879
|
+
fetchImpl: options.fetchImpl,
|
|
7880
|
+
timeoutMs: options.healthTimeoutMs
|
|
7881
|
+
});
|
|
7882
|
+
return {
|
|
7883
|
+
runtimeId: inspect.Id,
|
|
7884
|
+
baseUrl
|
|
7623
7885
|
};
|
|
7886
|
+
},
|
|
7887
|
+
async destroy(input) {
|
|
7888
|
+
try {
|
|
7889
|
+
await docker.getContainer(input.runtimeId).remove({ force: true });
|
|
7890
|
+
} catch {}
|
|
7624
7891
|
}
|
|
7625
|
-
|
|
7626
|
-
await removeExistingContainer(docker, input.organizationId);
|
|
7627
|
-
const container = await docker.createContainer({
|
|
7628
|
-
Image: launch.image,
|
|
7629
|
-
name: containerName(input.organizationId),
|
|
7630
|
-
Labels: {
|
|
7631
|
-
"keystroke.organization.id": input.organizationId,
|
|
7632
|
-
"keystroke.project.ids": input.projects.map((project) => project.projectId).join(",")
|
|
7633
|
-
},
|
|
7634
|
-
ExposedPorts: { [`${launch.port}/tcp`]: {} },
|
|
7635
|
-
HostConfig: {
|
|
7636
|
-
ExtraHosts: ["host.docker.internal:host-gateway"],
|
|
7637
|
-
PortBindings: { [`${launch.port}/tcp`]: [{ HostPort: "0" }] },
|
|
7638
|
-
...options.workspacesMount ? { Binds: [`${options.workspacesMount.hostPath}:${options.workspacesMount.containerPath}`] } : {}
|
|
7639
|
-
},
|
|
7640
|
-
NetworkingConfig: { EndpointsConfig: { [MINIO_DOCKER_NETWORK]: {} } },
|
|
7641
|
-
Env: formatDockerEnv(launch.env)
|
|
7642
|
-
});
|
|
7643
|
-
await container.start();
|
|
7644
|
-
const inspect = await container.inspect();
|
|
7645
|
-
const binding = inspect.NetworkSettings.Ports?.[`${launch.port}/tcp`]?.[0];
|
|
7646
|
-
if (!binding?.HostPort) throw new Error("Failed to resolve org container host port");
|
|
7647
|
-
const baseUrl = `http://127.0.0.1:${binding.HostPort}`;
|
|
7648
|
-
await waitForHealth(baseUrl, {
|
|
7649
|
-
fetchImpl: options.fetchImpl,
|
|
7650
|
-
timeoutMs: options.healthTimeoutMs
|
|
7651
|
-
});
|
|
7652
|
-
return {
|
|
7653
|
-
runtimeId: inspect.Id,
|
|
7654
|
-
baseUrl
|
|
7655
|
-
};
|
|
7656
|
-
} };
|
|
7892
|
+
};
|
|
7657
7893
|
}
|
|
7658
7894
|
function containerName(organizationId) {
|
|
7659
7895
|
return `keystroke-org-${organizationId}`;
|
|
@@ -7761,6 +7997,6 @@ async function fetchDeployStatus(baseUrl, options = {}) {
|
|
|
7761
7997
|
}
|
|
7762
7998
|
}
|
|
7763
7999
|
//#endregion
|
|
7764
|
-
export { DEV_PLATFORM_WORKER_TOKEN,
|
|
8000
|
+
export { DEV_PLATFORM_WORKER_TOKEN, PROJECT_SERVER_DEPLOY_STATUS, PROJECT_SERVER_FRAMEWORK_NODE_MODULES, PROJECT_SERVER_FRAMEWORK_ROOT, PROJECT_SERVER_HEALTH, PROJECT_SERVER_IMAGE, PROJECT_SERVER_PORT, PROJECT_SERVER_ROOT, RUNTIME_PING_TIMEOUT_MS, WorkerRuntimeConfigError, buildRuntimeEnv, canPingProjectTarget, defaultHostingPlugin, dockerPlugin, encodeOrgArtifacts, fetchDeployStatus, formatDockerEnv, mintOrgWorkerToken, parseOrgArtifactsFromEnv, pingProject, pingProjectTarget, resolvePlatformWorkerToken, resolveProjectServerImage, resolveRuntimeLaunch, resolveWorkerPlatformUrl, resolveWorkerRuntimeConfig, rewriteLoopbackHost, rewriteLoopbackUrl, verifyOrgWorkerToken, waitForHealth };
|
|
7765
8001
|
|
|
7766
8002
|
//# sourceMappingURL=index.mjs.map
|