fix(quick-save): Drain idempotent (srcId-Dedup) + isSafeUrl-Gate
Zwei Befunde aus der Integrations-Review: - Race: der Page-Drain und der Worker machen je ein read-modify-write auf 'quicksave_pending' ohne kontextuebergreifende Atomizitaet. Ein Worker-Append im await-Fenster des Drains konnte einen bereits gedrainten Eintrag in der Queue belassen, den ein Folge-Drain erneut in die Inbox schrieb (Duplikat). Jede eingespielte Bookmark traegt jetzt die Pending-id als srcId; ein erneut auftauchender Eintrag wird uebersprungen statt doppelt eingefuegt. boards-Write bleibt vor der Queue-Bereinigung -> kein Verlust. - Validierung: der Drain hat e.url ohne isSafeUrl gepusht, anders als jeder andere Bookmark-Schreibpfad. isSafeUrl (jetzt im DOM-freien quicksave-core, http/https/ftp) filtert unsichere/leere Protokolle vor dem Schreiben ins Board.
This commit is contained in:
@@ -34,6 +34,17 @@
|
||||
return inbox;
|
||||
}
|
||||
|
||||
// Sicheres URL-Protokoll (http/https/ftp). Inhaltlich identisch zur data.js-Variante, aber
|
||||
// DOM-frei und auf globalThis, damit der Quick-Save-Drain (app.js) dieselbe Validierung nutzt
|
||||
// wie jeder andere Bookmark-Schreibpfad. URL ist in Worker UND Seite verfuegbar.
|
||||
function isSafeUrl(url) {
|
||||
try {
|
||||
return ['http:', 'https:', 'ftp:'].includes(new URL(url).protocol);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalisiert eine Bookmark in die kanonische Form { id, title, url, desc }.
|
||||
// title-Fallback auf url, desc auf ''. Begrenzt Laengen wie data.js (200/500),
|
||||
// damit Quick-Save-Eintraege das gleiche Schema wie Import/Manuell haben.
|
||||
@@ -52,6 +63,7 @@
|
||||
|
||||
root.INBOX_ID = INBOX_ID;
|
||||
root.uid = uid;
|
||||
root.isSafeUrl = isSafeUrl;
|
||||
root.ensureInbox = ensureInbox;
|
||||
root.normalizeBookmark = normalizeBookmark;
|
||||
})(typeof globalThis !== 'undefined' ? globalThis : self);
|
||||
|
||||
Reference in New Issue
Block a user