ethyca-fides 2.66.2rc0__py2.py3-none-any.whl → 2.67.0__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 (335) hide show
  1. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/METADATA +1 -1
  2. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/RECORD +297 -282
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/7e9a2b52f498_adding_masking_secrets.py +60 -0
  5. fides/api/alembic/migrations/versions/a7065df4dcf1_add_finalized_fields_to_privacy_request.py +65 -0
  6. fides/api/alembic/migrations/versions/d0031087eacb_create_manualtaskconditionaldependency_.py +106 -0
  7. fides/api/api/v1/endpoints/dataset_config_endpoints.py +13 -5
  8. fides/api/api/v1/endpoints/drp_endpoints.py +7 -1
  9. fides/api/api/v1/endpoints/privacy_request_endpoints.py +44 -1
  10. fides/api/api/v1/endpoints/user_endpoints.py +83 -7
  11. fides/api/app_setup.py +3 -2
  12. fides/api/common_exceptions.py +8 -0
  13. fides/api/db/base.py +1 -0
  14. fides/api/db/database.py +1 -1
  15. fides/api/graph/execution.py +46 -0
  16. fides/api/graph/graph.py +13 -2
  17. fides/api/graph/traversal.py +126 -39
  18. fides/api/models/manual_task/__init__.py +2 -0
  19. fides/api/models/manual_task/conditional_dependency.py +144 -0
  20. fides/api/models/{manual_task.py → manual_task/manual_task.py} +10 -0
  21. fides/api/models/masking_secret.py +72 -0
  22. fides/api/models/policy.py +23 -0
  23. fides/api/models/privacy_request/execution_log.py +1 -0
  24. fides/api/models/privacy_request/privacy_request.py +64 -26
  25. fides/api/oauth/roles.py +2 -0
  26. fides/api/schemas/application_config.py +12 -1
  27. fides/api/schemas/connection_configuration/connection_secrets_datahub.py +10 -1
  28. fides/api/schemas/masking/masking_secrets.py +1 -1
  29. fides/api/schemas/policy.py +1 -0
  30. fides/api/schemas/privacy_request.py +5 -0
  31. fides/api/service/connectors/base_connector.py +15 -0
  32. fides/api/service/connectors/bigquery_connector.py +72 -19
  33. fides/api/service/connectors/dynamodb_connector.py +2 -1
  34. fides/api/service/connectors/fides_connector.py +1 -0
  35. fides/api/service/connectors/http_connector.py +1 -0
  36. fides/api/service/connectors/manual_task_connector.py +1 -0
  37. fides/api/service/connectors/manual_webhook_connector.py +2 -1
  38. fides/api/service/connectors/mongodb_connector.py +1 -0
  39. fides/api/service/connectors/okta_connector.py +1 -0
  40. fides/api/service/connectors/query_configs/bigquery_query_config.py +95 -36
  41. fides/api/service/connectors/query_configs/snowflake_query_config.py +3 -3
  42. fides/api/service/connectors/rds_mysql_connector.py +1 -0
  43. fides/api/service/connectors/rds_postgres_connector.py +1 -0
  44. fides/api/service/connectors/s3_connector.py +1 -0
  45. fides/api/service/connectors/saas_connector.py +1 -0
  46. fides/api/service/connectors/scylla_connector.py +1 -0
  47. fides/api/service/connectors/snowflake_connector.py +55 -2
  48. fides/api/service/connectors/sql_connector.py +159 -13
  49. fides/api/service/connectors/website_connector.py +1 -0
  50. fides/api/service/privacy_request/dsr_package/templates/welcome.html +2 -2
  51. fides/api/service/privacy_request/request_runner_service.py +145 -55
  52. fides/api/service/privacy_request/request_service.py +172 -52
  53. fides/api/task/conditional_dependencies/__init__.py +0 -0
  54. fides/api/task/conditional_dependencies/evaluator.py +109 -0
  55. fides/api/task/conditional_dependencies/schemas.py +54 -0
  56. fides/api/task/create_request_tasks.py +1 -1
  57. fides/api/task/deprecated_graph_task.py +24 -6
  58. fides/api/task/execute_request_tasks.py +93 -12
  59. fides/api/task/filter_results.py +1 -1
  60. fides/api/task/graph_task.py +86 -5
  61. fides/api/task/manual/manual_task_address.py +46 -0
  62. fides/api/task/manual/manual_task_graph_task.py +118 -126
  63. fides/api/task/manual/manual_task_utils.py +52 -105
  64. fides/api/util/aws_util.py +5 -1
  65. fides/api/util/cache.py +61 -0
  66. fides/api/util/encryption/secrets_util.py +48 -18
  67. fides/api/util/memory_watchdog.py +286 -0
  68. fides/common/api/scope_registry.py +3 -0
  69. fides/common/api/v1/urn_registry.py +1 -1
  70. fides/config/execution_settings.py +12 -0
  71. fides/config/utils.py +2 -0
  72. fides/service/privacy_request/privacy_request_service.py +6 -1
  73. fides/ui-build/static/admin/404.html +1 -1
  74. fides/ui-build/static/admin/_next/static/MNlh9olWjgbqAHKyQY3LF/_buildManifest.js +1 -0
  75. fides/ui-build/static/admin/_next/static/chunks/1316-2606e19807c08aa5.js +1 -0
  76. fides/ui-build/static/admin/_next/static/chunks/1467-8808ec8836e033f9.js +1 -0
  77. fides/ui-build/static/admin/_next/static/chunks/1817-b78b58ae3b75d75a.js +1 -0
  78. fides/ui-build/static/admin/_next/static/chunks/1975.7d4634a0e823a02b.js +1 -0
  79. fides/ui-build/static/admin/_next/static/chunks/{203-5a663f465ba26bb4.js → 203-cd78ea279cecba60.js} +1 -1
  80. fides/ui-build/static/admin/_next/static/chunks/2150-930ffaf2c4718edc.js +1 -0
  81. fides/ui-build/static/admin/_next/static/chunks/255-1bc0cbef7a59cdc6.js +1 -0
  82. fides/ui-build/static/admin/_next/static/chunks/{3450-0ba194991d0cca88.js → 3450-69f4e16978971bb8.js} +1 -1
  83. fides/ui-build/static/admin/_next/static/chunks/346-aa3b88efb85f2e28.js +1 -0
  84. fides/ui-build/static/admin/_next/static/chunks/3550-d04125c828d591a1.js +1 -0
  85. fides/ui-build/static/admin/_next/static/chunks/{3855-e172870d3e21b0dd.js → 3855-509ca7ac99b5eada.js} +1 -1
  86. fides/ui-build/static/admin/_next/static/chunks/{3872-46cebf7ec1b31a2b.js → 3872-0a0f0032ca39a93f.js} +1 -1
  87. fides/ui-build/static/admin/_next/static/chunks/409-ea70638a59296659.js +1 -0
  88. fides/ui-build/static/admin/_next/static/chunks/{4121-2bc09fc4ddbfe5cb.js → 4121-877e19d3fa078c7b.js} +1 -1
  89. fides/ui-build/static/admin/_next/static/chunks/{4230-60100f7ef3ddcde1.js → 4230-114e31621c19ea69.js} +1 -1
  90. fides/ui-build/static/admin/_next/static/chunks/4259.d1507e0db19cbed7.js +1 -0
  91. fides/ui-build/static/admin/_next/static/chunks/431-1db919f6569a4021.js +1 -0
  92. fides/ui-build/static/admin/_next/static/chunks/{4608-bbb7bf511a05c3c2.js → 4608-f16f281f2d05d963.js} +1 -1
  93. fides/ui-build/static/admin/_next/static/chunks/5163-e682273cd76a7d07.js +1 -0
  94. fides/ui-build/static/admin/_next/static/chunks/5309-d9a488457898263b.js +1 -0
  95. fides/ui-build/static/admin/_next/static/chunks/{905-ffdbd0b14167e8bd.js → 5596-4378b2927dae65b2.js} +3 -3
  96. fides/ui-build/static/admin/_next/static/chunks/5619-9b50cec521203989.js +1 -0
  97. fides/ui-build/static/admin/_next/static/chunks/{6084-7178ff6ea6822475.js → 6084-ddbad3149364725d.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/6148-59a59d5c5925344f.js +1 -0
  99. fides/ui-build/static/admin/_next/static/chunks/6419-d0c00d661b01f8fa.js +1 -0
  100. fides/ui-build/static/admin/_next/static/chunks/{6662-507be5d46e5b719b.js → 6662-a9e54ead3dc53644.js} +1 -1
  101. fides/ui-build/static/admin/_next/static/chunks/6780-b42a27e72707936d.js +1 -0
  102. fides/ui-build/static/admin/_next/static/chunks/{6853-2ad3e08fe6f9f5f2.js → 6853-d0190d2cca9dbde2.js} +1 -1
  103. fides/ui-build/static/admin/_next/static/chunks/{6882-6af16fef26c21e06.js → 6882-59ea739e3616ce83.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/6954-ba98e778a5b45ebf.js +1 -0
  105. fides/ui-build/static/admin/_next/static/chunks/{7476-281ee9a8286556f3.js → 7476-cc0d9a94ed7aad53.js} +1 -1
  106. fides/ui-build/static/admin/_next/static/chunks/7725-539d3a906f627531.js +1 -0
  107. fides/ui-build/static/admin/_next/static/chunks/{787-fb41002f797eb2df.js → 787-c57185ad89c4e288.js} +1 -1
  108. fides/ui-build/static/admin/_next/static/chunks/{79-7e87aff851423d4a.js → 79-2aab56be75e16187.js} +1 -1
  109. fides/ui-build/static/admin/_next/static/chunks/{796-329a5f823ec258a5.js → 796-3bdda2a7868464af.js} +1 -1
  110. fides/ui-build/static/admin/_next/static/chunks/8735-40caf91800a3610c.js +1 -0
  111. fides/ui-build/static/admin/_next/static/chunks/8765-f622a35b40a7ec63.js +1 -0
  112. fides/ui-build/static/admin/_next/static/chunks/9046-7085a401297c5520.js +1 -0
  113. fides/ui-build/static/admin/_next/static/chunks/9187-7438242f0d380bb0.js +1 -0
  114. fides/ui-build/static/admin/_next/static/chunks/{9226-746771d47dff6266.js → 9226-2dcac54ab3fb94be.js} +1 -1
  115. fides/ui-build/static/admin/_next/static/chunks/9278-08cc704317fe535e.js +1 -0
  116. fides/ui-build/static/admin/_next/static/chunks/{9951-9b753ad7c3f51bdf.js → 9951-7c6639e5d062779e.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-39ccb07327c2c5d5.js → _app-750d6bd16c971bb9.js} +56 -56
  118. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-98777246bec9dc2a.js → manual-2a655ff3a97f2492.js} +1 -1
  119. fides/ui-build/static/admin/_next/static/chunks/pages/{add-systems-a71c0aff4e0e6535.js → add-systems-0902f0bb4080643e.js} +1 -1
  120. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-1edf582ba3cd3bbb.js → [id]-f22ddd9b48a5c418.js} +1 -1
  121. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-06bb3b0bf097fcdb.js → new-e74cb5ea87f15b40.js} +1 -1
  122. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-685771e5f7196d87.js → privacy-experience-21f997c69fc3b4c2.js} +1 -1
  123. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-6ccedc70dc447089.js → [id]-da4124b7600a2a1d.js} +1 -1
  124. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-944bca1cc57985b5.js → new-a57d251c88ce68ae.js} +1 -1
  125. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-notices-84f4bd14ce8673bc.js → privacy-notices-ad105181bc91209b.js} +1 -1
  126. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-b0c4235fe6d0b0c8.js +1 -0
  127. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-11d52f1570759c4d.js → [resourceUrn]-aad6047a4604b945.js} +1 -1
  128. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{projects-32eac8bbd217615a.js → projects-29784a11fe0fbd0a.js} +1 -1
  129. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b83afa5565d0c84e.js → [resourceUrn]-b6b98cea25dd94fa.js} +1 -1
  130. fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-6f630d42ac9fb6b4.js → data-catalog-7770a8dc34bd0fc0.js} +1 -1
  131. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-3e5725cd06d7fe6c.js +1 -0
  132. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-92b0bd97d8e79340.js +1 -0
  133. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-ee3c0a103346fc06.js +1 -0
  134. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{activity-9aa744d56cdacb0d.js → activity-ad6a84a6276f914c.js} +1 -1
  135. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-14bd7500362ff224.js → [resourceUrn]-f98dd251babb7e28.js} +1 -1
  136. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-9e7dfd5a6acc2e8f.js → discovery-56eb4c014f0d96a3.js} +1 -1
  137. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-d23b3ae139f0428b.js +1 -0
  138. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-c0d2bfd465df20e0.js → [...subfieldNames]-15301bd6bf7cf718.js} +1 -1
  139. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-28280a8a39a6e37c.js → [collectionName]-0fa72873e464f581.js} +1 -1
  140. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{new-82fb246d87e58ebd.js → new-0d50084fbdf9b84c.js} +1 -1
  141. fides/ui-build/static/admin/_next/static/chunks/pages/{dataset-20165c31ab1bc7cf.js → dataset-f3348d0a92543bab.js} +1 -1
  142. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-b4a6bcc87d126840.js → [id]-7d6027570d05c57f.js} +1 -1
  143. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-f95d7b0bbfc58f5a.js → new-c6614583b14dc9f2.js} +1 -1
  144. fides/ui-build/static/admin/_next/static/chunks/pages/{fides-js-docs-5d8fd1af75f19e2f.js → fides-js-docs-1f4335dca5c09860.js} +1 -1
  145. fides/ui-build/static/admin/_next/static/chunks/pages/{index-1919aab9e5834b51.js → index-fbf9b845bb901238.js} +1 -1
  146. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-8e346fb36e8034d2.js +1 -0
  147. fides/ui-build/static/admin/_next/static/chunks/pages/{integrations-e2d5d7e2a5265e68.js → integrations-7f15cd8538cdc24d.js} +1 -1
  148. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-1bae386d8c190348.js +1 -0
  149. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{table-migration-69ad86b7a8a9a115.js → table-migration-05616e2ae20ff4f8.js} +1 -1
  150. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-79f1576b1126975c.js +1 -0
  151. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-f1d818242d8550f8.js +1 -0
  152. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-d40a26bddb126c5c.js +1 -0
  153. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-96a08c4431b5462c.js +1 -0
  154. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-9d1840f8309b706e.js +1 -0
  155. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/{[purpose_id]-fc201657f4a782c7.js → [purpose_id]-e891d01ece59669e.js} +1 -1
  156. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{consent-c2d39cba8396ef3a.js → consent-f61b87e79367865b.js} +1 -1
  157. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{custom-fields-d992103cc55901ae.js → custom-fields-f8eea5d508c60c64.js} +1 -1
  158. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-023e1895552817de.js → locations-ed6a140b362c5baa.js} +1 -1
  159. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{organization-ac403c0886b20e20.js → organization-ff9a34264d48c35f.js} +1 -1
  160. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/{test-datasets-7a3396ac819c7904.js → test-datasets-a4b6d41ca679298b.js} +1 -1
  161. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-8314a819837f5b2a.js → [id]-c8f5fbaa83dd9945.js} +1 -1
  162. fides/ui-build/static/admin/_next/static/chunks/pages/{systems-21f423a7c417aa9d.js → systems-c05b49ddec1a1b4f.js} +1 -1
  163. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-df0d88716578e295.js +1 -0
  164. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-da68efc31998dc66.js +1 -0
  165. fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-173ac3a1ed2b05a6.js → user-management-e98dfc7d4f2a4e16.js} +1 -1
  166. fides/ui-build/static/admin/_next/static/chunks/webpack-90e8ec1fc5c6455b.js +1 -0
  167. fides/ui-build/static/admin/_next/static/css/{5bfb2473e5701527.css → 23cf870196941c9a.css} +1 -1
  168. fides/ui-build/static/admin/_next/static/css/{94965f224bc991e9.css → 8bc1833f1fa53ff0.css} +1 -1
  169. fides/ui-build/static/admin/_next/static/css/d9924caa849931b3.css +1 -0
  170. fides/ui-build/static/admin/_next/static/css/dbcf63488933a4d5.css +29 -0
  171. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  172. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  173. fides/ui-build/static/admin/add-systems.html +1 -1
  174. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  175. fides/ui-build/static/admin/consent/configure.html +1 -1
  176. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  177. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  178. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  179. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  180. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  181. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  182. fides/ui-build/static/admin/consent/properties.html +1 -1
  183. fides/ui-build/static/admin/consent/reporting.html +1 -1
  184. fides/ui-build/static/admin/consent.html +1 -1
  185. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  186. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  187. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  188. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  189. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  190. fides/ui-build/static/admin/data-catalog.html +1 -1
  191. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  192. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  193. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  194. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  195. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  196. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  197. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  198. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  199. fides/ui-build/static/admin/datamap.html +1 -1
  200. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  201. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  202. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  203. fides/ui-build/static/admin/dataset/new.html +1 -1
  204. fides/ui-build/static/admin/dataset.html +1 -1
  205. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  206. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  207. fides/ui-build/static/admin/datastore-connection.html +1 -1
  208. fides/ui-build/static/admin/index.html +1 -1
  209. fides/ui-build/static/admin/integrations/[id].html +1 -1
  210. fides/ui-build/static/admin/integrations.html +1 -1
  211. fides/ui-build/static/admin/lib/fides-ext-gpp.js +1 -1
  212. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  213. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  214. fides/ui-build/static/admin/lib/fides-tcf.js +4 -4
  215. fides/ui-build/static/admin/lib/fides.js +4 -4
  216. fides/ui-build/static/admin/login/[provider].html +1 -1
  217. fides/ui-build/static/admin/login.html +1 -1
  218. fides/ui-build/static/admin/messaging/[id].html +1 -1
  219. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  220. fides/ui-build/static/admin/messaging.html +1 -1
  221. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  222. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  223. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  224. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  225. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  226. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  227. fides/ui-build/static/admin/poc/forms.html +1 -1
  228. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  229. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  230. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  231. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  232. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  233. fides/ui-build/static/admin/privacy-requests.html +1 -1
  234. fides/ui-build/static/admin/properties/[id].html +1 -1
  235. fides/ui-build/static/admin/properties/add-property.html +1 -1
  236. fides/ui-build/static/admin/properties.html +1 -1
  237. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  238. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  239. fides/ui-build/static/admin/settings/about.html +1 -1
  240. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  241. fides/ui-build/static/admin/settings/consent.html +1 -1
  242. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  243. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  244. fides/ui-build/static/admin/settings/domains.html +1 -1
  245. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  246. fides/ui-build/static/admin/settings/locations.html +1 -1
  247. fides/ui-build/static/admin/settings/organization.html +1 -1
  248. fides/ui-build/static/admin/settings/regulations.html +1 -1
  249. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  250. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  251. fides/ui-build/static/admin/systems.html +1 -1
  252. fides/ui-build/static/admin/taxonomy.html +1 -1
  253. fides/ui-build/static/admin/user-management/new.html +1 -1
  254. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  255. fides/ui-build/static/admin/user-management.html +1 -1
  256. fides/ui-build/static/admin/_next/static/8108ANFxs99VY7KZ_Xev2/_buildManifest.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/1316-6cc72a45ebf7ff81.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/1807-3beab149351d5ded.js +0 -1
  259. fides/ui-build/static/admin/_next/static/chunks/1817-e601e737e3cc7a0e.js +0 -1
  260. fides/ui-build/static/admin/_next/static/chunks/255-7db55b0e3a0f9dea.js +0 -1
  261. fides/ui-build/static/admin/_next/static/chunks/2599-6c4d22e75028d8b6.js +0 -1
  262. fides/ui-build/static/admin/_next/static/chunks/2858-0b44609b6be7850b.js +0 -1
  263. fides/ui-build/static/admin/_next/static/chunks/2866-a73888c17a195cbe.js +0 -1
  264. fides/ui-build/static/admin/_next/static/chunks/3615-5e2d062d684b8fa1.js +0 -1
  265. fides/ui-build/static/admin/_next/static/chunks/409-a257e14acebcd73b.js +0 -1
  266. fides/ui-build/static/admin/_next/static/chunks/431-34f0b91c26f8d9ab.js +0 -1
  267. fides/ui-build/static/admin/_next/static/chunks/5309-b2c4803370634ff8.js +0 -1
  268. fides/ui-build/static/admin/_next/static/chunks/570-c99f07161bd339cd.js +0 -1
  269. fides/ui-build/static/admin/_next/static/chunks/6780-e3d40aa17a4bf2e9.js +0 -1
  270. fides/ui-build/static/admin/_next/static/chunks/6954-bb875d9ac89f6030.js +0 -1
  271. fides/ui-build/static/admin/_next/static/chunks/7062.fda15dcb7df85675.js +0 -1
  272. fides/ui-build/static/admin/_next/static/chunks/7c79804f.7a7112aece470725.js +0 -1
  273. fides/ui-build/static/admin/_next/static/chunks/9014-eeae6f581158e645.js +0 -1
  274. fides/ui-build/static/admin/_next/static/chunks/9046-5c4c22c375de25b1.js +0 -1
  275. fides/ui-build/static/admin/_next/static/chunks/9278-9b1b5970f0702668.js +0 -1
  276. fides/ui-build/static/admin/_next/static/chunks/9392.f4520f66206d347d.js +0 -1
  277. fides/ui-build/static/admin/_next/static/chunks/ea076c0a.84423f606aef37cd.js +0 -1
  278. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-afdbd4665657cfa1.js +0 -1
  279. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-2265ecb899d45fbc.js +0 -1
  280. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-5d522637871ac6c8.js +0 -1
  281. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-9ddb52ebb7ac4c71.js +0 -1
  282. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-7674b97d655c193b.js +0 -1
  283. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-0a58aee2d1e7fa01.js +0 -1
  284. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-5094ffea13f32ed9.js +0 -1
  285. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-32600543eb7b584f.js +0 -1
  286. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-10ce53ea356f8bad.js +0 -1
  287. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-5501bbb129fee9c4.js +0 -1
  288. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-cbe4c8f9096b6543.js +0 -1
  289. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/datamap-e130c0197362e8f3.js +0 -1
  290. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-6387fcc8cce872eb.js +0 -1
  291. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/[id]-ff5738706da07801.js +0 -1
  292. fides/ui-build/static/admin/_next/static/chunks/webpack-ff0cd6bff75588da.js +0 -1
  293. fides/ui-build/static/admin/_next/static/css/2cadb5f62dcd7c2b.css +0 -1
  294. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/WHEEL +0 -0
  295. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/entry_points.txt +0 -0
  296. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/licenses/LICENSE +0 -0
  297. {ethyca_fides-2.66.2rc0.dist-info → ethyca_fides-2.67.0.dist-info}/top_level.txt +0 -0
  298. /fides/ui-build/static/admin/_next/static/{8108ANFxs99VY7KZ_Xev2 → MNlh9olWjgbqAHKyQY3LF}/_ssgManifest.js +0 -0
  299. /fides/ui-build/static/admin/_next/static/chunks/{2921-455e6357b74d2f76.js → 2921-86f1547ac40a5cdf.js} +0 -0
  300. /fides/ui-build/static/admin/_next/static/chunks/{3923-6cc911dafccc5f63.js → 3923-13a6b4da2d51bf8f.js} +0 -0
  301. /fides/ui-build/static/admin/_next/static/chunks/{401-1b529d5800aa1f3a.js → 401-3cc1fee61494e3bd.js} +0 -0
  302. /fides/ui-build/static/admin/_next/static/chunks/{5574-b13021775a15bfd2.js → 5574-9312f97b637d9ee2.js} +0 -0
  303. /fides/ui-build/static/admin/_next/static/chunks/{7630-9aac73191ed5ed13.js → 7630-b1c93688013ef013.js} +0 -0
  304. /fides/ui-build/static/admin/_next/static/chunks/{9826-111aaee8bd8dbd09.js → 9826-3c578665c6d3b21d.js} +0 -0
  305. /fides/ui-build/static/admin/_next/static/chunks/pages/{404-aece2c920ea14514.js → 404-2d803dab6a00f353.js} +0 -0
  306. /fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-dc75dc6e37e52f05.js → multiple-8ff7f37913ad736a.js} +0 -0
  307. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-24d226b5a8de5c74.js → add-vendors-d00c9034cdeb0236.js} +0 -0
  308. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{configure-6a8ef51138ac926a.js → configure-0e1ca0f4c8e7f4da.js} +0 -0
  309. /fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-6f86ab63a08a6528.js → properties-057cad65e7414a44.js} +0 -0
  310. /fides/ui-build/static/admin/_next/static/chunks/pages/{consent-73d3cbf68f7c3a31.js → consent-e17c56eec8d91371.js} +0 -0
  311. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-6ba9e160dae64695.js → [projectUrn]-80a6cc8e8573514a.js} +0 -0
  312. /fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/{resources-7648bbd4f6711e4d.js → resources-6c3714ee97a718c1.js} +0 -0
  313. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-393e20924c83373e.js → [resourceUrn]-31e6c54794a9883e.js} +0 -0
  314. /fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-8733807dad4bc96e.js → detection-2822a423a7ad0550.js} +0 -0
  315. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/{[datasetId]-006b695e5af5ef24.js → [datasetId]-a8e8b5f4ee7af86c.js} +0 -0
  316. /fides/ui-build/static/admin/_next/static/chunks/pages/{datastore-connection-c391c6fad56eec48.js → datastore-connection-3bd77864da523d41.js} +0 -0
  317. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-53fecfb9dd6a1e0c.js → [id]-5627d0d0668077f9.js} +0 -0
  318. /fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-76b01cec5fde10a9.js → add-template-feca66ad5c5fe54a.js} +0 -0
  319. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{ant-components-5c08e8447c45ce44.js → ant-components-64a322d01aae5ca7.js} +0 -0
  320. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-06ad5f34585480aa.js → AntForm-8bca16a7726e7eb2.js} +0 -0
  321. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-6f071c2bc9446cb0.js → FormikAntFormItem-b0f246fc3b67ebf7.js} +0 -0
  322. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-efcc38c58991ac9e.js → FormikControlled-1a0852b090bfc392.js} +0 -0
  323. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-430ba5c979abfb7c.js → FormikField-11f3de1b45e36583.js} +0 -0
  324. /fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-5c561880bf131afb.js → forms-1b73a1c2b6c6285f.js} +0 -0
  325. /fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/{configure-d888a69a3bbe040e.js → configure-e551a860ec727802.js} +0 -0
  326. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-d3d8e3d7583ec635.js → [id]-dd99183f93763ae4.js} +0 -0
  327. /fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-1af10ed303815d46.js → add-property-0bdbc1fcbf553b8f.js} +0 -0
  328. /fides/ui-build/static/admin/_next/static/chunks/pages/{properties-cebc0dc186be499a.js → properties-e959378bb32b6b73.js} +0 -0
  329. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/{alpha-5e1322de868d615e.js → alpha-1066f0c202ef744c.js} +0 -0
  330. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{about-241f95e372b65d0f.js → about-37ba24a72a06862e.js} +0 -0
  331. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-41242f805599feda.js → domain-records-51333dbd21cb37c8.js} +0 -0
  332. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domains-2e885f74c92f669c.js → domains-bde86e5f6c09da5a.js} +0 -0
  333. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{email-templates-ff112655ad5f41e5.js → email-templates-4f9a5cc8bea7725b.js} +0 -0
  334. /fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-86062a18e081a52a.js → regulations-102efd9199e87124.js} +0 -0
  335. /fides/ui-build/static/admin/_next/static/chunks/pages/user-management/{new-a2524414e968f862.js → new-de8cb3739ab99c09.js} +0 -0
@@ -0,0 +1,54 @@
1
+ from enum import Enum
2
+ from typing import List, Optional, Union
3
+
4
+ from pydantic import BaseModel, Field, model_validator
5
+
6
+
7
+ class Operator(str, Enum):
8
+ eq = "eq"
9
+ neq = "neq"
10
+ lt = "lt"
11
+ lte = "lte"
12
+ gt = "gt"
13
+ gte = "gte"
14
+ exists = "exists"
15
+ not_exists = "not_exists"
16
+ list_contains = "list_contains"
17
+ not_in_list = "not_in_list"
18
+
19
+
20
+ class GroupOperator(str, Enum):
21
+ and_ = "and"
22
+ or_ = "or"
23
+
24
+
25
+ # Leaf condition (e.g., "user.name exists", "user.created_at >= 2024-01-01")
26
+ class ConditionLeaf(BaseModel):
27
+ field_address: str = Field(
28
+ description="Field path to check (e.g., 'user.name', 'billing.subscription.status')"
29
+ )
30
+ operator: Operator = Field(description="Operator to apply")
31
+ value: Optional[
32
+ Union[str, int, float, bool, List[Union[str, int, float, bool]]]
33
+ ] = Field(default=None, description="Expected value for comparison")
34
+
35
+
36
+ # Nested logical condition (AND, OR)
37
+ class ConditionGroup(BaseModel):
38
+ logical_operator: GroupOperator = Field(
39
+ description="Logical operator: 'and' or 'or'"
40
+ )
41
+ conditions: list["Condition"] = Field(
42
+ description="List of conditions or nested groups"
43
+ )
44
+
45
+ @model_validator(mode="after")
46
+ def validate_conditions(self) -> "ConditionGroup":
47
+ if not self.conditions:
48
+ raise ValueError("conditions list cannot be empty")
49
+ return self
50
+
51
+
52
+ # Use model_rebuild to allow recursive nesting
53
+ Condition = Union[ConditionLeaf, ConditionGroup]
54
+ ConditionGroup.model_rebuild()
@@ -33,8 +33,8 @@ from fides.api.models.worker_task import ExecutionLogStatus
33
33
  from fides.api.schemas.policy import ActionType
34
34
  from fides.api.task.deprecated_graph_task import format_data_use_map_for_caching
35
35
  from fides.api.task.execute_request_tasks import log_task_queued, queue_request_task
36
+ from fides.api.task.manual.manual_task_address import ManualTaskAddress
36
37
  from fides.api.task.manual.manual_task_utils import (
37
- ManualTaskAddress,
38
38
  create_manual_task_instances_for_privacy_request,
39
39
  )
40
40
  from fides.api.util.logger_context_utils import log_context
@@ -1,4 +1,5 @@
1
1
  # pylint: disable=too-many-lines
2
+ from functools import partial
2
3
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
3
4
 
4
5
  import dask
@@ -252,16 +253,33 @@ def run_erasure_request_deprecated( # pylint: disable = too-many-arguments
252
253
 
253
254
  access_request_data[ROOT_COLLECTION_ADDRESS.value] = [identity]
254
255
 
255
- dsk: Dict[CollectionAddress, Any] = {
256
- k: (
257
- t.erasure_request,
256
+ # Build the dask task graph for erasure, ensuring we also pass along the
257
+ # upstream access data that may be required by the connector (e.g. BigQuery
258
+ # delete statements). We accomplish this by partially applying the
259
+ # `inputs` kwarg on each task's `erasure_request` method. The resulting
260
+ # callable accepts the original positional arguments expected by Dask.
261
+
262
+ dsk: Dict[CollectionAddress, Any] = {}
263
+ for k, t in env.items():
264
+ # Collect upstream access data in the same order as the input keys
265
+ upstream_access_data: List[List[Row]] = [
266
+ access_request_data.get(str(input_key), [])
267
+ for input_key in t.execution_node.input_keys
268
+ ]
269
+
270
+ # Bind the `inputs` keyword argument so it is supplied when the task executes
271
+ erasure_fn_with_inputs = partial(
272
+ t.erasure_request, inputs=upstream_access_data
273
+ )
274
+
275
+ # Build the task tuple: (callable, retrieved_data, *prereqs)
276
+ dsk[k] = (
277
+ erasure_fn_with_inputs,
258
278
  access_request_data.get(
259
279
  str(k), []
260
- ), # Pass in the results of the access request for this collection
280
+ ), # Data retrieved for this collection
261
281
  *_evaluate_erasure_dependencies(t, erasure_end_nodes),
262
282
  )
263
- for k, t in env.items()
264
- }
265
283
 
266
284
  # root node returns 0 to be consistent with the output of the other erasure tasks
267
285
  dsk[ROOT_COLLECTION_ADDRESS] = 0
@@ -29,13 +29,14 @@ from fides.api.task.graph_task import (
29
29
  GraphTask,
30
30
  mark_current_and_downstream_nodes_as_failed,
31
31
  )
32
+ from fides.api.task.manual.manual_task_address import ManualTaskAddress
32
33
  from fides.api.task.manual.manual_task_graph_task import ManualTaskGraphTask
33
- from fides.api.task.manual.manual_task_utils import ManualTaskAddress
34
34
  from fides.api.task.task_resources import TaskResources
35
35
  from fides.api.tasks import DSR_QUEUE_NAME, DatabaseTask, celery_app
36
36
  from fides.api.util.cache import cache_task_tracking_key
37
37
  from fides.api.util.collection_util import Row
38
38
  from fides.api.util.logger_context_utils import LoggerContextKeys, log_context
39
+ from fides.api.util.memory_watchdog import memory_limiter
39
40
 
40
41
  # DSR 3.0 task functions
41
42
 
@@ -255,6 +256,7 @@ def queue_downstream_tasks(
255
256
 
256
257
 
257
258
  @celery_app.task(base=DatabaseTask, bind=True)
259
+ @memory_limiter
258
260
  @log_context(
259
261
  capture_args={
260
262
  "privacy_request_id": LoggerContextKeys.privacy_request_id,
@@ -298,17 +300,11 @@ def run_access_node(
298
300
  )
299
301
  # Currently, upstream tasks and "input keys" (which are built by data dependencies)
300
302
  # are the same, but they may not be the same in the future.
301
- ordered_upstream_tasks: List[Optional[RequestTask]] = (
302
- _order_tasks_by_input_key(
303
+ upstream_access_data: List[List[Row]] = (
304
+ _build_upstream_access_data(
303
305
  graph_task.execution_node.input_keys, upstream_results
304
306
  )
305
307
  )
306
- # Pass in access data dependencies in the same order as the input keys.
307
- # If we don't have access data for an upstream node, pass in an empty list
308
- upstream_access_data: List[List[Row]] = [
309
- upstream.get_access_data() if upstream else []
310
- for upstream in ordered_upstream_tasks
311
- ]
312
308
  # Run the main access function
313
309
  graph_task.access_request(*upstream_access_data)
314
310
 
@@ -325,6 +321,7 @@ def run_access_node(
325
321
 
326
322
 
327
323
  @celery_app.task(base=DatabaseTask, bind=True)
324
+ @memory_limiter
328
325
  @log_context(
329
326
  capture_args={
330
327
  "privacy_request_id": LoggerContextKeys.privacy_request_id,
@@ -359,7 +356,7 @@ def run_erasure_node(
359
356
  session,
360
357
  ) as resources:
361
358
  # Build GraphTask resource to facilitate execution
362
- graph_task: GraphTask = create_graph_task(
359
+ erasure_graph_task: GraphTask = create_graph_task(
363
360
  session, request_task, resources
364
361
  )
365
362
  # Get access data that was saved in the erasure format that was collected from the
@@ -368,8 +365,24 @@ def run_erasure_node(
368
365
  request_task.get_data_for_erasures() or []
369
366
  )
370
367
 
371
- # Run the main erasure function!
372
- graph_task.erasure_request(retrieved_data)
368
+ upstream_access_data: List[List[Row]] = []
369
+
370
+ try:
371
+ upstream_access_data = (
372
+ get_upstream_access_data_for_erasure_task(
373
+ request_task, session, resources
374
+ )
375
+ )
376
+ except Exception as e:
377
+ logger.error(
378
+ f"Unable to get upstream access data for erasure task {request_task.collection_address}: {e}"
379
+ )
380
+
381
+ # Run the main erasure function, passing along the upstream access data.
382
+ # The extra data is currently only needed for generating BigQuery delete statements.
383
+ erasure_graph_task.erasure_request(
384
+ retrieved_data, inputs=upstream_access_data
385
+ )
373
386
 
374
387
  queue_downstream_tasks_with_retries(
375
388
  self,
@@ -381,6 +394,7 @@ def run_erasure_node(
381
394
 
382
395
 
383
396
  @celery_app.task(base=DatabaseTask, bind=True)
397
+ @memory_limiter
384
398
  @log_context(
385
399
  capture_args={
386
400
  "privacy_request_id": LoggerContextKeys.privacy_request_id,
@@ -487,6 +501,73 @@ def _order_tasks_by_input_key(
487
501
  return tasks
488
502
 
489
503
 
504
+ def get_upstream_access_data_for_erasure_task(
505
+ erasure_request_task: RequestTask,
506
+ session: Session,
507
+ resources: TaskResources,
508
+ ) -> List[List[Row]]:
509
+ """
510
+ Retrieves upstream access data for a given erasure request task.
511
+
512
+ This function finds the corresponding access task for the erasure task,
513
+ creates a GraphTask to extract input keys, and builds the upstream access data
514
+ needed for erasure operations (particularly for BigQuery delete statements).
515
+
516
+ Args:
517
+ erasure_request_task: The erasure task that needs upstream access data
518
+ session: Database session for querying
519
+ resources: Task resources for creating GraphTask
520
+
521
+ Returns:
522
+ List[List[Row]]: Upstream access data ordered by input keys
523
+
524
+ Raises:
525
+ Exception: If the corresponding access task cannot be found
526
+ """
527
+ # Get the corresponding access task for the current erasure task
528
+ access_request_task = (
529
+ session.query(RequestTask)
530
+ .filter(
531
+ RequestTask.privacy_request_id == erasure_request_task.privacy_request_id,
532
+ RequestTask.collection_address == erasure_request_task.collection_address,
533
+ RequestTask.action_type == ActionType.access,
534
+ )
535
+ .first()
536
+ )
537
+
538
+ if not access_request_task:
539
+ raise Exception(
540
+ f"Unable to find access request task for erasure task {erasure_request_task.collection_address}"
541
+ )
542
+
543
+ # Convert the request task to a GraphTask to get the input_keys
544
+ access_graph_task: GraphTask = create_graph_task(
545
+ session, access_request_task, resources
546
+ )
547
+
548
+ # Build and return the upstream access data
549
+ return _build_upstream_access_data(
550
+ access_graph_task.execution_node.input_keys,
551
+ access_request_task.upstream_tasks_objects(session),
552
+ )
553
+
554
+
555
+ def _build_upstream_access_data(
556
+ input_keys: List[CollectionAddress],
557
+ upstream_tasks: Query,
558
+ ) -> List[List[Row]]:
559
+ """
560
+ Helper function to build the access data for the current node.
561
+ The access data is passed in the same order as the input keys.
562
+ If we don't have access data for an upstream node, return an empty list.
563
+ """
564
+
565
+ ordered_upstream: List[Optional[RequestTask]] = _order_tasks_by_input_key(
566
+ input_keys, upstream_tasks
567
+ )
568
+ return [task.get_access_data() if task else [] for task in ordered_upstream]
569
+
570
+
490
571
  mapping = {
491
572
  ActionType.access.value: run_access_node,
492
573
  ActionType.erasure.value: run_erasure_node,
@@ -6,7 +6,7 @@ from loguru import logger
6
6
 
7
7
  from fides.api.graph.config import CollectionAddress, FieldPath
8
8
  from fides.api.graph.graph import DatasetGraph
9
- from fides.api.task.manual.manual_task_utils import ManualTaskAddress
9
+ from fides.api.task.manual.manual_task_address import ManualTaskAddress
10
10
  from fides.api.util.collection_util import Row
11
11
 
12
12
 
@@ -18,6 +18,7 @@ from fides.api.common_exceptions import (
18
18
  NotSupportedForCollection,
19
19
  PrivacyRequestErasureEmailSendRequired,
20
20
  SkippingConsentPropagation,
21
+ TableNotFound,
21
22
  )
22
23
  from fides.api.graph.config import (
23
24
  ROOT_COLLECTION_ADDRESS,
@@ -61,6 +62,7 @@ from fides.api.util.consent_util import (
61
62
  )
62
63
  from fides.api.util.logger import Pii
63
64
  from fides.api.util.logger_context_utils import LoggerContextKeys
65
+ from fides.api.util.memory_watchdog import MemoryLimitExceeded
64
66
  from fides.api.util.saas_util import FIDESOPS_GROUPED_INPUTS
65
67
  from fides.config import CONFIG
66
68
 
@@ -70,6 +72,16 @@ EMPTY_REQUEST = PrivacyRequest()
70
72
  EMPTY_REQUEST_TASK = RequestTask()
71
73
 
72
74
 
75
+ def _is_memory_limit_exceeded(exception: BaseException) -> bool:
76
+ """Check if the exception or any exception in its chain is a MemoryLimitExceeded."""
77
+ current_exception: Optional[BaseException] = exception
78
+ while current_exception:
79
+ if isinstance(current_exception, MemoryLimitExceeded):
80
+ return True
81
+ current_exception = current_exception.__cause__ or current_exception.__context__
82
+ return False
83
+
84
+
73
85
  def retry(
74
86
  action_type: ActionType,
75
87
  default_return: Any,
@@ -126,6 +138,7 @@ def retry(
126
138
  CollectionDisabled,
127
139
  ActionDisabled,
128
140
  NotSupportedForCollection,
141
+ TableNotFound,
129
142
  ) as exc:
130
143
  logger.warning(
131
144
  "{} - Skipping collection {} for privacy_request: {}",
@@ -144,7 +157,31 @@ def retry(
144
157
  self.log_skipped(action_type, exc)
145
158
  self.cache_system_status_for_preferences()
146
159
  return default_return
160
+ except MemoryLimitExceeded as ex:
161
+ # Hard failure – mark task & downstream as errored and abort.
162
+ logger.error(
163
+ "Memory watchdog exceeded ({}%). Aborting {} {} without retry.",
164
+ ex.memory_percent,
165
+ method_name,
166
+ self.execution_node.address,
167
+ )
168
+ # Persist error status and create execution logs before raising
169
+ self.log_end(action_type, ex)
170
+ self.add_error_status_for_consent_reporting()
171
+ raise
147
172
  except BaseException as ex: # pylint: disable=W0703
173
+ # Check if this exception was caused by memory limit exceeded
174
+ if _is_memory_limit_exceeded(ex):
175
+ logger.error(
176
+ "Memory watchdog exceeded (wrapped exception). Aborting {} {} without retry.",
177
+ method_name,
178
+ self.execution_node.address,
179
+ )
180
+ # Persist error status and create execution logs before raising
181
+ self.log_end(action_type, ex)
182
+ self.add_error_status_for_consent_reporting()
183
+ raise
184
+
148
185
  traceback.print_exc()
149
186
  func_delay *= CONFIG.execution.task_retry_backoff
150
187
  logger.warning(
@@ -421,6 +458,7 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
421
458
  action_type: ActionType,
422
459
  ex: Optional[BaseException] = None,
423
460
  success_override_msg: Optional[str] = None,
461
+ record_count: Optional[int] = None,
424
462
  ) -> None:
425
463
  """On completion activities"""
426
464
  if ex:
@@ -440,8 +478,23 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
440
478
  mark_current_and_downstream_nodes_as_failed(request_task, db)
441
479
  else:
442
480
  logger.info("Ending {}, {}", self.resources.request.id, self.key)
481
+
482
+ # Build standardized success message with record count
483
+ base_message = (
484
+ str(success_override_msg) if success_override_msg else "success"
485
+ )
486
+ if record_count is not None:
487
+ if action_type == ActionType.access:
488
+ message = f"{base_message} - retrieved {record_count} records"
489
+ elif action_type == ActionType.erasure:
490
+ message = f"{base_message} - masked {record_count} records"
491
+ else:
492
+ message = f"{base_message} - processed {record_count} records"
493
+ else:
494
+ message = base_message
495
+
443
496
  self.update_status(
444
- str(success_override_msg) if success_override_msg else "success",
497
+ message,
445
498
  build_affected_field_logs(
446
499
  self.execution_node, self.resources.policy, action_type
447
500
  ),
@@ -537,12 +590,21 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
537
590
  # For access request results, mutate rows in-place to remove non-matching
538
591
  # array elements. We already iterated over `output` above, so reuse the same
539
592
  # loop structure to keep cache locality.
593
+ logger.info(
594
+ "Filtering {} rows in {} for matching array elements.",
595
+ len(output),
596
+ self.execution_node.address,
597
+ )
540
598
  for row in output:
599
+ filter_element_match(row, post_processed_node_input_data)
600
+
601
+ if len(output) > 0:
541
602
  logger.info(
542
- "Filtering row in {} for matching array elements.",
603
+ "Filtering completed for {} rows in {}. Post-processed node size: {}",
604
+ len(output),
543
605
  self.execution_node.address,
606
+ len(post_processed_node_input_data),
544
607
  )
545
- filter_element_match(row, post_processed_node_input_data)
546
608
 
547
609
  if self.request_task.id:
548
610
  # Saves intermediate access results for DSR 3.0 directly on the Request Task
@@ -637,7 +699,11 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
637
699
  if messages:
638
700
  success_message = "\n".join(messages)
639
701
 
640
- self.log_end(ActionType.access, success_override_msg=success_message)
702
+ self.log_end(
703
+ ActionType.access,
704
+ success_override_msg=success_message,
705
+ record_count=len(filtered_output),
706
+ )
641
707
  return filtered_output
642
708
 
643
709
  @retry(action_type=ActionType.erasure, default_return=0)
@@ -645,9 +711,15 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
645
711
  self,
646
712
  retrieved_data: List[Row],
647
713
  *erasure_prereqs: int, # TODO Remove when we stop support for DSR 2.0. DSR 3.0 enforces with downstream_tasks.
714
+ inputs: Optional[
715
+ List[List[Row]]
716
+ ] = None, # Upstream data from corresponding access task
648
717
  ) -> int:
649
718
  """Run erasure request"""
650
719
 
720
+ if inputs is None:
721
+ inputs = []
722
+
651
723
  # if there is no primary key specified in the graph node configuration
652
724
  # note this in the execution log and perform no erasures on this node
653
725
  if (
@@ -694,6 +766,10 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
694
766
  )
695
767
  return 0
696
768
 
769
+ formatted_input_data: NodeInput = self.pre_process_input_data(
770
+ *inputs, group_dependent_fields=True
771
+ )
772
+
697
773
  # Use execution context to capture postprocessor messages
698
774
  with collect_execution_log_messages() as messages:
699
775
  output = self.connector.mask_data(
@@ -702,6 +778,7 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
702
778
  self.resources.request,
703
779
  self.resources.privacy_request_task,
704
780
  retrieved_data,
781
+ formatted_input_data,
705
782
  )
706
783
 
707
784
  if self.request_task.id:
@@ -720,7 +797,11 @@ class GraphTask(ABC): # pylint: disable=too-many-instance-attributes
720
797
  if messages:
721
798
  success_message = "\n".join(messages)
722
799
 
723
- self.log_end(ActionType.erasure, success_override_msg=success_message)
800
+ self.log_end(
801
+ ActionType.erasure,
802
+ success_override_msg=success_message,
803
+ record_count=output,
804
+ )
724
805
  return output
725
806
 
726
807
  @retry(action_type=ActionType.consent, default_return=False)
@@ -0,0 +1,46 @@
1
+ from fides.api.graph.config import CollectionAddress
2
+
3
+
4
+ class ManualTaskAddress:
5
+ """Utility class for creating and parsing manual task addresses"""
6
+
7
+ MANUAL_DATA_COLLECTION = "manual_data"
8
+
9
+ @staticmethod
10
+ def create(connection_config_key: str) -> CollectionAddress:
11
+ """Create a CollectionAddress for manual data: {connection_key}:manual_data"""
12
+ return CollectionAddress(
13
+ dataset=connection_config_key,
14
+ collection=ManualTaskAddress.MANUAL_DATA_COLLECTION,
15
+ )
16
+
17
+ @staticmethod
18
+ def _is_manual_data_collection(collection_name: str) -> bool:
19
+ """Check if collection name represents manual task data"""
20
+ return collection_name == ManualTaskAddress.MANUAL_DATA_COLLECTION
21
+
22
+ @staticmethod
23
+ def is_manual_task_address(address: CollectionAddress) -> bool:
24
+ """Check if address represents manual task data"""
25
+ if isinstance(address, str):
26
+ # Handle string format "connection_key:collection_name"
27
+ _, _, collection_part = address.partition(":")
28
+ if not collection_part:
29
+ return False
30
+ return ManualTaskAddress._is_manual_data_collection(collection_part)
31
+
32
+ # Handle CollectionAddress object
33
+ return ManualTaskAddress._is_manual_data_collection(address.collection)
34
+
35
+ @staticmethod
36
+ def get_connection_key(address: CollectionAddress) -> str:
37
+ """Extract connection config key from manual task address"""
38
+ if not ManualTaskAddress.is_manual_task_address(address):
39
+ raise ValueError(f"Not a manual task address: {address}")
40
+
41
+ if isinstance(address, str):
42
+ # Handle string format "connection_key:collection_name"
43
+ return address.split(":")[0]
44
+
45
+ # Handle CollectionAddress object
46
+ return address.dataset