mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
fix(activity): word the refusals that now reach a delegate's feed
The custom-metric create and update refusals and the medication layout refusal are filed through auditLog now, so a delegate's refused request reaches the owner's activity feed, where it read as the generic change. Each gets its own sentence in every bundle; the refusal sentences live in their own function. The audit write guard states its floor, and the schedule-reader guard names the medication create and edit, which answer through medicationDetail.
This commit is contained in:
1 parent
fb9cd9b965
commit
a0dce10c1a
14 files changed
+106
-54
No files matched your search
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} wollte eine Einnahme ändern und wurde abgewiesen",
|
||||
"rejectedDoseImport": "{name} wollte Einnahmen importieren und wurde abgewiesen",
|
||||
"rejectedTrackedValue": "{name} wollte einen eigenen Messwert eintragen und wurde abgewiesen",
|
||||
"rejectedTrackedValueTypeCreate": "{name} wollte eine eigene Messgröße anlegen und wurde abgewiesen",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} wollte eine eigene Messgröße ändern und wurde abgewiesen",
|
||||
"rejectedMedicationLayout": "{name} wollte die Medikamentenliste neu anordnen und wurde abgewiesen",
|
||||
"deniedDoseImport": "Ein von {name} gestarteter Einnahme-Import konnte nicht eingereiht werden",
|
||||
"anamnesisFactCreate": "{name} hat einen Fakt zur Vorgeschichte eingetragen",
|
||||
"customMetricCreate": "{name} hat eine eigene Messgröße angelegt",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} tried to change a dose and was refused",
|
||||
"rejectedDoseImport": "{name} tried to import doses and was refused",
|
||||
"rejectedTrackedValue": "{name} tried to log a tracked value and was refused",
|
||||
"rejectedTrackedValueTypeCreate": "{name} tried to add a tracked value type and was refused",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} tried to change a tracked value type and was refused",
|
||||
"rejectedMedicationLayout": "{name} tried to rearrange the medication list and was refused",
|
||||
"deniedDoseImport": "A dose import {name} started could not be queued",
|
||||
"anamnesisFactCreate": "{name} added a health background fact",
|
||||
"customMetricCreate": "{name} added a tracked value type",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} intentó cambiar una dosis y fue rechazado",
|
||||
"rejectedDoseImport": "{name} intentó importar dosis y fue rechazado",
|
||||
"rejectedTrackedValue": "{name} intentó registrar un valor propio y fue rechazado",
|
||||
"rejectedTrackedValueTypeCreate": "{name} intentó añadir un tipo de valor propio y fue rechazado",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} intentó cambiar un tipo de valor propio y fue rechazado",
|
||||
"rejectedMedicationLayout": "{name} intentó reordenar la lista de medicamentos y fue rechazado",
|
||||
"deniedDoseImport": "Una importación de dosis iniciada por {name} no se pudo poner en cola",
|
||||
"anamnesisFactCreate": "{name} añadió un dato de antecedentes de salud",
|
||||
"customMetricCreate": "{name} añadió un tipo de valor propio",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} a tenté de modifier une prise et a été refusé",
|
||||
"rejectedDoseImport": "{name} a tenté d'importer des prises et a été refusé",
|
||||
"rejectedTrackedValue": "{name} a tenté d'enregistrer une valeur personnalisée et a été refusé",
|
||||
"rejectedTrackedValueTypeCreate": "{name} a tenté d'ajouter un type de valeur personnalisée et a été refusé",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} a tenté de modifier un type de valeur personnalisée et a été refusé",
|
||||
"rejectedMedicationLayout": "{name} a tenté de réorganiser la liste des médicaments et a été refusé",
|
||||
"deniedDoseImport": "Un import de prises lancé par {name} n'a pas pu être mis en file",
|
||||
"anamnesisFactCreate": "{name} a ajouté un élément d'antécédents de santé",
|
||||
"customMetricCreate": "{name} a ajouté un type de valeur personnalisée",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} ha provato a modificare una dose ed è stato rifiutato",
|
||||
"rejectedDoseImport": "{name} ha provato a importare delle dosi ed è stato rifiutato",
|
||||
"rejectedTrackedValue": "{name} ha provato a registrare un valore personalizzato ed è stato rifiutato",
|
||||
"rejectedTrackedValueTypeCreate": "{name} ha provato ad aggiungere un tipo di valore personalizzato ed è stato rifiutato",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} ha provato a modificare un tipo di valore personalizzato ed è stato rifiutato",
|
||||
"rejectedMedicationLayout": "{name} ha provato a riordinare l'elenco dei farmaci ed è stato rifiutato",
|
||||
"deniedDoseImport": "Un'importazione di dosi avviata da {name} non è stata messa in coda",
|
||||
"anamnesisFactCreate": "{name} ha aggiunto un dato di anamnesi",
|
||||
"customMetricCreate": "{name} ha aggiunto un tipo di valore personalizzato",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} 님이 복용 기록을 수정하려다 거절됐어요",
|
||||
"rejectedDoseImport": "{name} 님이 복용 기록을 불러오려다 거절됐어요",
|
||||
"rejectedTrackedValue": "{name} 님이 추적 값을 기록하려다 거절됐어요",
|
||||
"rejectedTrackedValueTypeCreate": "{name} 님이 추적 값 종류를 추가하려다 거절됐어요",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} 님이 추적 값 종류를 수정하려다 거절됐어요",
|
||||
"rejectedMedicationLayout": "{name} 님이 약 목록 순서를 바꾸려다 거절됐어요",
|
||||
"deniedDoseImport": "{name} 님이 시작한 복용 기록 불러오기를 대기열에 넣지 못했어요",
|
||||
"anamnesisFactCreate": "{name} 님이 건강 배경 항목을 추가했어요",
|
||||
"customMetricCreate": "{name} 님이 추적 값 종류를 추가했어요",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} probeerde een dosis te wijzigen, maar dat werd geweigerd",
|
||||
"rejectedDoseImport": "{name} probeerde doses te importeren, maar dat werd geweigerd",
|
||||
"rejectedTrackedValue": "{name} probeerde een bijgehouden waarde vast te leggen, maar dat werd geweigerd",
|
||||
"rejectedTrackedValueTypeCreate": "{name} probeerde een type bijgehouden waarde toe te voegen, maar dat werd geweigerd",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} probeerde een type bijgehouden waarde te wijzigen, maar dat werd geweigerd",
|
||||
"rejectedMedicationLayout": "{name} probeerde de medicijnlijst anders te ordenen, maar dat werd geweigerd",
|
||||
"deniedDoseImport": "Een dosisimport die {name} had gestart, kon niet in de wachtrij worden gezet",
|
||||
"anamnesisFactCreate": "{name} heeft een gegeven aan de gezondheidsachtergrond toegevoegd",
|
||||
"customMetricCreate": "{name} heeft een type bijgehouden waarde toegevoegd",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} próbował zmienić przyjęcie dawki i został odrzucony",
|
||||
"rejectedDoseImport": "{name} próbował zaimportować przyjęcia dawek i został odrzucony",
|
||||
"rejectedTrackedValue": "{name} próbował zapisać własny pomiar i został odrzucony",
|
||||
"rejectedTrackedValueTypeCreate": "{name} próbował dodać własny typ pomiaru i został odrzucony",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} próbował zmienić własny typ pomiaru i został odrzucony",
|
||||
"rejectedMedicationLayout": "{name} próbował zmienić kolejność listy leków i został odrzucony",
|
||||
"deniedDoseImport": "Import przyjęć rozpoczęty przez {name} nie mógł zostać zakolejkowany",
|
||||
"anamnesisFactCreate": "{name} dodał fakt z wywiadu zdrowotnego",
|
||||
"customMetricCreate": "{name} dodał własny typ pomiaru",
|
||||
|
||||
@@ -12719,6 +12719,9 @@
|
||||
"rejectedDoseUpdate": "{name} tentou alterar uma dose e foi recusado",
|
||||
"rejectedDoseImport": "{name} tentou importar doses e foi recusado",
|
||||
"rejectedTrackedValue": "{name} tentou registrar um valor acompanhado e foi recusado",
|
||||
"rejectedTrackedValueTypeCreate": "{name} tentou adicionar um tipo de valor acompanhado e foi recusado",
|
||||
"rejectedTrackedValueTypeUpdate": "{name} tentou alterar um tipo de valor acompanhado e foi recusado",
|
||||
"rejectedMedicationLayout": "{name} tentou reorganizar a lista de medicamentos e foi recusado",
|
||||
"deniedDoseImport": "Uma importação de doses que {name} iniciou não pôde ser enfileirada",
|
||||
"anamnesisFactCreate": "{name} adicionou um fato do histórico de saúde",
|
||||
"customMetricCreate": "{name} adicionou um tipo de valor acompanhado",
|
||||
|
||||
@@ -39,6 +39,8 @@ describe("audit rows go through auditLog()", () => {
|
||||
.map(([rel]) => rel);
|
||||
|
||||
it("finds the writers it polices", () => {
|
||||
expect(files.length).toBeGreaterThan(3000);
|
||||
expect(writers.length).toBeGreaterThanOrEqual(2);
|
||||
expect(writers).toContain("lib/auth/audit.ts");
|
||||
});
|
||||
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
{
|
||||
"$comment": "Production files over 800 lines and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 101,
|
||||
"total": 116897,
|
||||
"count": 91,
|
||||
"total": 101342,
|
||||
"entries": {
|
||||
"app/medications/page-client.tsx": 839,
|
||||
"app/page-client.tsx": 2324,
|
||||
"components/admin/backups-section.tsx": 1462,
|
||||
"components/charts/health-chart.tsx": 2517,
|
||||
"components/charts/mood-chart.tsx": 1166,
|
||||
"components/cycle/log-day-sheet.tsx": 1639,
|
||||
"components/documents/document-detail-sheet.tsx": 1304,
|
||||
"components/documents/documents-view.tsx": 1223,
|
||||
"components/insights/coach-panel/chat-bubble.tsx": 888,
|
||||
"components/insights/coach-panel/coach-conversation.tsx": 1286,
|
||||
"components/insights/coach-panel/use-coach.ts": 1486,
|
||||
@@ -18,17 +13,12 @@
|
||||
"components/insights/health-score-card.tsx": 1023,
|
||||
"components/insights/insights-tab-strip.tsx": 1086,
|
||||
"components/layout/sidebar-nav.tsx": 855,
|
||||
"components/measurement-reminders/vorsorge-section.tsx": 1536,
|
||||
"components/measurements/measurement-form.tsx": 815,
|
||||
"components/measurements/measurement-list.tsx": 2019,
|
||||
"components/medications/detail/medication-detail-tabs.tsx": 1160,
|
||||
"components/medications/dose-history-ledger.tsx": 1052,
|
||||
"components/medications/medication-table.tsx": 853,
|
||||
"components/medications/wizard/wizard-payload.ts": 1414,
|
||||
"components/mood/mood-list.tsx": 1408,
|
||||
"components/records/life-circumstances-manager.tsx": 1080,
|
||||
"components/settings/dashboard-layout-section.tsx": 1033,
|
||||
"components/settings/managed-record-settings-section.tsx": 1071,
|
||||
"components/timeline/timeline-chart.tsx": 1174,
|
||||
"components/timeline/timeline-geometry.ts": 1395,
|
||||
"lib/ai/anthropic-client.ts": 804,
|
||||
@@ -92,7 +82,7 @@
|
||||
"lib/measurements/import-apple-health-export.ts": 1722,
|
||||
"lib/medications/scheduling/cadence.ts": 978,
|
||||
"lib/medications/scheduling/recurrence.ts": 1108,
|
||||
"lib/medications/scheduling/slot-upsert.ts": 926,
|
||||
"lib/medications/scheduling/slot-upsert.ts": 912,
|
||||
"lib/notifications/senders/apns.ts": 1100,
|
||||
"lib/oura/sync.ts": 900,
|
||||
"lib/rollups/measurement-rollups.ts": 1496,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Production functions over 200 lines, keyed \"file :: name\", and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 355,
|
||||
"total": 114858,
|
||||
"total": 114773,
|
||||
"entries": {
|
||||
"app/achievements/page.tsx :: AchievementsPage": 206,
|
||||
"app/api/admin/backups/upload/route.ts :: apiHandler(arg)": 314,
|
||||
@@ -15,16 +15,16 @@
|
||||
"app/api/cycle/calendar/route.ts :: apiHandler(arg)": 230,
|
||||
"app/api/cycle/day-logs/bulk/route.ts :: postBulk": 213,
|
||||
"app/api/cycle/insights/route.ts :: apiHandler(arg)": 226,
|
||||
"app/api/devices/route.ts :: apiHandler(arg)": 231,
|
||||
"app/api/devices/route.ts :: apiHandler(arg)": 226,
|
||||
"app/api/documents/inbound/bulk/route.ts :: apiHandler(arg)": 207,
|
||||
"app/api/encounters/[id]/route.ts :: apiHandler(arg) #2": 269,
|
||||
"app/api/environment/route.ts :: apiHandler(arg)": 201,
|
||||
"app/api/export/health-record/route.ts :: apiHandler(arg)": 241,
|
||||
"app/api/ingest/medication/route.ts :: apiHandler(arg)": 267,
|
||||
"app/api/ingest/medication/route.ts :: apiHandler(arg)": 262,
|
||||
"app/api/insights/cards/route.ts :: apiHandler(arg)": 211,
|
||||
"app/api/integrations/status/route.ts :: apiHandler(arg)": 451,
|
||||
"app/api/labs/[id]/route.ts :: apiHandler(arg) #2": 239,
|
||||
"app/api/labs/ocr/commit/route.ts :: commitOcrRows": 285,
|
||||
"app/api/labs/ocr/commit/route.ts :: commitOcrRows": 280,
|
||||
"app/api/labs/route.ts :: postLabResult": 242,
|
||||
"app/api/mcp/oauth/token/route.ts :: POST": 250,
|
||||
"app/api/mcp/oauth/token/route.ts :: POST > withBackgroundEvent(arg)": 248,
|
||||
@@ -346,7 +346,7 @@
|
||||
"lib/notifications/senders/web-push.ts :: sendViaWebPush": 268,
|
||||
"lib/personal-records/pr-detection-worker.ts :: detectPersonalRecordsForUser": 239,
|
||||
"lib/personal-records/pr-direction.ts :: getPRDirection": 202,
|
||||
"lib/record-activity/activity-verb.ts :: recordActivityVerbLine": 395,
|
||||
"lib/record-activity/activity-verb.ts :: recordActivityVerbLine": 325,
|
||||
"lib/strava/sync.ts :: runStravaSync": 219,
|
||||
"lib/support/report.ts :: collectSupportReportFacts": 332,
|
||||
"lib/targets/build-response.ts :: buildTargetsResponse": 330,
|
||||
|
||||
@@ -115,10 +115,17 @@ const MAY_READ_EVERY_ROW: Record<string, string> = {
|
||||
"units consumed by a recorded dose",
|
||||
"lib/medications/intake-slot-dedup.ts":
|
||||
"folds duplicate rows of doses already recorded",
|
||||
// The medication create and edit write the schedule rows and answer
|
||||
// through `medicationDetail` (read-medication.ts), which shapes them with
|
||||
// scheduleWireFields and derives the due state the switch allows.
|
||||
"lib/medications/create-medication.ts":
|
||||
"writes the schedules; answers through medicationDetail",
|
||||
"lib/medications/update-medication/update-medication.ts":
|
||||
"writes the schedules; answers through medicationDetail",
|
||||
// The medication edit: the schedule count and the primary schedule's id
|
||||
// for the reminder-window bridge, and the replaced rows archived as an era
|
||||
// whose payload is empty for a stretch with tracking off. Nothing due comes
|
||||
// out of either; the edit answers through scheduleWireFields.
|
||||
// out of either; the edit answers through medicationDetail.
|
||||
"lib/medications/update-medication/preflight.ts":
|
||||
"schedule count and the primary schedule's id, derives nothing due",
|
||||
"lib/medications/update-medication/write.ts":
|
||||
|
||||
@@ -61,6 +61,8 @@ export function recordActivityVerbLine(
|
||||
action: string,
|
||||
name: string,
|
||||
): string {
|
||||
const refused = refusedAttemptVerb(t, action, name);
|
||||
if (refused !== null) return refused;
|
||||
switch (action) {
|
||||
case "measurement.create":
|
||||
return t("recordSharing.activityVerb.measurementCreate", { name });
|
||||
@@ -342,6 +344,54 @@ export function recordActivityVerbLine(
|
||||
case "health-record.export":
|
||||
return t("recordSharing.activityVerb.healthRecordExport", { name });
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* Acts a delegable module performs outside its own route file. */
|
||||
/* */
|
||||
/* The two below are filed by library modules the routes import — a */
|
||||
/* background worker's completion row and a lifecycle reconciliation */
|
||||
/* — and a guard that walked only `route.ts` could not see either. */
|
||||
/* Both carry the actor through, so both reach the owner's feed. */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
case "medication.intake.import":
|
||||
return t("recordSharing.activityVerb.medicationIntakeImportFinished", {
|
||||
name,
|
||||
});
|
||||
case "medication.oneShot.reconciled":
|
||||
return t("recordSharing.activityVerb.medicationOneShotReconciled", {
|
||||
name,
|
||||
});
|
||||
|
||||
case "anamnesis.fact.create":
|
||||
return t("recordSharing.activityVerb.anamnesisFactCreate", { name });
|
||||
case "customMetric.create":
|
||||
return t("recordSharing.activityVerb.customMetricCreate", { name });
|
||||
case "customMetric.update":
|
||||
return t("recordSharing.activityVerb.customMetricUpdate", { name });
|
||||
case "customMetric.delete":
|
||||
return t("recordSharing.activityVerb.customMetricDelete", { name });
|
||||
case "documents.inbound.store":
|
||||
return t("recordSharing.activityVerb.documentStore", { name });
|
||||
case "documents.inbound.update":
|
||||
return t("recordSharing.activityVerb.documentUpdate", { name });
|
||||
case "documents.inbound.discard":
|
||||
return t("recordSharing.activityVerb.documentDiscard", { name });
|
||||
|
||||
default:
|
||||
return t("recordSharing.activity.acted", { name });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The sentence for an attempt that was refused, or null when `action` is no
|
||||
* refusal. Asked first by `recordActivityVerbLine`.
|
||||
*/
|
||||
function refusedAttemptVerb(
|
||||
t: Translator,
|
||||
action: string,
|
||||
name: string,
|
||||
): string | null {
|
||||
switch (action) {
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* Attempts that were REFUSED, and things that happened around them. */
|
||||
/* */
|
||||
@@ -407,47 +457,23 @@ export function recordActivityVerbLine(
|
||||
return t("recordSharing.activityVerb.rejectedDoseImport", { name });
|
||||
case "custom-metric.entry.create.validation-failed":
|
||||
return t("recordSharing.activityVerb.rejectedTrackedValue", { name });
|
||||
case "custom-metric.metric.create.validation-failed":
|
||||
return t("recordSharing.activityVerb.rejectedTrackedValueTypeCreate", {
|
||||
name,
|
||||
});
|
||||
case "custom-metric.metric.update.validation-failed":
|
||||
return t("recordSharing.activityVerb.rejectedTrackedValueTypeUpdate", {
|
||||
name,
|
||||
});
|
||||
case "medication.layout.validation-failed":
|
||||
return t("recordSharing.activityVerb.rejectedMedicationLayout", { name });
|
||||
// Not a validation failure: the request was well-formed and admitted,
|
||||
// and the queue would not take it. The owner sees an import that never
|
||||
// ran rather than one that was refused, because those need different
|
||||
// next steps.
|
||||
case "medication.intake.import.kickoff.denied":
|
||||
return t("recordSharing.activityVerb.deniedDoseImport", { name });
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* Acts a delegable module performs outside its own route file. */
|
||||
/* */
|
||||
/* The two below are filed by library modules the routes import — a */
|
||||
/* background worker's completion row and a lifecycle reconciliation */
|
||||
/* — and a guard that walked only `route.ts` could not see either. */
|
||||
/* Both carry the actor through, so both reach the owner's feed. */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
case "medication.intake.import":
|
||||
return t("recordSharing.activityVerb.medicationIntakeImportFinished", {
|
||||
name,
|
||||
});
|
||||
case "medication.oneShot.reconciled":
|
||||
return t("recordSharing.activityVerb.medicationOneShotReconciled", {
|
||||
name,
|
||||
});
|
||||
|
||||
case "anamnesis.fact.create":
|
||||
return t("recordSharing.activityVerb.anamnesisFactCreate", { name });
|
||||
case "customMetric.create":
|
||||
return t("recordSharing.activityVerb.customMetricCreate", { name });
|
||||
case "customMetric.update":
|
||||
return t("recordSharing.activityVerb.customMetricUpdate", { name });
|
||||
case "customMetric.delete":
|
||||
return t("recordSharing.activityVerb.customMetricDelete", { name });
|
||||
case "documents.inbound.store":
|
||||
return t("recordSharing.activityVerb.documentStore", { name });
|
||||
case "documents.inbound.update":
|
||||
return t("recordSharing.activityVerb.documentUpdate", { name });
|
||||
case "documents.inbound.discard":
|
||||
return t("recordSharing.activityVerb.documentDiscard", { name });
|
||||
|
||||
default:
|
||||
return t("recordSharing.activity.acted", { name });
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user