Release Privacy Tools 0.2.0
Verify / verify (push) Canceled after 0s

This commit is contained in:
2026-09-02 10:09:14 +02:00
parent bfd6422149
commit 38fa45dbaa
31 changed files with 1039 additions and 95 deletions
+23 -7
View File
@@ -42,7 +42,7 @@ test("serves the release identity and hardened headers", async ({
const manifest = await request.get("/deep/nested/privacy/toolbox-app.json");
await expect(manifest.json()).resolves.toMatchObject({
id: "de.add-ideas.privacy-tools",
version: "0.1.0",
version: "0.2.0",
entry: "./",
});
});
@@ -76,6 +76,14 @@ test("inspects and independently verifies a re-encoded PNG without network acces
await expect(page.getByText("Alice PNG").first()).toBeVisible();
await expect(page.getByText("PNG Alice").first()).toBeVisible();
await expect(page.getByText("inventory-only.pdf").first()).toBeVisible();
await expect(
page.getByRole("heading", { name: "Selective-removal policy" }),
).toBeVisible();
await expect(page.getByText("inspect-only", { exact: true })).toBeVisible();
await page.getByLabel("Policy profile").selectOption("location-only");
await expect(
page.getByText("policy-not-executable", { exact: true }),
).toBeVisible();
await page.getByRole("button", { name: "Re-encode & verify" }).click();
await expect(page.getByText("Mandatory output re-scan")).toBeVisible();
await expect(page.locator(".verification")).not.toHaveClass(/is-failed/u);
@@ -87,18 +95,26 @@ test("inspects and independently verifies a re-encoded PNG without network acces
await page
.getByRole("button", { name: "Download re-encoded output" })
.click();
expect((await imageDownload).suggestedFilename()).toBe(
"metadata-fixture.clean.png",
expect((await imageDownload).suggestedFilename()).toBe("image-001.clean.png");
const safeReportDownload = page.waitForEvent("download");
await page
.getByRole("button", { name: "Download safe-share report" })
.click();
expect((await safeReportDownload).suggestedFilename()).toBe(
"privacy-tools-safe-share-report.json",
);
const reportDownload = page.waitForEvent("download");
await page.getByRole("button", { name: "Download JSON report" }).click();
expect((await reportDownload).suggestedFilename()).toBe(
const detailedReportDownload = page.waitForEvent("download");
await page.getByRole("button", { name: "Download detailed report" }).click();
expect((await detailedReportDownload).suggestedFilename()).toBe(
"privacy-tools-report.json",
);
const archiveDownload = page.waitForEvent("download");
await page
.getByRole("button", { name: "Download 1 re-encoded image + report" })
.getByRole("button", {
name: "Download safe-share ZIP with 1 re-encoded image + report",
})
.click();
expect((await archiveDownload).suggestedFilename()).toBe(
"privacy-tools-re-encoded-images.zip",
+18
View File
@@ -0,0 +1,18 @@
import { expect, test } from "@playwright/test";
test("keeps the primary workspace inside a narrow viewport", async ({
page,
}) => {
await page.goto("/deep/nested/privacy/");
await expect(page.locator("main").first()).toBeVisible();
await expect(
page.locator("main .loading, main .workbench-loading"),
).toHaveCount(0);
const widths = await page.evaluate(() => ({
content: document.documentElement.scrollWidth,
viewport: document.documentElement.clientWidth,
}));
expect(widths.viewport).toBeLessThanOrEqual(430);
expect(widths.content).toBeLessThanOrEqual(widths.viewport + 1);
});
+96
View File
@@ -7,6 +7,10 @@ import {
buildSanitizationReport,
createBatchArchive,
createBatchReport,
createPolicyEvidence,
createSafeShareReport,
genericOutputName,
policyById,
serializeReport,
type ImageScanResult,
type MetadataFinding,
@@ -160,6 +164,98 @@ describe("sanitization and batch reports", () => {
),
).rejects.toThrow(/Archive image count/iu);
});
it("builds a pseudonymized safe-share report and generic names", () => {
const source = result({
id: "private-id",
name: "Alice-at-home.png",
sha256: "secret-hash",
findings: [sensitive],
coverage: {
projectScanner: "complete",
secondaryScanner: "complete",
notes: ["source metadata value"],
},
});
const output = result({ id: "clean", name: "output.png" });
const report = buildSanitizationReport(
source,
output,
"Alice-at-home.clean.png",
"image/png",
20,
comparison(true),
);
const safe = serializeReport(
createSafeShareReport(
[source],
[{ blob: new Blob(), report }],
"2026-09-01T00:00:00.000Z",
),
);
expect(safe).toContain('"profile": "safe-share"');
expect(safe).toContain("image-001.clean.png");
expect(safe).not.toContain("Alice");
expect(safe).not.toContain("secret-hash");
expect(safe).not.toContain("48.1 N");
expect(safe).not.toContain("source metadata value");
expect(genericOutputName(9, "jpeg")).toBe("image-010.clean.jpg");
});
it("evaluates reusable policies across cleanable and inspect-only formats", () => {
const cleanable = result({ findings: [sensitive] });
const unsupported = result({
id: "pdf",
name: "document.pdf",
identity: {
claimedType: "application/pdf",
extension: "pdf",
detectedKind: "pdf",
detectedType: "application/pdf",
typeMatch: "match",
},
deepSupported: false,
cleanable: false,
findings: [sensitive],
coverage: {
projectScanner: "unsupported",
secondaryScanner: "unsupported",
notes: [],
},
});
const strict = createPolicyEvidence(
[cleanable, unsupported],
[],
policyById("safe-share"),
"2026-09-01T00:00:00.000Z",
);
expect(strict.files[0]).toMatchObject({
decision: "review",
availableOperation: "reencode-available",
findings: { remove: 1 },
});
expect(strict.files[1]).toMatchObject({
decision: "blocked",
availableOperation: "inspect-only",
});
expect(JSON.stringify(strict)).not.toContain("document.pdf");
const selective = createPolicyEvidence(
[
result({
findings: [
sensitive,
{ ...sensitive, id: "author", category: "identity" },
],
}),
],
[],
policyById("location-only"),
);
expect(selective.files[0]?.availableOperation).toBe(
"policy-not-executable",
);
});
});
function comparison(identical: boolean) {