> ## Documentation Index
> Fetch the complete documentation index at: https://docs.comforthub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# How card numbers stay out of texts and transcripts

> The engine masks a card number the moment it is written, and an hourly scan opens an urgent condition if one ever slips through

export const Touches = ({systems}) => <p>
    <strong>Systems involved:</strong>{" "}
    {systems.split(",").map((s, i) => <span key={s}>
        {i > 0 ? " · " : ""}
        <a href={"/systems/" + s.trim()}>{s.trim().replace(/-/g, " ")}</a>
      </span>)}
  </p>;

<Touches systems="twilio, supabase-backend, sentry" />

A customer sometimes texts a card number or reads one out to voicemail. The engine never keeps it. Every text in or out, every voicemail transcript and every line of a call transcript is masked on the way in, so what the app shows, what the push notification carries and what the CRM receives is already clean.

## What a masked message looks like

| Written by the customer                    | Kept by the engine                       |
| ------------------------------------------ | ---------------------------------------- |
| my visa card number is 4242 4242 4242 4242 | my visa card number is `[CARD ****4242]` |
| expiry 12/28                               | expiry `[EXP]`                           |
| cvv 123                                    | cvv `[CVV]`                              |

The last four digits are kept so the office can still say "the card ending 4242". A security code is masked when it follows words like "cvv" or "security code", and an expiry when it follows words like "expiry" or "valid thru"; both are also caught when dictated right after a card number.

## How the engine decides a number is a card

A phone number or an invoice number must be left alone, so a run of 13 to 19 digits counts as a card only when both of these hold:

* it passes the checksum every real card number passes, and
* it is written as four groups of four, or there are payment words nearby, such as "visa", "credit card", "card number", "expiry" or "cvv".

Digits spoken as words ("four two four two…") are joined up and checked the same way.

An expiry read out in words, such as "December twenty-eight", is not masked. A card number read out in words is.

## The hourly scan

Every hour, at 45 minutes past, the monitor re-reads every stored text, voicemail transcript and call transcript. For each row that still holds a card number it opens an urgent condition in Sentry naming the row and the fix: redact the record in place, repair the write-time guard, and confirm the scan is clear. The card itself is never in the condition. See [How the monitor works](/handbook/running/how-the-monitor-works).

## When a text is removed

The **Messages** list shows, for each conversation, the newest text and when it arrived. When a text is deleted, that line is rebuilt from the texts that remain: the newest remaining text becomes the preview, and the conversation counts as unread only if an incoming text is still there. The app offers no way to delete a text: only a developer can delete one, in the engine. Hiding a conversation from your own list, which the app does offer, removes nothing.

## Related

* [How the phone works](/handbook/phone/how-the-phone-works)
* [How the monitor works](/handbook/running/how-the-monitor-works)
* [Monitor checks](/reference/monitor-checks)
