canopycms-cdk 0.0.59 → 0.0.61-int.74

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.
@@ -814,10 +814,10 @@ var require_src2 = __commonJS({
814
814
  var fs_1 = __require("fs");
815
815
  var debug_1 = __importDefault2(require_src());
816
816
  var log6 = debug_1.default("@kwsites/file-exists");
817
- function check(path12, isFile, isDirectory) {
818
- log6(`checking %s`, path12);
817
+ function check(path13, isFile, isDirectory) {
818
+ log6(`checking %s`, path13);
819
819
  try {
820
- const stat = fs_1.statSync(path12);
820
+ const stat = fs_1.statSync(path13);
821
821
  if (stat.isFile() && isFile) {
822
822
  log6(`[OK] path represents a file`);
823
823
  return true;
@@ -837,8 +837,8 @@ var require_src2 = __commonJS({
837
837
  throw e5;
838
838
  }
839
839
  }
840
- function exists2(path12, type = exports.READABLE) {
841
- return check(path12, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
840
+ function exists2(path13, type = exports.READABLE) {
841
+ return check(path13, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
842
842
  }
843
843
  exports.exists = exists2;
844
844
  exports.FILE = 1;
@@ -953,14 +953,14 @@ var require_polyfills = __commonJS({
953
953
  fs9.fstatSync = statFixSync(fs9.fstatSync);
954
954
  fs9.lstatSync = statFixSync(fs9.lstatSync);
955
955
  if (fs9.chmod && !fs9.lchmod) {
956
- fs9.lchmod = function(path12, mode, cb) {
956
+ fs9.lchmod = function(path13, mode, cb) {
957
957
  if (cb) process.nextTick(cb);
958
958
  };
959
959
  fs9.lchmodSync = function() {
960
960
  };
961
961
  }
962
962
  if (fs9.chown && !fs9.lchown) {
963
- fs9.lchown = function(path12, uid, gid, cb) {
963
+ fs9.lchown = function(path13, uid, gid, cb) {
964
964
  if (cb) process.nextTick(cb);
965
965
  };
966
966
  fs9.lchownSync = function() {
@@ -1027,9 +1027,9 @@ var require_polyfills = __commonJS({
1027
1027
  };
1028
1028
  })(fs9.readSync);
1029
1029
  function patchLchmod(fs10) {
1030
- fs10.lchmod = function(path12, mode, callback) {
1030
+ fs10.lchmod = function(path13, mode, callback) {
1031
1031
  fs10.open(
1032
- path12,
1032
+ path13,
1033
1033
  constants2.O_WRONLY | constants2.O_SYMLINK,
1034
1034
  mode,
1035
1035
  function(err, fd) {
@@ -1045,8 +1045,8 @@ var require_polyfills = __commonJS({
1045
1045
  }
1046
1046
  );
1047
1047
  };
1048
- fs10.lchmodSync = function(path12, mode) {
1049
- var fd = fs10.openSync(path12, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
1048
+ fs10.lchmodSync = function(path13, mode) {
1049
+ var fd = fs10.openSync(path13, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
1050
1050
  var threw = true;
1051
1051
  var ret;
1052
1052
  try {
@@ -1067,8 +1067,8 @@ var require_polyfills = __commonJS({
1067
1067
  }
1068
1068
  function patchLutimes(fs10) {
1069
1069
  if (constants2.hasOwnProperty("O_SYMLINK") && fs10.futimes) {
1070
- fs10.lutimes = function(path12, at, mt, cb) {
1071
- fs10.open(path12, constants2.O_SYMLINK, function(er, fd) {
1070
+ fs10.lutimes = function(path13, at, mt, cb) {
1071
+ fs10.open(path13, constants2.O_SYMLINK, function(er, fd) {
1072
1072
  if (er) {
1073
1073
  if (cb) cb(er);
1074
1074
  return;
@@ -1080,8 +1080,8 @@ var require_polyfills = __commonJS({
1080
1080
  });
1081
1081
  });
1082
1082
  };
1083
- fs10.lutimesSync = function(path12, at, mt) {
1084
- var fd = fs10.openSync(path12, constants2.O_SYMLINK);
1083
+ fs10.lutimesSync = function(path13, at, mt) {
1084
+ var fd = fs10.openSync(path13, constants2.O_SYMLINK);
1085
1085
  var ret;
1086
1086
  var threw = true;
1087
1087
  try {
@@ -1199,11 +1199,11 @@ var require_legacy_streams = __commonJS({
1199
1199
  ReadStream,
1200
1200
  WriteStream
1201
1201
  };
1202
- function ReadStream(path12, options) {
1203
- if (!(this instanceof ReadStream)) return new ReadStream(path12, options);
1202
+ function ReadStream(path13, options) {
1203
+ if (!(this instanceof ReadStream)) return new ReadStream(path13, options);
1204
1204
  Stream.call(this);
1205
1205
  var self2 = this;
1206
- this.path = path12;
1206
+ this.path = path13;
1207
1207
  this.fd = null;
1208
1208
  this.readable = true;
1209
1209
  this.paused = false;
@@ -1248,10 +1248,10 @@ var require_legacy_streams = __commonJS({
1248
1248
  self2._read();
1249
1249
  });
1250
1250
  }
1251
- function WriteStream(path12, options) {
1252
- if (!(this instanceof WriteStream)) return new WriteStream(path12, options);
1251
+ function WriteStream(path13, options) {
1252
+ if (!(this instanceof WriteStream)) return new WriteStream(path13, options);
1253
1253
  Stream.call(this);
1254
- this.path = path12;
1254
+ this.path = path13;
1255
1255
  this.fd = null;
1256
1256
  this.writable = true;
1257
1257
  this.flags = "w";
@@ -1394,14 +1394,14 @@ var require_graceful_fs = __commonJS({
1394
1394
  fs10.createWriteStream = createWriteStream;
1395
1395
  var fs$readFile = fs10.readFile;
1396
1396
  fs10.readFile = readFile;
1397
- function readFile(path12, options, cb) {
1397
+ function readFile(path13, options, cb) {
1398
1398
  if (typeof options === "function")
1399
1399
  cb = options, options = null;
1400
- return go$readFile(path12, options, cb);
1401
- function go$readFile(path13, options2, cb2, startTime) {
1402
- return fs$readFile(path13, options2, function(err) {
1400
+ return go$readFile(path13, options, cb);
1401
+ function go$readFile(path14, options2, cb2, startTime) {
1402
+ return fs$readFile(path14, options2, function(err) {
1403
1403
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1404
- enqueue([go$readFile, [path13, options2, cb2], err, startTime || Date.now(), Date.now()]);
1404
+ enqueue([go$readFile, [path14, options2, cb2], err, startTime || Date.now(), Date.now()]);
1405
1405
  else {
1406
1406
  if (typeof cb2 === "function")
1407
1407
  cb2.apply(this, arguments);
@@ -1411,14 +1411,14 @@ var require_graceful_fs = __commonJS({
1411
1411
  }
1412
1412
  var fs$writeFile = fs10.writeFile;
1413
1413
  fs10.writeFile = writeFile;
1414
- function writeFile(path12, data2, options, cb) {
1414
+ function writeFile(path13, data2, options, cb) {
1415
1415
  if (typeof options === "function")
1416
1416
  cb = options, options = null;
1417
- return go$writeFile(path12, data2, options, cb);
1418
- function go$writeFile(path13, data3, options2, cb2, startTime) {
1419
- return fs$writeFile(path13, data3, options2, function(err) {
1417
+ return go$writeFile(path13, data2, options, cb);
1418
+ function go$writeFile(path14, data3, options2, cb2, startTime) {
1419
+ return fs$writeFile(path14, data3, options2, function(err) {
1420
1420
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1421
- enqueue([go$writeFile, [path13, data3, options2, cb2], err, startTime || Date.now(), Date.now()]);
1421
+ enqueue([go$writeFile, [path14, data3, options2, cb2], err, startTime || Date.now(), Date.now()]);
1422
1422
  else {
1423
1423
  if (typeof cb2 === "function")
1424
1424
  cb2.apply(this, arguments);
@@ -1429,14 +1429,14 @@ var require_graceful_fs = __commonJS({
1429
1429
  var fs$appendFile = fs10.appendFile;
1430
1430
  if (fs$appendFile)
1431
1431
  fs10.appendFile = appendFile;
1432
- function appendFile(path12, data2, options, cb) {
1432
+ function appendFile(path13, data2, options, cb) {
1433
1433
  if (typeof options === "function")
1434
1434
  cb = options, options = null;
1435
- return go$appendFile(path12, data2, options, cb);
1436
- function go$appendFile(path13, data3, options2, cb2, startTime) {
1437
- return fs$appendFile(path13, data3, options2, function(err) {
1435
+ return go$appendFile(path13, data2, options, cb);
1436
+ function go$appendFile(path14, data3, options2, cb2, startTime) {
1437
+ return fs$appendFile(path14, data3, options2, function(err) {
1438
1438
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1439
- enqueue([go$appendFile, [path13, data3, options2, cb2], err, startTime || Date.now(), Date.now()]);
1439
+ enqueue([go$appendFile, [path14, data3, options2, cb2], err, startTime || Date.now(), Date.now()]);
1440
1440
  else {
1441
1441
  if (typeof cb2 === "function")
1442
1442
  cb2.apply(this, arguments);
@@ -1467,31 +1467,31 @@ var require_graceful_fs = __commonJS({
1467
1467
  var fs$readdir = fs10.readdir;
1468
1468
  fs10.readdir = readdir;
1469
1469
  var noReaddirOptionVersions = /^v[0-5]\./;
1470
- function readdir(path12, options, cb) {
1470
+ function readdir(path13, options, cb) {
1471
1471
  if (typeof options === "function")
1472
1472
  cb = options, options = null;
1473
- var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path13, options2, cb2, startTime) {
1474
- return fs$readdir(path13, fs$readdirCallback(
1475
- path13,
1473
+ var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path14, options2, cb2, startTime) {
1474
+ return fs$readdir(path14, fs$readdirCallback(
1475
+ path14,
1476
1476
  options2,
1477
1477
  cb2,
1478
1478
  startTime
1479
1479
  ));
1480
- } : function go$readdir2(path13, options2, cb2, startTime) {
1481
- return fs$readdir(path13, options2, fs$readdirCallback(
1482
- path13,
1480
+ } : function go$readdir2(path14, options2, cb2, startTime) {
1481
+ return fs$readdir(path14, options2, fs$readdirCallback(
1482
+ path14,
1483
1483
  options2,
1484
1484
  cb2,
1485
1485
  startTime
1486
1486
  ));
1487
1487
  };
1488
- return go$readdir(path12, options, cb);
1489
- function fs$readdirCallback(path13, options2, cb2, startTime) {
1488
+ return go$readdir(path13, options, cb);
1489
+ function fs$readdirCallback(path14, options2, cb2, startTime) {
1490
1490
  return function(err, files) {
1491
1491
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1492
1492
  enqueue([
1493
1493
  go$readdir,
1494
- [path13, options2, cb2],
1494
+ [path14, options2, cb2],
1495
1495
  err,
1496
1496
  startTime || Date.now(),
1497
1497
  Date.now()
@@ -1562,7 +1562,7 @@ var require_graceful_fs = __commonJS({
1562
1562
  enumerable: true,
1563
1563
  configurable: true
1564
1564
  });
1565
- function ReadStream(path12, options) {
1565
+ function ReadStream(path13, options) {
1566
1566
  if (this instanceof ReadStream)
1567
1567
  return fs$ReadStream.apply(this, arguments), this;
1568
1568
  else
@@ -1582,7 +1582,7 @@ var require_graceful_fs = __commonJS({
1582
1582
  }
1583
1583
  });
1584
1584
  }
1585
- function WriteStream(path12, options) {
1585
+ function WriteStream(path13, options) {
1586
1586
  if (this instanceof WriteStream)
1587
1587
  return fs$WriteStream.apply(this, arguments), this;
1588
1588
  else
@@ -1600,22 +1600,22 @@ var require_graceful_fs = __commonJS({
1600
1600
  }
1601
1601
  });
1602
1602
  }
1603
- function createReadStream(path12, options) {
1604
- return new fs10.ReadStream(path12, options);
1603
+ function createReadStream(path13, options) {
1604
+ return new fs10.ReadStream(path13, options);
1605
1605
  }
1606
- function createWriteStream(path12, options) {
1607
- return new fs10.WriteStream(path12, options);
1606
+ function createWriteStream(path13, options) {
1607
+ return new fs10.WriteStream(path13, options);
1608
1608
  }
1609
1609
  var fs$open = fs10.open;
1610
1610
  fs10.open = open;
1611
- function open(path12, flags, mode, cb) {
1611
+ function open(path13, flags, mode, cb) {
1612
1612
  if (typeof mode === "function")
1613
1613
  cb = mode, mode = null;
1614
- return go$open(path12, flags, mode, cb);
1615
- function go$open(path13, flags2, mode2, cb2, startTime) {
1616
- return fs$open(path13, flags2, mode2, function(err, fd) {
1614
+ return go$open(path13, flags, mode, cb);
1615
+ function go$open(path14, flags2, mode2, cb2, startTime) {
1616
+ return fs$open(path14, flags2, mode2, function(err, fd) {
1617
1617
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1618
- enqueue([go$open, [path13, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
1618
+ enqueue([go$open, [path14, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
1619
1619
  else {
1620
1620
  if (typeof cb2 === "function")
1621
1621
  cb2.apply(this, arguments);
@@ -2144,7 +2144,7 @@ var require_mtime_precision = __commonJS({
2144
2144
  var require_lockfile = __commonJS({
2145
2145
  "../../node_modules/.pnpm/proper-lockfile@4.1.2/node_modules/proper-lockfile/lib/lockfile.js"(exports, module) {
2146
2146
  "use strict";
2147
- var path12 = __require("path");
2147
+ var path13 = __require("path");
2148
2148
  var fs9 = require_graceful_fs();
2149
2149
  var retry2 = require_retry2();
2150
2150
  var onExit = require_signal_exit();
@@ -2155,7 +2155,7 @@ var require_lockfile = __commonJS({
2155
2155
  }
2156
2156
  function resolveCanonicalPath(file, options, callback) {
2157
2157
  if (!options.realpath) {
2158
- return callback(null, path12.resolve(file));
2158
+ return callback(null, path13.resolve(file));
2159
2159
  }
2160
2160
  options.fs.realpath(file, callback);
2161
2161
  }
@@ -3785,15 +3785,15 @@ var require_dist_node9 = __commonJS({
3785
3785
  octokit.log.debug("request", options);
3786
3786
  const start = Date.now();
3787
3787
  const requestOptions = octokit.request.endpoint.parse(options);
3788
- const path12 = requestOptions.url.replace(options.baseUrl, "");
3788
+ const path13 = requestOptions.url.replace(options.baseUrl, "");
3789
3789
  return request(options).then((response) => {
3790
3790
  octokit.log.info(
3791
- `${requestOptions.method} ${path12} - ${response.status} in ${Date.now() - start}ms`
3791
+ `${requestOptions.method} ${path13} - ${response.status} in ${Date.now() - start}ms`
3792
3792
  );
3793
3793
  return response;
3794
3794
  }).catch((error2) => {
3795
3795
  octokit.log.info(
3796
- `${requestOptions.method} ${path12} - ${error2.status} in ${Date.now() - start}ms`
3796
+ `${requestOptions.method} ${path13} - ${error2.status} in ${Date.now() - start}ms`
3797
3797
  );
3798
3798
  throw error2;
3799
3799
  });
@@ -7887,7 +7887,7 @@ var require_dist_node13 = __commonJS({
7887
7887
  ];
7888
7888
  function routeMatcher(paths) {
7889
7889
  const regexes = paths.map(
7890
- (path12) => path12.split("/").map((c7) => c7.startsWith("{") ? "(?:.+?)" : c7).join("/")
7890
+ (path13) => path13.split("/").map((c7) => c7.startsWith("{") ? "(?:.+?)" : c7).join("/")
7891
7891
  );
7892
7892
  const regex2 = `^(?:${regexes.map((r6) => `(?:${r6})`).join("|")})[^/]*$`;
7893
7893
  return new RegExp(regex2, "i");
@@ -9080,9 +9080,9 @@ var init_createPaginator = __esm({
9080
9080
  command = withCommand(command) ?? command;
9081
9081
  return await client.send(command, ...args);
9082
9082
  };
9083
- get = (fromObject, path12) => {
9083
+ get = (fromObject, path13) => {
9084
9084
  let cursor2 = fromObject;
9085
- const pathComponents = path12.split(".");
9085
+ const pathComponents = path13.split(".");
9086
9086
  for (const step of pathComponents) {
9087
9087
  if (!cursor2 || typeof cursor2 !== "object") {
9088
9088
  return void 0;
@@ -10100,12 +10100,12 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
10100
10100
  const password = request.password ?? "";
10101
10101
  auth = `${username}:${password}`;
10102
10102
  }
10103
- let path12 = request.path;
10103
+ let path13 = request.path;
10104
10104
  if (queryString) {
10105
- path12 += `?${queryString}`;
10105
+ path13 += `?${queryString}`;
10106
10106
  }
10107
10107
  if (request.fragment) {
10108
- path12 += `#${request.fragment}`;
10108
+ path13 += `#${request.fragment}`;
10109
10109
  }
10110
10110
  let hostname = request.hostname ?? "";
10111
10111
  if (hostname[0] === "[" && hostname.endsWith("]")) {
@@ -10117,7 +10117,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
10117
10117
  headers: request.headers,
10118
10118
  host: hostname,
10119
10119
  method: request.method,
10120
- path: path12,
10120
+ path: path13,
10121
10121
  port: request.port,
10122
10122
  agent,
10123
10123
  auth
@@ -10400,16 +10400,16 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
10400
10400
  reject(err);
10401
10401
  };
10402
10402
  const queryString = querystringBuilder.buildQueryString(query || {});
10403
- let path12 = request.path;
10403
+ let path13 = request.path;
10404
10404
  if (queryString) {
10405
- path12 += `?${queryString}`;
10405
+ path13 += `?${queryString}`;
10406
10406
  }
10407
10407
  if (request.fragment) {
10408
- path12 += `#${request.fragment}`;
10408
+ path13 += `#${request.fragment}`;
10409
10409
  }
10410
10410
  const req = session.request({
10411
10411
  ...request.headers,
10412
- [http2.constants.HTTP2_HEADER_PATH]: path12,
10412
+ [http2.constants.HTTP2_HEADER_PATH]: path13,
10413
10413
  [http2.constants.HTTP2_HEADER_METHOD]: method
10414
10414
  });
10415
10415
  session.ref();
@@ -10596,13 +10596,13 @@ var require_dist_cjs14 = __commonJS({
10596
10596
  const abortError = buildAbortError(abortSignal);
10597
10597
  return Promise.reject(abortError);
10598
10598
  }
10599
- let path12 = request.path;
10599
+ let path13 = request.path;
10600
10600
  const queryString = querystringBuilder.buildQueryString(request.query || {});
10601
10601
  if (queryString) {
10602
- path12 += `?${queryString}`;
10602
+ path13 += `?${queryString}`;
10603
10603
  }
10604
10604
  if (request.fragment) {
10605
- path12 += `#${request.fragment}`;
10605
+ path13 += `#${request.fragment}`;
10606
10606
  }
10607
10607
  let auth = "";
10608
10608
  if (request.username != null || request.password != null) {
@@ -10611,7 +10611,7 @@ var require_dist_cjs14 = __commonJS({
10611
10611
  auth = `${username}:${password}@`;
10612
10612
  }
10613
10613
  const { port, method } = request;
10614
- const url = `${request.protocol}//${auth}${request.hostname}${port ? `:${port}` : ""}${path12}`;
10614
+ const url = `${request.protocol}//${auth}${request.hostname}${port ? `:${port}` : ""}${path13}`;
10615
10615
  const body = method === "GET" || method === "HEAD" ? void 0 : request.body;
10616
10616
  const requestOptions = {
10617
10617
  body,
@@ -12843,13 +12843,13 @@ function __disposeResources(env) {
12843
12843
  }
12844
12844
  return next();
12845
12845
  }
12846
- function __rewriteRelativeImportExtension(path12, preserveJsx) {
12847
- if (typeof path12 === "string" && /^\.\.?\//.test(path12)) {
12848
- return path12.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m5, tsx, d5, ext, cm) {
12846
+ function __rewriteRelativeImportExtension(path13, preserveJsx) {
12847
+ if (typeof path13 === "string" && /^\.\.?\//.test(path13)) {
12848
+ return path13.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m5, tsx, d5, ext, cm) {
12849
12849
  return tsx ? preserveJsx ? ".jsx" : ".js" : d5 && (!ext || !cm) ? m5 : d5 + ext + "." + cm.toLowerCase() + "js";
12850
12850
  });
12851
12851
  }
12852
- return path12;
12852
+ return path13;
12853
12853
  }
12854
12854
  var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
12855
12855
  var init_tslib_es6 = __esm({
@@ -13747,11 +13747,11 @@ var init_HttpBindingProtocol = __esm({
13747
13747
  const opTraits = translateTraits(operationSchema.traits);
13748
13748
  if (opTraits.http) {
13749
13749
  request.method = opTraits.http[0];
13750
- const [path12, search] = opTraits.http[1].split("?");
13750
+ const [path13, search] = opTraits.http[1].split("?");
13751
13751
  if (request.path == "/") {
13752
- request.path = path12;
13752
+ request.path = path13;
13753
13753
  } else {
13754
- request.path += path12;
13754
+ request.path += path13;
13755
13755
  }
13756
13756
  const traitSearchParams = new URLSearchParams(search ?? "");
13757
13757
  Object.assign(query, Object.fromEntries(traitSearchParams));
@@ -14154,8 +14154,8 @@ var init_requestBuilder = __esm({
14154
14154
  return this;
14155
14155
  }
14156
14156
  p(memberName, labelValueProvider, uriLabel, isGreedyLabel) {
14157
- this.resolvePathStack.push((path12) => {
14158
- this.path = resolvedPath(path12, this.input, memberName, labelValueProvider, uriLabel, isGreedyLabel);
14157
+ this.resolvePathStack.push((path13) => {
14158
+ this.path = resolvedPath(path13, this.input, memberName, labelValueProvider, uriLabel, isGreedyLabel);
14159
14159
  });
14160
14160
  return this;
14161
14161
  }
@@ -14805,18 +14805,18 @@ var require_dist_cjs20 = __commonJS({
14805
14805
  }
14806
14806
  };
14807
14807
  var booleanEquals = (value1, value2) => value1 === value2;
14808
- var getAttrPathList = (path12) => {
14809
- const parts = path12.split(".");
14808
+ var getAttrPathList = (path13) => {
14809
+ const parts = path13.split(".");
14810
14810
  const pathList = [];
14811
14811
  for (const part of parts) {
14812
14812
  const squareBracketIndex = part.indexOf("[");
14813
14813
  if (squareBracketIndex !== -1) {
14814
14814
  if (part.indexOf("]") !== part.length - 1) {
14815
- throw new EndpointError(`Path: '${path12}' does not end with ']'`);
14815
+ throw new EndpointError(`Path: '${path13}' does not end with ']'`);
14816
14816
  }
14817
14817
  const arrayIndex = part.slice(squareBracketIndex + 1, -1);
14818
14818
  if (Number.isNaN(parseInt(arrayIndex))) {
14819
- throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path12}'`);
14819
+ throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path13}'`);
14820
14820
  }
14821
14821
  if (squareBracketIndex !== 0) {
14822
14822
  pathList.push(part.slice(0, squareBracketIndex));
@@ -14828,9 +14828,9 @@ var require_dist_cjs20 = __commonJS({
14828
14828
  }
14829
14829
  return pathList;
14830
14830
  };
14831
- var getAttr = (value, path12) => getAttrPathList(path12).reduce((acc, index) => {
14831
+ var getAttr = (value, path13) => getAttrPathList(path13).reduce((acc, index) => {
14832
14832
  if (typeof acc !== "object") {
14833
- throw new EndpointError(`Index '${index}' in '${path12}' not found in '${JSON.stringify(value)}'`);
14833
+ throw new EndpointError(`Index '${index}' in '${path13}' not found in '${JSON.stringify(value)}'`);
14834
14834
  } else if (Array.isArray(acc)) {
14835
14835
  return acc[parseInt(index)];
14836
14836
  }
@@ -14849,8 +14849,8 @@ var require_dist_cjs20 = __commonJS({
14849
14849
  return value;
14850
14850
  }
14851
14851
  if (typeof value === "object" && "hostname" in value) {
14852
- const { hostname: hostname2, port, protocol: protocol2 = "", path: path12 = "", query = {} } = value;
14853
- const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${path12}`);
14852
+ const { hostname: hostname2, port, protocol: protocol2 = "", path: path13 = "", query = {} } = value;
14853
+ const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${path13}`);
14854
14854
  url.search = Object.entries(query).map(([k6, v5]) => `${k6}=${v5}`).join("&");
14855
14855
  return url;
14856
14856
  }
@@ -16295,10 +16295,10 @@ ${longDate}
16295
16295
  ${credentialScope}
16296
16296
  ${utilHexEncoding.toHex(hashedRequest)}`;
16297
16297
  }
16298
- getCanonicalPath({ path: path12 }) {
16298
+ getCanonicalPath({ path: path13 }) {
16299
16299
  if (this.uriEscapePath) {
16300
16300
  const normalizedPathSegments = [];
16301
- for (const pathSegment of path12.split("/")) {
16301
+ for (const pathSegment of path13.split("/")) {
16302
16302
  if (pathSegment?.length === 0)
16303
16303
  continue;
16304
16304
  if (pathSegment === ".")
@@ -16309,11 +16309,11 @@ ${utilHexEncoding.toHex(hashedRequest)}`;
16309
16309
  normalizedPathSegments.push(pathSegment);
16310
16310
  }
16311
16311
  }
16312
- const normalizedPath = `${path12?.startsWith("/") ? "/" : ""}${normalizedPathSegments.join("/")}${normalizedPathSegments.length > 0 && path12?.endsWith("/") ? "/" : ""}`;
16312
+ const normalizedPath = `${path13?.startsWith("/") ? "/" : ""}${normalizedPathSegments.join("/")}${normalizedPathSegments.length > 0 && path13?.endsWith("/") ? "/" : ""}`;
16313
16313
  const doubleEncoded = utilUriEscape.escapeUri(normalizedPath);
16314
16314
  return doubleEncoded.replace(/%2F/g, "/");
16315
16315
  }
16316
- return path12;
16316
+ return path13;
16317
16317
  }
16318
16318
  validateResolvedCredentials(credentials) {
16319
16319
  if (typeof credentials !== "object" || typeof credentials.accessKeyId !== "string" || typeof credentials.secretAccessKey !== "string") {
@@ -17617,11 +17617,11 @@ var init_SmithyRpcV2CborProtocol = __esm({
17617
17617
  }
17618
17618
  }
17619
17619
  const { service, operation: operation2 } = (0, import_util_middleware5.getSmithyContext)(context);
17620
- const path12 = `/service/${service}/operation/${operation2}`;
17620
+ const path13 = `/service/${service}/operation/${operation2}`;
17621
17621
  if (request.path.endsWith("/")) {
17622
- request.path += path12.slice(1);
17622
+ request.path += path13.slice(1);
17623
17623
  } else {
17624
- request.path += path12;
17624
+ request.path += path13;
17625
17625
  }
17626
17626
  return request;
17627
17627
  }
@@ -23266,14 +23266,14 @@ var require_readFile = __commonJS({
23266
23266
  var promises_1 = __require("node:fs/promises");
23267
23267
  exports.filePromises = {};
23268
23268
  exports.fileIntercept = {};
23269
- var readFile = (path12, options) => {
23270
- if (exports.fileIntercept[path12] !== void 0) {
23271
- return exports.fileIntercept[path12];
23269
+ var readFile = (path13, options) => {
23270
+ if (exports.fileIntercept[path13] !== void 0) {
23271
+ return exports.fileIntercept[path13];
23272
23272
  }
23273
- if (!exports.filePromises[path12] || options?.ignoreCache) {
23274
- exports.filePromises[path12] = (0, promises_1.readFile)(path12, "utf8");
23273
+ if (!exports.filePromises[path13] || options?.ignoreCache) {
23274
+ exports.filePromises[path13] = (0, promises_1.readFile)(path13, "utf8");
23275
23275
  }
23276
- return exports.filePromises[path12];
23276
+ return exports.filePromises[path13];
23277
23277
  };
23278
23278
  exports.readFile = readFile;
23279
23279
  }
@@ -23286,7 +23286,7 @@ var require_dist_cjs33 = __commonJS({
23286
23286
  var getHomeDir = require_getHomeDir();
23287
23287
  var getSSOTokenFilepath = require_getSSOTokenFilepath();
23288
23288
  var getSSOTokenFromFile = require_getSSOTokenFromFile();
23289
- var path12 = __require("path");
23289
+ var path13 = __require("path");
23290
23290
  var types = require_dist_cjs();
23291
23291
  var readFile = require_readFile();
23292
23292
  var ENV_PROFILE = "AWS_PROFILE";
@@ -23308,9 +23308,9 @@ var require_dist_cjs33 = __commonJS({
23308
23308
  ...data2.default && { default: data2.default }
23309
23309
  });
23310
23310
  var ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
23311
- var getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || path12.join(getHomeDir.getHomeDir(), ".aws", "config");
23311
+ var getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || path13.join(getHomeDir.getHomeDir(), ".aws", "config");
23312
23312
  var ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
23313
- var getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || path12.join(getHomeDir.getHomeDir(), ".aws", "credentials");
23313
+ var getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || path13.join(getHomeDir.getHomeDir(), ".aws", "credentials");
23314
23314
  var prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/;
23315
23315
  var profileNameBlockList = ["__proto__", "profile __proto__"];
23316
23316
  var parseIni = (iniData) => {
@@ -23365,11 +23365,11 @@ var require_dist_cjs33 = __commonJS({
23365
23365
  const relativeHomeDirPrefix = "~/";
23366
23366
  let resolvedFilepath = filepath;
23367
23367
  if (filepath.startsWith(relativeHomeDirPrefix)) {
23368
- resolvedFilepath = path12.join(homeDir, filepath.slice(2));
23368
+ resolvedFilepath = path13.join(homeDir, filepath.slice(2));
23369
23369
  }
23370
23370
  let resolvedConfigFilepath = configFilepath;
23371
23371
  if (configFilepath.startsWith(relativeHomeDirPrefix)) {
23372
- resolvedConfigFilepath = path12.join(homeDir, configFilepath.slice(2));
23372
+ resolvedConfigFilepath = path13.join(homeDir, configFilepath.slice(2));
23373
23373
  }
23374
23374
  const parsedFiles = await Promise.all([
23375
23375
  readFile.readFile(resolvedConfigFilepath, {
@@ -23408,8 +23408,8 @@ var require_dist_cjs33 = __commonJS({
23408
23408
  getFileRecord() {
23409
23409
  return readFile.fileIntercept;
23410
23410
  },
23411
- interceptFile(path13, contents) {
23412
- readFile.fileIntercept[path13] = Promise.resolve(contents);
23411
+ interceptFile(path14, contents) {
23412
+ readFile.fileIntercept[path14] = Promise.resolve(contents);
23413
23413
  },
23414
23414
  getTokenRecord() {
23415
23415
  return getSSOTokenFromFile.tokenIntercept;
@@ -23734,8 +23734,8 @@ var require_dist_cjs36 = __commonJS({
23734
23734
  return endpoint.url.href;
23735
23735
  }
23736
23736
  if ("hostname" in endpoint) {
23737
- const { protocol, hostname, port, path: path12 } = endpoint;
23738
- return `${protocol}//${hostname}${port ? ":" + port : ""}${path12}`;
23737
+ const { protocol, hostname, port, path: path13 } = endpoint;
23738
+ return `${protocol}//${hostname}${port ? ":" + port : ""}${path13}`;
23739
23739
  }
23740
23740
  }
23741
23741
  return endpoint;
@@ -31933,7 +31933,7 @@ var require_dist_cjs53 = __commonJS({
31933
31933
 
31934
31934
  // ../canopycms/src/worker/cms-worker.ts
31935
31935
  import fs7 from "node:fs/promises";
31936
- import path9 from "node:path";
31936
+ import path10 from "node:path";
31937
31937
 
31938
31938
  // ../../node_modules/.pnpm/simple-git@3.36.0/node_modules/simple-git/dist/esm/index.js
31939
31939
  var import_file_exists = __toESM(require_dist(), 1);
@@ -32524,8 +32524,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
32524
32524
  function forEachLineWithContent(input, callback) {
32525
32525
  return toLinesWithContent(input, true).map((line) => callback(line));
32526
32526
  }
32527
- function folderExists(path12) {
32528
- return (0, import_file_exists.exists)(path12, import_file_exists.FOLDER);
32527
+ function folderExists(path13) {
32528
+ return (0, import_file_exists.exists)(path13, import_file_exists.FOLDER);
32529
32529
  }
32530
32530
  function append(target, item) {
32531
32531
  if (Array.isArray(target)) {
@@ -32927,8 +32927,8 @@ function checkIsRepoRootTask() {
32927
32927
  commands: commands5,
32928
32928
  format: "utf-8",
32929
32929
  onError,
32930
- parser(path12) {
32931
- return /^\.(git)?$/.test(path12.trim());
32930
+ parser(path13) {
32931
+ return /^\.(git)?$/.test(path13.trim());
32932
32932
  }
32933
32933
  };
32934
32934
  }
@@ -33362,11 +33362,11 @@ function parseGrep(grep) {
33362
33362
  const paths = /* @__PURE__ */ new Set();
33363
33363
  const results = {};
33364
33364
  forEachLineWithContent(grep, (input) => {
33365
- const [path12, line, preview] = input.split(NULL);
33366
- paths.add(path12);
33367
- (results[path12] = results[path12] || []).push({
33365
+ const [path13, line, preview] = input.split(NULL);
33366
+ paths.add(path13);
33367
+ (results[path13] = results[path13] || []).push({
33368
33368
  line: asNumber(line),
33369
- path: path12,
33369
+ path: path13,
33370
33370
  preview
33371
33371
  });
33372
33372
  });
@@ -34130,14 +34130,14 @@ var init_hash_object = __esm2({
34130
34130
  init_task();
34131
34131
  }
34132
34132
  });
34133
- function parseInit(bare, path12, text) {
34133
+ function parseInit(bare, path13, text) {
34134
34134
  const response = String(text).trim();
34135
34135
  let result;
34136
34136
  if (result = initResponseRegex.exec(response)) {
34137
- return new InitSummary(bare, path12, false, result[1]);
34137
+ return new InitSummary(bare, path13, false, result[1]);
34138
34138
  }
34139
34139
  if (result = reInitResponseRegex.exec(response)) {
34140
- return new InitSummary(bare, path12, true, result[1]);
34140
+ return new InitSummary(bare, path13, true, result[1]);
34141
34141
  }
34142
34142
  let gitDir = "";
34143
34143
  const tokens = response.split(" ");
@@ -34148,7 +34148,7 @@ function parseInit(bare, path12, text) {
34148
34148
  break;
34149
34149
  }
34150
34150
  }
34151
- return new InitSummary(bare, path12, /^re/i.test(response), gitDir);
34151
+ return new InitSummary(bare, path13, /^re/i.test(response), gitDir);
34152
34152
  }
34153
34153
  var InitSummary;
34154
34154
  var initResponseRegex;
@@ -34157,9 +34157,9 @@ var init_InitSummary = __esm2({
34157
34157
  "src/lib/responses/InitSummary.ts"() {
34158
34158
  "use strict";
34159
34159
  InitSummary = class {
34160
- constructor(bare, path12, existing, gitDir) {
34160
+ constructor(bare, path13, existing, gitDir) {
34161
34161
  this.bare = bare;
34162
- this.path = path12;
34162
+ this.path = path13;
34163
34163
  this.existing = existing;
34164
34164
  this.gitDir = gitDir;
34165
34165
  }
@@ -34171,7 +34171,7 @@ var init_InitSummary = __esm2({
34171
34171
  function hasBareCommand(command) {
34172
34172
  return command.includes(bareCommand);
34173
34173
  }
34174
- function initTask(bare = false, path12, customArgs) {
34174
+ function initTask(bare = false, path13, customArgs) {
34175
34175
  const commands5 = ["init", ...customArgs];
34176
34176
  if (bare && !hasBareCommand(commands5)) {
34177
34177
  commands5.splice(1, 0, bareCommand);
@@ -34180,7 +34180,7 @@ function initTask(bare = false, path12, customArgs) {
34180
34180
  commands: commands5,
34181
34181
  format: "utf-8",
34182
34182
  parser(text) {
34183
- return parseInit(commands5.includes("--bare"), path12, text);
34183
+ return parseInit(commands5.includes("--bare"), path13, text);
34184
34184
  }
34185
34185
  };
34186
34186
  }
@@ -34995,12 +34995,12 @@ var init_FileStatusSummary = __esm2({
34995
34995
  "use strict";
34996
34996
  fromPathRegex = /^(.+)\0(.+)$/;
34997
34997
  FileStatusSummary = class {
34998
- constructor(path12, index, working_dir) {
34999
- this.path = path12;
34998
+ constructor(path13, index, working_dir) {
34999
+ this.path = path13;
35000
35000
  this.index = index;
35001
35001
  this.working_dir = working_dir;
35002
35002
  if (index === "R" || working_dir === "R") {
35003
- const detail = fromPathRegex.exec(path12) || [null, path12, path12];
35003
+ const detail = fromPathRegex.exec(path13) || [null, path13, path13];
35004
35004
  this.from = detail[2] || "";
35005
35005
  this.path = detail[1] || "";
35006
35006
  }
@@ -35031,14 +35031,14 @@ function splitLine(result, lineStr) {
35031
35031
  default:
35032
35032
  return;
35033
35033
  }
35034
- function data2(index, workingDir, path12) {
35034
+ function data2(index, workingDir, path13) {
35035
35035
  const raw = `${index}${workingDir}`;
35036
35036
  const handler = parsers6.get(raw);
35037
35037
  if (handler) {
35038
- handler(result, path12);
35038
+ handler(result, path13);
35039
35039
  }
35040
35040
  if (raw !== "##" && raw !== "!!") {
35041
- result.files.push(new FileStatusSummary(path12, index, workingDir));
35041
+ result.files.push(new FileStatusSummary(path13, index, workingDir));
35042
35042
  }
35043
35043
  }
35044
35044
  }
@@ -35389,9 +35389,9 @@ var init_simple_git_api = __esm2({
35389
35389
  next
35390
35390
  );
35391
35391
  }
35392
- hashObject(path12, write) {
35392
+ hashObject(path13, write) {
35393
35393
  return this._runTask(
35394
- hashObjectTask(path12, write === true),
35394
+ hashObjectTask(path13, write === true),
35395
35395
  trailingFunctionArgument(arguments)
35396
35396
  );
35397
35397
  }
@@ -35745,8 +35745,8 @@ var init_branch = __esm2({
35745
35745
  }
35746
35746
  });
35747
35747
  function toPath(input) {
35748
- const path12 = input.trim().replace(/^["']|["']$/g, "");
35749
- return path12 && normalize(path12);
35748
+ const path13 = input.trim().replace(/^["']|["']$/g, "");
35749
+ return path13 && normalize(path13);
35750
35750
  }
35751
35751
  var parseCheckIgnore;
35752
35752
  var init_CheckIgnore = __esm2({
@@ -36031,8 +36031,8 @@ __export2(sub_module_exports, {
36031
36031
  subModuleTask: () => subModuleTask,
36032
36032
  updateSubModuleTask: () => updateSubModuleTask
36033
36033
  });
36034
- function addSubModuleTask(repo, path12) {
36035
- return subModuleTask(["add", repo, path12]);
36034
+ function addSubModuleTask(repo, path13) {
36035
+ return subModuleTask(["add", repo, path13]);
36036
36036
  }
36037
36037
  function initSubModuleTask(customArgs) {
36038
36038
  return subModuleTask(["init", ...customArgs]);
@@ -36346,8 +36346,8 @@ var require_git = __commonJS2({
36346
36346
  }
36347
36347
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
36348
36348
  };
36349
- Git2.prototype.submoduleAdd = function(repo, path12, then) {
36350
- return this._runTask(addSubModuleTask2(repo, path12), trailingFunctionArgument2(arguments));
36349
+ Git2.prototype.submoduleAdd = function(repo, path13, then) {
36350
+ return this._runTask(addSubModuleTask2(repo, path13), trailingFunctionArgument2(arguments));
36351
36351
  };
36352
36352
  Git2.prototype.submoduleUpdate = function(args, then) {
36353
36353
  return this._runTask(
@@ -37780,8 +37780,8 @@ function getErrorMap() {
37780
37780
 
37781
37781
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
37782
37782
  var makeIssue = (params) => {
37783
- const { data: data2, path: path12, errorMaps, issueData } = params;
37784
- const fullPath = [...path12, ...issueData.path || []];
37783
+ const { data: data2, path: path13, errorMaps, issueData } = params;
37784
+ const fullPath = [...path13, ...issueData.path || []];
37785
37785
  const fullIssue = {
37786
37786
  ...issueData,
37787
37787
  path: fullPath
@@ -37897,11 +37897,11 @@ var errorUtil;
37897
37897
 
37898
37898
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
37899
37899
  var ParseInputLazyPath = class {
37900
- constructor(parent, value, path12, key) {
37900
+ constructor(parent, value, path13, key) {
37901
37901
  this._cachedPath = [];
37902
37902
  this.parent = parent;
37903
37903
  this.data = value;
37904
- this._path = path12;
37904
+ this._path = path13;
37905
37905
  this._key = key;
37906
37906
  }
37907
37907
  get path() {
@@ -41488,7 +41488,13 @@ var mediaSchema = external_exports.discriminatedUnion("adapter", [
41488
41488
 
41489
41489
  // ../canopycms/src/config/schemas/config.ts
41490
41490
  var defaultBranchAccessSchema = external_exports.enum(["allow", "deny"]).default("deny");
41491
- var defaultPathAccessSchema = external_exports.enum(["allow", "deny"]).default("deny");
41491
+ var defaultPathAccessLevelSchema = external_exports.enum(["allow", "deny"]);
41492
+ var defaultPathAccessLevelsSchema = external_exports.object({
41493
+ read: defaultPathAccessLevelSchema.optional(),
41494
+ edit: defaultPathAccessLevelSchema.optional(),
41495
+ review: defaultPathAccessLevelSchema.optional()
41496
+ }).strict();
41497
+ var defaultPathAccessSchema = external_exports.union([defaultPathAccessLevelSchema, defaultPathAccessLevelsSchema]).default("deny");
41492
41498
  var defaultBaseBranchSchema = external_exports.string().default("main");
41493
41499
  var defaultRemoteNameSchema = external_exports.string().default("origin");
41494
41500
  var defaultRemoteUrlSchema = external_exports.string().min(1);
@@ -41521,6 +41527,10 @@ var CanopyConfigSchema = external_exports.object({
41521
41527
  // have .default('deny'), so the field is optional on input but always resolves to
41522
41528
  // 'allow'/'deny' (never undefined) on output. An outer .optional() would short-circuit
41523
41529
  // before the inner default runs, defeating the fail-closed default (SCH-M1).
41530
+ // defaultPathAccessSchema's union keeps the same rule: the .default('deny') sits on the
41531
+ // OUTER union, not inside defaultPathAccessLevelsSchema, so an omitted top-level field
41532
+ // still resolves to 'deny' and an omitted level inside the object form stays undefined
41533
+ // (resolved to 'deny' at read time by resolveDefaultPathAccess).
41524
41534
  defaultBranchAccess: defaultBranchAccessSchema,
41525
41535
  defaultPathAccess: defaultPathAccessSchema,
41526
41536
  // .optional() deliberately defeats defaultBaseBranchSchema's .default('main'):
@@ -41579,6 +41589,13 @@ function getErrorMessage2(err) {
41579
41589
  }
41580
41590
  return String(err);
41581
41591
  }
41592
+ function redactCredentials(message) {
41593
+ let result = message;
41594
+ result = result.replace(/(:\/\/)[^/\s@]+@/g, "$1***@");
41595
+ result = result.replace(/\b(?:gh[pousr]|github_pat)_[A-Za-z0-9_]{8,}/g, "***");
41596
+ result = result.replace(/\b(Bearer\s+)[A-Za-z0-9._~+/=-]{8,}/g, "$1***");
41597
+ return result;
41598
+ }
41582
41599
  function isNodeError(err) {
41583
41600
  return err instanceof Error && "code" in err;
41584
41601
  }
@@ -41871,7 +41888,15 @@ var BranchRegistry = class {
41871
41888
  continue;
41872
41889
  }
41873
41890
  const branchRoot = path5.join(this.root, entry.name);
41874
- const meta = await BranchMetadataFileManager.loadOnly(branchRoot);
41891
+ let meta;
41892
+ try {
41893
+ meta = await BranchMetadataFileManager.loadOnly(branchRoot);
41894
+ } catch (err) {
41895
+ console.warn(
41896
+ `CanopyCMS: Skipping branch directory '${entry.name}' during registry scan: ${getErrorMessage2(err)}`
41897
+ );
41898
+ continue;
41899
+ }
41875
41900
  if (meta) {
41876
41901
  branches.push({
41877
41902
  branch: meta.branch,
@@ -41898,6 +41923,14 @@ function isValidContentId(id) {
41898
41923
  return CONTENT_ID_PATTERN.test(id);
41899
41924
  }
41900
41925
 
41926
+ // ../canopycms/src/paths/branch-name.ts
41927
+ function sanitizeBranchName(branchName) {
41928
+ const replaced = branchName.replace(/[^a-zA-Z0-9._-]/g, "-");
41929
+ const squashed = replaced.replace(/-+/g, "-");
41930
+ const trimmedDots = squashed.replace(/^\.+/, "").replace(/(?<!\.)\.+$/, "");
41931
+ return trimmedDots || "branch";
41932
+ }
41933
+
41901
41934
  // ../canopycms/src/utils/async-mutex.ts
41902
41935
  var locks = /* @__PURE__ */ new Map();
41903
41936
  async function withLock(key, fn) {
@@ -42036,6 +42069,7 @@ async function withOccFileLock(filePath, fn) {
42036
42069
  return await fn();
42037
42070
  } finally {
42038
42071
  await release().catch((err) => {
42072
+ if (isNodeError(err) && err.code === "ENOENT") return;
42039
42073
  log3.warn("lock", `Failed to release lock for ${filePath}`, { error: getErrorMessage2(err) });
42040
42074
  });
42041
42075
  }
@@ -42051,6 +42085,14 @@ var BranchMetadataConflictError = class extends Error {
42051
42085
  this.name = "BranchMetadataConflictError";
42052
42086
  }
42053
42087
  };
42088
+ var BranchMetadataCorruptError = class extends Error {
42089
+ constructor(branchRoot, cause) {
42090
+ super(`Corrupt branch metadata in '${branchRoot}': ${cause}`);
42091
+ this.name = "BranchMetadataCorruptError";
42092
+ this.branchRoot = branchRoot;
42093
+ this.parseCause = cause;
42094
+ }
42095
+ };
42054
42096
  var BranchMetadataFileManager = class _BranchMetadataFileManager {
42055
42097
  constructor(branchRoot, baseRoot, options) {
42056
42098
  this.branchRoot = path7.resolve(branchRoot);
@@ -42063,7 +42105,8 @@ var BranchMetadataFileManager = class _BranchMetadataFileManager {
42063
42105
  * Use this for read-only access (e.g., in registry scanning or loadBranchContext).
42064
42106
  */
42065
42107
  static async loadOnly(branchRoot) {
42066
- const filePath = path7.join(path7.resolve(branchRoot), BRANCH_META_DIR, BRANCH_META_FILE);
42108
+ const resolvedRoot = path7.resolve(branchRoot);
42109
+ const filePath = path7.join(resolvedRoot, BRANCH_META_DIR, BRANCH_META_FILE);
42067
42110
  try {
42068
42111
  const raw = await fs6.readFile(filePath, "utf8");
42069
42112
  return JSON.parse(raw);
@@ -42071,6 +42114,9 @@ var BranchMetadataFileManager = class _BranchMetadataFileManager {
42071
42114
  if (isNotFoundError2(err)) {
42072
42115
  return null;
42073
42116
  }
42117
+ if (err instanceof SyntaxError) {
42118
+ throw new BranchMetadataCorruptError(resolvedRoot, err.message);
42119
+ }
42074
42120
  throw err;
42075
42121
  }
42076
42122
  }
@@ -42184,7 +42230,11 @@ var BranchMetadataFileManager = class _BranchMetadataFileManager {
42184
42230
  createdBy: existing?.branch.createdBy ?? incoming.branch?.createdBy ?? defaults.createdBy,
42185
42231
  createdAt: existing?.branch.createdAt ?? defaults.createdAt,
42186
42232
  // Fork point is recorded once at creation; later saves must not move it
42187
- baseBranch: existing?.branch.baseBranch ?? incoming.branch?.baseBranch
42233
+ baseBranch: existing?.branch.baseBranch ?? incoming.branch?.baseBranch,
42234
+ // Always stamped fresh — the spreads above would otherwise let
42235
+ // the existing (creation-time) value win forever, freezing the
42236
+ // timestamp the editor's Branches panel sorts and displays by
42237
+ updatedAt: now
42188
42238
  }
42189
42239
  };
42190
42240
  const written = await this.write(merged, version);
@@ -42211,6 +42261,14 @@ var BranchMetadataFileManager = class _BranchMetadataFileManager {
42211
42261
  await registry2.invalidate();
42212
42262
  }
42213
42263
  };
42264
+ function buildMergedBranchUpdate(branchName, now = /* @__PURE__ */ new Date()) {
42265
+ return {
42266
+ name: branchName,
42267
+ status: "archived",
42268
+ pullRequestState: "merged",
42269
+ mergedAt: now.toISOString()
42270
+ };
42271
+ }
42214
42272
  var getBranchMetadataFileManager = (branchRoot, baseRoot, options) => {
42215
42273
  return BranchMetadataFileManager.get(branchRoot, baseRoot, options);
42216
42274
  };
@@ -42313,10 +42371,28 @@ async function invalidateBranchContentCaches(root) {
42313
42371
  invalidateContentIndexesForRoot(root);
42314
42372
  }
42315
42373
 
42374
+ // ../canopycms/src/worker/worker-status.ts
42375
+ import path9 from "node:path";
42376
+ var WORKER_STATUS_FILE = "worker-status.json";
42377
+ async function writeWorkerStatus(taskDir, report) {
42378
+ const filePath = path9.join(taskDir, WORKER_STATUS_FILE);
42379
+ const stamped = { ...report, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
42380
+ await atomicWriteFile(filePath, JSON.stringify(stamped, null, 2));
42381
+ }
42382
+
42316
42383
  // ../canopycms/src/worker/cms-worker.ts
42317
42384
  var DEFAULT_TASK_TIMEOUT = 6e4;
42318
42385
  var DEFAULT_MAX_RETRIES = 3;
42319
42386
  var DEFAULT_LOCK_STALE_MS = 6e4;
42387
+ var TRASH_RETENTION_MS = 30 * 24 * 60 * 6e4;
42388
+ var TRASH_DIR_STAMP_RE = /-(\d{8}T\d{6}Z)$/;
42389
+ function parseTrashStamp(stamp) {
42390
+ const match2 = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z$/.exec(stamp);
42391
+ if (!match2) return null;
42392
+ const [, year2, month, day, hour, minute, second] = match2;
42393
+ const date2 = /* @__PURE__ */ new Date(`${year2}-${month}-${day}T${hour}:${minute}:${second}.000Z`);
42394
+ return Number.isNaN(date2.getTime()) ? null : date2;
42395
+ }
42320
42396
  var PermanentTaskError = class extends Error {
42321
42397
  };
42322
42398
  function isPermanentTaskFailure(err) {
@@ -42376,20 +42452,37 @@ var CmsWorker = class {
42376
42452
  this.releaseLockFn = null;
42377
42453
  this.log = cmsTaskQueueLogger;
42378
42454
  this.octokit = createCanopyOctokit({ auth: config.githubToken });
42379
- this.taskDir = path9.join(config.workspacePath, ".tasks");
42380
- this.remoteGitPath = path9.join(config.workspacePath, "remote.git");
42381
- this.contentBranchesPath = path9.join(config.workspacePath, "content-branches");
42455
+ this.taskDir = path10.join(config.workspacePath, ".tasks");
42456
+ this.remoteGitPath = path10.join(config.workspacePath, "remote.git");
42457
+ this.contentBranchesPath = path10.join(config.workspacePath, "content-branches");
42382
42458
  this.baseBranch = config.baseBranch ?? "main";
42459
+ this.sanitizedBaseBranch = sanitizeBranchName(this.baseBranch);
42383
42460
  this.maxTasksPerCycle = config.maxTasksPerCycle ?? 10;
42384
42461
  this.taskTimeoutMs = config.taskTimeoutMs ?? DEFAULT_TASK_TIMEOUT;
42385
42462
  this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
42386
- this.lockFilePath = path9.join(config.workspacePath, ".tasks", ".worker-lock");
42463
+ this.lockFilePath = path10.join(config.workspacePath, ".tasks", ".worker-lock");
42387
42464
  this.lockStaleMs = config.lockStaleMs ?? DEFAULT_LOCK_STALE_MS;
42388
42465
  this.contentRoot = config.contentRoot ?? "content";
42389
42466
  }
42467
+ /**
42468
+ * Lazily get (and initialize if necessary) this worker's self-reported
42469
+ * status object (PR-W1). Normally set once, up front, at the top of
42470
+ * start(). The lazy fallback here covers two cases: (1) something in
42471
+ * start() reaching a status-write point before that normal init runs
42472
+ * (defensive -- see start()'s catch), and (2) unit tests that exercise
42473
+ * syncGit()/processTaskQueue() directly without calling start() first.
42474
+ */
42475
+ ensureStatusReport() {
42476
+ if (!this.statusReport) {
42477
+ const now = (/* @__PURE__ */ new Date()).toISOString();
42478
+ this.statusReport = { version: 1, startedAt: now, updatedAt: now };
42479
+ }
42480
+ return this.statusReport;
42481
+ }
42390
42482
  async start() {
42391
42483
  this.running = true;
42392
42484
  console.log("CMS Worker starting...");
42485
+ this.ensureStatusReport();
42393
42486
  await this.acquireLock();
42394
42487
  try {
42395
42488
  await this.ensureRemoteGit();
@@ -42403,6 +42496,23 @@ var CmsWorker = class {
42403
42496
  }
42404
42497
  await Promise.allSettled(initialTasks);
42405
42498
  } catch (err) {
42499
+ const report = this.ensureStatusReport();
42500
+ report.lastFatalError = {
42501
+ // [HIGH-1] Persisted to worker-status.json and served to the
42502
+ // browser by the admin panel -- must never carry the bot token
42503
+ // that a poisoned/failed git URL (buildGitHubUrl()) can embed.
42504
+ message: redactCredentials(getErrorMessage2(err)),
42505
+ at: (/* @__PURE__ */ new Date()).toISOString(),
42506
+ phase: "startup"
42507
+ };
42508
+ try {
42509
+ await writeWorkerStatus(this.taskDir, report);
42510
+ } catch (writeErr) {
42511
+ console.error(
42512
+ "Failed to write worker status on startup failure:",
42513
+ getErrorMessage2(writeErr)
42514
+ );
42515
+ }
42406
42516
  await this.releaseLock();
42407
42517
  throw err;
42408
42518
  }
@@ -42609,15 +42719,16 @@ var CmsWorker = class {
42609
42719
  } catch (err) {
42610
42720
  const message = getErrorMessage2(err);
42611
42721
  console.error(`Task ${task.id} (${task.action}) failed:`, message);
42722
+ const persistedMessage = redactCredentials(message);
42612
42723
  const permanent = isPermanentTaskFailure(err);
42613
42724
  const retryCount = task.retryCount ?? 0;
42614
42725
  const maxRetries = task.maxRetries ?? this.maxRetries;
42615
42726
  if (!permanent && retryCount < maxRetries) {
42616
- await retryTask(this.taskDir, task.id, message, this.log);
42727
+ await retryTask(this.taskDir, task.id, persistedMessage, this.log);
42617
42728
  console.log(` Will retry (attempt ${retryCount + 1}/${maxRetries})`);
42618
42729
  } else {
42619
- await failTask(this.taskDir, task.id, message, this.log);
42620
- await this.updateBranchMetadataOnFailure(task, message);
42730
+ await failTask(this.taskDir, task.id, persistedMessage, this.log);
42731
+ await this.updateBranchMetadataOnFailure(task, persistedMessage);
42621
42732
  console.error(
42622
42733
  permanent ? " Permanently failed (non-retryable error)" : ` Permanently failed after ${maxRetries} retries`
42623
42734
  );
@@ -42625,6 +42736,13 @@ var CmsWorker = class {
42625
42736
  }
42626
42737
  processed++;
42627
42738
  }
42739
+ if (processed > 0) {
42740
+ const report = this.ensureStatusReport();
42741
+ report.lastTaskCycleAt = (/* @__PURE__ */ new Date()).toISOString();
42742
+ await writeWorkerStatus(this.taskDir, report).catch(
42743
+ (writeErr) => console.error("Failed to write worker status:", getErrorMessage2(writeErr))
42744
+ );
42745
+ }
42628
42746
  }
42629
42747
  /**
42630
42748
  * Execute a task bounded by taskTimeoutMs (DEP-H1). Two layers:
@@ -42694,13 +42812,19 @@ var CmsWorker = class {
42694
42812
  }
42695
42813
  case "push-and-create-or-update-pr": {
42696
42814
  const branch = requireString(payload2, "branch");
42815
+ const base = optionalString(payload2, "baseBranch", this.baseBranch);
42816
+ if (sanitizeBranchName(branch) === this.sanitizedBaseBranch) {
42817
+ throw new PermanentTaskError(
42818
+ `Refusing to push-and-create-or-update-pr for "${branch}": it is the base branch -- submitting the base branch is never valid`
42819
+ );
42820
+ }
42697
42821
  await this.pushBranchToGitHub(branch);
42698
42822
  const result = await createOrUpdatePullRequest({
42699
42823
  octokit: this.octokit,
42700
42824
  owner: this.config.githubOwner,
42701
42825
  repo: this.config.githubRepo,
42702
42826
  head: branch,
42703
- base: optionalString(payload2, "baseBranch", this.baseBranch),
42827
+ base,
42704
42828
  title: optionalString(payload2, "title", `Submit ${branch}`),
42705
42829
  body: optionalString(payload2, "body", ""),
42706
42830
  // Content submits (api/github-sync.ts) set this; settings-branch
@@ -42760,7 +42884,7 @@ var CmsWorker = class {
42760
42884
  async updateBranchMetadata(task, result) {
42761
42885
  const branch = typeof task.payload.branch === "string" ? task.payload.branch : null;
42762
42886
  if (!branch) return;
42763
- const branchPath = path9.join(this.contentBranchesPath, branch);
42887
+ const branchPath = path10.join(this.contentBranchesPath, branch);
42764
42888
  try {
42765
42889
  await fs7.stat(branchPath);
42766
42890
  } catch {
@@ -42773,7 +42897,14 @@ var CmsWorker = class {
42773
42897
  syncStatus: "synced"
42774
42898
  };
42775
42899
  if (result.prUrl) updates.pullRequestUrl = result.prUrl;
42776
- if (result.prNumber) updates.pullRequestNumber = result.prNumber;
42900
+ if (result.prNumber) {
42901
+ updates.pullRequestNumber = result.prNumber;
42902
+ const current = await BranchMetadataFileManager.loadOnly(branchPath);
42903
+ const terminal = current?.branch.status === "archived" || current?.branch.pullRequestState === "merged" || current?.branch.pullRequestState === "closed";
42904
+ if (!terminal) {
42905
+ updates.pullRequestState = "open";
42906
+ }
42907
+ }
42777
42908
  await meta.save({ branch: updates });
42778
42909
  } catch (err) {
42779
42910
  console.error(
@@ -42789,7 +42920,7 @@ var CmsWorker = class {
42789
42920
  async updateBranchMetadataOnFailure(task, _error) {
42790
42921
  const branch = typeof task.payload.branch === "string" ? task.payload.branch : null;
42791
42922
  if (!branch) return;
42792
- const branchPath = path9.join(this.contentBranchesPath, branch);
42923
+ const branchPath = path10.join(this.contentBranchesPath, branch);
42793
42924
  try {
42794
42925
  await fs7.stat(branchPath);
42795
42926
  } catch {
@@ -42845,6 +42976,7 @@ var CmsWorker = class {
42845
42976
  async syncGit() {
42846
42977
  if (!this.running) return;
42847
42978
  console.log("Syncing git...");
42979
+ const cycleStartedAt = Date.now();
42848
42980
  const git = simpleGit({
42849
42981
  baseDir: this.remoteGitPath,
42850
42982
  // DEP-H1: a hung fetch/push would stall the sync loop forever
@@ -42852,32 +42984,318 @@ var CmsWorker = class {
42852
42984
  // is inactivity-based, so a slow-but-flowing transfer is unaffected.
42853
42985
  timeout: { block: this.taskTimeoutMs }
42854
42986
  });
42855
- await git.raw(["fetch", this.buildGitHubUrl(), "--prune", "+refs/heads/*:refs/heads/*"]);
42856
- console.log("Fetched from GitHub");
42857
- await this.pushSettingsBranches(git);
42858
- await this.rebaseActiveBranches();
42859
- await cleanupOldTasks(this.taskDir, void 0, this.log);
42987
+ try {
42988
+ await git.raw(["fetch", this.buildGitHubUrl(), "--prune", "+refs/heads/*:refs/heads/*"]);
42989
+ console.log("Fetched from GitHub");
42990
+ await this.pushSettingsBranches(git);
42991
+ await this.refreshBaseBranchWorkspace();
42992
+ const rebaseSummary = await this.rebaseActiveBranches();
42993
+ await cleanupOldTasks(this.taskDir, void 0, this.log);
42994
+ const trashRemoved = await this.cleanupTrashedBranchDirs();
42995
+ if (trashRemoved > 0) {
42996
+ console.log(`Removed ${trashRemoved} expired trashed branch dir(s)`);
42997
+ }
42998
+ const report = this.ensureStatusReport();
42999
+ report.lastGitSyncAt = (/* @__PURE__ */ new Date()).toISOString();
43000
+ delete report.lastGitSyncError;
43001
+ report.lastGitSync = {
43002
+ durationMs: Date.now() - cycleStartedAt,
43003
+ rebased: rebaseSummary.rebased,
43004
+ skippedDirty: rebaseSummary.skippedDirty,
43005
+ failed: rebaseSummary.failed
43006
+ };
43007
+ await writeWorkerStatus(this.taskDir, report).catch(
43008
+ (writeErr) => console.error("Failed to write worker status:", getErrorMessage2(writeErr))
43009
+ );
43010
+ } catch (err) {
43011
+ const report = this.ensureStatusReport();
43012
+ report.lastGitSyncError = {
43013
+ message: redactCredentials(getErrorMessage2(err)),
43014
+ at: (/* @__PURE__ */ new Date()).toISOString()
43015
+ };
43016
+ await writeWorkerStatus(this.taskDir, report).catch(
43017
+ (writeErr) => console.error("Failed to write worker status:", getErrorMessage2(writeErr))
43018
+ );
43019
+ throw err;
43020
+ }
43021
+ }
43022
+ /**
43023
+ * [C1] Remove `.trash-*` branch directories (created by the admin purge
43024
+ * action, api/admin-branch-health.ts) whose name-embedded stamp is older
43025
+ * than {@link TRASH_RETENTION_MS}. Names that don't match the expected
43026
+ * `.trash-{dirName}-{STAMP}` shape, or whose stamp fails to parse, are
43027
+ * left alone (logged once per cycle, not per file, to avoid flooding logs
43028
+ * if something odd accumulates) -- purge is the only writer of this
43029
+ * naming scheme, so an unparseable name is unexpected and worth a human
43030
+ * looking rather than a silent skip.
43031
+ */
43032
+ async cleanupTrashedBranchDirs() {
43033
+ let entries;
43034
+ try {
43035
+ entries = await fs7.readdir(this.contentBranchesPath);
43036
+ } catch (err) {
43037
+ if (isNodeError(err) && err.code === "ENOENT") return 0;
43038
+ throw err;
43039
+ }
43040
+ const now = Date.now();
43041
+ let removed = 0;
43042
+ let loggedUnparseable = false;
43043
+ for (const name of entries) {
43044
+ if (!name.startsWith(".trash-")) continue;
43045
+ const stampMatch = TRASH_DIR_STAMP_RE.exec(name);
43046
+ const stampDate = stampMatch ? parseTrashStamp(stampMatch[1]) : null;
43047
+ if (!stampDate) {
43048
+ if (!loggedUnparseable) {
43049
+ console.log(`CanopyCMS: Skipping trash dir with unparseable stamp: ${name}`);
43050
+ loggedUnparseable = true;
43051
+ }
43052
+ continue;
43053
+ }
43054
+ if (now - stampDate.getTime() < TRASH_RETENTION_MS) continue;
43055
+ try {
43056
+ await fs7.rm(path10.join(this.contentBranchesPath, name), {
43057
+ recursive: true,
43058
+ force: true,
43059
+ maxRetries: 3,
43060
+ retryDelay: 100
43061
+ });
43062
+ removed++;
43063
+ } catch (err) {
43064
+ console.error(
43065
+ `CanopyCMS: Failed to remove trashed branch dir ${name}:`,
43066
+ getErrorMessage2(err)
43067
+ );
43068
+ }
43069
+ }
43070
+ return removed;
43071
+ }
43072
+ /**
43073
+ * Fast-forward the base branch's own working-tree clone
43074
+ * (content-branches/<baseBranch>) to match origin/<baseBranch>.
43075
+ *
43076
+ * Previously this clone was refreshed only incidentally, by the generic
43077
+ * rebase loop below (rebaseActiveBranches): for a branch with status
43078
+ * 'editing', rebasing onto origin/<baseBranch> degenerates to a
43079
+ * fast-forward when the clone IS the base branch. But that loop's skip
43080
+ * paths -- a dirty tree, a missing .git -- are silent, which is the
43081
+ * suspected live failure mode: a wedged base clone with no diagnosable
43082
+ * signal in the logs. This dedicated step makes the refresh explicit,
43083
+ * ff-only, and loud, so a stuck base view (an editor forking a new branch
43084
+ * "from base" that's actually a stale snapshot) is diagnosable from logs.
43085
+ * This runs every sync cycle so the drift window is bounded by
43086
+ * gitSyncInterval.
43087
+ *
43088
+ * ff-only on purpose: this clone must stay a linear mirror of
43089
+ * origin/<baseBranch>, so a merge that isn't a fast-forward (diverged
43090
+ * local history) is treated as a should-never-happen condition and left
43091
+ * untouched rather than force-resolved.
43092
+ */
43093
+ async refreshBaseBranchWorkspace() {
43094
+ const basePath32 = path10.join(this.contentBranchesPath, this.sanitizedBaseBranch);
43095
+ const gitDir = path10.join(basePath32, ".git");
43096
+ try {
43097
+ let gitDirStat;
43098
+ try {
43099
+ gitDirStat = await fs7.stat(gitDir);
43100
+ } catch {
43101
+ gitDirStat = null;
43102
+ }
43103
+ if (!gitDirStat || !gitDirStat.isDirectory()) {
43104
+ console.log(
43105
+ `Base branch workspace (${this.baseBranch}): not yet provisioned, skipping refresh`
43106
+ );
43107
+ return;
43108
+ }
43109
+ const baseGit = simpleGit({
43110
+ baseDir: basePath32,
43111
+ // Keep git non-interactive during the merge so it never blocks on an
43112
+ // editor. simple-git >=3.32 blocks setting core.editor unless
43113
+ // explicitly opted in; the value here is a hardcoded literal
43114
+ // ("true", the shell no-op), not user input, so enabling
43115
+ // allowUnsafeEditor carries no injection risk (same as the rebase
43116
+ // loop's git config below).
43117
+ config: ["core.editor=true"],
43118
+ unsafe: { allowUnsafeEditor: true },
43119
+ // DEP-H1: a hung fetch/merge against this EFS-backed clone would
43120
+ // stall the sync loop forever (scheduleLoop only reschedules after
43121
+ // completion). The block timeout is inactivity-based, so a
43122
+ // slow-but-flowing transfer is unaffected -- same as syncGit()'s
43123
+ // remote handle.
43124
+ timeout: { block: this.taskTimeoutMs }
43125
+ });
43126
+ const status = await baseGit.status();
43127
+ const trackedDirty = status.files.filter((f5) => f5.index !== "?" || f5.working_dir !== "?");
43128
+ if (trackedDirty.length > 0) {
43129
+ console.error(
43130
+ `Base branch workspace (${this.baseBranch}) has uncommitted changes -- skipping refresh. Dirty files: ${trackedDirty.map((f5) => f5.path).join(", ")}`
43131
+ );
43132
+ return;
43133
+ }
43134
+ await baseGit.fetch("origin", this.baseBranch);
43135
+ const fetchedTip = (await baseGit.revparse(["FETCH_HEAD"])).trim();
43136
+ const behindCount = parseInt(
43137
+ (await baseGit.raw(["rev-list", "--count", `HEAD..${fetchedTip}`])).trim(),
43138
+ 10
43139
+ );
43140
+ if (behindCount > 0) {
43141
+ try {
43142
+ await baseGit.merge(["--ff-only", fetchedTip]);
43143
+ } catch (err) {
43144
+ console.error(
43145
+ `Base branch workspace (${this.baseBranch}) failed to fast-forward (diverged local history?): ${getErrorMessage2(err)}`
43146
+ );
43147
+ return;
43148
+ }
43149
+ await invalidateBranchContentCaches(basePath32);
43150
+ }
43151
+ const currentMeta = await BranchMetadataFileManager.loadOnly(basePath32);
43152
+ const conflictStatus = currentMeta?.branch.conflictStatus;
43153
+ const conflictFiles = currentMeta?.branch.conflictFiles;
43154
+ const alreadyClean = (conflictStatus === void 0 || conflictStatus === "clean") && (conflictFiles === void 0 || conflictFiles.length === 0);
43155
+ if (!alreadyClean) {
43156
+ const meta = getBranchMetadataFileManager(basePath32, this.contentBranchesPath);
43157
+ await meta.save({
43158
+ branch: { name: this.baseBranch, conflictStatus: "clean", conflictFiles: [] }
43159
+ });
43160
+ }
43161
+ console.log(
43162
+ behindCount > 0 ? `Base branch workspace (${this.baseBranch}): fast-forwarded ${behindCount} commit(s)` : `Base branch workspace (${this.baseBranch}): up to date`
43163
+ );
43164
+ } catch (err) {
43165
+ console.error(
43166
+ `Base branch workspace (${this.baseBranch}) refresh failed: ${getErrorMessage2(err)}`
43167
+ );
43168
+ }
43169
+ }
43170
+ /**
43171
+ * Poll GitHub for a submitted/approved branch's PR resolution.
43172
+ *
43173
+ * submitted/approved branches sit outside the rebase loop and get no
43174
+ * other signal that their PR resolved on GitHub -- nothing pushes a
43175
+ * merge/close webhook back into the branch workspace. merged ->
43176
+ * auto-archive via buildMergedBranchUpdate (shared with the manual
43177
+ * markAsMerged API so both paths produce identical archived-branch
43178
+ * metadata). closed-without-merge -> record pullRequestState only; an
43179
+ * admin decides the workflow transition from there. Best-effort: any
43180
+ * failure here is logged and swallowed, retried next sync cycle.
43181
+ */
43182
+ async pollMergeState(branchDir, branchPath, metaFile) {
43183
+ const prNumber = metaFile?.branch.pullRequestNumber;
43184
+ if (!prNumber) return;
43185
+ const controller = new AbortController();
43186
+ const timer = setTimeout(() => controller.abort(), this.taskTimeoutMs);
43187
+ try {
43188
+ const { data: data2 } = await this.octokit.pulls.get({
43189
+ owner: this.config.githubOwner,
43190
+ repo: this.config.githubRepo,
43191
+ pull_number: prNumber,
43192
+ request: { signal: controller.signal }
43193
+ });
43194
+ if (data2.merged) {
43195
+ const meta2 = getBranchMetadataFileManager(branchPath, this.contentBranchesPath);
43196
+ await meta2.save({
43197
+ branch: buildMergedBranchUpdate(
43198
+ branchDir,
43199
+ data2.merged_at ? new Date(data2.merged_at) : void 0
43200
+ )
43201
+ });
43202
+ console.log(` PR #${prNumber} for ${branchDir} is merged -> archived`);
43203
+ return;
43204
+ }
43205
+ const newState = data2.state === "closed" ? "closed" : "open";
43206
+ const currentMeta = await BranchMetadataFileManager.loadOnly(branchPath);
43207
+ if (currentMeta?.branch.pullRequestState === newState) return;
43208
+ const meta = getBranchMetadataFileManager(branchPath, this.contentBranchesPath);
43209
+ await meta.save({ branch: { name: branchDir, pullRequestState: newState } });
43210
+ console.log(` PR #${prNumber} for ${branchDir}: pullRequestState -> ${newState}`);
43211
+ } catch (err) {
43212
+ console.warn(` Failed to poll PR #${prNumber} for ${branchDir}: ${getErrorMessage2(err)}`);
43213
+ } finally {
43214
+ clearTimeout(timer);
43215
+ }
43216
+ }
43217
+ /**
43218
+ * Persist a per-branch rebase failure to branch.json (PR-W2), bounded to
43219
+ * roughly one save per failing branch per hour: a branch stuck failing
43220
+ * every cycle must not turn into unbounded save-per-cycle x N-failing-
43221
+ * branches write amplification -- save() eager-regenerates the branch
43222
+ * registry (branch-metadata.ts's invalidateRegistry(), O(branch count) EFS
43223
+ * reads), the same concern the `alreadyClean` no-op guard above exists
43224
+ * for.
43225
+ *
43226
+ * Best-effort and non-fatal like every other metadata write in this
43227
+ * loop's error paths: a corrupt branch.json, a lock-contention error, or
43228
+ * any other save failure here must never abort the per-branch iteration.
43229
+ * This matters doubly at the two call sites -- one is inside the outer
43230
+ * per-branch catch, with no further catch of its own around this call --
43231
+ * so the whole method is wrapped, not just the load.
43232
+ */
43233
+ async recordRebaseFailure(branchPath, branchDir, message) {
43234
+ const RECORD_REFRESH_MS = 60 * 60 * 1e3;
43235
+ const redactedMessage = redactCredentials(message);
43236
+ try {
43237
+ const existing = await BranchMetadataFileManager.loadOnly(branchPath);
43238
+ const prior = existing?.branch.rebaseFailure;
43239
+ const sameMessage = prior?.message === redactedMessage;
43240
+ const now = /* @__PURE__ */ new Date();
43241
+ if (sameMessage) {
43242
+ const lastAtMs = Date.parse(prior.lastAt);
43243
+ if (!Number.isNaN(lastAtMs) && now.getTime() - lastAtMs < RECORD_REFRESH_MS) {
43244
+ return;
43245
+ }
43246
+ }
43247
+ const nowIso = now.toISOString();
43248
+ const firstAt = sameMessage ? prior.firstAt : nowIso;
43249
+ const meta = getBranchMetadataFileManager(branchPath, this.contentBranchesPath);
43250
+ await meta.save({
43251
+ branch: {
43252
+ name: branchDir,
43253
+ rebaseFailure: { message: redactedMessage, firstAt, lastAt: nowIso }
43254
+ }
43255
+ });
43256
+ } catch (err) {
43257
+ console.warn(` Failed to record rebase failure for ${branchDir}: ${getErrorMessage2(err)}`);
43258
+ }
42860
43259
  }
42861
43260
  async rebaseActiveBranches() {
43261
+ const rebased = [];
43262
+ const skippedDirty = [];
43263
+ const failed = [];
42862
43264
  let branchDirs;
42863
43265
  try {
42864
43266
  branchDirs = await fs7.readdir(this.contentBranchesPath);
42865
43267
  } catch {
42866
- return;
43268
+ return { rebased, skippedDirty, failed };
42867
43269
  }
42868
43270
  for (const branchDir of branchDirs) {
42869
- const branchPath = path9.join(this.contentBranchesPath, branchDir);
42870
- const gitDir = path9.join(branchPath, ".git");
43271
+ if (branchDir.startsWith(".") || branchDir === "branches.json") {
43272
+ continue;
43273
+ }
43274
+ const branchPath = path10.join(this.contentBranchesPath, branchDir);
43275
+ const gitDir = path10.join(branchPath, ".git");
42871
43276
  try {
42872
43277
  const stat = await fs7.stat(gitDir);
42873
- if (!stat.isDirectory()) continue;
43278
+ if (!stat.isDirectory()) {
43279
+ console.log(` Skipping ${branchDir}: .git is not a directory`);
43280
+ continue;
43281
+ }
42874
43282
  } catch {
43283
+ console.log(` Skipping ${branchDir}: no .git directory (not a branch workspace)`);
43284
+ continue;
43285
+ }
43286
+ if (branchDir === this.sanitizedBaseBranch) {
43287
+ console.log(` Skipping ${branchDir}: base branch (refreshed separately)`);
42875
43288
  continue;
42876
43289
  }
42877
43290
  try {
42878
43291
  const metaFile = await BranchMetadataFileManager.loadOnly(branchPath);
42879
43292
  const branchStatus2 = metaFile?.branch.status;
42880
- if (branchStatus2 === "submitted" || branchStatus2 === "approved" || branchStatus2 === "archived") {
43293
+ if (branchStatus2 === "submitted" || branchStatus2 === "approved") {
43294
+ console.log(` Skipping ${branchDir} (${branchStatus2})`);
43295
+ await this.pollMergeState(branchDir, branchPath, metaFile);
43296
+ continue;
43297
+ }
43298
+ if (branchStatus2 === "archived") {
42881
43299
  console.log(` Skipping ${branchDir} (${branchStatus2})`);
42882
43300
  continue;
42883
43301
  }
@@ -42893,11 +43311,13 @@ var CmsWorker = class {
42893
43311
  const dirtyCheck = await branchGit.status();
42894
43312
  if (dirtyCheck.files.length > 0) {
42895
43313
  console.log(` Skipping ${branchDir}: has uncommitted changes`);
43314
+ skippedDirty.push(branchDir);
42896
43315
  continue;
42897
43316
  }
42898
43317
  await branchGit.fetch("origin", this.baseBranch);
43318
+ const fetchedBaseTip = (await branchGit.revparse(["FETCH_HEAD"])).trim();
42899
43319
  const behindCount = parseInt(
42900
- (await branchGit.raw(["rev-list", "--count", `HEAD..origin/${this.baseBranch}`])).trim(),
43320
+ (await branchGit.raw(["rev-list", "--count", `HEAD..${fetchedBaseTip}`])).trim(),
42901
43321
  10
42902
43322
  );
42903
43323
  const meta = getBranchMetadataFileManager(branchPath, this.contentBranchesPath);
@@ -42905,7 +43325,8 @@ var CmsWorker = class {
42905
43325
  const currentMeta = await BranchMetadataFileManager.loadOnly(branchPath);
42906
43326
  const conflictStatus = currentMeta?.branch.conflictStatus;
42907
43327
  const conflictFiles = currentMeta?.branch.conflictFiles;
42908
- const alreadyClean = (conflictStatus === void 0 || conflictStatus === "clean") && (conflictFiles === void 0 || conflictFiles.length === 0);
43328
+ const conflictAlreadyClean = (conflictStatus === void 0 || conflictStatus === "clean") && (conflictFiles === void 0 || conflictFiles.length === 0);
43329
+ const alreadyClean = conflictAlreadyClean && currentMeta?.branch.rebaseFailure === void 0;
42909
43330
  if (alreadyClean) {
42910
43331
  continue;
42911
43332
  }
@@ -42913,7 +43334,8 @@ var CmsWorker = class {
42913
43334
  branch: {
42914
43335
  name: branchDir,
42915
43336
  conflictStatus: "clean",
42916
- conflictFiles: []
43337
+ conflictFiles: [],
43338
+ rebaseFailure: void 0
42917
43339
  }
42918
43340
  });
42919
43341
  continue;
@@ -42922,11 +43344,12 @@ var CmsWorker = class {
42922
43344
  const conflictedFiles = [];
42923
43345
  let nextAction = "start";
42924
43346
  let completed = false;
43347
+ let failureReason;
42925
43348
  const MAX_ROUNDS = 50;
42926
43349
  for (let round = 0; round < MAX_ROUNDS && !completed; round++) {
42927
43350
  try {
42928
43351
  if (nextAction === "start") {
42929
- await branchGit.rebase([`origin/${this.baseBranch}`]);
43352
+ await branchGit.rebase([fetchedBaseTip]);
42930
43353
  } else if (nextAction === "continue") {
42931
43354
  await branchGit.rebase(["--continue"]);
42932
43355
  } else {
@@ -42948,6 +43371,7 @@ var CmsWorker = class {
42948
43371
  nextAction = "skip";
42949
43372
  } else {
42950
43373
  console.warn(` Unexpected rebase error in ${branchDir}: ${msg || "Unknown error"}`);
43374
+ failureReason = msg || "Unknown error";
42951
43375
  await branchGit.rebase(["--abort"]).catch(() => {
42952
43376
  });
42953
43377
  break;
@@ -42957,20 +43381,27 @@ var CmsWorker = class {
42957
43381
  }
42958
43382
  if (!completed) {
42959
43383
  console.warn(
42960
- ` Rebase of ${branchDir} did not complete within ${MAX_ROUNDS} rounds, aborting`
43384
+ failureReason !== void 0 ? ` Rebase of ${branchDir} aborted due to unexpected error: ${failureReason}` : ` Rebase of ${branchDir} did not complete within ${MAX_ROUNDS} rounds, aborting`
42961
43385
  );
42962
43386
  await branchGit.rebase(["--abort"]).catch(() => {
42963
43387
  });
43388
+ const rebaseFailureMessage = failureReason ?? `did not complete within ${MAX_ROUNDS} rounds`;
43389
+ const redactedRebaseFailureMessage = redactCredentials(rebaseFailureMessage);
43390
+ failed.push({
43391
+ branch: branchDir,
43392
+ error: redactedRebaseFailureMessage
43393
+ });
43394
+ await this.recordRebaseFailure(branchPath, branchDir, redactedRebaseFailureMessage);
42964
43395
  continue;
42965
43396
  }
42966
43397
  await invalidateBranchContentCaches(branchPath);
42967
43398
  const conflictIds = [...new Set(conflictedFiles)].map((f5) => {
42968
- const fileId = extractIdFromFilename(path9.basename(f5));
43399
+ const fileId = extractIdFromFilename(path10.basename(f5));
42969
43400
  if (fileId) return fileId;
42970
- const parentDir = path9.basename(path9.dirname(f5));
43401
+ const parentDir = path10.basename(path10.dirname(f5));
42971
43402
  const dirId = extractIdFromFilename(parentDir);
42972
43403
  if (dirId) return dirId;
42973
- if (path9.basename(f5) === ".collection.json" && parentDir === this.contentRoot) {
43404
+ if (path10.basename(f5) === ".collection.json" && parentDir === this.contentRoot) {
42974
43405
  return ROOT_COLLECTION_ID;
42975
43406
  }
42976
43407
  return null;
@@ -42984,14 +43415,22 @@ var CmsWorker = class {
42984
43415
  branch: {
42985
43416
  name: branchDir,
42986
43417
  conflictStatus: hadConflicts ? "conflicts-detected" : "clean",
42987
- conflictFiles: conflictIdsDeduped
43418
+ conflictFiles: conflictIdsDeduped,
43419
+ // PR-W2: the cycle completed successfully -- clear any prior
43420
+ // failure record regardless of conflict outcome.
43421
+ rebaseFailure: void 0
42988
43422
  }
42989
43423
  });
43424
+ rebased.push(branchDir);
42990
43425
  } catch (err) {
42991
43426
  const message = err instanceof Error ? err.message : "Unknown error";
42992
43427
  console.warn(` Failed to sync ${branchDir}: ${message}`);
43428
+ const redactedMessage = redactCredentials(message);
43429
+ failed.push({ branch: branchDir, error: redactedMessage });
43430
+ await this.recordRebaseFailure(branchPath, branchDir, redactedMessage);
42993
43431
  }
42994
43432
  }
43433
+ return { rebased, skippedDirty, failed };
42995
43434
  }
42996
43435
  async refreshAuthCache() {
42997
43436
  if (!this.running || !this.config.refreshAuthCache) return;
@@ -46186,10 +46625,10 @@ var SessionAPI = class extends AbstractAPI {
46186
46625
  */
46187
46626
  async getToken(sessionId, template, expiresInSeconds) {
46188
46627
  this.requireId(sessionId);
46189
- const path12 = template ? joinPaths(basePath24, sessionId, "tokens", template) : joinPaths(basePath24, sessionId, "tokens");
46628
+ const path13 = template ? joinPaths(basePath24, sessionId, "tokens", template) : joinPaths(basePath24, sessionId, "tokens");
46190
46629
  const requestOptions = {
46191
46630
  method: "POST",
46192
- path: path12
46631
+ path: path13
46193
46632
  };
46194
46633
  if (expiresInSeconds !== void 0) {
46195
46634
  requestOptions.bodyParams = { expires_in_seconds: expiresInSeconds };
@@ -48311,12 +48750,12 @@ function buildRequest(options) {
48311
48750
  userAgent = USER_AGENT,
48312
48751
  skipApiVersionInUrl = false
48313
48752
  } = options;
48314
- const { path: path12, method, queryParams, headerParams, bodyParams, formData, options: opts } = requestOptions;
48753
+ const { path: path13, method, queryParams, headerParams, bodyParams, formData, options: opts } = requestOptions;
48315
48754
  const { deepSnakecaseBodyParamKeys = false } = opts || {};
48316
48755
  if (requireSecretKey) {
48317
48756
  assertValidSecretKey(secretKey);
48318
48757
  }
48319
- const url = skipApiVersionInUrl ? joinPaths(apiUrl, path12) : joinPaths(apiUrl, apiVersion, path12);
48758
+ const url = skipApiVersionInUrl ? joinPaths(apiUrl, path13) : joinPaths(apiUrl, apiVersion, path13);
48320
48759
  const finalUrl = new URL(url);
48321
48760
  if (queryParams) {
48322
48761
  const snakecasedQueryParams = snakecase_keys_default({ ...queryParams });
@@ -50379,21 +50818,21 @@ function createClerkClient(options) {
50379
50818
 
50380
50819
  // ../canopycms/src/auth/file-based-auth-cache.ts
50381
50820
  import fs8 from "node:fs/promises";
50382
- import path10 from "node:path";
50821
+ import path11 from "node:path";
50383
50822
  var log4 = createDebugLogger({ prefix: "FileBasedAuthCache" });
50384
50823
  async function writeAuthCacheSnapshot(cachePath, files) {
50385
50824
  await fs8.mkdir(cachePath, { recursive: true });
50386
50825
  const timestamp = Date.now();
50387
- const snapshotDir = path10.join(cachePath, `snapshot-${timestamp}`);
50826
+ const snapshotDir = path11.join(cachePath, `snapshot-${timestamp}`);
50388
50827
  await fs8.mkdir(snapshotDir, { recursive: true });
50389
50828
  for (const [fileName, data2] of Object.entries(files)) {
50390
- const tmpPath = path10.join(snapshotDir, `${fileName}.tmp`);
50391
- const finalPath = path10.join(snapshotDir, fileName);
50829
+ const tmpPath = path11.join(snapshotDir, `${fileName}.tmp`);
50830
+ const finalPath = path11.join(snapshotDir, fileName);
50392
50831
  await fs8.writeFile(tmpPath, JSON.stringify(data2, null, 2), "utf-8");
50393
50832
  await fs8.rename(tmpPath, finalPath);
50394
50833
  }
50395
- const currentLink = path10.join(cachePath, "current");
50396
- const tmpLink = path10.join(cachePath, `current-${timestamp}`);
50834
+ const currentLink = path11.join(cachePath, "current");
50835
+ const tmpLink = path11.join(cachePath, `current-${timestamp}`);
50397
50836
  await fs8.symlink(snapshotDir, tmpLink);
50398
50837
  await fs8.rename(tmpLink, currentLink);
50399
50838
  await cleanupOldSnapshots(cachePath, 2);
@@ -50409,7 +50848,7 @@ async function cleanupOldSnapshots(cachePath, keepCount) {
50409
50848
  const snapshots = entries.filter((e5) => e5.startsWith("snapshot-")).sort().reverse();
50410
50849
  for (const snapshot of snapshots.slice(keepCount)) {
50411
50850
  try {
50412
- await fs8.rm(path10.join(cachePath, snapshot), {
50851
+ await fs8.rm(path11.join(cachePath, snapshot), {
50413
50852
  recursive: true,
50414
50853
  force: true
50415
50854
  });
@@ -50498,7 +50937,7 @@ async function refreshClerkCache(options) {
50498
50937
  }
50499
50938
 
50500
50939
  // worker/index.ts
50501
- import path11 from "node:path";
50940
+ import path12 from "node:path";
50502
50941
  async function getSecret(secretArn, retries = 3) {
50503
50942
  const { SecretsManagerClient, GetSecretValueCommand } = await Promise.resolve().then(() => __toESM(require_dist_cjs53(), 1));
50504
50943
  const client = new SecretsManagerClient({});
@@ -50536,7 +50975,7 @@ async function main() {
50536
50975
  if (!clerkSecretKey && process.env.CLERK_SECRET_KEY_SECRET_ARN) {
50537
50976
  clerkSecretKey = await getSecret(process.env.CLERK_SECRET_KEY_SECRET_ARN);
50538
50977
  }
50539
- const cachePath = path11.join(workspacePath, ".cache");
50978
+ const cachePath = path12.join(workspacePath, ".cache");
50540
50979
  const refreshAuthCache = clerkSecretKey ? async () => {
50541
50980
  const result = await refreshClerkCache({
50542
50981
  secretKey: clerkSecretKey,