@apicity/cost 0.2.0-alpha.1 → 0.2.0

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.
@@ -1,4 +1,12 @@
1
- import { computeEstimate } from "./compute.js";
1
+ /**
2
+ * Exact paid-endpoint registry.
3
+ *
4
+ * Only endpoints listed here are considered paid. All unlisted endpoints
5
+ * are assumed free and must preserve current behavior with no caller changes.
6
+ *
7
+ * Matching is exact: provider + method + dotPath. No regex, prefix,
8
+ * wildcard, path-family, generated broad match, or fallback-by-method logic.
9
+ */
2
10
  /**
3
11
  * The canonical list of paid endpoints. Add new entries here only after
4
12
  * review. Keep the list small and explicit.
@@ -42,116 +50,4 @@ export function lookupPaidEndpoint(provider, method, dotPath) {
42
50
  export function isPaidEndpoint(provider, method, dotPath) {
43
51
  return lookupPaidEndpoint(provider, method, dotPath) !== undefined;
44
52
  }
45
- /**
46
- * Error thrown when a paid endpoint is called without an explicit maxSpend.
47
- */
48
- export class MaxSpendError extends Error {
49
- provider;
50
- method;
51
- dotPath;
52
- maxSpend;
53
- constructor(provider, method, dotPath, maxSpend) {
54
- super(`Endpoint ${provider} ${method} ${dotPath} may spend money. ` +
55
- `maxSpend is ${maxSpend} USD. ` +
56
- `Pass an explicit maxSpend to proceed.`);
57
- this.name = "MaxSpendError";
58
- this.provider = provider;
59
- this.method = method;
60
- this.dotPath = dotPath;
61
- this.maxSpend = maxSpend;
62
- }
63
- }
64
- /**
65
- * Error thrown when the estimated cost of a paid endpoint exceeds the
66
- * caller's maxSpend or when the cost cannot be safely estimated.
67
- */
68
- export class SpendBoundError extends Error {
69
- provider;
70
- method;
71
- dotPath;
72
- maxSpend;
73
- estimatedUsd;
74
- constructor(provider, method, dotPath, maxSpend, estimatedUsd, message) {
75
- super(message ??
76
- `Endpoint ${provider} ${method} ${dotPath} estimated cost ` +
77
- `(${estimatedUsd} USD) exceeds maxSpend (${maxSpend} USD).`);
78
- this.name = "SpendBoundError";
79
- this.provider = provider;
80
- this.method = method;
81
- this.dotPath = dotPath;
82
- this.maxSpend = maxSpend;
83
- this.estimatedUsd = estimatedUsd;
84
- }
85
- }
86
- /**
87
- * Preflight check for paid endpoints.
88
- *
89
- * For paid endpoints, maxSpend defaults to 0 when omitted. maxSpend=0 blocks
90
- * before the network request with a MaxSpendError. maxSpend>0 authorizes the
91
- * call to proceed.
92
- *
93
- * Free/unlisted endpoints are always allowed regardless of maxSpend.
94
- */
95
- export function maxSpendPreflight(provider, method, dotPath, maxSpend = 0) {
96
- if (!isPaidEndpoint(provider, method, dotPath)) {
97
- return;
98
- }
99
- if (maxSpend <= 0) {
100
- throw new MaxSpendError(provider, method, dotPath, maxSpend);
101
- }
102
- }
103
- /**
104
- * Verify that a cost estimate is within the caller's maxSpend.
105
- *
106
- * If the estimate has warnings (could not be computed safely), the spend
107
- * cannot be bounded and the call is blocked. If the estimated USD exceeds
108
- * maxSpend, the call is blocked. Otherwise the call proceeds.
109
- *
110
- * This must run AFTER maxSpendPreflight, so maxSpend is known to be > 0.
111
- */
112
- export function spendBoundCheck(provider, method, dotPath, maxSpend, estimate) {
113
- if (maxSpend === undefined || maxSpend <= 0) {
114
- return;
115
- }
116
- if (estimate.warnings.length > 0) {
117
- throw new SpendBoundError(provider, method, dotPath, maxSpend, estimate.usd, `Endpoint ${provider} ${method} ${dotPath} spend cannot be bounded ` +
118
- `from the payload: ${estimate.warnings.join("; ")}. ` +
119
- `Pass an explicit maxSpend that covers the worst-case cost, ` +
120
- `or adjust the payload so the cost can be estimated.`);
121
- }
122
- if (estimate.usd > maxSpend) {
123
- throw new SpendBoundError(provider, method, dotPath, maxSpend, estimate.usd);
124
- }
125
- }
126
- /**
127
- * Wrap a provider network dispatch with the paid-endpoint guard.
128
- *
129
- * This is the canonical boundary enforcement: it runs the preflight check
130
- * and spend-bound check before the actual HTTP request, and only calls the
131
- * supplied `dispatch` function when the checks pass.
132
- *
133
- * Free/unlisted endpoints return `dispatch()` immediately without guard
134
- * overhead, so callers that omit `maxSpend` on free endpoints see no change.
135
- *
136
- * @param provider - Provider identifier (e.g. "kie", "openai")
137
- * @param method - HTTP method (e.g. "POST", "GET")
138
- * @param dotPath - Exact endpoint dot-path (e.g. "api.v1.jobs.createTask")
139
- * @param payload - Request payload for cost estimation
140
- * @param maxSpend - Maximum spend authorization in USD (undefined for free endpoints)
141
- * @param dispatch - The actual network dispatch to wrap
142
- * @returns The result of `dispatch()`
143
- */
144
- export async function dispatchWithPaidGuard(provider, method, dotPath, payload, maxSpend, dispatch) {
145
- maxSpendPreflight(provider, method, dotPath, maxSpend);
146
- if (isPaidEndpoint(provider, method, dotPath) &&
147
- maxSpend !== undefined &&
148
- maxSpend > 0) {
149
- const estimate = computeEstimate({
150
- provider: provider,
151
- payload,
152
- });
153
- spendBoundCheck(provider, method, dotPath, maxSpend, estimate);
154
- }
155
- return dispatch();
156
- }
157
53
  //# sourceMappingURL=paid-endpoints.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"paid-endpoints.js","sourceRoot":"","sources":["../../src/paid-endpoints.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"paid-endpoints.js","sourceRoot":"","sources":["../../src/paid-endpoints.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsBH;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAiC;IAC1D;QACE,GAAG,EAAE;YACH,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,wBAAwB;SAClC;QACD,IAAI,EAAE;YACJ,MAAM,EACJ,wEAAwE;YAC1E,WAAW,EAAE,cAAc;YAC3B,SAAS,EACP,sEAAsE;SACzE;KACF;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAgB,EAChB,MAAc,EACd,OAAe;IAEf,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IACE,KAAK,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ;YAC/B,KAAK,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM;YAC3B,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,OAAO,EAC7B,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,MAAc,EACd,OAAe;IAEf,OAAO,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,SAAS,CAAC;AACrE,CAAC"}
@@ -1,19 +1,3 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Parse a TTL string like "10m", "1h", "30s" into seconds.
4
- */
5
- export declare function parseTtl(ttl: string): number;
6
- /**
7
- * Mint an OTP for a specific request.
8
- *
9
- * Requires `APICITY_PAYGATE_PRIVATE_KEY_PATH` to point to an Ed25519 private key PEM.
10
- */
11
- export declare function mintOtp(provider: string, method: string, dotPath: string, payload: Record<string, unknown>, maxSpendUsd: number, ttlSeconds: number): string;
12
- /**
13
- * Generate a fresh Ed25519 key pair for the pay gate.
14
- */
15
- export declare function generateKeyPair(): {
16
- publicKeyPem: string;
17
- privateKeyPem: string;
18
- };
2
+ export {};
19
3
  //# sourceMappingURL=paygate-cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paygate-cli.d.ts","sourceRoot":"","sources":["../../src/paygate-cli.ts"],"names":[],"mappings":";AAkBA;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqB5C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,MAAM,CAuCR;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAMA"}
1
+ {"version":3,"file":"paygate-cli.d.ts","sourceRoot":"","sources":["../../src/paygate-cli.ts"],"names":[],"mappings":""}
@@ -1,83 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { sign, generateKeyPairSync, randomBytes } from "node:crypto";
3
2
  import { readFileSync } from "node:fs";
4
3
  import { fileURLToPath } from "node:url";
5
- import { canonicalHash } from "./paygate.js";
6
- /**
7
- * Encode a buffer to unpadded base64url.
8
- */
9
- function base64urlEncode(data) {
10
- return data
11
- .toString("base64")
12
- .replace(/\+/g, "-")
13
- .replace(/\//g, "_")
14
- .replace(/=+$/g, "");
15
- }
16
- /**
17
- * Parse a TTL string like "10m", "1h", "30s" into seconds.
18
- */
19
- export function parseTtl(ttl) {
20
- const match = ttl.match(/^(\d+)([smhd])$/i);
21
- if (!match) {
22
- throw new Error(`Invalid TTL format: ${ttl}. Expected format like 10m, 1h, 30s.`);
23
- }
24
- const value = parseInt(match[1], 10);
25
- const unit = match[2].toLowerCase();
26
- switch (unit) {
27
- case "s":
28
- return value;
29
- case "m":
30
- return value * 60;
31
- case "h":
32
- return value * 60 * 60;
33
- case "d":
34
- return value * 60 * 60 * 24;
35
- default:
36
- throw new Error(`Unknown TTL unit: ${unit}`);
37
- }
38
- }
39
- /**
40
- * Mint an OTP for a specific request.
41
- *
42
- * Requires `APICITY_PAYGATE_PRIVATE_KEY_PATH` to point to an Ed25519 private key PEM.
43
- */
44
- export function mintOtp(provider, method, dotPath, payload, maxSpendUsd, ttlSeconds) {
45
- const privateKeyPath = process.env.APICITY_PAYGATE_PRIVATE_KEY_PATH;
46
- if (!privateKeyPath) {
47
- throw new Error("APICITY_PAYGATE_PRIVATE_KEY_PATH is not set. " +
48
- "Export the path to your Ed25519 private key PEM.");
49
- }
50
- const privateKeyPem = readFileSync(privateKeyPath, "utf8");
51
- const jti = randomBytes(16).toString("hex");
52
- const iat = Math.floor(Date.now() / 1000);
53
- const exp = iat + ttlSeconds;
54
- const payloadObj = {
55
- v: 1,
56
- jti,
57
- provider,
58
- method,
59
- dotPath,
60
- requestHash: canonicalHash(payload),
61
- maxSpendUsd,
62
- iat,
63
- exp,
64
- };
65
- const payloadJson = JSON.stringify(payloadObj);
66
- const payloadSegment = base64urlEncode(Buffer.from(payloadJson, "utf8"));
67
- const signature = sign(null, Buffer.from(payloadSegment, "utf8"), privateKeyPem);
68
- const signatureSegment = base64urlEncode(signature);
69
- return `${payloadSegment}.${signatureSegment}`;
70
- }
71
- /**
72
- * Generate a fresh Ed25519 key pair for the pay gate.
73
- */
74
- export function generateKeyPair() {
75
- const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
76
- publicKeyEncoding: { type: "spki", format: "pem" },
77
- privateKeyEncoding: { type: "pkcs8", format: "pem" },
78
- });
79
- return { publicKeyPem: publicKey, privateKeyPem: privateKey };
80
- }
4
+ import { mintOtp } from "./paygate.js";
81
5
  function parseMintArgs(argv) {
82
6
  const out = {};
83
7
  for (let i = 0; i < argv.length; i++) {
@@ -98,10 +22,10 @@ function parseMintArgs(argv) {
98
22
  out.payloadFile = argv[++i];
99
23
  else if (a.startsWith("--payload-file="))
100
24
  out.payloadFile = a.slice(15);
101
- else if (a === "--max-spend")
102
- out.maxSpend = parseFloat(argv[++i]);
103
- else if (a.startsWith("--max-spend="))
104
- out.maxSpend = parseFloat(a.slice(12));
25
+ else if (a === "--secret-file")
26
+ out.secretFile = argv[++i];
27
+ else if (a.startsWith("--secret-file="))
28
+ out.secretFile = a.slice(14);
105
29
  else if (a === "--ttl")
106
30
  out.ttl = argv[++i];
107
31
  else if (a.startsWith("--ttl="))
@@ -110,14 +34,7 @@ function parseMintArgs(argv) {
110
34
  console.error(`[apicity-paygate] unknown arg: ${a}`);
111
35
  }
112
36
  }
113
- const required = [
114
- "provider",
115
- "method",
116
- "dotPath",
117
- "payloadFile",
118
- "maxSpend",
119
- "ttl",
120
- ];
37
+ const required = ["dotPath", "payloadFile", "secretFile"];
121
38
  for (const key of required) {
122
39
  if (out[key] === undefined || out[key] === null) {
123
40
  throw new Error(`Missing required argument: --${key.replace(/([A-Z])/g, "-$1").toLowerCase()}`);
@@ -131,23 +48,20 @@ function printHelp() {
131
48
  "",
132
49
  "Usage:",
133
50
  " apicity-paygate otp mint \\",
134
- " --provider <provider> \\",
135
- " --method <HTTP method> \\",
51
+ " --secret-file <path> \\",
136
52
  " --dot-path <api.path> \\",
137
53
  " --payload-file <path> \\",
138
- " --max-spend <usd> \\",
139
- " --ttl <duration>",
54
+ " [--provider <provider>] \\",
55
+ " [--method <HTTP method>] \\",
56
+ " [--ttl <duration>]",
140
57
  "",
141
58
  "Options:",
142
- " --provider Provider name (e.g. kie, openai, xai)",
143
- " --method HTTP method (e.g. POST, GET)",
59
+ " --secret-file Path to a file containing the shared HMAC secret",
144
60
  " --dot-path API dot-path (e.g. api.v1.jobs.createTask)",
145
61
  " --payload-file Path to JSON request payload file",
146
- " --max-spend Maximum spend in USD",
147
- " --ttl Time-to-live: 10m, 1h, 30s, 1d",
148
- "",
149
- "Environment:",
150
- " APICITY_PAYGATE_PRIVATE_KEY_PATH Path to Ed25519 private key PEM",
62
+ " --provider Provider name (optional; resolved from the dot-path)",
63
+ " --method HTTP method (optional; resolved from the dot-path)",
64
+ " --ttl Time-to-live: 10m, 1h, 30s, 1d (default 10m)",
151
65
  ].join("\n"));
152
66
  }
153
67
  async function main() {
@@ -162,9 +76,15 @@ async function main() {
162
76
  process.exit(1);
163
77
  }
164
78
  const args = parseMintArgs(argv.slice(2));
165
- const payload = JSON.parse(readFileSync(args.payloadFile, "utf8"));
166
- const ttlSeconds = parseTtl(args.ttl);
167
- const otp = mintOtp(args.provider, args.method, args.dotPath, payload, args.maxSpend, ttlSeconds);
79
+ const secret = readFileSync(args.secretFile, "utf8").trim();
80
+ const request = JSON.parse(readFileSync(args.payloadFile, "utf8"));
81
+ const otp = mintOtp(secret, {
82
+ provider: args.provider,
83
+ method: args.method,
84
+ dotPath: args.dotPath,
85
+ request,
86
+ ttl: args.ttl,
87
+ });
168
88
  console.log(otp);
169
89
  }
170
90
  const __filename = fileURLToPath(import.meta.url);
@@ -1 +1 @@
1
- {"version":3,"file":"paygate-cli.js","sourceRoot":"","sources":["../../src/paygate-cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C;;GAEG;AACH,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI;SACR,QAAQ,CAAC,QAAQ,CAAC;SAClB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,uBAAuB,GAAG,sCAAsC,CACjE,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;IACrC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,GAAG;YACN,OAAO,KAAK,CAAC;QACf,KAAK,GAAG;YACN,OAAO,KAAK,GAAG,EAAE,CAAC;QACpB,KAAK,GAAG;YACN,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC;QACzB,KAAK,GAAG;YACN,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QAC9B;YACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CACrB,QAAgB,EAChB,MAAc,EACd,OAAe,EACf,OAAgC,EAChC,WAAmB,EACnB,UAAkB;IAElB,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC;IACpE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,+CAA+C;YAC7C,kDAAkD,CACrD,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAE3D,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,GAAG,GAAG,UAAU,CAAC;IAE7B,MAAM,UAAU,GAAG;QACjB,CAAC,EAAE,CAAU;QACb,GAAG;QACH,QAAQ;QACR,MAAM;QACN,OAAO;QACP,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC;QACnC,WAAW;QACX,GAAG;QACH,GAAG;KACJ,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAEzE,MAAM,SAAS,GAAG,IAAI,CACpB,IAAI,EACJ,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,EACnC,aAAa,CACd,CAAC;IAEF,MAAM,gBAAgB,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAEpD,OAAO,GAAG,cAAc,IAAI,gBAAgB,EAAE,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAI7B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,mBAAmB,CAAC,SAAS,EAAE;QAC/D,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QAClD,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;KACrD,CAAC,CAAC;IACH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC;AAChE,CAAC;AAWD,SAAS,aAAa,CAAC,IAAc;IACnC,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,YAAY;YAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC5C,IAAI,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC;YAAE,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aAC5D,IAAI,CAAC,KAAK,UAAU;YAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC7C,IAAI,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;aACvD,IAAI,CAAC,KAAK,YAAY;YAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAChD,IAAI,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC;YAAE,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aAC3D,IAAI,CAAC,KAAK,gBAAgB;YAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACxD,IAAI,CAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC;YAAE,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aACnE,IAAI,CAAC,KAAK,aAAa;YAAE,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CAAC,CAAC;aAC/D,IAAI,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC;YACnC,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;aACpC,IAAI,CAAC,KAAK,OAAO;YAAE,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACvC,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;aACjD,CAAC;YACJ,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAuB;QACnC,UAAU;QACV,QAAQ;QACR,SAAS;QACT,aAAa;QACb,UAAU;QACV,KAAK;KACN,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,gCAAgC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,CAC/E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,GAAe,CAAC;AACzB,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,KAAK,CACX;QACE,0DAA0D;QAC1D,EAAE;QACF,QAAQ;QACR,+BAA+B;QAC/B,8BAA8B;QAC9B,+BAA+B;QAC/B,8BAA8B;QAC9B,8BAA8B;QAC9B,0BAA0B;QAC1B,sBAAsB;QACtB,EAAE;QACF,UAAU;QACV,wDAAwD;QACxD,+CAA+C;QAC/C,6DAA6D;QAC7D,oDAAoD;QACpD,uCAAuC;QACvC,iDAAiD;QACjD,EAAE;QACF,cAAc;QACd,qEAAqE;KACtE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAClE,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACjE,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAGhE,CAAC;IACF,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,OAAO,CACjB,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,OAAO,EACZ,OAAO,EACP,IAAI,CAAC,QAAQ,EACb,UAAU,CACX,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACnB,CAAC;AACD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;IACnC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACnB,OAAO,CAAC,KAAK,CACX,0BAA0B,EAC1B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"paygate-cli.js","sourceRoot":"","sources":["../../src/paygate-cli.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  /**
2
- * OTP payload schema.
2
+ * OTP payload schema. An OTP commits to an exact
3
+ * `(provider, method, dotPath, requestHash)` tuple with an expiry, and is
4
+ * single-use via its `jti`.
3
5
  */
4
6
  export interface PayGateOtpPayload {
5
7
  v: 1;
@@ -8,7 +10,6 @@ export interface PayGateOtpPayload {
8
10
  method: string;
9
11
  dotPath: string;
10
12
  requestHash: `sha256:${string}`;
11
- maxSpendUsd: number;
12
13
  iat: number;
13
14
  exp: number;
14
15
  }
@@ -19,8 +20,29 @@ export interface PayGateApproval {
19
20
  otp: string;
20
21
  }
21
22
  /**
22
- * Error thrown when the pay gate blocks a request for any reason
23
- * other than spend bounds (which use SpendBoundError).
23
+ * Single-use replay ledger. The default is an in-process Set scoped to one
24
+ * provider instance (see `createReplayStore`). Pass a custom store for
25
+ * cross-process or persistent replay protection.
26
+ */
27
+ export interface ReplayStore {
28
+ has(jti: string): boolean;
29
+ add(jti: string): void;
30
+ }
31
+ /**
32
+ * Pay-gate configuration supplied by the code client at construction time
33
+ * (never by the autonomous caller). Holds the shared HMAC secret used to mint
34
+ * and verify OTPs. No environment variables, no key files.
35
+ */
36
+ export interface PayGateConfig {
37
+ /** Shared HMAC secret. The code client holds it; the AI never sees it. */
38
+ secret: string;
39
+ /** Replay ledger. Defaults to an in-process Set, per provider instance. */
40
+ replayStore?: ReplayStore;
41
+ /** Clock injection for testing. Defaults to `Date.now`. */
42
+ now?: () => number;
43
+ }
44
+ /**
45
+ * Error thrown when the pay gate blocks a request.
24
46
  */
25
47
  export declare class PayGateError extends Error {
26
48
  readonly provider: string;
@@ -29,6 +51,39 @@ export declare class PayGateError extends Error {
29
51
  readonly code: "paygate-not-configured" | "otp-missing" | "otp-malformed" | "otp-invalid-signature" | "otp-expired" | "otp-mismatched-request" | "otp-replayed";
30
52
  constructor(provider: string, method: string, dotPath: string, code: PayGateError["code"], message: string);
31
53
  }
54
+ /**
55
+ * Verification-only error codes — the subset of PayGateError codes that the
56
+ * pure `verifyOtp` can emit. The shell layer ("paygate-not-configured",
57
+ * "otp-missing") is handled separately in `dispatchWithPaidGate`.
58
+ */
59
+ export type VerifyFailureCode = "otp-malformed" | "otp-invalid-signature" | "otp-expired" | "otp-mismatched-request" | "otp-replayed";
60
+ /**
61
+ * Tagged-union result from the pure `verifyOtp` function.
62
+ */
63
+ export type VerifyResult = {
64
+ ok: true;
65
+ jti: string;
66
+ } | {
67
+ ok: false;
68
+ code: VerifyFailureCode;
69
+ message: string;
70
+ };
71
+ /**
72
+ * Pure inputs to `verifyOtp`. Every dependency is explicit — no env vars,
73
+ * no `Date.now()`, no filesystem reads.
74
+ */
75
+ export interface VerifyOtpInput {
76
+ nowSeconds: number;
77
+ secret: string;
78
+ expected: {
79
+ provider: string;
80
+ method: string;
81
+ dotPath: string;
82
+ };
83
+ payloadHash: `sha256:${string}`;
84
+ otp: string;
85
+ isJtiConsumed: (jti: string) => boolean;
86
+ }
32
87
  /**
33
88
  * Canonicalize a JSON value by sorting object keys recursively.
34
89
  * Arrays preserve order. Non-JSON values (undefined, functions, symbols,
@@ -39,6 +94,10 @@ export declare function canonicalizeJson(value: unknown): string;
39
94
  * Compute SHA-256 of canonical JSON, prefixed with `sha256:`.
40
95
  */
41
96
  export declare function canonicalHash(value: unknown): `sha256:${string}`;
97
+ /**
98
+ * Parse a TTL string like "10m", "1h", "30s", "1d" into seconds.
99
+ */
100
+ export declare function parseTtl(ttl: string): number;
42
101
  /**
43
102
  * Parse an OTP envelope: `<base64url(payloadJson)>.<base64url(signature)>`.
44
103
  * Returns the payload object and raw signature bytes.
@@ -48,33 +107,54 @@ export declare function parseOtp(otp: string): {
48
107
  signature: Buffer;
49
108
  };
50
109
  /**
51
- * Verify the Ed25519 signature of an OTP payload segment.
52
- * `publicKey` is the PEM string read from the public key file.
110
+ * Create an in-process, single-use replay store backed by a `Set`.
111
+ * Scoped to whatever holds the reference (typically one provider instance).
53
112
  */
54
- export declare function verifyOtpSignature(payloadSegmentBase64url: string, signature: Buffer, publicKeyPem: string): boolean;
113
+ export declare function createReplayStore(): ReplayStore;
55
114
  /**
56
- * Check whether a jti has already been consumed.
115
+ * The exact endpoint an OTP authorizes, plus the request it is bound to.
116
+ * `provider`/`method` may be omitted when `dotPath` uniquely identifies a
117
+ * single paid endpoint (it is resolved from `PAID_ENDPOINTS`).
118
+ */
119
+ export interface OtpCall {
120
+ provider?: string;
121
+ method?: string;
122
+ dotPath: string;
123
+ request: Record<string, unknown>;
124
+ /** Time-to-live as seconds or a string like "10m". Defaults to 10m. */
125
+ ttl?: string | number;
126
+ }
127
+ /**
128
+ * Mint an OTP for a specific request, signed with the shared HMAC secret.
57
129
  *
58
- * @param jti - The OTP jti to check
59
- * @param ledgerPath - Optional override path; defaults to XDG_STATE_HOME or ~/.local/state
130
+ * Pure and env-free: the secret is passed explicitly. The OTP binds to the
131
+ * exact request via its canonical hash, so changing any byte of the request
132
+ * invalidates the token.
60
133
  */
61
- export declare function isJtiConsumed(jti: string, ledgerPath?: string): boolean;
134
+ export declare function mintOtp(secret: string, call: OtpCall): string;
62
135
  /**
63
- * Append a jti to the replay ledger.
136
+ * Pure verification of an OTP against expected request context.
64
137
  *
65
- * @param jti - The OTP jti to consume
66
- * @param ledgerPath - Optional override path; defaults to XDG_STATE_HOME or ~/.local/state
138
+ * Returns a tagged-union `VerifyResult` never throws. The caller is
139
+ * responsible for converting `{ ok: false }` into a `PayGateError` at the
140
+ * boundary.
67
141
  */
68
- export declare function consumeJti(jti: string, ledgerPath?: string): void;
142
+ export declare function verifyOtp(input: VerifyOtpInput): VerifyResult;
69
143
  /**
70
144
  * Wrap a provider network dispatch with the OTP-based paid-endpoint gate.
71
145
  *
72
146
  * Free/unlisted endpoints return `dispatch()` immediately without OTP or
73
- * pay gate configuration.
147
+ * pay-gate configuration.
74
148
  *
75
149
  * Paid endpoints fail closed: if the pay gate is not configured, or the OTP
76
- * is missing, invalid, expired, replayed, mismatched, or the cost exceeds the
77
- * OTP's maxSpendUsd, the call throws before dispatch runs.
150
+ * is missing, invalid, expired, replayed, or mismatched, the call throws
151
+ * before dispatch runs. This is the "no bypass" guarantee a paid call cannot
152
+ * fire without a configured secret and a valid, human/code-client-minted OTP.
153
+ *
154
+ * The OTP jti is consumed BEFORE dispatch. If dispatch later fails for any
155
+ * reason, the jti remains consumed and the caller must mint a fresh OTP to
156
+ * retry. This is intentional — without it, a hostile caller could replay an
157
+ * OTP on every transient failure.
78
158
  */
79
- export declare function dispatchWithPaidGate<T>(provider: string, method: string, dotPath: string, payload: Record<string, unknown>, approval: PayGateApproval | undefined, dispatch: () => Promise<T>): Promise<T>;
159
+ export declare function dispatchWithPaidGate<T>(provider: string, method: string, dotPath: string, payload: Record<string, unknown>, approval: PayGateApproval | undefined, dispatch: () => Promise<T>, config?: PayGateConfig): Promise<T>;
80
160
  //# sourceMappingURL=paygate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paygate.d.ts","sourceRoot":"","sources":["../../src/paygate.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,CAAC,EAAE,CAAC,CAAC;IACL,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,UAAU,MAAM,EAAE,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EACT,wBAAwB,GACxB,aAAa,GACb,eAAe,GACf,uBAAuB,GACvB,aAAa,GACb,wBAAwB,GACxB,cAAc,CAAC;gBAGjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAC1B,OAAO,EAAE,MAAM;CASlB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAsCvD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,MAAM,EAAE,CAIhE;AAaD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;IACrC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB,CAyCA;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,uBAAuB,EAAE,MAAM,EAC/B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAIT;AAaD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,MAA4B,GACvC,OAAO,CAkBT;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,MAA4B,GACvC,IAAI,CAUN;AAuGD;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,CAAC,CAsEZ"}
1
+ {"version":3,"file":"paygate.d.ts","sourceRoot":"","sources":["../../src/paygate.ts"],"names":[],"mappings":"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"}