void 0.20.1 → 0.20.2

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.
Files changed (87) hide show
  1. package/README.md +5 -1
  2. package/dist/{auth-W9WII-mN.mjs → auth-DPl6kck4.mjs} +46 -26
  3. package/dist/{auth-cmd-CAH62yDU.mjs → auth-cmd-gniL2fNt.mjs} +5 -4
  4. package/dist/auth-link-NZdjCmSc.mjs +28 -0
  5. package/dist/{build-cmd-CJvZvPQO.mjs → build-cmd-sI18tX_O.mjs} +3 -3
  6. package/dist/{cache-BlNeQjuP.mjs → cache-IHn5MwBC.mjs} +3 -3
  7. package/dist/{cancel-deploy-CmlAZ9P6.mjs → cancel-deploy-C5qTOdLi.mjs} +3 -3
  8. package/dist/cf-access-DRsQRe6k.mjs +75 -0
  9. package/dist/cli/cli.mjs +308 -1958
  10. package/dist/cli/env-schema-probe.mjs +11 -2
  11. package/dist/{client-Clirrol3.mjs → client-dHfSJvAN.mjs} +300 -81
  12. package/dist/{cloudflare-auth-B1QtTO1b.mjs → cloudflare-auth-6M5llVPC.mjs} +2 -2
  13. package/dist/{cloudflare-cmd-B6_OZx2V.mjs → cloudflare-cmd-4RPGN3KB.mjs} +2 -2
  14. package/dist/{cloudflare-connect-j5D4hhrG.mjs → cloudflare-connect-t1UU5svD.mjs} +2 -2
  15. package/dist/{cloudflare-operations-CPTpRW6d.mjs → cloudflare-operations-BzWnlC1_.mjs} +1 -1
  16. package/dist/{config-BQFq7QvD.mjs → config-uNGuFsI2.mjs} +1 -1
  17. package/dist/{connect-C04Wdy_h.mjs → connect-Bfk31O_8.mjs} +6 -6
  18. package/dist/{create-project-ChGZ1DFd.mjs → create-project-Bk9Z0-Jg.mjs} +6 -5
  19. package/dist/{db-D2d_mUsB.mjs → db-BkRoptAt.mjs} +47 -30
  20. package/dist/{delete-D8GigDk8.mjs → delete-DouASY9P.mjs} +3 -3
  21. package/dist/{deploy-iXZ3F0N6.mjs → deploy-DTaWUS1S.mjs} +121 -110
  22. package/dist/{dev-inbox-DkgRWLkW.mjs → dev-inbox-P0u4tM8Y.mjs} +1 -1
  23. package/dist/{domain-B1VmoSr0.mjs → domain-1RhhOVrC.mjs} +4 -4
  24. package/dist/email-C-lGh51B.mjs +795 -0
  25. package/dist/{env-D4Emu-M_.mjs → env-DBKmK4vc.mjs} +1 -0
  26. package/dist/{env-BcQzYgoG.mjs → env-DJHsPE7Z.mjs} +5 -5
  27. package/dist/{env-validation-ENpMy6Ez.mjs → env-validation-CF6KvTRf.mjs} +3 -1
  28. package/dist/{gen-DI2YwdBM.mjs → gen-B_wPnVTK.mjs} +2 -2
  29. package/dist/{github-cmd-xItS5Zwf.mjs → github-cmd-PW7ZnWTp.mjs} +3 -3
  30. package/dist/{headers-D8QfRX9Y.mjs → headers-BAHwgHdW.mjs} +1 -1
  31. package/dist/help-CwOX-zmI.mjs +2216 -0
  32. package/dist/{inbound-afAcWeQ9.d.mts → inbound-CH5Mksyy.d.mts} +34 -48
  33. package/dist/{inbound-2d0zi2yS.mjs → inbound-aVHEUhKo.mjs} +130 -100
  34. package/dist/index.mjs +54 -17
  35. package/dist/{init-BD-9THgn.mjs → init-BWZ7q5Z4.mjs} +11 -11
  36. package/dist/{link-RMdgjF1v.mjs → link-Rmvu2Wl_.mjs} +4 -4
  37. package/dist/{list-3F52R_yO.mjs → list-DEE2S6mY.mjs} +4 -4
  38. package/dist/{login-pV69H-ZO.mjs → login-Uvferzmm.mjs} +28 -10
  39. package/dist/{logs-DFHHD6wE.mjs → logs-27FenuiC.mjs} +4 -4
  40. package/dist/{mime-BJD7d_qL.mjs → mime-D5Nmdzf7.mjs} +23 -9
  41. package/dist/{node-Dk3H2jmU.mjs → node-Ez5KW5rn.mjs} +2 -2
  42. package/dist/operator-auth-B3e08unv.mjs +52 -0
  43. package/dist/operator-client-LUZnlnYk.mjs +82 -0
  44. package/dist/{operator-cmd-DYWRbWUA.mjs → operator-cmd-CjOTmAYE.mjs} +35 -55
  45. package/dist/{output-tFQLLj26.mjs → output-B0cfNSx5.mjs} +316 -2
  46. package/dist/pages/index.mjs +2 -2
  47. package/dist/platform-auth-config-DrbQXXiW.mjs +368 -0
  48. package/dist/platform-auth-protection-Bhtvp0B_.mjs +219 -0
  49. package/dist/platform-auth-recovery-CeOKGVeJ.mjs +310 -0
  50. package/dist/{platform-cmd-DxJ2FRwR.mjs → platform-cmd-BFhieCdV.mjs} +16 -6
  51. package/dist/{platform-domain-ChvbJkdy.mjs → platform-domain-C74PULqV.mjs} +4 -4
  52. package/dist/{platform-lifecycle-DN4MzJF_.mjs → platform-lifecycle-BwAIgz-t.mjs} +1667 -191
  53. package/dist/{platform-management-Db2PXw0B.mjs → platform-management-COogu_Se.mjs} +33 -7
  54. package/dist/{platform-recovery-C_YO-tIs.mjs → platform-recovery-ewqLefp1.mjs} +6 -5
  55. package/dist/{prepare-CBetXvsN.mjs → prepare-CtDJjoOj.mjs} +2 -2
  56. package/dist/{prepare-BfJvFUtJ.mjs → prepare-blNRQvQl.mjs} +2 -2
  57. package/dist/prerender-render.d.mts +11 -0
  58. package/dist/prerender-render.mjs +111 -0
  59. package/dist/{project-cmd-Mo0V9yKS.mjs → project-cmd-DmZK9Hxf.mjs} +32 -14
  60. package/dist/project-team-D8jOJMUJ.mjs +130 -0
  61. package/dist/project-token-DA34bf-C.mjs +75 -0
  62. package/dist/{provision-Blnstcm2.mjs → provision-CSJOjjQk.mjs} +2 -0
  63. package/dist/{requests-BcKOVpRg.mjs → requests-CUExwGQQ.mjs} +3 -3
  64. package/dist/{rollback-Bx85-0xh.mjs → rollback-CDNGU1gr.mjs} +4 -4
  65. package/dist/runtime/ai.mjs +3 -2
  66. package/dist/runtime/email/testing.d.mts +1 -1
  67. package/dist/runtime/email/testing.mjs +3 -3
  68. package/dist/runtime/email-protocol.d.mts +15 -0
  69. package/dist/runtime/email-protocol.mjs +70 -0
  70. package/dist/runtime/email.d.mts +2 -2
  71. package/dist/runtime/email.mjs +189 -96
  72. package/dist/runtime/remote/index.mjs +5 -3
  73. package/dist/{secret-ByhJ9AMl.mjs → secret-Bzzi2e9E.mjs} +5 -5
  74. package/dist/{skills-Q46GZMO-.mjs → skills-C0RvGjeE.mjs} +1 -1
  75. package/dist/{subcommand-prompt-WfySCQ7S.mjs → subcommand-prompt-Bmyn5Rlc.mjs} +1 -1
  76. package/package.json +12 -7
  77. package/skills/void/SKILL.md +35 -4
  78. package/skills/void/docs/guide/deployment.md +2 -0
  79. package/skills/void/docs/guide/email.md +102 -110
  80. package/skills/void/docs/guide/platform-administration.md +214 -2
  81. package/skills/void/docs/guide/platform-development.md +64 -2
  82. package/skills/void/docs/guide/project-collaboration.md +94 -0
  83. package/skills/void/docs/guide/self-hosted-platform.md +184 -30
  84. package/skills/void/docs/reference/cli.md +249 -21
  85. package/dist/cf-access-AJ1ehiFR.mjs +0 -42
  86. package/dist/cf-access-DsSsZUPr.mjs +0 -67
  87. package/dist/email-uKyQYUVY.mjs +0 -1016
package/dist/index.mjs CHANGED
@@ -1,14 +1,15 @@
1
1
  import { r as __toESM } from "./rolldown-runtime-rQ84J-ij.mjs";
2
2
  import { c as relative, l as resolve, n as dirname, o as join } from "./dist-BrsS7cai.mjs";
3
- import { st as require_picocolors } from "./output-tFQLLj26.mjs";
4
- import { D as resolveAssetRoutingPolicy, E as hasDocumentRoutes, T as hasApiRoutes, _ as scanDurableObjectModules, c as resolveDistDir, d as generateQueueResolverSource, f as prerenderPages, g as hasRevalidate, h as collectRevalidate, l as resolveWorkerDirName, m as collectPages, p as prerenderPagesNode, v as SEND_EMAIL_BINDING } from "./deploy-iXZ3F0N6.mjs";
3
+ import { H as ensurePlatformProxyAccess, ft as require_picocolors } from "./output-B0cfNSx5.mjs";
4
+ import { D as resolveAssetRoutingPolicy, E as hasDocumentRoutes, T as hasApiRoutes, _ as scanDurableObjectModules, c as resolveDistDir, d as generateQueueResolverSource, f as prerenderPages, g as hasRevalidate, h as collectRevalidate, l as resolveWorkerDirName, m as collectPages, p as prerenderPagesNode, v as SEND_EMAIL_BINDING } from "./deploy-DTaWUS1S.mjs";
5
5
  import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-SK8nMHPp.mjs";
6
6
  import { a as scanQueuesSync, c as loadVoidAuthConfig, i as scanWebSocketRoutesSync, n as scanRoutePatternsSync, o as scanJobsSync, r as scanRoutes, s as findVoidAuthConfig, t as scanMiddlewareSync } from "./scan-BMH4rzlv.mjs";
7
- import { a as getApiUrl, b as readDeploymentPlatform, c as getToken, o as getProxyUrl, u as isStagingMode, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
7
+ import { r as scopedAccessCredentials } from "./cf-access-DRsQRe6k.mjs";
8
+ import { S as readProjectConfig, d as isStagingMode, l as getToken, o as getApiUrl, s as getProxyUrl, x as readDeploymentPlatform } from "./auth-DPl6kck4.mjs";
8
9
  import { C as readWranglerWebSocketTombstones, D as syncWranglerWebSockets, E as syncWranglerDurableObjects, M as isSandboxEnabled, P as resolveSandboxConfig, T as syncWranglerBindings, a as LIVE_MIGRATION_TAG, d as ensureWranglerNodejsAlsFlag, g as readExistingLiveBindingConfig, h as normalizeWranglerCompatibilityFlags, j as SANDBOX_MIGRATION_TAG, l as ensureWranglerCompat, m as nextDurableObjectMigrationTag, p as hasDurableObjectSqliteMigration, u as ensureWranglerCompatibilityDate, w as resolveLiveBindingConfig, y as readWranglerCompat } from "./wrangler--imS8n0d.mjs";
9
- import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-BQFq7QvD.mjs";
10
+ import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-uNGuFsI2.mjs";
10
11
  import { i as voidWarn, n as voidError, r as voidLog, t as setShowTimestamp } from "./log-ChfPKsVd.mjs";
11
- import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-D8QfRX9Y.mjs";
12
+ import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-BAHwgHdW.mjs";
12
13
  import { n as ensureProjectTsconfig, r as writeFileIfChanged } from "./project-tsconfig-Ql2XsSQp.mjs";
13
14
  import { a as inferBindingsFromSource, i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, o as walk, r as detectFramework, t as DEFAULT_SCAN_DIRS } from "./plugin-inference-BDRfZngg.mjs";
14
15
  import { a as validateSsrEntries, c as isIdentifier, l as isLiteral, n as SSR_SERVER_ENTRY_RELATIVE_PATHS, o as validateSsrEntry, t as SSR_CLIENT_ENTRY_RELATIVE_PATHS, u as isMemberExpression } from "./entry-DU3oDoQ3.mjs";
@@ -16,11 +17,11 @@ import { n as writeLocalD1PersistState, t as resolveLocalD1Target } from "./loca
16
17
  import { n as parseDotenvFile } from "./dotenv-VQxupEUv.mjs";
17
18
  import { i as generateVoidAuthDrizzleSchema, n as generateQueueTypes, o as DRIZZLE_OPERATORS, r as generateVoidAuthDatabaseModule, s as generateDbDts, t as generateRouteTypes } from "./route-types-Da-DpyUp.mjs";
18
19
  import { t as discoverSchema } from "./discover-xvfrgJeo.mjs";
19
- import { _ as parseCapturedMessage, a as DEV_INBOX_ENV_VAR, c as DEV_INBOX_TOKEN_ENV_VAR, f as clearDevBuffer, g as listDevMessages, l as DEV_INBOX_TOKEN_HEADER, m as findDevMessage, n as DEV_INBOX_ACK_VALUE, o as DEV_INBOX_MAX_CAPTURE_BYTES, s as DEV_INBOX_PREFIX, t as DEV_INBOX_ACK_HEADER, u as DEV_INBOX_TOKEN_QUERY, v as pushToDevBuffer, y as registerEmailSink } from "./dev-inbox-DkgRWLkW.mjs";
20
+ import { _ as parseCapturedMessage, a as DEV_INBOX_ENV_VAR, c as DEV_INBOX_TOKEN_ENV_VAR, f as clearDevBuffer, g as listDevMessages, l as DEV_INBOX_TOKEN_HEADER, m as findDevMessage, n as DEV_INBOX_ACK_VALUE, o as DEV_INBOX_MAX_CAPTURE_BYTES, s as DEV_INBOX_PREFIX, t as DEV_INBOX_ACK_HEADER, u as DEV_INBOX_TOKEN_QUERY, v as pushToDevBuffer, y as registerEmailSink } from "./dev-inbox-P0u4tM8Y.mjs";
20
21
  import { t as MagicString } from "./dist-BR1quN_w.mjs";
21
22
  import { n as findEnvFileForPaths, r as generateEnvTypes, t as findEnvFile } from "./env-types-BNPhro-M.mjs";
22
- import { h as loadUserEnvFile } from "./env-validation-ENpMy6Ez.mjs";
23
- import { a as loadLocalEnv, o as resolveRemoteMode, r as findLegacyEnvFiles, s as stripInternalEnvKeys, t as CLIENT_ENV_PREFIX$2 } from "./env-D4Emu-M_.mjs";
23
+ import { h as loadUserEnvFile } from "./env-validation-CF6KvTRf.mjs";
24
+ import { a as loadLocalEnv, o as resolveRemoteMode, r as findLegacyEnvFiles, s as stripInternalEnvKeys, t as CLIENT_ENV_PREFIX$2 } from "./env-DBKmK4vc.mjs";
24
25
  import { i as resolveLayoutIds, o as isRouteEnabledForEnvironment } from "./scan-CpK-57ug.mjs";
25
26
  import { a as scanEmailHandlersSync, r as hasEmailHandlers } from "./email-Ce6SQq-i.mjs";
26
27
  import { n as INTERNAL_BINDING_PREFIXES, t as INTERNAL_BINDING_EXACT_NAMES } from "./env-raw-Cx8ElDdj.mjs";
@@ -2013,7 +2014,7 @@ function migrationPlugin(root, dialect, databaseId = "local", persistRoot = join
2013
2014
  if (applied.length > 0) voidLog(`Applied ${applied.length} migration(s): ${applied.join(", ")}`);
2014
2015
  }
2015
2016
  if (auth?.enabled) {
2016
- const { runLocalVoidAuthMigrations } = await import("./node-Dk3H2jmU.mjs");
2017
+ const { runLocalVoidAuthMigrations } = await import("./node-Ez5KW5rn.mjs");
2017
2018
  await runLocalVoidAuthMigrations(root, dialect, persistRoot, databaseId, auth.configPath);
2018
2019
  voidLog("Applied Better Auth migrations");
2019
2020
  }
@@ -4116,6 +4117,7 @@ ${renderBlock}
4116
4117
  }`;
4117
4118
  const internalRouteHelper = `async function __handleInternal(request, env, ctx) {
4118
4119
  const url = new URL(request.url);
4120
+ ${hasEmail ? `if (url.pathname === "/__void/email/receipt/v1") return __handleEmailReceipt(request, env, ctx);` : ""}
4119
4121
  // Readiness probe — platform polls this to confirm the worker is live after WfP upload.
4120
4122
  // Handled here (before app.fetch) so user middleware cannot block it.
4121
4123
  if (request.method === "GET" && url.pathname === "/__void/ready") {
@@ -4144,7 +4146,7 @@ ${envValidateCall}${isrDeploymentStamp} const userEnv = __filterInternalBinding
4144
4146
  }`;
4145
4147
  const emailImport = hasEmail ? ", __emailHandler" : "";
4146
4148
  const emailRuntimePath = runtimeEmailPath ?? deriveEmailRuntimePath(runtimeEnvPath);
4147
- const emailProxyImport = hasEmail ? `import { createMessageProxy as __createMessageProxy, enactEmailActions as __enactEmailActions, isForwardableEmailMessage as __isForwardableEmailMessage } from ${JSON.stringify(emailRuntimePath)};\n` : "";
4149
+ const emailProxyImport = hasEmail ? `import { createMessageProxy as __createMessageProxy, enactEmailActions as __enactEmailActions, isForwardableEmailMessage as __isForwardableEmailMessage } from ${JSON.stringify(emailRuntimePath)};\nimport { EMAIL_PROTOCOL_VERSION as __EMAIL_PROTOCOL_VERSION, encodeEmailActions as __encodeEmailActions, readEmailEnvelope as __readEmailEnvelope, verifyEmailReceiptThroughProxy as __verifyEmailReceiptThroughProxy } from "void/_email-protocol";\n` : "";
4148
4150
  const emailHandler = hasEmail ? remotePath ? `async function handleEmail(envelope, env, ctx) {
4149
4151
  ${envValidateCall} if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};
4150
4152
  const userEnv = __filterInternalBindings(env);
@@ -4164,19 +4166,48 @@ ${envValidateCall} const userEnv = __filterInternalBindings(env);
4164
4166
  const __actions = getActions();
4165
4167
  if (__isForwardableEmailMessage(envelope)) await __enactEmailActions(envelope, __actions);
4166
4168
  return __actions;
4169
+ }` : "";
4170
+ const emailReceiptHandler = hasEmail ? `async function __handleEmailReceipt(request, env, ctx) {
4171
+ if (request.method !== "POST" || request.headers.get("content-encoding")) return new Response(null, { status: 404 });
4172
+ const __token = request.headers.get("x-void-email-receipt");
4173
+ const __recipient = request.headers.get("x-void-email-recipient");
4174
+ if (!__token || __token.length > 1536 || !__recipient || __recipient.length > 320 ||
4175
+ !env.__VOID_PROXY_TOKEN || !env.__PROJECT_ID || !env.__VOID_EMAIL_DEPLOYMENT_ID || !env.__VOID_PROXY) {
4176
+ return new Response(null, { status: 404 });
4177
+ }
4178
+ const __verified = await __verifyEmailReceiptThroughProxy(env.__VOID_PROXY, env.__VOID_PROXY_TOKEN, {
4179
+ receipt: __token, projectId: env.__PROJECT_ID,
4180
+ deploymentId: env.__VOID_EMAIL_DEPLOYMENT_ID, recipient: __recipient,
4181
+ });
4182
+ if (!__verified) return new Response(null, { status: 404 });
4183
+ let __envelope;
4184
+ try { __envelope = await __readEmailEnvelope(request.body); }
4185
+ catch { return new Response(null, { status: 400 }); }
4186
+ if (__envelope.to !== __recipient) return new Response(null, { status: 400 });
4187
+ const __actions = await handleEmail(__envelope, env, ctx);
4188
+ return new Response(__encodeEmailActions(__actions), {
4189
+ headers: { "content-type": "application/vnd.void.email-actions; version=" + __EMAIL_PROTOCOL_VERSION,
4190
+ "cache-control": "no-store" },
4191
+ });
4167
4192
  }` : "";
4168
4193
  const entryImport = `import { WorkerEntrypoint } from "cloudflare:workers";\n`;
4169
4194
  const fetchDeclaration = `const __voidFetch = ${fetchHandler};`;
4170
4195
  const entryClass = `export default class extends WorkerEntrypoint {
4171
4196
  async fetch(request) { return __voidFetch(request, this.env, this.ctx); }
4172
4197
  async scheduled(controller) { return handleScheduled(controller, this.env, this.ctx); }
4173
- ${hasQueues ? ` async queue(batch) { return __voidQueue(batch, this.env, this.ctx); }\n` : ""}${hasEmail ? ` async email(envelope) { return handleEmail(envelope, this.env, this.ctx); }\n` : ""}}`;
4198
+ ${hasQueues ? ` async queue(batch) { return __voidQueue(batch, this.env, this.ctx); }\n` : ""}${hasEmail ? ` async email(message) {
4199
+ if (this.env.__VOID_EMAIL_DEPLOYMENT_ID || !__isForwardableEmailMessage(message)) {
4200
+ throw new TypeError("Native email event required");
4201
+ }
4202
+ await handleEmail(message, this.env, this.ctx);
4203
+ }\n` : ""}}`;
4174
4204
  if (hasQueues) return `${sandboxImport}${entryImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleInternalRoute, __withRawEnv, __processQueue${emailImport}${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
4175
4205
  ${durableObjectImports}\n${runtimeEnvImport}${emailProxyImport}${envSchemaImport}${remoteImport}${isrImport}${filterBindingsHelper}${assetHelper}
4176
4206
  ${internalRouteHelper}
4177
4207
  ${fetchDeclaration}
4178
4208
  ${scheduledHandler}
4179
4209
  ${emailHandler}
4210
+ ${emailReceiptHandler}
4180
4211
  async function __voidQueue(batch, env, ctx) {
4181
4212
  ${envValidateCall}${remotePath ? ` if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};\n` : ""}${isrDeploymentStamp} const userEnv = __filterInternalBindings(env);
4182
4213
  const messages = [...batch.messages].map(m => ({
@@ -4209,6 +4240,7 @@ ${internalRouteHelper}
4209
4240
  ${fetchDeclaration}
4210
4241
  ${scheduledHandler}
4211
4242
  ${emailHandler}
4243
+ ${emailReceiptHandler}
4212
4244
  ${webSocketClasses.map((name) => `export { ${name} };`).join("\n")}
4213
4245
  ${liveExport}
4214
4246
  ${sandboxExport}
@@ -5523,11 +5555,14 @@ function readVoidDevCredentials(root) {
5523
5555
  token,
5524
5556
  staging
5525
5557
  };
5558
+ const proxyUrl = getProxyUrl(root);
5559
+ ensurePlatformProxyAccess(apiUrl, proxyUrl);
5526
5560
  return {
5527
5561
  status: "ok",
5528
5562
  token,
5529
5563
  projectId: project.projectId,
5530
- proxyUrl: getProxyUrl(root),
5564
+ proxyUrl,
5565
+ accessCredentials: scopedAccessCredentials(process.env, proxyUrl),
5531
5566
  staging
5532
5567
  };
5533
5568
  }
@@ -5537,9 +5572,9 @@ function readVoidDevCredentials(root) {
5537
5572
  * block the server. On completion, writes project.json and restarts the server.
5538
5573
  */
5539
5574
  async function runAiSetupPrompt(root, token, apiUrl, server) {
5540
- const { select, text, isCancel, log } = await import("./output-tFQLLj26.mjs").then((n) => n.T);
5541
- const { PlatformClient } = await import("./client-Clirrol3.mjs").then((n) => n.r);
5542
- const { attachSelectedPlatform, writeProjectConfig } = await import("./auth-W9WII-mN.mjs").then((n) => n.y);
5575
+ const { select, text, isCancel, log } = await import("./output-B0cfNSx5.mjs").then((n) => n.T);
5576
+ const { PlatformClient } = await import("./client-dHfSJvAN.mjs").then((n) => n.r);
5577
+ const { attachSelectedPlatform, writeProjectConfig } = await import("./auth-DPl6kck4.mjs").then((n) => n.b);
5543
5578
  const { inferDefaultSlug } = await import("./resolve-project--Vxawf7z.mjs").then((n) => n.i);
5544
5579
  const client = new PlatformClient(token, apiUrl);
5545
5580
  let projects;
@@ -5566,8 +5601,8 @@ async function runAiSetupPrompt(root, token, apiUrl, server) {
5566
5601
  let projectId;
5567
5602
  let slug;
5568
5603
  if (result === "__create__") {
5569
- const { validateProjectSlug } = await import("./create-project-ChGZ1DFd.mjs").then((n) => n.a);
5570
- const { createProjectWithSlugRetry } = await import("./create-project-ChGZ1DFd.mjs").then((n) => n.t);
5604
+ const { validateProjectSlug } = await import("./create-project-Bk9Z0-Jg.mjs").then((n) => n.a);
5605
+ const { createProjectWithSlugRetry } = await import("./create-project-Bk9Z0-Jg.mjs").then((n) => n.t);
5571
5606
  let created;
5572
5607
  try {
5573
5608
  created = await createProjectWithSlugRetry(client, inferDefaultSlug(root), async (defaultSlug) => {
@@ -6034,6 +6069,7 @@ function voidPlugin(options) {
6034
6069
  vars.__VOID_TOKEN = credentials.token;
6035
6070
  vars.__VOID_PROJECT_ID = credentials.projectId;
6036
6071
  vars.__VOID_PROXY_URL = credentials.proxyUrl;
6072
+ if (credentials.accessCredentials) vars.__VOID_ACCESS_CREDENTIALS = credentials.accessCredentials;
6037
6073
  if (credentials.staging) vars.__VOID_STAGING = "1";
6038
6074
  result.vars = vars;
6039
6075
  }
@@ -6043,6 +6079,7 @@ function voidPlugin(options) {
6043
6079
  if (credentials.status === "ok") {
6044
6080
  const vars = result.vars ?? {};
6045
6081
  vars.__VOID_PROXY_URL = credentials.proxyUrl;
6082
+ if (credentials.accessCredentials) vars.__VOID_ACCESS_CREDENTIALS = credentials.accessCredentials;
6046
6083
  vars.__VOID_TOKEN = credentials.token;
6047
6084
  vars.__VOID_PROJECT_ID = credentials.projectId;
6048
6085
  vars.__VOID_REMOTE = "1";
@@ -1,20 +1,20 @@
1
1
  import { a as isAbsolute, c as relative, l as resolve, n as dirname, o as join, t as basename } from "./dist-BrsS7cai.mjs";
2
- import { C as cancel, D as log, E as intro, F as isCancel, N as text, O as note, f as detectAgents, j as select, k as outro, p as getPackageDir, r as cliTitle, w as confirm } from "./output-tFQLLj26.mjs";
2
+ import { A as outro, C as cancel, D as log, E as intro, I as isCancel, M as select, P as text, f as detectAgents, k as note, p as getPackageDir, r as cliTitle, w as confirm } from "./output-B0cfNSx5.mjs";
3
3
  import { n as readProjectPaths } from "./project-paths-SK8nMHPp.mjs";
4
- import { C as writeDeploymentPlatform, T as writeProjectConfig, b as readDeploymentPlatform, c as getToken, u as isStagingMode, v as attachSelectedPlatform, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
4
+ import { E as writeProjectConfig, S as readProjectConfig, d as isStagingMode, l as getToken, w as writeDeploymentPlatform, x as readDeploymentPlatform, y as attachSelectedPlatform } from "./auth-DPl6kck4.mjs";
5
5
  import { i as LATEST_KNOWN_COMPAT_DATE, k as writeProvisionedWranglerConfig } from "./wrangler--imS8n0d.mjs";
6
- import { c as getDatabaseDialect, f as readConfig } from "./config-BQFq7QvD.mjs";
6
+ import { c as getDatabaseDialect, f as readConfig } from "./config-uNGuFsI2.mjs";
7
7
  import { n as ensureProjectTsconfig, t as createProjectTsconfig } from "./project-tsconfig-Ql2XsSQp.mjs";
8
8
  import { r as detectFramework } from "./plugin-inference-BDRfZngg.mjs";
9
9
  import { n as parseDotenvFile, t as expandDotenv } from "./dotenv-VQxupEUv.mjs";
10
10
  import { t as MagicString } from "./dist-BR1quN_w.mjs";
11
11
  import { n as writeDrizzleConfig } from "./config-NOG_U1aK.mjs";
12
- import { n as PlatformClient } from "./client-Clirrol3.mjs";
12
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
13
13
  import { r as formatProjectCommand } from "./preset-lAy0B0BQ.mjs";
14
- import { n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-ChGZ1DFd.mjs";
15
- import { t as promptForLoginToken } from "./login-pV69H-ZO.mjs";
16
- import { t as connectCloudflare } from "./cloudflare-connect-j5D4hhrG.mjs";
17
- import { discoverPlatform, saveDiscoveredPlatform } from "./platform-cmd-DxJ2FRwR.mjs";
14
+ import { n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-Bk9Z0-Jg.mjs";
15
+ import { n as promptForLoginToken } from "./login-Uvferzmm.mjs";
16
+ import { discoverPlatform, saveDiscoveredPlatform } from "./platform-cmd-BFhieCdV.mjs";
17
+ import { t as connectCloudflare } from "./cloudflare-connect-t1UU5svD.mjs";
18
18
  import { n as findInstalledYarnPnpRuntime, r as hasLocalLockfile, t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-DxSInkzL.mjs";
19
19
  import { createRequire } from "node:module";
20
20
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
@@ -1822,7 +1822,7 @@ async function ensureVoidPlatformConnection(root) {
1822
1822
  let selectedApiUrl = null;
1823
1823
  let promptedForPlatform = false;
1824
1824
  try {
1825
- const { getApiUrl, getSiteDomain } = await import("./auth-W9WII-mN.mjs").then((n) => n.t);
1825
+ const { getApiUrl, getSiteDomain } = await import("./auth-DPl6kck4.mjs").then((n) => n.t);
1826
1826
  selectedApiUrl = getApiUrl(root);
1827
1827
  getSiteDomain(root);
1828
1828
  } catch (error) {
@@ -2831,7 +2831,7 @@ async function runInitCommand(root, initArgs) {
2831
2831
  injectAgentBlock(root);
2832
2832
  const agents = detectAgents(root);
2833
2833
  if (agents.length > 0) {
2834
- const { linkSkillsForSpecificAgents } = await import("./skills-Q46GZMO-.mjs");
2834
+ const { linkSkillsForSpecificAgents } = await import("./skills-C0RvGjeE.mjs");
2835
2835
  linkSkillsForSpecificAgents(root, agents);
2836
2836
  } else log.info("No coding agent detected; read the bundled docs linked in AGENTS.md");
2837
2837
  }
@@ -2865,7 +2865,7 @@ async function runInitCommand(root, initArgs) {
2865
2865
  let shouldSetupGithub = targeted ? initArgs?.github === true : deploymentPlatform !== "none";
2866
2866
  if (shouldSetupGithub && !githubStepSkipForSubpackage && deploymentPlatform !== "cloudflare" && deploymentPlatform !== "none") {
2867
2867
  if (!voidPlatformDiscovery) {
2868
- const { getApiUrl } = await import("./auth-W9WII-mN.mjs").then((n) => n.t);
2868
+ const { getApiUrl } = await import("./auth-DPl6kck4.mjs").then((n) => n.t);
2869
2869
  voidPlatformDiscovery = await discoverPlatform(getApiUrl(root));
2870
2870
  }
2871
2871
  if (!voidPlatformDiscovery.capabilities.githubActions) {
@@ -1,7 +1,7 @@
1
- import { C as cancel, D as log, E as intro, c as import_picocolors, k as outro, r as cliTitle } from "./output-tFQLLj26.mjs";
2
- import { T as writeProjectConfig, c as getToken, s as getSiteDomain, v as attachSelectedPlatform, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-Clirrol3.mjs";
4
- import { n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-ChGZ1DFd.mjs";
1
+ import { A as outro, C as cancel, D as log, E as intro, c as import_picocolors, r as cliTitle } from "./output-B0cfNSx5.mjs";
2
+ import { E as writeProjectConfig, S as readProjectConfig, c as getSiteDomain, l as getToken, y as attachSelectedPlatform } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
+ import { n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-Bk9Z0-Jg.mjs";
5
5
  import { r as resolveProjectBySlug } from "./resolve-project--Vxawf7z.mjs";
6
6
  //#region src/cli/link.ts
7
7
  function projectLabel(slug, root, url) {
@@ -1,6 +1,6 @@
1
- import { D as log, E as intro, a as dim, c as import_picocolors, k as outro, o as ensureUtc, r as cliTitle, u as tablePrefix } from "./output-tFQLLj26.mjs";
2
- import { b as readDeploymentPlatform, c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-Clirrol3.mjs";
1
+ import { A as outro, D as log, E as intro, a as dim, c as import_picocolors, o as ensureUtc, r as cliTitle, u as tablePrefix } from "./output-B0cfNSx5.mjs";
2
+ import { S as readProjectConfig, l as getToken, x as readDeploymentPlatform } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
4
  import { r as resolveProjectBySlug } from "./resolve-project--Vxawf7z.mjs";
5
5
  //#region src/cli/list.ts
6
6
  async function runListCommand(root, slug) {
@@ -41,7 +41,7 @@ async function runListCommand(root, slug) {
41
41
  }
42
42
  async function showCloudflareDeployments(root, slug) {
43
43
  if (slug) throw new Error("project: A project name selects a Void platform project and is not used for direct Cloudflare apps.");
44
- const { readCloudflareWorkerStatus, resolveCloudflareOperationContext } = await import("./cloudflare-operations-CPTpRW6d.mjs").then((n) => n.t);
44
+ const { readCloudflareWorkerStatus, resolveCloudflareOperationContext } = await import("./cloudflare-operations-BzWnlC1_.mjs").then((n) => n.t);
45
45
  const status = await readCloudflareWorkerStatus(resolveCloudflareOperationContext(root));
46
46
  if (status.versions.length === 0) {
47
47
  outro(`No deployments for ${status.workerName}.`);
@@ -1,22 +1,40 @@
1
- import { C as cancel, D as log, E as intro, F as isCancel, c as import_picocolors, i as createSpinner, j as select, k as outro, r as cliTitle } from "./output-tFQLLj26.mjs";
2
- import { _ as saveToken, c as getToken, g as savePlatformToken, h as runPlatformLogin, l as getTokenSource, m as runLogin, p as removeToken, u as isStagingMode } from "./auth-W9WII-mN.mjs";
3
- import { a as isExpiredTokenError, n as PlatformClient } from "./client-Clirrol3.mjs";
1
+ import { n as __exportAll } from "./rolldown-runtime-rQ84J-ij.mjs";
2
+ import { A as outro, C as cancel, D as log, E as intro, I as isCancel, M as select, c as import_picocolors, i as createSpinner, r as cliTitle } from "./output-B0cfNSx5.mjs";
3
+ import { _ as savePlatformToken, d as isStagingMode, g as runPlatformLogin, h as runLogin, l as getToken, m as removeToken, o as getApiUrl, u as getTokenSource, v as saveToken } from "./auth-DPl6kck4.mjs";
4
+ import { a as isExpiredTokenError, n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
5
  //#region src/cli/login.ts
5
- async function promptForLoginToken(root = process.cwd(), platform) {
6
+ var login_exports = /* @__PURE__ */ __exportAll({
7
+ promptForLoginToken: () => promptForLoginToken,
8
+ runLoginCommand: () => runLoginCommand,
9
+ selectPlatformLoginMethod: () => selectPlatformLoginMethod
10
+ });
11
+ async function selectPlatformLoginMethod(platform, requestedId) {
6
12
  const providers = platform?.authenticationProviders ?? ["github", "google"];
7
- if (providers.length === 0) throw new Error("auth: This platform has no login providers.");
13
+ const methods = platform?.authentication?.methods ?? providers.map((id) => ({
14
+ id,
15
+ label: id === "github" ? "GitHub" : id === "google" ? "Google" : id
16
+ }));
17
+ if (providers.length === 0) throw new Error(platform?.authentication?.setupPending ? "auth: The platform administrator must finish initial setup." : "auth: This platform has no login providers.");
18
+ if (requestedId) {
19
+ const selected = methods.find((method) => method.id === requestedId);
20
+ if (!selected) throw new Error(`auth: Login method ${requestedId} is not enabled on this platform.`);
21
+ return selected;
22
+ }
8
23
  const provider = providers.length === 1 ? providers[0] : await select({
9
24
  message: "Choose a login provider:",
10
- options: providers.map((value) => ({
11
- value,
12
- label: value === "github" ? "GitHub" : "Google"
25
+ options: methods.map(({ id, label }) => ({
26
+ value: id,
27
+ label
13
28
  }))
14
29
  });
15
30
  if (isCancel(provider) || typeof provider === "symbol") {
16
31
  cancel("Login cancelled.");
17
32
  process.exit(0);
18
33
  }
19
- const providerName = provider === "github" ? "GitHub" : "Google";
34
+ return methods.find((method) => method.id === provider);
35
+ }
36
+ async function promptForLoginToken(root = process.cwd(), platform) {
37
+ const { id: provider, label: providerName } = await selectPlatformLoginMethod(platform ?? await import("./platform-cmd-BFhieCdV.mjs").then(({ discoverPlatform }) => discoverPlatform(getApiUrl(root))));
20
38
  const s = createSpinner();
21
39
  s.start(`Opening browser for ${providerName} login...`);
22
40
  try {
@@ -70,4 +88,4 @@ async function runLoginCommand(root = process.cwd()) {
70
88
  outro(isStagingMode(root) ? "Staging token saved." : "Token saved.");
71
89
  }
72
90
  //#endregion
73
- export { runLoginCommand as n, promptForLoginToken as t };
91
+ export { selectPlatformLoginMethod as i, promptForLoginToken as n, runLoginCommand as r, login_exports as t };
@@ -1,13 +1,13 @@
1
- import { D as log, E as intro, a as dim, c as import_picocolors, k as outro, r as cliTitle } from "./output-tFQLLj26.mjs";
2
- import { b as readDeploymentPlatform, c as getToken, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
3
- import { n as PlatformClient } from "./client-Clirrol3.mjs";
1
+ import { A as outro, D as log, E as intro, a as dim, c as import_picocolors, r as cliTitle } from "./output-B0cfNSx5.mjs";
2
+ import { S as readProjectConfig, l as getToken, x as readDeploymentPlatform } from "./auth-DPl6kck4.mjs";
3
+ import { n as PlatformClient } from "./client-dHfSJvAN.mjs";
4
4
  //#region src/cli/logs.ts
5
5
  async function runLogsCommand(root, filter, range, deployment, level) {
6
6
  console.log();
7
7
  intro(cliTitle("project logs"));
8
8
  const platform = readDeploymentPlatform(root);
9
9
  if (platform === "cloudflare") {
10
- const { resolveCloudflareOperationContext, tailCloudflareWorker } = await import("./cloudflare-operations-CPTpRW6d.mjs").then((n) => n.t);
10
+ const { resolveCloudflareOperationContext, tailCloudflareWorker } = await import("./cloudflare-operations-BzWnlC1_.mjs").then((n) => n.t);
11
11
  if (range !== "1h") log.warn("Cloudflare tail streams live logs; --range does not select historical entries.");
12
12
  if (level && level !== "all" && level !== "error") log.warn("Cloudflare tail cannot filter individual console levels; showing all invocation logs.");
13
13
  await tailCloudflareWorker(resolveCloudflareOperationContext(root), {
@@ -7,8 +7,8 @@ import { validate } from "email-validator";
7
7
  * and multipart/mixed for attachments — covering >95% of transactional sends.
8
8
  * Inline images use multipart/related when both attachments and html are present.
9
9
  */
10
- /** Cloudflare Email Workers reject messages larger than ~10 MB after base64 expansion. */
11
- const MAX_MESSAGE_BYTES = 10485760;
10
+ /** Encoded outbound MIME ceiling, separate from the 10 MiB inbound limit. */
11
+ const MAX_MESSAGE_BYTES = 5242880;
12
12
  /**
13
13
  * Upper bound on the TOTAL attachment bytes `normalizeEmail` will materialize.
14
14
  *
@@ -35,6 +35,8 @@ const MAX_MESSAGE_BYTES = 10485760;
35
35
  * on.
36
36
  */
37
37
  const MAX_ATTACHMENT_BYTES_TOTAL = Math.floor(MAX_MESSAGE_BYTES * 3 / 4);
38
+ /** Maximum serialized size of app-defined top-level MIME fields. */
39
+ const MAX_CUSTOM_HEADER_BYTES = 16384;
38
40
  const CRLF = "\r\n";
39
41
  const ASCII_PRINTABLE = /^[\x20-\x7e]*$/;
40
42
  const HEADER_NAME = /^[!-9;-~]+$/;
@@ -455,13 +457,25 @@ async function normalizeAttachment(att) {
455
457
  async function normalizeEmail(opts) {
456
458
  if (!opts.text && !opts.html) throw new MimeError("MIME_ERROR", "email: at least one of 'text' or 'html' is required.");
457
459
  if (opts.subject !== void 0) rejectCRLF("subject", opts.subject);
458
- if (opts.headers) for (const [name, value] of Object.entries(opts.headers)) {
459
- if (!HEADER_NAME.test(name)) throw new MimeError("MIME_ERROR", `headers: '${name}' is not a valid RFC 5322 header name.`);
460
- if (name.length + HEADER_NAME_LINE_OVERHEAD > MAX_LINE_OCTETS) throw new MimeError("MIME_ERROR", `headers: a header name is ${name.length} characters; a field name cannot be folded, so its line would exceed the ${MAX_LINE_OCTETS}-octet limit in RFC 5322 §2.1.1. Shorten the name.`);
461
- rejectCRLF(`header '${name}'`, value);
460
+ if (opts.headers) {
461
+ let headerInputBytes = 0;
462
+ let headerBytes = 0;
463
+ const encoder = new TextEncoder();
464
+ for (const [name, value] of Object.entries(opts.headers)) {
465
+ if (!HEADER_NAME.test(name)) throw new MimeError("MIME_ERROR", `headers: '${name}' is not a valid RFC 5322 header name.`);
466
+ if (name.length + HEADER_NAME_LINE_OVERHEAD > MAX_LINE_OCTETS) throw new MimeError("MIME_ERROR", `headers: a header name is ${name.length} characters; a field name cannot be folded, so its line would exceed the ${MAX_LINE_OCTETS}-octet limit in RFC 5322 §2.1.1. Shorten the name.`);
467
+ if (headerInputBytes + name.length + value.length + 4 > MAX_CUSTOM_HEADER_BYTES) throw new MimeError("MIME_ERROR", "email: custom headers exceed the 16 KiB limit.");
468
+ headerInputBytes += name.length + encoder.encode(value).byteLength + 4;
469
+ if (headerInputBytes > MAX_CUSTOM_HEADER_BYTES) throw new MimeError("MIME_ERROR", "email: custom headers exceed the 16 KiB limit.");
470
+ rejectCRLF(`header '${name}'`, value);
471
+ if (RESERVED_HEADERS.has(name.toLowerCase())) continue;
472
+ if (headerBytes + name.length + CUSTOM_HEADER_FRAMING_OCTETS + minHeaderValueOctets(value) > MAX_CUSTOM_HEADER_BYTES) throw new MimeError("MIME_ERROR", "email: custom headers exceed the 16 KiB limit.");
473
+ headerBytes += foldHeader(name, encodeWord(value)).length + 2;
474
+ if (headerBytes > MAX_CUSTOM_HEADER_BYTES) throw new MimeError("MIME_ERROR", "email: custom headers exceed the 16 KiB limit.");
475
+ }
462
476
  }
463
477
  const recipientCount = countRecipients(opts.to) + countRecipients(opts.cc) + countRecipients(opts.bcc);
464
- if (recipientCount > 100) throw new MimeError("INVALID_TO", `email: too many recipients (max 100, got ${recipientCount}) across 'to', 'cc' and 'bcc'.`);
478
+ if (recipientCount > 50) throw new MimeError("INVALID_TO", `email: too many recipients (max 50, got ${recipientCount}) across 'to', 'cc' and 'bcc'.`);
465
479
  const from = parseAddress(opts.from, "from");
466
480
  const to = parseAddresses(opts.to, "to");
467
481
  if (to.length === 0) throw new MimeError("INVALID_TO", "email: 'to' must include at least one recipient.");
@@ -1171,7 +1185,7 @@ function generateMessageId(fromEmail) {
1171
1185
  */
1172
1186
  function buildMime(email) {
1173
1187
  const projected = minHeaderOctets(email) + (email.text ? minBodyOctets(email.text) : 0) + (email.html ? minBodyOctets(email.html) : 0) + email.attachments.reduce((sum, a) => sum + base64Octets(a.bytes.byteLength), 0);
1174
- if (projected > 10485760) throw new MimeError("MIME_ERROR", `email: message is at least ${projected} bytes once encoded, which exceeds Cloudflare limit of ${MAX_MESSAGE_BYTES} bytes.`);
1188
+ if (projected > 5242880) throw new MimeError("MIME_ERROR", `email: message is at least ${projected} bytes once encoded, which exceeds Cloudflare limit of ${MAX_MESSAGE_BYTES} bytes.`);
1175
1189
  const messageId = generateMessageId(email.from.email);
1176
1190
  const topHeaders = [
1177
1191
  ["Date", (/* @__PURE__ */ new Date()).toUTCString().replace("GMT", "+0000")],
@@ -1206,7 +1220,7 @@ function buildMime(email) {
1206
1220
  const raw = new TextEncoder().encode(rawText);
1207
1221
  const overlong = findOverlongLine(rawText);
1208
1222
  if (overlong !== void 0) throw new MimeError("MIME_ERROR", `email: header line ${overlong.index + 1} is ${overlong.octets} octets, over the ${MAX_LINE_OCTETS}-octet limit in RFC 5322 §2.1.1. A value with no whitespace cannot be folded — shorten it, or move it into the body.`);
1209
- if (raw.byteLength > 10485760) throw new MimeError("MIME_ERROR", `email: message size ${raw.byteLength} bytes exceeds Cloudflare limit of ${MAX_MESSAGE_BYTES} bytes.`);
1223
+ if (raw.byteLength > 5242880) throw new MimeError("MIME_ERROR", `email: message size ${raw.byteLength} bytes exceeds Cloudflare limit of ${MAX_MESSAGE_BYTES} bytes.`);
1210
1224
  return {
1211
1225
  raw,
1212
1226
  messageId
@@ -1,9 +1,9 @@
1
1
  import { o as join } from "./dist-BrsS7cai.mjs";
2
2
  import { c as loadVoidAuthConfig, s as findVoidAuthConfig } from "./scan-BMH4rzlv.mjs";
3
- import { f as readConfig } from "./config-BQFq7QvD.mjs";
3
+ import { f as readConfig } from "./config-uNGuFsI2.mjs";
4
4
  import { r as getMiniflareDatabasePath } from "./local-d1-D2I6Ox5F.mjs";
5
5
  import { a as resolveVoidAuthMigrationSchema } from "./route-types-Da-DpyUp.mjs";
6
- import { a as loadLocalEnv } from "./env-D4Emu-M_.mjs";
6
+ import { a as loadLocalEnv } from "./env-DBKmK4vc.mjs";
7
7
  import { n as applyPgAuthMigrations, r as applySqliteAuthMigrations, t as applyMySqlAuthMigrations } from "./auth-migrations-9vif1uj8.mjs";
8
8
  //#region src/auth/node.ts
9
9
  async function runLocalVoidAuthMigrations(root, dialect, persistRoot = join(root, ".void"), databaseId = "local", configPath = findVoidAuthConfig(root)) {
@@ -0,0 +1,52 @@
1
+ import { K as getActivePlatformConnection, X as normalizePlatformApiUrl, Y as listPlatformConnections, Z as platformCredentialAccount, dt as writeKeyringPassword, lt as deleteKeyringPassword, ut as readKeyringPassword } from "./output-B0cfNSx5.mjs";
2
+ import { n as OperatorClient, r as OperatorClientError } from "./operator-client-LUZnlnYk.mjs";
3
+ /** Operator authority never comes from repository-controlled metadata. */
4
+ function resolveOperatorOrigin(connection = "") {
5
+ if (connection) {
6
+ let normalized = null;
7
+ try {
8
+ normalized = normalizePlatformApiUrl(connection);
9
+ } catch {}
10
+ const matches = listPlatformConnections().filter((entry) => entry.id === connection || entry.installationId === connection || entry.apiUrl === normalized);
11
+ if (matches.length !== 1) throw new OperatorClientError("Select a registered platform connection ID or URL. Run `void connect <url> --no-login` to register it first.", "invalid_connection");
12
+ return matches[0].apiUrl;
13
+ }
14
+ if (process.env.VOID_API_URL) return normalizePlatformApiUrl(process.env.VOID_API_URL);
15
+ if (process.env.VOID_OPERATOR_TOKEN) throw new OperatorClientError("VOID_OPERATOR_TOKEN requires an explicit --connection or VOID_API_URL to select its recipient.", "explicit_origin_required");
16
+ const active = getActivePlatformConnection();
17
+ if (!active) throw new OperatorClientError("No default platform connection. Run `void connect <url>` or specify --connection.", "connection_required");
18
+ return active.apiUrl;
19
+ }
20
+ function readOperatorToken(origin) {
21
+ const token = process.env.VOID_OPERATOR_TOKEN || readKeyringPassword("dev.void.cli.operator", platformCredentialAccount(origin));
22
+ if (!token) throw new OperatorClientError("No operator session. Run `void platform auth login` or set VOID_OPERATOR_TOKEN with an explicit origin.", "authentication_required");
23
+ return token;
24
+ }
25
+ function saveOperatorToken(origin, token) {
26
+ if (!writeKeyringPassword("dev.void.cli.operator", platformCredentialAccount(origin), token)) throw new OperatorClientError("The system keychain is unavailable. Use `void platform auth token --token-stdin` with a full API session to obtain a token for VOID_OPERATOR_TOKEN; plaintext credential storage is disabled.", "keychain_unavailable");
27
+ }
28
+ function removeOperatorToken(origin) {
29
+ const account = platformCredentialAccount(origin);
30
+ if (readKeyringPassword("dev.void.cli.operator", account) && !deleteKeyringPassword("dev.void.cli.operator", account)) throw new OperatorClientError("The operator session was revoked, but its local keychain entry could not be removed.", "keychain_unavailable");
31
+ }
32
+ async function readOperatorApiTokenStdin() {
33
+ if (process.stdin.isTTY) throw new OperatorClientError("--token-stdin requires an API session token piped on standard input.", "invalid_token_input");
34
+ let input = "";
35
+ for await (const chunk of process.stdin) {
36
+ input += String(chunk);
37
+ if (input.length > 32768) throw new OperatorClientError("API session token input is too large.", "invalid_token_input");
38
+ }
39
+ const token = input.trim();
40
+ if (!token || token.length > 32768 || /\s/.test(token)) throw new OperatorClientError("Standard input must contain one API session token.", "invalid_token_input");
41
+ return token;
42
+ }
43
+ async function exchangeOperatorSession(origin, apiToken) {
44
+ const session = await new OperatorClient(origin, apiToken).request("/session", {
45
+ method: "POST",
46
+ body: {}
47
+ });
48
+ if (typeof session.token !== "string" || !session.token || session.apiVersion !== 1 || typeof session.expiresAt !== "string") throw new OperatorClientError("Operator API returned an invalid session.", "invalid_response");
49
+ return session;
50
+ }
51
+ //#endregion
52
+ export { resolveOperatorOrigin as a, removeOperatorToken as i, readOperatorApiTokenStdin as n, saveOperatorToken as o, readOperatorToken as r, exchangeOperatorSession as t };
@@ -0,0 +1,82 @@
1
+ import { B as ensureCloudflaredToken, X as normalizePlatformApiUrl } from "./output-B0cfNSx5.mjs";
2
+ import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
3
+ const OPERATOR_MAX_TIMEOUT_MS = 36e5;
4
+ var OperatorClientError = class extends Error {
5
+ code;
6
+ status;
7
+ details;
8
+ constructor(message, code = "operator_error", status, details) {
9
+ super(message);
10
+ this.code = code;
11
+ this.status = status;
12
+ this.details = details;
13
+ this.name = "OperatorClientError";
14
+ }
15
+ toJSON() {
16
+ return {
17
+ error: this.code,
18
+ message: this.message,
19
+ ...this.status === void 0 ? {} : { status: this.status },
20
+ ...this.details === void 0 ? {} : { details: this.details }
21
+ };
22
+ }
23
+ };
24
+ var OperatorClient = class {
25
+ token;
26
+ fetcher;
27
+ origin;
28
+ constructor(origin, token, fetcher = fetch) {
29
+ this.token = token;
30
+ this.fetcher = fetcher;
31
+ this.origin = normalizePlatformApiUrl(origin);
32
+ }
33
+ async request(path, options = {}) {
34
+ if (!path.startsWith("/") || path.startsWith("//") || path.includes("?") || path.includes("#")) throw new OperatorClientError("Invalid operator API path.");
35
+ const timeoutMs = options.timeoutMs ?? (options.method === "POST" ? 3e5 : 3e4);
36
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1e3 || timeoutMs > 36e5) throw new OperatorClientError(`Operator request timeout must be an integer from 1 to ${OPERATOR_MAX_TIMEOUT_MS / 1e3} seconds.`, "invalid_timeout");
37
+ const url = new URL(`${this.origin}/operator/v1${path}`);
38
+ ensureCloudflaredToken(this.origin);
39
+ for (const [name, value] of Object.entries(options.query ?? {})) url.searchParams.set(name, value);
40
+ const timeoutController = new AbortController();
41
+ const timer = setTimeout(() => timeoutController.abort(), timeoutMs);
42
+ timer.unref();
43
+ const signal = options.signal ? AbortSignal.any([options.signal, timeoutController.signal]) : timeoutController.signal;
44
+ try {
45
+ let response;
46
+ try {
47
+ response = await this.fetcher(url, {
48
+ method: options.method ?? "GET",
49
+ headers: {
50
+ ...cfAccessHeaders(process.env, this.origin),
51
+ Authorization: `Bearer ${this.token}`,
52
+ Accept: "application/json",
53
+ ...options.body ? { "Content-Type": "application/json" } : {}
54
+ },
55
+ ...options.body ? { body: JSON.stringify(options.body) } : {},
56
+ redirect: "manual",
57
+ signal
58
+ });
59
+ } catch (error) {
60
+ if (options.signal?.aborted) throw error;
61
+ if (timeoutController.signal.aborted) throw new OperatorClientError(`Operator request exceeded the ${timeoutMs / 1e3}-second timeout. ${options.method === "POST" ? "Its outcome may be unknown; inspect platform state before retrying." : "Check connectivity and try again."}`, "request_timeout");
62
+ throw new OperatorClientError(`Operator request to ${this.origin} failed. ${options.method === "POST" ? "Its outcome may be unknown; inspect platform state before retrying." : "Check connectivity and try again."}`, "connection_failed");
63
+ }
64
+ if (response.status >= 300 && response.status < 400) throw new OperatorClientError("The operator API redirected the request. Credentials were not forwarded; use the exact platform API origin.", "redirect_rejected", response.status);
65
+ let data;
66
+ try {
67
+ data = await response.json();
68
+ } catch {
69
+ throw new OperatorClientError(`Operator API returned invalid JSON (HTTP ${response.status}).${options.method === "POST" ? " Inspect platform state before retrying." : ""}`, "invalid_response", response.status);
70
+ }
71
+ if (!data || typeof data !== "object" || Array.isArray(data)) throw new OperatorClientError("Operator API returned an invalid response object.", "invalid_response", response.status);
72
+ const result = data;
73
+ if (!response.ok) throw new OperatorClientError(typeof result.message === "string" ? result.message : `Operator request failed (HTTP ${response.status}).`, typeof result.error === "string" ? result.error : "request_failed", response.status, result.details);
74
+ if (result.partial === true || result.ok === false) throw new OperatorClientError("The operation did not fully complete. Inspect the partial result before retrying.", "partial_failure", response.status, result);
75
+ return result;
76
+ } finally {
77
+ clearTimeout(timer);
78
+ }
79
+ }
80
+ };
81
+ //#endregion
82
+ export { OperatorClient as n, OperatorClientError as r, OPERATOR_MAX_TIMEOUT_MS as t };