FAILURE MAP
← Case archive

FA-96481 / Phone number formatting / Open access

Display masking of subscriber digits: four-digit numbers are shown in full · case 01

"+8 1122" is displayed unmasked.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The short-number rule uses < 4, so exactly four digits count as long.

THE FAILURE

The short-number rule uses < 4, so exactly four digits count as long.

Unsuccessful approach: Raising the threshold to five fully masks numbers that should show four digits.

Case contract

Strip. A leading "+" and the digits right after it (the country code) are shown. Among the remaining digits only the last four are shown and the others become "*"; separators are kept. If four or fewer digits remain they are all masked.

Why this case matters

Masked numbers appear in receipts, logs and support tools; revealing too much leaks personal data and revealing too little makes verification impossible.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    cc_end = 0
    if s.startswith('+'):
        cc_end = 1
        while cc_end < len(s) and s[cc_end].isdigit():
            cc_end += 1
    head, body = s[:cc_end], s[cc_end:]
    total = sum(c.isdigit() for c in body)
    if total < 4:
        return head + ''.join('*' if c.isdigit() else c for c in body)
    seen, out = 0, []
    for c in body:
        if c.isdigit():
            seen += 1
            out.append(c if seen > total - 4 else '*')
        else:
            out.append(c)
    return head + ''.join(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['international with country code kept', '+42 555 010 1123', '+42 *** *** 1123'], ['three-digit code with hyphen', '+891 555-0114', '+891 ***-0114'], ['four subscriber digits are fully masked', '+8 1122', '+8 ****'], ['five subscriber digits', '+83 11123', '+83 *1123'], ['national number without code', '555 0115', '*** 0115'], ['parenthesized area', '+42 (555) 0112', '+42 (***) 0112'], ['hyphenated national number', '555-010-1122', '***-***-1122']], [['international with country code kept', '+42 555 010 1234', '+42 *** *** 1234'], ['three-digit code with hyphen', '+891 555-0125', '+891 ***-0125'], ['four subscriber digits are fully masked', '+8 2233', '+8 ****'], ['five subscriber digits', '+83 22234', '+83 *2234'], ['national number without code', '555 0126', '*** 0126'], ['parenthesized area', '+42 (555) 0123', '+42 (***) 0123'], ['hyphenated national number', '555-010-2233', '***-***-2233']], [['international with country code kept', '+42 555 010 1345', '+42 *** *** 1345'], ['three-digit code with hyphen', '+891 555-0136', '+891 ***-0136'], ['four subscriber digits are fully masked', '+8 3344', '+8 ****'], ['five subscriber digits', '+83 33345', '+83 *3345'], ['national number without code', '555 0137', '*** 0137'], ['parenthesized area', '+42 (555) 0134', '+42 (***) 0134'], ['hyphenated national number', '555-010-3344', '***-***-3344']], [['international with country code kept', '+42 555 010 1456', '+42 *** *** 1456'], ['three-digit code with hyphen', '+891 555-0147', '+891 ***-0147'], ['four subscriber digits are fully masked', '+8 4455', '+8 ****'], ['five subscriber digits', '+83 44456', '+83 *4456'], ['national number without code', '555 0148', '*** 0148'], ['parenthesized area', '+42 (555) 0145', '+42 (***) 0145'], ['hyphenated national number', '555-010-4455', '***-***-4455']], [['international with country code kept', '+42 555 010 1567', '+42 *** *** 1567'], ['three-digit code with hyphen', '+891 555-0158', '+891 ***-0158'], ['four subscriber digits are fully masked', '+8 5566', '+8 ****'], ['five subscriber digits', '+83 55567', '+83 *5567'], ['national number without code', '555 0159', '*** 0159'], ['parenthesized area', '+42 (555) 0156', '+42 (***) 0156'], ['hyphenated national number', '555-010-5566', '***-***-5566']]]
for label, arg, expected in fixtures[N - 1]:
    check(label, solve(arg), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
international with country code kept+42 *** *** 1123+42 *** *** 1123Passed
three-digit code with hyphen+891 ***-0114+891 ***-0114Passed
four subscriber digits are fully masked+8 1122+8 ****Failed
five subscriber digits+83 *1123+83 *1123Passed
national number without code*** 0115*** 0115Passed
parenthesized area+42 (***) 0112+42 (***) 0112Passed
hyphenated national number***-***-1122***-***-1122Passed

SHA-256 / 6ed102a3309d6152bba7cbeae17c390dd63d5c74fdff3a0c75321295293d789a

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    cc_end = 0
    if s.startswith('+'):
        cc_end = 1
        while cc_end < len(s) and s[cc_end].isdigit():
            cc_end += 1
    head, body = s[:cc_end], s[cc_end:]
    total = sum(c.isdigit() for c in body)
    if total <= 5:
        return head + ''.join('*' if c.isdigit() else c for c in body)
    seen, out = 0, []
    for c in body:
        if c.isdigit():
            seen += 1
            out.append(c if seen > total - 4 else '*')
        else:
            out.append(c)
    return head + ''.join(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['international with country code kept', '+42 555 010 1123', '+42 *** *** 1123'], ['three-digit code with hyphen', '+891 555-0114', '+891 ***-0114'], ['four subscriber digits are fully masked', '+8 1122', '+8 ****'], ['five subscriber digits', '+83 11123', '+83 *1123'], ['national number without code', '555 0115', '*** 0115'], ['parenthesized area', '+42 (555) 0112', '+42 (***) 0112'], ['hyphenated national number', '555-010-1122', '***-***-1122']], [['international with country code kept', '+42 555 010 1234', '+42 *** *** 1234'], ['three-digit code with hyphen', '+891 555-0125', '+891 ***-0125'], ['four subscriber digits are fully masked', '+8 2233', '+8 ****'], ['five subscriber digits', '+83 22234', '+83 *2234'], ['national number without code', '555 0126', '*** 0126'], ['parenthesized area', '+42 (555) 0123', '+42 (***) 0123'], ['hyphenated national number', '555-010-2233', '***-***-2233']], [['international with country code kept', '+42 555 010 1345', '+42 *** *** 1345'], ['three-digit code with hyphen', '+891 555-0136', '+891 ***-0136'], ['four subscriber digits are fully masked', '+8 3344', '+8 ****'], ['five subscriber digits', '+83 33345', '+83 *3345'], ['national number without code', '555 0137', '*** 0137'], ['parenthesized area', '+42 (555) 0134', '+42 (***) 0134'], ['hyphenated national number', '555-010-3344', '***-***-3344']], [['international with country code kept', '+42 555 010 1456', '+42 *** *** 1456'], ['three-digit code with hyphen', '+891 555-0147', '+891 ***-0147'], ['four subscriber digits are fully masked', '+8 4455', '+8 ****'], ['five subscriber digits', '+83 44456', '+83 *4456'], ['national number without code', '555 0148', '*** 0148'], ['parenthesized area', '+42 (555) 0145', '+42 (***) 0145'], ['hyphenated national number', '555-010-4455', '***-***-4455']], [['international with country code kept', '+42 555 010 1567', '+42 *** *** 1567'], ['three-digit code with hyphen', '+891 555-0158', '+891 ***-0158'], ['four subscriber digits are fully masked', '+8 5566', '+8 ****'], ['five subscriber digits', '+83 55567', '+83 *5567'], ['national number without code', '555 0159', '*** 0159'], ['parenthesized area', '+42 (555) 0156', '+42 (***) 0156'], ['hyphenated national number', '555-010-5566', '***-***-5566']]]
for label, arg, expected in fixtures[N - 1]:
    check(label, solve(arg), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
international with country code kept+42 *** *** 1123+42 *** *** 1123Passed
three-digit code with hyphen+891 ***-0114+891 ***-0114Passed
four subscriber digits are fully masked+8 ****+8 ****Passed
five subscriber digits+83 *****+83 *1123Failed
national number without code*** 0115*** 0115Passed
parenthesized area+42 (***) 0112+42 (***) 0112Passed
hyphenated national number***-***-1122***-***-1122Passed

SHA-256 / 71e4031bd4dd51abda08fdae35a852bea89e79d9394bdb11b4254ae4ad57d9a6

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 7 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

A deterministic toy contract over synthetic, obviously fictitious telephone numbers and toy country tables. The rules are stipulated for this model only and make no claim of conformance with any numbering plan or telecommunications standard. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:52:23.240204+00:00.

Case digest / b0ffa1de56b5c4f3fea3ba59332d80ca24313363f8ebe3f00f20cb14247a2131