fix(coach): feedback references coach_messages, drops plaintext column

Reviewer note: W5 H7 wrote Coach assistant prose plaintext into
recommendation_feedback.recommendation_text. Same prose lives
encrypted in coach_messages — backups captured the leak.

Migration 0042_coach_feedback_message_ref adds nullable coachMessageId
(FK + cascade) and drops recommendation_text. Aggregator joins +
decrypts on read; admin view reads through the same path.

Fixes: Sr-H3 (Wave-6 v1.4.23 senior-dev review)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-11 02:38:17 +02:00
1 parent deadc73863
commit 650f150353
5 files changed
+182 -41

No files matched your search

+6 -1
View File
@@ -87,7 +87,12 @@ export async function resolveFeedbackAttribution(
* thumbs row. The polymorphic `RecommendationFeedback` table reuses
* its existing slots for Coach rows:
* - `recommendationId` carries the Coach message id
* - `recommendationText` carries the assistant prose snapshot
* - `coachMessageId` (added in 0042) FKs the source message so the
* prose stays encrypted-at-rest in `coach_messages`. The senior-
* dev review (Sr-H3) flagged the original H7 design that
* snapshotted decrypted prose into `recommendationText` as a
* silent break of the Coach surface's encryption invariant.
* - `recommendationText` is always NULL for coach rows
* - `recommendationSeverity` is always "coach" so dashboards can
* filter / group on the literal
* - `metricSourceType` encodes the user's active prefs at the