@mesh-tech/mesh-cli 0.25.0 → 0.26.0

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 (53) hide show
  1. package/README.md +74 -246
  2. package/dist/bin/mesh.js +1415 -842
  3. package/dist/bin/mesh.js.map +3 -3
  4. package/dist/build-info.json +2 -2
  5. package/dist/src/commands/db/axes.d.ts +19 -0
  6. package/dist/src/commands/db/axes.js +35 -0
  7. package/dist/src/commands/db/connect.d.ts +2 -4
  8. package/dist/src/commands/db/connect.js +4 -19
  9. package/dist/src/commands/db/credentials.d.ts +2 -5
  10. package/dist/src/commands/db/credentials.js +7 -23
  11. package/dist/src/commands/db/env.d.ts +2 -5
  12. package/dist/src/commands/db/env.js +7 -23
  13. package/dist/src/commands/db/exec.js +7 -24
  14. package/dist/src/commands/db/psql.d.ts +2 -5
  15. package/dist/src/commands/db/psql.js +8 -23
  16. package/dist/src/commands/init/platform-setup.d.ts +68 -0
  17. package/dist/src/commands/init/platform-setup.js +203 -0
  18. package/dist/src/commands/init/wizard.d.ts +20 -0
  19. package/dist/src/commands/init/wizard.js +89 -7
  20. package/dist/src/commands/init.js +42 -36
  21. package/dist/src/commands/login.d.ts +4 -0
  22. package/dist/src/commands/login.js +16 -2
  23. package/dist/src/commands/registry.d.ts +2 -2
  24. package/dist/src/commands/registry.js +11 -6
  25. package/dist/src/commands/secrets/context.d.ts +5 -0
  26. package/dist/src/commands/secrets/context.js +5 -0
  27. package/dist/src/commands/secrets/index.js +3 -0
  28. package/dist/src/commands/secrets/migrate-config.d.ts +1 -0
  29. package/dist/src/commands/secrets/migrate-config.js +2 -3
  30. package/dist/src/commands/secrets/reindex.d.ts +1 -0
  31. package/dist/src/commands/secrets/reindex.js +2 -2
  32. package/dist/src/commands/secrets/set.d.ts +1 -0
  33. package/dist/src/commands/secrets/set.js +2 -2
  34. package/dist/src/commands/temporal.js +25 -8
  35. package/dist/src/commands/temporal.js.map +2 -2
  36. package/dist/src/commands/tunnel/index.d.ts +8 -0
  37. package/dist/src/commands/tunnel/index.js +3 -3
  38. package/dist/src/index.js +324 -62
  39. package/dist/src/index.js.map +3 -3
  40. package/dist/src/utils/context.d.ts +6 -1
  41. package/dist/src/utils/context.js +302 -39
  42. package/dist/src/utils/registry-identity.d.ts +5 -0
  43. package/dist/src/utils/registry-identity.js +16 -0
  44. package/fragments/agents/AGENTS.md.hbs +10 -2
  45. package/fragments/base/index.ts.hbs +15 -5
  46. package/package.json +2 -2
  47. package/skills/core/SKILL.md +73 -6
  48. package/templates/api-auth/index.ts.hbs +5 -4
  49. package/templates/api-role-gating/index.ts.hbs +5 -4
  50. package/templates/external-service/index.ts.hbs +5 -4
  51. package/templates/platform-repo/README.md.hbs +17 -3
  52. package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +7 -0
  53. package/templates/workflow/index.ts.hbs +5 -4
package/dist/bin/mesh.js CHANGED
@@ -126,99 +126,373 @@ var init_log = __esm({
126
126
  }
127
127
  });
128
128
 
129
- // libs/mesh-cli/src/utils/context.ts
129
+ // libs/mesh-cli/src/utils/mesh-json.ts
130
130
  import * as fs from "fs";
131
131
  import * as path from "path";
132
- function findFileUpward(filename, startDir = process.cwd()) {
132
+ function isValidTenantName(value) {
133
+ return /^[a-z][a-z0-9-]*$/.test(value);
134
+ }
135
+ function parseMeshJson(content) {
136
+ try {
137
+ const data = JSON.parse(content);
138
+ if (typeof data?.tenant !== "string" || !isValidTenantName(data.tenant)) return null;
139
+ const platform = typeof data.platform === "string" && data.platform ? data.platform : "local";
140
+ return { tenant: data.tenant, platform };
141
+ } catch {
142
+ return null;
143
+ }
144
+ }
145
+ function findMeshJson(startDir) {
146
+ let dir = path.resolve(startDir);
147
+ while (true) {
148
+ const candidate = path.join(dir, MESH_JSON);
149
+ if (fs.existsSync(candidate)) {
150
+ let content = "";
151
+ try {
152
+ content = fs.readFileSync(candidate, "utf-8");
153
+ } catch {
154
+ return null;
155
+ }
156
+ const data = parseMeshJson(content);
157
+ return data ? { path: candidate, data } : null;
158
+ }
159
+ if (fs.existsSync(path.join(dir, ".git"))) return null;
160
+ const parent = path.dirname(dir);
161
+ if (parent === dir) return null;
162
+ dir = parent;
163
+ }
164
+ }
165
+ function writeMeshJson(rootDir, data) {
166
+ const target = path.join(rootDir, MESH_JSON);
167
+ fs.writeFileSync(target, `${JSON.stringify({ tenant: data.tenant, platform: data.platform }, null, 2)}
168
+ `);
169
+ return target;
170
+ }
171
+ var MESH_JSON;
172
+ var init_mesh_json = __esm({
173
+ "libs/mesh-cli/src/utils/mesh-json.ts"() {
174
+ "use strict";
175
+ MESH_JSON = "mesh.json";
176
+ }
177
+ });
178
+
179
+ // libs/mesh-cli/src/utils/context.ts
180
+ import * as fs2 from "fs";
181
+ import * as path2 from "path";
182
+ function findFileUpwardInRepo(filename, startDir = process.cwd()) {
133
183
  let currentDir = startDir;
134
- const root = path.parse(currentDir).root;
135
- while (currentDir !== root) {
136
- const filePath = path.join(currentDir, filename);
137
- if (fs.existsSync(filePath)) {
184
+ const root = path2.parse(currentDir).root;
185
+ for (; ; ) {
186
+ const filePath = path2.join(currentDir, filename);
187
+ if (fs2.existsSync(filePath)) {
138
188
  return filePath;
139
189
  }
140
- currentDir = path.dirname(currentDir);
190
+ if (fs2.existsSync(path2.join(currentDir, ".git")) || fs2.existsSync(path2.join(currentDir, "pnpm-workspace.yaml")) || currentDir === root) {
191
+ return void 0;
192
+ }
193
+ currentDir = path2.dirname(currentDir);
194
+ }
195
+ }
196
+ function findRepoRoot(startDir) {
197
+ let currentDir = startDir;
198
+ const root = path2.parse(currentDir).root;
199
+ for (; ; ) {
200
+ if (fs2.existsSync(path2.join(currentDir, ".git")) || fs2.existsSync(path2.join(currentDir, "pnpm-workspace.yaml"))) {
201
+ return currentDir;
202
+ }
203
+ if (currentDir === root) {
204
+ return void 0;
205
+ }
206
+ currentDir = path2.dirname(currentDir);
207
+ }
208
+ }
209
+ function stripComments(source) {
210
+ let out = "";
211
+ for (let i = 0; i < source.length; i++) {
212
+ const ch = source[i];
213
+ if (ch === '"' || ch === "'" || ch === "`") {
214
+ const start = i;
215
+ i++;
216
+ while (i < source.length && source[i] !== ch) {
217
+ if (source[i] === "\\") i++;
218
+ i++;
219
+ }
220
+ out += source.slice(start, i + 1);
221
+ } else if (ch === "/" && source[i + 1] === "/") {
222
+ while (i < source.length && source[i] !== "\n") i++;
223
+ i--;
224
+ } else if (ch === "/" && source[i + 1] === "*") {
225
+ i += 2;
226
+ while (i < source.length && !(source[i] === "*" && source[i + 1] === "/")) i++;
227
+ i++;
228
+ } else {
229
+ out += ch;
230
+ }
231
+ }
232
+ return out;
233
+ }
234
+ function findExportedConfigStart(source) {
235
+ const declMatch = /export\s+(const\s+config\b|default\b)/.exec(source);
236
+ if (!declMatch) return void 0;
237
+ const start = source.indexOf("{", declMatch.index);
238
+ if (start === -1) return void 0;
239
+ const gap = source.slice(declMatch.index + declMatch[0].length, start);
240
+ if (!/^[\s=]*(:[^;{]*)?$/.test(gap)) return void 0;
241
+ return start;
242
+ }
243
+ function scanDepth1(source, start, visit) {
244
+ let depth = 0;
245
+ for (let i = start; i < source.length; i++) {
246
+ const ch = source[i];
247
+ if (ch === '"' || ch === "'" || ch === "`") {
248
+ i++;
249
+ while (i < source.length && source[i] !== ch) {
250
+ if (source[i] === "\\") i++;
251
+ i++;
252
+ }
253
+ } else if (ch === "{") {
254
+ depth++;
255
+ } else if (ch === "}") {
256
+ depth--;
257
+ if (depth === 0) return void 0;
258
+ } else if (depth === 1 && !/[\w$.]/.test(source[i - 1] ?? "")) {
259
+ const found = visit(i);
260
+ if (found !== void 0) return found;
261
+ }
262
+ }
263
+ return void 0;
264
+ }
265
+ function extractConfigTenant(rawSource) {
266
+ const source = stripComments(rawSource);
267
+ const start = findExportedConfigStart(source);
268
+ if (start === void 0) return void 0;
269
+ const tenantRe = /tenant\s*:\s*(["'])([^"'\n]+)\1/y;
270
+ return scanDepth1(source, start, (i) => {
271
+ tenantRe.lastIndex = i;
272
+ return tenantRe.exec(source)?.[2];
273
+ });
274
+ }
275
+ function matchBlock(source, open) {
276
+ let depth = 0;
277
+ for (let i = open; i < source.length; i++) {
278
+ const ch = source[i];
279
+ if (ch === '"' || ch === "'" || ch === "`") {
280
+ i++;
281
+ while (i < source.length && source[i] !== ch) {
282
+ if (source[i] === "\\") i++;
283
+ i++;
284
+ }
285
+ } else if (ch === "{") {
286
+ depth++;
287
+ } else if (ch === "}") {
288
+ depth--;
289
+ if (depth === 0) return source.slice(open, i + 1);
290
+ }
141
291
  }
142
292
  return void 0;
143
293
  }
144
- function detectContext(stageArg) {
294
+ function extractExportedConfigSource(cleanedSource) {
295
+ const start = findExportedConfigStart(cleanedSource);
296
+ return start === void 0 ? void 0 : matchBlock(cleanedSource, start);
297
+ }
298
+ function extractPlatformBlock(cleanedSource) {
299
+ const start = findExportedConfigStart(cleanedSource);
300
+ if (start === void 0) return void 0;
301
+ const platformRe = /platform\s*:\s*\{/y;
302
+ let open;
303
+ scanDepth1(cleanedSource, start, (i) => {
304
+ platformRe.lastIndex = i;
305
+ if (platformRe.exec(cleanedSource)) {
306
+ open = platformRe.lastIndex - 1;
307
+ return true;
308
+ }
309
+ return void 0;
310
+ });
311
+ if (open === void 0) return void 0;
312
+ return matchBlock(cleanedSource, open);
313
+ }
314
+ function pickStackFile(files, hint, explicitStack) {
315
+ if (explicitStack !== void 0) {
316
+ const wanted = `Pulumi.${explicitStack}.yaml`;
317
+ return { file: files.includes(wanted) ? wanted : void 0, qualified: true };
318
+ }
319
+ if (hint) {
320
+ const wanted = `Pulumi.${hint}.yaml`;
321
+ if (files.includes(wanted)) return { file: wanted, qualified: true };
322
+ }
323
+ const stageOf = (f) => f.slice("Pulumi.".length, -".yaml".length);
324
+ const byBaseFirst = [...files].sort(
325
+ (a, b) => stageOf(a).length - stageOf(b).length || a.localeCompare(b)
326
+ );
327
+ return { file: byBaseFirst[0], qualified: false };
328
+ }
329
+ function tenantNotDeclared(cwd, found) {
330
+ const looked = found.stackFile ? `${found.stackFile} in ${cwd} does not declare mesh:tenant` : found.hasProjectFile ? `${cwd} has a Pulumi.yaml but no Pulumi.<stack>.yaml to read mesh:tenant from` : `${cwd} is not a Pulumi project directory (no Pulumi.yaml)`;
331
+ return new MeshCliError(
332
+ `No tenant declared: ${looked}, and MESH_TENANT is not set. There is no default tenant \u2014 "mesh" is the live hub and is never assumed. Run from a directory whose Pulumi.<stack>.yaml declares mesh:tenant, set MESH_TENANT, or pass --tenant where the command accepts one.`,
333
+ {
334
+ remediation: {
335
+ command: "MESH_TENANT=<tenant> mesh \u2026 # or --tenant <tenant> where accepted, or run from a directory whose Pulumi.<stack>.yaml declares mesh:tenant"
336
+ }
337
+ }
338
+ );
339
+ }
340
+ function detectContext(stageArg, options = {}) {
145
341
  let tenant;
146
342
  let stage;
147
343
  const cwd = process.cwd();
148
- if (fs.existsSync("Pulumi.yaml")) {
149
- const files = fs.readdirSync(".").filter(
150
- (f) => f.startsWith("Pulumi.") && f.endsWith(".yaml") && f !== "Pulumi.yaml"
151
- );
152
- const configFile = files[0];
153
- if (configFile) {
154
- const content = fs.readFileSync(configFile, "utf-8");
155
- const tenantMatch = content.match(/^\s*mesh:tenant:\s*["']?([^"'\n]+)["']?/m);
344
+ const stageHint = stageArg || process.env.MESH_STAGE || process.env.SST_STAGE;
345
+ let hasProjectFile = false;
346
+ let stackFile;
347
+ let stackFilesHere = [];
348
+ let namedStackMissing = false;
349
+ if (fs2.existsSync("Pulumi.yaml")) {
350
+ hasProjectFile = true;
351
+ const files = fs2.readdirSync(".").filter((f) => f.startsWith("Pulumi.") && f.endsWith(".yaml") && f !== "Pulumi.yaml").sort();
352
+ const picked = pickStackFile(files, stageHint, options.stack);
353
+ stackFile = picked.file;
354
+ namedStackMissing = options.stack !== void 0 && picked.file === void 0;
355
+ stackFilesHere = files;
356
+ if (!picked.qualified && files.length > 1) {
357
+ const lengths = files.map((f) => f.length - "Pulumi..yaml".length).sort((a, b) => a - b);
358
+ if (lengths[0] === lengths[1]) {
359
+ logWarn(
360
+ `Several Pulumi stack configs here (${files.join(", ")}); using ${stackFile}. Pass --stack to choose one.`
361
+ );
362
+ }
363
+ }
364
+ if (stackFile) {
365
+ const content = fs2.readFileSync(stackFile, "utf-8");
366
+ const tenantMatch = content.match(/^\s*mesh:tenant:\s*["']?([^"'#\n]+)["']?/m);
156
367
  if (tenantMatch?.[1]) {
157
368
  tenant = tenantMatch[1].trim();
158
369
  }
159
- const stageMatch = configFile.match(/Pulumi\.(.+)\.yaml/);
370
+ const stageMatch = stackFile.match(/Pulumi\.(.+)\.yaml/);
160
371
  if (stageMatch?.[1]) {
161
372
  stage = stageMatch[1];
162
373
  }
163
374
  }
164
375
  }
165
- const sstConfigPath = findFileUpward("sst.config.ts");
376
+ const sstConfigPath = findFileUpwardInRepo("sst.config.ts");
166
377
  let sstDir;
167
378
  if (sstConfigPath) {
168
- sstDir = path.dirname(sstConfigPath);
169
- const parentConfigPath = path.join(sstDir, "..", "config.ts");
170
- if (fs.existsSync(parentConfigPath)) {
171
- const configContent = fs.readFileSync(parentConfigPath, "utf-8");
172
- const tenantMatch = configContent.match(/tenant:\s*["']([^"']+)["']/);
173
- if (tenantMatch) {
174
- tenant = tenantMatch[1];
175
- }
176
- }
177
- const sstStagePath = path.join(sstDir, ".sst", "stage");
178
- if (fs.existsSync(sstStagePath)) {
179
- stage = fs.readFileSync(sstStagePath, "utf-8").trim();
180
- }
181
- }
182
- if (!tenant) {
183
- const pathMatch = cwd.match(/tenants\/([^/]+)/);
379
+ sstDir = path2.dirname(sstConfigPath);
380
+ const sstStagePath = path2.join(sstDir, ".sst", "stage");
381
+ if (fs2.existsSync(sstStagePath)) {
382
+ stage = fs2.readFileSync(sstStagePath, "utf-8").trim();
383
+ }
384
+ }
385
+ const repoRoot2 = findRepoRoot(cwd);
386
+ const parentConfigPath = (sstDir ? [path2.join(sstDir, "config.ts"), path2.join(sstDir, "..", "config.ts")] : hasProjectFile ? [path2.resolve(cwd, "..", "config.ts")] : []).filter(
387
+ // Fail closed when no checkout root is found — same stance as the
388
+ // no-tenant throw: an arbitrary config.ts is not a context source.
389
+ (p) => repoRoot2 !== void 0 && !path2.relative(repoRoot2, p).startsWith("..")
390
+ ).find((p) => fs2.existsSync(p));
391
+ const parentConfig = parentConfigPath ? fs2.readFileSync(parentConfigPath, "utf-8") : void 0;
392
+ if (parentConfig && !tenant) {
393
+ tenant = extractConfigTenant(parentConfig);
394
+ }
395
+ if (!tenant && repoRoot2) {
396
+ const pathMatch = path2.relative(repoRoot2, cwd).match(/(?:^|\/)tenants\/([^/]+)/);
184
397
  if (pathMatch) {
185
398
  tenant = pathMatch[1];
186
399
  }
187
400
  }
188
- stage = stageArg || process.env.MESH_STAGE || process.env.SST_STAGE || stage || "dev";
189
- tenant = process.env.MESH_TENANT || tenant || "mesh";
401
+ if (!tenant) {
402
+ tenant = findMeshJson(cwd)?.data.tenant;
403
+ }
404
+ stage = stageHint || stage || "dev";
405
+ const detectedTenant = tenant;
406
+ tenant = options.tenant || process.env.MESH_TENANT || tenant;
407
+ if (!tenant) {
408
+ throw tenantNotDeclared(cwd, { stackFile, hasProjectFile });
409
+ }
410
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(tenant)) {
411
+ throw new MeshCliError(
412
+ `Invalid tenant "${tenant}": expected lowercase alphanumerics and hyphens. This usually means a config file was misparsed.`,
413
+ { remediation: { command: "mesh <command> --tenant <tenant>" } }
414
+ );
415
+ }
416
+ const overrideSource = options.tenant ? "--tenant" : "MESH_TENANT";
417
+ const tenantOverridden = detectedTenant !== void 0 && detectedTenant !== tenant;
418
+ if (tenantOverridden) {
419
+ logWarn(
420
+ `${overrideSource}=${tenant} overrides the tenant detected here (${detectedTenant}); paths will use ${tenant} while implicit AWS credentials still come from the ${detectedTenant} app's deployer role`
421
+ );
422
+ }
190
423
  let platformEnv = stage;
191
- let platformEnvMap = {};
424
+ const platformEnvMap = /* @__PURE__ */ Object.create(null);
192
425
  let defaultPlatformEnv;
193
- const configPath = sstDir ? path.join(sstDir, "..", "config.ts") : "../config.ts";
194
- if (fs.existsSync(configPath)) {
195
- const configContent = fs.readFileSync(configPath, "utf-8");
196
- const mapMatch = configContent.match(/platformEnvMap:\s*\{([^}]+)\}/);
197
- if (mapMatch?.[1]) {
198
- const entries = mapMatch[1].matchAll(/(\w+):\s*["']([^"']+)["']/g);
426
+ if (parentConfig) {
427
+ const cleaned = stripComments(parentConfig);
428
+ const platformScope = extractPlatformBlock(cleaned);
429
+ const legacyScope = extractExportedConfigSource(cleaned);
430
+ const mapSource = (scope, key) => {
431
+ if (!scope) return void 0;
432
+ const at = scope.search(new RegExp(`${key}\\s*:\\s*\\{`));
433
+ if (at === -1) return void 0;
434
+ return matchBlock(scope, scope.indexOf("{", at));
435
+ };
436
+ const mapBody = mapSource(platformScope, "envMap") ?? mapSource(legacyScope, "platformEnvMap");
437
+ if (mapBody) {
438
+ const entries = mapBody.matchAll(/(?:"([^"]+)"|'([^']+)'|([\w-]+))\s*:\s*["']([^"']+)["']/g);
199
439
  for (const entry of entries) {
200
- const key = entry[1];
201
- const value = entry[2];
440
+ const key = entry[1] ?? entry[2] ?? entry[3];
441
+ const value = entry[4];
202
442
  if (key && value) {
203
443
  platformEnvMap[key] = value;
204
444
  }
205
445
  }
206
446
  }
207
- const defaultMatch = configContent.match(/defaultPlatformEnv:\s*["']([^"']+)["']/);
447
+ const defaultMatch = platformScope?.match(/defaultEnv:\s*["']([^"']+)["']/) ?? legacyScope?.match(/defaultPlatformEnv:\s*["']([^"']+)["']/);
208
448
  if (defaultMatch?.[1]) {
209
449
  defaultPlatformEnv = defaultMatch[1];
210
450
  }
211
451
  }
212
- const tenantPrefix = `${tenant}-`;
213
- const parsedEnv = stage.startsWith(tenantPrefix) ? stage.slice(tenantPrefix.length) : stage;
214
- platformEnv = platformEnvMap[parsedEnv] ?? platformEnvMap[stage] ?? defaultPlatformEnv ?? parsedEnv;
452
+ const tenantPrefix = [detectedTenant, tenant].filter((t) => Boolean(t)).map((t) => `${t}-`).sort((a, b) => b.length - a.length).find((p) => stage.startsWith(p));
453
+ const parsedEnv = tenantPrefix ? stage.slice(tenantPrefix.length) : stage;
454
+ const mapApplies = !tenantOverridden;
455
+ if (tenantOverridden && (Object.keys(platformEnvMap).length > 0 || defaultPlatformEnv)) {
456
+ logWarn(
457
+ `${overrideSource}=${tenant} also leaves the ${detectedTenant} config's envMap unapplied \u2014 it maps ${detectedTenant}'s stages, not ${tenant}'s \u2014 so the platform env is the stage itself ("${parsedEnv}"). Pass -e/--env where the command takes one, or run from the ${tenant} app's own directory.`
458
+ );
459
+ }
460
+ const mapped = mapApplies ? platformEnvMap[stage] ?? platformEnvMap[parsedEnv] : void 0;
461
+ if (mapped) {
462
+ platformEnv = mapped;
463
+ } else if (mapApplies && defaultPlatformEnv) {
464
+ if (namedStackMissing) {
465
+ const known = [
466
+ ...stackFilesHere.map((f) => f.slice("Pulumi.".length, -".yaml".length)),
467
+ ...Object.keys(platformEnvMap)
468
+ ].filter((v, i, a) => a.indexOf(v) === i);
469
+ throw new MeshCliError(
470
+ `No such stack "${options.stack}": ${cwd} has no Pulumi.${options.stack}.yaml, and the app's config.ts does not map it to a platform env \u2014 it would address defaultEnv "${defaultPlatformEnv}", not the stack you asked for.`,
471
+ {
472
+ remediation: {
473
+ command: `mesh <command> --stack <${known.join("|") || "stack"}>`
474
+ }
475
+ }
476
+ );
477
+ }
478
+ platformEnv = defaultPlatformEnv;
479
+ if (Object.keys(platformEnvMap).length > 0) {
480
+ logWarn(
481
+ `Stage "${stage}" is not in the config's envMap (${Object.keys(platformEnvMap).join(", ")}); using defaultEnv "${defaultPlatformEnv}".`
482
+ );
483
+ }
484
+ } else {
485
+ platformEnv = parsedEnv;
486
+ }
215
487
  logInfo(`Stage: ${stage}, Platform: ${platformEnv}, Tenant: ${tenant}`);
216
- return { tenant, stage, platformEnv };
488
+ return { tenant, stage, platformEnv, detectedTenant };
217
489
  }
218
490
  var init_context = __esm({
219
491
  "libs/mesh-cli/src/utils/context.ts"() {
220
492
  "use strict";
493
+ init_errors();
221
494
  init_log();
495
+ init_mesh_json();
222
496
  }
223
497
  });
224
498
 
@@ -367,19 +641,19 @@ var init_credentials = __esm({
367
641
 
368
642
  // libs/mesh-cli/src/utils/pulumi.ts
369
643
  import { execFileSync } from "child_process";
370
- import * as path2 from "path";
371
- import * as fs2 from "fs";
644
+ import * as path3 from "path";
645
+ import * as fs3 from "fs";
372
646
  function findAppRoot(startDir) {
373
647
  let dir = startDir;
374
648
  while (true) {
375
- if (fs2.existsSync(path2.join(dir, "Pulumi.yaml"))) return dir;
376
- const parent = path2.dirname(dir);
649
+ if (fs3.existsSync(path3.join(dir, "Pulumi.yaml"))) return dir;
650
+ const parent = path3.dirname(dir);
377
651
  if (parent === dir) return null;
378
652
  dir = parent;
379
653
  }
380
654
  }
381
655
  function findStackConfigs(appRoot) {
382
- return fs2.readdirSync(appRoot).filter((f) => /^Pulumi\..+\.yaml$/.test(f) && f !== "Pulumi.yaml").map((f) => f.replace(/^Pulumi\./, "").replace(/\.yaml$/, ""));
656
+ return fs3.readdirSync(appRoot).filter((f) => /^Pulumi\..+\.yaml$/.test(f) && f !== "Pulumi.yaml").map((f) => f.replace(/^Pulumi\./, "").replace(/\.yaml$/, ""));
383
657
  }
384
658
  function getCurrentStack(appRoot) {
385
659
  try {
@@ -394,9 +668,9 @@ function getCurrentStack(appRoot) {
394
668
  }
395
669
  }
396
670
  function readStackConfig(appRoot, stack, key) {
397
- const configFile = path2.join(appRoot, `Pulumi.${stack}.yaml`);
398
- if (!fs2.existsSync(configFile)) return null;
399
- const content = fs2.readFileSync(configFile, "utf-8");
671
+ const configFile = path3.join(appRoot, `Pulumi.${stack}.yaml`);
672
+ if (!fs3.existsSync(configFile)) return null;
673
+ const content = fs3.readFileSync(configFile, "utf-8");
400
674
  const pattern = new RegExp(`^\\s+${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:\\s*(.+)$`, "m");
401
675
  const match = content.match(pattern);
402
676
  if (!match) return null;
@@ -438,7 +712,7 @@ var init_pulumi = __esm({
438
712
 
439
713
  // libs/mesh-cli/src/utils/vpn.ts
440
714
  import { execFile, execFileSync as execFileSync2 } from "node:child_process";
441
- import { existsSync as existsSync3 } from "node:fs";
715
+ import { existsSync as existsSync4 } from "node:fs";
442
716
  async function isVpnConnected() {
443
717
  try {
444
718
  const stdout = await execTailscaleCmd(["status", "--json"]);
@@ -458,7 +732,7 @@ function headscaleDnsConfig(tenant = "mesh", env = "dev", overrides) {
458
732
  };
459
733
  }
460
734
  function execTailscaleCmd(args) {
461
- const socketPath2 = TAILSCALE_SOCKET_PATHS.find(existsSync3);
735
+ const socketPath2 = TAILSCALE_SOCKET_PATHS.find(existsSync4);
462
736
  const attempts = [];
463
737
  for (const binary of TAILSCALE_PATHS) {
464
738
  if (socketPath2) {
@@ -466,7 +740,7 @@ function execTailscaleCmd(args) {
466
740
  }
467
741
  attempts.push({ binary, args });
468
742
  }
469
- return new Promise((resolve19, reject) => {
743
+ return new Promise((resolve20, reject) => {
470
744
  let index = 0;
471
745
  function tryNext() {
472
746
  if (index >= attempts.length) {
@@ -478,7 +752,7 @@ function execTailscaleCmd(args) {
478
752
  if (error) {
479
753
  tryNext();
480
754
  } else {
481
- resolve19(stdout);
755
+ resolve20(stdout);
482
756
  }
483
757
  });
484
758
  }
@@ -652,7 +926,7 @@ async function ensureTemporalNamespace(namespace, description) {
652
926
  });
653
927
  break;
654
928
  } catch {
655
- await new Promise((resolve19) => setTimeout(resolve19, 1e3));
929
+ await new Promise((resolve20) => setTimeout(resolve20, 1e3));
656
930
  }
657
931
  }
658
932
  logSuccess(`Temporal namespace '${namespace}' is active`);
@@ -855,16 +1129,16 @@ async function upsertLocalSecret(secretId, value, client) {
855
1129
  }
856
1130
  function probeTcp(port, opts = {}) {
857
1131
  const { host = "127.0.0.1", timeoutMs = 2e3 } = opts;
858
- return new Promise((resolve19) => {
1132
+ return new Promise((resolve20) => {
859
1133
  const socket = net.connect({ host, port, timeout: timeoutMs });
860
1134
  socket.once("connect", () => {
861
1135
  socket.destroy();
862
- resolve19(true);
1136
+ resolve20(true);
863
1137
  });
864
- socket.once("error", () => resolve19(false));
1138
+ socket.once("error", () => resolve20(false));
865
1139
  socket.once("timeout", () => {
866
1140
  socket.destroy();
867
- resolve19(false);
1141
+ resolve20(false);
868
1142
  });
869
1143
  });
870
1144
  }
@@ -957,15 +1231,15 @@ var init_helpers = __esm({
957
1231
  });
958
1232
 
959
1233
  // libs/mesh-cli/src/utils/cache-home.ts
960
- import fs3 from "node:fs";
1234
+ import fs4 from "node:fs";
961
1235
  import os from "node:os";
962
- import path3 from "node:path";
1236
+ import path4 from "node:path";
963
1237
  function meshCacheHome() {
964
- return process.env.MESH_CACHE_HOME || path3.join(os.homedir(), ".cache", "mesh");
1238
+ return process.env.MESH_CACHE_HOME || path4.join(os.homedir(), ".cache", "mesh");
965
1239
  }
966
1240
  function meshCacheDir(...segments) {
967
- const dir = path3.join(meshCacheHome(), ...segments);
968
- fs3.mkdirSync(dir, { recursive: true });
1241
+ const dir = path4.join(meshCacheHome(), ...segments);
1242
+ fs4.mkdirSync(dir, { recursive: true });
969
1243
  return dir;
970
1244
  }
971
1245
  var init_cache_home = __esm({
@@ -1005,8 +1279,8 @@ __export(stack_exports, {
1005
1279
  writeAppServiceProbes: () => writeAppServiceProbes
1006
1280
  });
1007
1281
  import { execFileSync as execFileSync4, spawn, spawnSync } from "child_process";
1008
- import * as fs4 from "fs";
1009
- import * as path4 from "path";
1282
+ import * as fs5 from "fs";
1283
+ import * as path5 from "path";
1010
1284
  import { fileURLToPath } from "url";
1011
1285
  import { parse as parseYaml } from "yaml";
1012
1286
  function localLogsDir() {
@@ -1030,8 +1304,8 @@ function writeAppServiceProbes(args) {
1030
1304
  target: name
1031
1305
  }
1032
1306
  }));
1033
- const file = path4.join(localProbesDir(), `${args.tenant}-${args.app}-services.json`);
1034
- fs4.writeFileSync(file, `${JSON.stringify(targets, null, 2)}
1307
+ const file = path5.join(localProbesDir(), `${args.tenant}-${args.app}-services.json`);
1308
+ fs5.writeFileSync(file, `${JSON.stringify(targets, null, 2)}
1035
1309
  `);
1036
1310
  return file;
1037
1311
  }
@@ -1063,17 +1337,17 @@ function hubEndpoints() {
1063
1337
  ];
1064
1338
  }
1065
1339
  function findPackageRoot(startDir) {
1066
- let dir = startDir ?? path4.dirname(fileURLToPath(import.meta.url));
1340
+ let dir = startDir ?? path5.dirname(fileURLToPath(import.meta.url));
1067
1341
  for (let i = 0; i < 8; i++) {
1068
- const pkgPath = path4.join(dir, "package.json");
1069
- if (fs4.existsSync(pkgPath)) {
1342
+ const pkgPath = path5.join(dir, "package.json");
1343
+ if (fs5.existsSync(pkgPath)) {
1070
1344
  try {
1071
- const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
1345
+ const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
1072
1346
  if (pkg.name === "@mesh-tech/mesh-cli") return dir;
1073
1347
  } catch {
1074
1348
  }
1075
1349
  }
1076
- const parent = path4.dirname(dir);
1350
+ const parent = path5.dirname(dir);
1077
1351
  if (parent === dir) break;
1078
1352
  dir = parent;
1079
1353
  }
@@ -1082,8 +1356,8 @@ function findPackageRoot(startDir) {
1082
1356
  });
1083
1357
  }
1084
1358
  function stackDir() {
1085
- const dir = path4.join(findPackageRoot(), "stack");
1086
- if (!fs4.existsSync(path4.join(dir, "docker-compose.yml"))) {
1359
+ const dir = path5.join(findPackageRoot(), "stack");
1360
+ if (!fs5.existsSync(path5.join(dir, "docker-compose.yml"))) {
1087
1361
  throw new MeshCliError(`Local stack assets not found at ${dir}.`, {
1088
1362
  remediation: { command: "npm install -g @mesh-tech/mesh-cli" }
1089
1363
  });
@@ -1096,13 +1370,13 @@ function parseComposeServiceNames(yamlText) {
1096
1370
  }
1097
1371
  function hubOverlayServices() {
1098
1372
  if (!hubOverlayServicesCache) {
1099
- const file = path4.join(stackDir(), HUB_OVERLAY_FILE);
1100
- if (!fs4.existsSync(file)) {
1373
+ const file = path5.join(stackDir(), HUB_OVERLAY_FILE);
1374
+ if (!fs5.existsSync(file)) {
1101
1375
  throw new MeshCliError(`Local stack assets are incomplete: ${file} is missing.`, {
1102
1376
  remediation: { command: "npm install -g @mesh-tech/mesh-cli" }
1103
1377
  });
1104
1378
  }
1105
- hubOverlayServicesCache = new Set(parseComposeServiceNames(fs4.readFileSync(file, "utf-8")));
1379
+ hubOverlayServicesCache = new Set(parseComposeServiceNames(fs5.readFileSync(file, "utf-8")));
1106
1380
  }
1107
1381
  return hubOverlayServicesCache;
1108
1382
  }
@@ -1118,9 +1392,9 @@ function stackOwnedElsewhere() {
1118
1392
  if (!label) return void 0;
1119
1393
  const real = (p) => {
1120
1394
  try {
1121
- return fs4.realpathSync(p);
1395
+ return fs5.realpathSync(p);
1122
1396
  } catch {
1123
- return path4.resolve(p);
1397
+ return path5.resolve(p);
1124
1398
  }
1125
1399
  };
1126
1400
  return real(label) === real(stackDir()) ? void 0 : label;
@@ -1140,8 +1414,8 @@ function ensureDockerAvailable() {
1140
1414
  }
1141
1415
  function compose(args, opts = {}) {
1142
1416
  const dir = stackDir();
1143
- const files = ["-f", path4.join(dir, "docker-compose.yml")];
1144
- if (opts.hub) files.push("-f", path4.join(dir, "docker-compose.hub.yml"));
1417
+ const files = ["-f", path5.join(dir, "docker-compose.yml")];
1418
+ if (opts.hub) files.push("-f", path5.join(dir, "docker-compose.hub.yml"));
1145
1419
  const fullArgs = ["compose", "-p", COMPOSE_PROJECT, ...files, ...args];
1146
1420
  return execFileSync4("docker", fullArgs, {
1147
1421
  cwd: dir,
@@ -1171,12 +1445,12 @@ function summarizeComposeFailure(output) {
1171
1445
  }
1172
1446
  function composeLogPath(op) {
1173
1447
  const dir = meshCacheDir("mesh-local");
1174
- return path4.join(dir, `compose-${op.replace(/[^a-z0-9-]/gi, "_")}.log`);
1448
+ return path5.join(dir, `compose-${op.replace(/[^a-z0-9-]/gi, "_")}.log`);
1175
1449
  }
1176
1450
  async function composeStreamed(args, opts = {}) {
1177
1451
  const dir = stackDir();
1178
- const files = ["-f", path4.join(dir, "docker-compose.yml")];
1179
- if (opts.hub) files.push("-f", path4.join(dir, "docker-compose.hub.yml"));
1452
+ const files = ["-f", path5.join(dir, "docker-compose.yml")];
1453
+ if (opts.hub) files.push("-f", path5.join(dir, "docker-compose.hub.yml"));
1180
1454
  const fullArgs = ["compose", "-p", COMPOSE_PROJECT, ...files, ...args];
1181
1455
  const env = {
1182
1456
  ...process.env,
@@ -1205,12 +1479,12 @@ async function composeStreamed(args, opts = {}) {
1205
1479
  return;
1206
1480
  }
1207
1481
  const logPath2 = composeLogPath(op);
1208
- const logStream = fs4.createWriteStream(logPath2);
1482
+ const logStream = fs5.createWriteStream(logPath2);
1209
1483
  const heartbeat = startHeartbeat(`docker compose ${args.join(" ")}`);
1210
1484
  let captured = "";
1211
1485
  let exitCode;
1212
1486
  try {
1213
- exitCode = await new Promise((resolve19, reject) => {
1487
+ exitCode = await new Promise((resolve20, reject) => {
1214
1488
  const child = spawn("docker", fullArgs, {
1215
1489
  cwd: dir,
1216
1490
  env,
@@ -1226,11 +1500,11 @@ async function composeStreamed(args, opts = {}) {
1226
1500
  child.stdout.on("data", consume);
1227
1501
  child.stderr.on("data", consume);
1228
1502
  child.on("error", reject);
1229
- child.on("close", (code) => resolve19(code ?? 1));
1503
+ child.on("close", (code) => resolve20(code ?? 1));
1230
1504
  });
1231
1505
  } finally {
1232
1506
  heartbeat.stop();
1233
- await new Promise((resolve19) => logStream.end(resolve19));
1507
+ await new Promise((resolve20) => logStream.end(resolve20));
1234
1508
  }
1235
1509
  if (exitCode !== 0) {
1236
1510
  throw new MeshCliError(
@@ -1400,8 +1674,17 @@ var init_stack = __esm({
1400
1674
  });
1401
1675
 
1402
1676
  // libs/mesh-cli/src/commands/skills.ts
1403
- import * as fs5 from "fs";
1404
- import * as path5 from "path";
1677
+ var skills_exports = {};
1678
+ __export(skills_exports, {
1679
+ INTENT_RANGE: () => INTENT_RANGE,
1680
+ listPackageSkills: () => listPackageSkills,
1681
+ registerSkillsCommands: () => registerSkillsCommands,
1682
+ resolveTargetRoot: () => resolveTargetRoot,
1683
+ seedAppSkill: () => seedAppSkill,
1684
+ syncSkills: () => syncSkills
1685
+ });
1686
+ import * as fs6 from "fs";
1687
+ import * as path6 from "path";
1405
1688
  import { execFileSync as execFileSync5 } from "child_process";
1406
1689
  function resolveTargetRoot(startDir = process.cwd()) {
1407
1690
  try {
@@ -1415,15 +1698,15 @@ function resolveTargetRoot(startDir = process.cwd()) {
1415
1698
  }
1416
1699
  }
1417
1700
  function cliAsset(...segments) {
1418
- return path5.join(findPackageRoot(), ...segments);
1701
+ return path6.join(findPackageRoot(), ...segments);
1419
1702
  }
1420
1703
  function listBaseSkills() {
1421
1704
  const dir = cliAsset("skills");
1422
- if (!fs5.existsSync(dir)) return [];
1423
- return fs5.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && fs5.existsSync(path5.join(dir, entry.name, "SKILL.md"))).map((entry) => ({ name: entry.name, source: path5.join(dir, entry.name, "SKILL.md") }));
1705
+ if (!fs6.existsSync(dir)) return [];
1706
+ return fs6.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && fs6.existsSync(path6.join(dir, entry.name, "SKILL.md"))).map((entry) => ({ name: entry.name, source: path6.join(dir, entry.name, "SKILL.md") }));
1424
1707
  }
1425
1708
  function renderManagedSkill(source) {
1426
- const raw = fs5.readFileSync(source, "utf-8");
1709
+ const raw = fs6.readFileSync(source, "utf-8");
1427
1710
  const frontmatter = raw.match(/^(---\n[\s\S]*?\n---\n)/)?.[1];
1428
1711
  if (!frontmatter) return `${MANAGED_MARKER}
1429
1712
 
@@ -1438,19 +1721,19 @@ function meshTechScopeDirs(root, maxDepth = 6) {
1438
1721
  if (depth > maxDepth) return;
1439
1722
  let entries;
1440
1723
  try {
1441
- entries = fs5.readdirSync(dir, { withFileTypes: true });
1724
+ entries = fs6.readdirSync(dir, { withFileTypes: true });
1442
1725
  } catch {
1443
1726
  return;
1444
1727
  }
1445
1728
  for (const entry of entries) {
1446
1729
  if (!entry.isDirectory()) continue;
1447
1730
  if (entry.name === "node_modules") {
1448
- const scope = path5.join(dir, entry.name, "@mesh-tech");
1449
- if (fs5.existsSync(scope)) scopes.push(scope);
1731
+ const scope = path6.join(dir, entry.name, "@mesh-tech");
1732
+ if (fs6.existsSync(scope)) scopes.push(scope);
1450
1733
  continue;
1451
1734
  }
1452
1735
  if (entry.name.startsWith(".")) continue;
1453
- walk2(path5.join(dir, entry.name), depth + 1);
1736
+ walk2(path6.join(dir, entry.name), depth + 1);
1454
1737
  }
1455
1738
  };
1456
1739
  walk2(root, 0);
@@ -1459,57 +1742,57 @@ function meshTechScopeDirs(root, maxDepth = 6) {
1459
1742
  function listPackageSkills(root) {
1460
1743
  const byName = /* @__PURE__ */ new Map();
1461
1744
  for (const scopeDir of meshTechScopeDirs(root)) {
1462
- for (const pkg of fs5.readdirSync(scopeDir, { withFileTypes: true })) {
1745
+ for (const pkg of fs6.readdirSync(scopeDir, { withFileTypes: true })) {
1463
1746
  if (!pkg.isDirectory() && !pkg.isSymbolicLink()) continue;
1464
1747
  if (pkg.name === BASE_SKILL_PACKAGE) continue;
1465
- const skillsDir = path5.join(scopeDir, pkg.name, "skills");
1466
- if (!fs5.existsSync(skillsDir)) continue;
1467
- for (const domain of fs5.readdirSync(skillsDir, { withFileTypes: true })) {
1468
- const source = path5.join(skillsDir, domain.name, "SKILL.md");
1469
- if (!fs5.existsSync(source)) continue;
1748
+ const skillsDir = path6.join(scopeDir, pkg.name, "skills");
1749
+ if (!fs6.existsSync(skillsDir)) continue;
1750
+ for (const domain of fs6.readdirSync(skillsDir, { withFileTypes: true })) {
1751
+ const source = path6.join(skillsDir, domain.name, "SKILL.md");
1752
+ if (!fs6.existsSync(source)) continue;
1470
1753
  const name = `mesh-${pkg.name}-${domain.name}`;
1471
- if (!byName.has(name)) byName.set(name, { name, dir: path5.join(skillsDir, domain.name), source });
1754
+ if (!byName.has(name)) byName.set(name, { name, dir: path6.join(skillsDir, domain.name), source });
1472
1755
  }
1473
1756
  }
1474
1757
  }
1475
1758
  return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
1476
1759
  }
1477
1760
  function copySkillExtras(sourceDir, targetDir) {
1478
- for (const entry of fs5.readdirSync(sourceDir, { withFileTypes: true })) {
1761
+ for (const entry of fs6.readdirSync(sourceDir, { withFileTypes: true })) {
1479
1762
  if (entry.name === "SKILL.md") continue;
1480
- fs5.cpSync(path5.join(sourceDir, entry.name), path5.join(targetDir, entry.name), { recursive: true });
1763
+ fs6.cpSync(path6.join(sourceDir, entry.name), path6.join(targetDir, entry.name), { recursive: true });
1481
1764
  }
1482
1765
  }
1483
1766
  function seedAppSkill(root, appName, appRelPath) {
1484
- const target = path5.join(root, ".claude", "skills", appName, "SKILL.md");
1485
- if (fs5.existsSync(target)) return null;
1486
- const template = fs5.readFileSync(cliAsset("assets", "app-skill", "SKILL.md"), "utf-8");
1767
+ const target = path6.join(root, ".claude", "skills", appName, "SKILL.md");
1768
+ if (fs6.existsSync(target)) return null;
1769
+ const template = fs6.readFileSync(cliAsset("assets", "app-skill", "SKILL.md"), "utf-8");
1487
1770
  const body = template.replaceAll("__APP_NAME__", appName).replaceAll("__APP_PATH__", appRelPath || ".");
1488
- fs5.mkdirSync(path5.dirname(target), { recursive: true });
1489
- fs5.writeFileSync(target, body);
1490
- return path5.relative(root, target);
1771
+ fs6.mkdirSync(path6.dirname(target), { recursive: true });
1772
+ fs6.writeFileSync(target, body);
1773
+ return path6.relative(root, target);
1491
1774
  }
1492
1775
  function planSync(root) {
1493
1776
  const items = [];
1494
1777
  for (const skill of listBaseSkills()) {
1495
- const target = path5.join(root, ".claude", "skills", `mesh-${skill.name}`, "SKILL.md");
1778
+ const target = path6.join(root, ".claude", "skills", `mesh-${skill.name}`, "SKILL.md");
1496
1779
  const desired = renderManagedSkill(skill.source);
1497
1780
  const label = `.claude/skills/mesh-${skill.name}/SKILL.md (base skill)`;
1498
- if (!fs5.existsSync(target)) {
1781
+ if (!fs6.existsSync(target)) {
1499
1782
  items.push({
1500
1783
  label,
1501
1784
  state: "write",
1502
1785
  apply: () => {
1503
- fs5.mkdirSync(path5.dirname(target), { recursive: true });
1504
- fs5.writeFileSync(target, desired);
1786
+ fs6.mkdirSync(path6.dirname(target), { recursive: true });
1787
+ fs6.writeFileSync(target, desired);
1505
1788
  }
1506
1789
  });
1507
1790
  } else {
1508
- const current = fs5.readFileSync(target, "utf-8");
1791
+ const current = fs6.readFileSync(target, "utf-8");
1509
1792
  if (current === desired) {
1510
1793
  items.push({ label, state: "ok" });
1511
1794
  } else if (current.includes(MANAGED_MARKER)) {
1512
- items.push({ label, state: "write", apply: () => fs5.writeFileSync(target, desired) });
1795
+ items.push({ label, state: "write", apply: () => fs6.writeFileSync(target, desired) });
1513
1796
  } else {
1514
1797
  items.push({ label: `${label} \u2014 exists without the managed marker, leaving as-is`, state: "skip" });
1515
1798
  }
@@ -1517,22 +1800,22 @@ function planSync(root) {
1517
1800
  }
1518
1801
  const packageSkills = listPackageSkills(root);
1519
1802
  for (const skill of packageSkills) {
1520
- const targetDir = path5.join(root, ".claude", "skills", skill.name);
1521
- const target = path5.join(targetDir, "SKILL.md");
1803
+ const targetDir = path6.join(root, ".claude", "skills", skill.name);
1804
+ const target = path6.join(targetDir, "SKILL.md");
1522
1805
  const desired = renderManagedSkill(skill.source);
1523
1806
  const label = `.claude/skills/${skill.name}/SKILL.md (platform skill)`;
1524
- if (!fs5.existsSync(target)) {
1807
+ if (!fs6.existsSync(target)) {
1525
1808
  items.push({
1526
1809
  label,
1527
1810
  state: "write",
1528
1811
  apply: () => {
1529
- fs5.mkdirSync(targetDir, { recursive: true });
1530
- fs5.writeFileSync(target, desired);
1812
+ fs6.mkdirSync(targetDir, { recursive: true });
1813
+ fs6.writeFileSync(target, desired);
1531
1814
  copySkillExtras(skill.dir, targetDir);
1532
1815
  }
1533
1816
  });
1534
1817
  } else {
1535
- const current = fs5.readFileSync(target, "utf-8");
1818
+ const current = fs6.readFileSync(target, "utf-8");
1536
1819
  if (current === desired) {
1537
1820
  items.push({ label, state: "ok" });
1538
1821
  } else if (current.includes(MANAGED_MARKER)) {
@@ -1540,7 +1823,7 @@ function planSync(root) {
1540
1823
  label,
1541
1824
  state: "write",
1542
1825
  apply: () => {
1543
- fs5.writeFileSync(target, desired);
1826
+ fs6.writeFileSync(target, desired);
1544
1827
  copySkillExtras(skill.dir, targetDir);
1545
1828
  }
1546
1829
  });
@@ -1553,24 +1836,24 @@ function planSync(root) {
1553
1836
  logInfo("No @mesh-tech packages installed yet \u2014 run `pnpm install`, then `mesh skills sync` again for the platform skills.");
1554
1837
  }
1555
1838
  const hookSource = cliAsset("assets", "intent", "intent-claude-gate.mjs");
1556
- const hookTarget = path5.join(root, HOOK_RELATIVE);
1557
- const hookDesired = fs5.readFileSync(hookSource, "utf-8");
1558
- const hookCurrent = fs5.existsSync(hookTarget) ? fs5.readFileSync(hookTarget, "utf-8") : null;
1839
+ const hookTarget = path6.join(root, HOOK_RELATIVE);
1840
+ const hookDesired = fs6.readFileSync(hookSource, "utf-8");
1841
+ const hookCurrent = fs6.existsSync(hookTarget) ? fs6.readFileSync(hookTarget, "utf-8") : null;
1559
1842
  items.push(
1560
1843
  hookCurrent === hookDesired ? { label: `${HOOK_RELATIVE} (Intent gate)`, state: "ok" } : {
1561
1844
  label: `${HOOK_RELATIVE} (Intent gate)`,
1562
1845
  state: "write",
1563
1846
  apply: () => {
1564
- fs5.mkdirSync(path5.dirname(hookTarget), { recursive: true });
1565
- fs5.writeFileSync(hookTarget, hookDesired, { mode: 493 });
1847
+ fs6.mkdirSync(path6.dirname(hookTarget), { recursive: true });
1848
+ fs6.writeFileSync(hookTarget, hookDesired, { mode: 493 });
1566
1849
  }
1567
1850
  }
1568
1851
  );
1569
- const rootPkgPath = path5.join(root, "package.json");
1570
- if (fs5.existsSync(rootPkgPath)) {
1852
+ const rootPkgPath = path6.join(root, "package.json");
1853
+ if (fs6.existsSync(rootPkgPath)) {
1571
1854
  let rootPkg = null;
1572
1855
  try {
1573
- rootPkg = JSON.parse(fs5.readFileSync(rootPkgPath, "utf-8"));
1856
+ rootPkg = JSON.parse(fs6.readFileSync(rootPkgPath, "utf-8"));
1574
1857
  } catch {
1575
1858
  rootPkg = null;
1576
1859
  }
@@ -1593,15 +1876,15 @@ function planSync(root) {
1593
1876
  rootPkg.devDependencies = Object.fromEntries(
1594
1877
  Object.entries(rootPkg.devDependencies).sort(([a], [b]) => a.localeCompare(b))
1595
1878
  );
1596
- fs5.writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2) + "\n");
1879
+ fs6.writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2) + "\n");
1597
1880
  }
1598
1881
  });
1599
1882
  }
1600
1883
  }
1601
- const settingsPath = path5.join(root, ".claude", "settings.json");
1884
+ const settingsPath = path6.join(root, ".claude", "settings.json");
1602
1885
  let settings = {};
1603
1886
  try {
1604
- settings = JSON.parse(fs5.readFileSync(settingsPath, "utf-8"));
1887
+ settings = JSON.parse(fs6.readFileSync(settingsPath, "utf-8"));
1605
1888
  } catch {
1606
1889
  settings = {};
1607
1890
  }
@@ -1628,14 +1911,14 @@ function planSync(root) {
1628
1911
  }
1629
1912
  ]
1630
1913
  });
1631
- fs5.mkdirSync(path5.dirname(settingsPath), { recursive: true });
1632
- fs5.writeFileSync(settingsPath, JSON.stringify(settings, null, 1) + "\n");
1914
+ fs6.mkdirSync(path6.dirname(settingsPath), { recursive: true });
1915
+ fs6.writeFileSync(settingsPath, JSON.stringify(settings, null, 1) + "\n");
1633
1916
  }
1634
1917
  }
1635
1918
  );
1636
- const agentsPath = path5.join(root, "AGENTS.md");
1637
- const fence2 = fs5.readFileSync(cliAsset("assets", "intent", "agents-fence.md"), "utf-8");
1638
- const agentsCurrent = fs5.existsSync(agentsPath) ? fs5.readFileSync(agentsPath, "utf-8") : null;
1919
+ const agentsPath = path6.join(root, "AGENTS.md");
1920
+ const fence2 = fs6.readFileSync(cliAsset("assets", "intent", "agents-fence.md"), "utf-8");
1921
+ const agentsCurrent = fs6.existsSync(agentsPath) ? fs6.readFileSync(agentsPath, "utf-8") : null;
1639
1922
  items.push(
1640
1923
  agentsCurrent?.includes(FENCE_START) ? { label: "AGENTS.md (intent-skills fence)", state: "ok" } : {
1641
1924
  label: "AGENTS.md (intent-skills fence)",
@@ -1645,7 +1928,7 @@ function planSync(root) {
1645
1928
  ${agentsCurrent}` : `${fence2}
1646
1929
  # Agent Instructions
1647
1930
  `;
1648
- fs5.writeFileSync(agentsPath, next);
1931
+ fs6.writeFileSync(agentsPath, next);
1649
1932
  }
1650
1933
  }
1651
1934
  );
@@ -1679,7 +1962,7 @@ function registerSkillsCommands(program2) {
1679
1962
  skills.command("sync").description(
1680
1963
  "Install the base building-with-Mesh skills into .claude/skills/, fetch the platform skills shipped by the repo's installed @mesh-tech/* packages, and wire TanStack-Intent discovery (intent devDependency + hook + settings + AGENTS.md fence)"
1681
1964
  ).option("--check", "verify only (CI/doctor): exit 1 when anything is missing or stale", false).option("--root <path>", "target repo root (default: enclosing git root)").action((opts) => {
1682
- const root = path5.resolve(opts.root ?? resolveTargetRoot());
1965
+ const root = path6.resolve(opts.root ?? resolveTargetRoot());
1683
1966
  const ok = syncSkills(root, { check: opts.check });
1684
1967
  if (opts.check && !ok) {
1685
1968
  throw new MeshCliError("Agent skills are missing or stale.", {
@@ -1697,7 +1980,7 @@ var init_skills = __esm({
1697
1980
  init_stack();
1698
1981
  MANAGED_MARKER = "<!-- managed-by: mesh skills sync \u2014 edits are overwritten; copy content elsewhere to customize -->";
1699
1982
  FENCE_START = "<!-- intent-skills:start -->";
1700
- HOOK_RELATIVE = path5.join(".intent", "hooks", "intent-claude-gate.mjs");
1983
+ HOOK_RELATIVE = path6.join(".intent", "hooks", "intent-claude-gate.mjs");
1701
1984
  INTENT_RANGE = "^0.3.6";
1702
1985
  BASE_SKILL_PACKAGE = "mesh-cli";
1703
1986
  }
@@ -1769,20 +2052,20 @@ var init_pid = __esm({
1769
2052
 
1770
2053
  // libs/mesh-cli/src/utils/tailscale-targets.ts
1771
2054
  import { execFileSync as execFileSync6 } from "node:child_process";
1772
- import * as fs6 from "node:fs";
1773
- import * as path6 from "node:path";
2055
+ import * as fs7 from "node:fs";
2056
+ import * as path7 from "node:path";
1774
2057
  function tenantPortIndex(tenant, registryPath) {
1775
- const p = registryPath ?? path6.join(CONFIG_DIR, "tailscale", "port-registry.json");
2058
+ const p = registryPath ?? path7.join(CONFIG_DIR, "tailscale", "port-registry.json");
1776
2059
  let reg;
1777
2060
  try {
1778
- reg = JSON.parse(fs6.readFileSync(p, "utf8"));
2061
+ reg = JSON.parse(fs7.readFileSync(p, "utf8"));
1779
2062
  } catch {
1780
2063
  reg = { mesh: 0 };
1781
2064
  }
1782
2065
  if (tenant in reg) return reg[tenant];
1783
2066
  const idx = Math.max(-1, ...Object.values(reg)) + 1;
1784
2067
  reg[tenant] = idx;
1785
- fs6.mkdirSync(path6.dirname(p), { recursive: true });
2068
+ fs7.mkdirSync(path7.dirname(p), { recursive: true });
1786
2069
  atomicWriteFileSync(p, JSON.stringify(reg, null, 2), 384);
1787
2070
  return idx;
1788
2071
  }
@@ -1909,29 +2192,29 @@ var init_socks_forward = __esm({
1909
2192
 
1910
2193
  // libs/mesh-cli/src/utils/tunnel-ownership.ts
1911
2194
  import * as crypto from "node:crypto";
1912
- import * as fs7 from "node:fs";
2195
+ import * as fs8 from "node:fs";
1913
2196
  import * as net3 from "node:net";
1914
- import * as path7 from "node:path";
2197
+ import * as path8 from "node:path";
1915
2198
  import { execFileSync as execFileSync7 } from "node:child_process";
1916
2199
  function mintRunnerToken() {
1917
2200
  return crypto.randomBytes(16).toString("hex");
1918
2201
  }
1919
2202
  function readRunnerManifest(file) {
1920
- if (!fs7.existsSync(file)) return null;
2203
+ if (!fs8.existsSync(file)) return null;
1921
2204
  try {
1922
- return JSON.parse(fs7.readFileSync(file, "utf8"));
2205
+ return JSON.parse(fs8.readFileSync(file, "utf8"));
1923
2206
  } catch {
1924
2207
  return null;
1925
2208
  }
1926
2209
  }
1927
2210
  function writeRunnerManifest(file, manifest) {
1928
- fs7.mkdirSync(path7.dirname(file), { recursive: true });
1929
- fs7.writeFileSync(file, JSON.stringify(manifest, null, 2), { mode: 384 });
2211
+ fs8.mkdirSync(path8.dirname(file), { recursive: true });
2212
+ fs8.writeFileSync(file, JSON.stringify(manifest, null, 2), { mode: 384 });
1930
2213
  }
1931
2214
  function clearRunnerManifest(file, token) {
1932
2215
  if (token !== void 0 && readRunnerManifest(file)?.token !== token) return;
1933
2216
  try {
1934
- fs7.unlinkSync(file);
2217
+ fs8.unlinkSync(file);
1935
2218
  } catch {
1936
2219
  }
1937
2220
  }
@@ -1973,7 +2256,7 @@ function discoverRunnerPids(tenant, exclude) {
1973
2256
  }
1974
2257
  }
1975
2258
  function startControlServer(payload) {
1976
- return new Promise((resolve19, reject) => {
2259
+ return new Promise((resolve20, reject) => {
1977
2260
  const server = net3.createServer((socket) => {
1978
2261
  socket.on("error", () => {
1979
2262
  });
@@ -1986,12 +2269,12 @@ function startControlServer(payload) {
1986
2269
  });
1987
2270
  server.on("error", reject);
1988
2271
  server.listen(0, "127.0.0.1", () => {
1989
- resolve19({ server, port: server.address().port });
2272
+ resolve20({ server, port: server.address().port });
1990
2273
  });
1991
2274
  });
1992
2275
  }
1993
2276
  function queryControl(port, timeoutMs = 700) {
1994
- return new Promise((resolve19) => {
2277
+ return new Promise((resolve20) => {
1995
2278
  const s = new net3.Socket();
1996
2279
  let buf = "";
1997
2280
  let done = false;
@@ -1999,7 +2282,7 @@ function queryControl(port, timeoutMs = 700) {
1999
2282
  if (done) return;
2000
2283
  done = true;
2001
2284
  s.destroy();
2002
- resolve19(v);
2285
+ resolve20(v);
2003
2286
  };
2004
2287
  s.setTimeout(timeoutMs);
2005
2288
  s.once("timeout", () => fin(null));
@@ -2100,64 +2383,64 @@ var init_tunnel_ownership = __esm({
2100
2383
  });
2101
2384
 
2102
2385
  // libs/mesh-cli/src/utils/tailscale.ts
2103
- import * as fs8 from "node:fs";
2386
+ import * as fs9 from "node:fs";
2104
2387
  import * as net4 from "node:net";
2105
2388
  import * as os2 from "node:os";
2106
- import * as path8 from "node:path";
2389
+ import * as path9 from "node:path";
2107
2390
  import { spawn as spawn2, execFileSync as execFileSync8 } from "node:child_process";
2108
2391
  function tenantStateDir(tenant) {
2109
- return path8.join(CONFIG_DIR, "tailscale", tenant);
2392
+ return path9.join(CONFIG_DIR, "tailscale", tenant);
2110
2393
  }
2111
2394
  function socketPath(tenant) {
2112
- return path8.join(tenantStateDir(tenant), "tailscaled.sock");
2395
+ return path9.join(tenantStateDir(tenant), "tailscaled.sock");
2113
2396
  }
2114
2397
  function logPath(tenant) {
2115
- return path8.join(tenantStateDir(tenant), "tailscaled.log");
2398
+ return path9.join(tenantStateDir(tenant), "tailscaled.log");
2116
2399
  }
2117
2400
  function statePath(tenant) {
2118
- return path8.join(tenantStateDir(tenant), "tunnel-state.json");
2401
+ return path9.join(tenantStateDir(tenant), "tunnel-state.json");
2119
2402
  }
2120
2403
  function daemonMetaPath(tenant) {
2121
- return path8.join(tenantStateDir(tenant), "daemon.json");
2404
+ return path9.join(tenantStateDir(tenant), "daemon.json");
2122
2405
  }
2123
2406
  function runnerManifestPath(tenant) {
2124
- return path8.join(tenantStateDir(tenant), "runner.json");
2407
+ return path9.join(tenantStateDir(tenant), "runner.json");
2125
2408
  }
2126
2409
  function readTunnelState(tenant) {
2127
2410
  const p = statePath(tenant);
2128
- if (!fs8.existsSync(p)) return null;
2411
+ if (!fs9.existsSync(p)) return null;
2129
2412
  try {
2130
- return JSON.parse(fs8.readFileSync(p, "utf8"));
2413
+ return JSON.parse(fs9.readFileSync(p, "utf8"));
2131
2414
  } catch {
2132
2415
  return null;
2133
2416
  }
2134
2417
  }
2135
2418
  function writeTunnelState(tenant, state) {
2136
- fs8.mkdirSync(tenantStateDir(tenant), { recursive: true });
2419
+ fs9.mkdirSync(tenantStateDir(tenant), { recursive: true });
2137
2420
  atomicWriteFileSync(statePath(tenant), JSON.stringify(state, null, 2), 384);
2138
2421
  }
2139
2422
  function clearTunnelState(tenant) {
2140
2423
  try {
2141
- fs8.unlinkSync(statePath(tenant));
2424
+ fs9.unlinkSync(statePath(tenant));
2142
2425
  } catch {
2143
2426
  }
2144
2427
  }
2145
2428
  function readDaemonMeta(tenant) {
2146
2429
  const p = daemonMetaPath(tenant);
2147
- if (!fs8.existsSync(p)) return null;
2430
+ if (!fs9.existsSync(p)) return null;
2148
2431
  try {
2149
- return JSON.parse(fs8.readFileSync(p, "utf8"));
2432
+ return JSON.parse(fs9.readFileSync(p, "utf8"));
2150
2433
  } catch {
2151
2434
  return null;
2152
2435
  }
2153
2436
  }
2154
2437
  function writeDaemonMeta(tenant, meta) {
2155
- fs8.mkdirSync(tenantStateDir(tenant), { recursive: true });
2438
+ fs9.mkdirSync(tenantStateDir(tenant), { recursive: true });
2156
2439
  atomicWriteFileSync(daemonMetaPath(tenant), JSON.stringify(meta, null, 2), 384);
2157
2440
  }
2158
2441
  function clearDaemonMeta(tenant) {
2159
2442
  try {
2160
- fs8.unlinkSync(daemonMetaPath(tenant));
2443
+ fs9.unlinkSync(daemonMetaPath(tenant));
2161
2444
  } catch {
2162
2445
  }
2163
2446
  }
@@ -2177,7 +2460,7 @@ function tailscaleBinPath() {
2177
2460
  }
2178
2461
  function resolveBrewBin(name) {
2179
2462
  const brew = `/opt/homebrew/bin/${name}`;
2180
- if (fs8.existsSync(brew)) return brew;
2463
+ if (fs9.existsSync(brew)) return brew;
2181
2464
  try {
2182
2465
  const p = execFileSync8("which", [name], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
2183
2466
  if (p) return p;
@@ -2186,7 +2469,7 @@ function resolveBrewBin(name) {
2186
2469
  throw new Error(`${name} not found \u2014 install the standalone binary: brew install tailscale`);
2187
2470
  }
2188
2471
  function daemonState(tenant) {
2189
- if (!fs8.existsSync(socketPath(tenant))) return { backendState: "Down" };
2472
+ if (!fs9.existsSync(socketPath(tenant))) return { backendState: "Down" };
2190
2473
  try {
2191
2474
  const out = execFileSync8(
2192
2475
  tailscaleBinPath(),
@@ -2224,14 +2507,14 @@ function findRunningDaemon(tenant) {
2224
2507
  return null;
2225
2508
  }
2226
2509
  function portAccepts(port, timeoutMs = 400) {
2227
- return new Promise((resolve19) => {
2510
+ return new Promise((resolve20) => {
2228
2511
  const s = new net4.Socket();
2229
2512
  let done = false;
2230
2513
  const fin = (v) => {
2231
2514
  if (done) return;
2232
2515
  done = true;
2233
2516
  s.destroy();
2234
- resolve19(v);
2517
+ resolve20(v);
2235
2518
  };
2236
2519
  s.setTimeout(timeoutMs);
2237
2520
  s.once("connect", () => fin(true));
@@ -2260,8 +2543,8 @@ async function ensureDaemon(tenant, opts) {
2260
2543
  }
2261
2544
  }
2262
2545
  const dir = tenantStateDir(tenant);
2263
- fs8.mkdirSync(dir, { recursive: true });
2264
- const log = fs8.openSync(logPath(tenant), "a");
2546
+ fs9.mkdirSync(dir, { recursive: true });
2547
+ const log = fs9.openSync(logPath(tenant), "a");
2265
2548
  try {
2266
2549
  const child = spawn2(
2267
2550
  tailscaledBinPath(),
@@ -2281,7 +2564,7 @@ async function ensureDaemon(tenant, opts) {
2281
2564
  child.unref();
2282
2565
  if (child.pid) writeDaemonMeta(tenant, { socksPort: opts.socksPort, pid: child.pid });
2283
2566
  } finally {
2284
- fs8.closeSync(log);
2567
+ fs9.closeSync(log);
2285
2568
  }
2286
2569
  for (let i = 0; i < 40; i++) {
2287
2570
  await sleep(250);
@@ -2307,7 +2590,7 @@ function stopDaemon(tenant) {
2307
2590
  }
2308
2591
  for (const p of [socketPath(tenant)]) {
2309
2592
  try {
2310
- fs8.unlinkSync(p);
2593
+ fs9.unlinkSync(p);
2311
2594
  } catch {
2312
2595
  }
2313
2596
  }
@@ -2452,7 +2735,7 @@ async function assertTunnelPortsFree(tenant, ports) {
2452
2735
  async function ensureForwarders(state) {
2453
2736
  const prior = readTunnelState(state.tenant);
2454
2737
  const expected = { socksPort: state.socksPort, ports: state.tunnels.map((t) => t.localPort) };
2455
- const runnerAlive = prior?.managed === "launchd" ? fs8.existsSync(launchAgentPath(state.tenant)) : pidAlive(prior?.supervisorPid);
2738
+ const runnerAlive = prior?.managed === "launchd" ? fs9.existsSync(launchAgentPath(state.tenant)) : pidAlive(prior?.supervisorPid);
2456
2739
  if (prior && runnerAlive && tunnelTargetsEqual(prior.tunnels, state.tunnels) && // A prior supervisor spawned for a DIFFERENT SOCKS port still binds the same
2457
2740
  // local ports but dials a dead upstream — reusing it silently strands every
2458
2741
  // tunnel. The port must match, and the runner must PROVE it is
@@ -2477,7 +2760,7 @@ async function ensureForwarders(state) {
2477
2760
  if (launchdAvailable()) {
2478
2761
  state.managed = "launchd";
2479
2762
  writeTunnelState(state.tenant, state);
2480
- if (path8.isAbsolute(meshBin) && installLaunchAgent(state.tenant, meshBin)) {
2763
+ if (path9.isAbsolute(meshBin) && installLaunchAgent(state.tenant, meshBin)) {
2481
2764
  if ((await awaitOwnership(state.tenant, expected, 8e3)).ok) return 0;
2482
2765
  uninstallLaunchAgent(state.tenant);
2483
2766
  await assertTunnelPortsFree(state.tenant, expected.ports);
@@ -2605,7 +2888,7 @@ function forwardersNeedingRebind(targets, listening) {
2605
2888
  return targets.filter((t) => !listening.has(t.localPort));
2606
2889
  }
2607
2890
  function launchAgentPath(tenant) {
2608
- return path8.join(os2.homedir(), "Library", "LaunchAgents", `${launchAgentLabel(tenant)}.plist`);
2891
+ return path9.join(os2.homedir(), "Library", "LaunchAgents", `${launchAgentLabel(tenant)}.plist`);
2609
2892
  }
2610
2893
  function guiDomain() {
2611
2894
  return `gui/${process.getuid?.() ?? 0}`;
@@ -2626,22 +2909,22 @@ function installLaunchAgent(tenant, meshBin) {
2626
2909
  try {
2627
2910
  let realMeshBin = meshBin;
2628
2911
  try {
2629
- realMeshBin = fs8.realpathSync(meshBin);
2912
+ realMeshBin = fs9.realpathSync(meshBin);
2630
2913
  } catch {
2631
2914
  }
2632
2915
  let pathEnv = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
2633
2916
  try {
2634
- pathEnv = `${path8.dirname(tailscaledBinPath())}:${pathEnv}`;
2917
+ pathEnv = `${path9.dirname(tailscaledBinPath())}:${pathEnv}`;
2635
2918
  } catch {
2636
2919
  }
2637
- fs8.mkdirSync(path8.dirname(plistPath), { recursive: true });
2638
- fs8.writeFileSync(
2920
+ fs9.mkdirSync(path9.dirname(plistPath), { recursive: true });
2921
+ fs9.writeFileSync(
2639
2922
  plistPath,
2640
2923
  renderLaunchAgentPlist({
2641
2924
  tenant,
2642
2925
  meshBin: realMeshBin,
2643
2926
  nodeBin: process.execPath,
2644
- logPath: path8.join(tenantStateDir(tenant), "runner.log"),
2927
+ logPath: path9.join(tenantStateDir(tenant), "runner.log"),
2645
2928
  pathEnv
2646
2929
  })
2647
2930
  );
@@ -2662,7 +2945,7 @@ function uninstallLaunchAgent(tenant) {
2662
2945
  } catch {
2663
2946
  }
2664
2947
  try {
2665
- fs8.unlinkSync(plistPath);
2948
+ fs9.unlinkSync(plistPath);
2666
2949
  } catch {
2667
2950
  }
2668
2951
  }
@@ -2769,24 +3052,24 @@ function deriveLoginServer(context) {
2769
3052
  return `https://${parts.join(".")}`;
2770
3053
  }
2771
3054
  function findFreePort() {
2772
- return new Promise((resolve19, reject) => {
3055
+ return new Promise((resolve20, reject) => {
2773
3056
  const s = net5.createServer();
2774
3057
  s.on("error", reject);
2775
3058
  s.listen(0, "127.0.0.1", () => {
2776
3059
  const port = s.address().port;
2777
- s.close(() => resolve19(port));
3060
+ s.close(() => resolve20(port));
2778
3061
  });
2779
3062
  });
2780
3063
  }
2781
3064
  function canConnect(port) {
2782
- return new Promise((resolve19) => {
3065
+ return new Promise((resolve20) => {
2783
3066
  const s = new net5.Socket();
2784
3067
  let settled = false;
2785
3068
  const done = (ok) => {
2786
3069
  if (settled) return;
2787
3070
  settled = true;
2788
3071
  s.destroy();
2789
- resolve19(ok);
3072
+ resolve20(ok);
2790
3073
  };
2791
3074
  s.setTimeout(500);
2792
3075
  s.once("connect", () => done(true));
@@ -3145,13 +3428,13 @@ function parseContextTenantEnv(context) {
3145
3428
  return { tenant: tenant || "mesh", env: env || "dev" };
3146
3429
  }
3147
3430
  function findFreePort2() {
3148
- return new Promise((resolve19, reject) => {
3431
+ return new Promise((resolve20, reject) => {
3149
3432
  const srv = net6.createServer();
3150
3433
  srv.on("error", reject);
3151
3434
  srv.listen(0, "127.0.0.1", () => {
3152
3435
  const addr = srv.address();
3153
3436
  const port = typeof addr === "object" && addr ? addr.port : 0;
3154
- srv.close(() => resolve19(port));
3437
+ srv.close(() => resolve20(port));
3155
3438
  });
3156
3439
  });
3157
3440
  }
@@ -3374,18 +3657,19 @@ __export(login_exports, {
3374
3657
  resolveRoleOrExplain: () => resolveRoleOrExplain,
3375
3658
  resolveUserAwsConfigPath: () => resolveUserAwsConfigPath,
3376
3659
  runLoginFlow: () => runLoginFlow,
3660
+ shorthandContext: () => shorthandContext,
3377
3661
  tokenStillValid: () => tokenStillValid,
3378
3662
  writeContextConfig: () => writeContextConfig
3379
3663
  });
3380
3664
  import * as http from "http";
3381
3665
  import * as crypto2 from "crypto";
3382
- import * as fs9 from "fs";
3383
- import * as path9 from "path";
3666
+ import * as fs10 from "fs";
3667
+ import * as path10 from "path";
3384
3668
  import { execFileSync as execFileSync10 } from "child_process";
3385
3669
  function readConfig() {
3386
- if (!fs9.existsSync(CONFIG_FILE)) return {};
3670
+ if (!fs10.existsSync(CONFIG_FILE)) return {};
3387
3671
  try {
3388
- return JSON.parse(fs9.readFileSync(CONFIG_FILE, "utf-8"));
3672
+ return JSON.parse(fs10.readFileSync(CONFIG_FILE, "utf-8"));
3389
3673
  } catch {
3390
3674
  return {};
3391
3675
  }
@@ -3393,15 +3677,15 @@ function readConfig() {
3393
3677
  function writeContextConfig(context, config) {
3394
3678
  const existing = readConfig();
3395
3679
  existing[context] = config;
3396
- fs9.mkdirSync(CONFIG_DIR, { recursive: true });
3397
- fs9.writeFileSync(CONFIG_FILE, JSON.stringify(existing, null, 2));
3680
+ fs10.mkdirSync(CONFIG_DIR, { recursive: true });
3681
+ fs10.writeFileSync(CONFIG_FILE, JSON.stringify(existing, null, 2));
3398
3682
  }
3399
3683
  function clearContextConfig(context) {
3400
3684
  const existing = readConfig();
3401
3685
  if (!(context in existing)) return;
3402
3686
  delete existing[context];
3403
- fs9.mkdirSync(CONFIG_DIR, { recursive: true });
3404
- fs9.writeFileSync(CONFIG_FILE, JSON.stringify(existing, null, 2));
3687
+ fs10.mkdirSync(CONFIG_DIR, { recursive: true });
3688
+ fs10.writeFileSync(CONFIG_FILE, JSON.stringify(existing, null, 2));
3405
3689
  }
3406
3690
  function getContextConfig(context) {
3407
3691
  const config = readConfig();
@@ -3509,9 +3793,9 @@ function discoverConfigFromWellKnown(domain, contextKey = domain, opts = {}) {
3509
3793
  return discoverConfig(domain, contextKey, opts);
3510
3794
  }
3511
3795
  function readAllCredentials() {
3512
- if (!fs9.existsSync(CREDENTIALS_FILE)) return {};
3796
+ if (!fs10.existsSync(CREDENTIALS_FILE)) return {};
3513
3797
  try {
3514
- return JSON.parse(fs9.readFileSync(CREDENTIALS_FILE, "utf-8"));
3798
+ return JSON.parse(fs10.readFileSync(CREDENTIALS_FILE, "utf-8"));
3515
3799
  } catch {
3516
3800
  return {};
3517
3801
  }
@@ -3519,21 +3803,21 @@ function readAllCredentials() {
3519
3803
  function readCredentials(context) {
3520
3804
  return readAllCredentials()[context] ?? null;
3521
3805
  }
3522
- function atomicWriteFileSync(path46, data, mode) {
3523
- const tmpPath = `${path46}.${process.pid}.${atomicWriteCounter++}.tmp`;
3806
+ function atomicWriteFileSync(path47, data, mode) {
3807
+ const tmpPath = `${path47}.${process.pid}.${atomicWriteCounter++}.tmp`;
3524
3808
  try {
3525
- fs9.writeFileSync(tmpPath, data, { mode });
3526
- fs9.renameSync(tmpPath, path46);
3809
+ fs10.writeFileSync(tmpPath, data, { mode });
3810
+ fs10.renameSync(tmpPath, path47);
3527
3811
  } catch (err) {
3528
3812
  try {
3529
- fs9.unlinkSync(tmpPath);
3813
+ fs10.unlinkSync(tmpPath);
3530
3814
  } catch {
3531
3815
  }
3532
3816
  throw err;
3533
3817
  }
3534
3818
  }
3535
3819
  function writeCredentials(context, creds) {
3536
- fs9.mkdirSync(CONFIG_DIR, { recursive: true });
3820
+ fs10.mkdirSync(CONFIG_DIR, { recursive: true });
3537
3821
  const all = readAllCredentials();
3538
3822
  all[context] = creds;
3539
3823
  atomicWriteFileSync(CREDENTIALS_FILE, JSON.stringify(all, null, 2), 384);
@@ -3541,8 +3825,8 @@ function writeCredentials(context, creds) {
3541
3825
  function clearCredentials(context) {
3542
3826
  const all = readAllCredentials();
3543
3827
  delete all[context];
3544
- fs9.mkdirSync(CONFIG_DIR, { recursive: true });
3545
- fs9.writeFileSync(CREDENTIALS_FILE, JSON.stringify(all, null, 2), {
3828
+ fs10.mkdirSync(CONFIG_DIR, { recursive: true });
3829
+ fs10.writeFileSync(CREDENTIALS_FILE, JSON.stringify(all, null, 2), {
3546
3830
  mode: 384
3547
3831
  });
3548
3832
  }
@@ -3596,7 +3880,7 @@ async function refreshTokens(issuer, clientId, refreshToken) {
3596
3880
  return resp.json();
3597
3881
  }
3598
3882
  function login(context, config) {
3599
- return new Promise((resolve19, reject) => {
3883
+ return new Promise((resolve20, reject) => {
3600
3884
  const codeVerifier = generateCodeVerifier();
3601
3885
  const codeChallenge = generateCodeChallenge(codeVerifier);
3602
3886
  const state = base64url(crypto2.randomBytes(16));
@@ -3680,7 +3964,7 @@ function login(context, config) {
3680
3964
  }
3681
3965
  hintVpnIfDisconnected(context);
3682
3966
  teardown();
3683
- resolve19();
3967
+ resolve20();
3684
3968
  } catch (err) {
3685
3969
  teardown();
3686
3970
  reject(err);
@@ -3821,7 +4105,7 @@ function loginTimeoutMessage(context) {
3821
4105
  }
3822
4106
  function isRemoteEnvironment() {
3823
4107
  if (process.env.REMOTE_CONTAINERS || process.env.CODESPACES) return true;
3824
- if (fs9.existsSync("/.dockerenv")) return true;
4108
+ if (fs10.existsSync("/.dockerenv")) return true;
3825
4109
  if (process.env.SSH_CLIENT || process.env.SSH_TTY) return true;
3826
4110
  if (!process.stdout.isTTY || !process.stdin.isTTY) return true;
3827
4111
  return false;
@@ -3967,7 +4251,9 @@ async function showStatus(context, config) {
3967
4251
  }
3968
4252
  }
3969
4253
  function registerLoginCommand(program2) {
3970
- program2.command("login").description("Authenticate with Zitadel (OIDC PKCE or Device Code)").argument("<context>", 'Platform context (e.g., "mesh.dev")').option(
4254
+ program2.command("login").description(
4255
+ "PLATFORM access: sign in to a deployed Mesh platform (`<tenant>.<env>`) \u2014 what `mesh deploy`, `mesh stack`, the Hub and the VPN use. It never touches your ~/.npmrc, and you do not need it to install packages: that is `mesh registry login`. OIDC PKCE, or device code with --device."
4256
+ ).argument("<context>", 'Platform context (e.g., "mesh.dev")').option(
3971
4257
  "--status",
3972
4258
  "Show current authentication status \u2014 the Zitadel session if one is cached, otherwise the AWS identity the credential chain resolves (SSO profile or key pair). Exits non-zero only when neither works."
3973
4259
  ).option("--device", "Force device code flow (no callback server needed)").option(
@@ -4021,7 +4307,7 @@ function registerLoginCommand(program2) {
4021
4307
  }
4022
4308
  await hintRegistryIfMissing();
4023
4309
  });
4024
- program2.command("logout").description("Clear cached Zitadel credentials").argument("<context>", 'Platform context (e.g., "mesh.dev")').action((context) => {
4310
+ program2.command("logout").description("Clear a platform context's cached credentials (the package-registry session under `mesh registry` is untouched)").argument("<context>", 'Platform context (e.g., "mesh.dev")').action((context) => {
4025
4311
  refuseReservedRegistryContext(context, "logout");
4026
4312
  clearCredentials(context);
4027
4313
  logSuccess(`Logged out of ${context}. Credentials cleared.`);
@@ -4046,8 +4332,17 @@ async function hintRegistryIfMissing() {
4046
4332
  } catch {
4047
4333
  }
4048
4334
  }
4335
+ function shorthandContext(context) {
4336
+ const parts = context.split(".");
4337
+ if (parts.length !== 2) return null;
4338
+ const [tenant, env] = parts;
4339
+ return tenant && env ? { tenant, env } : null;
4340
+ }
4049
4341
  function renderNoConfigHelp(context) {
4050
4342
  const pinned = firstPartyDomainFor(context);
4343
+ const shorthand = shorthandContext(context);
4344
+ const createOne = shorthand ? `mesh init --tenant ${shorthand.tenant} --new-platform ${shorthand.env}` : "mesh init --tenant <tenant> --new-platform <env>";
4345
+ const scaffoldOne = `mesh init platform ${shorthand?.tenant ?? "<tenant>"} --domain <a domain you control>`;
4051
4346
  return `No configuration found for "${context}".
4052
4347
 
4053
4348
  Tried:
@@ -4059,6 +4354,8 @@ Tried:
4059
4354
  (only attempted for a full domain, or a known first-party context)
4060
4355
 
4061
4356
  `) + `To fix:
4357
+ - No platform deployed yet? Create one: ${createOne}
4358
+ (or the scaffold on its own: ${scaffoldOne})
4062
4359
  - Use the platform's full domain: mesh login <env>.<tenant>.meshtech.io
4063
4360
  - Or, if you have AWS access, ensure SSO is active: aws sso login --profile <profile>
4064
4361
  - Or add config manually to ${CONFIG_FILE}:
@@ -4159,12 +4456,12 @@ export AWS_REGION=${shellSingleQuote(args.region)}
4159
4456
  `;
4160
4457
  }
4161
4458
  function resolveUserAwsConfigPath(env = process.env) {
4162
- return env.AWS_CONFIG_FILE ?? path9.join(env.HOME ?? "~", ".aws", "config");
4459
+ return env.AWS_CONFIG_FILE ?? path10.join(env.HOME ?? "~", ".aws", "config");
4163
4460
  }
4164
4461
  function canWriteDir(dir) {
4165
4462
  try {
4166
- fs9.mkdirSync(dir, { recursive: true });
4167
- fs9.accessSync(dir, fs9.constants.W_OK);
4463
+ fs10.mkdirSync(dir, { recursive: true });
4464
+ fs10.accessSync(dir, fs10.constants.W_OK);
4168
4465
  return true;
4169
4466
  } catch {
4170
4467
  return false;
@@ -4172,9 +4469,9 @@ function canWriteDir(dir) {
4172
4469
  }
4173
4470
  function resolveAwsConfigTarget(env = process.env) {
4174
4471
  if (env.AWS_CONFIG_FILE) return { configPath: env.AWS_CONFIG_FILE, redirected: false };
4175
- const real = path9.join(env.HOME ?? "~", ".aws", "config");
4176
- if (canWriteDir(path9.dirname(real))) return { configPath: real, redirected: false };
4177
- return { configPath: path9.join(CONFIG_DIR, "aws-config"), redirected: true };
4472
+ const real = path10.join(env.HOME ?? "~", ".aws", "config");
4473
+ if (canWriteDir(path10.dirname(real))) return { configPath: real, redirected: false };
4474
+ return { configPath: path10.join(CONFIG_DIR, "aws-config"), redirected: true };
4178
4475
  }
4179
4476
  function resolveRoleOrExplain(opts, config) {
4180
4477
  const role = opts.role ?? process.env.MESH_AWS_ROLE ?? config.defaultRole;
@@ -4294,10 +4591,10 @@ async function exportAwsCredentials(context, config, opts) {
4294
4591
  const sanitized = context.replace(/[^A-Za-z0-9_-]/g, "-");
4295
4592
  const profileName = `mesh-${sanitized}`;
4296
4593
  const { configPath, redirected } = resolveAwsConfigTarget();
4297
- fs9.mkdirSync(path9.dirname(configPath), { recursive: true });
4298
- const existedBefore = fs9.existsSync(configPath);
4299
- const existing = existedBefore ? fs9.readFileSync(configPath, "utf-8") : "";
4300
- const mode = existedBefore ? fs9.statSync(configPath).mode & 511 : 384;
4594
+ fs10.mkdirSync(path10.dirname(configPath), { recursive: true });
4595
+ const existedBefore = fs10.existsSync(configPath);
4596
+ const existing = existedBefore ? fs10.readFileSync(configPath, "utf-8") : "";
4597
+ const mode = existedBefore ? fs10.statSync(configPath).mode & 511 : 384;
4301
4598
  atomicWriteFileSync(
4302
4599
  configPath,
4303
4600
  upsertManagedAwsConfigSection(
@@ -4365,12 +4662,12 @@ var init_login = __esm({
4365
4662
  init_aws_auth();
4366
4663
  init_first_party_contexts();
4367
4664
  init_vpn2();
4368
- CONFIG_DIR = path9.join(
4369
- process.env.XDG_CONFIG_HOME ?? path9.join(process.env.HOME ?? "~", ".config"),
4665
+ CONFIG_DIR = path10.join(
4666
+ process.env.XDG_CONFIG_HOME ?? path10.join(process.env.HOME ?? "~", ".config"),
4370
4667
  "mesh"
4371
4668
  );
4372
- CONFIG_FILE = path9.join(CONFIG_DIR, "config.json");
4373
- CREDENTIALS_FILE = path9.join(CONFIG_DIR, "credentials.json");
4669
+ CONFIG_FILE = path10.join(CONFIG_DIR, "config.json");
4670
+ CREDENTIALS_FILE = path10.join(CONFIG_DIR, "credentials.json");
4374
4671
  REDIRECT_PORT = 9876;
4375
4672
  REDIRECT_URI = `http://localhost:${REDIRECT_PORT}/callback`;
4376
4673
  SCOPES = "openid email profile offline_access urn:zitadel:iam:org:project:id:zitadel:aud";
@@ -4487,6 +4784,7 @@ __export(registry_identity_exports, {
4487
4784
  logRegistryIdentity: () => logRegistryIdentity,
4488
4785
  readRegistrySession: () => readRegistrySession,
4489
4786
  refreshRegistrySession: () => refreshRegistrySession,
4787
+ registryAccountState: () => registryAccountState,
4490
4788
  registrySessionCandidates: () => registrySessionCandidates,
4491
4789
  registryTokenRoles: () => registryTokenRoles,
4492
4790
  resolveRegistryIdentity: () => resolveRegistryIdentity
@@ -4600,6 +4898,19 @@ function registryTokenRoles(idToken) {
4600
4898
  return [];
4601
4899
  }
4602
4900
  }
4901
+ function registryAccountState(idToken) {
4902
+ if (!idToken) return {};
4903
+ let claims = null;
4904
+ try {
4905
+ claims = decodeJwtPayload(idToken);
4906
+ } catch {
4907
+ return {};
4908
+ }
4909
+ if (!claims) return {};
4910
+ const email = typeof claims.email === "string" ? claims.email : void 0;
4911
+ const verified = claims.email_verified;
4912
+ return { email, emailVerified: typeof verified === "boolean" ? verified : void 0 };
4913
+ }
4603
4914
  async function refreshRegistrySession(context) {
4604
4915
  const before = registryTokenRoles(readCredentials(context)?.idToken);
4605
4916
  const idToken = await forceRefreshToken(context);
@@ -4689,14 +5000,14 @@ __export(auth_preflight_exports, {
4689
5000
  stripUnscopedCodeArtifactRegistry: () => stripUnscopedCodeArtifactRegistry,
4690
5001
  upsertNpmrcLines: () => upsertNpmrcLines
4691
5002
  });
4692
- import * as fs10 from "fs";
5003
+ import * as fs11 from "fs";
4693
5004
  import * as os3 from "os";
4694
- import * as path10 from "path";
5005
+ import * as path11 from "path";
4695
5006
  function registryLoginFix() {
4696
5007
  return REGISTRY_LOGIN_FIX;
4697
5008
  }
4698
5009
  function homeNpmrcPath() {
4699
- return path10.join(os3.homedir(), ".npmrc");
5010
+ return path11.join(os3.homedir(), ".npmrc");
4700
5011
  }
4701
5012
  function parseNpmrcRegistryAuth(content) {
4702
5013
  for (const line of content.split("\n")) {
@@ -4761,7 +5072,7 @@ async function probeRegistryToken(opts) {
4761
5072
  const fetchFn = opts?.fetchFn ?? fetch;
4762
5073
  let auth = null;
4763
5074
  try {
4764
- auth = parseNpmrcRegistryAuth(fs10.readFileSync(npmrcPath2, "utf-8"));
5075
+ auth = parseNpmrcRegistryAuth(fs11.readFileSync(npmrcPath2, "utf-8"));
4765
5076
  } catch {
4766
5077
  }
4767
5078
  if (!auth) return { state: "missing" };
@@ -4826,16 +5137,16 @@ function awsConfigHasProfile(content, profile) {
4826
5137
  return content.split("\n").some((line) => pattern.test(line.trim()));
4827
5138
  }
4828
5139
  function readAwsConfig() {
4829
- const file = process.env.AWS_CONFIG_FILE ?? path10.join(os3.homedir(), ".aws", "config");
5140
+ const file = process.env.AWS_CONFIG_FILE ?? path11.join(os3.homedir(), ".aws", "config");
4830
5141
  try {
4831
- return fs10.readFileSync(file, "utf-8");
5142
+ return fs11.readFileSync(file, "utf-8");
4832
5143
  } catch {
4833
5144
  return "";
4834
5145
  }
4835
5146
  }
4836
5147
  function appUsesMeshPackages(appRoot) {
4837
5148
  try {
4838
- const pkg = JSON.parse(fs10.readFileSync(path10.join(appRoot, "package.json"), "utf-8"));
5149
+ const pkg = JSON.parse(fs11.readFileSync(path11.join(appRoot, "package.json"), "utf-8"));
4839
5150
  return [pkg.dependencies, pkg.devDependencies, pkg.optionalDependencies].some(
4840
5151
  (deps) => deps && Object.keys(deps).some((name) => name.startsWith("@mesh-tech/"))
4841
5152
  );
@@ -4858,8 +5169,8 @@ sso_registration_scopes = sso:account:access`;
4858
5169
  });
4859
5170
 
4860
5171
  // libs/mesh-cli/src/utils/aws-auth.ts
4861
- import * as fs11 from "fs";
4862
- import * as path11 from "path";
5172
+ import * as fs12 from "fs";
5173
+ import * as path12 from "path";
4863
5174
  import {
4864
5175
  AssumeRoleCommand,
4865
5176
  AssumeRoleWithWebIdentityCommand,
@@ -4867,9 +5178,9 @@ import {
4867
5178
  STSClient
4868
5179
  } from "@aws-sdk/client-sts";
4869
5180
  function derivePlatformContext(appRoot, stack) {
4870
- const configFile = path11.join(appRoot, `Pulumi.${stack}.yaml`);
4871
- if (!fs11.existsSync(configFile)) return null;
4872
- const content = fs11.readFileSync(configFile, "utf-8");
5181
+ const configFile = path12.join(appRoot, `Pulumi.${stack}.yaml`);
5182
+ if (!fs12.existsSync(configFile)) return null;
5183
+ const content = fs12.readFileSync(configFile, "utf-8");
4873
5184
  const jsonMatch = content.match(/mesh:platform:\s*'(\{[^']+\})'/);
4874
5185
  if (jsonMatch) {
4875
5186
  try {
@@ -4889,11 +5200,11 @@ function quoteCredProcessToken(token) {
4889
5200
  return /\s/.test(token) ? `"${token}"` : token;
4890
5201
  }
4891
5202
  function resolveStableMeshBin(argv1, deps = {}) {
4892
- const exists = deps.exists ?? fs11.existsSync;
5203
+ const exists = deps.exists ?? fs12.existsSync;
4893
5204
  const warn = deps.warn ?? logWarn;
4894
- let resolved = argv1 ? path11.resolve(argv1) : void 0;
5205
+ let resolved = argv1 ? path12.resolve(argv1) : void 0;
4895
5206
  if (resolved && /\.ts$/.test(resolved)) {
4896
- resolved = path11.join(path11.dirname(resolved), path11.basename(resolved, ".ts") + ".mjs");
5207
+ resolved = path12.join(path12.dirname(resolved), path12.basename(resolved, ".ts") + ".mjs");
4897
5208
  }
4898
5209
  const transient = resolved !== void 0 && (/[\\/]_npx[\\/]/.test(resolved) || /^\/(?:private\/)?(?:tmp|var\/folders)\//.test(resolved));
4899
5210
  if (!resolved || !exists(resolved) || transient) {
@@ -5315,9 +5626,9 @@ var init_pulumi_run = __esm({
5315
5626
  });
5316
5627
 
5317
5628
  // libs/mesh-cli/src/utils/kubeconfig.ts
5318
- import * as fs12 from "fs";
5629
+ import * as fs13 from "fs";
5319
5630
  import * as os4 from "os";
5320
- import * as path12 from "path";
5631
+ import * as path13 from "path";
5321
5632
  function buildKubeconfig(cluster, region) {
5322
5633
  return `apiVersion: v1
5323
5634
  kind: Config
@@ -5348,7 +5659,7 @@ users:
5348
5659
  `;
5349
5660
  }
5350
5661
  function sessionKubeconfigPath(sessionName) {
5351
- return path12.join(os4.tmpdir(), "mesh-dev-sessions", `${sessionName}.kubeconfig`);
5662
+ return path13.join(os4.tmpdir(), "mesh-dev-sessions", `${sessionName}.kubeconfig`);
5352
5663
  }
5353
5664
  function resolveHubPlatformName(platform) {
5354
5665
  return platform?.name ?? "mesh";
@@ -5381,10 +5692,10 @@ async function ensureKubeconfig(platformName, env, sessionName, deps = {}) {
5381
5692
  }
5382
5693
  const region = process.env.AWS_REGION || "us-east-2";
5383
5694
  const kubeconfigPath = sessionKubeconfigPath(sessionName);
5384
- if (!fs12.existsSync(path12.dirname(kubeconfigPath))) {
5385
- fs12.mkdirSync(path12.dirname(kubeconfigPath), { recursive: true });
5695
+ if (!fs13.existsSync(path13.dirname(kubeconfigPath))) {
5696
+ fs13.mkdirSync(path13.dirname(kubeconfigPath), { recursive: true });
5386
5697
  }
5387
- fs12.writeFileSync(kubeconfigPath, buildKubeconfig(cluster, region), { mode: 384 });
5698
+ fs13.writeFileSync(kubeconfigPath, buildKubeconfig(cluster, region), { mode: 384 });
5388
5699
  return kubeconfigPath;
5389
5700
  }
5390
5701
  var init_kubeconfig = __esm({
@@ -5529,14 +5840,14 @@ var init_temporal_auth = __esm({
5529
5840
  // libs/mesh-cli/src/utils/reachability.ts
5530
5841
  import { createConnection } from "node:net";
5531
5842
  function probeTcpReachable(host, port, timeoutMs = 1500) {
5532
- return new Promise((resolve19) => {
5843
+ return new Promise((resolve20) => {
5533
5844
  let settled = false;
5534
5845
  const socket = createConnection({ host, port });
5535
5846
  const finish = (ok) => {
5536
5847
  if (settled) return;
5537
5848
  settled = true;
5538
5849
  socket.destroy();
5539
- resolve19(ok);
5850
+ resolve20(ok);
5540
5851
  };
5541
5852
  socket.setTimeout(timeoutMs);
5542
5853
  socket.once("connect", () => finish(true));
@@ -5545,7 +5856,7 @@ function probeTcpReachable(host, port, timeoutMs = 1500) {
5545
5856
  });
5546
5857
  }
5547
5858
  function probeConnectionHolds(host, port, timeoutMs = 800, holdMs = 25) {
5548
- return new Promise((resolve19) => {
5859
+ return new Promise((resolve20) => {
5549
5860
  let settled = false;
5550
5861
  let holdTimer;
5551
5862
  const socket = createConnection({ host, port });
@@ -5554,7 +5865,7 @@ function probeConnectionHolds(host, port, timeoutMs = 800, holdMs = 25) {
5554
5865
  settled = true;
5555
5866
  if (holdTimer) clearTimeout(holdTimer);
5556
5867
  socket.destroy();
5557
- resolve19(ok);
5868
+ resolve20(ok);
5558
5869
  };
5559
5870
  socket.setTimeout(timeoutMs);
5560
5871
  socket.once("connect", () => {
@@ -5573,27 +5884,27 @@ var init_reachability = __esm({
5573
5884
 
5574
5885
  // libs/mesh-cli/src/utils/workflow-fingerprint.ts
5575
5886
  import { createHash as createHash2 } from "node:crypto";
5576
- import { existsSync as existsSync11, readFileSync as readFileSync11, readdirSync as readdirSync4 } from "node:fs";
5577
- import { dirname as dirname11, isAbsolute as isAbsolute2, join as join11, relative as relative2 } from "node:path";
5578
- function findRepoRoot(startDir) {
5887
+ import { existsSync as existsSync12, readFileSync as readFileSync12, readdirSync as readdirSync4 } from "node:fs";
5888
+ import { dirname as dirname12, isAbsolute as isAbsolute2, join as join12, relative as relative3 } from "node:path";
5889
+ function findRepoRoot2(startDir) {
5579
5890
  let dir = startDir;
5580
5891
  for (; ; ) {
5581
- if (existsSync11(join11(dir, "pnpm-workspace.yaml"))) return dir;
5582
- const parent = dirname11(dir);
5892
+ if (existsSync12(join12(dir, "pnpm-workspace.yaml"))) return dir;
5893
+ const parent = dirname12(dir);
5583
5894
  if (parent === dir) return startDir;
5584
5895
  dir = parent;
5585
5896
  }
5586
5897
  }
5587
5898
  function workflowSourceDirs(repoRoot2, extraDirs = []) {
5588
- const pkgDirs = WORKFLOW_PACKAGE_DIRS.map((d) => join11(repoRoot2, d)).filter((d) => existsSync11(d));
5899
+ const pkgDirs = WORKFLOW_PACKAGE_DIRS.map((d) => join12(repoRoot2, d)).filter((d) => existsSync12(d));
5589
5900
  if (pkgDirs.length > 0) return pkgDirs;
5590
- return extraDirs.filter((d) => existsSync11(d));
5901
+ return extraDirs.filter((d) => existsSync12(d));
5591
5902
  }
5592
5903
  function resolveWorkerSourceDirs(repoRoot2, services = {}) {
5593
5904
  const dirs = [];
5594
5905
  for (const [name, svc] of Object.entries(services)) {
5595
5906
  if (/worker/i.test(name) && svc?.src) {
5596
- dirs.push(isAbsolute2(svc.src) ? svc.src : join11(repoRoot2, svc.src));
5907
+ dirs.push(isAbsolute2(svc.src) ? svc.src : join12(repoRoot2, svc.src));
5597
5908
  }
5598
5909
  }
5599
5910
  return dirs;
@@ -5609,7 +5920,7 @@ function computeWorkflowFingerprint(dirs, relativeTo) {
5609
5920
  }
5610
5921
  for (const rel2 of rels) {
5611
5922
  const p = String(rel2);
5612
- if (/\.(ts|tsx)$/.test(p) && !EXCLUDE.test(p)) files.push(join11(dir, p));
5923
+ if (/\.(ts|tsx)$/.test(p) && !EXCLUDE.test(p)) files.push(join12(dir, p));
5613
5924
  }
5614
5925
  }
5615
5926
  files.sort();
@@ -5617,8 +5928,8 @@ function computeWorkflowFingerprint(dirs, relativeTo) {
5617
5928
  const h = createHash2("sha256");
5618
5929
  for (const f of files) {
5619
5930
  try {
5620
- const content = readFileSync11(f);
5621
- h.update(relativeTo ? relative2(relativeTo, f) : f);
5931
+ const content = readFileSync12(f);
5932
+ h.update(relativeTo ? relative3(relativeTo, f) : f);
5622
5933
  h.update("\0");
5623
5934
  h.update(content);
5624
5935
  h.update("\0");
@@ -5628,7 +5939,7 @@ function computeWorkflowFingerprint(dirs, relativeTo) {
5628
5939
  return h.digest("hex").slice(0, 16);
5629
5940
  }
5630
5941
  function fingerprintWorkflowSource(appRoot, services = {}) {
5631
- const repoRoot2 = findRepoRoot(appRoot);
5942
+ const repoRoot2 = findRepoRoot2(appRoot);
5632
5943
  const workerDirs = resolveWorkerSourceDirs(repoRoot2, services);
5633
5944
  return computeWorkflowFingerprint(workflowSourceDirs(repoRoot2, workerDirs), repoRoot2);
5634
5945
  }
@@ -5646,9 +5957,9 @@ var init_workflow_fingerprint = __esm({
5646
5957
  });
5647
5958
 
5648
5959
  // libs/mesh-cli/src/commands/dev-launch.ts
5649
- import * as fs13 from "fs";
5960
+ import * as fs14 from "fs";
5650
5961
  import * as net7 from "net";
5651
- import * as path13 from "path";
5962
+ import * as path14 from "path";
5652
5963
  function quoteShellValue(value) {
5653
5964
  return `'${value.replace(/'/g, "'\\''")}'`;
5654
5965
  }
@@ -5670,9 +5981,9 @@ function envFileName(serviceName) {
5670
5981
  return `${serviceName.replace(/[^A-Za-z0-9._-]/g, "-")}.env.sh`;
5671
5982
  }
5672
5983
  function writeEnvFile(filePath, env) {
5673
- fs13.mkdirSync(path13.dirname(filePath), { recursive: true });
5674
- fs13.writeFileSync(filePath, renderEnvFile(env), { mode: ENV_FILE_MODE });
5675
- fs13.chmodSync(filePath, ENV_FILE_MODE);
5984
+ fs14.mkdirSync(path14.dirname(filePath), { recursive: true });
5985
+ fs14.writeFileSync(filePath, renderEnvFile(env), { mode: ENV_FILE_MODE });
5986
+ fs14.chmodSync(filePath, ENV_FILE_MODE);
5676
5987
  }
5677
5988
  function buildLaunchCommand(envFilePath, dir, command, logShipper) {
5678
5989
  const base = `cd ${quoteShellValue(dir)} && source ${quoteShellValue(envFilePath)} && `;
@@ -5686,16 +5997,16 @@ async function waitForPort(host, port, timeoutMs, intervalMs = 500) {
5686
5997
  const attemptTimeout = Math.max(250, Math.min(1e3, remaining));
5687
5998
  if (await tryConnect(host, port, attemptTimeout)) return true;
5688
5999
  if (Date.now() + intervalMs >= deadline) return false;
5689
- await new Promise((resolve19) => setTimeout(resolve19, intervalMs));
6000
+ await new Promise((resolve20) => setTimeout(resolve20, intervalMs));
5690
6001
  }
5691
6002
  }
5692
6003
  function tryConnect(host, port, timeoutMs) {
5693
- return new Promise((resolve19) => {
6004
+ return new Promise((resolve20) => {
5694
6005
  const socket = net7.connect({ host, port });
5695
6006
  const done = (ok) => {
5696
6007
  socket.removeAllListeners();
5697
6008
  socket.destroy();
5698
- resolve19(ok);
6009
+ resolve20(ok);
5699
6010
  };
5700
6011
  socket.setTimeout(timeoutMs);
5701
6012
  socket.once("connect", () => done(true));
@@ -5714,8 +6025,8 @@ var init_dev_launch = __esm({
5714
6025
 
5715
6026
  // libs/mesh-cli/src/commands/local/mocks.ts
5716
6027
  import { execFileSync as execFileSync12 } from "child_process";
5717
- import * as fs14 from "fs";
5718
- import * as path14 from "path";
6028
+ import * as fs15 from "fs";
6029
+ import * as path15 from "path";
5719
6030
  function externalMode(name, decl) {
5720
6031
  const mode = decl.mode ?? (decl.compose ? "local" : decl.openapi || decl.src ? "mock" : decl.sandbox || decl.credentials || decl.remote ? "remote" : void 0);
5721
6032
  if (!mode || !EXTERNAL_MODES.includes(mode)) {
@@ -5839,8 +6150,8 @@ async function planComposeExternal(composeFile, project, port, probes) {
5839
6150
  return { action: "up" };
5840
6151
  }
5841
6152
  async function composeExternalUp(appRoot, sessionName, name, decl, probes = dockerProbes) {
5842
- const composeFile = path14.resolve(appRoot, decl.compose);
5843
- if (!fs14.existsSync(composeFile)) {
6153
+ const composeFile = path15.resolve(appRoot, decl.compose);
6154
+ if (!fs15.existsSync(composeFile)) {
5844
6155
  throw new MeshCliError(`External '${name}': compose file not found at ${composeFile}.`, {
5845
6156
  remediation: { docs: 'package.json \u2192 "mesh": { "externals": { \u2026 } }' }
5846
6157
  });
@@ -5980,7 +6291,7 @@ function composeExternalsDown(refs) {
5980
6291
  }
5981
6292
  function readLocalMocks(appRoot) {
5982
6293
  try {
5983
- const pkg = JSON.parse(fs14.readFileSync(path14.join(appRoot, "package.json"), "utf-8"));
6294
+ const pkg = JSON.parse(fs15.readFileSync(path15.join(appRoot, "package.json"), "utf-8"));
5984
6295
  const mocks = pkg?.mesh?.mocks;
5985
6296
  const externals = pkg?.mesh?.externals;
5986
6297
  return {
@@ -6075,12 +6386,12 @@ function externalDocs(decl) {
6075
6386
  return typeof decl.docs === "string" ? { url: decl.docs } : decl.docs;
6076
6387
  }
6077
6388
  function localProbeFile(tenant, app, external) {
6078
- return path14.join(localProbesDir(), `${tenant}-${app}-${external}.json`);
6389
+ return path15.join(localProbesDir(), `${tenant}-${app}-${external}.json`);
6079
6390
  }
6080
6391
  function localProbesRemove(files) {
6081
6392
  for (const file of files ?? []) {
6082
6393
  try {
6083
- fs14.rmSync(file, { force: true });
6394
+ fs15.rmSync(file, { force: true });
6084
6395
  } catch {
6085
6396
  }
6086
6397
  }
@@ -6169,7 +6480,7 @@ async function seedLocalMock(args) {
6169
6480
  );
6170
6481
  const probeFile = localProbeFile(tenant, app, decl.external);
6171
6482
  if (probe) {
6172
- fs14.writeFileSync(
6483
+ fs15.writeFileSync(
6173
6484
  probeFile,
6174
6485
  JSON.stringify(
6175
6486
  [
@@ -6278,7 +6589,7 @@ var init_hub_roles = __esm({
6278
6589
 
6279
6590
  // libs/api-registry/src/index.ts
6280
6591
  import { z } from "zod";
6281
- var rateLimitSpecSchema, rateLimitDefaultsSchema, integrationHealthSchema, apiSurfaceKindSchema, apiDocsSiteAudienceSchema, apiSurfaceSchema, apiRegistryEntrySchema, integrationStatusSchema;
6592
+ var rateLimitSpecSchema, rateLimitDefaultsSchema, integrationHealthSchema, apiSurfaceKindSchema, apiDocsSiteAudienceSchema, apiSurfaceSchema, apiRegistryEntrySchema, integrationStatusSchema, hubActAsExportsSchema;
6282
6593
  var init_src = __esm({
6283
6594
  "libs/api-registry/src/index.ts"() {
6284
6595
  "use strict";
@@ -6314,6 +6625,7 @@ var init_src = __esm({
6314
6625
  docs: z.object({
6315
6626
  url: z.string().min(1),
6316
6627
  contentHash: z.string().min(1),
6628
+ trimmed: z.object({ url: z.string().min(1), contentHash: z.string().min(1) }).optional(),
6317
6629
  siteUrl: z.string().min(1).optional(),
6318
6630
  audience: apiDocsSiteAudienceSchema.optional()
6319
6631
  }),
@@ -6321,6 +6633,7 @@ var init_src = __esm({
6321
6633
  // The consumer schema strips unknown keys, so a producer-side field that is
6322
6634
  // not mirrored here never reaches a consumer — mirror every addition.
6323
6635
  status: z.object({ url: z.string().min(1) }).optional(),
6636
+ actAs: z.object({ url: z.string().min(1) }).optional(),
6324
6637
  appVersion: z.string().min(1).optional(),
6325
6638
  rateLimits: rateLimitDefaultsSchema.optional(),
6326
6639
  health: integrationHealthSchema.optional(),
@@ -6345,13 +6658,26 @@ var init_src = __esm({
6345
6658
  health: integrationHealthSchema.optional(),
6346
6659
  startedAt: z.string().min(1)
6347
6660
  });
6661
+ hubActAsExportsSchema = z.object({
6662
+ issuer: z.string().min(1),
6663
+ keys: z.array(
6664
+ z.object({
6665
+ kid: z.string().min(1),
6666
+ kty: z.literal("RSA"),
6667
+ n: z.string().min(1),
6668
+ e: z.string().min(1),
6669
+ alg: z.string().optional(),
6670
+ use: z.string().optional()
6671
+ })
6672
+ ).min(1)
6673
+ });
6348
6674
  }
6349
6675
  });
6350
6676
 
6351
6677
  // libs/mesh-cli/src/commands/local/seed-zitadel.ts
6352
- import * as fs15 from "fs";
6678
+ import * as fs16 from "fs";
6353
6679
  import * as os5 from "os";
6354
- import * as path15 from "path";
6680
+ import * as path16 from "path";
6355
6681
  function buildCliAppPayload() {
6356
6682
  return {
6357
6683
  name: CLI_APP_NAME,
@@ -6368,10 +6694,10 @@ function buildCliAppPayload() {
6368
6694
  };
6369
6695
  }
6370
6696
  function readSeederPat() {
6371
- const tmp = path15.join(fs15.mkdtempSync(path15.join(os5.tmpdir(), "mesh-zitadel-")), "pat.txt");
6697
+ const tmp = path16.join(fs16.mkdtempSync(path16.join(os5.tmpdir(), "mesh-zitadel-")), "pat.txt");
6372
6698
  try {
6373
6699
  compose(["cp", "zitadel:/machinekey/pat.txt", tmp]);
6374
- const pat = fs15.readFileSync(tmp, "utf-8").trim();
6700
+ const pat = fs16.readFileSync(tmp, "utf-8").trim();
6375
6701
  if (!pat) throw new Error("empty PAT file");
6376
6702
  return pat;
6377
6703
  } catch {
@@ -6380,7 +6706,7 @@ function readSeederPat() {
6380
6706
  { remediation: { command: "mesh stop --destroy && mesh start" } }
6381
6707
  );
6382
6708
  } finally {
6383
- fs15.rmSync(path15.dirname(tmp), { recursive: true, force: true });
6709
+ fs16.rmSync(path16.dirname(tmp), { recursive: true, force: true });
6384
6710
  }
6385
6711
  }
6386
6712
  async function api(pat, method, apiPath, body, orgId) {
@@ -6479,11 +6805,11 @@ async function ensureTestUsers(pat) {
6479
6805
  }
6480
6806
  }
6481
6807
  function hubAuthPath() {
6482
- return path15.join(meshCacheDir("mesh-local"), "hub-auth.json");
6808
+ return path16.join(meshCacheDir("mesh-local"), "hub-auth.json");
6483
6809
  }
6484
6810
  function readHubAuth() {
6485
6811
  try {
6486
- const parsed = JSON.parse(fs15.readFileSync(hubAuthPath(), "utf-8"));
6812
+ const parsed = JSON.parse(fs16.readFileSync(hubAuthPath(), "utf-8"));
6487
6813
  if (parsed?.clientId && parsed?.clientSecret && parsed?.cookieSecret) return parsed;
6488
6814
  return null;
6489
6815
  } catch {
@@ -6622,7 +6948,7 @@ async function seedHubAuth(pat) {
6622
6948
  clientSecret: app.clientSecret ?? persisted?.clientSecret ?? "",
6623
6949
  cookieSecret: persistedCookie ?? (await import("crypto")).randomBytes(16).toString("hex")
6624
6950
  };
6625
- fs15.writeFileSync(hubAuthPath(), JSON.stringify(config, null, 2), { mode: 384 });
6951
+ fs16.writeFileSync(hubAuthPath(), JSON.stringify(config, null, 2), { mode: 384 });
6626
6952
  return config;
6627
6953
  }
6628
6954
  async function publishHubAuthzPointer(projectId, orgId, awsConfig) {
@@ -7206,56 +7532,6 @@ var init_auth_provision = __esm({
7206
7532
  }
7207
7533
  });
7208
7534
 
7209
- // libs/mesh-cli/src/utils/mesh-json.ts
7210
- import * as fs16 from "fs";
7211
- import * as path16 from "path";
7212
- function isValidTenantName(value) {
7213
- return /^[a-z][a-z0-9-]*$/.test(value);
7214
- }
7215
- function parseMeshJson(content) {
7216
- try {
7217
- const data = JSON.parse(content);
7218
- if (typeof data?.tenant !== "string" || !isValidTenantName(data.tenant)) return null;
7219
- const platform = typeof data.platform === "string" && data.platform ? data.platform : "local";
7220
- return { tenant: data.tenant, platform };
7221
- } catch {
7222
- return null;
7223
- }
7224
- }
7225
- function findMeshJson(startDir) {
7226
- let dir = path16.resolve(startDir);
7227
- while (true) {
7228
- const candidate = path16.join(dir, MESH_JSON);
7229
- if (fs16.existsSync(candidate)) {
7230
- let content = "";
7231
- try {
7232
- content = fs16.readFileSync(candidate, "utf-8");
7233
- } catch {
7234
- return null;
7235
- }
7236
- const data = parseMeshJson(content);
7237
- return data ? { path: candidate, data } : null;
7238
- }
7239
- if (fs16.existsSync(path16.join(dir, ".git"))) return null;
7240
- const parent = path16.dirname(dir);
7241
- if (parent === dir) return null;
7242
- dir = parent;
7243
- }
7244
- }
7245
- function writeMeshJson(rootDir, data) {
7246
- const target = path16.join(rootDir, MESH_JSON);
7247
- fs16.writeFileSync(target, `${JSON.stringify({ tenant: data.tenant, platform: data.platform }, null, 2)}
7248
- `);
7249
- return target;
7250
- }
7251
- var MESH_JSON;
7252
- var init_mesh_json = __esm({
7253
- "libs/mesh-cli/src/utils/mesh-json.ts"() {
7254
- "use strict";
7255
- MESH_JSON = "mesh.json";
7256
- }
7257
- });
7258
-
7259
7535
  // libs/mesh-cli/src/commands/local/dev-local.ts
7260
7536
  import * as fs17 from "fs";
7261
7537
  import * as path17 from "path";
@@ -7780,7 +8056,7 @@ async function startTokenServer(port, context) {
7780
8056
  })();
7781
8057
  });
7782
8058
  server.on("error", (e) => logWarn(`token-server error: ${e.message}`));
7783
- await new Promise((resolve19) => server.listen(port, "127.0.0.1", resolve19));
8059
+ await new Promise((resolve20) => server.listen(port, "127.0.0.1", resolve20));
7784
8060
  logInfo(`dev-user token-server on http://127.0.0.1:${port} (context ${context})`);
7785
8061
  await new Promise(() => {
7786
8062
  });
@@ -7910,10 +8186,10 @@ function removeSessionState(sessionName) {
7910
8186
  }
7911
8187
  }
7912
8188
  async function isPortFree(port) {
7913
- const bindSucceeds = (host) => new Promise((resolve19) => {
8189
+ const bindSucceeds = (host) => new Promise((resolve20) => {
7914
8190
  const server = net8.createServer();
7915
- server.once("error", () => resolve19(false));
7916
- const onListening = () => server.close(() => resolve19(true));
8191
+ server.once("error", () => resolve20(false));
8192
+ const onListening = () => server.close(() => resolve20(true));
7917
8193
  if (host === void 0) server.listen(port, onListening);
7918
8194
  else server.listen(port, host, onListening);
7919
8195
  });
@@ -7921,24 +8197,24 @@ async function isPortFree(port) {
7921
8197
  return bindSucceeds("127.0.0.1");
7922
8198
  }
7923
8199
  async function findFreePort3() {
7924
- return new Promise((resolve19, reject) => {
8200
+ return new Promise((resolve20, reject) => {
7925
8201
  const server = net8.createServer();
7926
8202
  server.once("error", reject);
7927
8203
  server.listen(0, "127.0.0.1", () => {
7928
8204
  const { port } = server.address();
7929
- server.close(() => resolve19(port));
8205
+ server.close(() => resolve20(port));
7930
8206
  });
7931
8207
  });
7932
8208
  }
7933
8209
  function isPortListening(port) {
7934
- return new Promise((resolve19) => {
8210
+ return new Promise((resolve20) => {
7935
8211
  const s = new net8.Socket();
7936
8212
  let done = false;
7937
8213
  const fin = (ok) => {
7938
8214
  if (done) return;
7939
8215
  done = true;
7940
8216
  s.destroy();
7941
- resolve19(ok);
8217
+ resolve20(ok);
7942
8218
  };
7943
8219
  s.setTimeout(300);
7944
8220
  s.once("connect", () => fin(true));
@@ -10372,14 +10648,14 @@ function isConfigStale(configMtimeMs, startedAtIso) {
10372
10648
  return configMtimeMs > Date.parse(startedAtIso);
10373
10649
  }
10374
10650
  function canConnect2(host, port, timeoutMs = 800) {
10375
- return new Promise((resolve19) => {
10651
+ return new Promise((resolve20) => {
10376
10652
  const socket = new net9.Socket();
10377
10653
  let settled = false;
10378
10654
  const done = (ok) => {
10379
10655
  if (settled) return;
10380
10656
  settled = true;
10381
10657
  socket.destroy();
10382
- resolve19(ok);
10658
+ resolve20(ok);
10383
10659
  };
10384
10660
  socket.setTimeout(timeoutMs);
10385
10661
  socket.once("connect", () => done(true));
@@ -11982,11 +12258,11 @@ function createVcsFolderReader(opts) {
11982
12258
  }
11983
12259
  return p;
11984
12260
  };
11985
- const readPath = async (repo, path46) => {
12261
+ const readPath = async (repo, path47) => {
11986
12262
  const dir = await cloneRepo(repo);
11987
- const ref = await resolveFolderRef(dir, path46);
11988
- if (!ref) throw new Error(`path "${path46}" not found on any ref of ${repo}`);
11989
- const files = await readFolderAtRef(dir, ref, path46);
12263
+ const ref = await resolveFolderRef(dir, path47);
12264
+ if (!ref) throw new Error(`path "${path47}" not found on any ref of ${repo}`);
12265
+ const files = await readFolderAtRef(dir, ref, path47);
11990
12266
  return { ref, files };
11991
12267
  };
11992
12268
  const cleanup = async () => {
@@ -13280,25 +13556,50 @@ var init_create_app = __esm({
13280
13556
  }
13281
13557
  });
13282
13558
 
13559
+ // libs/mesh-cli/src/commands/db/axes.ts
13560
+ function platformAxis(options, usage, detect = detectContext) {
13561
+ if (options.tenant && !options.env || !options.tenant && options.env) {
13562
+ throw new MeshCliError("Both --tenant and --env are required", {
13563
+ remediation: { command: usage }
13564
+ });
13565
+ }
13566
+ let resolved;
13567
+ return () => {
13568
+ if (resolved) return resolved;
13569
+ if (options.tenant && options.env) {
13570
+ resolved = { tenant: options.tenant, env: options.env };
13571
+ logInfo(`Platform: Tenant=${resolved.tenant}, Env=${resolved.env}`);
13572
+ } else {
13573
+ const ctx = detect();
13574
+ resolved = { tenant: ctx.tenant, env: ctx.platformEnv };
13575
+ logInfo(`Auto-detected: Tenant=${resolved.tenant}, Env=${resolved.env}`);
13576
+ }
13577
+ return resolved;
13578
+ };
13579
+ }
13580
+ function appAxis(options, platform) {
13581
+ if (options.appTenant && options.appStage) {
13582
+ return { tenant: options.appTenant, stage: options.appStage };
13583
+ }
13584
+ const resolved = platform();
13585
+ return {
13586
+ tenant: options.appTenant ?? resolved.tenant,
13587
+ stage: options.appStage ?? resolved.env
13588
+ };
13589
+ }
13590
+ var init_axes = __esm({
13591
+ "libs/mesh-cli/src/commands/db/axes.ts"() {
13592
+ "use strict";
13593
+ init_context();
13594
+ init_errors();
13595
+ init_log();
13596
+ }
13597
+ });
13598
+
13283
13599
  // libs/mesh-cli/src/commands/db/connect.ts
13284
13600
  import { spawn as spawn4 } from "child_process";
13285
13601
  async function connectCommand(options) {
13286
- let tenant;
13287
- let platformEnv;
13288
- if (options.tenant && options.env) {
13289
- tenant = options.tenant;
13290
- platformEnv = options.env;
13291
- logInfo(`Explicit mode: Tenant=${tenant}, Env=${platformEnv}`);
13292
- } else if (options.tenant || options.env) {
13293
- logError("Both --tenant and --env are required");
13294
- logInfo("Usage: mesh db connect --tenant mesh --env dev-temporal");
13295
- process.exit(1);
13296
- } else {
13297
- const ctx = detectContext();
13298
- tenant = ctx.tenant;
13299
- platformEnv = ctx.platformEnv;
13300
- logInfo(`Auto-detected: Tenant=${tenant}, Env=${platformEnv}`);
13301
- }
13602
+ const { tenant, env: platformEnv } = platformAxis(options, USAGE)();
13302
13603
  const bastion = await getPlatformBastionInfo(tenant, platformEnv);
13303
13604
  const rdsService = bastion.services.rds;
13304
13605
  if (!rdsService) {
@@ -13341,38 +13642,25 @@ async function connectCommand(options) {
13341
13642
  process.exit(code ?? 0);
13342
13643
  });
13343
13644
  }
13645
+ var USAGE;
13344
13646
  var init_connect = __esm({
13345
13647
  "libs/mesh-cli/src/commands/db/connect.ts"() {
13346
13648
  "use strict";
13347
13649
  init_utils();
13650
+ init_axes();
13651
+ USAGE = "mesh db connect --tenant mesh --env dev-temporal";
13348
13652
  }
13349
13653
  });
13350
13654
 
13351
13655
  // libs/mesh-cli/src/commands/db/credentials.ts
13352
13656
  async function credentialsCommand(options) {
13353
- let platformTenant;
13354
- let platformEnv;
13355
- if (options.tenant && options.env) {
13356
- platformTenant = options.tenant;
13357
- platformEnv = options.env;
13358
- logInfo(`Platform: Tenant=${platformTenant}, Env=${platformEnv}`);
13359
- } else if (options.tenant || options.env) {
13360
- logError("Both --tenant and --env are required");
13361
- logInfo("Usage: mesh db credentials --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev");
13362
- process.exit(1);
13363
- } else {
13364
- const ctx = detectContext();
13365
- platformTenant = ctx.tenant;
13366
- platformEnv = ctx.platformEnv;
13367
- logInfo(`Auto-detected: Tenant=${platformTenant}, Env=${platformEnv}`);
13368
- }
13369
- const appTenant = options.appTenant ?? platformTenant;
13370
- const appStage = options.appStage ?? platformEnv;
13657
+ const platform = platformAxis(options, USAGE2);
13658
+ const app = appAxis(options, platform);
13371
13659
  const appName = options.app;
13372
13660
  if (appName) {
13373
- logInfo(`App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);
13661
+ logInfo(`App credentials: tenant=${app.tenant}, stage=${app.stage}, app=${appName}`);
13374
13662
  }
13375
- const databaseUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });
13663
+ const databaseUrl = await getDatabaseUrl(app.tenant, app.stage, { app: appName });
13376
13664
  const parsed = new URL(databaseUrl);
13377
13665
  console.log("");
13378
13666
  console.log("Database Credentials:");
@@ -13392,38 +13680,25 @@ async function credentialsCommand(options) {
13392
13680
  console.log(` ${tunnelUrl.toString()}`);
13393
13681
  console.log("");
13394
13682
  }
13683
+ var USAGE2;
13395
13684
  var init_credentials2 = __esm({
13396
13685
  "libs/mesh-cli/src/commands/db/credentials.ts"() {
13397
13686
  "use strict";
13398
13687
  init_utils();
13688
+ init_axes();
13689
+ USAGE2 = "mesh db credentials --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev";
13399
13690
  }
13400
13691
  });
13401
13692
 
13402
13693
  // libs/mesh-cli/src/commands/db/env.ts
13403
13694
  async function envCommand(options) {
13404
- let platformTenant;
13405
- let platformEnv;
13406
- if (options.tenant && options.env) {
13407
- platformTenant = options.tenant;
13408
- platformEnv = options.env;
13409
- console.error(`\u2139 Platform: Tenant=${platformTenant}, Env=${platformEnv}`);
13410
- } else if (options.tenant || options.env) {
13411
- logError("Both --tenant and --env are required");
13412
- logInfo("Usage: eval $(mesh db env --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev)");
13413
- process.exit(1);
13414
- } else {
13415
- const ctx = detectContext();
13416
- platformTenant = ctx.tenant;
13417
- platformEnv = ctx.platformEnv;
13418
- console.error(`\u2139 Auto-detected: Tenant=${platformTenant}, Env=${platformEnv}`);
13419
- }
13420
- const appTenant = options.appTenant ?? platformTenant;
13421
- const appStage = options.appStage ?? platformEnv;
13695
+ const platform = platformAxis(options, USAGE3);
13696
+ const app = appAxis(options, platform);
13422
13697
  const appName = options.app;
13423
13698
  if (appName) {
13424
- console.error(`\u2139 App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);
13699
+ console.error(`\u2139 App credentials: tenant=${app.tenant}, stage=${app.stage}, app=${appName}`);
13425
13700
  }
13426
- const rawUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });
13701
+ const rawUrl = await getDatabaseUrl(app.tenant, app.stage, { app: appName });
13427
13702
  const tunnelUrl = rewriteDatabaseUrl(rawUrl, { endpoint: "localhost:5432" });
13428
13703
  const parsed = new URL(tunnelUrl);
13429
13704
  console.log(`export DATABASE_URL="${tunnelUrl}"`);
@@ -13433,10 +13708,13 @@ async function envCommand(options) {
13433
13708
  console.log(`export DB_USERNAME="${parsed.username}"`);
13434
13709
  console.log(`export DB_PASSWORD="${decodeURIComponent(parsed.password)}"`);
13435
13710
  }
13711
+ var USAGE3;
13436
13712
  var init_env = __esm({
13437
13713
  "libs/mesh-cli/src/commands/db/env.ts"() {
13438
13714
  "use strict";
13439
13715
  init_utils();
13716
+ init_axes();
13717
+ USAGE3 = "eval $(mesh db env --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev)";
13440
13718
  }
13441
13719
  });
13442
13720
 
@@ -13479,58 +13757,43 @@ async function startTunnelBackground(instanceId, rdsHost, rdsPort, localPort) {
13479
13757
  throw new Error(`Tunnel failed to start after ${maxAttempts} seconds`);
13480
13758
  }
13481
13759
  function checkPort(port) {
13482
- return new Promise((resolve19) => {
13760
+ return new Promise((resolve20) => {
13483
13761
  const socket = new net10.Socket();
13484
13762
  socket.setTimeout(500);
13485
13763
  socket.on("connect", () => {
13486
13764
  socket.destroy();
13487
- resolve19(true);
13765
+ resolve20(true);
13488
13766
  });
13489
13767
  socket.on("timeout", () => {
13490
13768
  socket.destroy();
13491
- resolve19(false);
13769
+ resolve20(false);
13492
13770
  });
13493
13771
  socket.on("error", () => {
13494
13772
  socket.destroy();
13495
- resolve19(false);
13773
+ resolve20(false);
13496
13774
  });
13497
13775
  socket.connect(port, "localhost");
13498
13776
  });
13499
13777
  }
13500
13778
  function sleep2(ms) {
13501
- return new Promise((resolve19) => setTimeout(resolve19, ms));
13779
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
13502
13780
  }
13503
13781
  async function psqlCommand(options) {
13504
- let platformTenant;
13505
- let platformEnv;
13506
- if (options.tenant && options.env) {
13507
- platformTenant = options.tenant;
13508
- platformEnv = options.env;
13509
- logInfo(`Platform: Tenant=${platformTenant}, Env=${platformEnv}`);
13510
- } else if (options.tenant || options.env) {
13511
- logError("Both --tenant and --env are required");
13512
- logInfo("Usage: mesh db psql --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev");
13513
- process.exit(1);
13514
- } else {
13515
- const ctx = detectContext();
13516
- platformTenant = ctx.tenant;
13517
- platformEnv = ctx.platformEnv;
13518
- logInfo(`Auto-detected: Tenant=${platformTenant}, Env=${platformEnv}`);
13519
- }
13520
- const appTenant = options.appTenant ?? platformTenant;
13521
- const appStage = options.appStage ?? platformEnv;
13782
+ const platform = platformAxis(options, USAGE4);
13783
+ const { tenant: platformTenant, env: platformEnv } = platform();
13784
+ const app = appAxis(options, platform);
13522
13785
  const appName = options.app;
13523
13786
  if (appName) {
13524
- logInfo(`App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);
13787
+ logInfo(`App credentials: tenant=${app.tenant}, stage=${app.stage}, app=${appName}`);
13525
13788
  }
13526
13789
  const psqlCheck = spawn5("which", ["psql"]);
13527
- await new Promise((resolve19, reject) => {
13790
+ await new Promise((resolve20, reject) => {
13528
13791
  psqlCheck.on("exit", (code) => {
13529
13792
  if (code !== 0) {
13530
13793
  logError("psql not found. Install with: brew install postgresql");
13531
13794
  reject(new Error("psql not found"));
13532
13795
  } else {
13533
- resolve19();
13796
+ resolve20();
13534
13797
  }
13535
13798
  });
13536
13799
  });
@@ -13553,7 +13816,7 @@ async function psqlCommand(options) {
13553
13816
  process.on("exit", cleanup);
13554
13817
  process.on("SIGINT", cleanup);
13555
13818
  process.on("SIGTERM", cleanup);
13556
- const databaseUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });
13819
+ const databaseUrl = await getDatabaseUrl(app.tenant, app.stage, { app: appName });
13557
13820
  const parsed = new URL(databaseUrl);
13558
13821
  const username = parsed.username;
13559
13822
  const password2 = decodeURIComponent(parsed.password);
@@ -13574,10 +13837,13 @@ async function psqlCommand(options) {
13574
13837
  process.exit(code ?? 0);
13575
13838
  });
13576
13839
  }
13840
+ var USAGE4;
13577
13841
  var init_psql = __esm({
13578
13842
  "libs/mesh-cli/src/commands/db/psql.ts"() {
13579
13843
  "use strict";
13580
13844
  init_utils();
13845
+ init_axes();
13846
+ USAGE4 = "mesh db psql --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev";
13581
13847
  }
13582
13848
  });
13583
13849
 
@@ -13617,26 +13883,26 @@ function findSstOutputs() {
13617
13883
  return null;
13618
13884
  }
13619
13885
  function checkPort2(port) {
13620
- return new Promise((resolve19) => {
13886
+ return new Promise((resolve20) => {
13621
13887
  const socket = new net11.Socket();
13622
13888
  socket.setTimeout(500);
13623
13889
  socket.on("connect", () => {
13624
13890
  socket.destroy();
13625
- resolve19(true);
13891
+ resolve20(true);
13626
13892
  });
13627
13893
  socket.on("timeout", () => {
13628
13894
  socket.destroy();
13629
- resolve19(false);
13895
+ resolve20(false);
13630
13896
  });
13631
13897
  socket.on("error", () => {
13632
13898
  socket.destroy();
13633
- resolve19(false);
13899
+ resolve20(false);
13634
13900
  });
13635
13901
  socket.connect(port, "localhost");
13636
13902
  });
13637
13903
  }
13638
13904
  function sleep3(ms) {
13639
- return new Promise((resolve19) => setTimeout(resolve19, ms));
13905
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
13640
13906
  }
13641
13907
  async function startTunnelBackground2(instanceId, rdsEndpoint, rdsPort, localPort) {
13642
13908
  logInfo("Starting database tunnel...");
@@ -13760,28 +14026,14 @@ async function execCommand(commandArgs, options) {
13760
14026
  logWarn("Could not parse DATABASE_URL for rewriting");
13761
14027
  }
13762
14028
  } else {
13763
- let platformTenant;
13764
- let platformEnv;
13765
- if (options.tenant && options.env) {
13766
- platformTenant = options.tenant;
13767
- platformEnv = options.env;
13768
- logInfo(`Explicit mode: Platform Tenant=${platformTenant}, Platform Env=${platformEnv}`);
13769
- } else if (options.tenant || options.env) {
13770
- logError("Both --tenant and --env are required when using explicit mode");
13771
- logInfo("Usage: mesh db exec --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev -- <command>");
13772
- logInfo("Or omit both to use auto-detection");
13773
- process.exit(1);
13774
- } else {
13775
- const ctx = detectContext();
13776
- platformTenant = ctx.tenant;
13777
- platformEnv = ctx.platformEnv;
13778
- logInfo(`Discovery mode: Platform=${platformEnv}, Tenant=${platformTenant}`);
13779
- }
13780
- const appTenant = options.appTenant ?? platformTenant;
13781
- const appStage = options.appStage ?? platformEnv;
14029
+ const platform = platformAxis(
14030
+ options,
14031
+ "mesh db exec --tenant mesh --env dev-temporal --app rdc --app-tenant encore --app-stage dev -- <command>"
14032
+ );
14033
+ const app = appAxis(options, platform);
13782
14034
  const appName = options.app;
13783
14035
  if (appName) {
13784
- logInfo(`App credentials: tenant=${appTenant}, stage=${appStage}, app=${appName}`);
14036
+ logInfo(`App credentials: tenant=${app.tenant}, stage=${app.stage}, app=${appName}`);
13785
14037
  }
13786
14038
  const tunnelExists = await checkPort2(localPort);
13787
14039
  const sstOutputs = findSstOutputs();
@@ -13802,6 +14054,7 @@ async function execCommand(commandArgs, options) {
13802
14054
  }
13803
14055
  if (!databaseUrl) {
13804
14056
  if (!tunnelExists) {
14057
+ const { tenant: platformTenant, env: platformEnv } = platform();
13805
14058
  const bastion = await getPlatformBastionInfo(platformTenant, platformEnv);
13806
14059
  const rdsService = bastion.services.rds;
13807
14060
  if (!rdsService) {
@@ -13816,7 +14069,7 @@ async function execCommand(commandArgs, options) {
13816
14069
  } else {
13817
14070
  logSuccess(`Using existing tunnel on port ${localPort}`);
13818
14071
  }
13819
- const rawUrl = await getDatabaseUrl(appTenant, appStage, { app: appName });
14072
+ const rawUrl = await getDatabaseUrl(app.tenant, app.stage, { app: appName });
13820
14073
  databaseUrl = rewriteDatabaseUrl(rawUrl, {
13821
14074
  endpoint: `localhost:${localPort}`,
13822
14075
  sslMode: options.ssl
@@ -13856,6 +14109,7 @@ var init_exec = __esm({
13856
14109
  "libs/mesh-cli/src/commands/db/exec.ts"() {
13857
14110
  "use strict";
13858
14111
  init_utils();
14112
+ init_axes();
13859
14113
  DEFAULT_LOCAL_PORT = 5432;
13860
14114
  MAX_RETRIES = 12;
13861
14115
  RETRY_DELAY_MS = 5e3;
@@ -13884,7 +14138,7 @@ var init_db = __esm({
13884
14138
 
13885
14139
  // libs/mesh-cli/src/utils/deploy-preflight.ts
13886
14140
  import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
13887
- import { dirname as dirname22, join as join25, relative as relative6 } from "node:path";
14141
+ import { dirname as dirname22, join as join25, relative as relative7 } from "node:path";
13888
14142
  import { parse as parseYaml3 } from "yaml";
13889
14143
  function isGated(name) {
13890
14144
  return GATED_PREFIXES.some((p) => name.startsWith(p));
@@ -13950,7 +14204,7 @@ function checkDeployDepsFresh(appRoot) {
13950
14204
  );
13951
14205
  return null;
13952
14206
  }
13953
- const importerRel = relative6(dirname22(lockPath), appRoot) || ".";
14207
+ const importerRel = relative7(dirname22(lockPath), appRoot) || ".";
13954
14208
  const expected = extractImporterMeshVersions(lockDoc, importerRel);
13955
14209
  const names = Object.keys(expected);
13956
14210
  if (names.length === 0) return [];
@@ -14976,8 +15230,8 @@ function formatDefault(value, paths = currentMachinePaths()) {
14976
15230
  if (typeof value === "boolean" || typeof value === "number") return String(value);
14977
15231
  return normalizeMachinePaths(JSON.stringify(value), paths);
14978
15232
  }
14979
- function slugifyCommandPath(path46) {
14980
- return path46.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
15233
+ function slugifyCommandPath(path47) {
15234
+ return path47.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
14981
15235
  }
14982
15236
  function extractOptions(command) {
14983
15237
  const options = command.options ?? [];
@@ -15011,17 +15265,17 @@ function isUndocumented(command) {
15011
15265
  function extractCommand(command, parentPath, depth) {
15012
15266
  const internals = command;
15013
15267
  const name = internals._name ?? "";
15014
- const path46 = parentPath ? `${parentPath} ${name}` : name;
15268
+ const path47 = parentPath ? `${parentPath} ${name}` : name;
15015
15269
  return {
15016
- path: path46,
15270
+ path: path47,
15017
15271
  name,
15018
15272
  aliases: [...internals._aliases ?? []],
15019
15273
  description: internals._description ?? "",
15020
15274
  args: extractArgs(command),
15021
15275
  options: extractOptions(command),
15022
- slug: slugifyCommandPath(path46),
15276
+ slug: slugifyCommandPath(path47),
15023
15277
  depth,
15024
- subcommands: (internals.commands ?? []).filter((child) => !isUndocumented(child)).map((child) => extractCommand(child, path46, depth + 1))
15278
+ subcommands: (internals.commands ?? []).filter((child) => !isUndocumented(child)).map((child) => extractCommand(child, path47, depth + 1))
15025
15279
  };
15026
15280
  }
15027
15281
  function extractCliReference(program2) {
@@ -15249,14 +15503,14 @@ ${summary}`);
15249
15503
  function runZudoku(args) {
15250
15504
  const cliArgs = args.mode === "dev" ? ["dev", "--port", String(args.port ?? 3e3)] : ["build"];
15251
15505
  logInfo(`Running \`zudoku ${cliArgs.join(" ")}\` in ${args.appDir}`);
15252
- return new Promise((resolve19, reject) => {
15506
+ return new Promise((resolve20, reject) => {
15253
15507
  const child = spawn7("pnpm", ["exec", "zudoku", ...cliArgs], {
15254
15508
  cwd: args.appDir,
15255
15509
  stdio: "inherit",
15256
15510
  env: process.env
15257
15511
  });
15258
15512
  child.on("error", reject);
15259
- child.on("close", (code) => resolve19(code ?? 1));
15513
+ child.on("close", (code) => resolve20(code ?? 1));
15260
15514
  });
15261
15515
  }
15262
15516
  async function runPortalCommand(opts, deps) {
@@ -15467,17 +15721,17 @@ async function serveDocsSite(args) {
15467
15721
  res.writeHead(500).end("internal error");
15468
15722
  });
15469
15723
  });
15470
- await new Promise((resolve19, reject) => {
15724
+ await new Promise((resolve20, reject) => {
15471
15725
  server.once("error", reject);
15472
- server.listen(args.port, "127.0.0.1", () => resolve19());
15726
+ server.listen(args.port, "127.0.0.1", () => resolve20());
15473
15727
  });
15474
15728
  const address = server.address();
15475
15729
  const port = typeof address === "object" && address ? address.port : args.port;
15476
15730
  return {
15477
15731
  url: `http://127.0.0.1:${port}`,
15478
15732
  port,
15479
- close: () => new Promise((resolve19, reject) => {
15480
- server.close((error) => error ? reject(error) : resolve19());
15733
+ close: () => new Promise((resolve20, reject) => {
15734
+ server.close((error) => error ? reject(error) : resolve20());
15481
15735
  })
15482
15736
  };
15483
15737
  }
@@ -15730,7 +15984,7 @@ Or run in the foreground instead: mesh docs start --foreground`
15730
15984
  } catch (error) {
15731
15985
  lastError = error instanceof Error ? error.message : String(error);
15732
15986
  }
15733
- await new Promise((resolve19) => setTimeout(resolve19, 500));
15987
+ await new Promise((resolve20) => setTimeout(resolve20, 500));
15734
15988
  }
15735
15989
  throw new Error(
15736
15990
  `the docs server did not answer at ${url} within 60s (${lastError || "no response"}).
@@ -15767,8 +16021,8 @@ async function runDocsServeStatic(args) {
15767
16021
  }
15768
16022
  const server = await serveDocsSite({ root: args.root, port: requestedPort });
15769
16023
  logSuccess(`Mesh docs serving at ${server.url} (from ${args.root})`);
15770
- await new Promise((resolve19) => {
15771
- const stop = () => void server.close().finally(() => resolve19());
16024
+ await new Promise((resolve20) => {
16025
+ const stop = () => void server.close().finally(() => resolve20());
15772
16026
  process.once("SIGINT", stop);
15773
16027
  process.once("SIGTERM", stop);
15774
16028
  });
@@ -15822,8 +16076,8 @@ async function runDocsStart(args) {
15822
16076
  stdio: "inherit",
15823
16077
  env: process.env
15824
16078
  });
15825
- await new Promise((resolve19) => {
15826
- child.on("close", () => resolve19());
16079
+ await new Promise((resolve20) => {
16080
+ child.on("close", () => resolve20());
15827
16081
  process.once("SIGINT", () => child.kill("SIGINT"));
15828
16082
  process.once("SIGTERM", () => child.kill("SIGTERM"));
15829
16083
  });
@@ -15839,7 +16093,7 @@ async function runDocsStart(args) {
15839
16093
  reportAssembly(result);
15840
16094
  const { spawn: spawn10 } = await import("node:child_process");
15841
16095
  writeFileSync18(buildLog, "");
15842
- const code = await new Promise((resolve19) => {
16096
+ const code = await new Promise((resolve20) => {
15843
16097
  const child = spawn10("pnpm", ["exec", "zudoku", "build"], {
15844
16098
  cwd: appDir,
15845
16099
  stdio: ["ignore", "pipe", "pipe"],
@@ -15847,8 +16101,8 @@ async function runDocsStart(args) {
15847
16101
  });
15848
16102
  child.stdout?.on("data", (chunk) => appendFileSync2(buildLog, chunk));
15849
16103
  child.stderr?.on("data", (chunk) => appendFileSync2(buildLog, chunk));
15850
- child.on("error", () => resolve19(1));
15851
- child.on("close", (exitCode) => resolve19(exitCode ?? 1));
16104
+ child.on("error", () => resolve20(1));
16105
+ child.on("close", (exitCode) => resolve20(exitCode ?? 1));
15852
16106
  });
15853
16107
  if (code !== 0) throw new Error(`zudoku build exited with code ${code} \u2014 see ${buildLog}`);
15854
16108
  serveRoot = path32.join(appDir, "dist");
@@ -15868,9 +16122,9 @@ async function runDocsStart(args) {
15868
16122
  const server = await serveDocsSite({ root: serveRoot, port: requestedPort });
15869
16123
  logSuccess(`Mesh docs (${label}) serving at ${server.url}`);
15870
16124
  logInfo("Press Ctrl-C to stop");
15871
- await new Promise((resolve19) => {
16125
+ await new Promise((resolve20) => {
15872
16126
  const stop = () => {
15873
- void server.close().finally(() => resolve19());
16127
+ void server.close().finally(() => resolve20());
15874
16128
  };
15875
16129
  process.once("SIGINT", stop);
15876
16130
  process.once("SIGTERM", stop);
@@ -16025,7 +16279,7 @@ function guarded(action) {
16025
16279
  };
16026
16280
  }
16027
16281
  async function runCliReference(opts) {
16028
- const repoRoot2 = findRepoRoot(process.cwd());
16282
+ const repoRoot2 = findRepoRoot2(process.cwd());
16029
16283
  const outPath = resolvePath(repoRoot2, opts.out);
16030
16284
  const markdown = await renderCliReference();
16031
16285
  if (opts.check) {
@@ -16045,7 +16299,7 @@ async function runCliReference(opts) {
16045
16299
  logSuccess(`CLI reference \u2192 ${path33.relative(repoRoot2, outPath)}`);
16046
16300
  }
16047
16301
  async function runPortal(opts) {
16048
- const repoRoot2 = findRepoRoot(process.cwd());
16302
+ const repoRoot2 = findRepoRoot2(process.cwd());
16049
16303
  await runPortalCommand(
16050
16304
  {
16051
16305
  out: opts.out,
@@ -16083,7 +16337,7 @@ function registerDocsCommand(program2) {
16083
16337
  (opts) => guarded(async () => {
16084
16338
  const { runDocsStart: runDocsStart2 } = await Promise.resolve().then(() => (init_start(), start_exports));
16085
16339
  await runDocsStart2({
16086
- repoRoot: findRepoRoot(process.cwd()),
16340
+ repoRoot: findRepoRoot2(process.cwd()),
16087
16341
  version: opts.version,
16088
16342
  port: opts.port,
16089
16343
  dev: opts.dev,
@@ -16320,24 +16574,24 @@ function resolvePlatformDir(explicit, cwd, env = process.env) {
16320
16574
  );
16321
16575
  }
16322
16576
  async function findFreePort4() {
16323
- return new Promise((resolve19, reject) => {
16577
+ return new Promise((resolve20, reject) => {
16324
16578
  const server = net12.createServer();
16325
16579
  server.listen(0, "127.0.0.1", () => {
16326
16580
  const address = server.address();
16327
16581
  server.close(
16328
- () => typeof address === "object" && address ? resolve19(address.port) : reject(new Error("no port"))
16582
+ () => typeof address === "object" && address ? resolve20(address.port) : reject(new Error("no port"))
16329
16583
  );
16330
16584
  });
16331
16585
  server.on("error", reject);
16332
16586
  });
16333
16587
  }
16334
16588
  function isPortListening2(port) {
16335
- return new Promise((resolve19) => {
16589
+ return new Promise((resolve20) => {
16336
16590
  const socket = net12.connect({ host: "127.0.0.1", port, timeout: 400 });
16337
16591
  const done = (ok) => {
16338
16592
  socket.removeAllListeners();
16339
16593
  socket.destroy();
16340
- resolve19(ok);
16594
+ resolve20(ok);
16341
16595
  };
16342
16596
  socket.once("connect", () => done(true));
16343
16597
  socket.once("timeout", () => done(false));
@@ -16533,10 +16787,231 @@ var init_hub = __esm({
16533
16787
  }
16534
16788
  });
16535
16789
 
16536
- // libs/mesh-cli/src/commands/registry-publish.ts
16537
- import { execFileSync as execFileSync24, execSync } from "child_process";
16790
+ // libs/mesh-cli/src/commands/init/platform-setup.ts
16791
+ var platform_setup_exports = {};
16792
+ __export(platform_setup_exports, {
16793
+ DOMAIN_REQUIRED_MESSAGE: () => DOMAIN_REQUIRED_MESSAGE,
16794
+ PLATFORM_SETUP_DEFAULTS: () => PLATFORM_SETUP_DEFAULTS,
16795
+ defaultPlatformDir: () => defaultPlatformDir,
16796
+ defaultStateBucket: () => defaultStateBucket,
16797
+ ensureStateBucket: () => ensureStateBucket,
16798
+ exportCredentialsCommand: () => exportCredentialsCommand,
16799
+ realStateBucketDeps: () => realStateBucketDeps,
16800
+ renderPlatformNextSteps: () => renderPlatformNextSteps,
16801
+ resolvePlatformSetup: () => resolvePlatformSetup,
16802
+ resolveTargetDir: () => resolveTargetDir,
16803
+ scaffoldPlatformRepo: () => scaffoldPlatformRepo,
16804
+ stateBucketCreateCommand: () => stateBucketCreateCommand,
16805
+ validateDomain: () => validateDomain,
16806
+ validateEnv: () => validateEnv,
16807
+ validateRegion: () => validateRegion,
16808
+ validateStateBucket: () => validateStateBucket
16809
+ });
16538
16810
  import * as fs28 from "fs";
16539
16811
  import * as path35 from "path";
16812
+ import { execFileSync as execFileSync24 } from "child_process";
16813
+ function defaultStateBucket(tenant) {
16814
+ return `${tenant}-mesh-platform-pulumi-state`;
16815
+ }
16816
+ function defaultPlatformDir(tenant) {
16817
+ return `${tenant}-mesh-platform`;
16818
+ }
16819
+ function validateEnv(value) {
16820
+ return /^[a-z][a-z0-9-]*$/.test(value.trim()) ? true : "lowercase letters, digits and dashes, starting with a letter";
16821
+ }
16822
+ function validateRegion(value) {
16823
+ return /^[a-z]{2}(-[a-z]+)+-\d$/.test(value.trim()) ? true : "an AWS region, e.g. us-east-2 or eu-west-1";
16824
+ }
16825
+ function validateDomain(value) {
16826
+ const domain = value.trim().toLowerCase().replace(/\.$/, "");
16827
+ if (!domain) return "a public domain you control, e.g. q2poc.pub";
16828
+ if (!/^(?=.{1,253}$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/.test(domain)) {
16829
+ return "a public domain you control, e.g. q2poc.pub";
16830
+ }
16831
+ if (/(^|\.)(example\.(com|org|net)|invalid|localhost|test)$/.test(domain)) {
16832
+ return `${domain} is a placeholder \u2014 the deploy stalls on an ACM certificate for a zone nobody can delegate. Use a domain you control.`;
16833
+ }
16834
+ return true;
16835
+ }
16836
+ function validateStateBucket(value) {
16837
+ const bucket = value.trim();
16838
+ return /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(bucket) && !bucket.includes("..") ? true : "3\u201363 characters: lowercase letters, digits, dots and dashes, starting and ending alphanumeric";
16839
+ }
16840
+ function resolveTargetDir(tenant, flags, cwd) {
16841
+ const dir = path35.resolve(cwd, flags.dir ?? defaultPlatformDir(tenant));
16842
+ if (fs28.existsSync(dir) && fs28.readdirSync(dir).length > 0) {
16843
+ throw new MeshCliError(`Target directory is not empty: ${dir}`, {
16844
+ remediation: { command: `mesh init platform ${tenant} --dir <empty-dir>` }
16845
+ });
16846
+ }
16847
+ return dir;
16848
+ }
16849
+ async function resolvePlatformSetup(tenant, flags, deps) {
16850
+ const cwd = deps.cwd ?? process.cwd();
16851
+ const dir = resolveTargetDir(tenant, flags, cwd);
16852
+ const ask = deps.interactive && !flags.yes ? deps.prompts : void 0;
16853
+ const env = flags.env ?? (ask ? await ask.input({ message: "Environment", default: PLATFORM_SETUP_DEFAULTS.env, validate: validateEnv }) : PLATFORM_SETUP_DEFAULTS.env);
16854
+ if (validateEnv(env) !== true) throw new MeshCliError(`Invalid environment '${env}' \u2014 ${validateEnv(env)}.`);
16855
+ const region = flags.region ?? (ask ? await ask.input({ message: "AWS region", default: PLATFORM_SETUP_DEFAULTS.region, validate: validateRegion }) : PLATFORM_SETUP_DEFAULTS.region);
16856
+ if (validateRegion(region) !== true) throw new MeshCliError(`Invalid region '${region}' \u2014 ${validateRegion(region)}.`);
16857
+ let domain = flags.domain;
16858
+ if (domain === void 0) {
16859
+ if (!ask) throw new MeshCliError(DOMAIN_REQUIRED_MESSAGE, { remediation: { command: `mesh init platform ${tenant} --domain <your-domain>` } });
16860
+ domain = await ask.input({
16861
+ message: `Public base domain (the core stack creates the Route 53 zone ${env}.<domain>; its NS records must be delegated from the parent before the deploy can finish)`,
16862
+ validate: validateDomain
16863
+ });
16864
+ }
16865
+ const domainCheck = validateDomain(domain);
16866
+ if (domainCheck !== true) throw new MeshCliError(`Invalid --domain '${domain}' \u2014 ${domainCheck}`);
16867
+ domain = domain.trim().toLowerCase().replace(/\.$/, "");
16868
+ const profile = flags.profile ?? (ask ? await ask.input({ message: "AWS profile the stack config references", default: PLATFORM_SETUP_DEFAULTS.profile }) : PLATFORM_SETUP_DEFAULTS.profile);
16869
+ const bucketDefault = defaultStateBucket(tenant);
16870
+ const stateBucket = flags.stateBucket ?? (ask ? await ask.input({ message: "Pulumi state S3 bucket (holds this platform's state \u2014 created below if it does not exist)", default: bucketDefault, validate: validateStateBucket }) : bucketDefault);
16871
+ const bucketCheck = validateStateBucket(stateBucket);
16872
+ if (bucketCheck !== true) throw new MeshCliError(`Invalid --state-bucket '${stateBucket}' \u2014 ${bucketCheck}`);
16873
+ let createStateBucket = flags.createStateBucket ?? false;
16874
+ if (flags.createStateBucket === void 0 && ask) {
16875
+ createStateBucket = await ask.confirm({
16876
+ message: `Create s3://${stateBucket} in ${region} now (versioned), if it does not exist?`,
16877
+ default: true
16878
+ });
16879
+ }
16880
+ return {
16881
+ tenant,
16882
+ env,
16883
+ region,
16884
+ domain,
16885
+ profile,
16886
+ stateBucket: stateBucket.trim(),
16887
+ dir,
16888
+ createStateBucket
16889
+ };
16890
+ }
16891
+ function stateBucketCreateCommand(setup) {
16892
+ const location = setup.region === "us-east-1" ? "" : ` --create-bucket-configuration LocationConstraint=${setup.region}`;
16893
+ return `aws s3api create-bucket --bucket ${setup.stateBucket} --region ${setup.region}${location} --profile ${setup.profile}`;
16894
+ }
16895
+ function awsJson(args, profile) {
16896
+ return execFileSync24("aws", [...args, "--profile", profile], {
16897
+ encoding: "utf8",
16898
+ stdio: ["ignore", "pipe", "pipe"]
16899
+ });
16900
+ }
16901
+ async function ensureStateBucket(setup, deps = realStateBucketDeps) {
16902
+ if (!setup.createStateBucket) {
16903
+ return { created: false, present: false, detail: "not requested" };
16904
+ }
16905
+ try {
16906
+ if (deps.headBucket(setup)) {
16907
+ return { created: false, present: true, detail: `s3://${setup.stateBucket} already exists` };
16908
+ }
16909
+ } catch {
16910
+ }
16911
+ try {
16912
+ deps.createBucket(setup);
16913
+ } catch (err) {
16914
+ const why = errorDetail(err);
16915
+ return { created: false, present: false, detail: `could not create s3://${setup.stateBucket} \u2014 ${why}` };
16916
+ }
16917
+ try {
16918
+ deps.enableVersioning(setup);
16919
+ return { created: true, present: true, detail: `created s3://${setup.stateBucket} in ${setup.region} (versioning on)` };
16920
+ } catch (err) {
16921
+ return { created: true, present: true, detail: `created s3://${setup.stateBucket} in ${setup.region}, but versioning could not be enabled \u2014 ${errorDetail(err)}` };
16922
+ }
16923
+ }
16924
+ function errorDetail(err) {
16925
+ const stderr = err && typeof err === "object" && "stderr" in err ? String(err.stderr ?? "") : "";
16926
+ const text = stderr.trim() || (err instanceof Error ? err.message : String(err));
16927
+ return text.split("\n").filter(Boolean).slice(-1)[0] ?? "unknown error";
16928
+ }
16929
+ function exportCredentialsCommand(profile) {
16930
+ return `eval "$(aws configure export-credentials --profile ${profile} --format env)" # mesh deploy reads AWS_ACCESS_KEY_ID; a platform stack carries no mesh:deployerRole`;
16931
+ }
16932
+ function renderPlatformNextSteps(setup, opts = {}) {
16933
+ const dir = opts.relativeDir ?? setup.dir;
16934
+ const steps = [];
16935
+ if (!opts.bucket?.present) {
16936
+ steps.push(`${stateBucketCreateCommand(setup)} # the Pulumi state bucket, once`);
16937
+ }
16938
+ steps.push(
16939
+ `cd ${dir}`,
16940
+ "pnpm install",
16941
+ `aws sso login --profile ${setup.profile} # if this profile is SSO`,
16942
+ exportCredentialsCommand(setup.profile),
16943
+ `cd core && mesh deploy up # the VPC, EKS, RDS and the public zone ${setup.env}.${setup.domain}`,
16944
+ `# \u2192 then delegate the NS records of ${setup.env}.${setup.domain} from ${setup.domain}; the deploy waits on the ACM certificate until you do`,
16945
+ "cd ../platform && mesh deploy up # Temporal, Zitadel, the Hub (needs Docker \u2014 it builds service images)",
16946
+ `mesh login ${setup.tenant}.${setup.env} # your platform sign-in, once it is up`,
16947
+ "",
16948
+ "Then, in your apps repo, for the hello-world app:",
16949
+ ` mesh init --tenant ${setup.tenant} --platform ${setup.env}`,
16950
+ " mesh create-app --name hello --primitives service",
16951
+ " mesh deploy up # from the app directory"
16952
+ );
16953
+ return steps;
16954
+ }
16955
+ async function scaffoldPlatformRepo(setup) {
16956
+ if (fs28.existsSync(setup.dir) && fs28.readdirSync(setup.dir).length > 0) {
16957
+ throw new MeshCliError(`Target directory is not empty: ${setup.dir}`, {
16958
+ remediation: { command: `mesh init platform ${setup.tenant} --dir <empty-dir>` }
16959
+ });
16960
+ }
16961
+ const { copyTemplate: copyTemplate2 } = await Promise.resolve().then(() => (init_create_app(), create_app_exports));
16962
+ const { findPackageRoot: findPackageRoot2 } = await Promise.resolve().then(() => (init_stack(), stack_exports));
16963
+ const { syncSkills: syncSkills2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
16964
+ const templateDir = path35.join(findPackageRoot2(), "templates", "platform-repo");
16965
+ fs28.mkdirSync(setup.dir, { recursive: true });
16966
+ copyTemplate2(templateDir, setup.dir, {
16967
+ tenant: setup.tenant,
16968
+ env: setup.env,
16969
+ region: setup.region,
16970
+ domain: setup.domain,
16971
+ profile: setup.profile,
16972
+ stateBucket: setup.stateBucket
16973
+ });
16974
+ syncSkills2(setup.dir);
16975
+ }
16976
+ var PLATFORM_SETUP_DEFAULTS, DOMAIN_REQUIRED_MESSAGE, realStateBucketDeps;
16977
+ var init_platform_setup = __esm({
16978
+ "libs/mesh-cli/src/commands/init/platform-setup.ts"() {
16979
+ "use strict";
16980
+ init_errors();
16981
+ PLATFORM_SETUP_DEFAULTS = {
16982
+ env: "dev",
16983
+ region: "us-east-2",
16984
+ profile: "default"
16985
+ };
16986
+ DOMAIN_REQUIRED_MESSAGE = "--domain is required: the core stack creates the public Route 53 zone <env>.<domain>, and a placeholder domain scaffolds a zone that can never validate (the deploy stalls on the ACM certificate).";
16987
+ realStateBucketDeps = {
16988
+ headBucket(setup) {
16989
+ try {
16990
+ awsJson(["s3api", "head-bucket", "--bucket", setup.stateBucket, "--region", setup.region], setup.profile);
16991
+ return true;
16992
+ } catch {
16993
+ return false;
16994
+ }
16995
+ },
16996
+ createBucket(setup) {
16997
+ const args = ["s3api", "create-bucket", "--bucket", setup.stateBucket, "--region", setup.region];
16998
+ if (setup.region !== "us-east-1") args.push("--create-bucket-configuration", `LocationConstraint=${setup.region}`);
16999
+ awsJson(args, setup.profile);
17000
+ },
17001
+ enableVersioning(setup) {
17002
+ awsJson(
17003
+ ["s3api", "put-bucket-versioning", "--bucket", setup.stateBucket, "--region", setup.region, "--versioning-configuration", "Status=Enabled"],
17004
+ setup.profile
17005
+ );
17006
+ }
17007
+ };
17008
+ }
17009
+ });
17010
+
17011
+ // libs/mesh-cli/src/commands/registry-publish.ts
17012
+ import { execFileSync as execFileSync25, execSync } from "child_process";
17013
+ import * as fs29 from "fs";
17014
+ import * as path36 from "path";
16540
17015
  function repoRoot() {
16541
17016
  return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
16542
17017
  }
@@ -16546,9 +17021,9 @@ function computeSnapshotVersion(root) {
16546
17021
  return `0.0.0-dev.${stamp}.${sha}`;
16547
17022
  }
16548
17023
  function setPackageVersion(file, version) {
16549
- const content = fs28.readFileSync(file, "utf-8");
17024
+ const content = fs29.readFileSync(file, "utf-8");
16550
17025
  const next = content.replace(/"version"(\s*:\s*)"[^"]*"/, `"version"$1"${version}"`);
16551
- fs28.writeFileSync(file, next);
17026
+ fs29.writeFileSync(file, next);
16552
17027
  }
16553
17028
  function dirtyPackageJsons(root) {
16554
17029
  const out = execSync("git diff --name-only", { cwd: root, encoding: "utf-8" });
@@ -16581,8 +17056,8 @@ function registerRegistryPublish(registry) {
16581
17056
  logError("CodeArtifact login failed. Run: mesh registry login <context>");
16582
17057
  process.exit(1);
16583
17058
  }
16584
- const listPath = path35.join(root, "scripts/lib/publishable-packages.json");
16585
- const all = JSON.parse(fs28.readFileSync(listPath, "utf-8"));
17059
+ const listPath = path36.join(root, "scripts/lib/publishable-packages.json");
17060
+ const all = JSON.parse(fs29.readFileSync(listPath, "utf-8"));
16586
17061
  const patterns = (opts.only ?? "").split(",").map((s) => s.trim()).filter(Boolean);
16587
17062
  const selected = patterns.length ? all.filter((p) => patterns.some((pat) => p.dir.includes(pat) || p.name.includes(pat))) : all;
16588
17063
  if (selected.length === 0) {
@@ -16594,16 +17069,16 @@ function registerRegistryPublish(registry) {
16594
17069
  const preDirty = dirtyPackageJsons(root);
16595
17070
  const backups = [];
16596
17071
  const stamp = (dir) => {
16597
- const file = path35.join(root, dir, "package.json");
16598
- if (!fs28.existsSync(file)) return;
16599
- backups.push({ file, content: fs28.readFileSync(file, "utf-8") });
17072
+ const file = path36.join(root, dir, "package.json");
17073
+ if (!fs29.existsSync(file)) return;
17074
+ backups.push({ file, content: fs29.readFileSync(file, "utf-8") });
16600
17075
  setPackageVersion(file, version);
16601
17076
  };
16602
17077
  try {
16603
17078
  for (const p of selected) {
16604
17079
  stamp(p.dir);
16605
17080
  for (const sub of p.subPackages ?? []) {
16606
- stamp(path35.join(p.dir, typeof sub === "string" ? sub : sub.dir));
17081
+ stamp(path36.join(p.dir, typeof sub === "string" ? sub : sub.dir));
16607
17082
  }
16608
17083
  }
16609
17084
  const args = [
@@ -16618,14 +17093,14 @@ function registerRegistryPublish(registry) {
16618
17093
  ...opts.dryRun ? ["--dry-run"] : []
16619
17094
  ];
16620
17095
  logInfo(`Publishing ${selected.length} package(s)...`);
16621
- execFileSync24("bash", args, { cwd: root, stdio: "inherit", env: env ?? process.env });
17096
+ execFileSync25("bash", args, { cwd: root, stdio: "inherit", env: env ?? process.env });
16622
17097
  } finally {
16623
- for (const b of backups) fs28.writeFileSync(b.file, b.content);
17098
+ for (const b of backups) fs29.writeFileSync(b.file, b.content);
16624
17099
  logInfo("Restored source package.json versions.");
16625
17100
  const collateral = [...dirtyPackageJsons(root)].filter((f) => !preDirty.has(f));
16626
17101
  if (collateral.length) {
16627
17102
  try {
16628
- execFileSync24("git", ["checkout", "--", ...collateral], { cwd: root, stdio: "inherit" });
17103
+ execFileSync25("git", ["checkout", "--", ...collateral], { cwd: root, stdio: "inherit" });
16629
17104
  logInfo(`Reverted ${collateral.length} package.json file(s) re-vendored by build:publish.`);
16630
17105
  } catch {
16631
17106
  logError(
@@ -16677,12 +17152,12 @@ __export(registry_exports, {
16677
17152
  shouldRemintAfter: () => shouldRemintAfter,
16678
17153
  shouldRepairUserNpmrc: () => shouldRepairUserNpmrc
16679
17154
  });
16680
- import { execFileSync as execFileSync25 } from "child_process";
16681
- import * as fs29 from "fs";
16682
- import * as path36 from "path";
17155
+ import { execFileSync as execFileSync26 } from "child_process";
17156
+ import * as fs30 from "fs";
17157
+ import * as path37 from "path";
16683
17158
  function getEndpoint(env) {
16684
17159
  try {
16685
- const result = execFileSync25("aws", [
17160
+ const result = execFileSync26("aws", [
16686
17161
  "codeartifact",
16687
17162
  "get-repository-endpoint",
16688
17163
  "--domain",
@@ -16709,7 +17184,7 @@ function getEndpoint(env) {
16709
17184
  }
16710
17185
  function codeartifactLogin(env) {
16711
17186
  try {
16712
- execFileSync25("aws", [
17187
+ execFileSync26("aws", [
16713
17188
  "codeartifact",
16714
17189
  "login",
16715
17190
  "--tool",
@@ -16764,7 +17239,7 @@ function resolvePublisherRoleArn({
16764
17239
  }
16765
17240
  function assumeRole2(roleArn) {
16766
17241
  try {
16767
- const result = execFileSync25("aws", [
17242
+ const result = execFileSync26("aws", [
16768
17243
  "sts",
16769
17244
  "assume-role",
16770
17245
  "--role-arn",
@@ -16786,7 +17261,7 @@ function assumeRole2(roleArn) {
16786
17261
  }
16787
17262
  function assumeRoleWithWebIdentity2(roleArn, idToken, sessionName) {
16788
17263
  try {
16789
- const result = execFileSync25("aws", [
17264
+ const result = execFileSync26("aws", [
16790
17265
  "sts",
16791
17266
  "assume-role-with-web-identity",
16792
17267
  "--role-arn",
@@ -16850,55 +17325,58 @@ function resolveCredentials(context, roleArn) {
16850
17325
  function findProjectRoot2() {
16851
17326
  let dir = process.cwd();
16852
17327
  while (true) {
16853
- if (fs29.existsSync(path36.join(dir, "pnpm-workspace.yaml")) || fs29.existsSync(path36.join(dir, "pnpm-lock.yaml")) || fs29.existsSync(path36.join(dir, "Pulumi.yaml")) || fs29.existsSync(path36.join(dir, ".npmrc"))) {
17328
+ if (fs30.existsSync(path37.join(dir, "pnpm-workspace.yaml")) || fs30.existsSync(path37.join(dir, "pnpm-lock.yaml")) || fs30.existsSync(path37.join(dir, "Pulumi.yaml")) || fs30.existsSync(path37.join(dir, ".npmrc"))) {
16854
17329
  return dir;
16855
17330
  }
16856
- const parent = path36.dirname(dir);
17331
+ const parent = path37.dirname(dir);
16857
17332
  if (parent === dir) return null;
16858
17333
  dir = parent;
16859
17334
  }
16860
17335
  }
16861
17336
  function ensureProjectNpmrc(endpoint) {
16862
17337
  const projectRoot = findProjectRoot2() ?? process.cwd();
16863
- const npmrcPath2 = path36.join(projectRoot, ".npmrc");
17338
+ const npmrcPath2 = path37.join(projectRoot, ".npmrc");
16864
17339
  const scopeLine = `${CA_NAMESPACE}:registry=${endpoint}`;
16865
- if (!fs29.existsSync(npmrcPath2)) {
16866
- fs29.writeFileSync(npmrcPath2, scopeLine + "\n", "utf-8");
17340
+ if (!fs30.existsSync(npmrcPath2)) {
17341
+ fs30.writeFileSync(npmrcPath2, scopeLine + "\n", "utf-8");
16867
17342
  return { created: true, updated: false, path: npmrcPath2 };
16868
17343
  }
16869
- const content = fs29.readFileSync(npmrcPath2, "utf-8");
17344
+ const content = fs30.readFileSync(npmrcPath2, "utf-8");
16870
17345
  const scopeRegex = new RegExp(`^${CA_NAMESPACE.replace("/", "\\/")}:registry=.+$`, "m");
16871
17346
  if (scopeRegex.test(content)) {
16872
17347
  if (content.includes(scopeLine)) {
16873
17348
  return { created: false, updated: false, path: npmrcPath2 };
16874
17349
  }
16875
17350
  const updated = content.replace(scopeRegex, scopeLine);
16876
- fs29.writeFileSync(npmrcPath2, updated, "utf-8");
17351
+ fs30.writeFileSync(npmrcPath2, updated, "utf-8");
16877
17352
  return { created: false, updated: true, path: npmrcPath2 };
16878
17353
  }
16879
17354
  const separator = content.endsWith("\n") ? "" : "\n";
16880
- fs29.writeFileSync(npmrcPath2, content + separator + scopeLine + "\n", "utf-8");
17355
+ fs30.writeFileSync(npmrcPath2, content + separator + scopeLine + "\n", "utf-8");
16881
17356
  return { created: false, updated: true, path: npmrcPath2 };
16882
17357
  }
16883
17358
  function applyGrantToUserNpmrc(grant, npmrcPath2 = homeNpmrcPath()) {
16884
17359
  let existing = "";
16885
17360
  try {
16886
- existing = fs29.readFileSync(npmrcPath2, "utf-8");
17361
+ existing = fs30.readFileSync(npmrcPath2, "utf-8");
16887
17362
  } catch {
16888
17363
  }
16889
17364
  const content = upsertNpmrcLines(existing, [
16890
17365
  { key: `${grant.scope}:registry`, value: grant.endpoint },
16891
17366
  { key: `${npmrcAuthKeyForEndpoint(grant.endpoint)}:_authToken`, value: grant.authorizationToken }
16892
17367
  ]);
16893
- fs29.mkdirSync(path36.dirname(npmrcPath2), { recursive: true });
16894
- fs29.writeFileSync(npmrcPath2, content, { mode: 384 });
17368
+ fs30.mkdirSync(path37.dirname(npmrcPath2), { recursive: true });
17369
+ fs30.writeFileSync(npmrcPath2, content, { mode: 384 });
16895
17370
  try {
16896
- fs29.chmodSync(npmrcPath2, 384);
17371
+ fs30.chmodSync(npmrcPath2, 384);
16897
17372
  } catch {
16898
17373
  }
16899
17374
  return { path: npmrcPath2 };
16900
17375
  }
16901
- function describeBrokerFailure(failure) {
17376
+ function describeBrokerFailure(failure, account = {}) {
17377
+ const unverified = account.emailVerified === false ? `
17378
+ Your Mesh account${account.email ? ` (${account.email})` : ""} has never confirmed its email address, and an unconfirmed account cannot hold a registry grant.
17379
+ This is not something a role fixes: ask your Mesh contact to verify the address on your account (a self-registered, passkey-only sign-up lands here), then run: mesh registry logout && mesh registry login` : "";
16902
17380
  switch (failure.kind) {
16903
17381
  case "no-broker":
16904
17382
  return {
@@ -16913,7 +17391,7 @@ function describeBrokerFailure(failure) {
16913
17391
  };
16914
17392
  case "unauthenticated":
16915
17393
  return {
16916
- message: "The registry broker rejected your session (expired or wrong audience).",
17394
+ message: "The registry broker rejected your session (expired or wrong audience)." + unverified,
16917
17395
  hint: "mesh registry logout && mesh registry login",
16918
17396
  fatal: false
16919
17397
  };
@@ -16925,7 +17403,7 @@ function describeBrokerFailure(failure) {
16925
17403
  message: `Your Mesh account${failure.email ? ` (${failure.email})` : ""} is not authorized to read ${CA_NAMESPACE} packages.` + (failure.requiredRoles?.length ? `
16926
17404
  Needs one of these Zitadel roles: ${failure.requiredRoles.join(", ")}` : "") + (failure.requestUrl ? `
16927
17405
  Request access: ${failure.requestUrl}` : "\n Ask a Mesh platform admin to grant your account registry access.") + `
16928
- ${NOT_AUTHORIZED_RERUN}`,
17406
+ ${NOT_AUTHORIZED_RERUN}` + unverified,
16929
17407
  fatal: true
16930
17408
  };
16931
17409
  case "unavailable":
@@ -16988,7 +17466,10 @@ async function tryBrokerLogin(opts) {
16988
17466
  }
16989
17467
  }
16990
17468
  if (result.ok) return { grant: result.grant };
16991
- const { message, hint, fatal } = describeBrokerFailure(result.failure);
17469
+ const { message, hint, fatal } = describeBrokerFailure(
17470
+ result.failure,
17471
+ registryAccountState(readCredentials(session.context)?.idToken)
17472
+ );
16992
17473
  if (fatal) {
16993
17474
  throw new RegistryNotAuthorizedError(message);
16994
17475
  }
@@ -17010,7 +17491,7 @@ function shouldRepairUserNpmrc(opts) {
17010
17491
  function repairUnscopedRegistry(npmrcPath2 = homeNpmrcPath()) {
17011
17492
  let original;
17012
17493
  try {
17013
- original = fs29.readFileSync(npmrcPath2, "utf-8");
17494
+ original = fs30.readFileSync(npmrcPath2, "utf-8");
17014
17495
  } catch {
17015
17496
  return { removed: null };
17016
17497
  }
@@ -17018,8 +17499,8 @@ function repairUnscopedRegistry(npmrcPath2 = homeNpmrcPath()) {
17018
17499
  if (!removed) return { removed: null };
17019
17500
  const backupPath = `${npmrcPath2}.bak-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
17020
17501
  try {
17021
- fs29.writeFileSync(backupPath, original, "utf-8");
17022
- fs29.writeFileSync(npmrcPath2, content, "utf-8");
17502
+ fs30.writeFileSync(backupPath, original, "utf-8");
17503
+ fs30.writeFileSync(npmrcPath2, content, "utf-8");
17023
17504
  } catch (err) {
17024
17505
  return { removed: null, error: err instanceof Error ? err.message : String(err) };
17025
17506
  }
@@ -17031,9 +17512,9 @@ function renderRegistrySessionLine(session, now = Date.now()) {
17031
17512
  }
17032
17513
  async function checkExistingToken() {
17033
17514
  const npmrcPath2 = homeNpmrcPath();
17034
- if (!fs29.existsSync(npmrcPath2)) return { valid: false, state: "missing", reason: "no ~/.npmrc" };
17515
+ if (!fs30.existsSync(npmrcPath2)) return { valid: false, state: "missing", reason: "no ~/.npmrc" };
17035
17516
  const hijackLine = findUnscopedCodeArtifactRegistry(
17036
- fs29.readFileSync(npmrcPath2, "utf-8")
17517
+ fs30.readFileSync(npmrcPath2, "utf-8")
17037
17518
  ) ?? void 0;
17038
17519
  const probe = await probeRegistryToken({ npmrcPath: npmrcPath2 });
17039
17520
  if (probe.state === "missing") {
@@ -17086,9 +17567,9 @@ async function runRegistryStatus(opts) {
17086
17567
  logInfo(renderRegistrySessionLine(opts?.session ?? readRegistrySession()));
17087
17568
  const projectRoot = findProjectRoot2();
17088
17569
  if (projectRoot) {
17089
- const npmrcPath2 = path36.join(projectRoot, ".npmrc");
17090
- if (fs29.existsSync(npmrcPath2)) {
17091
- const content = fs29.readFileSync(npmrcPath2, "utf-8");
17570
+ const npmrcPath2 = path37.join(projectRoot, ".npmrc");
17571
+ if (fs30.existsSync(npmrcPath2)) {
17572
+ const content = fs30.readFileSync(npmrcPath2, "utf-8");
17092
17573
  if (content.includes(`${CA_NAMESPACE}:registry=`)) {
17093
17574
  logSuccess(`Project .npmrc configured (${npmrcPath2})`);
17094
17575
  } else {
@@ -17122,7 +17603,7 @@ region = us-east-2`,
17122
17603
  { remediation: { command: `aws configure sso --profile ${profile}` } }
17123
17604
  );
17124
17605
  }
17125
- const probe = () => execFileSync25("aws", ["sts", "get-caller-identity", "--profile", profile], {
17606
+ const probe = () => execFileSync26("aws", ["sts", "get-caller-identity", "--profile", profile], {
17126
17607
  stdio: ["ignore", "pipe", "pipe"],
17127
17608
  timeout: 2e4
17128
17609
  });
@@ -17133,7 +17614,7 @@ region = us-east-2`,
17133
17614
  } catch {
17134
17615
  logInfo(`AWS SSO session for profile '${profile}' is stale \u2014 opening browser login\u2026`);
17135
17616
  }
17136
- execFileSync25("aws", ["sso", "login", "--profile", profile], { stdio: "inherit" });
17617
+ execFileSync26("aws", ["sso", "login", "--profile", profile], { stdio: "inherit" });
17137
17618
  try {
17138
17619
  probe();
17139
17620
  } catch (err) {
@@ -17289,7 +17770,9 @@ To install packages you do not need AWS at all \u2014 drop the flag:
17289
17770
  }
17290
17771
  }
17291
17772
  function registerRegistryCommands(program2) {
17292
- const registry = program2.command("registry").description("Manage npm registry auth for @mesh-tech packages");
17773
+ const registry = program2.command("registry").description(
17774
+ "PACKAGE access: the sign-in that makes @mesh-tech/* installable. One global identity \u2014 no AWS account, no platform, no `<tenant>.<env>` context. (`mesh login <tenant>.<env>` is the other one; that is for deploying to or operating a platform.)"
17775
+ );
17293
17776
  registry.command("login").description(
17294
17777
  "Sign in to the Mesh package registry (browser, or device code with --device) and configure ~/.npmrc + the project .npmrc. Needs no platform context and no AWS account."
17295
17778
  ).argument(
@@ -17347,28 +17830,39 @@ __export(wizard_exports, {
17347
17830
  INIT_REPO_FIX: () => INIT_REPO_FIX,
17348
17831
  INTERRUPTED_EXIT_CODE: () => INTERRUPTED_EXIT_CODE,
17349
17832
  NO_SESSION_NO_TTY_MESSAGE: () => NO_SESSION_NO_TTY_MESSAGE,
17833
+ PLATFORM_SETUP_LABEL: () => PLATFORM_SETUP_LABEL,
17834
+ REGISTRY_WHY: () => REGISTRY_WHY,
17350
17835
  TENANT_REQUIRED_MESSAGE: () => TENANT_REQUIRED_MESSAGE,
17351
17836
  WIZARD_STEPS: () => WIZARD_STEPS,
17352
17837
  classifyRepo: () => classifyRepo,
17353
17838
  describeMode: () => describeMode,
17839
+ isNewPlatform: () => isNewPlatform,
17840
+ newPlatformStep: () => newPlatformStep,
17841
+ platformSetupFlags: () => platformSetupFlags,
17354
17842
  registryStep: () => registryStep,
17355
17843
  renderWizardSummary: () => renderWizardSummary,
17356
17844
  repoStep: () => repoStep,
17357
17845
  resolveAnswers: () => resolveAnswers,
17358
17846
  runInitWizard: () => runInitWizard,
17359
17847
  runWizardSteps: () => runWizardSteps,
17848
+ skillsStep: () => skillsStep,
17360
17849
  stepBlocks: () => stepBlocks,
17361
17850
  wizardExitCode: () => wizardExitCode,
17362
17851
  wizardNextCommands: () => wizardNextCommands
17363
17852
  });
17364
- import * as fs30 from "fs";
17365
- import * as path37 from "path";
17366
- import { execFileSync as execFileSync26 } from "child_process";
17853
+ import * as fs31 from "fs";
17854
+ import * as path38 from "path";
17855
+ import { execFileSync as execFileSync27 } from "child_process";
17367
17856
  import chalk4 from "chalk";
17857
+ function isNewPlatform(mode) {
17858
+ return typeof mode === "object" && "newPlatform" in mode;
17859
+ }
17368
17860
  function wizardExitCode(steps) {
17369
17861
  return steps.some((s) => s.status === "fail") ? 1 : 0;
17370
17862
  }
17371
17863
  function wizardNextCommands(mode, steps = []) {
17864
+ const owned = steps.find((s) => s.next?.length)?.next;
17865
+ if (owned) return owned;
17372
17866
  const repo = steps.find((s) => s.name === STEP_LABELS.repo);
17373
17867
  const first = repo && repo.status !== "pass" && repo.fix ? repo.fix : "mesh create-app";
17374
17868
  return mode === "local" ? [first] : [first, "mesh deploy up # from the app directory, once it exists"];
@@ -17377,7 +17871,9 @@ function stepBlocks(result) {
17377
17871
  return result.status === "fail" && result.blocking !== false;
17378
17872
  }
17379
17873
  function describeMode(mode) {
17380
- return mode === "local" ? "local only" : `deployed platform (${mode.platform})`;
17874
+ if (mode === "local") return "local only";
17875
+ if (isNewPlatform(mode)) return `a new platform (${mode.newPlatform.env ?? PLATFORM_SETUP_DEFAULTS.env})`;
17876
+ return `deployed platform (${mode.platform})`;
17381
17877
  }
17382
17878
  function renderWizardSummary(outcome, opts = {}) {
17383
17879
  const paint = opts.color === false ? { green: (s) => s, red: (s) => s, yellow: (s) => s, dim: (s) => s, cyan: (s) => s } : chalk4;
@@ -17403,10 +17899,12 @@ function resolveAnswers(opts, recorded, interactive) {
17403
17899
  open.push("tenant");
17404
17900
  }
17405
17901
  let mode;
17406
- if (opts.local && opts.platform) {
17407
- throw new MeshCliError("--local and --platform are mutually exclusive.");
17902
+ const chosen = [opts.local && "--local", opts.platform && "--platform", opts.newPlatform && "--new-platform"].filter(Boolean);
17903
+ if (chosen.length > 1) {
17904
+ throw new MeshCliError(`${chosen.join(", ")} are mutually exclusive \u2014 a tenant runs in exactly one of those three places.`);
17408
17905
  }
17409
- if (opts.platform) mode = { platform: opts.platform };
17906
+ if (opts.newPlatform) mode = { newPlatform: platformSetupFlags(opts) };
17907
+ else if (opts.platform) mode = { platform: opts.platform };
17410
17908
  else if (opts.local) mode = "local";
17411
17909
  else if (opts.yes || !interactive) {
17412
17910
  mode = recorded && recorded.platform !== "local" ? { platform: recorded.platform } : "local";
@@ -17415,22 +17913,34 @@ function resolveAnswers(opts, recorded, interactive) {
17415
17913
  }
17416
17914
  return { tenant, mode, open };
17417
17915
  }
17916
+ function platformSetupFlags(opts) {
17917
+ return {
17918
+ env: typeof opts.newPlatform === "string" ? opts.newPlatform : void 0,
17919
+ region: opts.region,
17920
+ domain: opts.domain,
17921
+ profile: opts.profile,
17922
+ stateBucket: opts.stateBucket,
17923
+ createStateBucket: opts.createStateBucket,
17924
+ dir: opts.dir,
17925
+ yes: opts.yes
17926
+ };
17927
+ }
17418
17928
  function classifyRepo(cwd) {
17419
17929
  if (isInsidePlatformMonorepo(cwd)) return { kind: "platform-monorepo", root: resolveTargetRoot(cwd) };
17420
17930
  if (shouldBootstrapAppsRepo(cwd)) return { kind: "empty-apps-repo", root: cwd };
17421
17931
  const root = resolveTargetRoot(cwd);
17422
- const inRepo = fs30.existsSync(path37.join(root, ".git"));
17932
+ const inRepo = fs31.existsSync(path38.join(root, ".git"));
17423
17933
  if (!inRepo) {
17424
- const hasContent = fs30.readdirSync(cwd).some((entry) => !entry.startsWith("."));
17934
+ const hasContent = fs31.readdirSync(cwd).some((entry) => !entry.startsWith("."));
17425
17935
  return { kind: hasContent ? "no-repo" : "empty-dir", root: cwd };
17426
17936
  }
17427
- const hasWorkspace = fs30.existsSync(path37.join(root, "pnpm-workspace.yaml")) || fs30.existsSync(path37.join(root, "pnpm-lock.yaml"));
17428
- const hasApps = fs30.existsSync(path37.join(root, "apps")) || fs30.existsSync(path37.join(root, "tenants"));
17937
+ const hasWorkspace = fs31.existsSync(path38.join(root, "pnpm-workspace.yaml")) || fs31.existsSync(path38.join(root, "pnpm-lock.yaml"));
17938
+ const hasApps = fs31.existsSync(path38.join(root, "apps")) || fs31.existsSync(path38.join(root, "tenants"));
17429
17939
  if (hasWorkspace || hasApps) return { kind: "apps-repo", root };
17430
17940
  return { kind: "other-repo", root };
17431
17941
  }
17432
17942
  function gitInit(dir) {
17433
- execFileSync26("git", ["init", "-q"], { cwd: dir, stdio: ["ignore", "ignore", "pipe"] });
17943
+ execFileSync27("git", ["init", "-q"], { cwd: dir, stdio: ["ignore", "ignore", "pipe"] });
17434
17944
  }
17435
17945
  async function runWizardSteps(ctx, steps) {
17436
17946
  const results = [];
@@ -17488,12 +17998,15 @@ async function runInitWizard(opts, deps = {}) {
17488
17998
  message: "Where does this tenant run?",
17489
17999
  choices: [
17490
18000
  { name: "Local only (mesh start / mesh dev \u2014 no deployed platform yet)", value: "local" },
17491
- { name: `A deployed Mesh platform (I have a ${tenant}.<env> context)`, value: "deployed" }
18001
+ { name: `A deployed Mesh platform (I have a ${tenant}.<env> context)`, value: "deployed" },
18002
+ { name: "Nothing yet \u2014 set up a new Mesh platform in my AWS account", value: "new" }
17492
18003
  ],
17493
18004
  default: recorded && recorded.platform !== "local" ? "deployed" : "local"
17494
18005
  });
17495
18006
  if (choice === "local") mode = "local";
17496
- else {
18007
+ else if (choice === "new") {
18008
+ mode = { newPlatform: platformSetupFlags({ ...opts, newPlatform: true }) };
18009
+ } else {
17497
18010
  const env = await prompts.input({
17498
18011
  message: "Environment",
17499
18012
  default: recorded && recorded.platform !== "local" ? recorded.platform : "dev",
@@ -17506,7 +18019,7 @@ async function runInitWizard(opts, deps = {}) {
17506
18019
  cwd,
17507
18020
  tenant,
17508
18021
  mode,
17509
- context: mode === "local" ? null : `${tenant}.${mode.platform}`,
18022
+ context: mode === "local" || isNewPlatform(mode) ? null : `${tenant}.${mode.platform}`,
17510
18023
  device: opts.device,
17511
18024
  profile: opts.profile,
17512
18025
  interactive,
@@ -17519,7 +18032,7 @@ async function runInitWizard(opts, deps = {}) {
17519
18032
  logInfo(`Setting up tenant '${tenant}' (${describeMode(mode)})\u2026`);
17520
18033
  const steps = await runWizardSteps(ctx, deps.steps ?? WIZARD_STEPS);
17521
18034
  const { kind, root } = classifyRepo(cwd);
17522
- if (!opts.skipRepo && (kind === "apps-repo" || kind === "empty-apps-repo")) {
18035
+ if (!opts.skipRepo && !isNewPlatform(mode) && (kind === "apps-repo" || kind === "empty-apps-repo")) {
17523
18036
  const written = writeMeshJson(root, { tenant, platform: mode === "local" ? "local" : mode.platform });
17524
18037
  logInfo(`Recorded tenant + mode in ${written}`);
17525
18038
  }
@@ -17545,7 +18058,7 @@ async function runInitWizard(opts, deps = {}) {
17545
18058
  console.log = origLog;
17546
18059
  }
17547
18060
  }
17548
- var NO_SESSION_NO_TTY_MESSAGE, TENANT_REQUIRED_MESSAGE, INTERRUPTED_EXIT_CODE, STEP_LABELS, registryStep, platformStep, INIT_REPO_FIX, repoStep, skillsStep, WIZARD_STEPS;
18061
+ var NO_SESSION_NO_TTY_MESSAGE, TENANT_REQUIRED_MESSAGE, REGISTRY_WHY, INTERRUPTED_EXIT_CODE, STEP_LABELS, PLATFORM_SETUP_LABEL, registryStep, newPlatformStep, platformStep, INIT_REPO_FIX, repoStep, skillsStep, WIZARD_STEPS;
17549
18062
  var init_wizard = __esm({
17550
18063
  "libs/mesh-cli/src/commands/init/wizard.ts"() {
17551
18064
  "use strict";
@@ -17559,8 +18072,10 @@ var init_wizard = __esm({
17559
18072
  init_create_app();
17560
18073
  init_skills();
17561
18074
  init_dev_local();
18075
+ init_platform_setup();
17562
18076
  NO_SESSION_NO_TTY_MESSAGE = "No registry session and no terminal to sign in with.\n On a headless box: mesh registry login --device (one-time, prints a code)\n In CI with AWS creds: mesh registry login --ci";
17563
18077
  TENANT_REQUIRED_MESSAGE = "--tenant is required (no TTY for interactive mode)";
18078
+ REGISTRY_WHY = "Package access \u2014 a sign-in to the Mesh package REGISTRY, which is what makes `@mesh-tech/*` installable.\n It is one global identity: no AWS account, no platform, no <tenant>.<env> context.\n (`mesh login <tenant>.<env>` is the other sign-in \u2014 that one is only for deploying to, or operating, a platform.)";
17564
18079
  INTERRUPTED_EXIT_CODE = 130;
17565
18080
  STEP_LABELS = {
17566
18081
  registry: "Registry access",
@@ -17568,6 +18083,7 @@ var init_wizard = __esm({
17568
18083
  repo: "Repo",
17569
18084
  skills: "Agent skills"
17570
18085
  };
18086
+ PLATFORM_SETUP_LABEL = "Platform setup";
17571
18087
  registryStep = {
17572
18088
  name: "registry",
17573
18089
  async run(ctx) {
@@ -17590,6 +18106,7 @@ var init_wizard = __esm({
17590
18106
  return { name, status: "fail", detail: NO_SESSION_NO_TTY_MESSAGE.split("\n")[0], fix: "mesh registry login --device", blocking: true };
17591
18107
  }
17592
18108
  try {
18109
+ logInfo(REGISTRY_WHY);
17593
18110
  const login2 = ctx.seams?.runRegistryLogin ?? (async (opts) => {
17594
18111
  const { runRegistryLogin: runRegistryLogin2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
17595
18112
  await runRegistryLogin2(void 0, opts);
@@ -17618,10 +18135,46 @@ var init_wizard = __esm({
17618
18135
  return { name, status: "pass", detail: `Registry access OK (${session ? `signed in as ${session.email}` : "token written"})` };
17619
18136
  }
17620
18137
  };
18138
+ newPlatformStep = {
18139
+ name: "platform",
18140
+ async run(ctx) {
18141
+ const name = PLATFORM_SETUP_LABEL;
18142
+ if (!isNewPlatform(ctx.mode)) return { name, status: "skip", detail: "no new platform requested" };
18143
+ let setup;
18144
+ try {
18145
+ setup = await resolvePlatformSetup(ctx.tenant, { ...ctx.mode.newPlatform, yes: ctx.yes }, {
18146
+ prompts: ctx.prompts,
18147
+ interactive: ctx.interactive,
18148
+ cwd: ctx.cwd
18149
+ });
18150
+ } catch (err) {
18151
+ return {
18152
+ name,
18153
+ status: "fail",
18154
+ detail: err.message.split("\n")[0],
18155
+ fix: `mesh init --tenant ${ctx.tenant} --new-platform --domain <your-domain>`
18156
+ };
18157
+ }
18158
+ try {
18159
+ await (ctx.seams?.scaffoldPlatform ?? scaffoldPlatformRepo)(setup);
18160
+ } catch (err) {
18161
+ return { name, status: "fail", detail: `platform repo not scaffolded: ${err.message.split("\n")[0]}`, fix: `mesh init platform ${ctx.tenant} --dir <empty-dir>` };
18162
+ }
18163
+ const bucket = await ensureStateBucket(setup, ctx.seams?.stateBucket);
18164
+ const next = renderPlatformNextSteps(setup, { bucket, relativeDir: path38.relative(ctx.cwd, setup.dir) || "." });
18165
+ return {
18166
+ name,
18167
+ status: setup.createStateBucket && !bucket.present ? "warn" : "pass",
18168
+ detail: `platform repo scaffolded at ${setup.dir} (${setup.tenant}.${setup.env}, ${setup.region}, zone ${setup.env}.${setup.domain})` + (setup.createStateBucket ? ` \u2014 state bucket: ${bucket.detail}` : ` \u2014 state bucket ${setup.stateBucket} not created (see Next)`),
18169
+ next
18170
+ };
18171
+ }
18172
+ };
17621
18173
  platformStep = {
17622
18174
  name: "platform",
17623
18175
  async run(ctx) {
17624
18176
  const name = STEP_LABELS.platform;
18177
+ if (isNewPlatform(ctx.mode)) return newPlatformStep.run(ctx);
17625
18178
  if (!ctx.context) return { name, status: "skip", detail: "local only \u2014 no platform to sign in to" };
17626
18179
  const context = ctx.context;
17627
18180
  const cached = readCredentials(context);
@@ -17655,6 +18208,9 @@ var init_wizard = __esm({
17655
18208
  async run(ctx) {
17656
18209
  const name = STEP_LABELS.repo;
17657
18210
  if (ctx.skipRepo) return { name, status: "skip", detail: "--skip-repo" };
18211
+ if (isNewPlatform(ctx.mode)) {
18212
+ return { name, status: "skip", detail: "setting up a platform \u2014 the apps repo comes after the first deploy (see Next)" };
18213
+ }
17658
18214
  const { kind, root } = classifyRepo(ctx.cwd);
17659
18215
  switch (kind) {
17660
18216
  case "platform-monorepo":
@@ -17703,8 +18259,8 @@ var init_wizard = __esm({
17703
18259
  }
17704
18260
  case "apps-repo": {
17705
18261
  const missing = [];
17706
- if (!fs30.existsSync(path37.join(root, "package.json"))) missing.push("package.json");
17707
- if (!fs30.existsSync(path37.join(root, "pnpm-workspace.yaml")) && !fs30.existsSync(path37.join(root, "pnpm-lock.yaml"))) {
18262
+ if (!fs31.existsSync(path38.join(root, "package.json"))) missing.push("package.json");
18263
+ if (!fs31.existsSync(path38.join(root, "pnpm-workspace.yaml")) && !fs31.existsSync(path38.join(root, "pnpm-lock.yaml"))) {
17708
18264
  missing.push("pnpm-workspace.yaml");
17709
18265
  }
17710
18266
  if (missing.length) {
@@ -17720,6 +18276,9 @@ var init_wizard = __esm({
17720
18276
  async run(ctx) {
17721
18277
  const name = STEP_LABELS.skills;
17722
18278
  if (ctx.skipRepo) return { name, status: "skip", detail: "--skip-repo" };
18279
+ if (isNewPlatform(ctx.mode)) {
18280
+ return { name, status: "skip", detail: "synced into the new platform repo by the scaffold" };
18281
+ }
17723
18282
  const { kind, root } = classifyRepo(ctx.cwd);
17724
18283
  if (kind !== "apps-repo" && kind !== "empty-apps-repo") {
17725
18284
  return { name, status: "skip", detail: "no apps repo to install skills into" };
@@ -17738,8 +18297,15 @@ var init_wizard = __esm({
17738
18297
 
17739
18298
  // libs/mesh-cli/src/commands/init.ts
17740
18299
  import chalk5 from "chalk";
17741
- import * as fs31 from "fs";
17742
- import * as path38 from "path";
18300
+ import * as fs32 from "fs";
18301
+ import * as path39 from "path";
18302
+ async function setupPrompts() {
18303
+ const [{ default: input2 }, { default: confirm }] = await Promise.all([
18304
+ import("@inquirer/input"),
18305
+ import("@inquirer/confirm")
18306
+ ]);
18307
+ return { input: (args) => input2(args), confirm: (args) => confirm(args) };
18308
+ }
17743
18309
  function isLocalContext(context) {
17744
18310
  return context === LOGIN_CONTEXT;
17745
18311
  }
@@ -17758,7 +18324,7 @@ async function probeHubTenants(hubUrl, accessToken) {
17758
18324
  }
17759
18325
  function readHomeNpmrc() {
17760
18326
  try {
17761
- return fs31.readFileSync(homeNpmrcPath(), "utf-8");
18327
+ return fs32.readFileSync(homeNpmrcPath(), "utf-8");
17762
18328
  } catch {
17763
18329
  return "";
17764
18330
  }
@@ -17882,9 +18448,9 @@ async function runChecks2(args) {
17882
18448
  if (local) {
17883
18449
  checks.push({ name: "Deployer role", status: "pass", detail: "local context \u2014 no deployer role required" });
17884
18450
  } else {
17885
- const stackFiles = fs31.existsSync(root) ? fs31.readdirSync(root).filter((f) => /^Pulumi\..*\.yaml$/.test(f)) : [];
18451
+ const stackFiles = fs32.existsSync(root) ? fs32.readdirSync(root).filter((f) => /^Pulumi\..*\.yaml$/.test(f)) : [];
17886
18452
  const hasRole = stackFiles.some(
17887
- (f) => /mesh:deployerRole/.test(fs31.readFileSync(path38.join(root, f), "utf-8"))
18453
+ (f) => /mesh:deployerRole/.test(fs32.readFileSync(path39.join(root, f), "utf-8"))
17888
18454
  );
17889
18455
  checks.push(
17890
18456
  hasRole ? { name: "Deployer role", status: "pass", detail: "mesh:deployerRole configured in stack config" } : {
@@ -17896,8 +18462,8 @@ async function runChecks2(args) {
17896
18462
  );
17897
18463
  }
17898
18464
  const shapeProblems = [];
17899
- if (!fs31.existsSync(path38.join(root, "package.json"))) shapeProblems.push("package.json");
17900
- const hasWorkspace = fs31.existsSync(path38.join(root, "pnpm-workspace.yaml")) || fs31.existsSync(path38.join(root, "pnpm-lock.yaml"));
18465
+ if (!fs32.existsSync(path39.join(root, "package.json"))) shapeProblems.push("package.json");
18466
+ const hasWorkspace = fs32.existsSync(path39.join(root, "pnpm-workspace.yaml")) || fs32.existsSync(path39.join(root, "pnpm-lock.yaml"));
17901
18467
  if (!hasWorkspace) shapeProblems.push("pnpm-workspace.yaml");
17902
18468
  checks.push(
17903
18469
  shapeProblems.length === 0 ? { name: "Repo shape", status: "pass", detail: "pnpm workspace layout present" } : {
@@ -17920,8 +18486,11 @@ async function runChecks2(args) {
17920
18486
  }
17921
18487
  function registerInitCommands(program2) {
17922
18488
  const init = program2.command("init").enablePositionalOptions().description(
17923
- "Set up this machine and repo for a tenant \u2014 a guided wizard with no subcommand (tenant, local or deployed, package-registry sign-in, repo, skills); `init platform` scaffolds a platform repo, `init app-tenant` is the apps-repo doctor"
17924
- ).option("--tenant <name>", "app tenant this repo belongs to (prompted when omitted on a TTY)").option("--local", "local only \u2014 mesh start / mesh dev, no deployed platform (the default)").option("--platform <env>", "a deployed platform's environment; signs in to <tenant>.<env>").option("--device", "device-code sign-in for the registry and platform steps (headless / SSH)").option("--profile <aws-profile>", "deployers only: AWS profile that can read the registry (skips the broker)").option("--skip-repo", "do not bootstrap, check or record anything in the current repo", false).option("--yes", "accept every default and never prompt", false).option("--json", "one JSON document on stdout ({tenant, mode, steps, next}); human output on stderr", false).action(
18489
+ "Set up this machine and repo for a tenant \u2014 a guided wizard with no subcommand. It starts from nothing: it asks where the tenant runs, and 'nowhere yet' is one of the answers (it scaffolds you a platform). Then package-registry sign-in, repo, skills. `init platform` is the same scaffold on its own; `init app-tenant` is the apps-repo doctor"
18490
+ ).option("--tenant <name>", "app tenant this repo belongs to (prompted when omitted on a TTY)").option("--local", "local only \u2014 mesh start / mesh dev, no deployed platform (the default)").option("--platform <env>", "a deployed platform's environment; signs in to `<tenant>.<env>`").option(
18491
+ "--new-platform [env]",
18492
+ `nothing deployed yet \u2014 scaffold a tenant platform repo for \`<tenant>.<env>\` (default env: ${PLATFORM_SETUP_DEFAULTS.env}) and print its deploy sequence`
18493
+ ).option("--region <region>", `--new-platform: AWS region (default: ${PLATFORM_SETUP_DEFAULTS.region})`).option("--domain <domain>", "--new-platform: base public domain you control; the core stack creates the zone {env}.{domain}. No default \u2014 a placeholder scaffolds a zone that can never validate").option("--state-bucket <bucket>", "--new-platform: Pulumi state S3 bucket (default: {tenant}-mesh-platform-pulumi-state)").option("--create-state-bucket", "--new-platform: create the state bucket (versioned) if it does not exist").option("--no-create-state-bucket", "--new-platform: never create the state bucket; print the aws command instead").option("--dir <path>", "--new-platform: where to scaffold the platform repo (default: ./{tenant}-mesh-platform)").option("--device", "device-code sign-in for the registry and platform steps (headless / SSH)").option("--profile <aws-profile>", "AWS profile this machine uses: read the registry without the broker (deployers only), and the profile a --new-platform stack config references").option("--skip-repo", "do not bootstrap, check or record anything in the current repo", false).option("--yes", "accept every default and never prompt", false).option("--json", "one JSON document on stdout ({tenant, mode, steps, next}); human output on stderr", false).action(
17925
18494
  async (opts) => {
17926
18495
  const { runInitWizard: runInitWizard2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
17927
18496
  const code = await runInitWizard2(opts);
@@ -17929,42 +18498,34 @@ function registerInitCommands(program2) {
17929
18498
  }
17930
18499
  );
17931
18500
  init.command("platform <tenant>").description(
17932
- "Scaffold a tenant PLATFORM repo (core + platform Pulumi layers on @mesh-tech/infra-components) that deploys with `mesh deploy` unmodified \u2014 the proven mesh-sandbox shape, annotated."
17933
- ).option("--env <env>", "environment the first stack targets", "dev").option("--region <region>", "AWS region", "us-east-2").option("--domain <domain>", "base public domain (ingress zone becomes {env}.{domain})", "example.com").option("--profile <profile>", "AWS profile the stack config references", "default").option("--state-bucket <bucket>", "Pulumi state S3 bucket (created by an operator)", void 0).option("--dir <path>", "target directory (default: ./{tenant}-mesh-platform)").action(async (tenant, opts) => {
17934
- if (!/^[a-z][a-z0-9-]*$/.test(tenant)) {
17935
- throw new MeshCliError(`Invalid tenant name '${tenant}' (lowercase alphanumeric + dashes).`);
17936
- }
17937
- const targetDir = path38.resolve(opts.dir ?? `${tenant}-mesh-platform`);
17938
- if (fs31.existsSync(targetDir) && fs31.readdirSync(targetDir).length > 0) {
17939
- throw new MeshCliError(`Target directory is not empty: ${targetDir}`, {
17940
- remediation: { command: `mesh init platform ${tenant} --dir <empty-dir>` }
18501
+ "Scaffold a tenant PLATFORM repo (core + platform Pulumi layers on @mesh-tech/infra-components) that deploys with `mesh deploy` unmodified \u2014 the proven mesh-sandbox shape, annotated. On a terminal it ASKS for the values that differ per install (env, region, domain, state bucket, AWS profile), each pre-filled with its default; every answer is also a flag."
18502
+ ).option("--env <env>", `environment the first stack targets (default: ${PLATFORM_SETUP_DEFAULTS.env})`).option("--region <region>", `AWS region (default: ${PLATFORM_SETUP_DEFAULTS.region})`).option(
18503
+ "--domain <domain>",
18504
+ "base public domain you control \u2014 the core stack creates the Route 53 zone {env}.{domain} and waits on its NS delegation. Required: it has no default, because a placeholder scaffolds a zone that can never validate"
18505
+ ).option("--profile <profile>", `AWS profile the stack config references (default: ${PLATFORM_SETUP_DEFAULTS.profile})`).option("--state-bucket <bucket>", "Pulumi state S3 bucket (default: {tenant}-mesh-platform-pulumi-state)").option("--create-state-bucket", "create the state bucket (versioned) if it does not exist \u2014 prompted on a terminal").option("--no-create-state-bucket", "never create the state bucket; print the aws command instead").option("--dir <path>", "target directory (default: ./{tenant}-mesh-platform)").option("--yes", "accept every default and never prompt", false).action(
18506
+ async (tenant, opts) => {
18507
+ if (!/^[a-z][a-z0-9-]*$/.test(tenant)) {
18508
+ throw new MeshCliError(`Invalid tenant name '${tenant}' (lowercase alphanumeric + dashes).`);
18509
+ }
18510
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
18511
+ const { resolvePlatformSetup: resolvePlatformSetup2, scaffoldPlatformRepo: scaffoldPlatformRepo2, ensureStateBucket: ensureStateBucket2, renderPlatformNextSteps: renderPlatformNextSteps2 } = await Promise.resolve().then(() => (init_platform_setup(), platform_setup_exports));
18512
+ const setup = await resolvePlatformSetup2(tenant, opts, {
18513
+ prompts: interactive && !opts.yes ? await setupPrompts() : void 0,
18514
+ interactive
17941
18515
  });
18516
+ await scaffoldPlatformRepo2(setup);
18517
+ logInfo(`Platform repo scaffolded at ${setup.dir}`);
18518
+ const bucket = await ensureStateBucket2(setup);
18519
+ if (bucket.detail !== "not requested") logInfo(`Pulumi state bucket: ${bucket.detail}`);
18520
+ console.log("");
18521
+ console.log("Next steps:");
18522
+ for (const line of renderPlatformNextSteps2(setup, { bucket, relativeDir: path39.relative(process.cwd(), setup.dir) || "." })) {
18523
+ console.log(line ? ` ${line}` : "");
18524
+ }
18525
+ console.log("");
18526
+ logInfo(`Review the annotated stack configs (Pulumi.${tenant}-${setup.env}.yaml) before the first deploy.`);
17942
18527
  }
17943
- const { copyTemplate: copyTemplate2 } = await Promise.resolve().then(() => (init_create_app(), create_app_exports));
17944
- const { findPackageRoot: findPackageRoot2 } = await Promise.resolve().then(() => (init_stack(), stack_exports));
17945
- const templateDir = path38.join(findPackageRoot2(), "templates", "platform-repo");
17946
- const context = {
17947
- tenant,
17948
- env: opts.env,
17949
- region: opts.region,
17950
- domain: opts.domain,
17951
- profile: opts.profile,
17952
- stateBucket: opts.stateBucket ?? `${tenant}-mesh-platform-pulumi-state`
17953
- };
17954
- fs31.mkdirSync(targetDir, { recursive: true });
17955
- copyTemplate2(templateDir, targetDir, context);
17956
- syncSkills(targetDir);
17957
- logInfo(`Platform repo scaffolded at ${targetDir}`);
17958
- console.log("");
17959
- console.log("Next steps:");
17960
- console.log(` cd ${path38.relative(process.cwd(), targetDir) || "."}`);
17961
- console.log(` mesh login ${tenant}.${opts.env} # or an operator context with access`);
17962
- console.log(" pnpm install");
17963
- console.log(" cd core && mesh deploy up");
17964
- console.log(" cd ../platform && mesh deploy up");
17965
- console.log("");
17966
- logInfo(`Review the annotated stack configs (Pulumi.${tenant}-${opts.env}.yaml) before the first deploy.`);
17967
- });
18528
+ );
17968
18529
  init.command("app-tenant").description(
17969
18530
  "Check (and with --fix, repair) everything an app-tenant repo needs: auth, registry, tenant registration, repo shape, agent skills. Re-run any time \u2014 it is the doctor."
17970
18531
  ).option("--tenant <name>", "app tenant (default: mesh:tenant from Pulumi config, else 'local')").option("--context <ctx>", "login context to check against (default: 'local' when the local platform is targeted)", LOGIN_CONTEXT).option("--hub-url <url>", "platform Hub API base URL", LOCAL_HUB_API).option("--fix", "apply developer-scope fixes (registry token, skills sync)", false).option("--profile <profile>", "AWS SSO profile --fix logs into CodeArtifact with (e.g. mesh-dev)").option("--json", "machine-readable output", false).action(async (opts) => {
@@ -18020,15 +18581,16 @@ var init_init = __esm({
18020
18581
  init_skills();
18021
18582
  init_dev_local();
18022
18583
  init_seed_zitadel();
18584
+ init_platform_setup();
18023
18585
  LOCAL_HUB_API = "http://localhost:4568";
18024
18586
  }
18025
18587
  });
18026
18588
 
18027
18589
  // libs/mesh-cli/src/commands/install-shim.ts
18028
- import { execFileSync as execFileSync27 } from "child_process";
18029
- import * as fs32 from "fs";
18590
+ import { execFileSync as execFileSync28 } from "child_process";
18591
+ import * as fs33 from "fs";
18030
18592
  import * as os10 from "os";
18031
- import * as path39 from "path";
18593
+ import * as path40 from "path";
18032
18594
  function shimScript() {
18033
18595
  return `#!/bin/sh
18034
18596
  # mesh \u2014 canonical launcher shim (installed by \`mesh install-shim\`).
@@ -18101,25 +18663,25 @@ exit 1
18101
18663
  `;
18102
18664
  }
18103
18665
  function defaultShimDir() {
18104
- return path39.join(os10.homedir(), ".local", "bin");
18666
+ return path40.join(os10.homedir(), ".local", "bin");
18105
18667
  }
18106
18668
  function dirOnPath(dir, pathEnv) {
18107
18669
  if (!pathEnv) return false;
18108
- return pathEnv.split(path39.delimiter).some((p) => p === dir);
18670
+ return pathEnv.split(path40.delimiter).some((p) => p === dir);
18109
18671
  }
18110
18672
  function registerInstallShimCommand(program2) {
18111
18673
  program2.command("install-shim").description("Install a build-free `mesh` shim on your PATH so bare `mesh` runs the local source").option("--dir <dir>", "Directory to install into (must be on your PATH)", defaultShimDir()).option("-f, --force", "Overwrite an existing file at the target path", false).action((opts) => {
18112
- const dir = path39.resolve(opts.dir);
18113
- const target = path39.join(dir, "mesh");
18114
- if (fs32.existsSync(target) && !opts.force) {
18674
+ const dir = path40.resolve(opts.dir);
18675
+ const target = path40.join(dir, "mesh");
18676
+ if (fs33.existsSync(target) && !opts.force) {
18115
18677
  logWarn(`A file already exists at ${target}.`);
18116
18678
  logInfo("Re-run with --force to overwrite it, or pass --dir <other-path-on-PATH>.");
18117
18679
  return;
18118
18680
  }
18119
18681
  try {
18120
- fs32.mkdirSync(dir, { recursive: true });
18121
- fs32.writeFileSync(target, shimScript(), { mode: 493 });
18122
- fs32.chmodSync(target, 493);
18682
+ fs33.mkdirSync(dir, { recursive: true });
18683
+ fs33.writeFileSync(target, shimScript(), { mode: 493 });
18684
+ fs33.chmodSync(target, 493);
18123
18685
  } catch (err) {
18124
18686
  logError(`Could not write the shim to ${target}: ${err.message}`);
18125
18687
  process.exitCode = 1;
@@ -18132,13 +18694,13 @@ function registerInstallShimCommand(program2) {
18132
18694
  } else {
18133
18695
  logInfo("Bare `mesh <cmd>` now runs the local source of whatever workspace you're in.");
18134
18696
  }
18135
- const diagPath = path39.join(os10.tmpdir(), "mesh-shim-selftest.log");
18697
+ const diagPath = path40.join(os10.tmpdir(), "mesh-shim-selftest.log");
18136
18698
  let stdout = "";
18137
18699
  let stderr = "";
18138
18700
  let status = 0;
18139
18701
  let ok = true;
18140
18702
  try {
18141
- stdout = execFileSync27(target, ["--help"], {
18703
+ stdout = execFileSync28(target, ["--help"], {
18142
18704
  cwd: process.cwd(),
18143
18705
  encoding: "utf8",
18144
18706
  stdio: ["ignore", "pipe", "pipe"]
@@ -18165,7 +18727,7 @@ function registerInstallShimCommand(program2) {
18165
18727
  ""
18166
18728
  ].join("\n");
18167
18729
  try {
18168
- fs32.writeFileSync(diagPath, diag);
18730
+ fs33.writeFileSync(diagPath, diag);
18169
18731
  } catch {
18170
18732
  }
18171
18733
  if (ok && /Commands:|Usage:/.test(stdout)) {
@@ -18185,17 +18747,17 @@ var init_install_shim = __esm({
18185
18747
  });
18186
18748
 
18187
18749
  // libs/mesh-cli/src/commands/local/hub-local.ts
18188
- import { execFile as execFile3, execFileSync as execFileSync28 } from "child_process";
18189
- import * as fs33 from "fs";
18750
+ import { execFile as execFile3, execFileSync as execFileSync29 } from "child_process";
18751
+ import * as fs34 from "fs";
18190
18752
  import * as os11 from "os";
18191
- import * as path40 from "path";
18753
+ import * as path41 from "path";
18192
18754
  import { promisify as promisify2 } from "util";
18193
18755
  function cacheDir() {
18194
18756
  return meshCacheDir("hub-local");
18195
18757
  }
18196
18758
  function npmrcPath() {
18197
- const p = path40.join(os11.homedir(), ".npmrc");
18198
- if (!fs33.existsSync(p) || !fs33.readFileSync(p, "utf-8").includes("codeartifact")) {
18759
+ const p = path41.join(os11.homedir(), ".npmrc");
18760
+ if (!fs34.existsSync(p) || !fs34.readFileSync(p, "utf-8").includes("codeartifact")) {
18199
18761
  throw new MeshCliError(
18200
18762
  "The local Hub builds from the published @mesh-tech/hub tarball, which needs registry auth.",
18201
18763
  { remediation: { command: REGISTRY_LOGIN_FIX } }
@@ -18205,7 +18767,7 @@ function npmrcPath() {
18205
18767
  }
18206
18768
  function imageExists(tag) {
18207
18769
  try {
18208
- execFileSync28("docker", ["image", "inspect", tag], { stdio: ["ignore", "pipe", "pipe"] });
18770
+ execFileSync29("docker", ["image", "inspect", tag], { stdio: ["ignore", "pipe", "pipe"] });
18209
18771
  return true;
18210
18772
  } catch {
18211
18773
  return false;
@@ -18214,22 +18776,22 @@ function imageExists(tag) {
18214
18776
  function ensureHubAuthImage() {
18215
18777
  if (imageExists(HUB_AUTH_IMAGE)) return;
18216
18778
  logInfo(`Building ${HUB_AUTH_IMAGE} (Hub auth proxy)\u2026`);
18217
- const hubStackDir = path40.join(findPackageRoot(), "stack", "hub");
18218
- execFileSync28(
18779
+ const hubStackDir = path41.join(findPackageRoot(), "stack", "hub");
18780
+ execFileSync29(
18219
18781
  "docker",
18220
- ["build", "-f", path40.join(hubStackDir, "Dockerfile.auth"), "-t", HUB_AUTH_IMAGE, hubStackDir],
18782
+ ["build", "-f", path41.join(hubStackDir, "Dockerfile.auth"), "-t", HUB_AUTH_IMAGE, hubStackDir],
18221
18783
  { stdio: ["ignore", "inherit", "inherit"], env: { ...process.env, DOCKER_BUILDKIT: "1" } }
18222
18784
  );
18223
18785
  logSuccess(`Built ${HUB_AUTH_IMAGE}`);
18224
18786
  }
18225
18787
  function hasRegistryAuth() {
18226
- const p = path40.join(os11.homedir(), ".npmrc");
18227
- return fs33.existsSync(p) && fs33.readFileSync(p, "utf-8").includes("codeartifact");
18788
+ const p = path41.join(os11.homedir(), ".npmrc");
18789
+ return fs34.existsSync(p) && fs34.readFileSync(p, "utf-8").includes("codeartifact");
18228
18790
  }
18229
18791
  function localHubVersion() {
18230
18792
  const versions = HUB_IMAGES.map((name) => {
18231
18793
  try {
18232
- const out = execFileSync28("docker", ["images", name, "--format", "{{.Tag}}"], {
18794
+ const out = execFileSync29("docker", ["images", name, "--format", "{{.Tag}}"], {
18233
18795
  encoding: "utf-8",
18234
18796
  stdio: ["ignore", "pipe", "pipe"]
18235
18797
  });
@@ -18255,10 +18817,10 @@ async function fetchTarball() {
18255
18817
  { encoding: "utf-8" }
18256
18818
  );
18257
18819
  const info = JSON.parse(stdout)[0];
18258
- return { tarball: path40.join(dir, info.filename), version: info.version };
18820
+ return { tarball: path41.join(dir, info.filename), version: info.version };
18259
18821
  } catch (err) {
18260
18822
  const authFailure = isNpmAuthError(err);
18261
- const cached = fs33.readdirSync(dir).filter((f) => f.startsWith("mesh-tech-hub-") && f.endsWith(".tgz")).sort((a, b) => a.localeCompare(b, void 0, { numeric: true })).at(-1);
18823
+ const cached = fs34.readdirSync(dir).filter((f) => f.startsWith("mesh-tech-hub-") && f.endsWith(".tgz")).sort((a, b) => a.localeCompare(b, void 0, { numeric: true })).at(-1);
18262
18824
  if (!cached) {
18263
18825
  if (authFailure) {
18264
18826
  throw new MeshCliError(
@@ -18276,7 +18838,7 @@ async function fetchTarball() {
18276
18838
  } else {
18277
18839
  logInfo(`Registry unavailable \u2014 using the cached hub tarball v${version}`);
18278
18840
  }
18279
- return { tarball: path40.join(dir, cached), version };
18841
+ return { tarball: path41.join(dir, cached), version };
18280
18842
  } finally {
18281
18843
  heartbeat.stop();
18282
18844
  }
@@ -18305,13 +18867,13 @@ async function ensureHubImages() {
18305
18867
  logInfo(`Local Hub images ready (v${version})`);
18306
18868
  return version;
18307
18869
  }
18308
- const context = path40.join(cacheDir(), `context-${version}`);
18309
- fs33.rmSync(context, { recursive: true, force: true });
18310
- fs33.mkdirSync(context, { recursive: true });
18311
- execFileSync28("tar", ["-xzf", tarball, "-C", context, "--strip-components", "1"], {
18870
+ const context = path41.join(cacheDir(), `context-${version}`);
18871
+ fs34.rmSync(context, { recursive: true, force: true });
18872
+ fs34.mkdirSync(context, { recursive: true });
18873
+ execFileSync29("tar", ["-xzf", tarball, "-C", context, "--strip-components", "1"], {
18312
18874
  stdio: ["ignore", "pipe", "pipe"]
18313
18875
  });
18314
- const hubStackDir = path40.join(findPackageRoot(), "stack", "hub");
18876
+ const hubStackDir = path41.join(findPackageRoot(), "stack", "hub");
18315
18877
  for (const [name, dockerfile] of [
18316
18878
  ["mesh-local-hub-api", "Dockerfile.api"],
18317
18879
  ["mesh-local-hub-ui", "Dockerfile.ui"]
@@ -18319,12 +18881,12 @@ async function ensureHubImages() {
18319
18881
  const tag = `${name}:${version}`;
18320
18882
  if (imageExists(tag)) continue;
18321
18883
  logInfo(`Building ${tag} from the published tarball\u2026`);
18322
- execFileSync28(
18884
+ execFileSync29(
18323
18885
  "docker",
18324
18886
  [
18325
18887
  "build",
18326
18888
  "-f",
18327
- path40.join(hubStackDir, dockerfile),
18889
+ path41.join(hubStackDir, dockerfile),
18328
18890
  "-t",
18329
18891
  tag,
18330
18892
  "--secret",
@@ -18342,29 +18904,29 @@ function tarballNameForImageVersion(version) {
18342
18904
  return `mesh-tech-hub-${version.replace(/-r\d+$/, "")}.tgz`;
18343
18905
  }
18344
18906
  function readHubCompiledAuthz(version) {
18345
- const context = path40.join(cacheDir(), `context-${version}`);
18346
- const file = path40.join(context, HUB_COMPILED_AUTHZ_REL);
18347
- if (!fs33.existsSync(file)) {
18907
+ const context = path41.join(cacheDir(), `context-${version}`);
18908
+ const file = path41.join(context, HUB_COMPILED_AUTHZ_REL);
18909
+ if (!fs34.existsSync(file)) {
18348
18910
  const tarball = tarballNameForImageVersion(version);
18349
- if (!tarball || !fs33.existsSync(path40.join(cacheDir(), tarball))) return null;
18350
- fs33.mkdirSync(context, { recursive: true });
18911
+ if (!tarball || !fs34.existsSync(path41.join(cacheDir(), tarball))) return null;
18912
+ fs34.mkdirSync(context, { recursive: true });
18351
18913
  try {
18352
- execFileSync28(
18914
+ execFileSync29(
18353
18915
  "tar",
18354
- ["-xzf", path40.join(cacheDir(), tarball), "-C", context, "--strip-components", "1", `package/${HUB_COMPILED_AUTHZ_REL}`],
18916
+ ["-xzf", path41.join(cacheDir(), tarball), "-C", context, "--strip-components", "1", `package/${HUB_COMPILED_AUTHZ_REL}`],
18355
18917
  { stdio: ["ignore", "pipe", "pipe"] }
18356
18918
  );
18357
18919
  } catch {
18358
18920
  return null;
18359
18921
  }
18360
- if (!fs33.existsSync(file)) return null;
18922
+ if (!fs34.existsSync(file)) return null;
18361
18923
  }
18362
- const parsed = JSON.parse(fs33.readFileSync(file, "utf-8"));
18924
+ const parsed = JSON.parse(fs34.readFileSync(file, "utf-8"));
18363
18925
  if (typeof parsed.zed !== "string" || !parsed.metadata || typeof parsed.metadata !== "object") return null;
18364
18926
  return { zed: parsed.zed, metadata: parsed.metadata };
18365
18927
  }
18366
18928
  function readWorkspaceCatalog(repoRoot2) {
18367
- const text = fs33.readFileSync(path40.join(repoRoot2, "pnpm-workspace.yaml"), "utf-8");
18929
+ const text = fs34.readFileSync(path41.join(repoRoot2, "pnpm-workspace.yaml"), "utf-8");
18368
18930
  const marker = "\ncatalog:\n";
18369
18931
  const at = text.indexOf(marker);
18370
18932
  if (at === -1) return {};
@@ -18379,11 +18941,11 @@ function readWorkspaceCatalog(repoRoot2) {
18379
18941
  function normalizeHubManifests(contextDir, catalog) {
18380
18942
  const DEP_FIELDS = ["dependencies", "optionalDependencies", "peerDependencies"];
18381
18943
  const touched = [];
18382
- for (const entry of fs33.readdirSync(contextDir, { withFileTypes: true })) {
18944
+ for (const entry of fs34.readdirSync(contextDir, { withFileTypes: true })) {
18383
18945
  if (!entry.isDirectory()) continue;
18384
- const manifest = path40.join(contextDir, entry.name, "package.json");
18385
- if (!fs33.existsSync(manifest)) continue;
18386
- const pkg = JSON.parse(fs33.readFileSync(manifest, "utf-8"));
18946
+ const manifest = path41.join(contextDir, entry.name, "package.json");
18947
+ if (!fs34.existsSync(manifest)) continue;
18948
+ const pkg = JSON.parse(fs34.readFileSync(manifest, "utf-8"));
18387
18949
  let changed = false;
18388
18950
  if (pkg.devDependencies) {
18389
18951
  delete pkg.devDependencies;
@@ -18412,7 +18974,7 @@ function normalizeHubManifests(contextDir, catalog) {
18412
18974
  }
18413
18975
  }
18414
18976
  if (changed) {
18415
- fs33.writeFileSync(manifest, `${JSON.stringify(pkg, null, 2)}
18977
+ fs34.writeFileSync(manifest, `${JSON.stringify(pkg, null, 2)}
18416
18978
  `);
18417
18979
  touched.push(`${entry.name}/package.json`);
18418
18980
  }
@@ -18420,15 +18982,15 @@ function normalizeHubManifests(contextDir, catalog) {
18420
18982
  return touched;
18421
18983
  }
18422
18984
  async function buildHubImagesFromSource(repoRoot2) {
18423
- const hubDir = path40.join(repoRoot2, "apps", "hub");
18424
- if (!fs33.existsSync(path40.join(hubDir, "package.json"))) {
18985
+ const hubDir = path41.join(repoRoot2, "apps", "hub");
18986
+ if (!fs34.existsSync(path41.join(hubDir, "package.json"))) {
18425
18987
  throw new MeshCliError(
18426
18988
  `--hub-from-source needs a mesh-platform checkout; no apps/hub under ${repoRoot2}.`,
18427
18989
  { remediation: { command: "Run mesh start from a mesh-platform checkout, or drop --hub-from-source" } }
18428
18990
  );
18429
18991
  }
18430
18992
  const npmrc = npmrcPath();
18431
- const version = `${JSON.parse(fs33.readFileSync(path40.join(hubDir, "package.json"), "utf-8")).version}-src`;
18993
+ const version = `${JSON.parse(fs34.readFileSync(path41.join(hubDir, "package.json"), "utf-8")).version}-src`;
18432
18994
  const build = startHeartbeat("building apps/hub (api + ui) from source");
18433
18995
  try {
18434
18996
  for (const pkg of ["@mesh-tech/hub-api", "@mesh-tech/hub-ui"]) {
@@ -18437,27 +18999,27 @@ async function buildHubImagesFromSource(repoRoot2) {
18437
18999
  } finally {
18438
19000
  build.stop();
18439
19001
  }
18440
- const context = path40.join(cacheDir(), `context-${version}`);
18441
- fs33.rmSync(context, { recursive: true, force: true });
18442
- fs33.mkdirSync(context, { recursive: true });
19002
+ const context = path41.join(cacheDir(), `context-${version}`);
19003
+ fs34.rmSync(context, { recursive: true, force: true });
19004
+ fs34.mkdirSync(context, { recursive: true });
18443
19005
  await execFileAsync2("pnpm", ["pack", "--pack-destination", context], { cwd: hubDir, maxBuffer: 64 * 1024 * 1024 });
18444
- const tarball = fs33.readdirSync(context).find((f) => f.endsWith(".tgz"));
19006
+ const tarball = fs34.readdirSync(context).find((f) => f.endsWith(".tgz"));
18445
19007
  if (!tarball) throw new MeshCliError("pnpm pack produced no tarball for apps/hub");
18446
- execFileSync28("tar", ["-xzf", path40.join(context, tarball), "-C", context, "--strip-components", "1"], {
19008
+ execFileSync29("tar", ["-xzf", path41.join(context, tarball), "-C", context, "--strip-components", "1"], {
18447
19009
  stdio: ["ignore", "pipe", "pipe"]
18448
19010
  });
18449
19011
  const rewritten = normalizeHubManifests(context, readWorkspaceCatalog(repoRoot2));
18450
19012
  if (rewritten.length > 0) logInfo(`Normalized ${rewritten.length} manifest(s) for npm: ${rewritten.join(", ")}`);
18451
- const hubStackDir = path40.join(findPackageRoot(), "stack", "hub");
19013
+ const hubStackDir = path41.join(findPackageRoot(), "stack", "hub");
18452
19014
  for (const [name, dockerfile] of [
18453
19015
  ["mesh-local-hub-api", "Dockerfile.api"],
18454
19016
  ["mesh-local-hub-ui", "Dockerfile.ui"]
18455
19017
  ]) {
18456
19018
  const tag = `${name}:${version}`;
18457
19019
  logInfo(`Building ${tag} from source\u2026`);
18458
- execFileSync28(
19020
+ execFileSync29(
18459
19021
  "docker",
18460
- ["build", "-f", path40.join(hubStackDir, dockerfile), "-t", tag, "--secret", `id=npmrc,src=${npmrc}`, context],
19022
+ ["build", "-f", path41.join(hubStackDir, dockerfile), "-t", tag, "--secret", `id=npmrc,src=${npmrc}`, context],
18461
19023
  { stdio: ["ignore", "inherit", "inherit"], env: { ...process.env, DOCKER_BUILDKIT: "1" } }
18462
19024
  );
18463
19025
  logSuccess(`Built ${tag}`);
@@ -18542,8 +19104,8 @@ var init_seed_hub_catalog = __esm({
18542
19104
  });
18543
19105
 
18544
19106
  // libs/mesh-cli/src/commands/local/index.ts
18545
- import * as fs34 from "fs";
18546
- import * as path41 from "path";
19107
+ import * as fs35 from "fs";
19108
+ import * as path42 from "path";
18547
19109
  import chalk6 from "chalk";
18548
19110
  function crashError(crashed) {
18549
19111
  return new MeshCliError(
@@ -18586,7 +19148,7 @@ async function waitForStack(io = {
18586
19148
  );
18587
19149
  }
18588
19150
  logInfo(`Waiting for ${pending.map((e) => e.label).join(", ")} \u2026`);
18589
- await new Promise((resolve19) => setTimeout(resolve19, WAIT_POLL_MS));
19151
+ await new Promise((resolve20) => setTimeout(resolve20, WAIT_POLL_MS));
18590
19152
  }
18591
19153
  }
18592
19154
  function printEndpoints(hubRunning) {
@@ -18665,12 +19227,12 @@ function portMoveHints() {
18665
19227
  }
18666
19228
  function repoRootForHubSource() {
18667
19229
  for (let dir = process.cwd(); ; ) {
18668
- if (fs34.existsSync(path41.join(dir, "apps", "hub", "package.json"))) return dir;
18669
- const parent = path41.dirname(dir);
19230
+ if (fs35.existsSync(path42.join(dir, "apps", "hub", "package.json"))) return dir;
19231
+ const parent = path42.dirname(dir);
18670
19232
  if (parent === dir) break;
18671
19233
  dir = parent;
18672
19234
  }
18673
- return path41.resolve(findPackageRoot(), "..", "..");
19235
+ return path42.resolve(findPackageRoot(), "..", "..");
18674
19236
  }
18675
19237
  function registerLocalCommands(program2) {
18676
19238
  program2.command("start").description("Start the full-local Mesh platform (Docker only \u2014 no AWS, no VPN)").option("--no-seed", "skip first-boot seeding (tenant registry, artifacts bucket)").option("--no-hub", "start without the Hub (API + UI)").option(
@@ -18817,7 +19379,7 @@ Re-running start from here may recreate shared containers with this checkout's c
18817
19379
  overlayStarted: true
18818
19380
  });
18819
19381
  if (crashed.length > 0) throw crashError(crashed);
18820
- await new Promise((resolve19) => setTimeout(resolve19, 2e3));
19382
+ await new Promise((resolve20) => setTimeout(resolve20, 2e3));
18821
19383
  up = await probeEndpoint(endpoint);
18822
19384
  }
18823
19385
  if (!up) {
@@ -19112,6 +19674,18 @@ var init_src3 = __esm({
19112
19674
  }
19113
19675
  });
19114
19676
 
19677
+ // libs/mesh-cli/src/commands/secrets/context.ts
19678
+ function resolveSecretsContext(opts, stackOpt = resolveStackOption(opts)) {
19679
+ return detectContext(stackOpt, { tenant: opts.tenant, stack: stackOpt });
19680
+ }
19681
+ var init_context2 = __esm({
19682
+ "libs/mesh-cli/src/commands/secrets/context.ts"() {
19683
+ "use strict";
19684
+ init_context();
19685
+ init_stack_flag();
19686
+ }
19687
+ });
19688
+
19115
19689
  // libs/mesh-cli/src/commands/secrets/set.ts
19116
19690
  import {
19117
19691
  SSMClient as SSMClient2,
@@ -19260,7 +19834,7 @@ function displaySummary(fields, values, depth = 0) {
19260
19834
  }
19261
19835
  async function setCommand(servicePath, opts) {
19262
19836
  const stackOpt = resolveStackOption(opts);
19263
- const context = detectContext(stackOpt);
19837
+ const context = resolveSecretsContext(opts, stackOpt);
19264
19838
  const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
19265
19839
  await ensureAwsCredentialsForStack(stackOpt ?? context.stage);
19266
19840
  const ssmClient = new SSMClient2({ region });
@@ -19498,9 +20072,9 @@ var init_set = __esm({
19498
20072
  "libs/mesh-cli/src/commands/secrets/set.ts"() {
19499
20073
  "use strict";
19500
20074
  init_src3();
19501
- init_context();
19502
20075
  init_log();
19503
20076
  init_stack_flag();
20077
+ init_context2();
19504
20078
  init_pulumi();
19505
20079
  init_aws_auth();
19506
20080
  }
@@ -19538,7 +20112,7 @@ function indexAlreadyMatches(missing, stale, indexExists, malformed) {
19538
20112
  }
19539
20113
  async function reindexCommand(servicePath, opts) {
19540
20114
  const stackOpt = resolveStackOption(opts);
19541
- const context = detectContext(stackOpt);
20115
+ const context = resolveSecretsContext(opts, stackOpt);
19542
20116
  const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
19543
20117
  await ensureAwsCredentialsForStack(stackOpt ?? context.stage);
19544
20118
  const ssmClient = new SSMClient3({ region });
@@ -19634,9 +20208,9 @@ var init_reindex = __esm({
19634
20208
  "libs/mesh-cli/src/commands/secrets/reindex.ts"() {
19635
20209
  "use strict";
19636
20210
  init_src3();
19637
- init_context();
19638
20211
  init_log();
19639
20212
  init_stack_flag();
20213
+ init_context2();
19640
20214
  init_set();
19641
20215
  }
19642
20216
  });
@@ -19840,7 +20414,7 @@ async function migrateService(smClient, meta, schema, opts) {
19840
20414
  return { migrated, skipped, errors };
19841
20415
  }
19842
20416
  async function migrateConfigCommand(opts) {
19843
- const context = detectContext(resolveStackOption(opts));
20417
+ const context = resolveSecretsContext(opts);
19844
20418
  const region = opts.region ?? process.env.AWS_REGION ?? "us-east-2";
19845
20419
  const ssmClient = new SSMClient4({ region });
19846
20420
  const smClient = new SecretsManagerClient8({ region });
@@ -19879,9 +20453,8 @@ Migrating: ${name}`);
19879
20453
  var init_migrate_config = __esm({
19880
20454
  "libs/mesh-cli/src/commands/secrets/migrate-config.ts"() {
19881
20455
  "use strict";
19882
- init_context();
19883
20456
  init_log();
19884
- init_stack_flag();
20457
+ init_context2();
19885
20458
  }
19886
20459
  });
19887
20460
 
@@ -19893,15 +20466,15 @@ function registerSecretsCommands(program2) {
19893
20466
  const args = cmd.args;
19894
20467
  await execCommand2(args);
19895
20468
  });
19896
- secrets.command("set [service]").description("Set credentials for an external service (e.g., mesh secrets set external/symitar)").option("--key <key>", "Instance key for multi-instance services (e.g., FI ID)").option("--all", "Prompt for all fields including optional ones").option("--json <json>", "Non-interactive: provide values as JSON").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (service, opts) => {
20469
+ secrets.command("set [service]").description("Set credentials for an external service (e.g., mesh secrets set external/symitar)").option("--key <key>", "Instance key for multi-instance services (e.g., FI ID)").option("--all", "Prompt for all fields including optional ones").option("--json <json>", "Non-interactive: provide values as JSON").option("-t, --tenant <tenant>", "Tenant to address (override detection)").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (service, opts) => {
19897
20470
  await setCommand(service, opts);
19898
20471
  });
19899
20472
  secrets.command("reindex [service]").description(
19900
20473
  "Rebuild a multi-instance external service's instance index (the {prefix}/.index secret listInstances() reads) from the per-key secrets actually in Secrets Manager \u2014 the repair for an instance secret created or deleted out of band"
19901
- ).option("--dry-run", "Show what would change without writing").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (service, opts) => {
20474
+ ).option("--dry-run", "Show what would change without writing").option("-t, --tenant <tenant>", "Tenant to address (override detection)").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (service, opts) => {
19902
20475
  await reindexCommand(service, opts);
19903
20476
  });
19904
- secrets.command("migrate-config").description("Backfill .config mirror secrets for all external services").option("--force", "Overwrite existing .config mirrors").option("--dry-run", "Show what would be written without writing").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (opts) => {
20477
+ secrets.command("migrate-config").description("Backfill .config mirror secrets for all external services").option("--force", "Overwrite existing .config mirrors").option("--dry-run", "Show what would be written without writing").option("-t, --tenant <tenant>", "Tenant to address (override detection)").option("--stack <stack>", "Pulumi stack name (override detection)").addOption(new Option2("--stage <stack>", "Deprecated alias for --stack").hideHelp()).option("--region <region>", "AWS region (default: us-east-2)").action(async (opts) => {
19905
20478
  await migrateConfigCommand(opts);
19906
20479
  });
19907
20480
  }
@@ -19919,7 +20492,7 @@ var init_secrets = __esm({
19919
20492
  import { createHash as createHash4 } from "node:crypto";
19920
20493
  import { createReadStream } from "node:fs";
19921
20494
  import { readdir, readFile as readFile2, stat } from "node:fs/promises";
19922
- import { join as join37, relative as relative9, resolve as resolve16, sep as sep6 } from "node:path";
20495
+ import { join as join38, relative as relative11, resolve as resolve17, sep as sep6 } from "node:path";
19923
20496
  async function describeSiteHttpError(res, target, site) {
19924
20497
  if (res.status === 403) {
19925
20498
  return `not allowed to publish "${site}" \u2014 you are authenticated but lack the grant. Need one of: sites:${site}:publish, sites:*:publish, or studio-admin.`;
@@ -19941,9 +20514,9 @@ async function walk(root) {
19941
20514
  async function visit(dir) {
19942
20515
  for (const entry of await readdir(dir, { withFileTypes: true })) {
19943
20516
  if (SKIP_ENTRIES.has(entry.name)) continue;
19944
- const absolute = join37(dir, entry.name);
20517
+ const absolute = join38(dir, entry.name);
19945
20518
  if (entry.isSymbolicLink()) {
19946
- logWarn(`skipping symlink ${relative9(root, absolute)}`);
20519
+ logWarn(`skipping symlink ${relative11(root, absolute)}`);
19947
20520
  continue;
19948
20521
  }
19949
20522
  if (entry.isDirectory()) {
@@ -19955,7 +20528,7 @@ async function walk(root) {
19955
20528
  out.push({
19956
20529
  // Manifest paths are always forward-slashed, whatever the host OS uses,
19957
20530
  // so a site published from Windows resolves identically to one from a Mac.
19958
- path: relative9(root, absolute).split(sep6).join("/"),
20531
+ path: relative11(root, absolute).split(sep6).join("/"),
19959
20532
  absolute,
19960
20533
  hash: await hashFile(absolute),
19961
20534
  size: info.size
@@ -19984,7 +20557,7 @@ async function pooled(items, limit, worker) {
19984
20557
  await Promise.all(runners);
19985
20558
  }
19986
20559
  async function publish(name, dir, opts, target) {
19987
- const root = resolve16(dir);
20560
+ const root = resolve17(dir);
19988
20561
  const info = await stat(root).catch(() => null);
19989
20562
  if (!info?.isDirectory()) throw new Error(`${root} is not a directory`);
19990
20563
  logInfo(`Hashing ${root}\u2026`);
@@ -20136,23 +20709,23 @@ var init_site = __esm({
20136
20709
  });
20137
20710
 
20138
20711
  // libs/mesh-cli/src/commands/stack.ts
20139
- import { execFileSync as execFileSync29 } from "child_process";
20140
- import * as path42 from "path";
20141
- import * as fs35 from "fs";
20712
+ import { execFileSync as execFileSync30 } from "child_process";
20713
+ import * as path43 from "path";
20714
+ import * as fs36 from "fs";
20142
20715
  import { parse as parseYaml5 } from "yaml";
20143
20716
  function readTopLevelYamlKey(appRoot, stack, key) {
20144
- const configFile = path42.join(appRoot, `Pulumi.${stack}.yaml`);
20145
- if (!fs35.existsSync(configFile)) return null;
20146
- const content = fs35.readFileSync(configFile, "utf-8");
20717
+ const configFile = path43.join(appRoot, `Pulumi.${stack}.yaml`);
20718
+ if (!fs36.existsSync(configFile)) return null;
20719
+ const content = fs36.readFileSync(configFile, "utf-8");
20147
20720
  const pattern = new RegExp(`^${key}:\\s*(.+)$`, "m");
20148
20721
  const match = content.match(pattern);
20149
20722
  if (!match) return null;
20150
20723
  return match[1].trim().replace(/^["']|["']$/g, "");
20151
20724
  }
20152
20725
  function readConfigBlockKey(appRoot, stack, key) {
20153
- const configFile = path42.join(appRoot, `Pulumi.${stack}.yaml`);
20154
- if (!fs35.existsSync(configFile)) return null;
20155
- const content = fs35.readFileSync(configFile, "utf-8");
20726
+ const configFile = path43.join(appRoot, `Pulumi.${stack}.yaml`);
20727
+ if (!fs36.existsSync(configFile)) return null;
20728
+ const content = fs36.readFileSync(configFile, "utf-8");
20156
20729
  const pattern = new RegExp(`^\\s{2}${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:\\s*(.+)$`, "m");
20157
20730
  const match = content.match(pattern);
20158
20731
  if (!match) return null;
@@ -20212,11 +20785,11 @@ ${records}
20212
20785
  }
20213
20786
  }
20214
20787
  function readBaseConfigFromYaml(appRoot, stack) {
20215
- const file = path42.join(appRoot, `Pulumi.${stack}.yaml`);
20216
- if (!fs35.existsSync(file)) return {};
20788
+ const file = path43.join(appRoot, `Pulumi.${stack}.yaml`);
20789
+ if (!fs36.existsSync(file)) return {};
20217
20790
  let doc;
20218
20791
  try {
20219
- doc = parseYaml5(fs35.readFileSync(file, "utf-8"));
20792
+ doc = parseYaml5(fs36.readFileSync(file, "utf-8"));
20220
20793
  } catch {
20221
20794
  return {};
20222
20795
  }
@@ -20229,7 +20802,7 @@ function readBaseConfigFromYaml(appRoot, stack) {
20229
20802
  }
20230
20803
  function getGitHubUsername() {
20231
20804
  try {
20232
- const result = execFileSync29("gh", ["api", "user", "--jq", ".login"], {
20805
+ const result = execFileSync30("gh", ["api", "user", "--jq", ".login"], {
20233
20806
  encoding: "utf-8",
20234
20807
  stdio: ["pipe", "pipe", "pipe"]
20235
20808
  });
@@ -20238,7 +20811,7 @@ function getGitHubUsername() {
20238
20811
  } catch {
20239
20812
  }
20240
20813
  try {
20241
- const result = execFileSync29("git", ["config", "user.email"], {
20814
+ const result = execFileSync30("git", ["config", "user.email"], {
20242
20815
  encoding: "utf-8",
20243
20816
  stdio: ["pipe", "pipe", "pipe"]
20244
20817
  });
@@ -20293,7 +20866,7 @@ Specify which to base on: mesh stack init --from <stack>`
20293
20866
  }
20294
20867
  }
20295
20868
  const baseConfigPath = `${appRoot}/Pulumi.${baseStack}.yaml`;
20296
- if (!fs35.existsSync(baseConfigPath)) {
20869
+ if (!fs36.existsSync(baseConfigPath)) {
20297
20870
  logError(`Stack config not found: Pulumi.${baseStack}.yaml`);
20298
20871
  process.exit(1);
20299
20872
  }
@@ -20315,8 +20888,8 @@ Specify which to base on: mesh stack init --from <stack>`
20315
20888
  );
20316
20889
  }
20317
20890
  }
20318
- const newConfigPath = path42.join(appRoot, `Pulumi.${newStack}.yaml`);
20319
- const configExists = fs35.existsSync(newConfigPath);
20891
+ const newConfigPath = path43.join(appRoot, `Pulumi.${newStack}.yaml`);
20892
+ const configExists = fs36.existsSync(newConfigPath);
20320
20893
  const secretsProvider = readTopLevelYamlKey(appRoot, baseStack, "secretsprovider");
20321
20894
  const credEnv = await resolvePulumiEnv({ appRoot, stack: baseStack });
20322
20895
  const pulumiEnv = { ...process.env, ...credEnv };
@@ -20324,7 +20897,7 @@ Specify which to base on: mesh stack init --from <stack>`
20324
20897
  if (!opts.adopt) {
20325
20898
  let existing = [];
20326
20899
  try {
20327
- const raw = execFileSync29("pulumi", ["stack", "ls", "--json"], {
20900
+ const raw = execFileSync30("pulumi", ["stack", "ls", "--json"], {
20328
20901
  cwd: appRoot,
20329
20902
  encoding: "utf-8",
20330
20903
  env: pulumiEnv,
@@ -20348,7 +20921,7 @@ Specify which to base on: mesh stack init --from <stack>`
20348
20921
  logInfo(`Using KMS secrets provider: ${secretsProvider}`);
20349
20922
  }
20350
20923
  try {
20351
- execFileSync29("pulumi", initArgs, {
20924
+ execFileSync30("pulumi", initArgs, {
20352
20925
  cwd: appRoot,
20353
20926
  env: pulumiEnv,
20354
20927
  stdio: "inherit"
@@ -20365,7 +20938,7 @@ Specify which to base on: mesh stack init --from <stack>`
20365
20938
  }
20366
20939
  }
20367
20940
  try {
20368
- execFileSync29("pulumi", ["stack", "select", newStack], {
20941
+ execFileSync30("pulumi", ["stack", "select", newStack], {
20369
20942
  cwd: appRoot,
20370
20943
  env: pulumiEnv,
20371
20944
  stdio: ["pipe", "pipe", "pipe"]
@@ -20375,7 +20948,7 @@ Specify which to base on: mesh stack init --from <stack>`
20375
20948
  if (!configExists) {
20376
20949
  let baseConfig = {};
20377
20950
  try {
20378
- const raw = execFileSync29(
20951
+ const raw = execFileSync30(
20379
20952
  "pulumi",
20380
20953
  ["config", "--json", "--stack", baseStack],
20381
20954
  { cwd: appRoot, env: pulumiEnv, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
@@ -20393,19 +20966,19 @@ Specify which to base on: mesh stack init --from <stack>`
20393
20966
  if (key === "mesh:deploy") continue;
20394
20967
  try {
20395
20968
  if (entry.objectValue !== void 0) {
20396
- execFileSync29(
20969
+ execFileSync30(
20397
20970
  "pulumi",
20398
20971
  ["config", "set", key, JSON.stringify(entry.objectValue)],
20399
20972
  { cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
20400
20973
  );
20401
20974
  } else if (entry.value === "true" || entry.value === "false") {
20402
- execFileSync29(
20975
+ execFileSync30(
20403
20976
  "pulumi",
20404
20977
  ["config", "set", "--type", "bool", key, entry.value],
20405
20978
  { cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
20406
20979
  );
20407
20980
  } else {
20408
- execFileSync29(
20981
+ execFileSync30(
20409
20982
  "pulumi",
20410
20983
  ["config", "set", key, entry.value],
20411
20984
  { cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
@@ -20418,7 +20991,7 @@ Specify which to base on: mesh stack init --from <stack>`
20418
20991
  const baseEnv = readConfigBlockKey(appRoot, baseStack, "mesh:coreEnv") ?? (baseTenant && baseStack.startsWith(`${baseTenant}-`) ? baseStack.slice(baseTenant.length + 1) : baseStack);
20419
20992
  const setCfg = (args) => {
20420
20993
  try {
20421
- execFileSync29("pulumi", ["config", "set", ...args], {
20994
+ execFileSync30("pulumi", ["config", "set", ...args], {
20422
20995
  cwd: appRoot,
20423
20996
  env: pulumiEnv,
20424
20997
  stdio: ["pipe", "pipe", "pipe"]
@@ -20467,7 +21040,7 @@ Specify which to base on: mesh stack init --from <stack>`
20467
21040
  `Configured Pulumi.${newStack}.yaml (personal platform env on core '${baseEnv}'${opts.parentZone ? `, DNS zone ${newStack.startsWith(`${baseTenant}-`) ? newStack.slice(baseTenant.length + 1) : newStack}.${opts.parentZone}` : ""})`
20468
21041
  );
20469
21042
  } else {
20470
- execFileSync29("pulumi", ["config", "set", "--type", "bool", "mesh:deploy", "false"], {
21043
+ execFileSync30("pulumi", ["config", "set", "--type", "bool", "mesh:deploy", "false"], {
20471
21044
  cwd: appRoot,
20472
21045
  env: pulumiEnv,
20473
21046
  stdio: ["pipe", "pipe", "pipe"]
@@ -20497,7 +21070,7 @@ Specify which to base on: mesh stack init --from <stack>`
20497
21070
  const args = ["stack", "rm", name];
20498
21071
  if (opts.yes) args.push("--yes");
20499
21072
  try {
20500
- execFileSync29("pulumi", args, { cwd: appRoot, env: pulumiEnv, stdio: "inherit" });
21073
+ execFileSync30("pulumi", args, { cwd: appRoot, env: pulumiEnv, stdio: "inherit" });
20501
21074
  logSuccess(`Removed stack ${name}`);
20502
21075
  } catch (err) {
20503
21076
  process.exit(err.status ?? 1);
@@ -20709,12 +21282,12 @@ var init_recover_conversation = __esm({
20709
21282
  });
20710
21283
 
20711
21284
  // libs/mesh-cli/src/utils/temporal-codec.ts
20712
- import { execFileSync as execFileSync30 } from "child_process";
21285
+ import { execFileSync as execFileSync31 } from "child_process";
20713
21286
  import { webcrypto as crypto4 } from "node:crypto";
20714
21287
  function resolveTemporalEncodingKeyFromK8s(namespace) {
20715
21288
  const secretName = `${namespace}-temporal-encoding-key`;
20716
21289
  try {
20717
- const b64 = execFileSync30(
21290
+ const b64 = execFileSync31(
20718
21291
  "kubectl",
20719
21292
  [
20720
21293
  "get",
@@ -20965,7 +21538,7 @@ var init_capture_history = __esm({
20965
21538
  import { spawnSync as spawnSync4 } from "node:child_process";
20966
21539
  import { writeFileSync as writeFileSync24, mkdirSync as mkdirSync19 } from "node:fs";
20967
21540
  import { homedir as homedir6 } from "node:os";
20968
- import { dirname as dirname28, join as join39, resolve as resolve17 } from "node:path";
21541
+ import { dirname as dirname28, join as join40, resolve as resolve18 } from "node:path";
20969
21542
  async function resolveConnection(options) {
20970
21543
  if (options.address && options.namespace) {
20971
21544
  return { address: options.address, namespace: options.namespace };
@@ -21393,7 +21966,7 @@ async function captureHistory(workflowId, runId, options) {
21393
21966
  }
21394
21967
  const { serializeHistoryToFixture: serializeHistoryToFixture2 } = await Promise.resolve().then(() => (init_capture_history(), capture_history_exports));
21395
21968
  const { fixture, eventCount, decryptedPayloads } = await serializeHistoryToFixture2(events, decrypter);
21396
- const outPath = options.out ?? join39(homedir6(), ".mesh", "replay-histories", `${sanitizeFileId(workflowId)}.json`);
21969
+ const outPath = options.out ?? join40(homedir6(), ".mesh", "replay-histories", `${sanitizeFileId(workflowId)}.json`);
21397
21970
  mkdirSync19(dirname28(outPath), { recursive: true });
21398
21971
  if (options.out) warnIfNotGitIgnored(options.out);
21399
21972
  writeFileSync24(outPath, JSON.stringify(fixture, null, 2) + "\n");
@@ -21411,7 +21984,7 @@ function sanitizeFileId(id) {
21411
21984
  return id.replace(/[^A-Za-z0-9._-]/g, "_");
21412
21985
  }
21413
21986
  function warnIfNotGitIgnored(outPath) {
21414
- const abs = resolve17(outPath);
21987
+ const abs = resolve18(outPath);
21415
21988
  try {
21416
21989
  const res = spawnSync4("git", ["-C", dirname28(abs), "check-ignore", "-q", abs], {
21417
21990
  stdio: "ignore"
@@ -21585,8 +22158,8 @@ var init_temporal = __esm({
21585
22158
 
21586
22159
  // libs/mesh-cli/src/commands/tenant.ts
21587
22160
  import chalk7 from "chalk";
21588
- import * as fs36 from "fs";
21589
- import * as path43 from "path";
22161
+ import * as fs37 from "fs";
22162
+ import * as path44 from "path";
21590
22163
  import { parseDocument, YAMLMap, isMap } from "yaml";
21591
22164
  function validateTenantName(name) {
21592
22165
  return /^[a-z][a-z0-9-]*$/.test(name) && !name.endsWith("-");
@@ -21654,16 +22227,16 @@ function resolveStackConfig(explicitStack) {
21654
22227
  { remediation: { command: "mesh tenant add <name> --stack <stack>" } }
21655
22228
  );
21656
22229
  }
21657
- const file = path43.join(appRoot, `Pulumi.${stack}.yaml`);
21658
- if (!fs36.existsSync(file)) {
22230
+ const file = path44.join(appRoot, `Pulumi.${stack}.yaml`);
22231
+ if (!fs37.existsSync(file)) {
21659
22232
  throw new MeshCliError(`Stack config not found: ${file}`, {
21660
22233
  remediation: { command: "mesh tenant add <name> --stack <stack>" }
21661
22234
  });
21662
22235
  }
21663
- return { appRoot, stack, file, content: fs36.readFileSync(file, "utf-8") };
22236
+ return { appRoot, stack, file, content: fs37.readFileSync(file, "utf-8") };
21664
22237
  }
21665
22238
  function readProjectName(appRoot) {
21666
- const projectDoc = parseDocument(fs36.readFileSync(path43.join(appRoot, "Pulumi.yaml"), "utf-8"));
22239
+ const projectDoc = parseDocument(fs37.readFileSync(path44.join(appRoot, "Pulumi.yaml"), "utf-8"));
21667
22240
  return String(projectDoc.get("name") ?? "");
21668
22241
  }
21669
22242
  function looksLikePlatformLayer(projectName) {
@@ -21706,12 +22279,12 @@ function registerTenantCommands(program2) {
21706
22279
  if (!result.ok) {
21707
22280
  if (result.reason === "exists") {
21708
22281
  throw new MeshCliError(
21709
- `${result.detail} (${path43.basename(resolved.file)}). Edit the existing entry instead of re-adding it.`
22282
+ `${result.detail} (${path44.basename(resolved.file)}). Edit the existing entry instead of re-adding it.`
21710
22283
  );
21711
22284
  }
21712
22285
  throw new MeshCliError(`${resolved.file}: ${result.detail}`);
21713
22286
  }
21714
- atomicWriteFileSync(resolved.file, result.yaml, fs36.statSync(resolved.file).mode & 511);
22287
+ atomicWriteFileSync(resolved.file, result.yaml, fs37.statSync(resolved.file).mode & 511);
21715
22288
  if (opts.json) {
21716
22289
  emitJsonPayload({
21717
22290
  ok: true,
@@ -21724,7 +22297,7 @@ function registerTenantCommands(program2) {
21724
22297
  return;
21725
22298
  }
21726
22299
  logInfo(
21727
- `Tenant '${name}' registered in ${path43.basename(resolved.file)} (mesh:tenants, subdomain '${subdomain}')${result.createdTenantsBlock ? " \u2014 created the mesh:tenants block" : ""}`
22300
+ `Tenant '${name}' registered in ${path44.basename(resolved.file)} (mesh:tenants, subdomain '${subdomain}')${result.createdTenantsBlock ? " \u2014 created the mesh:tenants block" : ""}`
21728
22301
  );
21729
22302
  console.log("");
21730
22303
  console.log("Next steps:");
@@ -21750,7 +22323,7 @@ function registerTenantCommands(program2) {
21750
22323
  `Project '${projectName}' does not look like a platform layer \u2014 tenants are declared on the tenant platform repo's PLATFORM stack (e.g. mesh-sandbox/platform).`
21751
22324
  );
21752
22325
  }
21753
- logInfo(`No tenants declared in ${path43.basename(resolved.file)}.`);
22326
+ logInfo(`No tenants declared in ${path44.basename(resolved.file)}.`);
21754
22327
  return;
21755
22328
  }
21756
22329
  logInfo(`Tenants on stack '${resolved.stack}':`);
@@ -21772,9 +22345,9 @@ var init_tenant = __esm({
21772
22345
 
21773
22346
  // libs/mesh-cli/src/commands/tunnel/index.ts
21774
22347
  import { spawn as spawn9 } from "child_process";
21775
- import * as fs37 from "fs";
22348
+ import * as fs38 from "fs";
21776
22349
  import * as os12 from "os";
21777
- import * as path44 from "path";
22350
+ import * as path45 from "path";
21778
22351
  import {
21779
22352
  SecretsManagerClient as SecretsManagerClient9,
21780
22353
  GetSecretValueCommand as GetSecretValueCommand9
@@ -21783,7 +22356,7 @@ function resolveTenantEnv(options) {
21783
22356
  if (options.tenant && options.env) {
21784
22357
  return { tenant: options.tenant, env: options.env };
21785
22358
  }
21786
- const ctx = detectContext(options.env);
22359
+ const ctx = detectContext(void 0, { tenant: options.tenant });
21787
22360
  return {
21788
22361
  tenant: options.tenant ?? ctx.tenant,
21789
22362
  env: options.env ?? ctx.platformEnv,
@@ -21794,9 +22367,9 @@ function readPulumiAwsRegion(stage) {
21794
22367
  const preferred = stage ? `Pulumi.${stage}.yaml` : void 0;
21795
22368
  const rank = (f) => f === preferred ? 0 : f === "Pulumi.yaml" ? 2 : 1;
21796
22369
  try {
21797
- const files = fs37.readdirSync(".").filter((f) => f.startsWith("Pulumi.") && f.endsWith(".yaml")).sort((a, b) => rank(a) - rank(b));
22370
+ const files = fs38.readdirSync(".").filter((f) => f.startsWith("Pulumi.") && f.endsWith(".yaml")).sort((a, b) => rank(a) - rank(b));
21798
22371
  for (const f of files) {
21799
- const m = fs37.readFileSync(f, "utf-8").match(/^\s*aws:region:\s*["']?([^"'\n]+)["']?/m);
22372
+ const m = fs38.readFileSync(f, "utf-8").match(/^\s*aws:region:\s*["']?([^"'\n]+)["']?/m);
21800
22373
  if (m?.[1]) return m[1].trim();
21801
22374
  }
21802
22375
  } catch {
@@ -21805,14 +22378,14 @@ function readPulumiAwsRegion(stage) {
21805
22378
  }
21806
22379
  function awsProfileSections(name) {
21807
22380
  return [
21808
- [path44.join(os12.homedir(), ".aws", "config"), `[profile ${name}]`],
21809
- [path44.join(os12.homedir(), ".aws", "credentials"), `[${name}]`]
22381
+ [path45.join(os12.homedir(), ".aws", "config"), `[profile ${name}]`],
22382
+ [path45.join(os12.homedir(), ".aws", "credentials"), `[${name}]`]
21810
22383
  ];
21811
22384
  }
21812
22385
  function awsProfileExists(name) {
21813
22386
  for (const [file, header] of awsProfileSections(name)) {
21814
22387
  try {
21815
- const lines = fs37.readFileSync(file, "utf-8").split("\n");
22388
+ const lines = fs38.readFileSync(file, "utf-8").split("\n");
21816
22389
  if (lines.some((l) => l.trim() === header)) return true;
21817
22390
  } catch {
21818
22391
  }
@@ -21838,7 +22411,7 @@ function awsProfileRegion(profile) {
21838
22411
  if (!profile) return void 0;
21839
22412
  for (const [file, header] of awsProfileSections(profile)) {
21840
22413
  try {
21841
- const region = parseProfileRegion(fs37.readFileSync(file, "utf-8"), header);
22414
+ const region = parseProfileRegion(fs38.readFileSync(file, "utf-8"), header);
21842
22415
  if (region) return region;
21843
22416
  } catch {
21844
22417
  }
@@ -21847,14 +22420,14 @@ function awsProfileRegion(profile) {
21847
22420
  }
21848
22421
  function awsDefaultProfileSections() {
21849
22422
  return [
21850
- [path44.join(os12.homedir(), ".aws", "config"), "[default]"],
21851
- [path44.join(os12.homedir(), ".aws", "credentials"), "[default]"]
22423
+ [path45.join(os12.homedir(), ".aws", "config"), "[default]"],
22424
+ [path45.join(os12.homedir(), ".aws", "credentials"), "[default]"]
21852
22425
  ];
21853
22426
  }
21854
22427
  function awsDefaultProfileRegion() {
21855
22428
  for (const [file, header] of awsDefaultProfileSections()) {
21856
22429
  try {
21857
- const region = parseProfileRegion(fs37.readFileSync(file, "utf-8"), header);
22430
+ const region = parseProfileRegion(fs38.readFileSync(file, "utf-8"), header);
21858
22431
  if (region) return region;
21859
22432
  } catch {
21860
22433
  }
@@ -21995,9 +22568,9 @@ async function tunnelServices(serviceNames, options) {
21995
22568
  process.on("SIGTERM", cleanup);
21996
22569
  await Promise.race(
21997
22570
  processes.map(
21998
- (proc) => new Promise((resolve19) => {
21999
- proc.on("exit", () => resolve19());
22000
- proc.on("error", () => resolve19());
22571
+ (proc) => new Promise((resolve20) => {
22572
+ proc.on("exit", () => resolve20());
22573
+ proc.on("error", () => resolve20());
22001
22574
  })
22002
22575
  )
22003
22576
  );
@@ -22094,9 +22667,9 @@ async function tunnelExternal(name, options) {
22094
22667
  };
22095
22668
  process.on("SIGINT", cleanup);
22096
22669
  process.on("SIGTERM", cleanup);
22097
- await new Promise((resolve19) => {
22098
- proc.on("exit", () => resolve19());
22099
- proc.on("error", () => resolve19());
22670
+ await new Promise((resolve20) => {
22671
+ proc.on("exit", () => resolve20());
22672
+ proc.on("error", () => resolve20());
22100
22673
  });
22101
22674
  cleanup();
22102
22675
  }
@@ -22141,7 +22714,7 @@ function registerTunnelCommands(program2) {
22141
22714
  "Tenant for the external service's credentials (default: --tenant)"
22142
22715
  ).option(
22143
22716
  "--app-stage <stage>",
22144
- "Stage for the external service's credentials (default: --env)"
22717
+ "Stage for the external service's credentials (default: the detected app stage, else --env)"
22145
22718
  ).option(
22146
22719
  "-k, --key <key>",
22147
22720
  "Instance key for a multi-instance external (credentials.keyedBy)"
@@ -22241,8 +22814,8 @@ async function resolveToken(opts) {
22241
22814
  "no token: pass --token, set VCS_TOKEN, or pass --context <platform-context> (after mesh login)"
22242
22815
  );
22243
22816
  }
22244
- async function vcsApi(baseUrl, token, path46, method = "GET", body) {
22245
- const res = await fetch(`${baseUrl}${path46}`, {
22817
+ async function vcsApi(baseUrl, token, path47, method = "GET", body) {
22818
+ const res = await fetch(`${baseUrl}${path47}`, {
22246
22819
  method,
22247
22820
  headers: {
22248
22821
  authorization: `Bearer ${token}`,
@@ -22253,7 +22826,7 @@ async function vcsApi(baseUrl, token, path46, method = "GET", body) {
22253
22826
  const data = await res.json().catch(() => ({}));
22254
22827
  if (!res.ok) {
22255
22828
  throw new Error(
22256
- `${method} ${path46} failed (${res.status}): ${String(data.error ?? "unknown error")}`
22829
+ `${method} ${path47} failed (${res.status}): ${String(data.error ?? "unknown error")}`
22257
22830
  );
22258
22831
  }
22259
22832
  return data;
@@ -22299,8 +22872,8 @@ var init_clone = __esm({
22299
22872
 
22300
22873
  // libs/mesh-cli/src/commands/vcs/get.ts
22301
22874
  import { writeFile as writeFile2, mkdir as mkdir2 } from "node:fs/promises";
22302
- import { join as join42, dirname as dirname29 } from "node:path";
22303
- async function getCommand(repo, path46, opts) {
22875
+ import { join as join43, dirname as dirname29 } from "node:path";
22876
+ async function getCommand(repo, path47, opts) {
22304
22877
  let vcsBaseUrl;
22305
22878
  let token;
22306
22879
  if (opts.target) {
@@ -22315,18 +22888,18 @@ async function getCommand(repo, path46, opts) {
22315
22888
  if (!token) throw new Error("no token: pass --target (after mesh login), or --token / --context");
22316
22889
  const reader = createVcsFolderReader({ vcsBaseUrl, token });
22317
22890
  try {
22318
- const { ref, files } = await reader.readPath(repo, path46);
22891
+ const { ref, files } = await reader.readPath(repo, path47);
22319
22892
  if (files.length === 0) {
22320
- logInfo(`no files at ${repo}:${path46}`);
22893
+ logInfo(`no files at ${repo}:${path47}`);
22321
22894
  return;
22322
22895
  }
22323
22896
  if (opts.output) {
22324
22897
  for (const f of files) {
22325
- const abs = join42(opts.output, f.path);
22898
+ const abs = join43(opts.output, f.path);
22326
22899
  await mkdir2(dirname29(abs), { recursive: true });
22327
22900
  await writeFile2(abs, f.contents);
22328
22901
  }
22329
- logInfo(`wrote ${files.length} file(s) from ${repo}:${path46} (${ref}) \u2192 ${opts.output}`);
22902
+ logInfo(`wrote ${files.length} file(s) from ${repo}:${path47} (${ref}) \u2192 ${opts.output}`);
22330
22903
  } else {
22331
22904
  for (const f of files) {
22332
22905
  if (files.length > 1) process.stdout.write(`
@@ -22351,10 +22924,10 @@ var init_get = __esm({
22351
22924
  });
22352
22925
 
22353
22926
  // libs/mesh-cli/src/commands/vcs/drafts.ts
22354
- async function call(opts, repo, path46, method = "GET", body) {
22927
+ async function call(opts, repo, path47, method = "GET", body) {
22355
22928
  const target = await resolveTarget2({ ...opts, repo });
22356
22929
  const token = await resolveToken(opts);
22357
- return vcsApi(target.baseUrl, token, `/v1/repos/${repo}${path46}`, method, body);
22930
+ return vcsApi(target.baseUrl, token, `/v1/repos/${repo}${path47}`, method, body);
22358
22931
  }
22359
22932
  async function draftsListCommand(repo, opts) {
22360
22933
  const data = await call(opts, repo, `/drafts${opts.all ? "?all=true" : ""}`);
@@ -22409,7 +22982,7 @@ var init_drafts = __esm({
22409
22982
 
22410
22983
  // libs/mesh-cli/src/commands/vcs/propose.ts
22411
22984
  import { readFile as readFile3 } from "node:fs/promises";
22412
- import { join as join43 } from "node:path";
22985
+ import { join as join44 } from "node:path";
22413
22986
  function parseStatus(out) {
22414
22987
  const tokens = out.split("\0");
22415
22988
  const changes = [];
@@ -22442,13 +23015,13 @@ function parseStatus(out) {
22442
23015
  }
22443
23016
  return changes;
22444
23017
  }
22445
- async function writeOp(cwd, path46) {
22446
- const buf = await readFile3(join43(cwd, path46));
23018
+ async function writeOp(cwd, path47) {
23019
+ const buf = await readFile3(join44(cwd, path47));
22447
23020
  const asUtf8 = buf.toString("utf8");
22448
23021
  if (Buffer.from(asUtf8, "utf8").equals(buf)) {
22449
- return { op: "write", path: path46, content: asUtf8 };
23022
+ return { op: "write", path: path47, content: asUtf8 };
22450
23023
  }
22451
- return { op: "write", path: path46, content: buf.toString("base64"), encoding: "base64" };
23024
+ return { op: "write", path: path47, content: buf.toString("base64"), encoding: "base64" };
22452
23025
  }
22453
23026
  async function proposeCommand(opts) {
22454
23027
  const cwd = process.cwd();
@@ -22492,8 +23065,8 @@ async function proposeCommand(opts) {
22492
23065
  operations,
22493
23066
  ...opts.mergeParent ? { mergeParent: opts.mergeParent } : {}
22494
23067
  };
22495
- const path46 = opts.revise ? `/v1/repos/${target.repo}/proposals/${opts.revise}/revisions` : `/v1/repos/${target.repo}/proposals`;
22496
- const data = await vcsApi(target.baseUrl, token, path46, "POST", body);
23068
+ const path47 = opts.revise ? `/v1/repos/${target.repo}/proposals/${opts.revise}/revisions` : `/v1/repos/${target.repo}/proposals`;
23069
+ const data = await vcsApi(target.baseUrl, token, path47, "POST", body);
22497
23070
  console.log(
22498
23071
  `proposal ${data.proposalId} @ ${data.sha.slice(0, 8)} \u2014 review: mesh vcs show ${target.repo} ${data.proposalId} --url ${target.baseUrl}`
22499
23072
  );
@@ -22508,28 +23081,28 @@ var init_propose = __esm({
22508
23081
  // libs/mesh-cli/src/commands/vcs/rm.ts
22509
23082
  import { mkdtemp as mkdtemp2, rm as rmrf } from "node:fs/promises";
22510
23083
  import { tmpdir as tmpdir10 } from "node:os";
22511
- import { join as join44 } from "node:path";
23084
+ import { join as join45 } from "node:path";
22512
23085
  function normalize2(p) {
22513
23086
  return p.trim().replace(/^\.\//, "").replace(/\/+$/, "");
22514
23087
  }
22515
23088
  function expandPathsToDeletions(repoFiles, requested) {
22516
23089
  const out = /* @__PURE__ */ new Set();
22517
23090
  for (const raw of requested) {
22518
- const path46 = normalize2(raw);
22519
- if (path46.startsWith("/") || path46.split("/").includes("..")) {
23091
+ const path47 = normalize2(raw);
23092
+ if (path47.startsWith("/") || path47.split("/").includes("..")) {
22520
23093
  throw new Error(
22521
23094
  `"${raw}" is not a repo-relative path \u2014 vcs paths never start with "/" or traverse with "..".`
22522
23095
  );
22523
23096
  }
22524
- const exact = repoFiles.filter((f) => f === path46);
23097
+ const exact = repoFiles.filter((f) => f === path47);
22525
23098
  if (exact.length > 0) {
22526
23099
  for (const f of exact) out.add(f);
22527
23100
  continue;
22528
23101
  }
22529
- const under = repoFiles.filter((f) => f.startsWith(`${path46}/`));
23102
+ const under = repoFiles.filter((f) => f.startsWith(`${path47}/`));
22530
23103
  if (under.length === 0) {
22531
23104
  throw new Error(
22532
- `"${raw}" matched no files in the repo \u2014 nothing was proposed. Check the path with: mesh vcs get <repo> ${path46}`
23105
+ `"${raw}" matched no files in the repo \u2014 nothing was proposed. Check the path with: mesh vcs get <repo> ${path47}`
22533
23106
  );
22534
23107
  }
22535
23108
  for (const f of under) out.add(f);
@@ -22540,7 +23113,7 @@ async function rmCommand(repo, paths, opts) {
22540
23113
  const baseUrl = (opts.url ?? process.env.VCS_URL)?.replace(/\/$/, "");
22541
23114
  if (!baseUrl) throw new Error("rm requires --url or VCS_URL");
22542
23115
  const token = await resolveToken(opts);
22543
- const dir = await mkdtemp2(join44(tmpdir10(), "mesh-vcs-rm-"));
23116
+ const dir = await mkdtemp2(join45(tmpdir10(), "mesh-vcs-rm-"));
22544
23117
  try {
22545
23118
  const git = (args, cwd) => gitWithAuth(args, token, cwd);
22546
23119
  await git([
@@ -22565,7 +23138,7 @@ async function rmCommand(repo, paths, opts) {
22565
23138
  const body = {
22566
23139
  baseCommit: head.trim(),
22567
23140
  message: opts.message ?? `Delete ${doomed.length} file(s)`,
22568
- operations: doomed.map((path46) => ({ op: "delete", path: path46 }))
23141
+ operations: doomed.map((path47) => ({ op: "delete", path: path47 }))
22569
23142
  };
22570
23143
  const data = await vcsApi(
22571
23144
  baseUrl,
@@ -22591,10 +23164,10 @@ var init_rm = __esm({
22591
23164
  });
22592
23165
 
22593
23166
  // libs/mesh-cli/src/commands/vcs/review.ts
22594
- async function call2(opts, repo, path46, method = "GET", body) {
23167
+ async function call2(opts, repo, path47, method = "GET", body) {
22595
23168
  const target = await resolveTarget2({ ...opts, repo });
22596
23169
  const token = await resolveToken(opts);
22597
- return vcsApi(target.baseUrl, token, `/v1/repos/${repo}${path46}`, method, body);
23170
+ return vcsApi(target.baseUrl, token, `/v1/repos/${repo}${path47}`, method, body);
22598
23171
  }
22599
23172
  async function proposalsCommand(repo, opts) {
22600
23173
  console.log(JSON.stringify(await call2(opts, repo, "/proposals"), null, 2));
@@ -22741,8 +23314,8 @@ function computeHappyPath(nodes, edges) {
22741
23314
  ];
22742
23315
  const visited = /* @__PURE__ */ new Set([startNode.id]);
22743
23316
  while (queue.length > 0) {
22744
- const { id, path: path46 } = queue.shift();
22745
- if (targetIds.has(id)) return path46;
23317
+ const { id, path: path47 } = queue.shift();
23318
+ if (targetIds.has(id)) return path47;
22746
23319
  const neighbors = adjacency.get(id) ?? [];
22747
23320
  const hasMainEdge = neighbors.some((e) => e.isMainPath);
22748
23321
  const candidates = hasMainEdge ? neighbors.filter((e) => e.isMainPath) : neighbors;
@@ -22762,7 +23335,7 @@ function computeHappyPath(nodes, edges) {
22762
23335
  if (!allowExceptional && (neighbor.isExceptional || neighbor.isTimeout || failureEndIds.has(neighbor.to)))
22763
23336
  continue;
22764
23337
  visited.add(neighbor.to);
22765
- queue.push({ id: neighbor.to, path: [...path46, neighbor.to] });
23338
+ queue.push({ id: neighbor.to, path: [...path47, neighbor.to] });
22766
23339
  }
22767
23340
  }
22768
23341
  return null;
@@ -23047,11 +23620,11 @@ function wrapIntoGroup(workflow, nodeIds, groupId, label, groupType) {
23047
23620
  }
23048
23621
  }
23049
23622
  if (found) {
23050
- const path46 = [];
23051
- for (let c = found; c !== void 0; c = prev.get(c)) path46.unshift(c);
23052
- for (let i = 0; i < path46.length - 1; i++) mainEdgeKeys.add(edgeKey(path46[i], path46[i + 1]));
23623
+ const path47 = [];
23624
+ for (let c = found; c !== void 0; c = prev.get(c)) path47.unshift(c);
23625
+ for (let i = 0; i < path47.length - 1; i++) mainEdgeKeys.add(edgeKey(path47[i], path47[i + 1]));
23053
23626
  mainEdgeKeys.add(edgeKey(found, successExit.id));
23054
- mainBody = path46;
23627
+ mainBody = path47;
23055
23628
  mainTail = [successExit.id];
23056
23629
  }
23057
23630
  }
@@ -23587,11 +24160,11 @@ function buildProcessManifest(artifact, outcomeNodeIds) {
23587
24160
  ...pointOfNoReturnStage ? { pointOfNoReturnStageId: pointOfNoReturnStage.id } : {}
23588
24161
  };
23589
24162
  }
23590
- function formatPath(path46) {
23591
- return path46.length > 0 ? z4.core.toDotPath(path46) : "(root)";
24163
+ function formatPath(path47) {
24164
+ return path47.length > 0 ? z4.core.toDotPath(path47) : "(root)";
23592
24165
  }
23593
24166
  function issueToDiagnostic(issue) {
23594
- const path46 = formatPath(issue.path);
24167
+ const path47 = formatPath(issue.path);
23595
24168
  let code = "SCHEMA_INVALID";
23596
24169
  if (issue.code === "custom") {
23597
24170
  const paramCode = issue.params?.code;
@@ -23602,8 +24175,8 @@ function issueToDiagnostic(issue) {
23602
24175
  return {
23603
24176
  severity: "error",
23604
24177
  code,
23605
- message: `${path46}: ${issue.message}`,
23606
- path: path46
24178
+ message: `${path47}: ${issue.message}`,
24179
+ path: path47
23607
24180
  };
23608
24181
  }
23609
24182
  function upgradeV1(artifact) {
@@ -23770,24 +24343,24 @@ var init_process_artifact = __esm({
23770
24343
  });
23771
24344
  }
23772
24345
  const declaredSelectors = new Set(Object.keys(process2.selectors ?? {}));
23773
- const checkActor = (actorId, path46) => {
24346
+ const checkActor = (actorId, path47) => {
23774
24347
  if (actorId === void 0) return;
23775
24348
  if (!Object.prototype.hasOwnProperty.call(process2.actors, actorId)) {
23776
24349
  ctx.addIssue({
23777
24350
  code: "custom",
23778
- path: path46,
23779
- message: `Actor "${actorId}" is referenced at ${z4.core.toDotPath(path46)} but not declared in process.actors. Declare the actor (label, and optionally category/selector) or fix the reference.`,
24351
+ path: path47,
24352
+ message: `Actor "${actorId}" is referenced at ${z4.core.toDotPath(path47)} but not declared in process.actors. Declare the actor (label, and optionally category/selector) or fix the reference.`,
23780
24353
  params: { code: "UNDECLARED_ACTOR" }
23781
24354
  });
23782
24355
  }
23783
24356
  };
23784
- const checkSelector = (selector, path46) => {
24357
+ const checkSelector = (selector, path47) => {
23785
24358
  if (selector === void 0) return;
23786
24359
  if (!declaredSelectors.has(selector)) {
23787
24360
  ctx.addIssue({
23788
24361
  code: "custom",
23789
- path: path46,
23790
- message: `Selector "${selector}" is referenced at ${z4.core.toDotPath(path46)} but not declared in process.selectors. Declare the selector or fix the reference.`,
24362
+ path: path47,
24363
+ message: `Selector "${selector}" is referenced at ${z4.core.toDotPath(path47)} but not declared in process.selectors. Declare the selector or fix the reference.`,
23791
24364
  params: { code: "UNDECLARED_SELECTOR" }
23792
24365
  });
23793
24366
  }
@@ -23801,20 +24374,20 @@ var init_process_artifact = __esm({
23801
24374
  outcome: "DUPLICATE_OUTCOME_ID"
23802
24375
  };
23803
24376
  const idFirstSeenAt = /* @__PURE__ */ new Map();
23804
- const checkId = (id, kind, path46) => {
24377
+ const checkId = (id, kind, path47) => {
23805
24378
  const first = idFirstSeenAt.get(id);
23806
24379
  if (first) {
23807
24380
  const kindLabel = kind === first.kind ? kind : "process";
23808
24381
  ctx.addIssue({
23809
24382
  code: "custom",
23810
- path: path46,
23811
- message: `Duplicate ${kindLabel} id "${id}": ${kind} at ${z4.core.toDotPath(path46)} collides with ${first.kind} at ${z4.core.toDotPath(first.path)}.`,
24383
+ path: path47,
24384
+ message: `Duplicate ${kindLabel} id "${id}": ${kind} at ${z4.core.toDotPath(path47)} collides with ${first.kind} at ${z4.core.toDotPath(first.path)}.`,
23812
24385
  params: {
23813
24386
  code: kind === first.kind ? SAME_KIND_CODE[kind] : "DUPLICATE_PROCESS_ID"
23814
24387
  }
23815
24388
  });
23816
24389
  } else {
23817
- idFirstSeenAt.set(id, { kind, path: path46 });
24390
+ idFirstSeenAt.set(id, { kind, path: path47 });
23818
24391
  }
23819
24392
  };
23820
24393
  process2.stages.forEach((stage, stageIndex) => {
@@ -23861,13 +24434,13 @@ function lintProcess(artifact, inventory, predicateNames, options = {}) {
23861
24434
  const internalCommands = process2.internalCommands ?? [];
23862
24435
  const internalSet = new Set(internalCommands);
23863
24436
  const boundCommandPaths = /* @__PURE__ */ new Map();
23864
- const checkPredicate = (predicate, path46) => {
24437
+ const checkPredicate = (predicate, path47) => {
23865
24438
  if (!predicateSet.has(predicate)) {
23866
24439
  diagnostics.push({
23867
24440
  severity: "error",
23868
24441
  code: "UNKNOWN_PREDICATE",
23869
- message: `Predicate "${predicate}" referenced at ${path46} is not in the predicate registry.`,
23870
- path: path46
24442
+ message: `Predicate "${predicate}" referenced at ${path47} is not in the predicate registry.`,
24443
+ path: path47
23871
24444
  });
23872
24445
  }
23873
24446
  };
@@ -23927,19 +24500,19 @@ function lintProcess(artifact, inventory, predicateNames, options = {}) {
23927
24500
  process2.outcomes.forEach((outcome, outcomeIndex) => {
23928
24501
  const whenPath = `process.outcomes[${outcomeIndex}].when`;
23929
24502
  outcomeTriggers(outcome).forEach((trigger, triggerIndex) => {
23930
- const path46 = Array.isArray(outcome.when) ? `${whenPath}[${triggerIndex}]` : whenPath;
24503
+ const path47 = Array.isArray(outcome.when) ? `${whenPath}[${triggerIndex}]` : whenPath;
23931
24504
  if (trigger.kind === "predicate") {
23932
- checkPredicate(trigger.name, `${path46}.predicate`);
24505
+ checkPredicate(trigger.name, `${path47}.predicate`);
23933
24506
  } else if (trigger.kind === "command") {
23934
24507
  if (!boundCommandPaths.has(trigger.name)) {
23935
- boundCommandPaths.set(trigger.name, `${path46}.command`);
24508
+ boundCommandPaths.set(trigger.name, `${path47}.command`);
23936
24509
  }
23937
24510
  if (!commandNames.has(trigger.name)) {
23938
24511
  diagnostics.push({
23939
24512
  severity: "error",
23940
24513
  code: "BOUND_COMMAND_NOT_IN_INVENTORY",
23941
- message: `Command "${trigger.name}" triggering outcome "${outcome.id}" (${path46}.command) does not exist in the inventory.`,
23942
- path: `${path46}.command`
24514
+ message: `Command "${trigger.name}" triggering outcome "${outcome.id}" (${path47}.command) does not exist in the inventory.`,
24515
+ path: `${path47}.command`
23943
24516
  });
23944
24517
  }
23945
24518
  }
@@ -24051,10 +24624,10 @@ var init_src4 = __esm({
24051
24624
  });
24052
24625
 
24053
24626
  // libs/mesh-cli/src/commands/workflow.ts
24054
- import * as fs38 from "fs";
24055
- import * as path45 from "path";
24627
+ import * as fs39 from "fs";
24628
+ import * as path46 from "path";
24056
24629
  import { createRequire as createRequire2 } from "module";
24057
- import { execFileSync as execFileSync31 } from "child_process";
24630
+ import { execFileSync as execFileSync32 } from "child_process";
24058
24631
  function resolveExtractorPath() {
24059
24632
  try {
24060
24633
  const require2 = createRequire2(import.meta.url);
@@ -24068,7 +24641,7 @@ function runExtraction(targetPath, extractorPath, explicitProcessPath) {
24068
24641
  let explicitProcessArtifact;
24069
24642
  if (explicitProcessPath) {
24070
24643
  try {
24071
- explicitProcessArtifact = JSON.parse(fs38.readFileSync(explicitProcessPath, "utf-8"));
24644
+ explicitProcessArtifact = JSON.parse(fs39.readFileSync(explicitProcessPath, "utf-8"));
24072
24645
  } catch (err) {
24073
24646
  logError(
24074
24647
  `Could not read/parse --process ${explicitProcessPath}: ${err instanceof Error ? err.message : String(err)}`
@@ -24109,7 +24682,7 @@ for (const file of files) {
24109
24682
  process.stdout.write(JSON.stringify(results));
24110
24683
  `;
24111
24684
  try {
24112
- const result = execFileSync31("npx", ["tsx", "--eval", script], {
24685
+ const result = execFileSync32("npx", ["tsx", "--eval", script], {
24113
24686
  encoding: "utf-8",
24114
24687
  stdio: ["pipe", "pipe", "inherit"],
24115
24688
  maxBuffer: 10 * 1024 * 1024
@@ -24151,7 +24724,7 @@ for (const file of files) {
24151
24724
  process.stdout.write(JSON.stringify(results));
24152
24725
  `;
24153
24726
  try {
24154
- const result = execFileSync31("npx", ["tsx", "--eval", script], {
24727
+ const result = execFileSync32("npx", ["tsx", "--eval", script], {
24155
24728
  encoding: "utf-8",
24156
24729
  stdio: ["pipe", "pipe", "inherit"],
24157
24730
  maxBuffer: 10 * 1024 * 1024
@@ -24168,7 +24741,7 @@ function runLintExtraction(targetPath, extractorPath, explicitProcessPath) {
24168
24741
  let explicitProcessArtifact;
24169
24742
  if (explicitProcessPath) {
24170
24743
  try {
24171
- explicitProcessArtifact = JSON.parse(fs38.readFileSync(explicitProcessPath, "utf-8"));
24744
+ explicitProcessArtifact = JSON.parse(fs39.readFileSync(explicitProcessPath, "utf-8"));
24172
24745
  } catch (err) {
24173
24746
  logError(
24174
24747
  `Could not read/parse --process ${explicitProcessPath}: ${err instanceof Error ? err.message : String(err)}`
@@ -24206,7 +24779,7 @@ for (const file of files) {
24206
24779
  process.stdout.write(JSON.stringify(results));
24207
24780
  `;
24208
24781
  try {
24209
- const result = execFileSync31("npx", ["tsx", "--eval", script], {
24782
+ const result = execFileSync32("npx", ["tsx", "--eval", script], {
24210
24783
  encoding: "utf-8",
24211
24784
  stdio: ["pipe", "pipe", "inherit"],
24212
24785
  maxBuffer: 10 * 1024 * 1024
@@ -24276,16 +24849,16 @@ function registerWorkflowCommands(program2) {
24276
24849
  ).action(
24277
24850
  async (targetPath, opts) => {
24278
24851
  try {
24279
- const resolvedPath = path45.resolve(targetPath);
24280
- if (!fs38.existsSync(resolvedPath)) {
24852
+ const resolvedPath = path46.resolve(targetPath);
24853
+ if (!fs39.existsSync(resolvedPath)) {
24281
24854
  logError(`Path does not exist: ${resolvedPath}`);
24282
24855
  process.exitCode = 1;
24283
24856
  return;
24284
24857
  }
24285
24858
  let resolvedProcessPath;
24286
24859
  if (opts.process) {
24287
- resolvedProcessPath = path45.resolve(opts.process);
24288
- if (!fs38.existsSync(resolvedProcessPath)) {
24860
+ resolvedProcessPath = path46.resolve(opts.process);
24861
+ if (!fs39.existsSync(resolvedProcessPath)) {
24289
24862
  logError(`--process path does not exist: ${resolvedProcessPath}`);
24290
24863
  process.exitCode = 1;
24291
24864
  return;
@@ -24334,8 +24907,8 @@ function registerWorkflowCommands(program2) {
24334
24907
  "Extract the as-built command/query/activity inventory from Temporal workflow source\n\nThe inventory ({ workflowType, commands, queries, activities }) is the process-\nconformance lint's code-side input \u2014 it is never hand-edited. Supports single\nfiles or directories."
24335
24908
  ).action(async (targetPath) => {
24336
24909
  try {
24337
- const resolvedPath = path45.resolve(targetPath);
24338
- if (!fs38.existsSync(resolvedPath)) {
24910
+ const resolvedPath = path46.resolve(targetPath);
24911
+ if (!fs39.existsSync(resolvedPath)) {
24339
24912
  logError(`Path does not exist: ${resolvedPath}`);
24340
24913
  process.exitCode = 1;
24341
24914
  return;
@@ -24381,16 +24954,16 @@ function registerWorkflowCommands(program2) {
24381
24954
  "Comma-separated named-selector registry (enables UNKNOWN_SELECTOR checks)"
24382
24955
  ).action(async (targetPath, opts) => {
24383
24956
  try {
24384
- const resolvedPath = path45.resolve(targetPath);
24385
- if (!fs38.existsSync(resolvedPath)) {
24957
+ const resolvedPath = path46.resolve(targetPath);
24958
+ if (!fs39.existsSync(resolvedPath)) {
24386
24959
  logError(`Path does not exist: ${resolvedPath}`);
24387
24960
  process.exitCode = 1;
24388
24961
  return;
24389
24962
  }
24390
24963
  let resolvedProcessPath;
24391
24964
  if (opts.process) {
24392
- resolvedProcessPath = path45.resolve(opts.process);
24393
- if (!fs38.existsSync(resolvedProcessPath)) {
24965
+ resolvedProcessPath = path46.resolve(opts.process);
24966
+ if (!fs39.existsSync(resolvedProcessPath)) {
24394
24967
  logError(`--process path does not exist: ${resolvedProcessPath}`);
24395
24968
  process.exitCode = 1;
24396
24969
  return;