Three questions before a fixture reaches CI
| Question | Evidence | What it does not establish |
|---|---|---|
| Are these the reviewed bytes? | Byte count and SHA-256 match a trusted reference. | That the reference itself is authentic. |
| Does the record satisfy my consumer? | Explicit version and schema validation. | That the downloaded bytes are unchanged. |
| Is the intended use permitted? | Reviewed provenance, fictional-range policy and delivery isolation. | A live phone line or permission to send a message. |
Our previous contract guide checks record shape. This page checks a different boundary: the bytes stored between a fixture download and its importer. No network or messaging operation occurs in the experiment.
A small, inspectable download baseline
We took the US record from our own country-format dataset at source commit cf0f25be5b00. Its e164Example is +12025550123, with the existing fixtureSafety and sourceUrl pointing to NANPA's limited fictional range. We added the same tutorial envelope used in our contract example: schema_version: 1 and delivery_allowed: false. These additions belong to the sample; they are not new fields in the public dataset.
The downloadable sample is UTF-8 JSON, two-space indentation, LF line endings and one final LF. On Python 3.13.15, the exact published sample has 354 bytes and this SHA-256 digest:
6fb5743dfa03a81bae2ea01f07070a54a2f9d7f5e6044c6f4b9d1e53d309fb25The manifest names that sample, byte count, algorithm, digest, tutorial release and source dataset commit. It covers only this sample file. It is not a signed release manifest for every GetPhoneNum download. Its date identifies the tutorial sample, not a newly released country dataset.
Our six measured download cases
On October 9, 2026 we ran the complete offline script against separate byte strings. JSON parsing is shown as an independent observation, not as the importer gate. The edited digit remains a fictional example; no real recipient is involved.
| Download case | Bytes | JSON parses? | Byte-check outcome |
|---|---|---|---|
| Unchanged sample | 354 | Yes | PASS |
| One phone digit changed; same byte count | 354 | Yes | DIGEST_MISMATCH |
| Last 17 bytes removed | 337 | No | BYTE_COUNT_MISMATCH |
| LF changed to CRLF | 366 | Yes | BYTE_COUNT_MISMATCH |
| JSON parsed and written compactly | 312 | Yes | BYTE_COUNT_MISMATCH |
| Edited sample + newly computed, unapproved manifest | 354 | Yes | PASS |
The equal-length edit passes a size-only check but fails SHA-256. CRLF conversion and compact reserialization both produce the same parsed record as the baseline, yet change its bytes. The truncated sample fails the byte-count check and cannot be parsed. These outcomes describe our exact inputs; they are not estimates of download failures.
We also measured rejection of a manifest with missing required fields, an unsupported md5 algorithm label and a boolean masquerading as a byte count. The script returns MANIFEST_INVALID for each. It accepts only manifest format 1, the named tutorial artifact, a positive integer size within its one-MiB small-file policy and a 64-character lowercase hexadecimal SHA-256 value.
The last row explains why the reference matters
When we edited the sample and recomputed the expected digest from that edited file, the comparison returned PASS. That reference was unapproved. This demonstrates the trust boundary: someone able to replace both the file and the expected hash can make them agree. The check has no way to decide who approved the reference.
Keep the approved manifest in your consumer's reviewed source control, or use your established authenticated release channel and verification process. Review an intended fixture update before changing the expected digest. Do not make a CI job "repair" a mismatch by recomputing its expected hash from the failing download.
The pip documentation makes the related distinction between local, pinned hashes and hashes supplied by the remote download source. We use that boundary as a design principle here; our script does not implement pip, signatures or publisher authentication. A matching digest also does not prove that arbitrary file contents are safe to execute.
Reproduce the experiment without dependencies
Save the Python checker and experiment, sample JSON and manifest JSON in the same folder. Review the small files before executing the script. It uses only the Python standard library and makes no network requests. Run:
python phone-fixture-download-integrity.py --demo
python phone-fixture-download-integrity.py --file phone-fixture-integrity-sample.json --manifest phone-fixture-integrity-manifest.jsonThe first command asserts all six expected outcomes and prints their measured byte counts. The second checks your saved file against your approved manifest; a mismatch, invalid manifest, unreadable file or invalid JSON returns a nonzero exit status. The one-MiB limit is our tutorial policy, not a phone-number standard.
For a consumer that already stores a reviewed manifest, keep the import order explicit:
approved = json.loads(read_bounded(manifest_path, 65536))
payload = read_bounded(download_path, MAX_BYTES) # opens "rb"
outcome = verify_bytes(payload, approved)
if outcome != "PASS":
raise ValueError(outcome)
record = json.loads(payload) # the same bytes, no second file read
# Apply your reviewed consumer schema and safety policy next.Python's hashlib documentation defines the SHA-256 constructor and byte-input interface. Binary reads preserve the stored bytes. This small-file implementation checks and parses one in-memory byte string so a second file read cannot silently switch to a different file. Larger artifacts need their own reviewed memory limit and stable-file handling.
Investigate a mismatch before importing
- Keep the approved reference unchanged. Record the expected release, byte count and digest.
- Record the observed artifact. Keep its actual byte count and digest in the failure report. A mismatch alone does not tell you whether the cause was corruption, transformation or an intentional update.
- Check for byte transformations. Our CRLF and compact-JSON cases show why opening and resaving can invalidate a byte reference.
- Review the source release. Determine whether the provider intentionally changed the artifact. Review provenance and contract changes separately.
- Resume only against an approved baseline. Obtain the reviewed bytes again or explicitly approve the new release. Run the byte, schema and safety checks in order.
Keep fixture metadata in the report; do not include live OTPs or production phone contacts. This page's sample is display/test data with delivery disabled.
FAQ from a real download question
A public developer question asks how to detect damaged downloads when no reference checksum is provided. It is one question signal, not evidence of frequency or the author's location. These answers distinguish the missing reference from parsing and byte-format changes.
Can I verify a download without an expected checksum?
You can calculate its digest and record it, but that alone does not compare it with an approved original. Parsing or a format-specific check may find damage; it does not establish unchanged bytes.
Can a modified phone fixture still be valid JSON?
Yes. Our one-digit edit parses successfully and keeps the byte count, but its digest differs. JSON parsing answers a different question from byte integrity.
Why does resaving unchanged data break a checksum?
Whitespace, key order, encoding or line endings can alter bytes while preserving parsed values. Our CRLF and compact-JSON cases both kept the same parsed record.
Is the checksum downloaded beside the file enough?
It helps compare the two, but it does not authenticate their source. Our replaced-file-and-manifest case passes the comparison against an unapproved reference. Use a separately reviewed or authenticated reference.
Does a matching hash mean a generated number can receive SMS?
No. It says these bytes match the chosen reference. It does not allocate a number, prove reachability or grant delivery permission. Keep schema and safety checks separate and parser tests offline.
Original material: our source-pinned US fixture, exact byte-count/digest manifest, six measured byte transformations, three manifest rejection checks, bounded offline checker and original gate diagram. No search volume, incident rate or publisher authenticity claim is inferred.