# PipelineStageTransition

## Description

PipelineStageTransition is an append-only audit log that records every stage-to-stage movement of an item. Each entry captures the item, the source stage, the destination stage, the user who initiated the move, and the event time. The standard `createdAt` timestamp doubles as the move time -- rows are immutable, so no separate moved-at field is needed (mirroring [PipelineItemChange](./PipelineItemChange.md)). These records are immutable once created and enable analytics such as cycle time calculation, stage duration reporting, conversion rates, and bottleneck detection.

## Domain Model Definitions

### Model type

AppendOnly

### Command Definitions

- None (entries are created internally by [MovePipelineItem](../command/MovePipelineItem.md))

### Query Definitions

- [ListPipelineStageTransitionsByItem](../query/ListPipelineStageTransitionsByItem.md) - List all stage transitions for an item, ordered by createdAt

### Models

- PipelineStageTransition

### Invariants

- PipelineItem ID is required and must reference an existing item
- From-stage ID is required and must reference an existing stage
- To-stage ID is required and must reference an existing stage
- From-stage and to-stage must be different (moving an item to its current stage is rejected with SAME_STAGE and does not create a record)
- Moved-by user ID is required
- The event timestamp is `createdAt`, set automatically at creation time (no separate moved-at field)
- Records are immutable -- they cannot be updated or deleted after creation

### Relationships

- **Belongs To PipelineItem**: Each transition belongs to an item via `itemId`
- **References PipelineStage (from)**: Each transition records the source stage via `fromStageId`
- **References PipelineStage (to)**: Each transition records the destination stage via `toStageId`
- **References User**: Each transition records which user initiated the move via `movedByUserId` from the user-management module
