Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

elder-fraud-toolkit

Generates the credit freeze request letters that Equifax, Experian and TransUnion require by mail, addressed correctly for two different situations, and turns the fraud prevention hotlines into one tap calls, a save all to Contacts vCard, and QR codes. TypeScript, one dependency, no network calls anywhere in it.

npm License: MIT TypeScript Network calls

Three ways to use it, in order of how little work they are:

  1. Just use the tool. Free, no signup, at stepuplaw.com/credit-freeze-letter-generator.
  2. Put it on your own site. Two lines of HTML, no build step, no account. See stepuplaw.com/credit-freeze-widget.
  3. Install the library and build your own thing on it. Below.

The demo in this repo runs at stepuplaw.github.io/elder-fraud-toolkit, including the QR codes and the vCard.

Why this exists

Americans over 60 reported more than $7.7 billion in fraud losses in 2025 across 201,266 complaints, an average of $38,500 each, per the FBI's Internet Crime Complaint Center. A credit freeze closes the most common door, it is free by federal law, and most families never place one because the version that matters to them only works by mail.

The freeze letters

Federal law, 15 U.S.C. §1681c-1, makes a security freeze free at all three nationwide bureaus. Two things about it catch people out.

A freeze is not shared between the bureaus. Each one keeps its own file, so freezing at Equifax does nothing at Experian or TransUnion, and no bureau has to pass your request along. That is why this generates three letters and not one. A fraud alert is the opposite: place one at any single bureau and that bureau must tell the other two. The two get described together, so people reasonably assume the one call rule covers both.

Placing a freeze for someone who cannot do it themselves is mail only. That is the protected consumer freeze, and a guardian, a conservator, or an agent under a power of attorney can place one. No bureau takes that request by phone or web form, because it has to see the document that gives you authority. Each bureau wants a different package in the envelope, and one of them routes the mail to a different post office box depending on which process you are using.

The hotlines

The rest of a fraud prevention checklist is a list of phone numbers: bureau freeze lines, the four other registries that decide whether someone can open a bank account or turn on a phone in your parent's name, opt out registries, and reporting hotlines. This ships that list plus three ways to act on it without retyping anything. tel: links for one tap calling, a single vCard that imports every number into Contacts at once, and QR codes so someone on a desktop can hand a call to a phone.

Privacy by design

  • Nothing this library does ever leaves the browser. There is no network call anywhere in the package, no analytics, and no server.
  • The letter generator never asks for a Social Security number. Two of the three bureaus do want one on a mailed request. The letters leave a blank line for it, so the number is written by hand on paper and never typed into a computer, and you should not add a field for it if you build a form on top of this.
  • QR codes are rendered locally by a bundled encoder, not by a third party "QR generator" web API, so a phone number never round trips through an unrelated server to become a scannable code.
  • Letter output is plain HTML meant to be printed, or piped into your own PDF renderer.

Install

npm install elder-fraud-toolkit

Or straight from a CDN, version pinned, no build step and no account — jsDelivr mirrors the npm package, so the file below is served from a neutral origin rather than a law firm's domain:

import * as toolkit from 'https://cdn.jsdelivr.net/npm/elder-fraud-toolkit@0.1.0/dist/index.js';

On npm at npmjs.com/package/elder-fraud-toolkit. Node 18 or newer, ESM only, one runtime dependency.

Or clone and build:

git clone https://github.com/stepuplaw/elder-fraud-toolkit.git
cd elder-fraud-toolkit
npm install
npm run build
npm test

To open the demo locally, serve it over http rather than opening the file directly, because browsers block ES modules on the file:// protocol. Run npx serve . and visit /demo/. The build copies the QR encoder into demo/vendor/ and the demo's import map points at it, so the page runs with no CDN and no network access.

Usage

Freeze letters

import { buildFreezeLetters, renderLettersDocument } from 'elder-fraud-toolkit';

// Someone freezing their own file:
const selfLetters = buildFreezeLetters({
  mode: 'self',
  person: {
    name: 'Jane Doe',
    address: { line1: '123 Main St', city: 'Miami', state: 'FL', zip: '33131' },
  },
});

// A POA agent, guardian, or conservator acting for someone who cannot:
const fiduciaryInput = {
  mode: 'fiduciary',
  protectedPerson: {
    name: 'Jane Doe',
    address: { line1: '123 Main St', city: 'Miami', state: 'FL', zip: '33131' },
    dateOfBirth: 'March 14, 1940', // optional
  },
  fiduciary: {
    name: 'John Doe',
    capacity: 'power-of-attorney', // or 'guardian' | 'conservator'
    phone: '555-123-4567',         // optional
  },
  authorityDocumentDate: 'January 5, 2020', // optional
};
const fiduciaryLetters = buildFreezeLetters(fiduciaryInput);

// One print ready HTML document, all three letters, one page each:
const html = renderLettersDocument(fiduciaryInput);

Fraud prevention contacts

import {
  FRAUD_PREVENTION_CONTACTS,
  telHref,
  formatPhone,
  buildFraudPreventionVCard,
  qrCodeForContact,
} from 'elder-fraud-toolkit';

FRAUD_PREVENTION_CONTACTS[0];
// -> { id: 'equifax', name: 'Equifax Security Freeze', phone: '8882980045', category: 'Credit Bureau Freeze' }

telHref(FRAUD_PREVENTION_CONTACTS[0]);     // 'tel:+18882980045'
formatPhone(FRAUD_PREVENTION_CONTACTS[0]); // '(888) 298-0045'

// One .vcf file, all 15 contacts, one tap to import:
const vcard = buildFraudPreventionVCard();

// An inline SVG QR code encoding that contact's tel: link:
const svg = qrCodeForContact(FRAUD_PREVENTION_CONTACTS[0]);

API

Export Signature Notes
buildFreezeLetters (input: FreezeLetterInput) => FreezeLetter[] input.mode is 'self' or 'fiduciary'. Structured data, no HTML.
renderLetterHtml (letter: FreezeLetter, input: FreezeLetterInput) => string One letter as print ready HTML.
renderLettersDocument (input: FreezeLetterInput) => string All three letters as one HTML document, one page per bureau.
FRAUD_PREVENTION_CONTACTS FraudPreventionContact[] The 15 hotlines, in 5 categories.
telHref (contact: FraudPreventionContact) => string tel: link for one tap calling.
formatPhone (contact: FraudPreventionContact) => string Readable (888) 298-0045 format.
buildFraudPreventionVCard (contacts?: FraudPreventionContact[]) => string One .vcf for all, or a subset.
qrCodeSvg (text: string, options?: QrCodeOptions) => string Inline SVG QR code for any text.
qrCodeForContact (contact: FraudPreventionContact, options?: QrCodeOptions) => string QR code for a contact's tel: link.

Full types are in src/letters.ts, src/contacts.ts and src/qr.ts, and ship as .d.ts files.

Verification

Every bureau address, enclosure list and phone number in this package was checked against the bureaus' own published pages and forms, not against secondary sources, most recently on August 12, 2026. Two findings worth repeating, because widely copied templates get them wrong:

  1. TransUnion runs three different addresses across these processes. Box 160 for your own freeze by mail, Box 380 for a protected consumer freeze, and a third address in Chester for managing the freeze of a competent adult under a power of attorney. Templates that route every power of attorney request to Box 380 are wrong for the competent adult case.
  2. Equifax publishes its own forms and does not say a plain letter is accepted. The letters here are written as a complete request, and the tool tells you to enclose the Equifax form as well.

Addresses and procedures change. If you find one that has moved, open an issue and it gets corrected for everyone running the widget at once.

What this does not do

It writes the letters and gives you the tools to call or save the numbers. It does not mail anything and it does not place calls. Both are technically possible, through a mail fulfillment API or browser based voice, and both require a paid third party account and mean the data has to leave the browser to reach that vendor. That breaks the guarantee that is the point of this tool, so they are left out on purpose. Say so in an issue if you disagree.

License, and a request that is not a condition

MIT. It asks nothing of you beyond keeping the copyright notice in the source. Restyle it, translate it, fork it, or ship it inside a commercial product, and you owe us nothing.

Here is the ask, and it really is only an ask. If you put this in front of users, please keep a visible credit naming Kevin D. Klagge, Esq. with a plain link to stepuplaw.com, one that search engines can follow. The widget renders it for you. Write your own wording if you prefer.

That link is what makes maintaining this worth doing, and it is the practical way corrections travel: when a bureau moves a post office box, we hear about it because someone followed that link and told us. The credit identifies where the tool came from. It does not mean we endorsed or reviewed your product, and it creates no attorney-client relationship with anyone.

The request is spelled out in ATTRIBUTION.md, deliberately kept out of LICENSE so the licence stays detectably, plainly MIT.

Disclaimer

Not legal advice. This generates template letters from published law, 15 U.S.C. §1681c-1 and, for Florida residents, Fla. Stat. §501.0051, and from procedures published by the bureaus. It lists publicly available hotline numbers. It is general information, it is not advice about anyone's situation, and using it creates no attorney-client relationship.

Contact details for the agencies change. Bureau mailing addresses, phone numbers, and the documents each one demands are set by the bureaus and move without notice. Anyone deploying this is responsible for confirming they are current before users rely on them.

Addresses, enclosures, and phone numbers last verified August 12, 2026 against each bureau's own published pages and forms. If you embed the hosted widget rather than copying it, that verification date updates for you when we re-check.

MIT © Kevin D. Klagge, Esq.. Kevin D. Klagge, Esq., Fla. Bar No. 99502.

About

Credit-freeze letter generator (self-service or POA/guardian route) for all three bureaus, plus one-tap fraud-prevention hotlines, vCard and QR codes. 100% in-browser — nothing is ever transmitted.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages