AlertStatus
Owner context: alerts | Entity: Alert | Field: status | Values: 2
Status of an operational alert raised against a shift (duplicate detection, unusual conditions, etc.). The simplest state machine in the system: a boolean dressed as an enum.
States
| State | Terminal | Description | Entry condition |
|---|---|---|---|
open | No | Alert raised, not yet resolved | Initial state (Alert.create()) |
solved | Yes (sink) | Alert resolved by a user or by the system | Alert.setSolved(userId) |
Helpers: isOpen(), isSolved(). No isFinal(), no canTransition(), no transition matrix.
Transitions
Transition Table
| From | To | Trigger (service) | Invariant / guard | Side effects |
|---|---|---|---|---|
(new) → open | AlertCreator | No pre-existing alert with the same (alertType, shiftId) — deduplicated at creation time | Emits AlertCreatedDomainEvent | |
open → solved | AlertUpdater via AlertsUpdaterController | userId must resolve to an existing user in users | Sets solvedBy to the user id; updates updatedAt |
Invariants
- Initial state is always
open—Alert.create()hardcodesAlertStatus.OPEN. - Only forward — the only transition is
open → solved. There is no reopen, no escalate, no cancel. solvedis a true sink — nothing moves an alert out ofsolved.- Dedup at creation —
AlertCreatorrefuses to insert a second alert with the same(alertType, shiftId)pair. If you see a single alert for a shift, you cannot be sure how many underlying incidents it represents — it was created once and never updated. solvedBycarries two kinds of value — the entity modelsId | null | 'system': a user id, unsolved, or the literal string'system'for automated resolution. TheAlertUpdaterservice only sets user ids; the'system'branch is set elsewhere (admin scripts or batch fixes) and should be documented if it starts being used more actively.- No solved event — only
AlertCreatedDomainEventis emitted. Solving an alert mutates the entity without publishing a domain event. If a consumer needs to react to resolutions, it must poll.
Code Pointers
- Value object: packages/alerts/domain/valueObjects/AlertStatus.ts
- Entity: packages/alerts/domain/entities/Alert.ts (
create,setSolved) - Creation (with dedup): packages/alerts/application/services/AlertCreator.ts
- Resolution: packages/alerts/application/services/AlertUpdater.ts
- HTTP surfaces: packages/alerts/infrastructure/controllers/AlertsUpdaterController.ts, packages/alerts/infrastructure/controllers/UnresolvedAlertsFinderController.ts
- Created event: packages/alerts/domain/events/AlertCreatedDomainEvent.ts
