@forgezero/providers 0.1.23 → 0.1.24

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 CHANGED
@@ -40,12 +40,11 @@ These are supported consumer entry points, not every internal module shipped for
40
40
  | @forgezero/providers/database | ArangoDB in the registry for credential rotation and health — with failover off by default. | portable | [Reference + usage](#forgezero-providers-database) |
41
41
  | @forgezero/providers/http | Outbound HTTP with a per-host weight budget reserved before the call and settled from the response. | portable | [Reference + usage](#forgezero-providers-http) |
42
42
  | @forgezero/providers/pool | Which outbound address a request leaves by, sticky per key, over the same budget as everything else. | portable | [Reference + usage](#forgezero-providers-pool) |
43
- | @forgezero/providers/chain | An EVM node behind the same failover as any other service: read logs, broadcast, and never stop scanning because one endpoint rate-limited. | portable | [Reference + usage](#forgezero-providers-chain) |
44
- | @forgezero/providers/binance | Binance behind the venue adapter: three hosts, one weight budget, signed over the exact string that is sent. | portable | [Reference + usage](#forgezero-providers-binance) |
45
43
  | @forgezero/providers/storage | S3-compatible object storage, SigV4 signed with Web Crypto and no vendor SDK. | portable | [Reference + usage](#forgezero-providers-storage) |
46
44
  | @forgezero/providers/translation | Google AI Studio translation with strict batch alignment and classified quota failures. | portable | [Reference + usage](#forgezero-providers-translation) |
47
45
  | @forgezero/providers/realtime | Cloudflare KV node-directory and Durable Object fan-out clients for project-defined realtime services. | portable | [Reference + usage](#forgezero-providers-realtime) |
48
46
  | @forgezero/providers/git | Versioned Git Connect contracts for accounts, repositories, branches, webhooks and short-lived clone credentials; GitHub, GitLab and private forges attach without changing the service. | portable | [Reference + usage](#forgezero-providers-git) |
47
+ | @forgezero/providers/billing | Versioned hosted-payment contracts for Stripe, PayPal and Razorpay; only opaque provider references cross the boundary. | portable | [Reference + usage](#forgezero-providers-billing) |
49
48
 
50
49
  ## Commands
51
50
 
@@ -259,52 +258,6 @@ import {
259
258
  export const selectedCapability = PoolEmpty;
260
259
  ```
261
260
 
262
- <a id="forgezero-providers-chain"></a>
263
- ## @forgezero/providers/chain
264
-
265
- An EVM node behind the same failover as any other service: read logs, broadcast, and never stop scanning because one endpoint rate-limited. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
266
-
267
- ```text
268
- import {
269
- evmRpc,
270
- } from '@forgezero/providers/chain';
271
- ```
272
-
273
- ## @forgezero/providers/chain — Use this entry point
274
-
275
- This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
276
-
277
- ```text
278
- import {
279
- evmRpc,
280
- } from '@forgezero/providers/chain';
281
-
282
- export const selectedCapability = evmRpc;
283
- ```
284
-
285
- <a id="forgezero-providers-binance"></a>
286
- ## @forgezero/providers/binance
287
-
288
- Binance behind the venue adapter: three hosts, one weight budget, signed over the exact string that is sent. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
289
-
290
- ```text
291
- import {
292
- binanceSymbol,
293
- } from '@forgezero/providers/binance';
294
- ```
295
-
296
- ## @forgezero/providers/binance — Use this entry point
297
-
298
- This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
299
-
300
- ```text
301
- import {
302
- binanceSymbol,
303
- } from '@forgezero/providers/binance';
304
-
305
- export const selectedCapability = binanceSymbol;
306
- ```
307
-
308
261
  <a id="forgezero-providers-storage"></a>
309
262
  ## @forgezero/providers/storage
310
263
 
@@ -381,7 +334,7 @@ Versioned Git Connect contracts for accounts, repositories, branches, webhooks a
381
334
 
382
335
  ```text
383
336
  import {
384
- defineGitConnectProvider,
337
+ defineGitHubProvider,
385
338
  } from '@forgezero/providers/git';
386
339
  ```
387
340
 
@@ -391,10 +344,47 @@ This minimal executable use imports one concrete value from this exact entry poi
391
344
 
392
345
  ```text
393
346
  import {
394
- defineGitConnectProvider,
347
+ defineGitHubProvider,
395
348
  } from '@forgezero/providers/git';
396
349
 
397
- export const selectedCapability = defineGitConnectProvider;
350
+ export const selectedCapability = defineGitHubProvider;
351
+ ```
352
+
353
+ <a id="forgezero-providers-billing"></a>
354
+ ## @forgezero/providers/billing
355
+
356
+ Versioned hosted-payment contracts for Stripe, PayPal and Razorpay; only opaque provider references cross the boundary. This is a supported entry point. Import only the named values used by the adjacent task example; the declaration file remains the complete API reference.
357
+
358
+ ```text
359
+ import {
360
+ PAYMENT_PROVIDER_KEYS,
361
+ } from '@forgezero/providers/billing';
362
+ ```
363
+
364
+ ## @forgezero/providers/billing — Bind a reviewed payment-provider API version
365
+
366
+ ForgeZero receives only hosted setup URLs and opaque provider references. The concrete HTTP driver and its Vault-backed credentials remain at the host boundary.
367
+
368
+ ```text
369
+ import {
370
+ paymentProviderAdapter,
371
+ type PaymentProviderDriver,
372
+ } from '@forgezero/providers/billing';
373
+
374
+ declare const stripeDriver: PaymentProviderDriver;
375
+ const stripe = paymentProviderAdapter({
376
+ key: 'stripe:v1',
377
+ providerApiVersion: '2026-08',
378
+ driver: stripeDriver
379
+ });
380
+
381
+ const setup = await stripe.createHostedSetup({
382
+ tenantKey: 'tenant_123',
383
+ returnUrl: 'https://app.example.com/billing/return',
384
+ cancelUrl: 'https://app.example.com/billing',
385
+ idempotencyKey: crypto.randomUUID()
386
+ });
387
+ location.assign(setup.hostedUrl);
398
388
  ```
399
389
 
400
390
  ## Built-in provider capabilities
@@ -402,14 +392,20 @@ export const selectedCapability = defineGitConnectProvider;
402
392
  A provider owns versioned capabilities; it does not own a service. A service method attaches an exact provider, method and version in an ordered array. Current, legacy and deprecated branches can coexist; retired branches never run.
403
393
 
404
394
  ```text
405
- github-app
406
- - listAccounts
395
+ github
396
+ - beginUserAuthorization
397
+ - completeUserAuthorization
398
+ - readVerifiedIdentity
399
+ - refreshUserGrant
400
+ - revokeUserGrant
401
+ - beginInstallation
402
+ - completeInstallation
403
+ - listInstallations
407
404
  - listRepositories
408
405
  - listBranches
409
- - ensureWebhook
410
- - cloneCredential
411
- evm-rpc
412
- - request
406
+ - mintCloneCredential
407
+ - verifyWebhook
408
+ - disconnectInstallation
413
409
  jetemail
414
410
  - send
415
411
  - sendBatch
@@ -425,19 +421,27 @@ google-ai-studio
425
421
  - translate
426
422
  ```
427
423
 
428
- ## GitHub App (github-app)
424
+ ## GitHub App (github)
429
425
 
430
- Import: @forgezero/providers/git. Each method below is a provider capability that a service attaches by exact version. User OAuth verifies an email and is discarded before the mandatory passkey. App installation credentials are minted on demand, limited to one selected repository, and expire rather than being stored. GitLab or a private forge implements the same Git Connect service without pretending to be GitHub.
426
+ Import: @forgezero/providers/git. Each method below is a provider capability that a service attaches by exact version. The OAuth Server projection verifies an email and revokes the temporary user grant before ForgeZero creates its own session. The Git Connect projection mints repository-scoped installation credentials on demand and never persists them. GitLab or a private forge can implement the same Git Connect service without changing pipelines or Agents.
431
427
 
432
428
  ```text
433
429
  importPath: '@forgezero/providers/git'
434
- providerId: 'github-app'
430
+ providerId: 'github'
435
431
  methods:
436
- - listAccounts
432
+ - beginUserAuthorization
433
+ - completeUserAuthorization
434
+ - readVerifiedIdentity
435
+ - refreshUserGrant
436
+ - revokeUserGrant
437
+ - beginInstallation
438
+ - completeInstallation
439
+ - listInstallations
437
440
  - listRepositories
438
441
  - listBranches
439
- - ensureWebhook
440
- - cloneCredential
442
+ - mintCloneCredential
443
+ - verifyWebhook
444
+ - disconnectInstallation
441
445
  credentials:
442
446
  - clientSecret
443
447
  - privateKey
@@ -448,24 +452,6 @@ config:
448
452
  - slug
449
453
  ```
450
454
 
451
- ## EVM JSON-RPC node (evm-rpc)
452
-
453
- Import: @forgezero/providers/chain. Each method below is a provider capability that a service attaches by exact version. Several endpoints per chain is the normal case, not a luxury: public RPC is rate-limited and paid gateways have outages, and a scanner that stops when one is down stops crediting deposits while the money sits on the chain. "Already known" and "nonce too low" are TERMINAL — the transaction is already in flight, so rebroadcasting through another node is how a sweep gets sent twice.
454
-
455
- ```text
456
- importPath: '@forgezero/providers/chain'
457
- providerId: 'evm-rpc'
458
- methods:
459
- - request
460
- credentials:
461
- - url
462
- - bearer
463
- config:
464
- - chainId
465
- - maxLogRange
466
- - timeoutMs
467
- ```
468
-
469
455
  ## JetEmail (jetemail)
470
456
 
471
457
  Import: @forgezero/providers/email. Each method below is a provider capability that a service attaches by exact version. A 401 is RETRYABLE at the loop level — that key is bad, the next provider's may not be. Treating any 4xx as fatal is what loses the fallback.
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Versioned hosted-payment provider boundary.
3
+ *
4
+ * ForgeZero never accepts payment credentials. A browser is redirected to (or
5
+ * embeds) the provider-hosted setup URL and only opaque provider references
6
+ * return. Concrete HTTP/auth implementations are injected by the API so this
7
+ * package contains no platform credential source and no vendor secret.
8
+ */
9
+ import { type FailureKind, type InvokeContext, type ProviderDefinition } from './index';
10
+ export declare const PAYMENT_PROVIDER_KEYS: readonly ["stripe:v1", "paypal:v1", "razorpay:v1"];
11
+ export type PaymentProviderKey = (typeof PAYMENT_PROVIDER_KEYS)[number];
12
+ /**
13
+ * Persisted operator configuration for the three supported billing providers.
14
+ * Secrets are deliberately separate write-only fields; the API stores them in
15
+ * the hidden operational Vault and returns only `hasSecret` to administrators.
16
+ */
17
+ export declare const paymentProviderDefinitions: readonly [{
18
+ readonly id: "stripe";
19
+ readonly label: "Stripe";
20
+ readonly multiInstance: true;
21
+ readonly config: {
22
+ readonly type: "object";
23
+ readonly properties: {
24
+ readonly providerApiVersion: {
25
+ readonly type: "string";
26
+ readonly minLength: 4;
27
+ readonly maxLength: 64;
28
+ };
29
+ readonly mode: {
30
+ readonly type: "string";
31
+ readonly enum: readonly ["test", "live"];
32
+ };
33
+ };
34
+ readonly required: readonly ["providerApiVersion", "mode"];
35
+ readonly additionalProperties: false;
36
+ };
37
+ readonly credentials: {
38
+ readonly type: "object";
39
+ readonly properties: {
40
+ readonly secretKey: {
41
+ readonly type: "string";
42
+ readonly minLength: 16;
43
+ readonly maxLength: 512;
44
+ readonly writeOnly: true;
45
+ };
46
+ readonly webhookSecret: {
47
+ readonly type: "string";
48
+ readonly minLength: 16;
49
+ readonly maxLength: 512;
50
+ readonly writeOnly: true;
51
+ };
52
+ };
53
+ readonly required: readonly ["secretKey", "webhookSecret"];
54
+ readonly additionalProperties: false;
55
+ };
56
+ readonly methods: {};
57
+ }, {
58
+ readonly id: "paypal";
59
+ readonly label: "PayPal";
60
+ readonly multiInstance: true;
61
+ readonly config: {
62
+ readonly type: "object";
63
+ readonly properties: {
64
+ readonly providerApiVersion: {
65
+ readonly type: "string";
66
+ readonly minLength: 2;
67
+ readonly maxLength: 64;
68
+ };
69
+ readonly environment: {
70
+ readonly type: "string";
71
+ readonly enum: readonly ["sandbox", "live"];
72
+ };
73
+ };
74
+ readonly required: readonly ["providerApiVersion", "environment"];
75
+ readonly additionalProperties: false;
76
+ };
77
+ readonly credentials: {
78
+ readonly type: "object";
79
+ readonly properties: {
80
+ readonly clientId: {
81
+ readonly type: "string";
82
+ readonly minLength: 10;
83
+ readonly maxLength: 512;
84
+ readonly writeOnly: true;
85
+ };
86
+ readonly clientSecret: {
87
+ readonly type: "string";
88
+ readonly minLength: 10;
89
+ readonly maxLength: 512;
90
+ readonly writeOnly: true;
91
+ };
92
+ readonly webhookId: {
93
+ readonly type: "string";
94
+ readonly minLength: 4;
95
+ readonly maxLength: 256;
96
+ readonly writeOnly: true;
97
+ };
98
+ };
99
+ readonly required: readonly ["clientId", "clientSecret", "webhookId"];
100
+ readonly additionalProperties: false;
101
+ };
102
+ readonly methods: {};
103
+ }, {
104
+ readonly id: "razorpay";
105
+ readonly label: "Razorpay";
106
+ readonly multiInstance: true;
107
+ readonly config: {
108
+ readonly type: "object";
109
+ readonly properties: {
110
+ readonly providerApiVersion: {
111
+ readonly type: "string";
112
+ readonly minLength: 2;
113
+ readonly maxLength: 64;
114
+ };
115
+ readonly mode: {
116
+ readonly type: "string";
117
+ readonly enum: readonly ["test", "live"];
118
+ };
119
+ };
120
+ readonly required: readonly ["providerApiVersion", "mode"];
121
+ readonly additionalProperties: false;
122
+ };
123
+ readonly credentials: {
124
+ readonly type: "object";
125
+ readonly properties: {
126
+ readonly keyId: {
127
+ readonly type: "string";
128
+ readonly minLength: 8;
129
+ readonly maxLength: 256;
130
+ readonly writeOnly: true;
131
+ };
132
+ readonly keySecret: {
133
+ readonly type: "string";
134
+ readonly minLength: 8;
135
+ readonly maxLength: 512;
136
+ readonly writeOnly: true;
137
+ };
138
+ readonly webhookSecret: {
139
+ readonly type: "string";
140
+ readonly minLength: 8;
141
+ readonly maxLength: 512;
142
+ readonly writeOnly: true;
143
+ };
144
+ };
145
+ readonly required: readonly ["keyId", "keySecret", "webhookSecret"];
146
+ readonly additionalProperties: false;
147
+ };
148
+ readonly methods: {};
149
+ }];
150
+ export type PaymentCurrency = 'USD';
151
+ export interface HostedSetupRequest {
152
+ tenantKey: string;
153
+ returnUrl: string;
154
+ cancelUrl: string;
155
+ idempotencyKey: string;
156
+ providerCustomerReference?: string;
157
+ }
158
+ export interface HostedSetupResult {
159
+ hostedUrl: string;
160
+ setupReference: string;
161
+ expiresAtTs: number;
162
+ }
163
+ export interface HostedSetupCompletionRequest {
164
+ tenantKey: string;
165
+ setupReference: string;
166
+ idempotencyKey: string;
167
+ }
168
+ /** Only opaque references and safe display metadata cross back into ForgeZero. */
169
+ export interface HostedSetupCompletionResult {
170
+ providerCustomerReference?: string;
171
+ providerPaymentMethodReference: string;
172
+ display: {
173
+ type: 'card' | 'bank' | 'upi' | 'paypal' | 'other';
174
+ brand?: string;
175
+ last4?: string;
176
+ expiresMonth?: number;
177
+ expiresYear?: number;
178
+ label?: string;
179
+ };
180
+ }
181
+ export interface CustomerRequest {
182
+ tenantKey: string;
183
+ email: string;
184
+ idempotencyKey: string;
185
+ }
186
+ export interface ChargeRequest {
187
+ tenantKey: string;
188
+ invoiceKey: string;
189
+ providerCustomerReference: string;
190
+ providerPaymentMethodReference: string;
191
+ amountMinor: string;
192
+ currency: PaymentCurrency;
193
+ idempotencyKey: string;
194
+ }
195
+ export interface ChargeResult {
196
+ providerAttemptReference: string;
197
+ status: 'succeeded' | 'failed' | 'pending';
198
+ failureCode?: string;
199
+ }
200
+ export interface VerifiedPaymentWebhook {
201
+ providerEventId: string;
202
+ eventType: string;
203
+ resourceReference: string;
204
+ /** Normalized terminal meaning; provider-specific event names never leak into settlement logic. */
205
+ status: 'succeeded' | 'failed' | 'pending';
206
+ failureCode?: string;
207
+ occurredAtTs: number;
208
+ }
209
+ export interface ReconciliationResult {
210
+ providerAttemptReference: string;
211
+ status: 'succeeded' | 'failed' | 'pending' | 'not_found';
212
+ failureCode?: string;
213
+ }
214
+ export interface PaymentProviderDriver {
215
+ createHostedSetup(input: HostedSetupRequest): Promise<HostedSetupResult>;
216
+ completeHostedSetup(input: HostedSetupCompletionRequest): Promise<HostedSetupCompletionResult>;
217
+ createCustomer(input: CustomerRequest): Promise<{
218
+ providerCustomerReference: string;
219
+ }>;
220
+ charge(input: ChargeRequest): Promise<ChargeResult>;
221
+ detachPaymentMethod(input: {
222
+ tenantKey: string;
223
+ providerPaymentMethodReference: string;
224
+ idempotencyKey: string;
225
+ }): Promise<void>;
226
+ verifyWebhook(input: {
227
+ rawBody: Uint8Array;
228
+ signatureHeaders: Readonly<Record<string, string>>;
229
+ }): Promise<VerifiedPaymentWebhook>;
230
+ reconcile(input: {
231
+ tenantKey: string;
232
+ providerAttemptReference: string;
233
+ }): Promise<ReconciliationResult>;
234
+ }
235
+ export declare const billingService: import("./index").ServiceDefinition<"billing", {
236
+ createHostedSetup: import("./index").ServiceMethodContract<HostedSetupRequest, HostedSetupResult>;
237
+ completeHostedSetup: import("./index").ServiceMethodContract<HostedSetupCompletionRequest, HostedSetupCompletionResult>;
238
+ createCustomer: import("./index").ServiceMethodContract<CustomerRequest, {
239
+ providerCustomerReference: string;
240
+ }>;
241
+ charge: import("./index").ServiceMethodContract<ChargeRequest, ChargeResult>;
242
+ detachPaymentMethod: import("./index").ServiceMethodContract<{
243
+ tenantKey: string;
244
+ providerPaymentMethodReference: string;
245
+ idempotencyKey: string;
246
+ }, void>;
247
+ verifyWebhook: import("./index").ServiceMethodContract<{
248
+ rawBody: Uint8Array;
249
+ signatureHeaders: Readonly<Record<string, string>>;
250
+ }, VerifiedPaymentWebhook>;
251
+ reconcile: import("./index").ServiceMethodContract<{
252
+ tenantKey: string;
253
+ providerAttemptReference: string;
254
+ }, ReconciliationResult>;
255
+ }>;
256
+ export interface VersionedPaymentProvider extends PaymentProviderDriver {
257
+ readonly key: PaymentProviderKey;
258
+ readonly provider: 'stripe' | 'paypal' | 'razorpay';
259
+ readonly contractVersion: 'v1';
260
+ /** Provider API version selected by operator config and persisted per attempt. */
261
+ readonly providerApiVersion: string;
262
+ }
263
+ /**
264
+ * Bind a reviewed provider/version identity to one concrete driver. Legacy API
265
+ * branches remain separate configured adapters rather than conditionals hidden
266
+ * inside the current implementation.
267
+ */
268
+ export declare function paymentProviderAdapter(args: {
269
+ key: PaymentProviderKey;
270
+ providerApiVersion: string;
271
+ driver: PaymentProviderDriver;
272
+ }): VersionedPaymentProvider;
273
+ /**
274
+ * Build a registry-compatible provider with one explicit current/legacy API
275
+ * branch. Vendor HTTP code stays outside the service and Vault remains injected.
276
+ */
277
+ export declare function definePaymentProvider(args: {
278
+ id: 'stripe' | 'paypal' | 'razorpay';
279
+ label: string;
280
+ version: string;
281
+ driver: {
282
+ createHostedSetup(context: InvokeContext, input: HostedSetupRequest): Promise<HostedSetupResult>;
283
+ completeHostedSetup(context: InvokeContext, input: HostedSetupCompletionRequest): Promise<HostedSetupCompletionResult>;
284
+ createCustomer(context: InvokeContext, input: CustomerRequest): Promise<{
285
+ providerCustomerReference: string;
286
+ }>;
287
+ charge(context: InvokeContext, input: ChargeRequest): Promise<ChargeResult>;
288
+ detachPaymentMethod(context: InvokeContext, input: {
289
+ tenantKey: string;
290
+ providerPaymentMethodReference: string;
291
+ idempotencyKey: string;
292
+ }): Promise<void>;
293
+ verifyWebhook(context: InvokeContext, input: {
294
+ rawBody: Uint8Array;
295
+ signatureHeaders: Readonly<Record<string, string>>;
296
+ }): Promise<VerifiedPaymentWebhook>;
297
+ reconcile(context: InvokeContext, input: {
298
+ tenantKey: string;
299
+ providerAttemptReference: string;
300
+ }): Promise<ReconciliationResult>;
301
+ };
302
+ config: Record<string, unknown>;
303
+ credentials: Record<string, unknown>;
304
+ classify?: (error: unknown) => FailureKind;
305
+ }): ProviderDefinition;