ethyca-fides 2.73.0rc4__py2.py3-none-any.whl → 2.73.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ethyca-fides might be problematic. Click here for more details.

Files changed (275) hide show
  1. {ethyca_fides-2.73.0rc4.dist-info → ethyca_fides-2.73.1.dist-info}/METADATA +1 -1
  2. {ethyca_fides-2.73.0rc4.dist-info → ethyca_fides-2.73.1.dist-info}/RECORD +264 -254
  3. fides/_version.py +3 -3
  4. fides/api/alembic/alembic.ini +5 -1
  5. fides/api/alembic/migrations/env.py +7 -1
  6. fides/api/alembic/migrations/versions/c09e76282dd1_add_privacy_request_duplication_cols.py +64 -0
  7. fides/api/alembic/migrations/versions/xx_2025_10_17_1603_5093e92e2a5a_add_consent_data_v3_to_the_database.py +72 -0
  8. fides/api/alembic/migrations/versions/xx_2025_10_27_1834_67f0f2f4748e_adding_identity_definition_model.py +45 -0
  9. fides/api/api/v1/endpoints/privacy_request_endpoints.py +27 -0
  10. fides/api/db/base.py +2 -0
  11. fides/api/db/database.py +32 -2
  12. fides/api/models/identity_definition.py +65 -0
  13. fides/api/models/privacy_request/privacy_request.py +3 -0
  14. fides/api/models/v3/__init__.py +0 -0
  15. fides/api/models/v3/privacy_preferences.py +85 -0
  16. fides/api/schemas/application_config.py +28 -0
  17. fides/api/schemas/privacy_request.py +2 -0
  18. fides/api/service/connectors/query_configs/saas_query_config.py +4 -1
  19. fides/api/service/connectors/saas_connector.py +4 -5
  20. fides/common/api/v1/urn_registry.py +1 -0
  21. fides/config/__init__.py +3 -0
  22. fides/config/config_proxy.py +10 -0
  23. fides/config/duplicate_detection_settings.py +31 -0
  24. fides/config/utils.py +5 -0
  25. fides/service/privacy_request/privacy_request_service.py +96 -38
  26. fides/ui-build/static/admin/404.html +1 -1
  27. fides/ui-build/static/admin/_next/static/BcQzR23eIPTcIJtpdoKEA/_buildManifest.js +1 -0
  28. fides/ui-build/static/admin/_next/static/chunks/{1099-fa8b82f521b23cce.js → 1099-31f9d973bc287df8.js} +1 -1
  29. fides/ui-build/static/admin/_next/static/chunks/{1115-d7ce851b36722c41.js → 1115-26393b586775ea29.js} +1 -1
  30. fides/ui-build/static/admin/_next/static/chunks/{1437-9dd64c20d38667df.js → 1437-8b1f6c8797c68bfd.js} +1 -1
  31. fides/ui-build/static/admin/_next/static/chunks/{155-1c80b19f58f44a0c.js → 155-f6302d32cba4cab6.js} +1 -1
  32. fides/ui-build/static/admin/_next/static/chunks/{1817-0de0312294019817.js → 1817-2d5cf537a2992c79.js} +1 -1
  33. fides/ui-build/static/admin/_next/static/chunks/{1975.6ca0e76b5a3d1955.js → 1975.afe8cad52f904fcf.js} +1 -1
  34. fides/ui-build/static/admin/_next/static/chunks/{2040-a18cc21821e2d121.js → 2040-7eed8491ca7276ed.js} +1 -1
  35. fides/ui-build/static/admin/_next/static/chunks/{2397-16820a09e8ebfe33.js → 2397-083fc511acb6105d.js} +1 -1
  36. fides/ui-build/static/admin/_next/static/chunks/{2921-a5dac2eacdcc32ff.js → 2921-34a43f2f8f5e5e69.js} +1 -1
  37. fides/ui-build/static/admin/_next/static/chunks/{3377-c2c9eb177bec8719.js → 3377-988ac2f3a2e8d5d4.js} +1 -1
  38. fides/ui-build/static/admin/_next/static/chunks/{3696-21e3dec6c2023875.js → 3696-6f90e41a53d22920.js} +1 -1
  39. fides/ui-build/static/admin/_next/static/chunks/{3700-a2903cd95b8a27cb.js → 3700-f695f2f6b8251971.js} +1 -1
  40. fides/ui-build/static/admin/_next/static/chunks/{3772-bb84842df51d3f3f.js → 3772-9f1713f9d5f97a10.js} +1 -1
  41. fides/ui-build/static/admin/_next/static/chunks/{3873-d759bbe7137ae8c2.js → 3873-d18e47b327445db5.js} +1 -1
  42. fides/ui-build/static/admin/_next/static/chunks/{3923-7f0aa36c9e09cedf.js → 3923-f0a85dc5c3684fa0.js} +1 -1
  43. fides/ui-build/static/admin/_next/static/chunks/{401-874303feb3899562.js → 401-7c345d019bb9bcbd.js} +1 -1
  44. fides/ui-build/static/admin/_next/static/chunks/{4496-903c81292ffd8f91.js → 4496-4ff19366c597ec16.js} +1 -1
  45. fides/ui-build/static/admin/_next/static/chunks/{4817-d0cc100f259b3c2e.js → 4817-1f3e6ea38625d8d5.js} +1 -1
  46. fides/ui-build/static/admin/_next/static/chunks/{5185-fc171b6acce9f915.js → 5185-e7f8b81dd3dfbe0b.js} +1 -1
  47. fides/ui-build/static/admin/_next/static/chunks/{5258-cf0d2c4c4d55a94b.js → 5258-62d6bc19add60aa6.js} +1 -1
  48. fides/ui-build/static/admin/_next/static/chunks/{5279-8637d735471ec7f1.js → 5279-bd6cccabdd6ca447.js} +1 -1
  49. fides/ui-build/static/admin/_next/static/chunks/{549-2d9bde37e5fe13eb.js → 549-28537a6de666944b.js} +1 -1
  50. fides/ui-build/static/admin/_next/static/chunks/{5643-48a5e0ad8b9fc3f7.js → 5643-3459282d296a3c59.js} +1 -1
  51. fides/ui-build/static/admin/_next/static/chunks/{5783-63912bab7f80b0f8.js → 5783-21775c232dce7af7.js} +1 -1
  52. fides/ui-build/static/admin/_next/static/chunks/{6277-ec0e3fa4e4614098.js → 6277-3759894435cb8569.js} +1 -1
  53. fides/ui-build/static/admin/_next/static/chunks/{6315-79a1506e01f2f92b.js → 6315-e2fb5ea77179a871.js} +1 -1
  54. fides/ui-build/static/admin/_next/static/chunks/{6853-c348f6e95f987cbf.js → 6853-de9905d28e5b19b3.js} +1 -1
  55. fides/ui-build/static/admin/_next/static/chunks/{6954-c44ac4e70e777c2f.js → 6954-84789a4e4fb04eb9.js} +1 -1
  56. fides/ui-build/static/admin/_next/static/chunks/7059-2bb7c38578549703.js +1 -0
  57. fides/ui-build/static/admin/_next/static/chunks/{7245-120f536e09decb85.js → 7245-c9bc628d078c2170.js} +1 -1
  58. fides/ui-build/static/admin/_next/static/chunks/{7476-4234fb244676ec13.js → 7476-a02d970ea4d3f7d0.js} +1 -1
  59. fides/ui-build/static/admin/_next/static/chunks/7488-cf92601852e3c509.js +1 -0
  60. fides/ui-build/static/admin/_next/static/chunks/{7630-d7bd74d0cfdb22df.js → 7630-a11610c2b31ab2ca.js} +1 -1
  61. fides/ui-build/static/admin/_next/static/chunks/{7773-6dce6187fe2c6984.js → 7773-9ae233109bc64ec2.js} +1 -1
  62. fides/ui-build/static/admin/_next/static/chunks/{796-fae64888b8b2f369.js → 796-e36d610066135f8c.js} +1 -1
  63. fides/ui-build/static/admin/_next/static/chunks/{8011-6e40c969c9fa7d35.js → 8011-75af8b480fa114e6.js} +1 -1
  64. fides/ui-build/static/admin/_next/static/chunks/{8212-18d8da0f9208f978.js → 8212-393420e5a9751791.js} +1 -1
  65. fides/ui-build/static/admin/_next/static/chunks/{8373-24379b7d98e6922e.js → 8373-22b4d20e8cc06b3a.js} +1 -1
  66. fides/ui-build/static/admin/_next/static/chunks/{9046-6428eac9f38b3886.js → 9046-d9c6498368b993d1.js} +1 -1
  67. fides/ui-build/static/admin/_next/static/chunks/{9330-540a113903cb3c28.js → 9330-f753636a31c4ea04.js} +1 -1
  68. fides/ui-build/static/admin/_next/static/chunks/{9676.704cc210f59d0083.js → 9676.7d029a5383595b69.js} +1 -1
  69. fides/ui-build/static/admin/_next/static/chunks/{9682-a3b2fb1a2df1c948.js → 9682-d1a3afa1394f8304.js} +1 -1
  70. fides/ui-build/static/admin/_next/static/chunks/{9826-aecc5ddec86989dc.js → 9826-a737a9956c1d0905.js} +1 -1
  71. fides/ui-build/static/admin/_next/static/chunks/{9899-303921e3d0697960.js → 9899-addc35c81190203d.js} +1 -1
  72. fides/ui-build/static/admin/_next/static/chunks/{9965-6906ffdaef0f0d69.js → 9965-25621dd507e0cfd6.js} +1 -1
  73. fides/ui-build/static/admin/_next/static/chunks/pages/{404-c31cef0ce3fbeebf.js → 404-eb019192ce498f32.js} +1 -1
  74. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-5fd4e06224960492.js → _app-ee588a308812715d.js} +11 -11
  75. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-a5865f42aafbe1f8.js → manual-7081e0e49f67716c.js} +1 -1
  76. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-f706664770dd3e7f.js → multiple-a188f84239f4b2a8.js} +1 -1
  77. fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-3f0d8698f01aabc5.js → add-systems-ee9df33ebd471099.js} +1 -1
  78. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-fcd031b2b775e4f3.js → add-vendors-4f9cf087fcee87e6.js} +1 -1
  79. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-0bd2eb0110873c4d.js → configure-9af75caefc74eaca.js} +1 -1
  80. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-0dd17c74a6cc17ff.js → [id]-1b02a4991201b7e4.js} +1 -1
  81. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-ae8dff75e1c6c413.js → privacy-experience-b08abefec298ccf1.js} +1 -1
  82. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-84ba8b9947b9af0a.js → [id]-8c164c4b8310214e.js} +1 -1
  83. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-f03d1d0df4661a33.js → new-db789002d84c8829.js} +1 -1
  84. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-5a553b4bdbf85aa9.js → privacy-notices-6528eb24165aceb6.js} +1 -1
  85. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-5cba88e6839a087d.js → properties-5cba30eba1e97e56.js} +1 -1
  86. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{reporting-f2690c381c1d1a52.js → reporting-11f1683aa15e1a62.js} +1 -1
  87. fides/ui-build/static/admin/_next/static/chunks/pages/{consent-289d21aa6c42828b.js → consent-614af0a2c2ba966c.js} +1 -1
  88. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-cb56d56b9d918682.js → [projectUrn]-d60761c20382b259.js} +1 -1
  89. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-ccb66ba6d1ad93fc.js → projects-07e7d38ce34e1e6c.js} +1 -1
  90. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-ecb2d925d75dfe1e.js → resources-aed94957009eb3fd.js} +1 -1
  91. fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-75403467491a251b.js → data-catalog-127c114dd8f102ed.js} +1 -1
  92. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/datastore/[monitorId]-21a0f5f1b5450976.js +1 -0
  93. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/website/[monitorId]/{[systemId]-71cf0b06b3d5a326.js → [systemId]-899bf30dde8b3292.js} +1 -1
  94. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/website/{[monitorId]-cc6b359fb4968bf0.js → [monitorId]-73085f50abb775c0.js} +1 -1
  95. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-823d0dd77e66585b.js +1 -0
  96. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-7dded115499a4a4a.js → activity-24a82e07a0008516.js} +1 -1
  97. fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-d1bb19fe4ef393dc.js → datamap-3b100c44ea9e3988.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-58c3f4c0b490264b.js → [...subfieldNames]-5f88280db168083e.js} +1 -1
  99. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-74290432e74fcdc5.js → [collectionName]-bfbcf19c28c794ae.js} +1 -1
  100. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-8dad45f070a06609.js → [datasetId]-6fbe2b584a509226.js} +1 -1
  101. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-6aed6dc24c3be001.js → new-3d1e48f4b95d7f6b.js} +1 -1
  102. fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-fdaec997c1b0753f.js → dataset-d3c6ecf7f29bea6e.js} +1 -1
  103. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-63c4805e40673c60.js → [id]-0a4aa42be2da0255.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-b5a49743387eecef.js → new-14313e441a13192c.js} +1 -1
  105. fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-8f0804d9a38688a4.js → datastore-connection-f139d1ce26404f30.js} +1 -1
  106. fides/ui-build/static/admin/_next/static/chunks/pages/{index-363b091a4d1d70ad.js → index-1343fa525a206571.js} +1 -1
  107. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-b2d3d28b10a758e6.js +1 -0
  108. fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-b0da32fe3564c129.js → integrations-a733e5d7c3ce9bb8.js} +1 -1
  109. fides/ui-build/static/admin/_next/static/chunks/pages/new-privacy-requests-df0c95e408c54c7e.js +1 -0
  110. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/digests/{[id]-0e4e4e7110362022.js → [id]-63b3be660fb12c0f.js} +1 -1
  111. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/digests/{new-2e15f6272e9aaeb6.js → new-d3b577962dd33266.js} +1 -1
  112. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/{digests-65626dfcfacdc605.js → digests-aed9afd988a48acf.js} +1 -1
  113. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/providers/{[key]-768c4e2f6b05304c.js → [key]-720cde29f81db47f.js} +1 -1
  114. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/providers/{new-2d57a70e4d32e651.js → new-3668866076b53016.js} +1 -1
  115. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/{providers-83f78354fa34bffe.js → providers-36a0ac36062abd02.js} +1 -1
  116. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/templates/{[id]-1b31764f520fbbc5.js → [id]-8063dceb32310c85.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/templates/{add-template-4c74456b6677bf07.js → add-template-4931c70bee62232f.js} +1 -1
  118. fides/ui-build/static/admin/_next/static/chunks/pages/notifications/{templates-5deb80abd6156f7f.js → templates-a14c876b49422597.js} +1 -1
  119. fides/ui-build/static/admin/_next/static/chunks/pages/{notifications-8d8716dda9a6f277.js → notifications-93af719dab3bd053.js} +1 -1
  120. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-52b1572442a20ab4.js → ant-components-9cfb469de7b4aeab.js} +1 -1
  121. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-a0437ba647d59799.js → AntForm-e715cc654fb6a5cd.js} +1 -1
  122. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-87285c544450ec46.js → FormikAntFormItem-72ae299bcb6adae6.js} +1 -1
  123. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-57997dbd451a6eed.js → FormikControlled-2337f8c81a766eb0.js} +1 -1
  124. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-65009783e0404153.js → FormikField-0af454f55494f6fa.js} +1 -1
  125. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-eafef007c179340f.js → forms-d1b90ffa996fbd89.js} +1 -1
  126. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-7933a824a45d0ee6.js → table-migration-19724b9e0581b96d.js} +1 -1
  127. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-cdd3754289a28317.js +1 -0
  128. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/{storage-16f77a6291bb02fe.js → storage-cc41ae605f2b55ae.js} +1 -1
  129. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-d2b3293ab496f7bc.js → configure-fa82cffba448ccd8.js} +1 -1
  130. fides/ui-build/static/admin/_next/static/chunks/pages/{privacy-requests-af4f48d10926e4a4.js → privacy-requests-6e4c535b6d614596.js} +1 -1
  131. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-dd3c3d780533a9c2.js → [id]-bc1c289647e52c48.js} +1 -1
  132. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-d1af260c3ddbf68b.js → add-property-cbfaa23d96f5ed0b.js} +1 -1
  133. fides/ui-build/static/admin/_next/static/chunks/pages/{properties-9bb7fe3577402008.js → properties-a15a3fd0ed88f39c.js} +1 -1
  134. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-632b3ee563d070f2.js +1 -0
  135. fides/ui-build/static/admin/_next/static/chunks/pages/sandbox/privacy-notices-afe921f6e2a526fb.js +1 -0
  136. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-35626e9d8e0a3ca2.js → [purpose_id]-19de0024418a4924.js} +1 -1
  137. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-39b5142099ed8705.js → consent-5b6807dced8d03c5.js} +1 -1
  138. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-64c638ea33bb3ff9.js → custom-fields-7dce52bfc1b2652c.js} +1 -1
  139. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-3843fbaf5bc433f1.js → domain-records-3b87002753b23ca5.js} +1 -1
  140. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-ea549fabce96fde4.js → domains-aacd9d0ad47082d4.js} +1 -1
  141. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-0fe318a9dfc1f593.js → email-templates-3cdd0b39901190ba.js} +1 -1
  142. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-c42c856510cad6fd.js → locations-61076eedbfd137b9.js} +1 -1
  143. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-e4c552a5797c3fa5.js → organization-b07b11d6002f8c8c.js} +1 -1
  144. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{privacy-requests-2790d31b59cc3c74.js → privacy-requests-084a2b4431d35322.js} +1 -1
  145. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-3c608512c415fca4.js → regulations-b7c0d3b1b754e70f.js} +1 -1
  146. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-e0e1a5142e41e9f2.js → test-datasets-b72d36243a0a545c.js} +1 -1
  147. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-9e815520adb3e580.js → [id]-59c89489fa32a4cb.js} +1 -1
  148. fides/ui-build/static/admin/_next/static/chunks/pages/{systems-d8ce572ad07ed28c.js → systems-cfaa37a0df83674b.js} +1 -1
  149. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-d2eb5a81d4a19c7d.js +1 -0
  150. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-75d96422db98196f.js → [id]-5d5a68e555d18693.js} +1 -1
  151. fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-598f98fd88505e1e.js → user-management-e6a211d8a0401086.js} +1 -1
  152. fides/ui-build/static/admin/_next/static/chunks/{webpack-0a3b419ab682b8f9.js → webpack-c2c11809187b9f84.js} +1 -1
  153. fides/ui-build/static/admin/_next/static/css/d41a048a166d50e4.css +1 -0
  154. fides/ui-build/static/admin/_next/static/css/d78390d6134d8328.css +1 -0
  155. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  156. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  157. fides/ui-build/static/admin/add-systems.html +1 -1
  158. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  159. fides/ui-build/static/admin/consent/configure.html +1 -1
  160. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  161. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  162. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  163. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  164. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  165. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  166. fides/ui-build/static/admin/consent/properties.html +1 -1
  167. fides/ui-build/static/admin/consent/reporting.html +1 -1
  168. fides/ui-build/static/admin/consent.html +1 -1
  169. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  170. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  171. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  172. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  173. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  174. fides/ui-build/static/admin/data-catalog.html +1 -1
  175. fides/ui-build/static/admin/data-discovery/action-center/datastore/[monitorId].html +1 -1
  176. fides/ui-build/static/admin/data-discovery/action-center/datastore.html +1 -1
  177. fides/ui-build/static/admin/data-discovery/action-center/website/[monitorId]/[systemId].html +1 -1
  178. fides/ui-build/static/admin/data-discovery/action-center/website/[monitorId].html +1 -1
  179. fides/ui-build/static/admin/data-discovery/action-center/website.html +1 -1
  180. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  181. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  182. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  183. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  184. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  185. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  186. fides/ui-build/static/admin/datamap.html +1 -1
  187. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  188. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  189. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  190. fides/ui-build/static/admin/dataset/new.html +1 -1
  191. fides/ui-build/static/admin/dataset.html +1 -1
  192. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  193. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  194. fides/ui-build/static/admin/datastore-connection.html +1 -1
  195. fides/ui-build/static/admin/index.html +1 -1
  196. fides/ui-build/static/admin/integrations/[id].html +1 -1
  197. fides/ui-build/static/admin/integrations.html +1 -1
  198. fides/ui-build/static/admin/login/[provider].html +1 -1
  199. fides/ui-build/static/admin/login.html +1 -1
  200. fides/ui-build/static/admin/new-privacy-requests.html +1 -1
  201. fides/ui-build/static/admin/notifications/digests/[id].html +1 -1
  202. fides/ui-build/static/admin/notifications/digests/new.html +1 -1
  203. fides/ui-build/static/admin/notifications/digests.html +1 -1
  204. fides/ui-build/static/admin/notifications/providers/[key].html +1 -1
  205. fides/ui-build/static/admin/notifications/providers/new.html +1 -1
  206. fides/ui-build/static/admin/notifications/providers.html +1 -1
  207. fides/ui-build/static/admin/notifications/templates/[id].html +1 -1
  208. fides/ui-build/static/admin/notifications/templates/add-template.html +1 -1
  209. fides/ui-build/static/admin/notifications/templates.html +1 -1
  210. fides/ui-build/static/admin/notifications.html +1 -1
  211. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  212. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  213. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  214. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  215. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  216. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  217. fides/ui-build/static/admin/poc/forms.html +1 -1
  218. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  219. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  220. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  221. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  222. fides/ui-build/static/admin/privacy-requests.html +1 -1
  223. fides/ui-build/static/admin/properties/[id].html +1 -1
  224. fides/ui-build/static/admin/properties/add-property.html +1 -1
  225. fides/ui-build/static/admin/properties.html +1 -1
  226. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  227. fides/ui-build/static/admin/sandbox/privacy-notices.html +1 -0
  228. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  229. fides/ui-build/static/admin/settings/about.html +1 -1
  230. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  231. fides/ui-build/static/admin/settings/consent.html +1 -1
  232. fides/ui-build/static/admin/settings/custom-fields/[id].html +1 -1
  233. fides/ui-build/static/admin/settings/custom-fields/new.html +1 -1
  234. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  235. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  236. fides/ui-build/static/admin/settings/domains.html +1 -1
  237. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  238. fides/ui-build/static/admin/settings/locations.html +1 -1
  239. fides/ui-build/static/admin/settings/organization.html +1 -1
  240. fides/ui-build/static/admin/settings/privacy-requests.html +1 -1
  241. fides/ui-build/static/admin/settings/regulations.html +1 -1
  242. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  243. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  244. fides/ui-build/static/admin/systems.html +1 -1
  245. fides/ui-build/static/admin/taxonomy.html +1 -1
  246. fides/ui-build/static/admin/user-management/new.html +1 -1
  247. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  248. fides/ui-build/static/admin/user-management.html +1 -1
  249. fides/ui-build/static/admin/_next/static/V6C1Uu1MRQoBEyjy_BoEr/_buildManifest.js +0 -1
  250. fides/ui-build/static/admin/_next/static/chunks/7059-3f2641e3130b4ef8.js +0 -1
  251. fides/ui-build/static/admin/_next/static/chunks/7488-2db0992474f8056e.js +0 -1
  252. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/datastore/[monitorId]-e46e017a3919f94e.js +0 -1
  253. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-cbff5db86e6951c4.js +0 -1
  254. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-3b7f47985452e01d.js +0 -1
  255. fides/ui-build/static/admin/_next/static/chunks/pages/new-privacy-requests-d1152cbc3c1bbbbb.js +0 -1
  256. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-27c56466eab98b15.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-33ce744d07982c0f.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-0cae23a599830708.js +0 -1
  259. fides/ui-build/static/admin/_next/static/css/919f947a862d28cd.css +0 -1
  260. {ethyca_fides-2.73.0rc4.dist-info → ethyca_fides-2.73.1.dist-info}/WHEEL +0 -0
  261. {ethyca_fides-2.73.0rc4.dist-info → ethyca_fides-2.73.1.dist-info}/entry_points.txt +0 -0
  262. {ethyca_fides-2.73.0rc4.dist-info → ethyca_fides-2.73.1.dist-info}/licenses/LICENSE +0 -0
  263. {ethyca_fides-2.73.0rc4.dist-info → ethyca_fides-2.73.1.dist-info}/top_level.txt +0 -0
  264. /fides/ui-build/static/admin/_next/static/{V6C1Uu1MRQoBEyjy_BoEr → BcQzR23eIPTcIJtpdoKEA}/_ssgManifest.js +0 -0
  265. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-5d133ec635cd716c.js → [resourceUrn]-32bd7a7c990e5bf6.js} +0 -0
  266. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-9d8efe43b69a285d.js → [resourceUrn]-b07a0707f8c2ec0d.js} +0 -0
  267. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{datastore-1b0ed3b3ceedfd94.js → datastore-4498881c26f1458d.js} +0 -0
  268. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/{website-60ad14c879b4fe27.js → website-5b3e0009d442bc3f.js} +0 -0
  269. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-2df143c1e1f79040.js → [resourceUrn]-b072cf25aefc98f6.js} +0 -0
  270. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-e37c800313e2a422.js → detection-fd3e8817d8e6dee4.js} +0 -0
  271. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-7022ca5fa834b633.js → [resourceUrn]-146624cf59792bf7.js} +0 -0
  272. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-6178e22397f20f92.js → discovery-9695cc9c85592ec5.js} +0 -0
  273. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields/{[id]-b5140de4431a7ff5.js → [id]-8634aae3259def37.js} +0 -0
  274. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields/{new-dcc16459e754fbbd.js → new-2d9dcca17965dc57.js} +0 -0
  275. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-bc1568bb47d198a9.js → new-7dce2916cc589c54.js} +0 -0
fides/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-10-24T16:42:20-0700",
11
+ "date": "2025-10-30T16:26:15-0400",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "ca872f4fade7f59c7c49c558ecb610e1f0b41128",
15
- "version": "2.73.0rc4"
14
+ "full-revisionid": "34dad3dac5891167e4a1b6cd743199971220da57",
15
+ "version": "2.73.1"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -5,7 +5,11 @@
5
5
  script_location = migrations
6
6
 
7
7
  # template used to generate migration files
8
- # file_template = %%(rev)s_%%(slug)s
8
+ # Adding the prefix xx_ make all new migrations (after changing the file template to date-based)
9
+ # show up below the existing mirations when files are sorted
10
+ file_template = xx_%%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d_%%(rev)s_%%(slug)s
11
+
12
+
9
13
 
10
14
  # sys.path path, will be prepended to sys.path if present.
11
15
  # defaults to the current working directory.
@@ -3,6 +3,7 @@ from logging.config import fileConfig
3
3
  from alembic import context
4
4
  from sqlalchemy import engine_from_config, pool
5
5
 
6
+ from fides.api.db.database import include_object
6
7
  from fides.api.util.logger import setup as setup_fidesapi_logger
7
8
  from fides.config import CONFIG
8
9
 
@@ -48,6 +49,7 @@ def run_migrations_offline():
48
49
  target_metadata=target_metadata,
49
50
  literal_binds=True,
50
51
  dialect_opts={"paramstyle": "named"},
52
+ include_object=include_object,
51
53
  )
52
54
 
53
55
  with context.begin_transaction():
@@ -70,7 +72,11 @@ def run_migrations_online():
70
72
  )
71
73
 
72
74
  with connectable.connect() as connection:
73
- context.configure(connection=connection, target_metadata=target_metadata)
75
+ context.configure(
76
+ connection=connection,
77
+ target_metadata=target_metadata,
78
+ include_object=include_object,
79
+ )
74
80
 
75
81
  with context.begin_transaction():
76
82
  context.run_migrations()
@@ -0,0 +1,64 @@
1
+ """add privacy request duplication cols
2
+
3
+ Revision ID: c09e76282dd1
4
+ Revises: 67f0f2f4748e
5
+ Create Date: 2025-10-21 21:46:38.006328
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "c09e76282dd1"
14
+ down_revision = "67f0f2f4748e"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ # Add duplicate group tracking column
22
+ op.add_column(
23
+ "privacyrequest",
24
+ sa.Column("duplicate_request_group_id", sa.String(), nullable=True),
25
+ )
26
+ op.create_index(
27
+ op.f("ix_privacyrequest_duplicate_request_group_id"),
28
+ "privacyrequest",
29
+ ["duplicate_request_group_id"],
30
+ unique=False,
31
+ )
32
+
33
+ # Add 'duplicate' status to enum
34
+ op.execute("alter type privacyrequeststatus add value 'duplicate'")
35
+ # ### end Alembic commands ###
36
+
37
+
38
+ def downgrade():
39
+ # ### commands auto generated by Alembic - please adjust! ###
40
+ # Drop group tracking column and index
41
+ op.drop_index(
42
+ op.f("ix_privacyrequest_duplicate_request_group_id"),
43
+ table_name="privacyrequest",
44
+ )
45
+ op.drop_column("privacyrequest", "duplicate_request_group_id")
46
+
47
+ # Remove 'duplicate' status from enum
48
+ # First delete any requests with duplicate status
49
+ op.execute("UPDATE privacyrequest SET status = 'error' WHERE status = 'duplicate'")
50
+
51
+ # Recreate enum without 'duplicate'
52
+ op.execute("alter type privacyrequeststatus rename to privacyrequeststatus_old")
53
+ op.execute(
54
+ "create type privacyrequeststatus as enum("
55
+ "'identity_unverified', 'requires_input', 'pending', 'approved', 'denied', "
56
+ "'in_processing', 'complete', 'paused', 'awaiting_email_send', "
57
+ "'requires_manual_finalization', 'canceled', 'error')"
58
+ )
59
+ op.execute(
60
+ "alter table privacyrequest alter column status type privacyrequeststatus "
61
+ "using status::text::privacyrequeststatus"
62
+ )
63
+ op.execute("drop type privacyrequeststatus_old")
64
+ # ### end Alembic commands ###
@@ -0,0 +1,72 @@
1
+ """Add consent data v3 to the database
2
+
3
+ Revision ID: 5093e92e2a5a
4
+ Revises: a55e12c2c2df
5
+ Create Date: 2025-10-17 16:03:37.933367
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+ from sqlalchemy import BigInteger, Identity
12
+ from sqlalchemy.dialects import postgresql
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision = "5093e92e2a5a"
16
+ down_revision = "a55e12c2c2df"
17
+ branch_labels = None
18
+ depends_on = None
19
+
20
+
21
+ def upgrade():
22
+ op.create_table(
23
+ "privacy_preferences",
24
+ # Use a big integer for the primary key to ensure we have enough space for all the records
25
+ # and also force the ID to be generated, never allowing it to be overridden without expressly using `OVERRIDING SYSTEM VALUE`
26
+ sa.Column(
27
+ "id",
28
+ BigInteger,
29
+ Identity(start=1, increment=1, always=True),
30
+ primary_key=True,
31
+ ),
32
+ sa.Column("search_data", postgresql.JSONB),
33
+ sa.Column("record_data", postgresql.TEXT),
34
+ # If we have a primary key we need to use a composite key because the primary key must be unique across _all_
35
+ # partitions, so we can't just use `id`, we have to use `is_latest` as well as part of the primary key. This
36
+ # should not be problematic as we will not allow for manually providing the ID so (unless someone deliberately does it)
37
+ # we should not end up with duplicate IDs having different `is_latest` values.
38
+ sa.Column(
39
+ "is_latest",
40
+ postgresql.BOOLEAN,
41
+ nullable=False,
42
+ server_default="f",
43
+ primary_key=True,
44
+ ),
45
+ sa.Column(
46
+ "created_at",
47
+ postgresql.TIMESTAMP(timezone=True),
48
+ nullable=False,
49
+ server_default=sa.text("now()"),
50
+ ),
51
+ sa.Column("updated_at", postgresql.TIMESTAMP(timezone=True), nullable=True),
52
+ postgresql_partition_by="LIST (is_latest)",
53
+ )
54
+ # Create our partition tables using _current and _historic as suffixes
55
+ op.execute(
56
+ """
57
+ CREATE TABLE privacy_preferences_current
58
+ PARTITION OF privacy_preferences
59
+ FOR VALUES IN (true);
60
+ """
61
+ )
62
+ op.execute(
63
+ """
64
+ CREATE TABLE privacy_preferences_historic
65
+ PARTITION OF privacy_preferences
66
+ FOR VALUES IN (false);
67
+ """
68
+ )
69
+
70
+
71
+ def downgrade():
72
+ op.drop_table("privacy_preferences")
@@ -0,0 +1,45 @@
1
+ """adding identity definition model
2
+
3
+ Revision ID: 67f0f2f4748e
4
+ Revises: 5093e92e2a5a
5
+ Create Date: 2025-10-27 18:34:38.326608
6
+
7
+ """
8
+
9
+ import sqlalchemy as sa
10
+ from alembic import op
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "67f0f2f4748e"
14
+ down_revision = "5093e92e2a5a"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ op.create_table(
21
+ "identity_definition",
22
+ sa.Column("id", sa.String(length=255), nullable=False, unique=True),
23
+ sa.Column(
24
+ "created_at",
25
+ sa.DateTime(timezone=True),
26
+ server_default=sa.text("now()"),
27
+ nullable=True,
28
+ ),
29
+ sa.Column(
30
+ "updated_at",
31
+ sa.DateTime(timezone=True),
32
+ server_default=sa.text("now()"),
33
+ nullable=True,
34
+ ),
35
+ sa.Column("identity_key", sa.String(length=255), nullable=False),
36
+ sa.Column("name", sa.String(length=255), nullable=False),
37
+ sa.Column("description", sa.Text(), nullable=True),
38
+ sa.Column("type", sa.String(length=255), nullable=False),
39
+ sa.Column("created_by", sa.String(length=255), nullable=True),
40
+ sa.PrimaryKeyConstraint("identity_key"),
41
+ )
42
+
43
+
44
+ def downgrade():
45
+ op.drop_table("identity_definition")
@@ -144,6 +144,7 @@ from fides.common.api.v1.urn_registry import (
144
144
  PRIVACY_REQUEST_APPROVE,
145
145
  PRIVACY_REQUEST_AUTHENTICATED,
146
146
  PRIVACY_REQUEST_BATCH_EMAIL_SEND,
147
+ PRIVACY_REQUEST_BULK_FINALIZE,
147
148
  PRIVACY_REQUEST_BULK_RETRY,
148
149
  PRIVACY_REQUEST_BULK_SOFT_DELETE,
149
150
  PRIVACY_REQUEST_DENY,
@@ -1971,6 +1972,32 @@ def resume_privacy_request_from_requires_input(
1971
1972
  return privacy_request # type: ignore[return-value]
1972
1973
 
1973
1974
 
1975
+ @router.post(
1976
+ PRIVACY_REQUEST_BULK_FINALIZE,
1977
+ status_code=HTTP_200_OK,
1978
+ response_model=BulkReviewResponse,
1979
+ )
1980
+ def bulk_finalize_privacy_requests(
1981
+ *,
1982
+ client: ClientDetail = Security(
1983
+ verify_oauth_client,
1984
+ scopes=[PRIVACY_REQUEST_REVIEW],
1985
+ ),
1986
+ privacy_request_service: PrivacyRequestService = Depends(
1987
+ get_privacy_request_service
1988
+ ),
1989
+ privacy_requests: ReviewPrivacyRequestIds,
1990
+ ) -> BulkReviewResponse:
1991
+ """
1992
+ Bulk finalize privacy requests that are in requires_manual_finalization status.
1993
+ Each request will be moved from the 'requires_finalization' state to 'complete'.
1994
+ Returns an object with the list of successfully finalized privacy requests and the list of failed finalizations.
1995
+ """
1996
+ return privacy_request_service.finalize_privacy_requests(
1997
+ privacy_requests.request_ids, user_id=client.user_id
1998
+ )
1999
+
2000
+
1974
2001
  @router.post(
1975
2002
  PRIVACY_REQUEST_FINALIZE,
1976
2003
  status_code=HTTP_200_OK,
fides/api/db/base.py CHANGED
@@ -33,6 +33,7 @@ from fides.api.models.fides_user_permissions import FidesUserPermissions
33
33
  from fides.api.models.fides_user_respondent_email_verification import (
34
34
  FidesUserRespondentEmailVerification,
35
35
  )
36
+ from fides.api.models.identity_definition import IdentityDefinition
36
37
  from fides.api.models.identity_salt import IdentitySalt
37
38
  from fides.api.models.location_regulation_selections import LocationRegulationSelections
38
39
  from fides.api.models.manual_task import (
@@ -95,3 +96,4 @@ from fides.api.models.tcf_publisher_restrictions import (
95
96
  TCFPublisherRestriction,
96
97
  )
97
98
  from fides.api.models.tcf_purpose_overrides import TCFPurposeOverride
99
+ from fides.api.models.v3.privacy_preferences import PrivacyPreferences
fides/api/db/database.py CHANGED
@@ -9,7 +9,9 @@ from alembic import command, script
9
9
  from alembic.config import Config
10
10
  from alembic.runtime import migration
11
11
  from loguru import logger as log
12
+ from sqlalchemy import text
12
13
  from sqlalchemy.orm import Session
14
+ from sqlalchemy.schema import SchemaItem
13
15
  from sqlalchemy_utils.functions import create_database, database_exists
14
16
  from sqlalchemy_utils.types.encrypted.encrypted_type import InvalidCiphertextError
15
17
 
@@ -20,6 +22,25 @@ from fides.api.util.errors import get_full_exception_name
20
22
 
21
23
  DatabaseHealth = Literal["healthy", "unhealthy", "needs migration"]
22
24
 
25
+ # Tables to exclude from migration auto-generation (e.g., tables without SQLAlchemy models)
26
+ EXCLUDED_TABLES = {
27
+ "privacy_preferences_current",
28
+ "privacy_preferences_historic",
29
+ }
30
+
31
+
32
+ def include_object(
33
+ object: SchemaItem, # pylint: disable=redefined-builtin
34
+ name: str,
35
+ type_: str,
36
+ reflected: bool,
37
+ compare_to: SchemaItem,
38
+ ) -> bool:
39
+ """Filter out excluded tables from migration comparison and auto-generation."""
40
+ if type_ == "table" and name in EXCLUDED_TABLES:
41
+ return False
42
+ return True
43
+
23
44
 
24
45
  def get_alembic_config(database_url: str) -> Config:
25
46
  """
@@ -91,6 +112,10 @@ def reset_db(database_url: str) -> None:
91
112
  log.info("Dropping tables...")
92
113
  Base.metadata.drop_all(connection)
93
114
 
115
+ log.info("Dropping excluded tables without models...")
116
+ for table_name in EXCLUDED_TABLES:
117
+ connection.execute(text(f"DROP TABLE IF EXISTS {table_name} CASCADE"))
118
+
94
119
  log.info("Dropping Alembic table...")
95
120
  migration_context = migration.MigrationContext.configure(connection)
96
121
  version = migration_context._version # pylint: disable=protected-access
@@ -151,13 +176,18 @@ def check_missing_migrations(database_url: str) -> None:
151
176
  Tries to autogenerate migrations, returns True if a migration
152
177
  was generated.
153
178
  """
154
-
155
179
  engine = get_db_engine(database_uri=database_url)
156
180
  connection = engine.connect()
157
181
 
158
- migration_context = migration.MigrationContext.configure(connection)
182
+ migration_context = migration.MigrationContext.configure(
183
+ connection, opts={"include_object": include_object}
184
+ )
159
185
  result = command.autogen.compare_metadata(migration_context, Base.metadata) # type: ignore[attr-defined]
160
186
 
161
187
  if result:
188
+ log.error("Migration needs to be generated!")
189
+ log.error("Detected the following schema differences:")
190
+ for item in result:
191
+ log.error(f" - {item}")
162
192
  raise SystemExit("Migration needs to be generated!")
163
193
  print("No migrations need to be generated.")
@@ -0,0 +1,65 @@
1
+ from enum import Enum
2
+
3
+ from sqlalchemy import Column, String, Text
4
+ from sqlalchemy.ext.declarative import declared_attr
5
+
6
+ from fides.api.db.base_class import Base, FidesBase
7
+ from fides.api.db.util import EnumColumn
8
+
9
+
10
+ class IdentityDefinitionType(str, Enum):
11
+ """Enum for the type of identity"""
12
+
13
+ EMAIL = "email"
14
+ PHONE_NUMBER = "phone_number"
15
+ UUID = "uuid"
16
+ STRING = "string"
17
+ INTEGER = "integer"
18
+
19
+
20
+ class IdentityDefinition(Base):
21
+ """
22
+ Model for identity definitions in Fides. This isn't for specific identity values,
23
+ but for the types of identities that can be used in Fides.
24
+
25
+ For example:
26
+ ```json
27
+ {
28
+ "identity_key": "customer_id",
29
+ "name": "Customer ID",
30
+ "description": "The unique identifier for the customer",
31
+ "type": "string"
32
+ }
33
+ ```
34
+ """
35
+
36
+ @declared_attr
37
+ def __tablename__(self) -> str:
38
+ return "identity_definition"
39
+
40
+ # Overriding the id definition from Base so we don't treat this as the primary key
41
+ id = Column(
42
+ String(255),
43
+ nullable=False,
44
+ index=False,
45
+ unique=True,
46
+ default=FidesBase.generate_uuid,
47
+ )
48
+
49
+ # Primary key
50
+ identity_key = Column(String(255), primary_key=True)
51
+
52
+ # Schema definition
53
+ name = Column(String(255), nullable=False)
54
+ description = Column(Text, nullable=True)
55
+ type = Column(
56
+ EnumColumn(
57
+ IdentityDefinitionType,
58
+ native_enum=False,
59
+ values_callable=lambda x: [
60
+ i.value for i in x
61
+ ], # allows enum _values_ to be stored rather than name
62
+ ),
63
+ nullable=False,
64
+ )
65
+ created_by = Column(String(255), nullable=True)
@@ -224,6 +224,9 @@ class PrivacyRequest(
224
224
  source = Column(EnumColumn(PrivacyRequestSource), nullable=True)
225
225
  location = Column(String, nullable=True)
226
226
 
227
+ # Duplicate detection - group ID to link duplicates together
228
+ duplicate_request_group_id = Column(String, index=True, nullable=True)
229
+
227
230
  # A PrivacyRequest can be soft deleted, so we store when it was deleted
228
231
  deleted_at = Column(DateTime(timezone=True), nullable=True)
229
232
  # and who deleted it
File without changes
@@ -0,0 +1,85 @@
1
+ """SQLAlchemy model for the v3 privacy_preferences table."""
2
+
3
+ from sqlalchemy import ( # type: ignore[attr-defined]
4
+ BigInteger,
5
+ Boolean,
6
+ Column,
7
+ DateTime,
8
+ Identity,
9
+ Text,
10
+ text,
11
+ )
12
+ from sqlalchemy.dialects.postgresql import JSONB
13
+ from sqlalchemy.ext.declarative import declared_attr
14
+ from sqlalchemy_utils.types.encrypted.encrypted_type import (
15
+ AesGcmEngine,
16
+ StringEncryptedType,
17
+ )
18
+
19
+ from fides.api.cryptography.cryptographic_util import hash_value_with_salt
20
+ from fides.api.cryptography.identity_salt import get_identity_salt
21
+ from fides.api.db.base_class import Base
22
+ from fides.api.schemas.redis_cache import MultiValue
23
+ from fides.config import CONFIG
24
+
25
+
26
+ class PrivacyPreferences(Base):
27
+ """
28
+ Model for the v3 privacy_preferences table.
29
+ This is used for the v3 privacy preferences API.
30
+
31
+ This table stores privacy preference records with a partitioning scheme
32
+ based on the is_latest flag, splitting records into current and historic partitions.
33
+ """
34
+
35
+ @declared_attr
36
+ def __tablename__(self) -> str:
37
+ return "privacy_preferences"
38
+
39
+ # Override the default id column from Base (which is a String UUID)
40
+ # with a BigInteger identity column for this table
41
+ id = Column(
42
+ BigInteger, # type: ignore[arg-type]
43
+ Identity(start=1, increment=1, always=True),
44
+ primary_key=True,
45
+ )
46
+
47
+ # Searchable/queryable data stored as JSONB
48
+ search_data = Column(JSONB, nullable=True)
49
+
50
+ # Full record data stored as encrypted text (contains PII)
51
+ record_data = Column(
52
+ StringEncryptedType(
53
+ type_in=Text(),
54
+ key=CONFIG.security.app_encryption_key,
55
+ engine=AesGcmEngine,
56
+ padding="pkcs5",
57
+ ),
58
+ nullable=True,
59
+ )
60
+
61
+ # Partition key - determines if record goes to _current or _historic partition
62
+ is_latest = Column(
63
+ Boolean, nullable=False, server_default=text("false"), primary_key=True
64
+ )
65
+
66
+ # Override base class timestamp columns to match migration
67
+ created_at = Column(
68
+ DateTime(timezone=True), nullable=False, server_default=text("now()")
69
+ )
70
+ updated_at = Column(DateTime(timezone=True), nullable=True)
71
+
72
+ @classmethod
73
+ def hash_value(
74
+ cls,
75
+ value: MultiValue,
76
+ encoding: str = "UTF-8",
77
+ ) -> str:
78
+ """Utility function to hash the value with a generated salt"""
79
+ salt = get_identity_salt()
80
+ value_str = str(value)
81
+ hashed_value = hash_value_with_salt(
82
+ value_str.encode(encoding),
83
+ salt.encode(encoding),
84
+ )
85
+ return hashed_value
@@ -101,6 +101,31 @@ class ConsentConfig(FidesSchema):
101
101
  model_config = ConfigDict(extra="forbid")
102
102
 
103
103
 
104
+ class DuplicateDetectionApplicationConfig(FidesSchema):
105
+ """
106
+ API model - configuration settings for duplicate privacy request detection.
107
+ """
108
+
109
+ enabled: Optional[bool] = Field(
110
+ default=False,
111
+ description="Whether duplicate detection is enabled. Disabled by default.",
112
+ )
113
+
114
+ time_window_days: Optional[int] = Field(
115
+ default=365,
116
+ description="Time window in days for duplicate detection. Default is 1 year.",
117
+ ge=1,
118
+ le=3650, # Max 10 years
119
+ )
120
+
121
+ match_identity_fields: Optional[List[str]] = Field(
122
+ default=["email"],
123
+ description="Identity field names to match on for duplicate detection (e.g., 'email', 'phone_number'). Default is email only.",
124
+ )
125
+
126
+ model_config = ConfigDict(extra="forbid")
127
+
128
+
104
129
  class SecurityApplicationConfig(FidesSchema):
105
130
  # only valid URLs should be set as cors_origins
106
131
  # for advanced usage of non-URLs, e.g. wildcards (`*`), the related
@@ -129,6 +154,9 @@ class ApplicationConfig(FidesSchema):
129
154
  consent: Optional[ConsentConfig] = None
130
155
  admin_ui: Optional[AdminUIConfig] = None
131
156
  privacy_center: Optional[PrivacyCenterConfig] = None
157
+ privacy_request_duplicate_detection: Optional[
158
+ DuplicateDetectionApplicationConfig
159
+ ] = None
132
160
 
133
161
  @model_validator(mode="before")
134
162
  @classmethod
@@ -306,6 +306,7 @@ class PrivacyRequestStatus(str, EnumType):
306
306
  requires_manual_finalization = "requires_manual_finalization"
307
307
  canceled = "canceled"
308
308
  error = "error"
309
+ duplicate = "duplicate" # Request identified as duplicate of another request
309
310
 
310
311
 
311
312
  class PrivacyRequestResponse(FidesSchema):
@@ -342,6 +343,7 @@ class PrivacyRequestResponse(FidesSchema):
342
343
  deleted_by: Optional[str] = None
343
344
  finalized_at: Optional[datetime] = None
344
345
  finalized_by: Optional[str] = None
346
+ duplicate_request_group_id: Optional[str] = None
345
347
 
346
348
  model_config = ConfigDict(from_attributes=True, use_enum_values=True)
347
349
 
@@ -314,7 +314,7 @@ class SaaSQueryConfig(QueryConfig[SaaSRequestParams]):
314
314
  collection_values: Dict[str, Row],
315
315
  identity_data: Dict[str, Any],
316
316
  input_data: Optional[Dict[str, List[Any]]] = None,
317
- param_values: Dict[str, Any] = {},
317
+ param_values: Optional[Dict[str, Any]] = None,
318
318
  ) -> None:
319
319
  """
320
320
  Process param_values for update generation (erasure requests).
@@ -326,6 +326,9 @@ class SaaSQueryConfig(QueryConfig[SaaSRequestParams]):
326
326
  identity_data: Identity data for parameter resolution
327
327
  input_data: Optional upstream data from other collections
328
328
  """
329
+ if param_values is None:
330
+ param_values = {}
331
+
329
332
  for param_value in request.param_values or []:
330
333
  if param_value.references:
331
334
  # we resolve the param reference here for consistency,
@@ -787,11 +787,10 @@ class SaaSConnector(BaseConnector[AuthenticatedClient], Contextualizable):
787
787
 
788
788
  else:
789
789
  # follow the basic (global opt-in/out) SaaS consent flow
790
- (
791
- should_opt_in,
792
- filtered_preferences,
793
- ) = build_user_consent_and_filtered_preferences_for_service(
794
- self.configuration.system, privacy_request, session, False
790
+ should_opt_in, filtered_preferences = (
791
+ build_user_consent_and_filtered_preferences_for_service(
792
+ self.configuration.system, privacy_request, session, False
793
+ )
795
794
  )
796
795
 
797
796
  if should_opt_in is None:
@@ -84,6 +84,7 @@ PRIVACY_REQUEST_BATCH_EMAIL_SEND = (
84
84
  "/privacy-request/administrate/process-awaiting-email-send"
85
85
  )
86
86
  PRIVACY_REQUEST_AUTHENTICATED = "/privacy-request/authenticated"
87
+ PRIVACY_REQUEST_BULK_FINALIZE = "/privacy-request/bulk/finalize"
87
88
  PRIVACY_REQUEST_BULK_RETRY = "/privacy-request/bulk/retry"
88
89
  PRIVACY_REQUEST_BULK_SOFT_DELETE = "/privacy-request/bulk/soft-delete"
89
90
  PRIVACY_REQUEST_DENY = "/privacy-request/administrate/deny"
fides/config/__init__.py CHANGED
@@ -24,6 +24,7 @@ from .cli_settings import CLISettings
24
24
  from .consent_settings import ConsentSettings
25
25
  from .credentials_settings import merge_credentials_environment
26
26
  from .database_settings import DatabaseSettings
27
+ from .duplicate_detection_settings import DuplicateDetectionSettings
27
28
  from .execution_settings import ExecutionSettings
28
29
  from .fides_settings import FidesSettings
29
30
  from .helpers import handle_deprecated_env_variables, handle_deprecated_fields
@@ -79,6 +80,7 @@ class FidesConfig(FidesSettings):
79
80
  description="This is a special section that is used to store arbitrary key/value pairs to be used as credentials."
80
81
  )
81
82
  database: DatabaseSettings
83
+ privacy_request_duplicate_detection: DuplicateDetectionSettings
82
84
  execution: ExecutionSettings
83
85
  logging: LoggingSettings
84
86
  notifications: NotificationSettings
@@ -161,6 +163,7 @@ def build_config(config_dict: Dict[str, Any]) -> FidesConfig:
161
163
  "consent": ConsentSettings,
162
164
  "cli": CLISettings,
163
165
  "database": DatabaseSettings,
166
+ "privacy_request_duplicate_detection": DuplicateDetectionSettings,
164
167
  "execution": ExecutionSettings,
165
168
  "logging": LoggingSettings,
166
169
  "notifications": NotificationSettings,