@conto_finance/sdk 0.3.1 → 0.5.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 CHANGED
@@ -1,5 +1,10 @@
1
1
  # @conto_finance/sdk
2
2
 
3
+ Conto is a buyer-side control layer. Integrate it in the agent owner's runtime or payment tools;
4
+ the owner or budget holder sets policy before the agent pays. Merchants do not install Conto.
5
+ See [buyer-side control](https://conto.finance/docs/guides/buyer-side-control) for the authorization
6
+ and execution boundary.
7
+
3
8
  TypeScript SDK for Conto. Use it when you control the agent runtime and want typed access to
4
9
  payment requests, payment execution, and organization-level provisioning.
5
10
 
@@ -19,6 +24,11 @@ npm install @conto_finance/sdk
19
24
  An admin SDK key is still an agent SDK key. It keeps the `conto_agent_...` prefix, so it is not a
20
25
  drop-in replacement for `ContoAdmin`.
21
26
 
27
+ ## Verify the connection
28
+
29
+ Requires Node.js 20.19+. Call `await conto.setup()` to inspect your agent, linked wallets,
30
+ effective policies, and scopes without creating a payment.
31
+
22
32
  ## Agent SDK Quick Start
23
33
 
24
34
  ```typescript
@@ -113,7 +123,9 @@ const cardAccess = new ContoCardAccess({
113
123
  Card Access claims each approved request exactly once before the executor can run. A
114
124
  duplicate or uncertain claim cannot invoke the executor again. It remains
115
125
  bypassable if another person or tool can access the card, and results are
116
- self-reported rather than issuer-verified. The legacy `conto.cards.controlled()`
126
+ self-reported rather than issuer-verified. The executor receives the normalized
127
+ purchase `idempotencyKey`; pass it to the payment processor so ambiguous
128
+ processor responses cannot create duplicate charges. The legacy `conto.cards.controlled()`
117
129
  helper remains available for compatibility, but new customer-hosted enforcement
118
130
  should use the standalone Card Access package. Use
119
131
  `admin.cards.listRequests({ status: 'EXECUTING' })` for reconciliation and
@@ -137,14 +149,16 @@ const result = await conto.payments.pay({
137
149
  ```typescript
138
150
  const paymentId = crypto.randomUUID();
139
151
 
140
- await conto.x402.preAuthorize({
152
+ const decision = await conto.x402.preAuthorize({
141
153
  amount: 0.01,
142
154
  recipientAddress: '0x...',
143
155
  resourceUrl: 'https://api.example.com/v1/search',
144
156
  paymentId,
145
157
  sessionId: 'session_123',
146
158
  });
159
+ if (!decision.authorized) throw new Error(decision.message);
147
160
 
161
+ // Sign and settle the x402 payment, then record it with the grant.
148
162
  await conto.x402.record({
149
163
  amount: 0.01,
150
164
  recipientAddress: '0x...',
@@ -152,13 +166,316 @@ await conto.x402.record({
152
166
  paymentId,
153
167
  txHash: '0x...',
154
168
  sessionId: 'session_123',
169
+ grantId: decision.grantId,
170
+ grantSignature: decision.grantSignature,
155
171
  });
156
172
 
157
173
  const budget = await conto.x402.budget();
158
174
  ```
159
175
 
176
+ An approved `preAuthorize` returns a single-use grant (`grantId`, `grantSignature`,
177
+ `grantExpiresAt`) for that wallet, recipient, and amount, and reserves the amount against the
178
+ agent's spend limits for 10 minutes. Pass the grant to `record`. A record without a valid,
179
+ unexpired grant is still accepted because the payment already settled, but Conto flags it as a
180
+ policy bypass and raises a critical alert. Organizations can also have the agent frozen
181
+ automatically. The record response then includes `policyBypass: true`, `bypassReason`, and
182
+ `agentFrozen`.
183
+
184
+ For a Privy-managed EVM wallet, `conto.x402.pay` replaces `preAuthorize`. Pass the same fields
185
+ plus the accepted 402 requirements; when approved, Conto signs the payment and returns the header
186
+ to retry with:
187
+
188
+ ```typescript
189
+ const paid = await conto.x402.pay({
190
+ amount: 0.01,
191
+ recipientAddress: requirements.payTo,
192
+ resourceUrl: 'https://api.example.com/v1/search',
193
+ paymentId,
194
+ paymentRequirements: requirements, // accepted entry from the 402 challenge
195
+ });
196
+ if (!paid.authorized) throw new Error(paid.message);
197
+
198
+ const response = await fetch('https://api.example.com/v1/search', {
199
+ headers: { [paid.paymentHeaderName!]: paid.xPaymentHeader! },
200
+ });
201
+ // Then record with paid.grantId, paid.grantSignature, and the settlement txHash.
202
+ ```
203
+
204
+ `pay` is not retried automatically: each grant is signed once, and a repeat returns
205
+ `GRANT_ALREADY_SIGNED`. External wallets get `MANAGED_SIGNING_UNAVAILABLE`.
206
+
160
207
  The MPP client mirrors the same shape with `conto.mpp.preAuthorize`, `conto.mpp.record`,
161
- `conto.mpp.budget`, and `conto.mpp.services`.
208
+ `conto.mpp.budget`, and `conto.mpp.services`. An MPP session grant is a ceiling: several
209
+ `record` calls with the same `sessionId` may draw it down until it is used up or expires.
210
+
211
+ ## Stripe Link Checkout Commerce (test only)
212
+
213
+ `LINK_CHECKOUT` is test-only and works only with a merchant enrolled with Conto. It is not a
214
+ general merchant integration. It evaluates policy before creating an ordinary Stripe-hosted
215
+ Checkout Session with card and Link enabled. It needs no private Link SDK permission,
216
+ Link connection, saved payment-method ID, SPT, or LPT.
217
+
218
+ Commerce execution responses separate the provider-neutral `executionChannel`, optional
219
+ `checkoutMethod`, and optional `settlementRail` from the legacy provider and adapter identifiers.
220
+ For dynamic hosted Checkout, `checkoutMethod` remains absent until settlement observes Link or the
221
+ card fallback; callers must not treat the adapter name as proof that Link was selected.
222
+
223
+ ```typescript
224
+ let { execution } = await conto.beginCommerceExecution({
225
+ executionMethod: 'LINK_CHECKOUT',
226
+ idempotencyKey: crypto.randomUUID(),
227
+ amountMinor: 6400,
228
+ currency: 'USD',
229
+ category: 'OFFICE_SUPPLIES',
230
+ purpose: 'Office supplies',
231
+ counterparty: {
232
+ canonicalId: 'conto-demo-office-supply',
233
+ },
234
+ cart: {
235
+ lineItems: [{ name: 'Office supplies', quantity: 1, unitAmountMinor: 6400 }],
236
+ totals: [{ type: 'total', label: 'Total', amountMinor: 6400 }],
237
+ },
238
+ providerPresentation: {
239
+ approvalSummary: 'Buy office supplies from the configured merchant',
240
+ lineItemLabels: ['Office supplies'],
241
+ },
242
+ });
243
+
244
+ if (execution.status !== 'ACTION_REQUIRED' || !execution.approvalUrl) {
245
+ throw new Error('Stripe Checkout was not created safely');
246
+ }
247
+
248
+ if (execution.executionAdapter !== 'LINK_CHECKOUT') {
249
+ throw new Error('Unexpected commerce execution adapter');
250
+ }
251
+
252
+ // Hand the temporary capability to a trusted interactive browser/UI. Do not log it.
253
+ await presentCheckoutActionSecurely(execution.approvalUrl);
254
+
255
+ while (execution.status === 'ACTION_REQUIRED' || execution.status === 'PROCESSING') {
256
+ ({ execution } = await conto.refreshCommerceExecution(execution.id));
257
+ }
258
+
259
+ if (execution.status !== 'SETTLED' || execution.evidence.actualPaymentMethod !== 'LINK') {
260
+ throw new Error('This execution did not settle with Link');
261
+ }
262
+ ```
263
+
264
+ Stripe decides whether Link appears and whether the customer chooses it. Card is an explicit
265
+ fallback, surfaced as `actualPaymentMethod: 'CARD'`; it is a valid payment but not Link evidence.
266
+ The read-only `getCommerceExecution` projection redacts action URLs; use the initial begin result or
267
+ the `payments:confirm` refresh path while action remains required.
268
+ The server resolves the exact merchant name, Stripe account, and return URLs from configuration, so
269
+ the caller cannot redirect the approved purchase. This path covers only that enrolled merchant's
270
+ Conto channel, not unrelated Checkout pages or the consumer's Link wallet. See
271
+ `docs/STRIPE_LINK_CHECKOUT_ADAPTER.md` for configuration, webhook, drill, and reconciliation
272
+ requirements.
273
+
274
+ ## Agent checkout guard
275
+
276
+ For browser checkouts on supported rails (Link, card, Shop Pay, or PayPal), use
277
+ `runGuardedCheckout` with `executionMethod: 'BROWSER_CHECKOUT'`. Other rails and checkout flows are
278
+ not covered. It binds and atomically authorizes one exact Link, card,
279
+ Shop Pay, or PayPal browser action without requiring merchant or private provider integration. The
280
+ privileged browser executor must be available only through this wrapper; an unrestricted click or
281
+ payment tool would bypass the control. Persist its stable dispatch attempt before calling the helper; it owns authorization,
282
+ one-use claim, the privileged callback, and finalization. See `docs/AGENT_CHECKOUT_GUARD.md` for the
283
+ runtime boundary and example.
284
+
285
+ Isolated browser processes can implement `PrivilegedBrowserCheckoutDriver` and use
286
+ `runGuardedCheckoutWithDriver`; the agent model must receive only that guarded wrapper, never the
287
+ driver's `dispatch` primitive. Generate `action.targetFingerprint` with
288
+ `fingerprintBrowserCheckoutTarget` during inspection, then wrap the privileged target resolver with
289
+ `createVerifiedBrowserCheckoutDriver`. The wrapper re-hashes the current page, locator, accessible
290
+ name, destination, form action, and disabled state immediately before dispatch and refuses any
291
+ changed target without clicking it. Observed link and form destinations must be explicitly bound as
292
+ the action's `targetUrl`, allowing Conto's origin trust policy to evaluate them before the claim.
293
+
294
+ For Browserbase, use the first-class provider host. Its binding store must reject duplicate session
295
+ IDs and atomically revoke only an active record matching the supplied organization, agent, and
296
+ project. Store the credential-free binding durably; never add the provider `connectUrl` to it.
297
+
298
+ ```typescript
299
+ import {
300
+ createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost,
301
+ createBrowserbaseSessionHandoffAssertion,
302
+ } from '@conto_finance/sdk/browserbase';
303
+ import { chromium } from 'playwright-core';
304
+
305
+ const host = createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost({
306
+ conto,
307
+ browserbase: {
308
+ apiKey: process.env.BROWSERBASE_API_KEY!,
309
+ projectId: process.env.BROWSERBASE_PROJECT_ID!,
310
+ organizationId,
311
+ agentId,
312
+ bindingStore: browserbaseSessionBindings,
313
+ contextId: process.env.BROWSERBASE_CONTEXT_ID,
314
+ handoffKey: Buffer.from(process.env.CONTO_BROWSER_HANDOFF_KEY!, 'base64'),
315
+ },
316
+ connectOverCDP: (connectUrl) => chromium.connectOverCDP(connectUrl),
317
+ targetStore: {
318
+ encryptionKey: Buffer.from(process.env.CONTO_BROWSER_TARGET_KEY!, 'base64'),
319
+ blobStore: durableTargetBlobs,
320
+ },
321
+ dispatchAttemptFor: ({ idempotencyKey }) => attempts.loadOrCreate(idempotencyKey),
322
+ token: process.env.CONTO_BROWSER_RUNTIME_TOKEN!,
323
+ });
324
+
325
+ const browser = await host.createSession();
326
+ // Give browser.browserSessionId, never a provider connection URL, to the guarded agent runtime.
327
+
328
+ // Or attach a session created by the customer's trusted Browserbase backend.
329
+ const browserSessionId = customerBrowserbaseSession.id;
330
+ const expiresAt = new Date(Date.now() + 60_000).toISOString();
331
+ const handoffAssertion = createBrowserbaseSessionHandoffAssertion(
332
+ {
333
+ browserSessionId,
334
+ projectId: process.env.BROWSERBASE_PROJECT_ID!,
335
+ organizationId,
336
+ agentId,
337
+ expiresAt,
338
+ },
339
+ Buffer.from(process.env.CONTO_BROWSER_HANDOFF_KEY!, 'base64')
340
+ );
341
+ await host.attachSession({ browserSessionId, handoffAssertion });
342
+ export const POST = host.handler;
343
+ ```
344
+
345
+ The Browserbase host exposes `handler`, `createSession`, `attachSession`, `observeSession`,
346
+ `liveViewForSession`, `releaseSession`, `detachSession`, and `close`. `observeSession` returns only a
347
+ bounded page origin/title and visible
348
+ link/button outline; it excludes full page text, DOM, form values, URL paths and queries,
349
+ screenshots, cookies, storage, and provider capabilities. It rechecks ownership and page identity
350
+ after observing.
351
+ `createSession` returns a session ID, active status, and expiry without a connection URL.
352
+ `liveViewForSession` is a privileged operator capability: expose it only behind separate human
353
+ authentication, never as an agent tool. A configured Context persists login state but must remain
354
+ server-side; its durable binding store should prevent concurrent sessions from sharing one Context.
355
+ `releaseSession` atomically revokes Conto ownership before closing the local connection and asking
356
+ Browserbase to release the keep-alive session. Call it when the agent session ends; `close` only
357
+ closes local Playwright connections. `attachSession` accepts only a five-minute HMAC assertion
358
+ binding the exact provider project, Conto organization, agent, session, and expiry. Its matching
359
+ `detachSession` revokes Conto access and closes the local connection without releasing the
360
+ agent-host-owned provider session. Keep the independent 32-byte handoff key and assertions outside
361
+ the model and browser page.
362
+
363
+ For another Playwright or secure CDP provider, use
364
+ `createGuardedPlaywrightCheckoutRuntimeHost` from `@conto_finance/sdk/playwright`. The generic host
365
+ exposes only `handler`, `observeSession`, `closeSession`, and `close`, keeping discovery, mutation
366
+ primitives, the target store, the Playwright page, and raw dispatch private.
367
+ Lower-level integrations can still compose `createGuardedPlaywrightCheckoutRuntime`, whose façade
368
+ exposes only `discover` and `run`; the raw driver is not returned. Target
369
+ registrations expire after ten minutes by default. The encrypted store persists only ciphertext
370
+ through a small durable blob port, so a runtime restart does not lose an approved
371
+ target or disclose its locator. `dispatchAttemptFor` must atomically return the same persisted ID for
372
+ the same checkout intent. The dispatch result classifies the browser outcome as `NEW_PAGE`,
373
+ `PAGE_NAVIGATION`, or `SAME_PAGE`, but always reports settlement as `UNVERIFIED`; only merchant or
374
+ provider evidence can prove payment. Never expose the page, target store, persisted registrations,
375
+ or provider-derived locator state to the model. The inert positional reference returned by
376
+ `observeSession` is the only locator intended for the model.
377
+
378
+ The generic CDP registry accepts connection URLs only from exact secure origins and rechecks
379
+ `connectUrlForSession` ownership on every lookup. Revocation closes a cached connection. It caches
380
+ one connection per owned session and requires exactly one open page unless the runtime supplies
381
+ an exact `selectPage` callback. Keep Browserbase API keys and `connectUrl` values in the privileged process.
382
+ Call `closeSession` only when the agent session is finished because closing the Playwright browser
383
+ may end the provider session.
384
+
385
+ ### Verify the exclusive checkout path
386
+
387
+ Use `@conto_finance/sdk/checkout-verifier` during agent-host onboarding and whenever its tool
388
+ registry changes. The manifest inventories every capability exposed to the model, identifies the
389
+ session ownership boundary, and names the supported checkout methods. The verifier reports
390
+ `ADVISORY` when an unrestricted payment-capable browser tool remains available and `UNVERIFIED`
391
+ when active probes have not run. It reports `ENFORCEABLE` and `canBypass: false` only after the
392
+ complete inventory is isolated and all denial, replay, tamper, alternate-path, and
393
+ ambiguous-dispatch probes pass.
394
+
395
+ The probe runner belongs to the trusted integration host and must execute against an isolated
396
+ fixture session. A report does not remotely attest an untrusted host or discover tools omitted from
397
+ its inventory. See `docs/CHECKOUT_INTEGRATION_VERIFIER.md` for the manifest, probe, and status
398
+ contract.
399
+
400
+ The HTTP handler implements the authenticated endpoint consumed by the optional
401
+ `guarded_browser_checkout` MCP tool. It accepts Web `Request` objects, so it can be mounted directly
402
+ in a compatible route or adapted to a Node server. It authenticates before reading the body,
403
+ rejects unknown fields and mismatched cart totals, performs discovery and guarded execution in one
404
+ request, and returns only minimized browser evidence. Use a dedicated random token of at least 32
405
+ characters; the handler rejects Conto API keys.
406
+
407
+ Organization-specific proposal facts can be sent through the typed normalization call after an
408
+ owner or administrator registers the namespace schema:
409
+
410
+ ```typescript
411
+ const proposal = await conto.normalizeCommerceProposal({
412
+ proposalKey: 'office-toner-2026-09-02',
413
+ purpose: 'Purchase toner for operations',
414
+ extensions: [
415
+ {
416
+ namespace: 'acme.procurement.v1',
417
+ value: { costCenter: 'OPS', project: 'AP_AUTOMATION' },
418
+ },
419
+ ],
420
+ });
421
+ ```
422
+
423
+ Conto rejects unregistered namespaces and schema-invalid values before policy evaluation. Accepted
424
+ facts are bound to the schema revision and fingerprint returned on the normalized proposal.
425
+
426
+ ## Stripe Link Sandbox Commerce
427
+
428
+ The gated Stripe Link sandbox surface uses the agent key for policy evaluation and execution. A
429
+ Link connection must first be created by its user and explicitly bound to the agent through the
430
+ authenticated session API. The agent SDK never receives the Link access token or payment artifact.
431
+
432
+ ```typescript
433
+ const linkContext = await conto.listStripeLinkPaymentMethods(connectionId);
434
+ if (linkContext.organizationId !== expectedOrganizationId) {
435
+ throw new Error('Agent key belongs to the wrong Conto organization');
436
+ }
437
+ const { paymentMethods } = linkContext;
438
+
439
+ let { execution } = await conto.beginCommerceExecution({
440
+ connectionId,
441
+ paymentMethodId: paymentMethods[0].id,
442
+ executionMethod: 'STRIPE_PAYMENT_INTENT',
443
+ idempotencyKey: crypto.randomUUID(),
444
+ amountMinor: 6400,
445
+ currency: 'USD',
446
+ purpose: 'Office supplies',
447
+ counterparty: {
448
+ canonicalId: 'conto-demo-office-supply',
449
+ displayName: 'Conto Demo Office Supply',
450
+ },
451
+ cart: {
452
+ lineItems: [{ name: 'Office supplies', quantity: 1, unitAmountMinor: 6400 }],
453
+ totals: [{ type: 'total', label: 'Total', amountMinor: 6400 }],
454
+ },
455
+ providerPresentation: {
456
+ approvalSummary: 'Buy office supplies from Conto Demo Office Supply',
457
+ lineItemLabels: ['Office supplies'],
458
+ },
459
+ });
460
+
461
+ if (execution.status === 'AWAITING_APPROVAL') {
462
+ // Present execution.approvalUrl to the Link user, then poll with refresh.
463
+ ({ execution } = await conto.refreshCommerceExecution(execution.id));
464
+ }
465
+
466
+ if (execution.status === 'READY') {
467
+ const result = await conto.executeCommerceExecution(execution.id);
468
+ console.log(result.execution.evidence, result.execution.evidenceFingerprint);
469
+ }
470
+ ```
471
+
472
+ Use `getCommerceExecution(id)` for read-only reconciliation and
473
+ `cancelCommerceExecution(id)` to cancel a nonterminal execution. `beginCommerceExecution` safely
474
+ retries with its stable idempotency key, and `refreshCommerceExecution` safely retries observation.
475
+ Checkout execution and cancellation are not transport-retried.
476
+ The Stripe account and Link business-network profile are resolved from server-owned configuration;
477
+ an agent cannot supply or replace them. Use `executionMethod: 'MPP'` only for the optional,
478
+ configured MPP compatibility transport.
162
479
 
163
480
  ## Admin SDK Quick Start
164
481
 
@@ -194,6 +511,27 @@ if (frozen) {
194
511
  }
195
512
  ```
196
513
 
514
+ ### Stripe Link Checkout readiness
515
+
516
+ Organization administrators can inspect the configured merchant Checkout adapter without calling
517
+ Stripe, then explicitly verify that Conto's configured credential resolves to its configured
518
+ merchant account:
519
+
520
+ ```typescript
521
+ const { readiness } = await admin.paymentRails.getStripeLinkCheckoutReadiness();
522
+
523
+ if (readiness.canVerify && !readiness.checks.accountVerified) {
524
+ const verified = await admin.paymentRails.verifyStripeLinkCheckoutAccount();
525
+ console.log(verified.readiness.status, verified.readiness.verification);
526
+ }
527
+ ```
528
+
529
+ The result contains only mode, booleans, safe status codes, timestamps, and scope statements. It
530
+ never contains merchant/account identifiers, URLs, credentials, hashes, Stripe objects, or raw
531
+ provider errors. Verification proves the configured account match only; Stripe still decides
532
+ whether Link is eligible, displayed, and selected at Checkout. The static GET is retry-safe; the
533
+ active POST verification is not automatically retried.
534
+
197
535
  ## What This Package Covers
198
536
 
199
537
  - `Conto` for agent-scoped payment flows
@@ -207,7 +545,9 @@ The SDK automatically adds an idempotency key to wallet payment authorization
207
545
  requests. Provide your own stable `idempotencyKey` when a retry may happen in
208
546
  another process or job attempt. External-card approvals always require a stable
209
547
  caller-supplied `idempotencyKey`; card approval and confirmation are safe to
210
- retry. x402 and MPP pre-authorization calls are non-mutating policy checks.
548
+ retry. x402 and MPP pre-authorization calls issue a grant and reserve spend. A retry
549
+ with the same `paymentId` (x402) or `challengeId`/`credentialId` (MPP) returns the
550
+ same live grant instead of reserving again.
211
551
  Record calls require an explicit stable `paymentId` or `credentialId` so an
212
552
  ambiguous failure can be reconciled safely.
213
553
 
@@ -235,8 +575,7 @@ try {
235
575
 
236
576
  ## What To Use Instead
237
577
 
238
- - Use the REST API docs if you need endpoints that are not wrapped by this package yet, especially
239
- external-wallet `approve -> transfer -> confirm` flows.
578
+ - Use `conto.payments.approve()` and `conto.payments.confirm()` for external wallets. Your own signer sends the transfer between those calls. Neither write retries automatically.
240
579
  - Use the MCP server if a tool-calling assistant should operate Conto directly.
241
580
 
242
581
  ## Docs
@@ -250,3 +589,15 @@ try {
250
589
  ## License
251
590
 
252
591
  MIT
592
+
593
+ Developer support: [support@conto.finance](mailto:support@conto.finance). Include the package version and request ID; never include API keys.
594
+
595
+ ### Connected-card delivery
596
+
597
+ For an organization with connected cards enabled, `conto.connectedCards.draw()` returns a disposable
598
+ credential exactly once. Keep it in memory and use it at the mandate's merchant before
599
+ `credentialExpiresAt`. Never log or persist it. After receipt, call
600
+ `conto.connectedCards.acknowledgeDelivery(draw.requestId)`. Acknowledgement is idempotent and records
601
+ delivery only, not payment settlement. Replaying the original draw key cannot recover a lost
602
+ credential; check the original outcome before requesting a replacement. Issued capacity stays
603
+ consumed even when checkout fails.
@@ -0,0 +1,141 @@
1
+ import { Browser } from 'playwright-core';
2
+ import { GuardedPlaywrightCheckoutHttpHandler, PlaywrightSessionObservation, GuardedPlaywrightCheckoutClient, PlaywrightCdpSessionRegistryConfig, EncryptedPlaywrightCheckoutTargetStoreConfig, GuardedPlaywrightCheckoutRuntimeConfig } from './playwright.mjs';
3
+ import './index.mjs';
4
+
5
+ /** Exact provider endpoints verified against Browserbase's session API; never use a wildcard. */
6
+ declare const BROWSERBASE_CONNECT_ORIGINS: readonly string[];
7
+ type BrowserbaseSessionStatus = 'PENDING' | 'RUNNING' | 'ERROR' | 'TIMED_OUT' | 'COMPLETED';
8
+ type BrowserbaseSessionBindingState = 'ACTIVE' | 'REVOKED';
9
+ type BrowserbaseSessionLifecycleOwner = 'CONTO_RUNTIME' | 'AGENT_HOST';
10
+ /** Credential-free durable record. Never persist Browserbase connect URLs or API keys here. */
11
+ interface BrowserbaseSessionBinding {
12
+ browserSessionId: string;
13
+ organizationId: string;
14
+ agentId: string;
15
+ projectId: string;
16
+ /** Missing legacy values are treated as CONTO_RUNTIME. */
17
+ lifecycleOwner?: BrowserbaseSessionLifecycleOwner;
18
+ state: BrowserbaseSessionBindingState;
19
+ createdAt: string;
20
+ expiresAt: string;
21
+ }
22
+ /**
23
+ * Durable ownership port for remote sessions. `create` must reject duplicate IDs and `revoke`
24
+ * must atomically transition only an ACTIVE record matching every supplied ownership field.
25
+ */
26
+ interface BrowserbaseSessionBindingStore {
27
+ create(binding: BrowserbaseSessionBinding): Promise<boolean>;
28
+ get(browserSessionId: string): Promise<BrowserbaseSessionBinding | null>;
29
+ revoke(input: {
30
+ browserSessionId: string;
31
+ organizationId: string;
32
+ agentId: string;
33
+ projectId: string;
34
+ revokedAt: string;
35
+ }): Promise<boolean>;
36
+ /** Required with contextId. Release only after Browserbase confirms the provider session closed. */
37
+ releaseContextLease?(input: {
38
+ browserSessionId: string;
39
+ organizationId: string;
40
+ agentId: string;
41
+ projectId: string;
42
+ }): Promise<boolean>;
43
+ }
44
+ interface BrowserbaseSessionConfig {
45
+ /** Browserbase credential retained by the privileged runtime. Conto credentials are rejected. */
46
+ apiKey: string;
47
+ projectId: string;
48
+ organizationId: string;
49
+ agentId: string;
50
+ bindingStore: BrowserbaseSessionBindingStore;
51
+ /** Optional 32-byte server-only key required to attach sessions created by an agent host. */
52
+ handoffKey?: Uint8Array;
53
+ /** Optional server-only Browserbase Context used to persist Link or merchant authentication. */
54
+ contextId?: string;
55
+ /** Browserbase session timeout. Defaults to 900 seconds. */
56
+ timeoutSeconds?: number;
57
+ /** Browserbase API request timeout. Defaults to 10 seconds and may not exceed 60 seconds. */
58
+ requestTimeoutMs?: number;
59
+ /** Injected for tests or runtimes with an instrumented fetch implementation. */
60
+ fetch?: typeof fetch;
61
+ now?: () => Date;
62
+ }
63
+ interface BrowserbaseGuardedPlaywrightCheckoutRuntimeHostConfig {
64
+ conto: GuardedPlaywrightCheckoutClient;
65
+ browserbase: BrowserbaseSessionConfig;
66
+ /** Usually `(url) => chromium.connectOverCDP(url)`. */
67
+ connectOverCDP(connectUrl: string): Promise<Browser>;
68
+ selectPage?: PlaywrightCdpSessionRegistryConfig['selectPage'];
69
+ maxSessions?: number;
70
+ targetStore: EncryptedPlaywrightCheckoutTargetStoreConfig;
71
+ dispatchAttemptFor: GuardedPlaywrightCheckoutRuntimeConfig['dispatchAttemptFor'];
72
+ /** Dedicated service credential. Conto and Browserbase API keys are rejected. */
73
+ token: string;
74
+ maxBodyBytes?: number;
75
+ clickTimeoutMs?: number;
76
+ popupTimeoutMs?: number;
77
+ targetTtlMs?: number;
78
+ now?: () => Date;
79
+ }
80
+ /** Safe session projection for the agent-facing browser launcher. */
81
+ interface BrowserbaseOwnedSession {
82
+ browserSessionId: string;
83
+ status: Extract<BrowserbaseSessionStatus, 'PENDING' | 'RUNNING'>;
84
+ expiresAt: string;
85
+ }
86
+ /** Proof-carrying request from a trusted agent host for an existing Browserbase session. */
87
+ interface BrowserbaseSessionHandoff {
88
+ browserSessionId: string;
89
+ handoffAssertion: string;
90
+ }
91
+ /** Safe projection for a session whose provider lifecycle remains owned by the agent host. */
92
+ interface BrowserbaseAttachedSession extends BrowserbaseOwnedSession {
93
+ lifecycleOwner: 'AGENT_HOST';
94
+ }
95
+ interface BrowserbaseSessionHandoffAssertionInput {
96
+ browserSessionId: string;
97
+ projectId: string;
98
+ organizationId: string;
99
+ agentId: string;
100
+ expiresAt: string;
101
+ }
102
+ /** Operator-only capability for a human authentication or challenge handoff. */
103
+ interface BrowserbaseOwnedLiveView {
104
+ browserSessionId: string;
105
+ liveViewUrl: string;
106
+ expiresAt: string;
107
+ }
108
+ /**
109
+ * Closed Browserbase lifecycle plus guarded checkout façade. It never exposes the provider API
110
+ * key, CDP connection URL, Playwright page, target store, discovery primitive, or raw dispatch.
111
+ */
112
+ interface BrowserbaseGuardedPlaywrightCheckoutRuntimeHost {
113
+ handler: GuardedPlaywrightCheckoutHttpHandler;
114
+ createSession(): Promise<BrowserbaseOwnedSession>;
115
+ /** Attaches an existing agent-host session after verifying a short-lived server assertion. */
116
+ attachSession(input: BrowserbaseSessionHandoff): Promise<BrowserbaseAttachedSession>;
117
+ /** Read-only, bounded projection of the exact runtime-owned page. */
118
+ observeSession(browserSessionId: string): Promise<PlaywrightSessionObservation>;
119
+ /** Returns a short-lived provider capability only to a separately authenticated operator path. */
120
+ liveViewForSession(browserSessionId: string): Promise<BrowserbaseOwnedLiveView>;
121
+ /** Revokes Conto ownership first, closes the local connection, then releases Browserbase. */
122
+ releaseSession(browserSessionId: string): Promise<void>;
123
+ /** Revokes the Conto binding without ending the externally owned Browserbase session. */
124
+ detachSession(browserSessionId: string): Promise<void>;
125
+ /** Closes local Playwright connections. Call releaseSession for each keep-alive provider session. */
126
+ close(): Promise<void>;
127
+ }
128
+ type BrowserbaseSessionErrorCode = 'BROWSERBASE_CONFIG_INVALID' | 'BROWSERBASE_PROVIDER_UNAVAILABLE' | 'BROWSERBASE_PROVIDER_RESPONSE_INVALID' | 'BROWSERBASE_SESSION_BINDING_FAILED' | 'BROWSERBASE_SESSION_HANDOFF_DISABLED' | 'BROWSERBASE_SESSION_HANDOFF_INVALID' | 'BROWSERBASE_LIVE_VIEW_UNAVAILABLE' | 'BROWSERBASE_SESSION_NOT_OWNED' | 'BROWSERBASE_SESSION_RELEASE_FAILED';
129
+ declare class BrowserbaseSessionError extends Error {
130
+ readonly code: BrowserbaseSessionErrorCode;
131
+ constructor(code: BrowserbaseSessionErrorCode, message: string);
132
+ }
133
+ /** Creates a short-lived assertion after the trusted agent host creates its Browserbase session. */
134
+ declare function createBrowserbaseSessionHandoffAssertion(input: BrowserbaseSessionHandoffAssertionInput, keyValue: Uint8Array): string;
135
+ /**
136
+ * Creates the recommended Browserbase deployment boundary. Provider lifecycle, ownership checks,
137
+ * remote connection resolution, guarded execution, and cleanup remain in one privileged object.
138
+ */
139
+ declare function createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost(config: BrowserbaseGuardedPlaywrightCheckoutRuntimeHostConfig): BrowserbaseGuardedPlaywrightCheckoutRuntimeHost;
140
+
141
+ export { BROWSERBASE_CONNECT_ORIGINS, type BrowserbaseAttachedSession, type BrowserbaseGuardedPlaywrightCheckoutRuntimeHost, type BrowserbaseGuardedPlaywrightCheckoutRuntimeHostConfig, type BrowserbaseOwnedLiveView, type BrowserbaseOwnedSession, type BrowserbaseSessionBinding, type BrowserbaseSessionBindingState, type BrowserbaseSessionBindingStore, type BrowserbaseSessionConfig, BrowserbaseSessionError, type BrowserbaseSessionErrorCode, type BrowserbaseSessionHandoff, type BrowserbaseSessionHandoffAssertionInput, type BrowserbaseSessionLifecycleOwner, type BrowserbaseSessionStatus, createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost, createBrowserbaseSessionHandoffAssertion };