@visa/cli 4.1.0-rc.254 → 4.1.0-rc.255

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.
@@ -159,9 +159,10 @@ export declare class MandateLedger {
159
159
  applyApprovedCeiling(mandateId: string, approvedCeilingMinor: number): Promise<CardMandateRecord>;
160
160
  /**
161
161
  * Atomically reserve headroom for a draw. Fail-closed: refuses when the
162
- * mandate is unknown, expired, or the amount exceeds remaining headroom. The
163
- * reservation counts against availability immediately, closing the window in
164
- * which two concurrent draws both see the same remaining balance.
162
+ * mandate is unknown, retired, expired, or the amount exceeds remaining
163
+ * headroom. The reservation counts against availability immediately, closing
164
+ * the window in which two concurrent draws both see the same remaining
165
+ * balance.
165
166
  */
166
167
  reserve(mandateId: string, amountMinor: number, now?: Date): Promise<string>;
167
168
  /** Commit a reservation to permanent spend and record the payable draw. */
@@ -325,9 +325,10 @@ export class MandateLedger {
325
325
  }
326
326
  /**
327
327
  * Atomically reserve headroom for a draw. Fail-closed: refuses when the
328
- * mandate is unknown, expired, or the amount exceeds remaining headroom. The
329
- * reservation counts against availability immediately, closing the window in
330
- * which two concurrent draws both see the same remaining balance.
328
+ * mandate is unknown, retired, expired, or the amount exceeds remaining
329
+ * headroom. The reservation counts against availability immediately, closing
330
+ * the window in which two concurrent draws both see the same remaining
331
+ * balance.
331
332
  */
332
333
  reserve(mandateId, amountMinor, now = new Date()) {
333
334
  return this.run(async () => {
@@ -338,6 +339,15 @@ export class MandateLedger {
338
339
  const record = file.mandates.find((m) => m.mandateId === mandateId);
339
340
  if (!record)
340
341
  throw new Error(`no such mandate ${mandateId}`);
342
+ if (record.serverRevokedAt) {
343
+ throw new Error(`mandate ${mandateId} was server-revoked at ${record.serverRevokedAt}`);
344
+ }
345
+ if (record.registerFailedAt) {
346
+ throw new Error(`mandate ${mandateId} registration failed at ${record.registerFailedAt}`);
347
+ }
348
+ if (record.unhonoredAt) {
349
+ throw new Error(`mandate ${mandateId} was unhonored at ${record.unhonoredAt}`);
350
+ }
341
351
  if (isExpired(record, now)) {
342
352
  throw new Error(`mandate ${mandateId} expired at ${record.expiresAt}`);
343
353
  }
@@ -360,6 +370,11 @@ export class MandateLedger {
360
370
  const record = file.mandates.find((m) => m.mandateId === mandateId);
361
371
  if (!record)
362
372
  throw new Error(`no such mandate ${mandateId}`);
373
+ // Revocation is authoritative even when it arrives after reserve(). Keep
374
+ // the reservation intact so this refusal cannot be mistaken for a commit.
375
+ if (record.serverRevokedAt) {
376
+ throw new Error(`mandate ${mandateId} was server-revoked at ${record.serverRevokedAt}`);
377
+ }
363
378
  const idx = record.reservations.findIndex((r) => r.reservationId === reservationId);
364
379
  if (idx === -1) {
365
380
  throw new Error(`reservation ${reservationId} is not open (already committed or released)`);