@clef-sh/cli 0.1.7-beta.45 → 0.1.8-beta.52

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
@@ -5882,8 +5882,8 @@ var require_int2 = __commonJS({
5882
5882
  var stringifyNumber = require_stringifyNumber();
5883
5883
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
5884
5884
  function intResolve(str2, offset, radix, { intAsBigInt }) {
5885
- const sign = str2[0];
5886
- if (sign === "-" || sign === "+")
5885
+ const sign2 = str2[0];
5886
+ if (sign2 === "-" || sign2 === "+")
5887
5887
  offset += 1;
5888
5888
  str2 = str2.substring(offset).replace(/_/g, "");
5889
5889
  if (intAsBigInt) {
@@ -5899,10 +5899,10 @@ var require_int2 = __commonJS({
5899
5899
  break;
5900
5900
  }
5901
5901
  const n2 = BigInt(str2);
5902
- return sign === "-" ? BigInt(-1) * n2 : n2;
5902
+ return sign2 === "-" ? BigInt(-1) * n2 : n2;
5903
5903
  }
5904
5904
  const n = parseInt(str2, radix);
5905
- return sign === "-" ? -1 * n : n;
5905
+ return sign2 === "-" ? -1 * n : n;
5906
5906
  }
5907
5907
  function intStringify(node, radix, prefix2) {
5908
5908
  const { value } = node;
@@ -6049,11 +6049,11 @@ var require_timestamp = __commonJS({
6049
6049
  "use strict";
6050
6050
  var stringifyNumber = require_stringifyNumber();
6051
6051
  function parseSexagesimal(str2, asBigInt) {
6052
- const sign = str2[0];
6053
- const parts = sign === "-" || sign === "+" ? str2.substring(1) : str2;
6052
+ const sign2 = str2[0];
6053
+ const parts = sign2 === "-" || sign2 === "+" ? str2.substring(1) : str2;
6054
6054
  const num2 = (n) => asBigInt ? BigInt(n) : Number(n);
6055
6055
  const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num2(60) + num2(p), num2(0));
6056
- return sign === "-" ? num2(-1) * res : res;
6056
+ return sign2 === "-" ? num2(-1) * res : res;
6057
6057
  }
6058
6058
  function stringifySexagesimal(node) {
6059
6059
  let { value } = node;
@@ -6062,9 +6062,9 @@ var require_timestamp = __commonJS({
6062
6062
  num2 = (n) => BigInt(n);
6063
6063
  else if (isNaN(value) || !isFinite(value))
6064
6064
  return stringifyNumber.stringifyNumber(node);
6065
- let sign = "";
6065
+ let sign2 = "";
6066
6066
  if (value < 0) {
6067
- sign = "-";
6067
+ sign2 = "-";
6068
6068
  value *= num2(-1);
6069
6069
  }
6070
6070
  const _60 = num2(60);
@@ -6079,7 +6079,7 @@ var require_timestamp = __commonJS({
6079
6079
  parts.unshift(value);
6080
6080
  }
6081
6081
  }
6082
- return sign + parts.map((n) => String(n).padStart(2, "0")).join(":").replace(/000000\d*$/, "");
6082
+ return sign2 + parts.map((n) => String(n).padStart(2, "0")).join(":").replace(/000000\d*$/, "");
6083
6083
  }
6084
6084
  var intTime = {
6085
6085
  identify: (value) => typeof value === "bigint" || Number.isInteger(value),
@@ -16005,13 +16005,13 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
16005
16005
  }
16006
16006
  return { seed, k2sig };
16007
16007
  }
16008
- function sign(message, secretKey, opts2 = {}) {
16008
+ function sign2(message, secretKey, opts2 = {}) {
16009
16009
  const { seed, k2sig } = prepSig(message, secretKey, opts2);
16010
16010
  const drbg = createHmacDrbg(hash.outputLen, Fn.BYTES, hmac4);
16011
16011
  const sig = drbg(seed, k2sig);
16012
16012
  return sig.toBytes(opts2.format);
16013
16013
  }
16014
- function verify(signature, message, publicKey, opts2 = {}) {
16014
+ function verify2(signature, message, publicKey, opts2 = {}) {
16015
16015
  const { lowS, prehash, format } = validateSigOpts(opts2, defaultSigOpts);
16016
16016
  publicKey = abytes4(publicKey, void 0, "publicKey");
16017
16017
  message = validateMsgAndHash(message, prehash);
@@ -16051,8 +16051,8 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
16051
16051
  utils,
16052
16052
  lengths,
16053
16053
  Point,
16054
- sign,
16055
- verify,
16054
+ sign: sign2,
16055
+ verify: verify2,
16056
16056
  recoverPublicKey,
16057
16057
  Signature,
16058
16058
  hash
@@ -22263,16 +22263,100 @@ var init_resolve = __esm({
22263
22263
  }
22264
22264
  });
22265
22265
 
22266
+ // ../core/src/artifact/signer.ts
22267
+ import * as crypto3 from "crypto";
22268
+ function buildSigningPayload(artifact) {
22269
+ const fields = [
22270
+ "clef-sig-v1",
22271
+ String(artifact.version),
22272
+ artifact.identity,
22273
+ artifact.environment,
22274
+ artifact.revision,
22275
+ artifact.packedAt,
22276
+ artifact.ciphertextHash,
22277
+ [...artifact.keys].sort().join(","),
22278
+ artifact.expiresAt ?? "",
22279
+ artifact.envelope?.provider ?? "",
22280
+ artifact.envelope?.keyId ?? "",
22281
+ artifact.envelope?.wrappedKey ?? "",
22282
+ artifact.envelope?.algorithm ?? ""
22283
+ ];
22284
+ return Buffer.from(fields.join("\n"), "utf-8");
22285
+ }
22286
+ function generateSigningKeyPair() {
22287
+ const pair = crypto3.generateKeyPairSync("ed25519");
22288
+ return {
22289
+ publicKey: pair.publicKey.export({ type: "spki", format: "der" }).toString(
22290
+ "base64"
22291
+ ),
22292
+ privateKey: pair.privateKey.export({ type: "pkcs8", format: "der" }).toString(
22293
+ "base64"
22294
+ )
22295
+ };
22296
+ }
22297
+ function signEd25519(payload, privateKeyBase64) {
22298
+ const keyObj = crypto3.createPrivateKey({
22299
+ key: Buffer.from(privateKeyBase64, "base64"),
22300
+ format: "der",
22301
+ type: "pkcs8"
22302
+ });
22303
+ const signature = crypto3.sign(null, payload, keyObj);
22304
+ return signature.toString("base64");
22305
+ }
22306
+ async function signKms(payload, kms, signingKeyId) {
22307
+ if (!kms.sign) {
22308
+ throw new Error(
22309
+ "KMS provider does not support signing. Ensure the provider implements the sign() method."
22310
+ );
22311
+ }
22312
+ const digest = crypto3.createHash("sha256").update(payload).digest();
22313
+ const signature = await kms.sign(signingKeyId, digest);
22314
+ return signature.toString("base64");
22315
+ }
22316
+ function verifySignature(payload, signatureBase64, publicKeyBase64) {
22317
+ const keyObj = crypto3.createPublicKey({
22318
+ key: Buffer.from(publicKeyBase64, "base64"),
22319
+ format: "der",
22320
+ type: "spki"
22321
+ });
22322
+ const signature = Buffer.from(signatureBase64, "base64");
22323
+ const keyType = keyObj.asymmetricKeyType;
22324
+ if (keyType === "ed25519") {
22325
+ return crypto3.verify(null, payload, keyObj, signature);
22326
+ }
22327
+ if (keyType === "ec") {
22328
+ return crypto3.verify("sha256", payload, keyObj, signature);
22329
+ }
22330
+ throw new Error(`Unsupported key type for signature verification: ${keyType}`);
22331
+ }
22332
+ function detectAlgorithm(publicKeyBase64) {
22333
+ const keyObj = crypto3.createPublicKey({
22334
+ key: Buffer.from(publicKeyBase64, "base64"),
22335
+ format: "der",
22336
+ type: "spki"
22337
+ });
22338
+ const keyType = keyObj.asymmetricKeyType;
22339
+ if (keyType === "ed25519") return "Ed25519";
22340
+ if (keyType === "ec") return "ECDSA_SHA256";
22341
+ throw new Error(`Unsupported key type: ${keyType}`);
22342
+ }
22343
+ var init_signer = __esm({
22344
+ "../core/src/artifact/signer.ts"() {
22345
+ "use strict";
22346
+ }
22347
+ });
22348
+
22266
22349
  // ../core/src/artifact/packer.ts
22267
22350
  import * as fs16 from "fs";
22268
22351
  import * as path18 from "path";
22269
- import * as crypto3 from "crypto";
22352
+ import * as crypto4 from "crypto";
22270
22353
  var ArtifactPacker;
22271
22354
  var init_packer = __esm({
22272
22355
  "../core/src/artifact/packer.ts"() {
22273
22356
  "use strict";
22274
22357
  init_types();
22275
22358
  init_resolve();
22359
+ init_signer();
22276
22360
  ArtifactPacker = class {
22277
22361
  constructor(encryption, matrixManager, kms) {
22278
22362
  this.encryption = encryption;
@@ -22284,6 +22368,11 @@ var init_packer = __esm({
22284
22368
  * values to the service identity's recipient, and write a JSON envelope.
22285
22369
  */
22286
22370
  async pack(config, manifest, repoRoot) {
22371
+ if (config.signingKey && config.signingKmsKeyId) {
22372
+ throw new Error(
22373
+ "Cannot specify both signingKey (Ed25519) and signingKmsKeyId (KMS). Choose one."
22374
+ );
22375
+ }
22287
22376
  const resolved = await resolveIdentitySecrets(
22288
22377
  config.identity,
22289
22378
  config.environment,
@@ -22312,8 +22401,8 @@ var init_packer = __esm({
22312
22401
  }
22313
22402
  const kmsConfig = resolved.envConfig.kms;
22314
22403
  const wrapped = await this.kms.wrap(kmsConfig.keyId, Buffer.from(ephemeralPrivateKey));
22315
- const revision = `${Date.now()}-${crypto3.randomBytes(4).toString("hex")}`;
22316
- const ciphertextHash = crypto3.createHash("sha256").update(ciphertext).digest("hex");
22404
+ const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
22405
+ const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
22317
22406
  artifact = {
22318
22407
  version: 1,
22319
22408
  identity: config.identity,
@@ -22340,8 +22429,8 @@ var init_packer = __esm({
22340
22429
  } catch {
22341
22430
  throw new Error("Failed to age-encrypt artifact. Check recipient key.");
22342
22431
  }
22343
- const revision = `${Date.now()}-${crypto3.randomBytes(4).toString("hex")}`;
22344
- const ciphertextHash = crypto3.createHash("sha256").update(ciphertext).digest("hex");
22432
+ const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
22433
+ const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
22345
22434
  artifact = {
22346
22435
  version: 1,
22347
22436
  identity: config.identity,
@@ -22360,6 +22449,18 @@ var init_packer = __esm({
22360
22449
  if (config.ttl && config.ttl > 0) {
22361
22450
  artifact.expiresAt = new Date(Date.now() + config.ttl * 1e3).toISOString();
22362
22451
  }
22452
+ if (config.signingKey) {
22453
+ const payload = buildSigningPayload(artifact);
22454
+ artifact.signature = signEd25519(payload, config.signingKey);
22455
+ artifact.signatureAlgorithm = "Ed25519";
22456
+ } else if (config.signingKmsKeyId) {
22457
+ if (!this.kms) {
22458
+ throw new Error("KMS provider required for KMS signing but none was provided.");
22459
+ }
22460
+ const payload = buildSigningPayload(artifact);
22461
+ artifact.signature = await signKms(payload, this.kms, config.signingKmsKeyId);
22462
+ artifact.signatureAlgorithm = "ECDSA_SHA256";
22463
+ }
22363
22464
  const json = JSON.stringify(artifact, null, 2);
22364
22465
  const tmpOutput = `${config.outputPath}.tmp.${process.pid}`;
22365
22466
  fs16.writeFileSync(tmpOutput, json, "utf-8");
@@ -22416,15 +22517,18 @@ __export(src_exports, {
22416
22517
  SopsMissingError: () => SopsMissingError,
22417
22518
  SopsVersionError: () => SopsVersionError,
22418
22519
  assertSops: () => assertSops,
22520
+ buildSigningPayload: () => buildSigningPayload,
22419
22521
  checkAll: () => checkAll,
22420
22522
  checkDependency: () => checkDependency,
22421
22523
  collectCIContext: () => collectCIContext,
22422
22524
  deriveAgePublicKey: () => deriveAgePublicKey,
22525
+ detectAlgorithm: () => detectAlgorithm,
22423
22526
  detectFormat: () => detectFormat,
22424
22527
  findRequest: () => findRequest,
22425
22528
  formatAgeKeyFile: () => formatAgeKeyFile,
22426
22529
  generateAgeIdentity: () => generateAgeIdentity,
22427
22530
  generateRandomValue: () => generateRandomValue,
22531
+ generateSigningKeyPair: () => generateSigningKeyPair,
22428
22532
  getPendingKeys: () => getPendingKeys,
22429
22533
  isHighEntropy: () => isHighEntropy,
22430
22534
  isKmsEnvelope: () => isKmsEnvelope,
@@ -22456,8 +22560,11 @@ __export(src_exports, {
22456
22560
  shannonEntropy: () => shannonEntropy,
22457
22561
  shouldIgnoreFile: () => shouldIgnoreFile,
22458
22562
  shouldIgnoreMatch: () => shouldIgnoreMatch,
22563
+ signEd25519: () => signEd25519,
22564
+ signKms: () => signKms,
22459
22565
  upsertRequest: () => upsertRequest,
22460
- validateAgePublicKey: () => validateAgePublicKey
22566
+ validateAgePublicKey: () => validateAgePublicKey,
22567
+ verifySignature: () => verifySignature
22461
22568
  });
22462
22569
  var init_src = __esm({
22463
22570
  "../core/src/index.ts"() {
@@ -22488,6 +22595,7 @@ var init_src = __esm({
22488
22595
  init_manager2();
22489
22596
  init_resolve();
22490
22597
  init_packer();
22598
+ init_signer();
22491
22599
  }
22492
22600
  });
22493
22601
 
@@ -23098,7 +23206,7 @@ var require_supports_color = __commonJS({
23098
23206
  return 1;
23099
23207
  }
23100
23208
  if ("CI" in env) {
23101
- if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
23209
+ if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign2) => sign2 in env) || env.CI_NAME === "codeship") {
23102
23210
  return 1;
23103
23211
  }
23104
23212
  return min;
@@ -38079,16 +38187,16 @@ var require_utils = __commonJS({
38079
38187
  var inflate = options?.inflate !== false;
38080
38188
  var limit = typeof options?.limit !== "number" ? bytes.parse(options?.limit || "100kb") : options?.limit;
38081
38189
  var type = options?.type || defaultType;
38082
- var verify = options?.verify || false;
38190
+ var verify2 = options?.verify || false;
38083
38191
  var defaultCharset = options?.defaultCharset || "utf-8";
38084
- if (verify !== false && typeof verify !== "function") {
38192
+ if (verify2 !== false && typeof verify2 !== "function") {
38085
38193
  throw new TypeError("option verify must be function");
38086
38194
  }
38087
38195
  var shouldParse = typeof type !== "function" ? typeChecker(type) : type;
38088
38196
  return {
38089
38197
  inflate,
38090
38198
  limit,
38091
- verify,
38199
+ verify: verify2,
38092
38200
  defaultCharset,
38093
38201
  shouldParse
38094
38202
  };
@@ -38146,7 +38254,7 @@ var require_read = __commonJS({
38146
38254
  var length;
38147
38255
  var opts2 = options;
38148
38256
  var stream2;
38149
- var verify = opts2.verify;
38257
+ var verify2 = opts2.verify;
38150
38258
  try {
38151
38259
  stream2 = contentstream(req, debug, opts2.inflate);
38152
38260
  length = stream2.length;
@@ -38155,7 +38263,7 @@ var require_read = __commonJS({
38155
38263
  return next(err);
38156
38264
  }
38157
38265
  opts2.length = length;
38158
- opts2.encoding = verify ? null : encoding;
38266
+ opts2.encoding = verify2 ? null : encoding;
38159
38267
  if (opts2.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) {
38160
38268
  return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
38161
38269
  charset: encoding.toLowerCase(),
@@ -38183,10 +38291,10 @@ var require_read = __commonJS({
38183
38291
  });
38184
38292
  return;
38185
38293
  }
38186
- if (verify) {
38294
+ if (verify2) {
38187
38295
  try {
38188
38296
  debug("verify body");
38189
- verify(req, res, body, encoding);
38297
+ verify2(req, res, body, encoding);
38190
38298
  } catch (err) {
38191
38299
  next(createError(403, err, {
38192
38300
  body,
@@ -39137,7 +39245,7 @@ var require_sign = __commonJS({
39137
39245
  "../../node_modules/math-intrinsics/sign.js"(exports, module) {
39138
39246
  "use strict";
39139
39247
  var $isNaN = require_isNaN();
39140
- module.exports = function sign(number) {
39248
+ module.exports = function sign2(number) {
39141
39249
  if ($isNaN(number) || number === 0) {
39142
39250
  return number;
39143
39251
  }
@@ -39501,7 +39609,7 @@ var require_get_intrinsic = __commonJS({
39501
39609
  var min = require_min();
39502
39610
  var pow = require_pow();
39503
39611
  var round = require_round();
39504
- var sign = require_sign();
39612
+ var sign2 = require_sign();
39505
39613
  var $Function = Function;
39506
39614
  var getEvalledConstructor = function(expressionSyntax) {
39507
39615
  try {
@@ -39615,7 +39723,7 @@ var require_get_intrinsic = __commonJS({
39615
39723
  "%Math.min%": min,
39616
39724
  "%Math.pow%": pow,
39617
39725
  "%Math.round%": round,
39618
- "%Math.sign%": sign,
39726
+ "%Math.sign%": sign2,
39619
39727
  "%Reflect.getPrototypeOf%": $ReflectGPO
39620
39728
  };
39621
39729
  if (getProto) {
@@ -41401,14 +41509,14 @@ var require_etag = __commonJS({
41401
41509
  "../../node_modules/etag/index.js"(exports, module) {
41402
41510
  "use strict";
41403
41511
  module.exports = etag;
41404
- var crypto5 = __require("crypto");
41512
+ var crypto6 = __require("crypto");
41405
41513
  var Stats = __require("fs").Stats;
41406
41514
  var toString = Object.prototype.toString;
41407
41515
  function entitytag(entity) {
41408
41516
  if (entity.length === 0) {
41409
41517
  return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"';
41410
41518
  }
41411
- var hash = crypto5.createHash("sha1").update(entity, "utf8").digest("base64").substring(0, 27);
41519
+ var hash = crypto6.createHash("sha1").update(entity, "utf8").digest("base64").substring(0, 27);
41412
41520
  var len = typeof entity === "string" ? Buffer.byteLength(entity, "utf8") : entity.length;
41413
41521
  return '"' + len.toString(16) + "-" + hash + '"';
41414
41522
  }
@@ -63833,17 +63941,17 @@ var require_content_disposition = __commonJS({
63833
63941
  // ../../node_modules/cookie-signature/index.js
63834
63942
  var require_cookie_signature = __commonJS({
63835
63943
  "../../node_modules/cookie-signature/index.js"(exports) {
63836
- var crypto5 = __require("crypto");
63944
+ var crypto6 = __require("crypto");
63837
63945
  exports.sign = function(val, secret) {
63838
63946
  if ("string" != typeof val) throw new TypeError("Cookie value must be provided as a string.");
63839
63947
  if (null == secret) throw new TypeError("Secret key must be provided.");
63840
- return val + "." + crypto5.createHmac("sha256", secret).update(val).digest("base64").replace(/\=+$/, "");
63948
+ return val + "." + crypto6.createHmac("sha256", secret).update(val).digest("base64").replace(/\=+$/, "");
63841
63949
  };
63842
63950
  exports.unsign = function(input, secret) {
63843
63951
  if ("string" != typeof input) throw new TypeError("Signed cookie string must be provided.");
63844
63952
  if (null == secret) throw new TypeError("Secret key must be provided.");
63845
63953
  var tentativeValue = input.slice(0, input.lastIndexOf(".")), expectedInput = exports.sign(tentativeValue, secret), expectedBuffer = Buffer.from(expectedInput), inputBuffer = Buffer.from(input);
63846
- return expectedBuffer.length === inputBuffer.length && crypto5.timingSafeEqual(expectedBuffer, inputBuffer) ? tentativeValue : false;
63954
+ return expectedBuffer.length === inputBuffer.length && crypto6.timingSafeEqual(expectedBuffer, inputBuffer) ? tentativeValue : false;
63847
63955
  };
63848
63956
  }
63849
63957
  });
@@ -74090,7 +74198,7 @@ var require_response = __commonJS({
74090
74198
  var path44 = __require("node:path");
74091
74199
  var pathIsAbsolute = __require("node:path").isAbsolute;
74092
74200
  var statuses = require_statuses();
74093
- var sign = require_cookie_signature().sign;
74201
+ var sign2 = require_cookie_signature().sign;
74094
74202
  var normalizeType = require_utils3().normalizeType;
74095
74203
  var normalizeTypes = require_utils3().normalizeTypes;
74096
74204
  var setCharset = require_utils3().setCharset;
@@ -74381,7 +74489,7 @@ var require_response = __commonJS({
74381
74489
  }
74382
74490
  var val = typeof value === "object" ? "j:" + JSON.stringify(value) : String(value);
74383
74491
  if (signed) {
74384
- val = "s:" + sign(val, secret);
74492
+ val = "s:" + sign2(val, secret);
74385
74493
  }
74386
74494
  if (opts2.maxAge != null) {
74387
74495
  var maxAge = opts2.maxAge - 0;
@@ -75747,9 +75855,8 @@ var require_api = __commonJS({
75747
75855
  }
75748
75856
  res.json({ success: true, key });
75749
75857
  }
75750
- } catch (err) {
75751
- const detail = err instanceof Error ? err.message : String(err);
75752
- res.status(500).json({ error: `Failed to set value: ${detail}`, code: "SET_ERROR" });
75858
+ } catch {
75859
+ res.status(500).json({ error: "Failed to set value", code: "SET_ERROR" });
75753
75860
  }
75754
75861
  });
75755
75862
  router.delete("/namespace/:ns/:env/:key", async (req, res) => {
@@ -76286,7 +76393,7 @@ var require_server = __commonJS({
76286
76393
  const app = (0, express_1.default)();
76287
76394
  const sessionToken = (0, crypto_1.randomBytes)(32).toString("hex");
76288
76395
  app.use(express_1.default.json());
76289
- app.use("/api", (req, res, next) => {
76396
+ app.use((req, res, next) => {
76290
76397
  const host = req.headers.host ?? "";
76291
76398
  const actualPort = req.socket.address()?.port ?? port;
76292
76399
  const allowedHosts = [`127.0.0.1:${actualPort}`, `127.0.0.1:${port}`];
@@ -76712,6 +76819,20 @@ var require_aws = __commonJS({
76712
76819
  }
76713
76820
  return Buffer.from(response.Plaintext);
76714
76821
  }
76822
+ async sign(keyId, digest) {
76823
+ await this.ensureClient();
76824
+ const command = new this.sdk.SignCommand({
76825
+ KeyId: keyId,
76826
+ Message: digest,
76827
+ MessageType: "DIGEST",
76828
+ SigningAlgorithm: "ECDSA_SHA_256"
76829
+ });
76830
+ const response = await this.client.send(command);
76831
+ if (!response.Signature) {
76832
+ throw new Error("AWS KMS Sign returned no signature.");
76833
+ }
76834
+ return Buffer.from(response.Signature);
76835
+ }
76715
76836
  };
76716
76837
  exports.AwsKmsProvider = AwsKmsProvider;
76717
76838
  }
@@ -76925,6 +77046,88 @@ var require_kms = __commonJS({
76925
77046
  }
76926
77047
  });
76927
77048
 
77049
+ // ../runtime/dist/signature.js
77050
+ var require_signature = __commonJS({
77051
+ "../runtime/dist/signature.js"(exports) {
77052
+ "use strict";
77053
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
77054
+ if (k2 === void 0) k2 = k;
77055
+ var desc = Object.getOwnPropertyDescriptor(m, k);
77056
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
77057
+ desc = { enumerable: true, get: function() {
77058
+ return m[k];
77059
+ } };
77060
+ }
77061
+ Object.defineProperty(o, k2, desc);
77062
+ }) : (function(o, m, k, k2) {
77063
+ if (k2 === void 0) k2 = k;
77064
+ o[k2] = m[k];
77065
+ }));
77066
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
77067
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
77068
+ }) : function(o, v) {
77069
+ o["default"] = v;
77070
+ });
77071
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
77072
+ var ownKeys = function(o) {
77073
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
77074
+ var ar = [];
77075
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
77076
+ return ar;
77077
+ };
77078
+ return ownKeys(o);
77079
+ };
77080
+ return function(mod3) {
77081
+ if (mod3 && mod3.__esModule) return mod3;
77082
+ var result = {};
77083
+ if (mod3 != null) {
77084
+ for (var k = ownKeys(mod3), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod3, k[i]);
77085
+ }
77086
+ __setModuleDefault(result, mod3);
77087
+ return result;
77088
+ };
77089
+ })();
77090
+ Object.defineProperty(exports, "__esModule", { value: true });
77091
+ exports.buildSigningPayload = buildSigningPayload2;
77092
+ exports.verifySignature = verifySignature2;
77093
+ var crypto6 = __importStar(__require("crypto"));
77094
+ function buildSigningPayload2(artifact) {
77095
+ const fields = [
77096
+ "clef-sig-v1",
77097
+ String(artifact.version),
77098
+ artifact.identity,
77099
+ artifact.environment,
77100
+ artifact.revision,
77101
+ artifact.packedAt,
77102
+ artifact.ciphertextHash,
77103
+ [...artifact.keys].sort().join(","),
77104
+ artifact.expiresAt ?? "",
77105
+ artifact.envelope?.provider ?? "",
77106
+ artifact.envelope?.keyId ?? "",
77107
+ artifact.envelope?.wrappedKey ?? "",
77108
+ artifact.envelope?.algorithm ?? ""
77109
+ ];
77110
+ return Buffer.from(fields.join("\n"), "utf-8");
77111
+ }
77112
+ function verifySignature2(payload, signatureBase64, publicKeyBase64) {
77113
+ const keyObj = crypto6.createPublicKey({
77114
+ key: Buffer.from(publicKeyBase64, "base64"),
77115
+ format: "der",
77116
+ type: "spki"
77117
+ });
77118
+ const signature = Buffer.from(signatureBase64, "base64");
77119
+ const keyType = keyObj.asymmetricKeyType;
77120
+ if (keyType === "ed25519") {
77121
+ return crypto6.verify(null, payload, keyObj, signature);
77122
+ }
77123
+ if (keyType === "ec") {
77124
+ return crypto6.verify("sha256", payload, keyObj, signature);
77125
+ }
77126
+ throw new Error(`Unsupported key type for signature verification: ${keyType}`);
77127
+ }
77128
+ }
77129
+ });
77130
+
76928
77131
  // ../runtime/dist/poller.js
76929
77132
  var require_poller = __commonJS({
76930
77133
  "../runtime/dist/poller.js"(exports) {
@@ -76968,9 +77171,10 @@ var require_poller = __commonJS({
76968
77171
  })();
76969
77172
  Object.defineProperty(exports, "__esModule", { value: true });
76970
77173
  exports.ArtifactPoller = void 0;
76971
- var crypto5 = __importStar(__require("crypto"));
77174
+ var crypto6 = __importStar(__require("crypto"));
76972
77175
  var decrypt_1 = require_decrypt();
76973
77176
  var kms_1 = require_kms();
77177
+ var signature_1 = require_signature();
76974
77178
  var MIN_POLL_MS = 5e3;
76975
77179
  var ArtifactPoller = class {
76976
77180
  timer = null;
@@ -77086,7 +77290,7 @@ var require_poller = __commonJS({
77086
77290
  }
77087
77291
  if (artifact.revision === this.lastRevision)
77088
77292
  return;
77089
- const hash = crypto5.createHash("sha256").update(artifact.ciphertext).digest("hex");
77293
+ const hash = crypto6.createHash("sha256").update(artifact.ciphertext).digest("hex");
77090
77294
  if (hash !== artifact.ciphertextHash) {
77091
77295
  const err = new Error(`Artifact integrity check failed: expected hash ${artifact.ciphertextHash}, got ${hash}`);
77092
77296
  this.telemetry?.artifactInvalid({
@@ -77095,6 +77299,36 @@ var require_poller = __commonJS({
77095
77299
  });
77096
77300
  throw err;
77097
77301
  }
77302
+ if (this.options.verifyKey) {
77303
+ if (!artifact.signature) {
77304
+ const err = new Error("Artifact signature verification failed: artifact is unsigned but a verify key is configured. Only signed artifacts are accepted when signature verification is enabled.");
77305
+ this.telemetry?.artifactInvalid({
77306
+ reason: "signature_missing",
77307
+ error: err.message
77308
+ });
77309
+ throw err;
77310
+ }
77311
+ const payload = (0, signature_1.buildSigningPayload)(artifact);
77312
+ let valid;
77313
+ try {
77314
+ valid = (0, signature_1.verifySignature)(payload, artifact.signature, this.options.verifyKey);
77315
+ } catch (sigErr) {
77316
+ const err = new Error(`Artifact signature verification error: ${sigErr instanceof Error ? sigErr.message : String(sigErr)}`);
77317
+ this.telemetry?.artifactInvalid({
77318
+ reason: "signature_error",
77319
+ error: err.message
77320
+ });
77321
+ throw err;
77322
+ }
77323
+ if (!valid) {
77324
+ const err = new Error("Artifact signature verification failed: signature does not match the verify key. The artifact may have been tampered with or signed by a different key.");
77325
+ this.telemetry?.artifactInvalid({
77326
+ reason: "signature_invalid",
77327
+ error: err.message
77328
+ });
77329
+ throw err;
77330
+ }
77331
+ }
77098
77332
  let agePrivateKey;
77099
77333
  if (artifact.envelope) {
77100
77334
  try {
@@ -77216,6 +77450,8 @@ var require_poller = __commonJS({
77216
77450
  return "missing_fields";
77217
77451
  if (msg.includes("incomplete envelope"))
77218
77452
  return "incomplete_envelope";
77453
+ if (msg.includes("signature"))
77454
+ return "signature";
77219
77455
  return "unknown";
77220
77456
  }
77221
77457
  }
@@ -77684,7 +77920,7 @@ var require_dist4 = __commonJS({
77684
77920
  "../runtime/dist/index.js"(exports) {
77685
77921
  "use strict";
77686
77922
  Object.defineProperty(exports, "__esModule", { value: true });
77687
- exports.ClefRuntime = exports.VcsArtifactSource = exports.FileArtifactSource = exports.HttpArtifactSource = exports.createKmsProvider = exports.AwsKmsProvider = exports.createVcsProvider = exports.BitbucketProvider = exports.GitLabProvider = exports.GitHubProvider = exports.TelemetryEmitter = exports.ArtifactPoller = exports.AgeDecryptor = exports.DiskCache = exports.SecretsCache = void 0;
77923
+ 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.ArtifactPoller = exports.AgeDecryptor = exports.DiskCache = exports.SecretsCache = void 0;
77688
77924
  exports.init = init;
77689
77925
  var secrets_cache_1 = require_secrets_cache();
77690
77926
  Object.defineProperty(exports, "SecretsCache", { enumerable: true, get: function() {
@@ -77742,6 +77978,13 @@ var require_dist4 = __commonJS({
77742
77978
  Object.defineProperty(exports, "VcsArtifactSource", { enumerable: true, get: function() {
77743
77979
  return vcs_1.VcsArtifactSource;
77744
77980
  } });
77981
+ var signature_1 = require_signature();
77982
+ Object.defineProperty(exports, "buildSigningPayload", { enumerable: true, get: function() {
77983
+ return signature_1.buildSigningPayload;
77984
+ } });
77985
+ Object.defineProperty(exports, "verifySignature", { enumerable: true, get: function() {
77986
+ return signature_1.verifySignature;
77987
+ } });
77745
77988
  var secrets_cache_2 = require_secrets_cache();
77746
77989
  var disk_cache_2 = require_disk_cache();
77747
77990
  var decrypt_2 = require_decrypt();
@@ -77770,7 +78013,8 @@ var require_dist4 = __commonJS({
77770
78013
  cache: this.cache,
77771
78014
  diskCache,
77772
78015
  cacheTtl: config.cacheTtl,
77773
- telemetry: config.telemetry
78016
+ telemetry: config.telemetry,
78017
+ verifyKey: config.verifyKey
77774
78018
  });
77775
78019
  }
77776
78020
  /** Initial fetch + decrypt. Must be called before get/getAll. */
@@ -79336,12 +79580,14 @@ function registerSetCommand(program3, deps2) {
79336
79580
  try {
79337
79581
  await markPendingWithRetry(filePath, [key], "clef set --random");
79338
79582
  } catch {
79339
- formatter.warn(
79583
+ formatter.error(
79340
79584
  `${key} was encrypted but pending state could not be recorded.
79341
- WARNING: The encrypted file contains a random placeholder value.
79585
+ The encrypted file contains a random placeholder value with no tracking metadata.
79342
79586
  This key MUST be set to a real value before deploying.
79343
79587
  Run: clef set ${namespace}/${environment} ${key}`
79344
79588
  );
79589
+ process.exit(1);
79590
+ return;
79345
79591
  }
79346
79592
  formatter.success(`${key} set in ${namespace}/${environment} ${sym("locked")}`);
79347
79593
  formatter.print(
@@ -79385,7 +79631,7 @@ function parseTarget2(target) {
79385
79631
  // src/commands/compare.ts
79386
79632
  init_src();
79387
79633
  import * as path23 from "path";
79388
- import * as crypto4 from "crypto";
79634
+ import * as crypto5 from "crypto";
79389
79635
  function registerCompareCommand(program3, deps2) {
79390
79636
  program3.command("compare <target> <key> [value]").description(
79391
79637
  "Compare a stored secret with a supplied value.\n\n target: namespace/environment (e.g. payments/staging)\n key: the key name to compare\n value: optional \u2014 if omitted, prompts with hidden input\n\nNeither value is ever printed to stdout.\n\nExit codes:\n 0 values match\n 1 values do not match or operation failed"
@@ -79421,7 +79667,7 @@ function registerCompareCommand(program3, deps2) {
79421
79667
  return;
79422
79668
  }
79423
79669
  const stored = decrypted.values[key];
79424
- const match = stored.length === compareValue.length && crypto4.timingSafeEqual(Buffer.from(stored), Buffer.from(compareValue));
79670
+ const match = stored.length === compareValue.length && crypto5.timingSafeEqual(Buffer.from(stored), Buffer.from(compareValue));
79425
79671
  if (match) {
79426
79672
  formatter.success(`${key} ${sym("arrow")} values match`);
79427
79673
  } else {
@@ -79883,7 +80129,7 @@ async function fetchCheckpoint(config) {
79883
80129
  }
79884
80130
 
79885
80131
  // package.json
79886
- var version = "0.1.7-beta.45";
80132
+ var version = "0.1.8-beta.52";
79887
80133
  var package_default = {
79888
80134
  name: "@clef-sh/cli",
79889
80135
  version,
@@ -79982,6 +80228,7 @@ function registerLintCommand(program3, deps2) {
79982
80228
  formatter.raw(JSON.stringify(result, null, 2) + "\n");
79983
80229
  const hasErrors2 = result.issues.some((i) => i.severity === "error");
79984
80230
  process.exit(hasErrors2 ? 1 : 0);
80231
+ return;
79985
80232
  }
79986
80233
  formatLintOutput(result);
79987
80234
  const hasErrors = result.issues.some((i) => i.severity === "error");
@@ -82029,7 +82276,11 @@ Service Identity: ${identity.name}`);
82029
82276
  formatter.error(err.message);
82030
82277
  const partialEntries = Object.entries(err.rotatedKeys);
82031
82278
  const partialBlock = partialEntries.map(([env, key]) => `${env}: ${key}`).join("\n");
82032
- const partialCopied = copyToClipboard(partialBlock);
82279
+ let partialCopied = false;
82280
+ try {
82281
+ partialCopied = copyToClipboard(partialBlock);
82282
+ } catch {
82283
+ }
82033
82284
  if (partialCopied) {
82034
82285
  formatter.warn(
82035
82286
  "Partial rotation succeeded. Rotated keys copied to clipboard \u2014 store them NOW.\n"
@@ -82065,7 +82316,13 @@ import * as path39 from "path";
82065
82316
  function registerPackCommand(program3, deps2) {
82066
82317
  program3.command("pack <identity> <environment>").description(
82067
82318
  "Pack an encrypted artifact for a service identity.\n\n The artifact is a JSON envelope with age-encrypted secrets that can be\n fetched by the Clef agent at runtime from any HTTP URL or local file.\n\nUsage:\n clef pack api-gateway production --output ./artifact.json\n # Then upload with your CI tools:\n # aws s3 cp ./artifact.json s3://my-bucket/clef/api-gateway/production.json"
82068
- ).requiredOption("-o, --output <path>", "Output file path for the artifact JSON").option("--ttl <seconds>", "Artifact TTL \u2014 embeds an expiresAt timestamp in the envelope").action(
82319
+ ).requiredOption("-o, --output <path>", "Output file path for the artifact JSON").option("--ttl <seconds>", "Artifact TTL \u2014 embeds an expiresAt timestamp in the envelope").option(
82320
+ "--signing-key <key>",
82321
+ "Ed25519 private key for artifact signing (base64 DER PKCS8, or env CLEF_SIGNING_KEY)"
82322
+ ).option(
82323
+ "--signing-kms-key <keyId>",
82324
+ "KMS asymmetric signing key ARN/ID (ECDSA_SHA_256, or env CLEF_SIGNING_KMS_KEY)"
82325
+ ).action(
82069
82326
  async (identity, environment, opts2) => {
82070
82327
  try {
82071
82328
  const repoRoot = program3.opts().dir || process.cwd();
@@ -82090,11 +82347,20 @@ function registerPackCommand(program3, deps2) {
82090
82347
  process.exit(1);
82091
82348
  return;
82092
82349
  }
82350
+ const signingKey = opts2.signingKey ?? process.env.CLEF_SIGNING_KEY;
82351
+ const signingKmsKeyId = opts2.signingKmsKey ?? process.env.CLEF_SIGNING_KMS_KEY;
82352
+ if (signingKey && signingKmsKeyId) {
82353
+ formatter.error(
82354
+ "Cannot specify both --signing-key (Ed25519) and --signing-kms-key (KMS). Choose one."
82355
+ );
82356
+ process.exit(1);
82357
+ return;
82358
+ }
82093
82359
  formatter.print(
82094
82360
  `${sym("working")} Packing artifact for '${identity}/${environment}'...`
82095
82361
  );
82096
82362
  const result = await packer.pack(
82097
- { identity, environment, outputPath, ttl },
82363
+ { identity, environment, outputPath, ttl, signingKey, signingKmsKeyId },
82098
82364
  manifest,
82099
82365
  repoRoot
82100
82366
  );
@@ -82107,11 +82373,13 @@ function registerPackCommand(program3, deps2) {
82107
82373
  if (envConfig && isKmsEnvelope(envConfig)) {
82108
82374
  formatter.print(` Envelope: KMS (${envConfig.kms.provider})`);
82109
82375
  }
82110
- formatter.warn(
82111
- "\nThe artifact contains encrypted secrets. Do NOT commit it to version control."
82112
- );
82376
+ if (signingKey) {
82377
+ formatter.print(` Signed: Ed25519`);
82378
+ } else if (signingKmsKeyId) {
82379
+ formatter.print(` Signed: KMS ECDSA_SHA256`);
82380
+ }
82113
82381
  formatter.hint(
82114
- "Upload the artifact to an HTTP-accessible store (S3, GCS, etc.) using your CI tools."
82382
+ "\nUpload the artifact to an HTTP-accessible store (S3, GCS, etc.) or commit to\n .clef/packed/ for VCS-based delivery. See: clef.sh/guide/service-identities"
82115
82383
  );
82116
82384
  } catch (err) {
82117
82385
  if (err instanceof SopsMissingError || err instanceof SopsVersionError) {
@@ -82214,6 +82482,7 @@ function registerDriftCommand(program3, _deps) {
82214
82482
  if (options.json) {
82215
82483
  formatter.raw(JSON.stringify(result, null, 2) + "\n");
82216
82484
  process.exit(result.issues.length > 0 ? 1 : 0);
82485
+ return;
82217
82486
  }
82218
82487
  formatDriftOutput(result);
82219
82488
  process.exit(result.issues.length > 0 ? 1 : 0);