본문으로 건너뛰기

Part 3: Personal Data Flow

ItemContent
Document NamePart 3: Personal Data Flow
Product NameDTA Wide Sleep Management Platform
Date2026-06-18
ScopePart 3 (Backend) — limited to user personal/sensitive data
Related ArticlesO.Purp_1/3/7, O.Data_1/2/3/5/6/7, O.Arch_2/5, O.TrdP_6/9/10, O.Ntwk_1
Reference StandardsBSI TR-03161, GDPR Art. 30 (Records of processing)

1. Purpose and Scope

This document defines the collection, processing, storage, transfer, and deletion flow of user personal and sensitive data processed by the DTA Wide backend (dta-wide-api). It serves as shared evidence for several BSI articles (see §0 mapping).

Scope limitation: This document covers personal and sensitive data only. Non-personal operational data (configuration, lookup tables, logging infrastructure) and the overall application architecture are out of scope. For system architecture see p3_01_backend_infra_architecture, for cloud outsourcing responsibility see p3_04_cloud_outsourcing_responsibility, and for cryptographic key lifecycle see p3_05_cryptographic_key_lifecycle.

Every factual statement in this document is backed by a code/schema anchor (file:line).

0. BSI Articles Covered by This Document

SectionCovered Articles
§2 Personal data inventory & classificationO.Purp_1 (BSIA-238), O.Data_3 (314), O.Arch_2 (246)
§3 Data flow diagramO.Arch_2 (246), O.Ntwk_1 (327)
§4 Lifecycle (collection→deletion)O.Purp_3 (240), O.Data_2 (313), O.Data_7 (318)
§5 Storage map + at-rest encryptionO.Data_1 (312), O.Arch_4 (248)
§6 External / third-party sharing matrixO.TrdP_6 (273), O.TrdP_9 (276), O.TrdP_10 (277), O.Purp_7 (244)
§7 Interface protection & notificationsO.Arch_5 (249), O.Data_5 (316), O.Data_6 (317)

2. Personal Data Inventory and Classification

Categories of personal/sensitive data processed by the backend. Default storage is PostgreSQL (Cloud SQL, private schema).

CategoryData itemStorage (anchor)Classification
Identity — eIDeidHash (SHA-256, unique)eid_links.eid_hash (private.prisma:247)Pseudonymized
Identity — eIDkvnr (insurance number, persisted)eid_links.kvnr VarChar(10) (private.prisma:248)Sensitive
Identity — eIDmetadata (sub·email·name [·insurer])eid_links.metadata Json (private.prisma:249)Personal
Identity — eIDbirthdateNot stored / not used (DTO only)
Authenticationrefresh/access token, app token, sessionRefreshToken/AccessToken/AppToken/Session (private.prisma:162/182/220/198)Secret
Authentication — 2FAdevice public key (ECC P-256 SPKI)user_device_authentications.public_key_spki (private.prisma)Public key
Consentconsent/revocation history, IP, integrity HMACuser_agreementments (private.prisma:307-329)Personal
Usage historyuserId, IP, User-Agent, timestampUsageHistory (private.prisma)Personal
Health datasleep logs / questionnaire responses (transformed)Firestore (agent-data repositories)Sensitive

eID attribute storage (correction reflected): eID profile attributes are not discarded transiently; they are stored in eid_links.metadata (Json). The stored fields differ by write path — initial signup (eu-signup-orchestrator.service.ts:270-273) stores sub·email·name, while link completion (complete-eid-link.handler.ts:104-110) additionally stores insurer. kvnr is persisted to prevent ePA re-authentication (schema comment, plan 177 agenda-001) and is masked on use (Kvnr.masked()kvnr.vo.ts:28). birthdate exists in the DTO but is neither stored nor used (cohort is determined by access-code/OAuth state).


3. Data Flow Diagram

Shows personal data collection → storage → (limited) external flow together with the trust boundary. The thick arrow (①) is inbound collection; the dotted arrow (④) is an inactive (no-transfer) path.

Flow summary: ① The app sends personal data over TLS; the API validates it (ValidationPipe) and ② stores it by category inside the trust boundary (GCP · EU, encrypted at rest — §5). The only personal/sensitive data flow that crosses the trust boundary is ③ the eID verification OAuth handshake with gematik, which carries no health data or KVNR. ④ The only external egress path for KVNR (ePA) is currently a stub, so no live transfer occurs (see §6). All inbound communication is TLS-encrypted (O.Ntwk_1, see p3_05/177-cryptography-justification).


4. Lifecycle (Collection → Processing → Storage → Transfer → Deletion)

StageProcessingControl / anchor
CollectionInbound data validated by global ValidationPipe (whitelist:true); undeclared fields strippedmain.ts:641-667 (O.Source_1 / BSIA-257)
ProcessingPurpose-based minimization. Identifiers such as KVNR are masked before loggingkvnr.vo.ts:28, logger masking (177-data-purpose-mapping)
StoragePer-category stores (§5). Sensitive tokens and file URLs are field-encryptedauth.prisma:95, private.prisma:2082/2203
TransferExternal transfer limited to the §6 matrix. No live external transfer of health data or KVNR§6
DeletionOn account termination eID links are deleted (eidLink.deleteMany); 2FA device keys are cascade-deletedprivate.prisma (UserDeviceAuthentication onDelete: Cascade)

For retention/deletion policy detail see 177-data-retention-policy (O.Data_2/_7).


5. Storage Map and At-Rest Encryption

StorePersonal data storedAt-rest encryption
PostgreSQL (Cloud SQL)identity (eID), authentication, consent, usage historyGCP default encryption at rest (platform) + application-level encryption for sensitive fields
Firestoretransformed sleep / questionnaire health dataGCP default encryption at rest (platform)
Redis (Memorystore)session / cache (short-lived)GCP default encryption at rest (platform)

Application-level field encryption (code-confirmed):

  • refresh_token_cipher — encrypted storage of external IdP refresh token (auth.prisma:95)
  • file_url_cipher — encrypted file URL (private.prisma:2203)
  • encryption_key_id — key identifier column (private.prisma:2082, a separate model from the above)

For platform encryption and key management detail see p3_05_cryptographic_key_lifecycle, 177-cryptography-justification.


6. External / Third-Party Sharing Matrix

Complete set of paths by which the backend transfers personal data externally. (O.TrdP_6/9/10, O.Purp_7)

RecipientData transferredPurposeProtectionNote
gematik eID IdPOAuth authentication handshakeeID identity verificationTLS + OAuth/PKCENo health data transferred
ePA export(KVNR — not transferred)ePA integration (under development)Only a stub adapter is bound — no live transfer (epa-export-stub.adapter.ts:16-25, binding feature-health-data-export.module.ts:103-104)
GCP sub-processorsdata stored per §5hosting · storage · messagingDPA + region pinning (EU)Cloud SQL/Firestore/Redis/Pub-Sub/BigQuery (p3_04)

O.TrdP_6 (no sensitive data transfer): Health data is not transferred to third parties other than GCP sub-processors (storage purpose, under DPA). The only external egress path for KVNR is ePA export; however, as of 2026-06-18 the ePA integration is under development, and the sole implementation bound in production is a stub adapter (EpaExportStubAdapter). On EpaExportPort.send the stub performs no actual transfer — it only emits a warning log and returns { accepted: true, referenceId: 'stub' }, and KVNR is not written to the log (epa-export-stub.adapter.ts:16-25). The domain handler's epaPort.send(...) call (epa-export.handler.ts:158) resolves to this stub via DI binding (feature-health-data-export.module.ts:103-104); thus the call site alone may read as a live transfer, but no live transfer occurs. A live adapter will replace the stub once the TIC/Konnektor infrastructure is ready. O.TrdP_9 (notification of external services): GCP sub-processors and data-sharing details are disclosed in the cloud outsourcing document (p3_04) and the privacy policy (the user-facing disclosure screen is in P.1-Mobile/landing scope).


7. Interface Protection and Notifications

  • Interface protection (O.Arch_5 / O.TrdP_10): All interfaces to external services apply TLS encryption + authentication/authorization (scope) + input validation. Inbound validation follows §4 (collection); transport encryption follows O.Ntwk_1 (p3_05/177-cryptography-justification).
  • Data export control (O.Data_5): Export of KVNR/health data outside its source is limited to the §6 matrix; no other export path exists.
  • Notification payload (O.Data_6): Identifiers (e.g. KVNR) are masked on use (Kvnr.masked()kvnr.vo.ts:28). Exclusion of sensitive data from notification/push payloads is managed separately as an O.Data_6 control item.

Appendix: Supporting Code Anchors

FactAnchor
eID attributes stored in metadatacomplete-eid-link.handler.ts:104-110
eID link model / KVNR persistenceprivate.prisma:244-263
consent/revocation history + integrity HMACprivate.prisma:307-329
KVNR maskingkvnr.vo.ts:28
ePA egress = stub (no live transfer)epa-export-stub.adapter.ts:16-25 + binding feature-health-data-export.module.ts:103-104 (call site epa-export.handler.ts:158)
inbound validation (ValidationPipe)main.ts:641-667
field encryption — refresh tokenauth.prisma:95 (refresh_token_cipher)
field encryption — file URLprivate.prisma:2203 (file_url_cipher), key id private.prisma:2082 (encryption_key_id, separate model)