Noticed while fixing #108 (PR #154), which filters soft-deleted tracks out of the portal picker.
The inconsistency
Milestone (src/modules/competitions/data/entities.ts:525) has no deleted_at column. Its
siblings in the same file all do — Competition, CompetitionParticipation, PortalLocalePreference,
ParticipantProfile, AgendaItem, Announcement, CompetitionInfoCard each declare:
@Property({ name: 'deleted_at', type: 'timestamptz', nullable: true })
deletedAt?: Date | null
So milestones cannot be soft-deleted anywhere: deleting one is either a hard delete or not offered.
Why it is worth a decision rather than a patch
Two readings, with different fixes:
- Intended. Milestones are cheap, schedule-shaped records with no downstream references worth
preserving, so a hard delete is fine. Then nothing needs changing — but it would help to say so,
because every adjacent entity sets the opposite expectation and the next person to touch this will
assume the column was forgotten.
- An oversight. Milestones are referenced by participant-facing deadlines and a hard delete
silently changes what participants were told. Then Milestone needs a deleted_at column, a
migration, and the delete path plus every read filter updated — which is an entity change, so it
needs confirmation before an agent touches it (AGENTS.md CRITICAL rule 1).
Filing this to get the call made rather than guessing. Note that issue #108 was written assuming
milestones could be soft-deleted, which is some evidence for reading 2.
Noticed while fixing #108 (PR #154), which filters soft-deleted tracks out of the portal picker.
The inconsistency
Milestone(src/modules/competitions/data/entities.ts:525) has nodeleted_atcolumn. Itssiblings in the same file all do —
Competition,CompetitionParticipation,PortalLocalePreference,ParticipantProfile,AgendaItem,Announcement,CompetitionInfoCardeach declare:So milestones cannot be soft-deleted anywhere: deleting one is either a hard delete or not offered.
Why it is worth a decision rather than a patch
Two readings, with different fixes:
preserving, so a hard delete is fine. Then nothing needs changing — but it would help to say so,
because every adjacent entity sets the opposite expectation and the next person to touch this will
assume the column was forgotten.
silently changes what participants were told. Then
Milestoneneeds adeleted_atcolumn, amigration, and the delete path plus every read filter updated — which is an entity change, so it
needs confirmation before an agent touches it (AGENTS.md CRITICAL rule 1).
Filing this to get the call made rather than guessing. Note that issue #108 was written assuming
milestones could be soft-deleted, which is some evidence for reading 2.