@ar-agents/mercadopago 0.9.0 → 0.11.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/CHANGELOG.md +42 -0
- package/MIGRATION.md +176 -0
- package/dist/audit-B9Nhj3PH.d.cts +294 -0
- package/dist/audit-B9Nhj3PH.d.ts +294 -0
- package/dist/index.cjs +1362 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +792 -6
- package/dist/index.d.ts +792 -6
- package/dist/index.js +1337 -50
- package/dist/index.js.map +1 -1
- package/dist/otel.cjs +102 -0
- package/dist/otel.cjs.map +1 -0
- package/dist/otel.d.cts +90 -0
- package/dist/otel.d.ts +90 -0
- package/dist/otel.js +100 -0
- package/dist/otel.js.map +1 -0
- package/dist/vercel-kv.cjs +81 -0
- package/dist/vercel-kv.cjs.map +1 -1
- package/dist/vercel-kv.d.cts +38 -2
- package/dist/vercel-kv.d.ts +38 -2
- package/dist/vercel-kv.js +81 -1
- package/dist/vercel-kv.js.map +1 -1
- package/package.json +22 -3
- package/tools.manifest.json +1 -1
- package/dist/state-C6Wzb_XX.d.cts +0 -106
- package/dist/state-C6Wzb_XX.d.ts +0 -106
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes — Composability + cross-LATAM + fraud scoring
|
|
6
|
+
|
|
7
|
+
**Tool middleware pattern (NEW)**: composable wrappers around any AI SDK tool. Ships `withAuditLog`, `withRateLimit`, `withMetrics`, `withRetry` + `compose()` + `applyToAllTools()`. Add audit + rate-limit + metrics to every tool with a single config block instead of wiring each concern into the tool implementation.
|
|
8
|
+
|
|
9
|
+
**TaxID validation cross-LATAM (NEW)**: `validateTaxId(input, type)` for AR (DNI/CUIT/CUIL with modulo-11), BR (CPF/CNPJ two-step weighted), MX (RFC structure), CL (RUT with K), CO (NIT modulo-11), UY (RUT 12-digit), PE (RUC 11-digit + prefix). `detectAndValidate(input, country)` auto-detects type from length. New `validate_tax_id` agent tool. Pure, no network.
|
|
10
|
+
|
|
11
|
+
**`additional_info` on `create_payment` (fraud scoring enrichment)**: `payer` profile (registration_date, authentication_type, is_first_purchase, is_prime_user, last_purchase), `shipments` (receiver_address, express_shipment, local_pickup), `ip_address`, `referral_url`. Per MP RG 5286/2023, payments without enrichment have 3-5x higher rejection rate — this is a real conversion uplift. Documented in tool description so the agent surfaces it proactively.
|
|
12
|
+
|
|
13
|
+
**VercelKVAuditLog (NEW)**: production audit-log adapter in `@ar-agents/mercadopago/vercel-kv` subpath. Storage layout: per-entry key + ZSET indexes by day/actor/tenant for O(log N) time-range queries. Backed by Vercel KV (Upstash Redis).
|
|
14
|
+
|
|
15
|
+
**Migration guide vs `mercadopago` (official SDK)** — `MIGRATION.md` shipped in tarball with side-by-side mappings, conceptual table, "when to use both" section.
|
|
16
|
+
|
|
17
|
+
**CI fixes**: build packages BEFORE typecheck (was failing for facturacion → identity workspace dep with subpath exports). Release workflow now `workflow_dispatch` only (was spamming failure emails on every push because changesets/action couldn't create PRs without explicit repo permission).
|
|
18
|
+
|
|
19
|
+
**New tools**: `validate_tax_id`. Tool count: **87** (was 86).
|
|
20
|
+
|
|
21
|
+
**Quality**: 284 tests pass (was 245; +39 v0.11 tests covering middleware, taxId, and more). publint clean, attw 🟢 across 3 subpaths. Bundle: main 42.9 KB brotli'd (size budget bumped 40→50 KB).
|
|
22
|
+
|
|
23
|
+
## 0.10.0
|
|
24
|
+
|
|
25
|
+
### Minor Changes — Compliance + DX + observability deepening
|
|
26
|
+
|
|
27
|
+
**Audit logging system (NEW)**: `AuditLogger` + `AuditLogAdapter` + `InMemoryAuditLog`. Captures every state-mutating tool call (operation, actor, tenantId, inputHash, outcome, errorCode, resourceId, idempotencyKey, durationMs). PII-conscious by default (`redact: true` hashes input, `redact: false` logs raw). Pluggable storage — InMemory shipped, plug your own Postgres/S3/SIEM.
|
|
28
|
+
|
|
29
|
+
**Webhook idempotency dedup (NEW)**: `WebhookDedup` class short-circuits duplicate MP webhook deliveries. MP retries on 5xx over an 8-day window — without dedup your handler processes the same event 5+ times. TTL default 7 days. Two modes: mark-on-first-sight and at-least-once.
|
|
30
|
+
|
|
31
|
+
**Pagination helpers (NEW)**: `paginate()` generic + 7 typed wrappers (payments, subscriptions, account movements, settlements, merchant orders, plans, subscription payments). AsyncIterable streaming, bounded concurrency, `maxItems` cap.
|
|
32
|
+
|
|
33
|
+
**Token bucket rate limiting (NEW)**: `TokenBucketRateLimiter` — proactive client-side limiter with **adaptive learning** from MP's `x-rate-limit-remaining` headers.
|
|
34
|
+
|
|
35
|
+
**AR issuer cuotas catalog (NEW)**: `AR_ISSUER_PROMOS` + `AHORA_PROGRAM_PROMOS` — embedded knowledge of AR bank promos. 14 issuer promos (Naranja, Galicia, Santander, Macro, BBVA, ICBC, Patagonia, Nación, Provincia, Ciudad). New `find_applicable_promos` tool.
|
|
36
|
+
|
|
37
|
+
**OpenTelemetry instrumentation subpath (NEW)**: `@ar-agents/mercadopago/otel` exports `createOtelHooks({ serviceName })`. Auto-emits spans + histograms + counters + gauges. `@opentelemetry/api` is OPTIONAL peer dep — graceful no-op fallback.
|
|
38
|
+
|
|
39
|
+
**3DS challenge resolution (NEW)**: `confirmChallengeAndPoll()` polls after the buyer completes the issuer challenge. New `confirm_3ds_challenge` tool — completes the FULL 3DS flow.
|
|
40
|
+
|
|
41
|
+
**New tools**: `find_applicable_promos`, `confirm_3ds_challenge`, `search_payments_all`, `list_settlements_all`. Tool count: **86** (was 82).
|
|
42
|
+
|
|
43
|
+
**Quality**: 245 tests pass (was 222). publint clean, attw 🟢 across 3 subpaths (`.`, `/vercel-kv`, `/otel`). Optional peer deps: `@vercel/kv`, `@opentelemetry/api`.
|
|
44
|
+
|
|
3
45
|
## 0.9.0
|
|
4
46
|
|
|
5
47
|
### Minor Changes — Production hardening: circuit breaker, deadline propagation, property-based tests, real MP sandbox integration tests, benchmarks
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Migration guide — `mercadopago` (official SDK) → `@ar-agents/mercadopago`
|
|
2
|
+
|
|
3
|
+
If you're already using MP's official Node SDK and want to switch to (or
|
|
4
|
+
add on top of) the agent toolkit, this guide shows the side-by-side mapping.
|
|
5
|
+
|
|
6
|
+
The agent toolkit is **not** a drop-in replacement — it's a layer ABOVE
|
|
7
|
+
the underlying API designed for AI agents. You can use both packages in
|
|
8
|
+
the same project: keep `mercadopago` for traditional server flows, add
|
|
9
|
+
`@ar-agents/mercadopago` for the agent layer.
|
|
10
|
+
|
|
11
|
+
## Conceptual mapping
|
|
12
|
+
|
|
13
|
+
| `mercadopago` (official) | `@ar-agents/mercadopago` |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `MercadoPagoConfig({ accessToken })` | `new MercadoPagoClient({ accessToken })` |
|
|
16
|
+
| `new Payment(config)` | Same `MercadoPagoClient` (single object, no per-resource client) |
|
|
17
|
+
| `payment.create({ body })` | `client.createPayment(params)` (camelCase params) |
|
|
18
|
+
| `payment.get({ id })` | `client.getPayment(id)` |
|
|
19
|
+
| `payment.search({ options })` | `client.searchPayments(filter)` |
|
|
20
|
+
| `preApproval.create({ body })` | `client.createPreapproval(params)` |
|
|
21
|
+
| `customer.search({ options: { criteria: 'desc', email } })` | `client.searchCustomers({ email })` |
|
|
22
|
+
| Manual webhook signature check | `verifyWebhookSignature({ ... })` (HMAC + replay protection) |
|
|
23
|
+
| Manual idempotency key generation | Auto-generated by tool layer (deterministic SHA-256) |
|
|
24
|
+
| Manual retry logic | Built-in retry budget + circuit breaker |
|
|
25
|
+
| Manual installments display | `findApplicablePromos({ issuer, ... })` |
|
|
26
|
+
|
|
27
|
+
## Side-by-side: create a payment
|
|
28
|
+
|
|
29
|
+
**Before (`mercadopago`):**
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { MercadoPagoConfig, Payment } from "mercadopago";
|
|
33
|
+
|
|
34
|
+
const config = new MercadoPagoConfig({ accessToken: process.env.MP_ACCESS_TOKEN! });
|
|
35
|
+
const payment = new Payment(config);
|
|
36
|
+
|
|
37
|
+
const created = await payment.create({
|
|
38
|
+
body: {
|
|
39
|
+
transaction_amount: 100,
|
|
40
|
+
payment_method_id: "visa",
|
|
41
|
+
payer: { email: "buyer@test.com" },
|
|
42
|
+
token: cardToken,
|
|
43
|
+
description: "Test",
|
|
44
|
+
external_reference: "order-123",
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
console.log(created.id, created.status);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**After (`@ar-agents/mercadopago` — direct client):**
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { MercadoPagoClient } from "@ar-agents/mercadopago";
|
|
54
|
+
|
|
55
|
+
const client = new MercadoPagoClient({ accessToken: process.env.MP_ACCESS_TOKEN! });
|
|
56
|
+
|
|
57
|
+
const created = await client.createPayment({
|
|
58
|
+
transactionAmount: 100, // camelCase
|
|
59
|
+
paymentMethodId: "visa",
|
|
60
|
+
payerEmail: "buyer@test.com", // flat (not nested under `payer`)
|
|
61
|
+
token: cardToken,
|
|
62
|
+
description: "Test",
|
|
63
|
+
externalReference: "order-123",
|
|
64
|
+
});
|
|
65
|
+
console.log(created.id, created.status);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**After (`@ar-agents/mercadopago` — agent tool):**
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { MercadoPagoClient, mercadoPagoTools, InMemoryStateAdapter } from "@ar-agents/mercadopago";
|
|
72
|
+
|
|
73
|
+
const client = new MercadoPagoClient({ accessToken: process.env.MP_ACCESS_TOKEN! });
|
|
74
|
+
const tools = mercadoPagoTools(client, {
|
|
75
|
+
state: new InMemoryStateAdapter(),
|
|
76
|
+
backUrl: "https://yourapp.com/done",
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Tool runs from inside an Agent.generate() call:
|
|
80
|
+
// "Cobrale 100 pesos a buyer@test.com"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Side-by-side: webhook signature verification
|
|
84
|
+
|
|
85
|
+
**Before (`mercadopago`)**: not provided — you implement HMAC-SHA256 yourself
|
|
86
|
+
from the docs.
|
|
87
|
+
|
|
88
|
+
**After (`@ar-agents/mercadopago`):**
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { verifyWebhookSignature, parseWebhookEvent } from "@ar-agents/mercadopago";
|
|
92
|
+
|
|
93
|
+
export async function POST(req: Request) {
|
|
94
|
+
const rawBody = await req.text();
|
|
95
|
+
const event = parseWebhookEvent(JSON.parse(rawBody));
|
|
96
|
+
const verified = await verifyWebhookSignature({
|
|
97
|
+
requestId: req.headers.get("x-request-id"),
|
|
98
|
+
dataId: event!.dataId,
|
|
99
|
+
signatureHeader: req.headers.get("x-signature"),
|
|
100
|
+
secret: process.env.MP_WEBHOOK_SECRET!,
|
|
101
|
+
// 5-min replay protection by default
|
|
102
|
+
});
|
|
103
|
+
if (!verified) return new Response("unauthorized", { status: 401 });
|
|
104
|
+
// ...
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Side-by-side: idempotency
|
|
109
|
+
|
|
110
|
+
**Before (`mercadopago`)**: pass `requestOptions: { idempotencyKey: "..." }`
|
|
111
|
+
manually on each call. You compute the key yourself.
|
|
112
|
+
|
|
113
|
+
**After (`@ar-agents/mercadopago`)**: tools auto-derive a deterministic
|
|
114
|
+
idempotency key from the meaningful inputs (SHA-256 of `external_reference`,
|
|
115
|
+
amount, payment_method, etc.). Same input → same key → MP dedupes safely
|
|
116
|
+
across retries. No manual work.
|
|
117
|
+
|
|
118
|
+
## Side-by-side: retries + timeouts
|
|
119
|
+
|
|
120
|
+
**Before**: implement your own retry loop + AbortController.
|
|
121
|
+
|
|
122
|
+
**After**: built into `MercadoPagoClient`:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
new MercadoPagoClient({
|
|
126
|
+
accessToken: "...",
|
|
127
|
+
requestTimeoutMs: 30_000, // default 30s
|
|
128
|
+
maxRetries: 1, // default 1, retries 5xx + 429
|
|
129
|
+
circuitBreaker: new CircuitBreaker({ failureThreshold: 5 }),
|
|
130
|
+
// Honors Retry-After on 429 automatically
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## What this toolkit adds that the official SDK doesn't have
|
|
135
|
+
|
|
136
|
+
- **Agent tool layer** for Vercel AI SDK 6+ (`mercadoPagoTools()`)
|
|
137
|
+
- **Webhook HMAC + replay protection** (`verifyWebhookSignature` async)
|
|
138
|
+
- **Circuit breaker** with state machine
|
|
139
|
+
- **Deadline propagation** via parent `AbortSignal`
|
|
140
|
+
- **W3C Trace Context** propagation (OpenTelemetry compat sin peer dep)
|
|
141
|
+
- **Audit logging** with pluggable adapter (`AuditLogger` + `InMemoryAuditLog`)
|
|
142
|
+
- **Webhook idempotency dedup** (`WebhookDedup` — short-circuits MP retries)
|
|
143
|
+
- **Pagination helpers** (`paginate()` AsyncIterable for 7 endpoints)
|
|
144
|
+
- **Token bucket rate limiter** with adaptive learning from MP headers
|
|
145
|
+
- **AR issuer cuotas catalog** (`AR_ISSUER_PROMOS`, `findApplicablePromos`)
|
|
146
|
+
- **OpenTelemetry instrumentation subpath** (`@ar-agents/mercadopago/otel`)
|
|
147
|
+
- **Tool middleware pattern** (`withAuditLog`, `withRateLimit`, `withMetrics`, `withRetry`)
|
|
148
|
+
- **3DS challenge resolution** (`confirmChallengeAndPoll`)
|
|
149
|
+
- **TaxID validation cross-LATAM** (DNI/CUIT/CPF/CNPJ/RFC/RUT/NIT/RUC)
|
|
150
|
+
- **Status detail explainer** (`explainPaymentStatus` — Spanish actionable guidance)
|
|
151
|
+
- **Marketplace fee calculator** (`computeMarketplaceFee`)
|
|
152
|
+
- **Vercel KV state adapters** (subscription state + OAuth tokens + idempotency cache + audit log)
|
|
153
|
+
- **Cookbook** with 8 production-grade recipes
|
|
154
|
+
- **Edge Runtime support** (Web Crypto, no `node:crypto`)
|
|
155
|
+
- **Property-based testing** with fast-check (~1500 random scenarios)
|
|
156
|
+
- **Failure injection tests** + integration tests vs MP sandbox
|
|
157
|
+
- **Benchmarks** (`pnpm bench`)
|
|
158
|
+
|
|
159
|
+
## When to keep using `mercadopago` (official) instead
|
|
160
|
+
|
|
161
|
+
- Your codebase is already deeply integrated with the official SDK
|
|
162
|
+
- You don't need the agent layer (no Vercel AI SDK)
|
|
163
|
+
- You operate primarily server-side with cron jobs and don't care about
|
|
164
|
+
agent ergonomics, audit logs, circuit breakers, or status explainers
|
|
165
|
+
|
|
166
|
+
## When to add `@ar-agents/mercadopago`
|
|
167
|
+
|
|
168
|
+
- You're building anything with an AI agent (Claude, GPT, Gemini)
|
|
169
|
+
- You're deploying to Vercel and want first-class KV adapters
|
|
170
|
+
- You need **production-grade webhook handling** (HMAC + dedup + replay protection)
|
|
171
|
+
- You operate a **marketplace** with per-seller OAuth flows
|
|
172
|
+
- You need **compliance-grade audit logging** for refunds/payments
|
|
173
|
+
- You want **AR-specific knowledge** (cuotas catalog, status_detail explainer in Spanish, AR landmines documented)
|
|
174
|
+
- You want **OpenTelemetry-native** observability without writing instrumentation glue
|
|
175
|
+
|
|
176
|
+
You can use BOTH packages in the same project — they don't conflict.
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory record of a subscription. The lib persists the MP-side fields
|
|
3
|
+
* needed to reason about a subscription without hitting the API every time
|
|
4
|
+
* (status, last webhook info, customer email, etc.) plus a free-form metadata
|
|
5
|
+
* bag for callers to attach business context (tenant id, plan name, etc.).
|
|
6
|
+
*/
|
|
7
|
+
interface SubscriptionStateRecord {
|
|
8
|
+
status?: string;
|
|
9
|
+
payerEmail?: string;
|
|
10
|
+
amount?: number;
|
|
11
|
+
currency?: string;
|
|
12
|
+
frequency?: number;
|
|
13
|
+
frequencyType?: string;
|
|
14
|
+
initPoint?: string;
|
|
15
|
+
externalReference?: string;
|
|
16
|
+
createdAt?: string;
|
|
17
|
+
cancelledAt?: string;
|
|
18
|
+
lastWebhookStatus?: string;
|
|
19
|
+
lastWebhookAt?: string;
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Persistence surface for subscription state. Implementations may back this
|
|
24
|
+
* with Upstash Redis, Vercel KV, Postgres, in-memory, or anything that
|
|
25
|
+
* supports the three operations. The default `InMemoryStateAdapter` is
|
|
26
|
+
* provided for tests and trivial single-process deployments; production
|
|
27
|
+
* setups should plug in a durable store.
|
|
28
|
+
*/
|
|
29
|
+
interface SubscriptionStateAdapter {
|
|
30
|
+
set(id: string, state: Partial<SubscriptionStateRecord>): Promise<void>;
|
|
31
|
+
get(id: string): Promise<SubscriptionStateRecord | null>;
|
|
32
|
+
list?(): Promise<string[]>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Volatile, single-process state adapter. Useful for tests and demos. Do not
|
|
36
|
+
* use in production: state is lost on restart and is not safe across tenants.
|
|
37
|
+
*/
|
|
38
|
+
declare class InMemoryStateAdapter implements SubscriptionStateAdapter {
|
|
39
|
+
private readonly store;
|
|
40
|
+
set(id: string, state: Partial<SubscriptionStateRecord>): Promise<void>;
|
|
41
|
+
get(id: string): Promise<SubscriptionStateRecord | null>;
|
|
42
|
+
list(): Promise<string[]>;
|
|
43
|
+
/** Test helper: drop everything. Not part of the adapter interface. */
|
|
44
|
+
reset(): void;
|
|
45
|
+
}
|
|
46
|
+
interface OAuthTokenRecord {
|
|
47
|
+
user_id: string;
|
|
48
|
+
access_token: string;
|
|
49
|
+
refresh_token: string;
|
|
50
|
+
/** Unix-ms timestamp when access_token expires. */
|
|
51
|
+
expires_at: number;
|
|
52
|
+
/** OAuth scope granted, if any. */
|
|
53
|
+
scope?: string;
|
|
54
|
+
/** Optional: any business metadata you want to attach (tenant id, etc.). */
|
|
55
|
+
metadata?: Record<string, unknown>;
|
|
56
|
+
}
|
|
57
|
+
interface OAuthTokenStore {
|
|
58
|
+
/** Persist (or update) the token for `user_id`. */
|
|
59
|
+
set(userId: string, token: OAuthTokenRecord): Promise<void>;
|
|
60
|
+
/** Fetch the stored token, or null if no token registered for that seller. */
|
|
61
|
+
get(userId: string): Promise<OAuthTokenRecord | null>;
|
|
62
|
+
/** Forget a seller's token (e.g., they revoked the app). */
|
|
63
|
+
delete(userId: string): Promise<void>;
|
|
64
|
+
/** Optional: enumerate all sellers (useful for batch refresh jobs). */
|
|
65
|
+
list?(): Promise<string[]>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Volatile, single-process OAuth token store. NOT for production marketplace
|
|
69
|
+
* setups — tokens are lost on restart. Plug in `VercelKVOAuthTokenStore`
|
|
70
|
+
* (from `@ar-agents/mercadopago/vercel-kv`) or your own Postgres-backed
|
|
71
|
+
* implementation.
|
|
72
|
+
*/
|
|
73
|
+
declare class InMemoryOAuthTokenStore implements OAuthTokenStore {
|
|
74
|
+
private readonly store;
|
|
75
|
+
set(userId: string, token: OAuthTokenRecord): Promise<void>;
|
|
76
|
+
get(userId: string): Promise<OAuthTokenRecord | null>;
|
|
77
|
+
delete(userId: string): Promise<void>;
|
|
78
|
+
list(): Promise<string[]>;
|
|
79
|
+
/** Test helper. */
|
|
80
|
+
reset(): void;
|
|
81
|
+
}
|
|
82
|
+
interface IdempotencyCache {
|
|
83
|
+
/** Get the cached response for a key, or null if not present / expired. */
|
|
84
|
+
get<T>(key: string): Promise<T | null>;
|
|
85
|
+
/**
|
|
86
|
+
* Store a response under `key`. `ttlSeconds` defaults to 24h — match MP's
|
|
87
|
+
* own idempotency window so the cache becomes irrelevant once MP would
|
|
88
|
+
* forget anyway.
|
|
89
|
+
*/
|
|
90
|
+
set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
91
|
+
/** Forget a cache entry (force a re-fetch on next call). */
|
|
92
|
+
delete(key: string): Promise<void>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Volatile, single-process idempotency cache. Tests + dev only.
|
|
96
|
+
*/
|
|
97
|
+
declare class InMemoryIdempotencyCache implements IdempotencyCache {
|
|
98
|
+
private readonly store;
|
|
99
|
+
get<T>(key: string): Promise<T | null>;
|
|
100
|
+
set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
101
|
+
delete(key: string): Promise<void>;
|
|
102
|
+
/** Test helper. */
|
|
103
|
+
reset(): void;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Compute SHA-256 hash of `input`. Returns the full 64-char hex digest.
|
|
108
|
+
*
|
|
109
|
+
* Used for deterministic idempotency keys derived from caller-meaningful
|
|
110
|
+
* fields. Truncate the output to 32 chars for storage if needed.
|
|
111
|
+
*/
|
|
112
|
+
declare function sha256Hex(input: string): Promise<string>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Audit logging — financial-grade compliance trail for every state-mutating
|
|
116
|
+
* operation. Captures who/what/when/idempotency_key/before/after/result.
|
|
117
|
+
*
|
|
118
|
+
* # Why this is a tier-1 feature
|
|
119
|
+
*
|
|
120
|
+
* Every mature payment integration has an audit log. The compliance officer
|
|
121
|
+
* asks "show me every refund issued in March 2026 by user X" and you need
|
|
122
|
+
* to answer in <60 seconds. Without an audit log, you're trawling through
|
|
123
|
+
* application logs hoping nothing was filtered out.
|
|
124
|
+
*
|
|
125
|
+
* # What gets logged
|
|
126
|
+
*
|
|
127
|
+
* Every **state-mutating** tool call automatically:
|
|
128
|
+
* - `create_payment`, `charge_saved_card`, `cancel_payment`, `capture_payment`
|
|
129
|
+
* - `refund_payment`
|
|
130
|
+
* - `create_subscription`, `cancel/pause/resume_subscription`, `update_subscription`
|
|
131
|
+
* - `create_order`, `capture_order`, `cancel_order`
|
|
132
|
+
* - `create_payment_preference`, `update_payment_preference`
|
|
133
|
+
* - `create_customer`, `update_customer`, `create_customer_card`, `delete_customer_card`
|
|
134
|
+
* - `create_subscription_plan`, `update_subscription_plan`
|
|
135
|
+
* - `create_store/pos`, `update_store/pos`, `delete_store/pos`
|
|
136
|
+
* - `create_qr_payment`, `cancel_qr_payment`
|
|
137
|
+
* - `create_point_payment_intent`, `cancel_point_payment_intent`, `update_point_device_mode`
|
|
138
|
+
* - OAuth: `oauth_exchange_code`, `oauth_refresh_token`
|
|
139
|
+
* - `register_bank_account`
|
|
140
|
+
* - `create_webhook`, `update_webhook`, `delete_webhook`
|
|
141
|
+
*
|
|
142
|
+
* **Read-only** tools do NOT emit audit entries (would flood the log without
|
|
143
|
+
* value): get_*, search_*, list_*, calculate_*, validate_*, lookup_*, analyze_*.
|
|
144
|
+
*
|
|
145
|
+
* # PII handling
|
|
146
|
+
*
|
|
147
|
+
* The audit log captures `inputSummary` (a deterministic hash of the input
|
|
148
|
+
* fields, NOT the raw input) by default. Configure `redact: false` to log
|
|
149
|
+
* raw inputs (payer email, CUIT, etc.) — only when your data-residency
|
|
150
|
+
* policy permits.
|
|
151
|
+
*
|
|
152
|
+
* # Storage
|
|
153
|
+
*
|
|
154
|
+
* Pluggable adapter pattern. Ships:
|
|
155
|
+
* - `InMemoryAuditLog` — for tests + single-process demos.
|
|
156
|
+
* - `VercelKVAuditLog` (in `/vercel-kv` subpath) — production-ready, KV-backed
|
|
157
|
+
* with daily-bucket indexing for efficient time-range queries.
|
|
158
|
+
*
|
|
159
|
+
* Implement your own for Postgres / S3 / SIEM integration.
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
type AuditOperation = "create_payment" | "charge_saved_card" | "cancel_payment" | "capture_payment" | "refund_payment" | "create_subscription" | "cancel_subscription" | "pause_subscription" | "resume_subscription" | "update_subscription" | "subscribe_to_plan" | "create_subscription_plan" | "update_subscription_plan" | "create_order" | "capture_order" | "cancel_order" | "update_order" | "create_payment_preference" | "update_payment_preference" | "create_customer" | "update_customer" | "create_customer_card" | "delete_customer_card" | "create_store" | "update_store" | "delete_store" | "create_pos" | "update_pos" | "delete_pos" | "create_qr_payment" | "cancel_qr_payment" | "create_point_payment_intent" | "cancel_point_payment_intent" | "update_point_device_mode" | "oauth_exchange_code" | "oauth_refresh_token" | "register_bank_account" | "create_webhook" | "update_webhook" | "delete_webhook" | (string & {});
|
|
163
|
+
interface AuditEntry {
|
|
164
|
+
/**
|
|
165
|
+
* Unique entry id. Format: `mpaud-{ISO date}-{random}`. Use as primary
|
|
166
|
+
* key in your storage layer.
|
|
167
|
+
*/
|
|
168
|
+
id: string;
|
|
169
|
+
/** ISO 8601 timestamp. */
|
|
170
|
+
timestamp: string;
|
|
171
|
+
/** The MP operation performed. */
|
|
172
|
+
operation: AuditOperation;
|
|
173
|
+
/**
|
|
174
|
+
* Logical actor that initiated the call. Caller-provided. Examples:
|
|
175
|
+
* `"agent:billing-bot"`, `"user:42"`, `"cron:daily-charge"`.
|
|
176
|
+
*
|
|
177
|
+
* Defaults to `"unknown"` when not provided. **Always pass this in
|
|
178
|
+
* production** — without it, your compliance trail is meaningless.
|
|
179
|
+
*/
|
|
180
|
+
actor: string;
|
|
181
|
+
/** Optional tenant/seller id for multi-tenant marketplace setups. */
|
|
182
|
+
tenantId?: string;
|
|
183
|
+
/**
|
|
184
|
+
* SHA-256 hex of the meaningful input fields (deterministic). Useful as
|
|
185
|
+
* a join key with the IdempotencyCache. Does NOT contain raw PII.
|
|
186
|
+
*/
|
|
187
|
+
inputHash: string;
|
|
188
|
+
/**
|
|
189
|
+
* Optional raw input — only populated when `redact: false` was configured.
|
|
190
|
+
* Defaults to undefined to comply with data-minimization principles.
|
|
191
|
+
*/
|
|
192
|
+
inputRaw?: Record<string, unknown>;
|
|
193
|
+
/** Outcome: success or error code. */
|
|
194
|
+
outcome: "ok" | "error";
|
|
195
|
+
/** Error code when `outcome === "error"`. */
|
|
196
|
+
errorCode?: string;
|
|
197
|
+
/** Error message when `outcome === "error"`. */
|
|
198
|
+
errorMessage?: string;
|
|
199
|
+
/**
|
|
200
|
+
* MP resource id created/updated by the operation (e.g., payment id).
|
|
201
|
+
* Allows joining audit entries to the actual MP resource.
|
|
202
|
+
*/
|
|
203
|
+
resourceId?: string;
|
|
204
|
+
/** Idempotency key passed to MP (for join with MP-side dedup logs). */
|
|
205
|
+
idempotencyKey?: string;
|
|
206
|
+
/** Duration in ms. */
|
|
207
|
+
durationMs?: number;
|
|
208
|
+
/** Free-form metadata bag. */
|
|
209
|
+
metadata?: Record<string, unknown>;
|
|
210
|
+
}
|
|
211
|
+
interface AuditLogAdapter {
|
|
212
|
+
append(entry: AuditEntry): Promise<void>;
|
|
213
|
+
/** Query a time range. Optional — implementations that don't support it can omit. */
|
|
214
|
+
query?(filter: {
|
|
215
|
+
actor?: string;
|
|
216
|
+
operation?: AuditOperation;
|
|
217
|
+
tenantId?: string;
|
|
218
|
+
from?: string;
|
|
219
|
+
to?: string;
|
|
220
|
+
limit?: number;
|
|
221
|
+
}): Promise<AuditEntry[]>;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Volatile, single-process audit log. Tests + dev only. Production deployments
|
|
225
|
+
* must use a durable adapter (`VercelKVAuditLog`, your Postgres/S3 impl, etc.)
|
|
226
|
+
*/
|
|
227
|
+
declare class InMemoryAuditLog implements AuditLogAdapter {
|
|
228
|
+
private readonly entries;
|
|
229
|
+
append(entry: AuditEntry): Promise<void>;
|
|
230
|
+
query(filter: {
|
|
231
|
+
actor?: string;
|
|
232
|
+
operation?: AuditOperation;
|
|
233
|
+
tenantId?: string;
|
|
234
|
+
from?: string;
|
|
235
|
+
to?: string;
|
|
236
|
+
limit?: number;
|
|
237
|
+
}): Promise<AuditEntry[]>;
|
|
238
|
+
/** All entries (test helper, not part of the adapter interface). */
|
|
239
|
+
all(): AuditEntry[];
|
|
240
|
+
reset(): void;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Audit logger — the user-facing facade that builds + ships entries.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* const audit = new AuditLogger({
|
|
248
|
+
* adapter: new InMemoryAuditLog(),
|
|
249
|
+
* defaultActor: "agent:billing-bot",
|
|
250
|
+
* redact: true, // default — hashes input, no raw PII
|
|
251
|
+
* });
|
|
252
|
+
*
|
|
253
|
+
* const tools = mercadoPagoTools(client, {
|
|
254
|
+
* state, backUrl, audit,
|
|
255
|
+
* });
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare class AuditLogger {
|
|
259
|
+
private readonly adapter;
|
|
260
|
+
private readonly defaultActor;
|
|
261
|
+
private readonly redact;
|
|
262
|
+
private readonly hash;
|
|
263
|
+
constructor(options: {
|
|
264
|
+
adapter: AuditLogAdapter;
|
|
265
|
+
defaultActor?: string;
|
|
266
|
+
redact?: boolean;
|
|
267
|
+
/** Override hash (testing). */
|
|
268
|
+
hashFn?: typeof sha256Hex;
|
|
269
|
+
});
|
|
270
|
+
/**
|
|
271
|
+
* Wrap a tool execute() function with auto-audit. The returned function:
|
|
272
|
+
* 1. Computes inputHash before the call.
|
|
273
|
+
* 2. Invokes the original execute().
|
|
274
|
+
* 3. On success, appends an entry with outcome="ok" + resourceId.
|
|
275
|
+
* 4. On failure, appends an entry with outcome="error" + errorCode/Message.
|
|
276
|
+
* 5. Re-throws the error transparently.
|
|
277
|
+
*/
|
|
278
|
+
record<I, O>(args: {
|
|
279
|
+
operation: AuditOperation;
|
|
280
|
+
input: I;
|
|
281
|
+
actor?: string;
|
|
282
|
+
tenantId?: string;
|
|
283
|
+
idempotencyKey?: string;
|
|
284
|
+
/**
|
|
285
|
+
* Function that extracts the resourceId from the result. Default: tries
|
|
286
|
+
* `result.id`, `result.payment_id`, `result.subscription_id`, `result.order_id`.
|
|
287
|
+
*/
|
|
288
|
+
extractResourceId?: (result: O) => string | undefined;
|
|
289
|
+
/** The actual operation to execute. */
|
|
290
|
+
fn: () => Promise<O>;
|
|
291
|
+
}): Promise<O>;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export { AuditLogger as A, type IdempotencyCache as I, type OAuthTokenRecord as O, type SubscriptionStateAdapter as S, type AuditOperation as a, type AuditEntry as b, type AuditLogAdapter as c, InMemoryAuditLog as d, InMemoryIdempotencyCache as e, InMemoryOAuthTokenStore as f, InMemoryStateAdapter as g, type OAuthTokenStore as h, type SubscriptionStateRecord as i };
|