feat(canopy-persons): historical income versioning with superseded_by pointer

Source: canopy-web-persons-wiring plan Potential Improvements.

The Income model has effective_date / end_date but no superseded_by pointer. For Pub 1075 audit trails and SNAP QC sampling, a worker's correction of a past income entry should leave both the original and the corrected row queryable, with the relationship explicit. This is closer to event-sourcing the income history than today's mutate-in-place approach.

Acceptance: income.superseded_by UUID NULL REFERENCES income(id) migration; PUT/PATCH on income inserts a new row + sets the superseded_by FK rather than mutating; query helper returns the as-of-date snapshot.

Depends on: a workflow design discussion before implementation (consider event-sourcing tradeoffs).