From 1face234ccdf538928d25583975ae056d77eac40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Tue, 7 Jul 2026 22:00:27 +0200 Subject: [PATCH] test(share-links): end-to-end document share, serve, and revoke lifecycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Playwright spec that drives the public sharing surface against the production server and a real Postgres: the owner picks documents into a new link through the Settings picker, a recipient unlocks it with the passphrase and pulls each blob through the token-scoped serve route, and a revoke closes it. Pins the load-bearing guarantees end to end — frozen-set confinement (an owned but un-attached document 404s), the serving posture (Class A inline with true type + nosniff + no-store, Class B opaque octet-stream attachment), the EXIF/GPS strip on the shared image, revocation enforced at serve time, and the scannable QR promotion at the mobile width. Seeds a fixed share trio (inline PDF, Exif-bearing JPEG, download-only text) through the same Postgres transport the vault fixture already uses. --- e2e/setup/vault-fixture.ts | 93 +++++++++++++ e2e/share-documents.spec.ts | 254 ++++++++++++++++++++++++++++++++++++ 2 files changed, 347 insertions(+) create mode 100644 e2e/share-documents.spec.ts diff --git a/e2e/setup/vault-fixture.ts b/e2e/setup/vault-fixture.ts index 31320e09c..cf7ee7764 100644 --- a/e2e/setup/vault-fixture.ts +++ b/e2e/setup/vault-fixture.ts @@ -160,6 +160,30 @@ function tinyPng(marker: string): Buffer { return Buffer.concat([PNG_1X1, Buffer.from(marker, "utf8")]); } +/** + * A minimal JPEG carrying a GPS marker inside an APP1 (Exif) segment so the + * share serve route's egress EXIF strip is observable end-to-end: the stored + * bytes contain `GPSLatitude`, the served bytes must not. SOI → APP1(Exif) → + * SOS(+entropy). Not a decodable photo — the serve route sniffs the STORED + * mime type, never re-decodes pixels, so this is enough to exercise the strip. + */ +function jpegWithGps(marker: string): Buffer { + const payload = Buffer.concat([ + Buffer.from("Exif\0\0"), + Buffer.from(`GPSLatitude=48.137 ${marker}`), + ]); + const lenField = Buffer.alloc(2); + lenField.writeUInt16BE(payload.length + 2); + const app1 = Buffer.concat([Buffer.from([0xff, 0xe1]), lenField, payload]); + const sos = Buffer.concat([ + Buffer.from([0xff, 0xda]), + Buffer.from([0x00, 0x08]), + Buffer.from([0x01, 0x01, 0x00, 0x3f, 0x00, 0x00]), + Buffer.from([0xaa, 0xbb]), + ]); + return Buffer.concat([Buffer.from([0xff, 0xd8]), app1, sos]); +} + // ─── Fixture identity ─────────────────────────────────────────────────────── export const KNIE_EPISODE_ID = "e2evaultknie000000000001"; @@ -173,6 +197,21 @@ export const AI_PROBE_DOC_ID = "e2evaultaiprobe000000001"; export const CONTENT_DOC_ID = "e2evaultcontent00000001"; /** The whole word that appears only in `CONTENT_DOC_ID`'s indexed body. */ export const CONTENT_BODY_WORD = "pneumothorax"; + +/** + * v1.28 (Phase 3) — a fixed trio the clinician-share e2e attaches to a link and + * serves through the public `/c//d/` route: + * - a PDF (Class A, inline preview via