openship 0.6.7 → 0.6.8

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 (67) hide show
  1. package/dist/bare-FA66N7GC.js +29 -0
  2. package/dist/{chunk-LHFXSC36.js → chunk-3MP6ACKM.js} +183 -87
  3. package/dist/{chunk-MEE6OZFP.js → chunk-5DJOB7IX.js} +3 -3
  4. package/dist/{chunk-PPEBIY5F.js → chunk-5I3COAFH.js} +35 -12
  5. package/dist/{chunk-VQM6JHJB.js → chunk-5UXHT6ED.js} +9 -9
  6. package/dist/{chunk-XWHWTHEL.js → chunk-6GU6JSK6.js} +21 -2
  7. package/dist/{chunk-QHMDCYZ3.js → chunk-7PEXM2UI.js} +213 -45
  8. package/dist/{chunk-RDXT4BQB.js → chunk-7YBWXEM6.js} +4 -4
  9. package/dist/{chunk-H4FS5BED.js → chunk-AHJYP7DG.js} +13 -11
  10. package/dist/{chunk-VSTFHUCV.js → chunk-BO6CY4V2.js} +109 -23
  11. package/dist/{chunk-J3K6XABC.js → chunk-D3OEMXYP.js} +3 -3
  12. package/dist/{chunk-UWEV6XTS.js → chunk-D6HU4VUZ.js} +1 -1
  13. package/dist/{chunk-S6B2Z3OO.js → chunk-ENKJ7XIF.js} +21 -11
  14. package/dist/{chunk-BLEXTYRK.js → chunk-GNOMEMNI.js} +1 -1
  15. package/dist/{chunk-NRTJRNAE.js → chunk-IAMOUDHY.js} +138 -54
  16. package/dist/{chunk-CIJV43LH.js → chunk-MUWVC5R4.js} +161 -39
  17. package/dist/{chunk-ZPJ74LXE.js → chunk-NIYD7MD2.js} +197 -45
  18. package/dist/{chunk-FZ6QCF6B.js → chunk-NPSRGIHV.js} +2 -2
  19. package/dist/{chunk-2GWYYHOR.js → chunk-NRU2EBYZ.js} +2 -2
  20. package/dist/{chunk-J2XM3QSP.js → chunk-NUT6HKK6.js} +5 -5
  21. package/dist/{chunk-H3WT3A6R.js → chunk-P7RCYELG.js} +1 -1
  22. package/dist/{chunk-FYPFEDPZ.js → chunk-R5DC5PEF.js} +1 -1
  23. package/dist/{chunk-DDFUESPJ.js → chunk-RCMERVBL.js} +9 -9
  24. package/dist/{chunk-RXQBD4ZY.js → chunk-RHLNVZMS.js} +2 -2
  25. package/dist/{chunk-WU54BXFE.js → chunk-SK4FFCFR.js} +1 -1
  26. package/dist/{chunk-PVP4RGWT.js → chunk-T46BQOLY.js} +3 -3
  27. package/dist/{chunk-E2X26PXR.js → chunk-T6DVUX4F.js} +1 -1
  28. package/dist/{chunk-5T4UVOM3.js → chunk-TAZZZKYO.js} +1 -1
  29. package/dist/{chunk-GGIAIGUL.js → chunk-UAWY6X7V.js} +34 -12
  30. package/dist/{chunk-2ANV5ZQ5.js → chunk-VAI5VOOI.js} +1 -1
  31. package/dist/{chunk-2VSW6Q6C.js → chunk-WEZFTL4V.js} +655 -62
  32. package/dist/{chunk-GIPJNNI5.js → chunk-X53JXRS4.js} +3 -3
  33. package/dist/{cloud-KRTZ2IL5.js → cloud-2CRDKOWQ.js} +1 -1
  34. package/dist/cloud-REV3DPJH.js +42 -0
  35. package/dist/{detect-G4DR3U2N.js → detect-BBFT5GEU.js} +4 -4
  36. package/dist/{docker-YOVPCIB4.js → docker-EG3QSE6I.js} +10 -10
  37. package/dist/{docker-edge-executor-QFXD3337.js → docker-edge-executor-E5TOTLMR.js} +7 -7
  38. package/dist/edge-import-YJVJUGYC.js +56 -0
  39. package/dist/{edge-preflight-MXERVAMG.js → edge-preflight-QUW4BM7N.js} +13 -13
  40. package/dist/{ensure-container-edge-F4JUNQIK.js → ensure-container-edge-FOEFQ3PI.js} +13 -11
  41. package/dist/{executor-CVPAYYHR.js → executor-NTWDJ3DB.js} +6 -6
  42. package/dist/host-channel-preflight-OMCZMMKR.js +54 -0
  43. package/dist/index.js +158 -72
  44. package/dist/{local-executor-ODC6RANU.js → local-executor-OQ2GRN7K.js} +3 -3
  45. package/dist/{nginx-KLFF43TC.js → nginx-4U4C2XUS.js} +9 -9
  46. package/dist/{noop-NJ72F46T.js → noop-CLLJHCPL.js} +1 -1
  47. package/dist/{openresty-lua-VKWUV4GB.js → openresty-lua-LLWT5XQW.js} +7 -5
  48. package/dist/{privilege-7D3SSOL3.js → privilege-MNDVMDST.js} +5 -5
  49. package/dist/server/index.js +31643 -25553
  50. package/dist/server/migrations/0109_service_build_args.sql +9 -0
  51. package/dist/server/migrations/0110_service_deployment_host_ports.sql +18 -0
  52. package/dist/server/migrations/0111_host_port_claim.sql +381 -0
  53. package/dist/server/migrations/0112_backup_run_execution_lease.sql +12 -0
  54. package/dist/server/migrations/0113_docker_migration_execution_lease.sql +11 -0
  55. package/dist/server/migrations/0114_build_session_execution_lease_index.sql +6 -0
  56. package/dist/server/migrations/0115_orphan_target_key.sql +3 -0
  57. package/dist/server/migrations/0116_domain_ssl_challenge.sql +2 -0
  58. package/dist/server/migrations/meta/_journal.json +56 -0
  59. package/dist/{setup-I5AJC6NJ.js → setup-IFIMPQZJ.js} +12 -12
  60. package/dist/{ssh-client-625VWGKP.js → ssh-client-2XWZCMGI.js} +2 -2
  61. package/dist/up-HQS7IR7H.js +61 -0
  62. package/package.json +1 -1
  63. package/dist/bare-7QD623QV.js +0 -29
  64. package/dist/cloud-KNNABE3O.js +0 -40
  65. package/dist/edge-import-CRFVSR6P.js +0 -56
  66. package/dist/host-channel-preflight-QTDNGLCK.js +0 -54
  67. package/dist/up-QXTOOVXC.js +0 -61
@@ -10,28 +10,28 @@ import {
10
10
  readComposeEnvFile,
11
11
  resolveLocalEnvironmentSync,
12
12
  thisHost
13
- } from "./chunk-VQM6JHJB.js";
13
+ } from "./chunk-5UXHT6ED.js";
14
14
  import {
15
15
  OS_DIR
16
16
  } from "./chunk-ELGRMZOW.js";
17
17
  import {
18
18
  systemCatalog
19
- } from "./chunk-ZPJ74LXE.js";
19
+ } from "./chunk-NIYD7MD2.js";
20
20
  import {
21
21
  EDGE_CONTAINER_MOUNTS,
22
22
  EDGE_HOST_STATE_DIR
23
- } from "./chunk-QHMDCYZ3.js";
23
+ } from "./chunk-7PEXM2UI.js";
24
24
  import {
25
25
  DEFAULT_DOCKER_SOCKET_PATH,
26
26
  resolveLocalDockerSocketPath
27
- } from "./chunk-LHFXSC36.js";
27
+ } from "./chunk-3MP6ACKM.js";
28
28
  import {
29
29
  LocalExecutor
30
- } from "./chunk-E2X26PXR.js";
30
+ } from "./chunk-T6DVUX4F.js";
31
31
  import {
32
32
  invalidateEdgeContainer,
33
33
  sanitizeEdgeVhosts
34
- } from "./chunk-GIPJNNI5.js";
34
+ } from "./chunk-X53JXRS4.js";
35
35
  import {
36
36
  DEFAULT_IMAGE_REGISTRY,
37
37
  HOST_CHANNEL_BLOCKED,
@@ -51,7 +51,7 @@ import {
51
51
  hostFirewallRule,
52
52
  hostFirewallRuleRemoval,
53
53
  wrapText
54
- } from "./chunk-2VSW6Q6C.js";
54
+ } from "./chunk-WEZFTL4V.js";
55
55
 
56
56
  // src/lib/host-channel-preflight.ts
57
57
  import { spawnSync as spawnSync4 } from "child_process";
@@ -66,13 +66,14 @@ import {
66
66
  existsSync as existsSync4,
67
67
  mkdirSync as mkdirSync3,
68
68
  readFileSync as readFileSync3,
69
+ realpathSync,
69
70
  renameSync,
70
71
  rmSync,
71
72
  statSync,
72
73
  writeFileSync as writeFileSync2
73
74
  } from "fs";
74
75
  import { homedir, userInfo } from "os";
75
- import { dirname, join as join4, resolve as resolve2 } from "path";
76
+ import { dirname, join as join4, relative, resolve as resolve2 } from "path";
76
77
 
77
78
  // src/lib/ports.ts
78
79
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -400,8 +401,30 @@ async function rebuildFromSource(info) {
400
401
  // src/lib/compose.ts
401
402
  var EDGE_SITES_HOST_DIR = `${EDGE_HOST_STATE_DIR}/sites-enabled`;
402
403
  var EDGE_ACME_HOST_DIR = `${EDGE_HOST_STATE_DIR}/acme`;
404
+ function canonicalComposeHostPath(target, platform = process.platform, resolvePath = realpathSync) {
405
+ if (platform !== "darwin") return target;
406
+ try {
407
+ return resolvePath(target);
408
+ } catch {
409
+ let parent = target;
410
+ while (parent !== dirname(parent)) {
411
+ parent = dirname(parent);
412
+ try {
413
+ return join4(resolvePath(parent), relative(parent, target));
414
+ } catch {
415
+ }
416
+ }
417
+ throw new Error(`Could not resolve edge bind-mount source ${target} on this Mac.`);
418
+ }
419
+ }
420
+ function composeEdgeMounts() {
421
+ return EDGE_CONTAINER_MOUNTS.map((mount) => ({
422
+ ...mount,
423
+ host: canonicalComposeHostPath(mount.host)
424
+ }));
425
+ }
403
426
  function edgeVolumeYaml(indent) {
404
- return EDGE_CONTAINER_MOUNTS.map((m) => `${indent}- ${m.host}:${m.container}:z`).join("\n");
427
+ return composeEdgeMounts().map((m) => `${indent}- ${m.host}:${m.container}:z`).join("\n");
405
428
  }
406
429
  var DOCKER_CONFIG_MOUNT_MARKER = "__OPENSHIP_DOCKER_CONFIG_MOUNT__";
407
430
  function dockerConfigMountYaml(indent) {
@@ -1604,7 +1627,7 @@ function operatorEnvPassthrough(managed, prev) {
1604
1627
  }
1605
1628
  var PRESERVED_ENV_HEADER = "# Preserved from your existing .env \u2014 set by you, not by `openship up` (#485).";
1606
1629
  function resolveImageVersion(opts) {
1607
- return opts.version?.trim() || process.env.OPENSHIP_VERSION?.trim() || (true ? "0.6.7" : "latest");
1630
+ return opts.version?.trim() || process.env.OPENSHIP_VERSION?.trim() || (true ? "0.6.8" : "latest");
1608
1631
  }
1609
1632
  function managedEnvLines(opts, host, cfg, prev) {
1610
1633
  const lines = [
@@ -1774,7 +1797,7 @@ function composePlan(opts) {
1774
1797
  secretRotation: opts.resetSecrets ? null : secretRotationRisk(prev),
1775
1798
  pgDataRisk: pgDataDetectionRisk(prev),
1776
1799
  existing: Object.keys(prev).length > 0,
1777
- mountDirs: EDGE_CONTAINER_MOUNTS.map((m) => m.host),
1800
+ mountDirs: composeEdgeMounts().map((m) => m.host),
1778
1801
  buildDir,
1779
1802
  hostChannel
1780
1803
  };
@@ -1854,7 +1877,7 @@ function composePrefetch(opts) {
1854
1877
  }
1855
1878
  function ensureEdgeMountDirs() {
1856
1879
  const failed = [];
1857
- for (const { host } of EDGE_CONTAINER_MOUNTS) {
1880
+ for (const { host } of composeEdgeMounts()) {
1858
1881
  try {
1859
1882
  mkdirSync3(host, { recursive: true });
1860
1883
  } catch (err) {
@@ -134,10 +134,10 @@ import {
134
134
  } from "./chunk-ZWLDLTJP.js";
135
135
  import {
136
136
  CloudRuntime
137
- } from "./chunk-CIJV43LH.js";
137
+ } from "./chunk-MUWVC5R4.js";
138
138
  import {
139
139
  OPENRESTY_DEFAULT_PATHS
140
- } from "./chunk-QHMDCYZ3.js";
140
+ } from "./chunk-7PEXM2UI.js";
141
141
  import {
142
142
  DockerRuntime,
143
143
  daemonConnectionFrom,
@@ -146,26 +146,26 @@ import {
146
146
  resolveExecExitCode,
147
147
  startAttachStream,
148
148
  startExecStream
149
- } from "./chunk-LHFXSC36.js";
149
+ } from "./chunk-3MP6ACKM.js";
150
150
  import {
151
151
  BareRuntime
152
- } from "./chunk-S6B2Z3OO.js";
152
+ } from "./chunk-ENKJ7XIF.js";
153
153
  import {
154
154
  createExecutor
155
- } from "./chunk-GGIAIGUL.js";
155
+ } from "./chunk-UAWY6X7V.js";
156
156
  import {
157
157
  envOps
158
- } from "./chunk-BLEXTYRK.js";
158
+ } from "./chunk-GNOMEMNI.js";
159
159
  import {
160
160
  ENVIRONMENT_PROBE_SCRIPT,
161
161
  ENVIRONMENT_PROBE_TIMEOUT_MS,
162
162
  cacheEnvironment,
163
163
  parseEnvironmentProbe,
164
164
  profileIsFresh
165
- } from "./chunk-FZ6QCF6B.js";
165
+ } from "./chunk-NPSRGIHV.js";
166
166
  import {
167
167
  MAIL_HOST_STATE_DIR
168
- } from "./chunk-UWEV6XTS.js";
168
+ } from "./chunk-D6HU4VUZ.js";
169
169
  import {
170
170
  FAMILY_BY_DISTRO,
171
171
  isAwsS3Endpoint,
@@ -177,7 +177,7 @@ import {
177
177
  validateBackupPath,
178
178
  validateClearPath,
179
179
  withTimeout
180
- } from "./chunk-2VSW6Q6C.js";
180
+ } from "./chunk-WEZFTL4V.js";
181
181
 
182
182
  // ../../packages/adapters/src/runtime/image-transfer.ts
183
183
  import { Transform } from "stream";
@@ -13,11 +13,14 @@ import {
13
13
  resolveDockerRootDirectory,
14
14
  resolveDockerfileCandidates,
15
15
  resolveWithinDirectory
16
- } from "./chunk-H4FS5BED.js";
16
+ } from "./chunk-AHJYP7DG.js";
17
17
  import {
18
18
  getTarCreateEnv,
19
19
  prepareSourceTarArgs
20
- } from "./chunk-2ANV5ZQ5.js";
20
+ } from "./chunk-VAI5VOOI.js";
21
+ import {
22
+ isValidEnvKey
23
+ } from "./chunk-WEZFTL4V.js";
21
24
  import {
22
25
  __commonJS,
23
26
  __toESM
@@ -481,6 +484,21 @@ var require_ignore = __commonJS({
481
484
  }
482
485
  });
483
486
 
487
+ // ../../packages/adapters/src/runtime/docker-build-args.ts
488
+ function resolveDockerBuildArgs(config) {
489
+ const invalidExplicit = Object.keys(config.buildArgs ?? {}).filter((key) => !isValidEnvKey(key));
490
+ if (invalidExplicit.length > 0) {
491
+ throw new Error(`Invalid Docker build argument name(s): ${invalidExplicit.join(", ")}`);
492
+ }
493
+ const inherited = Object.fromEntries(
494
+ Object.entries({
495
+ ...config.envVars,
496
+ NODE_ENV: "production"
497
+ }).filter(([key]) => isValidEnvKey(key))
498
+ );
499
+ return { ...inherited, ...config.buildArgs };
500
+ }
501
+
484
502
  // ../../packages/adapters/src/runtime/docker-buildkit-trace.ts
485
503
  var WIRE_VARINT = 0;
486
504
  var WIRE_64BIT = 1;
@@ -1037,6 +1055,7 @@ async function createDockerBuildContext(config, opts) {
1037
1055
  }
1038
1056
 
1039
1057
  export {
1058
+ resolveDockerBuildArgs,
1040
1059
  BuildKitTraceDecoder,
1041
1060
  prepareSourceTree,
1042
1061
  missingContextDockerfileMessage,
@@ -5,19 +5,23 @@ const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  envOps,
7
7
  opScript
8
- } from "./chunk-BLEXTYRK.js";
8
+ } from "./chunk-GNOMEMNI.js";
9
9
  import {
10
10
  resolveEnvironment
11
- } from "./chunk-FZ6QCF6B.js";
11
+ } from "./chunk-NPSRGIHV.js";
12
12
  import {
13
13
  sq
14
- } from "./chunk-H3WT3A6R.js";
14
+ } from "./chunk-P7RCYELG.js";
15
+ import {
16
+ describeProcess,
17
+ probeListeningPortOwners
18
+ } from "./chunk-BO6CY4V2.js";
15
19
  import {
16
20
  SYSTEM,
17
21
  answered,
18
22
  refused,
19
23
  safeErrorMessage
20
- } from "./chunk-2VSW6Q6C.js";
24
+ } from "./chunk-WEZFTL4V.js";
21
25
 
22
26
  // ../../packages/adapters/src/infra/openresty-lua.ts
23
27
  import { createHash, randomBytes } from "crypto";
@@ -240,6 +244,184 @@ var EDGE_NOT_FOUND_LOCATION = ` server_tokens off;
240
244
  return 404 '${EDGE_NOT_FOUND_HTML}';
241
245
  }`;
242
246
 
247
+ // ../../packages/adapters/src/infra/openresty-reload.ts
248
+ var NGINX_MASTER_RE = /\b(?:nginx|openresty)\s*:\s*master process/i;
249
+ var NGINX_WORKER_RE = /\b(?:nginx|openresty)\s*:\s*worker process/i;
250
+ var NGINX_PROCESS_RE = /\b(?:nginx|openresty)\b/i;
251
+ async function canonicalRemotePath(executor, path) {
252
+ const resolved = await executor.exec(`readlink -f ${sq(path)} 2>/dev/null || true`, { timeout: 5e3 }).catch(() => "");
253
+ return resolved.trim() || null;
254
+ }
255
+ function explicitNginxConfig(rawCommand) {
256
+ const match = rawCommand.match(/(?:^|\s)-c(?:(?:\s+|=)(?:"([^"]+)"|'([^']+)'|(\S+))|(\S+))/);
257
+ if (!match) return void 0;
258
+ const value = match[1] ?? match[2] ?? match[3] ?? match[4] ?? "";
259
+ return value.startsWith("/") ? value : null;
260
+ }
261
+ function hasExplicitNginxPrefix(rawCommand) {
262
+ return /(?:^|\s)-p(?:\s+|=|\S)/.test(rawCommand);
263
+ }
264
+ async function processStartTime(executor, pid) {
265
+ const value = await executor.exec(
266
+ `awk '{ line=$0; sub(/^.*\\) /, "", line); split(line, fields, " "); print fields[20] }' /proc/${pid}/stat 2>/dev/null || true`,
267
+ { timeout: 5e3 }
268
+ ).catch(() => "");
269
+ return /^\d+$/.test(value.trim()) ? value.trim() : null;
270
+ }
271
+ async function verifyNginxProcessIdentity(executor, occupant, paths) {
272
+ if (!occupant.pid) return "unknown";
273
+ const rawCommand = occupant.rawCommand?.trim();
274
+ if (!rawCommand || !NGINX_MASTER_RE.test(rawCommand)) return "unknown";
275
+ const [actualExe, expectedExe] = await Promise.all([
276
+ canonicalRemotePath(executor, `/proc/${occupant.pid}/exe`),
277
+ canonicalRemotePath(executor, paths.bin)
278
+ ]);
279
+ if (!actualExe || !expectedExe) return "unknown";
280
+ if (actualExe !== expectedExe) return "foreign";
281
+ if (hasExplicitNginxPrefix(rawCommand)) return "unknown";
282
+ const explicitConfig = explicitNginxConfig(rawCommand);
283
+ if (explicitConfig === null) return "unknown";
284
+ const effectiveConfig = explicitConfig ?? paths.compiledConfPath;
285
+ const [actualConfig, expectedConfig] = await Promise.all([
286
+ canonicalRemotePath(executor, effectiveConfig),
287
+ canonicalRemotePath(executor, paths.confPath)
288
+ ]);
289
+ if (!actualConfig || !expectedConfig || actualConfig !== expectedConfig) return "unknown";
290
+ return "match";
291
+ }
292
+ async function resolveListeningNginxMaster(executor, occupant) {
293
+ const description = `${occupant.rawCommand ?? ""} ${occupant.command}`;
294
+ if (!occupant.pid || !NGINX_WORKER_RE.test(description)) return occupant;
295
+ const rawParent = await executor.exec(`awk '/^PPid:/{print $2}' /proc/${occupant.pid}/status 2>/dev/null || true`).catch(() => "");
296
+ const parentPid = Number.parseInt(rawParent.trim(), 10);
297
+ if (!Number.isInteger(parentPid) || parentPid <= 1) return occupant;
298
+ const parent = await describeProcess(executor, parentPid).catch(() => null);
299
+ if (!parent) return occupant;
300
+ const parentDescription = `${parent.rawCommand ?? ""} ${parent.command}`;
301
+ return NGINX_MASTER_RE.test(parentDescription) ? parent : occupant;
302
+ }
303
+ async function reloadBareOpenResty(executor, paths, opts = {}) {
304
+ await executor.exec(`${sq(paths.bin)} -t -c ${sq(paths.confPath)} 2>&1`, {
305
+ timeout: 15e3
306
+ });
307
+ const listenerStates = await Promise.all([
308
+ probeListeningPortOwners(executor, 80),
309
+ probeListeningPortOwners(executor, 443)
310
+ ]);
311
+ if (listenerStates.some((state) => !state.checked)) {
312
+ throw new Error(
313
+ "OpenResty config is valid, but the port 80/443 listener probe was inconclusive; refusing to assume the managed daemon is stopped."
314
+ );
315
+ }
316
+ if (listenerStates.some((state) => !state.ownershipComplete)) {
317
+ throw new Error(
318
+ "OpenResty config is valid, but every listener on port 80/443 could not be identified; refusing to signal an unknown or mixed owner."
319
+ );
320
+ }
321
+ const occupants = listenerStates.flatMap((state) => state.occupants);
322
+ const verifiedMasters = /* @__PURE__ */ new Map();
323
+ let foreignListenerOwner = false;
324
+ let ambiguousNginxOwner = false;
325
+ let containerBackedNginxOwner = false;
326
+ for (const occupant of occupants) {
327
+ if (!occupant.rawCommand?.trim()) {
328
+ ambiguousNginxOwner = true;
329
+ continue;
330
+ }
331
+ const description = [
332
+ occupant.rawCommand,
333
+ occupant.command,
334
+ occupant.systemdUnit,
335
+ occupant.systemdDescription
336
+ ].filter(Boolean).join(" ");
337
+ if (!NGINX_PROCESS_RE.test(description)) {
338
+ foreignListenerOwner = true;
339
+ continue;
340
+ }
341
+ if (occupant.containerId) {
342
+ containerBackedNginxOwner = true;
343
+ continue;
344
+ }
345
+ const master = await resolveListeningNginxMaster(executor, occupant);
346
+ if (master.containerId) {
347
+ containerBackedNginxOwner = true;
348
+ continue;
349
+ }
350
+ const initialIdentity = await verifyNginxProcessIdentity(executor, master, paths);
351
+ if (initialIdentity === "foreign") {
352
+ foreignListenerOwner = true;
353
+ continue;
354
+ }
355
+ if (initialIdentity === "unknown" || !master.pid) {
356
+ ambiguousNginxOwner = true;
357
+ continue;
358
+ }
359
+ if (master.cgroupVerified !== true || !master.processCgroup) {
360
+ ambiguousNginxOwner = true;
361
+ continue;
362
+ }
363
+ const startTime = await processStartTime(executor, master.pid);
364
+ if (!startTime) {
365
+ ambiguousNginxOwner = true;
366
+ continue;
367
+ }
368
+ const refreshedMaster = await describeProcess(executor, master.pid).catch(() => null);
369
+ const confirmedStartTime = await processStartTime(executor, master.pid);
370
+ if (!refreshedMaster || confirmedStartTime !== startTime || refreshedMaster.cgroupVerified !== true || !refreshedMaster.processCgroup) {
371
+ ambiguousNginxOwner = true;
372
+ continue;
373
+ }
374
+ if (refreshedMaster.containerId) {
375
+ containerBackedNginxOwner = true;
376
+ continue;
377
+ }
378
+ const identity = await verifyNginxProcessIdentity(executor, refreshedMaster, paths);
379
+ if (identity !== "match") {
380
+ ambiguousNginxOwner = true;
381
+ continue;
382
+ }
383
+ verifiedMasters.set(master.pid, {
384
+ pid: master.pid,
385
+ startTime,
386
+ processCgroup: refreshedMaster.processCgroup
387
+ });
388
+ }
389
+ if (containerBackedNginxOwner) {
390
+ throw new Error(
391
+ "A container-backed nginx/OpenResty listener owns port 80/443; refusing to signal it from bare-host reload."
392
+ );
393
+ }
394
+ if (ambiguousNginxOwner) {
395
+ throw new Error(
396
+ "A live nginx/OpenResty listener was found, but its executable and configuration could not be verified, or its host ownership could not be proven; refusing to signal an ambiguous process."
397
+ );
398
+ }
399
+ if (foreignListenerOwner) {
400
+ throw new Error(
401
+ verifiedMasters.size > 0 ? "The managed OpenResty master shares ports 80/443 with a foreign listener; refusing a reload that cannot apply the validated configuration safely." : "A foreign listener owns port 80/443; refusing to treat a live daemon as stopped or report the managed route reload as complete."
402
+ );
403
+ }
404
+ if (verifiedMasters.size === 0) {
405
+ if (opts.allowStopped && occupants.length === 0) return;
406
+ const owners = occupants.map((occupant) => occupant.command).filter(Boolean);
407
+ throw new Error(
408
+ "OpenResty config is valid, but no verified bare-host master is listening on port 80/443" + (owners.length > 0 ? ` (found: ${owners.join(", ")})` : "") + "; refusing to start a second daemon."
409
+ );
410
+ }
411
+ if (verifiedMasters.size !== 1) {
412
+ throw new Error(
413
+ `Found ${verifiedMasters.size} verified nginx/OpenResty masters on ports 80/443; refusing an ambiguous reload.`
414
+ );
415
+ }
416
+ const target = [...verifiedMasters.values()][0];
417
+ await executor.exec(
418
+ `current_exe=$(readlink -f /proc/${target.pid}/exe 2>/dev/null || true); expected_exe=$(readlink -f ${sq(paths.bin)} 2>/dev/null || true); current_start=$(awk '{ line=$0; sub(/^.*\\) /, "", line); split(line, fields, " "); print fields[20] }' /proc/${target.pid}/stat 2>/dev/null || true); current_cgroup=$(cat /proc/${target.pid}/cgroup 2>/dev/null) || { echo "nginx master cgroup became unreadable; refusing reload" >&2; exit 1; }; [ -n "$current_exe" ] && [ "$current_exe" = "$expected_exe" ] && [ "$current_start" = ${sq(target.startTime)} ] && [ -n "$current_cgroup" ] && [ "$current_cgroup" = ${sq(target.processCgroup)} ] || { echo "nginx master identity changed; refusing reload" >&2; exit 1; }; kill -HUP ${target.pid}`,
419
+ { timeout: 5e3 }
420
+ ).catch((err) => {
421
+ throw new Error(`Safe bare-host OpenResty reload failed: ${safeErrorMessage(err)}`);
422
+ });
423
+ }
424
+
243
425
  // ../../packages/adapters/src/infra/openresty-lua.ts
244
426
  var OPENRESTY_LUA_DIR = "/usr/local/openresty/site/lualib/openship";
245
427
  var LUA_LOGGER_PATH = `${OPENRESTY_LUA_DIR}/site_logger.lua`;
@@ -293,6 +475,7 @@ function parseNginxVersion(raw) {
293
475
  }
294
476
  var OPENRESTY_DEFAULT_PATHS = {
295
477
  bin: "/usr/local/openresty/bin/openresty",
478
+ compiledConfPath: "/usr/local/openresty/nginx/conf/nginx.conf",
296
479
  confPath: "/usr/local/openresty/nginx/conf/nginx.conf",
297
480
  confDir: "/usr/local/openresty/nginx/conf",
298
481
  sitesDir: "/usr/local/openresty/nginx/conf/sites-enabled",
@@ -316,6 +499,7 @@ var EDGE_SAME_PATH_MOUNTS = EDGE_CONTAINER_MOUNTS.filter(
316
499
  ).map((m) => m.host.replace(/\/+$/, ""));
317
500
  var EDGE_HOST_PATHS = {
318
501
  bin: OPENRESTY_DEFAULT_PATHS.bin,
502
+ compiledConfPath: OPENRESTY_DEFAULT_PATHS.compiledConfPath,
319
503
  confPath: OPENRESTY_DEFAULT_PATHS.confPath,
320
504
  confDir: OPENRESTY_DEFAULT_PATHS.confDir,
321
505
  sitesDir: `${EDGE_HOST_STATE_DIR}/sites-enabled`,
@@ -333,7 +517,8 @@ async function detectOpenRestyPaths(executor) {
333
517
  return m ? m[1] : null;
334
518
  };
335
519
  const bin = parseFlag("sbin-path") ?? OPENRESTY_DEFAULT_PATHS.bin;
336
- let confPath = parseFlag("conf-path") ?? OPENRESTY_DEFAULT_PATHS.confPath;
520
+ const compiledConfPath = parseFlag("conf-path") ?? OPENRESTY_DEFAULT_PATHS.compiledConfPath;
521
+ let confPath = compiledConfPath;
337
522
  const pidPath = parseFlag("pid-path") ?? OPENRESTY_DEFAULT_PATHS.pidPath;
338
523
  if (!await executor.exists(confPath)) {
339
524
  let found = false;
@@ -351,6 +536,7 @@ async function detectOpenRestyPaths(executor) {
351
536
  const nginxVersion = parseNginxVersion(raw);
352
537
  return {
353
538
  bin,
539
+ compiledConfPath,
354
540
  confPath,
355
541
  confDir,
356
542
  sitesDir: `${confDir}/sites-enabled`,
@@ -358,28 +544,11 @@ async function detectOpenRestyPaths(executor) {
358
544
  ...nginxVersion ? { nginxVersion } : {}
359
545
  };
360
546
  }
361
- function buildReloadCommand(paths, opts = {}) {
362
- if (opts.containerEdge) {
363
- return `${paths.bin} -t 2>&1 || exit 1
364
- ${paths.bin} -s reload 2>&1 || exit 1`;
365
- }
366
- return `${paths.bin} -t 2>&1 || exit 1
367
-
368
- reload_err=$(${paths.bin} -s reload 2>&1) && exit 0
369
-
370
- if [ "$(cat /proc/1/comm 2>/dev/null)" = "openresty" ] || [ "$(cat /proc/1/comm 2>/dev/null)" = "nginx" ]; then
371
- echo "openresty reload failed and openresty is PID 1 (containerized edge) \u2014 not killing it; the container supervisor owns restarts." >&2
372
- echo "$reload_err" >&2
373
- exit 1
374
- fi
375
-
376
- if [ -f ${paths.pidPath} ] && kill -0 "$(cat ${paths.pidPath} 2>/dev/null)" 2>/dev/null; then
377
- echo "openresty (pid $(cat ${paths.pidPath})) is running but refused -s reload" >&2
378
- exit 1
379
- fi
380
-
381
- rm -f ${paths.pidPath}
382
- ${paths.bin}`;
547
+ function buildReloadCommand(paths) {
548
+ const bin = sq(paths?.bin || "openresty");
549
+ const config = sq(paths?.confPath || "/etc/openresty/nginx.conf");
550
+ return `${bin} -t -c ${config} 2>&1 || exit 1
551
+ ${bin} -s reload -c ${config} 2>&1 || exit 1`;
383
552
  }
384
553
  async function ensureEdgeDefaultCert(executor, confDir) {
385
554
  const { dir, certPath, keyPath } = edgeDefaultCertPaths(confDir);
@@ -422,10 +591,7 @@ async function ensureOpenRestyConfig(executor, paths) {
422
591
  await executor.writeFile(`${paths.sitesDir}/_default.conf`, edgeDefaultCatchAllConf(defaultCert));
423
592
  if (!await executor.exists(paths.confPath)) {
424
593
  await executor.mkdir(paths.confDir);
425
- await executor.writeFile(
426
- paths.confPath,
427
- MINIMAL_NGINX_CONF(paths.confDir, paths.sitesDir)
428
- );
594
+ await executor.writeFile(paths.confPath, MINIMAL_NGINX_CONF(paths.confDir, paths.sitesDir));
429
595
  return;
430
596
  }
431
597
  const hasCorrectInclude = await executor.exec(`grep -qF 'include ${paths.sitesDir}/' ${paths.confPath}`).then(() => true).catch(() => false);
@@ -518,11 +684,11 @@ var ACME_CHALLENGE_LOCATION = ` location ^~ /.well-known/acme-challenge/ {
518
684
  }`;
519
685
  var EDGE_CHALLENGE_URL_PREFIX = "/.well-known/oblien-proxy-challenge/";
520
686
  var EDGE_CHALLENGE_ROOT = "/var/www/acme/oblien";
521
- var EDGE_CHALLENGE_DIR = `${EDGE_CHALLENGE_ROOT}${EDGE_CHALLENGE_URL_PREFIX}`.replace(/\/$/, "");
522
- var EDGE_CHALLENGE_HOST_DIR = `${EDGE_HOST_STATE_DIR}/acme/oblien${EDGE_CHALLENGE_URL_PREFIX}`.replace(
687
+ var EDGE_CHALLENGE_DIR = `${EDGE_CHALLENGE_ROOT}${EDGE_CHALLENGE_URL_PREFIX}`.replace(
523
688
  /\/$/,
524
689
  ""
525
690
  );
691
+ var EDGE_CHALLENGE_HOST_DIR = `${EDGE_HOST_STATE_DIR}/acme/oblien${EDGE_CHALLENGE_URL_PREFIX}`.replace(/\/$/, "");
526
692
  var EDGE_CHALLENGE_LOCATION = ` location ^~ ${EDGE_CHALLENGE_URL_PREFIX} {
527
693
  root ${EDGE_CHALLENGE_ROOT};
528
694
  default_type text/plain;
@@ -635,7 +801,9 @@ async function ensureLuaScripts(executor, paths) {
635
801
  const expected = luaBundleHash();
636
802
  await executor.mkdir(OPENRESTY_LUA_DIR);
637
803
  const listing = await executor.exec(`ls -1 '${OPENRESTY_LUA_DIR}' 2>/dev/null || true`).catch(() => "");
638
- const present = new Set(listing.split("\n").map((s) => s.trim()).filter(Boolean));
804
+ const present = new Set(
805
+ listing.split("\n").map((s) => s.trim()).filter(Boolean)
806
+ );
639
807
  const missing = LUA_SCRIPTS.filter((name) => !present.has(name));
640
808
  const onBoxVersion = (await executor.readFile(LUA_VERSION_MARKER).catch(() => "")).trim();
641
809
  if (missing.length === 0 && onBoxVersion === expected) {
@@ -647,12 +815,14 @@ async function ensureLuaScripts(executor, paths) {
647
815
  await executor.writeFile(LUA_VERSION_MARKER, expected);
648
816
  const reason = missing.length ? `missing: ${missing.join(", ")}` : "version changed";
649
817
  console.warn(`[openresty] (re)installed Lua (${reason}) \u2014 reloading edge.`);
650
- await executor.exec(buildReloadCommand(paths)).catch((err) => {
818
+ await reloadBareOpenResty(executor, paths).catch((err) => {
651
819
  console.error(`[openresty] reload after Lua (re)install failed: ${safeErrorMessage(err)}`);
652
820
  });
653
821
  return { repaired: missing.length ? missing : [...LUA_SCRIPTS], available: true };
654
822
  } catch (err) {
655
- console.error(`[openresty] ensureLuaScripts failed (deploy continues): ${safeErrorMessage(err)}`);
823
+ console.error(
824
+ `[openresty] ensureLuaScripts failed (deploy continues): ${safeErrorMessage(err)}`
825
+ );
656
826
  return { repaired: [], available: false };
657
827
  }
658
828
  }
@@ -672,15 +842,15 @@ async function installGeoDeps(executor) {
672
842
  );
673
843
  });
674
844
  } else {
675
- console.warn(`[openresty] libmaxminddb not installed \u2014 geo lookups return nil: ${install.reason}`);
845
+ console.warn(
846
+ `[openresty] libmaxminddb not installed \u2014 geo lookups return nil: ${install.reason}`
847
+ );
676
848
  }
677
849
  try {
678
850
  const exists = await executor.exists(GEOIP_DB_PATH);
679
851
  if (!exists) {
680
852
  await executor.mkdir(GEOIP_DIR);
681
- await executor.exec(
682
- `curl -fsSL -o ${GEOIP_DB_PATH} "${GEOIP_DB_URL}"`
683
- );
853
+ await executor.exec(`curl -fsSL -o ${GEOIP_DB_PATH} "${GEOIP_DB_URL}"`);
684
854
  }
685
855
  } catch {
686
856
  }
@@ -694,10 +864,7 @@ async function deployLuaScripts(executor, paths) {
694
864
  }
695
865
  await executor.mkdir(OPENRESTY_LUA_DIR);
696
866
  for (const name of LUA_SCRIPTS) {
697
- await executor.writeFile(
698
- `${OPENRESTY_LUA_DIR}/${name}`,
699
- readLua(name)
700
- );
867
+ await executor.writeFile(`${OPENRESTY_LUA_DIR}/${name}`, readLua(name));
701
868
  }
702
869
  await ensureOpenRestyConfig(executor, paths);
703
870
  for (const dict of EDGE_SHARED_DICTS) {
@@ -713,12 +880,13 @@ async function deployLuaScripts(executor, paths) {
713
880
  await executor.exec(
714
881
  `grep -q '${EDGE_REAL_IP_CONF_NAME}' '${paths.confPath}' || sed -i '/http *{/a \\ include ${realIpPath};' '${paths.confPath}'`
715
882
  );
716
- await executor.exec(buildReloadCommand(paths));
883
+ await reloadBareOpenResty(executor, paths);
717
884
  }
718
885
 
719
886
  export {
720
887
  isCloudFrontedHost,
721
888
  cloudEdgeRealIpConf,
889
+ reloadBareOpenResty,
722
890
  OPENRESTY_LUA_DIR,
723
891
  LUA_LOGGER_PATH,
724
892
  RULES_GUARD_PATH,
@@ -7,20 +7,20 @@ import {
7
7
  composeInstallExists,
8
8
  readComposeEnvFile,
9
9
  startUnitHint
10
- } from "./chunk-VQM6JHJB.js";
10
+ } from "./chunk-5UXHT6ED.js";
11
11
  import {
12
12
  INTERNAL_TOKEN_FILE,
13
13
  OS_DIR
14
14
  } from "./chunk-ELGRMZOW.js";
15
15
  import {
16
16
  LocalExecutor
17
- } from "./chunk-E2X26PXR.js";
17
+ } from "./chunk-T6DVUX4F.js";
18
18
  import {
19
19
  edgeCrashReason
20
- } from "./chunk-GIPJNNI5.js";
20
+ } from "./chunk-X53JXRS4.js";
21
21
  import {
22
22
  EDGE_CONTAINER_NAME
23
- } from "./chunk-UWEV6XTS.js";
23
+ } from "./chunk-D6HU4VUZ.js";
24
24
 
25
25
  // src/lib/edge-import.ts
26
26
  import chalk from "chalk";
@@ -5,7 +5,7 @@ const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  getTarCreateEnv,
7
7
  prepareSourceTarArgs
8
- } from "./chunk-2ANV5ZQ5.js";
8
+ } from "./chunk-VAI5VOOI.js";
9
9
  import {
10
10
  TRANSFER_EXCLUDES,
11
11
  nodeBinDirs,
@@ -13,23 +13,25 @@ import {
13
13
  packageManagerEnsureCommand,
14
14
  safeErrorMessage,
15
15
  shellQuote
16
- } from "./chunk-2VSW6Q6C.js";
16
+ } from "./chunk-WEZFTL4V.js";
17
17
 
18
18
  // ../../packages/adapters/src/runtime/git-clone.ts
19
19
  var sq = shellQuote;
20
+ function gitCredentialPair(hostname, token) {
21
+ if (hostname === "github.com" && !token.startsWith("ghs_")) {
22
+ return { username: token, password: "x-oauth-basic" };
23
+ }
24
+ return { username: "x-access-token", password: token };
25
+ }
20
26
  function injectGitToken(repoUrl, token) {
21
- if (!token) return repoUrl;
27
+ const secret = token?.trim();
28
+ if (!secret) return repoUrl;
22
29
  try {
23
30
  const url = new URL(repoUrl);
24
31
  if (url.protocol !== "https:") return repoUrl;
25
- const isGitHub = /(^|\.)github\.com$/.test(url.hostname);
26
- if (isGitHub && !token.startsWith("ghs_")) {
27
- url.username = token;
28
- url.password = "";
29
- } else {
30
- url.username = "x-access-token";
31
- url.password = token;
32
- }
32
+ const { username, password } = gitCredentialPair(url.hostname, secret);
33
+ url.username = username;
34
+ url.password = password;
33
35
  return url.toString();
34
36
  } catch {
35
37
  return repoUrl;