m's t-paliad-217 Q1 lock-in (2026-05-20): the suggest-changes modal lets
the approver edit EVERY field on the underlying deadline / appointment,
not just the date allowlist that triggers approval. Server-side support
for the wider counter shape:
- buildCounterSetClauses (new) — the counter-allowlist:
deadline: title, due_date, original_due_date, warning_date,
description, notes, rule_code (event_type_ids handled
separately via junction-table rewrite).
appointment: title, start_at, end_at, description, location,
appointment_type.
- buildRevertSetClauses (existing) stays narrow — Reject only restores
what pre_image actually contains (defence-in-depth: a hostile UPDATE
on the request row must not let arbitrary fields be reverted, and
pre_image is server-written so what's in there is what we trust).
- rewriteDeadlineEventTypes — junction-table DELETE+INSERT for the
deadline_event_types m-to-m when counter_payload carries
event_type_ids. Runs in the same tx as the entity UPDATE.
- applyEntityUpdate — switched from buildRevertSetClauses to
buildCounterSetClauses; gained the event_type_ids branch for
deadlines.
- SuggestChanges no-op validator — now uses buildCounterSetClauses
so the wider field set counts as "differs".
- title is treated as NOT NULL — whitespace-only counter title
surfaces ErrSuggestionRequiresChange (defence-in-depth against the
column's own NOT NULL CHECK).
Tests:
- TestApprovalService_SuggestChanges_TitleOnlyCounter — title diff
succeeds; entity title updates.
- TestApprovalService_SuggestChanges_NotesOnlyCounter — notes diff
succeeds; entity notes column populates.
- TestApprovalService_SuggestChanges_EmptyTitleRejected — whitespace-
only title rejected with ErrSuggestionRequiresChange.
No DB migration needed (counter_payload jsonb already accepts arbitrary
shape; the change is in the column-allowlist switch on read).