mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
test(settings): prove the wipe against real Postgres, and state what deletion means
The defect is about rows that survive, so a mocked client proves nothing. The new integration test seeds a row into every table in the schema, driven by information_schema and pg_constraint rather than a fixture, runs the wipe and asks the database what is left. A table added later is seeded and asserted without anyone remembering to. It holds all four halves: nothing in the wipe list survives, everything in the exemption list does, everything reached only by a database cascade is gone, and the account row comes back reset but able to sign in. A second file pins the allergy and checkup-reminder deletes actually removing their row. The reproductive-health note gains a Deletion section. It taught people to reason carefully about a host being imaged and never said what pressing delete does; now it says which of the three deletions removes the row and which only hides it.
This commit is contained in:
1 parent
5e66ebaa54
commit
dccd2f320b
8 files changed
+678
-7
No files matched your search
@@ -169,7 +169,7 @@ describe("data-wipe completeness", () => {
|
||||
}
|
||||
|
||||
const orphans = [...models]
|
||||
.filter(([name, shape]) => !shape.scalars.includes("userId"))
|
||||
.filter(([, shape]) => !shape.scalars.includes("userId"))
|
||||
.map(([name]) => name)
|
||||
.filter(
|
||||
(name) =>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* `GET /api/allergies/{id}` — one owned, live allergy record.
|
||||
* `PATCH /api/allergies/{id}` — edit it (partial; field-by-field).
|
||||
* `DELETE /api/allergies/{id}` — soft-delete it (idempotent; `{ deleted: true }`).
|
||||
* `DELETE /api/allergies/{id}` — delete it outright (`{ deleted: true }`; 404
|
||||
* once it is gone). The confirmation dialog promises it cannot be undone, and
|
||||
* nothing here needs a tombstone to keep that promise honest.
|
||||
*
|
||||
* Owner-scoped. `userId` is narrowed from auth and fed to the Prisma `where`;
|
||||
* the body never carries it. The free-text `reaction` + `note` are encrypted
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* v1.17.1 — Vorsorge (measurement) reminder by id: get + patch + delete.
|
||||
*
|
||||
* PATCH re-derives the server-authoritative `nextDueAt` after applying
|
||||
* the (mutually-exclusive cadence) edit. DELETE soft-deletes (tombstone)
|
||||
* for parity with the rest of the tree.
|
||||
* the (mutually-exclusive cadence) edit. DELETE removes the row; the
|
||||
* confirmation dialog says the reminder is permanently deleted, and nothing
|
||||
* here needs a tombstone to keep that promise honest.
|
||||
*/
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
|
||||
@@ -91,7 +91,10 @@ export const DELETE = apiHandler(async (request: NextRequest) => {
|
||||
const deletedRows = Object.values(counts).reduce((sum, n) => sum + n, 0);
|
||||
|
||||
// Written after the transaction commits, so the row cannot be removed by the
|
||||
// AuditLog delete inside it.
|
||||
// AuditLog delete inside it. The person's whole audit history goes; this one
|
||||
// row stays as the receipt for the erasure they asked for. Account deletion
|
||||
// takes the other branch and purges even this, because there is no longer an
|
||||
// account for it to belong to.
|
||||
await auditLog("user.data.clear", {
|
||||
userId,
|
||||
ipAddress: getClientIp(request),
|
||||
|
||||
@@ -160,8 +160,6 @@ export const WIPE_MODELS = [
|
||||
"ApiToken",
|
||||
] as const;
|
||||
|
||||
export type WipeModel = (typeof WIPE_MODELS)[number];
|
||||
|
||||
/**
|
||||
* User-scoped models this action deliberately keeps, each with the reason.
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user