Startup Validation
Cohort would rather not start than run a retention model it can't execute safely. Everything on this page is checked when the host starts, before any row is touched. A failure names the entity and the problem.
Annotations and identity
- Every retained entity has a
[RetentionEntityId]. Missing, empty, malformed and duplicate identities are rejected. - An entity can't be both
[Retain]and[ExemptFromRetention]. - Each convention marker attribute (
[RetentionRecordId],[RetentionTenant],[RetentionSoftDelete],[RetentionDeletedAt],[RetentionAnonymisedAt]) appears on at most one property. [RetentionTenantless]isn't combined with a tenant property. Otherwise the tenant property would win and the marker would be silently ignored.
Rules and capabilities
- The union of strategies each category declares in
GetCapabilitiesis checked against every entity in it. For example, an entity that may be anonymised needs anAnonymisedAtmarker, and one that may be soft-deleted needs a soft-delete flag. - At run time, a rule whose strategy wasn't declared is rejected.
RetentionRulerejects a negativePeriodorLegalMin, which would compute a future cutoff and sweep everything.[AnonymiseWith]factories are registered exactly once asIAnonymiseValueFactory.[ErasureSubject(kind)]kinds aren't blank, every column of one kind holds the same CLR type across the model, and each marked property maps to a physical column with a compatible provider type.
Mapping shapes
Cohort mutates one independently owned table per retained entity, and won't guess which columns or rows belong to it. So these are rejected:
- retained owned types
- entities sharing a table with another EF type
- entities split across multiple tables
- entities in an EF inheritance hierarchy (TPH, TPT or TPC), because sweep SQL targets the table without a discriminator
Columns
- Anchor,
DeletedAtandAnonymisedAtcolumns map totimestamp with time zone(timestamptzand precision variants are fine). Cohort compares and writes retention timestamps as UTC instants, and a naivetimestamp without time zonecolumn silently drifts with the session time zone. - Tenant, anchor, soft-delete, deleted-at and anonymised-at properties don't use EF value converters. Cohort filters and writes those columns in SQL, where a converter wouldn't apply.
- A record ID that isn't the primary key is unique through an alternate key or an unfiltered unique index. A filtered index doesn't make it unique.
- Record-ID types whose text form depends on session settings are rejected. See Identities.
Foreign keys
- No
ON DELETE CASCADEforeign key leads from a purgeable retained entity into another retained entity. A cascade would bypass the dependent's retention window, holds and audit trail. - No cascade leads from a purgeable retained entity back into a retained type, including itself through a self-reference.
- Retained entities can't form a foreign-key cycle. Cohort sweeps dependents before their principals, so it needs an order.