Athena — auditPic/compliance/dpia.md

DPIA — Data Protection Impact Assessment

Project: auditPic Version: 1.1 Date: 2026-04-15 Status: Draft Owner: GloryLabs


1. Project Description

What does this system do? auditPic is a Flutter mobile application for field auditors. Auditors use the app to photograph physical locations, assets, or situations as evidence for audits. Each photo is hashed using SHA-256 on-device and the hash is re-verified server-side to guarantee integrity (tamper-evidence). A QR code is generated per photo that opens a public viewer where anyone can confirm the photo has not been altered. Photos are stored in MinIO (local) / Firebase Storage (production), audit metadata in PostgreSQL, and user accounts are managed via a self-issued JWT system (not Firebase Auth).

Why is a DPIA required?

  • [x] Processing of special categories of data (Art. 9 GDPR) — audit photos may incidentally capture faces of individuals (biometric-adjacent) or reveal location data; depending on audit context, photos may reveal health, religious, or other sensitive information about people present at the audited location
  • [x] Processing of data of vulnerable persons — audited locations may include healthcare facilities, schools, or social care environments where vulnerable individuals may appear in photos
  • [x] New technologies or innovative use of existing technologies — SHA-256 hashing for photo integrity and QR-code-based verification chain is an innovative use of cryptographic evidence in audit workflows
  • [x] Large-scale processing of personal data — depending on deployment, the system may process photos from many audits involving many different individuals who appear incidentally

2. Data Inventory

Personal data processed

| Category | Data fields | Purpose | Legal basis (Art. 6) | Retention | |----------|------------|---------|----------------------|-----------| | Auditor account data | Internal UUID, email address (AES-256-GCM encrypted at rest), password hash (BCrypt) | Identity management; access control | Art. 6(b) — contract with auditor's organisation | For the duration of the account; deleted on account removal | | Audit photos | Photo files (JPEG/PNG) potentially containing faces, locations, identifiable individuals | Evidence capture for audit | Art. 6(b) — performance of audit contract; Art. 6(f) — legitimate interest of audit organisation | Duration of audit retention policy (to be defined by client organisation); default proposal: 7 years for regulated audits | | Audit metadata | Audit ID, auditor UID, timestamp, GPS coordinates (if captured), audit type, status | Traceability and audit trail | Art. 6(b) — performance of contract | Same as photos | | SHA-256 hashes | Hash of each photo file | Integrity verification; tamper-evidence | Art. 6(b) — performance of contract; necessary for purpose | Stored alongside metadata; same retention | | Crash reports | Anonymised stack traces, device model, OS version (via Crashlytics) | Application stability monitoring | Art. 6(f) — legitimate interest in maintaining a functioning service | 90 days (Crashlytics default) |

Special categories (Art. 9 GDPR)

| Category | Data fields | Explicit consent obtained? | |----------|------------|---------------------------| | Biometric data (incidental) — faces captured in audit photos | Photo files where faces of individuals are identifiable | Potentially not — photos are taken in the context of auditing a location/asset, not specifically of the people present. This must be addressed in the audit briefing and privacy notice posted at the audited location. | | Health data (incidental) — photos taken in healthcare settings | Photo files that may reveal health-related information about identifiable individuals | Same as above — contextual; audit organisations must ensure a legal basis under Art. 9 for their specific audit type | | Location data revealing religious/political affiliation (incidental) | Photos at places of worship, political offices, etc. | Same as above |

Data subjects

| Group | Estimated count | Vulnerable? | |-------|----------------|-------------| | Auditors (app users) | Tens to hundreds depending on deployment | No | | Individuals incidentally appearing in audit photos | Potentially many; context-dependent | Possibly — depends on audit location (healthcare, schools, social care) | | Audit subjects / organisations | Varies | No |


3. Data Flows

Collection

  • Auditors capture photos via the Flutter app (camera-only; gallery upload is blocked).
  • SHA-256 hash is computed on-device before upload; the server re-verifies it against the received bytes.
  • Audit metadata (auditor ID, timestamp, audit context) is collected by the app.
  • User accounts are created and managed via the auditPic backend (email/password, JWT-issued).

Processing

  1. Photo is captured on device; SHA-256 hash computed on-device.
  2. Photo and hash uploaded to Spring Boot backend; server verifies the hash matches the file.
  3. Backend stores photo in MinIO / Firebase Storage; metadata written to PostgreSQL (email encrypted at rest).
  4. QR code generated encoding the public viewer URL (/public/photos/{verificationId}).
  5. Verifier scans QR code → browser opens the public viewer; HMAC signature is verified server-side.
  6. AI detection runs asynchronously to flag AI-generated images.

Storage

  • MinIO / Firebase Storage (self-hosted VPS / Google Cloud EU): stores photo files. MinIO encrypted at rest; Firebase Storage encrypted by Google. Access is server-side only — no client SDK access to storage (Firebase Security Rules deny all client access).
  • PostgreSQL (self-hosted TransIP VPS, NL): stores audit metadata, SHA-256 hashes, auditor references. Email field encrypted with AES-256-GCM at rest; lookup via HMAC-SHA256 email hash.
  • JWT tokens: short-lived access tokens (24h) + refresh tokens (30d); stored in device secure storage.

Transfer

Photo data is transmitted over TLS to the self-hosted backend on a TransIP VPS in the Netherlands (EU). In production, photos may be forwarded to Firebase Storage (Google Cloud EU region). Google Cloud DPA + SCCs are in place. Photos are not shared with any other third party except the AI detection provider (Hive Moderation, if enabled) which receives the image for analysis.

Deletion

Auditors delete their own account through DELETE /api/v1/auth/me, which atomically removes the user row, refresh tokens, photo metadata in PostgreSQL, and photo objects in MinIO. The endpoint is idempotent so repeat calls (e.g. retried over flaky networks) return 401 once the user is gone. The retention_days column per photo controls automated expiry for photos held beyond their retention period.


4. Necessity & Proportionality

Is the processing necessary for the stated purpose? Yes. Photo evidence is the core purpose of the system. SHA-256 hashing is necessary to guarantee integrity and provide tamper-evidence — without it, photos cannot serve as legally reliable audit evidence. Account data is necessary for access control and audit traceability.

Could the purpose be achieved with less data or less intrusive means? The design already minimises data: only the hash is used for verification, not the photo itself. The photo is stored only because it is the audit evidence; it cannot be replaced with a hash alone (the photo must be retrievable by the audit organisation). GPS coordinates should be optional and only enabled when the audit requires location evidence. Auditors should be briefed to minimise capture of individuals in photos where the audit subject is a location or asset.

Is the retention period proportionate? The 7-year default for regulated audits is proportionate to statutory audit record-keeping requirements in many jurisdictions. Audit organisations deploying the system must define their own retention policy based on applicable law. Crashlytics data at 90 days is proportionate to crash analysis needs.


5. Risk Assessment

| Risk | Likelihood (1-5) | Impact (1-5) | Score | Mitigation | |------|-----------------|--------------|-------|------------| | Unauthorised access to audit photos | 2 | 5 | 10 | JWT authentication required; private photos return 404 to unauthenticated callers; DB user separation (DML-only app role); MinIO/Firebase server-side only | | PII breach (email addresses) | 1 | 4 | 4 | Email encrypted at rest with AES-256-GCM; only email_hash stored in index; key in 1Password → Sealed Secrets | | Photo tampering / integrity failure | 1 | 5 | 5 | SHA-256 hash computed on-device AND re-verified server-side; HMAC-SHA256 signature over hash+timestamp; versioned key rotation | | Rate-limit bypass / brute force | 1 | 3 | 3 | RFC-1918 trusted-proxy check ensures X-Forwarded-For cannot be spoofed; sliding-window rate limiter | | Incidental capture of Art. 9 data without legal basis | 3 | 4 | 12 | Audit briefings; privacy notices at audit locations; auditor training; minimise capture of individuals | | Public viewer exposes photo to unintended audience | 2 | 3 | 6 | Photos are public by default (required for QR verification); premium users can set private; private photos return 404 | | Data loss (photos lost) | 1 | 5 | 5 | Daily encrypted off-site backups (pg_dump → GPG AES-256 → S3); retention_days enforced per photo | | Unlawful processing (no valid legal basis for audit photos) | 2 | 4 | 8 | Legal basis documented per audit type; deploying organisation responsible for their legal basis | | AI detection data (photo sent to third party) | 2 | 3 | 6 | AI detection disabled by default; when enabled, only the photo file is sent to Hive Moderation; DPA required with Hive |

Residual risk after mitigation: Medium — primarily due to the incidental capture of Art. 9 data in photos, which requires procedural controls by the deploying audit organisation.


6. Technical & Organisational Measures

  • [x] Encryption at rest (PII) — email field AES-256-GCM encrypted; key in 1Password → Sealed Secrets
  • [x] Encryption at rest (storage) — MinIO server-side encryption; Firebase Storage encrypted by Google
  • [x] Encryption in transit — TLS 1.3 via k3s nginx ingress + cert-manager Let's Encrypt
  • [x] Access control — JWT authentication; DB DML-only app user (auditpic_app); private photos 404 for unauthenticated
  • [x] Integrity guarantee — SHA-256 computed on-device AND re-verified server-side; HMAC-SHA256 signature with versioned key rotation
  • [x] Rate limiting — login (5/min), register (3/min), public viewer (30/min); spoofing-resistant X-Forwarded-For handling
  • [x] HTTP security headers — HSTS (1y, includeSubDomains), CSP, X-Frame-Options on public viewer
  • [x] Off-site backups — daily encrypted (GPG AES-256) database backup to S3
  • [x] Data minimisation — hash used for verification; GPS not collected; no photo content in error logs
  • [x] Pseudonymisation — email stored encrypted + hashed; UUIDs used as user identifiers
  • [x] Incident response procedure — see docs/incident-response.md (GDPR Art.33/34, 72h AP notification)
  • [x] BCP/DR procedure — see docs/bcp-dr.md (NIS2 Art.21, RTO 8h / RPO 1h)
  • [x] Automated account + photo deletion workflow — DELETE /api/v1/auth/me (cascades to MinIO objects, photo rows, refresh tokens, user row in one transaction; idempotent)
  • [x] Processor agreements (DPA) — Google Cloud DPA (Firebase Storage); Hive Moderation DPA required if AI detection enabled
  • [x] Staff / auditor privacy training — see docs/privacy-training.md

7. Third-Party Processors

| Processor | Country | Processing activity | DPA in place? | |-----------|---------|---------------------|--------------| | TransIP B.V. | Netherlands (EU) | VPS hosting for backend, PostgreSQL, MinIO | Yes — TransIP DPA (NL processor) | | Google (Firebase Storage) | EU (europe-west) | Photo file storage in production | Yes — Google Cloud DPA + SCCs | | Hive Moderation | USA | AI-generated image detection (when enabled) | DPA required before enabling in production |


8. Data Subject Rights

| Right | How it is fulfilled | |-------|---------------------| | Access (Art. 15) | Auditors can view their own audit records in the app. Individuals incidentally appearing in photos may submit a request; the audit organisation (as controller) responds. | | Rectification (Art. 16) | Auditor profile data (name, email) updatable in app. Photo evidence is immutable by design (integrity guarantee); rectification may require creating a new audit record. | | Erasure (Art. 17) | Auditor account deletion is self-service via DELETE /api/v1/auth/me, which cascades to refresh tokens, photo metadata, and MinIO objects in one transaction. Individuals appearing in photos may request erasure from the audit organisation (controller). | | Restriction (Art. 18) | Audit records can be locked (read-only) via admin controls pending dispute resolution. | | Portability (Art. 20) | Audit metadata and photo exports available to admin users. Firebase Auth data exportable. | | Object (Art. 21) | For processing based on legitimate interest (Art. 6f), individuals may object; the audit organisation (controller) assesses on a case-by-case basis. |


9. DPO / Legal Consultation

DPO consulted: Not applicable — GloryLabs does not meet the threshold for mandatory DPO appointment. However, deploying audit organisations in regulated sectors may be required to appoint a DPO and conduct their own DPIA. Date: 2026-03-27 Outcome: Pending review of incidental Art. 9 data handling procedures and audit briefing requirements.

Prior consultation with AP required (Art. 36)? No for GloryLabs as platform provider. Deploying audit organisations should assess independently based on their specific audit context.


10. Approval

| Role | Name | Date | Signature | |------|------|------|-----------| | Author | GloryLabs | 2026-03-27 | | | Reviewer | | | | | Approver | | | |


11. Review History

| Version | Date | Author | Changes | |---------|------|--------|---------| | 1.0 | 2026-03-27 | GloryLabs | Initial version | | 1.1 | 2026-04-15 | GloryLabs | Updated to reflect actual implementation: custom JWT (not Firebase Auth), PostgreSQL + MinIO (not Firestore), AES-256-GCM email encryption, server-side SHA-256 verification, HMAC key rotation, rate limiting, HSTS/CSP, off-site backups, corrected third-party processor table |

Reacties

Nog geen reacties