void 0.9.3 → 0.10.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 (104) hide show
  1. package/dist/{auth-cmd-CPkWrQR9.mjs → auth-cmd-DLvXvN-0.mjs} +2 -2
  2. package/dist/{better-auth-shared-CmEQZs1T.d.mts → better-auth-shared-a7H3wk9J.d.mts} +2 -2
  3. package/dist/{cache-1SVxZ7BK.mjs → cache-CHFZmqa5.mjs} +1 -1
  4. package/dist/{cancel-deploy-JaFClLr7.mjs → cancel-deploy-BwpT4U4a.mjs} +1 -1
  5. package/dist/cli/cli.mjs +273 -36
  6. package/dist/{client-DIfOFf1W.mjs → client-CTHvucDv.mjs} +166 -45
  7. package/dist/{create-project-DCUrFJxa.mjs → create-project-CruTH_TQ.mjs} +1 -1
  8. package/dist/{db-UW4IYQFw.mjs → db-BxnfKs7f.mjs} +14 -14
  9. package/dist/{delete-CYknzwXU.mjs → delete-IQe1O4Re.mjs} +1 -1
  10. package/dist/{deploy-RQXpVBL-.mjs → deploy-CuxXxVgz.mjs} +195 -89
  11. package/dist/{domain-B7RntQ1r.mjs → domain-Bq6kzr_T.mjs} +1 -1
  12. package/dist/{env-C_ZcxxED.mjs → env-BD3U_0Av.mjs} +1 -1
  13. package/dist/{env-helpers-Bd2wVdxz.d.mts → env-helpers-ZatKyjen.d.mts} +1 -1
  14. package/dist/{gen-O5mXZ76K.mjs → gen-Dgi4D7GC.mjs} +1 -1
  15. package/dist/git-metadata-Ce0AtSZL.mjs +82 -0
  16. package/dist/github-cmd-CD0Z8KCF.mjs +441 -0
  17. package/dist/{handler-hm9KldPP.d.mts → handler-DczZlaXR.d.mts} +3 -3
  18. package/dist/index.d.mts +3 -3
  19. package/dist/index.mjs +18 -18
  20. package/dist/{init-DGrLx2ls.mjs → init-CTe46nIr.mjs} +113 -77
  21. package/dist/{link-7MoXUMaI.mjs → link-BGFW4pHD.mjs} +2 -2
  22. package/dist/{list-N2mCHv8q.mjs → list-CbGxdbe7.mjs} +1 -1
  23. package/dist/{login-tt1OmNVg.mjs → login-v4wle1vn.mjs} +1 -1
  24. package/dist/{logs-Cl7q2CjZ.mjs → logs-BFgY5Vqc.mjs} +1 -1
  25. package/dist/{mcp-BXD35N2J.mjs → mcp-STKL-uWs.mjs} +1 -1
  26. package/dist/{node-Df8UjQ2H.mjs → node-B07cZs0d.mjs} +3 -3
  27. package/dist/pages/client.d.mts +1 -1
  28. package/dist/pages/client.mjs +1 -0
  29. package/dist/pages/head-client.d.mts +1 -1
  30. package/dist/pages/head.d.mts +1 -1
  31. package/dist/pages/index.d.mts +2 -2
  32. package/dist/pages/index.mjs +1 -1
  33. package/dist/pages/islands-plugin.d.mts +1 -1
  34. package/dist/pages/protocol.d.mts +2 -2
  35. package/dist/pages/protocol.mjs +1 -1
  36. package/dist/{plugin-inference--7geW5Z2.mjs → plugin-inference-C3fLzFvP.mjs} +2 -0
  37. package/dist/{prepare-DT-7QII_.mjs → prepare-DH2WnEpD.mjs} +3 -3
  38. package/dist/{preset-2aBxMfY1.mjs → preset-B7ZQZn0u.mjs} +2 -2
  39. package/dist/{project-cmd-CLrqSbqj.mjs → project-cmd-DZh-vbEL.mjs} +8 -8
  40. package/dist/{protocol-B9GZA4Bn.d.mts → protocol-63PHtCHS.d.mts} +3 -3
  41. package/dist/{rollback-CEbAwbHK.mjs → rollback-o0M0Qo_n.mjs} +1 -1
  42. package/dist/{runner-DLZ9E_cX.mjs → runner-BQyKUqAL.mjs} +1 -1
  43. package/dist/runtime/ai.mjs +1 -1
  44. package/dist/runtime/auth.d.mts +1 -1
  45. package/dist/runtime/better-auth-pg.d.mts +1 -1
  46. package/dist/runtime/better-auth-pg.mjs +3 -3
  47. package/dist/runtime/better-auth.d.mts +1 -1
  48. package/dist/runtime/better-auth.mjs +2 -2
  49. package/dist/runtime/client-react.d.mts +2 -2
  50. package/dist/runtime/client-react.mjs +1 -1
  51. package/dist/runtime/client-solid.d.mts +2 -2
  52. package/dist/runtime/client-solid.mjs +1 -1
  53. package/dist/runtime/client-svelte.d.mts +2 -2
  54. package/dist/runtime/client-svelte.mjs +1 -1
  55. package/dist/runtime/client-vue.d.mts +2 -2
  56. package/dist/runtime/client-vue.mjs +1 -1
  57. package/dist/runtime/client.d.mts +2 -2
  58. package/dist/runtime/client.mjs +1 -1
  59. package/dist/runtime/env-helpers.d.mts +1 -1
  60. package/dist/runtime/env-public-client.d.mts +1 -1
  61. package/dist/runtime/env-public.d.mts +2 -2
  62. package/dist/runtime/env-public.mjs +1 -1
  63. package/dist/runtime/env.mjs +1 -1
  64. package/dist/runtime/fetch-stream.d.mts +1 -1
  65. package/dist/runtime/fetch-stream.mjs +1 -1
  66. package/dist/runtime/fetch.d.mts +1 -1
  67. package/dist/runtime/fetch.mjs +1 -1
  68. package/dist/runtime/handler.d.mts +1 -1
  69. package/dist/runtime/handler.mjs +1 -1
  70. package/dist/runtime/isr.mjs +1 -1
  71. package/dist/runtime/live.d.mts +2 -2
  72. package/dist/runtime/live.mjs +1 -1
  73. package/dist/runtime/migration-handler-pg.mjs +1 -1
  74. package/dist/runtime/sandbox.mjs +1 -1
  75. package/dist/runtime/validator.d.mts +1 -1
  76. package/dist/runtime/ws-server.d.mts +2 -2
  77. package/dist/runtime/ws.d.mts +3 -3
  78. package/dist/{scan-B2H1Vo2C.mjs → scan-DGEp1-1Q.mjs} +17 -9
  79. package/dist/{secret-C_uTY7xx.mjs → secret-gs_yyGZL.mjs} +1 -1
  80. package/package.json +2 -2
  81. package/schema.json +3 -3
  82. package/skills/void/docs/guide/deployment.md +26 -11
  83. package/skills/void/docs/guide/edge/headers.md +10 -3
  84. package/skills/void/docs/guide/edge/rewrites.md +5 -5
  85. package/skills/void/docs/reference/cli.md +89 -2
  86. /package/dist/{auth-migrations-CuQkjjWE.mjs → auth-migrations-BP-hMzYl.mjs} +0 -0
  87. /package/dist/{auth-CDeb2XAl.d.mts → auth-nEUVHuFI.d.mts} +0 -0
  88. /package/dist/{better-auth-shared-QAfk8CAS.mjs → better-auth-shared-D0Mbmx5V.mjs} +0 -0
  89. /package/dist/{defer-CouVukrf.mjs → defer-C-bdSM_b.mjs} +0 -0
  90. /package/dist/{drizzle-DYstYz0j.mjs → drizzle-DqstQTGq.mjs} +0 -0
  91. /package/dist/{env-raw-RDkMnSTC.mjs → env-raw-Dtj1UAoK.mjs} +0 -0
  92. /package/dist/{fetch-error-CimrygMq.d.mts → fetch-error-BQMdPvge.d.mts} +0 -0
  93. /package/dist/{fetch-error-BFIoojjf.mjs → fetch-error-C6qffTl2.mjs} +0 -0
  94. /package/dist/{head-BsSTGnIe.d.mts → head-JAH2l3fg.d.mts} +0 -0
  95. /package/dist/{headers-VkAnACKX.mjs → headers-BNWymgnH.mjs} +0 -0
  96. /package/dist/{package-json-B2TD0JLu.mjs → package-json-Bg_GJdJB.mjs} +0 -0
  97. /package/dist/{pg-CMZ_5wsC.mjs → pg-CempqvEJ.mjs} +0 -0
  98. /package/dist/{providers-3Kkv63Ha.d.mts → providers-BkiAlEad.d.mts} +0 -0
  99. /package/dist/{runner-pg-Cv9V7ydr.mjs → runner-pg-BAheiT6v.mjs} +0 -0
  100. /package/dist/{skills-BRKc--As.mjs → skills--OMgLmXW.mjs} +0 -0
  101. /package/dist/{standard-schema-Dnsh2vnl.d.mts → standard-schema-BCBv-QaP.d.mts} +0 -0
  102. /package/dist/{subcommand-prompt-OD-x_Tsm.mjs → subcommand-prompt-ClwpLlKD.mjs} +0 -0
  103. /package/dist/{types-DEWCqHtl.d.mts → types-BnHMXezo.d.mts} +0 -0
  104. /package/dist/{yarn-pnp-0SwYgQxx.mjs → yarn-pnp-DhCHHLAz.mjs} +0 -0
@@ -3,12 +3,13 @@ import { a as join, c as resolve, i as isAbsolute, n as dirname, r as extname, s
3
3
  import { n as cliTitle, r as createSpinner, s as import_picocolors } from "./output-DeiS4oEX.mjs";
4
4
  import { i as resolveProjectPaths, n as readProjectPaths } from "./project-paths-CCMrHYQm.mjs";
5
5
  import { t as findVoidAuthConfig } from "./config-hhMYPVRT.mjs";
6
- import { a as isExpiredTokenError, c as getToken, i as isCliOutdatedError, l as getTokenSource, n as PlatformClient, o as parsePlatformErrorBody, t as PlatformApiError, u as isStagingMode } from "./client-DIfOFf1W.mjs";
6
+ import { t as cfAccessHeaders } from "./cf-access-DKDsgwOU.mjs";
7
+ import { a as isExpiredTokenError, f as getToken, i as isCliOutdatedError, m as isStagingMode, n as PlatformClient, o as parsePlatformErrorBody, p as getTokenSource, t as PlatformApiError, u as getApiUrl, y as ensureCloudflaredToken } from "./client-CTHvucDv.mjs";
7
8
  import { c as R, g as ge, u as Se, v as ue, x as q, y as ye } from "./dist-abzUneor.mjs";
8
9
  import { a as writeProjectConfig, r as readProjectConfig } from "./project-CH9pdo16.mjs";
9
10
  import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-8dLIngKW.mjs";
10
- import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes } from "./scan-B2H1Vo2C.mjs";
11
- import { i as inferProjectBindings, l as validateSsrEntry, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference--7geW5Z2.mjs";
11
+ import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes } from "./scan-DGEp1-1Q.mjs";
12
+ import { i as inferProjectBindings, l as validateSsrEntry, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-C3fLzFvP.mjs";
12
13
  import { i as voidWarn, r as voidLog } from "./log-BdD_Fpms.mjs";
13
14
  import { t as discoverSchema } from "./discover-C8N1I4tK.mjs";
14
15
  import { t as findEnvFile } from "./env-types-CaJaIRXU.mjs";
@@ -19,18 +20,19 @@ import { n as buildMigrationPlanBundle } from "./plan-aD3wRDqF.mjs";
19
20
  import { r as validateMigrations, t as assertJournalCoherence } from "./validate-CNWm-PsL.mjs";
20
21
  import { t as scanPages } from "./scan-VCAM1oh3.mjs";
21
22
  import { n as STAGING_PROXY_URL, t as DEFAULT_PROXY_URL } from "./proxy-M3pxItg2.mjs";
22
- import { i as promptProjectSetupAction, n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-DCUrFJxa.mjs";
23
+ import { i as promptProjectSetupAction, n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-CruTH_TQ.mjs";
23
24
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-D4O1_fZz.mjs";
24
- import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-VkAnACKX.mjs";
25
- import { t as promptForLoginToken } from "./login-tt1OmNVg.mjs";
26
- import { i as resolveProjectCommand, n as detectPreset, r as formatProjectCommand, t as FRAMEWORK_PRESETS } from "./preset-2aBxMfY1.mjs";
25
+ import { t as collectGitDeployMetadata } from "./git-metadata-Ce0AtSZL.mjs";
26
+ import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-BNWymgnH.mjs";
27
+ import { t as promptForLoginToken } from "./login-v4wle1vn.mjs";
28
+ import { i as resolveProjectCommand, n as detectPreset, r as formatProjectCommand, t as FRAMEWORK_PRESETS } from "./preset-B7ZQZn0u.mjs";
27
29
  import { createRequire } from "node:module";
28
30
  import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
29
31
  import { fileURLToPath, pathToFileURL } from "node:url";
30
32
  import { build, loadEnv } from "vite";
31
33
  import { createHash } from "node:crypto";
32
34
  import { homedir } from "node:os";
33
- import { execFile, execFileSync, execSync, spawnSync } from "node:child_process";
35
+ import { execFile, execSync, spawnSync } from "node:child_process";
34
36
  import { parse } from "jsonc-parser";
35
37
  import { hash } from "blake3-jit";
36
38
  import ignore from "ignore";
@@ -1167,84 +1169,127 @@ function sleep(ms) {
1167
1169
  return new Promise((resolve) => setTimeout(resolve, ms));
1168
1170
  }
1169
1171
  //#endregion
1170
- //#region src/cli/git-metadata.ts
1171
- function git(root, args) {
1172
- try {
1173
- return execFileSync("git", args, {
1174
- cwd: root,
1175
- encoding: "utf-8",
1176
- stdio: [
1177
- "ignore",
1178
- "pipe",
1179
- "ignore"
1180
- ]
1181
- }).trim();
1182
- } catch {
1183
- return null;
1184
- }
1172
+ //#region src/cli/github-oidc.ts
1173
+ /**
1174
+ * GitHub Actions OIDC → Void deploy-token exchange.
1175
+ *
1176
+ * When `void deploy` runs inside GitHub Actions with no explicit `VOID_TOKEN`,
1177
+ * the CLI mints a short-lived GitHub OIDC token (audience `void`) and exchanges
1178
+ * it at `POST $VOID_API_URL/auth/github-oidc` for a short-lived, project-scoped
1179
+ * Void deploy token. Doing the exchange in-process lets the scaffolded workflow
1180
+ * collapse to a single `void deploy` step — no curl/jq token-exchange step.
1181
+ *
1182
+ * Server contract (platform `POST /auth/github-oidc` handler):
1183
+ * request { oidcToken: string, project: string } (project = slug)
1184
+ * response { token: string, projectId, buildId }
1185
+ */
1186
+ const OIDC_AUDIENCE = "void";
1187
+ /**
1188
+ * True when the process is running inside GitHub Actions with the OIDC token
1189
+ * request endpoint available — i.e. the workflow granted
1190
+ * `permissions: id-token: write`, so GitHub injected the request URL + token.
1191
+ */
1192
+ function isGithubActionsOidcAvailable(env = process.env) {
1193
+ return env.GITHUB_ACTIONS === "true" && typeof env.ACTIONS_ID_TOKEN_REQUEST_URL === "string" && env.ACTIONS_ID_TOKEN_REQUEST_URL.length > 0 && typeof env.ACTIONS_ID_TOKEN_REQUEST_TOKEN === "string" && env.ACTIONS_ID_TOKEN_REQUEST_TOKEN.length > 0;
1185
1194
  }
1186
- function stripGitSuffix(pathname) {
1187
- return pathname.endsWith(".git") ? pathname.slice(0, -4) : pathname;
1195
+ /**
1196
+ * Mint a GitHub Actions OIDC token (audience `void`) and exchange it for a
1197
+ * short-lived, project-scoped Void deploy token.
1198
+ *
1199
+ * Two hops:
1200
+ * 1. GET $ACTIONS_ID_TOKEN_REQUEST_URL&audience=void (Bearer request token)
1201
+ * → `.value` is the OIDC JWT.
1202
+ * 2. POST $apiUrl/auth/github-oidc { oidcToken, project }
1203
+ * → `.token` is the Void deploy token.
1204
+ *
1205
+ * Throws a clear, actionable error (including the HTTP status and server error
1206
+ * body when available) on any non-OK response or missing field.
1207
+ */
1208
+ async function exchangeGithubOidcForDeployToken(apiUrl, project, env = process.env) {
1209
+ const requestUrl = env.ACTIONS_ID_TOKEN_REQUEST_URL;
1210
+ const requestToken = env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
1211
+ if (!requestUrl || !requestToken) throw new Error("github-oidc: GitHub Actions OIDC is unavailable (missing ACTIONS_ID_TOKEN_REQUEST_URL/TOKEN). Ensure the workflow grants `permissions: id-token: write`.");
1212
+ return exchangeOidcTokenAtApi(apiUrl, project, await requestGithubOidcToken(requestUrl, requestToken));
1188
1213
  }
1189
- function normalizeGitRemoteUrl(remote) {
1190
- if (!remote) return null;
1191
- const trimmed = remote.trim();
1192
- if (!trimmed) return null;
1193
- const scpLike = /^(?:[^@]+@)?([^:]+):(.+)$/.exec(trimmed);
1194
- if (scpLike && !trimmed.includes("://")) {
1195
- const host = scpLike[1]?.toLowerCase();
1196
- const path = stripGitSuffix(scpLike[2] ?? "").replace(/^\/+/, "");
1197
- return host && path ? `https://${host}/${path}` : null;
1214
+ /**
1215
+ * GET the GitHub Actions OIDC token for audience `void`. GitHub's request URL
1216
+ * already carries a query string, so `audience` is appended alongside it.
1217
+ */
1218
+ async function requestGithubOidcToken(requestUrl, requestToken) {
1219
+ const url = new URL(requestUrl);
1220
+ url.searchParams.set("audience", OIDC_AUDIENCE);
1221
+ let res;
1222
+ try {
1223
+ res = await fetch(url, { headers: { Authorization: `Bearer ${requestToken}` } });
1224
+ } catch (err) {
1225
+ throw new Error(`github-oidc: Failed to reach the GitHub OIDC token endpoint: ${errText(err)}`);
1198
1226
  }
1227
+ if (!res.ok) {
1228
+ const body = await safeText(res);
1229
+ throw new Error(`github-oidc: Failed to mint a GitHub OIDC token (${res.status})${body ? `: ${body}` : ""}.`);
1230
+ }
1231
+ let body;
1199
1232
  try {
1200
- const url = new URL(trimmed);
1201
- if (url.protocol !== "https:" && url.protocol !== "http:" && url.protocol !== "ssh:") return null;
1202
- const host = url.hostname.toLowerCase();
1203
- const path = stripGitSuffix(url.pathname).replace(/^\/+/, "");
1204
- return host && path ? `https://${host}/${path}` : null;
1233
+ body = await res.json();
1205
1234
  } catch {
1206
- return null;
1235
+ throw new Error("github-oidc: GitHub OIDC token endpoint returned an invalid response.");
1207
1236
  }
1237
+ const value = body?.value;
1238
+ if (typeof value !== "string" || value.length === 0) throw new Error("github-oidc: GitHub OIDC token endpoint did not return a token value.");
1239
+ return value;
1208
1240
  }
1209
- function buildCommitUrl(repositoryUrl, commit) {
1210
- if (!repositoryUrl || !commit) return null;
1241
+ /** POST the OIDC JWT to the Void API and return the minted deploy token. */
1242
+ async function exchangeOidcTokenAtApi(apiUrl, project, oidcToken) {
1243
+ const url = `${apiUrl.endsWith("/") ? apiUrl.slice(0, -1) : apiUrl}/auth/github-oidc`;
1244
+ ensureCloudflaredToken(apiUrl);
1245
+ let res;
1246
+ try {
1247
+ res = await fetch(url, {
1248
+ method: "POST",
1249
+ headers: {
1250
+ "Content-Type": "application/json",
1251
+ ...cfAccessHeaders(process.env)
1252
+ },
1253
+ body: JSON.stringify({
1254
+ oidcToken,
1255
+ project
1256
+ })
1257
+ });
1258
+ } catch (err) {
1259
+ throw new Error(`github-oidc: Failed to reach ${url}: ${errText(err)}`);
1260
+ }
1261
+ if (!res.ok) {
1262
+ const body = await safeText(res);
1263
+ throw new Error(`github-oidc: OIDC token exchange failed (${res.status})${body ? `: ${body}` : ""}. Confirm the repository is connected to project "${project}" with the github_actions executor.`);
1264
+ }
1265
+ let body;
1211
1266
  try {
1212
- const url = new URL(repositoryUrl);
1213
- if (url.hostname === "github.com") return `${repositoryUrl}/commit/${commit}`;
1214
- if (url.hostname === "gitlab.com") return `${repositoryUrl}/-/commit/${commit}`;
1215
- if (url.hostname === "bitbucket.org") return `${repositoryUrl}/commits/${commit}`;
1267
+ body = await res.json();
1216
1268
  } catch {
1217
- return null;
1269
+ throw new Error("github-oidc: OIDC token exchange returned an invalid response.");
1218
1270
  }
1219
- return null;
1271
+ const token = body?.token;
1272
+ if (typeof token !== "string" || token.length === 0) throw new Error("github-oidc: OIDC token exchange did not return a deploy token.");
1273
+ return token;
1220
1274
  }
1221
- function getGitRefFromEnv(env) {
1222
- if (env.GITHUB_HEAD_REF) return env.GITHUB_HEAD_REF;
1223
- if (env.GITHUB_REF_NAME) return env.GITHUB_REF_NAME;
1224
- if (env.GITHUB_REF) return env.GITHUB_REF.replace(/^refs\/(?:heads|tags|pull)\//, "");
1225
- return null;
1275
+ /**
1276
+ * Emit a GitHub Actions `::add-mask::` workflow command so `value` is redacted
1277
+ * from workflow logs. No-op when not running inside GitHub Actions. GitHub reads
1278
+ * workflow commands from stdout.
1279
+ */
1280
+ function maskGithubActionsSecret(value, env = process.env) {
1281
+ if (env.GITHUB_ACTIONS !== "true" || !value) return;
1282
+ process.stdout.write(`::add-mask::${value}\n`);
1226
1283
  }
1227
- function getGitHubRepositoryUrl(env) {
1228
- if (!env.GITHUB_REPOSITORY) return null;
1229
- return normalizeGitRemoteUrl(`${env.GITHUB_SERVER_URL ?? "https://github.com"}/${env.GITHUB_REPOSITORY}`);
1230
- }
1231
- function collectGitDeployMetadata(root, commit, env = process.env) {
1232
- const repositoryUrl = getGitHubRepositoryUrl(env) ?? normalizeGitRemoteUrl(git(root, [
1233
- "remote",
1234
- "get-url",
1235
- "origin"
1236
- ]));
1237
- const gitRef = getGitRefFromEnv(env) ?? git(root, [
1238
- "rev-parse",
1239
- "--abbrev-ref",
1240
- "HEAD"
1241
- ]);
1242
- return {
1243
- commit,
1244
- commitUrl: buildCommitUrl(repositoryUrl, commit),
1245
- gitRef: gitRef && gitRef !== "HEAD" ? gitRef : null,
1246
- repositoryUrl
1247
- };
1284
+ function errText(err) {
1285
+ return err instanceof Error ? err.message : String(err);
1286
+ }
1287
+ async function safeText(res) {
1288
+ try {
1289
+ return (await res.text()).trim();
1290
+ } catch {
1291
+ return "";
1292
+ }
1248
1293
  }
1249
1294
  //#endregion
1250
1295
  //#region src/cli/log-file.ts
@@ -2292,6 +2337,7 @@ function generateHandlersSource(root, features) {
2292
2337
  //#region src/cli/deploy.ts
2293
2338
  var deploy_exports = /* @__PURE__ */ __exportAll({
2294
2339
  applyDeployEvent: () => applyDeployEvent,
2340
+ buildEnv: () => buildEnv,
2295
2341
  ensurePreviouslyDeployedLiveBindingConfig: () => ensurePreviouslyDeployedLiveBindingConfig,
2296
2342
  generateDeployWrapperIfNeeded: () => generateDeployWrapperIfNeeded,
2297
2343
  hasDeploySchemaDrift: () => hasDeploySchemaDrift,
@@ -2305,7 +2351,9 @@ var deploy_exports = /* @__PURE__ */ __exportAll({
2305
2351
  resolveWorkerDirName: () => resolveWorkerDirName,
2306
2352
  runDeploy: () => runDeploy,
2307
2353
  runStaticDeploy: () => runStaticDeploy,
2308
- warnRedundantForceOn3xx: () => warnRedundantForceOn3xx
2354
+ streamDeployEvents: () => streamDeployEvents,
2355
+ warnRedundantForceOn3xx: () => warnRedundantForceOn3xx,
2356
+ warnUnpublishedRouting: () => warnUnpublishedRouting
2309
2357
  });
2310
2358
  const drizzleKitBin = join(fileURLToPath(import.meta.resolve("drizzle-kit")), "..", "bin.cjs");
2311
2359
  const deployDriftCheckDir = join(".void", "deploy-drift-check");
@@ -2423,10 +2471,47 @@ async function runDeploy(root, options) {
2423
2471
  await cliLog.close().catch(() => {});
2424
2472
  }
2425
2473
  }
2474
+ /**
2475
+ * Build a child-process environment with the CF Access service-token PAIR
2476
+ * removed.
2477
+ *
2478
+ * The deploy flow spawns UNTRUSTED user build code (`vite build`, framework
2479
+ * preset builds, drizzle-kit loading the user schema) which inherits the
2480
+ * spawn env. A shared, long-lived CF Access service token is needed only by
2481
+ * this CLI's own API client (which captures the Access headers once at
2482
+ * construction and reuses them for every request) — never by the build — so it
2483
+ * must not survive into those children, or it would leak to arbitrary repo
2484
+ * build scripts/plugins.
2485
+ *
2486
+ * We scrub it on the CHILD env rather than mutating `process.env`: deleting it
2487
+ * from the parent also breaks interactive expired-token re-auth, which reads
2488
+ * `cfAccessHeaders(process.env)` / the cloudflared pair-guard AFTER the build
2489
+ * step. Only the service-token pair is scrubbed; the cloudflared
2490
+ * `CF_ACCESS_TOKEN` JWT (dev path) is left untouched.
2491
+ */
2492
+ function buildEnv(extra) {
2493
+ const env = {
2494
+ ...process.env,
2495
+ ...extra
2496
+ };
2497
+ delete env.CF_ACCESS_CLIENT_ID;
2498
+ delete env.CF_ACCESS_CLIENT_SECRET;
2499
+ return env;
2500
+ }
2426
2501
  async function runDeployInner(root, options, cliLog) {
2427
2502
  let reauthenticated = false;
2428
2503
  while (true) try {
2429
- const token = getToken(root);
2504
+ let token = process.env.VOID_TOKEN ?? null;
2505
+ if (!token && isGithubActionsOidcAvailable()) {
2506
+ const slug = getRequestedProjectSlug(options) ?? readProjectConfig(root)?.slug;
2507
+ if (!slug) throw new Error("deploy: running in GitHub Actions but the project is unknown — pass --project <slug> or link the project.");
2508
+ cliLog.info("github_oidc_exchange_start", { slug });
2509
+ token = await exchangeGithubOidcForDeployToken(getApiUrl(root), slug);
2510
+ maskGithubActionsSecret(token);
2511
+ process.env.VOID_TOKEN = token;
2512
+ cliLog.info("github_oidc_exchange_success", { slug });
2513
+ }
2514
+ token ??= getToken(root);
2430
2515
  if (!token) {
2431
2516
  R.error("No auth token found. Run `void auth login` first.");
2432
2517
  process.exit(1);
@@ -2598,7 +2683,8 @@ function applyDeployEvent(event, s) {
2598
2683
  s.message(`Prerendering ${event.pages} pages...`);
2599
2684
  return { kind: "continue" };
2600
2685
  case "done":
2601
- s.stop("Deployed!");
2686
+ if (event.published === false) s.stop("Deployed, but routing was not published — the project may be unreachable or still serving the previous deploy. Re-run `void deploy` to publish routing.");
2687
+ else s.stop("Deployed!");
2602
2688
  return {
2603
2689
  kind: "done",
2604
2690
  event
@@ -2639,12 +2725,14 @@ async function streamDeployEvents(projectId, events, s, cliLog) {
2639
2725
  deploymentId = result.deploymentId;
2640
2726
  cliLog?.info("stream_deployment_id", { deploymentId });
2641
2727
  } else if (result.kind === "done") {
2642
- cliLog?.info("deploy_success", {
2728
+ const degraded = result.event.published === false;
2729
+ cliLog?.info(degraded ? "deploy_degraded" : "deploy_success", {
2643
2730
  deploymentId,
2644
2731
  url: result.event.url,
2645
2732
  assets: result.event.assets,
2646
2733
  workers: result.event.workers,
2647
- durationMs: Date.now() - startedAt
2734
+ durationMs: Date.now() - startedAt,
2735
+ degraded
2648
2736
  });
2649
2737
  return result.event;
2650
2738
  } else if (result.kind === "error") {
@@ -2784,7 +2872,8 @@ async function runStaticDeploy(root, config, client, preset, skipBuild, gitMetad
2784
2872
  const buildStartedAt = Date.now();
2785
2873
  execSync(preset.buildCommand, {
2786
2874
  cwd: root,
2787
- stdio: "inherit"
2875
+ stdio: "inherit",
2876
+ env: buildEnv()
2788
2877
  });
2789
2878
  cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
2790
2879
  } else if (skipBuild) cliLog?.info("build_skipped", { reason: "skipBuild" });
@@ -2836,9 +2925,21 @@ async function runStaticDeploy(root, config, client, preset, skipBuild, gitMetad
2836
2925
  });
2837
2926
  const result = await streamDirectR2Deploy(client, config.projectId, manifest, assetManifest, assetFiles, needed, gitMetadata, neededSet !== null, void 0, s, cliLog);
2838
2927
  Se([`${typeLabel} — ${formatKnownAssetSummary(result, skipped)}`].join("\n"), result.url);
2928
+ warnUnpublishedRouting(result);
2839
2929
  ye("Done!");
2840
2930
  }
2841
2931
  /**
2932
+ * Surface a persistent warning when a deploy committed live but its routing
2933
+ * KV was not published. Uses `log.warn` (not the spinner) so the warning
2934
+ * survives the following `note`/`outro` calls and the user sees it after the
2935
+ * deploy summary. The deploy is still committed — this is a warning, not a
2936
+ * failure, so the process exit code is unaffected.
2937
+ */
2938
+ function warnUnpublishedRouting(result) {
2939
+ if (result.published !== false) return;
2940
+ R.warn("Routing was not published for this deploy. The project may be unreachable (first deploy) or still serving the previous deploy. Re-run `void deploy` to publish routing.");
2941
+ }
2942
+ /**
2842
2943
  * Emit a single aggregated lint warning when a `_redirects` file contains
2843
2944
  * one or more `!` force suffixes on 3xx entries (e.g. `301!`, `302!`).
2844
2945
  * The `!` is a no-op on redirects — we parse them as if the `!` weren't
@@ -2866,7 +2967,8 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
2866
2967
  const buildStartedAt = Date.now();
2867
2968
  execSync(voidConfig.inference?.build ?? resolveProjectCommand(root, fwPreset.buildCommand), {
2868
2969
  cwd: root,
2869
- stdio: "inherit"
2970
+ stdio: "inherit",
2971
+ env: buildEnv()
2870
2972
  });
2871
2973
  cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
2872
2974
  } else cliLog?.info("build_skipped", { reason: "skipBuild" });
@@ -3043,6 +3145,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
3043
3145
  summary.push(`Framework: ${detected.name}`);
3044
3146
  Se(summary.join("\n"), result.url);
3045
3147
  cleanupWrapper(root);
3148
+ warnUnpublishedRouting(result);
3046
3149
  ye("Done!");
3047
3150
  }
3048
3151
  async function runFullDeploy(root, config, client, fwPreset, skipBuild, gitMetadata, detected, cliLog) {
@@ -3059,10 +3162,7 @@ async function runFullDeploy(root, config, client, fwPreset, skipBuild, gitMetad
3059
3162
  execSync(resolveProjectCommand(root, "vite build"), {
3060
3163
  cwd: root,
3061
3164
  stdio: "inherit",
3062
- env: {
3063
- ...process.env,
3064
- VOID_DEPLOY_PROJECT_ID: config.projectId
3065
- }
3165
+ env: buildEnv({ VOID_DEPLOY_PROJECT_ID: config.projectId })
3066
3166
  });
3067
3167
  cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
3068
3168
  } catch (err) {
@@ -3343,6 +3443,7 @@ async function runFullDeploy(root, config, client, fwPreset, skipBuild, gitMetad
3343
3443
  else summary.push(`ISR revalidate: ${Object.keys(revalidate).length} path rule(s)`);
3344
3444
  if (isFrameworkMode) summary.push("Framework mode");
3345
3445
  Se(summary.join("\n"), result.url);
3446
+ warnUnpublishedRouting(result);
3346
3447
  ye("Done!");
3347
3448
  }
3348
3449
  async function createProjectFromSlug(root, client, slug, cliLog) {
@@ -3365,17 +3466,21 @@ function getGitCommit(root) {
3365
3466
  try {
3366
3467
  const githubSha = process.env.GITHUB_SHA?.trim();
3367
3468
  if (githubSha && /^[0-9a-f]{7,64}$/i.test(githubSha)) return githubSha;
3469
+ const gitEnv = buildEnv();
3368
3470
  execSync("git rev-parse --is-inside-work-tree", {
3369
3471
  cwd: root,
3370
- stdio: "ignore"
3472
+ stdio: "ignore",
3473
+ env: gitEnv
3371
3474
  });
3372
3475
  if (execSync("git status --porcelain", {
3373
3476
  cwd: root,
3374
- encoding: "utf-8"
3477
+ encoding: "utf-8",
3478
+ env: gitEnv
3375
3479
  }).trim() !== "") return null;
3376
3480
  return execSync("git rev-parse HEAD", {
3377
3481
  cwd: root,
3378
- encoding: "utf-8"
3482
+ encoding: "utf-8",
3483
+ env: gitEnv
3379
3484
  }).trim();
3380
3485
  } catch {
3381
3486
  return null;
@@ -3421,7 +3526,8 @@ function runDrizzleKitGenerate(root, configPath) {
3421
3526
  configPath
3422
3527
  ], {
3423
3528
  cwd: root,
3424
- encoding: "utf-8"
3529
+ encoding: "utf-8",
3530
+ env: buildEnv()
3425
3531
  });
3426
3532
  const stderr = bufferToString(result.stderr);
3427
3533
  const output = [stderr, bufferToString(result.stdout)].filter(Boolean).join("\n").trim();
@@ -1,5 +1,5 @@
1
1
  import { s as import_picocolors } from "./output-DeiS4oEX.mjs";
2
- import { c as getToken, n as PlatformClient } from "./client-DIfOFf1W.mjs";
2
+ import { f as getToken, n as PlatformClient } from "./client-CTHvucDv.mjs";
3
3
  import { c as R, u as Se } from "./dist-abzUneor.mjs";
4
4
  import { r as readProjectConfig } from "./project-CH9pdo16.mjs";
5
5
  //#region src/cli/domain.ts
@@ -1,6 +1,6 @@
1
1
  import { a as join } from "./pathe.M-eThtNZ-BrPhGF_K.mjs";
2
2
  import { n as cliTitle } from "./output-DeiS4oEX.mjs";
3
- import { c as getToken, n as PlatformClient } from "./client-DIfOFf1W.mjs";
3
+ import { f as getToken, n as PlatformClient } from "./client-CTHvucDv.mjs";
4
4
  import { c as R, g as ge, u as Se, y as ye } from "./dist-abzUneor.mjs";
5
5
  import { r as readProjectConfig } from "./project-CH9pdo16.mjs";
6
6
  import { r as generateEnvTypes, t as findEnvFile } from "./env-types-CaJaIRXU.mjs";
@@ -1,4 +1,4 @@
1
- import { t as StandardSchemaV1 } from "./standard-schema-Dnsh2vnl.mjs";
1
+ import { t as StandardSchemaV1 } from "./standard-schema-BCBv-QaP.mjs";
2
2
 
3
3
  //#region src/shared/env-mask.d.ts
4
4
  /** Per-key override set by `.secret()` / `.public()` on built-in helpers. */
@@ -7,7 +7,7 @@ import { c as getDatabaseDialect, f as readConfig } from "./config-8dLIngKW.mjs"
7
7
  import { n as writeDrizzleConfig } from "./config--wXmVOoe.mjs";
8
8
  import { r as readJournal, t as collectMigrations } from "./collect-9rO3JFNM.mjs";
9
9
  import { n as listDrizzleArtifacts, t as assertJournalCoherence } from "./validate-CNWm-PsL.mjs";
10
- import { t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-0SwYgQxx.mjs";
10
+ import { t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-DhCHHLAz.mjs";
11
11
  import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import { spawnSync } from "node:child_process";
@@ -0,0 +1,82 @@
1
+ import { execFileSync } from "node:child_process";
2
+ //#region src/cli/git-metadata.ts
3
+ function git(root, args) {
4
+ try {
5
+ return execFileSync("git", args, {
6
+ cwd: root,
7
+ encoding: "utf-8",
8
+ stdio: [
9
+ "ignore",
10
+ "pipe",
11
+ "ignore"
12
+ ]
13
+ }).trim();
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ function stripGitSuffix(pathname) {
19
+ return pathname.endsWith(".git") ? pathname.slice(0, -4) : pathname;
20
+ }
21
+ function normalizeGitRemoteUrl(remote) {
22
+ if (!remote) return null;
23
+ const trimmed = remote.trim();
24
+ if (!trimmed) return null;
25
+ const scpLike = /^(?:[^@]+@)?([^:]+):(.+)$/.exec(trimmed);
26
+ if (scpLike && !trimmed.includes("://")) {
27
+ const host = scpLike[1]?.toLowerCase();
28
+ const path = stripGitSuffix(scpLike[2] ?? "").replace(/^\/+/, "");
29
+ return host && path ? `https://${host}/${path}` : null;
30
+ }
31
+ try {
32
+ const url = new URL(trimmed);
33
+ if (url.protocol !== "https:" && url.protocol !== "http:" && url.protocol !== "ssh:") return null;
34
+ const host = url.hostname.toLowerCase();
35
+ const path = stripGitSuffix(url.pathname).replace(/^\/+/, "");
36
+ return host && path ? `https://${host}/${path}` : null;
37
+ } catch {
38
+ return null;
39
+ }
40
+ }
41
+ function buildCommitUrl(repositoryUrl, commit) {
42
+ if (!repositoryUrl || !commit) return null;
43
+ try {
44
+ const url = new URL(repositoryUrl);
45
+ if (url.hostname === "github.com") return `${repositoryUrl}/commit/${commit}`;
46
+ if (url.hostname === "gitlab.com") return `${repositoryUrl}/-/commit/${commit}`;
47
+ if (url.hostname === "bitbucket.org") return `${repositoryUrl}/commits/${commit}`;
48
+ } catch {
49
+ return null;
50
+ }
51
+ return null;
52
+ }
53
+ function getGitRefFromEnv(env) {
54
+ if (env.GITHUB_HEAD_REF) return env.GITHUB_HEAD_REF;
55
+ if (env.GITHUB_REF_NAME) return env.GITHUB_REF_NAME;
56
+ if (env.GITHUB_REF) return env.GITHUB_REF.replace(/^refs\/(?:heads|tags|pull)\//, "");
57
+ return null;
58
+ }
59
+ function getGitHubRepositoryUrl(env) {
60
+ if (!env.GITHUB_REPOSITORY) return null;
61
+ return normalizeGitRemoteUrl(`${env.GITHUB_SERVER_URL ?? "https://github.com"}/${env.GITHUB_REPOSITORY}`);
62
+ }
63
+ function collectGitDeployMetadata(root, commit, env = process.env) {
64
+ const repositoryUrl = getGitHubRepositoryUrl(env) ?? normalizeGitRemoteUrl(git(root, [
65
+ "remote",
66
+ "get-url",
67
+ "origin"
68
+ ]));
69
+ const gitRef = getGitRefFromEnv(env) ?? git(root, [
70
+ "rev-parse",
71
+ "--abbrev-ref",
72
+ "HEAD"
73
+ ]);
74
+ return {
75
+ commit,
76
+ commitUrl: buildCommitUrl(repositoryUrl, commit),
77
+ gitRef: gitRef && gitRef !== "HEAD" ? gitRef : null,
78
+ repositoryUrl
79
+ };
80
+ }
81
+ //#endregion
82
+ export { collectGitDeployMetadata as t };