Entfernter Protokoll-Anfang wurde nicht erkannt
Gefunden bei der Vorbereitung des Prod-Siegels. Die Verkettung wird zeilenweise gegen die Vorgaengerin geprueft - die erste Zeile hat keine, also fiel bisher nichts auf, wenn ein zusammenhaengender Anfang des Protokolls entfernt wurde. Kein Kettenbruch, kein Befund, valid blieb gruen. Das ist die stillste Loeschung von allen: Wer die aeltesten Eintraege loswerden will, muss nur vorne anfangen. Erkennbar ist es trotzdem. Die allererste Zeile wird ohne Vorgaenger geschrieben und traegt einen leeren previousHash; traegt die erste VORHANDENE Zeile einen Wert, hat es eine Vorgaengerin gegeben und die ist weg. Wird jetzt als Kettenluecke an dieser Zeile gefuehrt, mit derselben Manifest- und Beglaubigungslogik wie jede andere Luecke - eine dokumentierte Loeschung erklaert sie also weiterhin. Nur bei Pruefung des Gesamtbereichs: mit fromId ist ein gefuellter previousHash selbstverstaendlich. Gegengeprueft, kein Fehlalarm. Getestet ueber HTTP gegen eine Wegwerf-DB: vollstaendiges Protokoll -> valid:true; erste drei Zeilen entfernt -> vorher unveraendert valid:true, jetzt valid:false mit chainGaps:[4], wegen Hash-Version 3 zusaetzlich als Manipulation eskaliert. Auf Prod ausgeschlossen: Das Protokoll beginnt bei ID 1 (07.05.2026, Inbetriebnahme), kein Cleanup, keine Neuberechnung. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1297,6 +1297,34 @@ export async function verifyIntegrity(fromId?: number, toId?: number): Promise<{
|
||||
}
|
||||
tamperedEntries.push(...backlogTampered, ...backlogMissing);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Fehlender ANFANG des Protokolls.
|
||||
//
|
||||
// Die Verkettung wird zeilenweise gegen die Vorgaengerin geprueft - die
|
||||
// erste Zeile hat keine, also fiel bisher NICHTS auf, wenn ein
|
||||
// zusammenhaengender Anfang entfernt wurde. Kein Kettenbruch, kein Befund,
|
||||
// `valid` blieb gruen. Das ist die stillste Loeschung von allen: Wer die
|
||||
// aeltesten Eintraege loswerden will, muss nur vorne anfangen.
|
||||
//
|
||||
// Erkennbar ist es trotzdem: Die allererste Zeile eines Protokolls wird ohne
|
||||
// Vorgaenger geschrieben und traegt deshalb einen leeren `previousHash`.
|
||||
// Traegt die erste vorhandene Zeile einen Wert, hat es eine Vorgaengerin
|
||||
// gegeben - und die ist weg.
|
||||
//
|
||||
// Nur bei Pruefung des GESAMTEN Bereichs; bei `fromId` ist ein gefuellter
|
||||
// `previousHash` selbstverstaendlich und kein Befund.
|
||||
if (fromId === undefined && logs.length > 0 && logs[0].previousHash) {
|
||||
chainGaps.push(logs[0].id);
|
||||
// Ein protokolliertes Loeschungs-Manifest erklaert auch diese Luecke; die
|
||||
// Pruefung laeuft ueber denselben Weg wie bei jeder anderen.
|
||||
if (!gapErklaert(0, logs[0].id)) {
|
||||
unexplainedGaps.push(logs[0].id);
|
||||
if (erwarteteVersion(logs[0].id) === 3) {
|
||||
tamperedEntries.push(logs[0].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < logs.length; i++) {
|
||||
const log = logs[i];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user