From e4a154406e8c4d762fba1e4d88e2b35aa55b8fec Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 27 May 2026 11:20:39 +0200 Subject: [PATCH] docs: record owner decisions on re-import authority and path-escape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DEPLOYMENT §6: clarify re-import keeps person/tag scalar human edits but re-applies document sender/receivers/tags from the canonical export (canonical-authoritative), per owner sign-off. - ADR-025: path-escape/symlink aborts the whole import (fail-closed) by deliberate owner decision, chosen over a per-file skip. Refs #669 --- docs/DEPLOYMENT.md | 2 +- ...anonical-import-and-single-migration-schema-foundation.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index dee25e49..0e1fe07e 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -592,7 +592,7 @@ closed (`IMPORT_ARTIFACT_INVALID`) if any is missing. 2. Make sure `IMPORT_HOST_DIR=` is set in `.env.staging` / `.env.production` (the nightly/release workflows already write this — see §3). Compose refuses to start without it. 3. Redeploy the stack so the bind mount picks up — or, if the mount is already in place, skip to step 4. 4. Call `POST /api/admin/trigger-import` (requires `ADMIN` permission), or click the "Import starten" button on `/admin/system`. -5. The import runs asynchronously — poll `GET /api/admin/import-status`, watch `/admin/system`, or tail the backend logs. Re-running is safe: the import is idempotent (upsert by `source_ref` / document `index`) and never overwrites a human-edited field. +5. The import runs asynchronously — poll `GET /api/admin/import-status`, watch `/admin/system`, or tail the backend logs. Re-running is safe and idempotent (upsert by `source_ref` / document `index`). Person and tag scalar fields you edited in the app are preserved on re-import; a document's sender/receivers/tags are **canonical-authoritative** — a re-import re-applies them to exactly match the export, so a link removed from the export is removed from the document (the raw sender/receiver cell text is always kept). --- diff --git a/docs/adr/025-canonical-import-and-single-migration-schema-foundation.md b/docs/adr/025-canonical-import-and-single-migration-schema-foundation.md index 94f3991e..3515413b 100644 --- a/docs/adr/025-canonical-import-and-single-migration-schema-foundation.md +++ b/docs/adr/025-canonical-import-and-single-migration-schema-foundation.md @@ -138,6 +138,11 @@ Settled sub-decisions: the same state, so the operational recovery for a partial failure is simply to fix the offending artifact and re-trigger the import — no manual cleanup of half-written data is required. A future maintainer must not assume all-or-nothing semantics. +- **Path-escape aborts the whole import (fail-closed), by design.** A path-traversal or + symlink-escape in a row's file path is treated as an attack signal: the import aborts rather + than recording the row as a `SkippedFile` and continuing. This is a deliberate owner decision + (2026-05-27) over a per-file skip — a malicious path must surface loudly, not be silently + tolerated. - **`PersonSummaryDTO` coupling.** `provisional` was added to the `PersonSummaryDTO` native interface projection; because the projection is backed by native SQL, the column had to be added to all three native `SELECT`s (`findAllWithDocumentCount`, `searchWithDocumentCount`,