ethyca-fides 2.71.0rc4__py2.py3-none-any.whl → 2.71.1b1__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 (182) hide show
  1. {ethyca_fides-2.71.0rc4.dist-info → ethyca_fides-2.71.1b1.dist-info}/METADATA +2 -2
  2. {ethyca_fides-2.71.0rc4.dist-info → ethyca_fides-2.71.1b1.dist-info}/RECORD +158 -154
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/3efe14d4469a_adds_new_experience_configs_for_vendor_.py +79 -0
  5. fides/api/alembic/migrations/versions/918aefc950c9_create_digest_conditional_dependencies.py +125 -0
  6. fides/api/alembic/migrations/versions/9caf76161e55_make_user_assigned_data_uses_nullable_.py +64 -0
  7. fides/api/alembic/migrations/versions/f108fa05c579_adds_optional_duration_field_to_assets.py +28 -0
  8. fides/api/api/v1/endpoints/generic_overrides.py +9 -3
  9. fides/api/db/base.py +1 -1
  10. fides/api/models/asset.py +14 -1
  11. fides/api/models/conditional_dependency/conditional_dependency_base.py +253 -24
  12. fides/api/models/detection_discovery/core.py +57 -3
  13. fides/api/models/digest/__init__.py +5 -1
  14. fides/api/models/digest/conditional_dependencies.py +267 -1
  15. fides/api/models/digest/digest_config.py +34 -9
  16. fides/api/models/fides_user.py +9 -0
  17. fides/api/models/manual_task/conditional_dependency.py +16 -18
  18. fides/api/models/privacy_experience.py +10 -0
  19. fides/api/models/privacy_notice.py +139 -20
  20. fides/api/task/manual/manual_task_conditional_evaluation.py +1 -1
  21. fides/service/dataset/dataset_service.py +39 -0
  22. fides/service/privacy_request/privacy_request_service.py +103 -48
  23. fides/ui-build/static/admin/404.html +1 -1
  24. fides/ui-build/static/admin/_next/static/_IxwgneyQjdSaZFEF3Tqu/_buildManifest.js +1 -0
  25. fides/ui-build/static/admin/_next/static/chunks/155-b4337d0826d5addc.js +1 -0
  26. fides/ui-build/static/admin/_next/static/chunks/1817-1ad037b7d6d2f6d2.js +1 -0
  27. fides/ui-build/static/admin/_next/static/chunks/{3585-efd5d41f08e180c4.js → 3585-f728d32fda6f1ac1.js} +1 -1
  28. fides/ui-build/static/admin/_next/static/chunks/3855-ed226b8a8050bd40.js +1 -0
  29. fides/ui-build/static/admin/_next/static/chunks/409-5c3d31163028339f.js +1 -0
  30. fides/ui-build/static/admin/_next/static/chunks/4558-8305aee48def1dcd.js +1 -0
  31. fides/ui-build/static/admin/_next/static/chunks/4608-0c6ef78e30a51f84.js +1 -0
  32. fides/ui-build/static/admin/_next/static/chunks/{4718-6585c97c26647e65.js → 4718-3a412bdb90add82f.js} +1 -1
  33. fides/ui-build/static/admin/_next/static/chunks/502-0d9f4ac29ef34a1c.js +1 -0
  34. fides/ui-build/static/admin/_next/static/chunks/5279-12c9cbdc67ad7b14.js +1 -0
  35. fides/ui-build/static/admin/_next/static/chunks/6277-182efc294d413f64.js +1 -0
  36. fides/ui-build/static/admin/_next/static/chunks/{7045-f15044a4d4525946.js → 7045-14e955890f1147e4.js} +1 -1
  37. fides/ui-build/static/admin/_next/static/chunks/7079-50571e9f3269d74d.js +1 -0
  38. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-a77584f9ad3334af.js → _app-c1c2f757b1f3da12.js} +1 -1
  39. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-75e99306393938e8.js → manual-4ec03eed67572861.js} +1 -1
  40. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-19214babd1f219e3.js +1 -0
  41. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-fd41ffaff543e05a.js → [id]-e1e2fd704ac2d71d.js} +1 -1
  42. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{new-e74cb5ea87f15b40.js → new-a5e738a234dadc7e.js} +1 -1
  43. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-9c23fbe813c997d0.js → [id]-5fc78b78a51c239c.js} +1 -1
  44. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-0e5e38bbcfe59fd2.js → new-b79bcb93b5f4c734.js} +1 -1
  45. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-c1a3caf3c286bf5d.js +1 -0
  46. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-5b57f9132426fe52.js +1 -0
  47. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-a28cc0e23bbe4fc8.js +1 -0
  48. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-7d22222608ec3aac.js +1 -0
  49. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-d514cd4ec62e3b03.js +1 -0
  50. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-153eb88ab4e7dc6d.js +1 -0
  51. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-331544e9b85c4ac2.js +1 -0
  52. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-479890582973deaf.js +1 -0
  53. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-4d658222ec800511.js +1 -0
  54. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-2fcd95c41e578d57.js +1 -0
  55. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{privacy-requests-8cbdfd08e0fa88fb.js → privacy-requests-97221067330c0c27.js} +1 -1
  56. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-547c6ef0ad52b85d.js → [id]-4d470bbf199a2f9c.js} +1 -1
  57. fides/ui-build/static/admin/_next/static/chunks/pages/systems-6c91bdea40875227.js +1 -0
  58. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-3059aba38adefa56.js +1 -0
  59. fides/ui-build/static/admin/_next/static/css/{64fac6fb884435c2.css → 295d729ea1b11885.css} +1 -1
  60. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  61. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  62. fides/ui-build/static/admin/add-systems.html +1 -1
  63. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  64. fides/ui-build/static/admin/consent/configure.html +1 -1
  65. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  66. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  67. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  68. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  69. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  70. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  71. fides/ui-build/static/admin/consent/properties.html +1 -1
  72. fides/ui-build/static/admin/consent/reporting.html +1 -1
  73. fides/ui-build/static/admin/consent.html +1 -1
  74. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  75. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  76. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  77. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  78. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  79. fides/ui-build/static/admin/data-catalog.html +1 -1
  80. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  81. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  82. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  83. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  84. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  85. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  86. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  87. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  88. fides/ui-build/static/admin/datamap.html +1 -1
  89. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  90. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  91. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  92. fides/ui-build/static/admin/dataset/new.html +1 -1
  93. fides/ui-build/static/admin/dataset.html +1 -1
  94. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  95. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  96. fides/ui-build/static/admin/datastore-connection.html +1 -1
  97. fides/ui-build/static/admin/index.html +1 -1
  98. fides/ui-build/static/admin/integrations/[id].html +1 -1
  99. fides/ui-build/static/admin/integrations.html +1 -1
  100. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  101. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  102. fides/ui-build/static/admin/lib/fides-tcf.js +3 -3
  103. fides/ui-build/static/admin/lib/fides.js +3 -3
  104. fides/ui-build/static/admin/login/[provider].html +1 -1
  105. fides/ui-build/static/admin/login.html +1 -1
  106. fides/ui-build/static/admin/messaging/[id].html +1 -1
  107. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  108. fides/ui-build/static/admin/messaging.html +1 -1
  109. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  110. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  111. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  112. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  113. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  114. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  115. fides/ui-build/static/admin/poc/forms.html +1 -1
  116. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  117. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  118. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  119. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  120. fides/ui-build/static/admin/privacy-requests.html +1 -1
  121. fides/ui-build/static/admin/properties/[id].html +1 -1
  122. fides/ui-build/static/admin/properties/add-property.html +1 -1
  123. fides/ui-build/static/admin/properties.html +1 -1
  124. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  125. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  126. fides/ui-build/static/admin/settings/about.html +1 -1
  127. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  128. fides/ui-build/static/admin/settings/consent.html +1 -1
  129. fides/ui-build/static/admin/settings/custom-fields/[id].html +1 -1
  130. fides/ui-build/static/admin/settings/custom-fields/new.html +1 -1
  131. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  132. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  133. fides/ui-build/static/admin/settings/domains.html +1 -1
  134. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  135. fides/ui-build/static/admin/settings/locations.html +1 -1
  136. fides/ui-build/static/admin/settings/messaging-providers/[key].html +1 -1
  137. fides/ui-build/static/admin/settings/messaging-providers/new.html +1 -1
  138. fides/ui-build/static/admin/settings/messaging-providers.html +1 -1
  139. fides/ui-build/static/admin/settings/organization.html +1 -1
  140. fides/ui-build/static/admin/settings/privacy-requests.html +1 -1
  141. fides/ui-build/static/admin/settings/regulations.html +1 -1
  142. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  143. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  144. fides/ui-build/static/admin/systems.html +1 -1
  145. fides/ui-build/static/admin/taxonomy.html +1 -1
  146. fides/ui-build/static/admin/user-management/new.html +1 -1
  147. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  148. fides/ui-build/static/admin/user-management.html +1 -1
  149. fides/ui-build/static/admin/_next/static/chunks/155-047c3806cc41295e.js +0 -1
  150. fides/ui-build/static/admin/_next/static/chunks/1817-ca6473f31a67a804.js +0 -1
  151. fides/ui-build/static/admin/_next/static/chunks/3700-08e0703b1ef770da.js +0 -1
  152. fides/ui-build/static/admin/_next/static/chunks/3855-12ee1dfbbe47fd28.js +0 -1
  153. fides/ui-build/static/admin/_next/static/chunks/409-c1256ecda1b15db6.js +0 -1
  154. fides/ui-build/static/admin/_next/static/chunks/4558-de5ced790b3380dc.js +0 -1
  155. fides/ui-build/static/admin/_next/static/chunks/4608-a9941d0c236ebca1.js +0 -1
  156. fides/ui-build/static/admin/_next/static/chunks/502-d3ecae97b67befbd.js +0 -1
  157. fides/ui-build/static/admin/_next/static/chunks/6084-d0943ee628bf4388.js +0 -1
  158. fides/ui-build/static/admin/_next/static/chunks/6416-0ccadfefcdad00cc.js +0 -1
  159. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-58920afe2b67f952.js +0 -1
  160. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-ae4909cad9b67822.js +0 -1
  161. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-2e1e2b7808d3b21f.js +0 -1
  162. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-2635ef588bf06145.js +0 -1
  163. fides/ui-build/static/admin/_next/static/chunks/pages/datamap-15616bea02397ef4.js +0 -1
  164. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-ea198c4a7869f402.js +0 -1
  165. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/[id]-01e025f878ba806c.js +0 -1
  166. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-14120a529d7dac27.js +0 -1
  167. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-648d775d0fce49dc.js +0 -1
  168. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-e5d781b28f8e29c8.js +0 -1
  169. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-5edfec10a945ca43.js +0 -1
  170. fides/ui-build/static/admin/_next/static/chunks/pages/systems-0f1d833282f09684.js +0 -1
  171. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-a8cfa7de4948b374.js +0 -1
  172. fides/ui-build/static/admin/_next/static/kdnucJIsIefS6ViqY-8w3/_buildManifest.js +0 -1
  173. {ethyca_fides-2.71.0rc4.dist-info → ethyca_fides-2.71.1b1.dist-info}/WHEEL +0 -0
  174. {ethyca_fides-2.71.0rc4.dist-info → ethyca_fides-2.71.1b1.dist-info}/entry_points.txt +0 -0
  175. {ethyca_fides-2.71.0rc4.dist-info → ethyca_fides-2.71.1b1.dist-info}/licenses/LICENSE +0 -0
  176. {ethyca_fides-2.71.0rc4.dist-info → ethyca_fides-2.71.1b1.dist-info}/top_level.txt +0 -0
  177. /fides/ui-build/static/admin/_next/static/{kdnucJIsIefS6ViqY-8w3 → _IxwgneyQjdSaZFEF3Tqu}/_ssgManifest.js +0 -0
  178. /fides/ui-build/static/admin/_next/static/chunks/{6882-10296485ec326e6b.js → 6882-dbe0a25dcf1a8ee0.js} +0 -0
  179. /fides/ui-build/static/admin/_next/static/chunks/{9046-2a332fe338535c84.js → 9046-b6616ba7b59d947e.js} +0 -0
  180. /fides/ui-build/static/admin/_next/static/chunks/pages/{data-catalog-56fd0f3e465e52b6.js → data-catalog-b7326c51d88cc2cc.js} +0 -0
  181. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/{[...subfieldNames]-d4031e438c363fff.js → [...subfieldNames]-0abd30eada811b5b.js} +0 -0
  182. /fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/{[collectionName]-9463af37079762d0.js → [collectionName]-007965429368d9a3.js} +0 -0
@@ -1,17 +1,20 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import itertools
3
4
  import re
4
5
  from enum import Enum
6
+ from functools import cached_property
5
7
  from typing import Any, Dict, List, Optional, Set, Type
6
8
 
7
9
  from fideslang.validation import FidesKey, validate_fides_key
8
10
  from sqlalchemy import Boolean, Column
9
11
  from sqlalchemy import Enum as EnumColumn
10
- from sqlalchemy import Float, ForeignKey, String, UniqueConstraint, or_, text
12
+ from sqlalchemy import Float, ForeignKey, String, UniqueConstraint, false, or_, text
11
13
  from sqlalchemy.dialects.postgresql import ARRAY, JSONB
12
14
  from sqlalchemy.ext.mutable import MutableList
13
- from sqlalchemy.orm import RelationshipProperty, Session, relationship
15
+ from sqlalchemy.orm import RelationshipProperty, Session, relationship, selectinload
14
16
  from sqlalchemy.orm.dynamic import AppenderQuery
17
+ from sqlalchemy.sql.elements import ColumnElement
15
18
  from sqlalchemy.util import hybridproperty
16
19
 
17
20
  from fides.api.db.base_class import Base, FidesBase
@@ -189,21 +192,17 @@ class PrivacyNotice(PrivacyNoticeBase, Base):
189
192
 
190
193
  raise Exception("Invalid notice consent mechanism.")
191
194
 
192
- @property
193
- def cookies(self) -> List[Asset]:
195
+ @staticmethod
196
+ def _get_cookie_filter_for_data_uses(data_uses: List[str]) -> ColumnElement:
194
197
  """
195
- Return the privacy notice's assets of type 'cookie'.
196
- Cookies are matched to the privacy notice if they have at least one data use
197
- that is either an exact match or a hierarchical descendant of a one of the
198
- data uses in the privacy notice.
198
+ Returns the SQLAlchemy filter clause to find cookies for the given data uses.
199
+ This is a helper method to keep the query logic consistent and safe.
199
200
  """
200
- db = Session.object_session(self)
201
-
202
- if not self.data_uses:
203
- return []
201
+ if not data_uses:
202
+ return false()
204
203
 
205
204
  # Use array overlap operator (&&) for exact matches - GIN index friendly
206
- exact_matches_condition = Asset.data_uses.op("&&")(self.data_uses)
205
+ exact_matches_condition = Asset.data_uses.op("&&")(data_uses)
207
206
 
208
207
  # For hierarchical children, we still need to check individual elements with LIKE
209
208
  # They have to match the data_use and the period separator, so we know it's a hierarchical descendant
@@ -211,20 +210,132 @@ class PrivacyNotice(PrivacyNoticeBase, Base):
211
210
  text(
212
211
  f"EXISTS(SELECT 1 FROM unnest(data_uses) AS data_use WHERE data_use LIKE :pattern_{i})"
213
212
  ).bindparams(**{f"pattern_{i}": f"{data_use}.%"})
214
- for i, data_use in enumerate(self.data_uses)
213
+ for i, data_use in enumerate(data_uses)
215
214
  ]
216
215
 
217
- asset_matching_condition = or_(
218
- exact_matches_condition, *hierarchical_conditions
219
- )
216
+ return or_(exact_matches_condition, *hierarchical_conditions)
217
+
218
+ @classmethod
219
+ def _query_cookie_assets_for_data_uses(
220
+ cls,
221
+ db: Session,
222
+ data_uses: Set[str],
223
+ exclude_cookies_from_systems: Optional[Set[str]] = None,
224
+ ) -> List[Asset]:
225
+ """
226
+ Query cookie Assets for the given set of data uses using the shared filter logic.
227
+ Applies optional exclusion by `System.fides_key` and eagerly loads the `system` relationship.
228
+ """
229
+ if not data_uses:
230
+ return []
220
231
 
221
- query = db.query(Asset).filter(
222
- Asset.asset_type == "Cookie",
223
- asset_matching_condition,
232
+ cookie_filter = cls._get_cookie_filter_for_data_uses(list(data_uses))
233
+ query = (
234
+ db.query(Asset)
235
+ .options(selectinload("system"))
236
+ .filter(
237
+ Asset.asset_type == "Cookie",
238
+ cookie_filter,
239
+ )
224
240
  )
241
+ if exclude_cookies_from_systems:
242
+ query = query.outerjoin(System).filter(
243
+ or_(
244
+ Asset.system_id.is_(None),
245
+ System.fides_key.not_in(exclude_cookies_from_systems),
246
+ )
247
+ )
225
248
 
226
249
  return query.all()
227
250
 
251
+ @staticmethod
252
+ def _group_cookies_by_data_use(cookies: List[Asset]) -> Dict[str, List[Asset]]:
253
+ """Build a mapping of data_use -> list of cookie Assets."""
254
+ cookies_by_data_use: Dict[str, List[Asset]] = {}
255
+ for cookie in cookies:
256
+ for data_use in cookie.data_uses or []:
257
+ cookies_by_data_use.setdefault(data_use, []).append(cookie)
258
+ return cookies_by_data_use
259
+
260
+ @staticmethod
261
+ def _select_cookies_for_notice_data_uses(
262
+ notice_data_uses: List[str],
263
+ cookies_by_data_use: Dict[str, List[Asset]],
264
+ ) -> List[Asset]:
265
+ """
266
+ Return cookies that match the notice data uses either exactly or as hierarchical descendants.
267
+ Deduplicate by object identity; ordering is not guaranteed.
268
+ """
269
+ unique_cookies_by_id: Dict[int, Asset] = {}
270
+
271
+ for notice_data_use in notice_data_uses or []:
272
+ # Exact matches
273
+ for cookie in cookies_by_data_use.get(notice_data_use, []):
274
+ unique_cookies_by_id[id(cookie)] = cookie
275
+
276
+ # Hierarchical descendants: e.g., "analytics" matches "analytics.reporting"
277
+ prefix = f"{notice_data_use}."
278
+ for du_key, cookie_list in cookies_by_data_use.items():
279
+ if du_key.startswith(prefix):
280
+ for cookie in cookie_list:
281
+ unique_cookies_by_id[id(cookie)] = cookie
282
+
283
+ return list(unique_cookies_by_id.values())
284
+
285
+ @cached_property
286
+ def cookies(self) -> List[Asset]:
287
+ """
288
+ Return relevant assets of type 'cookie' (via the data use)
289
+
290
+ Cookies are matched to the privacy notice if they have at least one data use
291
+ that is either an exact match or a hierarchical descendant of a one of the
292
+ data uses in the privacy notice.
293
+
294
+ This is a cached_property, so the database query is only executed
295
+ once per instance, and the result is cached for subsequent accesses.
296
+ """
297
+ db = Session.object_session(self)
298
+ cookie_filter = self._get_cookie_filter_for_data_uses(self.data_uses)
299
+
300
+ return (
301
+ db.query(Asset)
302
+ .filter(
303
+ Asset.asset_type == "Cookie",
304
+ cookie_filter,
305
+ )
306
+ .all()
307
+ )
308
+
309
+ @classmethod
310
+ def load_cookie_data_for_notices(
311
+ cls,
312
+ db: Session,
313
+ notices: List["PrivacyNotice"],
314
+ exclude_cookies_from_systems: Optional[Set[str]] = None,
315
+ ) -> None:
316
+ """
317
+ An efficient method to bulk-load cookie data for a list of PrivacyNotice objects.
318
+ This prevents the "N+1" query problem by pre-populating the `cookies`
319
+ cached_property for each notice.
320
+ """
321
+ if not notices:
322
+ return
323
+
324
+ all_data_uses = set(itertools.chain.from_iterable(n.data_uses for n in notices))
325
+ all_relevant_cookies = cls._query_cookie_assets_for_data_uses(
326
+ db, all_data_uses, exclude_cookies_from_systems
327
+ )
328
+ cookies_by_data_use = cls._group_cookies_by_data_use(all_relevant_cookies)
329
+
330
+ for notice in notices:
331
+ matching_cookies = cls._select_cookies_for_notice_data_uses(
332
+ notice.data_uses, cookies_by_data_use
333
+ )
334
+
335
+ # Pre-populate the cache of the 'cookies' cached_property.
336
+ # This directly sets the attribute that the decorator would otherwise compute.
337
+ setattr(notice, "cookies", matching_cookies)
338
+
228
339
  @property
229
340
  def calculated_systems_applicable(self) -> bool:
230
341
  """Convenience property to return if any systems overlap with this notice's data uses
@@ -419,6 +530,10 @@ class PrivacyNotice(PrivacyNoticeBase, Base):
419
530
  # to prevent the dry update from being added to Session.new
420
531
  updated_attributes.pop("translations", [])
421
532
  updated_attributes.pop("children", [])
533
+ # The source PrivacyNotice may have cached/computed attributes (e.g., @cached_property)
534
+ # stored on the instance dict. These should not be included in historical payloads.
535
+ # For example, 'cookies' is cached on the PrivacyNotice instance when accessed.
536
+ updated_attributes.pop("cookies", None)
422
537
 
423
538
  # create a new object with the updated attribute data to keep this
424
539
  # ORM object (i.e., `self`) pristine
@@ -565,6 +680,10 @@ def create_historical_record_for_notice_and_translation(
565
680
  history_data: dict = create_historical_data_from_record(privacy_notice)
566
681
  history_data.pop("translations", None)
567
682
  history_data.pop("parent_id", None)
683
+ # The source PrivacyNotice may have cached/computed attributes (e.g., @cached_property)
684
+ # stored on the instance dict. These should not be included in historical payloads.
685
+ # For example, 'cookies' is cached on the PrivacyNotice instance when accessed.
686
+ history_data.pop("cookies", None)
568
687
 
569
688
  updated_translation_data: dict = create_historical_data_from_record(
570
689
  notice_translation
@@ -181,7 +181,7 @@ def evaluate_conditional_dependencies(
181
181
  """
182
182
  # Get the root condition for this manual task
183
183
  root_condition = ManualTaskConditionalDependency.get_root_condition(
184
- db, manual_task.id
184
+ db, manual_task_id=manual_task.id
185
185
  )
186
186
 
187
187
  if not root_condition:
@@ -6,6 +6,7 @@ from loguru import logger
6
6
  from sqlalchemy import select
7
7
  from sqlalchemy.orm import Session
8
8
 
9
+ from fides.api.models.datasetconfig import DatasetConfig # type: ignore[attr-defined]
9
10
  from fides.api.schemas.dataset import ValidateDatasetResponse
10
11
  from fides.service.dataset.dataset_validator import DatasetValidator
11
12
 
@@ -26,6 +27,10 @@ class DatasetNotFoundException(DatasetError):
26
27
  """Raised when a dataset is not found"""
27
28
 
28
29
 
30
+ class LinkedDatasetException(DatasetError):
31
+ """Raised when attempting to delete a dataset that's associated to a DatasetConfig"""
32
+
33
+
29
34
  class DatasetService:
30
35
  def __init__(self, db: Session):
31
36
  self.db = db
@@ -68,6 +73,40 @@ class DatasetService:
68
73
  def delete_dataset(self, fides_key: str) -> CtlDataset:
69
74
  """Delete a dataset by fides key"""
70
75
  dataset = self.get_dataset(fides_key)
76
+
77
+ # Check if dataset is associated with any DatasetConfigs
78
+ associated_configs = (
79
+ self.db.query(DatasetConfig)
80
+ .filter(DatasetConfig.ctl_dataset_id == dataset.id)
81
+ .all()
82
+ )
83
+
84
+ if associated_configs:
85
+ # Create detailed error message
86
+ integration_details = []
87
+ for config in associated_configs:
88
+ connection_name = (
89
+ config.connection_config.name or config.connection_config.key
90
+ )
91
+ detail = f"'{connection_name}' ({config.connection_config.connection_type.value})" # type: ignore[attr-defined]
92
+
93
+ # Add system information if available
94
+ if config.connection_config.system_id:
95
+ system = config.connection_config.system
96
+ if system:
97
+ system_name = system.name or system.fides_key
98
+ detail += f" in system '{system_name}'"
99
+
100
+ integration_details.append(detail)
101
+
102
+ message = (
103
+ f"Cannot delete dataset '{fides_key}' because it is associated with "
104
+ f"the following integration(s): {', '.join(integration_details)}. "
105
+ f"Remove the dataset from these integrations before deleting."
106
+ )
107
+
108
+ raise LinkedDatasetException(message)
109
+
71
110
  dataset.delete(self.db)
72
111
  return dataset
73
112
 
@@ -90,65 +90,120 @@ class PrivacyRequestService:
90
90
  if privacy_request_data.location:
91
91
  return
92
92
 
93
- # Get the Privacy Center configuration from the database
94
- privacy_center_config_record = PrivacyCenterConfigModel.filter(
95
- db=self.db, conditions=PrivacyCenterConfigModel.single_row # type: ignore[arg-type]
96
- ).first()
93
+ config_dict = self._resolve_privacy_center_config_dict(
94
+ privacy_request_data.property_id
95
+ )
96
+ if not config_dict:
97
+ return
97
98
 
98
- if not privacy_center_config_record:
99
- # No Privacy Center config found, skip validation
99
+ privacy_center_config = self._parse_privacy_center_config(config_dict)
100
+ if not privacy_center_config:
100
101
  return
101
102
 
102
- try:
103
- # Parse the config using the Pydantic schema
104
- privacy_center_config = PrivacyCenterConfigSchema.model_validate(
105
- privacy_center_config_record.config
103
+ action = self._get_matching_action(
104
+ privacy_center_config, privacy_request_data.policy_key
105
+ )
106
+ if not action or not action.custom_privacy_request_fields:
107
+ return
108
+
109
+ missing_required = self._is_required_location_missing(
110
+ action, privacy_request_data
111
+ )
112
+ if missing_required:
113
+ # Find the first location field name to reference in the error for clarity
114
+ first_location_field = next(
115
+ (
116
+ name
117
+ for name, cfg in action.custom_privacy_request_fields.items()
118
+ if isinstance(cfg, LocationCustomPrivacyRequestField)
119
+ and getattr(cfg, "required", False)
120
+ ),
121
+ "location",
106
122
  )
107
- except Exception as exc:
123
+ raise PrivacyRequestError(
124
+ f"Location is required for field '{first_location_field}' but was not provided",
125
+ privacy_request_data.model_dump(mode="json"),
126
+ )
127
+
128
+ def _resolve_privacy_center_config_dict(
129
+ self, property_id: Optional[str]
130
+ ) -> Optional[Dict[str, Any]]:
131
+ """Return the applicable Privacy Center config as a dict using precedence.
132
+
133
+ Precedence:
134
+ 1) The request's property config (if provided)
135
+ 2) The default property's config (if available)
136
+ 3) The single-row Privacy Center config table (legacy/global)
137
+ """
138
+ # 1) Request's property config
139
+ if property_id:
140
+ prop = Property.get_by(self.db, field="id", value=property_id)
141
+ if prop and getattr(prop, "privacy_center_config", None):
142
+ return prop.privacy_center_config # type: ignore[return-value]
143
+
144
+ # 2) Default property config
145
+ default_prop = Property.get_by(self.db, field="is_default", value=True)
146
+ if default_prop and getattr(default_prop, "privacy_center_config", None):
147
+ return default_prop.privacy_center_config # type: ignore[return-value]
148
+
149
+ # 3) Single-row global config
150
+ privacy_center_config_record = PrivacyCenterConfigModel.filter(
151
+ db=self.db, conditions=PrivacyCenterConfigModel.single_row # type: ignore[arg-type]
152
+ ).first()
153
+ if privacy_center_config_record:
154
+ return privacy_center_config_record.config # type: ignore[return-value]
155
+ return None
156
+
157
+ def _parse_privacy_center_config(
158
+ self, config_dict: Dict[str, Any]
159
+ ) -> Optional[PrivacyCenterConfigSchema]:
160
+ """Parse a config dict into a schema instance, logging and skipping on error."""
161
+ try:
162
+ return PrivacyCenterConfigSchema.model_validate(config_dict)
163
+ except Exception as exc: # pylint: disable=broad-except
108
164
  logger.warning(
109
165
  f"Could not parse Privacy Center config for location validation: {exc}"
110
166
  )
111
- return
167
+ return None
112
168
 
113
- # Find the action that matches the policy key
114
- matching_action = None
169
+ @staticmethod
170
+ def _get_matching_action(
171
+ privacy_center_config: PrivacyCenterConfigSchema, policy_key: str
172
+ ) -> Optional[Any]:
173
+ """Return the action entry matching the given policy key, if any."""
115
174
  for action in privacy_center_config.actions:
116
- if action.policy_key == privacy_request_data.policy_key:
117
- matching_action = action
118
- break
175
+ if action.policy_key == policy_key:
176
+ return action
177
+ return None
178
+
179
+ @staticmethod
180
+ def _is_required_location_missing(
181
+ action: Any, privacy_request_data: PrivacyRequestCreate
182
+ ) -> bool:
183
+ """Check if any required location fields exist without values in the request."""
184
+ if not getattr(action, "custom_privacy_request_fields", None):
185
+ return False
186
+
187
+ custom_fields = action.custom_privacy_request_fields
188
+ for field_name, field_config in custom_fields.items():
189
+ if not isinstance(field_config, LocationCustomPrivacyRequestField):
190
+ continue
191
+ if not getattr(field_config, "required", False):
192
+ continue
119
193
 
120
- if not matching_action or not matching_action.custom_privacy_request_fields:
121
- # No matching action or no custom fields defined
122
- return
194
+ # Check if this location field has a value in the request custom fields
195
+ field_has_value = False
196
+ if privacy_request_data.custom_privacy_request_fields:
197
+ field_data = privacy_request_data.custom_privacy_request_fields.get(
198
+ field_name
199
+ )
200
+ if field_data and getattr(field_data, "value", None):
201
+ field_has_value = True
202
+
203
+ if not field_has_value:
204
+ return True
123
205
 
124
- # Check if any location fields are required
125
- for (
126
- field_name,
127
- field_config,
128
- ) in matching_action.custom_privacy_request_fields.items():
129
- if isinstance(field_config, LocationCustomPrivacyRequestField):
130
- # This is a location field - check if it's required
131
- if field_config.required:
132
- # Check if this field has a value in the request
133
- field_has_value = False
134
- if privacy_request_data.custom_privacy_request_fields:
135
- field_data = (
136
- privacy_request_data.custom_privacy_request_fields.get(
137
- field_name
138
- )
139
- )
140
- if (
141
- field_data
142
- and hasattr(field_data, "value")
143
- and field_data.value
144
- ):
145
- field_has_value = True
146
-
147
- if not field_has_value:
148
- raise PrivacyRequestError(
149
- f"Location is required for field '{field_name}' but was not provided",
150
- privacy_request_data.model_dump(mode="json"),
151
- )
206
+ return False
152
207
 
153
208
  # pylint: disable=too-many-branches
154
209
  def create_privacy_request(
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/64fac6fb884435c2.css" as="style"/><link rel="stylesheet" href="/_next/static/css/64fac6fb884435c2.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-2766492c5dbceb0a.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-a77584f9ad3334af.js" defer=""></script><script src="/_next/static/chunks/pages/404-2eb8aed4939f1142.js" defer=""></script><script src="/_next/static/kdnucJIsIefS6ViqY-8w3/_buildManifest.js" defer=""></script><script src="/_next/static/kdnucJIsIefS6ViqY-8w3/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"kdnucJIsIefS6ViqY-8w3","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link data-next-font="" rel="preconnect" href="/" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/295d729ea1b11885.css" as="style"/><link rel="stylesheet" href="/_next/static/css/295d729ea1b11885.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-2766492c5dbceb0a.js" defer=""></script><script src="/_next/static/chunks/framework-c92fc3344e6fd165.js" defer=""></script><script src="/_next/static/chunks/main-090643377c8254e6.js" defer=""></script><script src="/_next/static/chunks/pages/_app-c1c2f757b1f3da12.js" defer=""></script><script src="/_next/static/chunks/pages/404-2eb8aed4939f1142.js" defer=""></script><script src="/_next/static/_IxwgneyQjdSaZFEF3Tqu/_buildManifest.js" defer=""></script><script src="/_next/static/_IxwgneyQjdSaZFEF3Tqu/_ssgManifest.js" defer=""></script><style>.data-ant-cssinjs-cache-path{content:"";}</style></head><body><div id="__next"><div style="height:100%;display:flex"></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"_IxwgneyQjdSaZFEF3Tqu","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -0,0 +1 @@
1
+ self.__BUILD_MANIFEST=function(s,e,t,a,c,n,i,d,o,r,p,g,u,f,m,j,k,b,h,y,l,v,I,F,x,_,w,U,q,N,A,S,B,C,z,D,E,L,M,T,P,G,H,J,K,O,Q,R,V,W,X,Y,Z,$,ss,se,st,sa){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":[q,"static/chunks/pages/index-b74d1e8608ae5b5d.js"],"/404":["static/chunks/pages/404-2eb8aed4939f1142.js"],"/_error":["static/chunks/pages/_error-bede3a8288930dcf.js"],"/add-systems":[s,q,"static/chunks/pages/add-systems-19214babd1f219e3.js"],"/add-systems/manual":[e,s,t,a,n,f,c,i,r,m,l,N,A,"static/chunks/pages/add-systems/manual-4ec03eed67572861.js"],"/add-systems/multiple":[r,j,S,"static/chunks/pages/add-systems/multiple-2ca59996860a33c5.js"],"/consent":["static/chunks/pages/consent-d2bf72508c3cad55.js"],"/consent/configure":[r,j,"static/chunks/pages/consent/configure-fb5017ff5fa54fcc.js"],"/consent/configure/add-vendors":[r,j,S,"static/chunks/pages/consent/configure/add-vendors-7a258b7ecd6da4b8.js"],"/consent/privacy-experience":[f,B,"static/chunks/pages/consent/privacy-experience-92182be6603c2842.js"],"/consent/privacy-experience/new":[e,d,k,p,b,C,"static/chunks/pages/consent/privacy-experience/new-a5e738a234dadc7e.js"],"/consent/privacy-experience/[id]":[e,d,k,p,b,C,"static/chunks/pages/consent/privacy-experience/[id]-e1e2fd704ac2d71d.js"],"/consent/privacy-notices":[B,"static/chunks/pages/consent/privacy-notices-ab54b19609bff325.js"],"/consent/privacy-notices/new":[e,d,k,p,b,z,"static/chunks/pages/consent/privacy-notices/new-b79bcb93b5f4c734.js"],"/consent/privacy-notices/[id]":[e,d,k,p,b,z,"static/chunks/pages/consent/privacy-notices/[id]-5fc78b78a51c239c.js"],"/consent/properties":[h,D,"static/chunks/pages/consent/properties-069f4e3ee96ebf77.js"],"/consent/reporting":[s,"static/chunks/2150-930ffaf2c4718edc.js","static/chunks/pages/consent/reporting-c1a3caf3c286bf5d.js"],"/data-catalog":[e,t,a,c,"static/css/95ac327e5d70148d.css","static/chunks/pages/data-catalog-b7326c51d88cc2cc.js"],"/data-catalog/[systemId]/projects":[e,t,a,c,v,o,"static/chunks/pages/data-catalog/[systemId]/projects-99573a1ee3ef8f4c.js"],"/data-catalog/[systemId]/projects/[projectUrn]":[E,"static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]-4a1af12d2d7cd660.js"],"/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn]":[e,s,t,a,c,v,L,o,"static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn]-2fa4b3a58f75f81d.js"],"/data-catalog/[systemId]/resources":[E,"static/chunks/pages/data-catalog/[systemId]/resources-6e429b7511028d60.js"],"/data-catalog/[systemId]/resources/[resourceUrn]":[e,s,t,a,c,v,L,o,"static/chunks/pages/data-catalog/[systemId]/resources/[resourceUrn]-5b31e3d7727b917a.js"],"/data-discovery/action-center":[I,"static/chunks/pages/data-discovery/action-center-040813022f0890c9.js"],"/data-discovery/action-center/[monitorId]":[e,s,t,a,i,I,M,F,"static/chunks/pages/data-discovery/action-center/[monitorId]-0d512528b498d75c.js"],"/data-discovery/action-center/[monitorId]/[systemId]":[e,s,t,a,i,r,l,I,M,"static/css/23cf870196941c9a.css","static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-5b57f9132426fe52.js"],"/data-discovery/activity":[s,u,"static/chunks/pages/data-discovery/activity-a28cc0e23bbe4fc8.js"],"/data-discovery/detection":[s,i,u,T,"static/chunks/pages/data-discovery/detection-11b07cf2d91b17ef.js"],"/data-discovery/detection/[resourceUrn]":[s,i,u,T,"static/chunks/pages/data-discovery/detection/[resourceUrn]-844a8de0d1b506e2.js"],"/data-discovery/discovery":[e,s,t,a,c,i,u,P,o,"static/chunks/pages/data-discovery/discovery-ed4723e1b67d890e.js"],"/data-discovery/discovery/[resourceUrn]":[e,s,t,a,c,i,u,P,o,"static/chunks/pages/data-discovery/discovery/[resourceUrn]-5525cf287d4ab493.js"],"/datamap":[s,a,"static/chunks/255-1bc0cbef7a59cdc6.js",m,G,"static/chunks/pages/datamap-7d22222608ec3aac.js"],"/dataset":[g,y,"static/chunks/pages/dataset-0e3a6ac4797ffbbb.js"],"/dataset/new":[s,g,y,"static/chunks/pages/dataset/new-d514cd4ec62e3b03.js"],"/dataset/[datasetId]":["static/chunks/9729-fcf6ff4e3534e4a8.js",x,"static/chunks/pages/dataset/[datasetId]-60a4a9eb4aab4c11.js"],"/dataset/[datasetId]/[collectionName]":[e,t,a,n,c,x,o,"static/chunks/pages/dataset/[datasetId]/[collectionName]-007965429368d9a3.js"],"/dataset/[datasetId]/[collectionName]/[...subfieldNames]":[e,t,a,n,c,x,o,"static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-0abd30eada811b5b.js"],"/datastore-connection":["static/css/5f393dea1c0d031c.css","static/chunks/pages/datastore-connection-223c2d1ded51bfb1.js"],"/datastore-connection/new":[e,s,n,g,f,H,y,J,"static/chunks/pages/datastore-connection/new-b6838162200141b3.js"],"/datastore-connection/[id]":[e,s,n,g,H,y,J,"static/chunks/pages/datastore-connection/[id]-816e02b6cbe4a684.js"],"/fides-js-docs":["static/chunks/2fbcc6de-a6c61724c327e9fa.js","static/chunks/e3251fe7-5777b5d778e6fffa.js",e,t,a,n,g,"static/chunks/5619-9b50cec521203989.js",K,"static/css/0b4b1b65cc874774.css","static/chunks/5596-29a7c8322530b7cf.js","static/chunks/pages/fides-js-docs-1f4335dca5c09860.js"],"/integrations":[e,s,t,a,n,d,O,Q,o,"static/chunks/pages/integrations-331544e9b85c4ac2.js"],"/integrations/[id]":[e,s,t,a,n,d,O,i,p,Q,o,"static/chunks/pages/integrations/[id]-153eb88ab4e7dc6d.js"],"/login":["static/chunks/pages/login-0cb0eb44bf2dd24c.js"],"/login/[provider]":["static/chunks/pages/login/[provider]-c58beef131c3a82d.js"],"/messaging":[e,t,"static/chunks/346-aa3b88efb85f2e28.js","static/chunks/pages/messaging-b5f7d6afdecd013d.js"],"/messaging/add-template":[R,"static/chunks/pages/messaging/add-template-e3f93462a08251bf.js"],"/messaging/[id]":[R,"static/chunks/pages/messaging/[id]-e8d2140787045acd.js"],"/poc/ant-components":["static/chunks/pages/poc/ant-components-248ad9f65a872442.js"],"/poc/form-experiments/AntForm":["static/chunks/pages/poc/form-experiments/AntForm-aedb66a62042b10a.js"],"/poc/form-experiments/FormikAntFormItem":["static/chunks/pages/poc/form-experiments/FormikAntFormItem-018df38b7cd77fdb.js"],"/poc/form-experiments/FormikControlled":["static/chunks/pages/poc/form-experiments/FormikControlled-6ca9099d03aab817.js"],"/poc/form-experiments/FormikField":["static/chunks/pages/poc/form-experiments/FormikField-0f2c90786ea005a4.js"],"/poc/form-experiments/FormikSpreadField":[V,"static/chunks/pages/poc/form-experiments/FormikSpreadField-af097d661f6abcf4.js"],"/poc/forms":[V,"static/chunks/pages/poc/forms-200b51a725f8b2d1.js"],"/poc/table-migration":[r,j,"static/chunks/pages/poc/table-migration-29fb7b39f8962650.js"],"/privacy-requests":[e,s,"static/chunks/3550-83cb70e80cbe41ba.js",W,"static/chunks/pages/privacy-requests-7af00f72cf694077.js"],"/privacy-requests/configure":["static/chunks/pages/privacy-requests/configure-8f577df28ebca869.js"],"/privacy-requests/configure/storage":[s,"static/chunks/pages/privacy-requests/configure/storage-479890582973deaf.js"],"/privacy-requests/[id]":[s,W,"static/css/073713cd1eddda79.css","static/chunks/pages/privacy-requests/[id]-7dac2302f573f5ee.js"],"/properties":[h,D,"static/chunks/pages/properties-08472b2a6bf1d392.js"],"/properties/add-property":[h,X,"static/chunks/pages/properties/add-property-8964c2300206bc89.js"],"/properties/[id]":[h,X,"static/chunks/pages/properties/[id]-57a75c7e9659271a.js"],"/reporting/datamap":[e,s,t,a,K,m,_,G,"static/chunks/pages/reporting/datamap-f7753e9effae3816.js"],"/settings/about":[Y,"static/chunks/pages/settings/about-6c4904c157477285.js"],"/settings/about/alpha":[Y,"static/chunks/pages/settings/about/alpha-68eaac2d79133679.js"],"/settings/consent":[p,"static/chunks/pages/settings/consent-4d658222ec800511.js"],"/settings/consent/[configuration_id]/[purpose_id]":["static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-f3e6e74e0efb005c.js"],"/settings/custom-fields":[s,"static/chunks/pages/settings/custom-fields-2fcd95c41e578d57.js"],"/settings/custom-fields/new":[e,Z,$,"static/chunks/pages/settings/custom-fields/new-469ad83c8cfa1290.js"],"/settings/custom-fields/[id]":[e,Z,$,"static/chunks/pages/settings/custom-fields/[id]-bd1042a0e9be6aff.js"],"/settings/domain-records":["static/chunks/pages/settings/domain-records-744f669431b84f71.js"],"/settings/domains":["static/chunks/pages/settings/domains-a3275554ffe8e640.js"],"/settings/email-templates":["static/chunks/pages/settings/email-templates-604790638c656fbd.js"],"/settings/locations":[ss,F,"static/chunks/pages/settings/locations-be2a885150adc133.js"],"/settings/messaging-providers":[s,w,"static/chunks/pages/settings/messaging-providers-8d92be437793c96f.js"],"/settings/messaging-providers/new":[e,s,t,d,se,w,st,"static/chunks/pages/settings/messaging-providers/new-8bf1821722b082e9.js"],"/settings/messaging-providers/[key]":[e,s,t,d,se,w,st,"static/chunks/pages/settings/messaging-providers/[key]-77239269acc2d31a.js"],"/settings/organization":["static/chunks/pages/settings/organization-3c86162afe9759df.js"],"/settings/privacy-requests":[s,"static/chunks/pages/settings/privacy-requests-97221067330c0c27.js"],"/settings/regulations":[ss,F,"static/chunks/pages/settings/regulations-4fe3b90747d885e5.js"],"/systems":[e,s,t,a,"static/chunks/1896-49010da5c2705fc5.js",_,"static/chunks/pages/systems-6c91bdea40875227.js"],"/systems/configure/[id]":[e,s,t,a,n,f,c,i,r,m,l,N,A,"static/chunks/pages/systems/configure/[id]-4d470bbf199a2f9c.js"],"/systems/configure/[id]/test-datasets":[g,"static/chunks/pages/systems/configure/[id]/test-datasets-2deb6becece69d46.js"],"/taxonomy":["static/chunks/678d4732-50255cc09048e643.js",e,s,t,a,d,"static/chunks/6148-59a59d5c5925344f.js",_,"static/css/34a7eb08b86ddb57.css","static/chunks/pages/taxonomy-3059aba38adefa56.js"],"/user-management":[U,"static/chunks/pages/user-management-562624e5461083ec.js"],"/user-management/new":[U,sa,"static/chunks/pages/user-management/new-629c88e90699369b.js"],"/user-management/profile/[id]":[U,sa,"static/chunks/pages/user-management/profile/[id]-98f737e735eaa0f0.js"],sortedPages:["/","/404","/_app","/_error","/add-systems","/add-systems/manual","/add-systems/multiple","/consent","/consent/configure","/consent/configure/add-vendors","/consent/privacy-experience","/consent/privacy-experience/new","/consent/privacy-experience/[id]","/consent/privacy-notices","/consent/privacy-notices/new","/consent/privacy-notices/[id]","/consent/properties","/consent/reporting","/data-catalog","/data-catalog/[systemId]/projects","/data-catalog/[systemId]/projects/[projectUrn]","/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn]","/data-catalog/[systemId]/resources","/data-catalog/[systemId]/resources/[resourceUrn]","/data-discovery/action-center","/data-discovery/action-center/[monitorId]","/data-discovery/action-center/[monitorId]/[systemId]","/data-discovery/activity","/data-discovery/detection","/data-discovery/detection/[resourceUrn]","/data-discovery/discovery","/data-discovery/discovery/[resourceUrn]","/datamap","/dataset","/dataset/new","/dataset/[datasetId]","/dataset/[datasetId]/[collectionName]","/dataset/[datasetId]/[collectionName]/[...subfieldNames]","/datastore-connection","/datastore-connection/new","/datastore-connection/[id]","/fides-js-docs","/integrations","/integrations/[id]","/login","/login/[provider]","/messaging","/messaging/add-template","/messaging/[id]","/poc/ant-components","/poc/form-experiments/AntForm","/poc/form-experiments/FormikAntFormItem","/poc/form-experiments/FormikControlled","/poc/form-experiments/FormikField","/poc/form-experiments/FormikSpreadField","/poc/forms","/poc/table-migration","/privacy-requests","/privacy-requests/configure","/privacy-requests/configure/storage","/privacy-requests/[id]","/properties","/properties/add-property","/properties/[id]","/reporting/datamap","/settings/about","/settings/about/alpha","/settings/consent","/settings/consent/[configuration_id]/[purpose_id]","/settings/custom-fields","/settings/custom-fields/new","/settings/custom-fields/[id]","/settings/domain-records","/settings/domains","/settings/email-templates","/settings/locations","/settings/messaging-providers","/settings/messaging-providers/new","/settings/messaging-providers/[key]","/settings/organization","/settings/privacy-requests","/settings/regulations","/systems","/systems/configure/[id]","/systems/configure/[id]/test-datasets","/taxonomy","/user-management","/user-management/new","/user-management/profile/[id]"]}}("static/chunks/431-78bf05f35d7eec4f.js","static/chunks/8765-f622a35b40a7ec63.js","static/chunks/9278-08cc704317fe535e.js","static/chunks/5163-e682273cd76a7d07.js","static/chunks/409-5c3d31163028339f.js","static/chunks/699-8ca44b0de9fa20f0.js","static/chunks/7045-14e955890f1147e4.js","static/chunks/3662-f6a1ddca5ee42076.js","static/css/d2d4e9a6923e6730.css","static/chunks/401-ffe4e8436e1eceb9.js","static/chunks/5279-12c9cbdc67ad7b14.js","static/chunks/6527-0eed08abe252a918.js","static/chunks/8002-ed832921ad190832.js","static/chunks/5277-e8a036319456127f.js","static/chunks/7218-e2983b96b95e33b4.js","static/chunks/3923-98bea73b618292aa.js","static/chunks/6419-9b3a86af57c86791.js","static/chunks/6277-182efc294d413f64.js","static/chunks/2040-fdecc41a18e40bdc.js","static/chunks/5574-c31ea831371610d5.js","static/chunks/3585-f728d32fda6f1ac1.js","static/chunks/6882-dbe0a25dcf1a8ee0.js","static/chunks/7725-f2a7be705b75dcc3.js","static/css/10994e916bc9a00a.css","static/chunks/9226-4a7027057f55ca2a.js","static/chunks/4718-3a412bdb90add82f.js","static/chunks/502-0d9f4ac29ef34a1c.js","static/chunks/7476-d055aa931da47ac0.js","static/css/972dc7eef106ee7c.css","static/chunks/7079-50571e9f3269d74d.js","static/css/304c6f148886a8d4.css","static/chunks/796-02086581996a0548.js","static/chunks/6853-7004a8c420b1ca02.js","static/chunks/1817-1ad037b7d6d2f6d2.js","static/chunks/6954-4b24e1731c1cc3b3.js","static/chunks/5783-d119cb132abd8a91.js","static/chunks/3872-04d3afbfa41a7782.js","static/chunks/3855-ed226b8a8050bd40.js","static/chunks/7929-0fd0d4948bc8d70e.js","static/chunks/5309-3b6cf0cc9d0c6a83.js","static/chunks/9046-b6616ba7b59d947e.js","static/chunks/504-88caa30c03374e9b.js","static/chunks/1467-8808ec8836e033f9.js","static/chunks/4608-0c6ef78e30a51f84.js","static/chunks/9187-7438242f0d380bb0.js","static/chunks/1316-2606e19807c08aa5.js","static/chunks/155-b4337d0826d5addc.js","static/chunks/7630-d0d3a0fe3f95e971.js","static/chunks/2921-66f65496c3a09316.js","static/chunks/4558-8305aee48def1dcd.js","static/chunks/5185-51eaa78e3ed6bfb7.js","static/chunks/1115-90baef2a89f361ad.js","static/chunks/2962-e92d525bf570a9a3.js","static/chunks/5643-10a36584c399526c.js","static/chunks/9826-ccedc28e978ca9e1.js","static/chunks/9037-453224ba3ee65b13.js","static/chunks/7158-04745cc8d684b2e7.js","static/chunks/3696-90c8b336bbc46782.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();