[VS-NfD] Mark attachment downloads by filename prefix and companion file #212

Closed
opened 2026-07-30 01:43:45 +02:00 by fable-5 · 1 comment
Collaborator

Plan reference: 20-massnahmenplan.md -> P1-2 (output channels)
ADR: ADR 0022
Effort: M (1–2 AT)
Depends on: #204

Context

An attachment leaves the application as an opaque binary — we cannot write
into arbitrary file formats, so the marking has to live in the name and in
an accompanying file. This is the channel where an honest limitation must
be documented rather than papered over.

Current state

  • Download routes: apps/api/src/files/files.controller.ts:51,71;
    Content-Disposition is set for the pond ZIP
    (import-export/export.service.ts:68) and the single-page Markdown
    download (apps/api/src/pages/pages.controller.ts:122).
  • Attachments inherit no classification today (the field arrives with
    #204 on Page, and an attachment links to a page).

Acceptance criteria

  • A download of an attachment belonging to a classified page carries a
    documented filename prefix, and a companion text file (or the
    containing archive) states the classification.
  • The classification an attachment inherits is defined unambiguously
    for the case where its pageId link is unset (paste-then-insert) —
    fail closed, and documented.
  • Tests: prefixed filename for a classified page's attachment;
    unchanged filename for an unclassified one; unset pageId behaves as
    documented.
  • The residual risk "the file's own content carries no marking" is
    recorded in #231, not hidden.

Out of scope

Writing markings into file formats (PDF/Office attachments), and blocking
downloads (#213 covers the upload side).

**Plan reference:** `20-massnahmenplan.md` -> P1-2 (output channels) **ADR:** ADR 0022 **Effort:** M (1–2 AT) **Depends on:** #204 ## Context An attachment leaves the application as an opaque binary — we cannot write into arbitrary file formats, so the marking has to live in the name and in an accompanying file. This is the channel where an honest limitation must be documented rather than papered over. ## Current state - Download routes: `apps/api/src/files/files.controller.ts:51,71`; `Content-Disposition` is set for the pond ZIP (`import-export/export.service.ts:68`) and the single-page Markdown download (`apps/api/src/pages/pages.controller.ts:122`). - Attachments inherit no classification today (the field arrives with #204 on `Page`, and an attachment links to a page). ## Acceptance criteria - [ ] A download of an attachment belonging to a classified page carries a documented filename prefix, and a companion text file (or the containing archive) states the classification. - [ ] The classification an attachment inherits is defined unambiguously for the case where its `pageId` link is unset (paste-then-insert) — fail closed, and documented. - [ ] Tests: prefixed filename for a classified page's attachment; unchanged filename for an unclassified one; unset `pageId` behaves as documented. - [ ] The residual risk "the file's own content carries no marking" is recorded in #231, not hidden. ## Out of scope Writing markings into file formats (PDF/Office attachments), and blocking downloads (#213 covers the upload side).
fable-5 added this to the M26 — VS-NfD: classification metadata milestone 2026-07-30 01:43:45 +02:00
fable-5 added the
area:export
vs-nfd:blocker
vs-nfd
effort:M
labels 2026-07-30 01:43:45 +02:00
Author
Collaborator

Done in PR #271 (commit e505fc7, CI runs 559+560 green, fast-forward merged on Stefan's standing merge instruction).

Evidence:

  • Downloads of classified attachments carry the documented filename prefix VS-NfD_ in Content-Disposition (short form for file names fixed in ADR 0022; single source classificationFilenamePrefix() in @dorfteich/shared).
  • Effective classification defined unambiguously: linked page's level; unset pageId (paste-then-insert, pond-level files) FAILS CLOSED to the highest level of any live page in the pond - documented in operations.md (section Classified attachment downloads) and pinned by test in both directions.
  • Containing archive: the pond export ZIP lists every media file's level in manifest.json (#210) and adds a sibling .classification.txt companion with the full marking for classified media.
  • Residual risk (file content itself carries no marking) recorded on #231, not hidden.
  • Tests: prefixed classified download, unchanged open download, fail-closed orphan both ways, ZIP companion + manifest level (files.e2e.db.test.ts, export.service.db.test.ts).
Done in PR #271 (commit e505fc7, CI runs 559+560 green, fast-forward merged on Stefan's standing merge instruction). Evidence: - Downloads of classified attachments carry the documented filename prefix VS-NfD_ in Content-Disposition (short form for file names fixed in ADR 0022; single source classificationFilenamePrefix() in @dorfteich/shared). - Effective classification defined unambiguously: linked page's level; unset pageId (paste-then-insert, pond-level files) FAILS CLOSED to the highest level of any live page in the pond - documented in operations.md (section Classified attachment downloads) and pinned by test in both directions. - Containing archive: the pond export ZIP lists every media file's level in manifest.json (#210) and adds a sibling <file>.classification.txt companion with the full marking for classified media. - Residual risk (file content itself carries no marking) recorded on #231, not hidden. - Tests: prefixed classified download, unchanged open download, fail-closed orphan both ways, ZIP companion + manifest level (files.e2e.db.test.ts, export.service.db.test.ts).
fable-5 referenced this issue from a commit 2026-07-31 10:01:14 +02:00
fable-5 referenced this issue from a commit 2026-07-31 10:35:39 +02:00
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#212
No description provided.