Project: auditPic Version: 1.1 Date: 2026-04-15 Status: Draft Owner: GloryLabs
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?
| 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) |
| 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 |
| 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 |
/public/photos/{verificationId}).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.
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.
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.
| 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.
docs/incident-response.md (GDPR Art.33/34, 72h AP notification)docs/bcp-dr.md (NIS2 Art.21, RTO 8h / RPO 1h)DELETE /api/v1/auth/me (cascades to MinIO objects, photo rows, refresh tokens, user row in one transaction; idempotent)docs/privacy-training.md| 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 |
| 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. |
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.
| Role | Name | Date | Signature | |------|------|------|-----------| | Author | GloryLabs | 2026-03-27 | | | Reviewer | | | | | Approver | | | |
| 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