Receipt-driven architecture: making decisions visible
How Phosphor's receipt system turns implicit colour interpretation into an explicit, inspectable artifact, and why every media tool should work this way.
Every video player makes colour decisions. Most of them hide those decisions behind “auto” modes, best-guess defaults, and undocumented fallback chains. When footage looks different between two players, the answer is always the same: they interpreted the colour metadata differently, and neither told you what it decided.
Phosphor takes a different approach. Every interpretation decision is recorded in a receipt, a structured artifact that documents what was probed, what was assumed, what was overridden, and why.
Same file, two players. The only difference is how they interpreted the colour metadata. Neither told you what it decided.
The four-tier precedence chain
When Phosphor opens a media file, it resolves colour parameters (primaries, transfer function, matrix coefficients, sample range) through four tiers of precedence:
- Profile. An explicit override file that says “this footage is ARRI LogC4 / Wide Gamut 4, period.” Highest authority.
- Tagged. Colour metadata embedded in the container or codec headers (colour_primaries, transfer_characteristics, matrix_coefficients in H.264/H.265).
- Inferred. Rules derived from camera identification, codec family, or resolution patterns. “This is a RED .R3D file, so it’s REDWideGamutRGB / Log3G10.”
- Fallback. The conservative default when nothing else applies. Rec. 709, full range, no CDL.
The receipt records which tier won for each parameter. You can see at a glance: “primaries came from the profile, transfer was tagged in the container, matrix was inferred from the codec, range used the fallback.”
Why receipts matter
A receipt is not a log. It’s not debug output. It’s a first-class artifact with specific properties:
- Deterministic: same file + same profile = same receipt, always
- Diffable: compare two receipts to see exactly where interpretations diverge
- Portable: share a receipt with a colleague to reproduce your viewing conditions
- Hashable: the receipt has a content hash, so you can verify it hasn’t been tampered with
The limitations vector
Sometimes a transform can’t be applied. The OCIO config isn’t loaded. The display doesn’t support the requested gamut. The CDL values are out of range for the target space.
Most systems either silently skip the transform or throw an error. Phosphor records a limitation, a structured note explaining what couldn’t be applied and why. The receipt carries both what happened and what didn’t happen.
This might seem like over-engineering until the first time you’re debugging a colour mismatch between two facilities and the receipt tells you: “CDL was applied on machine A but skipped on machine B because the OCIO config didn’t include the required look transform.” That’s not a log message you’d go hunting for. It’s right there in the receipt.
Building on receipts
The receipt pattern isn’t specific to colour. Any system that makes interpretation decisions (audio level normalisation, timecode resolution, metadata inference) benefits from making those decisions explicit and portable.
The key insight: the receipt is the interface. It’s what you share, diff, and version. The probe data is an implementation detail. The playback is a consequence. The receipt is the thing.