ethyca-fides 2.68.1b2__py2.py3-none-any.whl → 2.68.1b3__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 (292) hide show
  1. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b3.dist-info}/METADATA +3 -1
  2. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b3.dist-info}/RECORD +231 -216
  3. fides/_version.py +3 -3
  4. fides/api/alembic/migrations/versions/90502bcda282_update_request_tasks_add_polling_async.py +35 -0
  5. fides/api/api/v1/endpoints/privacy_request_endpoints.py +1 -1
  6. fides/api/common_exceptions.py +12 -3
  7. fides/api/models/detection_discovery/core.py +6 -0
  8. fides/api/models/privacy_request/request_task.py +25 -0
  9. fides/api/schemas/privacy_center_config.py +48 -19
  10. fides/api/schemas/storage/storage.py +2 -0
  11. fides/api/service/async_dsr/__init__.py +0 -0
  12. fides/api/service/async_dsr/async_dsr_service.py +75 -0
  13. fides/api/service/connectors/saas_connector.py +5 -6
  14. fides/api/service/privacy_request/dsr_package/dsr_report_builder.py +6 -4
  15. fides/api/service/privacy_request/request_service.py +50 -2
  16. fides/api/service/storage/storage_uploader_service.py +80 -5
  17. fides/api/service/storage/streaming/__init__.py +42 -0
  18. fides/api/service/storage/streaming/base_storage_client.py +61 -0
  19. fides/api/service/storage/streaming/dsr_storage.py +98 -0
  20. fides/api/service/storage/streaming/retry.py +282 -0
  21. fides/api/service/storage/streaming/s3/__init__.py +5 -0
  22. fides/api/service/storage/streaming/s3/s3_storage_client.py +113 -0
  23. fides/api/service/storage/streaming/s3/streaming_s3.py +196 -0
  24. fides/api/service/storage/streaming/schemas.py +173 -0
  25. fides/api/service/storage/streaming/smart_open_client.py +265 -0
  26. fides/api/service/storage/streaming/smart_open_streaming_storage.py +998 -0
  27. fides/api/service/storage/streaming/storage_client_factory.py +60 -0
  28. fides/api/task/graph_task.py +4 -4
  29. fides/api/task/manual/manual_task_graph_task.py +3 -4
  30. fides/config/execution_settings.py +4 -0
  31. fides/service/privacy_request/privacy_request_service.py +1 -9
  32. fides/ui-build/static/admin/404.html +1 -1
  33. fides/ui-build/static/admin/_next/static/_BLI2ArqQzY5XnXbrcxa2/_buildManifest.js +1 -0
  34. fides/ui-build/static/admin/_next/static/chunks/1099-7b2085a3931da9e4.js +1 -0
  35. fides/ui-build/static/admin/_next/static/chunks/1138-0d846ffef62c580f.js +1 -0
  36. fides/ui-build/static/admin/_next/static/chunks/1345-ab756811e19ff4fc.js +1 -0
  37. fides/ui-build/static/admin/_next/static/chunks/{1817-c90365325f8a3d75.js → 1817-fd21f1f5ef0faffa.js} +1 -1
  38. fides/ui-build/static/admin/_next/static/chunks/{1975.e5cc7a1ccd477671.js → 1975.16126463309143e3.js} +1 -1
  39. fides/ui-build/static/admin/_next/static/chunks/{2921-46f9465c2852a46b.js → 2921-0e5cc63a82e31830.js} +1 -1
  40. fides/ui-build/static/admin/_next/static/chunks/3620-6cceae71bae5b531.js +1 -0
  41. fides/ui-build/static/admin/_next/static/chunks/3729-7d2d52400f1f7413.js +1 -0
  42. fides/ui-build/static/admin/_next/static/chunks/3855-64541570e2f838fb.js +1 -0
  43. fides/ui-build/static/admin/_next/static/chunks/3872-7a18d18a5e287e4e.js +1 -0
  44. fides/ui-build/static/admin/_next/static/chunks/{3923-a33633feba5e655e.js → 3923-5c87b3d7f1626678.js} +1 -1
  45. fides/ui-build/static/admin/_next/static/chunks/{401-741bb31b586b7c96.js → 401-3902e3e98790d401.js} +1 -1
  46. fides/ui-build/static/admin/_next/static/chunks/{4121-94354b50a41f8497.js → 4121-64ef70ef906bbdd0.js} +1 -1
  47. fides/ui-build/static/admin/_next/static/chunks/431-86ad2beeb93c95c9.js +1 -0
  48. fides/ui-build/static/admin/_next/static/chunks/4608-70521532195124de.js +1 -0
  49. fides/ui-build/static/admin/_next/static/chunks/4786-53ef1662f2d0d98c.js +1 -0
  50. fides/ui-build/static/admin/_next/static/chunks/4808-8713433c84a62efe.js +1 -0
  51. fides/ui-build/static/admin/_next/static/chunks/4844-351f99b6644b654e.js +1 -0
  52. fides/ui-build/static/admin/_next/static/chunks/5258-c6f96dc740eb5fb1.js +1 -0
  53. fides/ui-build/static/admin/_next/static/chunks/5487-338800277d36b8d7.js +1 -0
  54. fides/ui-build/static/admin/_next/static/chunks/549-e6453a3526023e85.js +1 -0
  55. fides/ui-build/static/admin/_next/static/chunks/602-80d113e801d7407d.js +1 -0
  56. fides/ui-build/static/admin/_next/static/chunks/{6084-02abe12327fc3dbc.js → 6084-da63f20d9416a982.js} +1 -1
  57. fides/ui-build/static/admin/_next/static/chunks/{6853-270261ef5537a106.js → 6853-1d947b75eb07188c.js} +1 -1
  58. fides/ui-build/static/admin/_next/static/chunks/6954-24f9a4f27d67b732.js +1 -0
  59. fides/ui-build/static/admin/_next/static/chunks/7476-a0dd03bfccf60d0c.js +1 -0
  60. fides/ui-build/static/admin/_next/static/chunks/7630-9fbe06cfb98266fe.js +1 -0
  61. fides/ui-build/static/admin/_next/static/chunks/{787-5ba991cad1f7664a.js → 787-3dd31844cf7fec55.js} +1 -1
  62. fides/ui-build/static/admin/_next/static/chunks/79-dcd20e8b09501c17.js +1 -0
  63. fides/ui-build/static/admin/_next/static/chunks/796-8773e04b64ce2260.js +1 -0
  64. fides/ui-build/static/admin/_next/static/chunks/8002-dcd02da6e5649a1c.js +1 -0
  65. fides/ui-build/static/admin/_next/static/chunks/9046-57eab238570b8bf4.js +1 -0
  66. fides/ui-build/static/admin/_next/static/chunks/9676.bf0a8a6ff6dfd2af.js +1 -0
  67. fides/ui-build/static/admin/_next/static/chunks/{9826-8c81c97a72510fcf.js → 9826-756c958aecab59a2.js} +1 -1
  68. fides/ui-build/static/admin/_next/static/chunks/9951-cdf73904a3adb27b.js +1 -0
  69. fides/ui-build/static/admin/_next/static/chunks/pages/{404-9174cdb70126c2c5.js → 404-dd625a559ada46ca.js} +1 -1
  70. fides/ui-build/static/admin/_next/static/chunks/pages/{_app-2c10f6b217b7978b.js → _app-b6b09b2878b77b21.js} +136 -135
  71. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{manual-621416493c89ef01.js → manual-92cf5e313be1f9e2.js} +1 -1
  72. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems/{multiple-0b9908c3e1dfe49e.js → multiple-d6c525ee731a2993.js} +1 -1
  73. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-5664a3ea796e5ffb.js +1 -0
  74. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure/{add-vendors-5bb1b31ae8752250.js → add-vendors-78f13de90111fd80.js} +1 -1
  75. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-0fc678f3d6d2fcec.js +1 -0
  76. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-experience/{[id]-4e4d9426743b5cb4.js → [id]-126db59dc25ca326.js} +1 -1
  77. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{privacy-experience-d72460348fadcab8.js → privacy-experience-289605267d6cce7e.js} +1 -1
  78. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{[id]-3e7ddc252da00c98.js → [id]-e9fd9b28ac9705af.js} +1 -1
  79. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices/{new-35a7c305beee9428.js → new-28c003b6043bd16c.js} +1 -1
  80. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-c643eff04525298e.js +1 -0
  81. fides/ui-build/static/admin/_next/static/chunks/pages/consent/{properties-ab96939421639153.js → properties-3ef5d01779a26455.js} +1 -1
  82. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-baa4a2f8f08ac224.js +1 -0
  83. fides/ui-build/static/admin/_next/static/chunks/pages/{consent-13240e3ca77acfeb.js → consent-8d4be9e7ec7d2a35.js} +1 -1
  84. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/[projectUrn]/{[resourceUrn]-aad6047a4604b945.js → [resourceUrn]-f27ec4578c674181.js} +1 -1
  85. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects/{[projectUrn]-bd37b407c80c6986.js → [projectUrn]-27b6c255bd9e73b6.js} +1 -1
  86. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-0f66dac32040519c.js +1 -0
  87. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/resources/{[resourceUrn]-b6b98cea25dd94fa.js → [resourceUrn]-3b938562df81c4b0.js} +1 -1
  88. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-ebf5e7fa4e2ffb49.js +1 -0
  89. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-b27c660039d951c9.js +1 -0
  90. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-8ce5d24af470888e.js +1 -0
  91. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-8e35e33928abbcdc.js +1 -0
  92. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-21c141279e66237a.js +1 -0
  93. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/detection/{[resourceUrn]-31e6c54794a9883e.js → [resourceUrn]-3bc6a207693fd175.js} +1 -1
  94. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{detection-2822a423a7ad0550.js → detection-da16e73df395ad1d.js} +1 -1
  95. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/discovery/{[resourceUrn]-f98dd251babb7e28.js → [resourceUrn]-04b242632a114405.js} +1 -1
  96. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/{discovery-56eb4c014f0d96a3.js → discovery-900fe50183a40d72.js} +1 -1
  97. fides/ui-build/static/admin/_next/static/chunks/pages/{datamap-8f88dc31c5144ea8.js → datamap-4f1f7c3a9531a8f4.js} +1 -1
  98. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-343294dcb10d9532.js +1 -0
  99. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-1c097a0809fa5b6f.js +1 -0
  100. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-b47fa2498b534719.js +1 -0
  101. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-a31f881cab25704a.js +1 -0
  102. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-858c59c9e67e318d.js +1 -0
  103. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{[id]-67a7fe58b96ea739.js → [id]-16c28d272225afb6.js} +1 -1
  104. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection/{new-90a8df230cb89877.js → new-68f502d8b0b5792c.js} +1 -1
  105. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-1eb9acb17b133fd1.js +1 -0
  106. fides/ui-build/static/admin/_next/static/chunks/pages/{index-876bfd7210040cec.js → index-fec557d99211f577.js} +1 -1
  107. fides/ui-build/static/admin/_next/static/chunks/pages/integrations/{[id]-4e286a1e501a0c73.js → [id]-e613543818d6cbd2.js} +1 -1
  108. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-8069f7c33695fd45.js +1 -0
  109. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{[id]-6e796c3fe632280b.js → [id]-4a08ca7762a19700.js} +1 -1
  110. fides/ui-build/static/admin/_next/static/chunks/pages/messaging/{add-template-fa0f3841c5bdfdeb.js → add-template-343a965dcdb3d11e.js} +1 -1
  111. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-3ade4c54b1c8a11e.js +1 -0
  112. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-9103bfb854f71410.js +1 -0
  113. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{AntForm-11503454a62d8d7b.js → AntForm-3b97029bd4d3c3ea.js} +1 -1
  114. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikAntFormItem-a504941807bdb7f1.js → FormikAntFormItem-9d9beb8f0d8a278c.js} +1 -1
  115. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikControlled-0119403c8ff97f83.js → FormikControlled-84a4d8fc60f839ed.js} +1 -1
  116. fides/ui-build/static/admin/_next/static/chunks/pages/poc/form-experiments/{FormikField-94f6d57d6c94ddf7.js → FormikField-1fccf542ab2e33bf.js} +1 -1
  117. fides/ui-build/static/admin/_next/static/chunks/pages/poc/{forms-ed1a3ae09d72df89.js → forms-aa75263ae1ba67bb.js} +1 -1
  118. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-db334a1cbb102255.js +1 -0
  119. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-11c1e4545c8f528c.js +1 -0
  120. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-192a986f61c23268.js +1 -0
  121. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-9216ac993d71387e.js +1 -0
  122. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-e55ec84d5380401d.js +1 -0
  123. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-48f447b31c786b80.js +1 -0
  124. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{[id]-41976b28503623cd.js → [id]-a74b51b704b80cb2.js} +1 -1
  125. fides/ui-build/static/admin/_next/static/chunks/pages/properties/{add-property-cb438d8f5ec6007a.js → add-property-8d23f0c55ff6510a.js} +1 -1
  126. fides/ui-build/static/admin/_next/static/chunks/pages/{properties-b6db7036993709b3.js → properties-77acceac4f99e7af.js} +1 -1
  127. fides/ui-build/static/admin/_next/static/chunks/pages/reporting/{datamap-4bc3e281409265cc.js → datamap-e60d398e255f4e00.js} +1 -1
  128. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-6aad3f563ed03b3f.js +1 -0
  129. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-c1b8f3606d160bb1.js +1 -0
  130. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-d9f7f78810d58d08.js +1 -0
  131. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-ee2c7dde99b1dafb.js +1 -0
  132. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-a4dad8ca9de2d07b.js +1 -0
  133. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{domain-records-386368bf7cb31771.js → domain-records-31c270d228e00581.js} +1 -1
  134. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-996b3f250dd3ea1f.js +1 -0
  135. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-ee94981326ddcbf4.js +1 -0
  136. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{locations-b41fb5ad277088ab.js → locations-0b831c58966782b8.js} +1 -1
  137. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-94271ba4a224a353.js +1 -0
  138. fides/ui-build/static/admin/_next/static/chunks/pages/settings/{regulations-a94dfeea43fbca7d.js → regulations-41b8136e50320fd3.js} +1 -1
  139. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-52b45569cbc82e60.js +1 -0
  140. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/{[id]-18b316e2dad73731.js → [id]-36d74e93e54aabaf.js} +1 -1
  141. fides/ui-build/static/admin/_next/static/chunks/pages/systems-24dfc8e2279ced2e.js +1 -0
  142. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-d9675cf5e6083b27.js +1 -0
  143. fides/ui-build/static/admin/_next/static/chunks/pages/user-management/profile/{[id]-3237881945acc0ee.js → [id]-866826d7959df487.js} +1 -1
  144. fides/ui-build/static/admin/_next/static/chunks/pages/{user-management-a3a50d9d79066935.js → user-management-e63b61a8f99ccd57.js} +1 -1
  145. fides/ui-build/static/admin/_next/static/chunks/{webpack-69658aeaf6155d89.js → webpack-6d0a487039bcf30c.js} +1 -1
  146. fides/ui-build/static/admin/_next/static/css/{a72179b1754aadd3.css → 92441453b27e9c34.css} +1 -1
  147. fides/ui-build/static/admin/add-systems/manual.html +1 -1
  148. fides/ui-build/static/admin/add-systems/multiple.html +1 -1
  149. fides/ui-build/static/admin/add-systems.html +1 -1
  150. fides/ui-build/static/admin/consent/configure/add-vendors.html +1 -1
  151. fides/ui-build/static/admin/consent/configure.html +1 -1
  152. fides/ui-build/static/admin/consent/privacy-experience/[id].html +1 -1
  153. fides/ui-build/static/admin/consent/privacy-experience/new.html +1 -1
  154. fides/ui-build/static/admin/consent/privacy-experience.html +1 -1
  155. fides/ui-build/static/admin/consent/privacy-notices/[id].html +1 -1
  156. fides/ui-build/static/admin/consent/privacy-notices/new.html +1 -1
  157. fides/ui-build/static/admin/consent/privacy-notices.html +1 -1
  158. fides/ui-build/static/admin/consent/properties.html +1 -1
  159. fides/ui-build/static/admin/consent/reporting.html +1 -1
  160. fides/ui-build/static/admin/consent.html +1 -1
  161. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn]/[resourceUrn].html +1 -1
  162. fides/ui-build/static/admin/data-catalog/[systemId]/projects/[projectUrn].html +1 -1
  163. fides/ui-build/static/admin/data-catalog/[systemId]/projects.html +1 -1
  164. fides/ui-build/static/admin/data-catalog/[systemId]/resources/[resourceUrn].html +1 -1
  165. fides/ui-build/static/admin/data-catalog/[systemId]/resources.html +1 -1
  166. fides/ui-build/static/admin/data-catalog.html +1 -1
  167. fides/ui-build/static/admin/data-discovery/action-center/[monitorId]/[systemId].html +1 -1
  168. fides/ui-build/static/admin/data-discovery/action-center/[monitorId].html +1 -1
  169. fides/ui-build/static/admin/data-discovery/action-center.html +1 -1
  170. fides/ui-build/static/admin/data-discovery/activity.html +1 -1
  171. fides/ui-build/static/admin/data-discovery/detection/[resourceUrn].html +1 -1
  172. fides/ui-build/static/admin/data-discovery/detection.html +1 -1
  173. fides/ui-build/static/admin/data-discovery/discovery/[resourceUrn].html +1 -1
  174. fides/ui-build/static/admin/data-discovery/discovery.html +1 -1
  175. fides/ui-build/static/admin/datamap.html +1 -1
  176. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName]/[...subfieldNames].html +1 -1
  177. fides/ui-build/static/admin/dataset/[datasetId]/[collectionName].html +1 -1
  178. fides/ui-build/static/admin/dataset/[datasetId].html +1 -1
  179. fides/ui-build/static/admin/dataset/new.html +1 -1
  180. fides/ui-build/static/admin/dataset.html +1 -1
  181. fides/ui-build/static/admin/datastore-connection/[id].html +1 -1
  182. fides/ui-build/static/admin/datastore-connection/new.html +1 -1
  183. fides/ui-build/static/admin/datastore-connection.html +1 -1
  184. fides/ui-build/static/admin/index.html +1 -1
  185. fides/ui-build/static/admin/integrations/[id].html +1 -1
  186. fides/ui-build/static/admin/integrations.html +1 -1
  187. fides/ui-build/static/admin/login/[provider].html +1 -1
  188. fides/ui-build/static/admin/login.html +1 -1
  189. fides/ui-build/static/admin/messaging/[id].html +1 -1
  190. fides/ui-build/static/admin/messaging/add-template.html +1 -1
  191. fides/ui-build/static/admin/messaging.html +1 -1
  192. fides/ui-build/static/admin/poc/ant-components.html +1 -1
  193. fides/ui-build/static/admin/poc/form-experiments/AntForm.html +1 -1
  194. fides/ui-build/static/admin/poc/form-experiments/FormikAntFormItem.html +1 -1
  195. fides/ui-build/static/admin/poc/form-experiments/FormikControlled.html +1 -1
  196. fides/ui-build/static/admin/poc/form-experiments/FormikField.html +1 -1
  197. fides/ui-build/static/admin/poc/form-experiments/FormikSpreadField.html +1 -1
  198. fides/ui-build/static/admin/poc/forms.html +1 -1
  199. fides/ui-build/static/admin/poc/table-migration.html +1 -1
  200. fides/ui-build/static/admin/privacy-requests/[id].html +1 -1
  201. fides/ui-build/static/admin/privacy-requests/configure/messaging.html +1 -1
  202. fides/ui-build/static/admin/privacy-requests/configure/storage.html +1 -1
  203. fides/ui-build/static/admin/privacy-requests/configure.html +1 -1
  204. fides/ui-build/static/admin/privacy-requests.html +1 -1
  205. fides/ui-build/static/admin/properties/[id].html +1 -1
  206. fides/ui-build/static/admin/properties/add-property.html +1 -1
  207. fides/ui-build/static/admin/properties.html +1 -1
  208. fides/ui-build/static/admin/reporting/datamap.html +1 -1
  209. fides/ui-build/static/admin/settings/about/alpha.html +1 -1
  210. fides/ui-build/static/admin/settings/about.html +1 -1
  211. fides/ui-build/static/admin/settings/consent/[configuration_id]/[purpose_id].html +1 -1
  212. fides/ui-build/static/admin/settings/consent.html +1 -1
  213. fides/ui-build/static/admin/settings/custom-fields.html +1 -1
  214. fides/ui-build/static/admin/settings/domain-records.html +1 -1
  215. fides/ui-build/static/admin/settings/domains.html +1 -1
  216. fides/ui-build/static/admin/settings/email-templates.html +1 -1
  217. fides/ui-build/static/admin/settings/locations.html +1 -1
  218. fides/ui-build/static/admin/settings/organization.html +1 -1
  219. fides/ui-build/static/admin/settings/regulations.html +1 -1
  220. fides/ui-build/static/admin/systems/configure/[id]/test-datasets.html +1 -1
  221. fides/ui-build/static/admin/systems/configure/[id].html +1 -1
  222. fides/ui-build/static/admin/systems.html +1 -1
  223. fides/ui-build/static/admin/taxonomy.html +1 -1
  224. fides/ui-build/static/admin/user-management/new.html +1 -1
  225. fides/ui-build/static/admin/user-management/profile/[id].html +1 -1
  226. fides/ui-build/static/admin/user-management.html +1 -1
  227. fides/ui-build/static/admin/_next/static/chunks/203-0c6cadcda98bdd33.js +0 -1
  228. fides/ui-build/static/admin/_next/static/chunks/3450-9314e1b15df8a8da.js +0 -1
  229. fides/ui-build/static/admin/_next/static/chunks/3855-4267fd8193e7f525.js +0 -1
  230. fides/ui-build/static/admin/_next/static/chunks/3872-ac5feefd40b61ae3.js +0 -1
  231. fides/ui-build/static/admin/_next/static/chunks/409-5bc4369b80a8c11d.js +0 -1
  232. fides/ui-build/static/admin/_next/static/chunks/4230-1ebc8c0ab293a077.js +0 -1
  233. fides/ui-build/static/admin/_next/static/chunks/431-a34d7ceff17c2169.js +0 -1
  234. fides/ui-build/static/admin/_next/static/chunks/4608-557fb24665b2e4bf.js +0 -1
  235. fides/ui-build/static/admin/_next/static/chunks/5309-ffdec884eec79d29.js +0 -1
  236. fides/ui-build/static/admin/_next/static/chunks/5574-831167a8da90e2e6.js +0 -1
  237. fides/ui-build/static/admin/_next/static/chunks/6662-499c189f932a35aa.js +0 -1
  238. fides/ui-build/static/admin/_next/static/chunks/6780-7d28e030f6516e5d.js +0 -1
  239. fides/ui-build/static/admin/_next/static/chunks/6882-7cc1d14e27a80c10.js +0 -1
  240. fides/ui-build/static/admin/_next/static/chunks/6954-7784e8d5ad6b8110.js +0 -1
  241. fides/ui-build/static/admin/_next/static/chunks/7476-4de465016d3433b4.js +0 -1
  242. fides/ui-build/static/admin/_next/static/chunks/7630-2a5c57787632693d.js +0 -1
  243. fides/ui-build/static/admin/_next/static/chunks/7725-c79513b04113112b.js +0 -1
  244. fides/ui-build/static/admin/_next/static/chunks/79-98cfab20bb831137.js +0 -1
  245. fides/ui-build/static/admin/_next/static/chunks/796-0b768155bf20505f.js +0 -1
  246. fides/ui-build/static/admin/_next/static/chunks/8735-f84afcc50885883c.js +0 -1
  247. fides/ui-build/static/admin/_next/static/chunks/9046-97a972cc8a8ed24d.js +0 -1
  248. fides/ui-build/static/admin/_next/static/chunks/9226-318dadf1c050ecda.js +0 -1
  249. fides/ui-build/static/admin/_next/static/chunks/9676.9e6828b42ef05e06.js +0 -1
  250. fides/ui-build/static/admin/_next/static/chunks/9951-4df2b67e0def5500.js +0 -1
  251. fides/ui-build/static/admin/_next/static/chunks/pages/add-systems-18e96ce81dab51a4.js +0 -1
  252. fides/ui-build/static/admin/_next/static/chunks/pages/consent/configure-54d7c7310763c66d.js +0 -1
  253. fides/ui-build/static/admin/_next/static/chunks/pages/consent/privacy-notices-6bc3b73a21576869.js +0 -1
  254. fides/ui-build/static/admin/_next/static/chunks/pages/consent/reporting-fe3d6887fecf0f86.js +0 -1
  255. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog/[systemId]/projects-e4770acf7044e2f5.js +0 -1
  256. fides/ui-build/static/admin/_next/static/chunks/pages/data-catalog-0db635c3483c9da8.js +0 -1
  257. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]/[systemId]-0c0e0a7798345541.js +0 -1
  258. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center/[monitorId]-3c56e5fe072a44c6.js +0 -1
  259. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/action-center-58827eb86516931f.js +0 -1
  260. fides/ui-build/static/admin/_next/static/chunks/pages/data-discovery/activity-6a90131dcecd694c.js +0 -1
  261. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]/[...subfieldNames]-145fe9e4cfcb231d.js +0 -1
  262. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]/[collectionName]-8a1e5d140785c1e9.js +0 -1
  263. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/[datasetId]-227b5db4b472a6a7.js +0 -1
  264. fides/ui-build/static/admin/_next/static/chunks/pages/dataset/new-8401f17fe5d9a1dc.js +0 -1
  265. fides/ui-build/static/admin/_next/static/chunks/pages/dataset-7d77b3ad069be268.js +0 -1
  266. fides/ui-build/static/admin/_next/static/chunks/pages/datastore-connection-cfb25b02abb8da71.js +0 -1
  267. fides/ui-build/static/admin/_next/static/chunks/pages/integrations-3fdc55d4c129e618.js +0 -1
  268. fides/ui-build/static/admin/_next/static/chunks/pages/messaging-8f9c006b6166f002.js +0 -1
  269. fides/ui-build/static/admin/_next/static/chunks/pages/poc/ant-components-6ba7ae4f26c06cb0.js +0 -1
  270. fides/ui-build/static/admin/_next/static/chunks/pages/poc/table-migration-e8db3ad525e7ddbd.js +0 -1
  271. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/[id]-c14dd24592369467.js +0 -1
  272. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/messaging-100d7d03930629a8.js +0 -1
  273. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure/storage-6f8d1b3ec83cfcf0.js +0 -1
  274. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests/configure-3ce15577435d47cb.js +0 -1
  275. fides/ui-build/static/admin/_next/static/chunks/pages/privacy-requests-709bcb0bc6a5382d.js +0 -1
  276. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about/alpha-1ea40fcd6b4268bf.js +0 -1
  277. fides/ui-build/static/admin/_next/static/chunks/pages/settings/about-65c7600fadc6e55a.js +0 -1
  278. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent/[configuration_id]/[purpose_id]-33dab986141b3663.js +0 -1
  279. fides/ui-build/static/admin/_next/static/chunks/pages/settings/consent-1195042727c399ed.js +0 -1
  280. fides/ui-build/static/admin/_next/static/chunks/pages/settings/custom-fields-71b98858ecb4e097.js +0 -1
  281. fides/ui-build/static/admin/_next/static/chunks/pages/settings/domains-cf427e04f862b5d2.js +0 -1
  282. fides/ui-build/static/admin/_next/static/chunks/pages/settings/email-templates-eabeeec5bf2773c6.js +0 -1
  283. fides/ui-build/static/admin/_next/static/chunks/pages/settings/organization-ee56698ae3a6a78b.js +0 -1
  284. fides/ui-build/static/admin/_next/static/chunks/pages/systems/configure/[id]/test-datasets-0e2e98cc38ee5499.js +0 -1
  285. fides/ui-build/static/admin/_next/static/chunks/pages/systems-c32589c86081b750.js +0 -1
  286. fides/ui-build/static/admin/_next/static/chunks/pages/taxonomy-a8f09bf8f3204ca7.js +0 -1
  287. fides/ui-build/static/admin/_next/static/qvk5eMANVfwYkdURE7fgG/_buildManifest.js +0 -1
  288. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b3.dist-info}/WHEEL +0 -0
  289. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b3.dist-info}/entry_points.txt +0 -0
  290. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b3.dist-info}/licenses/LICENSE +0 -0
  291. {ethyca_fides-2.68.1b2.dist-info → ethyca_fides-2.68.1b3.dist-info}/top_level.txt +0 -0
  292. /fides/ui-build/static/admin/_next/static/{qvk5eMANVfwYkdURE7fgG → _BLI2ArqQzY5XnXbrcxa2}/_ssgManifest.js +0 -0
@@ -0,0 +1,113 @@
1
+ """S3-specific storage client implementation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from fideslang.validation import AnyHttpUrlString
8
+ from loguru import logger
9
+
10
+ from fides.api.schemas.storage.storage import AWSAuthMethod, StorageSecrets
11
+ from fides.api.service.storage.s3 import create_presigned_url_for_s3
12
+ from fides.api.service.storage.streaming.base_storage_client import BaseStorageClient
13
+ from fides.api.util.aws_util import get_s3_client
14
+
15
+
16
+ class S3StorageClient(BaseStorageClient):
17
+ """S3-specific storage client implementation.
18
+
19
+ Handles S3-specific URI construction, transport parameters, and presigned URL
20
+ generation for the smart-open storage client.
21
+ """
22
+
23
+ def __init__(self, storage_secrets: dict[StorageSecrets, Any]):
24
+ """Initialize the storage client with secrets.
25
+
26
+ Args:
27
+ storage_secrets: Provider-specific storage credentials and configuration using StorageSecrets enum keys
28
+ """
29
+ super().__init__(storage_secrets)
30
+ self.storage_secrets: dict[StorageSecrets, Any] = storage_secrets
31
+
32
+ def build_uri(self, bucket: str, key: str) -> str:
33
+ """Build the S3 URI for the storage location.
34
+
35
+ Args:
36
+ bucket: S3 bucket name
37
+ key: Object key/path
38
+
39
+ Returns:
40
+ S3 URI string for smart-open
41
+ """
42
+ # Handle custom endpoint (e.g., MinIO) - endpoint_url is not in StorageSecrets enum
43
+ # For now, we'll use standard S3 URI since we only have enum keys
44
+ return f"s3://{bucket}/{key}"
45
+
46
+ def get_transport_params(self) -> dict[str, Any]:
47
+ """Get S3-specific transport parameters for smart-open.
48
+
49
+ Returns:
50
+ Dictionary of S3 transport parameters for smart-open
51
+ """
52
+ params = {}
53
+
54
+ if StorageSecrets.AWS_ACCESS_KEY_ID in self.storage_secrets:
55
+ params["access_key"] = self.storage_secrets[
56
+ StorageSecrets.AWS_ACCESS_KEY_ID
57
+ ]
58
+ if StorageSecrets.AWS_SECRET_ACCESS_KEY in self.storage_secrets:
59
+ params["secret_key"] = self.storage_secrets[
60
+ StorageSecrets.AWS_SECRET_ACCESS_KEY
61
+ ]
62
+ if StorageSecrets.REGION_NAME in self.storage_secrets:
63
+ params["region"] = self.storage_secrets[StorageSecrets.REGION_NAME]
64
+ if StorageSecrets.AWS_ASSUME_ROLE in self.storage_secrets:
65
+ params["assume_role_arn"] = self.storage_secrets[
66
+ StorageSecrets.AWS_ASSUME_ROLE
67
+ ]
68
+
69
+ return params
70
+
71
+ def generate_presigned_url(
72
+ self, bucket: str, key: str, ttl_seconds: Optional[int] = None
73
+ ) -> AnyHttpUrlString:
74
+ """Generate an S3 presigned URL for the object.
75
+
76
+ Args:
77
+ bucket: S3 bucket name
78
+ key: Object key/path
79
+ ttl_seconds: Time to live in seconds
80
+
81
+ Returns:
82
+ S3 presigned URL for the object
83
+
84
+ Raises:
85
+ Exception: If presigned URL generation fails
86
+ """
87
+ try:
88
+ # Storage secrets are already in the right format for get_s3_client
89
+ # get_s3_client expects dict[StorageSecrets, Any] with enum keys
90
+ s3_secrets = self.storage_secrets
91
+
92
+ # Determine auth method based on available credentials
93
+ # If AWS credentials are present, use SECRET_KEYS, otherwise use AUTOMATIC
94
+ if (
95
+ StorageSecrets.AWS_ACCESS_KEY_ID in self.storage_secrets
96
+ and StorageSecrets.AWS_SECRET_ACCESS_KEY in self.storage_secrets
97
+ and self.storage_secrets[StorageSecrets.AWS_ACCESS_KEY_ID]
98
+ and self.storage_secrets[StorageSecrets.AWS_SECRET_ACCESS_KEY]
99
+ ):
100
+ auth_method = AWSAuthMethod.SECRET_KEYS.value
101
+ else:
102
+ auth_method = AWSAuthMethod.AUTOMATIC.value
103
+
104
+ # Extract assume_role_arn if present for role assumption
105
+ assume_role_arn = None
106
+ if StorageSecrets.AWS_ASSUME_ROLE in self.storage_secrets:
107
+ assume_role_arn = self.storage_secrets[StorageSecrets.AWS_ASSUME_ROLE]
108
+
109
+ s3_client = get_s3_client(auth_method, s3_secrets, assume_role_arn)
110
+ return create_presigned_url_for_s3(s3_client, bucket, key, ttl_seconds)
111
+ except Exception as e:
112
+ logger.error(f"Failed to generate S3 presigned URL: {e}")
113
+ raise
@@ -0,0 +1,196 @@
1
+ from __future__ import annotations
2
+
3
+ from io import BytesIO
4
+ from typing import Any, Optional, Union
5
+
6
+ from fideslang.validation import AnyHttpUrlString
7
+ from loguru import logger
8
+
9
+ from fides.api.common_exceptions import StorageUploadError
10
+ from fides.api.models.privacy_request import PrivacyRequest
11
+ from fides.api.schemas.storage.storage import StorageSecrets, StorageSecretsS3
12
+ from fides.api.service.storage.s3 import generic_upload_to_s3
13
+ from fides.api.service.storage.streaming.retry import retry_cloud_storage_operation
14
+ from fides.api.service.storage.streaming.schemas import StorageUploadConfig
15
+ from fides.api.service.storage.streaming.smart_open_client import SmartOpenStorageClient
16
+ from fides.api.service.storage.streaming.smart_open_streaming_storage import (
17
+ SmartOpenStreamingStorage,
18
+ )
19
+
20
+
21
+ @retry_cloud_storage_operation(
22
+ provider="s3_streaming",
23
+ operation_name="upload_to_s3_streaming",
24
+ max_retries=2,
25
+ base_delay=2.0,
26
+ max_delay=30.0,
27
+ )
28
+ def upload_to_s3_streaming(
29
+ storage_secrets: Union[StorageSecretsS3, dict[StorageSecrets, Any]],
30
+ data: dict,
31
+ bucket_name: str,
32
+ file_key: str,
33
+ resp_format: str,
34
+ privacy_request: PrivacyRequest,
35
+ document: Optional[BytesIO],
36
+ auth_method: str,
37
+ max_workers: int = 5,
38
+ ) -> Optional[AnyHttpUrlString]:
39
+ """Uploads arbitrary data to S3 using smart-open streaming for memory efficiency.
40
+
41
+ This function now uses smart-open for efficient cloud storage operations while maintaining
42
+ our DSR-specific business logic for package splitting and attachment processing.
43
+ """
44
+ formatted_secrets = format_secrets(storage_secrets)
45
+
46
+ if document is not None:
47
+ _, response = generic_upload_to_s3(
48
+ formatted_secrets, # type: ignore[arg-type]
49
+ bucket_name,
50
+ file_key,
51
+ auth_method,
52
+ document,
53
+ )
54
+ return response
55
+
56
+ try:
57
+ storage_client = SmartOpenStorageClient("s3", formatted_secrets)
58
+
59
+ # Create upload config for the streaming interface
60
+ upload_config = StorageUploadConfig(
61
+ bucket_name=bucket_name,
62
+ file_key=file_key,
63
+ resp_format=resp_format,
64
+ max_workers=max_workers,
65
+ )
66
+
67
+ # Use the smart-open streaming implementation
68
+ streaming_storage = SmartOpenStreamingStorage(storage_client)
69
+ result = streaming_storage.upload_to_storage_streaming(
70
+ data,
71
+ upload_config,
72
+ privacy_request,
73
+ document,
74
+ )
75
+
76
+ logger.debug(
77
+ "Successfully uploaded streaming archive to S3 using smart-open: {}",
78
+ file_key,
79
+ )
80
+ return result
81
+
82
+ except Exception as e:
83
+ logger.error("Unexpected error during smart-open streaming upload: {}", e)
84
+ raise StorageUploadError(
85
+ f"Unexpected error during smart-open streaming upload: {e}"
86
+ )
87
+
88
+
89
+ def _process_storage_secrets_input(
90
+ storage_secrets: Union[StorageSecretsS3, dict[StorageSecrets, Any]] # type: ignore[misc]
91
+ ) -> dict[str, Any]:
92
+ """Process input and convert to string-keyed dictionary."""
93
+ final_secrets: dict[str, Any] = {}
94
+
95
+ if isinstance(storage_secrets, StorageSecretsS3):
96
+ # Convert StorageSecretsS3 model directly to string keys
97
+ for key, value in storage_secrets.model_dump().items():
98
+ if value is not None:
99
+ final_secrets[key] = value
100
+ else:
101
+ # Process dict input, converting enum keys to strings if needed
102
+ for key, value in (storage_secrets or {}).items(): # type: ignore[assignment]
103
+ if isinstance(key, str):
104
+ final_secrets[key] = value
105
+ elif isinstance(key, StorageSecrets):
106
+ final_secrets[key.value] = value
107
+
108
+ return final_secrets
109
+
110
+
111
+ def _validate_aws_credentials(final_secrets: dict[str, Any]) -> None:
112
+ """Validate that required AWS credentials are present."""
113
+ has_access_key = (
114
+ "aws_access_key_id" in final_secrets and final_secrets["aws_access_key_id"]
115
+ )
116
+ has_secret_key = (
117
+ "aws_secret_access_key" in final_secrets
118
+ and final_secrets["aws_secret_access_key"]
119
+ )
120
+
121
+ # If we have any AWS credentials, we need both for SECRET_KEYS auth
122
+ if has_access_key or has_secret_key:
123
+ if not has_access_key:
124
+ raise ValueError(
125
+ "Missing required AWS credentials for SECRET_KEYS auth: aws_access_key_id. "
126
+ "Storage configuration must include valid AWS access key and secret key."
127
+ )
128
+ if not has_secret_key:
129
+ raise ValueError(
130
+ "Missing required AWS credentials for SECRET_KEYS auth: aws_secret_access_key. "
131
+ "Storage configuration must include valid AWS access key and secret key."
132
+ )
133
+ else:
134
+ # AUTOMATIC authentication - check if region is provided
135
+ has_region = "region_name" in final_secrets and final_secrets["region_name"]
136
+ if not has_region:
137
+ raise ValueError(
138
+ "Missing required region_name for AUTOMATIC authentication. "
139
+ "Storage configuration must include a valid AWS region."
140
+ )
141
+
142
+
143
+ def _set_default_region(final_secrets: dict[str, Any]) -> None:
144
+ """Set default region if missing."""
145
+ if "region_name" not in final_secrets or not final_secrets["region_name"]:
146
+ logger.debug("Setting default region to 'us-east-1'")
147
+ final_secrets["region_name"] = "us-east-1"
148
+
149
+
150
+ def format_secrets(
151
+ storage_secrets: Union[StorageSecretsS3, dict[StorageSecrets, Any]] # type: ignore[misc]
152
+ ) -> dict[str, Any]:
153
+ """
154
+ Returns the correct format for the S3StorageClient.
155
+
156
+ This function handles multiple credential formats and processes them through several stages:
157
+ 1. Input processing: Accepts either StorageSecretsS3 models (from API) or raw dicts (from database)
158
+ 2. Key normalization: Converts all keys to string format for consistency
159
+ 3. Validation: Ensures required AWS credentials are present based on auth method
160
+ 4. Default setting: Sets default region if missing (after validation)
161
+ 5. Return: Returns string-keyed dict ready for S3StorageClient
162
+
163
+ Input formats:
164
+ - StorageSecretsS3: Used by storage API endpoints (e.g., put_config_secrets)
165
+ - dict[StorageSecrets, Any]: Used by storage models (e.g., StorageConfig.secrets)
166
+ - dict[str, Any]: Used by database queries (e.g., StorageConfig.get_by)
167
+
168
+ Authentication methods:
169
+ - SECRET_KEYS: Requires aws_access_key_id, aws_secret_access_key, and region_name
170
+ - AUTOMATIC: Requires only region_name (relies on AWS SDK credential chain)
171
+ - Role assumption: Can be used with either auth method via assume_role_arn
172
+
173
+ Output format:
174
+ - dict[str, Any]: Required by S3StorageClient.generate_presigned_url() and other AWS operations
175
+
176
+ Returns:
177
+ dict[str, Any]: Credentials with string keys like 'aws_access_key_id'
178
+
179
+ Raises:
180
+ ValueError: If required AWS credentials are missing for the chosen auth method
181
+ """
182
+ logger.debug("format_secrets called with type: {}", type(storage_secrets).__name__)
183
+
184
+ # Stage 1: Process input and create final format directly
185
+ final_secrets = _process_storage_secrets_input(storage_secrets)
186
+
187
+ # Stage 2: Validate required credentials BEFORE setting defaults
188
+ _validate_aws_credentials(final_secrets)
189
+
190
+ # Stage 3: Set default region if missing (after validation)
191
+ _set_default_region(final_secrets)
192
+
193
+ logger.debug(
194
+ "format_secrets completed successfully with {} keys", len(final_secrets)
195
+ )
196
+ return final_secrets
@@ -0,0 +1,173 @@
1
+ from typing import Annotated, Any, Optional
2
+
3
+ from pydantic import BaseModel, Field, field_validator
4
+
5
+ # multipart upload requirements
6
+ MIN_PART_SIZE = 5 * 1024 * 1024 # 5MB minimum part size for AWS S3 uploads
7
+ ZIP_BUFFER_THRESHOLD = 5 * 1024 * 1024 # 5MB threshold for zip buffer uploads
8
+ CHUNK_SIZE_THRESHOLD = 5 * 1024 * 1024 # 5MB threshold for chunk-based uploads
9
+ LARGE_FILE_THRESHOLD = 25 * 1024 * 1024 # 25MB threshold for large file handling
10
+
11
+
12
+ class AttachmentInfo(BaseModel):
13
+ """Schema for attachment information in streaming storage"""
14
+
15
+ storage_key: str = Field(
16
+ ..., description="Storage key for the attachment (cloud-agnostic)"
17
+ )
18
+ file_name: Optional[str] = Field(None, description="Human-readable filename")
19
+ size: Optional[int] = Field(None, ge=0, description="File size in bytes")
20
+ content_type: Optional[str] = Field(None, description="MIME type of the file")
21
+
22
+ @field_validator("storage_key")
23
+ @classmethod
24
+ def validate_storage_key(cls, v: str) -> str:
25
+ if not v or not v.strip():
26
+ raise ValueError("storage_key cannot be empty or whitespace")
27
+ return v.strip()
28
+
29
+ @field_validator("file_name")
30
+ @classmethod
31
+ def validate_file_name(cls, v: Optional[str]) -> Optional[str]:
32
+ if v is not None and (not v or not v.strip()):
33
+ raise ValueError("file_name cannot be empty or whitespace if provided")
34
+ return v.strip() if v else None
35
+
36
+
37
+ class StorageUploadConfig(BaseModel):
38
+ """Configuration for storage upload operations"""
39
+
40
+ bucket_name: str = Field(..., description="Storage bucket name")
41
+ file_key: str = Field(..., description="File key in storage")
42
+ max_workers: int = Field(
43
+ default=5, ge=1, le=20, description="Maximum parallel workers"
44
+ )
45
+ resp_format: str = Field(..., description="Response format (csv, json, html)")
46
+
47
+ @field_validator("bucket_name", "file_key")
48
+ @classmethod
49
+ def validate_storage_identifiers(cls, v: str) -> str:
50
+ if not v or not v.strip():
51
+ raise ValueError("Storage identifier cannot be empty or whitespace")
52
+ return v.strip()
53
+
54
+
55
+ class PackageSplitConfig(BaseModel):
56
+ """Configuration for package splitting operations"""
57
+
58
+ max_attachments: int = Field(
59
+ default=100, ge=1, le=1000, description="Max attachments per package"
60
+ )
61
+
62
+ @field_validator("max_attachments")
63
+ @classmethod
64
+ def validate_max_attachments(cls, v: int) -> int:
65
+ if v < 1:
66
+ raise ValueError("max_attachments must be at least 1")
67
+ return v
68
+
69
+
70
+ class StreamingBufferConfig(BaseModel):
71
+ """Configuration for streaming buffer operations"""
72
+
73
+ zip_buffer_threshold: int = Field(
74
+ default=5 * 1024 * 1024,
75
+ ge=1024 * 1024,
76
+ description="Zip buffer threshold in bytes (default: 5MB)",
77
+ )
78
+ stream_buffer_threshold: int = Field(
79
+ default=1024 * 1024,
80
+ ge=1024 * 1024,
81
+ description="Stream buffer threshold in bytes (default: 1MB)",
82
+ )
83
+ chunk_size_threshold: int = Field(
84
+ default=1024 * 1024,
85
+ ge=1024 * 1024,
86
+ description="Chunk size threshold in bytes (default: 1MB)",
87
+ )
88
+
89
+
90
+ class AttachmentProcessingInfo(BaseModel):
91
+ """Information for processing a single attachment"""
92
+
93
+ attachment: AttachmentInfo = Field(..., description="Attachment to process")
94
+ base_path: str = Field(..., description="Base path for the attachment in the zip")
95
+ item: dict[str, Any] = Field(..., description="Associated item data")
96
+
97
+ @field_validator("base_path")
98
+ @classmethod
99
+ def validate_base_path(cls, v: str) -> str:
100
+ if not v or not v.strip():
101
+ raise ValueError("base_path cannot be empty or whitespace")
102
+ return v.strip()
103
+
104
+
105
+ class MultipartUploadResponse(BaseModel):
106
+ """Response from initiating a multipart upload"""
107
+
108
+ upload_id: Annotated[
109
+ str, Field(..., description="Unique identifier for the multipart upload")
110
+ ]
111
+ metadata: Optional[dict[str, Any]] = Field(
112
+ default=None, description="Additional metadata from the storage provider"
113
+ )
114
+
115
+ model_config = {
116
+ "extra": "allow", # Allow extra fields from storage providers
117
+ }
118
+
119
+ @field_validator("upload_id")
120
+ @classmethod
121
+ def validate_upload_id(cls, v: Any) -> str:
122
+ """Validate upload ID is not empty or whitespace."""
123
+ if not isinstance(v, str):
124
+ raise ValueError("Upload ID must be a string")
125
+ if not v or not v.strip():
126
+ raise ValueError("Upload ID cannot be empty or whitespace")
127
+ return v.strip()
128
+
129
+ def is_valid_upload_id(self) -> bool:
130
+ """Check if the upload ID is valid (not empty or whitespace)"""
131
+ return bool(self.upload_id and self.upload_id.strip())
132
+
133
+ def get_provider_metadata(self, key: str, default: Any = None) -> Any:
134
+ """Get metadata value by key with fallback to default"""
135
+ if self.metadata is not None:
136
+ return self.metadata.get(key, default) # pylint: disable=no-member
137
+ return default
138
+
139
+
140
+ class UploadPartResponse(BaseModel):
141
+ """Response from uploading a part"""
142
+
143
+ etag: Annotated[str, Field(..., description="ETag/checksum of the uploaded part")]
144
+ part_number: Annotated[
145
+ int, Field(..., description="Sequential number of the part (1-10,000)")
146
+ ]
147
+ metadata: Optional[dict[str, Any]] = Field(
148
+ default=None, description="Additional metadata from the storage provider"
149
+ )
150
+
151
+ model_config = {
152
+ "extra": "allow", # Allow extra fields from storage providers
153
+ }
154
+
155
+ @field_validator("part_number")
156
+ @classmethod
157
+ def validate_part_number(cls, v: Any) -> int:
158
+ """Validate part number is within AWS S3 limits (1-10,000)."""
159
+ if not isinstance(v, int):
160
+ raise ValueError("Part number must be an integer")
161
+ if v < 1 or v > 10000:
162
+ raise ValueError("Part number must be between 1 and 10,000")
163
+ return v
164
+
165
+ def is_valid_etag(self) -> bool:
166
+ """Check if the ETag is valid (not empty and properly formatted)"""
167
+ return bool(self.etag and self.etag.strip())
168
+
169
+ def get_provider_metadata(self, key: str, default: Any = None) -> Any:
170
+ """Get metadata value by key with fallback to default"""
171
+ if self.metadata is not None:
172
+ return self.metadata.get(key, default) # pylint: disable=no-member
173
+ return default