@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.cjs CHANGED
@@ -10228,7 +10228,7 @@ var require_public_api = __commonJS({
10228
10228
  }
10229
10229
  return doc;
10230
10230
  }
10231
- function parse16(src, reviver, options) {
10231
+ function parse15(src, reviver, options) {
10232
10232
  let _reviver = void 0;
10233
10233
  if (typeof reviver === "function") {
10234
10234
  _reviver = reviver;
@@ -10269,7 +10269,7 @@ var require_public_api = __commonJS({
10269
10269
  return value.toString(options);
10270
10270
  return new Document.Document(value, _replacer, options).toString(options);
10271
10271
  }
10272
- exports2.parse = parse16;
10272
+ exports2.parse = parse15;
10273
10273
  exports2.parseAllDocuments = parseAllDocuments;
10274
10274
  exports2.parseDocument = parseDocument;
10275
10275
  exports2.stringify = stringify8;
@@ -10801,8 +10801,26 @@ var init_parser = __esm({
10801
10801
  "sops.default_backend"
10802
10802
  );
10803
10803
  }
10804
+ const ageObj = sopsObj.age;
10805
+ const ageRecipients = ageObj && Array.isArray(ageObj.recipients) ? ageObj.recipients : void 0;
10806
+ const parsedAge = ageRecipients ? {
10807
+ age: {
10808
+ recipients: ageRecipients.map((r) => {
10809
+ if (typeof r === "string") return r;
10810
+ if (typeof r === "object" && r !== null) {
10811
+ const obj2 = r;
10812
+ return {
10813
+ key: String(obj2.key ?? ""),
10814
+ ...typeof obj2.label === "string" ? { label: obj2.label } : {}
10815
+ };
10816
+ }
10817
+ return String(r);
10818
+ })
10819
+ }
10820
+ } : {};
10804
10821
  const sopsConfig = {
10805
10822
  default_backend: sopsObj.default_backend,
10823
+ ...parsedAge,
10806
10824
  ...typeof sopsObj.aws_kms_arn === "string" ? { aws_kms_arn: sopsObj.aws_kms_arn } : {},
10807
10825
  ...typeof sopsObj.gcp_kms_resource_id === "string" ? { gcp_kms_resource_id: sopsObj.gcp_kms_resource_id } : {},
10808
10826
  ...typeof sopsObj.azure_kv_url === "string" ? { azure_kv_url: sopsObj.azure_kv_url } : {},
@@ -11195,8 +11213,8 @@ var init_scanner = __esm({
11195
11213
  ALWAYS_SKIP_EXTENSIONS = [".enc.yaml", ".enc.json"];
11196
11214
  ALWAYS_SKIP_NAMES = [
11197
11215
  ".clef-meta.yaml",
11198
- ".sops.yaml"
11199
- // contains age public keys and KMS ARNs — configuration, not secrets
11216
+ "clef.yaml"
11217
+ // manifest — contains public keys and config, not secrets
11200
11218
  ];
11201
11219
  ALWAYS_SKIP_DIRS = ["node_modules", ".git"];
11202
11220
  MAX_FILE_SIZE = 1024 * 1024;
@@ -19483,9 +19501,12 @@ var init_client = __esm({
19483
19501
  }
19484
19502
  let result;
19485
19503
  try {
19504
+ const configPath = process.platform === "win32" ? "NUL" : "/dev/null";
19486
19505
  result = await this.runner.run(
19487
19506
  this.sopsCommand,
19488
19507
  [
19508
+ "--config",
19509
+ configPath,
19489
19510
  "encrypt",
19490
19511
  ...args,
19491
19512
  "--input-type",
@@ -19722,8 +19743,15 @@ var init_client = __esm({
19722
19743
  pgp_fingerprint: manifest.sops.pgp_fingerprint
19723
19744
  };
19724
19745
  switch (config.backend) {
19725
- case "age":
19746
+ case "age": {
19747
+ const envRecipients = environment ? resolveRecipientsForEnvironment(manifest, environment) : void 0;
19748
+ const recipients = envRecipients ?? manifest.sops.age?.recipients ?? [];
19749
+ const keys = recipients.map((r) => typeof r === "string" ? r : r.key);
19750
+ if (keys.length > 0) {
19751
+ args.push("--age", keys.join(","));
19752
+ }
19726
19753
  break;
19754
+ }
19727
19755
  case "awskms":
19728
19756
  if (config.aws_kms_arn) {
19729
19757
  args.push("--kms", config.aws_kms_arn);
@@ -21870,14 +21898,13 @@ var init_resolve = __esm({
21870
21898
  // ../core/src/artifact/signer.ts
21871
21899
  function buildSigningPayload(artifact) {
21872
21900
  const fields = [
21873
- "clef-sig-v2",
21901
+ "clef-sig-v3",
21874
21902
  String(artifact.version),
21875
21903
  artifact.identity,
21876
21904
  artifact.environment,
21877
21905
  artifact.revision,
21878
21906
  artifact.packedAt,
21879
21907
  artifact.ciphertextHash,
21880
- [...artifact.keys].sort().join(","),
21881
21908
  artifact.expiresAt ?? "",
21882
21909
  artifact.envelope?.provider ?? "",
21883
21910
  artifact.envelope?.keyId ?? "",
@@ -22017,7 +22044,6 @@ var init_packer = __esm({
22017
22044
  revision,
22018
22045
  ciphertextHash,
22019
22046
  ciphertext,
22020
- keys: Object.keys(resolved.values),
22021
22047
  envelope: {
22022
22048
  provider: kmsConfig.provider,
22023
22049
  keyId: kmsConfig.keyId,
@@ -22051,8 +22077,7 @@ var init_packer = __esm({
22051
22077
  packedAt: (/* @__PURE__ */ new Date()).toISOString(),
22052
22078
  revision,
22053
22079
  ciphertextHash,
22054
- ciphertext,
22055
- keys: Object.keys(resolved.values)
22080
+ ciphertext
22056
22081
  };
22057
22082
  }
22058
22083
  const outputDir = path19.dirname(config.outputPath);
@@ -22137,7 +22162,7 @@ var init_backend = __esm({
22137
22162
  this.encryption = encryption;
22138
22163
  this.matrixManager = matrixManager;
22139
22164
  }
22140
- async migrate(manifest, repoRoot, options, callbacks, onProgress) {
22165
+ async migrate(manifest, repoRoot, options, onProgress) {
22141
22166
  const { target, environment, dryRun, skipVerify } = options;
22142
22167
  if (environment) {
22143
22168
  const env = manifest.environments.find((e) => e.name === environment);
@@ -22207,14 +22232,11 @@ var init_backend = __esm({
22207
22232
  }
22208
22233
  const manifestPath = path20.join(repoRoot, CLEF_MANIFEST_FILENAME);
22209
22234
  const manifestBackup = fs17.readFileSync(manifestPath, "utf-8");
22210
- const sopsYamlPath = path20.join(repoRoot, ".sops.yaml");
22211
- const sopsYamlBackup = fs17.existsSync(sopsYamlPath) ? fs17.readFileSync(sopsYamlPath, "utf-8") : void 0;
22212
22235
  const fileBackups = /* @__PURE__ */ new Map();
22213
22236
  const doc = readManifestYaml(repoRoot);
22214
22237
  this.updateManifestDoc(doc, target, environment);
22215
22238
  writeManifestYaml(repoRoot, doc);
22216
22239
  const updatedManifest = YAML11.parse(YAML11.stringify(doc));
22217
- callbacks.regenerateSopsConfig();
22218
22240
  const migratedFiles = [];
22219
22241
  for (const cell of toMigrate) {
22220
22242
  try {
@@ -22233,7 +22255,7 @@ var init_backend = __esm({
22233
22255
  );
22234
22256
  migratedFiles.push(cell.filePath);
22235
22257
  } catch (err) {
22236
- this.rollback(manifestPath, manifestBackup, sopsYamlPath, sopsYamlBackup, fileBackups);
22258
+ this.rollback(manifestPath, manifestBackup, fileBackups);
22237
22259
  const errorMsg = err instanceof Error ? err.message : String(err);
22238
22260
  onProgress?.({
22239
22261
  type: "warn",
@@ -22297,15 +22319,10 @@ var init_backend = __esm({
22297
22319
  }
22298
22320
  }
22299
22321
  }
22300
- rollback(manifestPath, manifestBackup, sopsYamlPath, sopsYamlBackup, fileBackups) {
22322
+ rollback(manifestPath, manifestBackup, fileBackups) {
22301
22323
  for (const [filePath, backup] of fileBackups) {
22302
22324
  fs17.writeFileSync(filePath, backup, "utf-8");
22303
22325
  }
22304
- if (sopsYamlBackup !== void 0) {
22305
- fs17.writeFileSync(sopsYamlPath, sopsYamlBackup, "utf-8");
22306
- } else if (fs17.existsSync(sopsYamlPath)) {
22307
- fs17.unlinkSync(sopsYamlPath);
22308
- }
22309
22326
  fs17.writeFileSync(manifestPath, manifestBackup, "utf-8");
22310
22327
  }
22311
22328
  checkAgeRecipientsWarning(manifest, target, environment, warnings) {
@@ -22535,7 +22552,7 @@ var require_ms = __commonJS({
22535
22552
  options = options || {};
22536
22553
  var type = typeof val;
22537
22554
  if (type === "string" && val.length > 0) {
22538
- return parse16(val);
22555
+ return parse15(val);
22539
22556
  } else if (type === "number" && isFinite(val)) {
22540
22557
  return options.long ? fmtLong(val) : fmtShort(val);
22541
22558
  }
@@ -22543,7 +22560,7 @@ var require_ms = __commonJS({
22543
22560
  "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
22544
22561
  );
22545
22562
  };
22546
- function parse16(str2) {
22563
+ function parse15(str2) {
22547
22564
  str2 = String(str2);
22548
22565
  if (str2.length > 100) {
22549
22566
  return;
@@ -23982,7 +23999,7 @@ var require_bytes = __commonJS({
23982
23999
  "use strict";
23983
24000
  module2.exports = bytes;
23984
24001
  module2.exports.format = format;
23985
- module2.exports.parse = parse16;
24002
+ module2.exports.parse = parse15;
23986
24003
  var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
23987
24004
  var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
23988
24005
  var map = {
@@ -23996,7 +24013,7 @@ var require_bytes = __commonJS({
23996
24013
  var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
23997
24014
  function bytes(value, options) {
23998
24015
  if (typeof value === "string") {
23999
- return parse16(value);
24016
+ return parse15(value);
24000
24017
  }
24001
24018
  if (typeof value === "number") {
24002
24019
  return format(value, options);
@@ -24040,7 +24057,7 @@ var require_bytes = __commonJS({
24040
24057
  }
24041
24058
  return str2 + unitSeparator + unit;
24042
24059
  }
24043
- function parse16(val) {
24060
+ function parse15(val) {
24044
24061
  if (typeof val === "number" && !isNaN(val)) {
24045
24062
  return val;
24046
24063
  }
@@ -28245,7 +28262,7 @@ var require_content_type = __commonJS({
28245
28262
  var QUOTE_REGEXP = /([\\"])/g;
28246
28263
  var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
28247
28264
  exports2.format = format;
28248
- exports2.parse = parse16;
28265
+ exports2.parse = parse15;
28249
28266
  function format(obj) {
28250
28267
  if (!obj || typeof obj !== "object") {
28251
28268
  throw new TypeError("argument obj is required");
@@ -28269,7 +28286,7 @@ var require_content_type = __commonJS({
28269
28286
  }
28270
28287
  return string;
28271
28288
  }
28272
- function parse16(string) {
28289
+ function parse15(string) {
28273
28290
  if (!string) {
28274
28291
  throw new TypeError("argument string is required");
28275
28292
  }
@@ -37851,7 +37868,7 @@ var require_media_typer = __commonJS({
37851
37868
  var TYPE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/;
37852
37869
  var TYPE_REGEXP = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
37853
37870
  exports2.format = format;
37854
- exports2.parse = parse16;
37871
+ exports2.parse = parse15;
37855
37872
  exports2.test = test;
37856
37873
  function format(obj) {
37857
37874
  if (!obj || typeof obj !== "object") {
@@ -37884,7 +37901,7 @@ var require_media_typer = __commonJS({
37884
37901
  }
37885
37902
  return TYPE_REGEXP.test(string.toLowerCase());
37886
37903
  }
37887
- function parse16(string) {
37904
+ function parse15(string) {
37888
37905
  if (!string) {
37889
37906
  throw new TypeError("argument string is required");
37890
37907
  }
@@ -38070,7 +38087,7 @@ var require_read = __commonJS({
38070
38087
  var hasBody = require_type_is().hasBody;
38071
38088
  var { getCharset } = require_utils();
38072
38089
  module2.exports = read;
38073
- function read(req, res, next, parse16, debug, options) {
38090
+ function read(req, res, next, parse15, debug, options) {
38074
38091
  if (onFinished.isFinished(req)) {
38075
38092
  debug("body already parsed");
38076
38093
  next();
@@ -38158,7 +38175,7 @@ var require_read = __commonJS({
38158
38175
  try {
38159
38176
  debug("parse body");
38160
38177
  str2 = typeof body !== "string" && encoding !== null ? iconv.decode(body, encoding) : body;
38161
- req.body = parse16(str2, encoding);
38178
+ req.body = parse15(str2, encoding);
38162
38179
  } catch (err) {
38163
38180
  next(createError(400, err, {
38164
38181
  body: str2,
@@ -38231,7 +38248,7 @@ var require_json = __commonJS({
38231
38248
  const normalizedOptions = normalizeOptions(options, "application/json");
38232
38249
  var reviver = options?.reviver;
38233
38250
  var strict = options?.strict !== false;
38234
- function parse16(body) {
38251
+ function parse15(body) {
38235
38252
  if (body.length === 0) {
38236
38253
  return {};
38237
38254
  }
@@ -38258,7 +38275,7 @@ var require_json = __commonJS({
38258
38275
  isValidCharset: (charset) => charset.slice(0, 4) === "utf-"
38259
38276
  };
38260
38277
  return function jsonParser(req, res, next) {
38261
- read(req, res, next, parse16, debug, readOptions);
38278
+ read(req, res, next, parse15, debug, readOptions);
38262
38279
  };
38263
38280
  }
38264
38281
  function createStrictSyntaxError(str2, char) {
@@ -40836,11 +40853,11 @@ var require_lib2 = __commonJS({
40836
40853
  "../../node_modules/qs/lib/index.js"(exports2, module2) {
40837
40854
  "use strict";
40838
40855
  var stringify8 = require_stringify2();
40839
- var parse16 = require_parse();
40856
+ var parse15 = require_parse();
40840
40857
  var formats = require_formats();
40841
40858
  module2.exports = {
40842
40859
  formats,
40843
- parse: parse16,
40860
+ parse: parse15,
40844
40861
  stringify: stringify8
40845
40862
  };
40846
40863
  }
@@ -40862,7 +40879,7 @@ var require_urlencoded = __commonJS({
40862
40879
  throw new TypeError("option defaultCharset must be either utf-8 or iso-8859-1");
40863
40880
  }
40864
40881
  var queryparse = createQueryParser(options);
40865
- function parse16(body, encoding) {
40882
+ function parse15(body, encoding) {
40866
40883
  return body.length ? queryparse(body, encoding) : {};
40867
40884
  }
40868
40885
  const readOptions = {
@@ -40871,7 +40888,7 @@ var require_urlencoded = __commonJS({
40871
40888
  isValidCharset: (charset) => charset === "utf-8" || charset === "iso-8859-1"
40872
40889
  };
40873
40890
  return function urlencodedParser(req, res, next) {
40874
- read(req, res, next, parse16, debug, readOptions);
40891
+ read(req, res, next, parse15, debug, readOptions);
40875
40892
  };
40876
40893
  }
40877
40894
  function createQueryParser(options) {
@@ -41055,7 +41072,7 @@ var require_parseurl = __commonJS({
41055
41072
  "../../node_modules/parseurl/index.js"(exports2, module2) {
41056
41073
  "use strict";
41057
41074
  var url = require("url");
41058
- var parse16 = url.parse;
41075
+ var parse15 = url.parse;
41059
41076
  var Url = url.Url;
41060
41077
  module2.exports = parseurl;
41061
41078
  module2.exports.original = originalurl;
@@ -41087,7 +41104,7 @@ var require_parseurl = __commonJS({
41087
41104
  }
41088
41105
  function fastparse(str2) {
41089
41106
  if (typeof str2 !== "string" || str2.charCodeAt(0) !== 47) {
41090
- return parse16(str2);
41107
+ return parse15(str2);
41091
41108
  }
41092
41109
  var pathname = str2;
41093
41110
  var query = null;
@@ -41115,7 +41132,7 @@ var require_parseurl = __commonJS({
41115
41132
  /* # */
41116
41133
  case 160:
41117
41134
  case 65279:
41118
- return parse16(str2);
41135
+ return parse15(str2);
41119
41136
  }
41120
41137
  }
41121
41138
  var url2 = Url !== void 0 ? new Url() : {};
@@ -50911,7 +50928,7 @@ var require_forwarded = __commonJS({
50911
50928
  if (!req) {
50912
50929
  throw new TypeError("argument req is required");
50913
50930
  }
50914
- var proxyAddrs = parse16(req.headers["x-forwarded-for"] || "");
50931
+ var proxyAddrs = parse15(req.headers["x-forwarded-for"] || "");
50915
50932
  var socketAddr = getSocketAddr(req);
50916
50933
  var addrs = [socketAddr].concat(proxyAddrs);
50917
50934
  return addrs;
@@ -50919,7 +50936,7 @@ var require_forwarded = __commonJS({
50919
50936
  function getSocketAddr(req) {
50920
50937
  return req.socket ? req.socket.remoteAddress : req.connection.remoteAddress;
50921
50938
  }
50922
- function parse16(header) {
50939
+ function parse15(header) {
50923
50940
  var end = header.length;
50924
50941
  var list = [];
50925
50942
  var start = header.length;
@@ -51948,7 +51965,7 @@ var require_dist2 = __commonJS({
51948
51965
  "use strict";
51949
51966
  Object.defineProperty(exports2, "__esModule", { value: true });
51950
51967
  exports2.PathError = exports2.TokenData = void 0;
51951
- exports2.parse = parse16;
51968
+ exports2.parse = parse15;
51952
51969
  exports2.compile = compile;
51953
51970
  exports2.match = match;
51954
51971
  exports2.pathToRegexp = pathToRegexp;
@@ -51983,7 +52000,7 @@ var require_dist2 = __commonJS({
51983
52000
  }
51984
52001
  };
51985
52002
  exports2.PathError = PathError;
51986
- function parse16(str2, options = {}) {
52003
+ function parse15(str2, options = {}) {
51987
52004
  const { encodePath = NOOP_VALUE } = options;
51988
52005
  const chars = [...str2];
51989
52006
  const tokens = [];
@@ -52072,7 +52089,7 @@ var require_dist2 = __commonJS({
52072
52089
  }
52073
52090
  function compile(path47, options = {}) {
52074
52091
  const { encode = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
52075
- const data = typeof path47 === "object" ? path47 : parse16(path47, options);
52092
+ const data = typeof path47 === "object" ? path47 : parse15(path47, options);
52076
52093
  const fn = tokensToFunction(data.tokens, delimiter, encode);
52077
52094
  return function path48(params = {}) {
52078
52095
  const [path49, ...missing] = fn(params);
@@ -52173,7 +52190,7 @@ var require_dist2 = __commonJS({
52173
52190
  paths.push(...path48);
52174
52191
  continue;
52175
52192
  }
52176
- const data = typeof path48 === "object" ? path48 : parse16(path48, options);
52193
+ const data = typeof path48 === "object" ? path48 : parse15(path48, options);
52177
52194
  flatten(data.tokens, 0, [], (tokens) => {
52178
52195
  if (combinations++ >= 256) {
52179
52196
  throw new PathError("Too many path combinations", data.originalPath);
@@ -63498,7 +63515,7 @@ var require_request = __commonJS({
63498
63515
  var http = require("node:http");
63499
63516
  var fresh = require_fresh();
63500
63517
  var parseRange = require_range_parser();
63501
- var parse16 = require_parseurl();
63518
+ var parse15 = require_parseurl();
63502
63519
  var proxyaddr = require_proxy_addr();
63503
63520
  var req = Object.create(http.IncomingMessage.prototype);
63504
63521
  module2.exports = req;
@@ -63543,7 +63560,7 @@ var require_request = __commonJS({
63543
63560
  if (!queryparse) {
63544
63561
  return /* @__PURE__ */ Object.create(null);
63545
63562
  }
63546
- var querystring = parse16(this).query;
63563
+ var querystring = parse15(this).query;
63547
63564
  return queryparse(querystring);
63548
63565
  });
63549
63566
  req.is = function is(types) {
@@ -63587,7 +63604,7 @@ var require_request = __commonJS({
63587
63604
  return subdomains2.slice(offset);
63588
63605
  });
63589
63606
  defineGetter(req, "path", function path47() {
63590
- return parse16(this).pathname;
63607
+ return parse15(this).pathname;
63591
63608
  });
63592
63609
  defineGetter(req, "host", function host() {
63593
63610
  var trust = this.app.get("trust proxy fn");
@@ -63641,7 +63658,7 @@ var require_content_disposition = __commonJS({
63641
63658
  "../../node_modules/content-disposition/index.js"(exports2, module2) {
63642
63659
  "use strict";
63643
63660
  module2.exports = contentDisposition;
63644
- module2.exports.parse = parse16;
63661
+ module2.exports.parse = parse15;
63645
63662
  var basename5 = require("path").basename;
63646
63663
  var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
63647
63664
  var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
@@ -63732,7 +63749,7 @@ var require_content_disposition = __commonJS({
63732
63749
  function getlatin1(val) {
63733
63750
  return String(val).replace(NON_LATIN1_REGEXP, "?");
63734
63751
  }
63735
- function parse16(string) {
63752
+ function parse15(string) {
63736
63753
  if (!string || typeof string !== "string") {
63737
63754
  throw new TypeError("argument string is required");
63738
63755
  }
@@ -63821,7 +63838,7 @@ var require_cookie_signature = __commonJS({
63821
63838
  var require_cookie = __commonJS({
63822
63839
  "../../node_modules/cookie/index.js"(exports2) {
63823
63840
  "use strict";
63824
- exports2.parse = parse16;
63841
+ exports2.parse = parse15;
63825
63842
  exports2.serialize = serialize;
63826
63843
  var __toString = Object.prototype.toString;
63827
63844
  var __hasOwnProperty = Object.prototype.hasOwnProperty;
@@ -63829,7 +63846,7 @@ var require_cookie = __commonJS({
63829
63846
  var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
63830
63847
  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;
63831
63848
  var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
63832
- function parse16(str2, opt) {
63849
+ function parse15(str2, opt) {
63833
63850
  if (typeof str2 !== "string") {
63834
63851
  throw new TypeError("argument str must be a string");
63835
63852
  }
@@ -73985,7 +74002,7 @@ var require_vary = __commonJS({
73985
74002
  if (!field) {
73986
74003
  throw new TypeError("field argument is required");
73987
74004
  }
73988
- var fields = !Array.isArray(field) ? parse16(String(field)) : field;
74005
+ var fields = !Array.isArray(field) ? parse15(String(field)) : field;
73989
74006
  for (var j = 0; j < fields.length; j++) {
73990
74007
  if (!FIELD_NAME_REGEXP.test(fields[j])) {
73991
74008
  throw new TypeError("field argument contains an invalid header name");
@@ -73995,7 +74012,7 @@ var require_vary = __commonJS({
73995
74012
  return header;
73996
74013
  }
73997
74014
  var val = header;
73998
- var vals = parse16(header.toLowerCase());
74015
+ var vals = parse15(header.toLowerCase());
73999
74016
  if (fields.indexOf("*") !== -1 || vals.indexOf("*") !== -1) {
74000
74017
  return "*";
74001
74018
  }
@@ -74008,7 +74025,7 @@ var require_vary = __commonJS({
74008
74025
  }
74009
74026
  return val;
74010
74027
  }
74011
- function parse16(header) {
74028
+ function parse15(header) {
74012
74029
  var end = 0;
74013
74030
  var list = [];
74014
74031
  var start = 0;
@@ -75469,161 +75486,6 @@ var require_dist3 = __commonJS({
75469
75486
  }
75470
75487
  });
75471
75488
 
75472
- // ../ui/dist/server/sops-config.js
75473
- var require_sops_config = __commonJS({
75474
- "../ui/dist/server/sops-config.js"(exports2) {
75475
- "use strict";
75476
- var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
75477
- if (k2 === void 0) k2 = k;
75478
- var desc = Object.getOwnPropertyDescriptor(m, k);
75479
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
75480
- desc = { enumerable: true, get: function() {
75481
- return m[k];
75482
- } };
75483
- }
75484
- Object.defineProperty(o, k2, desc);
75485
- }) : (function(o, m, k, k2) {
75486
- if (k2 === void 0) k2 = k;
75487
- o[k2] = m[k];
75488
- }));
75489
- var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
75490
- Object.defineProperty(o, "default", { enumerable: true, value: v });
75491
- }) : function(o, v) {
75492
- o["default"] = v;
75493
- });
75494
- var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
75495
- var ownKeys = function(o) {
75496
- ownKeys = Object.getOwnPropertyNames || function(o2) {
75497
- var ar = [];
75498
- for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
75499
- return ar;
75500
- };
75501
- return ownKeys(o);
75502
- };
75503
- return function(mod) {
75504
- if (mod && mod.__esModule) return mod;
75505
- var result = {};
75506
- if (mod != null) {
75507
- for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
75508
- }
75509
- __setModuleDefault(result, mod);
75510
- return result;
75511
- };
75512
- })();
75513
- Object.defineProperty(exports2, "__esModule", { value: true });
75514
- exports2.scaffoldSopsConfig = scaffoldSopsConfig2;
75515
- var fs28 = __importStar(require("fs"));
75516
- var path47 = __importStar(require("path"));
75517
- var YAML15 = __importStar(require_dist());
75518
- var core_1 = (init_src(), __toCommonJS(src_exports));
75519
- function scaffoldSopsConfig2(repoRoot, ageKeyFile, ageKey) {
75520
- const parser = new core_1.ManifestParser();
75521
- const manifest = parser.parse(path47.join(repoRoot, "clef.yaml"));
75522
- const sopsYamlPath = path47.join(repoRoot, ".sops.yaml");
75523
- let agePublicKey;
75524
- if (manifest.sops.default_backend === "age") {
75525
- agePublicKey = resolveAgePublicKey(repoRoot, ageKeyFile, ageKey);
75526
- }
75527
- const sopsConfig = buildSopsYaml2(manifest, agePublicKey);
75528
- fs28.writeFileSync(sopsYamlPath, YAML15.stringify(sopsConfig), "utf-8");
75529
- }
75530
- function buildSopsYaml2(manifest, agePublicKey) {
75531
- const creationRules = [];
75532
- for (const ns of manifest.namespaces) {
75533
- for (const env of manifest.environments) {
75534
- const pathRegex = `${ns.name}/${env.name}\\.enc\\.yaml$`;
75535
- const rule = { path_regex: pathRegex };
75536
- const backend = env.sops?.backend ?? manifest.sops.default_backend;
75537
- switch (backend) {
75538
- case "age": {
75539
- const envRecipients = (0, core_1.resolveRecipientsForEnvironment)(manifest, env.name);
75540
- if (envRecipients && envRecipients.length > 0) {
75541
- const keys = envRecipients.map((r) => typeof r === "string" ? r : r.key);
75542
- rule.age = keys.join(",");
75543
- } else if (agePublicKey) {
75544
- rule.age = agePublicKey;
75545
- }
75546
- break;
75547
- }
75548
- case "awskms": {
75549
- const arn = env.sops?.aws_kms_arn ?? manifest.sops.aws_kms_arn;
75550
- if (arn)
75551
- rule.kms = arn;
75552
- break;
75553
- }
75554
- case "gcpkms": {
75555
- const resourceId = env.sops?.gcp_kms_resource_id ?? manifest.sops.gcp_kms_resource_id;
75556
- if (resourceId)
75557
- rule.gcp_kms = resourceId;
75558
- break;
75559
- }
75560
- case "azurekv": {
75561
- const kvUrl = env.sops?.azure_kv_url ?? manifest.sops.azure_kv_url;
75562
- if (kvUrl)
75563
- rule.azure_keyvault = kvUrl;
75564
- break;
75565
- }
75566
- case "pgp": {
75567
- const fingerprint = env.sops?.pgp_fingerprint ?? manifest.sops.pgp_fingerprint;
75568
- if (fingerprint)
75569
- rule.pgp = fingerprint;
75570
- break;
75571
- }
75572
- }
75573
- creationRules.push(rule);
75574
- }
75575
- }
75576
- return { creation_rules: creationRules };
75577
- }
75578
- function resolveAgePublicKey(repoRoot, ageKeyFile, ageKey) {
75579
- if (ageKeyFile) {
75580
- const pubKey = extractAgePublicKey2(ageKeyFile);
75581
- if (pubKey)
75582
- return pubKey;
75583
- }
75584
- if (ageKey) {
75585
- const match = ageKey.match(/# public key: (age1[a-z0-9]+)/);
75586
- if (match)
75587
- return match[1];
75588
- }
75589
- if (process.env.CLEF_AGE_KEY_FILE) {
75590
- const pubKey = extractAgePublicKey2(process.env.CLEF_AGE_KEY_FILE);
75591
- if (pubKey)
75592
- return pubKey;
75593
- }
75594
- if (process.env.CLEF_AGE_KEY) {
75595
- const match = process.env.CLEF_AGE_KEY.match(/# public key: (age1[a-z0-9]+)/);
75596
- if (match)
75597
- return match[1];
75598
- }
75599
- const clefConfigPath = path47.join(repoRoot, ".clef", "config.yaml");
75600
- if (fs28.existsSync(clefConfigPath)) {
75601
- try {
75602
- const config = YAML15.parse(fs28.readFileSync(clefConfigPath, "utf-8"));
75603
- if (config?.age_key_file) {
75604
- const pubKey = extractAgePublicKey2(config.age_key_file);
75605
- if (pubKey)
75606
- return pubKey;
75607
- }
75608
- } catch {
75609
- }
75610
- }
75611
- return void 0;
75612
- }
75613
- function extractAgePublicKey2(keyFilePath) {
75614
- try {
75615
- if (!fs28.existsSync(keyFilePath))
75616
- return void 0;
75617
- const content = fs28.readFileSync(keyFilePath, "utf-8");
75618
- const match = content.match(/# public key: (age1[a-z0-9]+)/);
75619
- return match ? match[1] : void 0;
75620
- } catch {
75621
- return void 0;
75622
- }
75623
- }
75624
- }
75625
- });
75626
-
75627
75489
  // ../ui/dist/server/api.js
75628
75490
  var require_api = __commonJS({
75629
75491
  "../ui/dist/server/api.js"(exports2) {
@@ -75673,7 +75535,6 @@ var require_api = __commonJS({
75673
75535
  var express_1 = require_express2();
75674
75536
  var _useStdinFifo = process.platform === "linux" && !process.env.JEST_WORKER_ID;
75675
75537
  var core_1 = (init_src(), __toCommonJS(src_exports));
75676
- var sops_config_1 = require_sops_config();
75677
75538
  function createApiRouter(deps2) {
75678
75539
  const router = (0, express_1.Router)();
75679
75540
  const parser = new core_1.ManifestParser();
@@ -75686,7 +75547,7 @@ var require_api = __commonJS({
75686
75547
  return deps2.runner.run(cmd, args, {
75687
75548
  ...opts,
75688
75549
  cwd: opts?.cwd ?? deps2.repoRoot,
75689
- env: { SOPS_CONFIG: path47.join(deps2.repoRoot, ".sops.yaml"), ...opts?.env }
75550
+ env: opts?.env
75690
75551
  });
75691
75552
  }
75692
75553
  const fifoDir = (0, child_process_1.execFileSync)("mktemp", ["-d", path47.join(os4.tmpdir(), "clef-fifo-XXXXXX")]).toString().trim();
@@ -75925,6 +75786,29 @@ var require_api = __commonJS({
75925
75786
  res.status(500).json({ error: "Failed to delete key", code: "DELETE_ERROR" });
75926
75787
  }
75927
75788
  });
75789
+ router.post("/namespace/:ns/:env/:key/accept", async (req, res) => {
75790
+ setNoCacheHeaders(res);
75791
+ try {
75792
+ const manifest = loadManifest();
75793
+ const { ns, env, key } = req.params;
75794
+ const nsExists = manifest.namespaces.some((n) => n.name === ns);
75795
+ const envExists = manifest.environments.some((e) => e.name === env);
75796
+ if (!nsExists || !envExists) {
75797
+ res.status(404).json({
75798
+ error: `Namespace '${ns}' or environment '${env}' not found in manifest.`,
75799
+ code: "NOT_FOUND"
75800
+ });
75801
+ return;
75802
+ }
75803
+ const filePath = `${deps2.repoRoot}/${manifest.file_pattern.replace("{namespace}", ns).replace("{environment}", env)}`;
75804
+ const decrypted = await sops.decrypt(filePath);
75805
+ const value = key in decrypted.values ? String(decrypted.values[key]) : void 0;
75806
+ await (0, core_1.markResolved)(filePath, [key]);
75807
+ res.json({ success: true, key, value });
75808
+ } catch {
75809
+ res.status(500).json({ error: "Failed to accept pending value", code: "ACCEPT_ERROR" });
75810
+ }
75811
+ });
75928
75812
  router.post("/copy", async (req, res) => {
75929
75813
  try {
75930
75814
  const manifest = loadManifest();
@@ -76442,9 +76326,7 @@ var require_api = __commonJS({
76442
76326
  return;
76443
76327
  }
76444
76328
  const events = [];
76445
- const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: true }, {
76446
- regenerateSopsConfig: () => (0, sops_config_1.scaffoldSopsConfig)(deps2.repoRoot, deps2.ageKeyFile, deps2.ageKey)
76447
- }, (event) => events.push(event));
76329
+ const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: true }, (event) => events.push(event));
76448
76330
  res.json({ success: !result.rolledBack, result, events });
76449
76331
  } catch (err) {
76450
76332
  const message = err instanceof Error ? err.message : "Migration preview failed";
@@ -76470,9 +76352,7 @@ var require_api = __commonJS({
76470
76352
  return;
76471
76353
  }
76472
76354
  const events = [];
76473
- const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: false }, {
76474
- regenerateSopsConfig: () => (0, sops_config_1.scaffoldSopsConfig)(deps2.repoRoot, deps2.ageKeyFile, deps2.ageKey)
76475
- }, (event) => events.push(event));
76355
+ const result = await backendMigrator.migrate(manifest, deps2.repoRoot, { target, environment, dryRun: false }, (event) => events.push(event));
76476
76356
  res.json({ success: !result.rolledBack, result, events });
76477
76357
  } catch (err) {
76478
76358
  const message = err instanceof Error ? err.message : "Migration failed";
@@ -77336,7 +77216,7 @@ var require_artifact_decryptor = __commonJS({
77336
77216
  } finally {
77337
77217
  plaintext = "";
77338
77218
  }
77339
- return { values, keys: artifact.keys, revision: artifact.revision };
77219
+ return { values, keys: Object.keys(values), revision: artifact.revision };
77340
77220
  }
77341
77221
  /** KMS envelope: unwrap DEK via KMS, then AES-256-GCM decrypt. */
77342
77222
  async decryptKmsEnvelope(artifact) {
@@ -77437,14 +77317,13 @@ var require_signature = __commonJS({
77437
77317
  var crypto6 = __importStar(require("crypto"));
77438
77318
  function buildSigningPayload2(artifact) {
77439
77319
  const fields = [
77440
- "clef-sig-v2",
77320
+ "clef-sig-v3",
77441
77321
  String(artifact.version),
77442
77322
  artifact.identity,
77443
77323
  artifact.environment,
77444
77324
  artifact.revision,
77445
77325
  artifact.packedAt,
77446
77326
  artifact.ciphertextHash,
77447
- [...artifact.keys].sort().join(","),
77448
77327
  artifact.expiresAt ?? "",
77449
77328
  artifact.envelope?.provider ?? "",
77450
77329
  artifact.envelope?.keyId ?? "",
@@ -77577,7 +77456,6 @@ var require_poller = __commonJS({
77577
77456
  this.options.onRefresh?.(artifact.revision);
77578
77457
  this.telemetry?.artifactRefreshed({
77579
77458
  revision: artifact.revision,
77580
- keyCount: artifact.keys.length,
77581
77459
  kmsEnvelope: !!artifact.envelope
77582
77460
  });
77583
77461
  }
@@ -77734,14 +77612,15 @@ var require_poller = __commonJS({
77734
77612
  if (artifact.revision === this.lastRevision)
77735
77613
  return;
77736
77614
  const { values } = await this.decryptor.decrypt(artifact);
77737
- this.options.cache.swap(values, artifact.keys, artifact.revision);
77615
+ const keys = Object.keys(values);
77616
+ this.options.cache.swap(values, keys, artifact.revision);
77738
77617
  this.lastRevision = artifact.revision;
77739
77618
  this.lastContentHash = contentHash ?? null;
77740
77619
  this.lastExpiresAt = artifact.expiresAt ?? null;
77741
77620
  this.options.onRefresh?.(artifact.revision);
77742
77621
  this.telemetry?.artifactRefreshed({
77743
77622
  revision: artifact.revision,
77744
- keyCount: artifact.keys.length,
77623
+ keyCount: keys.length,
77745
77624
  kmsEnvelope: !!artifact.envelope
77746
77625
  });
77747
77626
  }
@@ -77864,10 +77743,6 @@ var require_encrypted_artifact_store = __commonJS({
77864
77743
  getStoredAt() {
77865
77744
  return this._storedAt;
77866
77745
  }
77867
- /** Get key names from the stored artifact metadata (no decryption needed). */
77868
- getKeys() {
77869
- return this.artifact ? [...this.artifact.keys] : [];
77870
- }
77871
77746
  /** Get the revision from the stored artifact. */
77872
77747
  getRevision() {
77873
77748
  return this.artifact?.revision ?? null;
@@ -78349,12 +78224,228 @@ var require_vcs2 = __commonJS({
78349
78224
  }
78350
78225
  });
78351
78226
 
78227
+ // ../runtime/dist/sources/s3.js
78228
+ var require_s3 = __commonJS({
78229
+ "../runtime/dist/sources/s3.js"(exports2) {
78230
+ "use strict";
78231
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
78232
+ if (k2 === void 0) k2 = k;
78233
+ var desc = Object.getOwnPropertyDescriptor(m, k);
78234
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
78235
+ desc = { enumerable: true, get: function() {
78236
+ return m[k];
78237
+ } };
78238
+ }
78239
+ Object.defineProperty(o, k2, desc);
78240
+ }) : (function(o, m, k, k2) {
78241
+ if (k2 === void 0) k2 = k;
78242
+ o[k2] = m[k];
78243
+ }));
78244
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
78245
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
78246
+ }) : function(o, v) {
78247
+ o["default"] = v;
78248
+ });
78249
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
78250
+ var ownKeys = function(o) {
78251
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
78252
+ var ar = [];
78253
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
78254
+ return ar;
78255
+ };
78256
+ return ownKeys(o);
78257
+ };
78258
+ return function(mod) {
78259
+ if (mod && mod.__esModule) return mod;
78260
+ var result = {};
78261
+ if (mod != null) {
78262
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
78263
+ }
78264
+ __setModuleDefault(result, mod);
78265
+ return result;
78266
+ };
78267
+ })();
78268
+ Object.defineProperty(exports2, "__esModule", { value: true });
78269
+ exports2.S3ArtifactSource = void 0;
78270
+ exports2.isS3Url = isS3Url;
78271
+ var crypto6 = __importStar(require("crypto"));
78272
+ function isS3Url(url) {
78273
+ return parseS3UrlSafe(url) !== null;
78274
+ }
78275
+ function parseS3Url(url) {
78276
+ const loc = parseS3UrlSafe(url);
78277
+ if (!loc)
78278
+ throw new Error(`Not a valid S3 URL: ${url}`);
78279
+ return loc;
78280
+ }
78281
+ function parseS3UrlSafe(url) {
78282
+ let u;
78283
+ try {
78284
+ u = new URL(url);
78285
+ } catch {
78286
+ return null;
78287
+ }
78288
+ if (u.protocol !== "https:")
78289
+ return null;
78290
+ const host = u.hostname;
78291
+ const key = u.pathname.slice(1);
78292
+ if (!key)
78293
+ return null;
78294
+ const vhMatch = host.match(/^(.+)\.s3\.([a-z0-9-]+)\.amazonaws\.com$/) ?? host.match(/^(.+)\.s3\.amazonaws\.com$/);
78295
+ if (vhMatch) {
78296
+ return { bucket: vhMatch[1], key, region: vhMatch[2] || "us-east-1" };
78297
+ }
78298
+ const psMatch = host.match(/^s3\.([a-z0-9-]+)\.amazonaws\.com$/) ?? host.match(/^s3\.amazonaws\.com$/);
78299
+ if (psMatch) {
78300
+ const slashIdx = key.indexOf("/");
78301
+ if (slashIdx < 0)
78302
+ return null;
78303
+ return {
78304
+ bucket: key.slice(0, slashIdx),
78305
+ key: key.slice(slashIdx + 1),
78306
+ region: psMatch[1] || "us-east-1"
78307
+ };
78308
+ }
78309
+ return null;
78310
+ }
78311
+ var S3ArtifactSource = class {
78312
+ url;
78313
+ location;
78314
+ cachedCredentials = null;
78315
+ constructor(url) {
78316
+ this.url = url;
78317
+ this.location = parseS3Url(url);
78318
+ }
78319
+ async fetch() {
78320
+ const creds = await this.resolveCredentials();
78321
+ const { bucket, key, region } = this.location;
78322
+ const host = `${bucket}.s3.${region}.amazonaws.com`;
78323
+ const path47 = `/${encodeS3Key(key)}`;
78324
+ const now = /* @__PURE__ */ new Date();
78325
+ const headers = signS3GetRequest(host, path47, region, creds, now);
78326
+ const res = await globalThis.fetch(`https://${host}${path47}`, { headers });
78327
+ if (!res.ok) {
78328
+ throw new Error(`Failed to fetch artifact from ${this.describe()}: ${res.status} ${res.statusText}`);
78329
+ }
78330
+ const raw = await res.text();
78331
+ const etag = res.headers.get("etag") ?? void 0;
78332
+ return { raw, contentHash: etag };
78333
+ }
78334
+ describe() {
78335
+ const { bucket, key } = this.location;
78336
+ return `S3 s3://${bucket}/${key}`;
78337
+ }
78338
+ async resolveCredentials() {
78339
+ if (this.cachedCredentials && Date.now() < this.cachedCredentials.expiresAt - 3e5) {
78340
+ return this.cachedCredentials.creds;
78341
+ }
78342
+ const relativeUri = process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI;
78343
+ if (relativeUri) {
78344
+ return this.fetchEcsCredentials(`http://169.254.170.2${relativeUri}`);
78345
+ }
78346
+ const fullUri = process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI;
78347
+ if (fullUri) {
78348
+ return this.fetchEcsCredentials(fullUri);
78349
+ }
78350
+ const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
78351
+ const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
78352
+ if (accessKeyId && secretAccessKey) {
78353
+ return {
78354
+ accessKeyId,
78355
+ secretAccessKey,
78356
+ sessionToken: process.env.AWS_SESSION_TOKEN
78357
+ };
78358
+ }
78359
+ 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.");
78360
+ }
78361
+ async fetchEcsCredentials(endpoint) {
78362
+ const headers = {};
78363
+ const authToken = process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;
78364
+ if (authToken) {
78365
+ headers["Authorization"] = authToken;
78366
+ }
78367
+ const res = await globalThis.fetch(endpoint, { headers });
78368
+ if (!res.ok) {
78369
+ throw new Error(`Failed to fetch ECS credentials: ${res.status} ${res.statusText}`);
78370
+ }
78371
+ const data = await res.json();
78372
+ const creds = {
78373
+ accessKeyId: data.AccessKeyId,
78374
+ secretAccessKey: data.SecretAccessKey,
78375
+ sessionToken: data.Token
78376
+ };
78377
+ if (data.Expiration) {
78378
+ this.cachedCredentials = {
78379
+ creds,
78380
+ expiresAt: new Date(data.Expiration).getTime()
78381
+ };
78382
+ }
78383
+ return creds;
78384
+ }
78385
+ };
78386
+ exports2.S3ArtifactSource = S3ArtifactSource;
78387
+ function hmacSha256(key, data) {
78388
+ return crypto6.createHmac("sha256", key).update(data, "utf-8").digest();
78389
+ }
78390
+ function sha256Hex(data) {
78391
+ return crypto6.createHash("sha256").update(data, "utf-8").digest("hex");
78392
+ }
78393
+ function toAmzDate(date) {
78394
+ return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}/, "");
78395
+ }
78396
+ function toDateStamp(date) {
78397
+ return toAmzDate(date).slice(0, 8);
78398
+ }
78399
+ function encodeS3Key(key) {
78400
+ return key.split("/").map((s) => encodeURIComponent(s)).join("/");
78401
+ }
78402
+ function signS3GetRequest(host, path47, region, creds, now) {
78403
+ const amzDate = toAmzDate(now);
78404
+ const dateStamp = toDateStamp(now);
78405
+ const service = "s3";
78406
+ const scope = `${dateStamp}/${region}/${service}/aws4_request`;
78407
+ const headers = {
78408
+ host,
78409
+ "x-amz-date": amzDate,
78410
+ "x-amz-content-sha256": "UNSIGNED-PAYLOAD"
78411
+ };
78412
+ if (creds.sessionToken) {
78413
+ headers["x-amz-security-token"] = creds.sessionToken;
78414
+ }
78415
+ const signedHeaderKeys = Object.keys(headers).sort();
78416
+ const signedHeaders = signedHeaderKeys.join(";");
78417
+ const canonicalHeaders = signedHeaderKeys.map((k) => `${k}:${headers[k]}
78418
+ `).join("");
78419
+ const canonicalRequest = [
78420
+ "GET",
78421
+ path47,
78422
+ "",
78423
+ // no query string
78424
+ canonicalHeaders,
78425
+ signedHeaders,
78426
+ "UNSIGNED-PAYLOAD"
78427
+ ].join("\n");
78428
+ const stringToSign = ["AWS4-HMAC-SHA256", amzDate, scope, sha256Hex(canonicalRequest)].join("\n");
78429
+ const kDate = hmacSha256(`AWS4${creds.secretAccessKey}`, dateStamp);
78430
+ const kRegion = hmacSha256(kDate, region);
78431
+ const kService = hmacSha256(kRegion, service);
78432
+ const kSigning = hmacSha256(kService, "aws4_request");
78433
+ const signature = hmacSha256(kSigning, stringToSign).toString("hex");
78434
+ const authorization = `AWS4-HMAC-SHA256 Credential=${creds.accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
78435
+ return {
78436
+ ...headers,
78437
+ Authorization: authorization
78438
+ };
78439
+ }
78440
+ }
78441
+ });
78442
+
78352
78443
  // ../runtime/dist/index.js
78353
78444
  var require_dist4 = __commonJS({
78354
78445
  "../runtime/dist/index.js"(exports2) {
78355
78446
  "use strict";
78356
78447
  Object.defineProperty(exports2, "__esModule", { value: true });
78357
- exports2.ClefRuntime = exports2.verifySignature = exports2.buildSigningPayload = exports2.VcsArtifactSource = exports2.FileArtifactSource = exports2.HttpArtifactSource = exports2.createKmsProvider = exports2.AwsKmsProvider = exports2.createVcsProvider = exports2.BitbucketProvider = exports2.GitLabProvider = exports2.GitHubProvider = exports2.TelemetryEmitter = exports2.EncryptedArtifactStore = exports2.ArtifactDecryptor = exports2.ArtifactPoller = exports2.AgeDecryptor = exports2.DiskCache = exports2.SecretsCache = void 0;
78448
+ exports2.ClefRuntime = exports2.verifySignature = exports2.buildSigningPayload = exports2.isS3Url = exports2.S3ArtifactSource = exports2.VcsArtifactSource = exports2.FileArtifactSource = exports2.HttpArtifactSource = exports2.createKmsProvider = exports2.AwsKmsProvider = exports2.createVcsProvider = exports2.BitbucketProvider = exports2.GitLabProvider = exports2.GitHubProvider = exports2.TelemetryEmitter = exports2.EncryptedArtifactStore = exports2.ArtifactDecryptor = exports2.ArtifactPoller = exports2.AgeDecryptor = exports2.DiskCache = exports2.SecretsCache = void 0;
78358
78449
  exports2.init = init;
78359
78450
  var secrets_cache_1 = require_secrets_cache();
78360
78451
  Object.defineProperty(exports2, "SecretsCache", { enumerable: true, get: function() {
@@ -78420,6 +78511,13 @@ var require_dist4 = __commonJS({
78420
78511
  Object.defineProperty(exports2, "VcsArtifactSource", { enumerable: true, get: function() {
78421
78512
  return vcs_1.VcsArtifactSource;
78422
78513
  } });
78514
+ var s3_1 = require_s3();
78515
+ Object.defineProperty(exports2, "S3ArtifactSource", { enumerable: true, get: function() {
78516
+ return s3_1.S3ArtifactSource;
78517
+ } });
78518
+ Object.defineProperty(exports2, "isS3Url", { enumerable: true, get: function() {
78519
+ return s3_1.isS3Url;
78520
+ } });
78423
78521
  var signature_1 = require_signature();
78424
78522
  Object.defineProperty(exports2, "buildSigningPayload", { enumerable: true, get: function() {
78425
78523
  return signature_1.buildSigningPayload;
@@ -78435,6 +78533,7 @@ var require_dist4 = __commonJS({
78435
78533
  var vcs_2 = require_vcs2();
78436
78534
  var http_2 = require_http();
78437
78535
  var file_2 = require_file();
78536
+ var s3_2 = require_s3();
78438
78537
  var ClefRuntime = class {
78439
78538
  cache = new secrets_cache_2.SecretsCache();
78440
78539
  poller;
@@ -78528,6 +78627,9 @@ var require_dist4 = __commonJS({
78528
78627
  return new vcs_2.VcsArtifactSource(provider, config.identity, config.environment);
78529
78628
  }
78530
78629
  if (config.source) {
78630
+ if ((0, s3_2.isS3Url)(config.source)) {
78631
+ return new s3_2.S3ArtifactSource(config.source);
78632
+ }
78531
78633
  if (config.source.startsWith("http://") || config.source.startsWith("https://")) {
78532
78634
  return new http_2.HttpArtifactSource(config.source);
78533
78635
  }
@@ -79460,12 +79562,6 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
79460
79562
  }
79461
79563
  fs18.writeFileSync(manifestPath, YAML12.stringify(manifestDoc), "utf-8");
79462
79564
  formatter.success("Created clef.yaml");
79463
- {
79464
- const sopsYamlPath = path21.join(repoRoot, ".sops.yaml");
79465
- const sopsConfig = buildSopsYaml(manifest, repoRoot, publicKey);
79466
- fs18.writeFileSync(sopsYamlPath, YAML12.stringify(sopsConfig), "utf-8");
79467
- formatter.success("Created .sops.yaml");
79468
- }
79469
79565
  const sopsClient = new SopsClient(deps2.runner, ageKeyFile, ageKey);
79470
79566
  const matrixManager = new MatrixManager();
79471
79567
  const cells = matrixManager.resolveMatrix(manifest, repoRoot);
@@ -79543,102 +79639,6 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
79543
79639
  formatter.hint("clef lint \u2014 check repo health");
79544
79640
  formatter.hint("clef ui \u2014 open the web UI");
79545
79641
  }
79546
- function scaffoldSopsConfig(repoRoot) {
79547
- const manifestPath = path21.join(repoRoot, "clef.yaml");
79548
- const parser = new ManifestParser();
79549
- const manifest = parser.parse(manifestPath);
79550
- const sopsYamlPath = path21.join(repoRoot, ".sops.yaml");
79551
- let agePublicKey;
79552
- if (manifest.sops.default_backend === "age") {
79553
- agePublicKey = resolveAgePublicKeyFromEnvOrFile(repoRoot);
79554
- }
79555
- const sopsConfig = buildSopsYaml(manifest, repoRoot, agePublicKey);
79556
- fs18.writeFileSync(sopsYamlPath, YAML12.stringify(sopsConfig), "utf-8");
79557
- }
79558
- function buildSopsYaml(manifest, _repoRoot, agePublicKey) {
79559
- const creationRules = [];
79560
- for (const ns of manifest.namespaces) {
79561
- for (const env of manifest.environments) {
79562
- const pathRegex = `${ns.name}/${env.name}\\.enc\\.yaml$`;
79563
- const rule = { path_regex: pathRegex };
79564
- const backend = env.sops?.backend ?? manifest.sops.default_backend;
79565
- switch (backend) {
79566
- case "age": {
79567
- const envRecipients = resolveRecipientsForEnvironment(manifest, env.name);
79568
- if (envRecipients && envRecipients.length > 0) {
79569
- const keys = envRecipients.map((r) => typeof r === "string" ? r : r.key);
79570
- rule.age = keys.join(",");
79571
- } else if (agePublicKey) {
79572
- rule.age = agePublicKey;
79573
- }
79574
- break;
79575
- }
79576
- case "awskms": {
79577
- const arn = env.sops?.aws_kms_arn ?? manifest.sops.aws_kms_arn;
79578
- if (arn) {
79579
- rule.kms = arn;
79580
- }
79581
- break;
79582
- }
79583
- case "gcpkms": {
79584
- const resourceId = env.sops?.gcp_kms_resource_id ?? manifest.sops.gcp_kms_resource_id;
79585
- if (resourceId) {
79586
- rule.gcp_kms = resourceId;
79587
- }
79588
- break;
79589
- }
79590
- case "azurekv": {
79591
- const kvUrl = env.sops?.azure_kv_url ?? manifest.sops.azure_kv_url;
79592
- if (kvUrl) {
79593
- rule.azure_keyvault = kvUrl;
79594
- }
79595
- break;
79596
- }
79597
- case "pgp": {
79598
- const fingerprint = env.sops?.pgp_fingerprint ?? manifest.sops.pgp_fingerprint;
79599
- if (fingerprint) {
79600
- rule.pgp = fingerprint;
79601
- }
79602
- break;
79603
- }
79604
- }
79605
- creationRules.push(rule);
79606
- }
79607
- }
79608
- return { creation_rules: creationRules };
79609
- }
79610
- function resolveAgePublicKeyFromEnvOrFile(repoRoot) {
79611
- if (process.env.CLEF_AGE_KEY_FILE) {
79612
- const pubKey = extractAgePublicKey(process.env.CLEF_AGE_KEY_FILE);
79613
- if (pubKey) return pubKey;
79614
- }
79615
- if (process.env.CLEF_AGE_KEY) {
79616
- const match = process.env.CLEF_AGE_KEY.match(/# public key: (age1[a-z0-9]+)/);
79617
- if (match) return match[1];
79618
- }
79619
- const clefConfigPath = path21.join(repoRoot, CLEF_DIR, CLEF_CONFIG_FILENAME);
79620
- if (fs18.existsSync(clefConfigPath)) {
79621
- try {
79622
- const config = YAML12.parse(fs18.readFileSync(clefConfigPath, "utf-8"));
79623
- if (config?.age_key_file) {
79624
- const pubKey = extractAgePublicKey(config.age_key_file);
79625
- if (pubKey) return pubKey;
79626
- }
79627
- } catch {
79628
- }
79629
- }
79630
- return void 0;
79631
- }
79632
- function extractAgePublicKey(keyFilePath) {
79633
- try {
79634
- if (!fs18.existsSync(keyFilePath)) return void 0;
79635
- const content = fs18.readFileSync(keyFilePath, "utf-8");
79636
- const match = content.match(/# public key: (age1[a-z0-9]+)/);
79637
- return match ? match[1] : void 0;
79638
- } catch {
79639
- return void 0;
79640
- }
79641
- }
79642
79642
  async function scaffoldRandomValues(ns, manifest, schemaValidator, sopsClient, repoRoot, includeOptional, addCount) {
79643
79643
  let schema;
79644
79644
  try {
@@ -80553,7 +80553,7 @@ async function fetchCheckpoint(config) {
80553
80553
  }
80554
80554
 
80555
80555
  // package.json
80556
- var version = "0.1.11-beta.62";
80556
+ var version = "0.1.11-beta.66";
80557
80557
  var package_default = {
80558
80558
  name: "@clef-sh/cli",
80559
80559
  version,
@@ -81108,15 +81108,11 @@ Usage: clef export payments/production --format env`
81108
81108
  // src/commands/doctor.ts
81109
81109
  var fs21 = __toESM(require("fs"));
81110
81110
  var path34 = __toESM(require("path"));
81111
- var YAML14 = __toESM(require_dist());
81112
81111
  init_src();
81113
81112
  function registerDoctorCommand(program3, deps2) {
81114
81113
  program3.command("doctor").description(
81115
81114
  "Check your environment for required dependencies and configuration.\n\nExit codes:\n 0 All checks pass\n 1 One or more checks failed"
81116
- ).option("--json", "Output the full status as JSON").option(
81117
- "--fix",
81118
- "Attempt to auto-fix issues (runs clef init if .sops.yaml is the only failure)"
81119
- ).action(async (options) => {
81115
+ ).option("--json", "Output the full status as JSON").option("--fix", "Attempt to auto-fix issues").action(async (options) => {
81120
81116
  const repoRoot = program3.opts().dir || process.cwd();
81121
81117
  const clefVersion = program3.version() ?? "unknown";
81122
81118
  const checks = [];
@@ -81167,14 +81163,6 @@ function registerDoctorCommand(program3, deps2) {
81167
81163
  });
81168
81164
  const ageKeyResult = await checkAgeKey(repoRoot, deps2.runner);
81169
81165
  checks.push(ageKeyResult);
81170
- const sopsYamlPath = path34.join(repoRoot, ".sops.yaml");
81171
- const sopsYamlFound = fs21.existsSync(sopsYamlPath);
81172
- checks.push({
81173
- name: ".sops.yaml",
81174
- ok: sopsYamlFound,
81175
- detail: sopsYamlFound ? "found" : "not found",
81176
- hint: sopsYamlFound ? void 0 : "run: clef init"
81177
- });
81178
81166
  const clefignorePath = path34.join(repoRoot, ".clefignore");
81179
81167
  const clefignoreFound = fs21.existsSync(clefignorePath);
81180
81168
  let clefignoreRuleCount = 0;
@@ -81207,25 +81195,7 @@ function registerDoctorCommand(program3, deps2) {
81207
81195
  });
81208
81196
  if (options.fix) {
81209
81197
  const failures2 = checks.filter((c) => !c.ok);
81210
- const onlySopsYamlMissing = failures2.length === 1 && failures2[0].name === ".sops.yaml" && !sopsYamlFound;
81211
- if (onlySopsYamlMissing) {
81212
- formatter.info("Attempting to fix: generating .sops.yaml from manifest...");
81213
- try {
81214
- scaffoldSopsConfig(repoRoot);
81215
- const nowFound = fs21.existsSync(sopsYamlPath);
81216
- if (nowFound) {
81217
- const sopsYamlCheck = checks.find((c) => c.name === ".sops.yaml");
81218
- if (sopsYamlCheck) {
81219
- sopsYamlCheck.ok = true;
81220
- sopsYamlCheck.detail = "found (fixed)";
81221
- delete sopsYamlCheck.hint;
81222
- }
81223
- formatter.success(".sops.yaml created from manifest.");
81224
- }
81225
- } catch {
81226
- formatter.error("Failed to generate .sops.yaml. Run 'clef init' manually to diagnose.");
81227
- }
81228
- } else if (failures2.length > 0) {
81198
+ if (failures2.length > 0) {
81229
81199
  formatter.warn("--fix cannot resolve these issues automatically.");
81230
81200
  }
81231
81201
  }
@@ -81247,14 +81217,8 @@ function registerDoctorCommand(program3, deps2) {
81247
81217
  manifest: { found: manifestFound, ok: manifestFound },
81248
81218
  ageKey: {
81249
81219
  source: ageKeyResult.source,
81250
- recipients: countAgeRecipients(sopsYamlPath),
81251
81220
  ok: ageKeyResult.ok
81252
81221
  },
81253
- sopsYaml: {
81254
- found: checks.find((c) => c.name === ".sops.yaml").ok,
81255
- ok: checks.find((c) => c.name === ".sops.yaml").ok,
81256
- ...!checks.find((c) => c.name === ".sops.yaml").ok ? { fix: "clef init" } : {}
81257
- },
81258
81222
  scanner: {
81259
81223
  clefignoreFound: checks.find((c) => c.name === "scanner")?.ok ?? false,
81260
81224
  ok: checks.find((c) => c.name === "scanner")?.ok ?? false
@@ -81353,30 +81317,6 @@ async function checkAgeKey(repoRoot, runner2) {
81353
81317
  };
81354
81318
  }
81355
81319
  }
81356
- function countAgeRecipients(sopsYamlPath) {
81357
- try {
81358
- if (!fs21.existsSync(sopsYamlPath)) return 0;
81359
- const content = fs21.readFileSync(sopsYamlPath, "utf-8");
81360
- const config = YAML14.parse(content);
81361
- if (!config?.creation_rules || !Array.isArray(config.creation_rules)) {
81362
- return 0;
81363
- }
81364
- const recipients = /* @__PURE__ */ new Set();
81365
- for (const rule of config.creation_rules) {
81366
- if (typeof rule.age === "string") {
81367
- for (const r of rule.age.split(",")) {
81368
- const trimmed = r.trim();
81369
- if (trimmed) {
81370
- recipients.add(trimmed);
81371
- }
81372
- }
81373
- }
81374
- }
81375
- return recipients.size;
81376
- } catch {
81377
- return 0;
81378
- }
81379
- }
81380
81320
  function getSopsInstallHint() {
81381
81321
  if (process.platform === "darwin") return "brew install sops";
81382
81322
  return "see https://github.com/getsops/sops/releases";
@@ -83239,7 +83179,7 @@ function resolveTarget(opts) {
83239
83179
  }
83240
83180
  function registerMigrateBackendCommand(program3, deps2) {
83241
83181
  program3.command("migrate-backend").description(
83242
- "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)"
83182
+ "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)"
83243
83183
  ).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 (opts) => {
83244
83184
  try {
83245
83185
  const repoRoot = program3.opts().dir || process.cwd();
@@ -83287,7 +83227,6 @@ ${sym("working")} Backend migration summary:`);
83287
83227
  dryRun: opts.dryRun,
83288
83228
  skipVerify: opts.skipVerify
83289
83229
  },
83290
- { regenerateSopsConfig: () => scaffoldSopsConfig(repoRoot) },
83291
83230
  (event) => {
83292
83231
  switch (event.type) {
83293
83232
  case "skip":
@@ -83336,7 +83275,7 @@ ${sym("working")} Backend migration summary:`);
83336
83275
  }
83337
83276
  if (!opts.dryRun && result.migratedFiles.length > 0) {
83338
83277
  formatter.hint(
83339
- 'git add clef.yaml .sops.yaml secrets/ && git commit -m "chore: migrate backend to ' + target.backend + '"'
83278
+ 'git add clef.yaml secrets/ && git commit -m "chore: migrate backend to ' + target.backend + '"'
83340
83279
  );
83341
83280
  }
83342
83281
  } catch (err) {