Consolidate GVL deletion workflow and document purge semantics
Dieser Commit ist enthalten in:
@@ -0,0 +1,28 @@
|
|||||||
|
### GVL-Purge-Summary und Snapshot-Events
|
||||||
|
|
||||||
|
Bei der Untersuchung der GVL-Bereinigung wurde festgestellt, dass die Purge-Summary je nach Herkunft einer GVL-Revision unterschiedliche Gesamtzahlen ausweisen kann.
|
||||||
|
|
||||||
|
Beobachtung:
|
||||||
|
|
||||||
|
* Vault-GVL importiert → Purge-Summary: `13593 Records`
|
||||||
|
* Web-GVL geladen, passende Vault-GVL verifiziert → Purge-Summary: `13594 Records`
|
||||||
|
|
||||||
|
Die Differenz von genau einem Record stellt keinen Zählfehler dar.
|
||||||
|
|
||||||
|
Ursache:
|
||||||
|
|
||||||
|
Der Web-Ingest einer offiziellen GVL erzeugt zusätzlich einen Eintrag im Store `gvl_snapshot_events`. Dabei handelt es sich um ein Ereignis des lokalen Beobachtungsverlaufs, beispielsweise `gvl_snapshot_ingested`.
|
||||||
|
|
||||||
|
Der Import einer GVL-Revision aus einem Vault-Paket rekonstruiert dagegen die Revision selbst, importiert jedoch keine Snapshot-Event-Historie und erzeugt auch kein entsprechendes Ereignis.
|
||||||
|
|
||||||
|
Die globale Purge-Summary zählt `gvl_snapshot_events` mit. Daher entsteht im Web-Pfad gegenüber dem Vault-Pfad ein zusätzlicher gelöschter Record.
|
||||||
|
|
||||||
|
Fachliche Einordnung:
|
||||||
|
|
||||||
|
Die unterschiedliche Gesamtzahl ist erwartetes Verhalten und Ausdruck unterschiedlicher Provenienz:
|
||||||
|
|
||||||
|
* Web-GVL: dokumentierter lokaler Ingest-Vorgang.
|
||||||
|
* Vault-GVL: rekonstruiertes Evidenzobjekt ohne lokale Beobachtungshistorie.
|
||||||
|
|
||||||
|
Die Purge-Summary ist daher nicht nur ein Maß für die Größe einer Revision, sondern kann auch Unterschiede im Entstehungskontext der lokalen Evidence widerspiegeln.
|
||||||
|
|
||||||
+2
-11
@@ -125,10 +125,6 @@ async function handleVendorGetMessage(message, sender) {
|
|||||||
return handlePurgeUnlockedEvidenceRecordsMessage();
|
return handlePurgeUnlockedEvidenceRecordsMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.type === "purge_gvl_reference_data") {
|
|
||||||
return handlePurgeGvlReferenceDataMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.type === "delete_all_evidence_database") {
|
if (message.type === "delete_all_evidence_database") {
|
||||||
return handleDeleteAllEvidenceDatabaseMessage();
|
return handleDeleteAllEvidenceDatabaseMessage();
|
||||||
}
|
}
|
||||||
@@ -302,7 +298,8 @@ async function handleMarkGvlRevisionEvidenceVaultCopyMessage(message) {
|
|||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
mark: await markVendorGetGvlRevisionEvidenceVaultCopy(
|
mark: await markVendorGetGvlRevisionEvidenceVaultCopy(
|
||||||
message?.payload?.snapshotSha256 ?? null
|
message?.payload?.snapshotSha256 ?? null,
|
||||||
|
message?.payload?.verification ?? null
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1229,12 +1226,6 @@ async function handlePurgeUnlockedEvidenceRecordsMessage() {
|
|||||||
return purgeUnlockedEvidenceRecords(db);
|
return purgeUnlockedEvidenceRecords(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handlePurgeGvlReferenceDataMessage() {
|
|
||||||
const db = await openVendorGetDb();
|
|
||||||
|
|
||||||
return purgeGvlReferenceData(db);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDeleteAllEvidenceDatabaseMessage() {
|
function handleDeleteAllEvidenceDatabaseMessage() {
|
||||||
return deleteVendorGetDatabase();
|
return deleteVendorGetDatabase();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,16 +33,3 @@ const VENDORGET_EVIDENCE_STORE_NAMES = [
|
|||||||
VENDORGET_STORE_NAMES.gvlDataCategories,
|
VENDORGET_STORE_NAMES.gvlDataCategories,
|
||||||
VENDORGET_STORE_NAMES.gvlVendorRelationships
|
VENDORGET_STORE_NAMES.gvlVendorRelationships
|
||||||
];
|
];
|
||||||
|
|
||||||
const VENDORGET_GVL_REFERENCE_STORE_NAMES = [
|
|
||||||
VENDORGET_STORE_NAMES.gvlRawEvidence,
|
|
||||||
VENDORGET_STORE_NAMES.gvlSnapshots,
|
|
||||||
VENDORGET_STORE_NAMES.gvlSnapshotEvents,
|
|
||||||
VENDORGET_STORE_NAMES.gvlVendors,
|
|
||||||
VENDORGET_STORE_NAMES.gvlPurposes,
|
|
||||||
VENDORGET_STORE_NAMES.gvlSpecialPurposes,
|
|
||||||
VENDORGET_STORE_NAMES.gvlFeatures,
|
|
||||||
VENDORGET_STORE_NAMES.gvlSpecialFeatures,
|
|
||||||
VENDORGET_STORE_NAMES.gvlDataCategories,
|
|
||||||
VENDORGET_STORE_NAMES.gvlVendorRelationships
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -89,31 +89,11 @@ async function purgeUnlockedEvidenceRecords(db) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function purgeGvlReferenceData(db) {
|
// TODO: GVL-Datenpflege darf nicht storeweise per clear() erfolgen.
|
||||||
return new Promise((resolve, reject) => {
|
// Loeschbar ist nur eine GVL-Revision, wenn ihre zugehoerigen Raw-, Snapshot-,
|
||||||
const clearedStores = {};
|
// Event- und normalisierten Records identifiziert sind, ihr Schutzstatus
|
||||||
const tx = db.transaction(VENDORGET_GVL_REFERENCE_STORE_NAMES, "readwrite");
|
// vollstaendig bewertet wurde und eine vorhandene Vault-/Workspace-Schutzlogik
|
||||||
|
// die Loeschung erlaubt.
|
||||||
tx.onerror = () => reject(tx.error);
|
|
||||||
tx.onabort = () => reject(tx.error);
|
|
||||||
tx.oncomplete = () => {
|
|
||||||
resolve({
|
|
||||||
success: true,
|
|
||||||
clearedStores
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const storeName of VENDORGET_GVL_REFERENCE_STORE_NAMES) {
|
|
||||||
const objectStore = tx.objectStore(storeName);
|
|
||||||
const countRequest = objectStore.count();
|
|
||||||
|
|
||||||
countRequest.onsuccess = () => {
|
|
||||||
clearedStores[storeName] = countRequest.result;
|
|
||||||
objectStore.clear();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildGvlWorkspaceProtectionIndex(db) {
|
function buildGvlWorkspaceProtectionIndex(db) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
@@ -287,14 +287,21 @@ async function importVendorGetGvlRevisionEvidenceJson(exportContainer) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function markVendorGetGvlRevisionEvidenceVaultCopy(snapshotSha256) {
|
async function markVendorGetGvlRevisionEvidenceVaultCopy(
|
||||||
|
snapshotSha256,
|
||||||
|
verification = null
|
||||||
|
) {
|
||||||
if (!snapshotSha256) {
|
if (!snapshotSha256) {
|
||||||
throw new Error("missing_snapshot_sha256");
|
throw new Error("missing_snapshot_sha256");
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = await openVendorGetDb();
|
const db = await openVendorGetDb();
|
||||||
|
|
||||||
return markGvlRevisionEvidenceVaultCopyAvailable(db, snapshotSha256);
|
return markGvlRevisionEvidenceVaultCopyAvailable(
|
||||||
|
db,
|
||||||
|
snapshotSha256,
|
||||||
|
verification
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGvlEvidenceRecordByKey(db, storeName, key) {
|
function getGvlEvidenceRecordByKey(db, storeName, key) {
|
||||||
@@ -632,9 +639,16 @@ function formatGvlEvidenceProvenance(values) {
|
|||||||
return "web";
|
return "web";
|
||||||
}
|
}
|
||||||
|
|
||||||
function markGvlRevisionEvidenceVaultCopyAvailable(db, snapshotSha256) {
|
function markGvlRevisionEvidenceVaultCopyAvailable(
|
||||||
return updateGvlRevisionEvidenceRecords(db, snapshotSha256, (record) =>
|
db,
|
||||||
markGvlEvidenceRecordVaultCopyAvailable(record)
|
snapshotSha256,
|
||||||
|
verification = null
|
||||||
|
) {
|
||||||
|
return updateGvlRevisionEvidenceRecords(
|
||||||
|
db,
|
||||||
|
snapshotSha256,
|
||||||
|
(record) => markGvlEvidenceRecordVaultCopyAvailable(record),
|
||||||
|
verification
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,7 +666,12 @@ function markGvlRevisionEvidenceProvenance(db, snapshotSha256, provenance) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateGvlRevisionEvidenceRecords(db, snapshotSha256, updateRecord) {
|
function updateGvlRevisionEvidenceRecords(
|
||||||
|
db,
|
||||||
|
snapshotSha256,
|
||||||
|
updateRecord,
|
||||||
|
verification = null
|
||||||
|
) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const tx = db.transaction(
|
const tx = db.transaction(
|
||||||
[VENDORGET_STORE_NAMES.gvlSnapshots, VENDORGET_STORE_NAMES.gvlRawEvidence],
|
[VENDORGET_STORE_NAMES.gvlSnapshots, VENDORGET_STORE_NAMES.gvlRawEvidence],
|
||||||
@@ -665,7 +684,8 @@ function updateGvlRevisionEvidenceRecords(db, snapshotSha256, updateRecord) {
|
|||||||
snapshotMarked: false,
|
snapshotMarked: false,
|
||||||
rawEvidenceMarked: false,
|
rawEvidenceMarked: false,
|
||||||
snapshotSha256,
|
snapshotSha256,
|
||||||
rawGvlSha256: null
|
rawGvlSha256: null,
|
||||||
|
skippedReason: null
|
||||||
};
|
};
|
||||||
|
|
||||||
snapshotRequest.onerror = () => reject(snapshotRequest.error);
|
snapshotRequest.onerror = () => reject(snapshotRequest.error);
|
||||||
@@ -673,6 +693,12 @@ function updateGvlRevisionEvidenceRecords(db, snapshotSha256, updateRecord) {
|
|||||||
const snapshot = snapshotRequest.result ?? null;
|
const snapshot = snapshotRequest.result ?? null;
|
||||||
|
|
||||||
if (!snapshot) {
|
if (!snapshot) {
|
||||||
|
result.skippedReason = "gvl_snapshot_not_found";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!doesGvlRevisionEvidenceMatchVerification(snapshot, verification)) {
|
||||||
|
result.skippedReason = "gvl_revision_evidence_verification_mismatch";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,6 +734,40 @@ function updateGvlRevisionEvidenceRecords(db, snapshotSha256, updateRecord) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doesGvlRevisionEvidenceMatchVerification(snapshot, verification) {
|
||||||
|
if (!verification) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verification.valid !== true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
verification.snapshotSha256 &&
|
||||||
|
snapshot.sha256 !== verification.snapshotSha256
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
verification.vendorListVersion !== null &&
|
||||||
|
verification.vendorListVersion !== undefined &&
|
||||||
|
snapshot.vendorListVersion !== verification.vendorListVersion
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
verification.rawGvlSha256 &&
|
||||||
|
snapshot.rawGvlSha256 !== verification.rawGvlSha256
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function formatGvlEvidenceUtcCompact(date) {
|
function formatGvlEvidenceUtcCompact(date) {
|
||||||
return [
|
return [
|
||||||
date.getUTCFullYear(),
|
date.getUTCFullYear(),
|
||||||
|
|||||||
@@ -81,15 +81,6 @@
|
|||||||
<strong>Analyse-Vorbereitung</strong>
|
<strong>Analyse-Vorbereitung</strong>
|
||||||
<span>Datenbestände und vorbereitete Prüffelder, keine Engine.</span>
|
<span>Datenbestände und vorbereitete Prüffelder, keine Engine.</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="workspace-link workspace-placeholder" href="../data-maintenance/data-maintenance.html">
|
|
||||||
<strong>Datenpflege</strong>
|
|
||||||
<span>
|
|
||||||
Gezielte Verwaltung lokaler Datenbestände. Löschen,
|
|
||||||
Wiederherstellen und Exportieren erfolgen künftig segmentbezogen.
|
|
||||||
Vorgesehene Segmente sind GVL-Referenzdaten der Browser-DB,
|
|
||||||
Consent-Daten, Analyse-Daten und weitere künftige Datenbereiche.
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -127,6 +118,16 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="panel" aria-labelledby="data-maintenance-title">
|
||||||
|
<h2 id="data-maintenance-title">Datenpflege</h2>
|
||||||
|
<div class="workspace-actions">
|
||||||
|
<a class="workspace-link workspace-placeholder" href="../data-maintenance/data-maintenance.html">
|
||||||
|
<strong>Datenpflege</strong>
|
||||||
|
<span>Verwaltung lokaler Datenbestände.</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="dashboard.js"></script>
|
<script src="dashboard.js"></script>
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ p {
|
|||||||
background: #172033;
|
background: #172033;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.protected-revisions {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
Consent-Daten, Request-Beobachtungen und Analyse-Daten bleiben
|
Consent-Daten, Request-Beobachtungen und Analyse-Daten bleiben
|
||||||
unberührt.
|
unberührt.
|
||||||
</p>
|
</p>
|
||||||
<button id="purge-gvl-reference-data-button" type="button">
|
<button id="purge-gvl-reference-data-button" type="button" disabled>
|
||||||
GVL-Referenzdaten bereinigen
|
GVL-Referenzdaten bereinigen
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,7 +40,16 @@
|
|||||||
class="segment-status"
|
class="segment-status"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
Bereit.
|
–
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
id="gvl-reference-protected-revisions"
|
||||||
|
class="protected-revisions"
|
||||||
|
aria-live="polite"
|
||||||
|
hidden
|
||||||
|
></p>
|
||||||
|
<p id="gvl-reference-maintenance-message">
|
||||||
|
Keine GVL-Revisionen.
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
|||||||
@@ -1,69 +1,119 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const purgeGvlReferenceDataButton = document.getElementById(
|
|
||||||
"purge-gvl-reference-data-button"
|
|
||||||
);
|
|
||||||
const gvlReferenceMaintenanceStatus = document.getElementById(
|
const gvlReferenceMaintenanceStatus = document.getElementById(
|
||||||
"gvl-reference-maintenance-status"
|
"gvl-reference-maintenance-status"
|
||||||
);
|
);
|
||||||
|
const gvlReferenceProtectedRevisions = document.getElementById(
|
||||||
|
"gvl-reference-protected-revisions"
|
||||||
|
);
|
||||||
|
const gvlReferenceMaintenanceMessage = document.getElementById(
|
||||||
|
"gvl-reference-maintenance-message"
|
||||||
|
);
|
||||||
|
const purgeGvlReferenceDataButton = document.getElementById(
|
||||||
|
"purge-gvl-reference-data-button"
|
||||||
|
);
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
purgeGvlReferenceDataButton?.addEventListener("click", async () => {
|
purgeGvlReferenceDataButton.addEventListener("click", async () => {
|
||||||
await purgeGvlReferenceData();
|
await purgeUnlockedEvidenceRecords();
|
||||||
});
|
});
|
||||||
|
await renderGvlReferenceMaintenanceStatus();
|
||||||
});
|
});
|
||||||
|
|
||||||
async function purgeGvlReferenceData() {
|
async function renderGvlReferenceMaintenanceStatus() {
|
||||||
if (!confirm(buildGvlReferenceDataPurgeConfirmationText())) {
|
try {
|
||||||
renderGvlReferenceMaintenanceStatus("Abgebrochen.");
|
const result = await browser.runtime.sendMessage({
|
||||||
|
type: "list_gvl_snapshots"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result?.success) {
|
||||||
|
throw new Error(result?.error ?? "list_gvl_snapshots_failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
renderGvlReferenceSnapshotStatus(result.gvlSnapshots ?? []);
|
||||||
|
} catch (error) {
|
||||||
|
renderGvlReferenceStatus("–", true, "Status nicht verfügbar.");
|
||||||
|
renderProtectedRevisions([]);
|
||||||
|
console.warn("VG-Observe GVL maintenance status failed", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderGvlReferenceSnapshotStatus(snapshots) {
|
||||||
|
if (!snapshots.length) {
|
||||||
|
renderGvlReferenceStatus("–", true, "Keine GVL-Revisionen.");
|
||||||
|
renderProtectedRevisions([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const protectedRevisions = snapshots
|
||||||
|
.filter((snapshot) => snapshot.workspaceDeleteProtected === true)
|
||||||
|
.map((snapshot) => snapshot.vendorListVersion)
|
||||||
|
.filter((vendorListVersion) => vendorListVersion !== null)
|
||||||
|
.filter((vendorListVersion) => vendorListVersion !== undefined);
|
||||||
|
const allRevisionsDeleteAllowed = snapshots.every((snapshot) => {
|
||||||
|
return snapshot.workspaceDeleteAllowed === true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allRevisionsDeleteAllowed) {
|
||||||
|
renderGvlReferenceStatus("🔓", false, "GVL-Revisionen löschbar.");
|
||||||
|
} else if (protectedRevisions.length) {
|
||||||
|
renderGvlReferenceStatus("🔒", true, "GVL-Revisionen geschützt.");
|
||||||
|
} else {
|
||||||
|
renderGvlReferenceStatus("–", true, "Status nicht verfügbar.");
|
||||||
|
}
|
||||||
|
|
||||||
|
renderProtectedRevisions(protectedRevisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderGvlReferenceStatus(statusSymbol, buttonDisabled, message) {
|
||||||
|
gvlReferenceMaintenanceStatus.textContent = statusSymbol;
|
||||||
|
purgeGvlReferenceDataButton.disabled = buttonDisabled;
|
||||||
|
gvlReferenceMaintenanceMessage.textContent = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function purgeUnlockedEvidenceRecords() {
|
||||||
|
if (
|
||||||
|
!confirm(
|
||||||
|
"Ungesperrte Evidence-Daten mit bestehender Schutzlogik bereinigen?"
|
||||||
|
)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
purgeGvlReferenceDataButton.disabled = true;
|
purgeGvlReferenceDataButton.disabled = true;
|
||||||
renderGvlReferenceMaintenanceStatus("GVL-Referenzdaten werden bereinigt...");
|
gvlReferenceMaintenanceMessage.textContent = "Bereinigung läuft...";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await browser.runtime.sendMessage({
|
const result = await browser.runtime.sendMessage({
|
||||||
type: "purge_gvl_reference_data"
|
type: "purge_unlocked_evidence_records"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!result?.success) {
|
if (!result?.success) {
|
||||||
throw new Error(result?.error ?? "purge_gvl_reference_data_failed");
|
throw new Error(result?.error ?? "purge_unlocked_evidence_records_failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
renderGvlReferenceMaintenanceStatus(
|
await renderGvlReferenceMaintenanceStatus();
|
||||||
buildGvlReferenceDataPurgeSuccessMessage(result)
|
gvlReferenceMaintenanceMessage.textContent = buildPurgeSuccessMessage(result);
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
renderGvlReferenceMaintenanceStatus(
|
await renderGvlReferenceMaintenanceStatus();
|
||||||
"GVL-Referenzdaten konnten nicht bereinigt werden."
|
gvlReferenceMaintenanceMessage.textContent = "Bereinigung fehlgeschlagen.";
|
||||||
);
|
console.warn("VG-Observe protected purge failed", error);
|
||||||
console.warn("VG-Observe GVL reference data purge failed", error);
|
|
||||||
} finally {
|
|
||||||
purgeGvlReferenceDataButton.disabled = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildGvlReferenceDataPurgeConfirmationText() {
|
function buildPurgeSuccessMessage(result) {
|
||||||
return [
|
if (Number.isFinite(result.deletedCount)) {
|
||||||
"GVL-Referenzdaten bereinigen?",
|
return `Bereinigung abgeschlossen: ${result.deletedCount} Records.`;
|
||||||
"",
|
|
||||||
"Betroffen: GVL-Referenzdaten der Browser-DB.",
|
|
||||||
"Nicht betroffen: Consent-Daten, Request-Beobachtungen, Analyse-Daten.",
|
|
||||||
"",
|
|
||||||
"Diese Aktion entfernt lokale GVL-Referenzdaten aus der Browser-Datenbank."
|
|
||||||
].join("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildGvlReferenceDataPurgeSuccessMessage(result) {
|
return "Bereinigung abgeschlossen.";
|
||||||
const clearedCount = Object.values(result.clearedStores ?? {}).reduce(
|
|
||||||
(total, count) => total + Number(count ?? 0),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
return `GVL-Referenzdaten bereinigt: ${clearedCount} Records entfernt.`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderGvlReferenceMaintenanceStatus(message) {
|
function renderProtectedRevisions(vendorListVersions) {
|
||||||
gvlReferenceMaintenanceStatus.textContent = message;
|
gvlReferenceProtectedRevisions.hidden = vendorListVersions.length === 0;
|
||||||
|
gvlReferenceProtectedRevisions.textContent = vendorListVersions.length
|
||||||
|
? `Geschützt: ${vendorListVersions
|
||||||
|
.map((vendorListVersion) => String(vendorListVersion))
|
||||||
|
.join(", ")}`
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ async function exportSelectedGvlRevisionEvidenceJsonFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
downloadGvlRevisionEvidenceJsonExport(result.export);
|
downloadGvlRevisionEvidenceJsonExport(result.export);
|
||||||
await markGvlRevisionEvidenceVaultCopy(result.export);
|
await markGvlRevisionEvidenceVaultCopy(result.export, verification);
|
||||||
await renderGvlSnapshots();
|
await renderGvlSnapshots();
|
||||||
renderGvlEvidenceTransportStatus(
|
renderGvlEvidenceTransportStatus(
|
||||||
[
|
[
|
||||||
@@ -271,7 +271,10 @@ function downloadGvlRevisionEvidenceJsonExport(exportContainer) {
|
|||||||
setTimeout(() => URL.revokeObjectURL(url), 0);
|
setTimeout(() => URL.revokeObjectURL(url), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function markGvlRevisionEvidenceVaultCopy(exportContainer) {
|
async function markGvlRevisionEvidenceVaultCopy(
|
||||||
|
exportContainer,
|
||||||
|
verification = null
|
||||||
|
) {
|
||||||
const snapshotSha256 = exportContainer?.metadata?.snapshotSha256 ?? null;
|
const snapshotSha256 = exportContainer?.metadata?.snapshotSha256 ?? null;
|
||||||
|
|
||||||
if (!snapshotSha256) {
|
if (!snapshotSha256) {
|
||||||
@@ -281,7 +284,8 @@ async function markGvlRevisionEvidenceVaultCopy(exportContainer) {
|
|||||||
const result = await browser.runtime.sendMessage({
|
const result = await browser.runtime.sendMessage({
|
||||||
type: "mark_gvl_revision_evidence_vault_copy",
|
type: "mark_gvl_revision_evidence_vault_copy",
|
||||||
payload: {
|
payload: {
|
||||||
snapshotSha256
|
snapshotSha256,
|
||||||
|
verification
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -338,6 +342,11 @@ async function verifyGvlRevisionEvidenceJsonFile() {
|
|||||||
exportContainer
|
exportContainer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (verification.valid) {
|
||||||
|
await markGvlRevisionEvidenceVaultCopy(exportContainer, verification);
|
||||||
|
await renderGvlSnapshots();
|
||||||
|
}
|
||||||
|
|
||||||
renderGvlEvidenceTransportStatus(
|
renderGvlEvidenceTransportStatus(
|
||||||
buildGvlRevisionEvidenceVerificationMessage(verification),
|
buildGvlRevisionEvidenceVerificationMessage(verification),
|
||||||
verification.valid ? "success" : "error"
|
verification.valid ? "success" : "error"
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren