@clef-sh/cli 0.1.11-beta.62 → 0.1.11-beta.66

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.
package/dist/index.mjs CHANGED
@@ -10238,7 +10238,7 @@ var require_public_api = __commonJS({
10238
10238
  }
10239
10239
  return doc;
10240
10240
  }
10241
- function parse16(src, reviver, options) {
10241
+ function parse15(src, reviver, options) {
10242
10242
  let _reviver = void 0;
10243
10243
  if (typeof reviver === "function") {
10244
10244
  _reviver = reviver;
@@ -10279,7 +10279,7 @@ var require_public_api = __commonJS({
10279
10279
  return value.toString(options);
10280
10280
  return new Document.Document(value, _replacer, options).toString(options);
10281
10281
  }
10282
- exports.parse = parse16;
10282
+ exports.parse = parse15;
10283
10283
  exports.parseAllDocuments = parseAllDocuments;
10284
10284
  exports.parseDocument = parseDocument;
10285
10285
  exports.stringify = stringify8;
@@ -10811,8 +10811,26 @@ var init_parser = __esm({
10811
10811
  "sops.default_backend"
10812
10812
  );
10813
10813
  }
10814
+ const ageObj = sopsObj.age;
10815
+ const ageRecipients = ageObj && Array.isArray(ageObj.recipients) ? ageObj.recipients : void 0;
10816
+ const parsedAge = ageRecipients ? {
10817
+ age: {
10818
+ recipients: ageRecipients.map((r) => {
10819
+ if (typeof r === "string") return r;
10820
+ if (typeof r === "object" && r !== null) {
10821
+ const obj2 = r;
10822
+ return {
10823
+ key: String(obj2.key ?? ""),
10824
+ ...typeof obj2.label === "string" ? { label: obj2.label } : {}
10825
+ };
10826
+ }
10827
+ return String(r);
10828
+ })
10829
+ }
10830
+ } : {};
10814
10831
  const sopsConfig = {
10815
10832
  default_backend: sopsObj.default_backend,
10833
+ ...parsedAge,
10816
10834
  ...typeof sopsObj.aws_kms_arn === "string" ? { aws_kms_arn: sopsObj.aws_kms_arn } : {},
10817
10835
  ...typeof sopsObj.gcp_kms_resource_id === "string" ? { gcp_kms_resource_id: sopsObj.gcp_kms_resource_id } : {},
10818
10836
  ...typeof sopsObj.azure_kv_url === "string" ? { azure_kv_url: sopsObj.azure_kv_url } : {},
@@ -11204,8 +11222,8 @@ var init_scanner = __esm({
11204
11222
  ALWAYS_SKIP_EXTENSIONS = [".enc.yaml", ".enc.json"];
11205
11223
  ALWAYS_SKIP_NAMES = [
11206
11224
  ".clef-meta.yaml",
11207
- ".sops.yaml"
11208
- // contains age public keys and KMS ARNs — configuration, not secrets
11225
+ "clef.yaml"
11226
+ // manifest — contains public keys and config, not secrets
11209
11227
  ];
11210
11228
  ALWAYS_SKIP_DIRS = ["node_modules", ".git"];
11211
11229
  MAX_FILE_SIZE = 1024 * 1024;
@@ -19883,9 +19901,12 @@ var init_client = __esm({
19883
19901
  }
19884
19902
  let result;
19885
19903
  try {
19904
+ const configPath = process.platform === "win32" ? "NUL" : "/dev/null";
19886
19905
  result = await this.runner.run(
19887
19906
  this.sopsCommand,
19888
19907
  [
19908
+ "--config",
19909
+ configPath,
19889
19910
  "encrypt",
19890
19911
  ...args,
19891
19912
  "--input-type",
@@ -20122,8 +20143,15 @@ var init_client = __esm({
20122
20143
  pgp_fingerprint: manifest.sops.pgp_fingerprint
20123
20144
  };
20124
20145
  switch (config.backend) {
20125
- case "age":
20146
+ case "age": {
20147
+ const envRecipients = environment ? resolveRecipientsForEnvironment(manifest, environment) : void 0;
20148
+ const recipients = envRecipients ?? manifest.sops.age?.recipients ?? [];
20149
+ const keys = recipients.map((r) => typeof r === "string" ? r : r.key);
20150
+ if (keys.length > 0) {
20151
+ args.push("--age", keys.join(","));
20152
+ }
20126
20153
  break;
20154
+ }
20127
20155
  case "awskms":
20128
20156
  if (config.aws_kms_arn) {
20129
20157
  args.push("--kms", config.aws_kms_arn);
@@ -22271,14 +22299,13 @@ var init_resolve = __esm({
22271
22299
  import * as crypto3 from "crypto";
22272
22300
  function buildSigningPayload(artifact) {
22273
22301
  const fields = [
22274
- "clef-sig-v2",
22302
+ "clef-sig-v3",
22275
22303
  String(artifact.version),
22276
22304
  artifact.identity,
22277
22305
  artifact.environment,
22278
22306
  artifact.revision,
22279
22307
  artifact.packedAt,
22280
22308
  artifact.ciphertextHash,
22281
- [...artifact.keys].sort().join(","),
22282
22309
  artifact.expiresAt ?? "",
22283
22310
  artifact.envelope?.provider ?? "",
22284
22311
  artifact.envelope?.keyId ?? "",
@@ -22416,7 +22443,6 @@ var init_packer = __esm({
22416
22443
  revision,
22417
22444
  ciphertextHash,
22418
22445
  ciphertext,
22419
- keys: Object.keys(resolved.values),
22420
22446
  envelope: {
22421
22447
  provider: kmsConfig.provider,
22422
22448
  keyId: kmsConfig.keyId,
@@ -22450,8 +22476,7 @@ var init_packer = __esm({
22450
22476
  packedAt: (/* @__PURE__ */ new Date()).toISOString(),
22451
22477
  revision,
22452
22478
  ciphertextHash,
22453
- ciphertext,
22454
- keys: Object.keys(resolved.values)
22479
+ ciphertext
22455
22480
  };
22456
22481
  }
22457
22482
  const outputDir = path19.dirname(config.outputPath);
@@ -22536,7 +22561,7 @@ var init_backend = __esm({
22536
22561
  this.encryption = encryption;
22537
22562
  this.matrixManager = matrixManager;
22538
22563
  }
22539
- async migrate(manifest, repoRoot, options, callbacks, onProgress) {
22564
+ async migrate(manifest, repoRoot, options, onProgress) {
22540
22565
  const { target, environment, dryRun, skipVerify } = options;
22541
22566
  if (environment) {
22542
22567
  const env = manifest.environments.find((e) => e.name === environment);
@@ -22606,14 +22631,11 @@ var init_backend = __esm({
22606
22631
  }
22607
22632
  const manifestPath = path20.join(repoRoot, CLEF_MANIFEST_FILENAME);
22608
22633
  const manifestBackup = fs17.readFileSync(manifestPath, "utf-8");
22609
- const sopsYamlPath = path20.join(repoRoot, ".sops.yaml");
22610
- const sopsYamlBackup = fs17.existsSync(sopsYamlPath) ? fs17.readFileSync(sopsYamlPath, "utf-8") : void 0;
22611
22634
  const fileBackups = /* @__PURE__ */ new Map();
22612
22635
  const doc = readManifestYaml(repoRoot);
22613
22636
  this.updateManifestDoc(doc, target, environment);
22614
22637
  writeManifestYaml(repoRoot, doc);
22615
22638
  const updatedManifest = YAML11.parse(YAML11.stringify(doc));
22616
- callbacks.regenerateSopsConfig();
22617
22639
  const migratedFiles = [];
22618
22640
  for (const cell of toMigrate) {
22619
22641
  try {
@@ -22632,7 +22654,7 @@ var init_backend = __esm({
22632
22654
  );
22633
22655
  migratedFiles.push(cell.filePath);
22634
22656
  } catch (err) {
22635
- this.rollback(manifestPath, manifestBackup, sopsYamlPath, sopsYamlBackup, fileBackups);
22657
+ this.rollback(manifestPath, manifestBackup, fileBackups);
22636
22658
  const errorMsg = err instanceof Error ? err.message : String(err);
22637
22659
  onProgress?.({
22638
22660
  type: "warn",
@@ -22696,15 +22718,10 @@ var init_backend = __esm({
22696
22718
  }
22697
22719
  }
22698
22720
  }
22699
- rollback(manifestPath, manifestBackup, sopsYamlPath, sopsYamlBackup, fileBackups) {
22721
+ rollback(manifestPath, manifestBackup, fileBackups) {
22700
22722
  for (const [filePath, backup] of fileBackups) {
22701
22723
  fs17.writeFileSync(filePath, backup, "utf-8");
22702
22724
  }
22703
- if (sopsYamlBackup !== void 0) {
22704
- fs17.writeFileSync(sopsYamlPath, sopsYamlBackup, "utf-8");
22705
- } else if (fs17.existsSync(sopsYamlPath)) {
22706
- fs17.unlinkSync(sopsYamlPath);
22707
- }
22708
22725
  fs17.writeFileSync(manifestPath, manifestBackup, "utf-8");
22709
22726
  }
22710
22727
  checkAgeRecipientsWarning(manifest, target, environment, warnings) {
@@ -22934,7 +22951,7 @@ var require_ms = __commonJS({
22934
22951
  options = options || {};
22935
22952
  var type = typeof val;
22936
22953
  if (type === "string" && val.length > 0) {
22937
- return parse16(val);
22954
+ return parse15(val);
22938
22955
  } else if (type === "number" && isFinite(val)) {
22939
22956
  return options.long ? fmtLong(val) : fmtShort(val);
22940
22957
  }
@@ -22942,7 +22959,7 @@ var require_ms = __commonJS({
22942
22959
  "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
22943
22960
  );
22944
22961
  };
22945
- function parse16(str2) {
22962
+ function parse15(str2) {
22946
22963
  str2 = String(str2);
22947
22964
  if (str2.length > 100) {
22948
22965
  return;
@@ -24381,7 +24398,7 @@ var require_bytes = __commonJS({
24381
24398
  "use strict";
24382
24399
  module.exports = bytes;
24383
24400
  module.exports.format = format;
24384
- module.exports.parse = parse16;
24401
+ module.exports.parse = parse15;
24385
24402
  var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
24386
24403
  var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
24387
24404
  var map = {
@@ -24395,7 +24412,7 @@ var require_bytes = __commonJS({
24395
24412
  var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
24396
24413
  function bytes(value, options) {
24397
24414
  if (typeof value === "string") {
24398
- return parse16(value);
24415
+ return parse15(value);
24399
24416
  }
24400
24417
  if (typeof value === "number") {
24401
24418
  return format(value, options);
@@ -24439,7 +24456,7 @@ var require_bytes = __commonJS({
24439
24456
  }
24440
24457
  return str2 + unitSeparator + unit;
24441
24458
  }
24442
- function parse16(val) {
24459
+ function parse15(val) {
24443
24460
  if (typeof val === "number" && !isNaN(val)) {
24444
24461
  return val;
24445
24462
  }
@@ -28644,7 +28661,7 @@ var require_content_type = __commonJS({
28644
28661
  var QUOTE_REGEXP = /([\\"])/g;
28645
28662
  var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
28646
28663
  exports.format = format;
28647
- exports.parse = parse16;
28664
+ exports.parse = parse15;
28648
28665
  function format(obj) {
28649
28666
  if (!obj || typeof obj !== "object") {
28650
28667
  throw new TypeError("argument obj is required");
@@ -28668,7 +28685,7 @@ var require_content_type = __commonJS({
28668
28685
  }
28669
28686
  return string;
28670
28687
  }
28671
- function parse16(string) {
28688
+ function parse15(string) {
28672
28689
  if (!string) {
28673
28690
  throw new TypeError("argument string is required");
28674
28691
  }
@@ -38250,7 +38267,7 @@ var require_media_typer = __commonJS({
38250
38267
  var TYPE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/;
38251
38268
  var TYPE_REGEXP = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
38252
38269
  exports.format = format;
38253
- exports.parse = parse16;
38270
+ exports.parse = parse15;
38254
38271
  exports.test = test;
38255
38272
  function format(obj) {
38256
38273
  if (!obj || typeof obj !== "object") {
@@ -38283,7 +38300,7 @@ var require_media_typer = __commonJS({
38283
38300
  }
38284
38301
  return TYPE_REGEXP.test(string.toLowerCase());
38285
38302
  }
38286
- function parse16(string) {
38303
+ function parse15(string) {
38287
38304
  if (!string) {
38288
38305
  throw new TypeError("argument string is required");
38289
38306
  }
@@ -38469,7 +38486,7 @@ var require_read = __commonJS({
38469
38486
  var hasBody = require_type_is().hasBody;
38470
38487
  var { getCharset } = require_utils();
38471
38488
  module.exports = read2;
38472
- function read2(req, res, next, parse16, debug, options) {
38489
+ function read2(req, res, next, parse15, debug, options) {
38473
38490
  if (onFinished.isFinished(req)) {
38474
38491
  debug("body already parsed");
38475
38492
  next();
@@ -38557,7 +38574,7 @@ var require_read = __commonJS({
38557
38574
  try {
38558
38575
  debug("parse body");
38559
38576
  str2 = typeof body !== "string" && encoding !== null ? iconv.decode(body, encoding) : body;
38560
- req.body = parse16(str2, encoding);
38577
+ req.body = parse15(str2, encoding);
38561
38578
  } catch (err) {
38562
38579
  next(createError(400, err, {
38563
38580
  body: str2,
@@ -38630,7 +38647,7 @@ var require_json = __commonJS({
38630
38647
  const normalizedOptions = normalizeOptions(options, "application/json");
38631
38648
  var reviver = options?.reviver;
38632
38649
  var strict = options?.strict !== false;
38633
- function parse16(body) {
38650
+ function parse15(body) {
38634
38651
  if (body.length === 0) {
38635
38652
  return {};
38636
38653
  }
@@ -38657,7 +38674,7 @@ var require_json = __commonJS({
38657
38674
  isValidCharset: (charset) => charset.slice(0, 4) === "utf-"
38658
38675
  };
38659
38676
  return function jsonParser(req, res, next) {
38660
- read2(req, res, next, parse16, debug, readOptions);
38677
+ read2(req, res, next, parse15, debug, readOptions);
38661
38678
  };
38662
38679
  }
38663
38680
  function createStrictSyntaxError(str2, char) {
@@ -41235,11 +41252,11 @@ var require_lib2 = __commonJS({
41235
41252
  "../../node_modules/qs/lib/index.js"(exports, module) {
41236
41253
  "use strict";
41237
41254
  var stringify8 = require_stringify2();
41238
- var parse16 = require_parse();
41255
+ var parse15 = require_parse();
41239
41256
  var formats = require_formats();
41240
41257
  module.exports = {
41241
41258
  formats,
41242
- parse: parse16,
41259
+ parse: parse15,
41243
41260
  stringify: stringify8
41244
41261
  };
41245
41262
  }
@@ -41261,7 +41278,7 @@ var require_urlencoded = __commonJS({
41261
41278
  throw new TypeError("option defaultCharset must be either utf-8 or iso-8859-1");
41262
41279
  }
41263
41280
  var queryparse = createQueryParser(options);
41264
- function parse16(body, encoding) {
41281
+ function parse15(body, encoding) {
41265
41282
  return body.length ? queryparse(body, encoding) : {};
41266
41283
  }
41267
41284
  const readOptions = {
@@ -41270,7 +41287,7 @@ var require_urlencoded = __commonJS({
41270
41287
  isValidCharset: (charset) => charset === "utf-8" || charset === "iso-8859-1"
41271
41288
  };
41272
41289
  return function urlencodedParser(req, res, next) {
41273
- read2(req, res, next, parse16, debug, readOptions);
41290
+ read2(req, res, next, parse15, debug, readOptions);
41274
41291
  };
41275
41292
  }
41276
41293
  function createQueryParser(options) {
@@ -41454,7 +41471,7 @@ var require_parseurl = __commonJS({
41454
41471
  "../../node_modules/parseurl/index.js"(exports, module) {
41455
41472
  "use strict";
41456
41473
  var url = __require("url");
41457
- var parse16 = url.parse;
41474
+ var parse15 = url.parse;
41458
41475
  var Url = url.Url;
41459
41476
  module.exports = parseurl;
41460
41477
  module.exports.original = originalurl;
@@ -41486,7 +41503,7 @@ var require_parseurl = __commonJS({
41486
41503
  }
41487
41504
  function fastparse(str2) {
41488
41505
  if (typeof str2 !== "string" || str2.charCodeAt(0) !== 47) {
41489
- return parse16(str2);
41506
+ return parse15(str2);
41490
41507
  }
41491
41508
  var pathname = str2;
41492
41509
  var query = null;
@@ -41514,7 +41531,7 @@ var require_parseurl = __commonJS({
41514
41531
  /* # */
41515
41532
  case 160:
41516
41533
  case 65279:
41517
- return parse16(str2);
41534
+ return parse15(str2);
41518
41535
  }
41519
41536
  }
41520
41537
  var url2 = Url !== void 0 ? new Url() : {};
@@ -51310,7 +51327,7 @@ var require_forwarded = __commonJS({
51310
51327
  if (!req) {
51311
51328
  throw new TypeError("argument req is required");
51312
51329
  }
51313
- var proxyAddrs = parse16(req.headers["x-forwarded-for"] || "");
51330
+ var proxyAddrs = parse15(req.headers["x-forwarded-for"] || "");
51314
51331
  var socketAddr = getSocketAddr(req);
51315
51332
  var addrs = [socketAddr].concat(proxyAddrs);
51316
51333
  return addrs;
@@ -51318,7 +51335,7 @@ var require_forwarded = __commonJS({
51318
51335
  function getSocketAddr(req) {
51319
51336
  return req.socket ? req.socket.remoteAddress : req.connection.remoteAddress;
51320
51337
  }
51321
- function parse16(header) {
51338
+ function parse15(header) {
51322
51339
  var end = header.length;
51323
51340
  var list = [];
51324
51341
  var start = header.length;
@@ -52347,7 +52364,7 @@ var require_dist2 = __commonJS({
52347
52364
  "use strict";
52348
52365
  Object.defineProperty(exports, "__esModule", { value: true });
52349
52366
  exports.PathError = exports.TokenData = void 0;
52350
- exports.parse = parse16;
52367
+ exports.parse = parse15;
52351
52368
  exports.compile = compile;
52352
52369
  exports.match = match;
52353
52370
  exports.pathToRegexp = pathToRegexp;
@@ -52382,7 +52399,7 @@ var require_dist2 = __commonJS({
52382
52399
  }
52383
52400
  };
52384
52401
  exports.PathError = PathError;
52385
- function parse16(str2, options = {}) {
52402
+ function parse15(str2, options = {}) {
52386
52403
  const { encodePath = NOOP_VALUE } = options;
52387
52404
  const chars = [...str2];
52388
52405
  const tokens = [];
@@ -52471,7 +52488,7 @@ var require_dist2 = __commonJS({
52471
52488
  }
52472
52489
  function compile(path47, options = {}) {
52473
52490
  const { encode: encode2 = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
52474
- const data = typeof path47 === "object" ? path47 : parse16(path47, options);
52491
+ const data = typeof path47 === "object" ? path47 : parse15(path47, options);
52475
52492
  const fn = tokensToFunction(data.tokens, delimiter, encode2);
52476
52493
  return function path48(params = {}) {
52477
52494
  const [path49, ...missing] = fn(params);
@@ -52572,7 +52589,7 @@ var require_dist2 = __commonJS({
52572
52589
  paths.push(...path48);
52573
52590
  continue;
52574
52591
  }
52575
- const data = typeof path48 === "object" ? path48 : parse16(path48, options);
52592
+ const data = typeof path48 === "object" ? path48 : parse15(path48, options);
52576
52593
  flatten2(data.tokens, 0, [], (tokens) => {
52577
52594
  if (combinations++ >= 256) {
52578
52595
  throw new PathError("Too many path combinations", data.originalPath);
@@ -63897,7 +63914,7 @@ var require_request = __commonJS({
63897
63914
  var http = __require("node:http");
63898
63915
  var fresh = require_fresh();
63899
63916
  var parseRange = require_range_parser();
63900
- var parse16 = require_parseurl();
63917
+ var parse15 = require_parseurl();
63901
63918
  var proxyaddr = require_proxy_addr();
63902
63919
  var req = Object.create(http.IncomingMessage.prototype);
63903
63920
  module.exports = req;
@@ -63942,7 +63959,7 @@ var require_request = __commonJS({
63942
63959
  if (!queryparse) {
63943
63960
  return /* @__PURE__ */ Object.create(null);
63944
63961
  }
63945
- var querystring = parse16(this).query;
63962
+ var querystring = parse15(this).query;
63946
63963
  return queryparse(querystring);
63947
63964
  });
63948
63965
  req.is = function is(types) {
@@ -63986,7 +64003,7 @@ var require_request = __commonJS({
63986
64003
  return subdomains2.slice(offset);
63987
64004
  });
63988
64005
  defineGetter(req, "path", function path47() {
63989
- return parse16(this).pathname;
64006
+ return parse15(this).pathname;
63990
64007
  });
63991
64008
  defineGetter(req, "host", function host() {
63992
64009
  var trust = this.app.get("trust proxy fn");
@@ -64040,7 +64057,7 @@ var require_content_disposition = __commonJS({
64040
64057
  "../../node_modules/content-disposition/index.js"(exports, module) {
64041
64058
  "use strict";
64042
64059
  module.exports = contentDisposition;
64043
- module.exports.parse = parse16;
64060
+ module.exports.parse = parse15;
64044
64061
  var basename5 = __require("path").basename;
64045
64062
  var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
64046
64063
  var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
@@ -64131,7 +64148,7 @@ var require_content_disposition = __commonJS({
64131
64148
  function getlatin1(val) {
64132
64149
  return String(val).replace(NON_LATIN1_REGEXP, "?");
64133
64150
  }
64134
- function parse16(string) {
64151
+ function parse15(string) {
64135
64152
  if (!string || typeof string !== "string") {
64136
64153
  throw new TypeError("argument string is required");
64137
64154
  }
@@ -64220,7 +64237,7 @@ var require_cookie_signature = __commonJS({
64220
64237
  var require_cookie = __commonJS({
64221
64238
  "../../node_modules/cookie/index.js"(exports) {
64222
64239
  "use strict";
64223
- exports.parse = parse16;
64240
+ exports.parse = parse15;
64224
64241
  exports.serialize = serialize;
64225
64242
  var __toString = Object.prototype.toString;
64226
64243
  var __hasOwnProperty = Object.prototype.hasOwnProperty;
@@ -64228,7 +64245,7 @@ var require_cookie = __commonJS({
64228
64245
  var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
64229
64246
  var domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
64230
64247
  var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
64231
- function parse16(str2, opt) {
64248
+ function parse15(str2, opt) {
64232
64249
  if (typeof str2 !== "string") {
64233
64250
  throw new TypeError("argument str must be a string");
64234
64251
  }
@@ -74384,7 +74401,7 @@ var require_vary = __commonJS({
74384
74401
  if (!field) {
74385
74402
  throw new TypeError("field argument is required");
74386
74403
  }
74387
- var fields = !Array.isArray(field) ? parse16(String(field)) : field;
74404
+ var fields = !Array.isArray(field) ? parse15(String(field)) : field;
74388
74405
  for (var j = 0; j < fields.length; j++) {
74389
74406
  if (!FIELD_NAME_REGEXP.test(fields[j])) {
74390
74407
  throw new TypeError("field argument contains an invalid header name");
@@ -74394,7 +74411,7 @@ var require_vary = __commonJS({
74394
74411
  return header;
74395
74412
  }
74396
74413
  var val = header;
74397
- var vals = parse16(header.toLowerCase());
74414
+ var vals = parse15(header.toLowerCase());
74398
74415
  if (fields.indexOf("*") !== -1 || vals.indexOf("*") !== -1) {
74399
74416
  return "*";
74400
74417
  }
@@ -74407,7 +74424,7 @@ var require_vary = __commonJS({
74407
74424
  }
74408
74425
  return val;
74409
74426
  }
74410
- function parse16(header) {
74427
+ function parse15(header) {
74411
74428
  var end = 0;
74412
74429
  var list = [];
74413
74430
  var start = 0;
@@ -75868,161 +75885,6 @@ var require_dist3 = __commonJS({
75868
75885
  }
75869
75886
  });
75870
75887
 
75871
- // ../ui/dist/server/sops-config.js
75872
- var require_sops_config = __commonJS({
75873
- "../ui/dist/server/sops-config.js"(exports) {
75874
- "use strict";
75875
- var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
75876
- if (k2 === void 0) k2 = k;
75877
- var desc = Object.getOwnPropertyDescriptor(m, k);
75878
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
75879
- desc = { enumerable: true, get: function() {
75880
- return m[k];
75881
- } };
75882
- }
75883
- Object.defineProperty(o, k2, desc);
75884
- }) : (function(o, m, k, k2) {
75885
- if (k2 === void 0) k2 = k;
75886
- o[k2] = m[k];
75887
- }));
75888
- var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
75889
- Object.defineProperty(o, "default", { enumerable: true, value: v });
75890
- }) : function(o, v) {
75891
- o["default"] = v;
75892
- });
75893
- var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
75894
- var ownKeys = function(o) {
75895
- ownKeys = Object.getOwnPropertyNames || function(o2) {
75896
- var ar = [];
75897
- for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
75898
- return ar;
75899
- };
75900
- return ownKeys(o);
75901
- };
75902
- return function(mod3) {
75903
- if (mod3 && mod3.__esModule) return mod3;
75904
- var result = {};
75905
- if (mod3 != null) {
75906
- for (var k = ownKeys(mod3), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod3, k[i]);
75907
- }
75908
- __setModuleDefault(result, mod3);
75909
- return result;
75910
- };
75911
- })();
75912
- Object.defineProperty(exports, "__esModule", { value: true });
75913
- exports.scaffoldSopsConfig = scaffoldSopsConfig2;
75914
- var fs28 = __importStar(__require("fs"));
75915
- var path47 = __importStar(__require("path"));
75916
- var YAML15 = __importStar(require_dist());
75917
- var core_1 = (init_src(), __toCommonJS(src_exports));
75918
- function scaffoldSopsConfig2(repoRoot, ageKeyFile, ageKey) {
75919
- const parser = new core_1.ManifestParser();
75920
- const manifest = parser.parse(path47.join(repoRoot, "clef.yaml"));
75921
- const sopsYamlPath = path47.join(repoRoot, ".sops.yaml");
75922
- let agePublicKey;
75923
- if (manifest.sops.default_backend === "age") {
75924
- agePublicKey = resolveAgePublicKey(repoRoot, ageKeyFile, ageKey);
75925
- }
75926
- const sopsConfig = buildSopsYaml2(manifest, agePublicKey);
75927
- fs28.writeFileSync(sopsYamlPath, YAML15.stringify(sopsConfig), "utf-8");
75928
- }
75929
- function buildSopsYaml2(manifest, agePublicKey) {
75930
- const creationRules = [];
75931
- for (const ns of manifest.namespaces) {
75932
- for (const env of manifest.environments) {
75933
- const pathRegex = `${ns.name}/${env.name}\\.enc\\.yaml$`;
75934
- const rule = { path_regex: pathRegex };
75935
- const backend = env.sops?.backend ?? manifest.sops.default_backend;
75936
- switch (backend) {
75937
- case "age": {
75938
- const envRecipients = (0, core_1.resolveRecipientsForEnvironment)(manifest, env.name);
75939
- if (envRecipients && envRecipients.length > 0) {
75940
- const keys = envRecipients.map((r) => typeof r === "string" ? r : r.key);
75941
- rule.age = keys.join(",");
75942
- } else if (agePublicKey) {
75943
- rule.age = agePublicKey;
75944
- }
75945
- break;
75946
- }
75947
- case "awskms": {
75948
- const arn = env.sops?.aws_kms_arn ?? manifest.sops.aws_kms_arn;
75949
- if (arn)
75950
- rule.kms = arn;
75951
- break;
75952
- }
75953
- case "gcpkms": {
75954
- const resourceId = env.sops?.gcp_kms_resource_id ?? manifest.sops.gcp_kms_resource_id;
75955
- if (resourceId)
75956
- rule.gcp_kms = resourceId;
75957
- break;
75958
- }
75959
- case "azurekv": {
75960
- const kvUrl = env.sops?.azure_kv_url ?? manifest.sops.azure_kv_url;
75961
- if (kvUrl)
75962
- rule.azure_keyvault = kvUrl;
75963
- break;
75964
- }
75965
- case "pgp": {
75966
- const fingerprint = env.sops?.pgp_fingerprint ?? manifest.sops.pgp_fingerprint;
75967
- if (fingerprint)
75968
- rule.pgp = fingerprint;
75969
- break;
75970
- }
75971
- }
75972
- creationRules.push(rule);
75973
- }
75974
- }
75975
- return { creation_rules: creationRules };
75976
- }
75977
- function resolveAgePublicKey(repoRoot, ageKeyFile, ageKey) {
75978
- if (ageKeyFile) {
75979
- const pubKey = extractAgePublicKey2(ageKeyFile);
75980
- if (pubKey)
75981
- return pubKey;
75982
- }
75983
- if (ageKey) {
75984
- const match = ageKey.match(/# public key: (age1[a-z0-9]+)/);
75985
- if (match)
75986
- return match[1];
75987
- }
75988
- if (process.env.CLEF_AGE_KEY_FILE) {
75989
- const pubKey = extractAgePublicKey2(process.env.CLEF_AGE_KEY_FILE);
75990
- if (pubKey)
75991
- return pubKey;
75992
- }
75993
- if (process.env.CLEF_AGE_KEY) {
75994
- const match = process.env.CLEF_AGE_KEY.match(/# public key: (age1[a-z0-9]+)/);
75995
- if (match)
75996
- return match[1];
75997
- }
75998
- const clefConfigPath = path47.join(repoRoot, ".clef", "config.yaml");
75999
- if (fs28.existsSync(clefConfigPath)) {
76000
- try {
76001
- const config = YAML15.parse(fs28.readFileSync(clefConfigPath, "utf-8"));
76002
- if (config?.age_key_file) {
76003
- const pubKey = extractAgePublicKey2(config.age_key_file);
76004
- if (pubKey)
76005
- return pubKey;
76006
- }
76007
- } catch {
76008
- }
76009
- }
76010
- return void 0;
76011
- }
76012
- function extractAgePublicKey2(keyFilePath) {
76013
- try {
76014
- if (!fs28.existsSync(keyFilePath))
76015
- return void 0;
76016
- const content = fs28.readFileSync(keyFilePath, "utf-8");
76017
- const match = content.match(/# public key: (age1[a-z0-9]+)/);
76018
- return match ? match[1] : void 0;
76019
- } catch {
76020
- return void 0;
76021
- }
76022
- }
76023
- }
76024
- });
76025
-
76026
75888
  // ../ui/dist/server/api.js
76027
75889
  var require_api = __commonJS({
76028
75890
  "../ui/dist/server/api.js"(exports) {
@@ -76072,7 +75934,6 @@ var require_api = __commonJS({
76072
75934
  var express_1 = require_express2();
76073
75935
  var _useStdinFifo = process.platform === "linux" && !process.env.JEST_WORKER_ID;
76074
75936
  var core_1 = (init_src(), __toCommonJS(src_exports));
76075
- var sops_config_1 = require_sops_config();
76076
75937
  function createApiRouter(deps2) {
76077
75938
  const router = (0, express_1.Router)();
76078
75939
  const parser = new core_1.ManifestParser();
@@ -76085,7 +75946,7 @@ var require_api = __commonJS({
76085
75946
  return deps2.runner.run(cmd, args, {
76086
75947
  ...opts2,
76087
75948
  cwd: opts2?.cwd ?? deps2.repoRoot,
76088
- env: { SOPS_CONFIG: path47.join(deps2.repoRoot, ".sops.yaml"), ...opts2?.env }
75949
+ env: opts2?.env
76089
75950
  });
76090
75951
  }
76091
75952
  const fifoDir = (0, child_process_1.execFileSync)("mktemp", ["-d", path47.join(os4.tmpdir(), "clef-fifo-XXXXXX")]).toString().trim();
@@ -76324,6 +76185,29 @@ var require_api = __commonJS({
76324
76185
  res.status(500).json({ error: "Failed to delete key", code: "DELETE_ERROR" });
76325
76186
  }
76326
76187
  });
76188
+ router.post("/namespace/:ns/:env/:key/accept", async (req, res) => {
76189
+ setNoCacheHeaders(res);
76190
+ try {
76191
+ const manifest = loadManifest();
76192
+ const { ns, env, key } = req.params;
76193
+ const nsExists = manifest.namespaces.some((n) => n.name === ns);
76194
+ const envExists = manifest.environments.some((e) => e.name === env);
76195
+ if (!nsExists || !envExists) {
76196
+ res.status(404).json({
76197
+ error: `Namespace '${ns}' or environment '${env}' not found in manifest.`,
76198
+ code: "NOT_FOUND"
76199
+ });
76200
+ return;
76201
+ }
76202
+ const filePath = `${deps2.repoRoot}/${manifest.file_pattern.replace("{namespace}", ns).replace("{environment}", env)}`;
76203
+ const decrypted = await sops.decrypt(filePath);
76204
+ const value = key in decrypted.values ? String(decrypted.values[key]) : void 0;
76205
+ await (0, core_1.markResolved)(filePath, [key]);
76206
+ res.json({ success: true, key, value });
76207
+ } catch {
76208
+ res.status(500).json({ error: "Failed to accept pending value", code: "ACCEPT_ERROR" });
76209
+ }
76210
+ });
76327
76211
  router.post("/copy", async (req, res) => {
76328
76212
  try {
76329
76213
  const manifest = loadManifest();
@@ -76841,9 +76725,7 @@ var require_api = __commonJS({
76841
76725
  return;
76842
76726
  }
76843
76727
  const events = [];
76844
- const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: true }, {
76845
- regenerateSopsConfig: () => (0, sops_config_1.scaffoldSopsConfig)(deps2.repoRoot, deps2.ageKeyFile, deps2.ageKey)
76846
- }, (event) => events.push(event));
76728
+ const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: true }, (event) => events.push(event));
76847
76729
  res.json({ success: !result.rolledBack, result, events });
76848
76730
  } catch (err) {
76849
76731
  const message = err instanceof Error ? err.message : "Migration preview failed";
@@ -76869,9 +76751,7 @@ var require_api = __commonJS({
76869
76751
  return;
76870
76752
  }
76871
76753
  const events = [];
76872
- const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: false }, {
76873
- regenerateSopsConfig: () => (0, sops_config_1.scaffoldSopsConfig)(deps2.repoRoot, deps2.ageKeyFile, deps2.ageKey)
76874
- }, (event) => events.push(event));
76754
+ const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: false }, (event) => events.push(event));
76875
76755
  res.json({ success: !result.rolledBack, result, events });
76876
76756
  } catch (err) {
76877
76757
  const message = err instanceof Error ? err.message : "Migration failed";
@@ -77735,7 +77615,7 @@ var require_artifact_decryptor = __commonJS({
77735
77615
  } finally {
77736
77616
  plaintext = "";
77737
77617
  }
77738
- return { values, keys: artifact.keys, revision: artifact.revision };
77618
+ return { values, keys: Object.keys(values), revision: artifact.revision };
77739
77619
  }
77740
77620
  /** KMS envelope: unwrap DEK via KMS, then AES-256-GCM decrypt. */
77741
77621
  async decryptKmsEnvelope(artifact) {
@@ -77836,14 +77716,13 @@ var require_signature = __commonJS({
77836
77716
  var crypto6 = __importStar(__require("crypto"));
77837
77717
  function buildSigningPayload2(artifact) {
77838
77718
  const fields = [
77839
- "clef-sig-v2",
77719
+ "clef-sig-v3",
77840
77720
  String(artifact.version),
77841
77721
  artifact.identity,
77842
77722
  artifact.environment,
77843
77723
  artifact.revision,
77844
77724
  artifact.packedAt,
77845
77725
  artifact.ciphertextHash,
77846
- [...artifact.keys].sort().join(","),
77847
77726
  artifact.expiresAt ?? "",
77848
77727
  artifact.envelope?.provider ?? "",
77849
77728
  artifact.envelope?.keyId ?? "",
@@ -77976,7 +77855,6 @@ var require_poller = __commonJS({
77976
77855
  this.options.onRefresh?.(artifact.revision);
77977
77856
  this.telemetry?.artifactRefreshed({
77978
77857
  revision: artifact.revision,
77979
- keyCount: artifact.keys.length,
77980
77858
  kmsEnvelope: !!artifact.envelope
77981
77859
  });
77982
77860
  }
@@ -78133,14 +78011,15 @@ var require_poller = __commonJS({
78133
78011
  if (artifact.revision === this.lastRevision)
78134
78012
  return;
78135
78013
  const { values } = await this.decryptor.decrypt(artifact);
78136
- this.options.cache.swap(values, artifact.keys, artifact.revision);
78014
+ const keys = Object.keys(values);
78015
+ this.options.cache.swap(values, keys, artifact.revision);
78137
78016
  this.lastRevision = artifact.revision;
78138
78017
  this.lastContentHash = contentHash ?? null;
78139
78018
  this.lastExpiresAt = artifact.expiresAt ?? null;
78140
78019
  this.options.onRefresh?.(artifact.revision);
78141
78020
  this.telemetry?.artifactRefreshed({
78142
78021
  revision: artifact.revision,
78143
- keyCount: artifact.keys.length,
78022
+ keyCount: keys.length,
78144
78023
  kmsEnvelope: !!artifact.envelope
78145
78024
  });
78146
78025
  }
@@ -78263,10 +78142,6 @@ var require_encrypted_artifact_store = __commonJS({
78263
78142
  getStoredAt() {
78264
78143
  return this._storedAt;
78265
78144
  }
78266
- /** Get key names from the stored artifact metadata (no decryption needed). */
78267
- getKeys() {
78268
- return this.artifact ? [...this.artifact.keys] : [];
78269
- }
78270
78145
  /** Get the revision from the stored artifact. */
78271
78146
  getRevision() {
78272
78147
  return this.artifact?.revision ?? null;
@@ -78748,12 +78623,228 @@ var require_vcs2 = __commonJS({
78748
78623
  }
78749
78624
  });
78750
78625
 
78626
+ // ../runtime/dist/sources/s3.js
78627
+ var require_s3 = __commonJS({
78628
+ "../runtime/dist/sources/s3.js"(exports) {
78629
+ "use strict";
78630
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
78631
+ if (k2 === void 0) k2 = k;
78632
+ var desc = Object.getOwnPropertyDescriptor(m, k);
78633
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
78634
+ desc = { enumerable: true, get: function() {
78635
+ return m[k];
78636
+ } };
78637
+ }
78638
+ Object.defineProperty(o, k2, desc);
78639
+ }) : (function(o, m, k, k2) {
78640
+ if (k2 === void 0) k2 = k;
78641
+ o[k2] = m[k];
78642
+ }));
78643
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
78644
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
78645
+ }) : function(o, v) {
78646
+ o["default"] = v;
78647
+ });
78648
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
78649
+ var ownKeys = function(o) {
78650
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
78651
+ var ar = [];
78652
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
78653
+ return ar;
78654
+ };
78655
+ return ownKeys(o);
78656
+ };
78657
+ return function(mod3) {
78658
+ if (mod3 && mod3.__esModule) return mod3;
78659
+ var result = {};
78660
+ if (mod3 != null) {
78661
+ for (var k = ownKeys(mod3), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod3, k[i]);
78662
+ }
78663
+ __setModuleDefault(result, mod3);
78664
+ return result;
78665
+ };
78666
+ })();
78667
+ Object.defineProperty(exports, "__esModule", { value: true });
78668
+ exports.S3ArtifactSource = void 0;
78669
+ exports.isS3Url = isS3Url;
78670
+ var crypto6 = __importStar(__require("crypto"));
78671
+ function isS3Url(url) {
78672
+ return parseS3UrlSafe(url) !== null;
78673
+ }
78674
+ function parseS3Url(url) {
78675
+ const loc = parseS3UrlSafe(url);
78676
+ if (!loc)
78677
+ throw new Error(`Not a valid S3 URL: ${url}`);
78678
+ return loc;
78679
+ }
78680
+ function parseS3UrlSafe(url) {
78681
+ let u;
78682
+ try {
78683
+ u = new URL(url);
78684
+ } catch {
78685
+ return null;
78686
+ }
78687
+ if (u.protocol !== "https:")
78688
+ return null;
78689
+ const host = u.hostname;
78690
+ const key = u.pathname.slice(1);
78691
+ if (!key)
78692
+ return null;
78693
+ const vhMatch = host.match(/^(.+)\.s3\.([a-z0-9-]+)\.amazonaws\.com$/) ?? host.match(/^(.+)\.s3\.amazonaws\.com$/);
78694
+ if (vhMatch) {
78695
+ return { bucket: vhMatch[1], key, region: vhMatch[2] || "us-east-1" };
78696
+ }
78697
+ const psMatch = host.match(/^s3\.([a-z0-9-]+)\.amazonaws\.com$/) ?? host.match(/^s3\.amazonaws\.com$/);
78698
+ if (psMatch) {
78699
+ const slashIdx = key.indexOf("/");
78700
+ if (slashIdx < 0)
78701
+ return null;
78702
+ return {
78703
+ bucket: key.slice(0, slashIdx),
78704
+ key: key.slice(slashIdx + 1),
78705
+ region: psMatch[1] || "us-east-1"
78706
+ };
78707
+ }
78708
+ return null;
78709
+ }
78710
+ var S3ArtifactSource = class {
78711
+ url;
78712
+ location;
78713
+ cachedCredentials = null;
78714
+ constructor(url) {
78715
+ this.url = url;
78716
+ this.location = parseS3Url(url);
78717
+ }
78718
+ async fetch() {
78719
+ const creds = await this.resolveCredentials();
78720
+ const { bucket, key, region } = this.location;
78721
+ const host = `${bucket}.s3.${region}.amazonaws.com`;
78722
+ const path47 = `/${encodeS3Key(key)}`;
78723
+ const now = /* @__PURE__ */ new Date();
78724
+ const headers = signS3GetRequest(host, path47, region, creds, now);
78725
+ const res = await globalThis.fetch(`https://${host}${path47}`, { headers });
78726
+ if (!res.ok) {
78727
+ throw new Error(`Failed to fetch artifact from ${this.describe()}: ${res.status} ${res.statusText}`);
78728
+ }
78729
+ const raw = await res.text();
78730
+ const etag = res.headers.get("etag") ?? void 0;
78731
+ return { raw, contentHash: etag };
78732
+ }
78733
+ describe() {
78734
+ const { bucket, key } = this.location;
78735
+ return `S3 s3://${bucket}/${key}`;
78736
+ }
78737
+ async resolveCredentials() {
78738
+ if (this.cachedCredentials && Date.now() < this.cachedCredentials.expiresAt - 3e5) {
78739
+ return this.cachedCredentials.creds;
78740
+ }
78741
+ const relativeUri = process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;
78742
+ if (relativeUri) {
78743
+ return this.fetchEcsCredentials(`http://169.254.170.2${relativeUri}`);
78744
+ }
78745
+ const fullUri = process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI;
78746
+ if (fullUri) {
78747
+ return this.fetchEcsCredentials(fullUri);
78748
+ }
78749
+ const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
78750
+ const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
78751
+ if (accessKeyId && secretAccessKey) {
78752
+ return {
78753
+ accessKeyId,
78754
+ secretAccessKey,
78755
+ sessionToken: process.env.AWS_SESSION_TOKEN
78756
+ };
78757
+ }
78758
+ throw new Error("No AWS credentials found. Set AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, or run in ECS/Fargate with a task role.");
78759
+ }
78760
+ async fetchEcsCredentials(endpoint) {
78761
+ const headers = {};
78762
+ const authToken = process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;
78763
+ if (authToken) {
78764
+ headers["Authorization"] = authToken;
78765
+ }
78766
+ const res = await globalThis.fetch(endpoint, { headers });
78767
+ if (!res.ok) {
78768
+ throw new Error(`Failed to fetch ECS credentials: ${res.status} ${res.statusText}`);
78769
+ }
78770
+ const data = await res.json();
78771
+ const creds = {
78772
+ accessKeyId: data.AccessKeyId,
78773
+ secretAccessKey: data.SecretAccessKey,
78774
+ sessionToken: data.Token
78775
+ };
78776
+ if (data.Expiration) {
78777
+ this.cachedCredentials = {
78778
+ creds,
78779
+ expiresAt: new Date(data.Expiration).getTime()
78780
+ };
78781
+ }
78782
+ return creds;
78783
+ }
78784
+ };
78785
+ exports.S3ArtifactSource = S3ArtifactSource;
78786
+ function hmacSha256(key, data) {
78787
+ return crypto6.createHmac("sha256", key).update(data, "utf-8").digest();
78788
+ }
78789
+ function sha256Hex(data) {
78790
+ return crypto6.createHash("sha256").update(data, "utf-8").digest("hex");
78791
+ }
78792
+ function toAmzDate(date) {
78793
+ return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}/, "");
78794
+ }
78795
+ function toDateStamp(date) {
78796
+ return toAmzDate(date).slice(0, 8);
78797
+ }
78798
+ function encodeS3Key(key) {
78799
+ return key.split("/").map((s) => encodeURIComponent(s)).join("/");
78800
+ }
78801
+ function signS3GetRequest(host, path47, region, creds, now) {
78802
+ const amzDate = toAmzDate(now);
78803
+ const dateStamp = toDateStamp(now);
78804
+ const service = "s3";
78805
+ const scope = `${dateStamp}/${region}/${service}/aws4_request`;
78806
+ const headers = {
78807
+ host,
78808
+ "x-amz-date": amzDate,
78809
+ "x-amz-content-sha256": "UNSIGNED-PAYLOAD"
78810
+ };
78811
+ if (creds.sessionToken) {
78812
+ headers["x-amz-security-token"] = creds.sessionToken;
78813
+ }
78814
+ const signedHeaderKeys = Object.keys(headers).sort();
78815
+ const signedHeaders = signedHeaderKeys.join(";");
78816
+ const canonicalHeaders = signedHeaderKeys.map((k) => `${k}:${headers[k]}
78817
+ `).join("");
78818
+ const canonicalRequest = [
78819
+ "GET",
78820
+ path47,
78821
+ "",
78822
+ // no query string
78823
+ canonicalHeaders,
78824
+ signedHeaders,
78825
+ "UNSIGNED-PAYLOAD"
78826
+ ].join("\n");
78827
+ const stringToSign = ["AWS4-HMAC-SHA256", amzDate, scope, sha256Hex(canonicalRequest)].join("\n");
78828
+ const kDate = hmacSha256(`AWS4${creds.secretAccessKey}`, dateStamp);
78829
+ const kRegion = hmacSha256(kDate, region);
78830
+ const kService = hmacSha256(kRegion, service);
78831
+ const kSigning = hmacSha256(kService, "aws4_request");
78832
+ const signature = hmacSha256(kSigning, stringToSign).toString("hex");
78833
+ const authorization = `AWS4-HMAC-SHA256 Credential=${creds.accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
78834
+ return {
78835
+ ...headers,
78836
+ Authorization: authorization
78837
+ };
78838
+ }
78839
+ }
78840
+ });
78841
+
78751
78842
  // ../runtime/dist/index.js
78752
78843
  var require_dist4 = __commonJS({
78753
78844
  "../runtime/dist/index.js"(exports) {
78754
78845
  "use strict";
78755
78846
  Object.defineProperty(exports, "__esModule", { value: true });
78756
- exports.ClefRuntime = exports.verifySignature = exports.buildSigningPayload = exports.VcsArtifactSource = exports.FileArtifactSource = exports.HttpArtifactSource = exports.createKmsProvider = exports.AwsKmsProvider = exports.createVcsProvider = exports.BitbucketProvider = exports.GitLabProvider = exports.GitHubProvider = exports.TelemetryEmitter = exports.EncryptedArtifactStore = exports.ArtifactDecryptor = exports.ArtifactPoller = exports.AgeDecryptor = exports.DiskCache = exports.SecretsCache = void 0;
78847
+ exports.ClefRuntime = exports.verifySignature = exports.buildSigningPayload = exports.isS3Url = exports.S3ArtifactSource = exports.VcsArtifactSource = exports.FileArtifactSource = exports.HttpArtifactSource = exports.createKmsProvider = exports.AwsKmsProvider = exports.createVcsProvider = exports.BitbucketProvider = exports.GitLabProvider = exports.GitHubProvider = exports.TelemetryEmitter = exports.EncryptedArtifactStore = exports.ArtifactDecryptor = exports.ArtifactPoller = exports.AgeDecryptor = exports.DiskCache = exports.SecretsCache = void 0;
78757
78848
  exports.init = init;
78758
78849
  var secrets_cache_1 = require_secrets_cache();
78759
78850
  Object.defineProperty(exports, "SecretsCache", { enumerable: true, get: function() {
@@ -78819,6 +78910,13 @@ var require_dist4 = __commonJS({
78819
78910
  Object.defineProperty(exports, "VcsArtifactSource", { enumerable: true, get: function() {
78820
78911
  return vcs_1.VcsArtifactSource;
78821
78912
  } });
78913
+ var s3_1 = require_s3();
78914
+ Object.defineProperty(exports, "S3ArtifactSource", { enumerable: true, get: function() {
78915
+ return s3_1.S3ArtifactSource;
78916
+ } });
78917
+ Object.defineProperty(exports, "isS3Url", { enumerable: true, get: function() {
78918
+ return s3_1.isS3Url;
78919
+ } });
78822
78920
  var signature_1 = require_signature();
78823
78921
  Object.defineProperty(exports, "buildSigningPayload", { enumerable: true, get: function() {
78824
78922
  return signature_1.buildSigningPayload;
@@ -78834,6 +78932,7 @@ var require_dist4 = __commonJS({
78834
78932
  var vcs_2 = require_vcs2();
78835
78933
  var http_2 = require_http();
78836
78934
  var file_2 = require_file();
78935
+ var s3_2 = require_s3();
78837
78936
  var ClefRuntime = class {
78838
78937
  cache = new secrets_cache_2.SecretsCache();
78839
78938
  poller;
@@ -78927,6 +79026,9 @@ var require_dist4 = __commonJS({
78927
79026
  return new vcs_2.VcsArtifactSource(provider, config.identity, config.environment);
78928
79027
  }
78929
79028
  if (config.source) {
79029
+ if ((0, s3_2.isS3Url)(config.source)) {
79030
+ return new s3_2.S3ArtifactSource(config.source);
79031
+ }
78930
79032
  if (config.source.startsWith("http://") || config.source.startsWith("https://")) {
78931
79033
  return new http_2.HttpArtifactSource(config.source);
78932
79034
  }
@@ -79859,12 +79961,6 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
79859
79961
  }
79860
79962
  fs18.writeFileSync(manifestPath, YAML12.stringify(manifestDoc), "utf-8");
79861
79963
  formatter.success("Created clef.yaml");
79862
- {
79863
- const sopsYamlPath = path21.join(repoRoot, ".sops.yaml");
79864
- const sopsConfig = buildSopsYaml(manifest, repoRoot, publicKey);
79865
- fs18.writeFileSync(sopsYamlPath, YAML12.stringify(sopsConfig), "utf-8");
79866
- formatter.success("Created .sops.yaml");
79867
- }
79868
79964
  const sopsClient = new SopsClient(deps2.runner, ageKeyFile, ageKey);
79869
79965
  const matrixManager = new MatrixManager();
79870
79966
  const cells = matrixManager.resolveMatrix(manifest, repoRoot);
@@ -79942,102 +80038,6 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
79942
80038
  formatter.hint("clef lint \u2014 check repo health");
79943
80039
  formatter.hint("clef ui \u2014 open the web UI");
79944
80040
  }
79945
- function scaffoldSopsConfig(repoRoot) {
79946
- const manifestPath = path21.join(repoRoot, "clef.yaml");
79947
- const parser = new ManifestParser();
79948
- const manifest = parser.parse(manifestPath);
79949
- const sopsYamlPath = path21.join(repoRoot, ".sops.yaml");
79950
- let agePublicKey;
79951
- if (manifest.sops.default_backend === "age") {
79952
- agePublicKey = resolveAgePublicKeyFromEnvOrFile(repoRoot);
79953
- }
79954
- const sopsConfig = buildSopsYaml(manifest, repoRoot, agePublicKey);
79955
- fs18.writeFileSync(sopsYamlPath, YAML12.stringify(sopsConfig), "utf-8");
79956
- }
79957
- function buildSopsYaml(manifest, _repoRoot, agePublicKey) {
79958
- const creationRules = [];
79959
- for (const ns of manifest.namespaces) {
79960
- for (const env of manifest.environments) {
79961
- const pathRegex = `${ns.name}/${env.name}\\.enc\\.yaml$`;
79962
- const rule = { path_regex: pathRegex };
79963
- const backend = env.sops?.backend ?? manifest.sops.default_backend;
79964
- switch (backend) {
79965
- case "age": {
79966
- const envRecipients = resolveRecipientsForEnvironment(manifest, env.name);
79967
- if (envRecipients && envRecipients.length > 0) {
79968
- const keys = envRecipients.map((r) => typeof r === "string" ? r : r.key);
79969
- rule.age = keys.join(",");
79970
- } else if (agePublicKey) {
79971
- rule.age = agePublicKey;
79972
- }
79973
- break;
79974
- }
79975
- case "awskms": {
79976
- const arn = env.sops?.aws_kms_arn ?? manifest.sops.aws_kms_arn;
79977
- if (arn) {
79978
- rule.kms = arn;
79979
- }
79980
- break;
79981
- }
79982
- case "gcpkms": {
79983
- const resourceId = env.sops?.gcp_kms_resource_id ?? manifest.sops.gcp_kms_resource_id;
79984
- if (resourceId) {
79985
- rule.gcp_kms = resourceId;
79986
- }
79987
- break;
79988
- }
79989
- case "azurekv": {
79990
- const kvUrl = env.sops?.azure_kv_url ?? manifest.sops.azure_kv_url;
79991
- if (kvUrl) {
79992
- rule.azure_keyvault = kvUrl;
79993
- }
79994
- break;
79995
- }
79996
- case "pgp": {
79997
- const fingerprint = env.sops?.pgp_fingerprint ?? manifest.sops.pgp_fingerprint;
79998
- if (fingerprint) {
79999
- rule.pgp = fingerprint;
80000
- }
80001
- break;
80002
- }
80003
- }
80004
- creationRules.push(rule);
80005
- }
80006
- }
80007
- return { creation_rules: creationRules };
80008
- }
80009
- function resolveAgePublicKeyFromEnvOrFile(repoRoot) {
80010
- if (process.env.CLEF_AGE_KEY_FILE) {
80011
- const pubKey = extractAgePublicKey(process.env.CLEF_AGE_KEY_FILE);
80012
- if (pubKey) return pubKey;
80013
- }
80014
- if (process.env.CLEF_AGE_KEY) {
80015
- const match = process.env.CLEF_AGE_KEY.match(/# public key: (age1[a-z0-9]+)/);
80016
- if (match) return match[1];
80017
- }
80018
- const clefConfigPath = path21.join(repoRoot, CLEF_DIR, CLEF_CONFIG_FILENAME);
80019
- if (fs18.existsSync(clefConfigPath)) {
80020
- try {
80021
- const config = YAML12.parse(fs18.readFileSync(clefConfigPath, "utf-8"));
80022
- if (config?.age_key_file) {
80023
- const pubKey = extractAgePublicKey(config.age_key_file);
80024
- if (pubKey) return pubKey;
80025
- }
80026
- } catch {
80027
- }
80028
- }
80029
- return void 0;
80030
- }
80031
- function extractAgePublicKey(keyFilePath) {
80032
- try {
80033
- if (!fs18.existsSync(keyFilePath)) return void 0;
80034
- const content = fs18.readFileSync(keyFilePath, "utf-8");
80035
- const match = content.match(/# public key: (age1[a-z0-9]+)/);
80036
- return match ? match[1] : void 0;
80037
- } catch {
80038
- return void 0;
80039
- }
80040
- }
80041
80041
  async function scaffoldRandomValues(ns, manifest, schemaValidator, sopsClient, repoRoot, includeOptional, addCount) {
80042
80042
  let schema;
80043
80043
  try {
@@ -80952,7 +80952,7 @@ async function fetchCheckpoint(config) {
80952
80952
  }
80953
80953
 
80954
80954
  // package.json
80955
- var version = "0.1.11-beta.62";
80955
+ var version = "0.1.11-beta.66";
80956
80956
  var package_default = {
80957
80957
  name: "@clef-sh/cli",
80958
80958
  version,
@@ -81505,17 +81505,13 @@ Usage: clef export payments/production --format env`
81505
81505
  }
81506
81506
 
81507
81507
  // src/commands/doctor.ts
81508
- var YAML14 = __toESM(require_dist());
81509
81508
  init_src();
81510
81509
  import * as fs21 from "fs";
81511
81510
  import * as path34 from "path";
81512
81511
  function registerDoctorCommand(program3, deps2) {
81513
81512
  program3.command("doctor").description(
81514
81513
  "Check your environment for required dependencies and configuration.\n\nExit codes:\n 0 All checks pass\n 1 One or more checks failed"
81515
- ).option("--json", "Output the full status as JSON").option(
81516
- "--fix",
81517
- "Attempt to auto-fix issues (runs clef init if .sops.yaml is the only failure)"
81518
- ).action(async (options) => {
81514
+ ).option("--json", "Output the full status as JSON").option("--fix", "Attempt to auto-fix issues").action(async (options) => {
81519
81515
  const repoRoot = program3.opts().dir || process.cwd();
81520
81516
  const clefVersion = program3.version() ?? "unknown";
81521
81517
  const checks = [];
@@ -81566,14 +81562,6 @@ function registerDoctorCommand(program3, deps2) {
81566
81562
  });
81567
81563
  const ageKeyResult = await checkAgeKey(repoRoot, deps2.runner);
81568
81564
  checks.push(ageKeyResult);
81569
- const sopsYamlPath = path34.join(repoRoot, ".sops.yaml");
81570
- const sopsYamlFound = fs21.existsSync(sopsYamlPath);
81571
- checks.push({
81572
- name: ".sops.yaml",
81573
- ok: sopsYamlFound,
81574
- detail: sopsYamlFound ? "found" : "not found",
81575
- hint: sopsYamlFound ? void 0 : "run: clef init"
81576
- });
81577
81565
  const clefignorePath = path34.join(repoRoot, ".clefignore");
81578
81566
  const clefignoreFound = fs21.existsSync(clefignorePath);
81579
81567
  let clefignoreRuleCount = 0;
@@ -81606,25 +81594,7 @@ function registerDoctorCommand(program3, deps2) {
81606
81594
  });
81607
81595
  if (options.fix) {
81608
81596
  const failures2 = checks.filter((c) => !c.ok);
81609
- const onlySopsYamlMissing = failures2.length === 1 && failures2[0].name === ".sops.yaml" && !sopsYamlFound;
81610
- if (onlySopsYamlMissing) {
81611
- formatter.info("Attempting to fix: generating .sops.yaml from manifest...");
81612
- try {
81613
- scaffoldSopsConfig(repoRoot);
81614
- const nowFound = fs21.existsSync(sopsYamlPath);
81615
- if (nowFound) {
81616
- const sopsYamlCheck = checks.find((c) => c.name === ".sops.yaml");
81617
- if (sopsYamlCheck) {
81618
- sopsYamlCheck.ok = true;
81619
- sopsYamlCheck.detail = "found (fixed)";
81620
- delete sopsYamlCheck.hint;
81621
- }
81622
- formatter.success(".sops.yaml created from manifest.");
81623
- }
81624
- } catch {
81625
- formatter.error("Failed to generate .sops.yaml. Run 'clef init' manually to diagnose.");
81626
- }
81627
- } else if (failures2.length > 0) {
81597
+ if (failures2.length > 0) {
81628
81598
  formatter.warn("--fix cannot resolve these issues automatically.");
81629
81599
  }
81630
81600
  }
@@ -81646,14 +81616,8 @@ function registerDoctorCommand(program3, deps2) {
81646
81616
  manifest: { found: manifestFound, ok: manifestFound },
81647
81617
  ageKey: {
81648
81618
  source: ageKeyResult.source,
81649
- recipients: countAgeRecipients(sopsYamlPath),
81650
81619
  ok: ageKeyResult.ok
81651
81620
  },
81652
- sopsYaml: {
81653
- found: checks.find((c) => c.name === ".sops.yaml").ok,
81654
- ok: checks.find((c) => c.name === ".sops.yaml").ok,
81655
- ...!checks.find((c) => c.name === ".sops.yaml").ok ? { fix: "clef init" } : {}
81656
- },
81657
81621
  scanner: {
81658
81622
  clefignoreFound: checks.find((c) => c.name === "scanner")?.ok ?? false,
81659
81623
  ok: checks.find((c) => c.name === "scanner")?.ok ?? false
@@ -81752,30 +81716,6 @@ async function checkAgeKey(repoRoot, runner2) {
81752
81716
  };
81753
81717
  }
81754
81718
  }
81755
- function countAgeRecipients(sopsYamlPath) {
81756
- try {
81757
- if (!fs21.existsSync(sopsYamlPath)) return 0;
81758
- const content = fs21.readFileSync(sopsYamlPath, "utf-8");
81759
- const config = YAML14.parse(content);
81760
- if (!config?.creation_rules || !Array.isArray(config.creation_rules)) {
81761
- return 0;
81762
- }
81763
- const recipients = /* @__PURE__ */ new Set();
81764
- for (const rule of config.creation_rules) {
81765
- if (typeof rule.age === "string") {
81766
- for (const r of rule.age.split(",")) {
81767
- const trimmed = r.trim();
81768
- if (trimmed) {
81769
- recipients.add(trimmed);
81770
- }
81771
- }
81772
- }
81773
- }
81774
- return recipients.size;
81775
- } catch {
81776
- return 0;
81777
- }
81778
- }
81779
81719
  function getSopsInstallHint() {
81780
81720
  if (process.platform === "darwin") return "brew install sops";
81781
81721
  return "see https://github.com/getsops/sops/releases";
@@ -83638,7 +83578,7 @@ function resolveTarget(opts2) {
83638
83578
  }
83639
83579
  function registerMigrateBackendCommand(program3, deps2) {
83640
83580
  program3.command("migrate-backend").description(
83641
- "Migrate encrypted files from one SOPS backend to another.\n\n Decrypts each file with the current backend, re-encrypts with\n the new one, updates clef.yaml, and regenerates .sops.yaml.\n\nExit codes:\n 0 migration completed successfully\n 1 migration failed (all changes rolled back)"
83581
+ "Migrate encrypted files from one SOPS backend to another.\n\n Decrypts each file with the current backend, re-encrypts with\n the new one, and updates clef.yaml.\n\nExit codes:\n 0 migration completed successfully\n 1 migration failed (all changes rolled back)"
83642
83582
  ).option("--aws-kms-arn <arn>", "Migrate to AWS KMS with this key ARN").option("--gcp-kms-resource-id <id>", "Migrate to GCP KMS with this resource ID").option("--azure-kv-url <url>", "Migrate to Azure Key Vault with this URL").option("--pgp-fingerprint <fp>", "Migrate to PGP with this fingerprint").option("--age", "Migrate to age backend").option("-e, --environment <env>", "Scope migration to a single environment").option("--dry-run", "Preview changes without modifying any files").option("--skip-verify", "Skip post-migration verification step").action(async (opts2) => {
83643
83583
  try {
83644
83584
  const repoRoot = program3.opts().dir || process.cwd();
@@ -83686,7 +83626,6 @@ ${sym("working")} Backend migration summary:`);
83686
83626
  dryRun: opts2.dryRun,
83687
83627
  skipVerify: opts2.skipVerify
83688
83628
  },
83689
- { regenerateSopsConfig: () => scaffoldSopsConfig(repoRoot) },
83690
83629
  (event) => {
83691
83630
  switch (event.type) {
83692
83631
  case "skip":
@@ -83735,7 +83674,7 @@ ${sym("working")} Backend migration summary:`);
83735
83674
  }
83736
83675
  if (!opts2.dryRun && result.migratedFiles.length > 0) {
83737
83676
  formatter.hint(
83738
- 'git add clef.yaml .sops.yaml secrets/ && git commit -m "chore: migrate backend to ' + target.backend + '"'
83677
+ 'git add clef.yaml secrets/ && git commit -m "chore: migrate backend to ' + target.backend + '"'
83739
83678
  );
83740
83679
  }
83741
83680
  } catch (err) {