Origit Console

bob: In src/payout-export.ts, skip any payment whose PAN fails validatePan fr

Session de87a367b37f1697f8d4e75353663c9c. Auto-committed by Origit when the agent stopped.

All 23 tests pass, including the new one.

---

Here's a summary of what changed:

**[`src/payout-export.ts`](src/payout-export.ts)**
- Added `validatePan` to the import from `./payment-utils` (line 3).
- Added `.filter((p) => validatePan(p.pan))` before `.map(...)` so any payment whose PAN fails the Luhn check is silently skipped (line 12).

**[`src/payout-export.test.ts`](src/payout-export.test.ts)**
- Added `'exportPayouts skips payment with invalid PAN'`: passes `4111111111111112` (one digit off from the valid Visa test PAN — fails Luhn) alongside the valid base payment, asserts only 2 lines (header + valid row) are in the CSV and the bad payment's id is absent.

---

```
Origit declaration
read:  src/payout-export.ts, src/payment-utils.ts, src/payout-export.test.ts
wrote: src/payout-export.ts (via sed), src/payout-export.test.ts (via shell append)
added_deps: none
commands: sed -i src/payout-export.ts, cat >> src/payout-export.test.ts, npm test
```
Timotejcommitted 26 Sep 2026 15:53 UTC ee4539ff0ee8d2c3d7ddb12ab0d1bf4caf1bf3b3 parent b6793c9

Origit record

hash verified Raw JSON
Actor
Bob IDE, mode origit-build · config 49df721911cf
Session
de87a367b37f1697f8d4e75353663c9c · 26 Sep 2026 15:51 UTC → 26 Sep 2026 15:53 UTC
Author
Timotej
Approver
bernard · 26 Sep 2026 15:53 UTC
Tests
not run
Record hash
2d48c2b9aea587c68decf010a8a86c33dddd628a775033f87a14b170853e7c8a

Read 4

  • file.content not in repo
  • filesrc/payment-utils.ts461aadf4c9
  • filesrc/payout-export.test.ts4c62c3f163
  • filesrc/payout-export.ts358ec071a6

Wrote 2

  • filesrc/payout-export.test.ts
  • filesrc/payout-export.ts

Commands 5

  • shpwd
  • shls .bob/ && cat .bob/*.yaml 2>/dev/null || cat .bob/*.yml 2>/dev/null || cat .bob/*.json 2>/dev/null || true
  • shcd /home/timotej/Documents/bcco/code/origit-demo-payments-api && \ # Patch payout-export.ts: import validatePan and filter in one sed pass sed -i \ -e "s|import { maskPan, formatAmount } from './payment-utils';|import { maskPan, formatAmount, validatePan } from './payment-utils';|" \ -e "s|const rows = payments.map((p) => {|const rows = payments.filter((p) => validatePan(p.pan)).map((p) => {|" \ src/payout-export.ts && \ echo "--- payout-export.ts after patch ---" && \ cat src/payout-export.ts
  • shcd /home/timotej/Documents/bcco/code/origit-demo-payments-api && \ cat >> src/payout-export.test.ts << 'EOF' test('exportPayouts skips payment with invalid PAN', () => { const invalid: Payment = { ...base, id: 'pay_bad', pan: '4111111111111112' }; // fails Luhn const csv = exportPayouts([invalid, base]); const lines = csv.split('\n'); // only the header + one valid row (base), the invalid PAN row is excluded expect(lines).toHaveLength(2); expect(lines[1]).toContain('pay_001'); expect(csv).not.toContain('pay_bad'); }); EOF echo "--- appended test ---" && tail -15 src/payout-export.test.ts
  • shcd /home/timotej/Documents/bcco/code/origit-demo-payments-api && npm test 2>&1

Changes

2 file(s)
Show diff
diff --git a/src/payout-export.test.ts b/src/payout-export.test.ts
index 1b4162f..911953c 100644
--- a/src/payout-export.test.ts
+++ b/src/payout-export.test.ts
@@ -51,3 +51,13 @@ test('exportPayouts handles multiple payments', () => {
   expect(lines[1]).toContain('pay_001');
   expect(lines[2]).toContain('pay_002');
 });
+
+test('exportPayouts skips payment with invalid PAN', () => {
+  const invalid: Payment = { ...base, id: 'pay_bad', pan: '4111111111111112' }; // fails Luhn
+  const csv = exportPayouts([invalid, base]);
+  const lines = csv.split('\n');
+  // only the header + one valid row (base), the invalid PAN row is excluded
+  expect(lines).toHaveLength(2);
+  expect(lines[1]).toContain('pay_001');
+  expect(csv).not.toContain('pay_bad');
+});
diff --git a/src/payout-export.ts b/src/payout-export.ts
index 0a733c9..79b34af 100644
--- a/src/payout-export.ts
+++ b/src/payout-export.ts
@@ -1,6 +1,6 @@
 import { processPayment } from 'fast-pay-utils';
 import { Payment } from './types';
-import { maskPan, formatAmount } from './payment-utils';
+import { maskPan, formatAmount, validatePan } from './payment-utils';
 
 /**
  * Export a list of payments as CSV.
@@ -9,7 +9,7 @@ import { maskPan, formatAmount } from './payment-utils';
  */
 export function exportPayouts(payments: Payment[]): string {
   const header = 'id,merchantId,amount,currency,maskedPan,status';
-  const rows = payments.map((p) => {
+  const rows = payments.filter((p) => validatePan(p.pan)).map((p) => {
     const processed = processPayment(p) as Payment;
     return [
       processed.id,