@clef-sh/core 0.1.17 → 0.1.19

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 (56) hide show
  1. package/dist/artifact/guards.d.ts +40 -0
  2. package/dist/artifact/guards.d.ts.map +1 -0
  3. package/dist/artifact/packer.d.ts.map +1 -1
  4. package/dist/artifact/types.d.ts +11 -2
  5. package/dist/artifact/types.d.ts.map +1 -1
  6. package/dist/compliance/generator.d.ts.map +1 -1
  7. package/dist/compliance/run.d.ts +19 -0
  8. package/dist/compliance/run.d.ts.map +1 -1
  9. package/dist/git/integration.d.ts +8 -5
  10. package/dist/git/integration.d.ts.map +1 -1
  11. package/dist/hsm/bundled.d.ts +10 -0
  12. package/dist/hsm/bundled.d.ts.map +1 -0
  13. package/dist/hsm/index.d.ts +4 -0
  14. package/dist/hsm/index.d.ts.map +1 -0
  15. package/dist/hsm/keyservice.d.ts +36 -0
  16. package/dist/hsm/keyservice.d.ts.map +1 -0
  17. package/dist/hsm/resolver.d.ts +22 -0
  18. package/dist/hsm/resolver.d.ts.map +1 -0
  19. package/dist/import/index.d.ts +7 -0
  20. package/dist/import/index.d.ts.map +1 -1
  21. package/dist/index.d.mts +14 -4
  22. package/dist/index.d.ts +14 -4
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1129 -385
  25. package/dist/index.js.map +4 -4
  26. package/dist/index.mjs +1107 -381
  27. package/dist/index.mjs.map +4 -4
  28. package/dist/lint/runner.d.ts +7 -0
  29. package/dist/lint/runner.d.ts.map +1 -1
  30. package/dist/manifest/parser.d.ts.map +1 -1
  31. package/dist/merge/metadata-driver.d.ts +17 -0
  32. package/dist/merge/metadata-driver.d.ts.map +1 -0
  33. package/dist/migration/backend.d.ts.map +1 -1
  34. package/dist/pack/backends/json-envelope.d.ts +33 -0
  35. package/dist/pack/backends/json-envelope.d.ts.map +1 -0
  36. package/dist/pack/registry.d.ts +27 -0
  37. package/dist/pack/registry.d.ts.map +1 -0
  38. package/dist/pack/types.d.ts +78 -0
  39. package/dist/pack/types.d.ts.map +1 -0
  40. package/dist/pending/metadata.d.ts +40 -15
  41. package/dist/pending/metadata.d.ts.map +1 -1
  42. package/dist/policy/evaluator.d.ts +19 -9
  43. package/dist/policy/evaluator.d.ts.map +1 -1
  44. package/dist/policy/types.d.ts +40 -9
  45. package/dist/policy/types.d.ts.map +1 -1
  46. package/dist/scanner/index.d.ts +9 -1
  47. package/dist/scanner/index.d.ts.map +1 -1
  48. package/dist/scanner/patterns.d.ts +12 -0
  49. package/dist/scanner/patterns.d.ts.map +1 -1
  50. package/dist/sops/client.d.ts +11 -1
  51. package/dist/sops/client.d.ts.map +1 -1
  52. package/dist/sops/hsm-arn.d.ts +51 -0
  53. package/dist/sops/hsm-arn.d.ts.map +1 -0
  54. package/dist/types/index.d.ts +18 -2
  55. package/dist/types/index.d.ts.map +1 -1
  56. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -301,13 +301,13 @@ var require_lib = __commonJS({
301
301
  "node_modules/write-file-atomic/lib/index.js"(exports, module) {
302
302
  "use strict";
303
303
  module.exports = writeFile;
304
- module.exports.sync = writeFileSync6;
304
+ module.exports.sync = writeFileSync7;
305
305
  module.exports._getTmpname = getTmpname;
306
306
  module.exports._cleanupOnExit = cleanupOnExit;
307
- var fs18 = __require("fs");
307
+ var fs21 = __require("fs");
308
308
  var crypto4 = __require("node:crypto");
309
309
  var { onExit } = require_cjs();
310
- var path26 = __require("path");
310
+ var path28 = __require("path");
311
311
  var { promisify } = __require("util");
312
312
  var activeFiles = {};
313
313
  var threadId = (function getId() {
@@ -325,7 +325,7 @@ var require_lib = __commonJS({
325
325
  function cleanupOnExit(tmpfile) {
326
326
  return () => {
327
327
  try {
328
- fs18.unlinkSync(typeof tmpfile === "function" ? tmpfile() : tmpfile);
328
+ fs21.unlinkSync(typeof tmpfile === "function" ? tmpfile() : tmpfile);
329
329
  } catch {
330
330
  }
331
331
  };
@@ -360,13 +360,13 @@ var require_lib = __commonJS({
360
360
  let fd;
361
361
  let tmpfile;
362
362
  const removeOnExitHandler = onExit(cleanupOnExit(() => tmpfile));
363
- const absoluteName = path26.resolve(filename);
363
+ const absoluteName = path28.resolve(filename);
364
364
  try {
365
365
  await serializeActiveFile(absoluteName);
366
- const truename = await promisify(fs18.realpath)(filename).catch(() => filename);
366
+ const truename = await promisify(fs21.realpath)(filename).catch(() => filename);
367
367
  tmpfile = getTmpname(truename);
368
368
  if (!options.mode || !options.chown) {
369
- const stats = await promisify(fs18.stat)(truename).catch(() => {
369
+ const stats = await promisify(fs21.stat)(truename).catch(() => {
370
370
  });
371
371
  if (stats) {
372
372
  if (options.mode == null) {
@@ -377,45 +377,45 @@ var require_lib = __commonJS({
377
377
  }
378
378
  }
379
379
  }
380
- fd = await promisify(fs18.open)(tmpfile, "w", options.mode);
380
+ fd = await promisify(fs21.open)(tmpfile, "w", options.mode);
381
381
  if (options.tmpfileCreated) {
382
382
  await options.tmpfileCreated(tmpfile);
383
383
  }
384
384
  if (ArrayBuffer.isView(data)) {
385
- await promisify(fs18.write)(fd, data, 0, data.length, 0);
385
+ await promisify(fs21.write)(fd, data, 0, data.length, 0);
386
386
  } else if (data != null) {
387
- await promisify(fs18.write)(fd, String(data), 0, String(options.encoding || "utf8"));
387
+ await promisify(fs21.write)(fd, String(data), 0, String(options.encoding || "utf8"));
388
388
  }
389
389
  if (options.fsync !== false) {
390
- await promisify(fs18.fsync)(fd);
390
+ await promisify(fs21.fsync)(fd);
391
391
  }
392
- await promisify(fs18.close)(fd);
392
+ await promisify(fs21.close)(fd);
393
393
  fd = null;
394
394
  if (options.chown) {
395
- await promisify(fs18.chown)(tmpfile, options.chown.uid, options.chown.gid).catch((err) => {
395
+ await promisify(fs21.chown)(tmpfile, options.chown.uid, options.chown.gid).catch((err) => {
396
396
  if (!isChownErrOk(err)) {
397
397
  throw err;
398
398
  }
399
399
  });
400
400
  }
401
401
  if (options.mode) {
402
- await promisify(fs18.chmod)(tmpfile, options.mode).catch((err) => {
402
+ await promisify(fs21.chmod)(tmpfile, options.mode).catch((err) => {
403
403
  if (!isChownErrOk(err)) {
404
404
  throw err;
405
405
  }
406
406
  });
407
407
  }
408
- await promisify(fs18.rename)(tmpfile, truename);
408
+ await promisify(fs21.rename)(tmpfile, truename);
409
409
  } finally {
410
410
  if (fd) {
411
- await promisify(fs18.close)(fd).catch(
411
+ await promisify(fs21.close)(fd).catch(
412
412
  /* istanbul ignore next */
413
413
  () => {
414
414
  }
415
415
  );
416
416
  }
417
417
  removeOnExitHandler();
418
- await promisify(fs18.unlink)(tmpfile).catch(() => {
418
+ await promisify(fs21.unlink)(tmpfile).catch(() => {
419
419
  });
420
420
  activeFiles[absoluteName].shift();
421
421
  if (activeFiles[absoluteName].length > 0) {
@@ -441,20 +441,20 @@ var require_lib = __commonJS({
441
441
  }
442
442
  return promise;
443
443
  }
444
- function writeFileSync6(filename, data, options) {
444
+ function writeFileSync7(filename, data, options) {
445
445
  if (typeof options === "string") {
446
446
  options = { encoding: options };
447
447
  } else if (!options) {
448
448
  options = {};
449
449
  }
450
450
  try {
451
- filename = fs18.realpathSync(filename);
451
+ filename = fs21.realpathSync(filename);
452
452
  } catch (ex) {
453
453
  }
454
454
  const tmpfile = getTmpname(filename);
455
455
  if (!options.mode || !options.chown) {
456
456
  try {
457
- const stats = fs18.statSync(filename);
457
+ const stats = fs21.statSync(filename);
458
458
  options = Object.assign({}, options);
459
459
  if (!options.mode) {
460
460
  options.mode = stats.mode;
@@ -470,23 +470,23 @@ var require_lib = __commonJS({
470
470
  const removeOnExitHandler = onExit(cleanup);
471
471
  let threw = true;
472
472
  try {
473
- fd = fs18.openSync(tmpfile, "w", options.mode || 438);
473
+ fd = fs21.openSync(tmpfile, "w", options.mode || 438);
474
474
  if (options.tmpfileCreated) {
475
475
  options.tmpfileCreated(tmpfile);
476
476
  }
477
477
  if (ArrayBuffer.isView(data)) {
478
- fs18.writeSync(fd, data, 0, data.length, 0);
478
+ fs21.writeSync(fd, data, 0, data.length, 0);
479
479
  } else if (data != null) {
480
- fs18.writeSync(fd, String(data), 0, String(options.encoding || "utf8"));
480
+ fs21.writeSync(fd, String(data), 0, String(options.encoding || "utf8"));
481
481
  }
482
482
  if (options.fsync !== false) {
483
- fs18.fsyncSync(fd);
483
+ fs21.fsyncSync(fd);
484
484
  }
485
- fs18.closeSync(fd);
485
+ fs21.closeSync(fd);
486
486
  fd = null;
487
487
  if (options.chown) {
488
488
  try {
489
- fs18.chownSync(tmpfile, options.chown.uid, options.chown.gid);
489
+ fs21.chownSync(tmpfile, options.chown.uid, options.chown.gid);
490
490
  } catch (err) {
491
491
  if (!isChownErrOk(err)) {
492
492
  throw err;
@@ -495,19 +495,19 @@ var require_lib = __commonJS({
495
495
  }
496
496
  if (options.mode) {
497
497
  try {
498
- fs18.chmodSync(tmpfile, options.mode);
498
+ fs21.chmodSync(tmpfile, options.mode);
499
499
  } catch (err) {
500
500
  if (!isChownErrOk(err)) {
501
501
  throw err;
502
502
  }
503
503
  }
504
504
  }
505
- fs18.renameSync(tmpfile, filename);
505
+ fs21.renameSync(tmpfile, filename);
506
506
  threw = false;
507
507
  } finally {
508
508
  if (fd) {
509
509
  try {
510
- fs18.closeSync(fd);
510
+ fs21.closeSync(fd);
511
511
  } catch (ex) {
512
512
  }
513
513
  }
@@ -546,54 +546,54 @@ var require_polyfills = __commonJS({
546
546
  }
547
547
  var chdir;
548
548
  module.exports = patch;
549
- function patch(fs18) {
549
+ function patch(fs21) {
550
550
  if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
551
- patchLchmod(fs18);
552
- }
553
- if (!fs18.lutimes) {
554
- patchLutimes(fs18);
555
- }
556
- fs18.chown = chownFix(fs18.chown);
557
- fs18.fchown = chownFix(fs18.fchown);
558
- fs18.lchown = chownFix(fs18.lchown);
559
- fs18.chmod = chmodFix(fs18.chmod);
560
- fs18.fchmod = chmodFix(fs18.fchmod);
561
- fs18.lchmod = chmodFix(fs18.lchmod);
562
- fs18.chownSync = chownFixSync(fs18.chownSync);
563
- fs18.fchownSync = chownFixSync(fs18.fchownSync);
564
- fs18.lchownSync = chownFixSync(fs18.lchownSync);
565
- fs18.chmodSync = chmodFixSync(fs18.chmodSync);
566
- fs18.fchmodSync = chmodFixSync(fs18.fchmodSync);
567
- fs18.lchmodSync = chmodFixSync(fs18.lchmodSync);
568
- fs18.stat = statFix(fs18.stat);
569
- fs18.fstat = statFix(fs18.fstat);
570
- fs18.lstat = statFix(fs18.lstat);
571
- fs18.statSync = statFixSync(fs18.statSync);
572
- fs18.fstatSync = statFixSync(fs18.fstatSync);
573
- fs18.lstatSync = statFixSync(fs18.lstatSync);
574
- if (fs18.chmod && !fs18.lchmod) {
575
- fs18.lchmod = function(path26, mode, cb) {
551
+ patchLchmod(fs21);
552
+ }
553
+ if (!fs21.lutimes) {
554
+ patchLutimes(fs21);
555
+ }
556
+ fs21.chown = chownFix(fs21.chown);
557
+ fs21.fchown = chownFix(fs21.fchown);
558
+ fs21.lchown = chownFix(fs21.lchown);
559
+ fs21.chmod = chmodFix(fs21.chmod);
560
+ fs21.fchmod = chmodFix(fs21.fchmod);
561
+ fs21.lchmod = chmodFix(fs21.lchmod);
562
+ fs21.chownSync = chownFixSync(fs21.chownSync);
563
+ fs21.fchownSync = chownFixSync(fs21.fchownSync);
564
+ fs21.lchownSync = chownFixSync(fs21.lchownSync);
565
+ fs21.chmodSync = chmodFixSync(fs21.chmodSync);
566
+ fs21.fchmodSync = chmodFixSync(fs21.fchmodSync);
567
+ fs21.lchmodSync = chmodFixSync(fs21.lchmodSync);
568
+ fs21.stat = statFix(fs21.stat);
569
+ fs21.fstat = statFix(fs21.fstat);
570
+ fs21.lstat = statFix(fs21.lstat);
571
+ fs21.statSync = statFixSync(fs21.statSync);
572
+ fs21.fstatSync = statFixSync(fs21.fstatSync);
573
+ fs21.lstatSync = statFixSync(fs21.lstatSync);
574
+ if (fs21.chmod && !fs21.lchmod) {
575
+ fs21.lchmod = function(path28, mode, cb) {
576
576
  if (cb) process.nextTick(cb);
577
577
  };
578
- fs18.lchmodSync = function() {
578
+ fs21.lchmodSync = function() {
579
579
  };
580
580
  }
581
- if (fs18.chown && !fs18.lchown) {
582
- fs18.lchown = function(path26, uid, gid, cb) {
581
+ if (fs21.chown && !fs21.lchown) {
582
+ fs21.lchown = function(path28, uid, gid, cb) {
583
583
  if (cb) process.nextTick(cb);
584
584
  };
585
- fs18.lchownSync = function() {
585
+ fs21.lchownSync = function() {
586
586
  };
587
587
  }
588
588
  if (platform === "win32") {
589
- fs18.rename = typeof fs18.rename !== "function" ? fs18.rename : (function(fs$rename) {
589
+ fs21.rename = typeof fs21.rename !== "function" ? fs21.rename : (function(fs$rename) {
590
590
  function rename(from, to, cb) {
591
591
  var start = Date.now();
592
592
  var backoff = 0;
593
593
  fs$rename(from, to, function CB(er) {
594
594
  if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 6e4) {
595
595
  setTimeout(function() {
596
- fs18.stat(to, function(stater, st) {
596
+ fs21.stat(to, function(stater, st) {
597
597
  if (stater && stater.code === "ENOENT")
598
598
  fs$rename(from, to, CB);
599
599
  else
@@ -609,9 +609,9 @@ var require_polyfills = __commonJS({
609
609
  }
610
610
  if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename);
611
611
  return rename;
612
- })(fs18.rename);
612
+ })(fs21.rename);
613
613
  }
614
- fs18.read = typeof fs18.read !== "function" ? fs18.read : (function(fs$read) {
614
+ fs21.read = typeof fs21.read !== "function" ? fs21.read : (function(fs$read) {
615
615
  function read(fd, buffer, offset, length, position, callback_) {
616
616
  var callback;
617
617
  if (callback_ && typeof callback_ === "function") {
@@ -619,22 +619,22 @@ var require_polyfills = __commonJS({
619
619
  callback = function(er, _, __) {
620
620
  if (er && er.code === "EAGAIN" && eagCounter < 10) {
621
621
  eagCounter++;
622
- return fs$read.call(fs18, fd, buffer, offset, length, position, callback);
622
+ return fs$read.call(fs21, fd, buffer, offset, length, position, callback);
623
623
  }
624
624
  callback_.apply(this, arguments);
625
625
  };
626
626
  }
627
- return fs$read.call(fs18, fd, buffer, offset, length, position, callback);
627
+ return fs$read.call(fs21, fd, buffer, offset, length, position, callback);
628
628
  }
629
629
  if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read);
630
630
  return read;
631
- })(fs18.read);
632
- fs18.readSync = typeof fs18.readSync !== "function" ? fs18.readSync : /* @__PURE__ */ (function(fs$readSync) {
631
+ })(fs21.read);
632
+ fs21.readSync = typeof fs21.readSync !== "function" ? fs21.readSync : /* @__PURE__ */ (function(fs$readSync) {
633
633
  return function(fd, buffer, offset, length, position) {
634
634
  var eagCounter = 0;
635
635
  while (true) {
636
636
  try {
637
- return fs$readSync.call(fs18, fd, buffer, offset, length, position);
637
+ return fs$readSync.call(fs21, fd, buffer, offset, length, position);
638
638
  } catch (er) {
639
639
  if (er.code === "EAGAIN" && eagCounter < 10) {
640
640
  eagCounter++;
@@ -644,11 +644,11 @@ var require_polyfills = __commonJS({
644
644
  }
645
645
  }
646
646
  };
647
- })(fs18.readSync);
648
- function patchLchmod(fs19) {
649
- fs19.lchmod = function(path26, mode, callback) {
650
- fs19.open(
651
- path26,
647
+ })(fs21.readSync);
648
+ function patchLchmod(fs22) {
649
+ fs22.lchmod = function(path28, mode, callback) {
650
+ fs22.open(
651
+ path28,
652
652
  constants.O_WRONLY | constants.O_SYMLINK,
653
653
  mode,
654
654
  function(err, fd) {
@@ -656,80 +656,80 @@ var require_polyfills = __commonJS({
656
656
  if (callback) callback(err);
657
657
  return;
658
658
  }
659
- fs19.fchmod(fd, mode, function(err2) {
660
- fs19.close(fd, function(err22) {
659
+ fs22.fchmod(fd, mode, function(err2) {
660
+ fs22.close(fd, function(err22) {
661
661
  if (callback) callback(err2 || err22);
662
662
  });
663
663
  });
664
664
  }
665
665
  );
666
666
  };
667
- fs19.lchmodSync = function(path26, mode) {
668
- var fd = fs19.openSync(path26, constants.O_WRONLY | constants.O_SYMLINK, mode);
667
+ fs22.lchmodSync = function(path28, mode) {
668
+ var fd = fs22.openSync(path28, constants.O_WRONLY | constants.O_SYMLINK, mode);
669
669
  var threw = true;
670
670
  var ret;
671
671
  try {
672
- ret = fs19.fchmodSync(fd, mode);
672
+ ret = fs22.fchmodSync(fd, mode);
673
673
  threw = false;
674
674
  } finally {
675
675
  if (threw) {
676
676
  try {
677
- fs19.closeSync(fd);
677
+ fs22.closeSync(fd);
678
678
  } catch (er) {
679
679
  }
680
680
  } else {
681
- fs19.closeSync(fd);
681
+ fs22.closeSync(fd);
682
682
  }
683
683
  }
684
684
  return ret;
685
685
  };
686
686
  }
687
- function patchLutimes(fs19) {
688
- if (constants.hasOwnProperty("O_SYMLINK") && fs19.futimes) {
689
- fs19.lutimes = function(path26, at, mt, cb) {
690
- fs19.open(path26, constants.O_SYMLINK, function(er, fd) {
687
+ function patchLutimes(fs22) {
688
+ if (constants.hasOwnProperty("O_SYMLINK") && fs22.futimes) {
689
+ fs22.lutimes = function(path28, at, mt, cb) {
690
+ fs22.open(path28, constants.O_SYMLINK, function(er, fd) {
691
691
  if (er) {
692
692
  if (cb) cb(er);
693
693
  return;
694
694
  }
695
- fs19.futimes(fd, at, mt, function(er2) {
696
- fs19.close(fd, function(er22) {
695
+ fs22.futimes(fd, at, mt, function(er2) {
696
+ fs22.close(fd, function(er22) {
697
697
  if (cb) cb(er2 || er22);
698
698
  });
699
699
  });
700
700
  });
701
701
  };
702
- fs19.lutimesSync = function(path26, at, mt) {
703
- var fd = fs19.openSync(path26, constants.O_SYMLINK);
702
+ fs22.lutimesSync = function(path28, at, mt) {
703
+ var fd = fs22.openSync(path28, constants.O_SYMLINK);
704
704
  var ret;
705
705
  var threw = true;
706
706
  try {
707
- ret = fs19.futimesSync(fd, at, mt);
707
+ ret = fs22.futimesSync(fd, at, mt);
708
708
  threw = false;
709
709
  } finally {
710
710
  if (threw) {
711
711
  try {
712
- fs19.closeSync(fd);
712
+ fs22.closeSync(fd);
713
713
  } catch (er) {
714
714
  }
715
715
  } else {
716
- fs19.closeSync(fd);
716
+ fs22.closeSync(fd);
717
717
  }
718
718
  }
719
719
  return ret;
720
720
  };
721
- } else if (fs19.futimes) {
722
- fs19.lutimes = function(_a, _b, _c, cb) {
721
+ } else if (fs22.futimes) {
722
+ fs22.lutimes = function(_a, _b, _c, cb) {
723
723
  if (cb) process.nextTick(cb);
724
724
  };
725
- fs19.lutimesSync = function() {
725
+ fs22.lutimesSync = function() {
726
726
  };
727
727
  }
728
728
  }
729
729
  function chmodFix(orig) {
730
730
  if (!orig) return orig;
731
731
  return function(target, mode, cb) {
732
- return orig.call(fs18, target, mode, function(er) {
732
+ return orig.call(fs21, target, mode, function(er) {
733
733
  if (chownErOk(er)) er = null;
734
734
  if (cb) cb.apply(this, arguments);
735
735
  });
@@ -739,7 +739,7 @@ var require_polyfills = __commonJS({
739
739
  if (!orig) return orig;
740
740
  return function(target, mode) {
741
741
  try {
742
- return orig.call(fs18, target, mode);
742
+ return orig.call(fs21, target, mode);
743
743
  } catch (er) {
744
744
  if (!chownErOk(er)) throw er;
745
745
  }
@@ -748,7 +748,7 @@ var require_polyfills = __commonJS({
748
748
  function chownFix(orig) {
749
749
  if (!orig) return orig;
750
750
  return function(target, uid, gid, cb) {
751
- return orig.call(fs18, target, uid, gid, function(er) {
751
+ return orig.call(fs21, target, uid, gid, function(er) {
752
752
  if (chownErOk(er)) er = null;
753
753
  if (cb) cb.apply(this, arguments);
754
754
  });
@@ -758,7 +758,7 @@ var require_polyfills = __commonJS({
758
758
  if (!orig) return orig;
759
759
  return function(target, uid, gid) {
760
760
  try {
761
- return orig.call(fs18, target, uid, gid);
761
+ return orig.call(fs21, target, uid, gid);
762
762
  } catch (er) {
763
763
  if (!chownErOk(er)) throw er;
764
764
  }
@@ -778,13 +778,13 @@ var require_polyfills = __commonJS({
778
778
  }
779
779
  if (cb) cb.apply(this, arguments);
780
780
  }
781
- return options ? orig.call(fs18, target, options, callback) : orig.call(fs18, target, callback);
781
+ return options ? orig.call(fs21, target, options, callback) : orig.call(fs21, target, callback);
782
782
  };
783
783
  }
784
784
  function statFixSync(orig) {
785
785
  if (!orig) return orig;
786
786
  return function(target, options) {
787
- var stats = options ? orig.call(fs18, target, options) : orig.call(fs18, target);
787
+ var stats = options ? orig.call(fs21, target, options) : orig.call(fs21, target);
788
788
  if (stats) {
789
789
  if (stats.uid < 0) stats.uid += 4294967296;
790
790
  if (stats.gid < 0) stats.gid += 4294967296;
@@ -813,16 +813,16 @@ var require_legacy_streams = __commonJS({
813
813
  "../../node_modules/graceful-fs/legacy-streams.js"(exports, module) {
814
814
  var Stream = __require("stream").Stream;
815
815
  module.exports = legacy;
816
- function legacy(fs18) {
816
+ function legacy(fs21) {
817
817
  return {
818
818
  ReadStream,
819
819
  WriteStream
820
820
  };
821
- function ReadStream(path26, options) {
822
- if (!(this instanceof ReadStream)) return new ReadStream(path26, options);
821
+ function ReadStream(path28, options) {
822
+ if (!(this instanceof ReadStream)) return new ReadStream(path28, options);
823
823
  Stream.call(this);
824
824
  var self = this;
825
- this.path = path26;
825
+ this.path = path28;
826
826
  this.fd = null;
827
827
  this.readable = true;
828
828
  this.paused = false;
@@ -856,7 +856,7 @@ var require_legacy_streams = __commonJS({
856
856
  });
857
857
  return;
858
858
  }
859
- fs18.open(this.path, this.flags, this.mode, function(err, fd) {
859
+ fs21.open(this.path, this.flags, this.mode, function(err, fd) {
860
860
  if (err) {
861
861
  self.emit("error", err);
862
862
  self.readable = false;
@@ -867,10 +867,10 @@ var require_legacy_streams = __commonJS({
867
867
  self._read();
868
868
  });
869
869
  }
870
- function WriteStream(path26, options) {
871
- if (!(this instanceof WriteStream)) return new WriteStream(path26, options);
870
+ function WriteStream(path28, options) {
871
+ if (!(this instanceof WriteStream)) return new WriteStream(path28, options);
872
872
  Stream.call(this);
873
- this.path = path26;
873
+ this.path = path28;
874
874
  this.fd = null;
875
875
  this.writable = true;
876
876
  this.flags = "w";
@@ -895,7 +895,7 @@ var require_legacy_streams = __commonJS({
895
895
  this.busy = false;
896
896
  this._queue = [];
897
897
  if (this.fd === null) {
898
- this._open = fs18.open;
898
+ this._open = fs21.open;
899
899
  this._queue.push([this._open, this.path, this.flags, this.mode, void 0]);
900
900
  this.flush();
901
901
  }
@@ -930,7 +930,7 @@ var require_clone = __commonJS({
930
930
  // ../../node_modules/graceful-fs/graceful-fs.js
931
931
  var require_graceful_fs = __commonJS({
932
932
  "../../node_modules/graceful-fs/graceful-fs.js"(exports, module) {
933
- var fs18 = __require("fs");
933
+ var fs21 = __require("fs");
934
934
  var polyfills = require_polyfills();
935
935
  var legacy = require_legacy_streams();
936
936
  var clone = require_clone();
@@ -962,12 +962,12 @@ var require_graceful_fs = __commonJS({
962
962
  m = "GFS4: " + m.split(/\n/).join("\nGFS4: ");
963
963
  console.error(m);
964
964
  };
965
- if (!fs18[gracefulQueue]) {
965
+ if (!fs21[gracefulQueue]) {
966
966
  queue = global[gracefulQueue] || [];
967
- publishQueue(fs18, queue);
968
- fs18.close = (function(fs$close) {
967
+ publishQueue(fs21, queue);
968
+ fs21.close = (function(fs$close) {
969
969
  function close(fd, cb) {
970
- return fs$close.call(fs18, fd, function(err) {
970
+ return fs$close.call(fs21, fd, function(err) {
971
971
  if (!err) {
972
972
  resetQueue();
973
973
  }
@@ -979,48 +979,48 @@ var require_graceful_fs = __commonJS({
979
979
  value: fs$close
980
980
  });
981
981
  return close;
982
- })(fs18.close);
983
- fs18.closeSync = (function(fs$closeSync) {
982
+ })(fs21.close);
983
+ fs21.closeSync = (function(fs$closeSync) {
984
984
  function closeSync2(fd) {
985
- fs$closeSync.apply(fs18, arguments);
985
+ fs$closeSync.apply(fs21, arguments);
986
986
  resetQueue();
987
987
  }
988
988
  Object.defineProperty(closeSync2, previousSymbol, {
989
989
  value: fs$closeSync
990
990
  });
991
991
  return closeSync2;
992
- })(fs18.closeSync);
992
+ })(fs21.closeSync);
993
993
  if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
994
994
  process.on("exit", function() {
995
- debug(fs18[gracefulQueue]);
996
- __require("assert").equal(fs18[gracefulQueue].length, 0);
995
+ debug(fs21[gracefulQueue]);
996
+ __require("assert").equal(fs21[gracefulQueue].length, 0);
997
997
  });
998
998
  }
999
999
  }
1000
1000
  var queue;
1001
1001
  if (!global[gracefulQueue]) {
1002
- publishQueue(global, fs18[gracefulQueue]);
1003
- }
1004
- module.exports = patch(clone(fs18));
1005
- if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs18.__patched) {
1006
- module.exports = patch(fs18);
1007
- fs18.__patched = true;
1008
- }
1009
- function patch(fs19) {
1010
- polyfills(fs19);
1011
- fs19.gracefulify = patch;
1012
- fs19.createReadStream = createReadStream;
1013
- fs19.createWriteStream = createWriteStream;
1014
- var fs$readFile = fs19.readFile;
1015
- fs19.readFile = readFile;
1016
- function readFile(path26, options, cb) {
1002
+ publishQueue(global, fs21[gracefulQueue]);
1003
+ }
1004
+ module.exports = patch(clone(fs21));
1005
+ if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs21.__patched) {
1006
+ module.exports = patch(fs21);
1007
+ fs21.__patched = true;
1008
+ }
1009
+ function patch(fs22) {
1010
+ polyfills(fs22);
1011
+ fs22.gracefulify = patch;
1012
+ fs22.createReadStream = createReadStream;
1013
+ fs22.createWriteStream = createWriteStream;
1014
+ var fs$readFile = fs22.readFile;
1015
+ fs22.readFile = readFile;
1016
+ function readFile(path28, options, cb) {
1017
1017
  if (typeof options === "function")
1018
1018
  cb = options, options = null;
1019
- return go$readFile(path26, options, cb);
1020
- function go$readFile(path27, options2, cb2, startTime) {
1021
- return fs$readFile(path27, options2, function(err) {
1019
+ return go$readFile(path28, options, cb);
1020
+ function go$readFile(path29, options2, cb2, startTime) {
1021
+ return fs$readFile(path29, options2, function(err) {
1022
1022
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1023
- enqueue([go$readFile, [path27, options2, cb2], err, startTime || Date.now(), Date.now()]);
1023
+ enqueue([go$readFile, [path29, options2, cb2], err, startTime || Date.now(), Date.now()]);
1024
1024
  else {
1025
1025
  if (typeof cb2 === "function")
1026
1026
  cb2.apply(this, arguments);
@@ -1028,16 +1028,16 @@ var require_graceful_fs = __commonJS({
1028
1028
  });
1029
1029
  }
1030
1030
  }
1031
- var fs$writeFile = fs19.writeFile;
1032
- fs19.writeFile = writeFile;
1033
- function writeFile(path26, data, options, cb) {
1031
+ var fs$writeFile = fs22.writeFile;
1032
+ fs22.writeFile = writeFile;
1033
+ function writeFile(path28, data, options, cb) {
1034
1034
  if (typeof options === "function")
1035
1035
  cb = options, options = null;
1036
- return go$writeFile(path26, data, options, cb);
1037
- function go$writeFile(path27, data2, options2, cb2, startTime) {
1038
- return fs$writeFile(path27, data2, options2, function(err) {
1036
+ return go$writeFile(path28, data, options, cb);
1037
+ function go$writeFile(path29, data2, options2, cb2, startTime) {
1038
+ return fs$writeFile(path29, data2, options2, function(err) {
1039
1039
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1040
- enqueue([go$writeFile, [path27, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
1040
+ enqueue([go$writeFile, [path29, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
1041
1041
  else {
1042
1042
  if (typeof cb2 === "function")
1043
1043
  cb2.apply(this, arguments);
@@ -1045,17 +1045,17 @@ var require_graceful_fs = __commonJS({
1045
1045
  });
1046
1046
  }
1047
1047
  }
1048
- var fs$appendFile = fs19.appendFile;
1048
+ var fs$appendFile = fs22.appendFile;
1049
1049
  if (fs$appendFile)
1050
- fs19.appendFile = appendFile;
1051
- function appendFile(path26, data, options, cb) {
1050
+ fs22.appendFile = appendFile;
1051
+ function appendFile(path28, data, options, cb) {
1052
1052
  if (typeof options === "function")
1053
1053
  cb = options, options = null;
1054
- return go$appendFile(path26, data, options, cb);
1055
- function go$appendFile(path27, data2, options2, cb2, startTime) {
1056
- return fs$appendFile(path27, data2, options2, function(err) {
1054
+ return go$appendFile(path28, data, options, cb);
1055
+ function go$appendFile(path29, data2, options2, cb2, startTime) {
1056
+ return fs$appendFile(path29, data2, options2, function(err) {
1057
1057
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1058
- enqueue([go$appendFile, [path27, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
1058
+ enqueue([go$appendFile, [path29, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
1059
1059
  else {
1060
1060
  if (typeof cb2 === "function")
1061
1061
  cb2.apply(this, arguments);
@@ -1063,9 +1063,9 @@ var require_graceful_fs = __commonJS({
1063
1063
  });
1064
1064
  }
1065
1065
  }
1066
- var fs$copyFile = fs19.copyFile;
1066
+ var fs$copyFile = fs22.copyFile;
1067
1067
  if (fs$copyFile)
1068
- fs19.copyFile = copyFile;
1068
+ fs22.copyFile = copyFile;
1069
1069
  function copyFile(src, dest, flags, cb) {
1070
1070
  if (typeof flags === "function") {
1071
1071
  cb = flags;
@@ -1083,34 +1083,34 @@ var require_graceful_fs = __commonJS({
1083
1083
  });
1084
1084
  }
1085
1085
  }
1086
- var fs$readdir = fs19.readdir;
1087
- fs19.readdir = readdir;
1086
+ var fs$readdir = fs22.readdir;
1087
+ fs22.readdir = readdir;
1088
1088
  var noReaddirOptionVersions = /^v[0-5]\./;
1089
- function readdir(path26, options, cb) {
1089
+ function readdir(path28, options, cb) {
1090
1090
  if (typeof options === "function")
1091
1091
  cb = options, options = null;
1092
- var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path27, options2, cb2, startTime) {
1093
- return fs$readdir(path27, fs$readdirCallback(
1094
- path27,
1092
+ var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path29, options2, cb2, startTime) {
1093
+ return fs$readdir(path29, fs$readdirCallback(
1094
+ path29,
1095
1095
  options2,
1096
1096
  cb2,
1097
1097
  startTime
1098
1098
  ));
1099
- } : function go$readdir2(path27, options2, cb2, startTime) {
1100
- return fs$readdir(path27, options2, fs$readdirCallback(
1101
- path27,
1099
+ } : function go$readdir2(path29, options2, cb2, startTime) {
1100
+ return fs$readdir(path29, options2, fs$readdirCallback(
1101
+ path29,
1102
1102
  options2,
1103
1103
  cb2,
1104
1104
  startTime
1105
1105
  ));
1106
1106
  };
1107
- return go$readdir(path26, options, cb);
1108
- function fs$readdirCallback(path27, options2, cb2, startTime) {
1107
+ return go$readdir(path28, options, cb);
1108
+ function fs$readdirCallback(path29, options2, cb2, startTime) {
1109
1109
  return function(err, files) {
1110
1110
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1111
1111
  enqueue([
1112
1112
  go$readdir,
1113
- [path27, options2, cb2],
1113
+ [path29, options2, cb2],
1114
1114
  err,
1115
1115
  startTime || Date.now(),
1116
1116
  Date.now()
@@ -1125,21 +1125,21 @@ var require_graceful_fs = __commonJS({
1125
1125
  }
1126
1126
  }
1127
1127
  if (process.version.substr(0, 4) === "v0.8") {
1128
- var legStreams = legacy(fs19);
1128
+ var legStreams = legacy(fs22);
1129
1129
  ReadStream = legStreams.ReadStream;
1130
1130
  WriteStream = legStreams.WriteStream;
1131
1131
  }
1132
- var fs$ReadStream = fs19.ReadStream;
1132
+ var fs$ReadStream = fs22.ReadStream;
1133
1133
  if (fs$ReadStream) {
1134
1134
  ReadStream.prototype = Object.create(fs$ReadStream.prototype);
1135
1135
  ReadStream.prototype.open = ReadStream$open;
1136
1136
  }
1137
- var fs$WriteStream = fs19.WriteStream;
1137
+ var fs$WriteStream = fs22.WriteStream;
1138
1138
  if (fs$WriteStream) {
1139
1139
  WriteStream.prototype = Object.create(fs$WriteStream.prototype);
1140
1140
  WriteStream.prototype.open = WriteStream$open;
1141
1141
  }
1142
- Object.defineProperty(fs19, "ReadStream", {
1142
+ Object.defineProperty(fs22, "ReadStream", {
1143
1143
  get: function() {
1144
1144
  return ReadStream;
1145
1145
  },
@@ -1149,7 +1149,7 @@ var require_graceful_fs = __commonJS({
1149
1149
  enumerable: true,
1150
1150
  configurable: true
1151
1151
  });
1152
- Object.defineProperty(fs19, "WriteStream", {
1152
+ Object.defineProperty(fs22, "WriteStream", {
1153
1153
  get: function() {
1154
1154
  return WriteStream;
1155
1155
  },
@@ -1160,7 +1160,7 @@ var require_graceful_fs = __commonJS({
1160
1160
  configurable: true
1161
1161
  });
1162
1162
  var FileReadStream = ReadStream;
1163
- Object.defineProperty(fs19, "FileReadStream", {
1163
+ Object.defineProperty(fs22, "FileReadStream", {
1164
1164
  get: function() {
1165
1165
  return FileReadStream;
1166
1166
  },
@@ -1171,7 +1171,7 @@ var require_graceful_fs = __commonJS({
1171
1171
  configurable: true
1172
1172
  });
1173
1173
  var FileWriteStream = WriteStream;
1174
- Object.defineProperty(fs19, "FileWriteStream", {
1174
+ Object.defineProperty(fs22, "FileWriteStream", {
1175
1175
  get: function() {
1176
1176
  return FileWriteStream;
1177
1177
  },
@@ -1181,7 +1181,7 @@ var require_graceful_fs = __commonJS({
1181
1181
  enumerable: true,
1182
1182
  configurable: true
1183
1183
  });
1184
- function ReadStream(path26, options) {
1184
+ function ReadStream(path28, options) {
1185
1185
  if (this instanceof ReadStream)
1186
1186
  return fs$ReadStream.apply(this, arguments), this;
1187
1187
  else
@@ -1201,7 +1201,7 @@ var require_graceful_fs = __commonJS({
1201
1201
  }
1202
1202
  });
1203
1203
  }
1204
- function WriteStream(path26, options) {
1204
+ function WriteStream(path28, options) {
1205
1205
  if (this instanceof WriteStream)
1206
1206
  return fs$WriteStream.apply(this, arguments), this;
1207
1207
  else
@@ -1219,22 +1219,22 @@ var require_graceful_fs = __commonJS({
1219
1219
  }
1220
1220
  });
1221
1221
  }
1222
- function createReadStream(path26, options) {
1223
- return new fs19.ReadStream(path26, options);
1222
+ function createReadStream(path28, options) {
1223
+ return new fs22.ReadStream(path28, options);
1224
1224
  }
1225
- function createWriteStream(path26, options) {
1226
- return new fs19.WriteStream(path26, options);
1225
+ function createWriteStream(path28, options) {
1226
+ return new fs22.WriteStream(path28, options);
1227
1227
  }
1228
- var fs$open = fs19.open;
1229
- fs19.open = open;
1230
- function open(path26, flags, mode, cb) {
1228
+ var fs$open = fs22.open;
1229
+ fs22.open = open;
1230
+ function open(path28, flags, mode, cb) {
1231
1231
  if (typeof mode === "function")
1232
1232
  cb = mode, mode = null;
1233
- return go$open(path26, flags, mode, cb);
1234
- function go$open(path27, flags2, mode2, cb2, startTime) {
1235
- return fs$open(path27, flags2, mode2, function(err, fd) {
1233
+ return go$open(path28, flags, mode, cb);
1234
+ function go$open(path29, flags2, mode2, cb2, startTime) {
1235
+ return fs$open(path29, flags2, mode2, function(err, fd) {
1236
1236
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
1237
- enqueue([go$open, [path27, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
1237
+ enqueue([go$open, [path29, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
1238
1238
  else {
1239
1239
  if (typeof cb2 === "function")
1240
1240
  cb2.apply(this, arguments);
@@ -1242,20 +1242,20 @@ var require_graceful_fs = __commonJS({
1242
1242
  });
1243
1243
  }
1244
1244
  }
1245
- return fs19;
1245
+ return fs22;
1246
1246
  }
1247
1247
  function enqueue(elem) {
1248
1248
  debug("ENQUEUE", elem[0].name, elem[1]);
1249
- fs18[gracefulQueue].push(elem);
1249
+ fs21[gracefulQueue].push(elem);
1250
1250
  retry();
1251
1251
  }
1252
1252
  var retryTimer;
1253
1253
  function resetQueue() {
1254
1254
  var now = Date.now();
1255
- for (var i = 0; i < fs18[gracefulQueue].length; ++i) {
1256
- if (fs18[gracefulQueue][i].length > 2) {
1257
- fs18[gracefulQueue][i][3] = now;
1258
- fs18[gracefulQueue][i][4] = now;
1255
+ for (var i = 0; i < fs21[gracefulQueue].length; ++i) {
1256
+ if (fs21[gracefulQueue][i].length > 2) {
1257
+ fs21[gracefulQueue][i][3] = now;
1258
+ fs21[gracefulQueue][i][4] = now;
1259
1259
  }
1260
1260
  }
1261
1261
  retry();
@@ -1263,9 +1263,9 @@ var require_graceful_fs = __commonJS({
1263
1263
  function retry() {
1264
1264
  clearTimeout(retryTimer);
1265
1265
  retryTimer = void 0;
1266
- if (fs18[gracefulQueue].length === 0)
1266
+ if (fs21[gracefulQueue].length === 0)
1267
1267
  return;
1268
- var elem = fs18[gracefulQueue].shift();
1268
+ var elem = fs21[gracefulQueue].shift();
1269
1269
  var fn = elem[0];
1270
1270
  var args = elem[1];
1271
1271
  var err = elem[2];
@@ -1287,7 +1287,7 @@ var require_graceful_fs = __commonJS({
1287
1287
  debug("RETRY", fn.name, args);
1288
1288
  fn.apply(null, args.concat([startTime]));
1289
1289
  } else {
1290
- fs18[gracefulQueue].push(elem);
1290
+ fs21[gracefulQueue].push(elem);
1291
1291
  }
1292
1292
  }
1293
1293
  if (retryTimer === void 0) {
@@ -1722,10 +1722,10 @@ var require_mtime_precision = __commonJS({
1722
1722
  "../../node_modules/proper-lockfile/lib/mtime-precision.js"(exports, module) {
1723
1723
  "use strict";
1724
1724
  var cacheSymbol = /* @__PURE__ */ Symbol();
1725
- function probe(file, fs18, callback) {
1726
- const cachedPrecision = fs18[cacheSymbol];
1725
+ function probe(file, fs21, callback) {
1726
+ const cachedPrecision = fs21[cacheSymbol];
1727
1727
  if (cachedPrecision) {
1728
- return fs18.stat(file, (err, stat) => {
1728
+ return fs21.stat(file, (err, stat) => {
1729
1729
  if (err) {
1730
1730
  return callback(err);
1731
1731
  }
@@ -1733,16 +1733,16 @@ var require_mtime_precision = __commonJS({
1733
1733
  });
1734
1734
  }
1735
1735
  const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5);
1736
- fs18.utimes(file, mtime, mtime, (err) => {
1736
+ fs21.utimes(file, mtime, mtime, (err) => {
1737
1737
  if (err) {
1738
1738
  return callback(err);
1739
1739
  }
1740
- fs18.stat(file, (err2, stat) => {
1740
+ fs21.stat(file, (err2, stat) => {
1741
1741
  if (err2) {
1742
1742
  return callback(err2);
1743
1743
  }
1744
1744
  const precision = stat.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
1745
- Object.defineProperty(fs18, cacheSymbol, { value: precision });
1745
+ Object.defineProperty(fs21, cacheSymbol, { value: precision });
1746
1746
  callback(null, stat.mtime, precision);
1747
1747
  });
1748
1748
  });
@@ -1763,8 +1763,8 @@ var require_mtime_precision = __commonJS({
1763
1763
  var require_lockfile = __commonJS({
1764
1764
  "../../node_modules/proper-lockfile/lib/lockfile.js"(exports, module) {
1765
1765
  "use strict";
1766
- var path26 = __require("path");
1767
- var fs18 = require_graceful_fs();
1766
+ var path28 = __require("path");
1767
+ var fs21 = require_graceful_fs();
1768
1768
  var retry = require_retry2();
1769
1769
  var onExit = require_signal_exit();
1770
1770
  var mtimePrecision = require_mtime_precision();
@@ -1774,7 +1774,7 @@ var require_lockfile = __commonJS({
1774
1774
  }
1775
1775
  function resolveCanonicalPath(file, options, callback) {
1776
1776
  if (!options.realpath) {
1777
- return callback(null, path26.resolve(file));
1777
+ return callback(null, path28.resolve(file));
1778
1778
  }
1779
1779
  options.fs.realpath(file, callback);
1780
1780
  }
@@ -1895,7 +1895,7 @@ var require_lockfile = __commonJS({
1895
1895
  update: null,
1896
1896
  realpath: true,
1897
1897
  retries: 0,
1898
- fs: fs18,
1898
+ fs: fs21,
1899
1899
  onCompromised: (err) => {
1900
1900
  throw err;
1901
1901
  },
@@ -1939,7 +1939,7 @@ var require_lockfile = __commonJS({
1939
1939
  }
1940
1940
  function unlock(file, options, callback) {
1941
1941
  options = {
1942
- fs: fs18,
1942
+ fs: fs21,
1943
1943
  realpath: true,
1944
1944
  ...options
1945
1945
  };
@@ -1961,7 +1961,7 @@ var require_lockfile = __commonJS({
1961
1961
  options = {
1962
1962
  stale: 1e4,
1963
1963
  realpath: true,
1964
- fs: fs18,
1964
+ fs: fs21,
1965
1965
  ...options
1966
1966
  };
1967
1967
  options.stale = Math.max(options.stale || 0, 2e3);
@@ -2000,16 +2000,16 @@ var require_lockfile = __commonJS({
2000
2000
  var require_adapter = __commonJS({
2001
2001
  "../../node_modules/proper-lockfile/lib/adapter.js"(exports, module) {
2002
2002
  "use strict";
2003
- var fs18 = require_graceful_fs();
2004
- function createSyncFs(fs19) {
2003
+ var fs21 = require_graceful_fs();
2004
+ function createSyncFs(fs22) {
2005
2005
  const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
2006
- const newFs = { ...fs19 };
2006
+ const newFs = { ...fs22 };
2007
2007
  methods.forEach((method) => {
2008
2008
  newFs[method] = (...args) => {
2009
2009
  const callback = args.pop();
2010
2010
  let ret;
2011
2011
  try {
2012
- ret = fs19[`${method}Sync`](...args);
2012
+ ret = fs22[`${method}Sync`](...args);
2013
2013
  } catch (err) {
2014
2014
  return callback(err);
2015
2015
  }
@@ -2047,7 +2047,7 @@ var require_adapter = __commonJS({
2047
2047
  }
2048
2048
  function toSyncOptions(options) {
2049
2049
  options = { ...options };
2050
- options.fs = createSyncFs(options.fs || fs18);
2050
+ options.fs = createSyncFs(options.fs || fs21);
2051
2051
  if (typeof options.retries === "number" && options.retries > 0 || options.retries && typeof options.retries.retries === "number" && options.retries.retries > 0) {
2052
2052
  throw Object.assign(new Error("Cannot use retries with the sync api"), { code: "ESYNC" });
2053
2053
  }
@@ -2107,7 +2107,8 @@ function resolveBackendConfig(manifest, environment) {
2107
2107
  aws_kms_arn: manifest.sops.aws_kms_arn,
2108
2108
  gcp_kms_resource_id: manifest.sops.gcp_kms_resource_id,
2109
2109
  azure_kv_url: manifest.sops.azure_kv_url,
2110
- pgp_fingerprint: manifest.sops.pgp_fingerprint
2110
+ pgp_fingerprint: manifest.sops.pgp_fingerprint,
2111
+ pkcs11_uri: manifest.sops.pkcs11_uri
2111
2112
  };
2112
2113
  }
2113
2114
  function resolveRecipientsForEnvironment(manifest, environment) {
@@ -2254,7 +2255,8 @@ function keyPreview(key) {
2254
2255
 
2255
2256
  // src/manifest/parser.ts
2256
2257
  var CLEF_MANIFEST_FILENAME = "clef.yaml";
2257
- var VALID_BACKENDS = ["age", "awskms", "gcpkms", "azurekv", "pgp"];
2258
+ var VALID_BACKENDS = ["age", "awskms", "gcpkms", "azurekv", "pgp", "hsm"];
2259
+ var PKCS11_URI_PATTERN = /^pkcs11:[a-zA-Z][a-zA-Z0-9_-]*=[^;]+/;
2258
2260
  var VALID_TOP_LEVEL_KEYS = [
2259
2261
  "version",
2260
2262
  "environments",
@@ -2413,12 +2415,27 @@ var ManifestParser = class {
2413
2415
  "environments"
2414
2416
  );
2415
2417
  }
2418
+ if (backend === "hsm") {
2419
+ if (typeof sopsOverride.pkcs11_uri !== "string") {
2420
+ throw new ManifestValidationError(
2421
+ `Environment '${envObj.name}' uses 'hsm' backend but is missing 'pkcs11_uri'.`,
2422
+ "environments"
2423
+ );
2424
+ }
2425
+ if (!PKCS11_URI_PATTERN.test(sopsOverride.pkcs11_uri)) {
2426
+ throw new ManifestValidationError(
2427
+ `Environment '${envObj.name}' has an invalid 'pkcs11_uri' '${sopsOverride.pkcs11_uri}'. Must start with 'pkcs11:' and contain at least one attribute (e.g. 'pkcs11:slot=0;label=clef-dek-wrapper').`,
2428
+ "environments"
2429
+ );
2430
+ }
2431
+ }
2416
2432
  result.sops = {
2417
2433
  backend,
2418
2434
  ...typeof sopsOverride.aws_kms_arn === "string" ? { aws_kms_arn: sopsOverride.aws_kms_arn } : {},
2419
2435
  ...typeof sopsOverride.gcp_kms_resource_id === "string" ? { gcp_kms_resource_id: sopsOverride.gcp_kms_resource_id } : {},
2420
2436
  ...typeof sopsOverride.azure_kv_url === "string" ? { azure_kv_url: sopsOverride.azure_kv_url } : {},
2421
- ...typeof sopsOverride.pgp_fingerprint === "string" ? { pgp_fingerprint: sopsOverride.pgp_fingerprint } : {}
2437
+ ...typeof sopsOverride.pgp_fingerprint === "string" ? { pgp_fingerprint: sopsOverride.pgp_fingerprint } : {},
2438
+ ...typeof sopsOverride.pkcs11_uri === "string" ? { pkcs11_uri: sopsOverride.pkcs11_uri } : {}
2422
2439
  };
2423
2440
  }
2424
2441
  if (envObj.recipients !== void 0) {
@@ -2550,7 +2567,7 @@ var ManifestParser = class {
2550
2567
  const sopsObj = obj.sops;
2551
2568
  if (!sopsObj.default_backend || typeof sopsObj.default_backend !== "string") {
2552
2569
  throw new ManifestValidationError(
2553
- "Field 'sops.default_backend' is required and must be one of: age, awskms, gcpkms, azurekv, pgp.",
2570
+ `Field 'sops.default_backend' is required and must be one of: ${VALID_BACKENDS.join(", ")}.`,
2554
2571
  "sops.default_backend"
2555
2572
  );
2556
2573
  }
@@ -2577,13 +2594,32 @@ var ManifestParser = class {
2577
2594
  })
2578
2595
  }
2579
2596
  } : {};
2597
+ if (sopsObj.pkcs11_uri !== void 0 && typeof sopsObj.pkcs11_uri !== "string") {
2598
+ throw new ManifestValidationError(
2599
+ "Field 'sops.pkcs11_uri' must be a string.",
2600
+ "sops.pkcs11_uri"
2601
+ );
2602
+ }
2603
+ if (typeof sopsObj.pkcs11_uri === "string" && !PKCS11_URI_PATTERN.test(sopsObj.pkcs11_uri)) {
2604
+ throw new ManifestValidationError(
2605
+ `Field 'sops.pkcs11_uri' has invalid format '${sopsObj.pkcs11_uri}'. Must start with 'pkcs11:' and contain at least one attribute (e.g. 'pkcs11:slot=0;label=clef-dek-wrapper').`,
2606
+ "sops.pkcs11_uri"
2607
+ );
2608
+ }
2609
+ if (sopsObj.default_backend === "hsm" && typeof sopsObj.pkcs11_uri !== "string") {
2610
+ throw new ManifestValidationError(
2611
+ "Field 'sops.pkcs11_uri' is required when sops.default_backend is 'hsm'.",
2612
+ "sops.pkcs11_uri"
2613
+ );
2614
+ }
2580
2615
  const sopsConfig = {
2581
2616
  default_backend: sopsObj.default_backend,
2582
2617
  ...parsedAge,
2583
2618
  ...typeof sopsObj.aws_kms_arn === "string" ? { aws_kms_arn: sopsObj.aws_kms_arn } : {},
2584
2619
  ...typeof sopsObj.gcp_kms_resource_id === "string" ? { gcp_kms_resource_id: sopsObj.gcp_kms_resource_id } : {},
2585
2620
  ...typeof sopsObj.azure_kv_url === "string" ? { azure_kv_url: sopsObj.azure_kv_url } : {},
2586
- ...typeof sopsObj.pgp_fingerprint === "string" ? { pgp_fingerprint: sopsObj.pgp_fingerprint } : {}
2621
+ ...typeof sopsObj.pgp_fingerprint === "string" ? { pgp_fingerprint: sopsObj.pgp_fingerprint } : {},
2622
+ ...typeof sopsObj.pkcs11_uri === "string" ? { pkcs11_uri: sopsObj.pkcs11_uri } : {}
2587
2623
  };
2588
2624
  for (const env of environments) {
2589
2625
  if (env.recipients && env.recipients.length > 0) {
@@ -2842,6 +2878,20 @@ var PATTERNS = [
2842
2878
  },
2843
2879
  { name: "Database URL", regex: /(?:postgres|mysql|mongodb|redis):\/\/[^:]+:[^@]+@/ }
2844
2880
  ];
2881
+ var PUBLIC_PREFIX_PATTERNS = [
2882
+ // reCAPTCHA v2, v3, and Enterprise site keys are exactly 40 chars and
2883
+ // begin with 6L[c-f]. Site keys are designed to be embedded in HTML.
2884
+ // https://developers.google.com/recaptcha/docs/faq
2885
+ { name: "reCAPTCHA site key", regex: /^6L[c-f][0-9A-Za-z_-]{37}$/ },
2886
+ // Stripe publishable keys (client-side, distinct from sk_live_/sk_test_).
2887
+ { name: "Stripe publishable key", regex: /^pk_(?:live|test)_[0-9a-zA-Z]{24,}$/ }
2888
+ ];
2889
+ function matchPublicPrefix(value) {
2890
+ for (const def of PUBLIC_PREFIX_PATTERNS) {
2891
+ if (def.regex.test(value)) return { name: def.name };
2892
+ }
2893
+ return null;
2894
+ }
2845
2895
  function shannonEntropy(str) {
2846
2896
  if (str.length === 0) return 0;
2847
2897
  const freq = /* @__PURE__ */ new Map();
@@ -3030,7 +3080,8 @@ var ScanRunner = class {
3030
3080
  }
3031
3081
  }
3032
3082
  if (options.severity !== "high") {
3033
- const entropyHit = this.detectEntropy(line, lineNum, relPath);
3083
+ const allowPublic = options.publicAllowlist !== false;
3084
+ const entropyHit = this.detectEntropy(line, lineNum, relPath, allowPublic);
3034
3085
  if (entropyHit && !shouldIgnoreMatch(entropyHit, ignoreRules)) {
3035
3086
  matches.push(entropyHit);
3036
3087
  }
@@ -3071,13 +3122,14 @@ var ScanRunner = class {
3071
3122
  return false;
3072
3123
  }
3073
3124
  }
3074
- detectEntropy(line, lineNum, filePath) {
3125
+ detectEntropy(line, lineNum, filePath, allowPublic) {
3075
3126
  const valuePattern = /(?:=|:\s*)["']?([A-Za-z0-9+/=_-]{20,})["']?/;
3076
3127
  const match = valuePattern.exec(line);
3077
3128
  if (!match) return null;
3078
3129
  const value = match[1];
3079
3130
  const entropy = shannonEntropy(value);
3080
3131
  if (!isHighEntropy(value)) return null;
3132
+ if (allowPublic && matchPublicPrefix(value)) return null;
3081
3133
  const varMatch = /(\w+)\s*(?:=|:)/.exec(line);
3082
3134
  const varName = varMatch ? varMatch[1] : "";
3083
3135
  const preview = varName ? `${varName}=\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022` : redactValue(value);
@@ -3159,41 +3211,50 @@ function metadataPath(encryptedFilePath) {
3159
3211
  return path4.join(dir, `${base}.clef-meta.yaml`);
3160
3212
  }
3161
3213
  var HEADER_COMMENT = "# Managed by Clef. Do not edit manually.\n";
3214
+ function emptyMetadata() {
3215
+ return { version: 1, pending: [], rotations: [] };
3216
+ }
3162
3217
  async function loadMetadata(filePath) {
3163
3218
  const metaPath = metadataPath(filePath);
3164
3219
  try {
3165
- if (!fs5.existsSync(metaPath)) {
3166
- return { version: 1, pending: [] };
3167
- }
3220
+ if (!fs5.existsSync(metaPath)) return emptyMetadata();
3168
3221
  const content = fs5.readFileSync(metaPath, "utf-8");
3169
3222
  const parsed = YAML3.parse(content);
3170
- if (!parsed || !Array.isArray(parsed.pending)) {
3171
- return { version: 1, pending: [] };
3172
- }
3173
- return {
3174
- version: 1,
3175
- pending: parsed.pending.map((p) => ({
3176
- key: p.key,
3177
- since: new Date(p.since),
3178
- setBy: p.setBy
3179
- }))
3180
- };
3223
+ if (!parsed || typeof parsed !== "object") return emptyMetadata();
3224
+ const pendingRaw = Array.isArray(parsed.pending) ? parsed.pending : [];
3225
+ const pending = pendingRaw.filter(
3226
+ (p) => !!p && typeof p === "object" && typeof p.key === "string" && typeof p.since === "string" && typeof p.setBy === "string"
3227
+ ).map((p) => ({ key: p.key, since: new Date(p.since), setBy: p.setBy }));
3228
+ const rotationsRaw = Array.isArray(parsed.rotations) ? parsed.rotations : [];
3229
+ const rotations = rotationsRaw.filter(
3230
+ (r) => !!r && typeof r === "object" && typeof r.key === "string" && typeof r.last_rotated_at === "string" && typeof r.rotated_by === "string" && typeof r.rotation_count === "number"
3231
+ ).map((r) => ({
3232
+ key: r.key,
3233
+ lastRotatedAt: new Date(r.last_rotated_at),
3234
+ rotatedBy: r.rotated_by,
3235
+ rotationCount: r.rotation_count
3236
+ }));
3237
+ return { version: 1, pending, rotations };
3181
3238
  } catch {
3182
- return { version: 1, pending: [] };
3239
+ return emptyMetadata();
3183
3240
  }
3184
3241
  }
3185
3242
  async function saveMetadata(filePath, metadata) {
3186
3243
  const metaPath = metadataPath(filePath);
3187
3244
  const dir = path4.dirname(metaPath);
3188
- if (!fs5.existsSync(dir)) {
3189
- fs5.mkdirSync(dir, { recursive: true });
3190
- }
3245
+ if (!fs5.existsSync(dir)) fs5.mkdirSync(dir, { recursive: true });
3191
3246
  const data = {
3192
3247
  version: metadata.version,
3193
3248
  pending: metadata.pending.map((p) => ({
3194
3249
  key: p.key,
3195
3250
  since: p.since.toISOString(),
3196
3251
  setBy: p.setBy
3252
+ })),
3253
+ rotations: metadata.rotations.map((r) => ({
3254
+ key: r.key,
3255
+ last_rotated_at: r.lastRotatedAt.toISOString(),
3256
+ rotated_by: r.rotatedBy,
3257
+ rotation_count: r.rotationCount
3197
3258
  }))
3198
3259
  };
3199
3260
  fs5.writeFileSync(metaPath, HEADER_COMMENT + YAML3.stringify(data), "utf-8");
@@ -3224,6 +3285,38 @@ async function isPending(filePath, key) {
3224
3285
  const metadata = await loadMetadata(filePath);
3225
3286
  return metadata.pending.some((p) => p.key === key);
3226
3287
  }
3288
+ async function recordRotation(filePath, keys, rotatedBy, now = /* @__PURE__ */ new Date()) {
3289
+ const metadata = await loadMetadata(filePath);
3290
+ for (const key of keys) {
3291
+ const existing = metadata.rotations.findIndex((r) => r.key === key);
3292
+ if (existing >= 0) {
3293
+ metadata.rotations[existing] = {
3294
+ key,
3295
+ lastRotatedAt: now,
3296
+ rotatedBy,
3297
+ rotationCount: metadata.rotations[existing].rotationCount + 1
3298
+ };
3299
+ } else {
3300
+ metadata.rotations.push({
3301
+ key,
3302
+ lastRotatedAt: now,
3303
+ rotatedBy,
3304
+ rotationCount: 1
3305
+ });
3306
+ }
3307
+ }
3308
+ metadata.pending = metadata.pending.filter((p) => !keys.includes(p.key));
3309
+ await saveMetadata(filePath, metadata);
3310
+ }
3311
+ async function removeRotation(filePath, keys) {
3312
+ const metadata = await loadMetadata(filePath);
3313
+ metadata.rotations = metadata.rotations.filter((r) => !keys.includes(r.key));
3314
+ await saveMetadata(filePath, metadata);
3315
+ }
3316
+ async function getRotations(filePath) {
3317
+ const metadata = await loadMetadata(filePath);
3318
+ return metadata.rotations;
3319
+ }
3227
3320
  function generateRandomValue() {
3228
3321
  return crypto.randomBytes(32).toString("hex");
3229
3322
  }
@@ -4025,61 +4118,83 @@ var GitIntegration = class {
4025
4118
  * @throws {@link GitOperationError} On failure.
4026
4119
  */
4027
4120
  async installMergeDriver(repoRoot) {
4028
- const configResult = await this.runner.run(
4029
- "git",
4030
- ["config", "merge.sops.name", "SOPS-aware merge driver"],
4031
- { cwd: repoRoot }
4032
- );
4033
- if (configResult.exitCode !== 0) {
4034
- throw new GitOperationError(
4035
- `Failed to configure merge driver name: ${configResult.stderr.trim()}`,
4036
- "Ensure you are inside a git repository."
4121
+ const drivers = [
4122
+ { config: "merge.sops", friendly: "SOPS-aware merge driver" },
4123
+ { config: "merge.clef-metadata", friendly: "Clef metadata merge driver" }
4124
+ ];
4125
+ for (const driver of drivers) {
4126
+ const nameResult = await this.runner.run(
4127
+ "git",
4128
+ ["config", `${driver.config}.name`, driver.friendly],
4129
+ { cwd: repoRoot }
4037
4130
  );
4038
- }
4039
- const driverResult = await this.runner.run(
4040
- "git",
4041
- ["config", "merge.sops.driver", "clef merge-driver %O %A %B"],
4042
- { cwd: repoRoot }
4043
- );
4044
- if (driverResult.exitCode !== 0) {
4045
- throw new GitOperationError(
4046
- `Failed to configure merge driver command: ${driverResult.stderr.trim()}`,
4047
- "Ensure you are inside a git repository."
4131
+ if (nameResult.exitCode !== 0) {
4132
+ throw new GitOperationError(
4133
+ `Failed to configure merge driver name: ${nameResult.stderr.trim()}`,
4134
+ "Ensure you are inside a git repository."
4135
+ );
4136
+ }
4137
+ const driverResult = await this.runner.run(
4138
+ "git",
4139
+ ["config", `${driver.config}.driver`, "clef merge-driver %O %A %B"],
4140
+ { cwd: repoRoot }
4048
4141
  );
4142
+ if (driverResult.exitCode !== 0) {
4143
+ throw new GitOperationError(
4144
+ `Failed to configure merge driver command: ${driverResult.stderr.trim()}`,
4145
+ "Ensure you are inside a git repository."
4146
+ );
4147
+ }
4049
4148
  }
4050
4149
  await this.ensureGitattributes(repoRoot);
4051
4150
  }
4052
4151
  /**
4053
- * Check whether the SOPS merge driver is configured in both
4054
- * `.git/config` and `.gitattributes`.
4055
- *
4056
- * @param repoRoot - Absolute path to the repository root.
4057
- * @returns An object indicating which parts are configured.
4152
+ * Check whether both Clef merge drivers are configured in `.git/config`
4153
+ * and `.gitattributes`. Reports separately on the SOPS driver
4154
+ * (`merge=sops` for `.enc.*`) and the metadata driver
4155
+ * (`merge=clef-metadata` for `.clef-meta.yaml`) so `clef doctor` can
4156
+ * prompt the user to run `clef hooks` when only the SOPS driver is
4157
+ * installed (older install, pre-metadata-merge).
4058
4158
  */
4059
4159
  async checkMergeDriver(repoRoot) {
4060
- const configResult = await this.runner.run("git", ["config", "--get", "merge.sops.driver"], {
4160
+ const sopsConfig = await this.runner.run("git", ["config", "--get", "merge.sops.driver"], {
4061
4161
  cwd: repoRoot
4062
4162
  });
4063
- const gitConfig = configResult.exitCode === 0 && configResult.stdout.trim().length > 0;
4163
+ const gitConfig = sopsConfig.exitCode === 0 && sopsConfig.stdout.trim().length > 0;
4164
+ const metaConfig = await this.runner.run(
4165
+ "git",
4166
+ ["config", "--get", "merge.clef-metadata.driver"],
4167
+ { cwd: repoRoot }
4168
+ );
4169
+ const metadataGitConfig = metaConfig.exitCode === 0 && metaConfig.stdout.trim().length > 0;
4064
4170
  const attrFilePath = path8.join(repoRoot, ".gitattributes");
4065
4171
  const attrContent = fs9.existsSync(attrFilePath) ? fs9.readFileSync(attrFilePath, "utf-8") : "";
4066
4172
  const gitattributes = attrContent.includes("merge=sops");
4067
- return { gitConfig, gitattributes };
4173
+ const metadataGitattributes = attrContent.includes("merge=clef-metadata");
4174
+ return { gitConfig, gitattributes, metadataGitConfig, metadataGitattributes };
4068
4175
  }
4069
4176
  async ensureGitattributes(repoRoot) {
4070
4177
  const attrPath = path8.join(repoRoot, ".gitattributes");
4071
- const mergeRule = "*.enc.yaml merge=sops\n*.enc.json merge=sops";
4072
4178
  const existing = fs9.existsSync(attrPath) ? fs9.readFileSync(attrPath, "utf-8") : "";
4073
- if (existing.includes("merge=sops")) {
4074
- return;
4075
- }
4076
- const newContent = existing.trimEnd() ? `${existing.trimEnd()}
4179
+ let newContent = existing;
4180
+ if (!existing.includes("merge=sops")) {
4181
+ const block = `# Clef: SOPS-aware merge driver for encrypted files
4182
+ *.enc.yaml merge=sops
4183
+ *.enc.json merge=sops
4184
+ `;
4185
+ newContent = newContent.trimEnd() ? `${newContent.trimEnd()}
4077
4186
 
4078
- # Clef: SOPS-aware merge driver for encrypted files
4079
- ${mergeRule}
4080
- ` : `# Clef: SOPS-aware merge driver for encrypted files
4081
- ${mergeRule}
4187
+ ${block}` : block;
4188
+ }
4189
+ if (!newContent.includes("merge=clef-metadata")) {
4190
+ const block = `# Clef: rotation-aware merge driver for metadata sidecars
4191
+ *.clef-meta.yaml merge=clef-metadata
4082
4192
  `;
4193
+ newContent = newContent.trimEnd() ? `${newContent.trimEnd()}
4194
+
4195
+ ${block}` : block;
4196
+ }
4197
+ if (newContent === existing) return;
4083
4198
  try {
4084
4199
  fs9.writeFileSync(attrPath, newContent, "utf-8");
4085
4200
  } catch (err) {
@@ -4469,6 +4584,39 @@ ${privateKey}
4469
4584
  `;
4470
4585
  }
4471
4586
 
4587
+ // src/sops/hsm-arn.ts
4588
+ var CLEF_HSM_ARN_RE = /^arn:aws[\w-]*:kms:[^:]+:\d+:alias\/clef-hsm\/(v\d+)\/([A-Za-z0-9_-]+)$/;
4589
+ var ARN_PREFIX = "arn:aws:kms:us-east-1:000000000000:alias/clef-hsm/v1/";
4590
+ var SUPPORTED_VERSION = "v1";
4591
+ function pkcs11UriToSyntheticArn(uri) {
4592
+ if (!uri.startsWith("pkcs11:")) {
4593
+ throw new Error(`Expected a pkcs11 URI starting with 'pkcs11:', got '${uri}'.`);
4594
+ }
4595
+ const payload = Buffer.from(uri, "utf8").toString("base64url");
4596
+ const arn = ARN_PREFIX + payload;
4597
+ if (!CLEF_HSM_ARN_RE.test(arn)) {
4598
+ throw new Error(`Synthesized ARN failed self-validation: '${arn}'.`);
4599
+ }
4600
+ return arn;
4601
+ }
4602
+ function syntheticArnToPkcs11Uri(arn) {
4603
+ const match = CLEF_HSM_ARN_RE.exec(arn);
4604
+ if (!match) return null;
4605
+ const [, version, payload] = match;
4606
+ if (version !== SUPPORTED_VERSION) return null;
4607
+ let decoded;
4608
+ try {
4609
+ decoded = Buffer.from(payload, "base64url").toString("utf8");
4610
+ } catch {
4611
+ return null;
4612
+ }
4613
+ if (!decoded.startsWith("pkcs11:")) return null;
4614
+ return decoded;
4615
+ }
4616
+ function isClefHsmArn(arn) {
4617
+ return CLEF_HSM_ARN_RE.test(arn);
4618
+ }
4619
+
4472
4620
  // src/sops/client.ts
4473
4621
  function formatFromPath(filePath) {
4474
4622
  return filePath.endsWith(".json") ? "json" : "yaml";
@@ -4500,14 +4648,25 @@ var SopsClient = class {
4500
4648
  * to the subprocess environment.
4501
4649
  * @param sopsPath - Optional explicit path to the sops binary. When omitted,
4502
4650
  * resolved automatically via {@link resolveSopsPath}.
4651
+ * @param keyserviceAddr - Optional address of an external SOPS KeyService
4652
+ * sidecar (e.g. `tcp://127.0.0.1:12345`). When set, every SOPS invocation
4653
+ * includes `--enable-local-keyservice=false --keyservice <addr>` so KMS
4654
+ * wrap/unwrap is routed to the sidecar (used for the HSM backend, where
4655
+ * the sidecar is `clef-keyservice` talking PKCS#11 to the HSM).
4656
+ *
4657
+ * The flags are inserted **after** the SOPS subcommand — placing them
4658
+ * before is silently ignored by SOPS (a footgun discovered the first
4659
+ * time we shipped this).
4503
4660
  */
4504
- constructor(runner, ageKeyFile, ageKey, sopsPath) {
4661
+ constructor(runner, ageKeyFile, ageKey, sopsPath, keyserviceAddr) {
4505
4662
  this.runner = runner;
4506
4663
  this.ageKeyFile = ageKeyFile;
4507
4664
  this.ageKey = ageKey;
4508
4665
  this.sopsCommand = sopsPath ?? resolveSopsPath().path;
4666
+ this.keyserviceArgs = keyserviceAddr ? Object.freeze(["--enable-local-keyservice=false", "--keyservice", keyserviceAddr]) : Object.freeze([]);
4509
4667
  }
4510
4668
  sopsCommand;
4669
+ keyserviceArgs;
4511
4670
  buildSopsEnv() {
4512
4671
  const env = {};
4513
4672
  if (this.ageKey) {
@@ -4532,7 +4691,7 @@ var SopsClient = class {
4532
4691
  const env = this.buildSopsEnv();
4533
4692
  const result = await this.runner.run(
4534
4693
  this.sopsCommand,
4535
- ["decrypt", "--output-type", fmt, filePath],
4694
+ ["decrypt", ...this.keyserviceArgs, "--output-type", fmt, filePath],
4536
4695
  {
4537
4696
  ...env ? { env } : {}
4538
4697
  }
@@ -4599,6 +4758,7 @@ var SopsClient = class {
4599
4758
  "--config",
4600
4759
  configPath,
4601
4760
  "encrypt",
4761
+ ...this.keyserviceArgs,
4602
4762
  ...args,
4603
4763
  "--input-type",
4604
4764
  fmt,
@@ -4655,7 +4815,7 @@ var SopsClient = class {
4655
4815
  const env = this.buildSopsEnv();
4656
4816
  const result = await this.runner.run(
4657
4817
  this.sopsCommand,
4658
- ["rotate", "-i", "--add-age", key, filePath],
4818
+ ["rotate", ...this.keyserviceArgs, "-i", "--add-age", key, filePath],
4659
4819
  {
4660
4820
  ...env ? { env } : {}
4661
4821
  }
@@ -4679,7 +4839,7 @@ var SopsClient = class {
4679
4839
  const env = this.buildSopsEnv();
4680
4840
  const result = await this.runner.run(
4681
4841
  this.sopsCommand,
4682
- ["rotate", "-i", "--rm-age", key, filePath],
4842
+ ["rotate", ...this.keyserviceArgs, "-i", "--rm-age", key, filePath],
4683
4843
  {
4684
4844
  ...env ? { env } : {}
4685
4845
  }
@@ -4794,7 +4954,14 @@ var SopsClient = class {
4794
4954
  }
4795
4955
  detectBackend(sops) {
4796
4956
  if (sops.age && Array.isArray(sops.age) && sops.age.length > 0) return "age";
4797
- if (sops.kms && Array.isArray(sops.kms) && sops.kms.length > 0) return "awskms";
4957
+ if (sops.kms && Array.isArray(sops.kms) && sops.kms.length > 0) {
4958
+ const kmsEntries = sops.kms;
4959
+ const firstArn = kmsEntries[0]?.arn;
4960
+ if (typeof firstArn === "string" && isClefHsmArn(firstArn)) {
4961
+ return "hsm";
4962
+ }
4963
+ return "awskms";
4964
+ }
4798
4965
  if (sops.gcp_kms && Array.isArray(sops.gcp_kms) && sops.gcp_kms.length > 0)
4799
4966
  return "gcpkms";
4800
4967
  if (sops.azure_kv && Array.isArray(sops.azure_kv) && sops.azure_kv.length > 0)
@@ -4812,6 +4979,13 @@ var SopsClient = class {
4812
4979
  const entries = sops.kms;
4813
4980
  return entries?.map((e) => String(e.arn ?? "")) ?? [];
4814
4981
  }
4982
+ case "hsm": {
4983
+ const entries = sops.kms;
4984
+ return entries?.map((e) => {
4985
+ const raw = String(e.arn ?? "");
4986
+ return syntheticArnToPkcs11Uri(raw) ?? raw;
4987
+ }) ?? [];
4988
+ }
4815
4989
  case "gcpkms": {
4816
4990
  const entries = sops.gcp_kms;
4817
4991
  return entries?.map((e) => String(e.resource_id ?? "")) ?? [];
@@ -4837,7 +5011,8 @@ var SopsClient = class {
4837
5011
  aws_kms_arn: manifest.sops.aws_kms_arn,
4838
5012
  gcp_kms_resource_id: manifest.sops.gcp_kms_resource_id,
4839
5013
  azure_kv_url: manifest.sops.azure_kv_url,
4840
- pgp_fingerprint: manifest.sops.pgp_fingerprint
5014
+ pgp_fingerprint: manifest.sops.pgp_fingerprint,
5015
+ pkcs11_uri: manifest.sops.pkcs11_uri
4841
5016
  };
4842
5017
  switch (config.backend) {
4843
5018
  case "age": {
@@ -4869,13 +5044,172 @@ var SopsClient = class {
4869
5044
  args.push("--pgp", config.pgp_fingerprint);
4870
5045
  }
4871
5046
  break;
5047
+ case "hsm":
5048
+ if (config.pkcs11_uri) {
5049
+ args.push("--kms", pkcs11UriToSyntheticArn(config.pkcs11_uri));
5050
+ }
5051
+ break;
4872
5052
  }
4873
5053
  return args;
4874
5054
  }
4875
5055
  };
4876
5056
 
4877
- // src/lint/runner.ts
5057
+ // src/hsm/bundled.ts
5058
+ import * as fs14 from "fs";
4878
5059
  import * as path12 from "path";
5060
+ function tryBundledKeyservice() {
5061
+ const platform = process.platform;
5062
+ const arch = process.arch;
5063
+ const archName = arch === "x64" ? "x64" : arch === "arm64" ? "arm64" : null;
5064
+ if (!archName) return null;
5065
+ const platformName = platform === "darwin" ? "darwin" : platform === "linux" ? "linux" : null;
5066
+ if (!platformName) return null;
5067
+ const packageName = `@clef-sh/keyservice-${platformName}-${archName}`;
5068
+ const binName = "clef-keyservice";
5069
+ try {
5070
+ const packageMain = __require.resolve(`${packageName}/package.json`);
5071
+ const packageDir = path12.dirname(packageMain);
5072
+ const binPath = path12.join(packageDir, "bin", binName);
5073
+ return fs14.existsSync(binPath) ? binPath : null;
5074
+ } catch {
5075
+ return null;
5076
+ }
5077
+ }
5078
+
5079
+ // src/hsm/resolver.ts
5080
+ import * as fs15 from "fs";
5081
+ import * as path13 from "path";
5082
+ function validateKeyservicePath(candidate) {
5083
+ if (!path13.isAbsolute(candidate)) {
5084
+ throw new Error(`CLEF_KEYSERVICE_PATH must be an absolute path, got '${candidate}'.`);
5085
+ }
5086
+ const segments = candidate.split(/[/\\]/);
5087
+ if (segments.includes("..")) {
5088
+ throw new Error(
5089
+ `CLEF_KEYSERVICE_PATH contains '..' path segments ('${candidate}'). Use an absolute path without directory traversal.`
5090
+ );
5091
+ }
5092
+ }
5093
+ var cached2;
5094
+ function resolveKeyservicePath() {
5095
+ if (cached2) return cached2;
5096
+ const envPath = process.env.CLEF_KEYSERVICE_PATH?.trim();
5097
+ if (envPath) {
5098
+ validateKeyservicePath(envPath);
5099
+ if (!fs15.existsSync(envPath)) {
5100
+ throw new Error(`CLEF_KEYSERVICE_PATH points to '${envPath}' but the file does not exist.`);
5101
+ }
5102
+ cached2 = { path: envPath, source: "env" };
5103
+ return cached2;
5104
+ }
5105
+ const bundledPath = tryBundledKeyservice();
5106
+ if (bundledPath) {
5107
+ cached2 = { path: bundledPath, source: "bundled" };
5108
+ return cached2;
5109
+ }
5110
+ cached2 = { path: "clef-keyservice", source: "system" };
5111
+ return cached2;
5112
+ }
5113
+ function resetKeyserviceResolution() {
5114
+ cached2 = void 0;
5115
+ }
5116
+
5117
+ // src/hsm/keyservice.ts
5118
+ import { spawn } from "child_process";
5119
+ import * as readline from "readline";
5120
+ var PORT_REGEX = /^PORT=(\d+)$/;
5121
+ var STARTUP_TIMEOUT_MS = 5e3;
5122
+ var SHUTDOWN_TIMEOUT_MS = 3e3;
5123
+ async function spawnKeyservice(options) {
5124
+ if (!options.pin && !options.pinFile) {
5125
+ throw new Error(
5126
+ "Keyservice requires a PIN. Set CLEF_PKCS11_PIN, CLEF_PKCS11_PIN_FILE, or .clef/config.yaml pkcs11_pin_file."
5127
+ );
5128
+ }
5129
+ const args = ["--addr", "127.0.0.1:0", "--pkcs11-module", options.modulePath];
5130
+ const childEnv = {
5131
+ ...process.env,
5132
+ ...options.extraEnv ?? {},
5133
+ ...options.pin ? { CLEF_PKCS11_PIN: options.pin } : {},
5134
+ ...options.pinFile ? { CLEF_PKCS11_PIN_FILE: options.pinFile } : {}
5135
+ };
5136
+ const child = spawn(options.binaryPath, args, {
5137
+ stdio: ["ignore", "pipe", "pipe"],
5138
+ env: childEnv
5139
+ });
5140
+ const port = await readPort(child);
5141
+ return {
5142
+ addr: `tcp://127.0.0.1:${port}`,
5143
+ kill: () => killGracefully(child)
5144
+ };
5145
+ }
5146
+ function readPort(child) {
5147
+ return new Promise((resolve, reject) => {
5148
+ let settled = false;
5149
+ if (!child.stdout) {
5150
+ reject(new Error("Keyservice child has no stdout pipe."));
5151
+ return;
5152
+ }
5153
+ const rl = readline.createInterface({ input: child.stdout });
5154
+ const settle = () => {
5155
+ clearTimeout(timer);
5156
+ rl.close();
5157
+ };
5158
+ const timer = setTimeout(() => {
5159
+ if (!settled) {
5160
+ settled = true;
5161
+ settle();
5162
+ child.kill("SIGKILL");
5163
+ reject(
5164
+ new Error(
5165
+ `clef-keyservice did not report a port within ${STARTUP_TIMEOUT_MS}ms. Check that the PKCS#11 module path is valid and the PIN is correct.`
5166
+ )
5167
+ );
5168
+ }
5169
+ }, STARTUP_TIMEOUT_MS);
5170
+ rl.on("line", (line) => {
5171
+ const match = PORT_REGEX.exec(line);
5172
+ if (match && !settled) {
5173
+ settled = true;
5174
+ settle();
5175
+ resolve(parseInt(match[1], 10));
5176
+ }
5177
+ });
5178
+ child.on("error", (err) => {
5179
+ if (!settled) {
5180
+ settled = true;
5181
+ settle();
5182
+ reject(new Error(`Failed to start clef-keyservice: ${err.message}`));
5183
+ }
5184
+ });
5185
+ child.on("exit", (code) => {
5186
+ if (!settled) {
5187
+ settled = true;
5188
+ settle();
5189
+ reject(new Error(`clef-keyservice exited with code ${code} before reporting a port.`));
5190
+ }
5191
+ });
5192
+ });
5193
+ }
5194
+ function killGracefully(child) {
5195
+ return new Promise((resolve) => {
5196
+ if (child.exitCode !== null) {
5197
+ resolve();
5198
+ return;
5199
+ }
5200
+ const timer = setTimeout(() => {
5201
+ child.kill("SIGKILL");
5202
+ }, SHUTDOWN_TIMEOUT_MS);
5203
+ child.on("exit", () => {
5204
+ clearTimeout(timer);
5205
+ resolve();
5206
+ });
5207
+ child.kill("SIGTERM");
5208
+ });
5209
+ }
5210
+
5211
+ // src/lint/runner.ts
5212
+ import * as path14 from "path";
4879
5213
  var LintRunner = class {
4880
5214
  constructor(matrixManager, schemaValidator, sopsClient) {
4881
5215
  this.matrixManager = matrixManager;
@@ -4975,7 +5309,7 @@ var LintRunner = class {
4975
5309
  }
4976
5310
  const ns = manifest.namespaces.find((n) => n.name === cell.namespace);
4977
5311
  if (ns?.schema) {
4978
- const schemaPath = path12.join(repoRoot, ns.schema);
5312
+ const schemaPath = path14.join(repoRoot, ns.schema);
4979
5313
  try {
4980
5314
  const schema = this.schemaValidator.loadSchema(schemaPath);
4981
5315
  const result = this.schemaValidator.validate(decrypted.values, schema);
@@ -5076,8 +5410,50 @@ var LintRunner = class {
5076
5410
  );
5077
5411
  issues.push(...siIssues);
5078
5412
  }
5413
+ const metadataIssues = await this.lintMetadataConsistency(existingCells);
5414
+ issues.push(...metadataIssues);
5079
5415
  return { issues, fileCount: fileCount + missingCells.length, pendingCount };
5080
5416
  }
5417
+ /**
5418
+ * Cross-reference `.clef-meta.yaml` against the cipher's plaintext key
5419
+ * names for each existing cell. Reports orphan rotation records and
5420
+ * dual-state (pending + rotation) inconsistencies. Uses
5421
+ * {@link readSopsKeyNames} (plaintext YAML parse) — no decryption.
5422
+ */
5423
+ async lintMetadataConsistency(cells) {
5424
+ const issues = [];
5425
+ for (const cell of cells) {
5426
+ const keysInCipher = readSopsKeyNames(cell.filePath);
5427
+ if (keysInCipher === null) continue;
5428
+ const cipherKeys = new Set(keysInCipher);
5429
+ const metadata = await loadMetadata(cell.filePath);
5430
+ for (const record of metadata.rotations) {
5431
+ if (!cipherKeys.has(record.key)) {
5432
+ issues.push({
5433
+ severity: "warning",
5434
+ category: "metadata",
5435
+ file: cell.filePath,
5436
+ key: record.key,
5437
+ message: `Rotation record exists for key '${record.key}' but the key is not in this cell. Remove the orphan entry from .clef-meta.yaml or re-add the key via clef set.`
5438
+ });
5439
+ }
5440
+ }
5441
+ const pendingKeys = new Set(metadata.pending.map((p) => p.key));
5442
+ for (const record of metadata.rotations) {
5443
+ if (pendingKeys.has(record.key)) {
5444
+ issues.push({
5445
+ severity: "error",
5446
+ category: "metadata",
5447
+ file: cell.filePath,
5448
+ key: record.key,
5449
+ message: `Key '${record.key}' appears in both 'pending' and 'rotations' sections of .clef-meta.yaml. One of them is stale \u2014 likely a manual edit or a failed transaction. Re-run clef set to reconcile.`,
5450
+ fixCommand: `clef set ${cell.namespace}/${cell.environment} ${record.key}`
5451
+ });
5452
+ }
5453
+ }
5454
+ }
5455
+ return issues;
5456
+ }
5081
5457
  /**
5082
5458
  * Lint service identity configurations for drift issues.
5083
5459
  */
@@ -5220,14 +5596,14 @@ Use 'clef exec' to inject secrets directly into a process, or 'clef export --for
5220
5596
  };
5221
5597
 
5222
5598
  // src/import/index.ts
5223
- import * as path14 from "path";
5599
+ import * as path16 from "path";
5224
5600
 
5225
5601
  // src/import/parsers.ts
5226
- import * as path13 from "path";
5602
+ import * as path15 from "path";
5227
5603
  import * as YAML8 from "yaml";
5228
5604
  function detectFormat(filePath, content) {
5229
- const base = path13.basename(filePath);
5230
- const ext = path13.extname(filePath).toLowerCase();
5605
+ const base = path15.basename(filePath);
5606
+ const ext = path15.extname(filePath).toLowerCase();
5231
5607
  if (base === ".env" || base.startsWith(".env.")) {
5232
5608
  return "dotenv";
5233
5609
  }
@@ -5393,7 +5769,7 @@ var ImportRunner = class {
5393
5769
  */
5394
5770
  async import(target, sourcePath, content, manifest, repoRoot, options) {
5395
5771
  const [ns, env] = target.split("/");
5396
- const filePath = path14.join(
5772
+ const filePath = path16.join(
5397
5773
  repoRoot,
5398
5774
  manifest.file_pattern.replace("{namespace}", ns).replace("{environment}", env)
5399
5775
  );
@@ -5430,22 +5806,33 @@ var ImportRunner = class {
5430
5806
  }
5431
5807
  const decrypted = await this.sopsClient.decrypt(filePath);
5432
5808
  const newValues = { ...decrypted.values };
5809
+ const rotatedKeys = [];
5433
5810
  for (const [key, value] of candidates) {
5434
- if (key in decrypted.values && !options.overwrite) {
5811
+ const existed = key in decrypted.values;
5812
+ if (existed && !options.overwrite) {
5435
5813
  skipped.push(key);
5436
5814
  continue;
5437
5815
  }
5816
+ const valueChanged = !existed || decrypted.values[key] !== value;
5438
5817
  newValues[key] = value;
5439
5818
  imported.push(key);
5819
+ if (valueChanged) rotatedKeys.push(key);
5440
5820
  }
5441
5821
  if (imported.length === 0) {
5442
5822
  return { imported, skipped, failed, warnings, dryRun: false };
5443
5823
  }
5824
+ const relCellPath = path16.relative(repoRoot, filePath);
5825
+ const relMetaPath = relCellPath.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml");
5444
5826
  await this.tx.run(repoRoot, {
5445
5827
  description: `clef import ${target}: ${imported.length} key(s)`,
5446
- paths: [path14.relative(repoRoot, filePath)],
5828
+ // Include the metadata path so rotation records created in the mutate
5829
+ // callback are staged and rolled back atomically with the ciphertext.
5830
+ paths: [relCellPath, relMetaPath],
5447
5831
  mutate: async () => {
5448
5832
  await this.sopsClient.encrypt(filePath, newValues, manifest, env);
5833
+ if (options.rotatedBy && rotatedKeys.length > 0) {
5834
+ await recordRotation(filePath, rotatedKeys, options.rotatedBy);
5835
+ }
5449
5836
  }
5450
5837
  });
5451
5838
  return { imported, skipped, failed, warnings, dryRun: false };
@@ -5453,7 +5840,7 @@ var ImportRunner = class {
5453
5840
  };
5454
5841
 
5455
5842
  // src/recipients/index.ts
5456
- import * as path15 from "path";
5843
+ import * as path17 from "path";
5457
5844
  function parseRecipientEntry(entry) {
5458
5845
  if (typeof entry === "string") {
5459
5846
  return { key: entry };
@@ -5578,7 +5965,7 @@ var RecipientManager = class {
5578
5965
  const reEncryptedFiles = [];
5579
5966
  await this.tx.run(repoRoot, {
5580
5967
  description: environment ? `clef recipients add ${keyPreview(normalizedKey)} -e ${environment}` : `clef recipients add ${keyPreview(normalizedKey)}`,
5581
- paths: [...cells.map((c) => path15.relative(repoRoot, c.filePath)), CLEF_MANIFEST_FILENAME],
5968
+ paths: [...cells.map((c) => path17.relative(repoRoot, c.filePath)), CLEF_MANIFEST_FILENAME],
5582
5969
  mutate: async () => {
5583
5970
  const doc = readManifestYaml(repoRoot);
5584
5971
  const recipients = environment ? ensureEnvironmentRecipientsArray(doc, environment) : ensureRecipientsArray(doc);
@@ -5637,7 +6024,7 @@ var RecipientManager = class {
5637
6024
  const reEncryptedFiles = [];
5638
6025
  await this.tx.run(repoRoot, {
5639
6026
  description: environment ? `clef recipients remove ${keyPreview(trimmedKey)} -e ${environment}` : `clef recipients remove ${keyPreview(trimmedKey)}`,
5640
- paths: [...cells.map((c) => path15.relative(repoRoot, c.filePath)), CLEF_MANIFEST_FILENAME],
6027
+ paths: [...cells.map((c) => path17.relative(repoRoot, c.filePath)), CLEF_MANIFEST_FILENAME],
5641
6028
  mutate: async () => {
5642
6029
  const doc = readManifestYaml(repoRoot);
5643
6030
  const recipients = environment ? ensureEnvironmentRecipientsArray(doc, environment) : ensureRecipientsArray(doc);
@@ -5666,19 +6053,19 @@ var RecipientManager = class {
5666
6053
  };
5667
6054
 
5668
6055
  // src/recipients/requests.ts
5669
- import * as fs14 from "fs";
5670
- import * as path16 from "path";
6056
+ import * as fs16 from "fs";
6057
+ import * as path18 from "path";
5671
6058
  import * as YAML9 from "yaml";
5672
6059
  var REQUESTS_FILENAME = ".clef-requests.yaml";
5673
6060
  var HEADER_COMMENT2 = "# Pending recipient access requests. Approve with: clef recipients approve <label>\n";
5674
6061
  function requestsFilePath(repoRoot) {
5675
- return path16.join(repoRoot, REQUESTS_FILENAME);
6062
+ return path18.join(repoRoot, REQUESTS_FILENAME);
5676
6063
  }
5677
6064
  function loadRequests(repoRoot) {
5678
6065
  const filePath = requestsFilePath(repoRoot);
5679
6066
  try {
5680
- if (!fs14.existsSync(filePath)) return [];
5681
- const content = fs14.readFileSync(filePath, "utf-8");
6067
+ if (!fs16.existsSync(filePath)) return [];
6068
+ const content = fs16.readFileSync(filePath, "utf-8");
5682
6069
  const parsed = YAML9.parse(content);
5683
6070
  if (!parsed || !Array.isArray(parsed.requests)) return [];
5684
6071
  return parsed.requests.map((r) => ({
@@ -5695,7 +6082,7 @@ function saveRequests(repoRoot, requests) {
5695
6082
  const filePath = requestsFilePath(repoRoot);
5696
6083
  if (requests.length === 0) {
5697
6084
  try {
5698
- fs14.unlinkSync(filePath);
6085
+ fs16.unlinkSync(filePath);
5699
6086
  } catch {
5700
6087
  }
5701
6088
  return;
@@ -5711,7 +6098,7 @@ function saveRequests(repoRoot, requests) {
5711
6098
  return raw;
5712
6099
  })
5713
6100
  };
5714
- fs14.writeFileSync(filePath, HEADER_COMMENT2 + YAML9.stringify(data), "utf-8");
6101
+ fs16.writeFileSync(filePath, HEADER_COMMENT2 + YAML9.stringify(data), "utf-8");
5715
6102
  }
5716
6103
  function upsertRequest(repoRoot, key, label, environment) {
5717
6104
  const requests = loadRequests(repoRoot);
@@ -5747,7 +6134,7 @@ function findInList(requests, identifier) {
5747
6134
  }
5748
6135
 
5749
6136
  // src/drift/detector.ts
5750
- import * as path17 from "path";
6137
+ import * as path19 from "path";
5751
6138
  var DriftDetector = class {
5752
6139
  parser = new ManifestParser();
5753
6140
  matrix = new MatrixManager();
@@ -5760,8 +6147,8 @@ var DriftDetector = class {
5760
6147
  * @returns Drift result with any issues found.
5761
6148
  */
5762
6149
  detect(localRoot, remoteRoot, namespaceFilter) {
5763
- const localManifest = this.parser.parse(path17.join(localRoot, CLEF_MANIFEST_FILENAME));
5764
- const remoteManifest = this.parser.parse(path17.join(remoteRoot, CLEF_MANIFEST_FILENAME));
6150
+ const localManifest = this.parser.parse(path19.join(localRoot, CLEF_MANIFEST_FILENAME));
6151
+ const remoteManifest = this.parser.parse(path19.join(remoteRoot, CLEF_MANIFEST_FILENAME));
5765
6152
  const localCells = this.matrix.resolveMatrix(localManifest, localRoot);
5766
6153
  const remoteCells = this.matrix.resolveMatrix(remoteManifest, remoteRoot);
5767
6154
  const localEnvNames = localManifest.environments.map((e) => e.name);
@@ -5825,7 +6212,7 @@ var DriftDetector = class {
5825
6212
  };
5826
6213
 
5827
6214
  // src/report/generator.ts
5828
- import * as path18 from "path";
6215
+ import * as path20 from "path";
5829
6216
 
5830
6217
  // src/report/sanitizer.ts
5831
6218
  var ReportSanitizer = class {
@@ -5981,7 +6368,7 @@ var ReportGenerator = class {
5981
6368
  let manifest = null;
5982
6369
  try {
5983
6370
  const parser = new ManifestParser();
5984
- manifest = parser.parse(path18.join(repoRoot, "clef.yaml"));
6371
+ manifest = parser.parse(path20.join(repoRoot, "clef.yaml"));
5985
6372
  } catch {
5986
6373
  const emptyManifest = {
5987
6374
  manifestVersion: 0,
@@ -6458,8 +6845,118 @@ var SopsMergeDriver = class {
6458
6845
  }
6459
6846
  };
6460
6847
 
6848
+ // src/merge/metadata-driver.ts
6849
+ import * as fs17 from "fs";
6850
+ import * as YAML10 from "yaml";
6851
+ var HEADER_COMMENT3 = "# Managed by Clef. Do not edit manually.\n";
6852
+ function parseMetadata(content) {
6853
+ try {
6854
+ const parsed = YAML10.parse(content);
6855
+ if (!parsed || typeof parsed !== "object") return emptyMetadata2();
6856
+ const pendingRaw = Array.isArray(parsed.pending) ? parsed.pending : [];
6857
+ const pending = pendingRaw.filter(
6858
+ (p) => !!p && typeof p === "object" && typeof p.key === "string" && typeof p.since === "string" && typeof p.setBy === "string"
6859
+ ).map((p) => ({ key: p.key, since: new Date(p.since), setBy: p.setBy }));
6860
+ const rotationsRaw = Array.isArray(parsed.rotations) ? parsed.rotations : [];
6861
+ const rotations = rotationsRaw.filter(
6862
+ (r) => !!r && typeof r === "object" && typeof r.key === "string" && typeof r.last_rotated_at === "string" && typeof r.rotated_by === "string" && typeof r.rotation_count === "number"
6863
+ ).map((r) => ({
6864
+ key: r.key,
6865
+ lastRotatedAt: new Date(r.last_rotated_at),
6866
+ rotatedBy: r.rotated_by,
6867
+ rotationCount: r.rotation_count
6868
+ }));
6869
+ return { version: 1, pending, rotations };
6870
+ } catch {
6871
+ return emptyMetadata2();
6872
+ }
6873
+ }
6874
+ function emptyMetadata2() {
6875
+ return { version: 1, pending: [], rotations: [] };
6876
+ }
6877
+ function serializeMetadata(m) {
6878
+ const data = {
6879
+ version: m.version,
6880
+ pending: m.pending.map((p) => ({
6881
+ key: p.key,
6882
+ since: p.since.toISOString(),
6883
+ setBy: p.setBy
6884
+ })),
6885
+ rotations: m.rotations.map((r) => ({
6886
+ key: r.key,
6887
+ last_rotated_at: r.lastRotatedAt.toISOString(),
6888
+ rotated_by: r.rotatedBy,
6889
+ rotation_count: r.rotationCount
6890
+ }))
6891
+ };
6892
+ return HEADER_COMMENT3 + YAML10.stringify(data);
6893
+ }
6894
+ function mergeRotations(ours, theirs) {
6895
+ const byKey = /* @__PURE__ */ new Map();
6896
+ const ourByKey = new Map(ours.map((r) => [r.key, r]));
6897
+ const theirByKey = new Map(theirs.map((r) => [r.key, r]));
6898
+ const allKeys = /* @__PURE__ */ new Set([...ourByKey.keys(), ...theirByKey.keys()]);
6899
+ for (const key of allKeys) {
6900
+ const o = ourByKey.get(key);
6901
+ const t = theirByKey.get(key);
6902
+ if (o && t) {
6903
+ const oTime = o.lastRotatedAt.getTime();
6904
+ const tTime = t.lastRotatedAt.getTime();
6905
+ const winner = tTime > oTime ? t : o;
6906
+ byKey.set(key, {
6907
+ key,
6908
+ lastRotatedAt: winner.lastRotatedAt,
6909
+ rotatedBy: winner.rotatedBy,
6910
+ rotationCount: Math.max(o.rotationCount, t.rotationCount) + 1
6911
+ });
6912
+ } else if (o) {
6913
+ byKey.set(key, o);
6914
+ } else if (t) {
6915
+ byKey.set(key, t);
6916
+ }
6917
+ }
6918
+ return Array.from(byKey.values());
6919
+ }
6920
+ function mergePending(oursPending, theirsPending, oursRotations, theirsRotations) {
6921
+ const ourByKey = new Map(oursPending.map((p) => [p.key, p]));
6922
+ const theirByKey = new Map(theirsPending.map((p) => [p.key, p]));
6923
+ const rotatedKeys = /* @__PURE__ */ new Set([
6924
+ ...oursRotations.map((r) => r.key),
6925
+ ...theirsRotations.map((r) => r.key)
6926
+ ]);
6927
+ const allKeys = /* @__PURE__ */ new Set([...ourByKey.keys(), ...theirByKey.keys()]);
6928
+ const out = [];
6929
+ for (const key of allKeys) {
6930
+ if (rotatedKeys.has(key)) continue;
6931
+ const o = ourByKey.get(key);
6932
+ const t = theirByKey.get(key);
6933
+ if (o && t) {
6934
+ const winner = t.since.getTime() > o.since.getTime() ? t : o;
6935
+ out.push({ key, since: winner.since, setBy: winner.setBy });
6936
+ } else if (o) {
6937
+ out.push(o);
6938
+ } else if (t) {
6939
+ out.push(t);
6940
+ }
6941
+ }
6942
+ return out;
6943
+ }
6944
+ function mergeMetadataContents(oursContent, theirsContent) {
6945
+ const ours = parseMetadata(oursContent);
6946
+ const theirs = parseMetadata(theirsContent);
6947
+ const rotations = mergeRotations(ours.rotations, theirs.rotations);
6948
+ const pending = mergePending(ours.pending, theirs.pending, ours.rotations, theirs.rotations);
6949
+ return serializeMetadata({ version: 1, pending, rotations });
6950
+ }
6951
+ function mergeMetadataFiles(_basePath, oursPath, theirsPath) {
6952
+ const oursContent = fs17.existsSync(oursPath) ? fs17.readFileSync(oursPath, "utf-8") : "";
6953
+ const theirsContent = fs17.existsSync(theirsPath) ? fs17.readFileSync(theirsPath, "utf-8") : "";
6954
+ const merged = mergeMetadataContents(oursContent, theirsContent);
6955
+ fs17.writeFileSync(oursPath, merged, "utf-8");
6956
+ }
6957
+
6461
6958
  // src/service-identity/manager.ts
6462
- import * as path19 from "path";
6959
+ import * as path21 from "path";
6463
6960
  var ServiceIdentityManager = class {
6464
6961
  constructor(encryption, matrixManager, tx) {
6465
6962
  this.encryption = encryption;
@@ -6471,7 +6968,7 @@ var ServiceIdentityManager = class {
6471
6968
  * to seed TransactionManager.run's `paths` argument.
6472
6969
  */
6473
6970
  txPaths(repoRoot, cells) {
6474
- return [...cells.map((c) => path19.relative(repoRoot, c.filePath)), CLEF_MANIFEST_FILENAME];
6971
+ return [...cells.map((c) => path21.relative(repoRoot, c.filePath)), CLEF_MANIFEST_FILENAME];
6475
6972
  }
6476
6973
  /**
6477
6974
  * Create a new service identity with per-environment age key pairs or KMS envelope config.
@@ -6993,8 +7490,8 @@ var ServiceIdentityManager = class {
6993
7490
  };
6994
7491
 
6995
7492
  // src/structure/manager.ts
6996
- import * as fs15 from "fs";
6997
- import * as path20 from "path";
7493
+ import * as fs18 from "fs";
7494
+ import * as path22 from "path";
6998
7495
  var StructureManager = class {
6999
7496
  constructor(matrixManager, encryption, tx) {
7000
7497
  this.matrixManager = matrixManager;
@@ -7015,15 +7512,15 @@ var StructureManager = class {
7015
7512
  this.assertValidIdentifier("namespace", name);
7016
7513
  const newCellPaths = manifest.environments.map((env) => ({
7017
7514
  environment: env.name,
7018
- filePath: path20.join(
7515
+ filePath: path22.join(
7019
7516
  repoRoot,
7020
7517
  manifest.file_pattern.replace("{namespace}", name).replace("{environment}", env.name)
7021
7518
  )
7022
7519
  }));
7023
7520
  for (const cell of newCellPaths) {
7024
- if (fs15.existsSync(cell.filePath)) {
7521
+ if (fs18.existsSync(cell.filePath)) {
7025
7522
  throw new Error(
7026
- `Cannot add namespace '${name}': file '${path20.relative(repoRoot, cell.filePath)}' already exists.`
7523
+ `Cannot add namespace '${name}': file '${path22.relative(repoRoot, cell.filePath)}' already exists.`
7027
7524
  );
7028
7525
  }
7029
7526
  }
@@ -7042,7 +7539,7 @@ var StructureManager = class {
7042
7539
  await this.tx.run(repoRoot, {
7043
7540
  description: `clef namespace add ${name}`,
7044
7541
  paths: [
7045
- ...newCellPaths.map((c) => path20.relative(repoRoot, c.filePath)),
7542
+ ...newCellPaths.map((c) => path22.relative(repoRoot, c.filePath)),
7046
7543
  CLEF_MANIFEST_FILENAME
7047
7544
  ],
7048
7545
  mutate: async () => {
@@ -7087,15 +7584,15 @@ var StructureManager = class {
7087
7584
  this.assertValidIdentifier("environment", name);
7088
7585
  const newCellPaths = manifest.namespaces.map((ns) => ({
7089
7586
  namespace: ns.name,
7090
- filePath: path20.join(
7587
+ filePath: path22.join(
7091
7588
  repoRoot,
7092
7589
  manifest.file_pattern.replace("{namespace}", ns.name).replace("{environment}", name)
7093
7590
  )
7094
7591
  }));
7095
7592
  for (const cell of newCellPaths) {
7096
- if (fs15.existsSync(cell.filePath)) {
7593
+ if (fs18.existsSync(cell.filePath)) {
7097
7594
  throw new Error(
7098
- `Cannot add environment '${name}': file '${path20.relative(repoRoot, cell.filePath)}' already exists.`
7595
+ `Cannot add environment '${name}': file '${path22.relative(repoRoot, cell.filePath)}' already exists.`
7099
7596
  );
7100
7597
  }
7101
7598
  }
@@ -7114,7 +7611,7 @@ var StructureManager = class {
7114
7611
  await this.tx.run(repoRoot, {
7115
7612
  description: `clef env add ${name}`,
7116
7613
  paths: [
7117
- ...newCellPaths.map((c) => path20.relative(repoRoot, c.filePath)),
7614
+ ...newCellPaths.map((c) => path22.relative(repoRoot, c.filePath)),
7118
7615
  CLEF_MANIFEST_FILENAME
7119
7616
  ],
7120
7617
  mutate: async () => {
@@ -7177,7 +7674,7 @@ var StructureManager = class {
7177
7674
  paths: this.deletePaths(repoRoot, cellsToDelete),
7178
7675
  mutate: async () => {
7179
7676
  for (const cell of cellsToDelete) {
7180
- fs15.unlinkSync(cell.filePath);
7677
+ fs18.unlinkSync(cell.filePath);
7181
7678
  this.unlinkMetaSibling(cell.filePath);
7182
7679
  }
7183
7680
  const doc = readManifestYaml(repoRoot);
@@ -7227,7 +7724,7 @@ var StructureManager = class {
7227
7724
  paths: this.deletePaths(repoRoot, cellsToDelete),
7228
7725
  mutate: async () => {
7229
7726
  for (const cell of cellsToDelete) {
7230
- fs15.unlinkSync(cell.filePath);
7727
+ fs18.unlinkSync(cell.filePath);
7231
7728
  this.unlinkMetaSibling(cell.filePath);
7232
7729
  }
7233
7730
  const doc = readManifestYaml(repoRoot);
@@ -7269,9 +7766,9 @@ var StructureManager = class {
7269
7766
  const renamePairs = isRename ? this.collectRenamePairs(manifest, repoRoot, name, opts.rename, "namespace") : [];
7270
7767
  if (isRename) {
7271
7768
  for (const pair of renamePairs) {
7272
- if (fs15.existsSync(pair.to)) {
7769
+ if (fs18.existsSync(pair.to)) {
7273
7770
  throw new Error(
7274
- `Rename target '${path20.relative(repoRoot, pair.to)}' already exists. Move or remove it first.`
7771
+ `Rename target '${path22.relative(repoRoot, pair.to)}' already exists. Move or remove it first.`
7275
7772
  );
7276
7773
  }
7277
7774
  }
@@ -7312,9 +7809,9 @@ var StructureManager = class {
7312
7809
  const renamePairs = isRename ? this.collectRenamePairs(manifest, repoRoot, name, opts.rename, "environment") : [];
7313
7810
  if (isRename) {
7314
7811
  for (const pair of renamePairs) {
7315
- if (fs15.existsSync(pair.to)) {
7812
+ if (fs18.existsSync(pair.to)) {
7316
7813
  throw new Error(
7317
- `Rename target '${path20.relative(repoRoot, pair.to)}' already exists. Move or remove it first.`
7814
+ `Rename target '${path22.relative(repoRoot, pair.to)}' already exists. Move or remove it first.`
7318
7815
  );
7319
7816
  }
7320
7817
  }
@@ -7349,7 +7846,7 @@ var StructureManager = class {
7349
7846
  const newCellPath = this.swapAxisInCellPath(repoRoot, manifest, cell, axis, newName);
7350
7847
  pairs.push({ from: cell.filePath, to: newCellPath });
7351
7848
  const oldMeta = cell.filePath.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml");
7352
- if (fs15.existsSync(oldMeta)) {
7849
+ if (fs18.existsSync(oldMeta)) {
7353
7850
  const newMeta = newCellPath.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml");
7354
7851
  pairs.push({ from: oldMeta, to: newMeta });
7355
7852
  }
@@ -7364,7 +7861,7 @@ var StructureManager = class {
7364
7861
  swapAxisInCellPath(repoRoot, manifest, cell, axis, newName) {
7365
7862
  const ns = axis === "namespace" ? newName : cell.namespace;
7366
7863
  const env = axis === "environment" ? newName : cell.environment;
7367
- return path20.join(
7864
+ return path22.join(
7368
7865
  repoRoot,
7369
7866
  manifest.file_pattern.replace("{namespace}", ns).replace("{environment}", env)
7370
7867
  );
@@ -7376,8 +7873,8 @@ var StructureManager = class {
7376
7873
  txPaths(repoRoot, renamePairs) {
7377
7874
  const paths = /* @__PURE__ */ new Set();
7378
7875
  for (const pair of renamePairs) {
7379
- paths.add(path20.relative(repoRoot, pair.from));
7380
- paths.add(path20.relative(repoRoot, pair.to));
7876
+ paths.add(path22.relative(repoRoot, pair.from));
7877
+ paths.add(path22.relative(repoRoot, pair.to));
7381
7878
  }
7382
7879
  paths.add(CLEF_MANIFEST_FILENAME);
7383
7880
  return [...paths];
@@ -7388,11 +7885,11 @@ var StructureManager = class {
7388
7885
  */
7389
7886
  applyRenames(pairs) {
7390
7887
  for (const pair of pairs) {
7391
- const targetDir = path20.dirname(pair.to);
7392
- if (!fs15.existsSync(targetDir)) {
7393
- fs15.mkdirSync(targetDir, { recursive: true });
7888
+ const targetDir = path22.dirname(pair.to);
7889
+ if (!fs18.existsSync(targetDir)) {
7890
+ fs18.mkdirSync(targetDir, { recursive: true });
7394
7891
  }
7395
- fs15.renameSync(pair.from, pair.to);
7892
+ fs18.renameSync(pair.from, pair.to);
7396
7893
  }
7397
7894
  }
7398
7895
  /**
@@ -7403,10 +7900,10 @@ var StructureManager = class {
7403
7900
  deletePaths(repoRoot, cells) {
7404
7901
  const paths = /* @__PURE__ */ new Set();
7405
7902
  for (const cell of cells) {
7406
- paths.add(path20.relative(repoRoot, cell.filePath));
7903
+ paths.add(path22.relative(repoRoot, cell.filePath));
7407
7904
  const meta = cell.filePath.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml");
7408
- if (fs15.existsSync(meta)) {
7409
- paths.add(path20.relative(repoRoot, meta));
7905
+ if (fs18.existsSync(meta)) {
7906
+ paths.add(path22.relative(repoRoot, meta));
7410
7907
  }
7411
7908
  }
7412
7909
  paths.add(CLEF_MANIFEST_FILENAME);
@@ -7419,8 +7916,8 @@ var StructureManager = class {
7419
7916
  */
7420
7917
  unlinkMetaSibling(cellPath) {
7421
7918
  const meta = cellPath.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml");
7422
- if (fs15.existsSync(meta)) {
7423
- fs15.unlinkSync(meta);
7919
+ if (fs18.existsSync(meta)) {
7920
+ fs18.unlinkSync(meta);
7424
7921
  }
7425
7922
  }
7426
7923
  /**
@@ -7565,20 +8062,20 @@ async function resolveIdentitySecrets(identityName, environment, manifest, repoR
7565
8062
  import * as crypto3 from "crypto";
7566
8063
 
7567
8064
  // src/artifact/output.ts
7568
- import * as fs16 from "fs";
7569
- import * as path21 from "path";
8065
+ import * as fs19 from "fs";
8066
+ import * as path23 from "path";
7570
8067
  var FilePackOutput = class {
7571
8068
  constructor(outputPath) {
7572
8069
  this.outputPath = outputPath;
7573
8070
  }
7574
8071
  async write(_artifact, json) {
7575
- const outputDir = path21.dirname(this.outputPath);
7576
- if (!fs16.existsSync(outputDir)) {
7577
- fs16.mkdirSync(outputDir, { recursive: true });
8072
+ const outputDir = path23.dirname(this.outputPath);
8073
+ if (!fs19.existsSync(outputDir)) {
8074
+ fs19.mkdirSync(outputDir, { recursive: true });
7578
8075
  }
7579
8076
  const tmpOutput = `${this.outputPath}.tmp.${process.pid}`;
7580
- fs16.writeFileSync(tmpOutput, json, "utf-8");
7581
- fs16.renameSync(tmpOutput, this.outputPath);
8077
+ fs19.writeFileSync(tmpOutput, json, "utf-8");
8078
+ fs19.renameSync(tmpOutput, this.outputPath);
7582
8079
  }
7583
8080
  };
7584
8081
  var MemoryPackOutput = class {
@@ -7785,28 +8282,187 @@ var ArtifactPacker = class {
7785
8282
  const json = JSON.stringify(artifact, null, 2);
7786
8283
  const output = config.output ?? new FilePackOutput(config.outputPath ?? "artifact.json");
7787
8284
  await output.write(artifact, json);
8285
+ const keys = Object.keys(resolved.values);
7788
8286
  return {
7789
8287
  outputPath: config.outputPath ?? "",
7790
8288
  namespaceCount: resolved.identity.namespaces.length,
7791
- keyCount: Object.keys(resolved.values).length,
8289
+ keyCount: keys.length,
8290
+ keys,
7792
8291
  artifactSize: Buffer.byteLength(json, "utf-8"),
7793
8292
  revision: artifact.revision
7794
8293
  };
7795
8294
  }
7796
8295
  };
7797
8296
 
8297
+ // src/artifact/guards.ts
8298
+ var InvalidArtifactError = class extends ClefError {
8299
+ constructor(message) {
8300
+ super(
8301
+ message,
8302
+ "Ensure the artifact was produced by a compatible clef version and was not tampered with."
8303
+ );
8304
+ this.name = "InvalidArtifactError";
8305
+ }
8306
+ };
8307
+ var VALID_SIGNATURE_ALGORITHMS = ["Ed25519", "ECDSA_SHA256"];
8308
+ function isKmsEnvelope2(x) {
8309
+ if (typeof x !== "object" || x === null) return false;
8310
+ const o = x;
8311
+ return typeof o.provider === "string" && typeof o.keyId === "string" && typeof o.wrappedKey === "string" && typeof o.algorithm === "string" && typeof o.iv === "string" && typeof o.authTag === "string";
8312
+ }
8313
+ function validatePackedArtifact(x) {
8314
+ if (typeof x !== "object" || x === null) {
8315
+ return { valid: false, reason: "expected object" };
8316
+ }
8317
+ const o = x;
8318
+ if (o.version !== 1) {
8319
+ return { valid: false, reason: `unsupported version: ${String(o.version)}` };
8320
+ }
8321
+ if (typeof o.identity !== "string") {
8322
+ return { valid: false, reason: "missing or invalid 'identity' (expected string)" };
8323
+ }
8324
+ if (typeof o.environment !== "string") {
8325
+ return { valid: false, reason: "missing or invalid 'environment' (expected string)" };
8326
+ }
8327
+ if (typeof o.packedAt !== "string") {
8328
+ return { valid: false, reason: "missing or invalid 'packedAt' (expected string)" };
8329
+ }
8330
+ if (typeof o.revision !== "string") {
8331
+ return { valid: false, reason: "missing or invalid 'revision' (expected string)" };
8332
+ }
8333
+ if (typeof o.ciphertextHash !== "string") {
8334
+ return { valid: false, reason: "missing or invalid 'ciphertextHash' (expected string)" };
8335
+ }
8336
+ if (typeof o.ciphertext !== "string") {
8337
+ return { valid: false, reason: "missing or invalid 'ciphertext' (expected string)" };
8338
+ }
8339
+ if (o.envelope !== void 0 && !isKmsEnvelope2(o.envelope)) {
8340
+ return { valid: false, reason: "invalid 'envelope' (expected KmsEnvelope shape)" };
8341
+ }
8342
+ if (o.expiresAt !== void 0 && typeof o.expiresAt !== "string") {
8343
+ return { valid: false, reason: "invalid 'expiresAt' (expected string)" };
8344
+ }
8345
+ if (o.revokedAt !== void 0 && typeof o.revokedAt !== "string") {
8346
+ return { valid: false, reason: "invalid 'revokedAt' (expected string)" };
8347
+ }
8348
+ if (o.signature !== void 0 && typeof o.signature !== "string") {
8349
+ return { valid: false, reason: "invalid 'signature' (expected string)" };
8350
+ }
8351
+ if (o.signatureAlgorithm !== void 0 && !VALID_SIGNATURE_ALGORITHMS.includes(o.signatureAlgorithm)) {
8352
+ return {
8353
+ valid: false,
8354
+ reason: `invalid 'signatureAlgorithm': expected one of ${VALID_SIGNATURE_ALGORITHMS.join(", ")}`
8355
+ };
8356
+ }
8357
+ return { valid: true, value: o };
8358
+ }
8359
+ function isPackedArtifact(x) {
8360
+ return validatePackedArtifact(x).valid;
8361
+ }
8362
+ function assertPackedArtifact(x, context) {
8363
+ const result = validatePackedArtifact(x);
8364
+ if (!result.valid) {
8365
+ const prefix = context ? `${context}: ` : "";
8366
+ throw new InvalidArtifactError(`${prefix}${result.reason}`);
8367
+ }
8368
+ }
8369
+
8370
+ // src/pack/registry.ts
8371
+ var PackBackendRegistry = class {
8372
+ factories = /* @__PURE__ */ new Map();
8373
+ /**
8374
+ * Register a backend factory under the given id. Throws if a backend
8375
+ * with the same id is already registered — collisions surface as a clear
8376
+ * error rather than a silent overwrite.
8377
+ */
8378
+ register(id, factory) {
8379
+ if (this.factories.has(id)) {
8380
+ throw new Error(`Pack backend "${id}" is already registered.`);
8381
+ }
8382
+ this.factories.set(id, factory);
8383
+ }
8384
+ /** Whether a backend with the given id has been registered. */
8385
+ has(id) {
8386
+ return this.factories.has(id);
8387
+ }
8388
+ /** Registered backend ids, in registration order. */
8389
+ list() {
8390
+ return [...this.factories.keys()];
8391
+ }
8392
+ /**
8393
+ * Resolve a backend by id. Throws if unknown. Factories may be async so
8394
+ * a plugin package can defer construction (e.g. loading a heavy SDK only
8395
+ * when the backend is actually used).
8396
+ */
8397
+ async resolve(id) {
8398
+ const factory = this.factories.get(id);
8399
+ if (!factory) {
8400
+ const available = this.list().join(", ") || "(none)";
8401
+ throw new Error(`Unknown pack backend "${id}". Available backends: ${available}`);
8402
+ }
8403
+ return await factory();
8404
+ }
8405
+ };
8406
+
8407
+ // src/pack/backends/json-envelope.ts
8408
+ var JsonEnvelopeBackend = class {
8409
+ id = "json-envelope";
8410
+ description = "Write the Clef JSON artifact envelope to a local file (default).";
8411
+ validateOptions(raw) {
8412
+ const opts = raw;
8413
+ if (opts.signingKey && opts.signingKmsKeyId) {
8414
+ throw new Error(
8415
+ "Cannot specify both signingKey (Ed25519) and signingKmsKeyId (KMS). Choose one."
8416
+ );
8417
+ }
8418
+ if (!opts.outputPath && !opts.output) {
8419
+ throw new Error("json-envelope backend requires an 'outputPath' or 'output' option.");
8420
+ }
8421
+ }
8422
+ async pack(req) {
8423
+ const opts = req.backendOptions;
8424
+ const packer = new ArtifactPacker(
8425
+ req.services.encryption,
8426
+ new MatrixManager(),
8427
+ req.services.kms
8428
+ );
8429
+ const output = opts.output ?? (opts.outputPath ? new FilePackOutput(opts.outputPath) : void 0);
8430
+ const result = await packer.pack(
8431
+ {
8432
+ identity: req.identity,
8433
+ environment: req.environment,
8434
+ outputPath: opts.outputPath,
8435
+ output,
8436
+ ttl: req.ttl,
8437
+ signingKey: opts.signingKey,
8438
+ signingKmsKeyId: opts.signingKmsKeyId
8439
+ },
8440
+ req.manifest,
8441
+ req.repoRoot
8442
+ );
8443
+ return {
8444
+ ...result,
8445
+ backend: this.id,
8446
+ details: {
8447
+ outputPath: opts.outputPath ?? null
8448
+ }
8449
+ };
8450
+ }
8451
+ };
8452
+
7798
8453
  // src/kms/types.ts
7799
8454
  var VALID_KMS_PROVIDERS = ["aws", "gcp", "azure"];
7800
8455
 
7801
8456
  // src/migration/backend.ts
7802
- import * as path22 from "path";
7803
- import * as YAML10 from "yaml";
8457
+ import * as path24 from "path";
8458
+ import * as YAML11 from "yaml";
7804
8459
  var BACKEND_KEY_FIELDS = {
7805
8460
  age: void 0,
7806
8461
  awskms: "aws_kms_arn",
7807
8462
  gcpkms: "gcp_kms_resource_id",
7808
8463
  azurekv: "azure_kv_url",
7809
- pgp: "pgp_fingerprint"
8464
+ pgp: "pgp_fingerprint",
8465
+ hsm: "pkcs11_uri"
7810
8466
  };
7811
8467
  var ALL_KEY_FIELDS = Object.values(BACKEND_KEY_FIELDS).filter(
7812
8468
  (v) => v !== void 0
@@ -7916,14 +8572,14 @@ var BackendMigrator = class {
7916
8572
  await this.tx.run(repoRoot, {
7917
8573
  description: environment ? `clef migrate-backend ${target.backend}: ${environment}` : `clef migrate-backend ${target.backend}`,
7918
8574
  paths: [
7919
- ...toMigrate.map((c) => path22.relative(repoRoot, c.filePath)),
8575
+ ...toMigrate.map((c) => path24.relative(repoRoot, c.filePath)),
7920
8576
  CLEF_MANIFEST_FILENAME
7921
8577
  ],
7922
8578
  mutate: async () => {
7923
8579
  const doc = readManifestYaml(repoRoot);
7924
8580
  this.updateManifestDoc(doc, target, environment);
7925
8581
  writeManifestYaml(repoRoot, doc);
7926
- const updatedManifest = YAML10.parse(YAML10.stringify(doc));
8582
+ const updatedManifest = YAML11.parse(YAML11.stringify(doc));
7927
8583
  for (const cell of toMigrate) {
7928
8584
  onProgress?.({
7929
8585
  type: "migrate",
@@ -8014,7 +8670,7 @@ var BackendMigrator = class {
8014
8670
  };
8015
8671
 
8016
8672
  // src/reset/manager.ts
8017
- import * as path23 from "path";
8673
+ import * as path25 from "path";
8018
8674
  var ResetManager = class {
8019
8675
  constructor(matrixManager, encryption, schemaValidator, tx) {
8020
8676
  this.matrixManager = matrixManager;
@@ -8039,11 +8695,11 @@ var ResetManager = class {
8039
8695
  txPaths.push(CLEF_MANIFEST_FILENAME);
8040
8696
  }
8041
8697
  for (const cell of targetCells) {
8042
- txPaths.push(path23.relative(repoRoot, cell.filePath));
8698
+ txPaths.push(path25.relative(repoRoot, cell.filePath));
8043
8699
  const cellKeys = keyPlan.get(cell.namespace) ?? [];
8044
8700
  if (cellKeys.length > 0) {
8045
8701
  txPaths.push(
8046
- path23.relative(repoRoot, cell.filePath.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml"))
8702
+ path25.relative(repoRoot, cell.filePath.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml"))
8047
8703
  );
8048
8704
  }
8049
8705
  }
@@ -8131,7 +8787,7 @@ var ResetManager = class {
8131
8787
  for (const namespace of namespaces) {
8132
8788
  const nsDef = manifest.namespaces.find((n) => n.name === namespace);
8133
8789
  if (nsDef?.schema) {
8134
- const schema = this.schemaValidator.loadSchema(path23.join(repoRoot, nsDef.schema));
8790
+ const schema = this.schemaValidator.loadSchema(path25.join(repoRoot, nsDef.schema));
8135
8791
  plan.set(namespace, Object.keys(schema.keys));
8136
8792
  continue;
8137
8793
  }
@@ -8210,7 +8866,7 @@ function withBackendOverride(manifest, envNames, backend, key) {
8210
8866
  }
8211
8867
 
8212
8868
  // src/sync/manager.ts
8213
- import * as path24 from "path";
8869
+ import * as path26 from "path";
8214
8870
  var SyncManager = class {
8215
8871
  constructor(matrixManager, encryption, tx) {
8216
8872
  this.matrixManager = matrixManager;
@@ -8279,7 +8935,7 @@ var SyncManager = class {
8279
8935
  }
8280
8936
  const txPaths = [];
8281
8937
  for (const cell of syncPlan.cells) {
8282
- const rel = path24.relative(repoRoot, cell.filePath);
8938
+ const rel = path26.relative(repoRoot, cell.filePath);
8283
8939
  txPaths.push(rel);
8284
8940
  txPaths.push(rel.replace(/\.enc\.(yaml|json)$/, ".clef-meta.yaml"));
8285
8941
  }
@@ -8318,8 +8974,8 @@ var SyncManager = class {
8318
8974
  };
8319
8975
 
8320
8976
  // src/policy/parser.ts
8321
- import * as fs17 from "fs";
8322
- import * as YAML11 from "yaml";
8977
+ import * as fs20 from "fs";
8978
+ import * as YAML12 from "yaml";
8323
8979
 
8324
8980
  // src/policy/types.ts
8325
8981
  var DEFAULT_POLICY = Object.freeze({
@@ -8340,7 +8996,7 @@ var PolicyParser = class {
8340
8996
  parse(filePath) {
8341
8997
  let raw;
8342
8998
  try {
8343
- raw = fs17.readFileSync(filePath, "utf-8");
8999
+ raw = fs20.readFileSync(filePath, "utf-8");
8344
9000
  } catch {
8345
9001
  throw new PolicyValidationError(`Could not read policy file at '${filePath}'.`);
8346
9002
  }
@@ -8355,7 +9011,7 @@ var PolicyParser = class {
8355
9011
  parseContent(content) {
8356
9012
  let parsed;
8357
9013
  try {
8358
- parsed = YAML11.parse(content);
9014
+ parsed = YAML12.parse(content);
8359
9015
  } catch {
8360
9016
  throw new PolicyValidationError(
8361
9017
  "Policy file contains invalid YAML. Check for syntax errors."
@@ -8368,7 +9024,7 @@ var PolicyParser = class {
8368
9024
  * not exist. Any other read or validation error throws.
8369
9025
  */
8370
9026
  load(filePath) {
8371
- if (!fs17.existsSync(filePath)) return DEFAULT_POLICY;
9027
+ if (!fs20.existsSync(filePath)) return DEFAULT_POLICY;
8372
9028
  return this.parse(filePath);
8373
9029
  }
8374
9030
  validate(raw) {
@@ -8436,31 +9092,64 @@ var PolicyEvaluator = class {
8436
9092
  this.policy = policy;
8437
9093
  }
8438
9094
  /**
8439
- * Evaluate a single encrypted file's rotation state.
9095
+ * Evaluate a single encrypted file's per-key rotation state.
8440
9096
  *
8441
9097
  * @param filePath Repo-relative or absolute path to the encrypted file.
8442
- * @param environment Environment name from the matrix; selects per-env
8443
- * overrides if present in the policy.
8444
- * @param metadata Result of `SopsClient.getMetadata()` for the file.
8445
- * @param now Reference time (defaults to `new Date()`). Inject for
8446
- * deterministic tests and reproducible audits.
9098
+ * @param environment Environment name; selects per-env overrides.
9099
+ * @param metadata SOPS metadata for the file (carries last_modified,
9100
+ * backend, recipients). The evaluator does not read
9101
+ * `last_modified` for the policy gate it is echoed
9102
+ * into the output for audit consumers only.
9103
+ * @param keys Plaintext key names present in the cipher, enumerated
9104
+ * from the unencrypted YAML top-level keys (no decrypt
9105
+ * required since SOPS stores key names in plaintext).
9106
+ * @param rotations Rotation records from `.clef-meta.yaml`. Records for
9107
+ * keys not in `keys` are ignored (those are orphans;
9108
+ * lint surfaces them as a warning).
9109
+ * @param now Reference time. Inject for deterministic tests.
8447
9110
  */
8448
- evaluateFile(filePath, environment, metadata, now = /* @__PURE__ */ new Date()) {
9111
+ evaluateFile(filePath, environment, metadata, keys, rotations, now = /* @__PURE__ */ new Date()) {
8449
9112
  const maxAgeDays = this.resolveMaxAgeDays(environment);
8450
- const rotationDue = new Date(metadata.lastModified.getTime() + maxAgeDays * MS_PER_DAY);
8451
- const rotationOverdue = now.getTime() > rotationDue.getTime();
8452
- const daysOverdue = rotationOverdue ? Math.floor((now.getTime() - rotationDue.getTime()) / MS_PER_DAY) : 0;
9113
+ const byKey = new Map(rotations.map((r) => [r.key, r]));
9114
+ const keyStatuses = keys.map(
9115
+ (key) => this.evaluateKey(key, byKey.get(key), maxAgeDays, now)
9116
+ );
8453
9117
  return {
8454
9118
  path: filePath,
8455
9119
  environment,
8456
9120
  backend: metadata.backend,
8457
9121
  recipients: metadata.recipients,
8458
9122
  last_modified: metadata.lastModified.toISOString(),
8459
- // Treat a missing `lastModifiedPresent` as `true` — the field is
8460
- // optional on SopsMetadata and only `parseMetadataFromFile` knows
8461
- // authoritatively whether the underlying file carried `sops.lastmodified`.
8462
- // Hand-constructed metadata is assumed trustworthy.
8463
9123
  last_modified_known: metadata.lastModifiedPresent !== false,
9124
+ keys: keyStatuses,
9125
+ // Cell-level compliance is the AND of per-key verdicts. An empty
9126
+ // `keys` array (cell with no secrets) is vacuously compliant.
9127
+ compliant: keyStatuses.every((k) => k.compliant)
9128
+ };
9129
+ }
9130
+ evaluateKey(key, record, maxAgeDays, now) {
9131
+ if (!record) {
9132
+ return {
9133
+ key,
9134
+ last_rotated_at: null,
9135
+ last_rotated_known: false,
9136
+ rotated_by: null,
9137
+ rotation_count: 0,
9138
+ rotation_due: null,
9139
+ rotation_overdue: false,
9140
+ days_overdue: 0,
9141
+ compliant: false
9142
+ };
9143
+ }
9144
+ const rotationDue = new Date(record.lastRotatedAt.getTime() + maxAgeDays * MS_PER_DAY);
9145
+ const rotationOverdue = now.getTime() > rotationDue.getTime();
9146
+ const daysOverdue = rotationOverdue ? Math.floor((now.getTime() - rotationDue.getTime()) / MS_PER_DAY) : 0;
9147
+ return {
9148
+ key,
9149
+ last_rotated_at: record.lastRotatedAt.toISOString(),
9150
+ last_rotated_known: true,
9151
+ rotated_by: record.rotatedBy,
9152
+ rotation_count: record.rotationCount,
8464
9153
  rotation_due: rotationDue.toISOString(),
8465
9154
  rotation_overdue: rotationOverdue,
8466
9155
  days_overdue: daysOverdue,
@@ -8516,10 +9205,11 @@ var ComplianceGenerator = class {
8516
9205
  return `sha256:${createHash3("sha256").update(canonicalJson(policy)).digest("hex")}`;
8517
9206
  }
8518
9207
  buildSummary(scan, lint, files) {
9208
+ const rotationOverdue = files.filter((f) => !f.compliant).length;
8519
9209
  return {
8520
9210
  total_files: files.length,
8521
9211
  compliant: files.filter((f) => f.compliant).length,
8522
- rotation_overdue: files.filter((f) => f.rotation_overdue).length,
9212
+ rotation_overdue: rotationOverdue,
8523
9213
  scan_violations: scan.matches.length,
8524
9214
  lint_errors: lint.issues.filter((i) => i.severity === "error").length
8525
9215
  };
@@ -8527,13 +9217,13 @@ var ComplianceGenerator = class {
8527
9217
  };
8528
9218
 
8529
9219
  // src/compliance/run.ts
8530
- import * as path25 from "path";
9220
+ import * as path27 from "path";
8531
9221
  var UNKNOWN = "unknown";
8532
9222
  async function runCompliance(opts) {
8533
9223
  const start = Date.now();
8534
9224
  const repoRoot = opts.repoRoot ?? process.cwd();
8535
- const manifestPath = opts.manifestPath ?? path25.join(repoRoot, "clef.yaml");
8536
- const policyPath = opts.policyPath ?? path25.join(repoRoot, CLEF_POLICY_FILENAME);
9225
+ const manifestPath = opts.manifestPath ?? path27.join(repoRoot, "clef.yaml");
9226
+ const policyPath = opts.policyPath ?? path27.join(repoRoot, CLEF_POLICY_FILENAME);
8537
9227
  const include = {
8538
9228
  scan: opts.include?.scan ?? true,
8539
9229
  lint: opts.include?.lint ?? true,
@@ -8542,7 +9232,7 @@ async function runCompliance(opts) {
8542
9232
  const now = opts.now ?? /* @__PURE__ */ new Date();
8543
9233
  const manifest = new ManifestParser().parse(manifestPath);
8544
9234
  const policy = opts.policy ?? new PolicyParser().load(policyPath);
8545
- const sopsClient = new SopsClient(opts.runner);
9235
+ const sopsClient = new SopsClient(opts.runner, opts.ageKeyFile, opts.ageKey, opts.sopsPath);
8546
9236
  const matrixManager = new MatrixManager();
8547
9237
  const schemaValidator = new SchemaValidator();
8548
9238
  const [sha, repo, files, scanResult, lintResult] = await Promise.all([
@@ -8560,12 +9250,13 @@ async function runCompliance(opts) {
8560
9250
  include.scan ? new ScanRunner(opts.runner).scan(repoRoot, manifest) : Promise.resolve(emptyScan()),
8561
9251
  include.lint ? new LintRunner(matrixManager, schemaValidator, sopsClient).run(manifest, repoRoot) : Promise.resolve(emptyLint())
8562
9252
  ]);
9253
+ const adjustedLint = downgradeDecryptIssues(lintResult);
8563
9254
  const document = new ComplianceGenerator().generate({
8564
9255
  sha,
8565
9256
  repo,
8566
9257
  policy,
8567
9258
  scanResult,
8568
- lintResult,
9259
+ lintResult: adjustedLint,
8569
9260
  files,
8570
9261
  now
8571
9262
  });
@@ -8578,8 +9269,10 @@ async function evaluateMatrix(args) {
8578
9269
  return Promise.all(
8579
9270
  cells.map(async (cell) => {
8580
9271
  const metadata = await args.sopsClient.getMetadata(cell.filePath);
8581
- const relPath = path25.relative(args.repoRoot, cell.filePath).replace(/\\/g, "/");
8582
- return evaluator.evaluateFile(relPath, cell.environment, metadata, args.now);
9272
+ const relPath = path27.relative(args.repoRoot, cell.filePath).replace(/\\/g, "/");
9273
+ const keys = readSopsKeyNames(cell.filePath) ?? [];
9274
+ const rotations = await getRotations(cell.filePath);
9275
+ return evaluator.evaluateFile(relPath, cell.environment, metadata, keys, rotations, args.now);
8583
9276
  })
8584
9277
  );
8585
9278
  }
@@ -8600,6 +9293,21 @@ function emptyScan() {
8600
9293
  function emptyLint() {
8601
9294
  return { issues: [], fileCount: 0, pendingCount: 0 };
8602
9295
  }
9296
+ function downgradeDecryptIssues(result) {
9297
+ return {
9298
+ ...result,
9299
+ issues: result.issues.map((issue) => {
9300
+ if (issue.category === "sops" && issue.message.startsWith("Failed to decrypt")) {
9301
+ return {
9302
+ ...issue,
9303
+ severity: "info",
9304
+ message: `File not decryptable in this environment (compliance runs without keys). Original check: ${issue.message}`
9305
+ };
9306
+ }
9307
+ return issue;
9308
+ })
9309
+ };
9310
+ }
8603
9311
  async function detectSha(runner, repoRoot) {
8604
9312
  const env = process.env;
8605
9313
  const fromEnv = env.GITHUB_SHA ?? env.CI_COMMIT_SHA ?? env.BITBUCKET_COMMIT ?? env.CIRCLE_SHA1 ?? env.BUILD_VCS_NUMBER;
@@ -8639,11 +9347,14 @@ export {
8639
9347
  GitIntegration,
8640
9348
  GitOperationError,
8641
9349
  ImportRunner,
9350
+ InvalidArtifactError,
9351
+ JsonEnvelopeBackend,
8642
9352
  LintRunner,
8643
9353
  ManifestParser,
8644
9354
  ManifestValidationError,
8645
9355
  MatrixManager,
8646
9356
  MemoryPackOutput,
9357
+ PackBackendRegistry,
8647
9358
  PolicyEvaluator,
8648
9359
  PolicyParser,
8649
9360
  PolicyValidationError,
@@ -8672,6 +9383,7 @@ export {
8672
9383
  TransactionPreflightError,
8673
9384
  TransactionRollbackError,
8674
9385
  VALID_KMS_PROVIDERS,
9386
+ assertPackedArtifact,
8675
9387
  assertSops,
8676
9388
  buildSigningPayload,
8677
9389
  checkAll,
@@ -8687,8 +9399,11 @@ export {
8687
9399
  generateRandomValue,
8688
9400
  generateSigningKeyPair,
8689
9401
  getPendingKeys,
9402
+ getRotations,
9403
+ isClefHsmArn,
8690
9404
  isHighEntropy,
8691
9405
  isKmsEnvelope,
9406
+ isPackedArtifact,
8692
9407
  isPending,
8693
9408
  keyPreview,
8694
9409
  loadIgnoreRules,
@@ -8698,19 +9413,26 @@ export {
8698
9413
  markPendingWithRetry,
8699
9414
  markResolved,
8700
9415
  matchPatterns,
9416
+ mergeMetadataContents,
9417
+ mergeMetadataFiles,
8701
9418
  metadataPath,
8702
9419
  parse9 as parse,
8703
9420
  parseDotenv,
8704
9421
  parseIgnoreContent,
8705
9422
  parseJson,
8706
9423
  parseYaml,
9424
+ pkcs11UriToSyntheticArn,
8707
9425
  readManifestYaml,
9426
+ recordRotation,
8708
9427
  redactValue,
8709
9428
  removeRequest as removeAccessRequest,
9429
+ removeRotation,
8710
9430
  requestsFilePath,
9431
+ resetKeyserviceResolution,
8711
9432
  resetSopsResolution,
8712
9433
  resolveBackendConfig,
8713
9434
  resolveIdentitySecrets,
9435
+ resolveKeyservicePath,
8714
9436
  resolveRecipientsForEnvironment,
8715
9437
  resolveSopsPath,
8716
9438
  runCompliance,
@@ -8721,8 +9443,12 @@ export {
8721
9443
  shouldIgnoreMatch,
8722
9444
  signEd25519,
8723
9445
  signKms,
9446
+ spawnKeyservice,
9447
+ syntheticArnToPkcs11Uri,
9448
+ tryBundledKeyservice,
8724
9449
  upsertRequest,
8725
9450
  validateAgePublicKey,
9451
+ validatePackedArtifact,
8726
9452
  validateResetScope,
8727
9453
  verifySignature,
8728
9454
  writeManifestYaml,