mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
feat(coach): store a turn's result tables encrypted beside the message
A new nullable column, coach_messages.results_encrypted, holds the tables of values a turn read as AES-GCM ciphertext; only their metadata rides the plaintext provenance. readMessageResults serves them to the owner, each table whole or withheld with a reason. The provenance restore learns the steps, method, table metadata, chips, clarification and the forced-answer marker, entry by entry against the wire schema. The column is registered for key rotation, carried through both backup formats (ciphertext in a disaster-recovery file, readable JSON in a portable one) and goes with its row on conversation delete and wipe.
This commit is contained in:
1 parent
cde7af3cf8
commit
a8b3e5d7f4
9 files changed
+714
-1
No files matched your search
@@ -0,0 +1,14 @@
|
||||
-- The tables of values a Coach turn read, stored with the assistant message
|
||||
-- that showed them: a JSON array of result tables, AES-256-GCM encrypted in
|
||||
-- the same Bytes codec as the message body. The values are health data, so
|
||||
-- they never sit in the plaintext `metric_source_json`, which carries only the
|
||||
-- tables' metadata (ref, source, shape, row count).
|
||||
--
|
||||
-- A stored table keeps the values the answer was given with; a later edit or
|
||||
-- sync does not rewrite what an earlier answer showed. The column goes with
|
||||
-- its row, so deleting a conversation or wiping the account removes it by
|
||||
-- the existing cascade.
|
||||
--
|
||||
-- Additive only: a nullable column, no table rewrite, no data change.
|
||||
|
||||
ALTER TABLE "coach_messages" ADD COLUMN "results_encrypted" BYTEA;
|
||||
@@ -6221,6 +6221,12 @@ model CoachMessage {
|
||||
// nullable: user turns, refusals, and pre-feature rows carry NULL.
|
||||
tokensUsed Int? @map("tokens_used")
|
||||
model String?
|
||||
// v1.39.4 — the tables of values this turn read (JSON `CoachResultTable[]`,
|
||||
// at most 128 KB), AES-256-GCM encrypted like `encryptedContent`. Health
|
||||
// values, so they never ride the plaintext `metricSourceJson`, which holds
|
||||
// only the tables' metadata. Read through `readMessageResults` by the
|
||||
// owner-narrowed results endpoint; NULL on every turn without a table.
|
||||
resultsEncrypted Bytes? @map("results_encrypted")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
conversation CoachConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
||||
|
||||
Reference in new issue
Block a user