Campflow — Tietosuojavaikutusten arviointi (DPIA)
GDPR-asetuksen (EU 2016/679) Art. 35 mukainen arviointi. Koskee Campflow-leirinhallintapalvelun käyttämiä käsittelytoimia, joissa käsitellään alaikäisten henkilötietoja sekä erityisiä henkilötietoryhmiä (terveys, allergiat, lääkitys).
1. Tarvittiinko DPIA?
Kyllä. GDPR Art. 35(3) listaa tilanteet, joissa DPIA on pakollinen. Campflow täyttää useita kriteerejä:
- Alaikäisten henkilötiedot (Art. 8) — pääosa rekisteröidyistä on alle 16-vuotiaita leiriläisiä.
- Erityiset henkilötietoryhmät (Art. 9) — terveystiedot, allergiat ja lääkitykset ovat järjestelmän ydintietoa.
- Suuri mittakaava — palvelua käytetään useissa organisaatioissa, joiden yhteenlaskettu rekisteröityjen määrä on tuhansia.
- Haavoittuva ryhmä — alaikäiset eivät pysty kaikilta osin ymmärtämään suostumuksensa vaikutuksia.
Tietosuojavaltuutetun toimiston julkaisema lista käsittelytoimista, joista DPIA on tehtävä (TSV 2018), tukee tätä arviointia.
2. Käsittelytoimien systemaattinen kuvaus
2.1 Käsittelyn kuvaus
Campflow on selainpohjainen leirinhallintapalvelu (SaaS), jonka avulla seurakunnat, lippukunnat, urheiluseurat ja yhdistykset hallinnoivat lasten ja nuorten leirejä. Huoltaja ilmoittaa lapsensa leirille, järjestäjä ottaa vastaan ilmoittautumiset, kerää tarvittavat lupatiedot, suunnittelee ohjelman ja viestii huoltajille leirin aikana.
2.2 Käsittelyn tarkoitukset
- Leirin ilmoittautumisten vastaanotto ja hallinta
- Osallistujien terveysturvallisuuden takaaminen (allergiat, lääkitys, uimataito)
- Ryhmien, majoituksen ja aikataulujen suunnittelu
- Yhteydenpito huoltajiin (leirikirje, huoltajaportaali, hätäilmoitukset)
- Lakisääteisten velvoitteiden täyttäminen (kirjanpito, työturvallisuus, lääkkeenantoloki)
2.3 Käsiteltävät tiedot
| Tietoryhmä | Esimerkkikentät | Käsittelyperuste |
|---|---|---|
| Perustiedot (lapsi) | nimi, syntymäaika, sukupuoli, osoite, kotikunta | Art. 6(1)(b) sopimus + Art. 8 huoltajan suostumus |
| Yhteystiedot (huoltaja) | nimi, puhelin, sähköposti | Art. 6(1)(b) sopimus |
| Yhteystieto (osallistuja itse) | oma puhelinnumero — vapaaehtoinen, kysytään oletuksena vain tapahtumissa ja matkoilla | Art. 6(1)(b) sopimus. Käyttötarkoitus: osallistujan tavoittaminen tilanteessa jossa hän ei ole jatkuvassa valvonnassa (bussimatka, tapahtuma-alue). Näkyvyys: matkanjohtaja, ryhmänjohtaja, EA-vastaava ja yövartija — ei keittiö- eikä muu tukihenkilöstö. Tapahtumassa ryhmänjohtaja näkee kaikki osallistujat, joten kenttä on hänelle laajempi kuin leirillä; tämä on tietoinen valinta, koska juuri ryhmänjohtaja etsii kadonneen nuoren. |
| Terveystiedot | allergiat, sairaudet, lääkitys, uimataito, kipulääkelupa | Art. 9(2)(a) nimenomainen suostumus |
| Erityisruokavaliot | kasvis, vegaani, gluteeniton, laktoositon, jne. | Art. 9(2)(a) nimenomainen suostumus |
| Kuvauslupa + valokuvat | photoOk-arvo, EXIF-stripatut valokuvat | Art. 6(1)(a) suostumus, Art. 9(2)(a) jos henkilökohtaisia piirteitä |
| Henkilökunta | nimi, puhelin, sähköposti, rooli | Art. 6(1)(f) oikeutettu etu (työsopimuksen täytäntöönpano) |
| Lääkkeenantoloki | annettu lääke, annos, aika, antaja | Art. 6(1)(c) lakisääteinen velvoite (potilasvahinkokäytäntö) |
| Paluuperhe-muistutus (vapaaehtoinen opt-in) | huoltajan nimi + sähköposti, lapsen etunimi, syntymävuosi, leirityyppi, peruutus-token — EI terveys-/allergiatietoja | Art. 6(1)(a) suostumus; rekisterinpitäjä = organisaatio; säilytys 24 kk inaktiivisuudesta tai heti peruttaessa |
2.4 Tietovirta
- Huoltaja täyttää julkisen ilmoittautumislomakkeen (ilmo.html) → tiedot kirjoitetaan Firestoreen.
- Järjestäjä kirjautuu sovellukseen (app.html), näkee ilmoittautumiset, hyväksyy/hylkää, jakaa ryhmiin.
- Henkilökunta (leiripomo, ohjaaja, EA-vastaava, keittiö, yövartija, uimavalvoja) saa rajatun pääsyn rooli-perusteisesti.
- Huoltajaportaali (huoltaja.html) — huoltaja saa parentToken-linkin sähköpostiin ja näkee leirin aikana lapsensa tilanteen.
- Cloud Functions hoitavat sähköpostit (Resend), valokuvankäsittelyn (Sharp + EXIF-strippaus), AI-toiminnot (Anthropic Claude) ja leirimainoksen taustakuvan generoinnin (OpenAI).
- Säilytysaikojen päätyttyä tiedot poistetaan automaattisesti porras-mallin mukaisesti (cleanupExpiredData).
2.5 Vastaanottajat ja tietojenkäsittelijät
| Vastaanottaja | Rooli | Sijainti |
|---|---|---|
| Google Firebase (Firestore, Storage, Cloud Functions, Auth) | Käsittelijä | EU (europe-west1) |
| Resend (sähköpostipalvelu) | Käsittelijä | EU/USA (Standard Contractual Clauses) |
| Anthropic (Claude API) | Käsittelijä — AI-toiminnot: osallistujakohtaiset allergia- ja ruokavaliotiedot ilman nimiä (keittiön AI-työkalut, pseudonymisoitu), numeroitu ikä, sukupuoli ja uimataito (joukkuejako), järjestäjän lataamat asiakirjat (voivat sisältää aikuisten vastuuhenkilöiden nimiä ja yhteystietoja), käyttäjän kirjoittamat kysymykset ja hakulausekkeet sekä ilmoittautumissivun esittelyteksti (konekäännös) | USA (SCC + tietoja minimoivat suojatoimet) |
| OpenAI (kuvagenerointi) | Käsittelijä — leirimainoksen taustakuva: vain leirin ajankohta, sijaintiteksti ja pääkäyttäjän tyylitoive (enintään 200 merkkiä), ei henkilötietoja | USA |
| Sentry (virheraportointi) | Käsittelijä — vain teknisiä lokeja | EU |
| Cloudflare Turnstile | Käsittelijä — bot-suoja | EU/USA |
| Rahastonhoitaja (organisaation nimeämä henkilö) | Vastaanottaja — aikarajoitettu token-linkki maksuseurantaan (leiriläisten nimet + odotettavat/maksetut summat, EI terveys-/allergiatietoja). Ei kirjautumista; pääsy peruutettavissa, voimassa ≤12 kk. Pääsy lokitetaan audit_log:iin. | EU (Firestore) |
3. Tarpeellisuuden ja oikeasuhtaisuuden arviointi
3.1 Käsittelyperuste
Pääperuste on Art. 6(1)(b) sopimus (osallistujan ja järjestäjän välinen sopimus; alaikäisen puolesta sen tekee huoltaja edustajana, laki holhoustoimesta 442/1999 4 §) sekä terveystietojen osalta Art. 9(2)(a) nimenomainen suostumus, joka annetaan ilmoittautumislomakkeessa erillisellä rastilla. Alaikäisen osallistujan puolesta suostumuksen antaa huoltaja; täysi-ikäinen osallistuja antaa sen itse (aikuisille tarkoitetut leirit ja tapahtumat sekä itse ilmoittautuvat täysi-ikäiset — lomake edellyttää itsenäiseltä ilmoittautujalta 18 vuoden ikää). Jos järjestäjä lisää täysi-ikäisen osallistujan tiedot itse, suostumuksen pyytäminen on järjestäjän vastuulla rekisterinpitäjänä. Lääkkeenantoloki perustuu Art. 6(1)(c) lakisääteiseen velvoitteeseen (potilasvahinkokäytäntö).
3.2 Tietojen minimointi
- Kerätään vain leiritoimintaan tarvittavat tiedot — ei esim. henkilötunnusta, koulutaustaa tai uskonnollista vakaumusta (paitsi jos seurakunnan oma toiminta perustuu uskonnolliseen ryhmittäytymiseen).
- Ryhmänjohtaja näkee oletuksena vain oman ryhmänsä leiriläisten täydet tiedot. Muiden ryhmien lapset näkyvät anonymisoituna ("Matti V.") esim. majoitustaulukossa. Poikkeus — tapahtumat: tapahtumissa (retki, matka, konsertti), joissa pienryhmiä ei ole, tapahtuman ohjaajat/vastuuhenkilöt näkevät koko osallistujalistan (peruste: Art. 9(2)(a) huoltajan nimenomainen suostumus + turvallisuusvastuu koko osallistujajoukosta; tapahtumissa terveystietoja ei oletuksena kerätä).
- Push-ilmoituksissa ei näytetä lapsen nimeä eikä terveystietoa (lukitusnäyttö-suoja).
- AI-toiminnoille lähetetään vain toiminnon tarvitsema tieto. Keittiön AI-työkalut (esim. ruokailun allergia-analyysi) saavat osallistujakohtaiset allergia- ja ruokavaliotekstit ilman nimiä ja yhteystietoja (pseudonymisoitu Art. 9 -tieto): nimet, sähköpostit ja puhelinnumerot poistetaan tai rivi estetään ennen lähetystä, mutta vapaatekstiin kirjoitettu taivutettu tai yksittäinen etunimi ei aina tunnistu.
3.3 Säilytysajat (porras-malli)
| Porras | Aika leirin päättymisestä | Mitä poistetaan |
|---|---|---|
| 1 | 30 vrk sig-expiryn jälkeen | Odottavat allekirjoituspyynnöt, jotka ovat vanhentuneet |
| 2 | 6 kk | Terveystiedot (allergiat, terveys, särkylääkelupa, uimataito, ruokavaliot, lisätiedot, huoltajan peruutusperustelu) osallistujilta, henkilökunnalta ja ilmoittautumiskopioista; allekirjoituskuvat ja valmiit allekirjoituspyynnöt; valokuvat; hylätyt, jonotetut ja tarjotut ilmoittautumiset sekä jonotustarjoukset; huoltajaportaalin tunnisteet, viestit, kysymykset ja muutoshistoria; Aktiviteetit-syötteen terveys- ja allergiarivit (myös henkilökunnan omat allergiamuutokset); keittiön erityisruokamerkintöjen henkilötiedot (nimi, tunniste ja huomautus myös perutuista merkinnöistä; allergeeni- ja vakavuustieto säilyy ilman henkilöä, kirjaajien nimet poistetaan 12 kk:ssa) |
| 3 | 12 kk | Osallistujien ja huoltajien perustiedot; henkilökunnan tiedot (myös roolien nimilistat, majoituksen asukkaat, ryhmät, keittiövuorot, henkilökunnan ilmoitukset); kaikki ilmoittautumiset; paikallaolo; jaot ja julkinen ilmoittautumissivun peili; leirin Aktiviteetit-syöte; palautelinkkien sähköpostit. Ilmoittautuminen suljetaan (asetus jää muotoon "suljettu"). |
| 4 | 2 v | Lääkitystiedot, lääkkeenantoloki ja kaikki muu jäljellä oleva — leiridokumentti tyhjennetään. Suostumus- ja poistotodisteet säilyvät 36 kk merkinnästä (ks. 5.3). |
| Lykkäys | enintään 12 kk havainnosta | Portaat 2–4 odottavat, jos leiriä on käytetty päättymisen jälkeen (ks. 5.3). Lykkäys ei pidennä merkintäkohtaisia enimmäisaikoja (audit_log 24 kk, suostumus- ja poistotodisteet 36 kk). |
| — | 24 kk käyttämättömyydestä TAI heti huoltajan peruessa | Paluuperhe-muistutus (opt-in). Erillinen logiikka — ei sidottu leirin päättymiseen; sisältää vain minimitiedon (ei Art. 9) |
4. Riskien arviointi
Riskit on arvioitu rekisteröityjen näkökulmasta käyttäen kolmiportaista asteikkoa (alhainen / kohtalainen / korkea), arvioiden todennäköisyys × vakavuus.
R1: Tietomurto — terveystietojen vuoto
Korkea ennen suojaustaAllergia-, lääkitys- ja sairaustiedot voisivat joutua vääriin käsiin tietomurron seurauksena. Vahinko alaikäisen yksityisyydelle olisi merkittävä ja pitkäkestoinen.
R2: parentToken-vuoto sähköpostista
Korkea ennen suojaustaJos huoltajan sähköposti vuotaa (phishing tms), kolmas osapuoli voi käyttää parentToken-linkkiä ja nähdä lapsen tiedot.
R3: Henkilökunnan väärinkäyttö
KohtalainenRyhmänjohtaja, joka ei tarvitse kaikkien lasten tietoja, voi kuitenkin nähdä niitä jos ryhmäjako on tekemättä.
R4: AI-palvelun tietovuoto
KohtalainenAnthropic Claude on USA-pohjainen palvelu, jolle keittiön AI-työkalut lähettävät pseudonymisoituja osallistujakohtaisia allergia- ja ruokavaliotietoja. Jos tunnistettavaa terveystietoa päätyisi sinne, riski olisi korkea.
R5: Säilytysaikojen ylitys
KohtalainenJos automaattinen puhdistus epäonnistuu, tiedot säilyvät tarpeettomasti.
R6: Huoltajan käyttöoikeuksien hallinta
AlhainenHuoltaja ei pysty käyttämään GDPR-oikeuksiaan (Art. 15/17/20) helposti.
5. Riskinhallintatoimenpiteet
5.1 Tekniset suojat (R1, R2, R4)
- Pääsynvalvonta: Firebase Authentication + Firestore Rules. Pääsy tietoihin perustuu rooliin (admin, leiripomo, ryhmänjohtaja, EA-vastaava, keittiö, yövartija, uimavalvoja). Ryhmänjohtajalla pääsy vain oman ryhmän leiriläisiin (tapahtumissa, joissa ryhmiä ei ole, koko osallistujalistaan).
- Token-pohjainen huoltajaportaali: parentToken on 48 merkkiä pitkä (24 random byteä hex-koodattuna) ja vanhentuu 6 kuukauden kuluttua leirin päättymisestä (jos päättymispäivä puuttuu, voimassaolo lasketaan lähetyshetkestä: 6–12 kk lähetystavasta riippuen). Leirin omistaja tai leiripomo voi peruuttaa linkin milloin tahansa osallistujan kortilta (Portaalilinkit → Peruuta linkki); peruutus on välitön ja kirjataan leirin tapahtumalokiin.
- Salaus levossa ja siirrossa: Firestore + Storage käyttävät TLS 1.3 + AES-256.
- Pseudonymisointi (IP-osoitteet): huoltajien suostumus- ja tietopyyntölokeissa (consentLog, audit_log) tallennetaan IP-osoitteesta vain päivittäin vaihtuvalla suolalla laskettu SHA-256-tiiviste — ei koskaan selväkielistä IP:tä. Suola säilytetään erillään datasta Google Secret Managerissa, eikä tiivisteitä käytetä henkilön tunnistamiseen tai palauteta rekisteröidylle Art. 15 -viennissä (arvo ei ole ymmärrettävä, Art. 12(1)).
- EXIF-strippaus: Valokuvista poistetaan EXIF-metatiedot (mm. GPS-sijainti) ennen tallennusta Sharp-kirjastolla.
- Tietojen minimointi AI-puolella: leiriläisten nimiä, sähköposteja ja puhelinnumeroita ei tarkoituksella lähetetä Anthropicille — ne poistetaan tai rivi estetään ennen kutsua, ja palvelimen PII-detektori (fail-closed) estää ilmeiset nimi + terveystieto -yhdistelmät. Keittiön AI-työkalut saavat allergia- ja ruokavaliotiedot pseudonymisoituina, joukkuejako numeroidut ikä-, sukupuoli- ja uimataitotiedot. Jäännösriski: vapaatekstiin kirjoitettu taivutettu etunimi ei aina tunnistu, ja järjestäjän lataamat asiakirjat (pelastussuunnitelma, aikataulu) välitetään skannaamatta — ne voivat sisältää aikuisten vastuuhenkilöiden nimiä ja yhteystietoja.
- Origin-validation + persistent rate-limit: claudeProxy, aiAssistant, chatHelp, summarizeAllergies tarkistavat HTTP-pyynnön alkuperän ja käyttävät Firestore-pohjaista rate-limittiä joka kestää Cloud Functions cold startit.
- Rooliperustainen XSS-suoja: kaikki käyttäjän syöte renderöidään esc()-funktion läpi (ml. PDF-tulostus ja ilmoittautumislomake).
- Sentry-virheraportointi: ei sisällä henkilötietoja (PII-maski).
- Firestore PITR (Point-in-Time Recovery): 7 päivän palautusikkuna katastrofin varalta.
- Subcollection-arkkitehtuuri: leiriläisten henkilötiedot tallennettu camp-doc -alikokoelmaan (camps/{cid}/participants), johon Firestore Rules myöntää lukuoikeuden vain need-to-know-rooleille — ryhmänjohtaja näkee vain oman ryhmänsä lapset. Keittiö, keittiö-avustaja, yövartija ja uimavalvoja eivät lue alikokoelmaa suoraan, vaan saavat palvelimen rajaaman kenttäjoukon (getKitchenView, getNightEmergencyView, getSwimmingView).
- Kovakoodatut field-allowlistit: guardian- ja guardianPhone-kenttiin pääsy vain campLeader+medic+night+admin, address- ja email-kenttiin vain campLeader+medic+admin (ohittaa custom-perms). Tapahtumapoikkeus huoltajan nimelle ja puhelimelle: ks. huoltajakentät alla.
- Multi-role-tuki: servRoles + extraRoles unionoidaan automaattisesti — leader+medic-käyttäjä saa molempien roolien oikeudet.
5.2 Organisatoriset suojat (R3)
- Leirin järjestäjä on rekisterinpitäjä, Campflow tietojenkäsittelijä — vastuunjako on selvästi dokumentoitu (DPA-sopimus).
- Henkilökunta-roolit dokumentoitu sovelluksen ohjeissa (docs.html).
- Käyttöehdoissa kielto luovuttaa tunnuksia kolmansille.
- Pääsyn rajaus rooliperusteisesti Firestore Rules + client-allowlist. Lisäksi sovellus kirjaa Art. 9 -tietojen katselut sovellustason audit-lokiin (logArt9Access) keskeisillä näyttöpinnoilla (henkilökortti, hätälista, raportit, tulosteet); audit_log-kokoelma kerää kirjoitustapahtumat ja vientipyynnöt.
5.3 Säilytysaikojen valvonta (R5)
- cleanupExpiredData-funktio ajaa joka yö klo 03:00 (Europe/Helsinki) ja poistaa automaattisesti porras-mallin mukaisesti.
- Portaat erääntyvät leirin päättymispäivästä. Kun porras erääntyy ja leiriä on käytetty päättymisen jälkeen – leirille on lisätty ilmoittautumisia, osallistujia tai paikallaolopäiviä yli 14 päivää päättymispäivän jälkeen, tai leirin tietoja on muokattu portaan erääntymistä edeltävien 90 päivän aikana (ja yli 14 päivää päättymisen jälkeen) – tuhoavia portaita 2–4 lykätään enintään 12 kuukautta ensimmäisestä havainnosta, jotta uuden kauden tietoja ei poisteta vahingossa. Järjestäjälle (leirin omistajalle; jos omistajan tili on poistettu käytöstä, leirin leiripomolle) lähetetään sähköposti lykkäyksen alkaessa ja muistutus 30 päivää ennen sen päättymistä, ja lykkäyksen alku kirjataan audit_logiin. Lykkäys tehdään kerran kutakin päättymispäivää kohden; sen jälkeen portaat ajetaan päättymispäivän mukaan. Poistetulle leirille lykkäystä ei tehdä, ja jos sähköpostin vastaanottajaa ei ole, lykkäys kirjataan palvelun ylläpidon valvontalokiin.
- Jos järjestäjä muuttaa leirin päivämääriä, kaikki portaat lasketaan uudesta päättymispäivästä, myös aiemman kauden tiedoille. Päivämäärien muuttaminen on rekisterinpitäjän päätös; järjestäjää ohjeistetaan (tietosuojaseloste §7 ja käyttöohje) poistamaan edellisen kauden tiedot, joita ei enää tarvita. Jos päivämäärät tyhjennetään, leiriin sovelletaan alla kuvattuja ehdottomia enimmäisaikoja.
- Toiminnasta kirjoitetaan system_log -merkintä, jota super-admin valvoo.
- Refaktoroitu collectionGroup-kyselyksi (poistaa N+1-ongelman ja parantaa luotettavuutta organisaatioiden määrän kasvaessa).
- Ehdoton enimmäissäilytys merkinnän tekohetkestä päättymispäivästä riippumatta, myös leireille joilla ei ole endDate:a tai joiden päivämäärät on tyhjennetty: participantHistory 24 kk; audit_log 24 kk (juuritason tietopyyntöjen käsittelyloki ja katselulokit sekä leiritason audit_log); suostumus- ja poistotodisteet 36 kk (consentLog sekä leiritason auditLog: alaikäisen apuohjaajan huoltajan suostumus ja osallistujan poiston todiste); aiAudit 90 vrk. Erilliset collectionGroup-fieldOverride-indeksit varmistavat että poistokysely toteutuu eikä jää hiljaa indeksipuutteeseen.
5.4 Huoltajan ja täysi-ikäisen osallistujan oikeudet (R6) — itsepalvelu
- Art. 15 (oikeus tutustua): huoltajaportaalissa "Lataa kopio tiedoista (PDF / luettava muoto)" — käyttäjäystävällinen kooste osallistujasta tallennetuista keskeisistä tiedoista portaalin kielellä (fi/en/sv/no). Kopio kertoo itse rajauksensa: siihen eivät sisälly esimerkiksi henkilökunnan sisäiset muistiinpanot, maksutiedot, ryhmä- ja järjestelytiedot, alkuperäinen ilmoittautumislomake, sähköisen allekirjoituksen tallenteet eikä järjestelmän loki- ja katselutiedot, ja rekisteröityä ohjataan pyytämään ne rekisterinpitäjältä (Art. 12(1), 15(3)). Kopio luettelee rekisteröidyn oikeudet (Art. 15–18, 20, 21, 7(3)) ja valitusoikeuden valvontaviranomaiselle (Art. 77, tietosuojavaltuutetun toimisto). Suostumuslokin (consentLog) IP-tiiviste (ipHash) jätetään tarkoituksellisesti pois viennistä, koska se on sisäinen pseudonyymi eikä ymmärrettävä rekisteröidylle (Art. 12(1)) — suostumuksen tyyppi, versio ja ajankohta sisältyvät silti vientiin.
- Art. 17 (oikeus tulla unohdetuksi): "Pyydä tietojen poistoa" — pyyntö rekisteröidään, leirin järjestäjä saa sähköposti-ilmoituksen ja käsittelee 30 vrk:n sisällä.
- Art. 7(3) (suostumuksen peruutus): "Peruuta suostumus terveystietojen käsittelyyn" — yhtä helppoa kuin suostumuksen antaminen, milloin tahansa, ilman aikarajaa. Tyhjentää osallistujan Art. 9 -kentät välittömästi, redaktoi aiemman participantHistory-erityistietosisällön muotoon "[withdrawn]", kirjaa consentLog-merkinnän (Art. 7(1) osoitusvelvollisuus) ja ilmoittaa rekisterinpitäjälle jäännösdatan viimeistelyä varten (Art. 17(1)(b)). Ei peruuta osallistumista.
- Art. 20 (siirto-oikeus): "Lataa raakadata (JSON, kehittäjille)" — koneluettava JSON, kelpaa siirtoon toiseen järjestelmään.
- Rate-limit: 5 latausta vuorokaudessa per token (riittää huoltajan käyttöön, estää tokenin vuotamisen tilanteessa massalataukset).
- Pyynnöt rekisteröidään audit_log-kokoelmaan.
- Täysi-ikäinen osallistuja (aikuisille tarkoitettu kohde tai itse ilmoittautunut täysi-ikäinen) käyttää samoja toimintoja omassa osallistujaportaalissaan. Portaalin ja tietokopion tekstit puhuvat hänelle itselleen eivätkä huoltajasta, ja itse ilmoittautuneen osallistujan kopiossa terveystietojen käsittelyn perusteeksi merkitään hänen oma suostumuksensa ja muutoshistorian tekijäksi "Osallistuja itse".
5.5 Erityiset toimenpiteet alaikäisille
- Lapsi ei kirjaudu sovellukseen — kaikki tiedot kulkevat huoltajan tai järjestäjän kautta.
- Huoltajan suostumus on edellytys ilmoittautumiselle (lupalappu + nimenomainen terveystietosuostumus).
- 12-vuotias tai vanhempi voi antaa oman suostumuksensa kuvankäyttöön (lainsäädännöllinen ikäraja vaihtelee).
- Ryhmänjohtaja näkee vain ryhmälleen kuuluvat lapset, ei muita. Tapahtumissa (ei pienryhmiä) ohjaaja näkee koko osallistujalistan.
- Suomen tietosuojalain (1050/2018) §5 mukaan alle 13-vuotiaiden tieto vaatii huoltajan suostumuksen — Campflow vaatii kaikilta alle 18-vuotiailta lisäsuojan vuoksi.
5.6 Roolikohtaiset Art. 9 -kenttärajaukset
Allowlist on kovakoodattu sovelluskoodissa ja Firestore Rulesissa, ei voi ohittaa custom-perms:lla:
- Lääkitysväkymä (medications-tabi): vain campLeader, medic, admin.
- Ruokailu-tabi (food): vain campLeader, kitchen, kitchenHelper, admin.
- Palaute-tabi (feedback): vain campLeader, admin.
- Huoltajakentät (guardian, guardianPhone): vain campLeader, medic, night, admin. Poikkeus tapahtumissa (v9.3.217): tapahtumatilassa (eventMode) myös leader (ohjaaja) näkee huoltajan nimen ja puhelinnumeron — matkalla ohjaaja tavoittaa huoltajan esim. kun osallistuja ei saavu bussille. Osoite ja sähköposti eivät avaudu.
- Osoite ja sähköposti (address, email): vain campLeader, medic, admin.
- Allergiat (allergies): oman ryhmän ohjaaja (need-to-know) + campLeader + medic + admin + kitchen + kitchenHelper (anafylaksia-riski tarjoilun yhteydessä) + night (hätätilannenäkymä, ks. alla).
- Erityisruokavaliot (dietaryNeeds): oman ryhmän ohjaaja + campLeader + medic + admin + kitchen + kitchenHelper. Ei night eikä swim.
- Terveystiedot (health: krooniset sairaudet, lääkitykset): oman ryhmän ohjaaja + campLeader + medic + admin + night. kitchen ja kitchenHelper EIVÄT näe näitä (Art. 5(1)(c) datan minimointi — keittiön tarve on allergiat ja ruokavaliot, v9.2.383).
- Yövartija (night) ja uimavalvoja (swim): kumpikaan ei lue osallistujadokumentteja suoraan. Yövartija saa palvelimen rajaaman hätätilannenäkymän (getNightEmergencyView: nimi, syntymäaika, allergiat, health, huoltajan nimi ja puhelin, osallistujan oma puhelin, ryhmä — ei osoitetta, sähköpostia, ruokavaliota, lupia eikä muistiinpanoja). Peruste: terveystietoihin annettu suostumus (Art. 9(2)(a)) — yöllisissä sairauskohtauksissa (epilepsia, astma, diabetes, anafylaksia) tieto tarvitaan heti; Art. 9(2)(c) (elintärkeä etu) vain äkillisessä hätätilanteessa, jossa suostumusta ei ole. Jokainen haku kirjataan audit_log-kokoelmaan (night_emergency_view). Uimavalvoja saa vain getSwimmingView-näkymän (nimi, uimataito, ryhmä, pelastusliivitarve) — ei terveystietoja eikä allergioita (v9.2.474, Art. 25).
- kitchenBriefings (allergeenit nimitasolla): vain campLeader, kitchen, medic, admin. kitchenHelper EI näe (suostumus rajattu pää-keittiöhenkilöstölle).
- Bussinäkymä: leirillä ohjaaja näkee vain oman ryhmänsä lapset, eivätkä huoltajan nimi ja puhelin näy ohjaajalle (attendance.js soveltaa samaa field-allowlistia). Tapahtumassa huoltajan nimi ja puhelin näkyvät ohjaajalle (v9.3.217 tapahtumapoikkeus, ks. huoltajakentät yllä).
- Tapahtumat (campInfo.eventMode): tapahtumassa ei ole pienryhmiä, joten ryhmäkohtainen rajaus ei ole rakenteellisesti mahdollinen — vaihtoehdot ovat 'kaikki' tai 'ei mitään'. Ryhmänjohtaja (leader) näkee tapahtumassa kaikkien osallistujien allergiat, ruokavaliot ja terveystiedot. Suhteellisuusarvio: tapahtuma on lyhytkestoinen ja vastuu jakautuu koko henkilökunnalle, joten ensiapuvalmius edellyttää tätä. Tapahtumassa ohjaaja näkee myös kaikkien osallistujien huoltajan nimen ja puhelinnumeron (v9.3.217 — huoltajan tavoittaminen esim. kun osallistuja ei saavu bussille); huoltajan osoite ja sähköposti, lääkitysdata ja lääkkeenantoloki pysyvät rajattuina myös tapahtumassa (firestore.rules 390-432). Pääsy kirjataan Art. 9 -katselulokiin.
- PDF-tulostus: sama field-allowlist pakottaa rajauksen (v9.3.217 alkaen myös raporttitulosteiden huoltajasarakkeissa: terveyskooste, allergiaraportti, nousupaikkalista).
6. Konsultaatio rekisteröityjen kanssa
Huoltajat saavat ilmoittautumisen yhteydessä:
- Linkin tietosuojaselosteeseen (Art. 13/14 informointivelvollisuus).
- Erillisen suostumusrastin terveystietojen käsittelyyn (Art. 9(2)(a)).
- Erillisen suostumusrastin kuvanjulkaisuun.
- Tiedon kuluttajansuojalain peruutusoikeuden puuttumisesta (KSL 6:16§ kohta 12 — vapaa-ajan palvelu määrätyllä ajankohdalla).
- Tiedon maksuvelvoitteesta selkeästi vahvistuspainikkeessa (KSL 6:13§ — "Ilmoittaudu ja maksa X €").
6.1 Viivakoodiskannaus
Pääkokille tarjotaan tukku-tilanteissa viivakoodiskanneri (BarcodeDetector + Open Food Facts -tietokanta), joka näyttää tuotteen allergeenit + ravintotiedot ja vertaa niitä leirin osallistujien strukturoituihin allergeenitietoihin.
Tietovirta
- Lähetettävät tiedot kolmannelle osapuolelle: vain tuotteen GTIN-numero (8/12/13/14 numeroa). EI henkilötietoja, EI leirin tietoja, EI allergeenivertailun tuloksia.
- Allergeenivertailu: tehdään client-puolella selaimessa — leiriläisten
p.allergens-data EI poistu Campflow-perimetristä. - Audit-loki:
users/{uid}/camps/{campId}/barcodeScans/{id}tallentaa staffin nimen, viivakoodin, tuotenimen ja allergeenit. Säilytys 2 vuotta (perustelu: elintarviketurvallisuuden jäljitettävyys, EU 852/2004 + Suomen elintarvikelaki 297/2021).
Riskinarviointi
R7 — Pääkokin tunnistetiedot OFF-palvelimella: Cloud Run lähettää OFF:lle User-Agent: Campflow - https://campflow.fi - info@campflow.fi + Cloud Run egress-IP:n. Tämä ei ole loppukäyttäjän henkilötieto, vaan Campflow-organisaation palvelinmerkintä. Lievä, ei vaadi DPA:ta.
R8 — OFF-data on vapaaehtoisten ylläpitämä: väärä tai vanhentunut allergeenitieto voi johtaa virheellisiin päätöksiin. Lievennys: UI-disclaimer "Tarkista aina pakkaus" + neutraali "ei osu listaan" -muotoilu joka ei anna positiivista turva-väitettä (EU 1169/2011 + vahingonkorvauslaki 412/1974).
R9 — Cache 30 päivää: jos OFF:ssa allergeeni lisätään tuotteelle, Campflow näyttää vanhaa tietoa max kuukauden. Lievennys: aina näkyvä disclaimer + Avaa OFF:ssa -linkki.
Lainmukainen peruste
Käsittely (audit-loki) perustuu GDPR Art. 6(1)(f) — oikeutettu intressi (rekisterinpitäjän intressi varmistaa elintarviketurvallisuus + jäljitettävyys, joka ylittää staff-henkilön intressin olla nimettömänä työajan kirjauksissa). Henkilötiedot rajattu staff-rooliin, ei leiriläisten tietoja audit-lokissa.
6.2 Keittiö-briefing
Pääkokin pysyvä muistio keittiön staffille (kitchen / campLeader / admin / medic). Sisältää: vapaamuotoisen otsikon ja viestin (max 2000 merkkiä), automaattisesti koostetun "vakavat allergiat"-listan (lapsen NIMI + EU14-allergeenit + vapaa lisäteksti), runOut/leftover-palautteen 3 päivän ajalta. Vaihtoehtoinen sähköpostilähetys ulkopuolisille vapaehtoisille.
Tietovirta
- Sisäinen käsittely: Firestore
users/{uid}/camps/{campId}/kitchenBriefings/{id}— luetaan vain leirin keittiöstaffilta (ks. firestore.rules). Leader-rooli (ryhmänjohtaja) EI näe briefing-paneelia, koska sisältää Art. 9 -tietoja (vakavasti allergisten lasten nimet) ja huoltajan suostumus on rajattu "keittiölle ja terveysvastaaville". - Sähköpostilähetys: Resend (USA/EU) → ulkopuolisen vapaaehtoisen sähköpostiin. Pääkokki kirjoittaa viestin ja valitsee opt-in "Lähetä myös sähköpostina". Modaali sisältää oranssin GDPR Art. 9 -varoituksen joka kehottaa ettei lapsen nimeä yhdistä terveystietoon vapaatekstissä.
- Säilytysaika: client suodattaa
expiresAt-kentällä (max 30 pv käyttäjän valinnasta),cleanupExpiredData-CF poistaa Firestoresta 7 pv expiresAt-jälkeen kovasti.
Riskinarviointi
R10 — Vapaateksti houkuttelee Art. 9 -tietoja: käyttäjä voi kirjoittaa "Liisa allerginen pähkinöille, EpiPen autossa" body-kenttään. Lievennys: oranssi varoitus modaalin alussa (4 kieltä), placeholder "esim. Tiistain ruokalistalle lisättiin gluteeniton vaihtoehto. Tarkista pakkaukset.", auto-osio (yläosassa) hoitaa vakavat allergiat strukturoidusti.
R11 — Recipient-osoitteet sähköpostilähetyksessä: CF tallentaa lähetysstatuksen audit-lokiin system_log-kokoelmaan, mutta ei sähköpostiosoitteita kirkkaasti — vain määrät (recipientCount, sentCount). Tämä rajaa Art. 5(1)(c) datan minimointi-vaatimusta.
R12 — Phishing-vektori: aiemmin client lähetti title+body POSTissa, mikä mahdollisti spämmin Campflow-brändillä. Korjaus: CF lukee briefingin Firestoresta briefingId:llä — ei luota client-bodyyn.
Lainmukainen peruste
Sisäinen käsittely: GDPR Art. 6(1)(f) — oikeutettu intressi (elintarviketurvallisuus + henkilökunnan tiedonkulku). Sähköpostilähetys ulkopuoliselle: Art. 6(1)(a) — käyttäjän nimenomainen suostumus opt-in-checkbox:lla. Vakavasti allergisten lasten nimet auto-osiossa: Art. 9(2)(a) — huoltajan suostumus "terveystietojen jakamiseen leirin staffin kesken".
6.3 Datalaatu-mittari
Reseptin pisteytys 0-100 % perustuu: perusresepti (+30), ainesosien allergeenitiedot (+25), Fineli-linkitys (+25), määrät (+10), reseptin allergensInRecipe-lista (+10). Alle 60 % näytetään päivänäkymässä punainen varoitus jos leirillä on vakavasti allerginen henkilö (heuristiikka: p.allergiesNotes sisältää "vakava"/"anafylak"/"epipen").
Tietovirta
- Käsittely: ainoastaan client-puolella (food.js:n
_calcRecipeQuality). Reseptin data tulee Firestoresta, ei siirretä eteenpäin. - Päivänäkymän varoitus: näkyy keittiöstaffille kun aterialla on resepti jonka data-laatu on alle 60 % JA leirillä on Art. 9 -merkitty vakavasti allerginen lapsi. UI ei näytä lapsen nimeä tai allergeenia, vain "tarkista pakkaukset käsin"-tekstin.
Riskinarviointi
R13 — Päivänäkymän varoitus paljastaa että "leirillä on vakavasti allerginen henkilö": tämä on Art. 9 -tieto (terveys), vaikka nimeä ei näytetä. Sama keittiön rooli-rajoitus kuin briefing-paneelissa (kitchen/campLeader/admin/medic). Leader-rooli näkee päivänäkymän mutta ei tätä varoitusta erikseen — kuitenkin ateriakortti on samalla sivulla ja staff voi päättää itse mitä tarvitsee.
R14 — Heuristinen severity-tunnistus: regex matchaa "vakava|anafylak|epipen|severe|anaphyl" allergiesNotes-kentästä. False negativeja ja false positiveja mahdollisia. Tämä ei ole automaattinen päätöksenteko Art. 22 mielessä — pelkkä UI-vihje, päätös on aina kokin.
Lainmukainen peruste
Art. 6(1)(f) oikeutettu intressi: lapsen turvallisuus + elintarviketurvallisuuden jäljitettävyys. Datalaatu-laskenta on pelkästään client-puolella, ei tallennu Firestoreen — joten ei uusia tallennuskategorioita. Läpinäkyvyys (Art. 5(1)(a)): UI-tekstit ovat selkeitä ja käyttäjä näkee mitä lasketaan.
7. Päätelmä
Tunnistetut korkean tason riskit (R1, R2) on lievennetty kohtalaiselle tasolle teknisten suojien yhdistelmällä (pääsynvalvonta + rooliperustaisuus + token-vanheneminen + EXIF-strippaus + audit-loki). Kohtalaiset riskit (R3-R5) on lievennetty alhaiselle tasolle organisatoristen ja teknisten toimenpiteiden yhdistelmällä. Viivakoodiskannauksen riskit (R7-R9) ovat lieviä.
Jäännösriski on hyväksyttävällä tasolla. Erityistä konsultaatiota tietosuojavaltuutetun toimiston kanssa (Art. 36) ei katsota tarpeelliseksi, mutta tämä DPIA toimitetaan TSV:lle pyynnöstä.
DPIA tarkistetaan vuosittain tai aiemmin, jos käsittelytoimissa tapahtuu merkittäviä muutoksia (uusi tietoryhmä, uusi käsittelijä, uusi käsittelyperuste).
8. Yhteystiedot
Tämän DPIA:n laatija:
Esa Mäkinen · Campflow palveluntarjoaja · info@campflow.fi
Rekisterinpitäjien (organisaatioiden) yhteystiedot löytyvät kunkin organisaation omasta tietosuojaselosteesta.
Tietosuojavaltuutetun toimisto (valvontaviranomainen Suomessa): tietosuoja.fi
Campflow — Data Protection Impact Assessment (DPIA)
Assessment under GDPR (EU 2016/679) Art. 35. Concerns processing operations within the Campflow camp management service involving minors’ personal data and special categories of personal data (health, allergies, medication).
1. Was a DPIA required?
Yes. GDPR Art. 35(3) lists situations where a DPIA is mandatory. Campflow meets several criteria:
- Minors’ personal data (Art. 8) — most data subjects are camp participants under 16.
- Special categories of personal data (Art. 9) — health information, allergies and medication are core data in the system.
- Large scale — the service is used by multiple organisations with thousands of data subjects in total.
- Vulnerable group — minors cannot fully understand the consequences of their consent.
The list of processing operations requiring a DPIA published by the Finnish Data Protection Ombudsman (TSV 2018) supports this assessment.
2. Systematic description of the processing
2.1 Description of processing
Campflow is a browser-based camp management service (SaaS) used by parishes, scout groups, sports clubs and associations to manage camps for children and young people. Guardians register their children for camps, organisers receive registrations, collect required permissions, plan the programme and communicate with guardians during the camp.
2.2 Purposes of processing
- Receiving and managing camp registrations
- Ensuring participants’ health safety (allergies, medication, swimming ability)
- Planning groups, accommodation and schedules
- Communication with guardians (camp letter, guardian portal, emergency notifications)
- Fulfilling statutory obligations (bookkeeping, occupational safety, medication log)
2.3 Data processed
| Data category | Example fields | Legal basis |
|---|---|---|
| Basic data (child) | name, date of birth, gender, address, municipality | Art. 6(1)(b) contract + Art. 8 guardian consent |
| Contacts (guardian) | name, phone, email | Art. 6(1)(b) contract |
| Health data | allergies, illnesses, medication, swimming ability, painkiller permission | Art. 9(2)(a) explicit consent |
| Special diets | vegetarian, vegan, gluten-free, lactose-free, etc. | Art. 9(2)(a) explicit consent |
| Photo permission + photos | photoOk value, EXIF-stripped photos | Art. 6(1)(a) consent, Art. 9(2)(a) if personal characteristics |
| Staff | name, phone, email, role | Art. 6(1)(f) legitimate interest (employment contract performance) |
| Medication log | medicine administered, dose, time, administrator | Art. 6(1)(c) statutory obligation (patient injury practice) |
| Returning-family reminder (voluntary opt-in) | guardian name + email, child's first name, birth year, camp type, cancel token — NO health/allergy data | Art. 6(1)(a) consent; organisation is the data controller; retention 24 months of inactivity or immediately on cancellation |
2.4 Data flow
- The guardian fills the public registration form (ilmo.html) → data is written to Firestore.
- The organiser logs into the app (app.html), sees registrations, approves/rejects, divides into groups.
- Staff (camp leader, group leader, first-aid responsible, kitchen, night watch, swim supervisor) get role-based limited access.
- Guardian portal (huoltaja.html) — the guardian receives a parentToken link via email and can see their child’s situation during the camp.
- Cloud Functions handle email (Resend), photo processing (Sharp + EXIF stripping), AI features (Anthropic Claude) and generation of camp poster background images (OpenAI).
- After retention periods expire, data is automatically deleted according to the tiered model (cleanupExpiredData).
2.5 Recipients and processors
| Recipient | Role | Location |
|---|---|---|
| Google Firebase (Firestore, Storage, Cloud Functions, Auth) | Processor | EU (europe-west1) |
| Resend (email service) | Processor | EU/USA (Standard Contractual Clauses) |
| Anthropic (Claude API) | Processor — AI features: participant-level allergy and dietary data without names (kitchen AI tools, pseudonymised), numbered age, gender and swimming ability (team split), documents uploaded by the organiser (may contain names and contact details of adult responsible persons), questions and search phrases typed by users, and the registration page's introduction text (machine translation) | USA (SCC + data-minimising safeguards) |
| OpenAI (image generation) | Processor — camp poster background image: only the camp dates, location text and the main user's style hint (up to 200 characters), no personal data | USA |
| Sentry (error reporting) | Processor — technical logs only | EU |
| Cloudflare Turnstile | Processor — bot protection | EU/USA |
3. Assessment of necessity and proportionality
3.1 Legal basis
The primary basis is Art. 6(1)(b) contract (contract between the participant and the organiser; for a minor it is concluded by the guardian as representative, Finnish Guardianship Services Act 442/1999, section 4), and for health data Art. 9(2)(a) explicit consent, given on the registration form with a separate checkbox. For a minor participant the guardian gives consent; an adult participant gives it themselves (camps and events intended for adults, and adults registering themselves — the form requires a self-registering person to be at least 18). If the organiser enters an adult participant’s details directly, obtaining consent is the organiser’s responsibility as data controller. The medication log is based on Art. 6(1)(c) statutory obligation (patient injury practice).
3.2 Data minimisation
- Only data necessary for camp activities is collected — no personal identity codes, school background or religious beliefs (except where a parish’s own activities are inherently religious in nature).
- By default, a group leader sees full data only for participants in their own group. Children from other groups appear anonymised (“John D.”) e.g. in the accommodation table. Exception — events: in events (trip, journey, concert) with no small groups, the event's leaders see the full participant list (basis: Art. 9(2)(a) explicit guardian consent + safety responsibility for the whole group; events do not collect health data by default).
- Push notifications do not show the child’s name or health data (lock screen protection).
- AI features are sent only the data they need. Kitchen AI tools (e.g. dining allergy analysis) receive participant-level allergy and dietary texts without names or contact details (pseudonymised Art. 9 data): names, emails and phone numbers are removed or the line is blocked before sending, but a first name written in free text is not always recognised.
3.3 Retention periods (tiered model)
| Tier | Time after camp end | What is deleted |
|---|---|---|
| 1 | 30 days after sig-expiry | Pending signature requests that have expired |
| 2 | 6 months | Health data (allergies, health, painkiller permission, swimming ability, diets, additional information, the guardian’s reason for cancellation) from participants, staff and registration copies; signature images and completed signature requests; photos; rejected, waitlisted and offered registrations and waitlist offers; guardian portal tokens, messages, questions and change history; health and allergy entries in the activity feed (including staff members’ own allergy changes); personal data in the kitchen’s special-diet entries (name, identifier and note, also in cancelled entries; allergen and severity information is kept without the person, and the names of the staff who recorded them are deleted after 12 months) |
| 3 | 12 months | Basic data of participants and guardians; staff data (including role name lists, lodging residents, groups, kitchen shifts, staff notices); all registrations; attendance; shares and the public registration-page mirror; the camp’s activity feed; feedback-link email addresses. Registration is closed (the setting remains as "closed"). |
| 4 | 2 years | Medication data, the medication administration log and everything else that remains — the camp document is emptied. Consent and deletion records are kept for 36 months from the entry (see 5.3). |
| Postponement | at most 12 months from the observation | Tiers 2–4 wait if the camp has been used after it ended (see 5.3). The postponement does not extend the per-entry maximum periods (audit_log 24 months, consent and deletion records 36 months). |
| — | 24 months of inactivity, OR immediately when the guardian cancels | Returning-family reminder (opt-in). Separate logic — not tied to camp end; minimal data only (no Art. 9) |
4. Risk assessment
Risks have been assessed from the perspective of the data subjects using a three-step scale (low / moderate / high), evaluating likelihood × severity.
R1: Data breach — health data leak
High before mitigationAllergy, medication and illness data could fall into wrong hands as a result of a data breach. The harm to a minor’s privacy would be significant and long-lasting.
R2: parentToken leak via email
High before mitigationIf a guardian’s email leaks (phishing etc.), a third party could use the parentToken link and see the child’s data.
R3: Staff misuse
ModerateA group leader who does not need the data of all children can still see them if the group assignment has not been done.
R4: AI service data leak
ModerateAnthropic Claude is a US-based service to which the kitchen AI tools send pseudonymised participant-level allergy and dietary data. If identifiable health data were to end up there, the risk would be high.
R5: Retention period overrun
ModerateIf automatic cleanup fails, data is retained unnecessarily.
R6: Guardian access rights management
LowThe guardian cannot easily exercise their GDPR rights (Art. 15/17/20).
5. Risk mitigation measures
5.1 Technical safeguards (R1, R2, R4)
- Access control: Firebase Authentication + Firestore Rules. Data access is role-based (admin, camp leader, group leader, first-aid responsible, kitchen, night watch, swim supervisor). A group leader only has access to participants in their own group (in events, which have no groups, to the full participant list).
- Token-based guardian portal: parentToken is 48 characters long (24 random bytes hex-encoded) and expires 6 months after the camp ends (if the end date is missing, validity is counted from sending: 6–12 months depending on how it was sent). The camp owner or camp leader can revoke the link at any time from the participant card (Portal links → Revoke link); revocation takes effect immediately and is recorded in the camp event log.
- Encryption at rest and in transit: Firestore + Storage use TLS 1.3 + AES-256.
- Pseudonymisation (IP addresses): guardians' consent and data-request logs (consentLog, audit_log) store only a SHA-256 hash of the IP address computed with a daily-rotating salt — never the plaintext IP. The salt is kept separate from the data in Google Secret Manager, the hashes are not used to identify anyone, and they are not returned in the Art. 15 export (the value would not be intelligible, Art. 12(1)).
- EXIF stripping: EXIF metadata (incl. GPS location) is removed from photos before storage using the Sharp library.
- Data minimisation for AI: participants’ names, emails and phone numbers are not intentionally sent to Anthropic — they are removed or the line is blocked before the call, and a server-side PII detector (fail-closed) blocks obvious name + health combinations. Kitchen AI tools receive allergy and dietary data pseudonymised; the team split receives numbered age, gender and swimming ability. Residual risk: a first name written in free text is not always recognised, and documents uploaded by the organiser (rescue plan, schedule) are passed on unscanned — they may contain names and contact details of adult responsible persons.
- Origin validation + persistent rate-limit: claudeProxy, aiAssistant, chatHelp, summarizeAllergies validate the origin of the HTTP request and use a Firestore-backed rate-limit that survives Cloud Functions cold starts.
- Role-based XSS protection: all user input is rendered through the esc() function (incl. PDF print and the registration form).
- Sentry error reporting: contains no personal data (PII mask).
- Firestore PITR (Point-in-Time Recovery): 7-day restore window for disaster recovery.
- Subcollection architecture: participants’ personal data is stored in a camp-doc subcollection (camps/{cid}/participants), to which Firestore Rules grant read access only to need-to-know roles — a group leader sees only their own group’s children. Kitchen, kitchen helper, night watch and swim supervisor do not read the subcollection directly; they receive a server-restricted field set (getKitchenView, getNightEmergencyView, getSwimmingView).
- Hard-coded field allowlists: access to guardian and guardianPhone is restricted to campLeader+medic+night+admin, and to address and email to campLeader+medic+admin (overrides custom permissions). Event-mode exception for the guardian's name and phone: see guardian fields below.
- Multi-role support: servRoles + extraRoles are automatically unioned — a leader+medic user receives the rights of both roles.
5.2 Organisational safeguards (R3)
- The camp organiser is the controller, Campflow is the processor — the division of responsibility is clearly documented (DPA agreement).
- Staff roles are documented in the service’s help pages (docs.html).
- The terms of service prohibit sharing credentials with third parties.
- Access is restricted on a role basis via Firestore Rules + client allowlist. In addition, the application records views of Art. 9 data in an application-level audit log (logArt9Access) on the key display surfaces (person card, emergency list, reports, printouts); the audit_log collection records write events and export requests.
5.3 Retention period monitoring (R5)
- The cleanupExpiredData function runs every night at 03:00 (Europe/Helsinki) and automatically deletes according to the tiered model.
- The tiers fall due from the camp's end date. When a tier falls due and the camp has been used after it ended – registrations, participants or attendance days have been added more than 14 days after the end date, or the camp's data has been edited within the 90 days before the tier falls due (and more than 14 days after the end) – the destructive tiers 2–4 are postponed by at most 12 months from the first observation so that new-season data is not deleted by mistake. The organiser (the camp owner; if the owner's account has been disabled, the camp's campLeader) receives an email when the postponement starts and a reminder 30 days before it ends, and the start of the postponement is recorded in audit_log. The postponement is applied once per end date; afterwards the tiers run according to the end date. A deleted camp is not postponed, and if there is no email recipient, the postponement is recorded in the service operator’s monitoring log.
- If the organiser changes the camp's dates, all tiers are counted from the new end date, also for data from the previous season. Changing the dates is the controller's decision; the organiser is instructed (privacy notice §7 and the user guide) to delete the previous season's data that is no longer needed. If the dates are cleared, the absolute maximum periods described below apply to the camp.
- Operations are written to a system_log entry monitored by a super-admin.
- Refactored as a collectionGroup query (removes the N+1 problem and improves reliability as the number of organisations grows).
- Absolute maximum retention from the entry, regardless of the end date, also for camps without an endDate or whose dates have been cleared: participantHistory 24 months; audit_log 24 months (the root-level data-request processing log and view logs, and the camp-level audit_log); consent and deletion records 36 months (consentLog and the camp-level auditLog: consent of a minor assistant leader's guardian and proof of a participant's deletion); aiAudit 90 days. Dedicated collectionGroup fieldOverride indexes ensure the deletion query actually executes and does not silently fail on a missing index.
5.4 Rights of guardians and adult participants (R6) — self-service
- Art. 15 (right of access): in the guardian portal “Download a copy of the data (PDF / readable format)” — a user-friendly summary of the key data stored about the participant, in the portal language (fi/en/sv/no). The copy states its own limits: it does not include, for example, staff-internal notes, payment data, group and other arrangement data, the original registration form, electronic signature records or system log and view data, and the data subject is directed to request these from the controller (Art. 12(1), 15(3)). The copy lists the data subject’s rights (Art. 15–18, 20, 21, 7(3)) and the right to lodge a complaint with a supervisory authority (Art. 77, Office of the Data Protection Ombudsman). The consent log's (consentLog) IP hash (ipHash) is deliberately omitted from the export, as it is an internal pseudonym and not intelligible to the data subject (Art. 12(1)) — the consent type, version and timing are still included in the export.
- Art. 17 (right to be forgotten): “Request data deletion” — the request is logged, the camp organiser receives an email notification and processes it within 30 days.
- Art. 7(3) (withdrawal of consent): “Withdraw consent to health data processing” — as easy as giving consent, at any time, with no time limit. Immediately clears the participant’s Art. 9 fields, redacts the special-category content of prior participantHistory to “[withdrawn]”, writes a consentLog entry (Art. 7(1) accountability) and notifies the controller to complete erasure of any residual data (Art. 17(1)(b)). Does not cancel participation.
- Art. 20 (right to data portability): “Download raw data (JSON, for developers)” — machine-readable JSON, suitable for transfer to another system.
- Rate-limit: 5 downloads per day per token (sufficient for guardian use, prevents mass downloads in case of token leak).
- Requests are recorded in the audit_log collection.
- An adult participant (a camp or event intended for adults, or an adult who registered themselves) uses the same functions in their own participant portal. The texts of the portal and the data copy address the participant directly rather than a guardian, and in the copy of a self-registered participant the legal basis for health data is recorded as their own consent and the author of changes in the update history as “The participant”.
5.5 Special measures for minors
- The child does not log into the application — all data flows through the guardian or organiser.
- Guardian consent is a prerequisite for registration (permission slip + explicit health data consent).
- A person aged 12 or older can give their own consent to photo use (the statutory age limit varies).
- A group leader only sees children belonging to their group, not others. In events (no small groups) a leader sees the full participant list.
- Under Finnish Data Protection Act (1050/2018) §5, data on children under 13 requires guardian consent — Campflow requires it for all under 18 as an extra safeguard.
5.6 Role-specific Art. 9 field restrictions
The allowlist is hard-coded in the application code and in Firestore Rules; it cannot be bypassed via custom permissions:
- Medications tab: only campLeader, medic, admin.
- Food tab: only campLeader, kitchen, kitchenHelper, admin.
- Feedback tab: only campLeader, admin.
- Guardian fields (guardian, guardianPhone): only campLeader, medic, night, admin. Event-mode exception (v9.3.217): in events the leader role also sees the guardian's name and phone number — on a trip the leader is the one who reaches the guardian e.g. when a participant does not show up for the bus. Address and email remain restricted.
- Address and email: only campLeader, medic, admin.
- Allergies: own group leader (need-to-know) + campLeader + medic + admin + kitchen + kitchenHelper (anaphylaxis risk during serving) + night (emergency view, see below).
- Special diets (dietaryNeeds): own group leader + campLeader + medic + admin + kitchen + kitchenHelper. Not night or swim.
- Health data (health: chronic illnesses, medications): own group leader + campLeader + medic + admin + night. kitchen and kitchenHelper do NOT see these (Art. 5(1)(c) data minimisation — the kitchen needs allergies and diets only, v9.2.383).
- Night watch (night) and swim supervisor (swim): neither reads participant documents directly. The night watch receives a server-restricted emergency view (getNightEmergencyView: name, date of birth, allergies, health, guardian's name and phone, participant's own phone, group — no address, email, diet, permissions or notes). Basis: consent given to the processing of health data (Art. 9(2)(a)) — night-time seizures (epilepsy, asthma, diabetes, anaphylaxis) require the information immediately; Art. 9(2)(c) (vital interests) only in a sudden emergency where there is no consent. Every retrieval is recorded in the audit_log collection (night_emergency_view). The swim supervisor receives only the getSwimmingView view (name, swimming ability, group, life-jacket need) — no health data or allergies (v9.2.474, Art. 25).
- kitchenBriefings (allergens at name level): only campLeader, kitchen, medic, admin. kitchenHelper does NOT see (consent limited to main kitchen staff).
- Bus view: at camp a leader sees only their own group’s children, without guardian contact details. In events the guardian’s name and phone are shown to the leader (v9.3.217 event exception, see guardian fields above).
- PDF print: the same field allowlist enforces the restriction (from v9.3.217 also in the guardian columns of report printouts: health summary, allergy report, pickup list).
6. Consultation with data subjects
Guardians receive, in connection with registration:
- A link to the privacy policy (Art. 13/14 information obligation).
- A separate consent checkbox for processing health data (Art. 9(2)(a)).
- A separate consent checkbox for photo publication.
- Information about the lack of a withdrawal right under the Finnish Consumer Protection Act (CPA 6:16§ item 12 — leisure-time service at a fixed point in time).
- Information about the payment obligation clearly on the confirmation button (CPA 6:13§ — “Register and pay X €”).
6.1 Barcode scanning
The head cook is offered a barcode scanner (BarcodeDetector + Open Food Facts database) for bulk situations, which displays the product’s allergens + nutritional info and compares them with the camp participants’ structured allergen data.
Data flow
- Data sent to third party: only the product’s GTIN number (8/12/13/14 digits). NO personal data, NO camp data, NO allergen comparison results.
- Allergen comparison: performed client-side in the browser — participants’
p.allergensdata does NOT leave the Campflow perimeter. - Audit log:
users/{uid}/camps/{campId}/barcodeScans/{id}stores the staff member’s name, barcode, product name and allergens. Retention 2 years (rationale: food safety traceability, EU 852/2004 + Finnish Food Act 297/2021).
Risk assessment
R7 — Head cook identifiers on OFF server: Cloud Run sends OFF the User-Agent: Campflow - https://campflow.fi - info@campflow.fi + the Cloud Run egress IP. This is not end-user personal data but a Campflow organisational server marker. Mild, does not require a DPA.
R8 — OFF data is maintained by volunteers: incorrect or outdated allergen information may lead to incorrect decisions. Mitigation: UI disclaimer “Always check the packaging” + neutral “does not match the list” wording that does not give a positive safety claim (EU 1169/2011 + Finnish Tort Liability Act 412/1974).
R9 — 30-day cache: if an allergen is added to a product in OFF, Campflow shows outdated information for up to a month. Mitigation: always-visible disclaimer + “Open in OFF” link.
Legal basis
Processing (audit log) is based on GDPR Art. 6(1)(f) — legitimate interest (the controller’s interest in ensuring food safety + traceability, which overrides the staff member’s interest in remaining anonymous in working-time entries). Personal data is limited to the staff role, no participant data in the audit log.
6.2 Kitchen briefing
A permanent note from the head cook to the kitchen staff (kitchen / campLeader / admin / medic). Includes: a free-form title and message (max 2000 characters), an automatically compiled “severe allergies” list (child’s NAME + EU14 allergens + free additional text), runOut/leftover feedback from the past 3 days. Optional email delivery to external volunteers.
Data flow
- Internal processing: Firestore
users/{uid}/camps/{campId}/kitchenBriefings/{id}— read only by the camp’s kitchen staff (see firestore.rules). The leader role (group leader) does NOT see the briefing panel because it contains Art. 9 data (names of children with serious allergies) and guardian consent is limited to “kitchen and health responsible”. - Email delivery: Resend (USA/EU) → external volunteer’s email. The head cook writes the message and opts in to “Also send by email”. The modal contains an orange GDPR Art. 9 warning that urges not to associate a child’s name with health data in free text.
- Retention period: the client filters by
expiresAt(max 30 days from user choice), thecleanupExpiredDataCF removes from Firestore 7 days after expiresAt hard.
Risk assessment
R10 — Free text invites Art. 9 data: a user may write “Liisa allergic to nuts, EpiPen in the car” in the body field. Mitigation: orange warning at the top of the modal (4 languages), placeholder “e.g. A gluten-free option was added to Tuesday’s menu. Check the packaging.”, the auto section (at the top) handles severe allergies in structured form.
R11 — Recipient addresses in email delivery: the CF stores delivery status in the audit log system_log collection, but not email addresses in clear text — only counts (recipientCount, sentCount). This restricts the Art. 5(1)(c) data minimisation requirement.
R12 — Phishing vector: previously the client sent title+body in the POST, which made spam in the Campflow brand possible. Fix: the CF reads the briefing from Firestore by briefingId — it does not trust the client body.
Legal basis
Internal processing: GDPR Art. 6(1)(f) — legitimate interest (food safety + staff information flow). Email delivery to an outsider: Art. 6(1)(a) — the user’s explicit consent via opt-in checkbox. Names of children with serious allergies in the auto section: Art. 9(2)(a) — guardian consent to “share health data among the camp staff”.
6.3 Data quality meter
Recipe scoring 0–100 % is based on: base recipe (+30), ingredient allergen information (+25), Fineli linkage (+25), quantities (+10), the recipe’s allergensInRecipe list (+10). Below 60 %, the day view shows a red warning if the camp has a person with severe allergies (heuristic: p.allergiesNotes contains “vakava”/“anafylak”/“epipen”).
Data flow
- Processing: only client-side (food.js’s
_calcRecipeQuality). Recipe data comes from Firestore, is not transferred onwards. - Day view warning: visible to the kitchen staff when a meal has a recipe whose data quality is below 60 % AND the camp has a child marked Art. 9 as severely allergic. The UI does not show the child’s name or the allergen, only “check the packaging by hand”.
Risk assessment
R13 — The day view warning reveals that “the camp has a person with serious allergies”: this is Art. 9 data (health), even though the name is not shown. Same role restriction as in the briefing panel (kitchen/campLeader/admin/medic). The leader role sees the day view but not this warning separately — however, the meal card is on the same page and the staff can decide for themselves what they need.
R14 — Heuristic severity detection: the regex matches “vakava|anafylak|epipen|severe|anaphyl” in the allergiesNotes field. False negatives and false positives are possible. This is not automated decision-making within the meaning of Art. 22 — merely a UI hint, the decision is always the cook’s.
Legal basis
Art. 6(1)(f) legitimate interest: child safety + food safety traceability. The data quality calculation is purely client-side and is not stored in Firestore — so no new storage categories. Transparency (Art. 5(1)(a)): the UI texts are clear and the user sees what is being calculated.
7. Conclusion
The identified high-level risks (R1, R2) have been mitigated to a moderate level through a combination of technical safeguards (access control + role basis + token expiry + EXIF stripping + audit log). The moderate risks (R3–R5) have been mitigated to a low level through a combination of organisational and technical measures. The risks for barcode scanning (R7–R9) are mild.
The residual risk is at an acceptable level. Prior consultation with the Data Protection Ombudsman (Art. 36) is not deemed necessary, but this DPIA will be provided to the Ombudsman upon request.
The DPIA is reviewed annually or earlier if significant changes occur in the processing operations (new data category, new processor, new legal basis).
8. Contact information
Author of this DPIA:
Esa Mäkinen · Campflow service provider · info@campflow.fi
Contact details of the controllers (organisations) can be found in each organisation’s own privacy policy.
Office of the Data Protection Ombudsman (supervisory authority in Finland): tietosuoja.fi
Campflow — Konsekvensbedömning avseende dataskydd (DPIA)
Bedömning enligt GDPR (EU 2016/679) Art. 35. Avser behandling av personuppgifter inom Campflow lägeradministrationstjänst som rör minderårigas personuppgifter och särskilda kategorier av personuppgifter (hälsa, allergier, medicinering).
Obs
Den fullständiga bedömningen finns på finska, eftersom den primärt riktar sig till finska Dataombudsmannens byrå (Tietosuojavaltuutetun toimisto). Denna svenska sammanfattning täcker de viktigaste slutsatserna.
1. DPIA krävs
Ja — Campflow behandlar minderårigas personuppgifter (Art. 8) och särskilda kategorier (Art. 9: hälsa, allergier, medicinering) i stor skala och berör en sårbar grupp.
2. Riskminimering
- Rollbaserad åtkomstkontroll via Firebase Rules
- parentToken upphör att gälla efter 6 månader och kan återkallas
- EXIF-data avlägsnas före lagring
- Pseudonymisering av vårdnadshavares IP-adresser (SHA-256-hash med dagligen roterande salt, aldrig i klartext) i loggar för samtycke och dataförfrågningar
- Pseudonymisering före AI-tjänster: namn och kontaktuppgifter tas bort, kökets AI-verktyg får allergi- och kostuppgifter per deltagare utan namn
- Stegvis automatisk radering (6 mån / 12 mån / 2 år); används lägret efter slutdatumet skjuts raderingen upp högst 12 månader och arrangören meddelas; ändras lägrets datum räknas tiderna från det nya slutdatumet
- Självbetjäning av GDPR-rättigheter (Art. 15/17/20, 7(3)) i vårdnadshavarportalen; en vuxen deltagare ger sitt eget samtycke och använder sin egen deltagarportal. Självbetjäningskopian anger sina begränsningar och hänvisar till den personuppgiftsansvarige för övriga uppgifter
3. Slutsats
Höga risker har minskats till måttlig nivå genom kombinerade tekniska och organisatoriska åtgärder. Restrisken är acceptabel.
Campflow — Personvernkonsekvensvurdering (DPIA)
Vurdering i henhold til GDPR (EU 2016/679) Art. 35. Gjelder behandling av personopplysninger i Campflow leiradministrasjon som omhandler mindreåriges personopplysninger og særlige kategorier av personopplysninger (helse, allergier, medisinering).
Merk
Den fullstendige vurderingen er tilgjengelig på finsk, ettersom den primært er rettet til det finske Datatilsynet (Tietosuojavaltuutetun toimisto). Dette norske sammendraget dekker de viktigste konklusjonene.
1. DPIA påkrevd
Ja — Campflow behandler mindreåriges personopplysninger (Art. 8) og særlige kategorier (Art. 9: helse, allergier, medisinering) i stor skala og berører en sårbar gruppe.
2. Risikoreduksjon
- Rollebasert tilgangskontroll via Firebase Rules
- parentToken utløper etter 6 måneder og kan tilbakekalles
- EXIF-data fjernes før lagring
- Pseudonymisering av foresattes IP-adresser (SHA-256-hash med daglig roterende salt, aldri i klartekst) i logger for samtykke og dataforespørsler
- Pseudonymisering før AI-tjenester: navn og kontaktopplysninger fjernes, kjøkkenets AI-verktøy får allergi- og kostopplysninger per deltaker uten navn
- Trinnvis automatisk sletting (6 mnd / 12 mnd / 2 år); brukes leiren etter sluttdatoen, utsettes slettingen høyst 12 måneder og arrangøren varsles; endres leirens datoer, regnes tidene fra den nye sluttdatoen
- Selvbetjening av GDPR-rettigheter (Art. 15/17/20, 7(3)) i foresattportalen; en voksen deltaker gir sitt eget samtykke og bruker sin egen deltakerportal. Selvbetjeningskopien opplyser om sine begrensninger og viser til den behandlingsansvarlige for øvrige opplysninger
3. Konklusjon
Høye risikoer er redusert til moderat nivå gjennom kombinerte tekniske og organisatoriske tiltak. Restrisikoen er akseptabel.