@apicity/cost 0.2.0-alpha.1 → 0.2.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.
- package/README.md +144 -147
- package/dist/src/cost.d.ts +1 -1
- package/dist/src/cost.d.ts.map +1 -1
- package/dist/src/cost.js +1 -1
- package/dist/src/cost.js.map +1 -1
- package/dist/src/index.d.ts +6 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/paid-endpoints.d.ts +0 -64
- package/dist/src/paid-endpoints.d.ts.map +1 -1
- package/dist/src/paid-endpoints.js +64 -113
- package/dist/src/paid-endpoints.js.map +1 -1
- package/dist/src/paygate-cli.d.ts +1 -17
- package/dist/src/paygate-cli.d.ts.map +1 -1
- package/dist/src/paygate-cli.js +23 -103
- package/dist/src/paygate-cli.js.map +1 -1
- package/dist/src/paygate.d.ts +99 -19
- package/dist/src/paygate.d.ts.map +1 -1
- package/dist/src/paygate.js +180 -122
- package/dist/src/paygate.js.map +1 -1
- package/dist/src/pricing/kie.d.ts.map +1 -1
- package/dist/src/pricing/kie.js +5 -0
- package/dist/src/pricing/kie.js.map +1 -1
- package/dist/src/slugs.d.ts +2 -0
- package/dist/src/slugs.d.ts.map +1 -1
- package/dist/src/slugs.js +2 -0
- package/dist/src/slugs.js.map +1 -1
- package/dist/src/with-paid-gate.d.ts +27 -0
- package/dist/src/with-paid-gate.d.ts.map +1 -0
- package/dist/src/with-paid-gate.js +91 -0
- package/dist/src/with-paid-gate.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
|
|
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.
|
|
@@ -16,6 +24,61 @@ export const PAID_ENDPOINTS = [
|
|
|
16
24
|
costNotes: "Billed per unit (seconds/images/songs) based on model and resolution",
|
|
17
25
|
},
|
|
18
26
|
},
|
|
27
|
+
{
|
|
28
|
+
key: {
|
|
29
|
+
provider: "xai",
|
|
30
|
+
method: "POST",
|
|
31
|
+
dotPath: "v1.images.generations",
|
|
32
|
+
},
|
|
33
|
+
info: {
|
|
34
|
+
reason: "Image generation task that incurs direct compute cost",
|
|
35
|
+
costNotes: "Billed per image based on model and resolution",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: {
|
|
40
|
+
provider: "xai",
|
|
41
|
+
method: "POST",
|
|
42
|
+
dotPath: "v1.images.edits",
|
|
43
|
+
},
|
|
44
|
+
info: {
|
|
45
|
+
reason: "Image edit task that incurs direct compute cost",
|
|
46
|
+
costNotes: "Billed per image edit based on model and resolution",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
key: {
|
|
51
|
+
provider: "xai",
|
|
52
|
+
method: "POST",
|
|
53
|
+
dotPath: "v1.videos.generations",
|
|
54
|
+
},
|
|
55
|
+
info: {
|
|
56
|
+
reason: "Video generation task that incurs direct compute cost",
|
|
57
|
+
costNotes: "Billed per video generation based on duration and model",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
key: {
|
|
62
|
+
provider: "xai",
|
|
63
|
+
method: "POST",
|
|
64
|
+
dotPath: "v1.videos.edits",
|
|
65
|
+
},
|
|
66
|
+
info: {
|
|
67
|
+
reason: "Video edit task that incurs direct compute cost",
|
|
68
|
+
costNotes: "Billed per video edit based on duration and model",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: {
|
|
73
|
+
provider: "xai",
|
|
74
|
+
method: "POST",
|
|
75
|
+
dotPath: "v1.videos.extensions",
|
|
76
|
+
},
|
|
77
|
+
info: {
|
|
78
|
+
reason: "Video extension task that incurs direct compute cost",
|
|
79
|
+
costNotes: "Billed per video extension based on duration and model",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
19
82
|
];
|
|
20
83
|
/**
|
|
21
84
|
* Look up a paid endpoint by exact key match.
|
|
@@ -42,116 +105,4 @@ export function lookupPaidEndpoint(provider, method, dotPath) {
|
|
|
42
105
|
export function isPaidEndpoint(provider, method, dotPath) {
|
|
43
106
|
return lookupPaidEndpoint(provider, method, dotPath) !== undefined;
|
|
44
107
|
}
|
|
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
108
|
//# sourceMappingURL=paid-endpoints.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paid-endpoints.js","sourceRoot":"","sources":["../../src/paid-endpoints.ts"],"names":[],"mappings":"AAAA
|
|
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;IACD;QACE,GAAG,EAAE;YACH,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,uBAAuB;SACjC;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,uDAAuD;YAC/D,SAAS,EAAE,gDAAgD;SAC5D;KACF;IACD;QACE,GAAG,EAAE;YACH,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,iBAAiB;SAC3B;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,iDAAiD;YACzD,SAAS,EAAE,qDAAqD;SACjE;KACF;IACD;QACE,GAAG,EAAE;YACH,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,uBAAuB;SACjC;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,uDAAuD;YAC/D,SAAS,EAAE,yDAAyD;SACrE;KACF;IACD;QACE,GAAG,EAAE;YACH,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,iBAAiB;SAC3B;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,iDAAiD;YACzD,SAAS,EAAE,mDAAmD;SAC/D;KACF;IACD;QACE,GAAG,EAAE;YACH,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,sBAAsB;SAChC;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,sDAAsD;YAC9D,SAAS,EAAE,wDAAwD;SACpE;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":"
|
|
1
|
+
{"version":3,"file":"paygate-cli.d.ts","sourceRoot":"","sources":["../../src/paygate-cli.ts"],"names":[],"mappings":""}
|
package/dist/src/paygate-cli.js
CHANGED
|
@@ -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 {
|
|
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 === "--
|
|
102
|
-
out.
|
|
103
|
-
else if (a.startsWith("--
|
|
104
|
-
out.
|
|
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
|
-
" --
|
|
135
|
-
" --method <HTTP method> \\",
|
|
51
|
+
" --secret-file <path> \\",
|
|
136
52
|
" --dot-path <api.path> \\",
|
|
137
53
|
" --payload-file <path> \\",
|
|
138
|
-
" --
|
|
139
|
-
" --
|
|
54
|
+
" [--provider <provider>] \\",
|
|
55
|
+
" [--method <HTTP method>] \\",
|
|
56
|
+
" [--ttl <duration>]",
|
|
140
57
|
"",
|
|
141
58
|
"Options:",
|
|
142
|
-
" --
|
|
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
|
-
" --
|
|
147
|
-
" --
|
|
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
|
|
166
|
-
const
|
|
167
|
-
const otp = mintOtp(
|
|
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,
|
|
1
|
+
{"version":3,"file":"paygate-cli.js","sourceRoot":"","sources":["../../src/paygate-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/src/paygate.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
23
|
-
*
|
|
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
|
-
*
|
|
52
|
-
*
|
|
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
|
|
113
|
+
export declare function createReplayStore(): ReplayStore;
|
|
55
114
|
/**
|
|
56
|
-
*
|
|
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
|
-
*
|
|
59
|
-
*
|
|
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
|
|
134
|
+
export declare function mintOtp(secret: string, call: OtpCall): string;
|
|
62
135
|
/**
|
|
63
|
-
*
|
|
136
|
+
* Pure verification of an OTP against expected request context.
|
|
64
137
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
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
|
|
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
|
|
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,
|
|
77
|
-
*
|
|
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
|
|
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":"
|
|
1
|
+
{"version":3,"file":"paygate.d.ts","sourceRoot":"","sources":["../../src/paygate.ts"],"names":[],"mappings":"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"}
|