A readonly class that survived a requirements change

A value object made readonly in 2022, and the requirement in 2026 that would have broken a mutable one.

final readonly class TaxRate
{
    public function __construct(
        public string $jurisdiction,
        public int $basisPoints,
        public DateTimeImmutable $effectiveFrom,
    ) {}
}

// the change: rates become time-varying, so a rate is
// now looked up for a date rather than held.
//
// because it is immutable, every existing instance is
// still valid — they are values at a point in time.
// a mutable one would have been updated in place
// somewhere, and the historical figures would have
// moved.

The property that mattered was not thread safety or defensive copying — it was that a value which cannot change cannot be retroactively wrong. Reports run against orders from 2023 still produce the 2023 figures, which is the requirement nobody stated and immutability satisfied by accident.