@clef-sh/cli 0.1.8-beta.52 → 0.1.9-beta.57
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/client/assets/index-D7AQh9Sx.js +58 -0
- package/dist/client/favicon-96x96.png +0 -0
- package/dist/client/favicon.ico +0 -0
- package/dist/client/favicon.svg +16 -0
- package/dist/client/index.html +4 -1
- package/dist/index.cjs +911 -741
- package/dist/index.cjs.map +4 -4
- package/dist/index.mjs +907 -737
- package/dist/index.mjs.map +4 -4
- package/package.json +1 -1
- package/dist/client/assets/index-BzdNUhUA.js +0 -58
package/dist/index.cjs
CHANGED
|
@@ -967,7 +967,7 @@ var require_command = __commonJS({
|
|
|
967
967
|
var EventEmitter = require("node:events").EventEmitter;
|
|
968
968
|
var childProcess = require("node:child_process");
|
|
969
969
|
var path44 = require("node:path");
|
|
970
|
-
var
|
|
970
|
+
var fs26 = require("node:fs");
|
|
971
971
|
var process2 = require("node:process");
|
|
972
972
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
973
973
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1900,10 +1900,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1900
1900
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1901
1901
|
function findFile(baseDir, baseName) {
|
|
1902
1902
|
const localBin = path44.resolve(baseDir, baseName);
|
|
1903
|
-
if (
|
|
1903
|
+
if (fs26.existsSync(localBin)) return localBin;
|
|
1904
1904
|
if (sourceExt.includes(path44.extname(baseName))) return void 0;
|
|
1905
1905
|
const foundExt = sourceExt.find(
|
|
1906
|
-
(ext) =>
|
|
1906
|
+
(ext) => fs26.existsSync(`${localBin}${ext}`)
|
|
1907
1907
|
);
|
|
1908
1908
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1909
1909
|
return void 0;
|
|
@@ -1915,7 +1915,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1915
1915
|
if (this._scriptPath) {
|
|
1916
1916
|
let resolvedScriptPath;
|
|
1917
1917
|
try {
|
|
1918
|
-
resolvedScriptPath =
|
|
1918
|
+
resolvedScriptPath = fs26.realpathSync(this._scriptPath);
|
|
1919
1919
|
} catch (err) {
|
|
1920
1920
|
resolvedScriptPath = this._scriptPath;
|
|
1921
1921
|
}
|
|
@@ -9866,14 +9866,14 @@ var require_parser = __commonJS({
|
|
|
9866
9866
|
case "scalar":
|
|
9867
9867
|
case "single-quoted-scalar":
|
|
9868
9868
|
case "double-quoted-scalar": {
|
|
9869
|
-
const
|
|
9869
|
+
const fs26 = this.flowScalar(this.type);
|
|
9870
9870
|
if (atNextItem || it.value) {
|
|
9871
|
-
map.items.push({ start, key:
|
|
9871
|
+
map.items.push({ start, key: fs26, sep: [] });
|
|
9872
9872
|
this.onKeyLine = true;
|
|
9873
9873
|
} else if (it.sep) {
|
|
9874
|
-
this.stack.push(
|
|
9874
|
+
this.stack.push(fs26);
|
|
9875
9875
|
} else {
|
|
9876
|
-
Object.assign(it, { key:
|
|
9876
|
+
Object.assign(it, { key: fs26, sep: [] });
|
|
9877
9877
|
this.onKeyLine = true;
|
|
9878
9878
|
}
|
|
9879
9879
|
return;
|
|
@@ -10001,13 +10001,13 @@ var require_parser = __commonJS({
|
|
|
10001
10001
|
case "scalar":
|
|
10002
10002
|
case "single-quoted-scalar":
|
|
10003
10003
|
case "double-quoted-scalar": {
|
|
10004
|
-
const
|
|
10004
|
+
const fs26 = this.flowScalar(this.type);
|
|
10005
10005
|
if (!it || it.value)
|
|
10006
|
-
fc.items.push({ start: [], key:
|
|
10006
|
+
fc.items.push({ start: [], key: fs26, sep: [] });
|
|
10007
10007
|
else if (it.sep)
|
|
10008
|
-
this.stack.push(
|
|
10008
|
+
this.stack.push(fs26);
|
|
10009
10009
|
else
|
|
10010
|
-
Object.assign(it, { key:
|
|
10010
|
+
Object.assign(it, { key: fs26, sep: [] });
|
|
10011
10011
|
return;
|
|
10012
10012
|
}
|
|
10013
10013
|
case "flow-map-end":
|
|
@@ -10215,7 +10215,7 @@ var require_public_api = __commonJS({
|
|
|
10215
10215
|
}
|
|
10216
10216
|
return doc;
|
|
10217
10217
|
}
|
|
10218
|
-
function
|
|
10218
|
+
function parse15(src, reviver, options) {
|
|
10219
10219
|
let _reviver = void 0;
|
|
10220
10220
|
if (typeof reviver === "function") {
|
|
10221
10221
|
_reviver = reviver;
|
|
@@ -10256,7 +10256,7 @@ var require_public_api = __commonJS({
|
|
|
10256
10256
|
return value.toString(options);
|
|
10257
10257
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
10258
10258
|
}
|
|
10259
|
-
exports2.parse =
|
|
10259
|
+
exports2.parse = parse15;
|
|
10260
10260
|
exports2.parseAllDocuments = parseAllDocuments;
|
|
10261
10261
|
exports2.parseDocument = parseDocument;
|
|
10262
10262
|
exports2.stringify = stringify7;
|
|
@@ -10737,6 +10737,12 @@ var init_parser = __esm({
|
|
|
10737
10737
|
"namespaces"
|
|
10738
10738
|
);
|
|
10739
10739
|
}
|
|
10740
|
+
if (!ENV_NAME_PATTERN.test(nsObj.name)) {
|
|
10741
|
+
throw new ManifestValidationError(
|
|
10742
|
+
`Namespace name '${nsObj.name}' is invalid. Names must start with a lowercase letter and contain only lowercase letters, digits, hyphens, and underscores.`,
|
|
10743
|
+
"namespaces"
|
|
10744
|
+
);
|
|
10745
|
+
}
|
|
10740
10746
|
if (!nsObj.description || typeof nsObj.description !== "string") {
|
|
10741
10747
|
throw new ManifestValidationError(
|
|
10742
10748
|
`Namespace '${nsObj.name}' is missing a 'description' string.`,
|
|
@@ -10837,9 +10843,9 @@ var init_parser = __esm({
|
|
|
10837
10843
|
);
|
|
10838
10844
|
}
|
|
10839
10845
|
const siName = siObj.name;
|
|
10840
|
-
if (
|
|
10846
|
+
if (siObj.description != null && typeof siObj.description !== "string") {
|
|
10841
10847
|
throw new ManifestValidationError(
|
|
10842
|
-
`Service identity '${siName}'
|
|
10848
|
+
`Service identity '${siName}' has a non-string 'description'.`,
|
|
10843
10849
|
"service_identities"
|
|
10844
10850
|
);
|
|
10845
10851
|
}
|
|
@@ -10954,7 +10960,7 @@ var init_parser = __esm({
|
|
|
10954
10960
|
}
|
|
10955
10961
|
return {
|
|
10956
10962
|
name: siName,
|
|
10957
|
-
description: siObj.description,
|
|
10963
|
+
description: siObj.description ?? "",
|
|
10958
10964
|
namespaces: siObj.namespaces,
|
|
10959
10965
|
environments: parsedEnvs
|
|
10960
10966
|
};
|
|
@@ -11155,7 +11161,11 @@ var init_scanner = __esm({
|
|
|
11155
11161
|
init_patterns();
|
|
11156
11162
|
init_ignore();
|
|
11157
11163
|
ALWAYS_SKIP_EXTENSIONS = [".enc.yaml", ".enc.json"];
|
|
11158
|
-
ALWAYS_SKIP_NAMES = [
|
|
11164
|
+
ALWAYS_SKIP_NAMES = [
|
|
11165
|
+
".clef-meta.yaml",
|
|
11166
|
+
".sops.yaml"
|
|
11167
|
+
// contains age public keys and KMS ARNs — configuration, not secrets
|
|
11168
|
+
];
|
|
11159
11169
|
ALWAYS_SKIP_DIRS = ["node_modules", ".git"];
|
|
11160
11170
|
MAX_FILE_SIZE = 1024 * 1024;
|
|
11161
11171
|
ScanRunner = class {
|
|
@@ -11451,15 +11461,36 @@ var init_metadata = __esm({
|
|
|
11451
11461
|
}
|
|
11452
11462
|
});
|
|
11453
11463
|
|
|
11464
|
+
// ../core/src/sops/keys.ts
|
|
11465
|
+
function readSopsKeyNames(filePath) {
|
|
11466
|
+
try {
|
|
11467
|
+
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
11468
|
+
const parsed = YAML3.parse(raw);
|
|
11469
|
+
if (parsed === null || parsed === void 0 || typeof parsed !== "object") return null;
|
|
11470
|
+
return Object.keys(parsed).filter((k) => k !== "sops");
|
|
11471
|
+
} catch {
|
|
11472
|
+
return null;
|
|
11473
|
+
}
|
|
11474
|
+
}
|
|
11475
|
+
var fs5, YAML3;
|
|
11476
|
+
var init_keys = __esm({
|
|
11477
|
+
"../core/src/sops/keys.ts"() {
|
|
11478
|
+
"use strict";
|
|
11479
|
+
fs5 = __toESM(require("fs"));
|
|
11480
|
+
YAML3 = __toESM(require_dist());
|
|
11481
|
+
}
|
|
11482
|
+
});
|
|
11483
|
+
|
|
11454
11484
|
// ../core/src/matrix/manager.ts
|
|
11455
|
-
var
|
|
11485
|
+
var fs6, path4, YAML4, MatrixManager;
|
|
11456
11486
|
var init_manager = __esm({
|
|
11457
11487
|
"../core/src/matrix/manager.ts"() {
|
|
11458
11488
|
"use strict";
|
|
11459
|
-
|
|
11489
|
+
fs6 = __toESM(require("fs"));
|
|
11460
11490
|
path4 = __toESM(require("path"));
|
|
11461
|
-
|
|
11491
|
+
YAML4 = __toESM(require_dist());
|
|
11462
11492
|
init_metadata();
|
|
11493
|
+
init_keys();
|
|
11463
11494
|
MatrixManager = class {
|
|
11464
11495
|
/**
|
|
11465
11496
|
* Build the full grid of {@link MatrixCell} objects from the manifest.
|
|
@@ -11478,7 +11509,7 @@ var init_manager = __esm({
|
|
|
11478
11509
|
namespace: ns.name,
|
|
11479
11510
|
environment: env.name,
|
|
11480
11511
|
filePath,
|
|
11481
|
-
exists:
|
|
11512
|
+
exists: fs6.existsSync(filePath)
|
|
11482
11513
|
});
|
|
11483
11514
|
}
|
|
11484
11515
|
}
|
|
@@ -11502,8 +11533,8 @@ var init_manager = __esm({
|
|
|
11502
11533
|
*/
|
|
11503
11534
|
async scaffoldCell(cell, sopsClient, manifest) {
|
|
11504
11535
|
const dir = path4.dirname(cell.filePath);
|
|
11505
|
-
if (!
|
|
11506
|
-
|
|
11536
|
+
if (!fs6.existsSync(dir)) {
|
|
11537
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
11507
11538
|
}
|
|
11508
11539
|
await sopsClient.encrypt(cell.filePath, {}, manifest, cell.environment);
|
|
11509
11540
|
}
|
|
@@ -11572,22 +11603,15 @@ var init_manager = __esm({
|
|
|
11572
11603
|
* SOPS stores key names in plaintext — only values are encrypted.
|
|
11573
11604
|
*/
|
|
11574
11605
|
readKeyNames(filePath) {
|
|
11575
|
-
|
|
11576
|
-
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
11577
|
-
const parsed = YAML3.parse(raw);
|
|
11578
|
-
if (!parsed || typeof parsed !== "object") return [];
|
|
11579
|
-
return Object.keys(parsed).filter((k) => k !== "sops");
|
|
11580
|
-
} catch {
|
|
11581
|
-
return [];
|
|
11582
|
-
}
|
|
11606
|
+
return readSopsKeyNames(filePath) ?? [];
|
|
11583
11607
|
}
|
|
11584
11608
|
/**
|
|
11585
11609
|
* Read the lastModified timestamp from SOPS metadata without decryption.
|
|
11586
11610
|
*/
|
|
11587
11611
|
readLastModified(filePath) {
|
|
11588
11612
|
try {
|
|
11589
|
-
const raw =
|
|
11590
|
-
const parsed =
|
|
11613
|
+
const raw = fs6.readFileSync(filePath, "utf-8");
|
|
11614
|
+
const parsed = YAML4.parse(raw);
|
|
11591
11615
|
const sops = parsed?.sops;
|
|
11592
11616
|
if (sops?.lastmodified) return new Date(String(sops.lastmodified));
|
|
11593
11617
|
return null;
|
|
@@ -11610,12 +11634,12 @@ var init_manager = __esm({
|
|
|
11610
11634
|
});
|
|
11611
11635
|
|
|
11612
11636
|
// ../core/src/schema/validator.ts
|
|
11613
|
-
var
|
|
11637
|
+
var fs7, YAML5, SchemaValidator;
|
|
11614
11638
|
var init_validator2 = __esm({
|
|
11615
11639
|
"../core/src/schema/validator.ts"() {
|
|
11616
11640
|
"use strict";
|
|
11617
|
-
|
|
11618
|
-
|
|
11641
|
+
fs7 = __toESM(require("fs"));
|
|
11642
|
+
YAML5 = __toESM(require_dist());
|
|
11619
11643
|
init_types();
|
|
11620
11644
|
SchemaValidator = class {
|
|
11621
11645
|
/**
|
|
@@ -11628,13 +11652,13 @@ var init_validator2 = __esm({
|
|
|
11628
11652
|
loadSchema(filePath) {
|
|
11629
11653
|
let raw;
|
|
11630
11654
|
try {
|
|
11631
|
-
raw =
|
|
11655
|
+
raw = fs7.readFileSync(filePath, "utf-8");
|
|
11632
11656
|
} catch {
|
|
11633
11657
|
throw new SchemaLoadError(`Could not read schema file at '${filePath}'.`, filePath);
|
|
11634
11658
|
}
|
|
11635
11659
|
let parsed;
|
|
11636
11660
|
try {
|
|
11637
|
-
parsed =
|
|
11661
|
+
parsed = YAML5.parse(raw);
|
|
11638
11662
|
} catch {
|
|
11639
11663
|
throw new SchemaLoadError(`Schema file '${filePath}' contains invalid YAML.`, filePath);
|
|
11640
11664
|
}
|
|
@@ -11949,11 +11973,11 @@ ${details}`
|
|
|
11949
11973
|
});
|
|
11950
11974
|
|
|
11951
11975
|
// ../core/src/git/integration.ts
|
|
11952
|
-
var
|
|
11976
|
+
var fs8, path7, PRE_COMMIT_HOOK, GitIntegration;
|
|
11953
11977
|
var init_integration = __esm({
|
|
11954
11978
|
"../core/src/git/integration.ts"() {
|
|
11955
11979
|
"use strict";
|
|
11956
|
-
|
|
11980
|
+
fs8 = __toESM(require("fs"));
|
|
11957
11981
|
path7 = __toESM(require("path"));
|
|
11958
11982
|
init_types();
|
|
11959
11983
|
PRE_COMMIT_HOOK = `#!/bin/sh
|
|
@@ -12163,14 +12187,14 @@ exit $EXIT_CODE
|
|
|
12163
12187
|
});
|
|
12164
12188
|
const gitConfig = configResult.exitCode === 0 && configResult.stdout.trim().length > 0;
|
|
12165
12189
|
const attrFilePath = path7.join(repoRoot, ".gitattributes");
|
|
12166
|
-
const attrContent =
|
|
12190
|
+
const attrContent = fs8.existsSync(attrFilePath) ? fs8.readFileSync(attrFilePath, "utf-8") : "";
|
|
12167
12191
|
const gitattributes = attrContent.includes("merge=sops");
|
|
12168
12192
|
return { gitConfig, gitattributes };
|
|
12169
12193
|
}
|
|
12170
12194
|
async ensureGitattributes(repoRoot) {
|
|
12171
12195
|
const attrPath = path7.join(repoRoot, ".gitattributes");
|
|
12172
12196
|
const mergeRule = "*.enc.yaml merge=sops\n*.enc.json merge=sops";
|
|
12173
|
-
const existing =
|
|
12197
|
+
const existing = fs8.existsSync(attrPath) ? fs8.readFileSync(attrPath, "utf-8") : "";
|
|
12174
12198
|
if (existing.includes("merge=sops")) {
|
|
12175
12199
|
return;
|
|
12176
12200
|
}
|
|
@@ -12233,16 +12257,16 @@ function tryBundled() {
|
|
|
12233
12257
|
const packageMain = require.resolve(`${packageName}/package.json`);
|
|
12234
12258
|
const packageDir = path8.dirname(packageMain);
|
|
12235
12259
|
const binPath = path8.join(packageDir, "bin", binName);
|
|
12236
|
-
return
|
|
12260
|
+
return fs9.existsSync(binPath) ? binPath : null;
|
|
12237
12261
|
} catch {
|
|
12238
12262
|
return null;
|
|
12239
12263
|
}
|
|
12240
12264
|
}
|
|
12241
|
-
var
|
|
12265
|
+
var fs9, path8;
|
|
12242
12266
|
var init_bundled = __esm({
|
|
12243
12267
|
"../core/src/sops/bundled.ts"() {
|
|
12244
12268
|
"use strict";
|
|
12245
|
-
|
|
12269
|
+
fs9 = __toESM(require("fs"));
|
|
12246
12270
|
path8 = __toESM(require("path"));
|
|
12247
12271
|
}
|
|
12248
12272
|
});
|
|
@@ -12264,7 +12288,7 @@ function resolveSopsPath() {
|
|
|
12264
12288
|
const envPath = process.env.CLEF_SOPS_PATH?.trim();
|
|
12265
12289
|
if (envPath) {
|
|
12266
12290
|
validateSopsPath(envPath);
|
|
12267
|
-
if (!
|
|
12291
|
+
if (!fs10.existsSync(envPath)) {
|
|
12268
12292
|
throw new Error(`CLEF_SOPS_PATH points to '${envPath}' but the file does not exist.`);
|
|
12269
12293
|
}
|
|
12270
12294
|
cached = { path: envPath, source: "env" };
|
|
@@ -12281,11 +12305,11 @@ function resolveSopsPath() {
|
|
|
12281
12305
|
function resetSopsResolution() {
|
|
12282
12306
|
cached = void 0;
|
|
12283
12307
|
}
|
|
12284
|
-
var
|
|
12308
|
+
var fs10, path9, cached;
|
|
12285
12309
|
var init_resolver = __esm({
|
|
12286
12310
|
"../core/src/sops/resolver.ts"() {
|
|
12287
12311
|
"use strict";
|
|
12288
|
-
|
|
12312
|
+
fs10 = __toESM(require("fs"));
|
|
12289
12313
|
path9 = __toESM(require("path"));
|
|
12290
12314
|
init_bundled();
|
|
12291
12315
|
}
|
|
@@ -19314,14 +19338,14 @@ function openWindowsInputPipe(content) {
|
|
|
19314
19338
|
});
|
|
19315
19339
|
});
|
|
19316
19340
|
}
|
|
19317
|
-
var
|
|
19341
|
+
var fs11, net, import_crypto, YAML6, SopsClient;
|
|
19318
19342
|
var init_client = __esm({
|
|
19319
19343
|
"../core/src/sops/client.ts"() {
|
|
19320
19344
|
"use strict";
|
|
19321
|
-
|
|
19345
|
+
fs11 = __toESM(require("fs"));
|
|
19322
19346
|
net = __toESM(require("net"));
|
|
19323
19347
|
import_crypto = require("crypto");
|
|
19324
|
-
|
|
19348
|
+
YAML6 = __toESM(require_dist());
|
|
19325
19349
|
init_types();
|
|
19326
19350
|
init_checker();
|
|
19327
19351
|
init_keygen();
|
|
@@ -19386,7 +19410,7 @@ var init_client = __esm({
|
|
|
19386
19410
|
}
|
|
19387
19411
|
let parsed;
|
|
19388
19412
|
try {
|
|
19389
|
-
parsed =
|
|
19413
|
+
parsed = YAML6.parse(result.stdout) ?? {};
|
|
19390
19414
|
} catch {
|
|
19391
19415
|
throw new SopsDecryptionError(
|
|
19392
19416
|
`Decrypted content of '${filePath}' is not valid YAML.`,
|
|
@@ -19413,7 +19437,7 @@ var init_client = __esm({
|
|
|
19413
19437
|
async encrypt(filePath, values, manifest, environment) {
|
|
19414
19438
|
await assertSops(this.runner, this.sopsCommand);
|
|
19415
19439
|
const fmt = formatFromPath(filePath);
|
|
19416
|
-
const content = fmt === "json" ? JSON.stringify(values, null, 2) :
|
|
19440
|
+
const content = fmt === "json" ? JSON.stringify(values, null, 2) : YAML6.stringify(values);
|
|
19417
19441
|
const args = this.buildEncryptArgs(filePath, manifest, environment);
|
|
19418
19442
|
const env = this.buildSopsEnv();
|
|
19419
19443
|
let inputArg;
|
|
@@ -19457,7 +19481,7 @@ var init_client = __esm({
|
|
|
19457
19481
|
);
|
|
19458
19482
|
}
|
|
19459
19483
|
try {
|
|
19460
|
-
|
|
19484
|
+
fs11.writeFileSync(filePath, result.stdout);
|
|
19461
19485
|
} catch {
|
|
19462
19486
|
throw new SopsEncryptionError(`Failed to write encrypted data to '${filePath}'.`, filePath);
|
|
19463
19487
|
}
|
|
@@ -19470,21 +19494,7 @@ var init_client = __esm({
|
|
|
19470
19494
|
* @throws {@link SopsEncryptionError} On failure.
|
|
19471
19495
|
*/
|
|
19472
19496
|
async reEncrypt(filePath, newKey) {
|
|
19473
|
-
await
|
|
19474
|
-
const env = this.buildSopsEnv();
|
|
19475
|
-
const result = await this.runner.run(
|
|
19476
|
-
this.sopsCommand,
|
|
19477
|
-
["rotate", "-i", "--add-age", newKey, filePath],
|
|
19478
|
-
{
|
|
19479
|
-
...env ? { env } : {}
|
|
19480
|
-
}
|
|
19481
|
-
);
|
|
19482
|
-
if (result.exitCode !== 0) {
|
|
19483
|
-
throw new SopsEncryptionError(
|
|
19484
|
-
`Failed to re-encrypt '${filePath}': ${result.stderr.trim()}`,
|
|
19485
|
-
filePath
|
|
19486
|
-
);
|
|
19487
|
-
}
|
|
19497
|
+
await this.addRecipient(filePath, newKey);
|
|
19488
19498
|
}
|
|
19489
19499
|
/**
|
|
19490
19500
|
* Add an age recipient to an existing SOPS file.
|
|
@@ -19587,7 +19597,7 @@ var init_client = __esm({
|
|
|
19587
19597
|
if (!this.ageKey && !this.ageKeyFile) return "key-not-found";
|
|
19588
19598
|
let keyContent;
|
|
19589
19599
|
try {
|
|
19590
|
-
keyContent = this.ageKey ??
|
|
19600
|
+
keyContent = this.ageKey ?? fs11.readFileSync(this.ageKeyFile, "utf-8");
|
|
19591
19601
|
} catch {
|
|
19592
19602
|
return "key-not-found";
|
|
19593
19603
|
}
|
|
@@ -19604,7 +19614,7 @@ var init_client = __esm({
|
|
|
19604
19614
|
parseMetadataFromFile(filePath) {
|
|
19605
19615
|
let content;
|
|
19606
19616
|
try {
|
|
19607
|
-
content =
|
|
19617
|
+
content = fs11.readFileSync(filePath, "utf-8");
|
|
19608
19618
|
} catch {
|
|
19609
19619
|
throw new SopsDecryptionError(
|
|
19610
19620
|
`Could not read file '${filePath}' to extract SOPS metadata.`,
|
|
@@ -19613,7 +19623,7 @@ var init_client = __esm({
|
|
|
19613
19623
|
}
|
|
19614
19624
|
let parsed;
|
|
19615
19625
|
try {
|
|
19616
|
-
parsed =
|
|
19626
|
+
parsed = YAML6.parse(content);
|
|
19617
19627
|
} catch {
|
|
19618
19628
|
throw new SopsDecryptionError(
|
|
19619
19629
|
`File '${filePath}' is not valid YAML. Cannot extract SOPS metadata.`,
|
|
@@ -20080,7 +20090,7 @@ function detectFormat(filePath, content) {
|
|
|
20080
20090
|
} catch {
|
|
20081
20091
|
}
|
|
20082
20092
|
try {
|
|
20083
|
-
const parsed =
|
|
20093
|
+
const parsed = YAML7.parse(content);
|
|
20084
20094
|
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
20085
20095
|
return "yaml";
|
|
20086
20096
|
}
|
|
@@ -20161,7 +20171,7 @@ function parseJson(content) {
|
|
|
20161
20171
|
function parseYaml(content) {
|
|
20162
20172
|
let parsed;
|
|
20163
20173
|
try {
|
|
20164
|
-
parsed =
|
|
20174
|
+
parsed = YAML7.parse(content);
|
|
20165
20175
|
} catch (err) {
|
|
20166
20176
|
throw new Error(`Invalid YAML: ${err.message}`);
|
|
20167
20177
|
}
|
|
@@ -20195,7 +20205,7 @@ function parseYaml(content) {
|
|
|
20195
20205
|
}
|
|
20196
20206
|
return { pairs, format: "yaml", skipped, warnings };
|
|
20197
20207
|
}
|
|
20198
|
-
function
|
|
20208
|
+
function parse8(content, format, filePath) {
|
|
20199
20209
|
const resolved = format === "auto" ? detectFormat(filePath ?? "", content) : format;
|
|
20200
20210
|
switch (resolved) {
|
|
20201
20211
|
case "dotenv":
|
|
@@ -20206,12 +20216,12 @@ function parse7(content, format, filePath) {
|
|
|
20206
20216
|
return parseYaml(content);
|
|
20207
20217
|
}
|
|
20208
20218
|
}
|
|
20209
|
-
var path11,
|
|
20219
|
+
var path11, YAML7;
|
|
20210
20220
|
var init_parsers = __esm({
|
|
20211
20221
|
"../core/src/import/parsers.ts"() {
|
|
20212
20222
|
"use strict";
|
|
20213
20223
|
path11 = __toESM(require("path"));
|
|
20214
|
-
|
|
20224
|
+
YAML7 = __toESM(require_dist());
|
|
20215
20225
|
}
|
|
20216
20226
|
});
|
|
20217
20227
|
|
|
@@ -20242,7 +20252,7 @@ var init_import = __esm({
|
|
|
20242
20252
|
repoRoot,
|
|
20243
20253
|
manifest.file_pattern.replace("{namespace}", ns).replace("{environment}", env)
|
|
20244
20254
|
);
|
|
20245
|
-
const parsed =
|
|
20255
|
+
const parsed = parse8(content, options.format ?? "auto", sourcePath ?? "");
|
|
20246
20256
|
let candidates = Object.entries(parsed.pairs);
|
|
20247
20257
|
if (options.prefix) {
|
|
20248
20258
|
const prefix = options.prefix;
|
|
@@ -20320,12 +20330,12 @@ function toRecipient(entry) {
|
|
|
20320
20330
|
}
|
|
20321
20331
|
function readManifestYaml(repoRoot) {
|
|
20322
20332
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20323
|
-
const raw =
|
|
20324
|
-
return
|
|
20333
|
+
const raw = fs12.readFileSync(manifestPath, "utf-8");
|
|
20334
|
+
return YAML8.parse(raw);
|
|
20325
20335
|
}
|
|
20326
20336
|
function writeManifestYaml(repoRoot, doc) {
|
|
20327
20337
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20328
|
-
|
|
20338
|
+
fs12.writeFileSync(manifestPath, YAML8.stringify(doc), "utf-8");
|
|
20329
20339
|
}
|
|
20330
20340
|
function getRecipientsArray(doc) {
|
|
20331
20341
|
const sops = doc.sops;
|
|
@@ -20373,13 +20383,13 @@ function ensureEnvironmentRecipientsArray(doc, envName) {
|
|
|
20373
20383
|
}
|
|
20374
20384
|
return env.recipients;
|
|
20375
20385
|
}
|
|
20376
|
-
var
|
|
20386
|
+
var fs12, path13, YAML8, RecipientManager;
|
|
20377
20387
|
var init_recipients = __esm({
|
|
20378
20388
|
"../core/src/recipients/index.ts"() {
|
|
20379
20389
|
"use strict";
|
|
20380
|
-
|
|
20390
|
+
fs12 = __toESM(require("fs"));
|
|
20381
20391
|
path13 = __toESM(require("path"));
|
|
20382
|
-
|
|
20392
|
+
YAML8 = __toESM(require_dist());
|
|
20383
20393
|
init_validator();
|
|
20384
20394
|
init_parser();
|
|
20385
20395
|
RecipientManager = class {
|
|
@@ -20435,7 +20445,7 @@ var init_recipients = __esm({
|
|
|
20435
20445
|
throw new Error(`Recipient '${keyPreview(normalizedKey)}' is already present.`);
|
|
20436
20446
|
}
|
|
20437
20447
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20438
|
-
const manifestBackup =
|
|
20448
|
+
const manifestBackup = fs12.readFileSync(manifestPath, "utf-8");
|
|
20439
20449
|
const recipients = environment ? ensureEnvironmentRecipientsArray(doc, environment) : ensureRecipientsArray(doc);
|
|
20440
20450
|
if (label) {
|
|
20441
20451
|
recipients.push({ key: normalizedKey, label });
|
|
@@ -20450,16 +20460,16 @@ var init_recipients = __esm({
|
|
|
20450
20460
|
const fileBackups = /* @__PURE__ */ new Map();
|
|
20451
20461
|
for (const cell of cells) {
|
|
20452
20462
|
try {
|
|
20453
|
-
fileBackups.set(cell.filePath,
|
|
20463
|
+
fileBackups.set(cell.filePath, fs12.readFileSync(cell.filePath, "utf-8"));
|
|
20454
20464
|
await this.encryption.addRecipient(cell.filePath, normalizedKey);
|
|
20455
20465
|
reEncryptedFiles.push(cell.filePath);
|
|
20456
20466
|
} catch {
|
|
20457
20467
|
failedFiles.push(cell.filePath);
|
|
20458
|
-
|
|
20468
|
+
fs12.writeFileSync(manifestPath, manifestBackup, "utf-8");
|
|
20459
20469
|
for (const reEncryptedFile of reEncryptedFiles) {
|
|
20460
20470
|
const backup = fileBackups.get(reEncryptedFile);
|
|
20461
20471
|
if (backup) {
|
|
20462
|
-
|
|
20472
|
+
fs12.writeFileSync(reEncryptedFile, backup, "utf-8");
|
|
20463
20473
|
}
|
|
20464
20474
|
}
|
|
20465
20475
|
const restoredDoc = readManifestYaml(repoRoot);
|
|
@@ -20513,7 +20523,7 @@ var init_recipients = __esm({
|
|
|
20513
20523
|
}
|
|
20514
20524
|
const removedEntry = parsed[matchIndex];
|
|
20515
20525
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20516
|
-
const manifestBackup =
|
|
20526
|
+
const manifestBackup = fs12.readFileSync(manifestPath, "utf-8");
|
|
20517
20527
|
const recipients = environment ? ensureEnvironmentRecipientsArray(doc, environment) : ensureRecipientsArray(doc);
|
|
20518
20528
|
recipients.splice(matchIndex, 1);
|
|
20519
20529
|
writeManifestYaml(repoRoot, doc);
|
|
@@ -20524,16 +20534,16 @@ var init_recipients = __esm({
|
|
|
20524
20534
|
const fileBackups = /* @__PURE__ */ new Map();
|
|
20525
20535
|
for (const cell of cells) {
|
|
20526
20536
|
try {
|
|
20527
|
-
fileBackups.set(cell.filePath,
|
|
20537
|
+
fileBackups.set(cell.filePath, fs12.readFileSync(cell.filePath, "utf-8"));
|
|
20528
20538
|
await this.encryption.removeRecipient(cell.filePath, trimmedKey);
|
|
20529
20539
|
reEncryptedFiles.push(cell.filePath);
|
|
20530
20540
|
} catch {
|
|
20531
20541
|
failedFiles.push(cell.filePath);
|
|
20532
|
-
|
|
20542
|
+
fs12.writeFileSync(manifestPath, manifestBackup, "utf-8");
|
|
20533
20543
|
for (const reEncryptedFile of reEncryptedFiles) {
|
|
20534
20544
|
const backup = fileBackups.get(reEncryptedFile);
|
|
20535
20545
|
if (backup) {
|
|
20536
|
-
|
|
20546
|
+
fs12.writeFileSync(reEncryptedFile, backup, "utf-8");
|
|
20537
20547
|
}
|
|
20538
20548
|
}
|
|
20539
20549
|
const restoredDoc = readManifestYaml(repoRoot);
|
|
@@ -20575,9 +20585,9 @@ function requestsFilePath(repoRoot) {
|
|
|
20575
20585
|
function loadRequests(repoRoot) {
|
|
20576
20586
|
const filePath = requestsFilePath(repoRoot);
|
|
20577
20587
|
try {
|
|
20578
|
-
if (!
|
|
20579
|
-
const content =
|
|
20580
|
-
const parsed =
|
|
20588
|
+
if (!fs13.existsSync(filePath)) return [];
|
|
20589
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
20590
|
+
const parsed = YAML9.parse(content);
|
|
20581
20591
|
if (!parsed || !Array.isArray(parsed.requests)) return [];
|
|
20582
20592
|
return parsed.requests.map((r) => ({
|
|
20583
20593
|
key: r.key,
|
|
@@ -20593,7 +20603,7 @@ function saveRequests(repoRoot, requests) {
|
|
|
20593
20603
|
const filePath = requestsFilePath(repoRoot);
|
|
20594
20604
|
if (requests.length === 0) {
|
|
20595
20605
|
try {
|
|
20596
|
-
|
|
20606
|
+
fs13.unlinkSync(filePath);
|
|
20597
20607
|
} catch {
|
|
20598
20608
|
}
|
|
20599
20609
|
return;
|
|
@@ -20609,7 +20619,7 @@ function saveRequests(repoRoot, requests) {
|
|
|
20609
20619
|
return raw;
|
|
20610
20620
|
})
|
|
20611
20621
|
};
|
|
20612
|
-
|
|
20622
|
+
fs13.writeFileSync(filePath, HEADER_COMMENT2 + YAML9.stringify(data), "utf-8");
|
|
20613
20623
|
}
|
|
20614
20624
|
function upsertRequest(repoRoot, key, label, environment) {
|
|
20615
20625
|
const requests = loadRequests(repoRoot);
|
|
@@ -20643,28 +20653,27 @@ function findInList(requests, identifier) {
|
|
|
20643
20653
|
const byKey = requests.find((r) => r.key === identifier);
|
|
20644
20654
|
return byKey ?? null;
|
|
20645
20655
|
}
|
|
20646
|
-
var
|
|
20656
|
+
var fs13, path14, YAML9, REQUESTS_FILENAME, HEADER_COMMENT2;
|
|
20647
20657
|
var init_requests = __esm({
|
|
20648
20658
|
"../core/src/recipients/requests.ts"() {
|
|
20649
20659
|
"use strict";
|
|
20650
|
-
|
|
20660
|
+
fs13 = __toESM(require("fs"));
|
|
20651
20661
|
path14 = __toESM(require("path"));
|
|
20652
|
-
|
|
20662
|
+
YAML9 = __toESM(require_dist());
|
|
20653
20663
|
REQUESTS_FILENAME = ".clef-requests.yaml";
|
|
20654
20664
|
HEADER_COMMENT2 = "# Pending recipient access requests. Approve with: clef recipients approve <label>\n";
|
|
20655
20665
|
}
|
|
20656
20666
|
});
|
|
20657
20667
|
|
|
20658
20668
|
// ../core/src/drift/detector.ts
|
|
20659
|
-
var
|
|
20669
|
+
var path15, DriftDetector;
|
|
20660
20670
|
var init_detector = __esm({
|
|
20661
20671
|
"../core/src/drift/detector.ts"() {
|
|
20662
20672
|
"use strict";
|
|
20663
|
-
fs13 = __toESM(require("fs"));
|
|
20664
20673
|
path15 = __toESM(require("path"));
|
|
20665
|
-
YAML9 = __toESM(require_dist());
|
|
20666
20674
|
init_parser();
|
|
20667
20675
|
init_manager();
|
|
20676
|
+
init_keys();
|
|
20668
20677
|
DriftDetector = class {
|
|
20669
20678
|
parser = new ManifestParser();
|
|
20670
20679
|
matrix = new MatrixManager();
|
|
@@ -20692,45 +20701,30 @@ var init_detector = __esm({
|
|
|
20692
20701
|
}
|
|
20693
20702
|
const issues = [];
|
|
20694
20703
|
let namespacesClean = 0;
|
|
20704
|
+
const remoteEnvSet = new Set(remoteEnvNames);
|
|
20705
|
+
const sharedEnvSet = new Set(localEnvNames.filter((e) => remoteEnvSet.has(e)));
|
|
20695
20706
|
for (const ns of sharedNamespaces) {
|
|
20696
|
-
const
|
|
20697
|
-
const
|
|
20698
|
-
const localNsCells = localCells.filter((c) => c.namespace === ns);
|
|
20699
|
-
for (const cell of localNsCells) {
|
|
20700
|
-
const keys = this.readKeysFromFile(cell.filePath);
|
|
20701
|
-
if (keys === null) continue;
|
|
20702
|
-
allEnvs.add(cell.environment);
|
|
20703
|
-
for (const key of keys) {
|
|
20704
|
-
if (!keyEnvs.has(key)) keyEnvs.set(key, /* @__PURE__ */ new Set());
|
|
20705
|
-
keyEnvs.get(key).add(cell.environment);
|
|
20706
|
-
}
|
|
20707
|
-
}
|
|
20708
|
-
const remoteNsCells = remoteCells.filter((c) => c.namespace === ns);
|
|
20709
|
-
for (const cell of remoteNsCells) {
|
|
20710
|
-
const keys = this.readKeysFromFile(cell.filePath);
|
|
20711
|
-
if (keys === null) continue;
|
|
20712
|
-
allEnvs.add(cell.environment);
|
|
20713
|
-
for (const key of keys) {
|
|
20714
|
-
if (!keyEnvs.has(key)) keyEnvs.set(key, /* @__PURE__ */ new Set());
|
|
20715
|
-
keyEnvs.get(key).add(cell.environment);
|
|
20716
|
-
}
|
|
20717
|
-
}
|
|
20718
|
-
const envList = [...allEnvs];
|
|
20707
|
+
const localKeyEnvs = this.collectKeyEnvs(localCells, ns, sharedEnvSet);
|
|
20708
|
+
const remoteKeyEnvs = this.collectKeyEnvs(remoteCells, ns, sharedEnvSet);
|
|
20719
20709
|
let nsClean = true;
|
|
20720
|
-
|
|
20721
|
-
const
|
|
20722
|
-
|
|
20723
|
-
|
|
20724
|
-
|
|
20725
|
-
|
|
20726
|
-
|
|
20727
|
-
|
|
20728
|
-
|
|
20729
|
-
|
|
20730
|
-
|
|
20731
|
-
|
|
20710
|
+
const reportDrift = (sourceMap, targetMap, direction) => {
|
|
20711
|
+
for (const [key, sourceEnvs] of sourceMap) {
|
|
20712
|
+
const targetEnvs = targetMap.get(key);
|
|
20713
|
+
const missingFrom = [...sourceEnvs].filter((e) => !targetEnvs?.has(e)).sort();
|
|
20714
|
+
if (missingFrom.length > 0) {
|
|
20715
|
+
nsClean = false;
|
|
20716
|
+
issues.push({
|
|
20717
|
+
namespace: ns,
|
|
20718
|
+
key,
|
|
20719
|
+
presentIn: [...sourceEnvs].sort(),
|
|
20720
|
+
missingFrom,
|
|
20721
|
+
message: `Key '${key}' in namespace '${ns}' exists in ${direction} [${[...sourceEnvs].sort().join(", ")}] but is missing from [${missingFrom.join(", ")}]`
|
|
20722
|
+
});
|
|
20723
|
+
}
|
|
20732
20724
|
}
|
|
20733
|
-
}
|
|
20725
|
+
};
|
|
20726
|
+
reportDrift(remoteKeyEnvs, localKeyEnvs, "remote");
|
|
20727
|
+
reportDrift(localKeyEnvs, remoteKeyEnvs, "local");
|
|
20734
20728
|
if (nsClean) namespacesClean++;
|
|
20735
20729
|
}
|
|
20736
20730
|
return {
|
|
@@ -20741,22 +20735,18 @@ var init_detector = __esm({
|
|
|
20741
20735
|
remoteEnvironments: remoteEnvNames
|
|
20742
20736
|
};
|
|
20743
20737
|
}
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
|
|
20749
|
-
|
|
20750
|
-
|
|
20751
|
-
|
|
20752
|
-
|
|
20753
|
-
|
|
20754
|
-
const parsed = YAML9.parse(raw);
|
|
20755
|
-
if (parsed === null || parsed === void 0 || typeof parsed !== "object") return null;
|
|
20756
|
-
return Object.keys(parsed).filter((k) => k !== "sops");
|
|
20757
|
-
} catch {
|
|
20758
|
-
return null;
|
|
20738
|
+
collectKeyEnvs(cells, ns, sharedEnvSet) {
|
|
20739
|
+
const keyEnvs = /* @__PURE__ */ new Map();
|
|
20740
|
+
for (const cell of cells) {
|
|
20741
|
+
if (cell.namespace !== ns || !sharedEnvSet.has(cell.environment)) continue;
|
|
20742
|
+
const keys = readSopsKeyNames(cell.filePath);
|
|
20743
|
+
if (keys === null) continue;
|
|
20744
|
+
for (const key of keys) {
|
|
20745
|
+
if (!keyEnvs.has(key)) keyEnvs.set(key, /* @__PURE__ */ new Set());
|
|
20746
|
+
keyEnvs.get(key).add(cell.environment);
|
|
20747
|
+
}
|
|
20759
20748
|
}
|
|
20749
|
+
return keyEnvs;
|
|
20760
20750
|
}
|
|
20761
20751
|
};
|
|
20762
20752
|
}
|
|
@@ -20902,19 +20892,18 @@ var init_sanitizer = __esm({
|
|
|
20902
20892
|
});
|
|
20903
20893
|
|
|
20904
20894
|
// ../core/src/report/generator.ts
|
|
20905
|
-
var
|
|
20895
|
+
var path16, ReportGenerator;
|
|
20906
20896
|
var init_generator = __esm({
|
|
20907
20897
|
"../core/src/report/generator.ts"() {
|
|
20908
20898
|
"use strict";
|
|
20909
|
-
fs14 = __toESM(require("fs"));
|
|
20910
20899
|
path16 = __toESM(require("path"));
|
|
20911
|
-
YAML10 = __toESM(require_dist());
|
|
20912
20900
|
init_types();
|
|
20913
20901
|
init_parser();
|
|
20914
20902
|
init_runner();
|
|
20915
20903
|
init_metadata();
|
|
20916
20904
|
init_checker();
|
|
20917
20905
|
init_sanitizer();
|
|
20906
|
+
init_keys();
|
|
20918
20907
|
ReportGenerator = class {
|
|
20919
20908
|
constructor(runner2, sopsClient, matrixManager, schemaValidator) {
|
|
20920
20909
|
this.runner = runner2;
|
|
@@ -21084,15 +21073,7 @@ var init_generator = __esm({
|
|
|
21084
21073
|
};
|
|
21085
21074
|
}
|
|
21086
21075
|
readKeyCount(filePath) {
|
|
21087
|
-
|
|
21088
|
-
if (!fs14.existsSync(filePath)) return 0;
|
|
21089
|
-
const raw = fs14.readFileSync(filePath, "utf-8");
|
|
21090
|
-
const parsed = YAML10.parse(raw);
|
|
21091
|
-
if (parsed === null || parsed === void 0 || typeof parsed !== "object") return 0;
|
|
21092
|
-
return Object.keys(parsed).filter((k) => k !== "sops").length;
|
|
21093
|
-
} catch {
|
|
21094
|
-
return 0;
|
|
21095
|
-
}
|
|
21076
|
+
return readSopsKeyNames(filePath)?.length ?? 0;
|
|
21096
21077
|
}
|
|
21097
21078
|
async buildPolicy(manifest, repoRoot) {
|
|
21098
21079
|
try {
|
|
@@ -21459,14 +21440,14 @@ var init_driver = __esm({
|
|
|
21459
21440
|
});
|
|
21460
21441
|
|
|
21461
21442
|
// ../core/src/service-identity/manager.ts
|
|
21462
|
-
var
|
|
21443
|
+
var fs14, os, path17, YAML10, PartialRotationError, ServiceIdentityManager;
|
|
21463
21444
|
var init_manager2 = __esm({
|
|
21464
21445
|
"../core/src/service-identity/manager.ts"() {
|
|
21465
21446
|
"use strict";
|
|
21466
|
-
|
|
21447
|
+
fs14 = __toESM(require("fs"));
|
|
21467
21448
|
os = __toESM(require("os"));
|
|
21468
21449
|
path17 = __toESM(require("path"));
|
|
21469
|
-
|
|
21450
|
+
YAML10 = __toESM(require_dist());
|
|
21470
21451
|
init_types();
|
|
21471
21452
|
init_keygen();
|
|
21472
21453
|
init_parser();
|
|
@@ -21521,8 +21502,8 @@ var init_manager2 = __esm({
|
|
|
21521
21502
|
};
|
|
21522
21503
|
await this.registerRecipients(definition, manifest, repoRoot);
|
|
21523
21504
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
21524
|
-
const raw =
|
|
21525
|
-
const doc =
|
|
21505
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
21506
|
+
const doc = YAML10.parse(raw);
|
|
21526
21507
|
if (!Array.isArray(doc.service_identities)) {
|
|
21527
21508
|
doc.service_identities = [];
|
|
21528
21509
|
}
|
|
@@ -21534,11 +21515,11 @@ var init_manager2 = __esm({
|
|
|
21534
21515
|
});
|
|
21535
21516
|
const tmpCreate = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
21536
21517
|
try {
|
|
21537
|
-
|
|
21538
|
-
|
|
21518
|
+
fs14.writeFileSync(tmpCreate, YAML10.stringify(doc), "utf-8");
|
|
21519
|
+
fs14.renameSync(tmpCreate, manifestPath);
|
|
21539
21520
|
} finally {
|
|
21540
21521
|
try {
|
|
21541
|
-
|
|
21522
|
+
fs14.unlinkSync(tmpCreate);
|
|
21542
21523
|
} catch {
|
|
21543
21524
|
}
|
|
21544
21525
|
}
|
|
@@ -21577,8 +21558,8 @@ var init_manager2 = __esm({
|
|
|
21577
21558
|
}
|
|
21578
21559
|
}
|
|
21579
21560
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
21580
|
-
const raw =
|
|
21581
|
-
const doc =
|
|
21561
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
21562
|
+
const doc = YAML10.parse(raw);
|
|
21582
21563
|
const identities = doc.service_identities;
|
|
21583
21564
|
if (Array.isArray(identities)) {
|
|
21584
21565
|
doc.service_identities = identities.filter(
|
|
@@ -21587,11 +21568,11 @@ var init_manager2 = __esm({
|
|
|
21587
21568
|
}
|
|
21588
21569
|
const tmp = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
21589
21570
|
try {
|
|
21590
|
-
|
|
21591
|
-
|
|
21571
|
+
fs14.writeFileSync(tmp, YAML10.stringify(doc), "utf-8");
|
|
21572
|
+
fs14.renameSync(tmp, manifestPath);
|
|
21592
21573
|
} finally {
|
|
21593
21574
|
try {
|
|
21594
|
-
|
|
21575
|
+
fs14.unlinkSync(tmp);
|
|
21595
21576
|
} catch {
|
|
21596
21577
|
}
|
|
21597
21578
|
}
|
|
@@ -21607,8 +21588,8 @@ var init_manager2 = __esm({
|
|
|
21607
21588
|
throw new Error(`Service identity '${name}' not found.`);
|
|
21608
21589
|
}
|
|
21609
21590
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
21610
|
-
const raw =
|
|
21611
|
-
const doc =
|
|
21591
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
21592
|
+
const doc = YAML10.parse(raw);
|
|
21612
21593
|
const identities = doc.service_identities;
|
|
21613
21594
|
const siDoc = identities.find((si) => si.name === name);
|
|
21614
21595
|
const envs = siDoc.environments;
|
|
@@ -21635,11 +21616,11 @@ var init_manager2 = __esm({
|
|
|
21635
21616
|
}
|
|
21636
21617
|
const tmp = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
21637
21618
|
try {
|
|
21638
|
-
|
|
21639
|
-
|
|
21619
|
+
fs14.writeFileSync(tmp, YAML10.stringify(doc), "utf-8");
|
|
21620
|
+
fs14.renameSync(tmp, manifestPath);
|
|
21640
21621
|
} finally {
|
|
21641
21622
|
try {
|
|
21642
|
-
|
|
21623
|
+
fs14.unlinkSync(tmp);
|
|
21643
21624
|
} catch {
|
|
21644
21625
|
}
|
|
21645
21626
|
}
|
|
@@ -21676,8 +21657,8 @@ var init_manager2 = __esm({
|
|
|
21676
21657
|
throw new Error(`Service identity '${name}' not found.`);
|
|
21677
21658
|
}
|
|
21678
21659
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
21679
|
-
const raw =
|
|
21680
|
-
const doc =
|
|
21660
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
21661
|
+
const doc = YAML10.parse(raw);
|
|
21681
21662
|
const identities = doc.service_identities;
|
|
21682
21663
|
const siDoc = identities.find((si) => si.name === name);
|
|
21683
21664
|
const envs = siDoc.environments;
|
|
@@ -21732,11 +21713,11 @@ var init_manager2 = __esm({
|
|
|
21732
21713
|
}
|
|
21733
21714
|
const tmpRotate = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
21734
21715
|
try {
|
|
21735
|
-
|
|
21736
|
-
|
|
21716
|
+
fs14.writeFileSync(tmpRotate, YAML10.stringify(doc), "utf-8");
|
|
21717
|
+
fs14.renameSync(tmpRotate, manifestPath);
|
|
21737
21718
|
} finally {
|
|
21738
21719
|
try {
|
|
21739
|
-
|
|
21720
|
+
fs14.unlinkSync(tmpRotate);
|
|
21740
21721
|
} catch {
|
|
21741
21722
|
}
|
|
21742
21723
|
}
|
|
@@ -21866,7 +21847,7 @@ var init_resolve = __esm({
|
|
|
21866
21847
|
// ../core/src/artifact/signer.ts
|
|
21867
21848
|
function buildSigningPayload(artifact) {
|
|
21868
21849
|
const fields = [
|
|
21869
|
-
"clef-sig-
|
|
21850
|
+
"clef-sig-v2",
|
|
21870
21851
|
String(artifact.version),
|
|
21871
21852
|
artifact.identity,
|
|
21872
21853
|
artifact.environment,
|
|
@@ -21878,7 +21859,9 @@ function buildSigningPayload(artifact) {
|
|
|
21878
21859
|
artifact.envelope?.provider ?? "",
|
|
21879
21860
|
artifact.envelope?.keyId ?? "",
|
|
21880
21861
|
artifact.envelope?.wrappedKey ?? "",
|
|
21881
|
-
artifact.envelope?.algorithm ?? ""
|
|
21862
|
+
artifact.envelope?.algorithm ?? "",
|
|
21863
|
+
artifact.envelope?.iv ?? "",
|
|
21864
|
+
artifact.envelope?.authTag ?? ""
|
|
21882
21865
|
];
|
|
21883
21866
|
return Buffer.from(fields.join("\n"), "utf-8");
|
|
21884
21867
|
}
|
|
@@ -21948,11 +21931,11 @@ var init_signer = __esm({
|
|
|
21948
21931
|
});
|
|
21949
21932
|
|
|
21950
21933
|
// ../core/src/artifact/packer.ts
|
|
21951
|
-
var
|
|
21934
|
+
var fs15, path18, crypto4, ArtifactPacker;
|
|
21952
21935
|
var init_packer = __esm({
|
|
21953
21936
|
"../core/src/artifact/packer.ts"() {
|
|
21954
21937
|
"use strict";
|
|
21955
|
-
|
|
21938
|
+
fs15 = __toESM(require("fs"));
|
|
21956
21939
|
path18 = __toESM(require("path"));
|
|
21957
21940
|
crypto4 = __toESM(require("crypto"));
|
|
21958
21941
|
init_types();
|
|
@@ -21989,37 +21972,41 @@ var init_packer = __esm({
|
|
|
21989
21972
|
if (!this.kms) {
|
|
21990
21973
|
throw new Error("KMS provider required for envelope encryption but none was provided.");
|
|
21991
21974
|
}
|
|
21992
|
-
const
|
|
21993
|
-
const
|
|
21994
|
-
const ephemeralPublicKey = await identityToRecipient(ephemeralPrivateKey);
|
|
21975
|
+
const dek = crypto4.randomBytes(32);
|
|
21976
|
+
const iv = crypto4.randomBytes(12);
|
|
21995
21977
|
try {
|
|
21996
|
-
const
|
|
21997
|
-
|
|
21998
|
-
|
|
21999
|
-
|
|
22000
|
-
|
|
22001
|
-
|
|
21978
|
+
const cipher = crypto4.createCipheriv("aes-256-gcm", dek, iv);
|
|
21979
|
+
const ciphertextBuf = Buffer.concat([
|
|
21980
|
+
cipher.update(Buffer.from(plaintext, "utf-8")),
|
|
21981
|
+
cipher.final()
|
|
21982
|
+
]);
|
|
21983
|
+
const authTag = cipher.getAuthTag();
|
|
21984
|
+
ciphertext = ciphertextBuf.toString("base64");
|
|
21985
|
+
const kmsConfig = resolved.envConfig.kms;
|
|
21986
|
+
const wrapped = await this.kms.wrap(kmsConfig.keyId, dek);
|
|
21987
|
+
const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
|
|
21988
|
+
const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
|
|
21989
|
+
artifact = {
|
|
21990
|
+
version: 1,
|
|
21991
|
+
identity: config.identity,
|
|
21992
|
+
environment: config.environment,
|
|
21993
|
+
packedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21994
|
+
revision,
|
|
21995
|
+
ciphertextHash,
|
|
21996
|
+
ciphertext,
|
|
21997
|
+
keys: Object.keys(resolved.values),
|
|
21998
|
+
envelope: {
|
|
21999
|
+
provider: kmsConfig.provider,
|
|
22000
|
+
keyId: kmsConfig.keyId,
|
|
22001
|
+
wrappedKey: wrapped.wrappedKey.toString("base64"),
|
|
22002
|
+
algorithm: wrapped.algorithm,
|
|
22003
|
+
iv: iv.toString("base64"),
|
|
22004
|
+
authTag: authTag.toString("base64")
|
|
22005
|
+
}
|
|
22006
|
+
};
|
|
22007
|
+
} finally {
|
|
22008
|
+
dek.fill(0);
|
|
22002
22009
|
}
|
|
22003
|
-
const kmsConfig = resolved.envConfig.kms;
|
|
22004
|
-
const wrapped = await this.kms.wrap(kmsConfig.keyId, Buffer.from(ephemeralPrivateKey));
|
|
22005
|
-
const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
|
|
22006
|
-
const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
|
|
22007
|
-
artifact = {
|
|
22008
|
-
version: 1,
|
|
22009
|
-
identity: config.identity,
|
|
22010
|
-
environment: config.environment,
|
|
22011
|
-
packedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22012
|
-
revision,
|
|
22013
|
-
ciphertextHash,
|
|
22014
|
-
ciphertext,
|
|
22015
|
-
keys: Object.keys(resolved.values),
|
|
22016
|
-
envelope: {
|
|
22017
|
-
provider: kmsConfig.provider,
|
|
22018
|
-
keyId: kmsConfig.keyId,
|
|
22019
|
-
wrappedKey: wrapped.wrappedKey.toString("base64"),
|
|
22020
|
-
algorithm: wrapped.algorithm
|
|
22021
|
-
}
|
|
22022
|
-
};
|
|
22023
22010
|
} else {
|
|
22024
22011
|
try {
|
|
22025
22012
|
const { Encrypter } = await Promise.resolve().then(() => __toESM(require_age_encryption()));
|
|
@@ -22027,8 +22014,10 @@ var init_packer = __esm({
|
|
|
22027
22014
|
e.addRecipient(resolved.recipient);
|
|
22028
22015
|
const encrypted = await e.encrypt(plaintext);
|
|
22029
22016
|
ciphertext = Buffer.from(encrypted).toString("base64");
|
|
22030
|
-
} catch {
|
|
22031
|
-
throw new Error(
|
|
22017
|
+
} catch (err) {
|
|
22018
|
+
throw new Error(
|
|
22019
|
+
`Failed to age-encrypt artifact: ${err instanceof Error ? err.message : String(err)}`
|
|
22020
|
+
);
|
|
22032
22021
|
}
|
|
22033
22022
|
const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
|
|
22034
22023
|
const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
|
|
@@ -22044,8 +22033,8 @@ var init_packer = __esm({
|
|
|
22044
22033
|
};
|
|
22045
22034
|
}
|
|
22046
22035
|
const outputDir = path18.dirname(config.outputPath);
|
|
22047
|
-
if (!
|
|
22048
|
-
|
|
22036
|
+
if (!fs15.existsSync(outputDir)) {
|
|
22037
|
+
fs15.mkdirSync(outputDir, { recursive: true });
|
|
22049
22038
|
}
|
|
22050
22039
|
if (config.ttl && config.ttl > 0) {
|
|
22051
22040
|
artifact.expiresAt = new Date(Date.now() + config.ttl * 1e3).toISOString();
|
|
@@ -22064,8 +22053,8 @@ var init_packer = __esm({
|
|
|
22064
22053
|
}
|
|
22065
22054
|
const json = JSON.stringify(artifact, null, 2);
|
|
22066
22055
|
const tmpOutput = `${config.outputPath}.tmp.${process.pid}`;
|
|
22067
|
-
|
|
22068
|
-
|
|
22056
|
+
fs15.writeFileSync(tmpOutput, json, "utf-8");
|
|
22057
|
+
fs15.renameSync(tmpOutput, config.outputPath);
|
|
22069
22058
|
return {
|
|
22070
22059
|
outputPath: config.outputPath,
|
|
22071
22060
|
namespaceCount: resolved.identity.namespaces.length,
|
|
@@ -22078,6 +22067,23 @@ var init_packer = __esm({
|
|
|
22078
22067
|
}
|
|
22079
22068
|
});
|
|
22080
22069
|
|
|
22070
|
+
// ../core/src/kms/types.ts
|
|
22071
|
+
var VALID_KMS_PROVIDERS;
|
|
22072
|
+
var init_types2 = __esm({
|
|
22073
|
+
"../core/src/kms/types.ts"() {
|
|
22074
|
+
"use strict";
|
|
22075
|
+
VALID_KMS_PROVIDERS = ["aws", "gcp", "azure"];
|
|
22076
|
+
}
|
|
22077
|
+
});
|
|
22078
|
+
|
|
22079
|
+
// ../core/src/kms/index.ts
|
|
22080
|
+
var init_kms = __esm({
|
|
22081
|
+
"../core/src/kms/index.ts"() {
|
|
22082
|
+
"use strict";
|
|
22083
|
+
init_types2();
|
|
22084
|
+
}
|
|
22085
|
+
});
|
|
22086
|
+
|
|
22081
22087
|
// ../core/src/index.ts
|
|
22082
22088
|
var src_exports = {};
|
|
22083
22089
|
__export(src_exports, {
|
|
@@ -22117,6 +22123,7 @@ __export(src_exports, {
|
|
|
22117
22123
|
SopsMergeDriver: () => SopsMergeDriver,
|
|
22118
22124
|
SopsMissingError: () => SopsMissingError,
|
|
22119
22125
|
SopsVersionError: () => SopsVersionError,
|
|
22126
|
+
VALID_KMS_PROVIDERS: () => VALID_KMS_PROVIDERS,
|
|
22120
22127
|
assertSops: () => assertSops,
|
|
22121
22128
|
buildSigningPayload: () => buildSigningPayload,
|
|
22122
22129
|
checkAll: () => checkAll,
|
|
@@ -22143,7 +22150,7 @@ __export(src_exports, {
|
|
|
22143
22150
|
markResolved: () => markResolved,
|
|
22144
22151
|
matchPatterns: () => matchPatterns,
|
|
22145
22152
|
metadataPath: () => metadataPath,
|
|
22146
|
-
parse: () =>
|
|
22153
|
+
parse: () => parse8,
|
|
22147
22154
|
parseDotenv: () => parseDotenv,
|
|
22148
22155
|
parseIgnoreContent: () => parseIgnoreContent,
|
|
22149
22156
|
parseJson: () => parseJson,
|
|
@@ -22197,6 +22204,7 @@ var init_src = __esm({
|
|
|
22197
22204
|
init_resolve();
|
|
22198
22205
|
init_packer();
|
|
22199
22206
|
init_signer();
|
|
22207
|
+
init_kms();
|
|
22200
22208
|
}
|
|
22201
22209
|
});
|
|
22202
22210
|
|
|
@@ -22285,7 +22293,7 @@ var require_ms = __commonJS({
|
|
|
22285
22293
|
options = options || {};
|
|
22286
22294
|
var type = typeof val;
|
|
22287
22295
|
if (type === "string" && val.length > 0) {
|
|
22288
|
-
return
|
|
22296
|
+
return parse15(val);
|
|
22289
22297
|
} else if (type === "number" && isFinite(val)) {
|
|
22290
22298
|
return options.long ? fmtLong(val) : fmtShort(val);
|
|
22291
22299
|
}
|
|
@@ -22293,7 +22301,7 @@ var require_ms = __commonJS({
|
|
|
22293
22301
|
"val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
|
|
22294
22302
|
);
|
|
22295
22303
|
};
|
|
22296
|
-
function
|
|
22304
|
+
function parse15(str2) {
|
|
22297
22305
|
str2 = String(str2);
|
|
22298
22306
|
if (str2.length > 100) {
|
|
22299
22307
|
return;
|
|
@@ -22752,7 +22760,7 @@ var require_has_flag = __commonJS({
|
|
|
22752
22760
|
var require_supports_color = __commonJS({
|
|
22753
22761
|
"../../node_modules/supports-color/index.js"(exports2, module2) {
|
|
22754
22762
|
"use strict";
|
|
22755
|
-
var
|
|
22763
|
+
var os4 = require("os");
|
|
22756
22764
|
var tty = require("tty");
|
|
22757
22765
|
var hasFlag = require_has_flag();
|
|
22758
22766
|
var { env } = process;
|
|
@@ -22800,7 +22808,7 @@ var require_supports_color = __commonJS({
|
|
|
22800
22808
|
return min;
|
|
22801
22809
|
}
|
|
22802
22810
|
if (process.platform === "win32") {
|
|
22803
|
-
const osRelease =
|
|
22811
|
+
const osRelease = os4.release().split(".");
|
|
22804
22812
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
22805
22813
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
22806
22814
|
}
|
|
@@ -23732,7 +23740,7 @@ var require_bytes = __commonJS({
|
|
|
23732
23740
|
"use strict";
|
|
23733
23741
|
module2.exports = bytes;
|
|
23734
23742
|
module2.exports.format = format;
|
|
23735
|
-
module2.exports.parse =
|
|
23743
|
+
module2.exports.parse = parse15;
|
|
23736
23744
|
var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
|
|
23737
23745
|
var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
|
|
23738
23746
|
var map = {
|
|
@@ -23746,7 +23754,7 @@ var require_bytes = __commonJS({
|
|
|
23746
23754
|
var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
|
|
23747
23755
|
function bytes(value, options) {
|
|
23748
23756
|
if (typeof value === "string") {
|
|
23749
|
-
return
|
|
23757
|
+
return parse15(value);
|
|
23750
23758
|
}
|
|
23751
23759
|
if (typeof value === "number") {
|
|
23752
23760
|
return format(value, options);
|
|
@@ -23790,7 +23798,7 @@ var require_bytes = __commonJS({
|
|
|
23790
23798
|
}
|
|
23791
23799
|
return str2 + unitSeparator + unit;
|
|
23792
23800
|
}
|
|
23793
|
-
function
|
|
23801
|
+
function parse15(val) {
|
|
23794
23802
|
if (typeof val === "number" && !isNaN(val)) {
|
|
23795
23803
|
return val;
|
|
23796
23804
|
}
|
|
@@ -27995,7 +28003,7 @@ var require_content_type = __commonJS({
|
|
|
27995
28003
|
var QUOTE_REGEXP = /([\\"])/g;
|
|
27996
28004
|
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
27997
28005
|
exports2.format = format;
|
|
27998
|
-
exports2.parse =
|
|
28006
|
+
exports2.parse = parse15;
|
|
27999
28007
|
function format(obj) {
|
|
28000
28008
|
if (!obj || typeof obj !== "object") {
|
|
28001
28009
|
throw new TypeError("argument obj is required");
|
|
@@ -28019,7 +28027,7 @@ var require_content_type = __commonJS({
|
|
|
28019
28027
|
}
|
|
28020
28028
|
return string;
|
|
28021
28029
|
}
|
|
28022
|
-
function
|
|
28030
|
+
function parse15(string) {
|
|
28023
28031
|
if (!string) {
|
|
28024
28032
|
throw new TypeError("argument string is required");
|
|
28025
28033
|
}
|
|
@@ -37601,7 +37609,7 @@ var require_media_typer = __commonJS({
|
|
|
37601
37609
|
var TYPE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/;
|
|
37602
37610
|
var TYPE_REGEXP = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
|
|
37603
37611
|
exports2.format = format;
|
|
37604
|
-
exports2.parse =
|
|
37612
|
+
exports2.parse = parse15;
|
|
37605
37613
|
exports2.test = test;
|
|
37606
37614
|
function format(obj) {
|
|
37607
37615
|
if (!obj || typeof obj !== "object") {
|
|
@@ -37634,7 +37642,7 @@ var require_media_typer = __commonJS({
|
|
|
37634
37642
|
}
|
|
37635
37643
|
return TYPE_REGEXP.test(string.toLowerCase());
|
|
37636
37644
|
}
|
|
37637
|
-
function
|
|
37645
|
+
function parse15(string) {
|
|
37638
37646
|
if (!string) {
|
|
37639
37647
|
throw new TypeError("argument string is required");
|
|
37640
37648
|
}
|
|
@@ -37820,7 +37828,7 @@ var require_read = __commonJS({
|
|
|
37820
37828
|
var hasBody = require_type_is().hasBody;
|
|
37821
37829
|
var { getCharset } = require_utils();
|
|
37822
37830
|
module2.exports = read;
|
|
37823
|
-
function read(req, res, next,
|
|
37831
|
+
function read(req, res, next, parse15, debug, options) {
|
|
37824
37832
|
if (onFinished.isFinished(req)) {
|
|
37825
37833
|
debug("body already parsed");
|
|
37826
37834
|
next();
|
|
@@ -37908,7 +37916,7 @@ var require_read = __commonJS({
|
|
|
37908
37916
|
try {
|
|
37909
37917
|
debug("parse body");
|
|
37910
37918
|
str2 = typeof body !== "string" && encoding !== null ? iconv.decode(body, encoding) : body;
|
|
37911
|
-
req.body =
|
|
37919
|
+
req.body = parse15(str2, encoding);
|
|
37912
37920
|
} catch (err) {
|
|
37913
37921
|
next(createError(400, err, {
|
|
37914
37922
|
body: str2,
|
|
@@ -37981,7 +37989,7 @@ var require_json = __commonJS({
|
|
|
37981
37989
|
const normalizedOptions = normalizeOptions(options, "application/json");
|
|
37982
37990
|
var reviver = options?.reviver;
|
|
37983
37991
|
var strict = options?.strict !== false;
|
|
37984
|
-
function
|
|
37992
|
+
function parse15(body) {
|
|
37985
37993
|
if (body.length === 0) {
|
|
37986
37994
|
return {};
|
|
37987
37995
|
}
|
|
@@ -38008,7 +38016,7 @@ var require_json = __commonJS({
|
|
|
38008
38016
|
isValidCharset: (charset) => charset.slice(0, 4) === "utf-"
|
|
38009
38017
|
};
|
|
38010
38018
|
return function jsonParser(req, res, next) {
|
|
38011
|
-
read(req, res, next,
|
|
38019
|
+
read(req, res, next, parse15, debug, readOptions);
|
|
38012
38020
|
};
|
|
38013
38021
|
}
|
|
38014
38022
|
function createStrictSyntaxError(str2, char) {
|
|
@@ -40586,11 +40594,11 @@ var require_lib2 = __commonJS({
|
|
|
40586
40594
|
"../../node_modules/qs/lib/index.js"(exports2, module2) {
|
|
40587
40595
|
"use strict";
|
|
40588
40596
|
var stringify7 = require_stringify2();
|
|
40589
|
-
var
|
|
40597
|
+
var parse15 = require_parse();
|
|
40590
40598
|
var formats = require_formats();
|
|
40591
40599
|
module2.exports = {
|
|
40592
40600
|
formats,
|
|
40593
|
-
parse:
|
|
40601
|
+
parse: parse15,
|
|
40594
40602
|
stringify: stringify7
|
|
40595
40603
|
};
|
|
40596
40604
|
}
|
|
@@ -40612,7 +40620,7 @@ var require_urlencoded = __commonJS({
|
|
|
40612
40620
|
throw new TypeError("option defaultCharset must be either utf-8 or iso-8859-1");
|
|
40613
40621
|
}
|
|
40614
40622
|
var queryparse = createQueryParser(options);
|
|
40615
|
-
function
|
|
40623
|
+
function parse15(body, encoding) {
|
|
40616
40624
|
return body.length ? queryparse(body, encoding) : {};
|
|
40617
40625
|
}
|
|
40618
40626
|
const readOptions = {
|
|
@@ -40621,7 +40629,7 @@ var require_urlencoded = __commonJS({
|
|
|
40621
40629
|
isValidCharset: (charset) => charset === "utf-8" || charset === "iso-8859-1"
|
|
40622
40630
|
};
|
|
40623
40631
|
return function urlencodedParser(req, res, next) {
|
|
40624
|
-
read(req, res, next,
|
|
40632
|
+
read(req, res, next, parse15, debug, readOptions);
|
|
40625
40633
|
};
|
|
40626
40634
|
}
|
|
40627
40635
|
function createQueryParser(options) {
|
|
@@ -40805,7 +40813,7 @@ var require_parseurl = __commonJS({
|
|
|
40805
40813
|
"../../node_modules/parseurl/index.js"(exports2, module2) {
|
|
40806
40814
|
"use strict";
|
|
40807
40815
|
var url = require("url");
|
|
40808
|
-
var
|
|
40816
|
+
var parse15 = url.parse;
|
|
40809
40817
|
var Url = url.Url;
|
|
40810
40818
|
module2.exports = parseurl;
|
|
40811
40819
|
module2.exports.original = originalurl;
|
|
@@ -40837,7 +40845,7 @@ var require_parseurl = __commonJS({
|
|
|
40837
40845
|
}
|
|
40838
40846
|
function fastparse(str2) {
|
|
40839
40847
|
if (typeof str2 !== "string" || str2.charCodeAt(0) !== 47) {
|
|
40840
|
-
return
|
|
40848
|
+
return parse15(str2);
|
|
40841
40849
|
}
|
|
40842
40850
|
var pathname = str2;
|
|
40843
40851
|
var query = null;
|
|
@@ -40865,7 +40873,7 @@ var require_parseurl = __commonJS({
|
|
|
40865
40873
|
/* # */
|
|
40866
40874
|
case 160:
|
|
40867
40875
|
case 65279:
|
|
40868
|
-
return
|
|
40876
|
+
return parse15(str2);
|
|
40869
40877
|
}
|
|
40870
40878
|
}
|
|
40871
40879
|
var url2 = Url !== void 0 ? new Url() : {};
|
|
@@ -41017,7 +41025,7 @@ var require_view = __commonJS({
|
|
|
41017
41025
|
"use strict";
|
|
41018
41026
|
var debug = require_src()("express:view");
|
|
41019
41027
|
var path44 = require("node:path");
|
|
41020
|
-
var
|
|
41028
|
+
var fs26 = require("node:fs");
|
|
41021
41029
|
var dirname7 = path44.dirname;
|
|
41022
41030
|
var basename5 = path44.basename;
|
|
41023
41031
|
var extname2 = path44.extname;
|
|
@@ -41097,7 +41105,7 @@ var require_view = __commonJS({
|
|
|
41097
41105
|
function tryStat(path45) {
|
|
41098
41106
|
debug('stat "%s"', path45);
|
|
41099
41107
|
try {
|
|
41100
|
-
return
|
|
41108
|
+
return fs26.statSync(path45);
|
|
41101
41109
|
} catch (e) {
|
|
41102
41110
|
return void 0;
|
|
41103
41111
|
}
|
|
@@ -50661,7 +50669,7 @@ var require_forwarded = __commonJS({
|
|
|
50661
50669
|
if (!req) {
|
|
50662
50670
|
throw new TypeError("argument req is required");
|
|
50663
50671
|
}
|
|
50664
|
-
var proxyAddrs =
|
|
50672
|
+
var proxyAddrs = parse15(req.headers["x-forwarded-for"] || "");
|
|
50665
50673
|
var socketAddr = getSocketAddr(req);
|
|
50666
50674
|
var addrs = [socketAddr].concat(proxyAddrs);
|
|
50667
50675
|
return addrs;
|
|
@@ -50669,7 +50677,7 @@ var require_forwarded = __commonJS({
|
|
|
50669
50677
|
function getSocketAddr(req) {
|
|
50670
50678
|
return req.socket ? req.socket.remoteAddress : req.connection.remoteAddress;
|
|
50671
50679
|
}
|
|
50672
|
-
function
|
|
50680
|
+
function parse15(header) {
|
|
50673
50681
|
var end = header.length;
|
|
50674
50682
|
var list = [];
|
|
50675
50683
|
var start = header.length;
|
|
@@ -51698,7 +51706,7 @@ var require_dist2 = __commonJS({
|
|
|
51698
51706
|
"use strict";
|
|
51699
51707
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
51700
51708
|
exports2.PathError = exports2.TokenData = void 0;
|
|
51701
|
-
exports2.parse =
|
|
51709
|
+
exports2.parse = parse15;
|
|
51702
51710
|
exports2.compile = compile;
|
|
51703
51711
|
exports2.match = match;
|
|
51704
51712
|
exports2.pathToRegexp = pathToRegexp;
|
|
@@ -51744,7 +51752,7 @@ var require_dist2 = __commonJS({
|
|
|
51744
51752
|
}
|
|
51745
51753
|
};
|
|
51746
51754
|
exports2.PathError = PathError;
|
|
51747
|
-
function
|
|
51755
|
+
function parse15(str2, options = {}) {
|
|
51748
51756
|
const { encodePath = NOOP_VALUE } = options;
|
|
51749
51757
|
const chars = [...str2];
|
|
51750
51758
|
const tokens = [];
|
|
@@ -51834,7 +51842,7 @@ var require_dist2 = __commonJS({
|
|
|
51834
51842
|
}
|
|
51835
51843
|
function compile(path44, options = {}) {
|
|
51836
51844
|
const { encode = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
51837
|
-
const data = typeof path44 === "object" ? path44 :
|
|
51845
|
+
const data = typeof path44 === "object" ? path44 : parse15(path44, options);
|
|
51838
51846
|
const fn = tokensToFunction(data.tokens, delimiter, encode);
|
|
51839
51847
|
return function path45(params = {}) {
|
|
51840
51848
|
const [path46, ...missing] = fn(params);
|
|
@@ -51929,7 +51937,7 @@ var require_dist2 = __commonJS({
|
|
|
51929
51937
|
const flags = sensitive ? "" : "i";
|
|
51930
51938
|
const sources = [];
|
|
51931
51939
|
for (const input of pathsToArray(path44, [])) {
|
|
51932
|
-
const data = typeof input === "object" ? input :
|
|
51940
|
+
const data = typeof input === "object" ? input : parse15(input, options);
|
|
51933
51941
|
for (const tokens of flatten(data.tokens, 0, [])) {
|
|
51934
51942
|
sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
|
|
51935
51943
|
}
|
|
@@ -63238,7 +63246,7 @@ var require_request = __commonJS({
|
|
|
63238
63246
|
var http = require("node:http");
|
|
63239
63247
|
var fresh = require_fresh();
|
|
63240
63248
|
var parseRange = require_range_parser();
|
|
63241
|
-
var
|
|
63249
|
+
var parse15 = require_parseurl();
|
|
63242
63250
|
var proxyaddr = require_proxy_addr();
|
|
63243
63251
|
var req = Object.create(http.IncomingMessage.prototype);
|
|
63244
63252
|
module2.exports = req;
|
|
@@ -63283,7 +63291,7 @@ var require_request = __commonJS({
|
|
|
63283
63291
|
if (!queryparse) {
|
|
63284
63292
|
return /* @__PURE__ */ Object.create(null);
|
|
63285
63293
|
}
|
|
63286
|
-
var querystring =
|
|
63294
|
+
var querystring = parse15(this).query;
|
|
63287
63295
|
return queryparse(querystring);
|
|
63288
63296
|
});
|
|
63289
63297
|
req.is = function is(types) {
|
|
@@ -63327,7 +63335,7 @@ var require_request = __commonJS({
|
|
|
63327
63335
|
return subdomains2.slice(offset);
|
|
63328
63336
|
});
|
|
63329
63337
|
defineGetter(req, "path", function path44() {
|
|
63330
|
-
return
|
|
63338
|
+
return parse15(this).pathname;
|
|
63331
63339
|
});
|
|
63332
63340
|
defineGetter(req, "host", function host() {
|
|
63333
63341
|
var trust = this.app.get("trust proxy fn");
|
|
@@ -63381,7 +63389,7 @@ var require_content_disposition = __commonJS({
|
|
|
63381
63389
|
"../../node_modules/content-disposition/index.js"(exports2, module2) {
|
|
63382
63390
|
"use strict";
|
|
63383
63391
|
module2.exports = contentDisposition;
|
|
63384
|
-
module2.exports.parse =
|
|
63392
|
+
module2.exports.parse = parse15;
|
|
63385
63393
|
var basename5 = require("path").basename;
|
|
63386
63394
|
var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
|
|
63387
63395
|
var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
|
|
@@ -63472,7 +63480,7 @@ var require_content_disposition = __commonJS({
|
|
|
63472
63480
|
function getlatin1(val) {
|
|
63473
63481
|
return String(val).replace(NON_LATIN1_REGEXP, "?");
|
|
63474
63482
|
}
|
|
63475
|
-
function
|
|
63483
|
+
function parse15(string) {
|
|
63476
63484
|
if (!string || typeof string !== "string") {
|
|
63477
63485
|
throw new TypeError("argument string is required");
|
|
63478
63486
|
}
|
|
@@ -63561,7 +63569,7 @@ var require_cookie_signature = __commonJS({
|
|
|
63561
63569
|
var require_cookie = __commonJS({
|
|
63562
63570
|
"../../node_modules/cookie/index.js"(exports2) {
|
|
63563
63571
|
"use strict";
|
|
63564
|
-
exports2.parse =
|
|
63572
|
+
exports2.parse = parse15;
|
|
63565
63573
|
exports2.serialize = serialize;
|
|
63566
63574
|
var __toString = Object.prototype.toString;
|
|
63567
63575
|
var __hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
@@ -63569,7 +63577,7 @@ var require_cookie = __commonJS({
|
|
|
63569
63577
|
var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
|
|
63570
63578
|
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;
|
|
63571
63579
|
var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
|
|
63572
|
-
function
|
|
63580
|
+
function parse15(str2, opt) {
|
|
63573
63581
|
if (typeof str2 !== "string") {
|
|
63574
63582
|
throw new TypeError("argument str must be a string");
|
|
63575
63583
|
}
|
|
@@ -73238,7 +73246,7 @@ var require_send = __commonJS({
|
|
|
73238
73246
|
var escapeHtml = require_escape_html();
|
|
73239
73247
|
var etag = require_etag();
|
|
73240
73248
|
var fresh = require_fresh();
|
|
73241
|
-
var
|
|
73249
|
+
var fs26 = require("fs");
|
|
73242
73250
|
var mime = require_mime_types4();
|
|
73243
73251
|
var ms = require_ms();
|
|
73244
73252
|
var onFinished = require_on_finished();
|
|
@@ -73520,7 +73528,7 @@ var require_send = __commonJS({
|
|
|
73520
73528
|
var i = 0;
|
|
73521
73529
|
var self = this;
|
|
73522
73530
|
debug('stat "%s"', path45);
|
|
73523
|
-
|
|
73531
|
+
fs26.stat(path45, function onstat(err, stat) {
|
|
73524
73532
|
var pathEndsWithSep = path45[path45.length - 1] === sep;
|
|
73525
73533
|
if (err && err.code === "ENOENT" && !extname2(path45) && !pathEndsWithSep) {
|
|
73526
73534
|
return next(err);
|
|
@@ -73537,7 +73545,7 @@ var require_send = __commonJS({
|
|
|
73537
73545
|
}
|
|
73538
73546
|
var p = path45 + "." + self._extensions[i++];
|
|
73539
73547
|
debug('stat "%s"', p);
|
|
73540
|
-
|
|
73548
|
+
fs26.stat(p, function(err2, stat) {
|
|
73541
73549
|
if (err2) return next(err2);
|
|
73542
73550
|
if (stat.isDirectory()) return next();
|
|
73543
73551
|
self.emit("file", p, stat);
|
|
@@ -73555,7 +73563,7 @@ var require_send = __commonJS({
|
|
|
73555
73563
|
}
|
|
73556
73564
|
var p = join39(path45, self._index[i]);
|
|
73557
73565
|
debug('stat "%s"', p);
|
|
73558
|
-
|
|
73566
|
+
fs26.stat(p, function(err2, stat) {
|
|
73559
73567
|
if (err2) return next(err2);
|
|
73560
73568
|
if (stat.isDirectory()) return next();
|
|
73561
73569
|
self.emit("file", p, stat);
|
|
@@ -73567,7 +73575,7 @@ var require_send = __commonJS({
|
|
|
73567
73575
|
SendStream.prototype.stream = function stream(path45, options) {
|
|
73568
73576
|
var self = this;
|
|
73569
73577
|
var res = this.res;
|
|
73570
|
-
var stream2 =
|
|
73578
|
+
var stream2 = fs26.createReadStream(path45, options);
|
|
73571
73579
|
this.emit("stream", stream2);
|
|
73572
73580
|
stream2.pipe(res);
|
|
73573
73581
|
function cleanup() {
|
|
@@ -73725,7 +73733,7 @@ var require_vary = __commonJS({
|
|
|
73725
73733
|
if (!field) {
|
|
73726
73734
|
throw new TypeError("field argument is required");
|
|
73727
73735
|
}
|
|
73728
|
-
var fields = !Array.isArray(field) ?
|
|
73736
|
+
var fields = !Array.isArray(field) ? parse15(String(field)) : field;
|
|
73729
73737
|
for (var j = 0; j < fields.length; j++) {
|
|
73730
73738
|
if (!FIELD_NAME_REGEXP.test(fields[j])) {
|
|
73731
73739
|
throw new TypeError("field argument contains an invalid header name");
|
|
@@ -73735,7 +73743,7 @@ var require_vary = __commonJS({
|
|
|
73735
73743
|
return header;
|
|
73736
73744
|
}
|
|
73737
73745
|
var val = header;
|
|
73738
|
-
var vals =
|
|
73746
|
+
var vals = parse15(header.toLowerCase());
|
|
73739
73747
|
if (fields.indexOf("*") !== -1 || vals.indexOf("*") !== -1) {
|
|
73740
73748
|
return "*";
|
|
73741
73749
|
}
|
|
@@ -73748,7 +73756,7 @@ var require_vary = __commonJS({
|
|
|
73748
73756
|
}
|
|
73749
73757
|
return val;
|
|
73750
73758
|
}
|
|
73751
|
-
function
|
|
73759
|
+
function parse15(header) {
|
|
73752
73760
|
var end = 0;
|
|
73753
73761
|
var list = [];
|
|
73754
73762
|
var start = 0;
|
|
@@ -75253,7 +75261,7 @@ var require_api = __commonJS({
|
|
|
75253
75261
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
75254
75262
|
exports2.createApiRouter = createApiRouter;
|
|
75255
75263
|
var path44 = __importStar(require("path"));
|
|
75256
|
-
var
|
|
75264
|
+
var os4 = __importStar(require("os"));
|
|
75257
75265
|
var child_process_1 = require("child_process");
|
|
75258
75266
|
var express_1 = require_express2();
|
|
75259
75267
|
var _useStdinFifo = process.platform === "linux" && !process.env.JEST_WORKER_ID;
|
|
@@ -75273,7 +75281,7 @@ var require_api = __commonJS({
|
|
|
75273
75281
|
env: { SOPS_CONFIG: path44.join(deps2.repoRoot, ".sops.yaml"), ...opts?.env }
|
|
75274
75282
|
});
|
|
75275
75283
|
}
|
|
75276
|
-
const fifoDir = (0, child_process_1.execFileSync)("mktemp", ["-d", path44.join(
|
|
75284
|
+
const fifoDir = (0, child_process_1.execFileSync)("mktemp", ["-d", path44.join(os4.tmpdir(), "clef-fifo-XXXXXX")]).toString().trim();
|
|
75277
75285
|
const fifoPath = path44.join(fifoDir, "input");
|
|
75278
75286
|
(0, child_process_1.execFileSync)("mkfifo", [fifoPath]);
|
|
75279
75287
|
const writer = (0, child_process_1.spawn)("dd", [`of=${fifoPath}`, "status=none"], {
|
|
@@ -75307,6 +75315,7 @@ var require_api = __commonJS({
|
|
|
75307
75315
|
const git = new core_1.GitIntegration(deps2.runner);
|
|
75308
75316
|
const scanRunner = new core_1.ScanRunner(deps2.runner);
|
|
75309
75317
|
const recipientManager = new core_1.RecipientManager(sops, matrix);
|
|
75318
|
+
const serviceIdManager = new core_1.ServiceIdentityManager(sops, matrix);
|
|
75310
75319
|
const bulkOps = new core_1.BulkOps();
|
|
75311
75320
|
let lastScanResult = null;
|
|
75312
75321
|
let lastScanAt = null;
|
|
@@ -75314,6 +75323,10 @@ var require_api = __commonJS({
|
|
|
75314
75323
|
const manifestPath = `${deps2.repoRoot}/clef.yaml`;
|
|
75315
75324
|
return parser.parse(manifestPath);
|
|
75316
75325
|
}
|
|
75326
|
+
function zeroStringRecord(record) {
|
|
75327
|
+
for (const k of Object.keys(record))
|
|
75328
|
+
record[k] = "";
|
|
75329
|
+
}
|
|
75317
75330
|
function setNoCacheHeaders(res) {
|
|
75318
75331
|
res.set({
|
|
75319
75332
|
"Cache-Control": "no-store, no-cache, must-revalidate",
|
|
@@ -75555,6 +75568,14 @@ var require_api = __commonJS({
|
|
|
75555
75568
|
return;
|
|
75556
75569
|
}
|
|
75557
75570
|
const result = await diffEngine.diffFiles(ns, envA, envB, manifest, sops, deps2.repoRoot);
|
|
75571
|
+
if (req.query.showValues !== "true") {
|
|
75572
|
+
for (const row of result.rows) {
|
|
75573
|
+
if (row.valueA !== null)
|
|
75574
|
+
row.valueA = "\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF";
|
|
75575
|
+
if (row.valueB !== null)
|
|
75576
|
+
row.valueB = "\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF";
|
|
75577
|
+
}
|
|
75578
|
+
}
|
|
75558
75579
|
res.json(result);
|
|
75559
75580
|
} catch {
|
|
75560
75581
|
res.status(500).json({ error: "Failed to compute diff", code: "DIFF_ERROR" });
|
|
@@ -75883,6 +75904,100 @@ var require_api = __commonJS({
|
|
|
75883
75904
|
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
75884
75905
|
}
|
|
75885
75906
|
});
|
|
75907
|
+
router.post("/service-identities", async (req, res) => {
|
|
75908
|
+
try {
|
|
75909
|
+
const manifest = loadManifest();
|
|
75910
|
+
const { name, description, namespaces, kmsEnvConfigs } = req.body;
|
|
75911
|
+
if (!name || typeof name !== "string") {
|
|
75912
|
+
res.status(400).json({ error: "name is required.", code: "BAD_REQUEST" });
|
|
75913
|
+
return;
|
|
75914
|
+
}
|
|
75915
|
+
if (!Array.isArray(namespaces) || namespaces.length === 0) {
|
|
75916
|
+
res.status(400).json({ error: "namespaces must be a non-empty array.", code: "BAD_REQUEST" });
|
|
75917
|
+
return;
|
|
75918
|
+
}
|
|
75919
|
+
let typedKmsConfigs;
|
|
75920
|
+
if (kmsEnvConfigs && Object.keys(kmsEnvConfigs).length > 0) {
|
|
75921
|
+
typedKmsConfigs = {};
|
|
75922
|
+
for (const [envName, cfg] of Object.entries(kmsEnvConfigs)) {
|
|
75923
|
+
if (!core_1.VALID_KMS_PROVIDERS.includes(cfg.provider)) {
|
|
75924
|
+
res.status(400).json({
|
|
75925
|
+
error: `Invalid KMS provider '${cfg.provider}' for environment '${envName}'. Must be aws, gcp, or azure.`,
|
|
75926
|
+
code: "BAD_REQUEST"
|
|
75927
|
+
});
|
|
75928
|
+
return;
|
|
75929
|
+
}
|
|
75930
|
+
typedKmsConfigs[envName] = {
|
|
75931
|
+
provider: cfg.provider,
|
|
75932
|
+
keyId: cfg.keyId
|
|
75933
|
+
};
|
|
75934
|
+
}
|
|
75935
|
+
}
|
|
75936
|
+
const result = await serviceIdManager.create(name, namespaces, description ?? "", manifest, deps2.repoRoot, typedKmsConfigs);
|
|
75937
|
+
setNoCacheHeaders(res);
|
|
75938
|
+
res.json({ identity: result.identity, privateKeys: result.privateKeys });
|
|
75939
|
+
zeroStringRecord(result.privateKeys);
|
|
75940
|
+
} catch (err) {
|
|
75941
|
+
const message = err instanceof Error ? err.message : "Failed to create service identity";
|
|
75942
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
75943
|
+
}
|
|
75944
|
+
});
|
|
75945
|
+
router.delete("/service-identities/:name", async (req, res) => {
|
|
75946
|
+
try {
|
|
75947
|
+
const name = req.params.name;
|
|
75948
|
+
const manifest = loadManifest();
|
|
75949
|
+
if (!manifest.service_identities?.find((si) => si.name === name)) {
|
|
75950
|
+
res.status(404).json({ error: `Service identity '${name}' not found.`, code: "NOT_FOUND" });
|
|
75951
|
+
return;
|
|
75952
|
+
}
|
|
75953
|
+
await serviceIdManager.delete(name, manifest, deps2.repoRoot);
|
|
75954
|
+
res.json({ ok: true });
|
|
75955
|
+
} catch (err) {
|
|
75956
|
+
const message = err instanceof Error ? err.message : "Failed to delete service identity";
|
|
75957
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
75958
|
+
}
|
|
75959
|
+
});
|
|
75960
|
+
router.patch("/service-identities/:name", async (req, res) => {
|
|
75961
|
+
try {
|
|
75962
|
+
const name = req.params.name;
|
|
75963
|
+
const { kmsEnvConfigs } = req.body;
|
|
75964
|
+
if (!kmsEnvConfigs || Object.keys(kmsEnvConfigs).length === 0) {
|
|
75965
|
+
res.status(400).json({ error: "kmsEnvConfigs must be a non-empty object.", code: "BAD_REQUEST" });
|
|
75966
|
+
return;
|
|
75967
|
+
}
|
|
75968
|
+
const manifest = loadManifest();
|
|
75969
|
+
const typedKmsConfigs = {};
|
|
75970
|
+
for (const [envName, cfg] of Object.entries(kmsEnvConfigs)) {
|
|
75971
|
+
if (cfg.provider !== "aws" && cfg.provider !== "gcp" && cfg.provider !== "azure") {
|
|
75972
|
+
res.status(400).json({
|
|
75973
|
+
error: `Invalid KMS provider '${cfg.provider}' for environment '${envName}'. Must be aws, gcp, or azure.`,
|
|
75974
|
+
code: "BAD_REQUEST"
|
|
75975
|
+
});
|
|
75976
|
+
return;
|
|
75977
|
+
}
|
|
75978
|
+
typedKmsConfigs[envName] = { provider: cfg.provider, keyId: cfg.keyId };
|
|
75979
|
+
}
|
|
75980
|
+
await serviceIdManager.updateEnvironments(name, typedKmsConfigs, manifest, deps2.repoRoot);
|
|
75981
|
+
res.json({ ok: true });
|
|
75982
|
+
} catch (err) {
|
|
75983
|
+
const message = err instanceof Error ? err.message : "Failed to update service identity";
|
|
75984
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
75985
|
+
}
|
|
75986
|
+
});
|
|
75987
|
+
router.post("/service-identities/:name/rotate", async (req, res) => {
|
|
75988
|
+
try {
|
|
75989
|
+
const name = req.params.name;
|
|
75990
|
+
const { environment } = req.body;
|
|
75991
|
+
const manifest = loadManifest();
|
|
75992
|
+
const privateKeys = await serviceIdManager.rotateKey(name, manifest, deps2.repoRoot, environment);
|
|
75993
|
+
setNoCacheHeaders(res);
|
|
75994
|
+
res.json({ privateKeys });
|
|
75995
|
+
zeroStringRecord(privateKeys);
|
|
75996
|
+
} catch (err) {
|
|
75997
|
+
const message = err instanceof Error ? err.message : "Failed to rotate service identity key";
|
|
75998
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
75999
|
+
}
|
|
76000
|
+
});
|
|
75886
76001
|
function dispose() {
|
|
75887
76002
|
lastScanResult = null;
|
|
75888
76003
|
lastScanAt = null;
|
|
@@ -76038,7 +76153,7 @@ var require_server = __commonJS({
|
|
|
76038
76153
|
const resolvedClientDir = clientDir ?? path44.resolve(__dirname, "../client");
|
|
76039
76154
|
app.use(staticLimiter, express_1.default.static(resolvedClientDir));
|
|
76040
76155
|
app.get("/{*splat}", staticLimiter, (_req, res) => {
|
|
76041
|
-
res.sendFile(
|
|
76156
|
+
res.sendFile("index.html", { root: resolvedClientDir });
|
|
76042
76157
|
});
|
|
76043
76158
|
}
|
|
76044
76159
|
const url = `http://127.0.0.1:${port}`;
|
|
@@ -76092,6 +76207,11 @@ var require_secrets_cache = __commonJS({
|
|
|
76092
76207
|
snapshot = null;
|
|
76093
76208
|
/** Replace the cached secrets in a single reference assignment. */
|
|
76094
76209
|
swap(values, keys, revision) {
|
|
76210
|
+
if (this.snapshot) {
|
|
76211
|
+
for (const k of Object.keys(this.snapshot.values)) {
|
|
76212
|
+
this.snapshot.values[k] = "";
|
|
76213
|
+
}
|
|
76214
|
+
}
|
|
76095
76215
|
this.snapshot = { values: { ...values }, keys: [...keys], revision, swappedAt: Date.now() };
|
|
76096
76216
|
}
|
|
76097
76217
|
/** Whether the cache has exceeded the given TTL (seconds). */
|
|
@@ -76100,8 +76220,13 @@ var require_secrets_cache = __commonJS({
|
|
|
76100
76220
|
return false;
|
|
76101
76221
|
return (Date.now() - this.snapshot.swappedAt) / 1e3 > ttlSeconds;
|
|
76102
76222
|
}
|
|
76103
|
-
/** Clear the cached snapshot. */
|
|
76223
|
+
/** Clear the cached snapshot, zeroing values first (best-effort). */
|
|
76104
76224
|
wipe() {
|
|
76225
|
+
if (this.snapshot) {
|
|
76226
|
+
for (const k of Object.keys(this.snapshot.values)) {
|
|
76227
|
+
this.snapshot.values[k] = "";
|
|
76228
|
+
}
|
|
76229
|
+
}
|
|
76105
76230
|
this.snapshot = null;
|
|
76106
76231
|
}
|
|
76107
76232
|
/** Epoch ms when the cache was last swapped, or null if never loaded. */
|
|
@@ -76180,7 +76305,7 @@ var require_disk_cache = __commonJS({
|
|
|
76180
76305
|
})();
|
|
76181
76306
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
76182
76307
|
exports2.DiskCache = void 0;
|
|
76183
|
-
var
|
|
76308
|
+
var fs26 = __importStar(require("fs"));
|
|
76184
76309
|
var path44 = __importStar(require("path"));
|
|
76185
76310
|
var DiskCache = class {
|
|
76186
76311
|
artifactPath;
|
|
@@ -76193,39 +76318,35 @@ var require_disk_cache = __commonJS({
|
|
|
76193
76318
|
/** Write an artifact and optional metadata to disk (atomic via tmp+rename). */
|
|
76194
76319
|
write(raw, sha) {
|
|
76195
76320
|
const dir = path44.dirname(this.artifactPath);
|
|
76196
|
-
|
|
76321
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
76197
76322
|
const tmpArtifact = `${this.artifactPath}.tmp.${process.pid}`;
|
|
76198
|
-
|
|
76199
|
-
|
|
76323
|
+
fs26.writeFileSync(tmpArtifact, raw, "utf-8");
|
|
76324
|
+
fs26.renameSync(tmpArtifact, this.artifactPath);
|
|
76200
76325
|
const meta = { sha, fetchedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
76201
76326
|
const tmpMeta = `${this.metaPath}.tmp.${process.pid}`;
|
|
76202
|
-
|
|
76203
|
-
|
|
76327
|
+
fs26.writeFileSync(tmpMeta, JSON.stringify(meta), "utf-8");
|
|
76328
|
+
fs26.renameSync(tmpMeta, this.metaPath);
|
|
76204
76329
|
}
|
|
76205
76330
|
/** Read the cached artifact. Returns null if no cache file exists. */
|
|
76206
76331
|
read() {
|
|
76207
76332
|
try {
|
|
76208
|
-
return
|
|
76333
|
+
return fs26.readFileSync(this.artifactPath, "utf-8");
|
|
76209
76334
|
} catch {
|
|
76210
76335
|
return null;
|
|
76211
76336
|
}
|
|
76212
76337
|
}
|
|
76213
76338
|
/** Get the SHA from the cached metadata, if available. */
|
|
76214
76339
|
getCachedSha() {
|
|
76215
|
-
|
|
76216
|
-
const raw = fs27.readFileSync(this.metaPath, "utf-8");
|
|
76217
|
-
const meta = JSON.parse(raw);
|
|
76218
|
-
return meta.sha;
|
|
76219
|
-
} catch {
|
|
76220
|
-
return void 0;
|
|
76221
|
-
}
|
|
76340
|
+
return this.readMeta()?.sha;
|
|
76222
76341
|
}
|
|
76223
76342
|
/** Get the fetchedAt timestamp from metadata, if available. */
|
|
76224
76343
|
getFetchedAt() {
|
|
76344
|
+
return this.readMeta()?.fetchedAt;
|
|
76345
|
+
}
|
|
76346
|
+
readMeta() {
|
|
76225
76347
|
try {
|
|
76226
|
-
const raw =
|
|
76227
|
-
|
|
76228
|
-
return meta.fetchedAt;
|
|
76348
|
+
const raw = fs26.readFileSync(this.metaPath, "utf-8");
|
|
76349
|
+
return JSON.parse(raw);
|
|
76229
76350
|
} catch {
|
|
76230
76351
|
return void 0;
|
|
76231
76352
|
}
|
|
@@ -76233,11 +76354,11 @@ var require_disk_cache = __commonJS({
|
|
|
76233
76354
|
/** Remove cached artifact and metadata files. */
|
|
76234
76355
|
purge() {
|
|
76235
76356
|
try {
|
|
76236
|
-
|
|
76357
|
+
fs26.unlinkSync(this.artifactPath);
|
|
76237
76358
|
} catch {
|
|
76238
76359
|
}
|
|
76239
76360
|
try {
|
|
76240
|
-
|
|
76361
|
+
fs26.unlinkSync(this.metaPath);
|
|
76241
76362
|
} catch {
|
|
76242
76363
|
}
|
|
76243
76364
|
}
|
|
@@ -76289,7 +76410,7 @@ var require_decrypt = __commonJS({
|
|
|
76289
76410
|
})();
|
|
76290
76411
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
76291
76412
|
exports2.AgeDecryptor = void 0;
|
|
76292
|
-
var
|
|
76413
|
+
var fs26 = __importStar(require("fs"));
|
|
76293
76414
|
var AgeDecryptor = class {
|
|
76294
76415
|
/**
|
|
76295
76416
|
* Decrypt an age-encrypted PEM-armored ciphertext string.
|
|
@@ -76315,7 +76436,7 @@ var require_decrypt = __commonJS({
|
|
|
76315
76436
|
if (ageKey)
|
|
76316
76437
|
return ageKey.trim();
|
|
76317
76438
|
if (ageKeyFile) {
|
|
76318
|
-
const content =
|
|
76439
|
+
const content = fs26.readFileSync(ageKeyFile, "utf-8").trim();
|
|
76319
76440
|
const lines = content.split("\n").filter((l) => l.startsWith("AGE-SECRET-KEY-"));
|
|
76320
76441
|
if (lines.length === 0) {
|
|
76321
76442
|
throw new Error(`No age secret key found in file: ${ageKeyFile}`);
|
|
@@ -76647,6 +76768,147 @@ var require_kms = __commonJS({
|
|
|
76647
76768
|
}
|
|
76648
76769
|
});
|
|
76649
76770
|
|
|
76771
|
+
// ../runtime/dist/artifact-decryptor.js
|
|
76772
|
+
var require_artifact_decryptor = __commonJS({
|
|
76773
|
+
"../runtime/dist/artifact-decryptor.js"(exports2) {
|
|
76774
|
+
"use strict";
|
|
76775
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
76776
|
+
if (k2 === void 0) k2 = k;
|
|
76777
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
76778
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
76779
|
+
desc = { enumerable: true, get: function() {
|
|
76780
|
+
return m[k];
|
|
76781
|
+
} };
|
|
76782
|
+
}
|
|
76783
|
+
Object.defineProperty(o, k2, desc);
|
|
76784
|
+
}) : (function(o, m, k, k2) {
|
|
76785
|
+
if (k2 === void 0) k2 = k;
|
|
76786
|
+
o[k2] = m[k];
|
|
76787
|
+
}));
|
|
76788
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
76789
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
76790
|
+
}) : function(o, v) {
|
|
76791
|
+
o["default"] = v;
|
|
76792
|
+
});
|
|
76793
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
76794
|
+
var ownKeys = function(o) {
|
|
76795
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
76796
|
+
var ar = [];
|
|
76797
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
76798
|
+
return ar;
|
|
76799
|
+
};
|
|
76800
|
+
return ownKeys(o);
|
|
76801
|
+
};
|
|
76802
|
+
return function(mod) {
|
|
76803
|
+
if (mod && mod.__esModule) return mod;
|
|
76804
|
+
var result = {};
|
|
76805
|
+
if (mod != null) {
|
|
76806
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
76807
|
+
}
|
|
76808
|
+
__setModuleDefault(result, mod);
|
|
76809
|
+
return result;
|
|
76810
|
+
};
|
|
76811
|
+
})();
|
|
76812
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
76813
|
+
exports2.ArtifactDecryptor = void 0;
|
|
76814
|
+
var crypto6 = __importStar(require("crypto"));
|
|
76815
|
+
var decrypt_1 = require_decrypt();
|
|
76816
|
+
var kms_1 = require_kms();
|
|
76817
|
+
var ArtifactDecryptor = class {
|
|
76818
|
+
ageDecryptor = new decrypt_1.AgeDecryptor();
|
|
76819
|
+
privateKey;
|
|
76820
|
+
telemetryOverride;
|
|
76821
|
+
initialTelemetry;
|
|
76822
|
+
constructor(options) {
|
|
76823
|
+
this.privateKey = options.privateKey;
|
|
76824
|
+
this.initialTelemetry = options.telemetry;
|
|
76825
|
+
}
|
|
76826
|
+
/** Set or replace the telemetry emitter. */
|
|
76827
|
+
setTelemetry(emitter) {
|
|
76828
|
+
this.telemetryOverride = emitter;
|
|
76829
|
+
}
|
|
76830
|
+
get telemetry() {
|
|
76831
|
+
return this.telemetryOverride ?? this.initialTelemetry;
|
|
76832
|
+
}
|
|
76833
|
+
/**
|
|
76834
|
+
* Decrypt an artifact envelope into plaintext key-value pairs.
|
|
76835
|
+
*
|
|
76836
|
+
* @throws On KMS unwrap failure, AES-GCM auth failure, age decrypt failure,
|
|
76837
|
+
* missing private key (config error), or malformed plaintext JSON.
|
|
76838
|
+
*/
|
|
76839
|
+
async decrypt(artifact) {
|
|
76840
|
+
let plaintext;
|
|
76841
|
+
if (artifact.envelope) {
|
|
76842
|
+
plaintext = await this.decryptKmsEnvelope(artifact);
|
|
76843
|
+
} else {
|
|
76844
|
+
plaintext = await this.decryptAge(artifact);
|
|
76845
|
+
}
|
|
76846
|
+
let values;
|
|
76847
|
+
try {
|
|
76848
|
+
values = JSON.parse(plaintext);
|
|
76849
|
+
} catch (err) {
|
|
76850
|
+
this.telemetry?.artifactInvalid({
|
|
76851
|
+
reason: "payload_parse",
|
|
76852
|
+
error: err instanceof Error ? err.message : String(err)
|
|
76853
|
+
});
|
|
76854
|
+
throw err;
|
|
76855
|
+
} finally {
|
|
76856
|
+
plaintext = "";
|
|
76857
|
+
}
|
|
76858
|
+
return { values, keys: artifact.keys, revision: artifact.revision };
|
|
76859
|
+
}
|
|
76860
|
+
/** KMS envelope: unwrap DEK via KMS, then AES-256-GCM decrypt. */
|
|
76861
|
+
async decryptKmsEnvelope(artifact) {
|
|
76862
|
+
const envelope = artifact.envelope;
|
|
76863
|
+
let dek;
|
|
76864
|
+
try {
|
|
76865
|
+
const kms = (0, kms_1.createKmsProvider)(envelope.provider);
|
|
76866
|
+
const wrappedKey = Buffer.from(envelope.wrappedKey, "base64");
|
|
76867
|
+
dek = await kms.unwrap(envelope.keyId, wrappedKey, envelope.algorithm);
|
|
76868
|
+
} catch (err) {
|
|
76869
|
+
this.telemetry?.artifactInvalid({
|
|
76870
|
+
reason: "kms_unwrap",
|
|
76871
|
+
error: err instanceof Error ? err.message : String(err)
|
|
76872
|
+
});
|
|
76873
|
+
throw err;
|
|
76874
|
+
}
|
|
76875
|
+
try {
|
|
76876
|
+
const iv = Buffer.from(envelope.iv, "base64");
|
|
76877
|
+
const authTag = Buffer.from(envelope.authTag, "base64");
|
|
76878
|
+
const ciphertextBuf = Buffer.from(artifact.ciphertext, "base64");
|
|
76879
|
+
const decipher = crypto6.createDecipheriv("aes-256-gcm", dek, iv);
|
|
76880
|
+
decipher.setAuthTag(authTag);
|
|
76881
|
+
return Buffer.concat([decipher.update(ciphertextBuf), decipher.final()]).toString("utf-8");
|
|
76882
|
+
} catch (err) {
|
|
76883
|
+
this.telemetry?.artifactInvalid({
|
|
76884
|
+
reason: "decrypt",
|
|
76885
|
+
error: err instanceof Error ? err.message : String(err)
|
|
76886
|
+
});
|
|
76887
|
+
throw err;
|
|
76888
|
+
} finally {
|
|
76889
|
+
dek.fill(0);
|
|
76890
|
+
}
|
|
76891
|
+
}
|
|
76892
|
+
/** Age-only: decrypt with the static private key. */
|
|
76893
|
+
async decryptAge(artifact) {
|
|
76894
|
+
if (!this.privateKey) {
|
|
76895
|
+
throw new Error("Artifact requires an age private key. Set CLEF_AGENT_AGE_KEY or use KMS envelope encryption.");
|
|
76896
|
+
}
|
|
76897
|
+
try {
|
|
76898
|
+
return await this.ageDecryptor.decrypt(artifact.ciphertext, this.privateKey);
|
|
76899
|
+
} catch (err) {
|
|
76900
|
+
this.telemetry?.artifactInvalid({
|
|
76901
|
+
reason: err instanceof SyntaxError ? "payload_parse" : "decrypt",
|
|
76902
|
+
error: err instanceof Error ? err.message : String(err)
|
|
76903
|
+
});
|
|
76904
|
+
throw err;
|
|
76905
|
+
}
|
|
76906
|
+
}
|
|
76907
|
+
};
|
|
76908
|
+
exports2.ArtifactDecryptor = ArtifactDecryptor;
|
|
76909
|
+
}
|
|
76910
|
+
});
|
|
76911
|
+
|
|
76650
76912
|
// ../runtime/dist/signature.js
|
|
76651
76913
|
var require_signature = __commonJS({
|
|
76652
76914
|
"../runtime/dist/signature.js"(exports2) {
|
|
@@ -76694,7 +76956,7 @@ var require_signature = __commonJS({
|
|
|
76694
76956
|
var crypto6 = __importStar(require("crypto"));
|
|
76695
76957
|
function buildSigningPayload2(artifact) {
|
|
76696
76958
|
const fields = [
|
|
76697
|
-
"clef-sig-
|
|
76959
|
+
"clef-sig-v2",
|
|
76698
76960
|
String(artifact.version),
|
|
76699
76961
|
artifact.identity,
|
|
76700
76962
|
artifact.environment,
|
|
@@ -76706,7 +76968,9 @@ var require_signature = __commonJS({
|
|
|
76706
76968
|
artifact.envelope?.provider ?? "",
|
|
76707
76969
|
artifact.envelope?.keyId ?? "",
|
|
76708
76970
|
artifact.envelope?.wrappedKey ?? "",
|
|
76709
|
-
artifact.envelope?.algorithm ?? ""
|
|
76971
|
+
artifact.envelope?.algorithm ?? "",
|
|
76972
|
+
artifact.envelope?.iv ?? "",
|
|
76973
|
+
artifact.envelope?.authTag ?? ""
|
|
76710
76974
|
];
|
|
76711
76975
|
return Buffer.from(fields.join("\n"), "utf-8");
|
|
76712
76976
|
}
|
|
@@ -76773,8 +77037,7 @@ var require_poller = __commonJS({
|
|
|
76773
77037
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
76774
77038
|
exports2.ArtifactPoller = void 0;
|
|
76775
77039
|
var crypto6 = __importStar(require("crypto"));
|
|
76776
|
-
var
|
|
76777
|
-
var kms_1 = require_kms();
|
|
77040
|
+
var artifact_decryptor_1 = require_artifact_decryptor();
|
|
76778
77041
|
var signature_1 = require_signature();
|
|
76779
77042
|
var MIN_POLL_MS = 5e3;
|
|
76780
77043
|
var ArtifactPoller = class {
|
|
@@ -76782,21 +77045,68 @@ var require_poller = __commonJS({
|
|
|
76782
77045
|
lastContentHash = null;
|
|
76783
77046
|
lastRevision = null;
|
|
76784
77047
|
lastExpiresAt = null;
|
|
76785
|
-
decryptor
|
|
77048
|
+
decryptor;
|
|
76786
77049
|
options;
|
|
77050
|
+
jitMode;
|
|
76787
77051
|
telemetryOverride;
|
|
76788
77052
|
constructor(options) {
|
|
76789
77053
|
this.options = options;
|
|
77054
|
+
this.jitMode = !!options.encryptedStore;
|
|
77055
|
+
this.decryptor = new artifact_decryptor_1.ArtifactDecryptor({
|
|
77056
|
+
privateKey: options.privateKey,
|
|
77057
|
+
telemetry: options.telemetry
|
|
77058
|
+
});
|
|
77059
|
+
}
|
|
77060
|
+
/** Get the decryptor instance (for JIT mode server wiring). */
|
|
77061
|
+
getDecryptor() {
|
|
77062
|
+
return this.decryptor;
|
|
76790
77063
|
}
|
|
76791
77064
|
/** Set or replace the telemetry emitter (e.g. after resolving token from secrets). */
|
|
76792
77065
|
setTelemetry(emitter) {
|
|
76793
77066
|
this.telemetryOverride = emitter;
|
|
77067
|
+
this.decryptor.setTelemetry(emitter);
|
|
76794
77068
|
}
|
|
76795
77069
|
get telemetry() {
|
|
76796
77070
|
return this.telemetryOverride ?? this.options.telemetry;
|
|
76797
77071
|
}
|
|
76798
|
-
/**
|
|
77072
|
+
/**
|
|
77073
|
+
* Fetch, validate, decrypt, and cache the artifact.
|
|
77074
|
+
* Used in cached mode (cacheTtl > 0).
|
|
77075
|
+
*/
|
|
76799
77076
|
async fetchAndDecrypt() {
|
|
77077
|
+
const result = await this.fetchRaw();
|
|
77078
|
+
if (!result)
|
|
77079
|
+
return;
|
|
77080
|
+
await this.validateDecryptAndCache(result.artifact, result.contentHash);
|
|
77081
|
+
}
|
|
77082
|
+
/**
|
|
77083
|
+
* Fetch and validate the artifact without decrypting.
|
|
77084
|
+
* Stores the validated envelope in the encryptedStore for on-demand decryption.
|
|
77085
|
+
* Used in JIT mode (cacheTtl = 0).
|
|
77086
|
+
*/
|
|
77087
|
+
async fetchAndValidate() {
|
|
77088
|
+
const result = await this.fetchRaw();
|
|
77089
|
+
if (!result)
|
|
77090
|
+
return;
|
|
77091
|
+
const artifact = this.validateArtifact(result.artifact);
|
|
77092
|
+
this.options.encryptedStore.swap(artifact);
|
|
77093
|
+
this.lastRevision = artifact.revision;
|
|
77094
|
+
this.lastContentHash = result.contentHash ?? null;
|
|
77095
|
+
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
77096
|
+
this.options.onRefresh?.(artifact.revision);
|
|
77097
|
+
this.telemetry?.artifactRefreshed({
|
|
77098
|
+
revision: artifact.revision,
|
|
77099
|
+
keyCount: artifact.keys.length,
|
|
77100
|
+
kmsEnvelope: !!artifact.envelope
|
|
77101
|
+
});
|
|
77102
|
+
}
|
|
77103
|
+
/**
|
|
77104
|
+
* Fetch the raw artifact from the source (with disk cache fallback),
|
|
77105
|
+
* parse JSON, and check for revocation.
|
|
77106
|
+
*
|
|
77107
|
+
* Returns null when the content hash is unchanged (short-circuit).
|
|
77108
|
+
*/
|
|
77109
|
+
async fetchRaw() {
|
|
76800
77110
|
let raw;
|
|
76801
77111
|
let contentHash;
|
|
76802
77112
|
try {
|
|
@@ -76804,7 +77114,7 @@ var require_poller = __commonJS({
|
|
|
76804
77114
|
raw = result.raw;
|
|
76805
77115
|
contentHash = result.contentHash;
|
|
76806
77116
|
if (contentHash && contentHash === this.lastContentHash)
|
|
76807
|
-
return;
|
|
77117
|
+
return null;
|
|
76808
77118
|
this.options.diskCache?.write(raw, contentHash);
|
|
76809
77119
|
} catch (err) {
|
|
76810
77120
|
this.telemetry?.fetchFailed({
|
|
@@ -76815,7 +77125,7 @@ var require_poller = __commonJS({
|
|
|
76815
77125
|
if (this.options.diskCache) {
|
|
76816
77126
|
const cached2 = this.options.diskCache.read();
|
|
76817
77127
|
if (cached2) {
|
|
76818
|
-
if (ttl !== void 0) {
|
|
77128
|
+
if (ttl !== void 0 && ttl > 0) {
|
|
76819
77129
|
const fetchedAt = this.options.diskCache.getFetchedAt();
|
|
76820
77130
|
if (fetchedAt && (Date.now() - new Date(fetchedAt).getTime()) / 1e3 > ttl) {
|
|
76821
77131
|
this.options.cache.wipe();
|
|
@@ -76830,9 +77140,9 @@ var require_poller = __commonJS({
|
|
|
76830
77140
|
raw = cached2;
|
|
76831
77141
|
contentHash = this.options.diskCache.getCachedSha();
|
|
76832
77142
|
if (contentHash && contentHash === this.lastContentHash)
|
|
76833
|
-
return;
|
|
77143
|
+
return null;
|
|
76834
77144
|
} else {
|
|
76835
|
-
if (ttl !== void 0 && this.options.cache.isExpired(ttl)) {
|
|
77145
|
+
if (ttl !== void 0 && ttl > 0 && this.options.cache.isExpired(ttl)) {
|
|
76836
77146
|
this.options.cache.wipe();
|
|
76837
77147
|
this.telemetry?.cacheExpired({
|
|
76838
77148
|
cacheTtlSeconds: ttl,
|
|
@@ -76843,7 +77153,7 @@ var require_poller = __commonJS({
|
|
|
76843
77153
|
throw err;
|
|
76844
77154
|
}
|
|
76845
77155
|
} else {
|
|
76846
|
-
if (ttl !== void 0 && this.options.cache.isExpired(ttl)) {
|
|
77156
|
+
if (ttl !== void 0 && ttl > 0 && this.options.cache.isExpired(ttl)) {
|
|
76847
77157
|
this.options.cache.wipe();
|
|
76848
77158
|
this.telemetry?.cacheExpired({
|
|
76849
77159
|
cacheTtlSeconds: ttl,
|
|
@@ -76857,6 +77167,7 @@ var require_poller = __commonJS({
|
|
|
76857
77167
|
const parsed = JSON.parse(raw);
|
|
76858
77168
|
if (parsed.revokedAt) {
|
|
76859
77169
|
this.options.cache.wipe();
|
|
77170
|
+
this.options.encryptedStore?.wipe();
|
|
76860
77171
|
this.options.diskCache?.purge();
|
|
76861
77172
|
this.lastRevision = null;
|
|
76862
77173
|
this.lastContentHash = null;
|
|
@@ -76865,17 +77176,18 @@ var require_poller = __commonJS({
|
|
|
76865
77176
|
});
|
|
76866
77177
|
throw new Error(`Artifact revoked: ${parsed.identity}/${parsed.environment} at ${parsed.revokedAt}`);
|
|
76867
77178
|
}
|
|
76868
|
-
|
|
77179
|
+
return { artifact: parsed, contentHash };
|
|
76869
77180
|
}
|
|
76870
77181
|
/**
|
|
76871
|
-
* Validate the artifact
|
|
76872
|
-
*
|
|
76873
|
-
*
|
|
77182
|
+
* Validate the artifact envelope: version, required fields, expiry,
|
|
77183
|
+
* revision dedup, integrity hash, and signature.
|
|
77184
|
+
* Emits `artifact.invalid` / `artifact.expired` telemetry on failure.
|
|
77185
|
+
* Returns the validated artifact, or throws.
|
|
76874
77186
|
*/
|
|
76875
|
-
|
|
77187
|
+
validateArtifact(parsed) {
|
|
76876
77188
|
let artifact;
|
|
76877
77189
|
try {
|
|
76878
|
-
artifact = this.
|
|
77190
|
+
artifact = this.validateEnvelope(parsed);
|
|
76879
77191
|
} catch (err) {
|
|
76880
77192
|
this.telemetry?.artifactInvalid({
|
|
76881
77193
|
reason: classifyValidationError(err),
|
|
@@ -76885,12 +77197,13 @@ var require_poller = __commonJS({
|
|
|
76885
77197
|
}
|
|
76886
77198
|
if (artifact.expiresAt && Date.now() > new Date(artifact.expiresAt).getTime()) {
|
|
76887
77199
|
this.options.cache.wipe();
|
|
77200
|
+
this.options.encryptedStore?.wipe();
|
|
76888
77201
|
this.options.diskCache?.purge();
|
|
76889
77202
|
this.telemetry?.artifactExpired({ expiresAt: artifact.expiresAt });
|
|
76890
77203
|
throw new Error(`Artifact expired at ${artifact.expiresAt}`);
|
|
76891
77204
|
}
|
|
76892
77205
|
if (artifact.revision === this.lastRevision)
|
|
76893
|
-
return;
|
|
77206
|
+
return artifact;
|
|
76894
77207
|
const hash = crypto6.createHash("sha256").update(artifact.ciphertext).digest("hex");
|
|
76895
77208
|
if (hash !== artifact.ciphertextHash) {
|
|
76896
77209
|
const err = new Error(`Artifact integrity check failed: expected hash ${artifact.ciphertextHash}, got ${hash}`);
|
|
@@ -76930,53 +77243,34 @@ var require_poller = __commonJS({
|
|
|
76930
77243
|
throw err;
|
|
76931
77244
|
}
|
|
76932
77245
|
}
|
|
76933
|
-
|
|
76934
|
-
|
|
76935
|
-
|
|
76936
|
-
|
|
76937
|
-
|
|
76938
|
-
|
|
76939
|
-
|
|
76940
|
-
|
|
76941
|
-
|
|
76942
|
-
|
|
76943
|
-
|
|
76944
|
-
|
|
76945
|
-
|
|
76946
|
-
|
|
76947
|
-
|
|
76948
|
-
|
|
76949
|
-
|
|
76950
|
-
|
|
76951
|
-
|
|
76952
|
-
|
|
76953
|
-
}
|
|
76954
|
-
try {
|
|
76955
|
-
const plaintext = await this.decryptor.decrypt(artifact.ciphertext, agePrivateKey);
|
|
76956
|
-
const values = JSON.parse(plaintext);
|
|
76957
|
-
this.options.cache.swap(values, artifact.keys, artifact.revision);
|
|
76958
|
-
this.lastRevision = artifact.revision;
|
|
76959
|
-
this.lastContentHash = contentHash ?? null;
|
|
76960
|
-
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
76961
|
-
this.options.onRefresh?.(artifact.revision);
|
|
76962
|
-
this.telemetry?.artifactRefreshed({
|
|
76963
|
-
revision: artifact.revision,
|
|
76964
|
-
keyCount: artifact.keys.length,
|
|
76965
|
-
kmsEnvelope: !!artifact.envelope
|
|
76966
|
-
});
|
|
76967
|
-
} catch (err) {
|
|
76968
|
-
if (err instanceof Error && !err.message.includes("integrity check failed")) {
|
|
76969
|
-
this.telemetry?.artifactInvalid({
|
|
76970
|
-
reason: err instanceof SyntaxError ? "payload_parse" : "decrypt",
|
|
76971
|
-
error: err.message
|
|
76972
|
-
});
|
|
76973
|
-
}
|
|
76974
|
-
throw err;
|
|
76975
|
-
}
|
|
77246
|
+
return artifact;
|
|
77247
|
+
}
|
|
77248
|
+
/**
|
|
77249
|
+
* Validate then decrypt and cache. Used by fetchAndDecrypt (cached mode).
|
|
77250
|
+
*/
|
|
77251
|
+
async validateDecryptAndCache(parsed, contentHash) {
|
|
77252
|
+
const artifact = this.validateArtifact(parsed);
|
|
77253
|
+
if (artifact.revision === this.lastRevision)
|
|
77254
|
+
return;
|
|
77255
|
+
const { values } = await this.decryptor.decrypt(artifact);
|
|
77256
|
+
this.options.cache.swap(values, artifact.keys, artifact.revision);
|
|
77257
|
+
this.lastRevision = artifact.revision;
|
|
77258
|
+
this.lastContentHash = contentHash ?? null;
|
|
77259
|
+
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
77260
|
+
this.options.onRefresh?.(artifact.revision);
|
|
77261
|
+
this.telemetry?.artifactRefreshed({
|
|
77262
|
+
revision: artifact.revision,
|
|
77263
|
+
keyCount: artifact.keys.length,
|
|
77264
|
+
kmsEnvelope: !!artifact.envelope
|
|
77265
|
+
});
|
|
76976
77266
|
}
|
|
76977
77267
|
/** Start the polling loop. Performs an initial fetch immediately. */
|
|
76978
77268
|
async start() {
|
|
76979
|
-
|
|
77269
|
+
if (this.jitMode) {
|
|
77270
|
+
await this.fetchAndValidate();
|
|
77271
|
+
} else {
|
|
77272
|
+
await this.fetchAndDecrypt();
|
|
77273
|
+
}
|
|
76980
77274
|
this.scheduleNext();
|
|
76981
77275
|
}
|
|
76982
77276
|
/** Start only the polling schedule (no initial fetch). */
|
|
@@ -77002,7 +77296,11 @@ var require_poller = __commonJS({
|
|
|
77002
77296
|
this.timer = setTimeout(async () => {
|
|
77003
77297
|
this.timer = null;
|
|
77004
77298
|
try {
|
|
77005
|
-
|
|
77299
|
+
if (this.jitMode) {
|
|
77300
|
+
await this.fetchAndValidate();
|
|
77301
|
+
} else {
|
|
77302
|
+
await this.fetchAndDecrypt();
|
|
77303
|
+
}
|
|
77006
77304
|
} catch (err) {
|
|
77007
77305
|
this.options.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
77008
77306
|
}
|
|
@@ -77018,14 +77316,15 @@ var require_poller = __commonJS({
|
|
|
77018
77316
|
}
|
|
77019
77317
|
return MIN_POLL_MS;
|
|
77020
77318
|
}
|
|
77319
|
+
if (this.jitMode)
|
|
77320
|
+
return MIN_POLL_MS;
|
|
77021
77321
|
const ttl = this.options.cacheTtl;
|
|
77022
77322
|
if (ttl !== void 0) {
|
|
77023
77323
|
return Math.max(ttl / 10 * 1e3, MIN_POLL_MS);
|
|
77024
77324
|
}
|
|
77025
77325
|
return 3e4;
|
|
77026
77326
|
}
|
|
77027
|
-
|
|
77028
|
-
const artifact = JSON.parse(raw);
|
|
77327
|
+
validateEnvelope(artifact) {
|
|
77029
77328
|
if (artifact.version !== 1) {
|
|
77030
77329
|
throw new Error(`Unsupported artifact version: ${artifact.version}`);
|
|
77031
77330
|
}
|
|
@@ -77033,7 +77332,7 @@ var require_poller = __commonJS({
|
|
|
77033
77332
|
throw new Error("Invalid artifact: missing required fields.");
|
|
77034
77333
|
}
|
|
77035
77334
|
if (artifact.envelope) {
|
|
77036
|
-
if (!artifact.envelope.provider || !artifact.envelope.keyId || !artifact.envelope.wrappedKey || !artifact.envelope.algorithm) {
|
|
77335
|
+
if (!artifact.envelope.provider || !artifact.envelope.keyId || !artifact.envelope.wrappedKey || !artifact.envelope.algorithm || !artifact.envelope.iv || !artifact.envelope.authTag) {
|
|
77037
77336
|
throw new Error("Invalid artifact: incomplete envelope fields.");
|
|
77038
77337
|
}
|
|
77039
77338
|
}
|
|
@@ -77058,6 +77357,50 @@ var require_poller = __commonJS({
|
|
|
77058
77357
|
}
|
|
77059
77358
|
});
|
|
77060
77359
|
|
|
77360
|
+
// ../runtime/dist/encrypted-artifact-store.js
|
|
77361
|
+
var require_encrypted_artifact_store = __commonJS({
|
|
77362
|
+
"../runtime/dist/encrypted-artifact-store.js"(exports2) {
|
|
77363
|
+
"use strict";
|
|
77364
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
77365
|
+
exports2.EncryptedArtifactStore = void 0;
|
|
77366
|
+
var EncryptedArtifactStore = class {
|
|
77367
|
+
artifact = null;
|
|
77368
|
+
_storedAt = null;
|
|
77369
|
+
/** Atomically replace the stored artifact. */
|
|
77370
|
+
swap(artifact) {
|
|
77371
|
+
this.artifact = artifact;
|
|
77372
|
+
this._storedAt = Date.now();
|
|
77373
|
+
}
|
|
77374
|
+
/** Get the current encrypted artifact. Returns null if not yet loaded. */
|
|
77375
|
+
get() {
|
|
77376
|
+
return this.artifact;
|
|
77377
|
+
}
|
|
77378
|
+
/** Whether an artifact has been stored. */
|
|
77379
|
+
isReady() {
|
|
77380
|
+
return this.artifact !== null;
|
|
77381
|
+
}
|
|
77382
|
+
/** Epoch ms of last store, or null. */
|
|
77383
|
+
getStoredAt() {
|
|
77384
|
+
return this._storedAt;
|
|
77385
|
+
}
|
|
77386
|
+
/** Get key names from the stored artifact metadata (no decryption needed). */
|
|
77387
|
+
getKeys() {
|
|
77388
|
+
return this.artifact ? [...this.artifact.keys] : [];
|
|
77389
|
+
}
|
|
77390
|
+
/** Get the revision from the stored artifact. */
|
|
77391
|
+
getRevision() {
|
|
77392
|
+
return this.artifact?.revision ?? null;
|
|
77393
|
+
}
|
|
77394
|
+
/** Clear the stored artifact (on revocation/expiry). */
|
|
77395
|
+
wipe() {
|
|
77396
|
+
this.artifact = null;
|
|
77397
|
+
this._storedAt = null;
|
|
77398
|
+
}
|
|
77399
|
+
};
|
|
77400
|
+
exports2.EncryptedArtifactStore = EncryptedArtifactStore;
|
|
77401
|
+
}
|
|
77402
|
+
});
|
|
77403
|
+
|
|
77061
77404
|
// ../runtime/dist/telemetry.js
|
|
77062
77405
|
var require_telemetry = __commonJS({
|
|
77063
77406
|
"../runtime/dist/telemetry.js"(exports2) {
|
|
@@ -77412,14 +77755,23 @@ var require_http = __commonJS({
|
|
|
77412
77755
|
async fetch() {
|
|
77413
77756
|
const res = await fetch(this.url);
|
|
77414
77757
|
if (!res.ok) {
|
|
77415
|
-
throw new Error(`Failed to fetch artifact from ${this.
|
|
77758
|
+
throw new Error(`Failed to fetch artifact from ${this.describe()}: ${res.status}`);
|
|
77416
77759
|
}
|
|
77417
77760
|
const raw = await res.text();
|
|
77418
77761
|
const etag = res.headers.get("etag") ?? void 0;
|
|
77419
77762
|
return { raw, contentHash: etag };
|
|
77420
77763
|
}
|
|
77421
77764
|
describe() {
|
|
77422
|
-
|
|
77765
|
+
try {
|
|
77766
|
+
const parsed = new URL(this.url);
|
|
77767
|
+
if (parsed.username || parsed.password) {
|
|
77768
|
+
parsed.username = "***";
|
|
77769
|
+
parsed.password = "";
|
|
77770
|
+
}
|
|
77771
|
+
return `HTTP ${parsed.href}`;
|
|
77772
|
+
} catch {
|
|
77773
|
+
return "HTTP <invalid-url>";
|
|
77774
|
+
}
|
|
77423
77775
|
}
|
|
77424
77776
|
};
|
|
77425
77777
|
exports2.HttpArtifactSource = HttpArtifactSource;
|
|
@@ -77469,14 +77821,14 @@ var require_file = __commonJS({
|
|
|
77469
77821
|
})();
|
|
77470
77822
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
77471
77823
|
exports2.FileArtifactSource = void 0;
|
|
77472
|
-
var
|
|
77824
|
+
var fs26 = __importStar(require("fs"));
|
|
77473
77825
|
var FileArtifactSource = class {
|
|
77474
77826
|
path;
|
|
77475
77827
|
constructor(filePath) {
|
|
77476
77828
|
this.path = filePath;
|
|
77477
77829
|
}
|
|
77478
77830
|
async fetch() {
|
|
77479
|
-
const raw =
|
|
77831
|
+
const raw = fs26.readFileSync(this.path, "utf-8");
|
|
77480
77832
|
return { raw };
|
|
77481
77833
|
}
|
|
77482
77834
|
describe() {
|
|
@@ -77521,7 +77873,7 @@ var require_dist4 = __commonJS({
|
|
|
77521
77873
|
"../runtime/dist/index.js"(exports2) {
|
|
77522
77874
|
"use strict";
|
|
77523
77875
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
77524
|
-
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.ArtifactPoller = exports2.AgeDecryptor = exports2.DiskCache = exports2.SecretsCache = void 0;
|
|
77876
|
+
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;
|
|
77525
77877
|
exports2.init = init;
|
|
77526
77878
|
var secrets_cache_1 = require_secrets_cache();
|
|
77527
77879
|
Object.defineProperty(exports2, "SecretsCache", { enumerable: true, get: function() {
|
|
@@ -77539,6 +77891,14 @@ var require_dist4 = __commonJS({
|
|
|
77539
77891
|
Object.defineProperty(exports2, "ArtifactPoller", { enumerable: true, get: function() {
|
|
77540
77892
|
return poller_1.ArtifactPoller;
|
|
77541
77893
|
} });
|
|
77894
|
+
var artifact_decryptor_1 = require_artifact_decryptor();
|
|
77895
|
+
Object.defineProperty(exports2, "ArtifactDecryptor", { enumerable: true, get: function() {
|
|
77896
|
+
return artifact_decryptor_1.ArtifactDecryptor;
|
|
77897
|
+
} });
|
|
77898
|
+
var encrypted_artifact_store_1 = require_encrypted_artifact_store();
|
|
77899
|
+
Object.defineProperty(exports2, "EncryptedArtifactStore", { enumerable: true, get: function() {
|
|
77900
|
+
return encrypted_artifact_store_1.EncryptedArtifactStore;
|
|
77901
|
+
} });
|
|
77542
77902
|
var telemetry_1 = require_telemetry();
|
|
77543
77903
|
Object.defineProperty(exports2, "TelemetryEmitter", { enumerable: true, get: function() {
|
|
77544
77904
|
return telemetry_1.TelemetryEmitter;
|
|
@@ -77751,10 +78111,13 @@ var NodeSubprocessRunner = class {
|
|
|
77751
78111
|
};
|
|
77752
78112
|
|
|
77753
78113
|
// src/commands/init.ts
|
|
77754
|
-
var
|
|
78114
|
+
var fs16 = __toESM(require("fs"));
|
|
77755
78115
|
var path19 = __toESM(require("path"));
|
|
77756
78116
|
var readline2 = __toESM(require("readline"));
|
|
77757
|
-
var
|
|
78117
|
+
var YAML11 = __toESM(require_dist());
|
|
78118
|
+
init_src();
|
|
78119
|
+
|
|
78120
|
+
// src/handle-error.ts
|
|
77758
78121
|
init_src();
|
|
77759
78122
|
|
|
77760
78123
|
// src/output/formatter.ts
|
|
@@ -77966,6 +78329,16 @@ function pad(str2, width) {
|
|
|
77966
78329
|
return diff > 0 ? str2 + " ".repeat(diff) : str2;
|
|
77967
78330
|
}
|
|
77968
78331
|
|
|
78332
|
+
// src/handle-error.ts
|
|
78333
|
+
function handleCommandError(err) {
|
|
78334
|
+
if (err instanceof SopsMissingError || err instanceof SopsVersionError) {
|
|
78335
|
+
formatter.formatDependencyError(err);
|
|
78336
|
+
} else {
|
|
78337
|
+
formatter.error(err.message);
|
|
78338
|
+
}
|
|
78339
|
+
process.exit(1);
|
|
78340
|
+
}
|
|
78341
|
+
|
|
77969
78342
|
// src/keychain.ts
|
|
77970
78343
|
var SERVICE = "clef";
|
|
77971
78344
|
var CRED_HELPER_CS = `
|
|
@@ -78416,8 +78789,8 @@ function registerInitCommand(program3, deps2) {
|
|
|
78416
78789
|
}
|
|
78417
78790
|
const manifestPath = path19.join(repoRoot, "clef.yaml");
|
|
78418
78791
|
const clefConfigPath = path19.join(repoRoot, CLEF_DIR, CLEF_CONFIG_FILENAME);
|
|
78419
|
-
const manifestExists =
|
|
78420
|
-
const localConfigExists =
|
|
78792
|
+
const manifestExists = fs16.existsSync(manifestPath);
|
|
78793
|
+
const localConfigExists = fs16.existsSync(clefConfigPath);
|
|
78421
78794
|
if (manifestExists && localConfigExists) {
|
|
78422
78795
|
formatter.print("Already initialised. Run 'clef update' to scaffold new environments.");
|
|
78423
78796
|
process.exit(0);
|
|
@@ -78439,8 +78812,7 @@ function registerInitCommand(program3, deps2) {
|
|
|
78439
78812
|
}
|
|
78440
78813
|
await handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, options);
|
|
78441
78814
|
} catch (err) {
|
|
78442
|
-
|
|
78443
|
-
process.exit(1);
|
|
78815
|
+
handleCommandError(err);
|
|
78444
78816
|
}
|
|
78445
78817
|
});
|
|
78446
78818
|
}
|
|
@@ -78472,22 +78844,22 @@ async function handleSecondDevOnboarding(repoRoot, clefConfigPath, deps2, option
|
|
|
78472
78844
|
const publicKey = identity.publicKey;
|
|
78473
78845
|
const keyContent = formatAgeKeyFile(privateKey, publicKey);
|
|
78474
78846
|
const keyDir = path19.dirname(keyPath);
|
|
78475
|
-
if (!
|
|
78476
|
-
|
|
78847
|
+
if (!fs16.existsSync(keyDir)) {
|
|
78848
|
+
fs16.mkdirSync(keyDir, { recursive: true });
|
|
78477
78849
|
}
|
|
78478
|
-
|
|
78850
|
+
fs16.writeFileSync(keyPath, keyContent, { encoding: "utf-8", mode: 384 });
|
|
78479
78851
|
formatter.success(`Generated age key at ${keyPath}`);
|
|
78480
78852
|
config = { age_key_file: keyPath, age_key_storage: "file", age_keychain_label: label };
|
|
78481
78853
|
}
|
|
78482
78854
|
const clefDir = path19.dirname(clefConfigPath);
|
|
78483
|
-
if (!
|
|
78484
|
-
|
|
78855
|
+
if (!fs16.existsSync(clefDir)) {
|
|
78856
|
+
fs16.mkdirSync(clefDir, { recursive: true });
|
|
78485
78857
|
}
|
|
78486
|
-
|
|
78858
|
+
fs16.writeFileSync(clefConfigPath, YAML11.stringify(config), "utf-8");
|
|
78487
78859
|
formatter.success("Created .clef/config.yaml");
|
|
78488
78860
|
const gitignorePath = path19.join(clefDir, ".gitignore");
|
|
78489
|
-
if (!
|
|
78490
|
-
|
|
78861
|
+
if (!fs16.existsSync(gitignorePath)) {
|
|
78862
|
+
fs16.writeFileSync(gitignorePath, "*\n", "utf-8");
|
|
78491
78863
|
formatter.success("Created .clef/.gitignore");
|
|
78492
78864
|
}
|
|
78493
78865
|
formatter.success(`Key label: ${label}`);
|
|
@@ -78579,38 +78951,38 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
|
|
|
78579
78951
|
}
|
|
78580
78952
|
const keyContent = formatAgeKeyFile(privateKey, publicKey);
|
|
78581
78953
|
const keyDir = path19.dirname(keyPath);
|
|
78582
|
-
if (!
|
|
78583
|
-
|
|
78954
|
+
if (!fs16.existsSync(keyDir)) {
|
|
78955
|
+
fs16.mkdirSync(keyDir, { recursive: true });
|
|
78584
78956
|
}
|
|
78585
|
-
|
|
78957
|
+
fs16.writeFileSync(keyPath, keyContent, { encoding: "utf-8", mode: 384 });
|
|
78586
78958
|
formatter.success(`Generated age key at ${keyPath}`);
|
|
78587
78959
|
ageKeyFile = keyPath;
|
|
78588
78960
|
}
|
|
78589
78961
|
const clefDir = path19.dirname(clefConfigPath);
|
|
78590
|
-
if (!
|
|
78591
|
-
|
|
78962
|
+
if (!fs16.existsSync(clefDir)) {
|
|
78963
|
+
fs16.mkdirSync(clefDir, { recursive: true });
|
|
78592
78964
|
}
|
|
78593
78965
|
const config = ageKeyFile ? { age_key_file: ageKeyFile, age_key_storage: "file", age_keychain_label: label } : { age_key_storage: "keychain", age_keychain_label: label };
|
|
78594
|
-
|
|
78966
|
+
fs16.writeFileSync(clefConfigPath, YAML11.stringify(config), "utf-8");
|
|
78595
78967
|
formatter.success("Created .clef/config.yaml");
|
|
78596
78968
|
const gitignorePath = path19.join(clefDir, ".gitignore");
|
|
78597
|
-
if (!
|
|
78598
|
-
|
|
78969
|
+
if (!fs16.existsSync(gitignorePath)) {
|
|
78970
|
+
fs16.writeFileSync(gitignorePath, "*\n", "utf-8");
|
|
78599
78971
|
formatter.success("Created .clef/.gitignore");
|
|
78600
78972
|
}
|
|
78601
78973
|
formatter.success(`Key label: ${label}`);
|
|
78602
78974
|
}
|
|
78603
|
-
const manifestDoc =
|
|
78975
|
+
const manifestDoc = YAML11.parse(YAML11.stringify(manifest));
|
|
78604
78976
|
if (backend === "age" && publicKey) {
|
|
78605
78977
|
const sopsDoc = manifestDoc.sops;
|
|
78606
78978
|
sopsDoc.age = { recipients: [publicKey] };
|
|
78607
78979
|
}
|
|
78608
|
-
|
|
78980
|
+
fs16.writeFileSync(manifestPath, YAML11.stringify(manifestDoc), "utf-8");
|
|
78609
78981
|
formatter.success("Created clef.yaml");
|
|
78610
78982
|
{
|
|
78611
78983
|
const sopsYamlPath = path19.join(repoRoot, ".sops.yaml");
|
|
78612
78984
|
const sopsConfig = buildSopsYaml(manifest, repoRoot, publicKey);
|
|
78613
|
-
|
|
78985
|
+
fs16.writeFileSync(sopsYamlPath, YAML11.stringify(sopsConfig), "utf-8");
|
|
78614
78986
|
formatter.success("Created .sops.yaml");
|
|
78615
78987
|
}
|
|
78616
78988
|
const sopsClient = new SopsClient(deps2.runner, ageKeyFile, ageKey);
|
|
@@ -78667,8 +79039,8 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
|
|
|
78667
79039
|
}
|
|
78668
79040
|
}
|
|
78669
79041
|
const clefignorePath = path19.join(repoRoot, ".clefignore");
|
|
78670
|
-
if (!
|
|
78671
|
-
|
|
79042
|
+
if (!fs16.existsSync(clefignorePath)) {
|
|
79043
|
+
fs16.writeFileSync(clefignorePath, DEFAULT_CLEFIGNORE, "utf-8");
|
|
78672
79044
|
formatter.success("Created .clefignore");
|
|
78673
79045
|
} else {
|
|
78674
79046
|
formatter.print(" .clefignore already exists \u2014 skipping");
|
|
@@ -78700,7 +79072,7 @@ function scaffoldSopsConfig(repoRoot) {
|
|
|
78700
79072
|
agePublicKey = resolveAgePublicKeyFromEnvOrFile(repoRoot);
|
|
78701
79073
|
}
|
|
78702
79074
|
const sopsConfig = buildSopsYaml(manifest, repoRoot, agePublicKey);
|
|
78703
|
-
|
|
79075
|
+
fs16.writeFileSync(sopsYamlPath, YAML11.stringify(sopsConfig), "utf-8");
|
|
78704
79076
|
}
|
|
78705
79077
|
function buildSopsYaml(manifest, _repoRoot, agePublicKey) {
|
|
78706
79078
|
const creationRules = [];
|
|
@@ -78764,9 +79136,9 @@ function resolveAgePublicKeyFromEnvOrFile(repoRoot) {
|
|
|
78764
79136
|
if (match) return match[1];
|
|
78765
79137
|
}
|
|
78766
79138
|
const clefConfigPath = path19.join(repoRoot, CLEF_DIR, CLEF_CONFIG_FILENAME);
|
|
78767
|
-
if (
|
|
79139
|
+
if (fs16.existsSync(clefConfigPath)) {
|
|
78768
79140
|
try {
|
|
78769
|
-
const config =
|
|
79141
|
+
const config = YAML11.parse(fs16.readFileSync(clefConfigPath, "utf-8"));
|
|
78770
79142
|
if (config?.age_key_file) {
|
|
78771
79143
|
const pubKey = extractAgePublicKey(config.age_key_file);
|
|
78772
79144
|
if (pubKey) return pubKey;
|
|
@@ -78778,8 +79150,8 @@ function resolveAgePublicKeyFromEnvOrFile(repoRoot) {
|
|
|
78778
79150
|
}
|
|
78779
79151
|
function extractAgePublicKey(keyFilePath) {
|
|
78780
79152
|
try {
|
|
78781
|
-
if (!
|
|
78782
|
-
const content =
|
|
79153
|
+
if (!fs16.existsSync(keyFilePath)) return void 0;
|
|
79154
|
+
const content = fs16.readFileSync(keyFilePath, "utf-8");
|
|
78783
79155
|
const match = content.match(/# public key: (age1[a-z0-9]+)/);
|
|
78784
79156
|
return match ? match[1] : void 0;
|
|
78785
79157
|
} catch {
|
|
@@ -78846,9 +79218,9 @@ var path21 = __toESM(require("path"));
|
|
|
78846
79218
|
init_src();
|
|
78847
79219
|
|
|
78848
79220
|
// src/age-credential.ts
|
|
78849
|
-
var
|
|
79221
|
+
var fs17 = __toESM(require("fs"));
|
|
78850
79222
|
var path20 = __toESM(require("path"));
|
|
78851
|
-
var
|
|
79223
|
+
var YAML12 = __toESM(require_dist());
|
|
78852
79224
|
init_src();
|
|
78853
79225
|
var CLEF_DIR2 = ".clef";
|
|
78854
79226
|
var CLEF_CONFIG_FILENAME2 = "config.yaml";
|
|
@@ -78913,7 +79285,7 @@ async function resolveAgePrivateKey(repoRoot, runner2) {
|
|
|
78913
79285
|
const filePath = process.env.CLEF_AGE_KEY_FILE;
|
|
78914
79286
|
if (!filePath) return null;
|
|
78915
79287
|
try {
|
|
78916
|
-
const content =
|
|
79288
|
+
const content = fs17.readFileSync(filePath, "utf-8");
|
|
78917
79289
|
const match = content.match(AGE_SECRET_KEY_RE);
|
|
78918
79290
|
return match ? match[1] : null;
|
|
78919
79291
|
} catch (err) {
|
|
@@ -78925,7 +79297,7 @@ async function resolveAgePrivateKey(repoRoot, runner2) {
|
|
|
78925
79297
|
}
|
|
78926
79298
|
case "config-file": {
|
|
78927
79299
|
try {
|
|
78928
|
-
const content =
|
|
79300
|
+
const content = fs17.readFileSync(credential.path, "utf-8");
|
|
78929
79301
|
const match = content.match(AGE_SECRET_KEY_RE);
|
|
78930
79302
|
return match ? match[1] : null;
|
|
78931
79303
|
} catch (err) {
|
|
@@ -78940,8 +79312,8 @@ async function resolveAgePrivateKey(repoRoot, runner2) {
|
|
|
78940
79312
|
function readLocalConfig(repoRoot) {
|
|
78941
79313
|
const clefConfigPath = path20.join(repoRoot, CLEF_DIR2, CLEF_CONFIG_FILENAME2);
|
|
78942
79314
|
try {
|
|
78943
|
-
if (!
|
|
78944
|
-
return
|
|
79315
|
+
if (!fs17.existsSync(clefConfigPath)) return null;
|
|
79316
|
+
return YAML12.parse(fs17.readFileSync(clefConfigPath, "utf-8"));
|
|
78945
79317
|
} catch (err) {
|
|
78946
79318
|
formatter.warn(
|
|
78947
79319
|
`Failed to parse ${clefConfigPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -78983,6 +79355,15 @@ function maskedPlaceholder() {
|
|
|
78983
79355
|
return "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
78984
79356
|
}
|
|
78985
79357
|
|
|
79358
|
+
// src/parse-target.ts
|
|
79359
|
+
function parseTarget(target) {
|
|
79360
|
+
const parts = target.split("/");
|
|
79361
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79362
|
+
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79363
|
+
}
|
|
79364
|
+
return [parts[0], parts[1]];
|
|
79365
|
+
}
|
|
79366
|
+
|
|
78986
79367
|
// src/commands/get.ts
|
|
78987
79368
|
function registerGetCommand(program3, deps2) {
|
|
78988
79369
|
program3.command("get <target> <key>").description(
|
|
@@ -79018,23 +79399,10 @@ function registerGetCommand(program3, deps2) {
|
|
|
79018
79399
|
}
|
|
79019
79400
|
}
|
|
79020
79401
|
} catch (err) {
|
|
79021
|
-
|
|
79022
|
-
formatter.formatDependencyError(err);
|
|
79023
|
-
process.exit(1);
|
|
79024
|
-
return;
|
|
79025
|
-
}
|
|
79026
|
-
formatter.error(err.message);
|
|
79027
|
-
process.exit(1);
|
|
79402
|
+
handleCommandError(err);
|
|
79028
79403
|
}
|
|
79029
79404
|
});
|
|
79030
79405
|
}
|
|
79031
|
-
function parseTarget(target) {
|
|
79032
|
-
const parts = target.split("/");
|
|
79033
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79034
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79035
|
-
}
|
|
79036
|
-
return [parts[0], parts[1]];
|
|
79037
|
-
}
|
|
79038
79406
|
|
|
79039
79407
|
// src/commands/set.ts
|
|
79040
79408
|
var path22 = __toESM(require("path"));
|
|
@@ -79149,7 +79517,7 @@ function registerSetCommand(program3, deps2) {
|
|
|
79149
79517
|
Consider using the interactive prompt instead: clef set ${target} ${key}`
|
|
79150
79518
|
);
|
|
79151
79519
|
}
|
|
79152
|
-
const [namespace, environment] =
|
|
79520
|
+
const [namespace, environment] = parseTarget(target);
|
|
79153
79521
|
const matrixManager = new MatrixManager();
|
|
79154
79522
|
if (matrixManager.isProtectedEnvironment(manifest, environment)) {
|
|
79155
79523
|
const confirmed = await formatter.confirm(
|
|
@@ -79181,11 +79549,22 @@ function registerSetCommand(program3, deps2) {
|
|
|
79181
79549
|
try {
|
|
79182
79550
|
await markPendingWithRetry(filePath, [key], "clef set --random");
|
|
79183
79551
|
} catch {
|
|
79184
|
-
|
|
79185
|
-
|
|
79186
|
-
|
|
79552
|
+
try {
|
|
79553
|
+
delete decrypted.values[key];
|
|
79554
|
+
await sopsClient.encrypt(filePath, decrypted.values, manifest, environment);
|
|
79555
|
+
} catch {
|
|
79556
|
+
formatter.error(
|
|
79557
|
+
`${key} was encrypted but pending state could not be recorded, and rollback failed.
|
|
79558
|
+
The encrypted file may contain an untracked random placeholder.
|
|
79187
79559
|
This key MUST be set to a real value before deploying.
|
|
79188
79560
|
Run: clef set ${namespace}/${environment} ${key}`
|
|
79561
|
+
);
|
|
79562
|
+
process.exit(1);
|
|
79563
|
+
return;
|
|
79564
|
+
}
|
|
79565
|
+
formatter.error(
|
|
79566
|
+
`${key}: pending state could not be recorded. The value was rolled back.
|
|
79567
|
+
Retry: clef set --random ${namespace}/${environment} ${key}`
|
|
79189
79568
|
);
|
|
79190
79569
|
process.exit(1);
|
|
79191
79570
|
return;
|
|
@@ -79210,24 +79589,11 @@ function registerSetCommand(program3, deps2) {
|
|
|
79210
79589
|
);
|
|
79211
79590
|
}
|
|
79212
79591
|
} catch (err) {
|
|
79213
|
-
|
|
79214
|
-
formatter.formatDependencyError(err);
|
|
79215
|
-
process.exit(1);
|
|
79216
|
-
return;
|
|
79217
|
-
}
|
|
79218
|
-
formatter.error(err.message);
|
|
79219
|
-
process.exit(1);
|
|
79592
|
+
handleCommandError(err);
|
|
79220
79593
|
}
|
|
79221
79594
|
}
|
|
79222
79595
|
);
|
|
79223
79596
|
}
|
|
79224
|
-
function parseTarget2(target) {
|
|
79225
|
-
const parts = target.split("/");
|
|
79226
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79227
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79228
|
-
}
|
|
79229
|
-
return [parts[0], parts[1]];
|
|
79230
|
-
}
|
|
79231
79597
|
|
|
79232
79598
|
// src/commands/compare.ts
|
|
79233
79599
|
var path23 = __toESM(require("path"));
|
|
@@ -79238,7 +79604,7 @@ function registerCompareCommand(program3, deps2) {
|
|
|
79238
79604
|
"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"
|
|
79239
79605
|
).action(async (target, key, value) => {
|
|
79240
79606
|
try {
|
|
79241
|
-
const [namespace, environment] =
|
|
79607
|
+
const [namespace, environment] = parseTarget(target);
|
|
79242
79608
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
79243
79609
|
const parser = new ManifestParser();
|
|
79244
79610
|
const manifest = parser.parse(path23.join(repoRoot, "clef.yaml"));
|
|
@@ -79268,7 +79634,15 @@ function registerCompareCommand(program3, deps2) {
|
|
|
79268
79634
|
return;
|
|
79269
79635
|
}
|
|
79270
79636
|
const stored = decrypted.values[key];
|
|
79271
|
-
const
|
|
79637
|
+
const storedBuf = Buffer.from(stored);
|
|
79638
|
+
const compareBuf = Buffer.from(compareValue);
|
|
79639
|
+
const maxLen = Math.max(storedBuf.length, compareBuf.length, 1);
|
|
79640
|
+
const paddedStored = Buffer.alloc(maxLen);
|
|
79641
|
+
const paddedCompare = Buffer.alloc(maxLen);
|
|
79642
|
+
storedBuf.copy(paddedStored);
|
|
79643
|
+
compareBuf.copy(paddedCompare);
|
|
79644
|
+
const timingEqual = crypto5.timingSafeEqual(paddedStored, paddedCompare);
|
|
79645
|
+
const match = storedBuf.length === compareBuf.length && timingEqual;
|
|
79272
79646
|
if (match) {
|
|
79273
79647
|
formatter.success(`${key} ${sym("arrow")} values match`);
|
|
79274
79648
|
} else {
|
|
@@ -79276,23 +79650,10 @@ function registerCompareCommand(program3, deps2) {
|
|
|
79276
79650
|
process.exit(1);
|
|
79277
79651
|
}
|
|
79278
79652
|
} catch (err) {
|
|
79279
|
-
|
|
79280
|
-
formatter.formatDependencyError(err);
|
|
79281
|
-
process.exit(1);
|
|
79282
|
-
return;
|
|
79283
|
-
}
|
|
79284
|
-
formatter.error(err.message);
|
|
79285
|
-
process.exit(1);
|
|
79653
|
+
handleCommandError(err);
|
|
79286
79654
|
}
|
|
79287
79655
|
});
|
|
79288
79656
|
}
|
|
79289
|
-
function parseTarget3(target) {
|
|
79290
|
-
const parts = target.split("/");
|
|
79291
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79292
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79293
|
-
}
|
|
79294
|
-
return [parts[0], parts[1]];
|
|
79295
|
-
}
|
|
79296
79657
|
|
|
79297
79658
|
// src/commands/delete.ts
|
|
79298
79659
|
var path24 = __toESM(require("path"));
|
|
@@ -79324,7 +79685,7 @@ Type the key name to confirm:`
|
|
|
79324
79685
|
await bulkOps.deleteAcrossEnvironments(namespace, key, manifest, sopsClient, repoRoot);
|
|
79325
79686
|
formatter.success(`Deleted '${key}' from ${namespace} in all environments`);
|
|
79326
79687
|
} else {
|
|
79327
|
-
const [namespace, environment] =
|
|
79688
|
+
const [namespace, environment] = parseTarget(target);
|
|
79328
79689
|
if (matrixManager.isProtectedEnvironment(manifest, environment)) {
|
|
79329
79690
|
const protConfirmed = await formatter.confirm(
|
|
79330
79691
|
`This is a protected environment (${environment}). Are you sure you want to delete '${key}'?`
|
|
@@ -79366,23 +79727,10 @@ Type the key name to confirm:`
|
|
|
79366
79727
|
);
|
|
79367
79728
|
}
|
|
79368
79729
|
} catch (err) {
|
|
79369
|
-
|
|
79370
|
-
formatter.formatDependencyError(err);
|
|
79371
|
-
process.exit(1);
|
|
79372
|
-
return;
|
|
79373
|
-
}
|
|
79374
|
-
formatter.error(err.message);
|
|
79375
|
-
process.exit(1);
|
|
79730
|
+
handleCommandError(err);
|
|
79376
79731
|
}
|
|
79377
79732
|
});
|
|
79378
79733
|
}
|
|
79379
|
-
function parseTarget4(target) {
|
|
79380
|
-
const parts = target.split("/");
|
|
79381
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79382
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79383
|
-
}
|
|
79384
|
-
return [parts[0], parts[1]];
|
|
79385
|
-
}
|
|
79386
79734
|
|
|
79387
79735
|
// src/commands/diff.ts
|
|
79388
79736
|
var path25 = __toESM(require("path"));
|
|
@@ -79437,13 +79785,7 @@ function registerDiffCommand(program3, deps2) {
|
|
|
79437
79785
|
const hasDiffs = result.rows.some((r) => r.status !== "identical");
|
|
79438
79786
|
process.exit(hasDiffs ? 1 : 0);
|
|
79439
79787
|
} catch (err) {
|
|
79440
|
-
|
|
79441
|
-
formatter.formatDependencyError(err);
|
|
79442
|
-
process.exit(1);
|
|
79443
|
-
return;
|
|
79444
|
-
}
|
|
79445
|
-
formatter.error(err.message);
|
|
79446
|
-
process.exit(1);
|
|
79788
|
+
handleCommandError(err);
|
|
79447
79789
|
}
|
|
79448
79790
|
}
|
|
79449
79791
|
);
|
|
@@ -79730,7 +80072,7 @@ async function fetchCheckpoint(config) {
|
|
|
79730
80072
|
}
|
|
79731
80073
|
|
|
79732
80074
|
// package.json
|
|
79733
|
-
var version = "0.1.
|
|
80075
|
+
var version = "0.1.9-beta.57";
|
|
79734
80076
|
var package_default = {
|
|
79735
80077
|
name: "@clef-sh/cli",
|
|
79736
80078
|
version,
|
|
@@ -79835,13 +80177,7 @@ function registerLintCommand(program3, deps2) {
|
|
|
79835
80177
|
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
79836
80178
|
process.exit(hasErrors ? 1 : 0);
|
|
79837
80179
|
} catch (err) {
|
|
79838
|
-
|
|
79839
|
-
formatter.formatDependencyError(err);
|
|
79840
|
-
process.exit(1);
|
|
79841
|
-
return;
|
|
79842
|
-
}
|
|
79843
|
-
formatter.error(err.message);
|
|
79844
|
-
process.exit(1);
|
|
80180
|
+
handleCommandError(err);
|
|
79845
80181
|
}
|
|
79846
80182
|
});
|
|
79847
80183
|
}
|
|
@@ -79911,7 +80247,7 @@ function registerRotateCommand(program3, deps2) {
|
|
|
79911
80247
|
"Rotate encryption key for a namespace/environment file.\n\n target: namespace/environment (e.g. payments/production)\n --new-key: the new age public key to add (required)\n\nExit codes:\n 0 key rotated successfully\n 1 operation failed"
|
|
79912
80248
|
).requiredOption("--new-key <key>", "New age public key to rotate to").action(async (target, options) => {
|
|
79913
80249
|
try {
|
|
79914
|
-
const [namespace, environment] =
|
|
80250
|
+
const [namespace, environment] = parseTarget(target);
|
|
79915
80251
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
79916
80252
|
const parser = new ManifestParser();
|
|
79917
80253
|
const manifest = parser.parse(path27.join(repoRoot, "clef.yaml"));
|
|
@@ -79938,26 +80274,13 @@ function registerRotateCommand(program3, deps2) {
|
|
|
79938
80274
|
`git add ${relativeFile} && git commit -m "rotate: ${namespace}/${environment}"`
|
|
79939
80275
|
);
|
|
79940
80276
|
} catch (err) {
|
|
79941
|
-
|
|
79942
|
-
formatter.formatDependencyError(err);
|
|
79943
|
-
process.exit(1);
|
|
79944
|
-
return;
|
|
79945
|
-
}
|
|
79946
|
-
formatter.error(err.message);
|
|
79947
|
-
process.exit(1);
|
|
80277
|
+
handleCommandError(err);
|
|
79948
80278
|
}
|
|
79949
80279
|
});
|
|
79950
80280
|
}
|
|
79951
|
-
function parseTarget5(target) {
|
|
79952
|
-
const parts = target.split("/");
|
|
79953
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79954
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79955
|
-
}
|
|
79956
|
-
return [parts[0], parts[1]];
|
|
79957
|
-
}
|
|
79958
80281
|
|
|
79959
80282
|
// src/commands/hooks.ts
|
|
79960
|
-
var
|
|
80283
|
+
var fs18 = __toESM(require("fs"));
|
|
79961
80284
|
var path28 = __toESM(require("path"));
|
|
79962
80285
|
init_src();
|
|
79963
80286
|
function registerHooksCommand(program3, deps2) {
|
|
@@ -79966,8 +80289,8 @@ function registerHooksCommand(program3, deps2) {
|
|
|
79966
80289
|
try {
|
|
79967
80290
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
79968
80291
|
const hookPath = path28.join(repoRoot, ".git", "hooks", "pre-commit");
|
|
79969
|
-
if (
|
|
79970
|
-
const content =
|
|
80292
|
+
if (fs18.existsSync(hookPath)) {
|
|
80293
|
+
const content = fs18.readFileSync(hookPath, "utf-8");
|
|
79971
80294
|
if (content.includes("clef") || content.includes("SOPS")) {
|
|
79972
80295
|
const confirmed = await formatter.confirm(
|
|
79973
80296
|
"A Clef pre-commit hook already exists. Overwrite?"
|
|
@@ -80097,6 +80420,7 @@ async function openBrowser(url, runner2) {
|
|
|
80097
80420
|
}
|
|
80098
80421
|
|
|
80099
80422
|
// src/commands/exec.ts
|
|
80423
|
+
var os2 = __toESM(require("os"));
|
|
80100
80424
|
var path30 = __toESM(require("path"));
|
|
80101
80425
|
var import_child_process3 = require("child_process");
|
|
80102
80426
|
init_src();
|
|
@@ -80133,7 +80457,7 @@ function registerExecCommand(program3, deps2) {
|
|
|
80133
80457
|
process.exit(1);
|
|
80134
80458
|
return;
|
|
80135
80459
|
}
|
|
80136
|
-
const [namespace, environment] =
|
|
80460
|
+
const [namespace, environment] = parseTarget(target);
|
|
80137
80461
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
80138
80462
|
const parser = new ManifestParser();
|
|
80139
80463
|
const manifest = parser.parse(path30.join(repoRoot, "clef.yaml"));
|
|
@@ -80150,7 +80474,7 @@ function registerExecCommand(program3, deps2) {
|
|
|
80150
80474
|
const mergedValues = { ...primaryDecrypted.values };
|
|
80151
80475
|
for (const alsoTarget of options.also) {
|
|
80152
80476
|
try {
|
|
80153
|
-
const [alsoNs, alsoEnv] =
|
|
80477
|
+
const [alsoNs, alsoEnv] = parseTarget(alsoTarget);
|
|
80154
80478
|
const alsoFilePath = path30.join(
|
|
80155
80479
|
repoRoot,
|
|
80156
80480
|
manifest.file_pattern.replace("{namespace}", alsoNs).replace("{environment}", alsoEnv)
|
|
@@ -80187,14 +80511,7 @@ function registerExecCommand(program3, deps2) {
|
|
|
80187
80511
|
const exitCode = await spawnChild(childCommand, childCommandArgs, childEnv);
|
|
80188
80512
|
process.exit(exitCode);
|
|
80189
80513
|
} catch (err) {
|
|
80190
|
-
|
|
80191
|
-
formatter.formatDependencyError(err);
|
|
80192
|
-
process.exit(1);
|
|
80193
|
-
return;
|
|
80194
|
-
}
|
|
80195
|
-
const message = err instanceof Error ? err.message : "Execution failed";
|
|
80196
|
-
formatter.error(message);
|
|
80197
|
-
process.exit(1);
|
|
80514
|
+
handleCommandError(err);
|
|
80198
80515
|
}
|
|
80199
80516
|
}
|
|
80200
80517
|
);
|
|
@@ -80220,12 +80537,8 @@ function spawnChild(command, args, env) {
|
|
|
80220
80537
|
process.off("SIGTERM", sigtermHandler);
|
|
80221
80538
|
process.off("SIGINT", sigintHandler);
|
|
80222
80539
|
if (signal) {
|
|
80223
|
-
const
|
|
80224
|
-
|
|
80225
|
-
SIGINT: 130,
|
|
80226
|
-
SIGTERM: 143
|
|
80227
|
-
};
|
|
80228
|
-
resolve6(signalCodes[signal] ?? 128);
|
|
80540
|
+
const sigNum = os2.constants?.signals?.[signal];
|
|
80541
|
+
resolve6(sigNum ? 128 + sigNum : 128);
|
|
80229
80542
|
} else {
|
|
80230
80543
|
resolve6(code ?? 1);
|
|
80231
80544
|
}
|
|
@@ -80243,13 +80556,6 @@ function spawnChild(command, args, env) {
|
|
|
80243
80556
|
process.on("SIGINT", sigintHandler);
|
|
80244
80557
|
});
|
|
80245
80558
|
}
|
|
80246
|
-
function parseTarget6(target) {
|
|
80247
|
-
const parts = target.split("/");
|
|
80248
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
80249
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
80250
|
-
}
|
|
80251
|
-
return [parts[0], parts[1]];
|
|
80252
|
-
}
|
|
80253
80559
|
|
|
80254
80560
|
// src/commands/export.ts
|
|
80255
80561
|
var path31 = __toESM(require("path"));
|
|
@@ -80278,7 +80584,7 @@ Usage: clef export payments/production --format env`
|
|
|
80278
80584
|
process.exit(1);
|
|
80279
80585
|
return;
|
|
80280
80586
|
}
|
|
80281
|
-
const [namespace, environment] =
|
|
80587
|
+
const [namespace, environment] = parseTarget(target);
|
|
80282
80588
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
80283
80589
|
const parser = new ManifestParser();
|
|
80284
80590
|
const manifest = parser.parse(path31.join(repoRoot, "clef.yaml"));
|
|
@@ -80313,29 +80619,15 @@ Usage: clef export payments/production --format env`
|
|
|
80313
80619
|
}
|
|
80314
80620
|
}
|
|
80315
80621
|
} catch (err) {
|
|
80316
|
-
|
|
80317
|
-
formatter.formatDependencyError(err);
|
|
80318
|
-
process.exit(1);
|
|
80319
|
-
return;
|
|
80320
|
-
}
|
|
80321
|
-
const message = err instanceof Error ? err.message : "Export failed";
|
|
80322
|
-
formatter.error(message);
|
|
80323
|
-
process.exit(1);
|
|
80622
|
+
handleCommandError(err);
|
|
80324
80623
|
}
|
|
80325
80624
|
});
|
|
80326
80625
|
}
|
|
80327
|
-
function parseTarget7(target) {
|
|
80328
|
-
const parts = target.split("/");
|
|
80329
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
80330
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
80331
|
-
}
|
|
80332
|
-
return [parts[0], parts[1]];
|
|
80333
|
-
}
|
|
80334
80626
|
|
|
80335
80627
|
// src/commands/doctor.ts
|
|
80336
|
-
var
|
|
80628
|
+
var fs19 = __toESM(require("fs"));
|
|
80337
80629
|
var path32 = __toESM(require("path"));
|
|
80338
|
-
var
|
|
80630
|
+
var YAML13 = __toESM(require_dist());
|
|
80339
80631
|
init_src();
|
|
80340
80632
|
function registerDoctorCommand(program3, deps2) {
|
|
80341
80633
|
program3.command("doctor").description(
|
|
@@ -80385,7 +80677,7 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80385
80677
|
});
|
|
80386
80678
|
}
|
|
80387
80679
|
const manifestPath = path32.join(repoRoot, "clef.yaml");
|
|
80388
|
-
const manifestFound =
|
|
80680
|
+
const manifestFound = fs19.existsSync(manifestPath);
|
|
80389
80681
|
checks.push({
|
|
80390
80682
|
name: "manifest",
|
|
80391
80683
|
ok: manifestFound,
|
|
@@ -80395,7 +80687,7 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80395
80687
|
const ageKeyResult = await checkAgeKey(repoRoot, deps2.runner);
|
|
80396
80688
|
checks.push(ageKeyResult);
|
|
80397
80689
|
const sopsYamlPath = path32.join(repoRoot, ".sops.yaml");
|
|
80398
|
-
const sopsYamlFound =
|
|
80690
|
+
const sopsYamlFound = fs19.existsSync(sopsYamlPath);
|
|
80399
80691
|
checks.push({
|
|
80400
80692
|
name: ".sops.yaml",
|
|
80401
80693
|
ok: sopsYamlFound,
|
|
@@ -80403,11 +80695,11 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80403
80695
|
hint: sopsYamlFound ? void 0 : "run: clef init"
|
|
80404
80696
|
});
|
|
80405
80697
|
const clefignorePath = path32.join(repoRoot, ".clefignore");
|
|
80406
|
-
const clefignoreFound =
|
|
80698
|
+
const clefignoreFound = fs19.existsSync(clefignorePath);
|
|
80407
80699
|
let clefignoreRuleCount = 0;
|
|
80408
80700
|
if (clefignoreFound) {
|
|
80409
80701
|
try {
|
|
80410
|
-
const content =
|
|
80702
|
+
const content = fs19.readFileSync(clefignorePath, "utf-8");
|
|
80411
80703
|
clefignoreRuleCount = content.split("\n").filter(
|
|
80412
80704
|
(l) => l.trim() && !l.trim().startsWith("#") && !l.trim().startsWith("ignore-pattern:")
|
|
80413
80705
|
).length;
|
|
@@ -80439,7 +80731,7 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80439
80731
|
formatter.info("Attempting to fix: generating .sops.yaml from manifest...");
|
|
80440
80732
|
try {
|
|
80441
80733
|
scaffoldSopsConfig(repoRoot);
|
|
80442
|
-
const nowFound =
|
|
80734
|
+
const nowFound = fs19.existsSync(sopsYamlPath);
|
|
80443
80735
|
if (nowFound) {
|
|
80444
80736
|
const sopsYamlCheck = checks.find((c) => c.name === ".sops.yaml");
|
|
80445
80737
|
if (sopsYamlCheck) {
|
|
@@ -80563,7 +80855,7 @@ async function checkAgeKey(repoRoot, runner2) {
|
|
|
80563
80855
|
source: "env"
|
|
80564
80856
|
};
|
|
80565
80857
|
case "config-file":
|
|
80566
|
-
if (!
|
|
80858
|
+
if (!fs19.existsSync(credential.path)) {
|
|
80567
80859
|
return {
|
|
80568
80860
|
name: "age key",
|
|
80569
80861
|
ok: false,
|
|
@@ -80582,9 +80874,9 @@ async function checkAgeKey(repoRoot, runner2) {
|
|
|
80582
80874
|
}
|
|
80583
80875
|
function countAgeRecipients(sopsYamlPath) {
|
|
80584
80876
|
try {
|
|
80585
|
-
if (!
|
|
80586
|
-
const content =
|
|
80587
|
-
const config =
|
|
80877
|
+
if (!fs19.existsSync(sopsYamlPath)) return 0;
|
|
80878
|
+
const content = fs19.readFileSync(sopsYamlPath, "utf-8");
|
|
80879
|
+
const config = YAML13.parse(content);
|
|
80588
80880
|
if (!config?.creation_rules || !Array.isArray(config.creation_rules)) {
|
|
80589
80881
|
return 0;
|
|
80590
80882
|
}
|
|
@@ -80610,7 +80902,7 @@ function getSopsInstallHint() {
|
|
|
80610
80902
|
}
|
|
80611
80903
|
|
|
80612
80904
|
// src/commands/update.ts
|
|
80613
|
-
var
|
|
80905
|
+
var fs20 = __toESM(require("fs"));
|
|
80614
80906
|
var path33 = __toESM(require("path"));
|
|
80615
80907
|
init_src();
|
|
80616
80908
|
function registerUpdateCommand(program3, deps2) {
|
|
@@ -80620,7 +80912,7 @@ function registerUpdateCommand(program3, deps2) {
|
|
|
80620
80912
|
try {
|
|
80621
80913
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
80622
80914
|
const manifestPath = path33.join(repoRoot, "clef.yaml");
|
|
80623
|
-
if (!
|
|
80915
|
+
if (!fs20.existsSync(manifestPath)) {
|
|
80624
80916
|
formatter.error("clef.yaml not found. Run 'clef init' to initialise this repository.");
|
|
80625
80917
|
process.exit(1);
|
|
80626
80918
|
return;
|
|
@@ -80654,19 +80946,12 @@ function registerUpdateCommand(program3, deps2) {
|
|
|
80654
80946
|
formatter.success(`Scaffolded ${scaffoldedCount} encrypted file(s)`);
|
|
80655
80947
|
}
|
|
80656
80948
|
if (failedCount === 0) {
|
|
80657
|
-
process.exit(0);
|
|
80658
80949
|
return;
|
|
80659
80950
|
}
|
|
80660
80951
|
formatter.error(`${failedCount} cell(s) could not be scaffolded.`);
|
|
80661
80952
|
process.exit(1);
|
|
80662
80953
|
} catch (err) {
|
|
80663
|
-
|
|
80664
|
-
formatter.formatDependencyError(err);
|
|
80665
|
-
process.exit(1);
|
|
80666
|
-
return;
|
|
80667
|
-
}
|
|
80668
|
-
formatter.error(err.message);
|
|
80669
|
-
process.exit(1);
|
|
80954
|
+
handleCommandError(err);
|
|
80670
80955
|
}
|
|
80671
80956
|
});
|
|
80672
80957
|
}
|
|
@@ -80791,7 +81076,7 @@ function formatScanOutput(result) {
|
|
|
80791
81076
|
}
|
|
80792
81077
|
|
|
80793
81078
|
// src/commands/import.ts
|
|
80794
|
-
var
|
|
81079
|
+
var fs21 = __toESM(require("fs"));
|
|
80795
81080
|
var path35 = __toESM(require("path"));
|
|
80796
81081
|
init_src();
|
|
80797
81082
|
async function readStdin() {
|
|
@@ -80853,13 +81138,13 @@ function registerImportCommand(program3, deps2) {
|
|
|
80853
81138
|
if (opts.stdin) {
|
|
80854
81139
|
content = await readStdin();
|
|
80855
81140
|
} else if (source) {
|
|
80856
|
-
if (!
|
|
81141
|
+
if (!fs21.existsSync(source)) {
|
|
80857
81142
|
formatter.error(`Source file not found: ${source}`);
|
|
80858
81143
|
process.exit(2);
|
|
80859
81144
|
return;
|
|
80860
81145
|
}
|
|
80861
81146
|
try {
|
|
80862
|
-
content =
|
|
81147
|
+
content = fs21.readFileSync(source, "utf-8");
|
|
80863
81148
|
sourcePath = source;
|
|
80864
81149
|
} catch (err) {
|
|
80865
81150
|
formatter.error(`Could not read source file: ${err.message}`);
|
|
@@ -80947,13 +81232,7 @@ ${result.imported.length} imported, ${result.skipped.length} skipped, ${result.f
|
|
|
80947
81232
|
}
|
|
80948
81233
|
}
|
|
80949
81234
|
} catch (err) {
|
|
80950
|
-
|
|
80951
|
-
formatter.formatDependencyError(err);
|
|
80952
|
-
process.exit(1);
|
|
80953
|
-
return;
|
|
80954
|
-
}
|
|
80955
|
-
formatter.error(err.message);
|
|
80956
|
-
process.exit(1);
|
|
81235
|
+
handleCommandError(err);
|
|
80957
81236
|
}
|
|
80958
81237
|
}
|
|
80959
81238
|
);
|
|
@@ -81012,13 +81291,7 @@ function registerRecipientsCommand(program3, deps2) {
|
|
|
81012
81291
|
formatter.recipientItem(r.label || r.preview, r.label ? r.preview : "");
|
|
81013
81292
|
}
|
|
81014
81293
|
} catch (err) {
|
|
81015
|
-
|
|
81016
|
-
formatter.formatDependencyError(err);
|
|
81017
|
-
process.exit(1);
|
|
81018
|
-
return;
|
|
81019
|
-
}
|
|
81020
|
-
formatter.error(err.message);
|
|
81021
|
-
process.exit(1);
|
|
81294
|
+
handleCommandError(err);
|
|
81022
81295
|
}
|
|
81023
81296
|
});
|
|
81024
81297
|
recipientsCmd.command("add <key>").description(
|
|
@@ -81048,13 +81321,7 @@ function registerRecipientsCommand(program3, deps2) {
|
|
|
81048
81321
|
);
|
|
81049
81322
|
}
|
|
81050
81323
|
} catch (err) {
|
|
81051
|
-
|
|
81052
|
-
formatter.formatDependencyError(err);
|
|
81053
|
-
process.exit(1);
|
|
81054
|
-
return;
|
|
81055
|
-
}
|
|
81056
|
-
formatter.error(err.message);
|
|
81057
|
-
process.exit(1);
|
|
81324
|
+
handleCommandError(err);
|
|
81058
81325
|
}
|
|
81059
81326
|
});
|
|
81060
81327
|
recipientsCmd.command("remove <key>").description("Remove an age recipient and re-encrypt all files in the matrix.").option("-e, --environment <env>", "Scope removal to a specific environment").action(async (key, opts) => {
|
|
@@ -81162,13 +81429,7 @@ ${sym("failure")} Re-encryption failed on ${path36.basename(failedFile)}`
|
|
|
81162
81429
|
`git add clef.yaml && git add -A && git commit -m "remove recipient: ${label}${envSuffix}"`
|
|
81163
81430
|
);
|
|
81164
81431
|
} catch (err) {
|
|
81165
|
-
|
|
81166
|
-
formatter.formatDependencyError(err);
|
|
81167
|
-
process.exit(1);
|
|
81168
|
-
return;
|
|
81169
|
-
}
|
|
81170
|
-
formatter.error(err.message);
|
|
81171
|
-
process.exit(1);
|
|
81432
|
+
handleCommandError(err);
|
|
81172
81433
|
}
|
|
81173
81434
|
});
|
|
81174
81435
|
recipientsCmd.command("request").description(
|
|
@@ -81286,13 +81547,7 @@ ${sym("failure")} Re-encryption failed on ${path36.basename(failedFile)}`
|
|
|
81286
81547
|
);
|
|
81287
81548
|
}
|
|
81288
81549
|
} catch (err) {
|
|
81289
|
-
|
|
81290
|
-
formatter.formatDependencyError(err);
|
|
81291
|
-
process.exit(1);
|
|
81292
|
-
return;
|
|
81293
|
-
}
|
|
81294
|
-
formatter.error(err.message);
|
|
81295
|
-
process.exit(1);
|
|
81550
|
+
handleCommandError(err);
|
|
81296
81551
|
}
|
|
81297
81552
|
});
|
|
81298
81553
|
}
|
|
@@ -81362,14 +81617,14 @@ ${sym("failure")} Re-encryption failed on ${path36.basename(failedFile)}`);
|
|
|
81362
81617
|
}
|
|
81363
81618
|
|
|
81364
81619
|
// src/commands/merge-driver.ts
|
|
81365
|
-
var
|
|
81620
|
+
var fs22 = __toESM(require("fs"));
|
|
81366
81621
|
var path37 = __toESM(require("path"));
|
|
81367
81622
|
init_src();
|
|
81368
81623
|
async function findRepoRoot(filePath, runner2) {
|
|
81369
81624
|
try {
|
|
81370
81625
|
let dir = path37.dirname(path37.resolve(filePath));
|
|
81371
81626
|
for (let i = 0; i < 50; i++) {
|
|
81372
|
-
if (
|
|
81627
|
+
if (fs22.existsSync(path37.join(dir, "clef.yaml"))) return dir;
|
|
81373
81628
|
const parent = path37.dirname(dir);
|
|
81374
81629
|
if (parent === dir) break;
|
|
81375
81630
|
dir = parent;
|
|
@@ -81402,7 +81657,7 @@ function registerMergeDriverCommand(program3, deps2) {
|
|
|
81402
81657
|
const manifestPath = path37.join(repoRoot, "clef.yaml");
|
|
81403
81658
|
let manifest;
|
|
81404
81659
|
let environment;
|
|
81405
|
-
if (
|
|
81660
|
+
if (fs22.existsSync(manifestPath)) {
|
|
81406
81661
|
const parser = new ManifestParser();
|
|
81407
81662
|
manifest = parser.parse(manifestPath);
|
|
81408
81663
|
for (const ns of manifest.namespaces) {
|
|
@@ -81496,40 +81751,7 @@ function registerServiceCommand(program3, deps2) {
|
|
|
81496
81751
|
const parser = new ManifestParser();
|
|
81497
81752
|
const manifest = parser.parse(path38.join(repoRoot, "clef.yaml"));
|
|
81498
81753
|
const namespaces = opts.namespaces.split(",").map((s) => s.trim());
|
|
81499
|
-
|
|
81500
|
-
if (opts.kmsEnv.length > 0) {
|
|
81501
|
-
kmsEnvConfigs = {};
|
|
81502
|
-
for (const mapping of opts.kmsEnv) {
|
|
81503
|
-
const eqIdx = mapping.indexOf("=");
|
|
81504
|
-
if (eqIdx === -1) {
|
|
81505
|
-
throw new Error(
|
|
81506
|
-
`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`
|
|
81507
|
-
);
|
|
81508
|
-
}
|
|
81509
|
-
const envName = mapping.slice(0, eqIdx);
|
|
81510
|
-
const rest = mapping.slice(eqIdx + 1);
|
|
81511
|
-
const colonIdx = rest.indexOf(":");
|
|
81512
|
-
if (colonIdx === -1) {
|
|
81513
|
-
throw new Error(
|
|
81514
|
-
`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`
|
|
81515
|
-
);
|
|
81516
|
-
}
|
|
81517
|
-
const provider = rest.slice(0, colonIdx);
|
|
81518
|
-
const keyId = rest.slice(colonIdx + 1);
|
|
81519
|
-
if (!["aws", "gcp", "azure"].includes(provider)) {
|
|
81520
|
-
throw new Error(
|
|
81521
|
-
`Invalid KMS provider '${provider}'. Must be one of: aws, gcp, azure.`
|
|
81522
|
-
);
|
|
81523
|
-
}
|
|
81524
|
-
if (kmsEnvConfigs[envName]) {
|
|
81525
|
-
throw new Error(`Duplicate --kms-env for environment '${envName}'.`);
|
|
81526
|
-
}
|
|
81527
|
-
kmsEnvConfigs[envName] = {
|
|
81528
|
-
provider,
|
|
81529
|
-
keyId
|
|
81530
|
-
};
|
|
81531
|
-
}
|
|
81532
|
-
}
|
|
81754
|
+
const kmsEnvConfigs = opts.kmsEnv.length > 0 ? parseKmsEnvMappings(opts.kmsEnv) : void 0;
|
|
81533
81755
|
const hasAgeEnvs = !kmsEnvConfigs || manifest.environments.some((e) => !kmsEnvConfigs[e.name]);
|
|
81534
81756
|
const protectedEnvs = manifest.environments.filter((e) => e.protected).map((e) => e.name);
|
|
81535
81757
|
if (protectedEnvs.length > 0 && hasAgeEnvs) {
|
|
@@ -81594,13 +81816,7 @@ function registerServiceCommand(program3, deps2) {
|
|
|
81594
81816
|
`git add clef.yaml && git commit -m "feat: add service identity '${name}'"`
|
|
81595
81817
|
);
|
|
81596
81818
|
} catch (err) {
|
|
81597
|
-
|
|
81598
|
-
formatter.formatDependencyError(err);
|
|
81599
|
-
process.exit(1);
|
|
81600
|
-
return;
|
|
81601
|
-
}
|
|
81602
|
-
formatter.error(err.message);
|
|
81603
|
-
process.exit(1);
|
|
81819
|
+
handleCommandError(err);
|
|
81604
81820
|
}
|
|
81605
81821
|
}
|
|
81606
81822
|
);
|
|
@@ -81625,13 +81841,7 @@ function registerServiceCommand(program3, deps2) {
|
|
|
81625
81841
|
});
|
|
81626
81842
|
formatter.table(rows, ["Name", "Namespaces", "Environments"]);
|
|
81627
81843
|
} catch (err) {
|
|
81628
|
-
|
|
81629
|
-
formatter.formatDependencyError(err);
|
|
81630
|
-
process.exit(1);
|
|
81631
|
-
return;
|
|
81632
|
-
}
|
|
81633
|
-
formatter.error(err.message);
|
|
81634
|
-
process.exit(1);
|
|
81844
|
+
handleCommandError(err);
|
|
81635
81845
|
}
|
|
81636
81846
|
});
|
|
81637
81847
|
serviceCmd.command("show <name>").description("Show details of a service identity.").action(async (name) => {
|
|
@@ -81664,13 +81874,7 @@ Service Identity: ${identity.name}`);
|
|
|
81664
81874
|
}
|
|
81665
81875
|
formatter.print("");
|
|
81666
81876
|
} catch (err) {
|
|
81667
|
-
|
|
81668
|
-
formatter.formatDependencyError(err);
|
|
81669
|
-
process.exit(1);
|
|
81670
|
-
return;
|
|
81671
|
-
}
|
|
81672
|
-
formatter.error(err.message);
|
|
81673
|
-
process.exit(1);
|
|
81877
|
+
handleCommandError(err);
|
|
81674
81878
|
}
|
|
81675
81879
|
});
|
|
81676
81880
|
serviceCmd.command("validate").description("Validate service identity configurations and report drift issues.").action(async () => {
|
|
@@ -81705,13 +81909,7 @@ Service Identity: ${identity.name}`);
|
|
|
81705
81909
|
formatter.warn(`${warnCount} warning(s)`);
|
|
81706
81910
|
}
|
|
81707
81911
|
} catch (err) {
|
|
81708
|
-
|
|
81709
|
-
formatter.formatDependencyError(err);
|
|
81710
|
-
process.exit(1);
|
|
81711
|
-
return;
|
|
81712
|
-
}
|
|
81713
|
-
formatter.error(err.message);
|
|
81714
|
-
process.exit(1);
|
|
81912
|
+
handleCommandError(err);
|
|
81715
81913
|
}
|
|
81716
81914
|
});
|
|
81717
81915
|
serviceCmd.command("update <name>").description("Update an existing service identity's environment backends.").option(
|
|
@@ -81732,31 +81930,7 @@ Service Identity: ${identity.name}`);
|
|
|
81732
81930
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
81733
81931
|
const parser = new ManifestParser();
|
|
81734
81932
|
const manifest = parser.parse(path38.join(repoRoot, "clef.yaml"));
|
|
81735
|
-
const kmsEnvConfigs =
|
|
81736
|
-
for (const mapping of opts.kmsEnv) {
|
|
81737
|
-
const eqIdx = mapping.indexOf("=");
|
|
81738
|
-
if (eqIdx === -1) {
|
|
81739
|
-
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
81740
|
-
}
|
|
81741
|
-
const envName = mapping.slice(0, eqIdx);
|
|
81742
|
-
const rest = mapping.slice(eqIdx + 1);
|
|
81743
|
-
const colonIdx = rest.indexOf(":");
|
|
81744
|
-
if (colonIdx === -1) {
|
|
81745
|
-
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
81746
|
-
}
|
|
81747
|
-
const provider = rest.slice(0, colonIdx);
|
|
81748
|
-
const keyId = rest.slice(colonIdx + 1);
|
|
81749
|
-
if (!["aws", "gcp", "azure"].includes(provider)) {
|
|
81750
|
-
throw new Error(`Invalid KMS provider '${provider}'. Must be one of: aws, gcp, azure.`);
|
|
81751
|
-
}
|
|
81752
|
-
if (kmsEnvConfigs[envName]) {
|
|
81753
|
-
throw new Error(`Duplicate --kms-env for environment '${envName}'.`);
|
|
81754
|
-
}
|
|
81755
|
-
kmsEnvConfigs[envName] = {
|
|
81756
|
-
provider,
|
|
81757
|
-
keyId
|
|
81758
|
-
};
|
|
81759
|
-
}
|
|
81933
|
+
const kmsEnvConfigs = parseKmsEnvMappings(opts.kmsEnv);
|
|
81760
81934
|
const matrixManager = new MatrixManager();
|
|
81761
81935
|
const sopsClient = await createSopsClient(repoRoot, deps2.runner);
|
|
81762
81936
|
const manager = new ServiceIdentityManager(sopsClient, matrixManager);
|
|
@@ -81770,13 +81944,7 @@ Service Identity: ${identity.name}`);
|
|
|
81770
81944
|
`git add clef.yaml && git commit -m "chore: update service identity '${name}'"`
|
|
81771
81945
|
);
|
|
81772
81946
|
} catch (err) {
|
|
81773
|
-
|
|
81774
|
-
formatter.formatDependencyError(err);
|
|
81775
|
-
process.exit(1);
|
|
81776
|
-
return;
|
|
81777
|
-
}
|
|
81778
|
-
formatter.error(err.message);
|
|
81779
|
-
process.exit(1);
|
|
81947
|
+
handleCommandError(err);
|
|
81780
81948
|
}
|
|
81781
81949
|
});
|
|
81782
81950
|
serviceCmd.command("delete <name>").description("Delete a service identity and remove its recipients from scoped files.").action(async (name) => {
|
|
@@ -81808,13 +81976,7 @@ Service Identity: ${identity.name}`);
|
|
|
81808
81976
|
`git add clef.yaml && git commit -m "chore: delete service identity '${name}'"`
|
|
81809
81977
|
);
|
|
81810
81978
|
} catch (err) {
|
|
81811
|
-
|
|
81812
|
-
formatter.formatDependencyError(err);
|
|
81813
|
-
process.exit(1);
|
|
81814
|
-
return;
|
|
81815
|
-
}
|
|
81816
|
-
formatter.error(err.message);
|
|
81817
|
-
process.exit(1);
|
|
81979
|
+
handleCommandError(err);
|
|
81818
81980
|
}
|
|
81819
81981
|
});
|
|
81820
81982
|
serviceCmd.command("rotate <name>").description("Rotate the age key for a service identity.").option("-e, --environment <env>", "Rotate only a specific environment").action(async (name, opts) => {
|
|
@@ -81868,11 +82030,6 @@ Service Identity: ${identity.name}`);
|
|
|
81868
82030
|
`git add clef.yaml && git commit -m "chore: rotate service identity '${name}'"`
|
|
81869
82031
|
);
|
|
81870
82032
|
} catch (err) {
|
|
81871
|
-
if (err instanceof SopsMissingError || err instanceof SopsVersionError) {
|
|
81872
|
-
formatter.formatDependencyError(err);
|
|
81873
|
-
process.exit(1);
|
|
81874
|
-
return;
|
|
81875
|
-
}
|
|
81876
82033
|
if (err instanceof PartialRotationError) {
|
|
81877
82034
|
formatter.error(err.message);
|
|
81878
82035
|
const partialEntries = Object.entries(err.rotatedKeys);
|
|
@@ -81905,11 +82062,37 @@ Service Identity: ${identity.name}`);
|
|
|
81905
82062
|
process.exit(1);
|
|
81906
82063
|
return;
|
|
81907
82064
|
}
|
|
81908
|
-
|
|
81909
|
-
process.exit(1);
|
|
82065
|
+
handleCommandError(err);
|
|
81910
82066
|
}
|
|
81911
82067
|
});
|
|
81912
82068
|
}
|
|
82069
|
+
function parseKmsEnvMappings(mappings) {
|
|
82070
|
+
const configs = {};
|
|
82071
|
+
for (const mapping of mappings) {
|
|
82072
|
+
const eqIdx = mapping.indexOf("=");
|
|
82073
|
+
if (eqIdx === -1) {
|
|
82074
|
+
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
82075
|
+
}
|
|
82076
|
+
const envName = mapping.slice(0, eqIdx);
|
|
82077
|
+
const rest = mapping.slice(eqIdx + 1);
|
|
82078
|
+
const colonIdx = rest.indexOf(":");
|
|
82079
|
+
if (colonIdx === -1) {
|
|
82080
|
+
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
82081
|
+
}
|
|
82082
|
+
const provider = rest.slice(0, colonIdx);
|
|
82083
|
+
const keyId = rest.slice(colonIdx + 1);
|
|
82084
|
+
if (!VALID_KMS_PROVIDERS.includes(provider)) {
|
|
82085
|
+
throw new Error(
|
|
82086
|
+
`Invalid KMS provider '${provider}'. Must be one of: ${VALID_KMS_PROVIDERS.join(", ")}.`
|
|
82087
|
+
);
|
|
82088
|
+
}
|
|
82089
|
+
if (configs[envName]) {
|
|
82090
|
+
throw new Error(`Duplicate --kms-env for environment '${envName}'.`);
|
|
82091
|
+
}
|
|
82092
|
+
configs[envName] = { provider, keyId };
|
|
82093
|
+
}
|
|
82094
|
+
return configs;
|
|
82095
|
+
}
|
|
81913
82096
|
|
|
81914
82097
|
// src/commands/pack.ts
|
|
81915
82098
|
var path39 = __toESM(require("path"));
|
|
@@ -81983,21 +82166,14 @@ function registerPackCommand(program3, deps2) {
|
|
|
81983
82166
|
"\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"
|
|
81984
82167
|
);
|
|
81985
82168
|
} catch (err) {
|
|
81986
|
-
|
|
81987
|
-
formatter.formatDependencyError(err);
|
|
81988
|
-
process.exit(1);
|
|
81989
|
-
return;
|
|
81990
|
-
}
|
|
81991
|
-
const message = err instanceof Error ? err.message : "Pack failed";
|
|
81992
|
-
formatter.error(message);
|
|
81993
|
-
process.exit(1);
|
|
82169
|
+
handleCommandError(err);
|
|
81994
82170
|
}
|
|
81995
82171
|
}
|
|
81996
82172
|
);
|
|
81997
82173
|
}
|
|
81998
82174
|
|
|
81999
82175
|
// src/commands/revoke.ts
|
|
82000
|
-
var
|
|
82176
|
+
var fs23 = __toESM(require("fs"));
|
|
82001
82177
|
var path40 = __toESM(require("path"));
|
|
82002
82178
|
init_src();
|
|
82003
82179
|
function registerRevokeCommand(program3, _deps) {
|
|
@@ -82031,8 +82207,8 @@ function registerRevokeCommand(program3, _deps) {
|
|
|
82031
82207
|
environment,
|
|
82032
82208
|
revokedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
82033
82209
|
};
|
|
82034
|
-
|
|
82035
|
-
|
|
82210
|
+
fs23.mkdirSync(artifactDir, { recursive: true });
|
|
82211
|
+
fs23.writeFileSync(artifactPath, JSON.stringify(revoked, null, 2) + "\n", "utf-8");
|
|
82036
82212
|
const relPath = path40.relative(repoRoot, artifactPath);
|
|
82037
82213
|
formatter.success(`Artifact revoked: ${relPath}`);
|
|
82038
82214
|
formatter.print("");
|
|
@@ -82134,12 +82310,12 @@ var import_picocolors6 = __toESM(require_picocolors());
|
|
|
82134
82310
|
init_src();
|
|
82135
82311
|
|
|
82136
82312
|
// src/report/historical.ts
|
|
82137
|
-
var
|
|
82313
|
+
var os3 = __toESM(require("os"));
|
|
82138
82314
|
var path42 = __toESM(require("path"));
|
|
82139
|
-
var
|
|
82315
|
+
var fs24 = __toESM(require("fs"));
|
|
82140
82316
|
init_src();
|
|
82141
82317
|
async function generateReportAtCommit(repoRoot, commitSha, clefVersion, runner2) {
|
|
82142
|
-
const tmpDir = path42.join(
|
|
82318
|
+
const tmpDir = path42.join(os3.tmpdir(), `clef-report-${commitSha.slice(0, 8)}-${Date.now()}`);
|
|
82143
82319
|
try {
|
|
82144
82320
|
const addResult = await runner2.run("git", ["worktree", "add", tmpDir, commitSha, "--detach"], {
|
|
82145
82321
|
cwd: repoRoot
|
|
@@ -82157,7 +82333,7 @@ async function generateReportAtCommit(repoRoot, commitSha, clefVersion, runner2)
|
|
|
82157
82333
|
await runner2.run("git", ["worktree", "remove", tmpDir, "--force"], { cwd: repoRoot });
|
|
82158
82334
|
} catch {
|
|
82159
82335
|
try {
|
|
82160
|
-
|
|
82336
|
+
fs24.rmSync(tmpDir, { recursive: true, force: true });
|
|
82161
82337
|
await runner2.run("git", ["worktree", "prune"], { cwd: repoRoot });
|
|
82162
82338
|
} catch {
|
|
82163
82339
|
}
|
|
@@ -82247,13 +82423,7 @@ function registerReportCommand(program3, deps2) {
|
|
|
82247
82423
|
}
|
|
82248
82424
|
outputReport(headReport, options);
|
|
82249
82425
|
} catch (err) {
|
|
82250
|
-
|
|
82251
|
-
formatter.formatDependencyError(err);
|
|
82252
|
-
process.exit(1);
|
|
82253
|
-
return;
|
|
82254
|
-
}
|
|
82255
|
-
formatter.error(err.message);
|
|
82256
|
-
process.exit(1);
|
|
82426
|
+
handleCommandError(err);
|
|
82257
82427
|
}
|
|
82258
82428
|
}
|
|
82259
82429
|
);
|
|
@@ -82384,7 +82554,7 @@ function formatReportOutput(report) {
|
|
|
82384
82554
|
}
|
|
82385
82555
|
|
|
82386
82556
|
// src/commands/install.ts
|
|
82387
|
-
var
|
|
82557
|
+
var fs25 = __toESM(require("fs"));
|
|
82388
82558
|
var path43 = __toESM(require("path"));
|
|
82389
82559
|
var import_yaml = __toESM(require_dist());
|
|
82390
82560
|
|
|
@@ -82434,7 +82604,7 @@ function registerInstallCommand(program3, _deps) {
|
|
|
82434
82604
|
return;
|
|
82435
82605
|
}
|
|
82436
82606
|
const brokerDir = path43.join(repoRoot, "brokers", entry.name);
|
|
82437
|
-
if (
|
|
82607
|
+
if (fs25.existsSync(brokerDir) && !options.force) {
|
|
82438
82608
|
const overwrite = await formatter.confirm(
|
|
82439
82609
|
`brokers/${entry.name}/ already exists. Overwrite?`
|
|
82440
82610
|
);
|
|
@@ -82465,11 +82635,11 @@ function registerInstallCommand(program3, _deps) {
|
|
|
82465
82635
|
process.exit(1);
|
|
82466
82636
|
return;
|
|
82467
82637
|
}
|
|
82468
|
-
if (!
|
|
82469
|
-
|
|
82638
|
+
if (!fs25.existsSync(brokerDir)) {
|
|
82639
|
+
fs25.mkdirSync(brokerDir, { recursive: true });
|
|
82470
82640
|
}
|
|
82471
82641
|
for (const file of files) {
|
|
82472
|
-
|
|
82642
|
+
fs25.writeFileSync(path43.join(brokerDir, file.name), file.content, "utf-8");
|
|
82473
82643
|
}
|
|
82474
82644
|
const manifestFile = files.find((f) => f.name === "broker.yaml");
|
|
82475
82645
|
const manifest = manifestFile ? (0, import_yaml.parse)(manifestFile.content) : {};
|