@conto_finance/sdk 0.6.1 → 0.7.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 +65 -0
- package/dist/browserbase.d.mts +3 -1
- package/dist/browserbase.d.ts +3 -1
- package/dist/browserbase.js +5 -2
- package/dist/browserbase.mjs +2 -2
- package/dist/checkout-verifier.d.mts +2 -1
- package/dist/checkout-verifier.d.ts +2 -1
- package/dist/checkout-verifier.mjs +1 -1
- package/dist/{chunk-VSIO6PYA.mjs → chunk-JBTJXIMI.mjs} +5 -2
- package/dist/{chunk-WSIKPUZJ.mjs → chunk-TGOYFBKZ.mjs} +3 -1
- package/dist/index.d.mts +508 -26
- package/dist/index.d.ts +508 -26
- package/dist/index.js +636 -96
- package/dist/index.mjs +633 -98
- package/dist/link-wallet.d.mts +121 -0
- package/dist/link-wallet.d.ts +121 -0
- package/dist/link-wallet.js +400 -0
- package/dist/link-wallet.mjs +365 -0
- package/dist/playwright.d.mts +3 -1
- package/dist/playwright.d.ts +3 -1
- package/dist/playwright.js +5 -2
- package/dist/playwright.mjs +2 -2
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -80,6 +80,9 @@ if (checkpoint.stage === 'AWAITING_APPROVAL') {
|
|
|
80
80
|
// The agent's rules need the owner. Throws if the owner rejects or the approval expires.
|
|
81
81
|
checkpoint = await conto.checkout.waitForApproval(checkpoint, { timeoutMs: 15 * 60_000 });
|
|
82
82
|
}
|
|
83
|
+
if (checkpoint.stage !== 'APPROVED') {
|
|
84
|
+
throw new Error('Inspect the existing purchase before continuing.');
|
|
85
|
+
}
|
|
83
86
|
// Open Link. The buyer signs in and the final total appears.
|
|
84
87
|
|
|
85
88
|
const confirmed = await conto.checkout.confirm(checkpoint, {
|
|
@@ -107,6 +110,68 @@ await conto.checkout.reportOutcome(confirmed.id, { outcome: 'PAID', reference: o
|
|
|
107
110
|
- Conto records what your checkout reports and does not see the charge. For control at the
|
|
108
111
|
moment of payment, pay with a Conto-managed wallet or a card Conto authorizes.
|
|
109
112
|
|
|
113
|
+
## Stripe Link cards
|
|
114
|
+
|
|
115
|
+
The Stripe Link card integration ships in SDK 0.7.0 and later (`npm install @conto_finance/sdk`).
|
|
116
|
+
The Link controls integration kit bundles the same SDK.
|
|
117
|
+
The [minimal trusted-runtime example](https://github.com/Conto-Finance/conto/tree/main/examples/link-wallet-agent)
|
|
118
|
+
uses the existing agent SDK key, requires no shopping frontend, and never pays.
|
|
119
|
+
|
|
120
|
+
Stripe Link is Stripe's payment wallet, and Conto integrates with it. `conto.checkout.getLinkCard()`
|
|
121
|
+
asks Conto first, then asks Stripe Link for a card only after Conto approves the purchase, for
|
|
122
|
+
exactly the approved amount at that store. Stripe Link issues the card. It runs Stripe's `link-cli`
|
|
123
|
+
on your machine with your own Link login (`npm i -g @stripe/link-cli`, then `link-cli auth login`).
|
|
124
|
+
The person approves each card in Link, in the app or on the web. Conto does not receive the card. It stores only the
|
|
125
|
+
Link request ID.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { linkCliWallet } from '@conto_finance/sdk/link-wallet';
|
|
129
|
+
|
|
130
|
+
const wallet = linkCliWallet({ test: true });
|
|
131
|
+
|
|
132
|
+
// At the payment step, once the final total with shipping and tax is known.
|
|
133
|
+
const result = await conto.checkout.getLinkCard({
|
|
134
|
+
idempotencyKey: order.id,
|
|
135
|
+
merchant: { id: 'acme-retail', name: 'ACME Retail', checkoutUrl: page.url() },
|
|
136
|
+
amountMinor: 8532,
|
|
137
|
+
purpose: 'Drip coffee maker the shopper chose',
|
|
138
|
+
lineItems: [{ name: 'Drip coffee maker', quantity: 1, unitAmountMinor: 7900 }],
|
|
139
|
+
wallet,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Fill in result.card in the store's card form, then right before paying:
|
|
143
|
+
const confirmed = await conto.checkout.confirm(result.checkpoint, {
|
|
144
|
+
amountMinor: 8532,
|
|
145
|
+
lineItems: observedItems,
|
|
146
|
+
totals: observedCharges,
|
|
147
|
+
paymentReference: result.paymentReference,
|
|
148
|
+
});
|
|
149
|
+
// Pay, then report the outcome with the same paymentReference.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- Link is never asked for a card before Conto approves. A denial at Conto throws before any Link
|
|
153
|
+
call. When a rule requires approval, `getLinkCard()` waits for the owner first.
|
|
154
|
+
- When the person declines in Link, the request expires, the wait passes `linkApprovalTimeoutMs`,
|
|
155
|
+
or `link-cli` is missing or logged out, `getLinkCard()` cancels the checkpoint to release the
|
|
156
|
+
held spend and throws `LinkCardDeniedError`, `LinkCardExpiredError`, `LinkCardTimeoutError`, or
|
|
157
|
+
`LinkWalletUnavailableError`. All extend `LinkCardError`. Do not pay.
|
|
158
|
+
- Retrying with the same input resumes the same checkpoint and Link request.
|
|
159
|
+
- The card (`number`, `securityValue` for the CVC, `expMonth`, `expYear`, `validUntil`, `last4`,
|
|
160
|
+
`brand`) stays in this process. Printing or serializing the result shows only the last four
|
|
161
|
+
digits. It never appears in an error.
|
|
162
|
+
- The card covers the approved total, so `confirm()` with a `paymentReference` refuses a
|
|
163
|
+
different total. Call `conto.checkout.replaceLinkCard(result, { wallet, amountMinor })` to
|
|
164
|
+
cancel the old card and checkpoint and get a card for the final total.
|
|
165
|
+
- Any `LinkWallet` works in place of `linkCliWallet()`: it creates a card request, waits for
|
|
166
|
+
approval, retrieves the card, and cancels.
|
|
167
|
+
- The protection holds only when the agent cannot also run `link-cli`, use a shell, or call Link
|
|
168
|
+
with your credentials itself.
|
|
169
|
+
- Pass observed final items and charges to `confirm()` even when the total is unchanged.
|
|
170
|
+
The server rejects a changed cart against the approved intent. The trusted host must
|
|
171
|
+
validate the actual merchant and checkout, own a durable one-use payment dispatch
|
|
172
|
+
claim, and keep card use outside model tools. Replaying a confirmed checkpoint is
|
|
173
|
+
not permission to submit payment again.
|
|
174
|
+
|
|
110
175
|
## External-card Policy Overlay
|
|
111
176
|
|
|
112
177
|
The admin client registers only a masked card alias and assigns cooperative
|
package/dist/browserbase.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Browser } from 'playwright-core';
|
|
2
2
|
import { GuardedPlaywrightCheckoutHttpHandler, PlaywrightSessionObservation, GuardedPlaywrightCheckoutClient, PlaywrightCdpSessionRegistryConfig, EncryptedPlaywrightCheckoutTargetStoreConfig, GuardedPlaywrightCheckoutRuntimeConfig } from './playwright.mjs';
|
|
3
3
|
import './index.mjs';
|
|
4
|
+
import './link-wallet.mjs';
|
|
4
5
|
|
|
5
6
|
/** Exact provider endpoints verified against Browserbase's session API; never use a wildcard. */
|
|
6
7
|
declare const BROWSERBASE_CONNECT_ORIGINS: readonly string[];
|
|
@@ -150,4 +151,5 @@ declare function createBrowserbaseSessionManager(config: BrowserbaseSessionConfi
|
|
|
150
151
|
*/
|
|
151
152
|
declare function createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost(config: BrowserbaseGuardedPlaywrightCheckoutRuntimeHostConfig): BrowserbaseGuardedPlaywrightCheckoutRuntimeHost;
|
|
152
153
|
|
|
153
|
-
export { BROWSERBASE_CONNECT_ORIGINS,
|
|
154
|
+
export { BROWSERBASE_CONNECT_ORIGINS, BrowserbaseSessionError, createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost, createBrowserbaseSessionHandoffAssertion, createBrowserbaseSessionManager };
|
|
155
|
+
export type { BrowserbaseAttachedSession, BrowserbaseGuardedPlaywrightCheckoutRuntimeHost, BrowserbaseGuardedPlaywrightCheckoutRuntimeHostConfig, BrowserbaseOwnedLiveView, BrowserbaseOwnedSession, BrowserbaseSessionBinding, BrowserbaseSessionBindingState, BrowserbaseSessionBindingStore, BrowserbaseSessionConfig, BrowserbaseSessionErrorCode, BrowserbaseSessionHandoff, BrowserbaseSessionHandoffAssertionInput, BrowserbaseSessionLifecycleOwner, BrowserbaseSessionManager, BrowserbaseSessionStatus };
|
package/dist/browserbase.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Browser } from 'playwright-core';
|
|
2
2
|
import { GuardedPlaywrightCheckoutHttpHandler, PlaywrightSessionObservation, GuardedPlaywrightCheckoutClient, PlaywrightCdpSessionRegistryConfig, EncryptedPlaywrightCheckoutTargetStoreConfig, GuardedPlaywrightCheckoutRuntimeConfig } from './playwright.js';
|
|
3
3
|
import './index.js';
|
|
4
|
+
import './link-wallet.js';
|
|
4
5
|
|
|
5
6
|
/** Exact provider endpoints verified against Browserbase's session API; never use a wildcard. */
|
|
6
7
|
declare const BROWSERBASE_CONNECT_ORIGINS: readonly string[];
|
|
@@ -150,4 +151,5 @@ declare function createBrowserbaseSessionManager(config: BrowserbaseSessionConfi
|
|
|
150
151
|
*/
|
|
151
152
|
declare function createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost(config: BrowserbaseGuardedPlaywrightCheckoutRuntimeHostConfig): BrowserbaseGuardedPlaywrightCheckoutRuntimeHost;
|
|
152
153
|
|
|
153
|
-
export { BROWSERBASE_CONNECT_ORIGINS,
|
|
154
|
+
export { BROWSERBASE_CONNECT_ORIGINS, BrowserbaseSessionError, createBrowserbaseGuardedPlaywrightCheckoutRuntimeHost, createBrowserbaseSessionHandoffAssertion, createBrowserbaseSessionManager };
|
|
155
|
+
export type { BrowserbaseAttachedSession, BrowserbaseGuardedPlaywrightCheckoutRuntimeHost, BrowserbaseGuardedPlaywrightCheckoutRuntimeHostConfig, BrowserbaseOwnedLiveView, BrowserbaseOwnedSession, BrowserbaseSessionBinding, BrowserbaseSessionBindingState, BrowserbaseSessionBindingStore, BrowserbaseSessionConfig, BrowserbaseSessionErrorCode, BrowserbaseSessionHandoff, BrowserbaseSessionHandoffAssertionInput, BrowserbaseSessionLifecycleOwner, BrowserbaseSessionManager, BrowserbaseSessionStatus };
|
package/dist/browserbase.js
CHANGED
|
@@ -322,13 +322,16 @@ function createEncryptedPlaywrightCheckoutTargetStore(config) {
|
|
|
322
322
|
if (envelope.version !== TARGET_STORE_ENVELOPE_VERSION || typeof envelope.iv !== "string" || typeof envelope.ciphertext !== "string" || typeof envelope.tag !== "string") {
|
|
323
323
|
throw new Error("invalid envelope");
|
|
324
324
|
}
|
|
325
|
+
const tag = Buffer.from(envelope.tag, "base64url");
|
|
326
|
+
if (tag.length !== 16) throw new Error("invalid envelope");
|
|
325
327
|
const decipher = (0, import_node_crypto2.createDecipheriv)(
|
|
326
328
|
"aes-256-gcm",
|
|
327
329
|
key,
|
|
328
|
-
Buffer.from(envelope.iv, "base64url")
|
|
330
|
+
Buffer.from(envelope.iv, "base64url"),
|
|
331
|
+
{ authTagLength: 16 }
|
|
329
332
|
);
|
|
330
333
|
decipher.setAAD(Buffer.from(storageKey));
|
|
331
|
-
decipher.setAuthTag(
|
|
334
|
+
decipher.setAuthTag(tag);
|
|
332
335
|
const plaintext = Buffer.concat([
|
|
333
336
|
decipher.update(Buffer.from(envelope.ciphertext, "base64url")),
|
|
334
337
|
decipher.final()
|
package/dist/browserbase.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createGuardedPlaywrightCheckoutRuntimeHost
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JBTJXIMI.mjs";
|
|
4
4
|
import "./chunk-O5RAAB2U.mjs";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-TGOYFBKZ.mjs";
|
|
6
6
|
|
|
7
7
|
// src/browserbase.ts
|
|
8
8
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
@@ -92,4 +92,5 @@ interface VerifyCheckoutIntegrationOptions {
|
|
|
92
92
|
*/
|
|
93
93
|
declare function verifyCheckoutIntegration(value: CheckoutCapabilityManifest | unknown, options?: VerifyCheckoutIntegrationOptions): Promise<CheckoutIntegrationVerificationReport>;
|
|
94
94
|
|
|
95
|
-
export { CHECKOUT_CAPABILITY_KINDS, CHECKOUT_CAPABILITY_MANIFEST_VERSION, CHECKOUT_CONFORMANCE_PROBE_IDS, CHECKOUT_METHOD_IDS, CHECKOUT_VERIFICATION_REPORT_VERSION,
|
|
95
|
+
export { CHECKOUT_CAPABILITY_KINDS, CHECKOUT_CAPABILITY_MANIFEST_VERSION, CHECKOUT_CONFORMANCE_PROBE_IDS, CHECKOUT_METHOD_IDS, CHECKOUT_VERIFICATION_REPORT_VERSION, verifyCheckoutIntegration };
|
|
96
|
+
export type { CheckoutCapabilityDescriptor, CheckoutCapabilityExposure, CheckoutCapabilityInventoryScope, CheckoutCapabilityKind, CheckoutCapabilityManifest, CheckoutCapabilityPaymentBoundary, CheckoutConformanceProbeId, CheckoutConformanceProbeObservation, CheckoutConformanceProbeOutcome, CheckoutConformanceProbeRequest, CheckoutConformanceProbeResult, CheckoutConformanceProbeRunner, CheckoutIntegrationComponent, CheckoutIntegrationStatus, CheckoutIntegrationVerificationReport, CheckoutMethodId, CheckoutSessionBinding, CheckoutVerificationFinding, CheckoutVerificationFindingCode, VerifyCheckoutIntegrationOptions };
|
|
@@ -92,4 +92,5 @@ interface VerifyCheckoutIntegrationOptions {
|
|
|
92
92
|
*/
|
|
93
93
|
declare function verifyCheckoutIntegration(value: CheckoutCapabilityManifest | unknown, options?: VerifyCheckoutIntegrationOptions): Promise<CheckoutIntegrationVerificationReport>;
|
|
94
94
|
|
|
95
|
-
export { CHECKOUT_CAPABILITY_KINDS, CHECKOUT_CAPABILITY_MANIFEST_VERSION, CHECKOUT_CONFORMANCE_PROBE_IDS, CHECKOUT_METHOD_IDS, CHECKOUT_VERIFICATION_REPORT_VERSION,
|
|
95
|
+
export { CHECKOUT_CAPABILITY_KINDS, CHECKOUT_CAPABILITY_MANIFEST_VERSION, CHECKOUT_CONFORMANCE_PROBE_IDS, CHECKOUT_METHOD_IDS, CHECKOUT_VERIFICATION_REPORT_VERSION, verifyCheckoutIntegration };
|
|
96
|
+
export type { CheckoutCapabilityDescriptor, CheckoutCapabilityExposure, CheckoutCapabilityInventoryScope, CheckoutCapabilityKind, CheckoutCapabilityManifest, CheckoutCapabilityPaymentBoundary, CheckoutConformanceProbeId, CheckoutConformanceProbeObservation, CheckoutConformanceProbeOutcome, CheckoutConformanceProbeRequest, CheckoutConformanceProbeResult, CheckoutConformanceProbeRunner, CheckoutIntegrationComponent, CheckoutIntegrationStatus, CheckoutIntegrationVerificationReport, CheckoutMethodId, CheckoutSessionBinding, CheckoutVerificationFinding, CheckoutVerificationFindingCode, VerifyCheckoutIntegrationOptions };
|
|
@@ -184,13 +184,16 @@ function createEncryptedPlaywrightCheckoutTargetStore(config) {
|
|
|
184
184
|
if (envelope.version !== TARGET_STORE_ENVELOPE_VERSION || typeof envelope.iv !== "string" || typeof envelope.ciphertext !== "string" || typeof envelope.tag !== "string") {
|
|
185
185
|
throw new Error("invalid envelope");
|
|
186
186
|
}
|
|
187
|
+
const tag = Buffer.from(envelope.tag, "base64url");
|
|
188
|
+
if (tag.length !== 16) throw new Error("invalid envelope");
|
|
187
189
|
const decipher = createDecipheriv(
|
|
188
190
|
"aes-256-gcm",
|
|
189
191
|
key,
|
|
190
|
-
Buffer.from(envelope.iv, "base64url")
|
|
192
|
+
Buffer.from(envelope.iv, "base64url"),
|
|
193
|
+
{ authTagLength: 16 }
|
|
191
194
|
);
|
|
192
195
|
decipher.setAAD(Buffer.from(storageKey));
|
|
193
|
-
decipher.setAuthTag(
|
|
196
|
+
decipher.setAuthTag(tag);
|
|
194
197
|
const plaintext = Buffer.concat([
|
|
195
198
|
decipher.update(Buffer.from(envelope.ciphertext, "base64url")),
|
|
196
199
|
decipher.final()
|
|
@@ -34,11 +34,13 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
|
|
|
34
34
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
35
35
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
36
36
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
37
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
37
38
|
|
|
38
39
|
export {
|
|
39
40
|
__commonJS,
|
|
40
41
|
__toESM,
|
|
41
42
|
__privateGet,
|
|
42
43
|
__privateAdd,
|
|
43
|
-
__privateSet
|
|
44
|
+
__privateSet,
|
|
45
|
+
__privateMethod
|
|
44
46
|
};
|