fix(quick-260910-krx): Konfliktklasse ueber den generierten Client messen statt sie zu behaupten

This commit is contained in:
2026-09-11 09:16:39 +02:00
parent b286bfb1a3
commit 6e7120648b
2 changed files with 101 additions and 1 deletions
+49 -1
View File
@@ -2451,7 +2451,9 @@ async function runDashboardAreaChecks(adminUrl, scratchRoleUrl, results) {
id text PRIMARY KEY,
"userId" text NOT NULL UNIQUE,
"tenantId" text NOT NULL,
layouts jsonb NOT NULL DEFAULT '{}'::jsonb
layouts jsonb NOT NULL DEFAULT '{}'::jsonb,
"createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
`);
await db.$executeRawUnsafe(`
@@ -2604,6 +2606,52 @@ async function runDashboardAreaChecks(adminUrl, scratchRoleUrl, results) {
conflictDetail,
);
// 5b: dashboardlayout-gebundenes-upsert-auf-unsichtbare-zeile-wirft-unknown
//
// Pruefung 5 misst mit Roh-SQL, WAS die Datenbank tut (42501). Der
// Anwendungscode in `saveLayout` faengt aber nicht SQLSTATEs, sondern die
// Fehlerklasse, die der GENERIERTE Prisma-Client daraus macht — und die
// ist nicht dieselbe wie beim P2002-Fall der Bereiche `tenders`/`user`
// (`PrismaClientKnownRequestError`), sondern
// `PrismaClientUnknownRequestError`, weil die Regel den Schreibzugriff
// abweist, bevor eine Eindeutigkeit ueberhaupt geprueft wird. Genau
// DIESE Klasse muss `saveLayout` uebersetzen; eine Uebersetzung der
// falschen Klasse spraenge nie an.
//
// Diese Messung fehlte in der ersten Lieferung von 260910-krx — die
// Zusammenfassung berief sich auf eine nicht committete Ad-hoc-Messung.
// Vom Verifizierer gefunden, hier nachgereicht: derselbe Vorgang wie in
// Pruefung 5, aber ueber `bound.dashboardLayout.upsert(...)` auf dem
// gebundenen generierten Client, und gepruegt wird der KONSTRUKTORNAME
// des geworfenen Fehlers.
let upsertThrewUnknown = false;
let upsertDetail = '';
try {
const bound = buildInlineExtendedClient(prisma, 'TENANT-A');
await bound.dashboardLayout.upsert({
where: { userId: 'user-conflict' },
update: { layouts: {} },
create: {
id: 'layout-conflict-attempt-upsert',
userId: 'user-conflict',
tenantId: 'TENANT-A',
layouts: {},
},
});
upsertDetail =
'gebundenes dashboardLayout.upsert unter TENANT-A auf die unter TENANT-B unsichtbare Zeile (user-conflict) ist NICHT fehlgeschlagen';
} catch (err) {
const ctor = err?.constructor?.name ?? 'unbekannt';
upsertThrewUnknown = ctor === 'PrismaClientUnknownRequestError';
upsertDetail = `gebundenes dashboardLayout.upsert unter TENANT-A auf die unter TENANT-B unsichtbare Zeile wirft ${ctor}${err?.code ? ` (code ${err.code})` : ''} — saveLayout uebersetzt genau diese Klasse; ${upsertThrewUnknown ? 'stimmt mit dem Anwendungscode ueberein' : 'STIMMT NICHT mit dem Anwendungscode ueberein, die Uebersetzung in saveLayout spraenge nie an'}`;
}
report(
results,
'dashboardlayout-gebundenes-upsert-auf-unsichtbare-zeile-wirft-unknown',
upsertThrewUnknown,
upsertDetail,
);
// 6: widgetinstance-gebundenes-einfuegen-fremder-mandant-abgelehnt
let foreignWidgetInsertRejected = false;
let foreignWidgetInsertDetail = '';