@ar-agents/mercadopago 0.10.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.
@@ -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 };