@keystrokehq/hosting 0.1.10 → 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 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");
@@ -4831,6 +4832,7 @@ const INFRA_SYSTEM_SLUGS = [
4831
4832
  "health",
4832
4833
  "healthcheck",
4833
4834
  "healthz",
4835
+ "hook-resume",
4834
4836
  "hooks",
4835
4837
  "internal",
4836
4838
  "item",
@@ -4996,14 +4998,14 @@ const OrganizationUserRoleSchema = _enum([
4996
4998
  "admin",
4997
4999
  "builder"
4998
5000
  ]);
4999
- const isoDateTime$5 = string().datetime();
5001
+ const isoDateTime$7 = string().datetime();
5000
5002
  const OrganizationSchema = object({
5001
5003
  id: string(),
5002
5004
  name: string(),
5003
5005
  slug: OrganizationSlugSchema,
5004
5006
  verified: boolean(),
5005
- createdAt: isoDateTime$5,
5006
- updatedAt: isoDateTime$5
5007
+ createdAt: isoDateTime$7,
5008
+ updatedAt: isoDateTime$7
5007
5009
  });
5008
5010
  const ProjectSchema = object({
5009
5011
  id: string(),
@@ -5015,8 +5017,8 @@ const ProjectSchema = object({
5015
5017
  baseUrl: string().nullable(),
5016
5018
  runtimeId: string().nullable(),
5017
5019
  lastError: string().nullable(),
5018
- createdAt: isoDateTime$5,
5019
- updatedAt: isoDateTime$5
5020
+ createdAt: isoDateTime$7,
5021
+ updatedAt: isoDateTime$7
5020
5022
  });
5021
5023
  object({
5022
5024
  organization: OrganizationSchema,
@@ -5036,7 +5038,7 @@ const ProjectListMetricsSchema = object({
5036
5038
  workflowCount: number$1(),
5037
5039
  skillCount: number$1(),
5038
5040
  credentialCount: number$1(),
5039
- lastDeploymentAt: isoDateTime$5.nullable()
5041
+ lastDeploymentAt: isoDateTime$7.nullable()
5040
5042
  });
5041
5043
  record(string(), ProjectListMetricsSchema);
5042
5044
  object({
@@ -5391,6 +5393,130 @@ object({
5391
5393
  skills: array(StoredRouteManifestSkillSchema).default([]),
5392
5394
  integrations: array(string()).optional()
5393
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
+ });
5394
5520
  /** Messaging platforms that support agent gateway bindings. */
5395
5521
  const ChannelPlatformKeySchema = _enum(["slack"]);
5396
5522
  const ChannelReactionSupportSchema = _enum([
@@ -5911,7 +6037,11 @@ object({
5911
6037
  isDefault: boolean().optional(),
5912
6038
  value: credentialSecretValueSchema.optional()
5913
6039
  }).refine((input) => input.label !== void 0 || input.isDefault !== void 0 || input.value !== void 0, { message: "At least one field is required" });
5914
- const CredentialAssignmentTargetTypeSchema = _enum(["workflow", "agent"]);
6040
+ const CredentialAssignmentTargetTypeSchema = _enum([
6041
+ "workflow",
6042
+ "agent",
6043
+ "poll"
6044
+ ]);
5915
6045
  object({ assignments: array(object({
5916
6046
  id: string(),
5917
6047
  targetType: CredentialAssignmentTargetTypeSchema,
@@ -6026,7 +6156,11 @@ const ValidationErrorDetailSchema = object({
6026
6156
  message: string()
6027
6157
  });
6028
6158
  /** Machine-readable codes returned in standard API error bodies. */
6029
- const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum(["needs_org_selection", "org_unverified"]));
6159
+ const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum([
6160
+ "needs_org_selection",
6161
+ "org_unverified",
6162
+ "connector_unavailable"
6163
+ ]));
6030
6164
  object({
6031
6165
  error: string(),
6032
6166
  code: ErrorResponseCodeSchema.optional(),
@@ -6137,6 +6271,17 @@ union([
6137
6271
  SkipResponseSchema,
6138
6272
  object({ runId: string() })
6139
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()) })) });
6140
6285
  const RunSourceKindSchema = _enum([
6141
6286
  "api",
6142
6287
  "trigger",
@@ -6457,12 +6602,19 @@ const HistoryRunActorSchema = object({
6457
6602
  const HistoryRunUsageLineItemSchema = object({
6458
6603
  id: string(),
6459
6604
  label: string(),
6460
- amountUsd: number$1()
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()
6461
6610
  });
6462
6611
  const HistoryRunUsageSchema = object({
6463
6612
  runDurationMs: number$1().nullable(),
6464
6613
  lineItems: array(HistoryRunUsageLineItemSchema),
6465
- totalExcludingDurationUsd: number$1().nullable()
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()
6466
6618
  });
6467
6619
  const HistoryRunSchema = object({
6468
6620
  id: string(),
@@ -6593,6 +6745,7 @@ const HistoryRunDetailSchema = discriminatedUnion("kind", [object({
6593
6745
  attachmentSlug: string().nullable()
6594
6746
  }).nullable(),
6595
6747
  messages: array(record(string(), unknown())),
6748
+ live: record(string(), unknown()).nullable().default(null),
6596
6749
  trace: HistoryTraceSchema.nullable(),
6597
6750
  ranAs: HistoryRunActorSchema.nullable().optional(),
6598
6751
  usage: HistoryRunUsageSchema.nullable().optional()
@@ -6882,7 +7035,7 @@ const OrganizationMemberStatusSchema = _enum([
6882
7035
  "suspended"
6883
7036
  ]);
6884
7037
  const InvitableOrganizationMemberRoleSchema = _enum(["admin", "builder"]);
6885
- const isoDateTime$4 = string().datetime();
7038
+ const isoDateTime$5 = string().datetime();
6886
7039
  object({
6887
7040
  id: string(),
6888
7041
  name: string(),
@@ -6890,8 +7043,8 @@ object({
6890
7043
  role: OrganizationMemberRoleSchema,
6891
7044
  status: OrganizationMemberStatusSchema,
6892
7045
  avatarUrl: string().optional(),
6893
- joinedAt: isoDateTime$4.optional(),
6894
- lastActiveAt: isoDateTime$4.nullable().optional()
7046
+ joinedAt: isoDateTime$5.optional(),
7047
+ lastActiveAt: isoDateTime$5.nullable().optional()
6895
7048
  });
6896
7049
  object({
6897
7050
  emails: array(string().trim().email()).min(1),
@@ -6918,7 +7071,7 @@ object({
6918
7071
  role: OrganizationMemberRoleSchema
6919
7072
  });
6920
7073
  object({ success: literal(true) });
6921
- const isoDateTime$3 = string().datetime();
7074
+ const isoDateTime$4 = string().datetime();
6922
7075
  const ApiKeyCreatorSchema = object({
6923
7076
  id: string(),
6924
7077
  name: string(),
@@ -6931,12 +7084,37 @@ const ApiKeySummarySchema = object({
6931
7084
  id: string(),
6932
7085
  name: string(),
6933
7086
  keyPreview: string(),
6934
- createdAt: isoDateTime$3,
7087
+ createdAt: isoDateTime$4,
6935
7088
  createdBy: ApiKeyCreatorSchema,
6936
7089
  isCreatedByCurrentUser: boolean()
6937
7090
  });
6938
7091
  object({ name: string().trim().min(1).max(128) });
6939
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) });
6940
7118
  const ProjectUserRoleSchema = _enum(["admin", "builder"]);
6941
7119
  const ProjectInvitePermissionSchema = _enum(["admin", "all"]);
6942
7120
  const ProjectMemberStatusSchema = _enum(["active", "invited"]);
@@ -7514,13 +7692,35 @@ function parseOrgArtifactsFromEnv(env = process.env) {
7514
7692
  });
7515
7693
  }
7516
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
7517
7718
  //#region src/runtime-env.ts
7518
7719
  const RUNTIME_ENV_KEYS = [
7519
7720
  "BETTER_AUTH_SECRET",
7520
7721
  "PUBLIC_PLATFORM_URL",
7521
7722
  "PUBLIC_PLATFORM_PROXY_URL",
7522
7723
  "PUBLIC_WEB_URL",
7523
- "POSTGRES_SSL",
7524
7724
  "UPSTASH_REDIS_URL",
7525
7725
  "REDIS_URL",
7526
7726
  "KEYSTROKE_QUEUE_PREFIX"
@@ -7534,25 +7734,6 @@ const PROVIDER_ENV_KEYS = [
7534
7734
  ];
7535
7735
  /** Shared dev token when `PLATFORM_WORKER_TOKEN` is unset (non-production only). */
7536
7736
  const DEV_PLATFORM_WORKER_TOKEN = "dev-platform-worker-token";
7537
- const PROJECT_DATABASE_ENV_KEYS = [
7538
- "POSTGRES_HOST",
7539
- "POSTGRES_PORT",
7540
- "POSTGRES_DB",
7541
- "POSTGRES_USER",
7542
- "POSTGRES_PASSWORD",
7543
- "DATABASE_SEARCH_PATH"
7544
- ];
7545
- /** Per-project postgres env injected into every project server container/machine. */
7546
- function projectDatabaseRuntimeEnv(database) {
7547
- return {
7548
- POSTGRES_HOST: rewriteLoopbackHost(database.host),
7549
- POSTGRES_PORT: String(database.port),
7550
- POSTGRES_DB: database.database,
7551
- POSTGRES_USER: database.user,
7552
- POSTGRES_PASSWORD: database.password,
7553
- DATABASE_SEARCH_PATH: database.searchPath
7554
- };
7555
- }
7556
7737
  /**
7557
7738
  * Builds the launch spec for an org worker. Each deploy artifact is encoded in
7558
7739
  * `KEYSTROKE_ORG_ARTIFACTS` — there is no base image, so at least one artifact is required.
@@ -7579,10 +7760,7 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
7579
7760
  ]);
7580
7761
  for (const key of RUNTIME_ENV_KEYS) {
7581
7762
  const value = source[key]?.trim();
7582
- if (!value) {
7583
- if (key === "POSTGRES_SSL") throw new Error("POSTGRES_SSL is required");
7584
- continue;
7585
- }
7763
+ if (!value) continue;
7586
7764
  entries.set(key, value);
7587
7765
  }
7588
7766
  if (!extraEnv) for (const key of PROVIDER_ENV_KEYS) {
@@ -7591,8 +7769,7 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
7591
7769
  }
7592
7770
  const worker = resolveWorkerRuntimeConfig(source);
7593
7771
  entries.set("PLATFORM_URL", worker.platformUrl);
7594
- entries.set("WORKER_INTERNAL_TOKEN", worker.workerToken);
7595
- for (const [key, value] of Object.entries(projectDatabaseRuntimeEnv(database))) entries.set(key, value);
7772
+ entries.set("WORKER_INTERNAL_TOKEN", mintOrgWorkerToken(worker.workerToken, database.organizationId));
7596
7773
  if (extraEnv) for (const [key, value] of Object.entries(extraEnv)) entries.set(key, value);
7597
7774
  return Object.fromEntries(entries);
7598
7775
  }
@@ -7845,7 +8022,6 @@ async function fetchDeployStatus(baseUrl, options = {}) {
7845
8022
  }
7846
8023
  //#endregion
7847
8024
  exports.DEV_PLATFORM_WORKER_TOKEN = DEV_PLATFORM_WORKER_TOKEN;
7848
- exports.PROJECT_DATABASE_ENV_KEYS = PROJECT_DATABASE_ENV_KEYS;
7849
8025
  exports.PROJECT_SERVER_DEPLOY_STATUS = PROJECT_SERVER_DEPLOY_STATUS;
7850
8026
  exports.PROJECT_SERVER_FRAMEWORK_NODE_MODULES = PROJECT_SERVER_FRAMEWORK_NODE_MODULES;
7851
8027
  exports.PROJECT_SERVER_FRAMEWORK_ROOT = PROJECT_SERVER_FRAMEWORK_ROOT;
@@ -7862,10 +8038,10 @@ exports.dockerPlugin = dockerPlugin;
7862
8038
  exports.encodeOrgArtifacts = encodeOrgArtifacts;
7863
8039
  exports.fetchDeployStatus = fetchDeployStatus;
7864
8040
  exports.formatDockerEnv = formatDockerEnv;
8041
+ exports.mintOrgWorkerToken = mintOrgWorkerToken;
7865
8042
  exports.parseOrgArtifactsFromEnv = parseOrgArtifactsFromEnv;
7866
8043
  exports.pingProject = pingProject;
7867
8044
  exports.pingProjectTarget = pingProjectTarget;
7868
- exports.projectDatabaseRuntimeEnv = projectDatabaseRuntimeEnv;
7869
8045
  exports.resolvePlatformWorkerToken = resolvePlatformWorkerToken;
7870
8046
  exports.resolveProjectServerImage = resolveProjectServerImage;
7871
8047
  exports.resolveRuntimeLaunch = resolveRuntimeLaunch;
@@ -7873,6 +8049,7 @@ exports.resolveWorkerPlatformUrl = resolveWorkerPlatformUrl;
7873
8049
  exports.resolveWorkerRuntimeConfig = resolveWorkerRuntimeConfig;
7874
8050
  exports.rewriteLoopbackHost = rewriteLoopbackHost;
7875
8051
  exports.rewriteLoopbackUrl = rewriteLoopbackUrl;
8052
+ exports.verifyOrgWorkerToken = verifyOrgWorkerToken;
7876
8053
  exports.waitForHealth = waitForHealth;
7877
8054
 
7878
8055
  //# sourceMappingURL=index.cjs.map