Add verified GVL evidence import provenance and protection
Dieser Commit ist enthalten in:
+154
-22
@@ -41,6 +41,14 @@ async function handleVendorGetMessage(message, sender) {
|
||||
return handleVerifyGvlRevisionEvidenceJsonMessage(message);
|
||||
}
|
||||
|
||||
if (message.type === "import_gvl_revision_evidence_json") {
|
||||
return handleImportGvlRevisionEvidenceJsonMessage(message);
|
||||
}
|
||||
|
||||
if (message.type === "mark_gvl_revision_evidence_vault_copy") {
|
||||
return handleMarkGvlRevisionEvidenceVaultCopyMessage(message);
|
||||
}
|
||||
|
||||
if (message.type === "import_gvl_evidence_json") {
|
||||
return handleImportGvlEvidenceJsonMessage(message);
|
||||
}
|
||||
@@ -265,6 +273,42 @@ async function handleImportGvlEvidenceJsonMessage(message) {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleImportGvlRevisionEvidenceJsonMessage(message) {
|
||||
try {
|
||||
const importResult = await importVendorGetGvlRevisionEvidenceJson(
|
||||
message?.payload?.export ?? null
|
||||
);
|
||||
|
||||
return {
|
||||
success: importResult.imported,
|
||||
import: importResult,
|
||||
verification: importResult.verification,
|
||||
error: importResult.imported ? null : "invalid_gvl_revision_evidence"
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error?.message ?? String(error)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function handleMarkGvlRevisionEvidenceVaultCopyMessage(message) {
|
||||
try {
|
||||
return {
|
||||
success: true,
|
||||
mark: await markVendorGetGvlRevisionEvidenceVaultCopy(
|
||||
message?.payload?.snapshotSha256 ?? null
|
||||
)
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error?.message ?? String(error)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGetLatestGvlUpdateStatusMessage() {
|
||||
const db = await openVendorGetDb();
|
||||
const latestSnapshot = await getLatestGvlSnapshotByVendorListVersion(db);
|
||||
@@ -311,12 +355,17 @@ async function handleListGvlSnapshotsMessage() {
|
||||
const snapshotsWithEvents = await Promise.all(
|
||||
snapshots.map(async (snapshot) => {
|
||||
const event = await getAnyGvlSnapshotEventBySha256(db, snapshot.sha256);
|
||||
const provenanceState = getGvlEvidenceProvenanceState(snapshot);
|
||||
|
||||
return {
|
||||
vendorListVersion: snapshot.vendorListVersion ?? null,
|
||||
sha256: snapshot.sha256 ?? null,
|
||||
fetchedAt: snapshot.fetchedAt ?? null,
|
||||
sourceUrl: snapshot.sourceUrl ?? null,
|
||||
provenance: provenanceState.provenance,
|
||||
vaultCopyAvailable: provenanceState.vaultCopyAvailable,
|
||||
workspaceDeleteAllowed: provenanceState.workspaceDeleteAllowed,
|
||||
workspaceDeleteProtected: provenanceState.workspaceDeleteProtected,
|
||||
eventType: event?.eventType ?? null,
|
||||
eventCapturedAt: event?.capturedAt ?? null
|
||||
};
|
||||
@@ -350,6 +399,7 @@ async function handleGetGvlSnapshotSummaryMessage(message) {
|
||||
db,
|
||||
vendorListVersion
|
||||
);
|
||||
const provenanceState = getGvlEvidenceProvenanceState(snapshot);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@@ -360,6 +410,10 @@ async function handleGetGvlSnapshotSummaryMessage(message) {
|
||||
sourceUrl: snapshot.sourceUrl ?? null,
|
||||
eventType: event?.eventType ?? null,
|
||||
eventCapturedAt: event?.capturedAt ?? null,
|
||||
provenance: provenanceState.provenance,
|
||||
vaultCopyAvailable: provenanceState.vaultCopyAvailable,
|
||||
workspaceDeleteAllowed: provenanceState.workspaceDeleteAllowed,
|
||||
workspaceDeleteProtected: provenanceState.workspaceDeleteProtected,
|
||||
vendorCount: snapshot.vendorCount ?? counts.vendorCount,
|
||||
snapshotVendorCount: snapshot.vendorCount ?? null,
|
||||
normalizedVendorCount: counts.vendorCount,
|
||||
@@ -1215,7 +1269,14 @@ function isGvlImportCandidate(value) {
|
||||
|
||||
async function handleFetchOfficialGvlMessage() {
|
||||
try {
|
||||
const { rawJson, rawGvlSha256, responseStatus } =
|
||||
const {
|
||||
rawBody,
|
||||
rawJson,
|
||||
rawGvlSha256,
|
||||
fetchedAt,
|
||||
contentType,
|
||||
responseStatus
|
||||
} =
|
||||
await fetchOfficialGvlJson();
|
||||
|
||||
if (!isGvlImportCandidate(rawJson)) {
|
||||
@@ -1232,16 +1293,50 @@ async function handleFetchOfficialGvlMessage() {
|
||||
db,
|
||||
currentVendorListVersion
|
||||
);
|
||||
const currentSnapshotSha256 =
|
||||
await VendorGetGvlService.calculateGvlSnapshotSha256(rawJson);
|
||||
let webProvenanceMark = null;
|
||||
|
||||
if (existingSnapshot?.sha256) {
|
||||
if (
|
||||
existingSnapshot.sha256 !== currentSnapshotSha256 ||
|
||||
existingSnapshot.rawGvlSha256 !== rawGvlSha256
|
||||
) {
|
||||
return {
|
||||
success: false,
|
||||
error: "gvl_revision_evidence_conflict",
|
||||
vendorListVersion: currentVendorListVersion,
|
||||
existingSnapshotSha256: existingSnapshot.sha256 ?? null,
|
||||
fetchedSnapshotSha256: currentSnapshotSha256,
|
||||
existingRawGvlSha256: existingSnapshot.rawGvlSha256 ?? null,
|
||||
fetchedRawGvlSha256: rawGvlSha256
|
||||
};
|
||||
}
|
||||
|
||||
await VendorGetGvlService.storeGvlRawEvidenceIfNew(db, {
|
||||
rawGvlSha256,
|
||||
sourceUrl: OFFICIAL_IAB_GVL_URL,
|
||||
fetchedAt,
|
||||
httpStatus: responseStatus,
|
||||
contentType,
|
||||
rawBody
|
||||
});
|
||||
webProvenanceMark = await markGvlRevisionEvidenceWebSource(
|
||||
db,
|
||||
existingSnapshot.sha256
|
||||
);
|
||||
}
|
||||
|
||||
const ingestResult = existingSnapshot
|
||||
? null
|
||||
: await VendorGetGvlService.ingestGvlSnapshot(db, rawJson, {
|
||||
sourceUrl: OFFICIAL_IAB_GVL_URL,
|
||||
fetchedAt: new Date().toISOString(),
|
||||
rawGvlSha256: rawGvlSha256,
|
||||
diagnostics: {
|
||||
ingestionSource: "official_iab_fetch",
|
||||
responseStatus: responseStatus
|
||||
}
|
||||
: await ingestOfficialGvlSnapshotFromFetchedEvidence(db, {
|
||||
rawBody,
|
||||
rawJson,
|
||||
rawGvlSha256,
|
||||
fetchedAt,
|
||||
contentType,
|
||||
responseStatus,
|
||||
ingestionSource: "official_iab_fetch"
|
||||
});
|
||||
const snapshot = existingSnapshot ?? ingestResult.snapshot;
|
||||
const completeness = await getGvlSnapshotNormalizedCompleteness(
|
||||
@@ -1274,6 +1369,7 @@ async function handleFetchOfficialGvlMessage() {
|
||||
syncStatus,
|
||||
vendorListVersion: snapshot.vendorListVersion,
|
||||
sha256: snapshot.sha256,
|
||||
webProvenanceMark,
|
||||
normalizationSummary,
|
||||
counts
|
||||
};
|
||||
@@ -1326,22 +1422,49 @@ async function fetchOfficialGvlJson() {
|
||||
const fetchedAt = new Date().toISOString();
|
||||
const contentType = response.headers.get("Content-Type");
|
||||
const rawGvlSha256 = await VendorGetGvlService.calculateRawGvlSha256(rawBody);
|
||||
const db = await openVendorGetDb();
|
||||
|
||||
return {
|
||||
rawBody,
|
||||
rawJson: JSON.parse(rawBody),
|
||||
rawGvlSha256: rawGvlSha256,
|
||||
fetchedAt,
|
||||
contentType,
|
||||
responseStatus: response.status
|
||||
};
|
||||
}
|
||||
|
||||
async function ingestOfficialGvlSnapshotFromFetchedEvidence(
|
||||
db,
|
||||
{
|
||||
rawBody,
|
||||
rawJson,
|
||||
rawGvlSha256,
|
||||
fetchedAt,
|
||||
contentType,
|
||||
responseStatus,
|
||||
ingestionSource,
|
||||
diagnostics
|
||||
}
|
||||
) {
|
||||
await VendorGetGvlService.storeGvlRawEvidenceIfNew(db, {
|
||||
rawGvlSha256,
|
||||
sourceUrl: OFFICIAL_IAB_GVL_URL,
|
||||
fetchedAt,
|
||||
httpStatus: response.status,
|
||||
httpStatus: responseStatus,
|
||||
contentType,
|
||||
rawBody
|
||||
});
|
||||
|
||||
return {
|
||||
rawJson: JSON.parse(rawBody),
|
||||
return VendorGetGvlService.ingestGvlSnapshot(db, rawJson, {
|
||||
sourceUrl: OFFICIAL_IAB_GVL_URL,
|
||||
fetchedAt,
|
||||
rawGvlSha256: rawGvlSha256,
|
||||
responseStatus: response.status
|
||||
};
|
||||
diagnostics: {
|
||||
ingestionSource,
|
||||
responseStatus: responseStatus,
|
||||
...(diagnostics ?? {})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function runStartupGvlAutoUpdateCheck() {
|
||||
@@ -1424,7 +1547,14 @@ async function runStartupGvlAutoUpdateCheck() {
|
||||
result: "started"
|
||||
});
|
||||
|
||||
const { rawJson, rawGvlSha256, responseStatus } =
|
||||
const {
|
||||
rawBody,
|
||||
rawJson,
|
||||
rawGvlSha256,
|
||||
fetchedAt,
|
||||
contentType,
|
||||
responseStatus
|
||||
} =
|
||||
await fetchOfficialGvlJson();
|
||||
|
||||
if (!isGvlImportCandidate(rawJson)) {
|
||||
@@ -1439,15 +1569,17 @@ async function runStartupGvlAutoUpdateCheck() {
|
||||
previousVendorListVersion
|
||||
);
|
||||
|
||||
const ingestResult = await VendorGetGvlService.ingestGvlSnapshot(
|
||||
const ingestResult = await ingestOfficialGvlSnapshotFromFetchedEvidence(
|
||||
db,
|
||||
rawJson,
|
||||
{
|
||||
sourceUrl: OFFICIAL_IAB_GVL_URL,
|
||||
fetchedAt: new Date().toISOString(),
|
||||
rawGvlSha256: rawGvlSha256,
|
||||
rawBody,
|
||||
rawJson,
|
||||
rawGvlSha256,
|
||||
fetchedAt,
|
||||
contentType,
|
||||
responseStatus,
|
||||
ingestionSource: "official_iab_auto_update",
|
||||
diagnostics: {
|
||||
ingestionSource: "official_iab_auto_update",
|
||||
responseStatus: responseStatus,
|
||||
updateCheckSource: GVL_AUTO_UPDATE_SOURCE,
|
||||
checkedAt: lastAutoGvlCheckStartedAt,
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren