[VS-NfD] Write the security documentation (architecture, data flows, network plan, ports, trust boundaries) #228

Closed
opened 2026-07-30 01:43:56 +02:00 by fable-5 · 5 comments
Collaborator

Plan reference: 20-massnahmenplan.md -> Phase 5
ADR: ADR 0019
Effort: L (4 AT)
Depends on:

Context

This is the document an assessor reads first and returns to. It has to be
accurate to the digit on ports, services and trust boundaries.

Current state

  • Substantial material exists and needs consolidating rather than
    inventing: docs/architecture/security.md, deployment.md,
    data-model.md, permissions.md, realtime-collaboration.md,
    plugin-architecture.md, plus deploy/compose/docker-compose.yml as the
    authoritative service and port list (web, api, collab, backup, db,
    gotenberg, pandoc, caddy).

Acceptance criteria

  • Component diagram with every service, its purpose and its
    privileges.
  • Data-flow diagrams for: authentication, editing (api ↔ collab ↔
    Postgres LISTEN/NOTIFY), export (pandoc/Gotenberg sidecars),
    backup, and each read channel from #222.
  • Network plan with all ports and protocols, internal versus
    externally exposed, matching the compose files exactly.
  • Trust boundaries named explicitly, including the plugin sandbox
    (ADR 0008) and the reverse-proxy boundary from #215.
  • Every content copy is listed — database, uploads, page_updates,
    page_content_cache including the search vector, versions, backups,
    export artefacts — because the deletion concept in #229 depends on
    this list being complete.
  • Diagrams are maintainable as text (the repo already renders
    Mermaid), not binary images.

Out of scope

Penetration test and threat model as separate deliverables.

**Plan reference:** `20-massnahmenplan.md` -> Phase 5 **ADR:** ADR 0019 **Effort:** L (4 AT) **Depends on:** — ## Context This is the document an assessor reads first and returns to. It has to be accurate to the digit on ports, services and trust boundaries. ## Current state - Substantial material exists and needs consolidating rather than inventing: `docs/architecture/security.md`, `deployment.md`, `data-model.md`, `permissions.md`, `realtime-collaboration.md`, `plugin-architecture.md`, plus `deploy/compose/docker-compose.yml` as the authoritative service and port list (web, api, collab, backup, db, gotenberg, pandoc, caddy). ## Acceptance criteria - [ ] Component diagram with every service, its purpose and its privileges. - [ ] Data-flow diagrams for: authentication, editing (api ↔ collab ↔ Postgres `LISTEN/NOTIFY`), export (pandoc/Gotenberg sidecars), backup, and each read channel from #222. - [ ] Network plan with all ports and protocols, internal versus externally exposed, matching the compose files exactly. - [ ] Trust boundaries named explicitly, including the plugin sandbox (ADR 0008) and the reverse-proxy boundary from #215. - [ ] Every content copy is listed — database, uploads, `page_updates`, `page_content_cache` including the search vector, versions, backups, export artefacts — because the deletion concept in #229 depends on this list being complete. - [ ] Diagrams are maintainable as text (the repo already renders Mermaid), not binary images. ## Out of scope Penetration test and threat model as separate deliverables.
fable-5 added this to the M30 — VS-NfD: compliance documentation milestone 2026-07-30 01:43:56 +02:00
fable-5 added the
effort:L
area:docs
vs-nfd
labels 2026-07-30 01:43:56 +02:00
Author
Collaborator

Toolchain versions for the hardening/ops documentation (from #236, PR #257): Node 22.15.1 (single authoritative source: .node-version; consumed by CI/CD via node-version-file, by all Dockerfiles as node:22.15.1-alpine, engines floor >=22.15.1; drift fails CI via an early checks step). pnpm 11.9.0 (packageManager). postgres 17.5-alpine, pandoc/core:3.6, gotenberg:8 (digest pinning tracked in #203). Update procedure: docs/architecture/operations.md, Update strategy section.

From #202 (PR #258, pending): SBOMs are published as build artefacts named supply-chain-vX.Y.Z on each release run of release.yml (one CycloneDX SBOM per image, one for the workspace, plus the pnpm licenses report); license policy lives in scripts/check-licenses.mjs.

Toolchain versions for the hardening/ops documentation (from #236, PR #257): Node 22.15.1 (single authoritative source: .node-version; consumed by CI/CD via node-version-file, by all Dockerfiles as node:22.15.1-alpine, engines floor >=22.15.1; drift fails CI via an early checks step). pnpm 11.9.0 (packageManager). postgres 17.5-alpine, pandoc/core:3.6, gotenberg:8 (digest pinning tracked in #203). Update procedure: docs/architecture/operations.md, Update strategy section. From #202 (PR #258, pending): SBOMs are published as build artefacts named supply-chain-vX.Y.Z on each release run of release.yml (one CycloneDX SBOM per image, one for the workspace, plus the pnpm licenses report); license policy lives in scripts/check-licenses.mjs.
Author
Collaborator

From #201 (PR #261): the audit event catalogue - the stable contract for SIEM/syslog rules - lives at docs/architecture/audit-events.md (v1.0). Forwarding path for the ops documentation: container stdout (Docker json-file with rotation) -> operator's collector (promtail/fluent-bit/vector/...) -> syslog/SIEM; there is deliberately no application-side syslog client. Selector: msg prefix 'audit: ', routing hint: the severity field (info|notice|warning|critical).

From #201 (PR #261): the audit event catalogue - the stable contract for SIEM/syslog rules - lives at docs/architecture/audit-events.md (v1.0). Forwarding path for the ops documentation: container stdout (Docker json-file with rotation) -> operator's collector (promtail/fluent-bit/vector/...) -> syslog/SIEM; there is deliberately no application-side syslog client. Selector: msg prefix 'audit: ', routing hint: the severity field (info|notice|warning|critical).
Author
Collaborator

Web-view marking convention (#206, for the operations manual): the fixed wording VS - NUR FUER DEN DIENSTGEBRAUCH renders as a bold, centered band with top+bottom rules ABOVE and BELOW the page content, in reading view, editor and public view; unclassified pages show nothing. Styling uses only the standard text token, so it holds in light and dark and under every accent theme. Screenshots (light/dark):

classified page, light theme

classified page, dark theme

Browser print (#207): the same pair repeats as running header+footer on EVERY printed sheet (real-table thead/tfoot mechanism; @page margin boxes are unimplemented in Chromium/Gecko and position:fixed places unreliably). Verified as PDF-from-browser in Chromium 140 and Firefox 153 on a multi-page document; the repeatable procedure is documented in apps/web/e2e/README.md (section Print marking check).

Web-view marking convention (#206, for the operations manual): the fixed wording VS - NUR FUER DEN DIENSTGEBRAUCH renders as a bold, centered band with top+bottom rules ABOVE and BELOW the page content, in reading view, editor and public view; unclassified pages show nothing. Styling uses only the standard text token, so it holds in light and dark and under every accent theme. Screenshots (light/dark): ![classified page, light theme](https://gitea.101010.cloud/attachments/8d6aeee4-6e01-41b2-8244-7ed9028eae0e) ![classified page, dark theme](https://gitea.101010.cloud/attachments/b80c9475-e2ca-491e-a6d6-1dc38506668c) Browser print (#207): the same pair repeats as running header+footer on EVERY printed sheet (real-table thead/tfoot mechanism; @page margin boxes are unimplemented in Chromium/Gecko and position:fixed places unreliably). Verified as PDF-from-browser in Chromium 140 and Firefox 153 on a multi-page document; the repeatable procedure is documented in apps/web/e2e/README.md (section Print marking check).
Author
Collaborator

Channel conventions from the rest of M26 (for the operations manual):

  • Server PDF (#208): Gotenberg header/footer templates repeat the marking on every page - bold centered running header, plus the marking next to the page numbers in the footer. Unclassified exports are unchanged.
  • DOCX/ODT (#209): classified exports use reference documents whose page setup defines header+footer with the marking (repeats per page in Word/LibreOffice, not deletable body text). Binaries + regeneration script in apps/api/assets/ (README there).
  • Markdown ZIP (#210): classified files carry frontmatter (classification: vs_nfd) + the visible marking line top and bottom; manifest.json lists every file with its level and states the highest once; classified media gets a sibling .classification.txt companion (#212).
  • Feeds/public API/search/no-JS shell (#211): Atom category element per classified entry + feed-level highest (scheme urn:dorfteich:classification, documented in public-api.md); classification field in every public API page representation; search hits carry the level and the UI shows the marking with every snippet; the shell renders the banner above and below the content.
  • Attachment downloads (#212): filename prefix VS-NfD_ (short form fixed in ADR 0022); pageId-unset attachments fail closed to the pond's highest level; operations.md has the full write-up.
  • Uploads (#213): persistent warning on classified pages; classification.uploadPolicy=block rejects server-side.
Channel conventions from the rest of M26 (for the operations manual): - **Server PDF (#208)**: Gotenberg header/footer templates repeat the marking on every page - bold centered running header, plus the marking next to the page numbers in the footer. Unclassified exports are unchanged. - **DOCX/ODT (#209)**: classified exports use reference documents whose page setup defines header+footer with the marking (repeats per page in Word/LibreOffice, not deletable body text). Binaries + regeneration script in apps/api/assets/ (README there). - **Markdown ZIP (#210)**: classified files carry frontmatter (classification: vs_nfd) + the visible marking line top and bottom; manifest.json lists every file with its level and states the highest once; classified media gets a sibling .classification.txt companion (#212). - **Feeds/public API/search/no-JS shell (#211)**: Atom category element per classified entry + feed-level highest (scheme urn:dorfteich:classification, documented in public-api.md); classification field in every public API page representation; search hits carry the level and the UI shows the marking with every snippet; the shell renders the banner above and below the content. - **Attachment downloads (#212)**: filename prefix VS-NfD_ (short form fixed in ADR 0022); pageId-unset attachments fail closed to the pond's highest level; operations.md has the full write-up. - **Uploads (#213)**: persistent warning on classified pages; classification.uploadPolicy=block rejects server-side.
Author
Collaborator

Done in commit f0c6af4 (PR #273, CI run 579 green, fast-forward merged on Stefan's standing merge instruction).

Evidence: docs/vs-nfd/60-sicherheitsdokumentation.md - component diagram with per-service purpose/privileges (all own images non-root), network plan digit-exact against deploy/compose/docker-compose.yml (127.0.0.1-only app bindings, internal-only data zone, no host binding for db/pandoc/gotenberg/backup), Mermaid data-flow diagrams for auth (fail-closed CSRF, Argon2id, session bounds), realtime editing (60s HKDF collab token, LISTEN/NOTIFY), export (pinned sidecars, marking options), backup (ADR-0026 allowlist) and all nine read channels with their marking; named trust boundaries incl. plugin sandbox and outbound-only SMTP/mirror; complete content-copy list (DB, volumes, outside-instance) as the basis of the #229 deletion concept; crypto inventory. Maintained-in-same-PR rule stated.

Done in commit f0c6af4 (PR #273, CI run 579 green, fast-forward merged on Stefan's standing merge instruction). Evidence: docs/vs-nfd/60-sicherheitsdokumentation.md - component diagram with per-service purpose/privileges (all own images non-root), network plan digit-exact against deploy/compose/docker-compose.yml (127.0.0.1-only app bindings, internal-only data zone, no host binding for db/pandoc/gotenberg/backup), Mermaid data-flow diagrams for auth (fail-closed CSRF, Argon2id, session bounds), realtime editing (60s HKDF collab token, LISTEN/NOTIFY), export (pinned sidecars, marking options), backup (ADR-0026 allowlist) and all nine read channels with their marking; named trust boundaries incl. plugin sandbox and outbound-only SMTP/mirror; complete content-copy list (DB, volumes, outside-instance) as the basis of the #229 deletion concept; crypto inventory. Maintained-in-same-PR rule stated.
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#228
No description provided.