calllint 1.0.0 → 1.0.1

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.
Files changed (2) hide show
  1. package/dist/index.js +60 -189
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4409,6 +4409,9 @@ function approveCommand(args, deps) {
4409
4409
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
4410
4410
  import { resolve as resolve4 } from "node:path";
4411
4411
 
4412
+ // ../../packages/signature/src/ed25519.ts
4413
+ import { createHash as createHash2 } from "node:crypto";
4414
+
4412
4415
  // ../../node_modules/.pnpm/@noble+ed25519@2.3.0/node_modules/@noble/ed25519/index.js
4413
4416
  var ed25519_CURVE = {
4414
4417
  p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
@@ -4759,8 +4762,8 @@ var hash2extK = (hashed) => {
4759
4762
  };
4760
4763
  var getExtendedPublicKeyAsync = (priv) => sha512a(toU8(priv, L)).then(hash2extK);
4761
4764
  var getExtendedPublicKey = (priv) => hash2extK(sha512s(toU8(priv, L)));
4762
- var getPublicKeyAsync = (priv) => getExtendedPublicKeyAsync(priv).then((p) => p.pointBytes);
4763
- var hashFinishA = (res) => sha512a(res.hashable).then(res.finish);
4765
+ var getPublicKey = (priv) => getExtendedPublicKey(priv).pointBytes;
4766
+ var hashFinishS = (res) => res.finish(sha512s(res.hashable));
4764
4767
  var _sign = (e, rBytes, msg) => {
4765
4768
  const { pointBytes: P2, scalar: s } = e;
4766
4769
  const r = modL_LE(rBytes);
@@ -4772,11 +4775,11 @@ var _sign = (e, rBytes, msg) => {
4772
4775
  };
4773
4776
  return { hashable, finish };
4774
4777
  };
4775
- var signAsync = async (msg, privKey) => {
4778
+ var sign = (msg, privKey) => {
4776
4779
  const m = toU8(msg);
4777
- const e = await getExtendedPublicKeyAsync(privKey);
4778
- const rBytes = await sha512a(e.prefix, m);
4779
- return hashFinishA(_sign(e, rBytes, m));
4780
+ const e = getExtendedPublicKey(privKey);
4781
+ const rBytes = sha512s(e.prefix, m);
4782
+ return hashFinishS(_sign(e, rBytes, m));
4780
4783
  };
4781
4784
  var veriOpts = { zip215: true };
4782
4785
  var _verify = (sig, msg, pub, opts = veriOpts) => {
@@ -4808,7 +4811,7 @@ var _verify = (sig, msg, pub, opts = veriOpts) => {
4808
4811
  };
4809
4812
  return { hashable, finish };
4810
4813
  };
4811
- var verifyAsync = async (s, m, p, opts = veriOpts) => hashFinishA(_verify(s, m, p, opts));
4814
+ var verify = (s, m, p, opts = veriOpts) => hashFinishS(_verify(s, m, p, opts));
4812
4815
  var etc = {
4813
4816
  sha512Async: async (...messages) => {
4814
4817
  const s = subtle();
@@ -4899,21 +4902,26 @@ function base64urlDecode(str) {
4899
4902
  }
4900
4903
 
4901
4904
  // ../../packages/signature/src/ed25519.ts
4902
- async function generateKeypair(keyId) {
4905
+ etc.sha512Sync = (...messages) => {
4906
+ const hash = createHash2("sha512");
4907
+ hash.update(etc.concatBytes(...messages));
4908
+ return new Uint8Array(hash.digest());
4909
+ };
4910
+ function generateKeypair(keyId) {
4903
4911
  const privateKey = utils.randomPrivateKey();
4904
- const publicKey = await getPublicKeyAsync(privateKey);
4912
+ const publicKey = getPublicKey(privateKey);
4905
4913
  return {
4906
4914
  privateKey,
4907
4915
  publicKey,
4908
4916
  keyId
4909
4917
  };
4910
4918
  }
4911
- async function signReceipt(unsignedReceipt, keypair) {
4919
+ function signReceipt(unsignedReceipt, keypair) {
4912
4920
  const canonical = stableStringify(unsignedReceipt);
4913
4921
  const hash = sha256(canonical);
4914
4922
  const hashHex = hash.slice(7);
4915
4923
  const hashBytes = Buffer.from(hashHex, "hex");
4916
- const signatureBytes = await signAsync(hashBytes, keypair.privateKey);
4924
+ const signatureBytes = sign(hashBytes, keypair.privateKey);
4917
4925
  const signatureBase64url = base64urlEncode(signatureBytes);
4918
4926
  return {
4919
4927
  algorithm: "ed25519",
@@ -4922,7 +4930,7 @@ async function signReceipt(unsignedReceipt, keypair) {
4922
4930
  signed_at: (/* @__PURE__ */ new Date()).toISOString()
4923
4931
  };
4924
4932
  }
4925
- async function verifyReceipt2(signedReceipt, publicKey) {
4933
+ function verifyReceipt2(signedReceipt, publicKey) {
4926
4934
  try {
4927
4935
  const sig = signedReceipt.signature;
4928
4936
  if (!sig) {
@@ -4944,7 +4952,7 @@ async function verifyReceipt2(signedReceipt, publicKey) {
4944
4952
  const hash = sha256(canonical);
4945
4953
  const hashHex = hash.slice(7);
4946
4954
  const hashBytes = Buffer.from(hashHex, "hex");
4947
- const valid = await verifyAsync(signatureBytes, hashBytes, publicKeyBytes);
4955
+ const valid = verify(signatureBytes, hashBytes, publicKeyBytes);
4948
4956
  return { valid, key_id: sig.key_id };
4949
4957
  } catch (error) {
4950
4958
  return {
@@ -5043,53 +5051,7 @@ function receiptVerify(args, deps) {
5043
5051
  }
5044
5052
  const receipt = parsed;
5045
5053
  if (receipt.signature) {
5046
- let cryptoResult = null;
5047
- let errorMsg = null;
5048
- try {
5049
- const promise = verifySignature(receipt, args);
5050
- let done = false;
5051
- promise.then(
5052
- (r) => {
5053
- cryptoResult = r;
5054
- done = true;
5055
- },
5056
- (e) => {
5057
- errorMsg = e instanceof Error ? e.message : String(e);
5058
- done = true;
5059
- }
5060
- );
5061
- const start = Date.now();
5062
- while (!done && Date.now() - start < 5e3) {
5063
- }
5064
- if (!done) {
5065
- return {
5066
- stdout: "",
5067
- stderr: "Signature verification timed out",
5068
- exitCode: EXIT.ERROR
5069
- };
5070
- }
5071
- if (errorMsg) {
5072
- return {
5073
- stdout: "",
5074
- stderr: `Signature verification failed: ${errorMsg}`,
5075
- exitCode: EXIT.ERROR
5076
- };
5077
- }
5078
- if (!cryptoResult) {
5079
- return {
5080
- stdout: "",
5081
- stderr: "Signature verification failed (no result)",
5082
- exitCode: EXIT.ERROR
5083
- };
5084
- }
5085
- return formatVerifyResult(receipt, cryptoResult, args);
5086
- } catch (e) {
5087
- return {
5088
- stdout: "",
5089
- stderr: `Signature verification error: ${e instanceof Error ? e.message : String(e)}`,
5090
- exitCode: EXIT.ERROR
5091
- };
5092
- }
5054
+ return verifySignature(receipt, args, deps);
5093
5055
  }
5094
5056
  if (flagBool(args.flags, "json")) {
5095
5057
  return {
@@ -5116,34 +5078,39 @@ function receiptVerify(args, deps) {
5116
5078
  ].join("\n");
5117
5079
  return { stdout, exitCode: EXIT.OK };
5118
5080
  }
5119
- async function verifySignature(receipt, args) {
5081
+ function verifySignature(receipt, args, deps) {
5120
5082
  const sig = receipt.signature;
5121
5083
  const publicKeyUrl = sig.public_key_url || "https://calllint.com/.well-known/receipt-keys.json";
5122
- let publicKey;
5123
5084
  const publicKeyFlag = args.flags["public-key"];
5124
- if (publicKeyFlag && typeof publicKeyFlag === "string") {
5125
- try {
5126
- const keyJson = JSON.parse(readFileSync8(publicKeyFlag, "utf8"));
5127
- publicKey = keyJson.public_key;
5128
- } catch (e) {
5129
- throw new Error(
5130
- `Could not read public key from ${publicKeyFlag}: ${e instanceof Error ? e.message : String(e)}`
5131
- );
5085
+ if (!publicKeyFlag || typeof publicKeyFlag !== "string") {
5086
+ return {
5087
+ stdout: "",
5088
+ stderr: [
5089
+ "Receipt has a signature but no public key was provided.",
5090
+ ` Signature key_id: ${sig.key_id}`,
5091
+ ` Public key URL: ${publicKeyUrl}`,
5092
+ "",
5093
+ "Verify offline by passing the public key:",
5094
+ " calllint receipt verify <receipt.json> --public-key <keyfile>"
5095
+ ].join("\n"),
5096
+ exitCode: EXIT.ERROR
5097
+ };
5098
+ }
5099
+ let publicKey;
5100
+ try {
5101
+ const keyJson = JSON.parse(readFileSync8(resolve4(deps.cwd, publicKeyFlag), "utf8"));
5102
+ publicKey = keyJson.public_key;
5103
+ if (typeof publicKey !== "string") {
5104
+ throw new Error("key file has no string 'public_key' field");
5132
5105
  }
5133
- } else {
5134
- throw new Error(
5135
- `Receipt has signature but public key not available.
5136
- Signature key_id: ${sig.key_id}
5137
- Public key URL: ${publicKeyUrl}
5138
-
5139
- To verify locally, provide public key with --public-key <keyfile>
5140
- Example: calllint receipt verify receipt.json --public-key dev-key.json`
5141
- );
5106
+ } catch (e) {
5107
+ return {
5108
+ stdout: "",
5109
+ stderr: `Could not read public key from ${publicKeyFlag}: ${e instanceof Error ? e.message : String(e)}`,
5110
+ exitCode: EXIT.ERROR
5111
+ };
5142
5112
  }
5143
- return await verifyReceipt2(receipt, publicKey);
5144
- }
5145
- function formatVerifyResult(receipt, cryptoResult, args) {
5146
- const sig = receipt.signature;
5113
+ const cryptoResult = verifyReceipt2(receipt, publicKey);
5147
5114
  if (flagBool(args.flags, "json")) {
5148
5115
  return {
5149
5116
  stdout: JSON.stringify(
@@ -5202,23 +5169,13 @@ function receiptSign(args, deps) {
5202
5169
  exitCode: EXIT.USAGE
5203
5170
  };
5204
5171
  }
5205
- let receiptRaw;
5206
- try {
5207
- receiptRaw = readFileSync8(resolve4(deps.cwd, receiptFile), "utf8");
5208
- } catch (e) {
5209
- return {
5210
- stdout: "",
5211
- stderr: `Could not read receipt ${receiptFile}: ${e instanceof Error ? e.message : String(e)}`,
5212
- exitCode: EXIT.ERROR
5213
- };
5214
- }
5215
5172
  let unsignedReceipt;
5216
5173
  try {
5217
- unsignedReceipt = JSON.parse(receiptRaw);
5174
+ unsignedReceipt = JSON.parse(readFileSync8(resolve4(deps.cwd, receiptFile), "utf8"));
5218
5175
  } catch (e) {
5219
5176
  return {
5220
5177
  stdout: "",
5221
- stderr: `Receipt is not valid JSON: ${e instanceof Error ? e.message : String(e)}`,
5178
+ stderr: `Could not read receipt ${receiptFile}: ${e instanceof Error ? e.message : String(e)}`,
5222
5179
  exitCode: EXIT.ERROR
5223
5180
  };
5224
5181
  }
@@ -5229,69 +5186,21 @@ function receiptSign(args, deps) {
5229
5186
  exitCode: EXIT.ERROR
5230
5187
  };
5231
5188
  }
5232
- let keyJson;
5233
- try {
5234
- const keyRaw = readFileSync8(resolve4(deps.cwd, keyFile), "utf8");
5235
- keyJson = JSON.parse(keyRaw);
5236
- } catch (e) {
5237
- return {
5238
- stdout: "",
5239
- stderr: `Could not read key file ${keyFile}: ${e instanceof Error ? e.message : String(e)}`,
5240
- exitCode: EXIT.ERROR
5241
- };
5242
- }
5243
5189
  let keypair;
5244
5190
  try {
5191
+ const keyJson = JSON.parse(readFileSync8(resolve4(deps.cwd, keyFile), "utf8"));
5245
5192
  keypair = importKeypair(keyJson);
5246
5193
  } catch (e) {
5247
5194
  return {
5248
5195
  stdout: "",
5249
- stderr: `Invalid keypair format: ${e instanceof Error ? e.message : String(e)}`,
5250
- exitCode: EXIT.ERROR
5251
- };
5252
- }
5253
- let signature = null;
5254
- let errorMsg = null;
5255
- const promise = signReceipt(unsignedReceipt, keypair);
5256
- let done = false;
5257
- promise.then(
5258
- (sig) => {
5259
- signature = sig;
5260
- done = true;
5261
- },
5262
- (e) => {
5263
- errorMsg = e instanceof Error ? e.message : String(e);
5264
- done = true;
5265
- }
5266
- );
5267
- const start = Date.now();
5268
- while (!done && Date.now() - start < 5e3) {
5269
- }
5270
- if (!done) {
5271
- return {
5272
- stdout: "",
5273
- stderr: "Signing timed out",
5274
- exitCode: EXIT.ERROR
5275
- };
5276
- }
5277
- if (errorMsg) {
5278
- return {
5279
- stdout: "",
5280
- stderr: `Signing failed: ${errorMsg}`,
5281
- exitCode: EXIT.ERROR
5282
- };
5283
- }
5284
- if (!signature) {
5285
- return {
5286
- stdout: "",
5287
- stderr: "Signing failed (no result)",
5196
+ stderr: `Could not read key file ${keyFile}: ${e instanceof Error ? e.message : String(e)}`,
5288
5197
  exitCode: EXIT.ERROR
5289
5198
  };
5290
5199
  }
5291
5200
  try {
5201
+ const signature = signReceipt(unsignedReceipt, keypair);
5292
5202
  const signedReceipt = { ...unsignedReceipt, signature };
5293
- const outPath = resolve4(deps.cwd, outFile);
5294
- writeFileSync6(outPath, JSON.stringify(signedReceipt, null, 2) + "\n", "utf8");
5203
+ writeFileSync6(resolve4(deps.cwd, outFile), JSON.stringify(signedReceipt, null, 2) + "\n", "utf8");
5295
5204
  const stdout = [
5296
5205
  "\u2713 Receipt signed successfully",
5297
5206
  ` Key ID: ${signature.key_id}`,
@@ -5303,7 +5212,7 @@ function receiptSign(args, deps) {
5303
5212
  } catch (e) {
5304
5213
  return {
5305
5214
  stdout: "",
5306
- stderr: `Failed to write signed receipt: ${e instanceof Error ? e.message : String(e)}`,
5215
+ stderr: `Signing failed: ${e instanceof Error ? e.message : String(e)}`,
5307
5216
  exitCode: EXIT.ERROR
5308
5217
  };
5309
5218
  }
@@ -5323,48 +5232,10 @@ function receiptKeygen(args, deps) {
5323
5232
  };
5324
5233
  }
5325
5234
  const keyId = args.flags["key-id"] || "calllint-dev-2026-h2";
5326
- let keypair = null;
5327
- let errorMsg = null;
5328
- const promise = generateKeypair(keyId);
5329
- let done = false;
5330
- promise.then(
5331
- (kp) => {
5332
- keypair = kp;
5333
- done = true;
5334
- },
5335
- (e) => {
5336
- errorMsg = e instanceof Error ? e.message : String(e);
5337
- done = true;
5338
- }
5339
- );
5340
- const start = Date.now();
5341
- while (!done && Date.now() - start < 5e3) {
5342
- }
5343
- if (!done) {
5344
- return {
5345
- stdout: "",
5346
- stderr: "Keygen timed out",
5347
- exitCode: EXIT.ERROR
5348
- };
5349
- }
5350
- if (errorMsg) {
5351
- return {
5352
- stdout: "",
5353
- stderr: `Keygen failed: ${errorMsg}`,
5354
- exitCode: EXIT.ERROR
5355
- };
5356
- }
5357
- if (!keypair) {
5358
- return {
5359
- stdout: "",
5360
- stderr: "Keygen failed (no result)",
5361
- exitCode: EXIT.ERROR
5362
- };
5363
- }
5364
5235
  try {
5236
+ const keypair = generateKeypair(keyId);
5365
5237
  const exported = exportKeypair(keypair);
5366
- const outPath = resolve4(deps.cwd, outFile);
5367
- writeFileSync6(outPath, JSON.stringify(exported, null, 2) + "\n", "utf8");
5238
+ writeFileSync6(resolve4(deps.cwd, outFile), JSON.stringify(exported, null, 2) + "\n", "utf8");
5368
5239
  const stdout = [
5369
5240
  "\u2713 Keypair generated successfully",
5370
5241
  ` Key ID: ${keyId}`,
@@ -5377,7 +5248,7 @@ function receiptKeygen(args, deps) {
5377
5248
  } catch (e) {
5378
5249
  return {
5379
5250
  stdout: "",
5380
- stderr: `Failed to write keypair: ${e instanceof Error ? e.message : String(e)}`,
5251
+ stderr: `Keygen failed: ${e instanceof Error ? e.message : String(e)}`,
5381
5252
  exitCode: EXIT.ERROR
5382
5253
  };
5383
5254
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "calllint",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Evidence-backed security verdicts for MCP servers and agent tools. Lint agent tool-call risk before tools run — SAFE / REVIEW / BLOCK / UNKNOWN, with evidence. Never executes the server it judges.",
5
5
  "keywords": [
6
6
  "mcp",