@arnaudjnn/billing-tools 2.19.0 → 3.1.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.
- package/README.md +1 -1
- package/dist/adapters/workos-org.d.ts +23 -0
- package/dist/adapters/workos-org.d.ts.map +1 -1
- package/dist/adapters/workos-org.js +4 -2
- package/dist/adapters/workos-org.js.map +1 -1
- package/dist/bound-api.d.ts +173 -0
- package/dist/bound-api.d.ts.map +1 -0
- package/dist/bound-api.js +152 -0
- package/dist/bound-api.js.map +1 -0
- package/dist/cli/commands.js +25 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/create-billing.d.ts +128 -41
- package/dist/create-billing.d.ts.map +1 -1
- package/dist/create-billing.js +24 -14
- package/dist/create-billing.js.map +1 -1
- package/dist/doctor.d.ts +31 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +63 -0
- package/dist/doctor.js.map +1 -1
- package/dist/entries/agent-auth.d.ts +5 -0
- package/dist/entries/agent-auth.d.ts.map +1 -0
- package/dist/entries/agent-auth.js +17 -0
- package/dist/entries/agent-auth.js.map +1 -0
- package/dist/entries/plans.d.ts +4 -0
- package/dist/entries/plans.d.ts.map +1 -0
- package/dist/entries/plans.js +36 -0
- package/dist/entries/plans.js.map +1 -0
- package/dist/entries/routes.d.ts +5 -0
- package/dist/entries/routes.d.ts.map +1 -0
- package/dist/entries/routes.js +17 -0
- package/dist/entries/routes.js.map +1 -0
- package/dist/entries/tools.d.ts +6 -0
- package/dist/entries/tools.d.ts.map +1 -0
- package/dist/entries/tools.js +20 -0
- package/dist/entries/tools.js.map +1 -0
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -16
- package/dist/index.js.map +1 -1
- package/dist/metering.d.ts +4 -3
- package/dist/metering.d.ts.map +1 -1
- package/dist/metering.js.map +1 -1
- package/dist/plan-model.d.ts +58 -3
- package/dist/plan-model.d.ts.map +1 -1
- package/dist/plan-model.js +61 -4
- package/dist/plan-model.js.map +1 -1
- package/dist/plans.d.ts +2 -2
- package/dist/plans.d.ts.map +1 -1
- package/dist/plans.js +1 -1
- package/dist/plans.js.map +1 -1
- package/dist/tools/billing.d.ts +2 -1
- package/dist/tools/billing.d.ts.map +1 -1
- package/dist/tools/billing.js +185 -64
- package/dist/tools/billing.js.map +1 -1
- package/dist/tools/management.d.ts +2 -1
- package/dist/tools/management.d.ts.map +1 -1
- package/dist/tools/management.js +210 -187
- package/dist/tools/management.js.map +1 -1
- package/dist/tools/register.d.ts +13 -1
- package/dist/tools/register.d.ts.map +1 -1
- package/dist/tools/register.js +28 -6
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/subscription.d.ts +2 -1
- package/dist/tools/subscription.d.ts.map +1 -1
- package/dist/tools/subscription.js +115 -108
- package/dist/tools/subscription.js.map +1 -1
- package/dist/usage-ledger.d.ts +15 -37
- package/dist/usage-ledger.d.ts.map +1 -1
- package/dist/usage-ledger.js +24 -119
- package/dist/usage-ledger.js.map +1 -1
- package/dist/usage-scopes.d.ts +55 -0
- package/dist/usage-scopes.d.ts.map +1 -0
- package/dist/usage-scopes.js +284 -0
- package/dist/usage-scopes.js.map +1 -0
- package/dist/util/clearout.d.ts.map +1 -1
- package/dist/util/clearout.js +15 -3
- package/dist/util/clearout.js.map +1 -1
- package/package.json +21 -1
- package/dist/usage-counters.d.ts +0 -104
- package/dist/usage-counters.d.ts.map +0 -1
- package/dist/usage-counters.js +0 -214
- package/dist/usage-counters.js.map +0 -1
package/dist/usage-ledger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-ledger.js","sourceRoot":"","sources":["../src/usage-ledger.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"usage-ledger.js","sourceRoot":"","sources":["../src/usage-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type UsageLedger } from "./usage-ledger.js";
|
|
2
|
+
/** The scope a query is asking about. */
|
|
3
|
+
export declare function scopeOf(filter?: {
|
|
4
|
+
callerKind?: string;
|
|
5
|
+
callerId?: string;
|
|
6
|
+
}): string;
|
|
7
|
+
/** Every scope a single event counts toward. One event is counted once per
|
|
8
|
+
* scope, so an org-wide read and a per-member read both see it. */
|
|
9
|
+
export declare function scopesFor(event: {
|
|
10
|
+
caller?: {
|
|
11
|
+
kind?: string;
|
|
12
|
+
id?: string;
|
|
13
|
+
};
|
|
14
|
+
}): string[];
|
|
15
|
+
/** Default name of the Stripe Billing Meter the per-caller scopes report to.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately NOT the org meter's event name. They could share one — the scopes
|
|
18
|
+
* are separated by customer either way — but a separate meter keeps a shadow
|
|
19
|
+
* customer's usage out of anything the org meter is ever attached to for actual
|
|
20
|
+
* billing. One extra account-level object, not one per org. */
|
|
21
|
+
export declare const SCOPE_METER_EVENT = "billing_tools_scope_usage";
|
|
22
|
+
/** Marks a customer as a counter rather than someone who buys anything. Read by
|
|
23
|
+
* the doctor, which must not sample these when it checks customer currency. */
|
|
24
|
+
export declare const USAGE_SCOPE_KIND = "usage_counter";
|
|
25
|
+
/** Where the scope string is stored, so the customer can be found again from
|
|
26
|
+
* nothing but the scope. */
|
|
27
|
+
export declare const USAGE_SCOPE_KEY = "bt_usage_scope";
|
|
28
|
+
/** Forget resolved scope customers — for a test, or after deleting one. */
|
|
29
|
+
export declare function invalidateUsageScopes(): void;
|
|
30
|
+
export interface ScopeLedgerOptions {
|
|
31
|
+
/** Meter event name. Defaults to `SCOPE_METER_EVENT`. */
|
|
32
|
+
eventName?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Where WALLET-funded per-caller usage is read from. Defaults to the balance
|
|
35
|
+
* ledger, which is exact and has no lag because the debit IS the record.
|
|
36
|
+
*
|
|
37
|
+
* A seam only so a test can substitute one; there is no second right answer.
|
|
38
|
+
*/
|
|
39
|
+
wallet?: UsageLedger;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A per-CALLER `UsageLedger` backed entirely by Stripe.
|
|
43
|
+
*
|
|
44
|
+
* Built to be the `perCaller` leg of the composite, which is the only thing that
|
|
45
|
+
* ever asks it a caller-filtered question:
|
|
46
|
+
*
|
|
47
|
+
* ```ts
|
|
48
|
+
* stripeUsageLedger({ perCaller: stripeScopeUsageLedger() })
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* `covers.orgIncluded` is false because it does not answer org-wide windows — the
|
|
52
|
+
* composite's own meter leg does, on the org's real customer, unchanged.
|
|
53
|
+
*/
|
|
54
|
+
export declare function stripeScopeUsageLedger(opts?: ScopeLedgerOptions): UsageLedger;
|
|
55
|
+
//# sourceMappingURL=usage-scopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-scopes.d.ts","sourceRoot":"","sources":["../src/usage-scopes.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,WAAW,EAEjB,MAAM,mBAAmB,CAAC;AA+D3B,yCAAyC;AACzC,wBAAgB,OAAO,CAAC,MAAM,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAInF;AAED;oEACoE;AACpE,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,EAAE,CAKtF;AAED;;;;;gEAKgE;AAChE,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAE7D;gFACgF;AAChF,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD;6BAC6B;AAC7B,eAAO,MAAM,eAAe,mBAAmB,CAAC;AA+EhD,2EAA2E;AAC3E,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAoBD,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,kBAAuB,GAAG,WAAW,CAuFjF"}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { getStripe } from "./billing.js";
|
|
2
|
+
import { meterIdFor, stripeBalanceUsageLedger, } from "./usage-ledger.js";
|
|
3
|
+
// Per-member usage counted in Stripe, so the one window Stripe "cannot" count
|
|
4
|
+
// needs no database after all.
|
|
5
|
+
//
|
|
6
|
+
// ── The gap this closes ─────────────────────────────────────────────────────
|
|
7
|
+
//
|
|
8
|
+
// A window that is both INCLUDED and PER-MEMBER (`cap: per_seat`, a
|
|
9
|
+
// `scope: "caller"` rate limit) was the single reason this library ever asked for
|
|
10
|
+
// a store. A balance transaction carries the caller but only exists where money
|
|
11
|
+
// moved, and a meter summary sees every call but cannot be filtered by one.
|
|
12
|
+
//
|
|
13
|
+
// That second half is true of a meter's DIMENSIONS, and only of those. Measured
|
|
14
|
+
// against the API: `listEventSummaries` requires `customer` and offers no
|
|
15
|
+
// group-by; `/v1/billing/analytics/meter_usage` is not available; there is no read
|
|
16
|
+
// API for raw meter events; a zero-amount balance transaction is rejected outright
|
|
17
|
+
// ("The transaction's `amount` must be non-zero"); WorkOS has no atomic increment.
|
|
18
|
+
// So Stripe exposes exactly ONE grouping key for usage — the Customer.
|
|
19
|
+
//
|
|
20
|
+
// Which is enough, because a customer is just a key. A counter here is an opaque
|
|
21
|
+
// scope string (`org` / `k:<kind>` / `u:<memberId>`) derived identically on the
|
|
22
|
+
// write and read paths, and this file backs each one with a Stripe Customer.
|
|
23
|
+
//
|
|
24
|
+
// That is what let the SQL and Redis counter backends be deleted outright: they
|
|
25
|
+
// existed for this one question, and it now has a Stripe answer.
|
|
26
|
+
//
|
|
27
|
+
// ── Why this does not inherit the meter's lag where it would hurt ───────────
|
|
28
|
+
//
|
|
29
|
+
// Meter summaries lag aggregation by roughly 40–60 seconds (measured three times:
|
|
30
|
+
// 40 s, 48 s, 58 s). Against a monthly seat pack that is noise. Against a
|
|
31
|
+
// `600/hour` limit on an API key it is not — a script would burn most of the
|
|
32
|
+
// window before any of it became visible.
|
|
33
|
+
//
|
|
34
|
+
// It does not have to apply to both, because the two are funded differently and
|
|
35
|
+
// the funding is already on the event. `deductCredits` writes `caller_kind` /
|
|
36
|
+
// `caller_id` onto every debit, so WALLET-funded per-caller usage is already
|
|
37
|
+
// exact, per member, with no lag at all. Only INCLUDED usage needs the meter.
|
|
38
|
+
//
|
|
39
|
+
// wallet-funded, per caller → balance transactions (exact, no lag)
|
|
40
|
+
// included, per caller → this scope meter (exact, ~60 s lag)
|
|
41
|
+
//
|
|
42
|
+
// The two sets are disjoint by construction — an event is funded by exactly one of
|
|
43
|
+
// them — so `total` is a plain sum with no double count. It also reproduces the
|
|
44
|
+
// SQL behaviour exactly: `counterUsageLedger.record` counts every event whatever
|
|
45
|
+
// funded it, and so does the sum of these two legs.
|
|
46
|
+
//
|
|
47
|
+
// ── Why the org scope gets no customer of its own ───────────────────────────
|
|
48
|
+
//
|
|
49
|
+
// Because it already has one. `stripeUsageLedger` routes org-wide windows to the
|
|
50
|
+
// meter on the org's REAL customer, and that leg is untouched here. This file only
|
|
51
|
+
// ever writes and reads `k:` and `u:` scopes, which is what makes it additive: an
|
|
52
|
+
// existing deployment's org-wide numbers cannot move.
|
|
53
|
+
// ── The scope contract ──────────────────────────────────────────────────────
|
|
54
|
+
//
|
|
55
|
+
// WHOSE usage. Derived identically on the write and the read path, which is the
|
|
56
|
+
// whole contract: a `total` that computed a different scope string from the same
|
|
57
|
+
// caller would look up a customer nobody writes to, and report 0 for that member
|
|
58
|
+
// for ever — a failure that looks like generosity rather than a fault.
|
|
59
|
+
//
|
|
60
|
+
// `org` is every call in the workspace. A caller kind with no id is every caller
|
|
61
|
+
// of that kind (how a shared API seat is measured); with an id it is one member.
|
|
62
|
+
/** The scope a query is asking about. */
|
|
63
|
+
export function scopeOf(filter) {
|
|
64
|
+
if (filter?.callerId)
|
|
65
|
+
return `u:${filter.callerId}`;
|
|
66
|
+
if (filter?.callerKind)
|
|
67
|
+
return `k:${filter.callerKind}`;
|
|
68
|
+
return "org";
|
|
69
|
+
}
|
|
70
|
+
/** Every scope a single event counts toward. One event is counted once per
|
|
71
|
+
* scope, so an org-wide read and a per-member read both see it. */
|
|
72
|
+
export function scopesFor(event) {
|
|
73
|
+
const scopes = ["org"];
|
|
74
|
+
if (event.caller?.kind)
|
|
75
|
+
scopes.push(`k:${event.caller.kind}`);
|
|
76
|
+
if (event.caller?.id)
|
|
77
|
+
scopes.push(`u:${event.caller.id}`);
|
|
78
|
+
return scopes;
|
|
79
|
+
}
|
|
80
|
+
/** Default name of the Stripe Billing Meter the per-caller scopes report to.
|
|
81
|
+
*
|
|
82
|
+
* Deliberately NOT the org meter's event name. They could share one — the scopes
|
|
83
|
+
* are separated by customer either way — but a separate meter keeps a shadow
|
|
84
|
+
* customer's usage out of anything the org meter is ever attached to for actual
|
|
85
|
+
* billing. One extra account-level object, not one per org. */
|
|
86
|
+
export const SCOPE_METER_EVENT = "billing_tools_scope_usage";
|
|
87
|
+
/** Marks a customer as a counter rather than someone who buys anything. Read by
|
|
88
|
+
* the doctor, which must not sample these when it checks customer currency. */
|
|
89
|
+
export const USAGE_SCOPE_KIND = "usage_counter";
|
|
90
|
+
/** Where the scope string is stored, so the customer can be found again from
|
|
91
|
+
* nothing but the scope. */
|
|
92
|
+
export const USAGE_SCOPE_KEY = "bt_usage_scope";
|
|
93
|
+
// ── Resolving a scope to its customer ───────────────────────────────────────
|
|
94
|
+
//
|
|
95
|
+
// Derived, never allocated. The key IS the member id, so there is no free list, no
|
|
96
|
+
// collision, and no way for a recycled slot to inherit someone else's usage — the
|
|
97
|
+
// failure that ruled out the obvious alternative (a meter per seat index, with the
|
|
98
|
+
// org staying the customer).
|
|
99
|
+
//
|
|
100
|
+
// Two mechanisms, and they cover each other's blind spot exactly:
|
|
101
|
+
//
|
|
102
|
+
// • `customers.search` on the scope. Authoritative, but the search index is
|
|
103
|
+
// EVENTUALLY consistent — measured, a fresh customer was still missing after
|
|
104
|
+
// 20 s. So it cannot be the only lookup.
|
|
105
|
+
// • `customers.create` under an idempotency key derived from the scope. Measured:
|
|
106
|
+
// two concurrent creates and a later repeat all returned the same customer id.
|
|
107
|
+
// Stripe keeps a key for 24 h.
|
|
108
|
+
//
|
|
109
|
+
// Search is stale only for objects created minutes ago; the idempotency key covers
|
|
110
|
+
// the next 24 hours. There is no window where both miss, so two instances cannot
|
|
111
|
+
// end up writing the same member's usage to two different customers — which would
|
|
112
|
+
// under-report, and under-reporting reads as generosity rather than as a fault.
|
|
113
|
+
const customers = new Map();
|
|
114
|
+
const inflight = new Map();
|
|
115
|
+
const warned = new Set();
|
|
116
|
+
/** One line per process, not per call: this is on the hot path of every metered
|
|
117
|
+
* execution, and a broken key would otherwise print thousands of them. */
|
|
118
|
+
function complain(what, e) {
|
|
119
|
+
if (warned.has(what))
|
|
120
|
+
return;
|
|
121
|
+
warned.add(what);
|
|
122
|
+
console.error(`[billing] per-caller usage scope "${what}" could not be resolved: ${e.message}. ` +
|
|
123
|
+
"Included usage for that caller counts as 0, so a seat pack or a caller-scoped rate " +
|
|
124
|
+
"limit will not apply to them. Grant the Stripe key read/write access to customers.");
|
|
125
|
+
}
|
|
126
|
+
function customerForScope(orgId, scope) {
|
|
127
|
+
const key = `${orgId}|${scope}`;
|
|
128
|
+
const hit = customers.get(key);
|
|
129
|
+
if (hit)
|
|
130
|
+
return Promise.resolve(hit);
|
|
131
|
+
const pending = inflight.get(key);
|
|
132
|
+
if (pending)
|
|
133
|
+
return pending;
|
|
134
|
+
const resolve = (async () => {
|
|
135
|
+
try {
|
|
136
|
+
const stripe = getStripe();
|
|
137
|
+
const found = await stripe.customers.search({
|
|
138
|
+
query: `metadata['${USAGE_SCOPE_KEY}']:'${key}'`,
|
|
139
|
+
limit: 1,
|
|
140
|
+
});
|
|
141
|
+
const id = found.data[0]?.id ??
|
|
142
|
+
(await stripe.customers.create({
|
|
143
|
+
name: `usage ${key}`,
|
|
144
|
+
metadata: { [USAGE_SCOPE_KEY]: key, bt_kind: USAGE_SCOPE_KIND },
|
|
145
|
+
},
|
|
146
|
+
// Covers precisely the window in which the search above can be stale.
|
|
147
|
+
{ idempotencyKey: `bt-usage-scope-${key}` })).id;
|
|
148
|
+
customers.set(key, id);
|
|
149
|
+
return id;
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
// NOT remembered as a failure. Unlike a meter, this is one cheap lookup and
|
|
153
|
+
// the memo already prevents repeats on success; caching the miss would keep
|
|
154
|
+
// a member uncounted for the life of the process after one blip.
|
|
155
|
+
complain(key, e);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
})().finally(() => inflight.delete(key));
|
|
159
|
+
inflight.set(key, resolve);
|
|
160
|
+
return resolve;
|
|
161
|
+
}
|
|
162
|
+
/** Forget resolved scope customers — for a test, or after deleting one. */
|
|
163
|
+
export function invalidateUsageScopes() {
|
|
164
|
+
customers.clear();
|
|
165
|
+
warned.clear();
|
|
166
|
+
}
|
|
167
|
+
// ── The v2 meter event stream ───────────────────────────────────────────────
|
|
168
|
+
//
|
|
169
|
+
// Used instead of `billing.meterEvents.create` because it carries every scope in
|
|
170
|
+
// ONE request, and because it is faster: measured, three events in one v2 call is
|
|
171
|
+
// 128 ms against 249 ms for a single v1 event. Writing per-caller scopes therefore
|
|
172
|
+
// costs less than the org write this library already does, rather than adding to
|
|
173
|
+
// it.
|
|
174
|
+
let session = null;
|
|
175
|
+
async function streamToken() {
|
|
176
|
+
// Refreshed a minute early: a token that expires mid-flight would drop the write,
|
|
177
|
+
// and a dropped write is usage counted by nothing.
|
|
178
|
+
if (session && session.expiresAt - Date.now() > 60_000)
|
|
179
|
+
return session.token;
|
|
180
|
+
const s = await getStripe().v2.billing.meterEventSession.create();
|
|
181
|
+
session = { token: s.authentication_token, expiresAt: Date.parse(s.expires_at) };
|
|
182
|
+
return session.token;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* A per-CALLER `UsageLedger` backed entirely by Stripe.
|
|
186
|
+
*
|
|
187
|
+
* Built to be the `perCaller` leg of the composite, which is the only thing that
|
|
188
|
+
* ever asks it a caller-filtered question:
|
|
189
|
+
*
|
|
190
|
+
* ```ts
|
|
191
|
+
* stripeUsageLedger({ perCaller: stripeScopeUsageLedger() })
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* `covers.orgIncluded` is false because it does not answer org-wide windows — the
|
|
195
|
+
* composite's own meter leg does, on the org's real customer, unchanged.
|
|
196
|
+
*/
|
|
197
|
+
export function stripeScopeUsageLedger(opts = {}) {
|
|
198
|
+
const eventName = opts.eventName ?? SCOPE_METER_EVENT;
|
|
199
|
+
const wallet = opts.wallet ?? stripeBalanceUsageLedger();
|
|
200
|
+
return {
|
|
201
|
+
covers: { orgIncluded: false, callerIncluded: true },
|
|
202
|
+
async record(event) {
|
|
203
|
+
if (!event.cost)
|
|
204
|
+
return; // a free call moves no counter
|
|
205
|
+
// The wallet leg has already recorded this one: `deductCredits` wrote the
|
|
206
|
+
// balance transaction, carrying the caller. Reporting it here as well would
|
|
207
|
+
// make `total` count it twice.
|
|
208
|
+
if (event.funded === "wallet")
|
|
209
|
+
return;
|
|
210
|
+
// `org` is deliberately absent: the composite's meter leg already reported
|
|
211
|
+
// this event on the org's real customer.
|
|
212
|
+
const scopes = scopesFor(event).filter((s) => s !== "org");
|
|
213
|
+
if (!scopes.length)
|
|
214
|
+
return;
|
|
215
|
+
try {
|
|
216
|
+
// Resolved BEFORE reporting, like the meter itself: an event naming a
|
|
217
|
+
// customer that does not exist is rejected outright (verified), and this is
|
|
218
|
+
// the write side, whose loss cannot be recovered by a later read.
|
|
219
|
+
const meter = await meterIdFor(eventName, { displayName: "billing-tools per-caller usage" });
|
|
220
|
+
if (!meter)
|
|
221
|
+
return;
|
|
222
|
+
const ids = await Promise.all(scopes.map((s) => customerForScope(event.orgId, s)));
|
|
223
|
+
const at = new Date(event.at ?? Date.now()).toISOString();
|
|
224
|
+
const events = ids.flatMap((id, i) => id
|
|
225
|
+
? [
|
|
226
|
+
{
|
|
227
|
+
event_name: eventName,
|
|
228
|
+
// Makes a retried execution a no-op rather than a double count,
|
|
229
|
+
// per scope. Without a key every event is genuinely distinct, so
|
|
230
|
+
// a fresh id is the honest answer.
|
|
231
|
+
identifier: `${event.idempotencyKey ?? globalThis.crypto.randomUUID()}-${scopes[i]}`,
|
|
232
|
+
timestamp: at,
|
|
233
|
+
payload: { stripe_customer_id: id, value: String(event.cost) },
|
|
234
|
+
},
|
|
235
|
+
]
|
|
236
|
+
: []);
|
|
237
|
+
if (!events.length)
|
|
238
|
+
return;
|
|
239
|
+
await getStripe().v2.billing.meterEventStream.create({ events }, { apiKey: await streamToken() });
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
// Never throws, for the same reason `meterIdFor` does not: this runs inside
|
|
243
|
+
// every metered call, and a counting failure must not take the product down.
|
|
244
|
+
complain(`${event.orgId}|record`, e);
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
async total(query) {
|
|
248
|
+
const scope = scopeOf(query.filter);
|
|
249
|
+
// No caller filter means an org-wide window, which this leg does not answer.
|
|
250
|
+
// The composite never routes one here; if something else does, the wallet
|
|
251
|
+
// figure alone is the honest answer rather than a wrong one.
|
|
252
|
+
if (scope === "org")
|
|
253
|
+
return wallet.total(query);
|
|
254
|
+
const [paid, included] = await Promise.all([
|
|
255
|
+
wallet.total(query),
|
|
256
|
+
(async () => {
|
|
257
|
+
try {
|
|
258
|
+
const meter = await meterIdFor(eventName, { create: false });
|
|
259
|
+
if (!meter)
|
|
260
|
+
return 0;
|
|
261
|
+
const id = await customerForScope(query.orgId, scope);
|
|
262
|
+
if (!id)
|
|
263
|
+
return 0;
|
|
264
|
+
// Seconds, and Stripe requires the window on minute boundaries.
|
|
265
|
+
const floorMinute = (ms) => Math.floor(ms / 60_000) * 60;
|
|
266
|
+
const summaries = await getStripe().billing.meters.listEventSummaries(meter, {
|
|
267
|
+
customer: id,
|
|
268
|
+
start_time: floorMinute(query.start),
|
|
269
|
+
end_time: floorMinute(query.end ?? Date.now()),
|
|
270
|
+
limit: 100,
|
|
271
|
+
});
|
|
272
|
+
return summaries.data.reduce((sum, s) => sum + s.aggregated_value, 0);
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
complain(`${query.orgId}|${scope}`, e);
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
})(),
|
|
279
|
+
]);
|
|
280
|
+
return paid + included;
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=usage-scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-scopes.js","sourceRoot":"","sources":["../src/usage-scopes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clearout.d.ts","sourceRoot":"","sources":["../../src/util/clearout.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"clearout.d.ts","sourceRoot":"","sources":["../../src/util/clearout.ts"],"names":[],"mappings":"AAcA,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAiBnD"}
|
package/dist/util/clearout.js
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
// Best-effort company enrichment from a domain (name + logo)
|
|
2
|
-
//
|
|
1
|
+
// Best-effort company enrichment from a domain (name + logo).
|
|
2
|
+
//
|
|
3
|
+
// **Opt-in.** Pass it to the adapter explicitly — `new WorkOSOrgAdapter({
|
|
4
|
+
// enrichOrg: lookupCompany })` — because it sends the domain to a third party
|
|
5
|
+
// (api.clearout.io). It used to be wired in unconditionally, so every deployment
|
|
6
|
+
// using that adapter forwarded its customers' email domains to an unrelated
|
|
7
|
+
// service with no env var to notice it by and no way to turn it off. Naming the
|
|
8
|
+
// call at the call site is the whole fix.
|
|
9
|
+
//
|
|
10
|
+
// Never throws AND never hangs: it sits on the path that creates a workspace, so a
|
|
11
|
+
// third party having a bad day must cost a nicer org name, not the signup. "Never
|
|
12
|
+
// throws" alone did not cover that — an unbounded `fetch` fails by not returning.
|
|
13
|
+
const TIMEOUT_MS = 3_000;
|
|
3
14
|
export async function lookupCompany(domain) {
|
|
4
15
|
try {
|
|
5
|
-
const res = await fetch(`https://api.clearout.io/public/companies/autocomplete?query=${encodeURIComponent(domain)}
|
|
16
|
+
const res = await fetch(`https://api.clearout.io/public/companies/autocomplete?query=${encodeURIComponent(domain)}`, { signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
6
17
|
if (!res.ok)
|
|
7
18
|
return null;
|
|
8
19
|
const data = (await res.json());
|
|
@@ -12,6 +23,7 @@ export async function lookupCompany(domain) {
|
|
|
12
23
|
return { name: match.name, logoUrl: match.logo_url };
|
|
13
24
|
}
|
|
14
25
|
catch {
|
|
26
|
+
// Includes the timeout: an AbortError lands here like any other failure.
|
|
15
27
|
return null;
|
|
16
28
|
}
|
|
17
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clearout.js","sourceRoot":"","sources":["../../src/util/clearout.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,
|
|
1
|
+
{"version":3,"file":"clearout.js","sourceRoot":"","sources":["../../src/util/clearout.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,0EAA0E;AAC1E,8EAA8E;AAC9E,iFAAiF;AACjF,4EAA4E;AAC5E,gFAAgF;AAChF,0CAA0C;AAC1C,EAAE;AACF,mFAAmF;AACnF,kFAAkF;AAClF,kFAAkF;AAClF,MAAM,UAAU,GAAG,KAAK,CAAC;AAEzB,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,+DAA+D,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAC3F,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAC5C,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAE7B,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QACtF,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnaudjnn/billing-tools",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "The get-paid engine for Stripe + WorkOS apps, for humans and AI agents. Drop-in API-key auth, credit + subscription billing, auth.md agent registration, and MPP machine payments, as MCP tools, a REST API, and a CLI. Framework-agnostic, storage-pluggable.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Arnaud Jeannin",
|
|
@@ -40,6 +40,26 @@
|
|
|
40
40
|
"import": "./dist/adapters/workos-org.js",
|
|
41
41
|
"default": "./dist/adapters/workos-org.js"
|
|
42
42
|
},
|
|
43
|
+
"./plans": {
|
|
44
|
+
"types": "./dist/entries/plans.d.ts",
|
|
45
|
+
"import": "./dist/entries/plans.js",
|
|
46
|
+
"default": "./dist/entries/plans.js"
|
|
47
|
+
},
|
|
48
|
+
"./tools": {
|
|
49
|
+
"types": "./dist/entries/tools.d.ts",
|
|
50
|
+
"import": "./dist/entries/tools.js",
|
|
51
|
+
"default": "./dist/entries/tools.js"
|
|
52
|
+
},
|
|
53
|
+
"./routes": {
|
|
54
|
+
"types": "./dist/entries/routes.d.ts",
|
|
55
|
+
"import": "./dist/entries/routes.js",
|
|
56
|
+
"default": "./dist/entries/routes.js"
|
|
57
|
+
},
|
|
58
|
+
"./agent-auth": {
|
|
59
|
+
"types": "./dist/entries/agent-auth.d.ts",
|
|
60
|
+
"import": "./dist/entries/agent-auth.js",
|
|
61
|
+
"default": "./dist/entries/agent-auth.js"
|
|
62
|
+
},
|
|
43
63
|
"./cli": {
|
|
44
64
|
"types": "./dist/cli/index.d.ts",
|
|
45
65
|
"import": "./dist/cli/index.js",
|
package/dist/usage-counters.d.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import type { UsageEvent, UsageLedger } from "./usage-ledger.js";
|
|
2
|
-
/** Milliseconds in the bucket grain. The tightest window a plan can declare. */
|
|
3
|
-
export declare const BUCKET_MS = 3600000;
|
|
4
|
-
/** The bucket an instant falls in: hours since the epoch, UTC-aligned. */
|
|
5
|
-
export declare const bucketOf: (atMs: number) => number;
|
|
6
|
-
/**
|
|
7
|
-
* WHOSE counter. Derived identically on the write and read paths, which is the
|
|
8
|
-
* whole contract — a `total` that computed a different scope string from the same
|
|
9
|
-
* caller would read a counter nobody writes, and report 0 forever.
|
|
10
|
-
*
|
|
11
|
-
* `org` is every call in the workspace. A caller kind with no id is every caller
|
|
12
|
-
* of that kind (how a shared API seat is measured); with an id it is one member.
|
|
13
|
-
*/
|
|
14
|
-
export declare function scopeOf(filter?: {
|
|
15
|
-
callerKind?: string;
|
|
16
|
-
callerId?: string;
|
|
17
|
-
}): string;
|
|
18
|
-
/** Every scope a single event counts toward. An event is counted once per scope,
|
|
19
|
-
* so an org-wide read and a per-member read both see it. */
|
|
20
|
-
export declare function scopesFor(event: UsageEvent): string[];
|
|
21
|
-
/** `org|scope|bucket` — derivable from either side, so no index is needed to find
|
|
22
|
-
* a counter and a KV store works as well as a table. */
|
|
23
|
-
export declare const counterKey: (orgId: string, scope: string, bucket: number) => string;
|
|
24
|
-
/**
|
|
25
|
-
* The store. Two operations, both of which every candidate backend already has.
|
|
26
|
-
*
|
|
27
|
-
* `add` must be ATOMIC per key — an increment, not a read-then-write. That is the
|
|
28
|
-
* whole reason this can live in Redis or Postgres but not in Stripe or WorkOS
|
|
29
|
-
* metadata: neither has an increment, so two concurrent metered calls would both
|
|
30
|
-
* read `n`, both write `n+1`, and one call would vanish.
|
|
31
|
-
*/
|
|
32
|
-
export interface UsageCounterStore {
|
|
33
|
-
/** Add `amount` to every key. `expiresAtMs` is a hint for stores with TTL; a
|
|
34
|
-
* table can ignore it and sweep on `bucket` instead. */
|
|
35
|
-
add(keys: string[], amount: number, expiresAtMs: number | null): Promise<void>;
|
|
36
|
-
/** Sum the given keys. Missing keys count as 0. ONE round trip. */
|
|
37
|
-
sum(keys: string[]): Promise<number>;
|
|
38
|
-
}
|
|
39
|
-
export interface CounterLedgerOptions {
|
|
40
|
-
/** How long a bucket is kept, for stores that expire. Default 400 days, which
|
|
41
|
-
* covers an annual window plus slack. */
|
|
42
|
-
retentionMs?: number;
|
|
43
|
-
/** Cap on keys per read, so a pathological window cannot issue an unbounded
|
|
44
|
-
* fetch. Default 8 784 (a leap year of hours). A window wider than this reads
|
|
45
|
-
* the most RECENT slice, which under-reports — the direction that refuses
|
|
46
|
-
* early rather than granting what nobody paid for. */
|
|
47
|
-
maxKeysPerRead?: number;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* A `UsageLedger` backed by counters. Counts EVERYTHING — included and
|
|
51
|
-
* wallet-funded, org-wide and per member — which is what `covers` declares.
|
|
52
|
-
*/
|
|
53
|
-
export declare function counterUsageLedger(store: UsageCounterStore, opts?: CounterLedgerOptions): UsageLedger;
|
|
54
|
-
/** The table + the one index its read uses. Idempotent, so it is safe to run from
|
|
55
|
-
* a migration on every deploy. Bounded by (orgs × scopes × hours kept), not by
|
|
56
|
-
* traffic — the reason to prefer it over `usage_events` at volume. */
|
|
57
|
-
export declare const USAGE_COUNTERS = "\nCREATE TABLE IF NOT EXISTS usage_counters (\n key text PRIMARY KEY,\n used bigint NOT NULL,\n -- Kept for bulk expiry; the read never filters on it.\n stale timestamptz\n);\nCREATE INDEX IF NOT EXISTS usage_counters_stale_idx ON usage_counters (stale);\n";
|
|
58
|
-
/** The one method this needs from a driver — the same duck type
|
|
59
|
-
* `postgresUsageLedger` uses, so `pg`'s Pool and Neon's driver both satisfy it. */
|
|
60
|
-
export interface SqlCounterClient {
|
|
61
|
-
query<R = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<{
|
|
62
|
-
rows: R[];
|
|
63
|
-
}>;
|
|
64
|
-
}
|
|
65
|
-
/** @deprecated Renamed to `USAGE_COUNTERS`, alongside `USAGE_EVENTS`. */
|
|
66
|
-
export declare const USAGE_COUNTERS_DDL = "\nCREATE TABLE IF NOT EXISTS usage_counters (\n key text PRIMARY KEY,\n used bigint NOT NULL,\n -- Kept for bulk expiry; the read never filters on it.\n stale timestamptz\n);\nCREATE INDEX IF NOT EXISTS usage_counters_stale_idx ON usage_counters (stale);\n";
|
|
67
|
-
export declare function ensureUsageCountersTable(client: SqlCounterClient): Promise<void>;
|
|
68
|
-
/**
|
|
69
|
-
* Counters in Postgres: one upsert per scope on write, one `SUM` over a primary-key
|
|
70
|
-
* lookup on read.
|
|
71
|
-
*
|
|
72
|
-
* `used = usage_counters.used + excluded.used` is the atomic increment — the row
|
|
73
|
-
* lock is held for the statement, so concurrent calls serialise instead of losing
|
|
74
|
-
* one another's writes.
|
|
75
|
-
*/
|
|
76
|
-
export declare function sqlUsageCounters(client: SqlCounterClient): UsageCounterStore;
|
|
77
|
-
/** Delete expired buckets. Call it from a cron; nothing depends on it running —
|
|
78
|
-
* a stale bucket is simply never read once its window has passed. */
|
|
79
|
-
export declare function pruneUsageCounters(client: SqlCounterClient, now?: number): Promise<void>;
|
|
80
|
-
/**
|
|
81
|
-
* The minimum a Redis-compatible client has to expose. Satisfied by `redis`,
|
|
82
|
-
* `ioredis`, `@upstash/redis` and Vercel KV — which is the point: a deployment
|
|
83
|
-
* with a KV and no SQL can still meter per member.
|
|
84
|
-
*/
|
|
85
|
-
export interface RedisCounterClient {
|
|
86
|
-
incrby(key: string, amount: number): Promise<unknown>;
|
|
87
|
-
pexpireat?(key: string, atMs: number): Promise<unknown>;
|
|
88
|
-
mget(keys: string[]): Promise<Array<string | number | null>>;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Counters in Redis: `INCRBY` per scope, one `MGET` per read.
|
|
92
|
-
*
|
|
93
|
-
* The expiry is set on every write rather than only on create. `PEXPIREAT` is
|
|
94
|
-
* idempotent and one round trip, whereas checking first is two and races — and a
|
|
95
|
-
* bucket that lost its expiry is a leak that only shows up as memory months later.
|
|
96
|
-
*/
|
|
97
|
-
export declare function redisUsageCounters(client: RedisCounterClient): UsageCounterStore;
|
|
98
|
-
/** In-memory counters, for tests and single-process development. Not for a
|
|
99
|
-
* deployment with more than one instance: each would count its own share, and the
|
|
100
|
-
* gate would allow the sum of every instance's window. */
|
|
101
|
-
export declare function memoryUsageCounters(): UsageCounterStore & {
|
|
102
|
-
readonly map: Map<string, number>;
|
|
103
|
-
};
|
|
104
|
-
//# sourceMappingURL=usage-counters.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usage-counters.d.ts","sourceRoot":"","sources":["../src/usage-counters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAc,MAAM,mBAAmB,CAAC;AA2C7E,gFAAgF;AAChF,eAAO,MAAM,SAAS,UAAY,CAAC;AAEnC,0EAA0E;AAC1E,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,KAAG,MAAsC,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,MAAM,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAInF;AAED;6DAC6D;AAC7D,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAKrD;AAED;yDACyD;AACzD,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,MAC3C,CAAC;AAEhC;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC;6DACyD;IACzD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,mEAAmE;IACnE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,oBAAoB;IACnC;8CAC0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;2DAGuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,iBAAiB,EACxB,IAAI,GAAE,oBAAyB,GAC9B,WAAW,CAqCb;AAID;;uEAEuE;AACvE,eAAO,MAAM,cAAc,4QAQ1B,CAAC;AAEF;oFACoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CAC7F;AAED,yEAAyE;AACzE,eAAO,MAAM,kBAAkB,4QAAiB,CAAC;AAEjD,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CA2B5E;AAED;sEACsE;AACtE,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,EACxB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,SAAS,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC9D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,iBAAiB,CAgBhF;AAED;;2DAE2D;AAC3D,wBAAgB,mBAAmB,IAAI,iBAAiB,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAa/F"}
|