# credit-card strategy ## Purpose The `credit-card` masking strategy produces the PCI-DSS-compatible truncation format for payment card numbers: last 4 digits visible, all preceding digit positions replaced with `*`, formatting separators preserved. This aligns with the PCI DSS 4.0 requirement that primary account numbers (PANs) must be rendered unreadable in logs and displays, while retaining just enough information for card identification and customer service operations. ## Features - Last-4-digit preservation regardless of separator style. - Hyphens, spaces, and other non-digit characters pass through unchanged. - Handles formatted (`4111-1111-1111-1111`) and raw (`4111111111111111`) inputs. - No regex capture groups — single linear pass, O(n) complexity. ## Usage: Basic Example ```ts import { maskCreditCard } from '@suaveplan/data-masking/strategies/credit-card'; const masked = maskCreditCard('4111-1111-1111-1111', { fields: ['cardNumber'], strategy: 'credit-card', }); // masked → '****-****-****-1111' ``` ## Usage: Advanced Example ```ts import { maskCreditCard } from '@suaveplan/data-masking/strategies/credit-card'; // No separators maskCreditCard('5500005555555559', { fields: ['pan'], strategy: 'credit-card' }); // → '************5559' // Space-separated format maskCreditCard('4111 1111 1111 1111', { fields: ['pan'], strategy: 'credit-card' }); // → '**** **** **** 1111' // Amex 15-digit maskCreditCard('3714 496353 98431', { fields: ['pan'], strategy: 'credit-card' }); // → '**** ****** *8431' // No digits at all → passthrough maskCreditCard('CARD-ON-FILE', { fields: ['pan'], strategy: 'credit-card' }); // → 'CARD-ON-FILE' ``` ## API Reference ### `maskCreditCard(value, rule)` ```ts function maskCreditCard(value: string, rule: MaskRule): string; ``` | Parameter | Type | Description | |-----------|------------|-----------------------------------------------------------| | `value` | `string` | The original card number in any format. | | `rule` | `MaskRule` | Driving rule (no fields consumed by credit-card strategy).| **Returns** the masked card number with last 4 digits preserved and all other digit positions replaced by `*`. **Does not throw.** Returns the original value unchanged when no digit characters are found. ## Implementation Notes - The algorithm is identical in structure to the `phone` strategy: extract all digits to find the `keepFrom` threshold, then rebuild the string in a single pass. The two strategies are kept as separate files to allow divergent evolution (e.g. future BIN-preservation or Luhn-check validation in the credit-card variant). - `Math.max(0, digits.length - 4)` ensures cards with 4 or fewer digits are returned unchanged, consistent with the principle of least surprise. - The `rule` parameter is silently voided to satisfy the uniform strategy interface; no `MaskRule` fields are read.