In mijn vorige artikel beschreef ik hoe je met App Connectors, GetConnectors en veldniveau-controle bepaalt welke data uit AFAS beschikbaar is voor AI-assistenten. Maar er is een volgende stap: wat als je data wilt delen, maar niet in herkenbare vorm? Dat is waar anonimisering om de hoek komt kijken.
Bij de MCP Server van ERP-Brug bouwen we anonimisering in op veldniveau. Per veld kies je de methode die past bij het type data en het gewenste privacyniveau. De anonimisering gebeurt automatisch, voordat de data de AI bereikt.
Vijf methoden, elk met een eigen doel
Niet elk veld vraagt om dezelfde aanpak. Een BSN-nummer moet volledig verdwijnen, maar een medewerker-ID moet herkenbaar blijven zodat de AI verbanden kan leggen tussen datasets. Daarom werken we met vijf anonimisatiemethoden:
Hash — voor ID-velden en kruisverwijzingen
Bij hashing wordt een waarde omgezet naar een unieke code, bijvoorbeeld f50bb2a8. Het bijzondere: dezelfde waarde levert altijd dezelfde hash op. Dat betekent dat een medewerker-ID in de ene GetConnector dezelfde hash krijgt als in een andere. AI-assistenten zoals Claude en ChatGPT herkennen dat automatisch en kunnen zo verbanden leggen tussen datasets — zonder de originele waarde te kennen.
Dit is cruciaal voor analyses. Een AI-assistent kan bijvoorbeeld uren per medewerker koppelen aan verlofgegevens, terwijl de echte medewerker-ID's verborgen blijven.
Mask — voor namen en leesbare context
Masking vervangt delen van een waarde door sterretjes: Jan de Vries wordt J** ** V****. Het resultaat is leesbaar maar niet herleidbaar. Ideaal voor namen waar de AI enige context nodig heeft, maar de volledige naam niet zichtbaar mag zijn.
Redact — voor hoogst gevoelige data
Redact verwijdert de waarde volledig uit de response. Het veld bestaat nog wel, maar de inhoud is weg. Dit is de juiste keuze voor BSN-nummers, IBAN-nummers, telefoonnummers en andere gegevens die onder geen enkele omstandigheid gedeeld mogen worden met een AI-assistent.
Partial — voor gedeeltelijke zichtbaarheid
Bij partial masking bepaal je hoeveel karakters aan het begin en einde zichtbaar blijven. Een e-mailadres wordt dan jo**********@bedrijf.nl: het domein blijft zichtbaar voor context, maar het volledige adres is niet te achterhalen. Bij postcodes kun je het cijferdeel tonen maar de letters verbergen: 1234** geeft regio-informatie zonder een exact adres prijs te geven.
Replace — voor volledige vervanging
Replace vervangt de originele waarde door een vaste tekst zoals [geanonimiseerd]. Handig voor adresgegevens of andere velden die geen analytische waarde hebben in geanonimiseerde vorm.
De juiste methode per veldtype
Op basis van onze ervaring met het anonimiseren van AFAS-data heb ik een overzicht gemaakt van de aanbevolen methode per type veld:
- ID- en sleutelvelden (EmployeeId, KlantId) → Hash. Consistent over connectoren heen, zodat AI cross-connector joins kan maken.
- Namen (EmployeeName, ContactName) → Mask. Leesbaar maar niet herleidbaar.
- BSN, IBAN, telefoonnummers → Redact. Hoogst gevoelig, volledig verwijderen.
- E-mailadressen → Partial. Domein zichtbaar voor context.
- Adressen (straat, postcode) → Replace of Redact. Geen analytische waarde in geanonimiseerde vorm.
- Numerieke waarden (salaris, FTE) → Geen regel. Aggregatie (SUM/AVG) werkt alleen op originele waarden.
- Datums (geboortedatum) → Replace of Redact. Hash op datums is weinig zinvol.
- Codes en enums (geslacht, status) → Geen regel. Beperkte waardeset, masken voegt geen privacy toe.
Cross-connector matching: waarom Hash essentieel is
Hash is de enige methode die cross-connector correlatie behoudt. Dezelfde waarde in verschillende connectoren geeft dezelfde hash. Dat betekent dat een AI-assistent automatisch herkent dat f50bb2a8 in Connector A dezelfde entiteit is als f50bb2a8 in Connector B.
Een paar technische details die relevant zijn:
- De salt is per App Connector — verschillende resellers of partners krijgen verschillende hashes voor dezelfde onderliggende waarde.
- Met 8 hex karakters zijn er 4,3 miljard mogelijke waarden — verwaarloosbare collision-kans voor typische datasets.
- U kunt een wildcard (
*) gebruiken voor ID-velden die in meerdere connectoren voorkomen, zodat EmployeeId overal dezelfde hash-methode krijgt.
Scope: connector-breed of per API key
De anonimisatie kun je op twee niveaus configureren:
- Connector-breed — alle API keys krijgen dezelfde anonimisatie. Dit is de standaard en werkt voor de meeste scenario's.
- Per API key — voor specifieke situaties. Een demo- of sales-key krijgt maximale anonimisering, terwijl een productie-key de volledige data ziet. Een partner-key krijgt beperkte zichtbaarheid.
Key-specifieke regels overschrijven connector-brede regels voor dezelfde connector-veld combinatie. Zo kun je fijnmazig sturen wie wat ziet, zonder extra App Connectors aan te maken.
Beveiligingsoverwegingen
Anonimisering is geen wondermiddel. Er zijn een paar aandachtspunten die ik transparant wil delen:
Filterwaarden worden verborgen
Als een veld geanonimiseerd is, toont de API [geanonimiseerd] in de filter-metadata in plaats van de originele filterwaarde. Dit voorkomt dat originele waarden lekken via de response.
Filteren op geanonimiseerde velden
Filters worden voor anonimisatie toegepast (op AFAS-niveau). Een gebruiker kan dus filteren op een specifieke waarde en via het resultaat achterhalen welke hash daarbij hoort. Voor Hash-velden is dit acceptabel — hash is bedoeld voor correlatie, niet voor geheimhouding van individuele waarden. Voor velden waar zelfs bevestiging van bestaan ongewenst is, is Redact de juiste keuze. Daarnaast beperkt het dagelijkse aanroeplimiet (DailyCallLimit) per API key de mogelijkheid tot brute-force pogingen.
Sortering volgt originele waarden
OrderBy werkt op de originele waarden, niet op de geanonimiseerde versie. Sorteren op een gehasht veld toont records in de volgorde van de originele waarden. Dit is goed om te weten en te documenteren richting gebruikers.
Aggregatie en anonimisatie
Niet elke methode werkt goed met aggregatie:
- Hash — GROUP BY werkt correct, unieke groepen blijven behouden. COUNT werkt, SUM/AVG is niet zinvol op hashes.
- Mask — risico bij GROUP BY: twee verschillende namen kunnen na masking samenvallen (J** en J**).
- Redact — veld is niet beschikbaar voor aggregatie.
- Replace — alles valt samen in één groep, niet zinvol voor analyse.
De vuistregel: gebruik uitsluitend Hash voor velden die in GROUP BY worden gebruikt.
Praktijkvoorbeeld: HRM-data anonimiseren
Een typische setup voor medewerkerdata uit AFAS laat goed zien hoe de methoden samenwerken:
- EmployeeId, EmployerId → Hash (wildcard, over alle connectoren)
- BSN → Redact (wildcard, nooit tonen)
- Mobiel, telefoon → Redact (privégegevens)
- E-mail → Partial (domein zichtbaar voor context)
- Voornaam, achternaam → Mask (leesbaar maar niet herleidbaar)
- Straat, geboortedatum → Redact (adres- en persoonsgegevens verwijderen)
- Postcode → Partial (regio zichtbaar: 1234**)
- Partnernaam → Mask (partner privacy)
Velden zoals organisatie-eenheid, functie, FTE en uren per week blijven ongewijzigd — deze hebben analytische waarde en bevatten geen persoonsgegevens.
Het resultaat: een AI-assistent kan vragen beantwoorden als "Hoeveel FTE heeft afdeling X?" of "Welke medewerkers hebben meer dan 20 verlofdagen staan?" zonder dat er privacygevoelige gegevens worden gedeeld.
Compliance als enabler, niet als rem
Het beeld dat compliance en AI-innovatie op gespannen voet staan, klopt niet. Met de juiste anonimisering op veldniveau kun je AI inzetten op HR-data, financiële gegevens en klantinformatie — volledig in lijn met de AVG en interne privacyrichtlijnen.
De combinatie van datacontrole via App Connectors en anonimisering op veldniveau geeft organisaties een compleet governance-model voor AI met data uit AFAS. U bepaalt wat beschikbaar is, in welke vorm, en voor wie.
Wilt u anonimisering inrichten voor uw AFAS-data? Ik help u graag met de juiste configuratie per veld en per connector.
Neem contact op