@clef-sh/agent 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/agent.cjs +419 -187
- package/dist/agent.cjs.map +4 -4
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/health.d.ts +3 -2
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +39 -16
- package/dist/health.js.map +1 -1
- package/dist/lifecycle/daemon.d.ts +2 -0
- package/dist/lifecycle/daemon.d.ts.map +1 -1
- package/dist/lifecycle/daemon.js +12 -4
- package/dist/lifecycle/daemon.js.map +1 -1
- package/dist/lifecycle/lambda-extension.d.ts.map +1 -1
- package/dist/lifecycle/lambda-extension.js +23 -6
- package/dist/lifecycle/lambda-extension.js.map +1 -1
- package/dist/main.js +21 -2
- package/dist/main.js.map +1 -1
- package/dist/server.d.ts +5 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +49 -28
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/agent.cjs
CHANGED
|
@@ -44607,22 +44607,22 @@ var require_crypto2 = __commonJS({
|
|
|
44607
44607
|
"use strict";
|
|
44608
44608
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
44609
44609
|
exports2.NodeCrypto = void 0;
|
|
44610
|
-
var
|
|
44610
|
+
var crypto17 = require("crypto");
|
|
44611
44611
|
var NodeCrypto = class {
|
|
44612
44612
|
async sha256DigestBase64(str) {
|
|
44613
|
-
return
|
|
44613
|
+
return crypto17.createHash("sha256").update(str).digest("base64");
|
|
44614
44614
|
}
|
|
44615
44615
|
randomBytesBase64(count) {
|
|
44616
|
-
return
|
|
44616
|
+
return crypto17.randomBytes(count).toString("base64");
|
|
44617
44617
|
}
|
|
44618
44618
|
async verify(pubkey, data, signature) {
|
|
44619
|
-
const verifier =
|
|
44619
|
+
const verifier = crypto17.createVerify("RSA-SHA256");
|
|
44620
44620
|
verifier.update(data);
|
|
44621
44621
|
verifier.end();
|
|
44622
44622
|
return verifier.verify(pubkey, signature, "base64");
|
|
44623
44623
|
}
|
|
44624
44624
|
async sign(privateKey, data) {
|
|
44625
|
-
const signer =
|
|
44625
|
+
const signer = crypto17.createSign("RSA-SHA256");
|
|
44626
44626
|
signer.update(data);
|
|
44627
44627
|
signer.end();
|
|
44628
44628
|
return signer.sign(privateKey, "base64");
|
|
@@ -44640,7 +44640,7 @@ var require_crypto2 = __commonJS({
|
|
|
44640
44640
|
* string in hexadecimal encoding.
|
|
44641
44641
|
*/
|
|
44642
44642
|
async sha256DigestHex(str) {
|
|
44643
|
-
return
|
|
44643
|
+
return crypto17.createHash("sha256").update(str).digest("hex");
|
|
44644
44644
|
}
|
|
44645
44645
|
/**
|
|
44646
44646
|
* Computes the HMAC hash of a message using the provided crypto key and the
|
|
@@ -44652,7 +44652,7 @@ var require_crypto2 = __commonJS({
|
|
|
44652
44652
|
*/
|
|
44653
44653
|
async signWithHmacSha256(key, msg) {
|
|
44654
44654
|
const cryptoKey = typeof key === "string" ? key : toBuffer(key);
|
|
44655
|
-
return toArrayBuffer(
|
|
44655
|
+
return toArrayBuffer(crypto17.createHmac("sha256", cryptoKey).update(msg).digest());
|
|
44656
44656
|
}
|
|
44657
44657
|
};
|
|
44658
44658
|
exports2.NodeCrypto = NodeCrypto;
|
|
@@ -45430,10 +45430,10 @@ var require_oauth2client = __commonJS({
|
|
|
45430
45430
|
* https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/oauth2-codeVerifier.js
|
|
45431
45431
|
*/
|
|
45432
45432
|
async generateCodeVerifierAsync() {
|
|
45433
|
-
const
|
|
45434
|
-
const randomString =
|
|
45433
|
+
const crypto17 = (0, crypto_1.createCrypto)();
|
|
45434
|
+
const randomString = crypto17.randomBytesBase64(96);
|
|
45435
45435
|
const codeVerifier = randomString.replace(/\+/g, "~").replace(/=/g, "_").replace(/\//g, "-");
|
|
45436
|
-
const unencodedCodeChallenge = await
|
|
45436
|
+
const unencodedCodeChallenge = await crypto17.sha256DigestBase64(codeVerifier);
|
|
45437
45437
|
const codeChallenge = unencodedCodeChallenge.split("=")[0].replace(/\+/g, "-").replace(/\//g, "_");
|
|
45438
45438
|
return { codeVerifier, codeChallenge };
|
|
45439
45439
|
}
|
|
@@ -45877,7 +45877,7 @@ var require_oauth2client = __commonJS({
|
|
|
45877
45877
|
* @return Returns a promise resolving to LoginTicket on verification.
|
|
45878
45878
|
*/
|
|
45879
45879
|
async verifySignedJwtWithCertsAsync(jwt2, certs, requiredAudience, issuers, maxExpiry) {
|
|
45880
|
-
const
|
|
45880
|
+
const crypto17 = (0, crypto_1.createCrypto)();
|
|
45881
45881
|
if (!maxExpiry) {
|
|
45882
45882
|
maxExpiry = _OAuth2Client.DEFAULT_MAX_TOKEN_LIFETIME_SECS_;
|
|
45883
45883
|
}
|
|
@@ -45890,7 +45890,7 @@ var require_oauth2client = __commonJS({
|
|
|
45890
45890
|
let envelope;
|
|
45891
45891
|
let payload;
|
|
45892
45892
|
try {
|
|
45893
|
-
envelope = JSON.parse(
|
|
45893
|
+
envelope = JSON.parse(crypto17.decodeBase64StringUtf8(segments[0]));
|
|
45894
45894
|
} catch (err) {
|
|
45895
45895
|
if (err instanceof Error) {
|
|
45896
45896
|
err.message = `Can't parse token envelope: ${segments[0]}': ${err.message}`;
|
|
@@ -45901,7 +45901,7 @@ var require_oauth2client = __commonJS({
|
|
|
45901
45901
|
throw new Error("Can't parse token envelope: " + segments[0]);
|
|
45902
45902
|
}
|
|
45903
45903
|
try {
|
|
45904
|
-
payload = JSON.parse(
|
|
45904
|
+
payload = JSON.parse(crypto17.decodeBase64StringUtf8(segments[1]));
|
|
45905
45905
|
} catch (err) {
|
|
45906
45906
|
if (err instanceof Error) {
|
|
45907
45907
|
err.message = `Can't parse token payload '${segments[0]}`;
|
|
@@ -45918,7 +45918,7 @@ var require_oauth2client = __commonJS({
|
|
|
45918
45918
|
if (envelope.alg === "ES256") {
|
|
45919
45919
|
signature = formatEcdsa.joseToDer(signature, "ES256").toString("base64");
|
|
45920
45920
|
}
|
|
45921
|
-
const verified = await
|
|
45921
|
+
const verified = await crypto17.verify(cert, signed, signature);
|
|
45922
45922
|
if (!verified) {
|
|
45923
45923
|
throw new Error("Invalid token signature: " + jwt2);
|
|
45924
45924
|
}
|
|
@@ -46286,14 +46286,14 @@ var require_buffer_equal_constant_time = __commonJS({
|
|
|
46286
46286
|
var require_jwa = __commonJS({
|
|
46287
46287
|
"../../node_modules/jwa/index.js"(exports2, module2) {
|
|
46288
46288
|
var Buffer3 = require_safe_buffer().Buffer;
|
|
46289
|
-
var
|
|
46289
|
+
var crypto17 = require("crypto");
|
|
46290
46290
|
var formatEcdsa = require_ecdsa_sig_formatter();
|
|
46291
46291
|
var util2 = require("util");
|
|
46292
46292
|
var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".';
|
|
46293
46293
|
var MSG_INVALID_SECRET = "secret must be a string or buffer";
|
|
46294
46294
|
var MSG_INVALID_VERIFIER_KEY = "key must be a string or a buffer";
|
|
46295
46295
|
var MSG_INVALID_SIGNER_KEY = "key must be a string, a buffer or an object";
|
|
46296
|
-
var supportsKeyObjects = typeof
|
|
46296
|
+
var supportsKeyObjects = typeof crypto17.createPublicKey === "function";
|
|
46297
46297
|
if (supportsKeyObjects) {
|
|
46298
46298
|
MSG_INVALID_VERIFIER_KEY += " or a KeyObject";
|
|
46299
46299
|
MSG_INVALID_SECRET += "or a KeyObject";
|
|
@@ -46383,17 +46383,17 @@ var require_jwa = __commonJS({
|
|
|
46383
46383
|
return function sign2(thing, secret) {
|
|
46384
46384
|
checkIsSecretKey(secret);
|
|
46385
46385
|
thing = normalizeInput(thing);
|
|
46386
|
-
var hmac =
|
|
46386
|
+
var hmac = crypto17.createHmac("sha" + bits, secret);
|
|
46387
46387
|
var sig = (hmac.update(thing), hmac.digest("base64"));
|
|
46388
46388
|
return fromBase64(sig);
|
|
46389
46389
|
};
|
|
46390
46390
|
}
|
|
46391
46391
|
var bufferEqual;
|
|
46392
|
-
var timingSafeEqual2 = "timingSafeEqual" in
|
|
46392
|
+
var timingSafeEqual2 = "timingSafeEqual" in crypto17 ? function timingSafeEqual3(a, b) {
|
|
46393
46393
|
if (a.byteLength !== b.byteLength) {
|
|
46394
46394
|
return false;
|
|
46395
46395
|
}
|
|
46396
|
-
return
|
|
46396
|
+
return crypto17.timingSafeEqual(a, b);
|
|
46397
46397
|
} : function timingSafeEqual3(a, b) {
|
|
46398
46398
|
if (!bufferEqual) {
|
|
46399
46399
|
bufferEqual = require_buffer_equal_constant_time();
|
|
@@ -46410,7 +46410,7 @@ var require_jwa = __commonJS({
|
|
|
46410
46410
|
return function sign2(thing, privateKey) {
|
|
46411
46411
|
checkIsPrivateKey(privateKey);
|
|
46412
46412
|
thing = normalizeInput(thing);
|
|
46413
|
-
var signer =
|
|
46413
|
+
var signer = crypto17.createSign("RSA-SHA" + bits);
|
|
46414
46414
|
var sig = (signer.update(thing), signer.sign(privateKey, "base64"));
|
|
46415
46415
|
return fromBase64(sig);
|
|
46416
46416
|
};
|
|
@@ -46420,7 +46420,7 @@ var require_jwa = __commonJS({
|
|
|
46420
46420
|
checkIsPublicKey(publicKey);
|
|
46421
46421
|
thing = normalizeInput(thing);
|
|
46422
46422
|
signature = toBase64(signature);
|
|
46423
|
-
var verifier =
|
|
46423
|
+
var verifier = crypto17.createVerify("RSA-SHA" + bits);
|
|
46424
46424
|
verifier.update(thing);
|
|
46425
46425
|
return verifier.verify(publicKey, signature, "base64");
|
|
46426
46426
|
};
|
|
@@ -46429,11 +46429,11 @@ var require_jwa = __commonJS({
|
|
|
46429
46429
|
return function sign2(thing, privateKey) {
|
|
46430
46430
|
checkIsPrivateKey(privateKey);
|
|
46431
46431
|
thing = normalizeInput(thing);
|
|
46432
|
-
var signer =
|
|
46432
|
+
var signer = crypto17.createSign("RSA-SHA" + bits);
|
|
46433
46433
|
var sig = (signer.update(thing), signer.sign({
|
|
46434
46434
|
key: privateKey,
|
|
46435
|
-
padding:
|
|
46436
|
-
saltLength:
|
|
46435
|
+
padding: crypto17.constants.RSA_PKCS1_PSS_PADDING,
|
|
46436
|
+
saltLength: crypto17.constants.RSA_PSS_SALTLEN_DIGEST
|
|
46437
46437
|
}, "base64"));
|
|
46438
46438
|
return fromBase64(sig);
|
|
46439
46439
|
};
|
|
@@ -46443,12 +46443,12 @@ var require_jwa = __commonJS({
|
|
|
46443
46443
|
checkIsPublicKey(publicKey);
|
|
46444
46444
|
thing = normalizeInput(thing);
|
|
46445
46445
|
signature = toBase64(signature);
|
|
46446
|
-
var verifier =
|
|
46446
|
+
var verifier = crypto17.createVerify("RSA-SHA" + bits);
|
|
46447
46447
|
verifier.update(thing);
|
|
46448
46448
|
return verifier.verify({
|
|
46449
46449
|
key: publicKey,
|
|
46450
|
-
padding:
|
|
46451
|
-
saltLength:
|
|
46450
|
+
padding: crypto17.constants.RSA_PKCS1_PSS_PADDING,
|
|
46451
|
+
saltLength: crypto17.constants.RSA_PSS_SALTLEN_DIGEST
|
|
46452
46452
|
}, signature, "base64");
|
|
46453
46453
|
};
|
|
46454
46454
|
}
|
|
@@ -48606,14 +48606,14 @@ var require_awsrequestsigner = __commonJS({
|
|
|
48606
48606
|
}
|
|
48607
48607
|
};
|
|
48608
48608
|
exports2.AwsRequestSigner = AwsRequestSigner;
|
|
48609
|
-
async function sign2(
|
|
48610
|
-
return await
|
|
48611
|
-
}
|
|
48612
|
-
async function getSigningKey(
|
|
48613
|
-
const kDate = await sign2(
|
|
48614
|
-
const kRegion = await sign2(
|
|
48615
|
-
const kService = await sign2(
|
|
48616
|
-
const kSigning = await sign2(
|
|
48609
|
+
async function sign2(crypto17, key, msg) {
|
|
48610
|
+
return await crypto17.signWithHmacSha256(key, msg);
|
|
48611
|
+
}
|
|
48612
|
+
async function getSigningKey(crypto17, key, dateStamp, region, serviceName) {
|
|
48613
|
+
const kDate = await sign2(crypto17, `AWS4${key}`, dateStamp);
|
|
48614
|
+
const kRegion = await sign2(crypto17, kDate, region);
|
|
48615
|
+
const kService = await sign2(crypto17, kRegion, serviceName);
|
|
48616
|
+
const kSigning = await sign2(crypto17, kService, "aws4_request");
|
|
48617
48617
|
return kSigning;
|
|
48618
48618
|
}
|
|
48619
48619
|
async function generateAuthenticationHeaderMap(options) {
|
|
@@ -50198,24 +50198,24 @@ var require_googleauth = __commonJS({
|
|
|
50198
50198
|
const signed = await client.sign(data);
|
|
50199
50199
|
return signed.signedBlob;
|
|
50200
50200
|
}
|
|
50201
|
-
const
|
|
50201
|
+
const crypto17 = (0, crypto_1.createCrypto)();
|
|
50202
50202
|
if (client instanceof jwtclient_1.JWT && client.key) {
|
|
50203
|
-
const sign2 = await
|
|
50203
|
+
const sign2 = await crypto17.sign(client.key, data);
|
|
50204
50204
|
return sign2;
|
|
50205
50205
|
}
|
|
50206
50206
|
const creds = await this.getCredentials();
|
|
50207
50207
|
if (!creds.client_email) {
|
|
50208
50208
|
throw new Error("Cannot sign data without `client_email`.");
|
|
50209
50209
|
}
|
|
50210
|
-
return this.signBlob(
|
|
50210
|
+
return this.signBlob(crypto17, creds.client_email, data, endpoint);
|
|
50211
50211
|
}
|
|
50212
|
-
async signBlob(
|
|
50212
|
+
async signBlob(crypto17, emailOrUniqueId, data, endpoint) {
|
|
50213
50213
|
const url = new URL(endpoint + `${emailOrUniqueId}:signBlob`);
|
|
50214
50214
|
const res = await this.request({
|
|
50215
50215
|
method: "POST",
|
|
50216
50216
|
url: url.href,
|
|
50217
50217
|
data: {
|
|
50218
|
-
payload:
|
|
50218
|
+
payload: crypto17.encodeBase64StringUtf8(data)
|
|
50219
50219
|
},
|
|
50220
50220
|
retry: true,
|
|
50221
50221
|
retryConfig: {
|
|
@@ -50632,7 +50632,7 @@ var require_src10 = __commonJS({
|
|
|
50632
50632
|
var require_object_hash = __commonJS({
|
|
50633
50633
|
"../../node_modules/object-hash/index.js"(exports2, module2) {
|
|
50634
50634
|
"use strict";
|
|
50635
|
-
var
|
|
50635
|
+
var crypto17 = require("crypto");
|
|
50636
50636
|
exports2 = module2.exports = objectHash;
|
|
50637
50637
|
function objectHash(object, options) {
|
|
50638
50638
|
options = applyDefaults(object, options);
|
|
@@ -50650,7 +50650,7 @@ var require_object_hash = __commonJS({
|
|
|
50650
50650
|
exports2.keysMD5 = function(object) {
|
|
50651
50651
|
return objectHash(object, { algorithm: "md5", encoding: "hex", excludeValues: true });
|
|
50652
50652
|
};
|
|
50653
|
-
var hashes =
|
|
50653
|
+
var hashes = crypto17.getHashes ? crypto17.getHashes().slice() : ["sha1", "md5"];
|
|
50654
50654
|
hashes.push("passthrough");
|
|
50655
50655
|
var encodings = ["buffer", "hex", "binary", "base64"];
|
|
50656
50656
|
function applyDefaults(object, sourceOptions) {
|
|
@@ -50696,7 +50696,7 @@ var require_object_hash = __commonJS({
|
|
|
50696
50696
|
function hash(object, options) {
|
|
50697
50697
|
var hashingStream;
|
|
50698
50698
|
if (options.algorithm !== "passthrough") {
|
|
50699
|
-
hashingStream =
|
|
50699
|
+
hashingStream = crypto17.createHash(options.algorithm);
|
|
50700
50700
|
} else {
|
|
50701
50701
|
hashingStream = new PassThrough();
|
|
50702
50702
|
}
|
|
@@ -150124,14 +150124,14 @@ var require_etag = __commonJS({
|
|
|
150124
150124
|
"../../node_modules/etag/index.js"(exports2, module2) {
|
|
150125
150125
|
"use strict";
|
|
150126
150126
|
module2.exports = etag;
|
|
150127
|
-
var
|
|
150127
|
+
var crypto17 = require("crypto");
|
|
150128
150128
|
var Stats = require("fs").Stats;
|
|
150129
150129
|
var toString = Object.prototype.toString;
|
|
150130
150130
|
function entitytag(entity) {
|
|
150131
150131
|
if (entity.length === 0) {
|
|
150132
150132
|
return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"';
|
|
150133
150133
|
}
|
|
150134
|
-
var hash =
|
|
150134
|
+
var hash = crypto17.createHash("sha1").update(entity, "utf8").digest("base64").substring(0, 27);
|
|
150135
150135
|
var len = typeof entity === "string" ? Buffer.byteLength(entity, "utf8") : entity.length;
|
|
150136
150136
|
return '"' + len.toString(16) + "-" + hash + '"';
|
|
150137
150137
|
}
|
|
@@ -172482,17 +172482,17 @@ var require_content_disposition = __commonJS({
|
|
|
172482
172482
|
// ../../node_modules/cookie-signature/index.js
|
|
172483
172483
|
var require_cookie_signature = __commonJS({
|
|
172484
172484
|
"../../node_modules/cookie-signature/index.js"(exports2) {
|
|
172485
|
-
var
|
|
172485
|
+
var crypto17 = require("crypto");
|
|
172486
172486
|
exports2.sign = function(val, secret) {
|
|
172487
172487
|
if ("string" != typeof val) throw new TypeError("Cookie value must be provided as a string.");
|
|
172488
172488
|
if (null == secret) throw new TypeError("Secret key must be provided.");
|
|
172489
|
-
return val + "." +
|
|
172489
|
+
return val + "." + crypto17.createHmac("sha256", secret).update(val).digest("base64").replace(/\=+$/, "");
|
|
172490
172490
|
};
|
|
172491
172491
|
exports2.unsign = function(input, secret) {
|
|
172492
172492
|
if ("string" != typeof input) throw new TypeError("Signed cookie string must be provided.");
|
|
172493
172493
|
if (null == secret) throw new TypeError("Secret key must be provided.");
|
|
172494
172494
|
var tentativeValue = input.slice(0, input.lastIndexOf(".")), expectedInput = exports2.sign(tentativeValue, secret), expectedBuffer = Buffer.from(expectedInput), inputBuffer = Buffer.from(input);
|
|
172495
|
-
return expectedBuffer.length === inputBuffer.length &&
|
|
172495
|
+
return expectedBuffer.length === inputBuffer.length && crypto17.timingSafeEqual(expectedBuffer, inputBuffer) ? tentativeValue : false;
|
|
172496
172496
|
};
|
|
172497
172497
|
}
|
|
172498
172498
|
});
|
|
@@ -183402,9 +183402,9 @@ function resolveConfig(env = process.env) {
|
|
|
183402
183402
|
}
|
|
183403
183403
|
const cacheTtlStr = env.CLEF_AGENT_CACHE_TTL ?? "300";
|
|
183404
183404
|
const cacheTtl = parseInt(cacheTtlStr, 10);
|
|
183405
|
-
if (isNaN(cacheTtl) || cacheTtl < 30) {
|
|
183405
|
+
if (isNaN(cacheTtl) || cacheTtl < 0 || cacheTtl > 0 && cacheTtl < 30) {
|
|
183406
183406
|
throw new ConfigError(
|
|
183407
|
-
`Invalid CLEF_AGENT_CACHE_TTL '${cacheTtlStr}'. Must be an integer >= 30.`
|
|
183407
|
+
`Invalid CLEF_AGENT_CACHE_TTL '${cacheTtlStr}'. Must be 0 (just-in-time mode) or an integer >= 30.`
|
|
183408
183408
|
);
|
|
183409
183409
|
}
|
|
183410
183410
|
const ageKey = env.CLEF_AGENT_AGE_KEY;
|
|
@@ -183434,6 +183434,11 @@ var SecretsCache = class {
|
|
|
183434
183434
|
snapshot = null;
|
|
183435
183435
|
/** Replace the cached secrets in a single reference assignment. */
|
|
183436
183436
|
swap(values, keys, revision) {
|
|
183437
|
+
if (this.snapshot) {
|
|
183438
|
+
for (const k of Object.keys(this.snapshot.values)) {
|
|
183439
|
+
this.snapshot.values[k] = "";
|
|
183440
|
+
}
|
|
183441
|
+
}
|
|
183437
183442
|
this.snapshot = { values: { ...values }, keys: [...keys], revision, swappedAt: Date.now() };
|
|
183438
183443
|
}
|
|
183439
183444
|
/** Whether the cache has exceeded the given TTL (seconds). */
|
|
@@ -183441,8 +183446,13 @@ var SecretsCache = class {
|
|
|
183441
183446
|
if (!this.snapshot) return false;
|
|
183442
183447
|
return (Date.now() - this.snapshot.swappedAt) / 1e3 > ttlSeconds;
|
|
183443
183448
|
}
|
|
183444
|
-
/** Clear the cached snapshot. */
|
|
183449
|
+
/** Clear the cached snapshot, zeroing values first (best-effort). */
|
|
183445
183450
|
wipe() {
|
|
183451
|
+
if (this.snapshot) {
|
|
183452
|
+
for (const k of Object.keys(this.snapshot.values)) {
|
|
183453
|
+
this.snapshot.values[k] = "";
|
|
183454
|
+
}
|
|
183455
|
+
}
|
|
183446
183456
|
this.snapshot = null;
|
|
183447
183457
|
}
|
|
183448
183458
|
/** Epoch ms when the cache was last swapped, or null if never loaded. */
|
|
@@ -183507,20 +183517,16 @@ var DiskCache = class {
|
|
|
183507
183517
|
}
|
|
183508
183518
|
/** Get the SHA from the cached metadata, if available. */
|
|
183509
183519
|
getCachedSha() {
|
|
183510
|
-
|
|
183511
|
-
const raw = fs.readFileSync(this.metaPath, "utf-8");
|
|
183512
|
-
const meta = JSON.parse(raw);
|
|
183513
|
-
return meta.sha;
|
|
183514
|
-
} catch {
|
|
183515
|
-
return void 0;
|
|
183516
|
-
}
|
|
183520
|
+
return this.readMeta()?.sha;
|
|
183517
183521
|
}
|
|
183518
183522
|
/** Get the fetchedAt timestamp from metadata, if available. */
|
|
183519
183523
|
getFetchedAt() {
|
|
183524
|
+
return this.readMeta()?.fetchedAt;
|
|
183525
|
+
}
|
|
183526
|
+
readMeta() {
|
|
183520
183527
|
try {
|
|
183521
183528
|
const raw = fs.readFileSync(this.metaPath, "utf-8");
|
|
183522
|
-
|
|
183523
|
-
return meta.fetchedAt;
|
|
183529
|
+
return JSON.parse(raw);
|
|
183524
183530
|
} catch {
|
|
183525
183531
|
return void 0;
|
|
183526
183532
|
}
|
|
@@ -183576,7 +183582,10 @@ var AgeDecryptor = class {
|
|
|
183576
183582
|
};
|
|
183577
183583
|
|
|
183578
183584
|
// ../runtime/src/poller.ts
|
|
183579
|
-
var
|
|
183585
|
+
var crypto16 = __toESM(require("crypto"));
|
|
183586
|
+
|
|
183587
|
+
// ../runtime/src/artifact-decryptor.ts
|
|
183588
|
+
var crypto14 = __toESM(require("crypto"));
|
|
183580
183589
|
|
|
183581
183590
|
// ../runtime/src/kms/aws.ts
|
|
183582
183591
|
var AwsKmsProvider = class {
|
|
@@ -183741,11 +183750,106 @@ function createKmsProvider(provider, options) {
|
|
|
183741
183750
|
}
|
|
183742
183751
|
}
|
|
183743
183752
|
|
|
183753
|
+
// ../runtime/src/artifact-decryptor.ts
|
|
183754
|
+
var ArtifactDecryptor = class {
|
|
183755
|
+
ageDecryptor = new AgeDecryptor();
|
|
183756
|
+
privateKey;
|
|
183757
|
+
telemetryOverride;
|
|
183758
|
+
initialTelemetry;
|
|
183759
|
+
constructor(options) {
|
|
183760
|
+
this.privateKey = options.privateKey;
|
|
183761
|
+
this.initialTelemetry = options.telemetry;
|
|
183762
|
+
}
|
|
183763
|
+
/** Set or replace the telemetry emitter. */
|
|
183764
|
+
setTelemetry(emitter) {
|
|
183765
|
+
this.telemetryOverride = emitter;
|
|
183766
|
+
}
|
|
183767
|
+
get telemetry() {
|
|
183768
|
+
return this.telemetryOverride ?? this.initialTelemetry;
|
|
183769
|
+
}
|
|
183770
|
+
/**
|
|
183771
|
+
* Decrypt an artifact envelope into plaintext key-value pairs.
|
|
183772
|
+
*
|
|
183773
|
+
* @throws On KMS unwrap failure, AES-GCM auth failure, age decrypt failure,
|
|
183774
|
+
* missing private key (config error), or malformed plaintext JSON.
|
|
183775
|
+
*/
|
|
183776
|
+
async decrypt(artifact) {
|
|
183777
|
+
let plaintext;
|
|
183778
|
+
if (artifact.envelope) {
|
|
183779
|
+
plaintext = await this.decryptKmsEnvelope(artifact);
|
|
183780
|
+
} else {
|
|
183781
|
+
plaintext = await this.decryptAge(artifact);
|
|
183782
|
+
}
|
|
183783
|
+
let values;
|
|
183784
|
+
try {
|
|
183785
|
+
values = JSON.parse(plaintext);
|
|
183786
|
+
} catch (err) {
|
|
183787
|
+
this.telemetry?.artifactInvalid({
|
|
183788
|
+
reason: "payload_parse",
|
|
183789
|
+
error: err instanceof Error ? err.message : String(err)
|
|
183790
|
+
});
|
|
183791
|
+
throw err;
|
|
183792
|
+
} finally {
|
|
183793
|
+
plaintext = "";
|
|
183794
|
+
}
|
|
183795
|
+
return { values, keys: artifact.keys, revision: artifact.revision };
|
|
183796
|
+
}
|
|
183797
|
+
/** KMS envelope: unwrap DEK via KMS, then AES-256-GCM decrypt. */
|
|
183798
|
+
async decryptKmsEnvelope(artifact) {
|
|
183799
|
+
const envelope = artifact.envelope;
|
|
183800
|
+
let dek;
|
|
183801
|
+
try {
|
|
183802
|
+
const kms = createKmsProvider(envelope.provider);
|
|
183803
|
+
const wrappedKey = Buffer.from(envelope.wrappedKey, "base64");
|
|
183804
|
+
dek = await kms.unwrap(envelope.keyId, wrappedKey, envelope.algorithm);
|
|
183805
|
+
} catch (err) {
|
|
183806
|
+
this.telemetry?.artifactInvalid({
|
|
183807
|
+
reason: "kms_unwrap",
|
|
183808
|
+
error: err instanceof Error ? err.message : String(err)
|
|
183809
|
+
});
|
|
183810
|
+
throw err;
|
|
183811
|
+
}
|
|
183812
|
+
try {
|
|
183813
|
+
const iv = Buffer.from(envelope.iv, "base64");
|
|
183814
|
+
const authTag = Buffer.from(envelope.authTag, "base64");
|
|
183815
|
+
const ciphertextBuf = Buffer.from(artifact.ciphertext, "base64");
|
|
183816
|
+
const decipher = crypto14.createDecipheriv("aes-256-gcm", dek, iv);
|
|
183817
|
+
decipher.setAuthTag(authTag);
|
|
183818
|
+
return Buffer.concat([decipher.update(ciphertextBuf), decipher.final()]).toString("utf-8");
|
|
183819
|
+
} catch (err) {
|
|
183820
|
+
this.telemetry?.artifactInvalid({
|
|
183821
|
+
reason: "decrypt",
|
|
183822
|
+
error: err instanceof Error ? err.message : String(err)
|
|
183823
|
+
});
|
|
183824
|
+
throw err;
|
|
183825
|
+
} finally {
|
|
183826
|
+
dek.fill(0);
|
|
183827
|
+
}
|
|
183828
|
+
}
|
|
183829
|
+
/** Age-only: decrypt with the static private key. */
|
|
183830
|
+
async decryptAge(artifact) {
|
|
183831
|
+
if (!this.privateKey) {
|
|
183832
|
+
throw new Error(
|
|
183833
|
+
"Artifact requires an age private key. Set CLEF_AGENT_AGE_KEY or use KMS envelope encryption."
|
|
183834
|
+
);
|
|
183835
|
+
}
|
|
183836
|
+
try {
|
|
183837
|
+
return await this.ageDecryptor.decrypt(artifact.ciphertext, this.privateKey);
|
|
183838
|
+
} catch (err) {
|
|
183839
|
+
this.telemetry?.artifactInvalid({
|
|
183840
|
+
reason: err instanceof SyntaxError ? "payload_parse" : "decrypt",
|
|
183841
|
+
error: err instanceof Error ? err.message : String(err)
|
|
183842
|
+
});
|
|
183843
|
+
throw err;
|
|
183844
|
+
}
|
|
183845
|
+
}
|
|
183846
|
+
};
|
|
183847
|
+
|
|
183744
183848
|
// ../runtime/src/signature.ts
|
|
183745
|
-
var
|
|
183849
|
+
var crypto15 = __toESM(require("crypto"));
|
|
183746
183850
|
function buildSigningPayload(artifact) {
|
|
183747
183851
|
const fields = [
|
|
183748
|
-
"clef-sig-
|
|
183852
|
+
"clef-sig-v2",
|
|
183749
183853
|
String(artifact.version),
|
|
183750
183854
|
artifact.identity,
|
|
183751
183855
|
artifact.environment,
|
|
@@ -183757,12 +183861,14 @@ function buildSigningPayload(artifact) {
|
|
|
183757
183861
|
artifact.envelope?.provider ?? "",
|
|
183758
183862
|
artifact.envelope?.keyId ?? "",
|
|
183759
183863
|
artifact.envelope?.wrappedKey ?? "",
|
|
183760
|
-
artifact.envelope?.algorithm ?? ""
|
|
183864
|
+
artifact.envelope?.algorithm ?? "",
|
|
183865
|
+
artifact.envelope?.iv ?? "",
|
|
183866
|
+
artifact.envelope?.authTag ?? ""
|
|
183761
183867
|
];
|
|
183762
183868
|
return Buffer.from(fields.join("\n"), "utf-8");
|
|
183763
183869
|
}
|
|
183764
183870
|
function verifySignature(payload, signatureBase64, publicKeyBase64) {
|
|
183765
|
-
const keyObj =
|
|
183871
|
+
const keyObj = crypto15.createPublicKey({
|
|
183766
183872
|
key: Buffer.from(publicKeyBase64, "base64"),
|
|
183767
183873
|
format: "der",
|
|
183768
183874
|
type: "spki"
|
|
@@ -183770,10 +183876,10 @@ function verifySignature(payload, signatureBase64, publicKeyBase64) {
|
|
|
183770
183876
|
const signature = Buffer.from(signatureBase64, "base64");
|
|
183771
183877
|
const keyType = keyObj.asymmetricKeyType;
|
|
183772
183878
|
if (keyType === "ed25519") {
|
|
183773
|
-
return
|
|
183879
|
+
return crypto15.verify(null, payload, keyObj, signature);
|
|
183774
183880
|
}
|
|
183775
183881
|
if (keyType === "ec") {
|
|
183776
|
-
return
|
|
183882
|
+
return crypto15.verify("sha256", payload, keyObj, signature);
|
|
183777
183883
|
}
|
|
183778
183884
|
throw new Error(`Unsupported key type for signature verification: ${keyType}`);
|
|
183779
183885
|
}
|
|
@@ -183785,28 +183891,73 @@ var ArtifactPoller = class {
|
|
|
183785
183891
|
lastContentHash = null;
|
|
183786
183892
|
lastRevision = null;
|
|
183787
183893
|
lastExpiresAt = null;
|
|
183788
|
-
decryptor
|
|
183894
|
+
decryptor;
|
|
183789
183895
|
options;
|
|
183896
|
+
jitMode;
|
|
183790
183897
|
telemetryOverride;
|
|
183791
183898
|
constructor(options) {
|
|
183792
183899
|
this.options = options;
|
|
183900
|
+
this.jitMode = !!options.encryptedStore;
|
|
183901
|
+
this.decryptor = new ArtifactDecryptor({
|
|
183902
|
+
privateKey: options.privateKey,
|
|
183903
|
+
telemetry: options.telemetry
|
|
183904
|
+
});
|
|
183905
|
+
}
|
|
183906
|
+
/** Get the decryptor instance (for JIT mode server wiring). */
|
|
183907
|
+
getDecryptor() {
|
|
183908
|
+
return this.decryptor;
|
|
183793
183909
|
}
|
|
183794
183910
|
/** Set or replace the telemetry emitter (e.g. after resolving token from secrets). */
|
|
183795
183911
|
setTelemetry(emitter) {
|
|
183796
183912
|
this.telemetryOverride = emitter;
|
|
183913
|
+
this.decryptor.setTelemetry(emitter);
|
|
183797
183914
|
}
|
|
183798
183915
|
get telemetry() {
|
|
183799
183916
|
return this.telemetryOverride ?? this.options.telemetry;
|
|
183800
183917
|
}
|
|
183801
|
-
/**
|
|
183918
|
+
/**
|
|
183919
|
+
* Fetch, validate, decrypt, and cache the artifact.
|
|
183920
|
+
* Used in cached mode (cacheTtl > 0).
|
|
183921
|
+
*/
|
|
183802
183922
|
async fetchAndDecrypt() {
|
|
183923
|
+
const result = await this.fetchRaw();
|
|
183924
|
+
if (!result) return;
|
|
183925
|
+
await this.validateDecryptAndCache(result.artifact, result.contentHash);
|
|
183926
|
+
}
|
|
183927
|
+
/**
|
|
183928
|
+
* Fetch and validate the artifact without decrypting.
|
|
183929
|
+
* Stores the validated envelope in the encryptedStore for on-demand decryption.
|
|
183930
|
+
* Used in JIT mode (cacheTtl = 0).
|
|
183931
|
+
*/
|
|
183932
|
+
async fetchAndValidate() {
|
|
183933
|
+
const result = await this.fetchRaw();
|
|
183934
|
+
if (!result) return;
|
|
183935
|
+
const artifact = this.validateArtifact(result.artifact);
|
|
183936
|
+
this.options.encryptedStore.swap(artifact);
|
|
183937
|
+
this.lastRevision = artifact.revision;
|
|
183938
|
+
this.lastContentHash = result.contentHash ?? null;
|
|
183939
|
+
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
183940
|
+
this.options.onRefresh?.(artifact.revision);
|
|
183941
|
+
this.telemetry?.artifactRefreshed({
|
|
183942
|
+
revision: artifact.revision,
|
|
183943
|
+
keyCount: artifact.keys.length,
|
|
183944
|
+
kmsEnvelope: !!artifact.envelope
|
|
183945
|
+
});
|
|
183946
|
+
}
|
|
183947
|
+
/**
|
|
183948
|
+
* Fetch the raw artifact from the source (with disk cache fallback),
|
|
183949
|
+
* parse JSON, and check for revocation.
|
|
183950
|
+
*
|
|
183951
|
+
* Returns null when the content hash is unchanged (short-circuit).
|
|
183952
|
+
*/
|
|
183953
|
+
async fetchRaw() {
|
|
183803
183954
|
let raw;
|
|
183804
183955
|
let contentHash;
|
|
183805
183956
|
try {
|
|
183806
183957
|
const result = await this.options.source.fetch();
|
|
183807
183958
|
raw = result.raw;
|
|
183808
183959
|
contentHash = result.contentHash;
|
|
183809
|
-
if (contentHash && contentHash === this.lastContentHash) return;
|
|
183960
|
+
if (contentHash && contentHash === this.lastContentHash) return null;
|
|
183810
183961
|
this.options.diskCache?.write(raw, contentHash);
|
|
183811
183962
|
} catch (err) {
|
|
183812
183963
|
this.telemetry?.fetchFailed({
|
|
@@ -183817,7 +183968,7 @@ var ArtifactPoller = class {
|
|
|
183817
183968
|
if (this.options.diskCache) {
|
|
183818
183969
|
const cached = this.options.diskCache.read();
|
|
183819
183970
|
if (cached) {
|
|
183820
|
-
if (ttl !== void 0) {
|
|
183971
|
+
if (ttl !== void 0 && ttl > 0) {
|
|
183821
183972
|
const fetchedAt = this.options.diskCache.getFetchedAt();
|
|
183822
183973
|
if (fetchedAt && (Date.now() - new Date(fetchedAt).getTime()) / 1e3 > ttl) {
|
|
183823
183974
|
this.options.cache.wipe();
|
|
@@ -183831,9 +183982,9 @@ var ArtifactPoller = class {
|
|
|
183831
183982
|
}
|
|
183832
183983
|
raw = cached;
|
|
183833
183984
|
contentHash = this.options.diskCache.getCachedSha();
|
|
183834
|
-
if (contentHash && contentHash === this.lastContentHash) return;
|
|
183985
|
+
if (contentHash && contentHash === this.lastContentHash) return null;
|
|
183835
183986
|
} else {
|
|
183836
|
-
if (ttl !== void 0 && this.options.cache.isExpired(ttl)) {
|
|
183987
|
+
if (ttl !== void 0 && ttl > 0 && this.options.cache.isExpired(ttl)) {
|
|
183837
183988
|
this.options.cache.wipe();
|
|
183838
183989
|
this.telemetry?.cacheExpired({
|
|
183839
183990
|
cacheTtlSeconds: ttl,
|
|
@@ -183844,7 +183995,7 @@ var ArtifactPoller = class {
|
|
|
183844
183995
|
throw err;
|
|
183845
183996
|
}
|
|
183846
183997
|
} else {
|
|
183847
|
-
if (ttl !== void 0 && this.options.cache.isExpired(ttl)) {
|
|
183998
|
+
if (ttl !== void 0 && ttl > 0 && this.options.cache.isExpired(ttl)) {
|
|
183848
183999
|
this.options.cache.wipe();
|
|
183849
184000
|
this.telemetry?.cacheExpired({
|
|
183850
184001
|
cacheTtlSeconds: ttl,
|
|
@@ -183858,6 +184009,7 @@ var ArtifactPoller = class {
|
|
|
183858
184009
|
const parsed = JSON.parse(raw);
|
|
183859
184010
|
if (parsed.revokedAt) {
|
|
183860
184011
|
this.options.cache.wipe();
|
|
184012
|
+
this.options.encryptedStore?.wipe();
|
|
183861
184013
|
this.options.diskCache?.purge();
|
|
183862
184014
|
this.lastRevision = null;
|
|
183863
184015
|
this.lastContentHash = null;
|
|
@@ -183868,17 +184020,18 @@ var ArtifactPoller = class {
|
|
|
183868
184020
|
`Artifact revoked: ${parsed.identity}/${parsed.environment} at ${parsed.revokedAt}`
|
|
183869
184021
|
);
|
|
183870
184022
|
}
|
|
183871
|
-
|
|
184023
|
+
return { artifact: parsed, contentHash };
|
|
183872
184024
|
}
|
|
183873
184025
|
/**
|
|
183874
|
-
* Validate the artifact
|
|
183875
|
-
*
|
|
183876
|
-
*
|
|
184026
|
+
* Validate the artifact envelope: version, required fields, expiry,
|
|
184027
|
+
* revision dedup, integrity hash, and signature.
|
|
184028
|
+
* Emits `artifact.invalid` / `artifact.expired` telemetry on failure.
|
|
184029
|
+
* Returns the validated artifact, or throws.
|
|
183877
184030
|
*/
|
|
183878
|
-
|
|
184031
|
+
validateArtifact(parsed) {
|
|
183879
184032
|
let artifact;
|
|
183880
184033
|
try {
|
|
183881
|
-
artifact = this.
|
|
184034
|
+
artifact = this.validateEnvelope(parsed);
|
|
183882
184035
|
} catch (err) {
|
|
183883
184036
|
this.telemetry?.artifactInvalid({
|
|
183884
184037
|
reason: classifyValidationError(err),
|
|
@@ -183888,12 +184041,13 @@ var ArtifactPoller = class {
|
|
|
183888
184041
|
}
|
|
183889
184042
|
if (artifact.expiresAt && Date.now() > new Date(artifact.expiresAt).getTime()) {
|
|
183890
184043
|
this.options.cache.wipe();
|
|
184044
|
+
this.options.encryptedStore?.wipe();
|
|
183891
184045
|
this.options.diskCache?.purge();
|
|
183892
184046
|
this.telemetry?.artifactExpired({ expiresAt: artifact.expiresAt });
|
|
183893
184047
|
throw new Error(`Artifact expired at ${artifact.expiresAt}`);
|
|
183894
184048
|
}
|
|
183895
|
-
if (artifact.revision === this.lastRevision) return;
|
|
183896
|
-
const hash =
|
|
184049
|
+
if (artifact.revision === this.lastRevision) return artifact;
|
|
184050
|
+
const hash = crypto16.createHash("sha256").update(artifact.ciphertext).digest("hex");
|
|
183897
184051
|
if (hash !== artifact.ciphertextHash) {
|
|
183898
184052
|
const err = new Error(
|
|
183899
184053
|
`Artifact integrity check failed: expected hash ${artifact.ciphertextHash}, got ${hash}`
|
|
@@ -183940,59 +184094,33 @@ var ArtifactPoller = class {
|
|
|
183940
184094
|
throw err;
|
|
183941
184095
|
}
|
|
183942
184096
|
}
|
|
183943
|
-
|
|
183944
|
-
|
|
183945
|
-
|
|
183946
|
-
|
|
183947
|
-
|
|
183948
|
-
|
|
183949
|
-
|
|
183950
|
-
|
|
183951
|
-
|
|
183952
|
-
|
|
183953
|
-
|
|
183954
|
-
|
|
183955
|
-
|
|
183956
|
-
|
|
183957
|
-
|
|
183958
|
-
|
|
183959
|
-
|
|
183960
|
-
|
|
183961
|
-
|
|
183962
|
-
} else {
|
|
183963
|
-
if (!this.options.privateKey) {
|
|
183964
|
-
throw new Error(
|
|
183965
|
-
"Artifact requires an age private key. Set CLEF_AGENT_AGE_KEY or use KMS envelope encryption."
|
|
183966
|
-
);
|
|
183967
|
-
}
|
|
183968
|
-
agePrivateKey = this.options.privateKey;
|
|
183969
|
-
}
|
|
183970
|
-
try {
|
|
183971
|
-
const plaintext = await this.decryptor.decrypt(artifact.ciphertext, agePrivateKey);
|
|
183972
|
-
const values = JSON.parse(plaintext);
|
|
183973
|
-
this.options.cache.swap(values, artifact.keys, artifact.revision);
|
|
183974
|
-
this.lastRevision = artifact.revision;
|
|
183975
|
-
this.lastContentHash = contentHash ?? null;
|
|
183976
|
-
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
183977
|
-
this.options.onRefresh?.(artifact.revision);
|
|
183978
|
-
this.telemetry?.artifactRefreshed({
|
|
183979
|
-
revision: artifact.revision,
|
|
183980
|
-
keyCount: artifact.keys.length,
|
|
183981
|
-
kmsEnvelope: !!artifact.envelope
|
|
183982
|
-
});
|
|
183983
|
-
} catch (err) {
|
|
183984
|
-
if (err instanceof Error && !err.message.includes("integrity check failed")) {
|
|
183985
|
-
this.telemetry?.artifactInvalid({
|
|
183986
|
-
reason: err instanceof SyntaxError ? "payload_parse" : "decrypt",
|
|
183987
|
-
error: err.message
|
|
183988
|
-
});
|
|
183989
|
-
}
|
|
183990
|
-
throw err;
|
|
183991
|
-
}
|
|
184097
|
+
return artifact;
|
|
184098
|
+
}
|
|
184099
|
+
/**
|
|
184100
|
+
* Validate then decrypt and cache. Used by fetchAndDecrypt (cached mode).
|
|
184101
|
+
*/
|
|
184102
|
+
async validateDecryptAndCache(parsed, contentHash) {
|
|
184103
|
+
const artifact = this.validateArtifact(parsed);
|
|
184104
|
+
if (artifact.revision === this.lastRevision) return;
|
|
184105
|
+
const { values } = await this.decryptor.decrypt(artifact);
|
|
184106
|
+
this.options.cache.swap(values, artifact.keys, artifact.revision);
|
|
184107
|
+
this.lastRevision = artifact.revision;
|
|
184108
|
+
this.lastContentHash = contentHash ?? null;
|
|
184109
|
+
this.lastExpiresAt = artifact.expiresAt ?? null;
|
|
184110
|
+
this.options.onRefresh?.(artifact.revision);
|
|
184111
|
+
this.telemetry?.artifactRefreshed({
|
|
184112
|
+
revision: artifact.revision,
|
|
184113
|
+
keyCount: artifact.keys.length,
|
|
184114
|
+
kmsEnvelope: !!artifact.envelope
|
|
184115
|
+
});
|
|
183992
184116
|
}
|
|
183993
184117
|
/** Start the polling loop. Performs an initial fetch immediately. */
|
|
183994
184118
|
async start() {
|
|
183995
|
-
|
|
184119
|
+
if (this.jitMode) {
|
|
184120
|
+
await this.fetchAndValidate();
|
|
184121
|
+
} else {
|
|
184122
|
+
await this.fetchAndDecrypt();
|
|
184123
|
+
}
|
|
183996
184124
|
this.scheduleNext();
|
|
183997
184125
|
}
|
|
183998
184126
|
/** Start only the polling schedule (no initial fetch). */
|
|
@@ -184017,7 +184145,11 @@ var ArtifactPoller = class {
|
|
|
184017
184145
|
this.timer = setTimeout(async () => {
|
|
184018
184146
|
this.timer = null;
|
|
184019
184147
|
try {
|
|
184020
|
-
|
|
184148
|
+
if (this.jitMode) {
|
|
184149
|
+
await this.fetchAndValidate();
|
|
184150
|
+
} else {
|
|
184151
|
+
await this.fetchAndDecrypt();
|
|
184152
|
+
}
|
|
184021
184153
|
} catch (err) {
|
|
184022
184154
|
this.options.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
184023
184155
|
}
|
|
@@ -184033,14 +184165,14 @@ var ArtifactPoller = class {
|
|
|
184033
184165
|
}
|
|
184034
184166
|
return MIN_POLL_MS;
|
|
184035
184167
|
}
|
|
184168
|
+
if (this.jitMode) return MIN_POLL_MS;
|
|
184036
184169
|
const ttl = this.options.cacheTtl;
|
|
184037
184170
|
if (ttl !== void 0) {
|
|
184038
184171
|
return Math.max(ttl / 10 * 1e3, MIN_POLL_MS);
|
|
184039
184172
|
}
|
|
184040
184173
|
return 3e4;
|
|
184041
184174
|
}
|
|
184042
|
-
|
|
184043
|
-
const artifact = JSON.parse(raw);
|
|
184175
|
+
validateEnvelope(artifact) {
|
|
184044
184176
|
if (artifact.version !== 1) {
|
|
184045
184177
|
throw new Error(`Unsupported artifact version: ${artifact.version}`);
|
|
184046
184178
|
}
|
|
@@ -184048,7 +184180,7 @@ var ArtifactPoller = class {
|
|
|
184048
184180
|
throw new Error("Invalid artifact: missing required fields.");
|
|
184049
184181
|
}
|
|
184050
184182
|
if (artifact.envelope) {
|
|
184051
|
-
if (!artifact.envelope.provider || !artifact.envelope.keyId || !artifact.envelope.wrappedKey || !artifact.envelope.algorithm) {
|
|
184183
|
+
if (!artifact.envelope.provider || !artifact.envelope.keyId || !artifact.envelope.wrappedKey || !artifact.envelope.algorithm || !artifact.envelope.iv || !artifact.envelope.authTag) {
|
|
184052
184184
|
throw new Error("Invalid artifact: incomplete envelope fields.");
|
|
184053
184185
|
}
|
|
184054
184186
|
}
|
|
@@ -184065,6 +184197,42 @@ function classifyValidationError(err) {
|
|
|
184065
184197
|
return "unknown";
|
|
184066
184198
|
}
|
|
184067
184199
|
|
|
184200
|
+
// ../runtime/src/encrypted-artifact-store.ts
|
|
184201
|
+
var EncryptedArtifactStore = class {
|
|
184202
|
+
artifact = null;
|
|
184203
|
+
_storedAt = null;
|
|
184204
|
+
/** Atomically replace the stored artifact. */
|
|
184205
|
+
swap(artifact) {
|
|
184206
|
+
this.artifact = artifact;
|
|
184207
|
+
this._storedAt = Date.now();
|
|
184208
|
+
}
|
|
184209
|
+
/** Get the current encrypted artifact. Returns null if not yet loaded. */
|
|
184210
|
+
get() {
|
|
184211
|
+
return this.artifact;
|
|
184212
|
+
}
|
|
184213
|
+
/** Whether an artifact has been stored. */
|
|
184214
|
+
isReady() {
|
|
184215
|
+
return this.artifact !== null;
|
|
184216
|
+
}
|
|
184217
|
+
/** Epoch ms of last store, or null. */
|
|
184218
|
+
getStoredAt() {
|
|
184219
|
+
return this._storedAt;
|
|
184220
|
+
}
|
|
184221
|
+
/** Get key names from the stored artifact metadata (no decryption needed). */
|
|
184222
|
+
getKeys() {
|
|
184223
|
+
return this.artifact ? [...this.artifact.keys] : [];
|
|
184224
|
+
}
|
|
184225
|
+
/** Get the revision from the stored artifact. */
|
|
184226
|
+
getRevision() {
|
|
184227
|
+
return this.artifact?.revision ?? null;
|
|
184228
|
+
}
|
|
184229
|
+
/** Clear the stored artifact (on revocation/expiry). */
|
|
184230
|
+
wipe() {
|
|
184231
|
+
this.artifact = null;
|
|
184232
|
+
this._storedAt = null;
|
|
184233
|
+
}
|
|
184234
|
+
};
|
|
184235
|
+
|
|
184068
184236
|
// ../runtime/src/telemetry.ts
|
|
184069
184237
|
var SEVERITY = {
|
|
184070
184238
|
"agent.started": { number: 9, text: "INFO" },
|
|
@@ -184357,14 +184525,23 @@ var HttpArtifactSource = class {
|
|
|
184357
184525
|
async fetch() {
|
|
184358
184526
|
const res = await fetch(this.url);
|
|
184359
184527
|
if (!res.ok) {
|
|
184360
|
-
throw new Error(`Failed to fetch artifact from ${this.
|
|
184528
|
+
throw new Error(`Failed to fetch artifact from ${this.describe()}: ${res.status}`);
|
|
184361
184529
|
}
|
|
184362
184530
|
const raw = await res.text();
|
|
184363
184531
|
const etag = res.headers.get("etag") ?? void 0;
|
|
184364
184532
|
return { raw, contentHash: etag };
|
|
184365
184533
|
}
|
|
184366
184534
|
describe() {
|
|
184367
|
-
|
|
184535
|
+
try {
|
|
184536
|
+
const parsed = new URL(this.url);
|
|
184537
|
+
if (parsed.username || parsed.password) {
|
|
184538
|
+
parsed.username = "***";
|
|
184539
|
+
parsed.password = "";
|
|
184540
|
+
}
|
|
184541
|
+
return `HTTP ${parsed.href}`;
|
|
184542
|
+
} catch {
|
|
184543
|
+
return "HTTP <invalid-url>";
|
|
184544
|
+
}
|
|
184368
184545
|
}
|
|
184369
184546
|
};
|
|
184370
184547
|
|
|
@@ -184410,41 +184587,59 @@ var import_crypto16 = require("crypto");
|
|
|
184410
184587
|
var import_express = __toESM(require_express2());
|
|
184411
184588
|
|
|
184412
184589
|
// src/health.ts
|
|
184413
|
-
function healthHandler(cache, cacheTtl) {
|
|
184590
|
+
function healthHandler(cache, cacheTtl, encryptedStore) {
|
|
184414
184591
|
return (_req, res) => {
|
|
184415
|
-
|
|
184416
|
-
|
|
184417
|
-
|
|
184418
|
-
|
|
184419
|
-
|
|
184420
|
-
|
|
184421
|
-
|
|
184592
|
+
if (encryptedStore) {
|
|
184593
|
+
res.json({
|
|
184594
|
+
status: "ok",
|
|
184595
|
+
mode: "jit",
|
|
184596
|
+
revision: encryptedStore.getRevision(),
|
|
184597
|
+
lastRefreshAt: encryptedStore.getStoredAt(),
|
|
184598
|
+
expired: false
|
|
184599
|
+
});
|
|
184600
|
+
} else {
|
|
184601
|
+
const expired = cacheTtl !== void 0 && cache.isExpired(cacheTtl);
|
|
184602
|
+
res.json({
|
|
184603
|
+
status: "ok",
|
|
184604
|
+
mode: "cached",
|
|
184605
|
+
revision: cache.getRevision(),
|
|
184606
|
+
lastRefreshAt: cache.getSwappedAt(),
|
|
184607
|
+
expired
|
|
184608
|
+
});
|
|
184609
|
+
}
|
|
184422
184610
|
};
|
|
184423
184611
|
}
|
|
184424
|
-
function readyHandler(cache, cacheTtl) {
|
|
184612
|
+
function readyHandler(cache, cacheTtl, encryptedStore) {
|
|
184425
184613
|
return (_req, res) => {
|
|
184426
|
-
if (
|
|
184427
|
-
|
|
184428
|
-
|
|
184429
|
-
|
|
184430
|
-
|
|
184431
|
-
res.status(
|
|
184432
|
-
|
|
184614
|
+
if (encryptedStore) {
|
|
184615
|
+
if (!encryptedStore.isReady()) {
|
|
184616
|
+
res.status(503).json({ ready: false, reason: "not_loaded" });
|
|
184617
|
+
return;
|
|
184618
|
+
}
|
|
184619
|
+
res.status(200).json({ ready: true });
|
|
184620
|
+
} else {
|
|
184621
|
+
if (!cache.isReady()) {
|
|
184622
|
+
res.status(503).json({ ready: false, reason: "not_loaded" });
|
|
184623
|
+
return;
|
|
184624
|
+
}
|
|
184625
|
+
if (cacheTtl !== void 0 && cache.isExpired(cacheTtl)) {
|
|
184626
|
+
res.status(503).json({ ready: false, reason: "cache_expired" });
|
|
184627
|
+
return;
|
|
184628
|
+
}
|
|
184629
|
+
res.status(200).json({ ready: true });
|
|
184433
184630
|
}
|
|
184434
|
-
res.status(200).json({ ready: true });
|
|
184435
184631
|
};
|
|
184436
184632
|
}
|
|
184437
184633
|
|
|
184438
184634
|
// src/server.ts
|
|
184439
184635
|
function startAgentServer(options) {
|
|
184440
|
-
const { port, token, cache, cacheTtl } = options;
|
|
184636
|
+
const { port, token, cache, cacheTtl, decryptor, encryptedStore } = options;
|
|
184637
|
+
const jitMode = !!decryptor && !!encryptedStore;
|
|
184441
184638
|
const app = (0, import_express.default)();
|
|
184442
|
-
|
|
184639
|
+
const allowedHosts = /* @__PURE__ */ new Set([`127.0.0.1:${port}`, "127.0.0.1"]);
|
|
184443
184640
|
app.use("/v1", (req, res, next) => {
|
|
184444
184641
|
const host = req.headers.host ?? "";
|
|
184445
|
-
|
|
184446
|
-
const allowedHosts = [`127.0.0.1:${actualPort}`, `127.0.0.1:${port}`];
|
|
184447
|
-
if (!allowedHosts.includes(host)) {
|
|
184642
|
+
if (!allowedHosts.has(host)) {
|
|
184448
184643
|
res.status(403).json({ error: "Forbidden: invalid Host header" });
|
|
184449
184644
|
return;
|
|
184450
184645
|
}
|
|
@@ -184454,12 +184649,17 @@ function startAgentServer(options) {
|
|
|
184454
184649
|
res.setHeader("Cache-Control", "no-store");
|
|
184455
184650
|
next();
|
|
184456
184651
|
});
|
|
184457
|
-
app.get("/v1/health", healthHandler(cache, cacheTtl));
|
|
184458
|
-
app.get("/v1/ready", readyHandler(cache, cacheTtl));
|
|
184652
|
+
app.get("/v1/health", healthHandler(cache, cacheTtl, encryptedStore));
|
|
184653
|
+
app.get("/v1/ready", readyHandler(cache, cacheTtl, encryptedStore));
|
|
184459
184654
|
app.use("/v1/secrets", authMiddleware(token));
|
|
184460
184655
|
app.use("/v1/keys", authMiddleware(token));
|
|
184461
184656
|
const ttlGuard = (_req, res, next) => {
|
|
184462
|
-
if (
|
|
184657
|
+
if (jitMode) {
|
|
184658
|
+
if (!encryptedStore.isReady()) {
|
|
184659
|
+
res.status(503).json({ error: "Secrets not yet loaded" });
|
|
184660
|
+
return;
|
|
184661
|
+
}
|
|
184662
|
+
} else if (cacheTtl !== void 0 && cache.isExpired(cacheTtl)) {
|
|
184463
184663
|
res.status(503).json({ error: "Secrets expired" });
|
|
184464
184664
|
return;
|
|
184465
184665
|
}
|
|
@@ -184467,24 +184667,35 @@ function startAgentServer(options) {
|
|
|
184467
184667
|
};
|
|
184468
184668
|
app.use("/v1/secrets", ttlGuard);
|
|
184469
184669
|
app.use("/v1/keys", ttlGuard);
|
|
184470
|
-
app.get("/v1/secrets", (_req, res) => {
|
|
184471
|
-
|
|
184472
|
-
|
|
184473
|
-
|
|
184474
|
-
|
|
184475
|
-
|
|
184476
|
-
|
|
184477
|
-
|
|
184478
|
-
|
|
184479
|
-
|
|
184480
|
-
|
|
184481
|
-
|
|
184482
|
-
|
|
184670
|
+
app.get("/v1/secrets", async (_req, res) => {
|
|
184671
|
+
if (jitMode) {
|
|
184672
|
+
const artifact = encryptedStore.get();
|
|
184673
|
+
if (!artifact) {
|
|
184674
|
+
res.status(503).json({ error: "Secrets not yet loaded" });
|
|
184675
|
+
return;
|
|
184676
|
+
}
|
|
184677
|
+
try {
|
|
184678
|
+
const { values } = await decryptor.decrypt(artifact);
|
|
184679
|
+
res.json(values);
|
|
184680
|
+
} catch (err) {
|
|
184681
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
184682
|
+
res.status(503).json({ error: "Decryption failed", detail: message });
|
|
184683
|
+
}
|
|
184684
|
+
} else {
|
|
184685
|
+
const all = cache.getAll();
|
|
184686
|
+
if (!all) {
|
|
184687
|
+
res.status(503).json({ error: "Secrets not yet loaded" });
|
|
184688
|
+
return;
|
|
184689
|
+
}
|
|
184690
|
+
res.json(all);
|
|
184483
184691
|
}
|
|
184484
|
-
res.json({ value });
|
|
184485
184692
|
});
|
|
184486
184693
|
app.get("/v1/keys", (_req, res) => {
|
|
184487
|
-
|
|
184694
|
+
if (jitMode) {
|
|
184695
|
+
res.json(encryptedStore.getKeys());
|
|
184696
|
+
} else {
|
|
184697
|
+
res.json(cache.getKeys());
|
|
184698
|
+
}
|
|
184488
184699
|
});
|
|
184489
184700
|
const url = `http://127.0.0.1:${port}`;
|
|
184490
184701
|
return new Promise((resolve, reject) => {
|
|
@@ -184510,11 +184721,11 @@ function startAgentServer(options) {
|
|
|
184510
184721
|
});
|
|
184511
184722
|
}
|
|
184512
184723
|
function authMiddleware(token) {
|
|
184724
|
+
const expectedBuf = Buffer.from(token);
|
|
184513
184725
|
return (req, res, next) => {
|
|
184514
184726
|
const authHeader = req.headers.authorization ?? "";
|
|
184515
184727
|
const provided = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : "";
|
|
184516
184728
|
const providedBuf = Buffer.from(provided);
|
|
184517
|
-
const expectedBuf = Buffer.from(token);
|
|
184518
184729
|
if (!provided || providedBuf.length !== expectedBuf.length || !(0, import_crypto16.timingSafeEqual)(providedBuf, expectedBuf)) {
|
|
184519
184730
|
res.status(401).json({ error: "Unauthorized" });
|
|
184520
184731
|
return;
|
|
@@ -184530,6 +184741,8 @@ var Daemon = class {
|
|
|
184530
184741
|
shutdownResolve;
|
|
184531
184742
|
shutdownPromise;
|
|
184532
184743
|
startedAt;
|
|
184744
|
+
sigTermHandler;
|
|
184745
|
+
sigIntHandler;
|
|
184533
184746
|
constructor(options) {
|
|
184534
184747
|
this.options = options;
|
|
184535
184748
|
this.startedAt = Date.now();
|
|
@@ -184544,6 +184757,8 @@ var Daemon = class {
|
|
|
184544
184757
|
if (this.shutdownRequested) return;
|
|
184545
184758
|
this.shutdownRequested = true;
|
|
184546
184759
|
onLog?.("Shutting down...");
|
|
184760
|
+
if (this.sigTermHandler) process.off("SIGTERM", this.sigTermHandler);
|
|
184761
|
+
if (this.sigIntHandler) process.off("SIGINT", this.sigIntHandler);
|
|
184547
184762
|
poller.stop();
|
|
184548
184763
|
telemetry?.agentStopped({
|
|
184549
184764
|
reason: "signal",
|
|
@@ -184560,14 +184775,16 @@ var Daemon = class {
|
|
|
184560
184775
|
onLog?.("Shutdown complete.");
|
|
184561
184776
|
this.shutdownResolve?.();
|
|
184562
184777
|
};
|
|
184563
|
-
|
|
184778
|
+
this.sigTermHandler = () => {
|
|
184564
184779
|
shutdown().catch(() => {
|
|
184565
184780
|
});
|
|
184566
|
-
}
|
|
184567
|
-
|
|
184781
|
+
};
|
|
184782
|
+
this.sigIntHandler = () => {
|
|
184568
184783
|
shutdown().catch(() => {
|
|
184569
184784
|
});
|
|
184570
|
-
}
|
|
184785
|
+
};
|
|
184786
|
+
process.on("SIGTERM", this.sigTermHandler);
|
|
184787
|
+
process.on("SIGINT", this.sigIntHandler);
|
|
184571
184788
|
onLog?.(`Agent server listening at ${server.url}`);
|
|
184572
184789
|
poller.startPolling();
|
|
184573
184790
|
onLog?.("Agent ready. Polling for updates.");
|
|
@@ -184579,11 +184796,12 @@ var Daemon = class {
|
|
|
184579
184796
|
};
|
|
184580
184797
|
|
|
184581
184798
|
// package.json
|
|
184582
|
-
var version5 = "0.1.
|
|
184799
|
+
var version5 = "0.1.9-beta.57";
|
|
184583
184800
|
|
|
184584
184801
|
// src/main.ts
|
|
184585
184802
|
async function main() {
|
|
184586
184803
|
const config = resolveConfig();
|
|
184804
|
+
const jitMode = config.cacheTtl === 0;
|
|
184587
184805
|
let privateKey;
|
|
184588
184806
|
try {
|
|
184589
184807
|
const decryptor = new AgeDecryptor();
|
|
@@ -184607,6 +184825,7 @@ async function main() {
|
|
|
184607
184825
|
}
|
|
184608
184826
|
const diskCache = config.cachePath && config.vcs ? new DiskCache(config.cachePath, config.vcs.identity, config.vcs.environment) : void 0;
|
|
184609
184827
|
const cache = new SecretsCache();
|
|
184828
|
+
const encryptedStore = jitMode ? new EncryptedArtifactStore() : void 0;
|
|
184610
184829
|
const poller = new ArtifactPoller({
|
|
184611
184830
|
source,
|
|
184612
184831
|
privateKey,
|
|
@@ -184614,9 +184833,17 @@ async function main() {
|
|
|
184614
184833
|
diskCache,
|
|
184615
184834
|
cacheTtl: config.cacheTtl,
|
|
184616
184835
|
verifyKey: config.verifyKey,
|
|
184836
|
+
encryptedStore,
|
|
184617
184837
|
onError: (err) => console.error(`[clef-agent] poll error: ${err.message}`)
|
|
184618
184838
|
});
|
|
184619
|
-
|
|
184839
|
+
if (jitMode) {
|
|
184840
|
+
await poller.fetchAndValidate();
|
|
184841
|
+
const artifact = encryptedStore.get();
|
|
184842
|
+
const { values } = await poller.getDecryptor().decrypt(artifact);
|
|
184843
|
+
cache.swap(values, artifact.keys, artifact.revision);
|
|
184844
|
+
} else {
|
|
184845
|
+
await poller.fetchAndDecrypt();
|
|
184846
|
+
}
|
|
184620
184847
|
let telemetry;
|
|
184621
184848
|
if (config.telemetry) {
|
|
184622
184849
|
const headers = {};
|
|
@@ -184642,11 +184869,15 @@ async function main() {
|
|
|
184642
184869
|
});
|
|
184643
184870
|
poller.setTelemetry(telemetry);
|
|
184644
184871
|
}
|
|
184872
|
+
if (jitMode) {
|
|
184873
|
+
cache.wipe();
|
|
184874
|
+
}
|
|
184645
184875
|
const server = await startAgentServer({
|
|
184646
184876
|
port: config.port,
|
|
184647
184877
|
token: config.token,
|
|
184648
184878
|
cache,
|
|
184649
|
-
cacheTtl: config.cacheTtl
|
|
184879
|
+
cacheTtl: config.cacheTtl,
|
|
184880
|
+
...jitMode ? { decryptor: poller.getDecryptor(), encryptedStore } : {}
|
|
184650
184881
|
});
|
|
184651
184882
|
const daemon = new Daemon({
|
|
184652
184883
|
poller,
|
|
@@ -184655,7 +184886,8 @@ async function main() {
|
|
|
184655
184886
|
onLog: (msg) => console.log(`[clef-agent] ${msg}`)
|
|
184656
184887
|
});
|
|
184657
184888
|
telemetry?.agentStarted({ version: version5 });
|
|
184658
|
-
console.log(`[clef-agent]
|
|
184889
|
+
console.log(`[clef-agent] mode: ${jitMode ? "jit" : "cached"}`);
|
|
184890
|
+
console.log(`[clef-agent] token: [set]`);
|
|
184659
184891
|
await daemon.start();
|
|
184660
184892
|
}
|
|
184661
184893
|
main().catch((err) => {
|