@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.mjs
CHANGED
|
@@ -977,7 +977,7 @@ var require_command = __commonJS({
|
|
|
977
977
|
var EventEmitter = __require("node:events").EventEmitter;
|
|
978
978
|
var childProcess = __require("node:child_process");
|
|
979
979
|
var path44 = __require("node:path");
|
|
980
|
-
var
|
|
980
|
+
var fs26 = __require("node:fs");
|
|
981
981
|
var process2 = __require("node:process");
|
|
982
982
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
983
983
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1910,10 +1910,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1910
1910
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1911
1911
|
function findFile(baseDir, baseName) {
|
|
1912
1912
|
const localBin = path44.resolve(baseDir, baseName);
|
|
1913
|
-
if (
|
|
1913
|
+
if (fs26.existsSync(localBin)) return localBin;
|
|
1914
1914
|
if (sourceExt.includes(path44.extname(baseName))) return void 0;
|
|
1915
1915
|
const foundExt = sourceExt.find(
|
|
1916
|
-
(ext) =>
|
|
1916
|
+
(ext) => fs26.existsSync(`${localBin}${ext}`)
|
|
1917
1917
|
);
|
|
1918
1918
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1919
1919
|
return void 0;
|
|
@@ -1925,7 +1925,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1925
1925
|
if (this._scriptPath) {
|
|
1926
1926
|
let resolvedScriptPath;
|
|
1927
1927
|
try {
|
|
1928
|
-
resolvedScriptPath =
|
|
1928
|
+
resolvedScriptPath = fs26.realpathSync(this._scriptPath);
|
|
1929
1929
|
} catch (err) {
|
|
1930
1930
|
resolvedScriptPath = this._scriptPath;
|
|
1931
1931
|
}
|
|
@@ -9876,14 +9876,14 @@ var require_parser = __commonJS({
|
|
|
9876
9876
|
case "scalar":
|
|
9877
9877
|
case "single-quoted-scalar":
|
|
9878
9878
|
case "double-quoted-scalar": {
|
|
9879
|
-
const
|
|
9879
|
+
const fs26 = this.flowScalar(this.type);
|
|
9880
9880
|
if (atNextItem || it.value) {
|
|
9881
|
-
map.items.push({ start, key:
|
|
9881
|
+
map.items.push({ start, key: fs26, sep: [] });
|
|
9882
9882
|
this.onKeyLine = true;
|
|
9883
9883
|
} else if (it.sep) {
|
|
9884
|
-
this.stack.push(
|
|
9884
|
+
this.stack.push(fs26);
|
|
9885
9885
|
} else {
|
|
9886
|
-
Object.assign(it, { key:
|
|
9886
|
+
Object.assign(it, { key: fs26, sep: [] });
|
|
9887
9887
|
this.onKeyLine = true;
|
|
9888
9888
|
}
|
|
9889
9889
|
return;
|
|
@@ -10011,13 +10011,13 @@ var require_parser = __commonJS({
|
|
|
10011
10011
|
case "scalar":
|
|
10012
10012
|
case "single-quoted-scalar":
|
|
10013
10013
|
case "double-quoted-scalar": {
|
|
10014
|
-
const
|
|
10014
|
+
const fs26 = this.flowScalar(this.type);
|
|
10015
10015
|
if (!it || it.value)
|
|
10016
|
-
fc.items.push({ start: [], key:
|
|
10016
|
+
fc.items.push({ start: [], key: fs26, sep: [] });
|
|
10017
10017
|
else if (it.sep)
|
|
10018
|
-
this.stack.push(
|
|
10018
|
+
this.stack.push(fs26);
|
|
10019
10019
|
else
|
|
10020
|
-
Object.assign(it, { key:
|
|
10020
|
+
Object.assign(it, { key: fs26, sep: [] });
|
|
10021
10021
|
return;
|
|
10022
10022
|
}
|
|
10023
10023
|
case "flow-map-end":
|
|
@@ -10225,7 +10225,7 @@ var require_public_api = __commonJS({
|
|
|
10225
10225
|
}
|
|
10226
10226
|
return doc;
|
|
10227
10227
|
}
|
|
10228
|
-
function
|
|
10228
|
+
function parse15(src, reviver, options) {
|
|
10229
10229
|
let _reviver = void 0;
|
|
10230
10230
|
if (typeof reviver === "function") {
|
|
10231
10231
|
_reviver = reviver;
|
|
@@ -10266,7 +10266,7 @@ var require_public_api = __commonJS({
|
|
|
10266
10266
|
return value.toString(options);
|
|
10267
10267
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
10268
10268
|
}
|
|
10269
|
-
exports.parse =
|
|
10269
|
+
exports.parse = parse15;
|
|
10270
10270
|
exports.parseAllDocuments = parseAllDocuments;
|
|
10271
10271
|
exports.parseDocument = parseDocument;
|
|
10272
10272
|
exports.stringify = stringify7;
|
|
@@ -10747,6 +10747,12 @@ var init_parser = __esm({
|
|
|
10747
10747
|
"namespaces"
|
|
10748
10748
|
);
|
|
10749
10749
|
}
|
|
10750
|
+
if (!ENV_NAME_PATTERN.test(nsObj.name)) {
|
|
10751
|
+
throw new ManifestValidationError(
|
|
10752
|
+
`Namespace name '${nsObj.name}' is invalid. Names must start with a lowercase letter and contain only lowercase letters, digits, hyphens, and underscores.`,
|
|
10753
|
+
"namespaces"
|
|
10754
|
+
);
|
|
10755
|
+
}
|
|
10750
10756
|
if (!nsObj.description || typeof nsObj.description !== "string") {
|
|
10751
10757
|
throw new ManifestValidationError(
|
|
10752
10758
|
`Namespace '${nsObj.name}' is missing a 'description' string.`,
|
|
@@ -10847,9 +10853,9 @@ var init_parser = __esm({
|
|
|
10847
10853
|
);
|
|
10848
10854
|
}
|
|
10849
10855
|
const siName = siObj.name;
|
|
10850
|
-
if (
|
|
10856
|
+
if (siObj.description != null && typeof siObj.description !== "string") {
|
|
10851
10857
|
throw new ManifestValidationError(
|
|
10852
|
-
`Service identity '${siName}'
|
|
10858
|
+
`Service identity '${siName}' has a non-string 'description'.`,
|
|
10853
10859
|
"service_identities"
|
|
10854
10860
|
);
|
|
10855
10861
|
}
|
|
@@ -10964,7 +10970,7 @@ var init_parser = __esm({
|
|
|
10964
10970
|
}
|
|
10965
10971
|
return {
|
|
10966
10972
|
name: siName,
|
|
10967
|
-
description: siObj.description,
|
|
10973
|
+
description: siObj.description ?? "",
|
|
10968
10974
|
namespaces: siObj.namespaces,
|
|
10969
10975
|
environments: parsedEnvs
|
|
10970
10976
|
};
|
|
@@ -11164,7 +11170,11 @@ var init_scanner = __esm({
|
|
|
11164
11170
|
init_patterns();
|
|
11165
11171
|
init_ignore();
|
|
11166
11172
|
ALWAYS_SKIP_EXTENSIONS = [".enc.yaml", ".enc.json"];
|
|
11167
|
-
ALWAYS_SKIP_NAMES = [
|
|
11173
|
+
ALWAYS_SKIP_NAMES = [
|
|
11174
|
+
".clef-meta.yaml",
|
|
11175
|
+
".sops.yaml"
|
|
11176
|
+
// contains age public keys and KMS ARNs — configuration, not secrets
|
|
11177
|
+
];
|
|
11168
11178
|
ALWAYS_SKIP_DIRS = ["node_modules", ".git"];
|
|
11169
11179
|
MAX_FILE_SIZE = 1024 * 1024;
|
|
11170
11180
|
ScanRunner = class {
|
|
@@ -11460,15 +11470,36 @@ var init_metadata = __esm({
|
|
|
11460
11470
|
}
|
|
11461
11471
|
});
|
|
11462
11472
|
|
|
11463
|
-
// ../core/src/
|
|
11473
|
+
// ../core/src/sops/keys.ts
|
|
11464
11474
|
import * as fs5 from "fs";
|
|
11475
|
+
function readSopsKeyNames(filePath) {
|
|
11476
|
+
try {
|
|
11477
|
+
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
11478
|
+
const parsed = YAML3.parse(raw);
|
|
11479
|
+
if (parsed === null || parsed === void 0 || typeof parsed !== "object") return null;
|
|
11480
|
+
return Object.keys(parsed).filter((k) => k !== "sops");
|
|
11481
|
+
} catch {
|
|
11482
|
+
return null;
|
|
11483
|
+
}
|
|
11484
|
+
}
|
|
11485
|
+
var YAML3;
|
|
11486
|
+
var init_keys = __esm({
|
|
11487
|
+
"../core/src/sops/keys.ts"() {
|
|
11488
|
+
"use strict";
|
|
11489
|
+
YAML3 = __toESM(require_dist());
|
|
11490
|
+
}
|
|
11491
|
+
});
|
|
11492
|
+
|
|
11493
|
+
// ../core/src/matrix/manager.ts
|
|
11494
|
+
import * as fs6 from "fs";
|
|
11465
11495
|
import * as path4 from "path";
|
|
11466
|
-
var
|
|
11496
|
+
var YAML4, MatrixManager;
|
|
11467
11497
|
var init_manager = __esm({
|
|
11468
11498
|
"../core/src/matrix/manager.ts"() {
|
|
11469
11499
|
"use strict";
|
|
11470
|
-
|
|
11500
|
+
YAML4 = __toESM(require_dist());
|
|
11471
11501
|
init_metadata();
|
|
11502
|
+
init_keys();
|
|
11472
11503
|
MatrixManager = class {
|
|
11473
11504
|
/**
|
|
11474
11505
|
* Build the full grid of {@link MatrixCell} objects from the manifest.
|
|
@@ -11487,7 +11518,7 @@ var init_manager = __esm({
|
|
|
11487
11518
|
namespace: ns.name,
|
|
11488
11519
|
environment: env.name,
|
|
11489
11520
|
filePath,
|
|
11490
|
-
exists:
|
|
11521
|
+
exists: fs6.existsSync(filePath)
|
|
11491
11522
|
});
|
|
11492
11523
|
}
|
|
11493
11524
|
}
|
|
@@ -11511,8 +11542,8 @@ var init_manager = __esm({
|
|
|
11511
11542
|
*/
|
|
11512
11543
|
async scaffoldCell(cell, sopsClient, manifest) {
|
|
11513
11544
|
const dir = path4.dirname(cell.filePath);
|
|
11514
|
-
if (!
|
|
11515
|
-
|
|
11545
|
+
if (!fs6.existsSync(dir)) {
|
|
11546
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
11516
11547
|
}
|
|
11517
11548
|
await sopsClient.encrypt(cell.filePath, {}, manifest, cell.environment);
|
|
11518
11549
|
}
|
|
@@ -11581,22 +11612,15 @@ var init_manager = __esm({
|
|
|
11581
11612
|
* SOPS stores key names in plaintext — only values are encrypted.
|
|
11582
11613
|
*/
|
|
11583
11614
|
readKeyNames(filePath) {
|
|
11584
|
-
|
|
11585
|
-
const raw = fs5.readFileSync(filePath, "utf-8");
|
|
11586
|
-
const parsed = YAML3.parse(raw);
|
|
11587
|
-
if (!parsed || typeof parsed !== "object") return [];
|
|
11588
|
-
return Object.keys(parsed).filter((k) => k !== "sops");
|
|
11589
|
-
} catch {
|
|
11590
|
-
return [];
|
|
11591
|
-
}
|
|
11615
|
+
return readSopsKeyNames(filePath) ?? [];
|
|
11592
11616
|
}
|
|
11593
11617
|
/**
|
|
11594
11618
|
* Read the lastModified timestamp from SOPS metadata without decryption.
|
|
11595
11619
|
*/
|
|
11596
11620
|
readLastModified(filePath) {
|
|
11597
11621
|
try {
|
|
11598
|
-
const raw =
|
|
11599
|
-
const parsed =
|
|
11622
|
+
const raw = fs6.readFileSync(filePath, "utf-8");
|
|
11623
|
+
const parsed = YAML4.parse(raw);
|
|
11600
11624
|
const sops = parsed?.sops;
|
|
11601
11625
|
if (sops?.lastmodified) return new Date(String(sops.lastmodified));
|
|
11602
11626
|
return null;
|
|
@@ -11619,12 +11643,12 @@ var init_manager = __esm({
|
|
|
11619
11643
|
});
|
|
11620
11644
|
|
|
11621
11645
|
// ../core/src/schema/validator.ts
|
|
11622
|
-
import * as
|
|
11623
|
-
var
|
|
11646
|
+
import * as fs7 from "fs";
|
|
11647
|
+
var YAML5, SchemaValidator;
|
|
11624
11648
|
var init_validator2 = __esm({
|
|
11625
11649
|
"../core/src/schema/validator.ts"() {
|
|
11626
11650
|
"use strict";
|
|
11627
|
-
|
|
11651
|
+
YAML5 = __toESM(require_dist());
|
|
11628
11652
|
init_types();
|
|
11629
11653
|
SchemaValidator = class {
|
|
11630
11654
|
/**
|
|
@@ -11637,13 +11661,13 @@ var init_validator2 = __esm({
|
|
|
11637
11661
|
loadSchema(filePath) {
|
|
11638
11662
|
let raw;
|
|
11639
11663
|
try {
|
|
11640
|
-
raw =
|
|
11664
|
+
raw = fs7.readFileSync(filePath, "utf-8");
|
|
11641
11665
|
} catch {
|
|
11642
11666
|
throw new SchemaLoadError(`Could not read schema file at '${filePath}'.`, filePath);
|
|
11643
11667
|
}
|
|
11644
11668
|
let parsed;
|
|
11645
11669
|
try {
|
|
11646
|
-
parsed =
|
|
11670
|
+
parsed = YAML5.parse(raw);
|
|
11647
11671
|
} catch {
|
|
11648
11672
|
throw new SchemaLoadError(`Schema file '${filePath}' contains invalid YAML.`, filePath);
|
|
11649
11673
|
}
|
|
@@ -11958,7 +11982,7 @@ ${details}`
|
|
|
11958
11982
|
});
|
|
11959
11983
|
|
|
11960
11984
|
// ../core/src/git/integration.ts
|
|
11961
|
-
import * as
|
|
11985
|
+
import * as fs8 from "fs";
|
|
11962
11986
|
import * as path7 from "path";
|
|
11963
11987
|
var PRE_COMMIT_HOOK, GitIntegration;
|
|
11964
11988
|
var init_integration = __esm({
|
|
@@ -12172,14 +12196,14 @@ exit $EXIT_CODE
|
|
|
12172
12196
|
});
|
|
12173
12197
|
const gitConfig = configResult.exitCode === 0 && configResult.stdout.trim().length > 0;
|
|
12174
12198
|
const attrFilePath = path7.join(repoRoot, ".gitattributes");
|
|
12175
|
-
const attrContent =
|
|
12199
|
+
const attrContent = fs8.existsSync(attrFilePath) ? fs8.readFileSync(attrFilePath, "utf-8") : "";
|
|
12176
12200
|
const gitattributes = attrContent.includes("merge=sops");
|
|
12177
12201
|
return { gitConfig, gitattributes };
|
|
12178
12202
|
}
|
|
12179
12203
|
async ensureGitattributes(repoRoot) {
|
|
12180
12204
|
const attrPath = path7.join(repoRoot, ".gitattributes");
|
|
12181
12205
|
const mergeRule = "*.enc.yaml merge=sops\n*.enc.json merge=sops";
|
|
12182
|
-
const existing =
|
|
12206
|
+
const existing = fs8.existsSync(attrPath) ? fs8.readFileSync(attrPath, "utf-8") : "";
|
|
12183
12207
|
if (existing.includes("merge=sops")) {
|
|
12184
12208
|
return;
|
|
12185
12209
|
}
|
|
@@ -12229,7 +12253,7 @@ ${mergeRule}
|
|
|
12229
12253
|
});
|
|
12230
12254
|
|
|
12231
12255
|
// ../core/src/sops/bundled.ts
|
|
12232
|
-
import * as
|
|
12256
|
+
import * as fs9 from "fs";
|
|
12233
12257
|
import * as path8 from "path";
|
|
12234
12258
|
function tryBundled() {
|
|
12235
12259
|
const platform = process.platform;
|
|
@@ -12244,7 +12268,7 @@ function tryBundled() {
|
|
|
12244
12268
|
const packageMain = __require.resolve(`${packageName}/package.json`);
|
|
12245
12269
|
const packageDir = path8.dirname(packageMain);
|
|
12246
12270
|
const binPath = path8.join(packageDir, "bin", binName);
|
|
12247
|
-
return
|
|
12271
|
+
return fs9.existsSync(binPath) ? binPath : null;
|
|
12248
12272
|
} catch {
|
|
12249
12273
|
return null;
|
|
12250
12274
|
}
|
|
@@ -12256,7 +12280,7 @@ var init_bundled = __esm({
|
|
|
12256
12280
|
});
|
|
12257
12281
|
|
|
12258
12282
|
// ../core/src/sops/resolver.ts
|
|
12259
|
-
import * as
|
|
12283
|
+
import * as fs10 from "fs";
|
|
12260
12284
|
import * as path9 from "path";
|
|
12261
12285
|
function validateSopsPath(candidate) {
|
|
12262
12286
|
if (!path9.isAbsolute(candidate)) {
|
|
@@ -12274,7 +12298,7 @@ function resolveSopsPath() {
|
|
|
12274
12298
|
const envPath = process.env.CLEF_SOPS_PATH?.trim();
|
|
12275
12299
|
if (envPath) {
|
|
12276
12300
|
validateSopsPath(envPath);
|
|
12277
|
-
if (!
|
|
12301
|
+
if (!fs10.existsSync(envPath)) {
|
|
12278
12302
|
throw new Error(`CLEF_SOPS_PATH points to '${envPath}' but the file does not exist.`);
|
|
12279
12303
|
}
|
|
12280
12304
|
cached = { path: envPath, source: "env" };
|
|
@@ -19693,7 +19717,7 @@ var init_keygen = __esm({
|
|
|
19693
19717
|
});
|
|
19694
19718
|
|
|
19695
19719
|
// ../core/src/sops/client.ts
|
|
19696
|
-
import * as
|
|
19720
|
+
import * as fs11 from "fs";
|
|
19697
19721
|
import * as net from "net";
|
|
19698
19722
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
19699
19723
|
function formatFromPath(filePath) {
|
|
@@ -19717,11 +19741,11 @@ function openWindowsInputPipe(content) {
|
|
|
19717
19741
|
});
|
|
19718
19742
|
});
|
|
19719
19743
|
}
|
|
19720
|
-
var
|
|
19744
|
+
var YAML6, SopsClient;
|
|
19721
19745
|
var init_client = __esm({
|
|
19722
19746
|
"../core/src/sops/client.ts"() {
|
|
19723
19747
|
"use strict";
|
|
19724
|
-
|
|
19748
|
+
YAML6 = __toESM(require_dist());
|
|
19725
19749
|
init_types();
|
|
19726
19750
|
init_checker();
|
|
19727
19751
|
init_keygen();
|
|
@@ -19786,7 +19810,7 @@ var init_client = __esm({
|
|
|
19786
19810
|
}
|
|
19787
19811
|
let parsed;
|
|
19788
19812
|
try {
|
|
19789
|
-
parsed =
|
|
19813
|
+
parsed = YAML6.parse(result.stdout) ?? {};
|
|
19790
19814
|
} catch {
|
|
19791
19815
|
throw new SopsDecryptionError(
|
|
19792
19816
|
`Decrypted content of '${filePath}' is not valid YAML.`,
|
|
@@ -19813,7 +19837,7 @@ var init_client = __esm({
|
|
|
19813
19837
|
async encrypt(filePath, values, manifest, environment) {
|
|
19814
19838
|
await assertSops(this.runner, this.sopsCommand);
|
|
19815
19839
|
const fmt = formatFromPath(filePath);
|
|
19816
|
-
const content = fmt === "json" ? JSON.stringify(values, null, 2) :
|
|
19840
|
+
const content = fmt === "json" ? JSON.stringify(values, null, 2) : YAML6.stringify(values);
|
|
19817
19841
|
const args = this.buildEncryptArgs(filePath, manifest, environment);
|
|
19818
19842
|
const env = this.buildSopsEnv();
|
|
19819
19843
|
let inputArg;
|
|
@@ -19857,7 +19881,7 @@ var init_client = __esm({
|
|
|
19857
19881
|
);
|
|
19858
19882
|
}
|
|
19859
19883
|
try {
|
|
19860
|
-
|
|
19884
|
+
fs11.writeFileSync(filePath, result.stdout);
|
|
19861
19885
|
} catch {
|
|
19862
19886
|
throw new SopsEncryptionError(`Failed to write encrypted data to '${filePath}'.`, filePath);
|
|
19863
19887
|
}
|
|
@@ -19870,21 +19894,7 @@ var init_client = __esm({
|
|
|
19870
19894
|
* @throws {@link SopsEncryptionError} On failure.
|
|
19871
19895
|
*/
|
|
19872
19896
|
async reEncrypt(filePath, newKey) {
|
|
19873
|
-
await
|
|
19874
|
-
const env = this.buildSopsEnv();
|
|
19875
|
-
const result = await this.runner.run(
|
|
19876
|
-
this.sopsCommand,
|
|
19877
|
-
["rotate", "-i", "--add-age", newKey, filePath],
|
|
19878
|
-
{
|
|
19879
|
-
...env ? { env } : {}
|
|
19880
|
-
}
|
|
19881
|
-
);
|
|
19882
|
-
if (result.exitCode !== 0) {
|
|
19883
|
-
throw new SopsEncryptionError(
|
|
19884
|
-
`Failed to re-encrypt '${filePath}': ${result.stderr.trim()}`,
|
|
19885
|
-
filePath
|
|
19886
|
-
);
|
|
19887
|
-
}
|
|
19897
|
+
await this.addRecipient(filePath, newKey);
|
|
19888
19898
|
}
|
|
19889
19899
|
/**
|
|
19890
19900
|
* Add an age recipient to an existing SOPS file.
|
|
@@ -19987,7 +19997,7 @@ var init_client = __esm({
|
|
|
19987
19997
|
if (!this.ageKey && !this.ageKeyFile) return "key-not-found";
|
|
19988
19998
|
let keyContent;
|
|
19989
19999
|
try {
|
|
19990
|
-
keyContent = this.ageKey ??
|
|
20000
|
+
keyContent = this.ageKey ?? fs11.readFileSync(this.ageKeyFile, "utf-8");
|
|
19991
20001
|
} catch {
|
|
19992
20002
|
return "key-not-found";
|
|
19993
20003
|
}
|
|
@@ -20004,7 +20014,7 @@ var init_client = __esm({
|
|
|
20004
20014
|
parseMetadataFromFile(filePath) {
|
|
20005
20015
|
let content;
|
|
20006
20016
|
try {
|
|
20007
|
-
content =
|
|
20017
|
+
content = fs11.readFileSync(filePath, "utf-8");
|
|
20008
20018
|
} catch {
|
|
20009
20019
|
throw new SopsDecryptionError(
|
|
20010
20020
|
`Could not read file '${filePath}' to extract SOPS metadata.`,
|
|
@@ -20013,7 +20023,7 @@ var init_client = __esm({
|
|
|
20013
20023
|
}
|
|
20014
20024
|
let parsed;
|
|
20015
20025
|
try {
|
|
20016
|
-
parsed =
|
|
20026
|
+
parsed = YAML6.parse(content);
|
|
20017
20027
|
} catch {
|
|
20018
20028
|
throw new SopsDecryptionError(
|
|
20019
20029
|
`File '${filePath}' is not valid YAML. Cannot extract SOPS metadata.`,
|
|
@@ -20481,7 +20491,7 @@ function detectFormat(filePath, content) {
|
|
|
20481
20491
|
} catch {
|
|
20482
20492
|
}
|
|
20483
20493
|
try {
|
|
20484
|
-
const parsed =
|
|
20494
|
+
const parsed = YAML7.parse(content);
|
|
20485
20495
|
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
20486
20496
|
return "yaml";
|
|
20487
20497
|
}
|
|
@@ -20562,7 +20572,7 @@ function parseJson(content) {
|
|
|
20562
20572
|
function parseYaml(content) {
|
|
20563
20573
|
let parsed;
|
|
20564
20574
|
try {
|
|
20565
|
-
parsed =
|
|
20575
|
+
parsed = YAML7.parse(content);
|
|
20566
20576
|
} catch (err) {
|
|
20567
20577
|
throw new Error(`Invalid YAML: ${err.message}`);
|
|
20568
20578
|
}
|
|
@@ -20596,7 +20606,7 @@ function parseYaml(content) {
|
|
|
20596
20606
|
}
|
|
20597
20607
|
return { pairs, format: "yaml", skipped, warnings };
|
|
20598
20608
|
}
|
|
20599
|
-
function
|
|
20609
|
+
function parse8(content, format, filePath) {
|
|
20600
20610
|
const resolved = format === "auto" ? detectFormat(filePath ?? "", content) : format;
|
|
20601
20611
|
switch (resolved) {
|
|
20602
20612
|
case "dotenv":
|
|
@@ -20607,11 +20617,11 @@ function parse7(content, format, filePath) {
|
|
|
20607
20617
|
return parseYaml(content);
|
|
20608
20618
|
}
|
|
20609
20619
|
}
|
|
20610
|
-
var
|
|
20620
|
+
var YAML7;
|
|
20611
20621
|
var init_parsers = __esm({
|
|
20612
20622
|
"../core/src/import/parsers.ts"() {
|
|
20613
20623
|
"use strict";
|
|
20614
|
-
|
|
20624
|
+
YAML7 = __toESM(require_dist());
|
|
20615
20625
|
}
|
|
20616
20626
|
});
|
|
20617
20627
|
|
|
@@ -20642,7 +20652,7 @@ var init_import = __esm({
|
|
|
20642
20652
|
repoRoot,
|
|
20643
20653
|
manifest.file_pattern.replace("{namespace}", ns).replace("{environment}", env)
|
|
20644
20654
|
);
|
|
20645
|
-
const parsed =
|
|
20655
|
+
const parsed = parse8(content, options.format ?? "auto", sourcePath ?? "");
|
|
20646
20656
|
let candidates = Object.entries(parsed.pairs);
|
|
20647
20657
|
if (options.prefix) {
|
|
20648
20658
|
const prefix2 = options.prefix;
|
|
@@ -20698,7 +20708,7 @@ var init_import = __esm({
|
|
|
20698
20708
|
});
|
|
20699
20709
|
|
|
20700
20710
|
// ../core/src/recipients/index.ts
|
|
20701
|
-
import * as
|
|
20711
|
+
import * as fs12 from "fs";
|
|
20702
20712
|
import * as path13 from "path";
|
|
20703
20713
|
function parseRecipientEntry(entry) {
|
|
20704
20714
|
if (typeof entry === "string") {
|
|
@@ -20722,12 +20732,12 @@ function toRecipient(entry) {
|
|
|
20722
20732
|
}
|
|
20723
20733
|
function readManifestYaml(repoRoot) {
|
|
20724
20734
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20725
|
-
const raw =
|
|
20726
|
-
return
|
|
20735
|
+
const raw = fs12.readFileSync(manifestPath, "utf-8");
|
|
20736
|
+
return YAML8.parse(raw);
|
|
20727
20737
|
}
|
|
20728
20738
|
function writeManifestYaml(repoRoot, doc) {
|
|
20729
20739
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20730
|
-
|
|
20740
|
+
fs12.writeFileSync(manifestPath, YAML8.stringify(doc), "utf-8");
|
|
20731
20741
|
}
|
|
20732
20742
|
function getRecipientsArray(doc) {
|
|
20733
20743
|
const sops = doc.sops;
|
|
@@ -20775,11 +20785,11 @@ function ensureEnvironmentRecipientsArray(doc, envName) {
|
|
|
20775
20785
|
}
|
|
20776
20786
|
return env.recipients;
|
|
20777
20787
|
}
|
|
20778
|
-
var
|
|
20788
|
+
var YAML8, RecipientManager;
|
|
20779
20789
|
var init_recipients2 = __esm({
|
|
20780
20790
|
"../core/src/recipients/index.ts"() {
|
|
20781
20791
|
"use strict";
|
|
20782
|
-
|
|
20792
|
+
YAML8 = __toESM(require_dist());
|
|
20783
20793
|
init_validator();
|
|
20784
20794
|
init_parser();
|
|
20785
20795
|
RecipientManager = class {
|
|
@@ -20835,7 +20845,7 @@ var init_recipients2 = __esm({
|
|
|
20835
20845
|
throw new Error(`Recipient '${keyPreview(normalizedKey)}' is already present.`);
|
|
20836
20846
|
}
|
|
20837
20847
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20838
|
-
const manifestBackup =
|
|
20848
|
+
const manifestBackup = fs12.readFileSync(manifestPath, "utf-8");
|
|
20839
20849
|
const recipients = environment ? ensureEnvironmentRecipientsArray(doc, environment) : ensureRecipientsArray(doc);
|
|
20840
20850
|
if (label2) {
|
|
20841
20851
|
recipients.push({ key: normalizedKey, label: label2 });
|
|
@@ -20850,16 +20860,16 @@ var init_recipients2 = __esm({
|
|
|
20850
20860
|
const fileBackups = /* @__PURE__ */ new Map();
|
|
20851
20861
|
for (const cell of cells) {
|
|
20852
20862
|
try {
|
|
20853
|
-
fileBackups.set(cell.filePath,
|
|
20863
|
+
fileBackups.set(cell.filePath, fs12.readFileSync(cell.filePath, "utf-8"));
|
|
20854
20864
|
await this.encryption.addRecipient(cell.filePath, normalizedKey);
|
|
20855
20865
|
reEncryptedFiles.push(cell.filePath);
|
|
20856
20866
|
} catch {
|
|
20857
20867
|
failedFiles.push(cell.filePath);
|
|
20858
|
-
|
|
20868
|
+
fs12.writeFileSync(manifestPath, manifestBackup, "utf-8");
|
|
20859
20869
|
for (const reEncryptedFile of reEncryptedFiles) {
|
|
20860
20870
|
const backup = fileBackups.get(reEncryptedFile);
|
|
20861
20871
|
if (backup) {
|
|
20862
|
-
|
|
20872
|
+
fs12.writeFileSync(reEncryptedFile, backup, "utf-8");
|
|
20863
20873
|
}
|
|
20864
20874
|
}
|
|
20865
20875
|
const restoredDoc = readManifestYaml(repoRoot);
|
|
@@ -20913,7 +20923,7 @@ var init_recipients2 = __esm({
|
|
|
20913
20923
|
}
|
|
20914
20924
|
const removedEntry = parsed[matchIndex];
|
|
20915
20925
|
const manifestPath = path13.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
20916
|
-
const manifestBackup =
|
|
20926
|
+
const manifestBackup = fs12.readFileSync(manifestPath, "utf-8");
|
|
20917
20927
|
const recipients = environment ? ensureEnvironmentRecipientsArray(doc, environment) : ensureRecipientsArray(doc);
|
|
20918
20928
|
recipients.splice(matchIndex, 1);
|
|
20919
20929
|
writeManifestYaml(repoRoot, doc);
|
|
@@ -20924,16 +20934,16 @@ var init_recipients2 = __esm({
|
|
|
20924
20934
|
const fileBackups = /* @__PURE__ */ new Map();
|
|
20925
20935
|
for (const cell of cells) {
|
|
20926
20936
|
try {
|
|
20927
|
-
fileBackups.set(cell.filePath,
|
|
20937
|
+
fileBackups.set(cell.filePath, fs12.readFileSync(cell.filePath, "utf-8"));
|
|
20928
20938
|
await this.encryption.removeRecipient(cell.filePath, trimmedKey);
|
|
20929
20939
|
reEncryptedFiles.push(cell.filePath);
|
|
20930
20940
|
} catch {
|
|
20931
20941
|
failedFiles.push(cell.filePath);
|
|
20932
|
-
|
|
20942
|
+
fs12.writeFileSync(manifestPath, manifestBackup, "utf-8");
|
|
20933
20943
|
for (const reEncryptedFile of reEncryptedFiles) {
|
|
20934
20944
|
const backup = fileBackups.get(reEncryptedFile);
|
|
20935
20945
|
if (backup) {
|
|
20936
|
-
|
|
20946
|
+
fs12.writeFileSync(reEncryptedFile, backup, "utf-8");
|
|
20937
20947
|
}
|
|
20938
20948
|
}
|
|
20939
20949
|
const restoredDoc = readManifestYaml(repoRoot);
|
|
@@ -20969,7 +20979,7 @@ var init_recipients2 = __esm({
|
|
|
20969
20979
|
});
|
|
20970
20980
|
|
|
20971
20981
|
// ../core/src/recipients/requests.ts
|
|
20972
|
-
import * as
|
|
20982
|
+
import * as fs13 from "fs";
|
|
20973
20983
|
import * as path14 from "path";
|
|
20974
20984
|
function requestsFilePath(repoRoot) {
|
|
20975
20985
|
return path14.join(repoRoot, REQUESTS_FILENAME);
|
|
@@ -20977,9 +20987,9 @@ function requestsFilePath(repoRoot) {
|
|
|
20977
20987
|
function loadRequests(repoRoot) {
|
|
20978
20988
|
const filePath = requestsFilePath(repoRoot);
|
|
20979
20989
|
try {
|
|
20980
|
-
if (!
|
|
20981
|
-
const content =
|
|
20982
|
-
const parsed =
|
|
20990
|
+
if (!fs13.existsSync(filePath)) return [];
|
|
20991
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
20992
|
+
const parsed = YAML9.parse(content);
|
|
20983
20993
|
if (!parsed || !Array.isArray(parsed.requests)) return [];
|
|
20984
20994
|
return parsed.requests.map((r) => ({
|
|
20985
20995
|
key: r.key,
|
|
@@ -20995,7 +21005,7 @@ function saveRequests(repoRoot, requests) {
|
|
|
20995
21005
|
const filePath = requestsFilePath(repoRoot);
|
|
20996
21006
|
if (requests.length === 0) {
|
|
20997
21007
|
try {
|
|
20998
|
-
|
|
21008
|
+
fs13.unlinkSync(filePath);
|
|
20999
21009
|
} catch {
|
|
21000
21010
|
}
|
|
21001
21011
|
return;
|
|
@@ -21011,7 +21021,7 @@ function saveRequests(repoRoot, requests) {
|
|
|
21011
21021
|
return raw;
|
|
21012
21022
|
})
|
|
21013
21023
|
};
|
|
21014
|
-
|
|
21024
|
+
fs13.writeFileSync(filePath, HEADER_COMMENT2 + YAML9.stringify(data), "utf-8");
|
|
21015
21025
|
}
|
|
21016
21026
|
function upsertRequest(repoRoot, key, label2, environment) {
|
|
21017
21027
|
const requests = loadRequests(repoRoot);
|
|
@@ -21045,26 +21055,25 @@ function findInList(requests, identifier) {
|
|
|
21045
21055
|
const byKey = requests.find((r) => r.key === identifier);
|
|
21046
21056
|
return byKey ?? null;
|
|
21047
21057
|
}
|
|
21048
|
-
var
|
|
21058
|
+
var YAML9, REQUESTS_FILENAME, HEADER_COMMENT2;
|
|
21049
21059
|
var init_requests = __esm({
|
|
21050
21060
|
"../core/src/recipients/requests.ts"() {
|
|
21051
21061
|
"use strict";
|
|
21052
|
-
|
|
21062
|
+
YAML9 = __toESM(require_dist());
|
|
21053
21063
|
REQUESTS_FILENAME = ".clef-requests.yaml";
|
|
21054
21064
|
HEADER_COMMENT2 = "# Pending recipient access requests. Approve with: clef recipients approve <label>\n";
|
|
21055
21065
|
}
|
|
21056
21066
|
});
|
|
21057
21067
|
|
|
21058
21068
|
// ../core/src/drift/detector.ts
|
|
21059
|
-
import * as fs13 from "fs";
|
|
21060
21069
|
import * as path15 from "path";
|
|
21061
|
-
var
|
|
21070
|
+
var DriftDetector;
|
|
21062
21071
|
var init_detector = __esm({
|
|
21063
21072
|
"../core/src/drift/detector.ts"() {
|
|
21064
21073
|
"use strict";
|
|
21065
|
-
YAML9 = __toESM(require_dist());
|
|
21066
21074
|
init_parser();
|
|
21067
21075
|
init_manager();
|
|
21076
|
+
init_keys();
|
|
21068
21077
|
DriftDetector = class {
|
|
21069
21078
|
parser = new ManifestParser();
|
|
21070
21079
|
matrix = new MatrixManager();
|
|
@@ -21092,45 +21101,30 @@ var init_detector = __esm({
|
|
|
21092
21101
|
}
|
|
21093
21102
|
const issues = [];
|
|
21094
21103
|
let namespacesClean = 0;
|
|
21104
|
+
const remoteEnvSet = new Set(remoteEnvNames);
|
|
21105
|
+
const sharedEnvSet = new Set(localEnvNames.filter((e) => remoteEnvSet.has(e)));
|
|
21095
21106
|
for (const ns of sharedNamespaces) {
|
|
21096
|
-
const
|
|
21097
|
-
const
|
|
21098
|
-
const localNsCells = localCells.filter((c) => c.namespace === ns);
|
|
21099
|
-
for (const cell of localNsCells) {
|
|
21100
|
-
const keys = this.readKeysFromFile(cell.filePath);
|
|
21101
|
-
if (keys === null) continue;
|
|
21102
|
-
allEnvs.add(cell.environment);
|
|
21103
|
-
for (const key of keys) {
|
|
21104
|
-
if (!keyEnvs.has(key)) keyEnvs.set(key, /* @__PURE__ */ new Set());
|
|
21105
|
-
keyEnvs.get(key).add(cell.environment);
|
|
21106
|
-
}
|
|
21107
|
-
}
|
|
21108
|
-
const remoteNsCells = remoteCells.filter((c) => c.namespace === ns);
|
|
21109
|
-
for (const cell of remoteNsCells) {
|
|
21110
|
-
const keys = this.readKeysFromFile(cell.filePath);
|
|
21111
|
-
if (keys === null) continue;
|
|
21112
|
-
allEnvs.add(cell.environment);
|
|
21113
|
-
for (const key of keys) {
|
|
21114
|
-
if (!keyEnvs.has(key)) keyEnvs.set(key, /* @__PURE__ */ new Set());
|
|
21115
|
-
keyEnvs.get(key).add(cell.environment);
|
|
21116
|
-
}
|
|
21117
|
-
}
|
|
21118
|
-
const envList = [...allEnvs];
|
|
21107
|
+
const localKeyEnvs = this.collectKeyEnvs(localCells, ns, sharedEnvSet);
|
|
21108
|
+
const remoteKeyEnvs = this.collectKeyEnvs(remoteCells, ns, sharedEnvSet);
|
|
21119
21109
|
let nsClean = true;
|
|
21120
|
-
|
|
21121
|
-
const
|
|
21122
|
-
|
|
21123
|
-
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
|
|
21127
|
-
|
|
21128
|
-
|
|
21129
|
-
|
|
21130
|
-
|
|
21131
|
-
|
|
21110
|
+
const reportDrift = (sourceMap, targetMap, direction) => {
|
|
21111
|
+
for (const [key, sourceEnvs] of sourceMap) {
|
|
21112
|
+
const targetEnvs = targetMap.get(key);
|
|
21113
|
+
const missingFrom = [...sourceEnvs].filter((e) => !targetEnvs?.has(e)).sort();
|
|
21114
|
+
if (missingFrom.length > 0) {
|
|
21115
|
+
nsClean = false;
|
|
21116
|
+
issues.push({
|
|
21117
|
+
namespace: ns,
|
|
21118
|
+
key,
|
|
21119
|
+
presentIn: [...sourceEnvs].sort(),
|
|
21120
|
+
missingFrom,
|
|
21121
|
+
message: `Key '${key}' in namespace '${ns}' exists in ${direction} [${[...sourceEnvs].sort().join(", ")}] but is missing from [${missingFrom.join(", ")}]`
|
|
21122
|
+
});
|
|
21123
|
+
}
|
|
21132
21124
|
}
|
|
21133
|
-
}
|
|
21125
|
+
};
|
|
21126
|
+
reportDrift(remoteKeyEnvs, localKeyEnvs, "remote");
|
|
21127
|
+
reportDrift(localKeyEnvs, remoteKeyEnvs, "local");
|
|
21134
21128
|
if (nsClean) namespacesClean++;
|
|
21135
21129
|
}
|
|
21136
21130
|
return {
|
|
@@ -21141,22 +21135,18 @@ var init_detector = __esm({
|
|
|
21141
21135
|
remoteEnvironments: remoteEnvNames
|
|
21142
21136
|
};
|
|
21143
21137
|
}
|
|
21144
|
-
|
|
21145
|
-
|
|
21146
|
-
|
|
21147
|
-
|
|
21148
|
-
|
|
21149
|
-
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
|
|
21154
|
-
const parsed = YAML9.parse(raw);
|
|
21155
|
-
if (parsed === null || parsed === void 0 || typeof parsed !== "object") return null;
|
|
21156
|
-
return Object.keys(parsed).filter((k) => k !== "sops");
|
|
21157
|
-
} catch {
|
|
21158
|
-
return null;
|
|
21138
|
+
collectKeyEnvs(cells, ns, sharedEnvSet) {
|
|
21139
|
+
const keyEnvs = /* @__PURE__ */ new Map();
|
|
21140
|
+
for (const cell of cells) {
|
|
21141
|
+
if (cell.namespace !== ns || !sharedEnvSet.has(cell.environment)) continue;
|
|
21142
|
+
const keys = readSopsKeyNames(cell.filePath);
|
|
21143
|
+
if (keys === null) continue;
|
|
21144
|
+
for (const key of keys) {
|
|
21145
|
+
if (!keyEnvs.has(key)) keyEnvs.set(key, /* @__PURE__ */ new Set());
|
|
21146
|
+
keyEnvs.get(key).add(cell.environment);
|
|
21147
|
+
}
|
|
21159
21148
|
}
|
|
21149
|
+
return keyEnvs;
|
|
21160
21150
|
}
|
|
21161
21151
|
};
|
|
21162
21152
|
}
|
|
@@ -21302,19 +21292,18 @@ var init_sanitizer = __esm({
|
|
|
21302
21292
|
});
|
|
21303
21293
|
|
|
21304
21294
|
// ../core/src/report/generator.ts
|
|
21305
|
-
import * as fs14 from "fs";
|
|
21306
21295
|
import * as path16 from "path";
|
|
21307
|
-
var
|
|
21296
|
+
var ReportGenerator;
|
|
21308
21297
|
var init_generator = __esm({
|
|
21309
21298
|
"../core/src/report/generator.ts"() {
|
|
21310
21299
|
"use strict";
|
|
21311
|
-
YAML10 = __toESM(require_dist());
|
|
21312
21300
|
init_types();
|
|
21313
21301
|
init_parser();
|
|
21314
21302
|
init_runner();
|
|
21315
21303
|
init_metadata();
|
|
21316
21304
|
init_checker();
|
|
21317
21305
|
init_sanitizer();
|
|
21306
|
+
init_keys();
|
|
21318
21307
|
ReportGenerator = class {
|
|
21319
21308
|
constructor(runner2, sopsClient, matrixManager, schemaValidator) {
|
|
21320
21309
|
this.runner = runner2;
|
|
@@ -21484,15 +21473,7 @@ var init_generator = __esm({
|
|
|
21484
21473
|
};
|
|
21485
21474
|
}
|
|
21486
21475
|
readKeyCount(filePath) {
|
|
21487
|
-
|
|
21488
|
-
if (!fs14.existsSync(filePath)) return 0;
|
|
21489
|
-
const raw = fs14.readFileSync(filePath, "utf-8");
|
|
21490
|
-
const parsed = YAML10.parse(raw);
|
|
21491
|
-
if (parsed === null || parsed === void 0 || typeof parsed !== "object") return 0;
|
|
21492
|
-
return Object.keys(parsed).filter((k) => k !== "sops").length;
|
|
21493
|
-
} catch {
|
|
21494
|
-
return 0;
|
|
21495
|
-
}
|
|
21476
|
+
return readSopsKeyNames(filePath)?.length ?? 0;
|
|
21496
21477
|
}
|
|
21497
21478
|
async buildPolicy(manifest, repoRoot) {
|
|
21498
21479
|
try {
|
|
@@ -21859,14 +21840,14 @@ var init_driver = __esm({
|
|
|
21859
21840
|
});
|
|
21860
21841
|
|
|
21861
21842
|
// ../core/src/service-identity/manager.ts
|
|
21862
|
-
import * as
|
|
21843
|
+
import * as fs14 from "fs";
|
|
21863
21844
|
import * as os from "os";
|
|
21864
21845
|
import * as path17 from "path";
|
|
21865
|
-
var
|
|
21846
|
+
var YAML10, PartialRotationError, ServiceIdentityManager;
|
|
21866
21847
|
var init_manager2 = __esm({
|
|
21867
21848
|
"../core/src/service-identity/manager.ts"() {
|
|
21868
21849
|
"use strict";
|
|
21869
|
-
|
|
21850
|
+
YAML10 = __toESM(require_dist());
|
|
21870
21851
|
init_types();
|
|
21871
21852
|
init_keygen();
|
|
21872
21853
|
init_parser();
|
|
@@ -21921,8 +21902,8 @@ var init_manager2 = __esm({
|
|
|
21921
21902
|
};
|
|
21922
21903
|
await this.registerRecipients(definition, manifest, repoRoot);
|
|
21923
21904
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
21924
|
-
const raw =
|
|
21925
|
-
const doc =
|
|
21905
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
21906
|
+
const doc = YAML10.parse(raw);
|
|
21926
21907
|
if (!Array.isArray(doc.service_identities)) {
|
|
21927
21908
|
doc.service_identities = [];
|
|
21928
21909
|
}
|
|
@@ -21934,11 +21915,11 @@ var init_manager2 = __esm({
|
|
|
21934
21915
|
});
|
|
21935
21916
|
const tmpCreate = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
21936
21917
|
try {
|
|
21937
|
-
|
|
21938
|
-
|
|
21918
|
+
fs14.writeFileSync(tmpCreate, YAML10.stringify(doc), "utf-8");
|
|
21919
|
+
fs14.renameSync(tmpCreate, manifestPath);
|
|
21939
21920
|
} finally {
|
|
21940
21921
|
try {
|
|
21941
|
-
|
|
21922
|
+
fs14.unlinkSync(tmpCreate);
|
|
21942
21923
|
} catch {
|
|
21943
21924
|
}
|
|
21944
21925
|
}
|
|
@@ -21977,8 +21958,8 @@ var init_manager2 = __esm({
|
|
|
21977
21958
|
}
|
|
21978
21959
|
}
|
|
21979
21960
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
21980
|
-
const raw =
|
|
21981
|
-
const doc =
|
|
21961
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
21962
|
+
const doc = YAML10.parse(raw);
|
|
21982
21963
|
const identities = doc.service_identities;
|
|
21983
21964
|
if (Array.isArray(identities)) {
|
|
21984
21965
|
doc.service_identities = identities.filter(
|
|
@@ -21987,11 +21968,11 @@ var init_manager2 = __esm({
|
|
|
21987
21968
|
}
|
|
21988
21969
|
const tmp = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
21989
21970
|
try {
|
|
21990
|
-
|
|
21991
|
-
|
|
21971
|
+
fs14.writeFileSync(tmp, YAML10.stringify(doc), "utf-8");
|
|
21972
|
+
fs14.renameSync(tmp, manifestPath);
|
|
21992
21973
|
} finally {
|
|
21993
21974
|
try {
|
|
21994
|
-
|
|
21975
|
+
fs14.unlinkSync(tmp);
|
|
21995
21976
|
} catch {
|
|
21996
21977
|
}
|
|
21997
21978
|
}
|
|
@@ -22007,8 +21988,8 @@ var init_manager2 = __esm({
|
|
|
22007
21988
|
throw new Error(`Service identity '${name}' not found.`);
|
|
22008
21989
|
}
|
|
22009
21990
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
22010
|
-
const raw =
|
|
22011
|
-
const doc =
|
|
21991
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
21992
|
+
const doc = YAML10.parse(raw);
|
|
22012
21993
|
const identities = doc.service_identities;
|
|
22013
21994
|
const siDoc = identities.find((si) => si.name === name);
|
|
22014
21995
|
const envs = siDoc.environments;
|
|
@@ -22035,11 +22016,11 @@ var init_manager2 = __esm({
|
|
|
22035
22016
|
}
|
|
22036
22017
|
const tmp = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
22037
22018
|
try {
|
|
22038
|
-
|
|
22039
|
-
|
|
22019
|
+
fs14.writeFileSync(tmp, YAML10.stringify(doc), "utf-8");
|
|
22020
|
+
fs14.renameSync(tmp, manifestPath);
|
|
22040
22021
|
} finally {
|
|
22041
22022
|
try {
|
|
22042
|
-
|
|
22023
|
+
fs14.unlinkSync(tmp);
|
|
22043
22024
|
} catch {
|
|
22044
22025
|
}
|
|
22045
22026
|
}
|
|
@@ -22076,8 +22057,8 @@ var init_manager2 = __esm({
|
|
|
22076
22057
|
throw new Error(`Service identity '${name}' not found.`);
|
|
22077
22058
|
}
|
|
22078
22059
|
const manifestPath = path17.join(repoRoot, CLEF_MANIFEST_FILENAME);
|
|
22079
|
-
const raw =
|
|
22080
|
-
const doc =
|
|
22060
|
+
const raw = fs14.readFileSync(manifestPath, "utf-8");
|
|
22061
|
+
const doc = YAML10.parse(raw);
|
|
22081
22062
|
const identities = doc.service_identities;
|
|
22082
22063
|
const siDoc = identities.find((si) => si.name === name);
|
|
22083
22064
|
const envs = siDoc.environments;
|
|
@@ -22132,11 +22113,11 @@ var init_manager2 = __esm({
|
|
|
22132
22113
|
}
|
|
22133
22114
|
const tmpRotate = path17.join(os.tmpdir(), `clef-manifest-${process.pid}-${Date.now()}.tmp`);
|
|
22134
22115
|
try {
|
|
22135
|
-
|
|
22136
|
-
|
|
22116
|
+
fs14.writeFileSync(tmpRotate, YAML10.stringify(doc), "utf-8");
|
|
22117
|
+
fs14.renameSync(tmpRotate, manifestPath);
|
|
22137
22118
|
} finally {
|
|
22138
22119
|
try {
|
|
22139
|
-
|
|
22120
|
+
fs14.unlinkSync(tmpRotate);
|
|
22140
22121
|
} catch {
|
|
22141
22122
|
}
|
|
22142
22123
|
}
|
|
@@ -22267,7 +22248,7 @@ var init_resolve = __esm({
|
|
|
22267
22248
|
import * as crypto3 from "crypto";
|
|
22268
22249
|
function buildSigningPayload(artifact) {
|
|
22269
22250
|
const fields = [
|
|
22270
|
-
"clef-sig-
|
|
22251
|
+
"clef-sig-v2",
|
|
22271
22252
|
String(artifact.version),
|
|
22272
22253
|
artifact.identity,
|
|
22273
22254
|
artifact.environment,
|
|
@@ -22279,7 +22260,9 @@ function buildSigningPayload(artifact) {
|
|
|
22279
22260
|
artifact.envelope?.provider ?? "",
|
|
22280
22261
|
artifact.envelope?.keyId ?? "",
|
|
22281
22262
|
artifact.envelope?.wrappedKey ?? "",
|
|
22282
|
-
artifact.envelope?.algorithm ?? ""
|
|
22263
|
+
artifact.envelope?.algorithm ?? "",
|
|
22264
|
+
artifact.envelope?.iv ?? "",
|
|
22265
|
+
artifact.envelope?.authTag ?? ""
|
|
22283
22266
|
];
|
|
22284
22267
|
return Buffer.from(fields.join("\n"), "utf-8");
|
|
22285
22268
|
}
|
|
@@ -22347,7 +22330,7 @@ var init_signer = __esm({
|
|
|
22347
22330
|
});
|
|
22348
22331
|
|
|
22349
22332
|
// ../core/src/artifact/packer.ts
|
|
22350
|
-
import * as
|
|
22333
|
+
import * as fs15 from "fs";
|
|
22351
22334
|
import * as path18 from "path";
|
|
22352
22335
|
import * as crypto4 from "crypto";
|
|
22353
22336
|
var ArtifactPacker;
|
|
@@ -22388,37 +22371,41 @@ var init_packer = __esm({
|
|
|
22388
22371
|
if (!this.kms) {
|
|
22389
22372
|
throw new Error("KMS provider required for envelope encryption but none was provided.");
|
|
22390
22373
|
}
|
|
22391
|
-
const
|
|
22392
|
-
const
|
|
22393
|
-
const ephemeralPublicKey = await identityToRecipient2(ephemeralPrivateKey);
|
|
22374
|
+
const dek = crypto4.randomBytes(32);
|
|
22375
|
+
const iv = crypto4.randomBytes(12);
|
|
22394
22376
|
try {
|
|
22395
|
-
const
|
|
22396
|
-
|
|
22397
|
-
|
|
22398
|
-
|
|
22399
|
-
|
|
22400
|
-
|
|
22377
|
+
const cipher = crypto4.createCipheriv("aes-256-gcm", dek, iv);
|
|
22378
|
+
const ciphertextBuf = Buffer.concat([
|
|
22379
|
+
cipher.update(Buffer.from(plaintext, "utf-8")),
|
|
22380
|
+
cipher.final()
|
|
22381
|
+
]);
|
|
22382
|
+
const authTag = cipher.getAuthTag();
|
|
22383
|
+
ciphertext = ciphertextBuf.toString("base64");
|
|
22384
|
+
const kmsConfig = resolved.envConfig.kms;
|
|
22385
|
+
const wrapped = await this.kms.wrap(kmsConfig.keyId, dek);
|
|
22386
|
+
const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
|
|
22387
|
+
const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
|
|
22388
|
+
artifact = {
|
|
22389
|
+
version: 1,
|
|
22390
|
+
identity: config.identity,
|
|
22391
|
+
environment: config.environment,
|
|
22392
|
+
packedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22393
|
+
revision,
|
|
22394
|
+
ciphertextHash,
|
|
22395
|
+
ciphertext,
|
|
22396
|
+
keys: Object.keys(resolved.values),
|
|
22397
|
+
envelope: {
|
|
22398
|
+
provider: kmsConfig.provider,
|
|
22399
|
+
keyId: kmsConfig.keyId,
|
|
22400
|
+
wrappedKey: wrapped.wrappedKey.toString("base64"),
|
|
22401
|
+
algorithm: wrapped.algorithm,
|
|
22402
|
+
iv: iv.toString("base64"),
|
|
22403
|
+
authTag: authTag.toString("base64")
|
|
22404
|
+
}
|
|
22405
|
+
};
|
|
22406
|
+
} finally {
|
|
22407
|
+
dek.fill(0);
|
|
22401
22408
|
}
|
|
22402
|
-
const kmsConfig = resolved.envConfig.kms;
|
|
22403
|
-
const wrapped = await this.kms.wrap(kmsConfig.keyId, Buffer.from(ephemeralPrivateKey));
|
|
22404
|
-
const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
|
|
22405
|
-
const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
|
|
22406
|
-
artifact = {
|
|
22407
|
-
version: 1,
|
|
22408
|
-
identity: config.identity,
|
|
22409
|
-
environment: config.environment,
|
|
22410
|
-
packedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22411
|
-
revision,
|
|
22412
|
-
ciphertextHash,
|
|
22413
|
-
ciphertext,
|
|
22414
|
-
keys: Object.keys(resolved.values),
|
|
22415
|
-
envelope: {
|
|
22416
|
-
provider: kmsConfig.provider,
|
|
22417
|
-
keyId: kmsConfig.keyId,
|
|
22418
|
-
wrappedKey: wrapped.wrappedKey.toString("base64"),
|
|
22419
|
-
algorithm: wrapped.algorithm
|
|
22420
|
-
}
|
|
22421
|
-
};
|
|
22422
22409
|
} else {
|
|
22423
22410
|
try {
|
|
22424
22411
|
const { Encrypter: Encrypter2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
@@ -22426,8 +22413,10 @@ var init_packer = __esm({
|
|
|
22426
22413
|
e.addRecipient(resolved.recipient);
|
|
22427
22414
|
const encrypted = await e.encrypt(plaintext);
|
|
22428
22415
|
ciphertext = Buffer.from(encrypted).toString("base64");
|
|
22429
|
-
} catch {
|
|
22430
|
-
throw new Error(
|
|
22416
|
+
} catch (err) {
|
|
22417
|
+
throw new Error(
|
|
22418
|
+
`Failed to age-encrypt artifact: ${err instanceof Error ? err.message : String(err)}`
|
|
22419
|
+
);
|
|
22431
22420
|
}
|
|
22432
22421
|
const revision = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}`;
|
|
22433
22422
|
const ciphertextHash = crypto4.createHash("sha256").update(ciphertext).digest("hex");
|
|
@@ -22443,8 +22432,8 @@ var init_packer = __esm({
|
|
|
22443
22432
|
};
|
|
22444
22433
|
}
|
|
22445
22434
|
const outputDir = path18.dirname(config.outputPath);
|
|
22446
|
-
if (!
|
|
22447
|
-
|
|
22435
|
+
if (!fs15.existsSync(outputDir)) {
|
|
22436
|
+
fs15.mkdirSync(outputDir, { recursive: true });
|
|
22448
22437
|
}
|
|
22449
22438
|
if (config.ttl && config.ttl > 0) {
|
|
22450
22439
|
artifact.expiresAt = new Date(Date.now() + config.ttl * 1e3).toISOString();
|
|
@@ -22463,8 +22452,8 @@ var init_packer = __esm({
|
|
|
22463
22452
|
}
|
|
22464
22453
|
const json = JSON.stringify(artifact, null, 2);
|
|
22465
22454
|
const tmpOutput = `${config.outputPath}.tmp.${process.pid}`;
|
|
22466
|
-
|
|
22467
|
-
|
|
22455
|
+
fs15.writeFileSync(tmpOutput, json, "utf-8");
|
|
22456
|
+
fs15.renameSync(tmpOutput, config.outputPath);
|
|
22468
22457
|
return {
|
|
22469
22458
|
outputPath: config.outputPath,
|
|
22470
22459
|
namespaceCount: resolved.identity.namespaces.length,
|
|
@@ -22477,6 +22466,23 @@ var init_packer = __esm({
|
|
|
22477
22466
|
}
|
|
22478
22467
|
});
|
|
22479
22468
|
|
|
22469
|
+
// ../core/src/kms/types.ts
|
|
22470
|
+
var VALID_KMS_PROVIDERS;
|
|
22471
|
+
var init_types2 = __esm({
|
|
22472
|
+
"../core/src/kms/types.ts"() {
|
|
22473
|
+
"use strict";
|
|
22474
|
+
VALID_KMS_PROVIDERS = ["aws", "gcp", "azure"];
|
|
22475
|
+
}
|
|
22476
|
+
});
|
|
22477
|
+
|
|
22478
|
+
// ../core/src/kms/index.ts
|
|
22479
|
+
var init_kms = __esm({
|
|
22480
|
+
"../core/src/kms/index.ts"() {
|
|
22481
|
+
"use strict";
|
|
22482
|
+
init_types2();
|
|
22483
|
+
}
|
|
22484
|
+
});
|
|
22485
|
+
|
|
22480
22486
|
// ../core/src/index.ts
|
|
22481
22487
|
var src_exports = {};
|
|
22482
22488
|
__export(src_exports, {
|
|
@@ -22516,6 +22522,7 @@ __export(src_exports, {
|
|
|
22516
22522
|
SopsMergeDriver: () => SopsMergeDriver,
|
|
22517
22523
|
SopsMissingError: () => SopsMissingError,
|
|
22518
22524
|
SopsVersionError: () => SopsVersionError,
|
|
22525
|
+
VALID_KMS_PROVIDERS: () => VALID_KMS_PROVIDERS,
|
|
22519
22526
|
assertSops: () => assertSops,
|
|
22520
22527
|
buildSigningPayload: () => buildSigningPayload,
|
|
22521
22528
|
checkAll: () => checkAll,
|
|
@@ -22542,7 +22549,7 @@ __export(src_exports, {
|
|
|
22542
22549
|
markResolved: () => markResolved,
|
|
22543
22550
|
matchPatterns: () => matchPatterns,
|
|
22544
22551
|
metadataPath: () => metadataPath,
|
|
22545
|
-
parse: () =>
|
|
22552
|
+
parse: () => parse8,
|
|
22546
22553
|
parseDotenv: () => parseDotenv,
|
|
22547
22554
|
parseIgnoreContent: () => parseIgnoreContent,
|
|
22548
22555
|
parseJson: () => parseJson,
|
|
@@ -22596,6 +22603,7 @@ var init_src = __esm({
|
|
|
22596
22603
|
init_resolve();
|
|
22597
22604
|
init_packer();
|
|
22598
22605
|
init_signer();
|
|
22606
|
+
init_kms();
|
|
22599
22607
|
}
|
|
22600
22608
|
});
|
|
22601
22609
|
|
|
@@ -22684,7 +22692,7 @@ var require_ms = __commonJS({
|
|
|
22684
22692
|
options = options || {};
|
|
22685
22693
|
var type = typeof val;
|
|
22686
22694
|
if (type === "string" && val.length > 0) {
|
|
22687
|
-
return
|
|
22695
|
+
return parse15(val);
|
|
22688
22696
|
} else if (type === "number" && isFinite(val)) {
|
|
22689
22697
|
return options.long ? fmtLong(val) : fmtShort(val);
|
|
22690
22698
|
}
|
|
@@ -22692,7 +22700,7 @@ var require_ms = __commonJS({
|
|
|
22692
22700
|
"val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
|
|
22693
22701
|
);
|
|
22694
22702
|
};
|
|
22695
|
-
function
|
|
22703
|
+
function parse15(str2) {
|
|
22696
22704
|
str2 = String(str2);
|
|
22697
22705
|
if (str2.length > 100) {
|
|
22698
22706
|
return;
|
|
@@ -23151,7 +23159,7 @@ var require_has_flag = __commonJS({
|
|
|
23151
23159
|
var require_supports_color = __commonJS({
|
|
23152
23160
|
"../../node_modules/supports-color/index.js"(exports, module) {
|
|
23153
23161
|
"use strict";
|
|
23154
|
-
var
|
|
23162
|
+
var os4 = __require("os");
|
|
23155
23163
|
var tty = __require("tty");
|
|
23156
23164
|
var hasFlag = require_has_flag();
|
|
23157
23165
|
var { env } = process;
|
|
@@ -23199,7 +23207,7 @@ var require_supports_color = __commonJS({
|
|
|
23199
23207
|
return min;
|
|
23200
23208
|
}
|
|
23201
23209
|
if (process.platform === "win32") {
|
|
23202
|
-
const osRelease =
|
|
23210
|
+
const osRelease = os4.release().split(".");
|
|
23203
23211
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
23204
23212
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
23205
23213
|
}
|
|
@@ -24131,7 +24139,7 @@ var require_bytes = __commonJS({
|
|
|
24131
24139
|
"use strict";
|
|
24132
24140
|
module.exports = bytes;
|
|
24133
24141
|
module.exports.format = format;
|
|
24134
|
-
module.exports.parse =
|
|
24142
|
+
module.exports.parse = parse15;
|
|
24135
24143
|
var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
|
|
24136
24144
|
var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
|
|
24137
24145
|
var map = {
|
|
@@ -24145,7 +24153,7 @@ var require_bytes = __commonJS({
|
|
|
24145
24153
|
var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
|
|
24146
24154
|
function bytes(value, options) {
|
|
24147
24155
|
if (typeof value === "string") {
|
|
24148
|
-
return
|
|
24156
|
+
return parse15(value);
|
|
24149
24157
|
}
|
|
24150
24158
|
if (typeof value === "number") {
|
|
24151
24159
|
return format(value, options);
|
|
@@ -24189,7 +24197,7 @@ var require_bytes = __commonJS({
|
|
|
24189
24197
|
}
|
|
24190
24198
|
return str2 + unitSeparator + unit;
|
|
24191
24199
|
}
|
|
24192
|
-
function
|
|
24200
|
+
function parse15(val) {
|
|
24193
24201
|
if (typeof val === "number" && !isNaN(val)) {
|
|
24194
24202
|
return val;
|
|
24195
24203
|
}
|
|
@@ -28394,7 +28402,7 @@ var require_content_type = __commonJS({
|
|
|
28394
28402
|
var QUOTE_REGEXP = /([\\"])/g;
|
|
28395
28403
|
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
28396
28404
|
exports.format = format;
|
|
28397
|
-
exports.parse =
|
|
28405
|
+
exports.parse = parse15;
|
|
28398
28406
|
function format(obj) {
|
|
28399
28407
|
if (!obj || typeof obj !== "object") {
|
|
28400
28408
|
throw new TypeError("argument obj is required");
|
|
@@ -28418,7 +28426,7 @@ var require_content_type = __commonJS({
|
|
|
28418
28426
|
}
|
|
28419
28427
|
return string;
|
|
28420
28428
|
}
|
|
28421
|
-
function
|
|
28429
|
+
function parse15(string) {
|
|
28422
28430
|
if (!string) {
|
|
28423
28431
|
throw new TypeError("argument string is required");
|
|
28424
28432
|
}
|
|
@@ -38000,7 +38008,7 @@ var require_media_typer = __commonJS({
|
|
|
38000
38008
|
var TYPE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/;
|
|
38001
38009
|
var TYPE_REGEXP = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
|
|
38002
38010
|
exports.format = format;
|
|
38003
|
-
exports.parse =
|
|
38011
|
+
exports.parse = parse15;
|
|
38004
38012
|
exports.test = test;
|
|
38005
38013
|
function format(obj) {
|
|
38006
38014
|
if (!obj || typeof obj !== "object") {
|
|
@@ -38033,7 +38041,7 @@ var require_media_typer = __commonJS({
|
|
|
38033
38041
|
}
|
|
38034
38042
|
return TYPE_REGEXP.test(string.toLowerCase());
|
|
38035
38043
|
}
|
|
38036
|
-
function
|
|
38044
|
+
function parse15(string) {
|
|
38037
38045
|
if (!string) {
|
|
38038
38046
|
throw new TypeError("argument string is required");
|
|
38039
38047
|
}
|
|
@@ -38219,7 +38227,7 @@ var require_read = __commonJS({
|
|
|
38219
38227
|
var hasBody = require_type_is().hasBody;
|
|
38220
38228
|
var { getCharset } = require_utils();
|
|
38221
38229
|
module.exports = read2;
|
|
38222
|
-
function read2(req, res, next,
|
|
38230
|
+
function read2(req, res, next, parse15, debug, options) {
|
|
38223
38231
|
if (onFinished.isFinished(req)) {
|
|
38224
38232
|
debug("body already parsed");
|
|
38225
38233
|
next();
|
|
@@ -38307,7 +38315,7 @@ var require_read = __commonJS({
|
|
|
38307
38315
|
try {
|
|
38308
38316
|
debug("parse body");
|
|
38309
38317
|
str2 = typeof body !== "string" && encoding !== null ? iconv.decode(body, encoding) : body;
|
|
38310
|
-
req.body =
|
|
38318
|
+
req.body = parse15(str2, encoding);
|
|
38311
38319
|
} catch (err) {
|
|
38312
38320
|
next(createError(400, err, {
|
|
38313
38321
|
body: str2,
|
|
@@ -38380,7 +38388,7 @@ var require_json = __commonJS({
|
|
|
38380
38388
|
const normalizedOptions = normalizeOptions(options, "application/json");
|
|
38381
38389
|
var reviver = options?.reviver;
|
|
38382
38390
|
var strict = options?.strict !== false;
|
|
38383
|
-
function
|
|
38391
|
+
function parse15(body) {
|
|
38384
38392
|
if (body.length === 0) {
|
|
38385
38393
|
return {};
|
|
38386
38394
|
}
|
|
@@ -38407,7 +38415,7 @@ var require_json = __commonJS({
|
|
|
38407
38415
|
isValidCharset: (charset) => charset.slice(0, 4) === "utf-"
|
|
38408
38416
|
};
|
|
38409
38417
|
return function jsonParser(req, res, next) {
|
|
38410
|
-
read2(req, res, next,
|
|
38418
|
+
read2(req, res, next, parse15, debug, readOptions);
|
|
38411
38419
|
};
|
|
38412
38420
|
}
|
|
38413
38421
|
function createStrictSyntaxError(str2, char) {
|
|
@@ -40985,11 +40993,11 @@ var require_lib2 = __commonJS({
|
|
|
40985
40993
|
"../../node_modules/qs/lib/index.js"(exports, module) {
|
|
40986
40994
|
"use strict";
|
|
40987
40995
|
var stringify7 = require_stringify2();
|
|
40988
|
-
var
|
|
40996
|
+
var parse15 = require_parse();
|
|
40989
40997
|
var formats = require_formats();
|
|
40990
40998
|
module.exports = {
|
|
40991
40999
|
formats,
|
|
40992
|
-
parse:
|
|
41000
|
+
parse: parse15,
|
|
40993
41001
|
stringify: stringify7
|
|
40994
41002
|
};
|
|
40995
41003
|
}
|
|
@@ -41011,7 +41019,7 @@ var require_urlencoded = __commonJS({
|
|
|
41011
41019
|
throw new TypeError("option defaultCharset must be either utf-8 or iso-8859-1");
|
|
41012
41020
|
}
|
|
41013
41021
|
var queryparse = createQueryParser(options);
|
|
41014
|
-
function
|
|
41022
|
+
function parse15(body, encoding) {
|
|
41015
41023
|
return body.length ? queryparse(body, encoding) : {};
|
|
41016
41024
|
}
|
|
41017
41025
|
const readOptions = {
|
|
@@ -41020,7 +41028,7 @@ var require_urlencoded = __commonJS({
|
|
|
41020
41028
|
isValidCharset: (charset) => charset === "utf-8" || charset === "iso-8859-1"
|
|
41021
41029
|
};
|
|
41022
41030
|
return function urlencodedParser(req, res, next) {
|
|
41023
|
-
read2(req, res, next,
|
|
41031
|
+
read2(req, res, next, parse15, debug, readOptions);
|
|
41024
41032
|
};
|
|
41025
41033
|
}
|
|
41026
41034
|
function createQueryParser(options) {
|
|
@@ -41204,7 +41212,7 @@ var require_parseurl = __commonJS({
|
|
|
41204
41212
|
"../../node_modules/parseurl/index.js"(exports, module) {
|
|
41205
41213
|
"use strict";
|
|
41206
41214
|
var url = __require("url");
|
|
41207
|
-
var
|
|
41215
|
+
var parse15 = url.parse;
|
|
41208
41216
|
var Url = url.Url;
|
|
41209
41217
|
module.exports = parseurl;
|
|
41210
41218
|
module.exports.original = originalurl;
|
|
@@ -41236,7 +41244,7 @@ var require_parseurl = __commonJS({
|
|
|
41236
41244
|
}
|
|
41237
41245
|
function fastparse(str2) {
|
|
41238
41246
|
if (typeof str2 !== "string" || str2.charCodeAt(0) !== 47) {
|
|
41239
|
-
return
|
|
41247
|
+
return parse15(str2);
|
|
41240
41248
|
}
|
|
41241
41249
|
var pathname = str2;
|
|
41242
41250
|
var query = null;
|
|
@@ -41264,7 +41272,7 @@ var require_parseurl = __commonJS({
|
|
|
41264
41272
|
/* # */
|
|
41265
41273
|
case 160:
|
|
41266
41274
|
case 65279:
|
|
41267
|
-
return
|
|
41275
|
+
return parse15(str2);
|
|
41268
41276
|
}
|
|
41269
41277
|
}
|
|
41270
41278
|
var url2 = Url !== void 0 ? new Url() : {};
|
|
@@ -41416,7 +41424,7 @@ var require_view = __commonJS({
|
|
|
41416
41424
|
"use strict";
|
|
41417
41425
|
var debug = require_src()("express:view");
|
|
41418
41426
|
var path44 = __require("node:path");
|
|
41419
|
-
var
|
|
41427
|
+
var fs26 = __require("node:fs");
|
|
41420
41428
|
var dirname7 = path44.dirname;
|
|
41421
41429
|
var basename5 = path44.basename;
|
|
41422
41430
|
var extname2 = path44.extname;
|
|
@@ -41496,7 +41504,7 @@ var require_view = __commonJS({
|
|
|
41496
41504
|
function tryStat(path45) {
|
|
41497
41505
|
debug('stat "%s"', path45);
|
|
41498
41506
|
try {
|
|
41499
|
-
return
|
|
41507
|
+
return fs26.statSync(path45);
|
|
41500
41508
|
} catch (e) {
|
|
41501
41509
|
return void 0;
|
|
41502
41510
|
}
|
|
@@ -51060,7 +51068,7 @@ var require_forwarded = __commonJS({
|
|
|
51060
51068
|
if (!req) {
|
|
51061
51069
|
throw new TypeError("argument req is required");
|
|
51062
51070
|
}
|
|
51063
|
-
var proxyAddrs =
|
|
51071
|
+
var proxyAddrs = parse15(req.headers["x-forwarded-for"] || "");
|
|
51064
51072
|
var socketAddr = getSocketAddr(req);
|
|
51065
51073
|
var addrs = [socketAddr].concat(proxyAddrs);
|
|
51066
51074
|
return addrs;
|
|
@@ -51068,7 +51076,7 @@ var require_forwarded = __commonJS({
|
|
|
51068
51076
|
function getSocketAddr(req) {
|
|
51069
51077
|
return req.socket ? req.socket.remoteAddress : req.connection.remoteAddress;
|
|
51070
51078
|
}
|
|
51071
|
-
function
|
|
51079
|
+
function parse15(header) {
|
|
51072
51080
|
var end = header.length;
|
|
51073
51081
|
var list = [];
|
|
51074
51082
|
var start = header.length;
|
|
@@ -52097,7 +52105,7 @@ var require_dist2 = __commonJS({
|
|
|
52097
52105
|
"use strict";
|
|
52098
52106
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52099
52107
|
exports.PathError = exports.TokenData = void 0;
|
|
52100
|
-
exports.parse =
|
|
52108
|
+
exports.parse = parse15;
|
|
52101
52109
|
exports.compile = compile;
|
|
52102
52110
|
exports.match = match;
|
|
52103
52111
|
exports.pathToRegexp = pathToRegexp;
|
|
@@ -52143,7 +52151,7 @@ var require_dist2 = __commonJS({
|
|
|
52143
52151
|
}
|
|
52144
52152
|
};
|
|
52145
52153
|
exports.PathError = PathError;
|
|
52146
|
-
function
|
|
52154
|
+
function parse15(str2, options = {}) {
|
|
52147
52155
|
const { encodePath = NOOP_VALUE } = options;
|
|
52148
52156
|
const chars = [...str2];
|
|
52149
52157
|
const tokens = [];
|
|
@@ -52233,7 +52241,7 @@ var require_dist2 = __commonJS({
|
|
|
52233
52241
|
}
|
|
52234
52242
|
function compile(path44, options = {}) {
|
|
52235
52243
|
const { encode: encode2 = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
|
52236
|
-
const data = typeof path44 === "object" ? path44 :
|
|
52244
|
+
const data = typeof path44 === "object" ? path44 : parse15(path44, options);
|
|
52237
52245
|
const fn = tokensToFunction(data.tokens, delimiter, encode2);
|
|
52238
52246
|
return function path45(params = {}) {
|
|
52239
52247
|
const [path46, ...missing] = fn(params);
|
|
@@ -52328,7 +52336,7 @@ var require_dist2 = __commonJS({
|
|
|
52328
52336
|
const flags = sensitive ? "" : "i";
|
|
52329
52337
|
const sources = [];
|
|
52330
52338
|
for (const input of pathsToArray(path44, [])) {
|
|
52331
|
-
const data = typeof input === "object" ? input :
|
|
52339
|
+
const data = typeof input === "object" ? input : parse15(input, options);
|
|
52332
52340
|
for (const tokens of flatten2(data.tokens, 0, [])) {
|
|
52333
52341
|
sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
|
|
52334
52342
|
}
|
|
@@ -63637,7 +63645,7 @@ var require_request = __commonJS({
|
|
|
63637
63645
|
var http = __require("node:http");
|
|
63638
63646
|
var fresh = require_fresh();
|
|
63639
63647
|
var parseRange = require_range_parser();
|
|
63640
|
-
var
|
|
63648
|
+
var parse15 = require_parseurl();
|
|
63641
63649
|
var proxyaddr = require_proxy_addr();
|
|
63642
63650
|
var req = Object.create(http.IncomingMessage.prototype);
|
|
63643
63651
|
module.exports = req;
|
|
@@ -63682,7 +63690,7 @@ var require_request = __commonJS({
|
|
|
63682
63690
|
if (!queryparse) {
|
|
63683
63691
|
return /* @__PURE__ */ Object.create(null);
|
|
63684
63692
|
}
|
|
63685
|
-
var querystring =
|
|
63693
|
+
var querystring = parse15(this).query;
|
|
63686
63694
|
return queryparse(querystring);
|
|
63687
63695
|
});
|
|
63688
63696
|
req.is = function is(types) {
|
|
@@ -63726,7 +63734,7 @@ var require_request = __commonJS({
|
|
|
63726
63734
|
return subdomains2.slice(offset);
|
|
63727
63735
|
});
|
|
63728
63736
|
defineGetter(req, "path", function path44() {
|
|
63729
|
-
return
|
|
63737
|
+
return parse15(this).pathname;
|
|
63730
63738
|
});
|
|
63731
63739
|
defineGetter(req, "host", function host() {
|
|
63732
63740
|
var trust = this.app.get("trust proxy fn");
|
|
@@ -63780,7 +63788,7 @@ var require_content_disposition = __commonJS({
|
|
|
63780
63788
|
"../../node_modules/content-disposition/index.js"(exports, module) {
|
|
63781
63789
|
"use strict";
|
|
63782
63790
|
module.exports = contentDisposition;
|
|
63783
|
-
module.exports.parse =
|
|
63791
|
+
module.exports.parse = parse15;
|
|
63784
63792
|
var basename5 = __require("path").basename;
|
|
63785
63793
|
var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
|
|
63786
63794
|
var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
|
|
@@ -63871,7 +63879,7 @@ var require_content_disposition = __commonJS({
|
|
|
63871
63879
|
function getlatin1(val) {
|
|
63872
63880
|
return String(val).replace(NON_LATIN1_REGEXP, "?");
|
|
63873
63881
|
}
|
|
63874
|
-
function
|
|
63882
|
+
function parse15(string) {
|
|
63875
63883
|
if (!string || typeof string !== "string") {
|
|
63876
63884
|
throw new TypeError("argument string is required");
|
|
63877
63885
|
}
|
|
@@ -63960,7 +63968,7 @@ var require_cookie_signature = __commonJS({
|
|
|
63960
63968
|
var require_cookie = __commonJS({
|
|
63961
63969
|
"../../node_modules/cookie/index.js"(exports) {
|
|
63962
63970
|
"use strict";
|
|
63963
|
-
exports.parse =
|
|
63971
|
+
exports.parse = parse15;
|
|
63964
63972
|
exports.serialize = serialize;
|
|
63965
63973
|
var __toString = Object.prototype.toString;
|
|
63966
63974
|
var __hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
@@ -63968,7 +63976,7 @@ var require_cookie = __commonJS({
|
|
|
63968
63976
|
var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
|
|
63969
63977
|
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;
|
|
63970
63978
|
var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
|
|
63971
|
-
function
|
|
63979
|
+
function parse15(str2, opt) {
|
|
63972
63980
|
if (typeof str2 !== "string") {
|
|
63973
63981
|
throw new TypeError("argument str must be a string");
|
|
63974
63982
|
}
|
|
@@ -73637,7 +73645,7 @@ var require_send = __commonJS({
|
|
|
73637
73645
|
var escapeHtml = require_escape_html();
|
|
73638
73646
|
var etag = require_etag();
|
|
73639
73647
|
var fresh = require_fresh();
|
|
73640
|
-
var
|
|
73648
|
+
var fs26 = __require("fs");
|
|
73641
73649
|
var mime = require_mime_types4();
|
|
73642
73650
|
var ms = require_ms();
|
|
73643
73651
|
var onFinished = require_on_finished();
|
|
@@ -73919,7 +73927,7 @@ var require_send = __commonJS({
|
|
|
73919
73927
|
var i = 0;
|
|
73920
73928
|
var self = this;
|
|
73921
73929
|
debug('stat "%s"', path45);
|
|
73922
|
-
|
|
73930
|
+
fs26.stat(path45, function onstat(err, stat) {
|
|
73923
73931
|
var pathEndsWithSep = path45[path45.length - 1] === sep;
|
|
73924
73932
|
if (err && err.code === "ENOENT" && !extname2(path45) && !pathEndsWithSep) {
|
|
73925
73933
|
return next(err);
|
|
@@ -73936,7 +73944,7 @@ var require_send = __commonJS({
|
|
|
73936
73944
|
}
|
|
73937
73945
|
var p = path45 + "." + self._extensions[i++];
|
|
73938
73946
|
debug('stat "%s"', p);
|
|
73939
|
-
|
|
73947
|
+
fs26.stat(p, function(err2, stat) {
|
|
73940
73948
|
if (err2) return next(err2);
|
|
73941
73949
|
if (stat.isDirectory()) return next();
|
|
73942
73950
|
self.emit("file", p, stat);
|
|
@@ -73954,7 +73962,7 @@ var require_send = __commonJS({
|
|
|
73954
73962
|
}
|
|
73955
73963
|
var p = join40(path45, self._index[i]);
|
|
73956
73964
|
debug('stat "%s"', p);
|
|
73957
|
-
|
|
73965
|
+
fs26.stat(p, function(err2, stat) {
|
|
73958
73966
|
if (err2) return next(err2);
|
|
73959
73967
|
if (stat.isDirectory()) return next();
|
|
73960
73968
|
self.emit("file", p, stat);
|
|
@@ -73966,7 +73974,7 @@ var require_send = __commonJS({
|
|
|
73966
73974
|
SendStream.prototype.stream = function stream2(path45, options) {
|
|
73967
73975
|
var self = this;
|
|
73968
73976
|
var res = this.res;
|
|
73969
|
-
var stream3 =
|
|
73977
|
+
var stream3 = fs26.createReadStream(path45, options);
|
|
73970
73978
|
this.emit("stream", stream3);
|
|
73971
73979
|
stream3.pipe(res);
|
|
73972
73980
|
function cleanup() {
|
|
@@ -74124,7 +74132,7 @@ var require_vary = __commonJS({
|
|
|
74124
74132
|
if (!field) {
|
|
74125
74133
|
throw new TypeError("field argument is required");
|
|
74126
74134
|
}
|
|
74127
|
-
var fields = !Array.isArray(field) ?
|
|
74135
|
+
var fields = !Array.isArray(field) ? parse15(String(field)) : field;
|
|
74128
74136
|
for (var j = 0; j < fields.length; j++) {
|
|
74129
74137
|
if (!FIELD_NAME_REGEXP.test(fields[j])) {
|
|
74130
74138
|
throw new TypeError("field argument contains an invalid header name");
|
|
@@ -74134,7 +74142,7 @@ var require_vary = __commonJS({
|
|
|
74134
74142
|
return header;
|
|
74135
74143
|
}
|
|
74136
74144
|
var val = header;
|
|
74137
|
-
var vals =
|
|
74145
|
+
var vals = parse15(header.toLowerCase());
|
|
74138
74146
|
if (fields.indexOf("*") !== -1 || vals.indexOf("*") !== -1) {
|
|
74139
74147
|
return "*";
|
|
74140
74148
|
}
|
|
@@ -74147,7 +74155,7 @@ var require_vary = __commonJS({
|
|
|
74147
74155
|
}
|
|
74148
74156
|
return val;
|
|
74149
74157
|
}
|
|
74150
|
-
function
|
|
74158
|
+
function parse15(header) {
|
|
74151
74159
|
var end = 0;
|
|
74152
74160
|
var list = [];
|
|
74153
74161
|
var start = 0;
|
|
@@ -75652,7 +75660,7 @@ var require_api = __commonJS({
|
|
|
75652
75660
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
75653
75661
|
exports.createApiRouter = createApiRouter;
|
|
75654
75662
|
var path44 = __importStar(__require("path"));
|
|
75655
|
-
var
|
|
75663
|
+
var os4 = __importStar(__require("os"));
|
|
75656
75664
|
var child_process_1 = __require("child_process");
|
|
75657
75665
|
var express_1 = require_express2();
|
|
75658
75666
|
var _useStdinFifo = process.platform === "linux" && !process.env.JEST_WORKER_ID;
|
|
@@ -75672,7 +75680,7 @@ var require_api = __commonJS({
|
|
|
75672
75680
|
env: { SOPS_CONFIG: path44.join(deps2.repoRoot, ".sops.yaml"), ...opts2?.env }
|
|
75673
75681
|
});
|
|
75674
75682
|
}
|
|
75675
|
-
const fifoDir = (0, child_process_1.execFileSync)("mktemp", ["-d", path44.join(
|
|
75683
|
+
const fifoDir = (0, child_process_1.execFileSync)("mktemp", ["-d", path44.join(os4.tmpdir(), "clef-fifo-XXXXXX")]).toString().trim();
|
|
75676
75684
|
const fifoPath = path44.join(fifoDir, "input");
|
|
75677
75685
|
(0, child_process_1.execFileSync)("mkfifo", [fifoPath]);
|
|
75678
75686
|
const writer = (0, child_process_1.spawn)("dd", [`of=${fifoPath}`, "status=none"], {
|
|
@@ -75706,6 +75714,7 @@ var require_api = __commonJS({
|
|
|
75706
75714
|
const git = new core_1.GitIntegration(deps2.runner);
|
|
75707
75715
|
const scanRunner = new core_1.ScanRunner(deps2.runner);
|
|
75708
75716
|
const recipientManager = new core_1.RecipientManager(sops, matrix);
|
|
75717
|
+
const serviceIdManager = new core_1.ServiceIdentityManager(sops, matrix);
|
|
75709
75718
|
const bulkOps = new core_1.BulkOps();
|
|
75710
75719
|
let lastScanResult = null;
|
|
75711
75720
|
let lastScanAt = null;
|
|
@@ -75713,6 +75722,10 @@ var require_api = __commonJS({
|
|
|
75713
75722
|
const manifestPath = `${deps2.repoRoot}/clef.yaml`;
|
|
75714
75723
|
return parser.parse(manifestPath);
|
|
75715
75724
|
}
|
|
75725
|
+
function zeroStringRecord(record) {
|
|
75726
|
+
for (const k of Object.keys(record))
|
|
75727
|
+
record[k] = "";
|
|
75728
|
+
}
|
|
75716
75729
|
function setNoCacheHeaders(res) {
|
|
75717
75730
|
res.set({
|
|
75718
75731
|
"Cache-Control": "no-store, no-cache, must-revalidate",
|
|
@@ -75954,6 +75967,14 @@ var require_api = __commonJS({
|
|
|
75954
75967
|
return;
|
|
75955
75968
|
}
|
|
75956
75969
|
const result = await diffEngine.diffFiles(ns, envA, envB, manifest, sops, deps2.repoRoot);
|
|
75970
|
+
if (req.query.showValues !== "true") {
|
|
75971
|
+
for (const row of result.rows) {
|
|
75972
|
+
if (row.valueA !== null)
|
|
75973
|
+
row.valueA = "\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF";
|
|
75974
|
+
if (row.valueB !== null)
|
|
75975
|
+
row.valueB = "\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF";
|
|
75976
|
+
}
|
|
75977
|
+
}
|
|
75957
75978
|
res.json(result);
|
|
75958
75979
|
} catch {
|
|
75959
75980
|
res.status(500).json({ error: "Failed to compute diff", code: "DIFF_ERROR" });
|
|
@@ -76282,6 +76303,100 @@ var require_api = __commonJS({
|
|
|
76282
76303
|
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
76283
76304
|
}
|
|
76284
76305
|
});
|
|
76306
|
+
router.post("/service-identities", async (req, res) => {
|
|
76307
|
+
try {
|
|
76308
|
+
const manifest = loadManifest();
|
|
76309
|
+
const { name, description, namespaces, kmsEnvConfigs } = req.body;
|
|
76310
|
+
if (!name || typeof name !== "string") {
|
|
76311
|
+
res.status(400).json({ error: "name is required.", code: "BAD_REQUEST" });
|
|
76312
|
+
return;
|
|
76313
|
+
}
|
|
76314
|
+
if (!Array.isArray(namespaces) || namespaces.length === 0) {
|
|
76315
|
+
res.status(400).json({ error: "namespaces must be a non-empty array.", code: "BAD_REQUEST" });
|
|
76316
|
+
return;
|
|
76317
|
+
}
|
|
76318
|
+
let typedKmsConfigs;
|
|
76319
|
+
if (kmsEnvConfigs && Object.keys(kmsEnvConfigs).length > 0) {
|
|
76320
|
+
typedKmsConfigs = {};
|
|
76321
|
+
for (const [envName, cfg] of Object.entries(kmsEnvConfigs)) {
|
|
76322
|
+
if (!core_1.VALID_KMS_PROVIDERS.includes(cfg.provider)) {
|
|
76323
|
+
res.status(400).json({
|
|
76324
|
+
error: `Invalid KMS provider '${cfg.provider}' for environment '${envName}'. Must be aws, gcp, or azure.`,
|
|
76325
|
+
code: "BAD_REQUEST"
|
|
76326
|
+
});
|
|
76327
|
+
return;
|
|
76328
|
+
}
|
|
76329
|
+
typedKmsConfigs[envName] = {
|
|
76330
|
+
provider: cfg.provider,
|
|
76331
|
+
keyId: cfg.keyId
|
|
76332
|
+
};
|
|
76333
|
+
}
|
|
76334
|
+
}
|
|
76335
|
+
const result = await serviceIdManager.create(name, namespaces, description ?? "", manifest, deps2.repoRoot, typedKmsConfigs);
|
|
76336
|
+
setNoCacheHeaders(res);
|
|
76337
|
+
res.json({ identity: result.identity, privateKeys: result.privateKeys });
|
|
76338
|
+
zeroStringRecord(result.privateKeys);
|
|
76339
|
+
} catch (err) {
|
|
76340
|
+
const message = err instanceof Error ? err.message : "Failed to create service identity";
|
|
76341
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
76342
|
+
}
|
|
76343
|
+
});
|
|
76344
|
+
router.delete("/service-identities/:name", async (req, res) => {
|
|
76345
|
+
try {
|
|
76346
|
+
const name = req.params.name;
|
|
76347
|
+
const manifest = loadManifest();
|
|
76348
|
+
if (!manifest.service_identities?.find((si) => si.name === name)) {
|
|
76349
|
+
res.status(404).json({ error: `Service identity '${name}' not found.`, code: "NOT_FOUND" });
|
|
76350
|
+
return;
|
|
76351
|
+
}
|
|
76352
|
+
await serviceIdManager.delete(name, manifest, deps2.repoRoot);
|
|
76353
|
+
res.json({ ok: true });
|
|
76354
|
+
} catch (err) {
|
|
76355
|
+
const message = err instanceof Error ? err.message : "Failed to delete service identity";
|
|
76356
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
76357
|
+
}
|
|
76358
|
+
});
|
|
76359
|
+
router.patch("/service-identities/:name", async (req, res) => {
|
|
76360
|
+
try {
|
|
76361
|
+
const name = req.params.name;
|
|
76362
|
+
const { kmsEnvConfigs } = req.body;
|
|
76363
|
+
if (!kmsEnvConfigs || Object.keys(kmsEnvConfigs).length === 0) {
|
|
76364
|
+
res.status(400).json({ error: "kmsEnvConfigs must be a non-empty object.", code: "BAD_REQUEST" });
|
|
76365
|
+
return;
|
|
76366
|
+
}
|
|
76367
|
+
const manifest = loadManifest();
|
|
76368
|
+
const typedKmsConfigs = {};
|
|
76369
|
+
for (const [envName, cfg] of Object.entries(kmsEnvConfigs)) {
|
|
76370
|
+
if (cfg.provider !== "aws" && cfg.provider !== "gcp" && cfg.provider !== "azure") {
|
|
76371
|
+
res.status(400).json({
|
|
76372
|
+
error: `Invalid KMS provider '${cfg.provider}' for environment '${envName}'. Must be aws, gcp, or azure.`,
|
|
76373
|
+
code: "BAD_REQUEST"
|
|
76374
|
+
});
|
|
76375
|
+
return;
|
|
76376
|
+
}
|
|
76377
|
+
typedKmsConfigs[envName] = { provider: cfg.provider, keyId: cfg.keyId };
|
|
76378
|
+
}
|
|
76379
|
+
await serviceIdManager.updateEnvironments(name, typedKmsConfigs, manifest, deps2.repoRoot);
|
|
76380
|
+
res.json({ ok: true });
|
|
76381
|
+
} catch (err) {
|
|
76382
|
+
const message = err instanceof Error ? err.message : "Failed to update service identity";
|
|
76383
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
76384
|
+
}
|
|
76385
|
+
});
|
|
76386
|
+
router.post("/service-identities/:name/rotate", async (req, res) => {
|
|
76387
|
+
try {
|
|
76388
|
+
const name = req.params.name;
|
|
76389
|
+
const { environment } = req.body;
|
|
76390
|
+
const manifest = loadManifest();
|
|
76391
|
+
const privateKeys = await serviceIdManager.rotateKey(name, manifest, deps2.repoRoot, environment);
|
|
76392
|
+
setNoCacheHeaders(res);
|
|
76393
|
+
res.json({ privateKeys });
|
|
76394
|
+
zeroStringRecord(privateKeys);
|
|
76395
|
+
} catch (err) {
|
|
76396
|
+
const message = err instanceof Error ? err.message : "Failed to rotate service identity key";
|
|
76397
|
+
res.status(500).json({ error: message, code: "SERVICE_IDENTITY_ERROR" });
|
|
76398
|
+
}
|
|
76399
|
+
});
|
|
76285
76400
|
function dispose() {
|
|
76286
76401
|
lastScanResult = null;
|
|
76287
76402
|
lastScanAt = null;
|
|
@@ -76437,7 +76552,7 @@ var require_server = __commonJS({
|
|
|
76437
76552
|
const resolvedClientDir = clientDir ?? path44.resolve(__dirname, "../client");
|
|
76438
76553
|
app.use(staticLimiter, express_1.default.static(resolvedClientDir));
|
|
76439
76554
|
app.get("/{*splat}", staticLimiter, (_req, res) => {
|
|
76440
|
-
res.sendFile(
|
|
76555
|
+
res.sendFile("index.html", { root: resolvedClientDir });
|
|
76441
76556
|
});
|
|
76442
76557
|
}
|
|
76443
76558
|
const url = `http://127.0.0.1:${port}`;
|
|
@@ -76491,6 +76606,11 @@ var require_secrets_cache = __commonJS({
|
|
|
76491
76606
|
snapshot = null;
|
|
76492
76607
|
/** Replace the cached secrets in a single reference assignment. */
|
|
76493
76608
|
swap(values, keys, revision) {
|
|
76609
|
+
if (this.snapshot) {
|
|
76610
|
+
for (const k of Object.keys(this.snapshot.values)) {
|
|
76611
|
+
this.snapshot.values[k] = "";
|
|
76612
|
+
}
|
|
76613
|
+
}
|
|
76494
76614
|
this.snapshot = { values: { ...values }, keys: [...keys], revision, swappedAt: Date.now() };
|
|
76495
76615
|
}
|
|
76496
76616
|
/** Whether the cache has exceeded the given TTL (seconds). */
|
|
@@ -76499,8 +76619,13 @@ var require_secrets_cache = __commonJS({
|
|
|
76499
76619
|
return false;
|
|
76500
76620
|
return (Date.now() - this.snapshot.swappedAt) / 1e3 > ttlSeconds;
|
|
76501
76621
|
}
|
|
76502
|
-
/** Clear the cached snapshot. */
|
|
76622
|
+
/** Clear the cached snapshot, zeroing values first (best-effort). */
|
|
76503
76623
|
wipe() {
|
|
76624
|
+
if (this.snapshot) {
|
|
76625
|
+
for (const k of Object.keys(this.snapshot.values)) {
|
|
76626
|
+
this.snapshot.values[k] = "";
|
|
76627
|
+
}
|
|
76628
|
+
}
|
|
76504
76629
|
this.snapshot = null;
|
|
76505
76630
|
}
|
|
76506
76631
|
/** Epoch ms when the cache was last swapped, or null if never loaded. */
|
|
@@ -76579,7 +76704,7 @@ var require_disk_cache = __commonJS({
|
|
|
76579
76704
|
})();
|
|
76580
76705
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76581
76706
|
exports.DiskCache = void 0;
|
|
76582
|
-
var
|
|
76707
|
+
var fs26 = __importStar(__require("fs"));
|
|
76583
76708
|
var path44 = __importStar(__require("path"));
|
|
76584
76709
|
var DiskCache = class {
|
|
76585
76710
|
artifactPath;
|
|
@@ -76592,39 +76717,35 @@ var require_disk_cache = __commonJS({
|
|
|
76592
76717
|
/** Write an artifact and optional metadata to disk (atomic via tmp+rename). */
|
|
76593
76718
|
write(raw, sha) {
|
|
76594
76719
|
const dir = path44.dirname(this.artifactPath);
|
|
76595
|
-
|
|
76720
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
76596
76721
|
const tmpArtifact = `${this.artifactPath}.tmp.${process.pid}`;
|
|
76597
|
-
|
|
76598
|
-
|
|
76722
|
+
fs26.writeFileSync(tmpArtifact, raw, "utf-8");
|
|
76723
|
+
fs26.renameSync(tmpArtifact, this.artifactPath);
|
|
76599
76724
|
const meta = { sha, fetchedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
76600
76725
|
const tmpMeta = `${this.metaPath}.tmp.${process.pid}`;
|
|
76601
|
-
|
|
76602
|
-
|
|
76726
|
+
fs26.writeFileSync(tmpMeta, JSON.stringify(meta), "utf-8");
|
|
76727
|
+
fs26.renameSync(tmpMeta, this.metaPath);
|
|
76603
76728
|
}
|
|
76604
76729
|
/** Read the cached artifact. Returns null if no cache file exists. */
|
|
76605
76730
|
read() {
|
|
76606
76731
|
try {
|
|
76607
|
-
return
|
|
76732
|
+
return fs26.readFileSync(this.artifactPath, "utf-8");
|
|
76608
76733
|
} catch {
|
|
76609
76734
|
return null;
|
|
76610
76735
|
}
|
|
76611
76736
|
}
|
|
76612
76737
|
/** Get the SHA from the cached metadata, if available. */
|
|
76613
76738
|
getCachedSha() {
|
|
76614
|
-
|
|
76615
|
-
const raw = fs27.readFileSync(this.metaPath, "utf-8");
|
|
76616
|
-
const meta = JSON.parse(raw);
|
|
76617
|
-
return meta.sha;
|
|
76618
|
-
} catch {
|
|
76619
|
-
return void 0;
|
|
76620
|
-
}
|
|
76739
|
+
return this.readMeta()?.sha;
|
|
76621
76740
|
}
|
|
76622
76741
|
/** Get the fetchedAt timestamp from metadata, if available. */
|
|
76623
76742
|
getFetchedAt() {
|
|
76743
|
+
return this.readMeta()?.fetchedAt;
|
|
76744
|
+
}
|
|
76745
|
+
readMeta() {
|
|
76624
76746
|
try {
|
|
76625
|
-
const raw =
|
|
76626
|
-
|
|
76627
|
-
return meta.fetchedAt;
|
|
76747
|
+
const raw = fs26.readFileSync(this.metaPath, "utf-8");
|
|
76748
|
+
return JSON.parse(raw);
|
|
76628
76749
|
} catch {
|
|
76629
76750
|
return void 0;
|
|
76630
76751
|
}
|
|
@@ -76632,11 +76753,11 @@ var require_disk_cache = __commonJS({
|
|
|
76632
76753
|
/** Remove cached artifact and metadata files. */
|
|
76633
76754
|
purge() {
|
|
76634
76755
|
try {
|
|
76635
|
-
|
|
76756
|
+
fs26.unlinkSync(this.artifactPath);
|
|
76636
76757
|
} catch {
|
|
76637
76758
|
}
|
|
76638
76759
|
try {
|
|
76639
|
-
|
|
76760
|
+
fs26.unlinkSync(this.metaPath);
|
|
76640
76761
|
} catch {
|
|
76641
76762
|
}
|
|
76642
76763
|
}
|
|
@@ -76688,7 +76809,7 @@ var require_decrypt = __commonJS({
|
|
|
76688
76809
|
})();
|
|
76689
76810
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76690
76811
|
exports.AgeDecryptor = void 0;
|
|
76691
|
-
var
|
|
76812
|
+
var fs26 = __importStar(__require("fs"));
|
|
76692
76813
|
var AgeDecryptor = class {
|
|
76693
76814
|
/**
|
|
76694
76815
|
* Decrypt an age-encrypted PEM-armored ciphertext string.
|
|
@@ -76714,7 +76835,7 @@ var require_decrypt = __commonJS({
|
|
|
76714
76835
|
if (ageKey)
|
|
76715
76836
|
return ageKey.trim();
|
|
76716
76837
|
if (ageKeyFile) {
|
|
76717
|
-
const content =
|
|
76838
|
+
const content = fs26.readFileSync(ageKeyFile, "utf-8").trim();
|
|
76718
76839
|
const lines = content.split("\n").filter((l) => l.startsWith("AGE-SECRET-KEY-"));
|
|
76719
76840
|
if (lines.length === 0) {
|
|
76720
76841
|
throw new Error(`No age secret key found in file: ${ageKeyFile}`);
|
|
@@ -77046,6 +77167,147 @@ var require_kms = __commonJS({
|
|
|
77046
77167
|
}
|
|
77047
77168
|
});
|
|
77048
77169
|
|
|
77170
|
+
// ../runtime/dist/artifact-decryptor.js
|
|
77171
|
+
var require_artifact_decryptor = __commonJS({
|
|
77172
|
+
"../runtime/dist/artifact-decryptor.js"(exports) {
|
|
77173
|
+
"use strict";
|
|
77174
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
77175
|
+
if (k2 === void 0) k2 = k;
|
|
77176
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
77177
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
77178
|
+
desc = { enumerable: true, get: function() {
|
|
77179
|
+
return m[k];
|
|
77180
|
+
} };
|
|
77181
|
+
}
|
|
77182
|
+
Object.defineProperty(o, k2, desc);
|
|
77183
|
+
}) : (function(o, m, k, k2) {
|
|
77184
|
+
if (k2 === void 0) k2 = k;
|
|
77185
|
+
o[k2] = m[k];
|
|
77186
|
+
}));
|
|
77187
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
77188
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
77189
|
+
}) : function(o, v) {
|
|
77190
|
+
o["default"] = v;
|
|
77191
|
+
});
|
|
77192
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
|
|
77193
|
+
var ownKeys = function(o) {
|
|
77194
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
77195
|
+
var ar = [];
|
|
77196
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
77197
|
+
return ar;
|
|
77198
|
+
};
|
|
77199
|
+
return ownKeys(o);
|
|
77200
|
+
};
|
|
77201
|
+
return function(mod3) {
|
|
77202
|
+
if (mod3 && mod3.__esModule) return mod3;
|
|
77203
|
+
var result = {};
|
|
77204
|
+
if (mod3 != null) {
|
|
77205
|
+
for (var k = ownKeys(mod3), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod3, k[i]);
|
|
77206
|
+
}
|
|
77207
|
+
__setModuleDefault(result, mod3);
|
|
77208
|
+
return result;
|
|
77209
|
+
};
|
|
77210
|
+
})();
|
|
77211
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77212
|
+
exports.ArtifactDecryptor = void 0;
|
|
77213
|
+
var crypto6 = __importStar(__require("crypto"));
|
|
77214
|
+
var decrypt_1 = require_decrypt();
|
|
77215
|
+
var kms_1 = require_kms();
|
|
77216
|
+
var ArtifactDecryptor = class {
|
|
77217
|
+
ageDecryptor = new decrypt_1.AgeDecryptor();
|
|
77218
|
+
privateKey;
|
|
77219
|
+
telemetryOverride;
|
|
77220
|
+
initialTelemetry;
|
|
77221
|
+
constructor(options) {
|
|
77222
|
+
this.privateKey = options.privateKey;
|
|
77223
|
+
this.initialTelemetry = options.telemetry;
|
|
77224
|
+
}
|
|
77225
|
+
/** Set or replace the telemetry emitter. */
|
|
77226
|
+
setTelemetry(emitter) {
|
|
77227
|
+
this.telemetryOverride = emitter;
|
|
77228
|
+
}
|
|
77229
|
+
get telemetry() {
|
|
77230
|
+
return this.telemetryOverride ?? this.initialTelemetry;
|
|
77231
|
+
}
|
|
77232
|
+
/**
|
|
77233
|
+
* Decrypt an artifact envelope into plaintext key-value pairs.
|
|
77234
|
+
*
|
|
77235
|
+
* @throws On KMS unwrap failure, AES-GCM auth failure, age decrypt failure,
|
|
77236
|
+
* missing private key (config error), or malformed plaintext JSON.
|
|
77237
|
+
*/
|
|
77238
|
+
async decrypt(artifact) {
|
|
77239
|
+
let plaintext;
|
|
77240
|
+
if (artifact.envelope) {
|
|
77241
|
+
plaintext = await this.decryptKmsEnvelope(artifact);
|
|
77242
|
+
} else {
|
|
77243
|
+
plaintext = await this.decryptAge(artifact);
|
|
77244
|
+
}
|
|
77245
|
+
let values;
|
|
77246
|
+
try {
|
|
77247
|
+
values = JSON.parse(plaintext);
|
|
77248
|
+
} catch (err) {
|
|
77249
|
+
this.telemetry?.artifactInvalid({
|
|
77250
|
+
reason: "payload_parse",
|
|
77251
|
+
error: err instanceof Error ? err.message : String(err)
|
|
77252
|
+
});
|
|
77253
|
+
throw err;
|
|
77254
|
+
} finally {
|
|
77255
|
+
plaintext = "";
|
|
77256
|
+
}
|
|
77257
|
+
return { values, keys: artifact.keys, revision: artifact.revision };
|
|
77258
|
+
}
|
|
77259
|
+
/** KMS envelope: unwrap DEK via KMS, then AES-256-GCM decrypt. */
|
|
77260
|
+
async decryptKmsEnvelope(artifact) {
|
|
77261
|
+
const envelope = artifact.envelope;
|
|
77262
|
+
let dek;
|
|
77263
|
+
try {
|
|
77264
|
+
const kms = (0, kms_1.createKmsProvider)(envelope.provider);
|
|
77265
|
+
const wrappedKey = Buffer.from(envelope.wrappedKey, "base64");
|
|
77266
|
+
dek = await kms.unwrap(envelope.keyId, wrappedKey, envelope.algorithm);
|
|
77267
|
+
} catch (err) {
|
|
77268
|
+
this.telemetry?.artifactInvalid({
|
|
77269
|
+
reason: "kms_unwrap",
|
|
77270
|
+
error: err instanceof Error ? err.message : String(err)
|
|
77271
|
+
});
|
|
77272
|
+
throw err;
|
|
77273
|
+
}
|
|
77274
|
+
try {
|
|
77275
|
+
const iv = Buffer.from(envelope.iv, "base64");
|
|
77276
|
+
const authTag = Buffer.from(envelope.authTag, "base64");
|
|
77277
|
+
const ciphertextBuf = Buffer.from(artifact.ciphertext, "base64");
|
|
77278
|
+
const decipher = crypto6.createDecipheriv("aes-256-gcm", dek, iv);
|
|
77279
|
+
decipher.setAuthTag(authTag);
|
|
77280
|
+
return Buffer.concat([decipher.update(ciphertextBuf), decipher.final()]).toString("utf-8");
|
|
77281
|
+
} catch (err) {
|
|
77282
|
+
this.telemetry?.artifactInvalid({
|
|
77283
|
+
reason: "decrypt",
|
|
77284
|
+
error: err instanceof Error ? err.message : String(err)
|
|
77285
|
+
});
|
|
77286
|
+
throw err;
|
|
77287
|
+
} finally {
|
|
77288
|
+
dek.fill(0);
|
|
77289
|
+
}
|
|
77290
|
+
}
|
|
77291
|
+
/** Age-only: decrypt with the static private key. */
|
|
77292
|
+
async decryptAge(artifact) {
|
|
77293
|
+
if (!this.privateKey) {
|
|
77294
|
+
throw new Error("Artifact requires an age private key. Set CLEF_AGENT_AGE_KEY or use KMS envelope encryption.");
|
|
77295
|
+
}
|
|
77296
|
+
try {
|
|
77297
|
+
return await this.ageDecryptor.decrypt(artifact.ciphertext, this.privateKey);
|
|
77298
|
+
} catch (err) {
|
|
77299
|
+
this.telemetry?.artifactInvalid({
|
|
77300
|
+
reason: err instanceof SyntaxError ? "payload_parse" : "decrypt",
|
|
77301
|
+
error: err instanceof Error ? err.message : String(err)
|
|
77302
|
+
});
|
|
77303
|
+
throw err;
|
|
77304
|
+
}
|
|
77305
|
+
}
|
|
77306
|
+
};
|
|
77307
|
+
exports.ArtifactDecryptor = ArtifactDecryptor;
|
|
77308
|
+
}
|
|
77309
|
+
});
|
|
77310
|
+
|
|
77049
77311
|
// ../runtime/dist/signature.js
|
|
77050
77312
|
var require_signature = __commonJS({
|
|
77051
77313
|
"../runtime/dist/signature.js"(exports) {
|
|
@@ -77093,7 +77355,7 @@ var require_signature = __commonJS({
|
|
|
77093
77355
|
var crypto6 = __importStar(__require("crypto"));
|
|
77094
77356
|
function buildSigningPayload2(artifact) {
|
|
77095
77357
|
const fields = [
|
|
77096
|
-
"clef-sig-
|
|
77358
|
+
"clef-sig-v2",
|
|
77097
77359
|
String(artifact.version),
|
|
77098
77360
|
artifact.identity,
|
|
77099
77361
|
artifact.environment,
|
|
@@ -77105,7 +77367,9 @@ var require_signature = __commonJS({
|
|
|
77105
77367
|
artifact.envelope?.provider ?? "",
|
|
77106
77368
|
artifact.envelope?.keyId ?? "",
|
|
77107
77369
|
artifact.envelope?.wrappedKey ?? "",
|
|
77108
|
-
artifact.envelope?.algorithm ?? ""
|
|
77370
|
+
artifact.envelope?.algorithm ?? "",
|
|
77371
|
+
artifact.envelope?.iv ?? "",
|
|
77372
|
+
artifact.envelope?.authTag ?? ""
|
|
77109
77373
|
];
|
|
77110
77374
|
return Buffer.from(fields.join("\n"), "utf-8");
|
|
77111
77375
|
}
|
|
@@ -77172,8 +77436,7 @@ var require_poller = __commonJS({
|
|
|
77172
77436
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77173
77437
|
exports.ArtifactPoller = void 0;
|
|
77174
77438
|
var crypto6 = __importStar(__require("crypto"));
|
|
77175
|
-
var
|
|
77176
|
-
var kms_1 = require_kms();
|
|
77439
|
+
var artifact_decryptor_1 = require_artifact_decryptor();
|
|
77177
77440
|
var signature_1 = require_signature();
|
|
77178
77441
|
var MIN_POLL_MS = 5e3;
|
|
77179
77442
|
var ArtifactPoller = class {
|
|
@@ -77181,21 +77444,68 @@ var require_poller = __commonJS({
|
|
|
77181
77444
|
lastContentHash = null;
|
|
77182
77445
|
lastRevision = null;
|
|
77183
77446
|
lastExpiresAt = null;
|
|
77184
|
-
decryptor
|
|
77447
|
+
decryptor;
|
|
77185
77448
|
options;
|
|
77449
|
+
jitMode;
|
|
77186
77450
|
telemetryOverride;
|
|
77187
77451
|
constructor(options) {
|
|
77188
77452
|
this.options = options;
|
|
77453
|
+
this.jitMode = !!options.encryptedStore;
|
|
77454
|
+
this.decryptor = new artifact_decryptor_1.ArtifactDecryptor({
|
|
77455
|
+
privateKey: options.privateKey,
|
|
77456
|
+
telemetry: options.telemetry
|
|
77457
|
+
});
|
|
77458
|
+
}
|
|
77459
|
+
/** Get the decryptor instance (for JIT mode server wiring). */
|
|
77460
|
+
getDecryptor() {
|
|
77461
|
+
return this.decryptor;
|
|
77189
77462
|
}
|
|
77190
77463
|
/** Set or replace the telemetry emitter (e.g. after resolving token from secrets). */
|
|
77191
77464
|
setTelemetry(emitter) {
|
|
77192
77465
|
this.telemetryOverride = emitter;
|
|
77466
|
+
this.decryptor.setTelemetry(emitter);
|
|
77193
77467
|
}
|
|
77194
77468
|
get telemetry() {
|
|
77195
77469
|
return this.telemetryOverride ?? this.options.telemetry;
|
|
77196
77470
|
}
|
|
77197
|
-
/**
|
|
77471
|
+
/**
|
|
77472
|
+
* Fetch, validate, decrypt, and cache the artifact.
|
|
77473
|
+
* Used in cached mode (cacheTtl > 0).
|
|
77474
|
+
*/
|
|
77198
77475
|
async fetchAndDecrypt() {
|
|
77476
|
+
const result = await this.fetchRaw();
|
|
77477
|
+
if (!result)
|
|
77478
|
+
return;
|
|
77479
|
+
await this.validateDecryptAndCache(result.artifact, result.contentHash);
|
|
77480
|
+
}
|
|
77481
|
+
/**
|
|
77482
|
+
* Fetch and validate the artifact without decrypting.
|
|
77483
|
+
* Stores the validated envelope in the encryptedStore for on-demand decryption.
|
|
77484
|
+
* Used in JIT mode (cacheTtl = 0).
|
|
77485
|
+
*/
|
|
77486
|
+
async fetchAndValidate() {
|
|
77487
|
+
const result = await this.fetchRaw();
|
|
77488
|
+
if (!result)
|
|
77489
|
+
return;
|
|
77490
|
+
const artifact = this.validateArtifact(result.artifact);
|
|
77491
|
+
this.options.encryptedStore.swap(artifact);
|
|
77492
|
+
this.lastRevision = artifact.revision;
|
|
77493
|
+
this.lastContentHash = result.contentHash ?? null;
|
|
77494
|
+
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
77495
|
+
this.options.onRefresh?.(artifact.revision);
|
|
77496
|
+
this.telemetry?.artifactRefreshed({
|
|
77497
|
+
revision: artifact.revision,
|
|
77498
|
+
keyCount: artifact.keys.length,
|
|
77499
|
+
kmsEnvelope: !!artifact.envelope
|
|
77500
|
+
});
|
|
77501
|
+
}
|
|
77502
|
+
/**
|
|
77503
|
+
* Fetch the raw artifact from the source (with disk cache fallback),
|
|
77504
|
+
* parse JSON, and check for revocation.
|
|
77505
|
+
*
|
|
77506
|
+
* Returns null when the content hash is unchanged (short-circuit).
|
|
77507
|
+
*/
|
|
77508
|
+
async fetchRaw() {
|
|
77199
77509
|
let raw;
|
|
77200
77510
|
let contentHash;
|
|
77201
77511
|
try {
|
|
@@ -77203,7 +77513,7 @@ var require_poller = __commonJS({
|
|
|
77203
77513
|
raw = result.raw;
|
|
77204
77514
|
contentHash = result.contentHash;
|
|
77205
77515
|
if (contentHash && contentHash === this.lastContentHash)
|
|
77206
|
-
return;
|
|
77516
|
+
return null;
|
|
77207
77517
|
this.options.diskCache?.write(raw, contentHash);
|
|
77208
77518
|
} catch (err) {
|
|
77209
77519
|
this.telemetry?.fetchFailed({
|
|
@@ -77214,7 +77524,7 @@ var require_poller = __commonJS({
|
|
|
77214
77524
|
if (this.options.diskCache) {
|
|
77215
77525
|
const cached2 = this.options.diskCache.read();
|
|
77216
77526
|
if (cached2) {
|
|
77217
|
-
if (ttl !== void 0) {
|
|
77527
|
+
if (ttl !== void 0 && ttl > 0) {
|
|
77218
77528
|
const fetchedAt = this.options.diskCache.getFetchedAt();
|
|
77219
77529
|
if (fetchedAt && (Date.now() - new Date(fetchedAt).getTime()) / 1e3 > ttl) {
|
|
77220
77530
|
this.options.cache.wipe();
|
|
@@ -77229,9 +77539,9 @@ var require_poller = __commonJS({
|
|
|
77229
77539
|
raw = cached2;
|
|
77230
77540
|
contentHash = this.options.diskCache.getCachedSha();
|
|
77231
77541
|
if (contentHash && contentHash === this.lastContentHash)
|
|
77232
|
-
return;
|
|
77542
|
+
return null;
|
|
77233
77543
|
} else {
|
|
77234
|
-
if (ttl !== void 0 && this.options.cache.isExpired(ttl)) {
|
|
77544
|
+
if (ttl !== void 0 && ttl > 0 && this.options.cache.isExpired(ttl)) {
|
|
77235
77545
|
this.options.cache.wipe();
|
|
77236
77546
|
this.telemetry?.cacheExpired({
|
|
77237
77547
|
cacheTtlSeconds: ttl,
|
|
@@ -77242,7 +77552,7 @@ var require_poller = __commonJS({
|
|
|
77242
77552
|
throw err;
|
|
77243
77553
|
}
|
|
77244
77554
|
} else {
|
|
77245
|
-
if (ttl !== void 0 && this.options.cache.isExpired(ttl)) {
|
|
77555
|
+
if (ttl !== void 0 && ttl > 0 && this.options.cache.isExpired(ttl)) {
|
|
77246
77556
|
this.options.cache.wipe();
|
|
77247
77557
|
this.telemetry?.cacheExpired({
|
|
77248
77558
|
cacheTtlSeconds: ttl,
|
|
@@ -77256,6 +77566,7 @@ var require_poller = __commonJS({
|
|
|
77256
77566
|
const parsed = JSON.parse(raw);
|
|
77257
77567
|
if (parsed.revokedAt) {
|
|
77258
77568
|
this.options.cache.wipe();
|
|
77569
|
+
this.options.encryptedStore?.wipe();
|
|
77259
77570
|
this.options.diskCache?.purge();
|
|
77260
77571
|
this.lastRevision = null;
|
|
77261
77572
|
this.lastContentHash = null;
|
|
@@ -77264,17 +77575,18 @@ var require_poller = __commonJS({
|
|
|
77264
77575
|
});
|
|
77265
77576
|
throw new Error(`Artifact revoked: ${parsed.identity}/${parsed.environment} at ${parsed.revokedAt}`);
|
|
77266
77577
|
}
|
|
77267
|
-
|
|
77578
|
+
return { artifact: parsed, contentHash };
|
|
77268
77579
|
}
|
|
77269
77580
|
/**
|
|
77270
|
-
* Validate the artifact
|
|
77271
|
-
*
|
|
77272
|
-
*
|
|
77581
|
+
* Validate the artifact envelope: version, required fields, expiry,
|
|
77582
|
+
* revision dedup, integrity hash, and signature.
|
|
77583
|
+
* Emits `artifact.invalid` / `artifact.expired` telemetry on failure.
|
|
77584
|
+
* Returns the validated artifact, or throws.
|
|
77273
77585
|
*/
|
|
77274
|
-
|
|
77586
|
+
validateArtifact(parsed) {
|
|
77275
77587
|
let artifact;
|
|
77276
77588
|
try {
|
|
77277
|
-
artifact = this.
|
|
77589
|
+
artifact = this.validateEnvelope(parsed);
|
|
77278
77590
|
} catch (err) {
|
|
77279
77591
|
this.telemetry?.artifactInvalid({
|
|
77280
77592
|
reason: classifyValidationError(err),
|
|
@@ -77284,12 +77596,13 @@ var require_poller = __commonJS({
|
|
|
77284
77596
|
}
|
|
77285
77597
|
if (artifact.expiresAt && Date.now() > new Date(artifact.expiresAt).getTime()) {
|
|
77286
77598
|
this.options.cache.wipe();
|
|
77599
|
+
this.options.encryptedStore?.wipe();
|
|
77287
77600
|
this.options.diskCache?.purge();
|
|
77288
77601
|
this.telemetry?.artifactExpired({ expiresAt: artifact.expiresAt });
|
|
77289
77602
|
throw new Error(`Artifact expired at ${artifact.expiresAt}`);
|
|
77290
77603
|
}
|
|
77291
77604
|
if (artifact.revision === this.lastRevision)
|
|
77292
|
-
return;
|
|
77605
|
+
return artifact;
|
|
77293
77606
|
const hash = crypto6.createHash("sha256").update(artifact.ciphertext).digest("hex");
|
|
77294
77607
|
if (hash !== artifact.ciphertextHash) {
|
|
77295
77608
|
const err = new Error(`Artifact integrity check failed: expected hash ${artifact.ciphertextHash}, got ${hash}`);
|
|
@@ -77329,53 +77642,34 @@ var require_poller = __commonJS({
|
|
|
77329
77642
|
throw err;
|
|
77330
77643
|
}
|
|
77331
77644
|
}
|
|
77332
|
-
|
|
77333
|
-
|
|
77334
|
-
|
|
77335
|
-
|
|
77336
|
-
|
|
77337
|
-
|
|
77338
|
-
|
|
77339
|
-
|
|
77340
|
-
|
|
77341
|
-
|
|
77342
|
-
|
|
77343
|
-
|
|
77344
|
-
|
|
77345
|
-
|
|
77346
|
-
|
|
77347
|
-
|
|
77348
|
-
|
|
77349
|
-
|
|
77350
|
-
|
|
77351
|
-
|
|
77352
|
-
}
|
|
77353
|
-
try {
|
|
77354
|
-
const plaintext = await this.decryptor.decrypt(artifact.ciphertext, agePrivateKey);
|
|
77355
|
-
const values = JSON.parse(plaintext);
|
|
77356
|
-
this.options.cache.swap(values, artifact.keys, artifact.revision);
|
|
77357
|
-
this.lastRevision = artifact.revision;
|
|
77358
|
-
this.lastContentHash = contentHash ?? null;
|
|
77359
|
-
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
77360
|
-
this.options.onRefresh?.(artifact.revision);
|
|
77361
|
-
this.telemetry?.artifactRefreshed({
|
|
77362
|
-
revision: artifact.revision,
|
|
77363
|
-
keyCount: artifact.keys.length,
|
|
77364
|
-
kmsEnvelope: !!artifact.envelope
|
|
77365
|
-
});
|
|
77366
|
-
} catch (err) {
|
|
77367
|
-
if (err instanceof Error && !err.message.includes("integrity check failed")) {
|
|
77368
|
-
this.telemetry?.artifactInvalid({
|
|
77369
|
-
reason: err instanceof SyntaxError ? "payload_parse" : "decrypt",
|
|
77370
|
-
error: err.message
|
|
77371
|
-
});
|
|
77372
|
-
}
|
|
77373
|
-
throw err;
|
|
77374
|
-
}
|
|
77645
|
+
return artifact;
|
|
77646
|
+
}
|
|
77647
|
+
/**
|
|
77648
|
+
* Validate then decrypt and cache. Used by fetchAndDecrypt (cached mode).
|
|
77649
|
+
*/
|
|
77650
|
+
async validateDecryptAndCache(parsed, contentHash) {
|
|
77651
|
+
const artifact = this.validateArtifact(parsed);
|
|
77652
|
+
if (artifact.revision === this.lastRevision)
|
|
77653
|
+
return;
|
|
77654
|
+
const { values } = await this.decryptor.decrypt(artifact);
|
|
77655
|
+
this.options.cache.swap(values, artifact.keys, artifact.revision);
|
|
77656
|
+
this.lastRevision = artifact.revision;
|
|
77657
|
+
this.lastContentHash = contentHash ?? null;
|
|
77658
|
+
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
77659
|
+
this.options.onRefresh?.(artifact.revision);
|
|
77660
|
+
this.telemetry?.artifactRefreshed({
|
|
77661
|
+
revision: artifact.revision,
|
|
77662
|
+
keyCount: artifact.keys.length,
|
|
77663
|
+
kmsEnvelope: !!artifact.envelope
|
|
77664
|
+
});
|
|
77375
77665
|
}
|
|
77376
77666
|
/** Start the polling loop. Performs an initial fetch immediately. */
|
|
77377
77667
|
async start() {
|
|
77378
|
-
|
|
77668
|
+
if (this.jitMode) {
|
|
77669
|
+
await this.fetchAndValidate();
|
|
77670
|
+
} else {
|
|
77671
|
+
await this.fetchAndDecrypt();
|
|
77672
|
+
}
|
|
77379
77673
|
this.scheduleNext();
|
|
77380
77674
|
}
|
|
77381
77675
|
/** Start only the polling schedule (no initial fetch). */
|
|
@@ -77401,7 +77695,11 @@ var require_poller = __commonJS({
|
|
|
77401
77695
|
this.timer = setTimeout(async () => {
|
|
77402
77696
|
this.timer = null;
|
|
77403
77697
|
try {
|
|
77404
|
-
|
|
77698
|
+
if (this.jitMode) {
|
|
77699
|
+
await this.fetchAndValidate();
|
|
77700
|
+
} else {
|
|
77701
|
+
await this.fetchAndDecrypt();
|
|
77702
|
+
}
|
|
77405
77703
|
} catch (err) {
|
|
77406
77704
|
this.options.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
77407
77705
|
}
|
|
@@ -77417,14 +77715,15 @@ var require_poller = __commonJS({
|
|
|
77417
77715
|
}
|
|
77418
77716
|
return MIN_POLL_MS;
|
|
77419
77717
|
}
|
|
77718
|
+
if (this.jitMode)
|
|
77719
|
+
return MIN_POLL_MS;
|
|
77420
77720
|
const ttl = this.options.cacheTtl;
|
|
77421
77721
|
if (ttl !== void 0) {
|
|
77422
77722
|
return Math.max(ttl / 10 * 1e3, MIN_POLL_MS);
|
|
77423
77723
|
}
|
|
77424
77724
|
return 3e4;
|
|
77425
77725
|
}
|
|
77426
|
-
|
|
77427
|
-
const artifact = JSON.parse(raw);
|
|
77726
|
+
validateEnvelope(artifact) {
|
|
77428
77727
|
if (artifact.version !== 1) {
|
|
77429
77728
|
throw new Error(`Unsupported artifact version: ${artifact.version}`);
|
|
77430
77729
|
}
|
|
@@ -77432,7 +77731,7 @@ var require_poller = __commonJS({
|
|
|
77432
77731
|
throw new Error("Invalid artifact: missing required fields.");
|
|
77433
77732
|
}
|
|
77434
77733
|
if (artifact.envelope) {
|
|
77435
|
-
if (!artifact.envelope.provider || !artifact.envelope.keyId || !artifact.envelope.wrappedKey || !artifact.envelope.algorithm) {
|
|
77734
|
+
if (!artifact.envelope.provider || !artifact.envelope.keyId || !artifact.envelope.wrappedKey || !artifact.envelope.algorithm || !artifact.envelope.iv || !artifact.envelope.authTag) {
|
|
77436
77735
|
throw new Error("Invalid artifact: incomplete envelope fields.");
|
|
77437
77736
|
}
|
|
77438
77737
|
}
|
|
@@ -77457,6 +77756,50 @@ var require_poller = __commonJS({
|
|
|
77457
77756
|
}
|
|
77458
77757
|
});
|
|
77459
77758
|
|
|
77759
|
+
// ../runtime/dist/encrypted-artifact-store.js
|
|
77760
|
+
var require_encrypted_artifact_store = __commonJS({
|
|
77761
|
+
"../runtime/dist/encrypted-artifact-store.js"(exports) {
|
|
77762
|
+
"use strict";
|
|
77763
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77764
|
+
exports.EncryptedArtifactStore = void 0;
|
|
77765
|
+
var EncryptedArtifactStore = class {
|
|
77766
|
+
artifact = null;
|
|
77767
|
+
_storedAt = null;
|
|
77768
|
+
/** Atomically replace the stored artifact. */
|
|
77769
|
+
swap(artifact) {
|
|
77770
|
+
this.artifact = artifact;
|
|
77771
|
+
this._storedAt = Date.now();
|
|
77772
|
+
}
|
|
77773
|
+
/** Get the current encrypted artifact. Returns null if not yet loaded. */
|
|
77774
|
+
get() {
|
|
77775
|
+
return this.artifact;
|
|
77776
|
+
}
|
|
77777
|
+
/** Whether an artifact has been stored. */
|
|
77778
|
+
isReady() {
|
|
77779
|
+
return this.artifact !== null;
|
|
77780
|
+
}
|
|
77781
|
+
/** Epoch ms of last store, or null. */
|
|
77782
|
+
getStoredAt() {
|
|
77783
|
+
return this._storedAt;
|
|
77784
|
+
}
|
|
77785
|
+
/** Get key names from the stored artifact metadata (no decryption needed). */
|
|
77786
|
+
getKeys() {
|
|
77787
|
+
return this.artifact ? [...this.artifact.keys] : [];
|
|
77788
|
+
}
|
|
77789
|
+
/** Get the revision from the stored artifact. */
|
|
77790
|
+
getRevision() {
|
|
77791
|
+
return this.artifact?.revision ?? null;
|
|
77792
|
+
}
|
|
77793
|
+
/** Clear the stored artifact (on revocation/expiry). */
|
|
77794
|
+
wipe() {
|
|
77795
|
+
this.artifact = null;
|
|
77796
|
+
this._storedAt = null;
|
|
77797
|
+
}
|
|
77798
|
+
};
|
|
77799
|
+
exports.EncryptedArtifactStore = EncryptedArtifactStore;
|
|
77800
|
+
}
|
|
77801
|
+
});
|
|
77802
|
+
|
|
77460
77803
|
// ../runtime/dist/telemetry.js
|
|
77461
77804
|
var require_telemetry = __commonJS({
|
|
77462
77805
|
"../runtime/dist/telemetry.js"(exports) {
|
|
@@ -77811,14 +78154,23 @@ var require_http = __commonJS({
|
|
|
77811
78154
|
async fetch() {
|
|
77812
78155
|
const res = await fetch(this.url);
|
|
77813
78156
|
if (!res.ok) {
|
|
77814
|
-
throw new Error(`Failed to fetch artifact from ${this.
|
|
78157
|
+
throw new Error(`Failed to fetch artifact from ${this.describe()}: ${res.status}`);
|
|
77815
78158
|
}
|
|
77816
78159
|
const raw = await res.text();
|
|
77817
78160
|
const etag = res.headers.get("etag") ?? void 0;
|
|
77818
78161
|
return { raw, contentHash: etag };
|
|
77819
78162
|
}
|
|
77820
78163
|
describe() {
|
|
77821
|
-
|
|
78164
|
+
try {
|
|
78165
|
+
const parsed = new URL(this.url);
|
|
78166
|
+
if (parsed.username || parsed.password) {
|
|
78167
|
+
parsed.username = "***";
|
|
78168
|
+
parsed.password = "";
|
|
78169
|
+
}
|
|
78170
|
+
return `HTTP ${parsed.href}`;
|
|
78171
|
+
} catch {
|
|
78172
|
+
return "HTTP <invalid-url>";
|
|
78173
|
+
}
|
|
77822
78174
|
}
|
|
77823
78175
|
};
|
|
77824
78176
|
exports.HttpArtifactSource = HttpArtifactSource;
|
|
@@ -77868,14 +78220,14 @@ var require_file = __commonJS({
|
|
|
77868
78220
|
})();
|
|
77869
78221
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77870
78222
|
exports.FileArtifactSource = void 0;
|
|
77871
|
-
var
|
|
78223
|
+
var fs26 = __importStar(__require("fs"));
|
|
77872
78224
|
var FileArtifactSource = class {
|
|
77873
78225
|
path;
|
|
77874
78226
|
constructor(filePath) {
|
|
77875
78227
|
this.path = filePath;
|
|
77876
78228
|
}
|
|
77877
78229
|
async fetch() {
|
|
77878
|
-
const raw =
|
|
78230
|
+
const raw = fs26.readFileSync(this.path, "utf-8");
|
|
77879
78231
|
return { raw };
|
|
77880
78232
|
}
|
|
77881
78233
|
describe() {
|
|
@@ -77920,7 +78272,7 @@ var require_dist4 = __commonJS({
|
|
|
77920
78272
|
"../runtime/dist/index.js"(exports) {
|
|
77921
78273
|
"use strict";
|
|
77922
78274
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77923
|
-
exports.ClefRuntime = exports.verifySignature = exports.buildSigningPayload = exports.VcsArtifactSource = exports.FileArtifactSource = exports.HttpArtifactSource = exports.createKmsProvider = exports.AwsKmsProvider = exports.createVcsProvider = exports.BitbucketProvider = exports.GitLabProvider = exports.GitHubProvider = exports.TelemetryEmitter = exports.ArtifactPoller = exports.AgeDecryptor = exports.DiskCache = exports.SecretsCache = void 0;
|
|
78275
|
+
exports.ClefRuntime = exports.verifySignature = exports.buildSigningPayload = exports.VcsArtifactSource = exports.FileArtifactSource = exports.HttpArtifactSource = exports.createKmsProvider = exports.AwsKmsProvider = exports.createVcsProvider = exports.BitbucketProvider = exports.GitLabProvider = exports.GitHubProvider = exports.TelemetryEmitter = exports.EncryptedArtifactStore = exports.ArtifactDecryptor = exports.ArtifactPoller = exports.AgeDecryptor = exports.DiskCache = exports.SecretsCache = void 0;
|
|
77924
78276
|
exports.init = init;
|
|
77925
78277
|
var secrets_cache_1 = require_secrets_cache();
|
|
77926
78278
|
Object.defineProperty(exports, "SecretsCache", { enumerable: true, get: function() {
|
|
@@ -77938,6 +78290,14 @@ var require_dist4 = __commonJS({
|
|
|
77938
78290
|
Object.defineProperty(exports, "ArtifactPoller", { enumerable: true, get: function() {
|
|
77939
78291
|
return poller_1.ArtifactPoller;
|
|
77940
78292
|
} });
|
|
78293
|
+
var artifact_decryptor_1 = require_artifact_decryptor();
|
|
78294
|
+
Object.defineProperty(exports, "ArtifactDecryptor", { enumerable: true, get: function() {
|
|
78295
|
+
return artifact_decryptor_1.ArtifactDecryptor;
|
|
78296
|
+
} });
|
|
78297
|
+
var encrypted_artifact_store_1 = require_encrypted_artifact_store();
|
|
78298
|
+
Object.defineProperty(exports, "EncryptedArtifactStore", { enumerable: true, get: function() {
|
|
78299
|
+
return encrypted_artifact_store_1.EncryptedArtifactStore;
|
|
78300
|
+
} });
|
|
77941
78301
|
var telemetry_1 = require_telemetry();
|
|
77942
78302
|
Object.defineProperty(exports, "TelemetryEmitter", { enumerable: true, get: function() {
|
|
77943
78303
|
return telemetry_1.TelemetryEmitter;
|
|
@@ -78150,12 +78510,15 @@ var NodeSubprocessRunner = class {
|
|
|
78150
78510
|
};
|
|
78151
78511
|
|
|
78152
78512
|
// src/commands/init.ts
|
|
78153
|
-
var
|
|
78513
|
+
var YAML11 = __toESM(require_dist());
|
|
78154
78514
|
init_src();
|
|
78155
|
-
import * as
|
|
78515
|
+
import * as fs16 from "fs";
|
|
78156
78516
|
import * as path19 from "path";
|
|
78157
78517
|
import * as readline2 from "readline";
|
|
78158
78518
|
|
|
78519
|
+
// src/handle-error.ts
|
|
78520
|
+
init_src();
|
|
78521
|
+
|
|
78159
78522
|
// src/output/formatter.ts
|
|
78160
78523
|
var import_picocolors = __toESM(require_picocolors());
|
|
78161
78524
|
init_src();
|
|
@@ -78365,6 +78728,16 @@ function pad(str2, width) {
|
|
|
78365
78728
|
return diff > 0 ? str2 + " ".repeat(diff) : str2;
|
|
78366
78729
|
}
|
|
78367
78730
|
|
|
78731
|
+
// src/handle-error.ts
|
|
78732
|
+
function handleCommandError(err) {
|
|
78733
|
+
if (err instanceof SopsMissingError || err instanceof SopsVersionError) {
|
|
78734
|
+
formatter.formatDependencyError(err);
|
|
78735
|
+
} else {
|
|
78736
|
+
formatter.error(err.message);
|
|
78737
|
+
}
|
|
78738
|
+
process.exit(1);
|
|
78739
|
+
}
|
|
78740
|
+
|
|
78368
78741
|
// src/keychain.ts
|
|
78369
78742
|
var SERVICE = "clef";
|
|
78370
78743
|
var CRED_HELPER_CS = `
|
|
@@ -78815,8 +79188,8 @@ function registerInitCommand(program3, deps2) {
|
|
|
78815
79188
|
}
|
|
78816
79189
|
const manifestPath = path19.join(repoRoot, "clef.yaml");
|
|
78817
79190
|
const clefConfigPath = path19.join(repoRoot, CLEF_DIR, CLEF_CONFIG_FILENAME);
|
|
78818
|
-
const manifestExists =
|
|
78819
|
-
const localConfigExists =
|
|
79191
|
+
const manifestExists = fs16.existsSync(manifestPath);
|
|
79192
|
+
const localConfigExists = fs16.existsSync(clefConfigPath);
|
|
78820
79193
|
if (manifestExists && localConfigExists) {
|
|
78821
79194
|
formatter.print("Already initialised. Run 'clef update' to scaffold new environments.");
|
|
78822
79195
|
process.exit(0);
|
|
@@ -78838,8 +79211,7 @@ function registerInitCommand(program3, deps2) {
|
|
|
78838
79211
|
}
|
|
78839
79212
|
await handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, options);
|
|
78840
79213
|
} catch (err) {
|
|
78841
|
-
|
|
78842
|
-
process.exit(1);
|
|
79214
|
+
handleCommandError(err);
|
|
78843
79215
|
}
|
|
78844
79216
|
});
|
|
78845
79217
|
}
|
|
@@ -78871,22 +79243,22 @@ async function handleSecondDevOnboarding(repoRoot, clefConfigPath, deps2, option
|
|
|
78871
79243
|
const publicKey = identity.publicKey;
|
|
78872
79244
|
const keyContent = formatAgeKeyFile(privateKey, publicKey);
|
|
78873
79245
|
const keyDir = path19.dirname(keyPath);
|
|
78874
|
-
if (!
|
|
78875
|
-
|
|
79246
|
+
if (!fs16.existsSync(keyDir)) {
|
|
79247
|
+
fs16.mkdirSync(keyDir, { recursive: true });
|
|
78876
79248
|
}
|
|
78877
|
-
|
|
79249
|
+
fs16.writeFileSync(keyPath, keyContent, { encoding: "utf-8", mode: 384 });
|
|
78878
79250
|
formatter.success(`Generated age key at ${keyPath}`);
|
|
78879
79251
|
config = { age_key_file: keyPath, age_key_storage: "file", age_keychain_label: label2 };
|
|
78880
79252
|
}
|
|
78881
79253
|
const clefDir = path19.dirname(clefConfigPath);
|
|
78882
|
-
if (!
|
|
78883
|
-
|
|
79254
|
+
if (!fs16.existsSync(clefDir)) {
|
|
79255
|
+
fs16.mkdirSync(clefDir, { recursive: true });
|
|
78884
79256
|
}
|
|
78885
|
-
|
|
79257
|
+
fs16.writeFileSync(clefConfigPath, YAML11.stringify(config), "utf-8");
|
|
78886
79258
|
formatter.success("Created .clef/config.yaml");
|
|
78887
79259
|
const gitignorePath = path19.join(clefDir, ".gitignore");
|
|
78888
|
-
if (!
|
|
78889
|
-
|
|
79260
|
+
if (!fs16.existsSync(gitignorePath)) {
|
|
79261
|
+
fs16.writeFileSync(gitignorePath, "*\n", "utf-8");
|
|
78890
79262
|
formatter.success("Created .clef/.gitignore");
|
|
78891
79263
|
}
|
|
78892
79264
|
formatter.success(`Key label: ${label2}`);
|
|
@@ -78978,38 +79350,38 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
|
|
|
78978
79350
|
}
|
|
78979
79351
|
const keyContent = formatAgeKeyFile(privateKey, publicKey);
|
|
78980
79352
|
const keyDir = path19.dirname(keyPath);
|
|
78981
|
-
if (!
|
|
78982
|
-
|
|
79353
|
+
if (!fs16.existsSync(keyDir)) {
|
|
79354
|
+
fs16.mkdirSync(keyDir, { recursive: true });
|
|
78983
79355
|
}
|
|
78984
|
-
|
|
79356
|
+
fs16.writeFileSync(keyPath, keyContent, { encoding: "utf-8", mode: 384 });
|
|
78985
79357
|
formatter.success(`Generated age key at ${keyPath}`);
|
|
78986
79358
|
ageKeyFile = keyPath;
|
|
78987
79359
|
}
|
|
78988
79360
|
const clefDir = path19.dirname(clefConfigPath);
|
|
78989
|
-
if (!
|
|
78990
|
-
|
|
79361
|
+
if (!fs16.existsSync(clefDir)) {
|
|
79362
|
+
fs16.mkdirSync(clefDir, { recursive: true });
|
|
78991
79363
|
}
|
|
78992
79364
|
const config = ageKeyFile ? { age_key_file: ageKeyFile, age_key_storage: "file", age_keychain_label: label2 } : { age_key_storage: "keychain", age_keychain_label: label2 };
|
|
78993
|
-
|
|
79365
|
+
fs16.writeFileSync(clefConfigPath, YAML11.stringify(config), "utf-8");
|
|
78994
79366
|
formatter.success("Created .clef/config.yaml");
|
|
78995
79367
|
const gitignorePath = path19.join(clefDir, ".gitignore");
|
|
78996
|
-
if (!
|
|
78997
|
-
|
|
79368
|
+
if (!fs16.existsSync(gitignorePath)) {
|
|
79369
|
+
fs16.writeFileSync(gitignorePath, "*\n", "utf-8");
|
|
78998
79370
|
formatter.success("Created .clef/.gitignore");
|
|
78999
79371
|
}
|
|
79000
79372
|
formatter.success(`Key label: ${label2}`);
|
|
79001
79373
|
}
|
|
79002
|
-
const manifestDoc =
|
|
79374
|
+
const manifestDoc = YAML11.parse(YAML11.stringify(manifest));
|
|
79003
79375
|
if (backend === "age" && publicKey) {
|
|
79004
79376
|
const sopsDoc = manifestDoc.sops;
|
|
79005
79377
|
sopsDoc.age = { recipients: [publicKey] };
|
|
79006
79378
|
}
|
|
79007
|
-
|
|
79379
|
+
fs16.writeFileSync(manifestPath, YAML11.stringify(manifestDoc), "utf-8");
|
|
79008
79380
|
formatter.success("Created clef.yaml");
|
|
79009
79381
|
{
|
|
79010
79382
|
const sopsYamlPath = path19.join(repoRoot, ".sops.yaml");
|
|
79011
79383
|
const sopsConfig = buildSopsYaml(manifest, repoRoot, publicKey);
|
|
79012
|
-
|
|
79384
|
+
fs16.writeFileSync(sopsYamlPath, YAML11.stringify(sopsConfig), "utf-8");
|
|
79013
79385
|
formatter.success("Created .sops.yaml");
|
|
79014
79386
|
}
|
|
79015
79387
|
const sopsClient = new SopsClient(deps2.runner, ageKeyFile, ageKey);
|
|
@@ -79066,8 +79438,8 @@ async function handleFullSetup(repoRoot, manifestPath, clefConfigPath, deps2, op
|
|
|
79066
79438
|
}
|
|
79067
79439
|
}
|
|
79068
79440
|
const clefignorePath = path19.join(repoRoot, ".clefignore");
|
|
79069
|
-
if (!
|
|
79070
|
-
|
|
79441
|
+
if (!fs16.existsSync(clefignorePath)) {
|
|
79442
|
+
fs16.writeFileSync(clefignorePath, DEFAULT_CLEFIGNORE, "utf-8");
|
|
79071
79443
|
formatter.success("Created .clefignore");
|
|
79072
79444
|
} else {
|
|
79073
79445
|
formatter.print(" .clefignore already exists \u2014 skipping");
|
|
@@ -79099,7 +79471,7 @@ function scaffoldSopsConfig(repoRoot) {
|
|
|
79099
79471
|
agePublicKey = resolveAgePublicKeyFromEnvOrFile(repoRoot);
|
|
79100
79472
|
}
|
|
79101
79473
|
const sopsConfig = buildSopsYaml(manifest, repoRoot, agePublicKey);
|
|
79102
|
-
|
|
79474
|
+
fs16.writeFileSync(sopsYamlPath, YAML11.stringify(sopsConfig), "utf-8");
|
|
79103
79475
|
}
|
|
79104
79476
|
function buildSopsYaml(manifest, _repoRoot, agePublicKey) {
|
|
79105
79477
|
const creationRules = [];
|
|
@@ -79163,9 +79535,9 @@ function resolveAgePublicKeyFromEnvOrFile(repoRoot) {
|
|
|
79163
79535
|
if (match) return match[1];
|
|
79164
79536
|
}
|
|
79165
79537
|
const clefConfigPath = path19.join(repoRoot, CLEF_DIR, CLEF_CONFIG_FILENAME);
|
|
79166
|
-
if (
|
|
79538
|
+
if (fs16.existsSync(clefConfigPath)) {
|
|
79167
79539
|
try {
|
|
79168
|
-
const config =
|
|
79540
|
+
const config = YAML11.parse(fs16.readFileSync(clefConfigPath, "utf-8"));
|
|
79169
79541
|
if (config?.age_key_file) {
|
|
79170
79542
|
const pubKey = extractAgePublicKey(config.age_key_file);
|
|
79171
79543
|
if (pubKey) return pubKey;
|
|
@@ -79177,8 +79549,8 @@ function resolveAgePublicKeyFromEnvOrFile(repoRoot) {
|
|
|
79177
79549
|
}
|
|
79178
79550
|
function extractAgePublicKey(keyFilePath) {
|
|
79179
79551
|
try {
|
|
79180
|
-
if (!
|
|
79181
|
-
const content =
|
|
79552
|
+
if (!fs16.existsSync(keyFilePath)) return void 0;
|
|
79553
|
+
const content = fs16.readFileSync(keyFilePath, "utf-8");
|
|
79182
79554
|
const match = content.match(/# public key: (age1[a-z0-9]+)/);
|
|
79183
79555
|
return match ? match[1] : void 0;
|
|
79184
79556
|
} catch {
|
|
@@ -79245,9 +79617,9 @@ init_src();
|
|
|
79245
79617
|
import * as path21 from "path";
|
|
79246
79618
|
|
|
79247
79619
|
// src/age-credential.ts
|
|
79248
|
-
var
|
|
79620
|
+
var YAML12 = __toESM(require_dist());
|
|
79249
79621
|
init_src();
|
|
79250
|
-
import * as
|
|
79622
|
+
import * as fs17 from "fs";
|
|
79251
79623
|
import * as path20 from "path";
|
|
79252
79624
|
var CLEF_DIR2 = ".clef";
|
|
79253
79625
|
var CLEF_CONFIG_FILENAME2 = "config.yaml";
|
|
@@ -79312,7 +79684,7 @@ async function resolveAgePrivateKey(repoRoot, runner2) {
|
|
|
79312
79684
|
const filePath = process.env.CLEF_AGE_KEY_FILE;
|
|
79313
79685
|
if (!filePath) return null;
|
|
79314
79686
|
try {
|
|
79315
|
-
const content =
|
|
79687
|
+
const content = fs17.readFileSync(filePath, "utf-8");
|
|
79316
79688
|
const match = content.match(AGE_SECRET_KEY_RE);
|
|
79317
79689
|
return match ? match[1] : null;
|
|
79318
79690
|
} catch (err) {
|
|
@@ -79324,7 +79696,7 @@ async function resolveAgePrivateKey(repoRoot, runner2) {
|
|
|
79324
79696
|
}
|
|
79325
79697
|
case "config-file": {
|
|
79326
79698
|
try {
|
|
79327
|
-
const content =
|
|
79699
|
+
const content = fs17.readFileSync(credential.path, "utf-8");
|
|
79328
79700
|
const match = content.match(AGE_SECRET_KEY_RE);
|
|
79329
79701
|
return match ? match[1] : null;
|
|
79330
79702
|
} catch (err) {
|
|
@@ -79339,8 +79711,8 @@ async function resolveAgePrivateKey(repoRoot, runner2) {
|
|
|
79339
79711
|
function readLocalConfig(repoRoot) {
|
|
79340
79712
|
const clefConfigPath = path20.join(repoRoot, CLEF_DIR2, CLEF_CONFIG_FILENAME2);
|
|
79341
79713
|
try {
|
|
79342
|
-
if (!
|
|
79343
|
-
return
|
|
79714
|
+
if (!fs17.existsSync(clefConfigPath)) return null;
|
|
79715
|
+
return YAML12.parse(fs17.readFileSync(clefConfigPath, "utf-8"));
|
|
79344
79716
|
} catch (err) {
|
|
79345
79717
|
formatter.warn(
|
|
79346
79718
|
`Failed to parse ${clefConfigPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -79382,6 +79754,15 @@ function maskedPlaceholder() {
|
|
|
79382
79754
|
return "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
79383
79755
|
}
|
|
79384
79756
|
|
|
79757
|
+
// src/parse-target.ts
|
|
79758
|
+
function parseTarget(target) {
|
|
79759
|
+
const parts = target.split("/");
|
|
79760
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79761
|
+
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79762
|
+
}
|
|
79763
|
+
return [parts[0], parts[1]];
|
|
79764
|
+
}
|
|
79765
|
+
|
|
79385
79766
|
// src/commands/get.ts
|
|
79386
79767
|
function registerGetCommand(program3, deps2) {
|
|
79387
79768
|
program3.command("get <target> <key>").description(
|
|
@@ -79417,23 +79798,10 @@ function registerGetCommand(program3, deps2) {
|
|
|
79417
79798
|
}
|
|
79418
79799
|
}
|
|
79419
79800
|
} catch (err) {
|
|
79420
|
-
|
|
79421
|
-
formatter.formatDependencyError(err);
|
|
79422
|
-
process.exit(1);
|
|
79423
|
-
return;
|
|
79424
|
-
}
|
|
79425
|
-
formatter.error(err.message);
|
|
79426
|
-
process.exit(1);
|
|
79801
|
+
handleCommandError(err);
|
|
79427
79802
|
}
|
|
79428
79803
|
});
|
|
79429
79804
|
}
|
|
79430
|
-
function parseTarget(target) {
|
|
79431
|
-
const parts = target.split("/");
|
|
79432
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79433
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79434
|
-
}
|
|
79435
|
-
return [parts[0], parts[1]];
|
|
79436
|
-
}
|
|
79437
79805
|
|
|
79438
79806
|
// src/commands/set.ts
|
|
79439
79807
|
init_src();
|
|
@@ -79548,7 +79916,7 @@ function registerSetCommand(program3, deps2) {
|
|
|
79548
79916
|
Consider using the interactive prompt instead: clef set ${target} ${key}`
|
|
79549
79917
|
);
|
|
79550
79918
|
}
|
|
79551
|
-
const [namespace, environment] =
|
|
79919
|
+
const [namespace, environment] = parseTarget(target);
|
|
79552
79920
|
const matrixManager = new MatrixManager();
|
|
79553
79921
|
if (matrixManager.isProtectedEnvironment(manifest, environment)) {
|
|
79554
79922
|
const confirmed = await formatter.confirm(
|
|
@@ -79580,11 +79948,22 @@ function registerSetCommand(program3, deps2) {
|
|
|
79580
79948
|
try {
|
|
79581
79949
|
await markPendingWithRetry(filePath, [key], "clef set --random");
|
|
79582
79950
|
} catch {
|
|
79583
|
-
|
|
79584
|
-
|
|
79585
|
-
|
|
79951
|
+
try {
|
|
79952
|
+
delete decrypted.values[key];
|
|
79953
|
+
await sopsClient.encrypt(filePath, decrypted.values, manifest, environment);
|
|
79954
|
+
} catch {
|
|
79955
|
+
formatter.error(
|
|
79956
|
+
`${key} was encrypted but pending state could not be recorded, and rollback failed.
|
|
79957
|
+
The encrypted file may contain an untracked random placeholder.
|
|
79586
79958
|
This key MUST be set to a real value before deploying.
|
|
79587
79959
|
Run: clef set ${namespace}/${environment} ${key}`
|
|
79960
|
+
);
|
|
79961
|
+
process.exit(1);
|
|
79962
|
+
return;
|
|
79963
|
+
}
|
|
79964
|
+
formatter.error(
|
|
79965
|
+
`${key}: pending state could not be recorded. The value was rolled back.
|
|
79966
|
+
Retry: clef set --random ${namespace}/${environment} ${key}`
|
|
79588
79967
|
);
|
|
79589
79968
|
process.exit(1);
|
|
79590
79969
|
return;
|
|
@@ -79609,24 +79988,11 @@ function registerSetCommand(program3, deps2) {
|
|
|
79609
79988
|
);
|
|
79610
79989
|
}
|
|
79611
79990
|
} catch (err) {
|
|
79612
|
-
|
|
79613
|
-
formatter.formatDependencyError(err);
|
|
79614
|
-
process.exit(1);
|
|
79615
|
-
return;
|
|
79616
|
-
}
|
|
79617
|
-
formatter.error(err.message);
|
|
79618
|
-
process.exit(1);
|
|
79991
|
+
handleCommandError(err);
|
|
79619
79992
|
}
|
|
79620
79993
|
}
|
|
79621
79994
|
);
|
|
79622
79995
|
}
|
|
79623
|
-
function parseTarget2(target) {
|
|
79624
|
-
const parts = target.split("/");
|
|
79625
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79626
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79627
|
-
}
|
|
79628
|
-
return [parts[0], parts[1]];
|
|
79629
|
-
}
|
|
79630
79996
|
|
|
79631
79997
|
// src/commands/compare.ts
|
|
79632
79998
|
init_src();
|
|
@@ -79637,7 +80003,7 @@ function registerCompareCommand(program3, deps2) {
|
|
|
79637
80003
|
"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"
|
|
79638
80004
|
).action(async (target, key, value) => {
|
|
79639
80005
|
try {
|
|
79640
|
-
const [namespace, environment] =
|
|
80006
|
+
const [namespace, environment] = parseTarget(target);
|
|
79641
80007
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
79642
80008
|
const parser = new ManifestParser();
|
|
79643
80009
|
const manifest = parser.parse(path23.join(repoRoot, "clef.yaml"));
|
|
@@ -79667,7 +80033,15 @@ function registerCompareCommand(program3, deps2) {
|
|
|
79667
80033
|
return;
|
|
79668
80034
|
}
|
|
79669
80035
|
const stored = decrypted.values[key];
|
|
79670
|
-
const
|
|
80036
|
+
const storedBuf = Buffer.from(stored);
|
|
80037
|
+
const compareBuf = Buffer.from(compareValue);
|
|
80038
|
+
const maxLen = Math.max(storedBuf.length, compareBuf.length, 1);
|
|
80039
|
+
const paddedStored = Buffer.alloc(maxLen);
|
|
80040
|
+
const paddedCompare = Buffer.alloc(maxLen);
|
|
80041
|
+
storedBuf.copy(paddedStored);
|
|
80042
|
+
compareBuf.copy(paddedCompare);
|
|
80043
|
+
const timingEqual = crypto5.timingSafeEqual(paddedStored, paddedCompare);
|
|
80044
|
+
const match = storedBuf.length === compareBuf.length && timingEqual;
|
|
79671
80045
|
if (match) {
|
|
79672
80046
|
formatter.success(`${key} ${sym("arrow")} values match`);
|
|
79673
80047
|
} else {
|
|
@@ -79675,23 +80049,10 @@ function registerCompareCommand(program3, deps2) {
|
|
|
79675
80049
|
process.exit(1);
|
|
79676
80050
|
}
|
|
79677
80051
|
} catch (err) {
|
|
79678
|
-
|
|
79679
|
-
formatter.formatDependencyError(err);
|
|
79680
|
-
process.exit(1);
|
|
79681
|
-
return;
|
|
79682
|
-
}
|
|
79683
|
-
formatter.error(err.message);
|
|
79684
|
-
process.exit(1);
|
|
80052
|
+
handleCommandError(err);
|
|
79685
80053
|
}
|
|
79686
80054
|
});
|
|
79687
80055
|
}
|
|
79688
|
-
function parseTarget3(target) {
|
|
79689
|
-
const parts = target.split("/");
|
|
79690
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79691
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79692
|
-
}
|
|
79693
|
-
return [parts[0], parts[1]];
|
|
79694
|
-
}
|
|
79695
80056
|
|
|
79696
80057
|
// src/commands/delete.ts
|
|
79697
80058
|
init_src();
|
|
@@ -79723,7 +80084,7 @@ Type the key name to confirm:`
|
|
|
79723
80084
|
await bulkOps.deleteAcrossEnvironments(namespace, key, manifest, sopsClient, repoRoot);
|
|
79724
80085
|
formatter.success(`Deleted '${key}' from ${namespace} in all environments`);
|
|
79725
80086
|
} else {
|
|
79726
|
-
const [namespace, environment] =
|
|
80087
|
+
const [namespace, environment] = parseTarget(target);
|
|
79727
80088
|
if (matrixManager.isProtectedEnvironment(manifest, environment)) {
|
|
79728
80089
|
const protConfirmed = await formatter.confirm(
|
|
79729
80090
|
`This is a protected environment (${environment}). Are you sure you want to delete '${key}'?`
|
|
@@ -79765,23 +80126,10 @@ Type the key name to confirm:`
|
|
|
79765
80126
|
);
|
|
79766
80127
|
}
|
|
79767
80128
|
} catch (err) {
|
|
79768
|
-
|
|
79769
|
-
formatter.formatDependencyError(err);
|
|
79770
|
-
process.exit(1);
|
|
79771
|
-
return;
|
|
79772
|
-
}
|
|
79773
|
-
formatter.error(err.message);
|
|
79774
|
-
process.exit(1);
|
|
80129
|
+
handleCommandError(err);
|
|
79775
80130
|
}
|
|
79776
80131
|
});
|
|
79777
80132
|
}
|
|
79778
|
-
function parseTarget4(target) {
|
|
79779
|
-
const parts = target.split("/");
|
|
79780
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
79781
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
79782
|
-
}
|
|
79783
|
-
return [parts[0], parts[1]];
|
|
79784
|
-
}
|
|
79785
80133
|
|
|
79786
80134
|
// src/commands/diff.ts
|
|
79787
80135
|
var import_picocolors2 = __toESM(require_picocolors());
|
|
@@ -79836,13 +80184,7 @@ function registerDiffCommand(program3, deps2) {
|
|
|
79836
80184
|
const hasDiffs = result.rows.some((r) => r.status !== "identical");
|
|
79837
80185
|
process.exit(hasDiffs ? 1 : 0);
|
|
79838
80186
|
} catch (err) {
|
|
79839
|
-
|
|
79840
|
-
formatter.formatDependencyError(err);
|
|
79841
|
-
process.exit(1);
|
|
79842
|
-
return;
|
|
79843
|
-
}
|
|
79844
|
-
formatter.error(err.message);
|
|
79845
|
-
process.exit(1);
|
|
80187
|
+
handleCommandError(err);
|
|
79846
80188
|
}
|
|
79847
80189
|
}
|
|
79848
80190
|
);
|
|
@@ -80129,7 +80471,7 @@ async function fetchCheckpoint(config) {
|
|
|
80129
80471
|
}
|
|
80130
80472
|
|
|
80131
80473
|
// package.json
|
|
80132
|
-
var version = "0.1.
|
|
80474
|
+
var version = "0.1.9-beta.57";
|
|
80133
80475
|
var package_default = {
|
|
80134
80476
|
name: "@clef-sh/cli",
|
|
80135
80477
|
version,
|
|
@@ -80234,13 +80576,7 @@ function registerLintCommand(program3, deps2) {
|
|
|
80234
80576
|
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
80235
80577
|
process.exit(hasErrors ? 1 : 0);
|
|
80236
80578
|
} catch (err) {
|
|
80237
|
-
|
|
80238
|
-
formatter.formatDependencyError(err);
|
|
80239
|
-
process.exit(1);
|
|
80240
|
-
return;
|
|
80241
|
-
}
|
|
80242
|
-
formatter.error(err.message);
|
|
80243
|
-
process.exit(1);
|
|
80579
|
+
handleCommandError(err);
|
|
80244
80580
|
}
|
|
80245
80581
|
});
|
|
80246
80582
|
}
|
|
@@ -80310,7 +80646,7 @@ function registerRotateCommand(program3, deps2) {
|
|
|
80310
80646
|
"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"
|
|
80311
80647
|
).requiredOption("--new-key <key>", "New age public key to rotate to").action(async (target, options) => {
|
|
80312
80648
|
try {
|
|
80313
|
-
const [namespace, environment] =
|
|
80649
|
+
const [namespace, environment] = parseTarget(target);
|
|
80314
80650
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
80315
80651
|
const parser = new ManifestParser();
|
|
80316
80652
|
const manifest = parser.parse(path27.join(repoRoot, "clef.yaml"));
|
|
@@ -80337,27 +80673,14 @@ function registerRotateCommand(program3, deps2) {
|
|
|
80337
80673
|
`git add ${relativeFile} && git commit -m "rotate: ${namespace}/${environment}"`
|
|
80338
80674
|
);
|
|
80339
80675
|
} catch (err) {
|
|
80340
|
-
|
|
80341
|
-
formatter.formatDependencyError(err);
|
|
80342
|
-
process.exit(1);
|
|
80343
|
-
return;
|
|
80344
|
-
}
|
|
80345
|
-
formatter.error(err.message);
|
|
80346
|
-
process.exit(1);
|
|
80676
|
+
handleCommandError(err);
|
|
80347
80677
|
}
|
|
80348
80678
|
});
|
|
80349
80679
|
}
|
|
80350
|
-
function parseTarget5(target) {
|
|
80351
|
-
const parts = target.split("/");
|
|
80352
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
80353
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
80354
|
-
}
|
|
80355
|
-
return [parts[0], parts[1]];
|
|
80356
|
-
}
|
|
80357
80680
|
|
|
80358
80681
|
// src/commands/hooks.ts
|
|
80359
80682
|
init_src();
|
|
80360
|
-
import * as
|
|
80683
|
+
import * as fs18 from "fs";
|
|
80361
80684
|
import * as path28 from "path";
|
|
80362
80685
|
function registerHooksCommand(program3, deps2) {
|
|
80363
80686
|
const hooks = program3.command("hooks").description("Manage git hooks for Clef");
|
|
@@ -80365,8 +80688,8 @@ function registerHooksCommand(program3, deps2) {
|
|
|
80365
80688
|
try {
|
|
80366
80689
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
80367
80690
|
const hookPath = path28.join(repoRoot, ".git", "hooks", "pre-commit");
|
|
80368
|
-
if (
|
|
80369
|
-
const content =
|
|
80691
|
+
if (fs18.existsSync(hookPath)) {
|
|
80692
|
+
const content = fs18.readFileSync(hookPath, "utf-8");
|
|
80370
80693
|
if (content.includes("clef") || content.includes("SOPS")) {
|
|
80371
80694
|
const confirmed = await formatter.confirm(
|
|
80372
80695
|
"A Clef pre-commit hook already exists. Overwrite?"
|
|
@@ -80497,6 +80820,7 @@ async function openBrowser(url, runner2) {
|
|
|
80497
80820
|
|
|
80498
80821
|
// src/commands/exec.ts
|
|
80499
80822
|
init_src();
|
|
80823
|
+
import * as os2 from "os";
|
|
80500
80824
|
import * as path30 from "path";
|
|
80501
80825
|
import { spawn } from "child_process";
|
|
80502
80826
|
function collect(value, previous) {
|
|
@@ -80532,7 +80856,7 @@ function registerExecCommand(program3, deps2) {
|
|
|
80532
80856
|
process.exit(1);
|
|
80533
80857
|
return;
|
|
80534
80858
|
}
|
|
80535
|
-
const [namespace, environment] =
|
|
80859
|
+
const [namespace, environment] = parseTarget(target);
|
|
80536
80860
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
80537
80861
|
const parser = new ManifestParser();
|
|
80538
80862
|
const manifest = parser.parse(path30.join(repoRoot, "clef.yaml"));
|
|
@@ -80549,7 +80873,7 @@ function registerExecCommand(program3, deps2) {
|
|
|
80549
80873
|
const mergedValues = { ...primaryDecrypted.values };
|
|
80550
80874
|
for (const alsoTarget of options.also) {
|
|
80551
80875
|
try {
|
|
80552
|
-
const [alsoNs, alsoEnv] =
|
|
80876
|
+
const [alsoNs, alsoEnv] = parseTarget(alsoTarget);
|
|
80553
80877
|
const alsoFilePath = path30.join(
|
|
80554
80878
|
repoRoot,
|
|
80555
80879
|
manifest.file_pattern.replace("{namespace}", alsoNs).replace("{environment}", alsoEnv)
|
|
@@ -80586,14 +80910,7 @@ function registerExecCommand(program3, deps2) {
|
|
|
80586
80910
|
const exitCode = await spawnChild(childCommand, childCommandArgs, childEnv);
|
|
80587
80911
|
process.exit(exitCode);
|
|
80588
80912
|
} catch (err) {
|
|
80589
|
-
|
|
80590
|
-
formatter.formatDependencyError(err);
|
|
80591
|
-
process.exit(1);
|
|
80592
|
-
return;
|
|
80593
|
-
}
|
|
80594
|
-
const message = err instanceof Error ? err.message : "Execution failed";
|
|
80595
|
-
formatter.error(message);
|
|
80596
|
-
process.exit(1);
|
|
80913
|
+
handleCommandError(err);
|
|
80597
80914
|
}
|
|
80598
80915
|
}
|
|
80599
80916
|
);
|
|
@@ -80619,12 +80936,8 @@ function spawnChild(command, args, env) {
|
|
|
80619
80936
|
process.off("SIGTERM", sigtermHandler);
|
|
80620
80937
|
process.off("SIGINT", sigintHandler);
|
|
80621
80938
|
if (signal) {
|
|
80622
|
-
const
|
|
80623
|
-
|
|
80624
|
-
SIGINT: 130,
|
|
80625
|
-
SIGTERM: 143
|
|
80626
|
-
};
|
|
80627
|
-
resolve6(signalCodes[signal] ?? 128);
|
|
80939
|
+
const sigNum = os2.constants?.signals?.[signal];
|
|
80940
|
+
resolve6(sigNum ? 128 + sigNum : 128);
|
|
80628
80941
|
} else {
|
|
80629
80942
|
resolve6(code ?? 1);
|
|
80630
80943
|
}
|
|
@@ -80642,13 +80955,6 @@ function spawnChild(command, args, env) {
|
|
|
80642
80955
|
process.on("SIGINT", sigintHandler);
|
|
80643
80956
|
});
|
|
80644
80957
|
}
|
|
80645
|
-
function parseTarget6(target) {
|
|
80646
|
-
const parts = target.split("/");
|
|
80647
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
80648
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
80649
|
-
}
|
|
80650
|
-
return [parts[0], parts[1]];
|
|
80651
|
-
}
|
|
80652
80958
|
|
|
80653
80959
|
// src/commands/export.ts
|
|
80654
80960
|
init_src();
|
|
@@ -80677,7 +80983,7 @@ Usage: clef export payments/production --format env`
|
|
|
80677
80983
|
process.exit(1);
|
|
80678
80984
|
return;
|
|
80679
80985
|
}
|
|
80680
|
-
const [namespace, environment] =
|
|
80986
|
+
const [namespace, environment] = parseTarget(target);
|
|
80681
80987
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
80682
80988
|
const parser = new ManifestParser();
|
|
80683
80989
|
const manifest = parser.parse(path31.join(repoRoot, "clef.yaml"));
|
|
@@ -80712,29 +81018,15 @@ Usage: clef export payments/production --format env`
|
|
|
80712
81018
|
}
|
|
80713
81019
|
}
|
|
80714
81020
|
} catch (err) {
|
|
80715
|
-
|
|
80716
|
-
formatter.formatDependencyError(err);
|
|
80717
|
-
process.exit(1);
|
|
80718
|
-
return;
|
|
80719
|
-
}
|
|
80720
|
-
const message = err instanceof Error ? err.message : "Export failed";
|
|
80721
|
-
formatter.error(message);
|
|
80722
|
-
process.exit(1);
|
|
81021
|
+
handleCommandError(err);
|
|
80723
81022
|
}
|
|
80724
81023
|
});
|
|
80725
81024
|
}
|
|
80726
|
-
function parseTarget7(target) {
|
|
80727
|
-
const parts = target.split("/");
|
|
80728
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
80729
|
-
throw new Error(`Invalid target "${target}". Expected format: namespace/environment`);
|
|
80730
|
-
}
|
|
80731
|
-
return [parts[0], parts[1]];
|
|
80732
|
-
}
|
|
80733
81025
|
|
|
80734
81026
|
// src/commands/doctor.ts
|
|
80735
|
-
var
|
|
81027
|
+
var YAML13 = __toESM(require_dist());
|
|
80736
81028
|
init_src();
|
|
80737
|
-
import * as
|
|
81029
|
+
import * as fs19 from "fs";
|
|
80738
81030
|
import * as path32 from "path";
|
|
80739
81031
|
function registerDoctorCommand(program3, deps2) {
|
|
80740
81032
|
program3.command("doctor").description(
|
|
@@ -80784,7 +81076,7 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80784
81076
|
});
|
|
80785
81077
|
}
|
|
80786
81078
|
const manifestPath = path32.join(repoRoot, "clef.yaml");
|
|
80787
|
-
const manifestFound =
|
|
81079
|
+
const manifestFound = fs19.existsSync(manifestPath);
|
|
80788
81080
|
checks.push({
|
|
80789
81081
|
name: "manifest",
|
|
80790
81082
|
ok: manifestFound,
|
|
@@ -80794,7 +81086,7 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80794
81086
|
const ageKeyResult = await checkAgeKey(repoRoot, deps2.runner);
|
|
80795
81087
|
checks.push(ageKeyResult);
|
|
80796
81088
|
const sopsYamlPath = path32.join(repoRoot, ".sops.yaml");
|
|
80797
|
-
const sopsYamlFound =
|
|
81089
|
+
const sopsYamlFound = fs19.existsSync(sopsYamlPath);
|
|
80798
81090
|
checks.push({
|
|
80799
81091
|
name: ".sops.yaml",
|
|
80800
81092
|
ok: sopsYamlFound,
|
|
@@ -80802,11 +81094,11 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80802
81094
|
hint: sopsYamlFound ? void 0 : "run: clef init"
|
|
80803
81095
|
});
|
|
80804
81096
|
const clefignorePath = path32.join(repoRoot, ".clefignore");
|
|
80805
|
-
const clefignoreFound =
|
|
81097
|
+
const clefignoreFound = fs19.existsSync(clefignorePath);
|
|
80806
81098
|
let clefignoreRuleCount = 0;
|
|
80807
81099
|
if (clefignoreFound) {
|
|
80808
81100
|
try {
|
|
80809
|
-
const content =
|
|
81101
|
+
const content = fs19.readFileSync(clefignorePath, "utf-8");
|
|
80810
81102
|
clefignoreRuleCount = content.split("\n").filter(
|
|
80811
81103
|
(l) => l.trim() && !l.trim().startsWith("#") && !l.trim().startsWith("ignore-pattern:")
|
|
80812
81104
|
).length;
|
|
@@ -80838,7 +81130,7 @@ function registerDoctorCommand(program3, deps2) {
|
|
|
80838
81130
|
formatter.info("Attempting to fix: generating .sops.yaml from manifest...");
|
|
80839
81131
|
try {
|
|
80840
81132
|
scaffoldSopsConfig(repoRoot);
|
|
80841
|
-
const nowFound =
|
|
81133
|
+
const nowFound = fs19.existsSync(sopsYamlPath);
|
|
80842
81134
|
if (nowFound) {
|
|
80843
81135
|
const sopsYamlCheck = checks.find((c) => c.name === ".sops.yaml");
|
|
80844
81136
|
if (sopsYamlCheck) {
|
|
@@ -80962,7 +81254,7 @@ async function checkAgeKey(repoRoot, runner2) {
|
|
|
80962
81254
|
source: "env"
|
|
80963
81255
|
};
|
|
80964
81256
|
case "config-file":
|
|
80965
|
-
if (!
|
|
81257
|
+
if (!fs19.existsSync(credential.path)) {
|
|
80966
81258
|
return {
|
|
80967
81259
|
name: "age key",
|
|
80968
81260
|
ok: false,
|
|
@@ -80981,9 +81273,9 @@ async function checkAgeKey(repoRoot, runner2) {
|
|
|
80981
81273
|
}
|
|
80982
81274
|
function countAgeRecipients(sopsYamlPath) {
|
|
80983
81275
|
try {
|
|
80984
|
-
if (!
|
|
80985
|
-
const content =
|
|
80986
|
-
const config =
|
|
81276
|
+
if (!fs19.existsSync(sopsYamlPath)) return 0;
|
|
81277
|
+
const content = fs19.readFileSync(sopsYamlPath, "utf-8");
|
|
81278
|
+
const config = YAML13.parse(content);
|
|
80987
81279
|
if (!config?.creation_rules || !Array.isArray(config.creation_rules)) {
|
|
80988
81280
|
return 0;
|
|
80989
81281
|
}
|
|
@@ -81010,7 +81302,7 @@ function getSopsInstallHint() {
|
|
|
81010
81302
|
|
|
81011
81303
|
// src/commands/update.ts
|
|
81012
81304
|
init_src();
|
|
81013
|
-
import * as
|
|
81305
|
+
import * as fs20 from "fs";
|
|
81014
81306
|
import * as path33 from "path";
|
|
81015
81307
|
function registerUpdateCommand(program3, deps2) {
|
|
81016
81308
|
program3.command("update").description(
|
|
@@ -81019,7 +81311,7 @@ function registerUpdateCommand(program3, deps2) {
|
|
|
81019
81311
|
try {
|
|
81020
81312
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
81021
81313
|
const manifestPath = path33.join(repoRoot, "clef.yaml");
|
|
81022
|
-
if (!
|
|
81314
|
+
if (!fs20.existsSync(manifestPath)) {
|
|
81023
81315
|
formatter.error("clef.yaml not found. Run 'clef init' to initialise this repository.");
|
|
81024
81316
|
process.exit(1);
|
|
81025
81317
|
return;
|
|
@@ -81053,19 +81345,12 @@ function registerUpdateCommand(program3, deps2) {
|
|
|
81053
81345
|
formatter.success(`Scaffolded ${scaffoldedCount} encrypted file(s)`);
|
|
81054
81346
|
}
|
|
81055
81347
|
if (failedCount === 0) {
|
|
81056
|
-
process.exit(0);
|
|
81057
81348
|
return;
|
|
81058
81349
|
}
|
|
81059
81350
|
formatter.error(`${failedCount} cell(s) could not be scaffolded.`);
|
|
81060
81351
|
process.exit(1);
|
|
81061
81352
|
} catch (err) {
|
|
81062
|
-
|
|
81063
|
-
formatter.formatDependencyError(err);
|
|
81064
|
-
process.exit(1);
|
|
81065
|
-
return;
|
|
81066
|
-
}
|
|
81067
|
-
formatter.error(err.message);
|
|
81068
|
-
process.exit(1);
|
|
81353
|
+
handleCommandError(err);
|
|
81069
81354
|
}
|
|
81070
81355
|
});
|
|
81071
81356
|
}
|
|
@@ -81191,7 +81476,7 @@ function formatScanOutput(result) {
|
|
|
81191
81476
|
|
|
81192
81477
|
// src/commands/import.ts
|
|
81193
81478
|
init_src();
|
|
81194
|
-
import * as
|
|
81479
|
+
import * as fs21 from "fs";
|
|
81195
81480
|
import * as path35 from "path";
|
|
81196
81481
|
async function readStdin() {
|
|
81197
81482
|
return new Promise((resolve6, reject) => {
|
|
@@ -81252,13 +81537,13 @@ function registerImportCommand(program3, deps2) {
|
|
|
81252
81537
|
if (opts2.stdin) {
|
|
81253
81538
|
content = await readStdin();
|
|
81254
81539
|
} else if (source) {
|
|
81255
|
-
if (!
|
|
81540
|
+
if (!fs21.existsSync(source)) {
|
|
81256
81541
|
formatter.error(`Source file not found: ${source}`);
|
|
81257
81542
|
process.exit(2);
|
|
81258
81543
|
return;
|
|
81259
81544
|
}
|
|
81260
81545
|
try {
|
|
81261
|
-
content =
|
|
81546
|
+
content = fs21.readFileSync(source, "utf-8");
|
|
81262
81547
|
sourcePath = source;
|
|
81263
81548
|
} catch (err) {
|
|
81264
81549
|
formatter.error(`Could not read source file: ${err.message}`);
|
|
@@ -81346,13 +81631,7 @@ ${result.imported.length} imported, ${result.skipped.length} skipped, ${result.f
|
|
|
81346
81631
|
}
|
|
81347
81632
|
}
|
|
81348
81633
|
} catch (err) {
|
|
81349
|
-
|
|
81350
|
-
formatter.formatDependencyError(err);
|
|
81351
|
-
process.exit(1);
|
|
81352
|
-
return;
|
|
81353
|
-
}
|
|
81354
|
-
formatter.error(err.message);
|
|
81355
|
-
process.exit(1);
|
|
81634
|
+
handleCommandError(err);
|
|
81356
81635
|
}
|
|
81357
81636
|
}
|
|
81358
81637
|
);
|
|
@@ -81411,13 +81690,7 @@ function registerRecipientsCommand(program3, deps2) {
|
|
|
81411
81690
|
formatter.recipientItem(r.label || r.preview, r.label ? r.preview : "");
|
|
81412
81691
|
}
|
|
81413
81692
|
} catch (err) {
|
|
81414
|
-
|
|
81415
|
-
formatter.formatDependencyError(err);
|
|
81416
|
-
process.exit(1);
|
|
81417
|
-
return;
|
|
81418
|
-
}
|
|
81419
|
-
formatter.error(err.message);
|
|
81420
|
-
process.exit(1);
|
|
81693
|
+
handleCommandError(err);
|
|
81421
81694
|
}
|
|
81422
81695
|
});
|
|
81423
81696
|
recipientsCmd.command("add <key>").description(
|
|
@@ -81447,13 +81720,7 @@ function registerRecipientsCommand(program3, deps2) {
|
|
|
81447
81720
|
);
|
|
81448
81721
|
}
|
|
81449
81722
|
} catch (err) {
|
|
81450
|
-
|
|
81451
|
-
formatter.formatDependencyError(err);
|
|
81452
|
-
process.exit(1);
|
|
81453
|
-
return;
|
|
81454
|
-
}
|
|
81455
|
-
formatter.error(err.message);
|
|
81456
|
-
process.exit(1);
|
|
81723
|
+
handleCommandError(err);
|
|
81457
81724
|
}
|
|
81458
81725
|
});
|
|
81459
81726
|
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, opts2) => {
|
|
@@ -81561,13 +81828,7 @@ ${sym("failure")} Re-encryption failed on ${path36.basename(failedFile)}`
|
|
|
81561
81828
|
`git add clef.yaml && git add -A && git commit -m "remove recipient: ${label2}${envSuffix}"`
|
|
81562
81829
|
);
|
|
81563
81830
|
} catch (err) {
|
|
81564
|
-
|
|
81565
|
-
formatter.formatDependencyError(err);
|
|
81566
|
-
process.exit(1);
|
|
81567
|
-
return;
|
|
81568
|
-
}
|
|
81569
|
-
formatter.error(err.message);
|
|
81570
|
-
process.exit(1);
|
|
81831
|
+
handleCommandError(err);
|
|
81571
81832
|
}
|
|
81572
81833
|
});
|
|
81573
81834
|
recipientsCmd.command("request").description(
|
|
@@ -81685,13 +81946,7 @@ ${sym("failure")} Re-encryption failed on ${path36.basename(failedFile)}`
|
|
|
81685
81946
|
);
|
|
81686
81947
|
}
|
|
81687
81948
|
} catch (err) {
|
|
81688
|
-
|
|
81689
|
-
formatter.formatDependencyError(err);
|
|
81690
|
-
process.exit(1);
|
|
81691
|
-
return;
|
|
81692
|
-
}
|
|
81693
|
-
formatter.error(err.message);
|
|
81694
|
-
process.exit(1);
|
|
81949
|
+
handleCommandError(err);
|
|
81695
81950
|
}
|
|
81696
81951
|
});
|
|
81697
81952
|
}
|
|
@@ -81762,13 +82017,13 @@ ${sym("failure")} Re-encryption failed on ${path36.basename(failedFile)}`);
|
|
|
81762
82017
|
|
|
81763
82018
|
// src/commands/merge-driver.ts
|
|
81764
82019
|
init_src();
|
|
81765
|
-
import * as
|
|
82020
|
+
import * as fs22 from "fs";
|
|
81766
82021
|
import * as path37 from "path";
|
|
81767
82022
|
async function findRepoRoot(filePath, runner2) {
|
|
81768
82023
|
try {
|
|
81769
82024
|
let dir = path37.dirname(path37.resolve(filePath));
|
|
81770
82025
|
for (let i = 0; i < 50; i++) {
|
|
81771
|
-
if (
|
|
82026
|
+
if (fs22.existsSync(path37.join(dir, "clef.yaml"))) return dir;
|
|
81772
82027
|
const parent = path37.dirname(dir);
|
|
81773
82028
|
if (parent === dir) break;
|
|
81774
82029
|
dir = parent;
|
|
@@ -81801,7 +82056,7 @@ function registerMergeDriverCommand(program3, deps2) {
|
|
|
81801
82056
|
const manifestPath = path37.join(repoRoot, "clef.yaml");
|
|
81802
82057
|
let manifest;
|
|
81803
82058
|
let environment;
|
|
81804
|
-
if (
|
|
82059
|
+
if (fs22.existsSync(manifestPath)) {
|
|
81805
82060
|
const parser = new ManifestParser();
|
|
81806
82061
|
manifest = parser.parse(manifestPath);
|
|
81807
82062
|
for (const ns of manifest.namespaces) {
|
|
@@ -81895,40 +82150,7 @@ function registerServiceCommand(program3, deps2) {
|
|
|
81895
82150
|
const parser = new ManifestParser();
|
|
81896
82151
|
const manifest = parser.parse(path38.join(repoRoot, "clef.yaml"));
|
|
81897
82152
|
const namespaces = opts2.namespaces.split(",").map((s) => s.trim());
|
|
81898
|
-
|
|
81899
|
-
if (opts2.kmsEnv.length > 0) {
|
|
81900
|
-
kmsEnvConfigs = {};
|
|
81901
|
-
for (const mapping of opts2.kmsEnv) {
|
|
81902
|
-
const eqIdx = mapping.indexOf("=");
|
|
81903
|
-
if (eqIdx === -1) {
|
|
81904
|
-
throw new Error(
|
|
81905
|
-
`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`
|
|
81906
|
-
);
|
|
81907
|
-
}
|
|
81908
|
-
const envName = mapping.slice(0, eqIdx);
|
|
81909
|
-
const rest = mapping.slice(eqIdx + 1);
|
|
81910
|
-
const colonIdx = rest.indexOf(":");
|
|
81911
|
-
if (colonIdx === -1) {
|
|
81912
|
-
throw new Error(
|
|
81913
|
-
`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`
|
|
81914
|
-
);
|
|
81915
|
-
}
|
|
81916
|
-
const provider = rest.slice(0, colonIdx);
|
|
81917
|
-
const keyId = rest.slice(colonIdx + 1);
|
|
81918
|
-
if (!["aws", "gcp", "azure"].includes(provider)) {
|
|
81919
|
-
throw new Error(
|
|
81920
|
-
`Invalid KMS provider '${provider}'. Must be one of: aws, gcp, azure.`
|
|
81921
|
-
);
|
|
81922
|
-
}
|
|
81923
|
-
if (kmsEnvConfigs[envName]) {
|
|
81924
|
-
throw new Error(`Duplicate --kms-env for environment '${envName}'.`);
|
|
81925
|
-
}
|
|
81926
|
-
kmsEnvConfigs[envName] = {
|
|
81927
|
-
provider,
|
|
81928
|
-
keyId
|
|
81929
|
-
};
|
|
81930
|
-
}
|
|
81931
|
-
}
|
|
82153
|
+
const kmsEnvConfigs = opts2.kmsEnv.length > 0 ? parseKmsEnvMappings(opts2.kmsEnv) : void 0;
|
|
81932
82154
|
const hasAgeEnvs = !kmsEnvConfigs || manifest.environments.some((e) => !kmsEnvConfigs[e.name]);
|
|
81933
82155
|
const protectedEnvs = manifest.environments.filter((e) => e.protected).map((e) => e.name);
|
|
81934
82156
|
if (protectedEnvs.length > 0 && hasAgeEnvs) {
|
|
@@ -81993,13 +82215,7 @@ function registerServiceCommand(program3, deps2) {
|
|
|
81993
82215
|
`git add clef.yaml && git commit -m "feat: add service identity '${name}'"`
|
|
81994
82216
|
);
|
|
81995
82217
|
} catch (err) {
|
|
81996
|
-
|
|
81997
|
-
formatter.formatDependencyError(err);
|
|
81998
|
-
process.exit(1);
|
|
81999
|
-
return;
|
|
82000
|
-
}
|
|
82001
|
-
formatter.error(err.message);
|
|
82002
|
-
process.exit(1);
|
|
82218
|
+
handleCommandError(err);
|
|
82003
82219
|
}
|
|
82004
82220
|
}
|
|
82005
82221
|
);
|
|
@@ -82024,13 +82240,7 @@ function registerServiceCommand(program3, deps2) {
|
|
|
82024
82240
|
});
|
|
82025
82241
|
formatter.table(rows, ["Name", "Namespaces", "Environments"]);
|
|
82026
82242
|
} catch (err) {
|
|
82027
|
-
|
|
82028
|
-
formatter.formatDependencyError(err);
|
|
82029
|
-
process.exit(1);
|
|
82030
|
-
return;
|
|
82031
|
-
}
|
|
82032
|
-
formatter.error(err.message);
|
|
82033
|
-
process.exit(1);
|
|
82243
|
+
handleCommandError(err);
|
|
82034
82244
|
}
|
|
82035
82245
|
});
|
|
82036
82246
|
serviceCmd.command("show <name>").description("Show details of a service identity.").action(async (name) => {
|
|
@@ -82063,13 +82273,7 @@ Service Identity: ${identity.name}`);
|
|
|
82063
82273
|
}
|
|
82064
82274
|
formatter.print("");
|
|
82065
82275
|
} catch (err) {
|
|
82066
|
-
|
|
82067
|
-
formatter.formatDependencyError(err);
|
|
82068
|
-
process.exit(1);
|
|
82069
|
-
return;
|
|
82070
|
-
}
|
|
82071
|
-
formatter.error(err.message);
|
|
82072
|
-
process.exit(1);
|
|
82276
|
+
handleCommandError(err);
|
|
82073
82277
|
}
|
|
82074
82278
|
});
|
|
82075
82279
|
serviceCmd.command("validate").description("Validate service identity configurations and report drift issues.").action(async () => {
|
|
@@ -82104,13 +82308,7 @@ Service Identity: ${identity.name}`);
|
|
|
82104
82308
|
formatter.warn(`${warnCount} warning(s)`);
|
|
82105
82309
|
}
|
|
82106
82310
|
} catch (err) {
|
|
82107
|
-
|
|
82108
|
-
formatter.formatDependencyError(err);
|
|
82109
|
-
process.exit(1);
|
|
82110
|
-
return;
|
|
82111
|
-
}
|
|
82112
|
-
formatter.error(err.message);
|
|
82113
|
-
process.exit(1);
|
|
82311
|
+
handleCommandError(err);
|
|
82114
82312
|
}
|
|
82115
82313
|
});
|
|
82116
82314
|
serviceCmd.command("update <name>").description("Update an existing service identity's environment backends.").option(
|
|
@@ -82131,31 +82329,7 @@ Service Identity: ${identity.name}`);
|
|
|
82131
82329
|
const repoRoot = program3.opts().dir || process.cwd();
|
|
82132
82330
|
const parser = new ManifestParser();
|
|
82133
82331
|
const manifest = parser.parse(path38.join(repoRoot, "clef.yaml"));
|
|
82134
|
-
const kmsEnvConfigs =
|
|
82135
|
-
for (const mapping of opts2.kmsEnv) {
|
|
82136
|
-
const eqIdx = mapping.indexOf("=");
|
|
82137
|
-
if (eqIdx === -1) {
|
|
82138
|
-
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
82139
|
-
}
|
|
82140
|
-
const envName = mapping.slice(0, eqIdx);
|
|
82141
|
-
const rest = mapping.slice(eqIdx + 1);
|
|
82142
|
-
const colonIdx = rest.indexOf(":");
|
|
82143
|
-
if (colonIdx === -1) {
|
|
82144
|
-
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
82145
|
-
}
|
|
82146
|
-
const provider = rest.slice(0, colonIdx);
|
|
82147
|
-
const keyId = rest.slice(colonIdx + 1);
|
|
82148
|
-
if (!["aws", "gcp", "azure"].includes(provider)) {
|
|
82149
|
-
throw new Error(`Invalid KMS provider '${provider}'. Must be one of: aws, gcp, azure.`);
|
|
82150
|
-
}
|
|
82151
|
-
if (kmsEnvConfigs[envName]) {
|
|
82152
|
-
throw new Error(`Duplicate --kms-env for environment '${envName}'.`);
|
|
82153
|
-
}
|
|
82154
|
-
kmsEnvConfigs[envName] = {
|
|
82155
|
-
provider,
|
|
82156
|
-
keyId
|
|
82157
|
-
};
|
|
82158
|
-
}
|
|
82332
|
+
const kmsEnvConfigs = parseKmsEnvMappings(opts2.kmsEnv);
|
|
82159
82333
|
const matrixManager = new MatrixManager();
|
|
82160
82334
|
const sopsClient = await createSopsClient(repoRoot, deps2.runner);
|
|
82161
82335
|
const manager = new ServiceIdentityManager(sopsClient, matrixManager);
|
|
@@ -82169,13 +82343,7 @@ Service Identity: ${identity.name}`);
|
|
|
82169
82343
|
`git add clef.yaml && git commit -m "chore: update service identity '${name}'"`
|
|
82170
82344
|
);
|
|
82171
82345
|
} catch (err) {
|
|
82172
|
-
|
|
82173
|
-
formatter.formatDependencyError(err);
|
|
82174
|
-
process.exit(1);
|
|
82175
|
-
return;
|
|
82176
|
-
}
|
|
82177
|
-
formatter.error(err.message);
|
|
82178
|
-
process.exit(1);
|
|
82346
|
+
handleCommandError(err);
|
|
82179
82347
|
}
|
|
82180
82348
|
});
|
|
82181
82349
|
serviceCmd.command("delete <name>").description("Delete a service identity and remove its recipients from scoped files.").action(async (name) => {
|
|
@@ -82207,13 +82375,7 @@ Service Identity: ${identity.name}`);
|
|
|
82207
82375
|
`git add clef.yaml && git commit -m "chore: delete service identity '${name}'"`
|
|
82208
82376
|
);
|
|
82209
82377
|
} catch (err) {
|
|
82210
|
-
|
|
82211
|
-
formatter.formatDependencyError(err);
|
|
82212
|
-
process.exit(1);
|
|
82213
|
-
return;
|
|
82214
|
-
}
|
|
82215
|
-
formatter.error(err.message);
|
|
82216
|
-
process.exit(1);
|
|
82378
|
+
handleCommandError(err);
|
|
82217
82379
|
}
|
|
82218
82380
|
});
|
|
82219
82381
|
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, opts2) => {
|
|
@@ -82267,11 +82429,6 @@ Service Identity: ${identity.name}`);
|
|
|
82267
82429
|
`git add clef.yaml && git commit -m "chore: rotate service identity '${name}'"`
|
|
82268
82430
|
);
|
|
82269
82431
|
} catch (err) {
|
|
82270
|
-
if (err instanceof SopsMissingError || err instanceof SopsVersionError) {
|
|
82271
|
-
formatter.formatDependencyError(err);
|
|
82272
|
-
process.exit(1);
|
|
82273
|
-
return;
|
|
82274
|
-
}
|
|
82275
82432
|
if (err instanceof PartialRotationError) {
|
|
82276
82433
|
formatter.error(err.message);
|
|
82277
82434
|
const partialEntries = Object.entries(err.rotatedKeys);
|
|
@@ -82304,11 +82461,37 @@ Service Identity: ${identity.name}`);
|
|
|
82304
82461
|
process.exit(1);
|
|
82305
82462
|
return;
|
|
82306
82463
|
}
|
|
82307
|
-
|
|
82308
|
-
process.exit(1);
|
|
82464
|
+
handleCommandError(err);
|
|
82309
82465
|
}
|
|
82310
82466
|
});
|
|
82311
82467
|
}
|
|
82468
|
+
function parseKmsEnvMappings(mappings) {
|
|
82469
|
+
const configs = {};
|
|
82470
|
+
for (const mapping of mappings) {
|
|
82471
|
+
const eqIdx = mapping.indexOf("=");
|
|
82472
|
+
if (eqIdx === -1) {
|
|
82473
|
+
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
82474
|
+
}
|
|
82475
|
+
const envName = mapping.slice(0, eqIdx);
|
|
82476
|
+
const rest = mapping.slice(eqIdx + 1);
|
|
82477
|
+
const colonIdx = rest.indexOf(":");
|
|
82478
|
+
if (colonIdx === -1) {
|
|
82479
|
+
throw new Error(`Invalid --kms-env format: '${mapping}'. Expected: env=provider:keyId`);
|
|
82480
|
+
}
|
|
82481
|
+
const provider = rest.slice(0, colonIdx);
|
|
82482
|
+
const keyId = rest.slice(colonIdx + 1);
|
|
82483
|
+
if (!VALID_KMS_PROVIDERS.includes(provider)) {
|
|
82484
|
+
throw new Error(
|
|
82485
|
+
`Invalid KMS provider '${provider}'. Must be one of: ${VALID_KMS_PROVIDERS.join(", ")}.`
|
|
82486
|
+
);
|
|
82487
|
+
}
|
|
82488
|
+
if (configs[envName]) {
|
|
82489
|
+
throw new Error(`Duplicate --kms-env for environment '${envName}'.`);
|
|
82490
|
+
}
|
|
82491
|
+
configs[envName] = { provider, keyId };
|
|
82492
|
+
}
|
|
82493
|
+
return configs;
|
|
82494
|
+
}
|
|
82312
82495
|
|
|
82313
82496
|
// src/commands/pack.ts
|
|
82314
82497
|
init_src();
|
|
@@ -82382,14 +82565,7 @@ function registerPackCommand(program3, deps2) {
|
|
|
82382
82565
|
"\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"
|
|
82383
82566
|
);
|
|
82384
82567
|
} catch (err) {
|
|
82385
|
-
|
|
82386
|
-
formatter.formatDependencyError(err);
|
|
82387
|
-
process.exit(1);
|
|
82388
|
-
return;
|
|
82389
|
-
}
|
|
82390
|
-
const message = err instanceof Error ? err.message : "Pack failed";
|
|
82391
|
-
formatter.error(message);
|
|
82392
|
-
process.exit(1);
|
|
82568
|
+
handleCommandError(err);
|
|
82393
82569
|
}
|
|
82394
82570
|
}
|
|
82395
82571
|
);
|
|
@@ -82397,7 +82573,7 @@ function registerPackCommand(program3, deps2) {
|
|
|
82397
82573
|
|
|
82398
82574
|
// src/commands/revoke.ts
|
|
82399
82575
|
init_src();
|
|
82400
|
-
import * as
|
|
82576
|
+
import * as fs23 from "fs";
|
|
82401
82577
|
import * as path40 from "path";
|
|
82402
82578
|
function registerRevokeCommand(program3, _deps) {
|
|
82403
82579
|
program3.command("revoke <identity> <environment>").description(
|
|
@@ -82430,8 +82606,8 @@ function registerRevokeCommand(program3, _deps) {
|
|
|
82430
82606
|
environment,
|
|
82431
82607
|
revokedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
82432
82608
|
};
|
|
82433
|
-
|
|
82434
|
-
|
|
82609
|
+
fs23.mkdirSync(artifactDir, { recursive: true });
|
|
82610
|
+
fs23.writeFileSync(artifactPath, JSON.stringify(revoked, null, 2) + "\n", "utf-8");
|
|
82435
82611
|
const relPath = path40.relative(repoRoot, artifactPath);
|
|
82436
82612
|
formatter.success(`Artifact revoked: ${relPath}`);
|
|
82437
82613
|
formatter.print("");
|
|
@@ -82534,11 +82710,11 @@ init_src();
|
|
|
82534
82710
|
|
|
82535
82711
|
// src/report/historical.ts
|
|
82536
82712
|
init_src();
|
|
82537
|
-
import * as
|
|
82713
|
+
import * as os3 from "os";
|
|
82538
82714
|
import * as path42 from "path";
|
|
82539
|
-
import * as
|
|
82715
|
+
import * as fs24 from "fs";
|
|
82540
82716
|
async function generateReportAtCommit(repoRoot, commitSha, clefVersion, runner2) {
|
|
82541
|
-
const tmpDir = path42.join(
|
|
82717
|
+
const tmpDir = path42.join(os3.tmpdir(), `clef-report-${commitSha.slice(0, 8)}-${Date.now()}`);
|
|
82542
82718
|
try {
|
|
82543
82719
|
const addResult = await runner2.run("git", ["worktree", "add", tmpDir, commitSha, "--detach"], {
|
|
82544
82720
|
cwd: repoRoot
|
|
@@ -82556,7 +82732,7 @@ async function generateReportAtCommit(repoRoot, commitSha, clefVersion, runner2)
|
|
|
82556
82732
|
await runner2.run("git", ["worktree", "remove", tmpDir, "--force"], { cwd: repoRoot });
|
|
82557
82733
|
} catch {
|
|
82558
82734
|
try {
|
|
82559
|
-
|
|
82735
|
+
fs24.rmSync(tmpDir, { recursive: true, force: true });
|
|
82560
82736
|
await runner2.run("git", ["worktree", "prune"], { cwd: repoRoot });
|
|
82561
82737
|
} catch {
|
|
82562
82738
|
}
|
|
@@ -82646,13 +82822,7 @@ function registerReportCommand(program3, deps2) {
|
|
|
82646
82822
|
}
|
|
82647
82823
|
outputReport(headReport, options);
|
|
82648
82824
|
} catch (err) {
|
|
82649
|
-
|
|
82650
|
-
formatter.formatDependencyError(err);
|
|
82651
|
-
process.exit(1);
|
|
82652
|
-
return;
|
|
82653
|
-
}
|
|
82654
|
-
formatter.error(err.message);
|
|
82655
|
-
process.exit(1);
|
|
82825
|
+
handleCommandError(err);
|
|
82656
82826
|
}
|
|
82657
82827
|
}
|
|
82658
82828
|
);
|
|
@@ -82784,7 +82954,7 @@ function formatReportOutput(report) {
|
|
|
82784
82954
|
|
|
82785
82955
|
// src/commands/install.ts
|
|
82786
82956
|
var import_yaml = __toESM(require_dist());
|
|
82787
|
-
import * as
|
|
82957
|
+
import * as fs25 from "fs";
|
|
82788
82958
|
import * as path43 from "path";
|
|
82789
82959
|
|
|
82790
82960
|
// src/registry/client.ts
|
|
@@ -82833,7 +83003,7 @@ function registerInstallCommand(program3, _deps) {
|
|
|
82833
83003
|
return;
|
|
82834
83004
|
}
|
|
82835
83005
|
const brokerDir = path43.join(repoRoot, "brokers", entry.name);
|
|
82836
|
-
if (
|
|
83006
|
+
if (fs25.existsSync(brokerDir) && !options.force) {
|
|
82837
83007
|
const overwrite = await formatter.confirm(
|
|
82838
83008
|
`brokers/${entry.name}/ already exists. Overwrite?`
|
|
82839
83009
|
);
|
|
@@ -82864,11 +83034,11 @@ function registerInstallCommand(program3, _deps) {
|
|
|
82864
83034
|
process.exit(1);
|
|
82865
83035
|
return;
|
|
82866
83036
|
}
|
|
82867
|
-
if (!
|
|
82868
|
-
|
|
83037
|
+
if (!fs25.existsSync(brokerDir)) {
|
|
83038
|
+
fs25.mkdirSync(brokerDir, { recursive: true });
|
|
82869
83039
|
}
|
|
82870
83040
|
for (const file of files) {
|
|
82871
|
-
|
|
83041
|
+
fs25.writeFileSync(path43.join(brokerDir, file.name), file.content, "utf-8");
|
|
82872
83042
|
}
|
|
82873
83043
|
const manifestFile = files.find((f) => f.name === "broker.yaml");
|
|
82874
83044
|
const manifest = manifestFile ? (0, import_yaml.parse)(manifestFile.content) : {};
|