ethyca-fides 2.64.0rc0__py2.py3-none-any.whl → 2.64.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.
Files changed (107) hide show
  1. {ethyca_fides-2.64.0rc0.dist-info → ethyca_fides-2.64.1b1.dist-info}/METADATA +2 -2
  2. {ethyca_fides-2.64.0rc0.dist-info → ethyca_fides-2.64.1b1.dist-info}/RECORD +107 -104
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/6a76a1fa4f3f_add_manual_task_instance_table.py +256 -0
  5. fides/api/db/base.py +4 -0
  6. fides/api/models/manual_tasks/__init__.py +7 -1
  7. fides/api/models/manual_tasks/manual_task.py +19 -3
  8. fides/api/models/manual_tasks/manual_task_config.py +39 -6
  9. fides/api/models/manual_tasks/manual_task_instance.py +187 -0
  10. fides/api/models/manual_tasks/manual_task_log.py +20 -7
  11. fides/api/schemas/manual_tasks/manual_task_schemas.py +42 -0
  12. fides/api/schemas/manual_tasks/manual_task_status.py +107 -46
  13. fides/api/service/connectors/postgres_connector.py +2 -2
  14. fides/service/manual_tasks/manual_task_config_service.py +17 -5
  15. fides/service/manual_tasks/manual_task_instance_service.py +285 -0
  16. fides/service/manual_tasks/manual_task_service.py +66 -10
  17. fides/ui-build/static/admin/404.html +1 -1
  18. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  19. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  20. fides/ui-build/static/admin/add-systems.html +1 -1
  21. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  22. fides/ui-build/static/admin/consent/configure.html +1 -1
  23. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  24. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  25. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  26. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  27. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  28. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  29. fides/ui-build/static/admin/consent/properties.html +1 -1
  30. fides/ui-build/static/admin/consent/reporting.html +1 -1
  31. fides/ui-build/static/admin/consent.html +1 -1
  32. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  33. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  34. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  35. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  36. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  37. fides/ui-build/static/admin/data-catalog.html +1 -1
  38. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  39. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  40. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  41. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  42. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  43. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  44. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  45. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  46. fides/ui-build/static/admin/datamap.html +1 -1
  47. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  48. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  49. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  50. fides/ui-build/static/admin/dataset/new.html +1 -1
  51. fides/ui-build/static/admin/dataset.html +1 -1
  52. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  53. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  54. fides/ui-build/static/admin/datastore-connection.html +1 -1
  55. fides/ui-build/static/admin/index.html +1 -1
  56. fides/ui-build/static/admin/integrations/[id].html +1 -1
  57. fides/ui-build/static/admin/integrations.html +1 -1
  58. fides/ui-build/static/admin/lib/fides-headless.js +1 -1
  59. fides/ui-build/static/admin/lib/fides-preview.js +1 -1
  60. fides/ui-build/static/admin/lib/fides-tcf.js +2 -2
  61. fides/ui-build/static/admin/lib/fides.js +2 -2
  62. fides/ui-build/static/admin/login/[provider].html +1 -1
  63. fides/ui-build/static/admin/login.html +1 -1
  64. fides/ui-build/static/admin/messaging/[id].html +1 -1
  65. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  66. fides/ui-build/static/admin/messaging.html +1 -1
  67. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  68. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  69. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  70. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  71. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  72. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  73. fides/ui-build/static/admin/poc/forms.html +1 -1
  74. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  75. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  76. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  77. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  78. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  79. fides/ui-build/static/admin/privacy-requests.html +1 -1
  80. fides/ui-build/static/admin/properties/[id].html +1 -1
  81. fides/ui-build/static/admin/properties/add-property.html +1 -1
  82. fides/ui-build/static/admin/properties.html +1 -1
  83. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  84. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  85. fides/ui-build/static/admin/settings/about.html +1 -1
  86. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  87. fides/ui-build/static/admin/settings/consent.html +1 -1
  88. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  89. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  90. fides/ui-build/static/admin/settings/domains.html +1 -1
  91. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  92. fides/ui-build/static/admin/settings/locations.html +1 -1
  93. fides/ui-build/static/admin/settings/organization.html +1 -1
  94. fides/ui-build/static/admin/settings/regulations.html +1 -1
  95. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  96. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  97. fides/ui-build/static/admin/systems.html +1 -1
  98. fides/ui-build/static/admin/taxonomy.html +1 -1
  99. fides/ui-build/static/admin/user-management/new.html +1 -1
  100. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  101. fides/ui-build/static/admin/user-management.html +1 -1
  102. {ethyca_fides-2.64.0rc0.dist-info → ethyca_fides-2.64.1b1.dist-info}/WHEEL +0 -0
  103. {ethyca_fides-2.64.0rc0.dist-info → ethyca_fides-2.64.1b1.dist-info}/entry_points.txt +0 -0
  104. {ethyca_fides-2.64.0rc0.dist-info → ethyca_fides-2.64.1b1.dist-info}/licenses/LICENSE +0 -0
  105. {ethyca_fides-2.64.0rc0.dist-info → ethyca_fides-2.64.1b1.dist-info}/top_level.txt +0 -0
  106. /fides/ui-build/static/admin/_next/static/{lDN8BtGGiw3b60__SDnAa → zBkPKRGECPjwEx0G7BvHe}/_buildManifest.js +0 -0
  107. /fides/ui-build/static/admin/_next/static/{lDN8BtGGiw3b60__SDnAa → zBkPKRGECPjwEx0G7BvHe}/_ssgManifest.js +0 -0
@@ -15,6 +15,14 @@ from fides.api.schemas.manual_tasks.manual_task_config import (
15
15
  from fides.service.manual_tasks.utils import validate_fields, with_task_logging
16
16
 
17
17
 
18
+ class ManualTaskConfigError(Exception):
19
+ """Exception raised when a manual task config error occurs."""
20
+
21
+ def __init__(self, message: str):
22
+ self.message = message
23
+ super().__init__(self.message)
24
+
25
+
18
26
  class ManualTaskConfigService:
19
27
  def __init__(self, db: Session):
20
28
  self.db = db
@@ -51,8 +59,8 @@ class ManualTaskConfigService:
51
59
  """
52
60
  try:
53
61
  ManualTaskConfigurationType(config_type)
54
- except ValueError:
55
- raise ValueError(f"Invalid config type: {config_type}")
62
+ except ManualTaskConfigError:
63
+ raise ManualTaskConfigError(f"Invalid config type: {config_type}")
56
64
 
57
65
  # Set all existing versions to non-current
58
66
  if is_current:
@@ -96,7 +104,11 @@ class ManualTaskConfigService:
96
104
  modified_keys = set(fields_to_remove or [])
97
105
 
98
106
  if field_updates:
99
- validate_fields(field_updates, is_submission=False)
107
+ try:
108
+ validate_fields(field_updates, is_submission=False)
109
+ except ValueError as e:
110
+ raise ManualTaskConfigError(f"Invalid field updates: {e}") from e
111
+
100
112
  fields_to_create = [
101
113
  {
102
114
  "task_id": config.task_id,
@@ -167,7 +179,7 @@ class ManualTaskConfigService:
167
179
  )
168
180
 
169
181
  if not config:
170
- raise ValueError(
182
+ raise ManualTaskConfigError(
171
183
  f"No current config found for task {task.id} and type {config_type}"
172
184
  )
173
185
  return config
@@ -355,7 +367,7 @@ class ManualTaskConfigService:
355
367
  """
356
368
  config = self.db.query(ManualTaskConfig).filter_by(id=config_id).first()
357
369
  if not config:
358
- raise ValueError(f"Config with ID {config_id} not found")
370
+ raise ManualTaskConfigError(f"Config with ID {config_id} not found")
359
371
 
360
372
  log_data = self._create_log_data(
361
373
  task.id,
@@ -0,0 +1,285 @@
1
+ from typing import Any, Optional
2
+
3
+ from loguru import logger
4
+ from sqlalchemy.orm import Session
5
+
6
+ from fides.api.models.attachment import Attachment
7
+ from fides.api.models.manual_tasks.manual_task_config import ManualTaskConfigField
8
+ from fides.api.models.manual_tasks.manual_task_instance import (
9
+ ManualTaskInstance,
10
+ ManualTaskSubmission,
11
+ )
12
+ from fides.api.schemas.manual_tasks.manual_task_status import (
13
+ StatusTransitionNotAllowed,
14
+ StatusType,
15
+ )
16
+ from fides.service.manual_tasks.utils import validate_fields, with_task_logging
17
+
18
+
19
+ class ManualTaskInstanceError(Exception):
20
+ """Exception raised when a manual task instance error occurs."""
21
+
22
+ def __init__(self, message: str):
23
+ self.message = message
24
+ super().__init__(self.message)
25
+
26
+
27
+ class ManualTaskSubmissionError(Exception):
28
+ """Exception raised when a manual task submission error occurs."""
29
+
30
+ def __init__(self, message: str):
31
+ self.message = message
32
+ super().__init__(self.message)
33
+
34
+
35
+ class ManualTaskInstanceService:
36
+ def __init__(self, db: Session):
37
+ self.db = db
38
+
39
+ def _create_log_data(
40
+ self,
41
+ task_id: str,
42
+ config_id: str,
43
+ instance_id: str,
44
+ details: dict[str, Any],
45
+ ) -> dict[str, Any]:
46
+ """Create standard log data structure."""
47
+ return {
48
+ "task_id": task_id,
49
+ "config_id": config_id,
50
+ "instance_id": instance_id,
51
+ "details": details,
52
+ }
53
+
54
+ def _get_instance(
55
+ self, instance_id: str, allow_completed: bool = False
56
+ ) -> ManualTaskInstance:
57
+ """Get and validate instance."""
58
+ instance = self.db.query(ManualTaskInstance).filter_by(id=instance_id).first()
59
+ if not instance:
60
+ raise ManualTaskInstanceError(f"Instance with ID {instance_id} not found")
61
+
62
+ if not allow_completed and instance.status == StatusType.completed:
63
+ raise StatusTransitionNotAllowed(
64
+ "Instance is already completed, no further changes allowed"
65
+ )
66
+
67
+ return instance
68
+
69
+ def _get_field(
70
+ self, field_id: str, validate_data: Optional[dict[str, Any]] = None
71
+ ) -> ManualTaskConfigField:
72
+ """Get and validate field."""
73
+ field = ManualTaskConfigField.get_by_key_or_id(
74
+ db=self.db, data={"id": field_id}
75
+ )
76
+ if not field:
77
+ raise ManualTaskInstanceError(f"Field with ID {field_id} not found")
78
+
79
+ if validate_data:
80
+ try:
81
+ validate_fields([validate_data], is_submission=True)
82
+ except ValueError as e:
83
+ raise ManualTaskInstanceError(f"Invalid field data: {e}") from e
84
+
85
+ return field
86
+
87
+ def _update_instance_status(
88
+ self,
89
+ instance: ManualTaskInstance,
90
+ new_status: Optional[StatusType] = None,
91
+ user_id: Optional[str] = None,
92
+ silent: bool = False,
93
+ ) -> None:
94
+ """Update instance status with optional error suppression."""
95
+ try:
96
+ if not new_status:
97
+ new_status = (
98
+ StatusType.in_progress
99
+ if instance.submissions
100
+ else StatusType.pending
101
+ )
102
+ instance.update_status(self.db, new_status, user_id)
103
+ except StatusTransitionNotAllowed as e:
104
+ if not silent:
105
+ raise
106
+ logger.info(f"Status not transitioning: {e}")
107
+
108
+ @with_task_logging("Created task instance")
109
+ def create_instance(
110
+ self, task_id: str, config_id: str, entity_id: str, entity_type: str
111
+ ) -> tuple[ManualTaskInstance, dict[str, Any]]:
112
+ """Create a new instance for an entity."""
113
+ instance = ManualTaskInstance.create(
114
+ self.db,
115
+ data={
116
+ "task_id": task_id,
117
+ "config_id": config_id,
118
+ "entity_id": entity_id,
119
+ "entity_type": entity_type,
120
+ },
121
+ )
122
+ return instance, self._create_log_data(
123
+ task_id, config_id, instance.id, {"entity_type": entity_type}
124
+ )
125
+
126
+ def get_submission_for_field(
127
+ self, instance_id: str, field_id: str
128
+ ) -> Optional[ManualTaskSubmission]:
129
+ """Get the submission for a specific field."""
130
+ return self._get_instance(instance_id).get_submission_for_field(field_id)
131
+
132
+ @with_task_logging("Updated task instance status")
133
+ def update_status(
134
+ self,
135
+ instance_id: str,
136
+ new_status: Optional[StatusType] = None,
137
+ user_id: Optional[str] = None,
138
+ ) -> tuple[ManualTaskInstance, dict[str, Any]]:
139
+ """Update instance status with logging."""
140
+ instance = self._get_instance(instance_id)
141
+ previous_status = instance.status
142
+ self._update_instance_status(instance, new_status, user_id)
143
+
144
+ return instance, self._create_log_data(
145
+ instance.task_id,
146
+ instance.config_id,
147
+ instance.id,
148
+ {
149
+ "previous_status": previous_status,
150
+ "new_status": instance.status,
151
+ "user_id": user_id,
152
+ },
153
+ )
154
+
155
+ @with_task_logging("Created task submission")
156
+ def create_submission(
157
+ self,
158
+ instance_id: str,
159
+ field_id: str,
160
+ data: dict[str, Any],
161
+ ) -> tuple[ManualTaskSubmission, dict[str, Any]]:
162
+ """Create a new submission for a field."""
163
+ instance = self._get_instance(instance_id)
164
+ field = self._get_field(field_id, data)
165
+
166
+ if instance.get_submission_for_field(field_id):
167
+ raise ManualTaskInstanceError(
168
+ f"Submission for field {field.field_key} already exists for instance {instance.id}"
169
+ )
170
+
171
+ submission = ManualTaskSubmission.create(
172
+ self.db,
173
+ data={
174
+ "task_id": instance.task_id,
175
+ "config_id": instance.config_id,
176
+ "instance_id": instance.id,
177
+ "field_id": field.id,
178
+ "data": data,
179
+ },
180
+ )
181
+
182
+ # Update instance status to in_progress
183
+ self._update_instance_status(instance, StatusType.in_progress, silent=True)
184
+
185
+ return submission, self._create_log_data(
186
+ instance.task_id,
187
+ instance.config_id,
188
+ instance.id,
189
+ {
190
+ "field_key": field.field_key,
191
+ "field_type": field.field_type,
192
+ },
193
+ )
194
+
195
+ @with_task_logging("Updated task submission")
196
+ def update_submission(
197
+ self,
198
+ instance_id: str,
199
+ submission_id: str,
200
+ data: dict[str, Any],
201
+ ) -> tuple[ManualTaskSubmission, dict[str, Any]]:
202
+ """Update a submission for a field."""
203
+ instance = self._get_instance(instance_id)
204
+ submission = next(
205
+ (s for s in instance.submissions if s.id == submission_id),
206
+ None,
207
+ )
208
+ if not submission or not submission.field_id:
209
+ raise ManualTaskSubmissionError(
210
+ f"Valid submission with ID {submission_id} not found"
211
+ )
212
+
213
+ field = self._get_field(submission.field_id, data)
214
+ submission.update(self.db, data={"data": data})
215
+ self._update_instance_status(instance, silent=True)
216
+
217
+ return submission, self._create_log_data(
218
+ instance.task_id,
219
+ instance.config_id,
220
+ instance.id,
221
+ {
222
+ "field_key": field.field_key,
223
+ "field_type": field.field_type,
224
+ },
225
+ )
226
+
227
+ @with_task_logging("Delete task attachment")
228
+ def delete_attachment_by_id(
229
+ self,
230
+ submission_id: str,
231
+ attachment_id: str,
232
+ ) -> None:
233
+ """Delete an attachment for a field."""
234
+ submission = (
235
+ self.db.query(ManualTaskSubmission).filter_by(id=submission_id).first()
236
+ )
237
+ if not submission:
238
+ raise ManualTaskSubmissionError(
239
+ f"Submission with ID {submission_id} does not exist"
240
+ )
241
+
242
+ self._get_instance(
243
+ submission.instance_id
244
+ ) # Validates instance is not completed
245
+
246
+ attachment = self.db.query(Attachment).filter_by(id=attachment_id).first()
247
+ if not attachment or attachment not in submission.attachments:
248
+ raise ManualTaskSubmissionError(
249
+ f"Attachment {attachment_id} not found in submission {submission_id}"
250
+ )
251
+
252
+ # Delete attachment and optionally submission
253
+ if (
254
+ len(submission.attachments) == 1
255
+ and submission.field.field_type == "attachment"
256
+ ):
257
+ attachment.delete(self.db)
258
+ submission.delete(self.db)
259
+ else:
260
+ attachment.delete(self.db)
261
+
262
+ @with_task_logging("Completed task instance")
263
+ def complete_task_instance(
264
+ self, task_id: str, config_id: str, instance_id: str, user_id: str
265
+ ) -> tuple[ManualTaskInstance, dict[str, Any]]:
266
+ """Complete a task instance."""
267
+ instance = self._get_instance(instance_id)
268
+
269
+ missing_fields = [
270
+ field.field_key
271
+ for field in instance.required_fields
272
+ if not instance.get_submission_for_field(field.id)
273
+ ]
274
+ if missing_fields:
275
+ raise StatusTransitionNotAllowed(
276
+ f"Cannot complete task instance. Missing required fields: {', '.join(missing_fields)}"
277
+ )
278
+
279
+ instance.update_status(self.db, StatusType.completed, user_id)
280
+ instance.completed_by_id = user_id
281
+ instance.save(self.db)
282
+
283
+ return instance, self._create_log_data(
284
+ task_id, config_id, instance_id, {"completed_by": user_id}
285
+ )
@@ -1,4 +1,4 @@
1
- from typing import Any, Optional, cast
1
+ from typing import TYPE_CHECKING, Any, Optional, cast
2
2
 
3
3
  from loguru import logger
4
4
  from sqlalchemy import select
@@ -15,13 +15,31 @@ from fides.api.schemas.manual_tasks.manual_task_schemas import (
15
15
  from fides.service.manual_tasks.manual_task_config_service import (
16
16
  ManualTaskConfigService,
17
17
  )
18
+ from fides.service.manual_tasks.manual_task_instance_service import (
19
+ ManualTaskInstanceService,
20
+ )
18
21
  from fides.service.manual_tasks.utils import with_task_logging
19
22
 
23
+ if TYPE_CHECKING:
24
+ from fides.api.models.manual_tasks.manual_task_instance import (
25
+ ManualTaskInstance,
26
+ ManualTaskSubmission,
27
+ )
28
+
29
+
30
+ class ManualTaskError(Exception):
31
+ """Exception raised when a manual task error occurs."""
32
+
33
+ def __init__(self, message: str):
34
+ self.message = message
35
+ super().__init__(self.message)
36
+
20
37
 
21
38
  class ManualTaskService:
22
39
  def __init__(self, db: Session):
23
40
  self.db = db
24
41
  self.config_service = ManualTaskConfigService(db)
42
+ self.instance_service = ManualTaskInstanceService(db)
25
43
 
26
44
  def get_task(
27
45
  self,
@@ -46,7 +64,7 @@ class ManualTaskService:
46
64
  """
47
65
  if not any([task_id, parent_entity_id, parent_entity_type, task_type]):
48
66
  logger.debug("No filters provided to get_task")
49
- raise ValueError("No filters provided to get_task")
67
+ raise ManualTaskError("No filters provided to get_task")
50
68
 
51
69
  # Build filter conditions and a human-readable description
52
70
  filters = []
@@ -72,7 +90,7 @@ class ManualTaskService:
72
90
  task = self.db.execute(stmt).scalar_one_or_none()
73
91
  if task is None:
74
92
  logger.debug(f"No task found with filters: {filter_desc}")
75
- raise ValueError(f"No task found with filters: {filter_desc}")
93
+ raise ManualTaskError(f"No task found with filters: {filter_desc}")
76
94
  return task
77
95
 
78
96
  @with_task_logging("Provided user IDs verified")
@@ -91,7 +109,7 @@ class ManualTaskService:
91
109
  None
92
110
  """
93
111
  if len(non_existent_user_ids) > 0:
94
- raise ValueError(
112
+ raise ManualTaskError(
95
113
  f"User(s) {sorted(list(non_existent_user_ids))} do not exist"
96
114
  )
97
115
 
@@ -128,11 +146,11 @@ class ManualTaskService:
128
146
  error_key: Key to use for error details
129
147
 
130
148
  Raises:
131
- ValueError: If no successful operations and users don't exist
149
+ ManualTaskError: If no successful operations and users don't exist
132
150
  """
133
151
  try:
134
152
  self._non_existent_users(non_existent_users, task_id=task_id)
135
- except ValueError as e:
153
+ except ManualTaskError as e:
136
154
  details[error_key] = sorted(non_existent_users)
137
155
  if success_count == 0:
138
156
  raise e
@@ -172,7 +190,7 @@ class ManualTaskService:
172
190
  tuple: (processed_users, log_data)
173
191
  """
174
192
  if not (user_ids := list(set(user_ids))):
175
- raise ValueError(f"User ID is required for {operation_type}ment")
193
+ raise ManualTaskError(f"User ID is required for {operation_type}ment")
176
194
 
177
195
  existing_users = set(
178
196
  u.id
@@ -188,7 +206,7 @@ class ManualTaskService:
188
206
  if non_existing := list(set(user_ids) - existing_users):
189
207
  try:
190
208
  self._non_existent_users(non_existing, task_id=task_id)
191
- except ValueError as e:
209
+ except ManualTaskError as e:
192
210
  details[f"user_ids_not_{operation_type}ed"] = sorted(non_existing)
193
211
  if not processed_users:
194
212
  raise e
@@ -281,8 +299,8 @@ class ManualTaskService:
281
299
  config: The config to delete
282
300
  task_id: The task ID
283
301
  Raises:
284
- ValueError: If there are active instances using this configuration
285
- ValueError: If the task does not exist
302
+ ManualTaskConfigError: If there are active instances using this configuration
303
+ ManualTaskError: If the task does not exist
286
304
 
287
305
  Returns:
288
306
  dict[str, Any]: The log details - intercepted by the `with_task_logging` decorator.
@@ -292,3 +310,41 @@ class ManualTaskService:
292
310
  # Delete the configuration
293
311
  config_id = config.id
294
312
  self.config_service.delete_config(task, config_id)
313
+
314
+ def create_instance(
315
+ self, task_id: str, config_id: str, entity_id: str, entity_type: str
316
+ ) -> "ManualTaskInstance":
317
+ """Create a new instance for a task.
318
+
319
+ Args:
320
+ task_id: The task ID
321
+ config_id: The config ID
322
+ entity_id: The entity ID
323
+ entity_type: The entity type
324
+
325
+ Returns:
326
+ ManualTaskInstance: The new instance
327
+ """
328
+ self.get_task(task_id=task_id)
329
+ instance = self.instance_service.create_instance(
330
+ task_id, config_id, entity_id, entity_type
331
+ )
332
+ return cast("ManualTaskInstance", instance)
333
+
334
+ def create_submission(
335
+ self, instance_id: str, field_id: str, data: dict[str, Any]
336
+ ) -> "ManualTaskSubmission":
337
+ """Create a new submission for a task.
338
+
339
+ Args:
340
+ instance_id: The instance ID
341
+ field_id: The field ID
342
+ data: The data for the submission
343
+
344
+ Returns:
345
+ ManualTaskSubmission: The new submission
346
+ """
347
+ submission = self.instance_service.create_submission(
348
+ instance_id, field_id, data
349
+ )
350
+ return cast("ManualTaskSubmission", submission)
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/pages/404-ac2f0844e5c4b4cd.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/pages/404-ac2f0844e5c4b4cd.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.css" data-n-g=""/><link rel="preload" href="/_next/static/css/92fc10cc7ed1aba3.css" as="style"/><link rel="stylesheet" href="/_next/static/css/92fc10cc7ed1aba3.css" data-n-p=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/2858-0b44609b6be7850b.js" defer=""></script><script src="/_next/static/chunks/2866-a73888c17a195cbe.js" defer=""></script><script src="/_next/static/chunks/9278-9b1b5970f0702668.js" defer=""></script><script src="/_next/static/chunks/699-8ca44b0de9fa20f0.js" defer=""></script><script src="/_next/static/chunks/5277-e8a036319456127f.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/409-037cfc3f096150f0.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/9951-f9ab5cac7e2c05ab.js" defer=""></script><script src="/_next/static/chunks/1040-630c7f4284dc6f70.js" defer=""></script><script src="/_next/static/chunks/3450-bdaeb35442d810b4.js" defer=""></script><script src="/_next/static/chunks/pages/add-systems/manual-0a5f2310ce6b1059.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/add-systems/manual","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.css" data-n-g=""/><link rel="preload" href="/_next/static/css/92fc10cc7ed1aba3.css" as="style"/><link rel="stylesheet" href="/_next/static/css/92fc10cc7ed1aba3.css" data-n-p=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/2858-0b44609b6be7850b.js" defer=""></script><script src="/_next/static/chunks/2866-a73888c17a195cbe.js" defer=""></script><script src="/_next/static/chunks/9278-9b1b5970f0702668.js" defer=""></script><script src="/_next/static/chunks/699-8ca44b0de9fa20f0.js" defer=""></script><script src="/_next/static/chunks/5277-e8a036319456127f.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/409-037cfc3f096150f0.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/9951-f9ab5cac7e2c05ab.js" defer=""></script><script src="/_next/static/chunks/1040-630c7f4284dc6f70.js" defer=""></script><script src="/_next/static/chunks/3450-bdaeb35442d810b4.js" defer=""></script><script src="/_next/static/chunks/pages/add-systems/manual-0a5f2310ce6b1059.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/add-systems/manual","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/3923-5d580fbb1dd6ae01.js" defer=""></script><script src="/_next/static/chunks/796-9a6b13c838e25538.js" defer=""></script><script src="/_next/static/chunks/pages/add-systems/multiple-00cb904825aad7e3.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/add-systems/multiple","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/3923-5d580fbb1dd6ae01.js" defer=""></script><script src="/_next/static/chunks/796-9a6b13c838e25538.js" defer=""></script><script src="/_next/static/chunks/pages/add-systems/multiple-00cb904825aad7e3.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/add-systems/multiple","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.css" data-n-g=""/><link rel="preload" href="/_next/static/css/972dc7eef106ee7c.css" as="style"/><link rel="stylesheet" href="/_next/static/css/972dc7eef106ee7c.css" data-n-p=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/pages/add-systems-587e21d14e0a5196.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/add-systems","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.css" data-n-g=""/><link rel="preload" href="/_next/static/css/972dc7eef106ee7c.css" as="style"/><link rel="stylesheet" href="/_next/static/css/972dc7eef106ee7c.css" data-n-p=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/pages/add-systems-587e21d14e0a5196.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/add-systems","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/3923-5d580fbb1dd6ae01.js" defer=""></script><script src="/_next/static/chunks/796-9a6b13c838e25538.js" defer=""></script><script src="/_next/static/chunks/pages/consent/configure/add-vendors-fa7305b88c1afd20.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/consent/configure/add-vendors","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/3923-5d580fbb1dd6ae01.js" defer=""></script><script src="/_next/static/chunks/796-9a6b13c838e25538.js" defer=""></script><script src="/_next/static/chunks/pages/consent/configure/add-vendors-fa7305b88c1afd20.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/consent/configure/add-vendors","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/3923-5d580fbb1dd6ae01.js" defer=""></script><script src="/_next/static/chunks/pages/consent/configure-f140ec9d8e8a0f7a.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/consent/configure","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/401-fceaae662cfca5a5.js" defer=""></script><script src="/_next/static/chunks/3923-5d580fbb1dd6ae01.js" defer=""></script><script src="/_next/static/chunks/pages/consent/configure-f140ec9d8e8a0f7a.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/consent/configure","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/2858-0b44609b6be7850b.js" defer=""></script><script src="/_next/static/chunks/2866-a73888c17a195cbe.js" defer=""></script><script src="/_next/static/chunks/3662-f6a1ddca5ee42076.js" defer=""></script><script src="/_next/static/chunks/3670-2abd9b2f17770872.js" defer=""></script><script src="/_next/static/chunks/69-6889d6674c95e7b5.js" defer=""></script><script src="/_next/static/chunks/6277-3fb4c7fc790a6d20.js" defer=""></script><script src="/_next/static/chunks/1817-b4688ba5042ec687.js" defer=""></script><script src="/_next/static/chunks/pages/consent/privacy-experience/%5Bid%5D-0edb7c92518e7d21.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/consent/privacy-experience/[id]","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/2858-0b44609b6be7850b.js" defer=""></script><script src="/_next/static/chunks/2866-a73888c17a195cbe.js" defer=""></script><script src="/_next/static/chunks/3662-f6a1ddca5ee42076.js" defer=""></script><script src="/_next/static/chunks/3670-2abd9b2f17770872.js" defer=""></script><script src="/_next/static/chunks/69-6889d6674c95e7b5.js" defer=""></script><script src="/_next/static/chunks/6277-3fb4c7fc790a6d20.js" defer=""></script><script src="/_next/static/chunks/1817-b4688ba5042ec687.js" defer=""></script><script src="/_next/static/chunks/pages/consent/privacy-experience/%5Bid%5D-0edb7c92518e7d21.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/consent/privacy-experience/[id]","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/2858-0b44609b6be7850b.js" defer=""></script><script src="/_next/static/chunks/2866-a73888c17a195cbe.js" defer=""></script><script src="/_next/static/chunks/3662-f6a1ddca5ee42076.js" defer=""></script><script src="/_next/static/chunks/3670-2abd9b2f17770872.js" defer=""></script><script src="/_next/static/chunks/69-6889d6674c95e7b5.js" defer=""></script><script src="/_next/static/chunks/6277-3fb4c7fc790a6d20.js" defer=""></script><script src="/_next/static/chunks/1817-b4688ba5042ec687.js" defer=""></script><script src="/_next/static/chunks/pages/consent/privacy-experience/new-a0039f216fb3eb93.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/consent/privacy-experience/new","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/2858-0b44609b6be7850b.js" defer=""></script><script src="/_next/static/chunks/2866-a73888c17a195cbe.js" defer=""></script><script src="/_next/static/chunks/3662-f6a1ddca5ee42076.js" defer=""></script><script src="/_next/static/chunks/3670-2abd9b2f17770872.js" defer=""></script><script src="/_next/static/chunks/69-6889d6674c95e7b5.js" defer=""></script><script src="/_next/static/chunks/6277-3fb4c7fc790a6d20.js" defer=""></script><script src="/_next/static/chunks/1817-b4688ba5042ec687.js" defer=""></script><script src="/_next/static/chunks/pages/consent/privacy-experience/new-a0039f216fb3eb93.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/consent/privacy-experience/new","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/5277-e8a036319456127f.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/6853-a4097260e402980e.js" defer=""></script><script src="/_next/static/chunks/pages/consent/privacy-experience-d8d926f0735a2546.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_buildManifest.js" defer=""></script><script src="/_next/static/lDN8BtGGiw3b60__SDnAa/_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":"/consent/privacy-experience","query":{},"buildId":"lDN8BtGGiw3b60__SDnAa","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/c693338e3bc8dcc6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c693338e3bc8dcc6.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-0a61b5bd21a41fe6.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-8ec6e466f3373ac0.js" defer=""></script><script src="/_next/static/chunks/c78d26b1-88a3e1bacb2a03c2.js" defer=""></script><script src="/_next/static/chunks/6060-cb1ab5be7067bf7b.js" defer=""></script><script src="/_next/static/chunks/5277-e8a036319456127f.js" defer=""></script><script src="/_next/static/chunks/7553-a95939c32d54b5b7.js" defer=""></script><script src="/_next/static/chunks/4481-f597a7cf03f8c9e1.js" defer=""></script><script src="/_next/static/chunks/6853-a4097260e402980e.js" defer=""></script><script src="/_next/static/chunks/pages/consent/privacy-experience-d8d926f0735a2546.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_buildManifest.js" defer=""></script><script src="/_next/static/zBkPKRGECPjwEx0G7BvHe/_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":"/consent/privacy-experience","query":{},"buildId":"zBkPKRGECPjwEx0G7BvHe","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>