# TimeCorrectionLog

## Description

TimeCorrectionLog is the **historical-correction journal** — an append-only record of every change made to a Timecard's time data *after* that Timecard has been LOCKED (signed off). Corrections while the covering Timecard is OPEN are handled in the reported layer by supersede (see `ReportedTimeBlock`); while SUBMITTED or APPROVED, a correction attempt is rejected (`TIMECARD_NOT_OPEN`) and requires `reopenTimecard` first. After LOCKED, the period is closed, so any further change must be recorded explicitly as a historical correction, mirroring UKG's post-sign-off historical-correction discipline (issue #7). LOCKED marks the point downstream payroll has consumed the data, so this is the audit boundary past which every change must be journaled rather than merely superseded.

Each entry captures `timecardId`, the optional `targetReportedBlockId` being corrected, the `field` changed, its `previousValue` and `newValue`, a mandatory `reason`, and the actor and timestamp (`correctedBy`, `correctedAt`). Together with effective-dated generations and the approval decision log, this journal is a primary piece of the audit trail that replaces the deprecated `audit` module (ADR-013): it answers "who changed a locked period, from what to what, and why."

## Domain Model Definitions

### Model type

AppendOnly

### Command Definitions

Command docs are out of scope for this design phase (ADR-011). Anticipated commands:

- reopenTimecard — reopening a LOCKED Timecard appends a correction entry (the LOCKED → OPEN status change, the reason, and the actor) and flags the Timecard's historicalCorrection; the actual data correction then flows through the OPEN-state supersede path (CorrectReportedBlock), so the CalculatedTimeBlocks payroll reads are re-derived. There is no direct-edit-while-LOCKED path — a locked period cannot be corrected without reopening

### Query Definitions

- getCorrectionLogEntry — retrieve a single correction entry by id
- listCorrectionsByTimecard — all historical corrections for a Timecard in chronological order, paginated
### Models

- TimeCorrectionLog

### Invariants

- Append-only: an entry is never modified or deleted; the correction trail for a locked period is permanent (ADR-013, ADR-014)
- An entry exists only for a change made against a Timecard in LOCKED state; corrections while the Timecard is OPEN are handled by ReportedTimeBlock supersede, not here, and corrections while SUBMITTED or APPROVED require `reopenTimecard` back to OPEN before they can be made
- Every entry records `previousValue`, `newValue`, a non-empty `reason`, `correctedBy` (a user-management User), and `correctedAt`
- Every entry references the `timecardId` it corrects; `targetReportedBlockId` is present when the correction targets a specific reported block and absent for period-level corrections
- Recording an entry sets the target Timecard's `historicalCorrection` flag, marking the period as changed after sign-off, and applies `newValue` to the corrected total on the Timecard in the same transaction (option A: the log is a pure audit journal, the Timecard is the current snapshot)
- `field`, `previousValue`, and `newValue` describe a single atomic field change; a multi-field correction is expressed as multiple entries

### Relationships

- **Belongs to Timecard**: `timecardId` references the locked Timecard whose period was changed; recording an entry flags that Timecard's `historicalCorrection`
- **References ReportedTimeBlock (optional)**: `targetReportedBlockId` references the specific reported block corrected, when applicable
- **Recorded by User** (user-management): `correctedBy` references the actor who made the historical correction
- **Audit source**: with effective-dated generations and the approval decision log, forms the "who/when/what" trail that replaces the deprecated audit module (ADR-013)
