I vibe coded Data Anonymization solution configuration app and then Azure Function but realized that functions are not my cup of tea anymore. I decided that if the logic is mainly already in configurations, why not create it with Power Automate which area of MVP I am. I started creationg traditionally dynamic flows, which reads the configuration and anonymized data in Dataverse.

I knew that Power Automate does not allow recursive functions so I split my solution into three flows. Actually the two child flows can be calling each other, so basically I could create recursive solution but dit not make it this far. This post shows how to use Power Automate with configurations and nested parametrization. I changed the configuration tables a bit adding some columns so this solution fits my needs. Copilot base was good, just couple adding’s and the first version is ready.

Main flow to trigger daily to anonymize first level data

Main flow triggering every day, getting the anonymization configuration and doing first level column anonymization
Main flow triggering every day, getting the anonymization configuration and doing first level column anonymization

First I create the main flow which reads the anonymization configuration that has the main functionality and table to follow.

  1. List active configurations, that has status of active
  2. Get table rows for that fits the datetime cap in to followed table
  3. List all field anonymization rules that should be applied in the table
  4. Check that there are rows both for steps 2 and 3
  5. Loop trough each target table row in this example events that have been ended N days ago, N comes from configuration table
  6. Choose whether to remove or replace the value in the row column configured in field anonymization rules
  7. Call related tables for the target table, in this example we have Events table and related tables are i.e. Event Registration table and Contacts

Below is the code snippets for formatting the N days. You need to get the first minute of the day and the first minute of the next day. This way you can get all events that ended exactly N days ago from today. The flow is run daily, so I will catch always the correct day and does not handle event rows multiple times. Doing this you don’t have to have any column in events table telling that this is anonymized. That could be also possible to add column in flow stating if anonymization is done and then exclude it from your query.

formatDateTime(startOfDay(addDays(utcNow(), sub(0, int(items('For_each_Anonymization_Configuration')?['dg_anonymizationdelaydays'])))), 'yyyy-MM-ddTHH:mm:ssZ')
formatDateTime(startOfDay(addDays(utcNow(), sub(1, int(items('For_each_Anonymization_Configuration')?['dg_anonymizationdelaydays'])))), 'yyyy-MM-ddTHH:mm:ssZ')
Getting target table rows between the given datetime field in Dataverse List Rows action
Getting target table rows between the given datetime field in Dataverse List Rows action

First child flow to anonymize second level table dat

Child flow triggering from main flow, getting the related tables and doing second level column anonymization
Child flow triggering from main flow, getting the related tables and doing second level column anonymization

The first child flow is called from main flow and the first action is to respond to the main flow. This is so that the main flow is not waiting this flow to finish. If you have multiple rows to handle, this speeds up the data handling quite much.

  1. Respond to main flow
  2. Get related table configurations
  3. Loop trough all related table configurations
  4. Get rows from related table, i.e. all Event Registrations for the event to be handled in main flow
  5. List field anonymization settings for related table, meaning which columns should be anonymized in the related table
  6. Go trough all fields (columns) and remove or replace the data values
  7. Call second child flow to anonymize third level tables i.e. Checkins

With event participation there are at least three level of tables to be checked and anonymized. What I’m lacking here is to check if second level table i.e. Contact has participated to another event that has less than N days from today. This logic should be added here so that it will not anonymize the related table rows (and call second child flow) if there are other main table rows related to this looped related table row.

Getting rows from Related Table Configurations table with parent Data Anonymization Configuration row id. The lookup field is also parametrized in the flow if this flow will be called again from second child flow when creating recursive solution and need for 5. level tables. It is because I added to Related Table Configuration lookup columns both to itself and Data Anonomization Configuration table. This way it is possible to create hierarchical setting tree.

Getting all related table rows with the parent row id
Getting all related table rows with the parent row id

Getting related table fields are done in lookup filter. In the configuration you should add the _ and _value, like _eventid_value when doing Power Automate query to lookupfield with the parent row id.

Getting all related table rows with the parent row id
Getting all related table rows with the parent row id

Data update is done parametrized. The table name comes from configuration rows which are looped inside each condition. Row id is nested parsed from each and then from field anonymization row. The primary key field should be always given in configuration with the table name. Table name is the plural name (Copy Set Name). Field configuration tells then which data column name is changed. Column names are always logical names etc. mgn_fieldname. If you wish to replace data, then get that value from configuration and set it instead of null with quotations (“value”).

Dataverse table column dynamics update with parametrized table and column name
Dataverse table column dynamics update with parametrized table and column name

Second child flow to anonymize third level data

Second child flow triggering from first child flow, getting the related tables and doing thirds level column anonymization
Second child flow triggering from first child flow, getting the related tables and doing thirds level column anonymization

The second child flow is exactly the same as the first child flow but missing the call to another child flow. This could be extended to call the first call flow and this way of creating recursive solution to anonymize data from fourth, fifth or more levels of data.

This is the first version of this data anonymization solution which configuration app I vibe coded with Copilots and then created these flows manually. I did not even try to use Power Automate Copilot for creating these, since I have so bad experience for Power Automate Copilot. Maybe in future Copilot is so smart that it could build flows like this. But now I’m the pilot of this solution 🙂