@mutmutco/cli 4.5.175 → 4.5.177

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 (2) hide show
  1. package/dist/main.cjs +39 -9
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -19193,10 +19193,10 @@ var rollout_plan_default = {
19193
19193
  note: "The v4.0.0 stamp happens at cut time (D6e #4463); until then the candidate is the origin/development head artifacts (built cli/dist + npm pack), identity proven by dist content hash (D6a)."
19194
19194
  },
19195
19195
  baseline: {
19196
- version: "4.5.175",
19197
- tag: "v4.5.175",
19198
- commit: "8efcf884c10f",
19199
- npm: "@mutmutco/cli@4.5.175"
19196
+ version: "4.5.177",
19197
+ tag: "v4.5.177",
19198
+ commit: "828c3b27cb77",
19199
+ npm: "@mutmutco/cli@4.5.177"
19200
19200
  },
19201
19201
  exitCriterion: "fleet-n-of-n",
19202
19202
  hubOnlyShortcut: "forbidden",
@@ -19213,14 +19213,14 @@ var rollout_plan_default = {
19213
19213
  repo: "mutmutco/mmi-hub",
19214
19214
  role: "canary",
19215
19215
  schedule: "train",
19216
- v3Target: "v4.5.175"
19216
+ v3Target: "v4.5.177"
19217
19217
  }
19218
19218
  ],
19219
19219
  rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
19220
19220
  rollback: {
19221
19221
  independent: true,
19222
- mechanism: "npm dist-tag latest -> 4.5.175 and redeploy the Hub Lambda from tag v4.5.175 (8efcf884c10f); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19223
- v3Target: "v4.5.175 (@mutmutco/cli@4.5.175, tag commit 8efcf884c10f \u2014 last known-good release carrying the repo-index v4-only contract)"
19222
+ mechanism: "npm dist-tag latest -> 4.5.177 and redeploy the Hub Lambda from tag v4.5.177 (828c3b27cb77); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19223
+ v3Target: "v4.5.177 (@mutmutco/cli@4.5.177, tag commit 828c3b27cb77 \u2014 last known-good release carrying the repo-index v4-only contract)"
19224
19224
  }
19225
19225
  },
19226
19226
  {
@@ -33381,7 +33381,20 @@ init_hub_auth();
33381
33381
  init_github_client();
33382
33382
 
33383
33383
  // src/project-set.ts
33384
- var UNSET_KEYS = ["projectAdmins", "installer", "oauth", "requiredRuntimeSecrets", "requiredBuildSecrets", "tenantTasks", "secrets", "edgeDomains", "requiredGcpApis", "publishRequired", "publishDir", "releaseChannel", "releaseLanguage", "ci", "requiredChecks", "requiredCheckBranches", "ciExemptReason", "gate", "seedCanary", "notifyOnDeploy", "vercelVersionEnv", "stageAllowlist", "suiteHold", "internalPeers", "previews"];
33384
+ function staticAssetsAreValid(value) {
33385
+ if (value === void 0 || value === null) return true;
33386
+ if (!Array.isArray(value) || value.length > 4) return false;
33387
+ const prefixes = /* @__PURE__ */ new Set();
33388
+ return value.every((entry) => {
33389
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
33390
+ const e = entry;
33391
+ if (Object.keys(e).some((k) => !["urlPrefix", "containerDir", "service"].includes(k))) return false;
33392
+ if (typeof e.urlPrefix !== "string" || !/^\/[A-Za-z0-9._/-]+\/$/.test(e.urlPrefix) || e.urlPrefix.includes("..") || e.urlPrefix.includes("//") || prefixes.has(e.urlPrefix)) return false;
33393
+ prefixes.add(e.urlPrefix);
33394
+ return typeof e.containerDir === "string" && /^\/[A-Za-z0-9._/-]+$/.test(e.containerDir) && !e.containerDir.includes("..") && !e.containerDir.includes("//") && (e.service === void 0 || typeof e.service === "string" && /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(e.service));
33395
+ });
33396
+ }
33397
+ var UNSET_KEYS = ["projectAdmins", "installer", "oauth", "requiredRuntimeSecrets", "requiredBuildSecrets", "tenantTasks", "secrets", "edgeDomains", "staticAssets", "requiredGcpApis", "publishRequired", "publishDir", "releaseChannel", "releaseLanguage", "ci", "requiredChecks", "requiredCheckBranches", "ciExemptReason", "gate", "seedCanary", "notifyOnDeploy", "vercelVersionEnv", "stageAllowlist", "suiteHold", "internalPeers", "previews"];
33385
33398
  var UNSET_KEY_SET = new Set(UNSET_KEYS);
33386
33399
  var RUNTIME_SECRET_STAGES = ["dev", "rc", "main"];
33387
33400
  var SECRET_CONSUMERS = ["runtime", "build", "lambda", "actions", "agent", "box"];
@@ -33928,6 +33941,7 @@ var SETTABLE_VAR_KEYS = [
33928
33941
  "tenantTasks",
33929
33942
  "internalPeers",
33930
33943
  "edgeDomains",
33944
+ "staticAssets",
33931
33945
  "statusFieldId",
33932
33946
  "statusOptions",
33933
33947
  "priorityFieldId",
@@ -33966,6 +33980,7 @@ var SETTABLE_VAR_HINTS = {
33966
33980
  tenantTasks: 'JSON map {name:{service,command[],stages[],timeoutSeconds?,artifact?:"required",output?:"file",secretOutput?:{path,vault:{repo,key},overwrite?}}} \u2014 merged per entry, at most 20 stored in total; retire ONE task with --unset-task NAME; use {artifact} in argv when required; a secretOutput is master-only',
33967
33981
  internalPeers: "JSON {owner/repo:[dev|rc|main]} \u2014 same-box suite peers via the box Caddy; clear with --unset internalPeers (#7886)",
33968
33982
  secrets: "JSON catalog map keyed by KEY {key,purpose,group,owner,stages[],consumers[],branchReadable?} \u2014 merged per entry; drop ONE entry with --unset-secret KEY; clear ALL with --unset secrets --confirm-clear-secrets; prefer --secrets-file",
33983
+ staticAssets: 'JSON array, e.g. [{"urlPrefix":"/assets/","containerDir":"/app/dist/assets"}] \u2014 immutable edge skew protection',
33969
33984
  edgeDomains: "JSON {dev,rc,main} domain map",
33970
33985
  statusOptions: "JSON name\u2192id map",
33971
33986
  priorityOptions: "JSON {Urgent,High,Medium,Low}\u2192id map",
@@ -34166,6 +34181,15 @@ function buildProjectSetPatch(input) {
34166
34181
  patch[key] = parseRequiredChecksVar(raw);
34167
34182
  } else if (key === "requiredCheckBranches") {
34168
34183
  patch[key] = parseRequiredCheckBranchesVar(raw);
34184
+ } else if (key === "staticAssets") {
34185
+ let value2;
34186
+ try {
34187
+ value2 = JSON.parse(raw);
34188
+ } catch {
34189
+ throw new Error("staticAssets must be JSON");
34190
+ }
34191
+ if (value2 === null || !staticAssetsAreValid(value2)) throw new Error("staticAssets must be an array of up to 4 {urlPrefix, containerDir, service?} safe absolute paths with unique prefixes");
34192
+ patch[key] = value2;
34169
34193
  } else if (key === "notifyOnDeploy") {
34170
34194
  patch[key] = parseNotifyOnDeployVar(raw);
34171
34195
  } else if (key === "vercelVersionEnv") {
@@ -38506,10 +38530,11 @@ function bundleTag(url) {
38506
38530
  }
38507
38531
  }
38508
38532
  async function stageStatus(member, stage, deps) {
38509
- const branch = stage === "dev" ? "development" : stage;
38510
38533
  if (member.repo === SUITE_REPO && stage === "rc") return { stage, head: "n/a", served: "n/a", source: "n/a", lag: null };
38511
38534
  let head;
38512
38535
  try {
38536
+ const track = stage === "main" ? await deps.releaseTrack?.(member.repo) : void 0;
38537
+ const branch = stage === "dev" || stage === "main" && track === "single" ? "development" : stage;
38513
38538
  const observed = await deps.head(member.repo, branch);
38514
38539
  if (observed === null) return { stage, head: "n/a", served: "n/a", source: "n/a", lag: null };
38515
38540
  head = observed || "unknown";
@@ -50939,6 +50964,11 @@ function suiteStatusDeps(github, registry2) {
50939
50964
  if (!file?.content) throw new Error(`MM-Work seed/modules.json at ${ref} is unavailable`);
50940
50965
  return JSON.parse(decodeGitHubContents(file.content));
50941
50966
  },
50967
+ releaseTrack: async (repo) => {
50968
+ const meta = await fetchProjectBySlugChecked(repo.split("/")[1].toLowerCase(), registry2);
50969
+ if (!meta.ok || !meta.project) throw new Error(`${repo} META unreadable${meta.ok ? "" : `: ${meta.error}`}`);
50970
+ return resolveReleaseTrack(meta.project, void 0, repo);
50971
+ },
50942
50972
  deploy: async (repo, stage) => {
50943
50973
  const slug = repo.split("/")[1].toLowerCase();
50944
50974
  const facts = await fetchDeployFactsBySlug(slug, registry2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.175",
3
+ "version": "4.5.177",
4
4
  "description": "MMI Future CLI — the org dev toolbox and shared cross-IDE engine for every registry-declared MMI coding surface.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",