diff --git a/.tsc-baseline.json b/.tsc-baseline.json
index 5bdb8a4a6..18887506e 100644
--- a/.tsc-baseline.json
+++ b/.tsc-baseline.json
@@ -1 +1,289 @@
-ewogICJnZW5lcmF0ZWRBdCI6ICIyMDI2LTA2LTAyVDIzOjM4OjAwLjAwMFoiLAogICJ0b3RhbEVycm9ycyI6IDMzNSwKICAiY291bnRzIjogewogICAgInNyYy9jb21wb25lbnRzL2FkbWluL3Byb2R1Y3RzL1Byb2R1Y3RNYXJrZXRpbmdTZWN0aW9uLnRzeCI6IHsKICAgICAgIlRTMjM0NSI6IDEKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvYWRtaW4vcHJvZHVjdHMvdXNlUHJvZHVjdHNNYW5hZ2VyLnRzIjogewogICAgICAiVFMyNTU0IjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9hZG1pbi9zdXBwbGllcnMtbWFuYWdlci91c2VTdXBwbGllcnNNYW5hZ2VyLnRzIjogewogICAgICAiVFMyNTU0IjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9jb2xsZWN0aW9ucy9FeHRlcm5hbENvbGxlY3Rpb25DYXJkLnRzeCI6IHsKICAgICAgIlRTMjMzOSI6IDcKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvY29sbGVjdGlvbnMvRXh0ZXJuYWxDb2xsZWN0aW9uVGFibGVWaWV3LnRzeCI6IHsKICAgICAgIlRTMjMzOSI6IDIKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvY29tbWFuZC9HbG9iYWxDb21tYW5kQmFyLnRzeCI6IHsKICAgICAgIlRTMjM0NSI6IDEKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvZGV2L19fdGVzdHNfXy9CcmlkZ2VNZXRyaWNzT3ZlcmxheS50ZXN0LnRzeCI6IHsKICAgICAgIlRTMjMwNyI6IDIKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvZGV2L19fdGVzdHNfXy9EZXZPbmx5QnJpZGdlT3ZlcmxheS50ZXN0LnRzeCI6IHsKICAgICAgIlRTMjMwNyI6IDEKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvZGV2L21ldHJpY3MvQnJpZGdlTWV0cmljc1N1bW1hcnkudHN4IjogewogICAgICAiVFMyMzA3IjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9sYXlvdXQvc2lkZWJhci9fX3Rlc3RzX18vU2lkZWJhck5hdkdyb3VwLnNob3J0Y3V0LWNhcnJpbmhvcy50ZXN0LnRzeCI6IHsKICAgICAgIlRTMjM0NSI6IDEKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvbW9ja3VwL2FwcHJvdmFsL09mZnNjcmVlbkxheW91dENhcHR1cmUudHN4IjogewogICAgICAiVFMyMzQ1IjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9ub3RpZmljYXRpb25zL05vdGlmaWNhdGlvbkRyYXdlci50c3giOiB7CiAgICAgICJUUzIzMjIiOiAxCiAgICB9LAogICAgInNyYy9jb21wb25lbnRzL25vdGlmaWNhdGlvbnMvTm90aWZpY2F0aW9uUHJlZmVyZW5jZXMudHN4IjogewogICAgICAiVFMyMzUyIjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9ub3ZlbHRpZXMvTm92ZWx0aWVzU2VjdGlvbi50c3giOiB7CiAgICAgICJUUzIzMzkiOiA2CiAgICB9LAogICAgInNyYy9jb21wb25lbnRzL25vdmVsdGllcy9Ob3ZlbHR5Q2FyZHMudHN4IjogewogICAgICAiVFMyMzM5IjogNAogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9ub3ZlbHRpZXMvTm92ZWx0eVByb2R1Y3RHcmlkLnRzeCI6IHsKICAgICAgIlRTMjc0MCI6IDEKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvbm92ZWx0aWVzL05vdmVsdHlTdGF0c0NhcmRzLnRzeCI6IHsKICAgICAgIlRTMjMzOSI6IDgKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvbm92ZWx0aWVzL1ZpcnR1YWxpemVkTm92ZWx0eUdyaWQudHN4IjogewogICAgICAiVFMyMzIyIjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9ub3ZlbHRpZXMvX190ZXN0c19fL05vdmVsdHlQcm9kdWN0R3JpZC5pbnRlZ3JhdGlvbi50ZXN0LnRzeCI6IHsKICAgICAgIlRTMjQ0MCI6IDEKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvcGRmL19fdGVzdHNfXy9QZGZHZW5lcmF0aW9uTW9kdWxlLnRlc3QudHMiOiB7CiAgICAgICJUUzIzNDUiOiAyCiAgICB9LAogICAgInNyYy9jb21wb25lbnRzL3Byb2R1Y3RzL0VuaGFuY2VkUHJvZHVjdENhcmQudHN4IjogewogICAgICAiVFMyMzIyIjogMiwKICAgICAgIlRTMjMzOSI6IDEwLAogICAgICAiVFMyMzY3IjogMiwKICAgICAgIlRTMjU1MSI6IDEsCiAgICAgICJUUzcwMDYiOiAyCiAgICB9LAogICAgInNyYy9jb21wb25lbnRzL3Byb2R1Y3RzL1Byb2R1Y3RDYXJkLnRzeCI6IHsKICAgICAgIlRTMjQ0OCI6IDEsCiAgICAgICJUUzI0NTQiOiAxCiAgICB9LAogICAgInNyYy9jb21wb25lbnRzL3Byb2R1Y3RzL1Byb2R1Y3RDYXJkSW1hZ2UudHN4IjogewogICAgICAiVFMyMzIyIjogMSwKICAgICAgIlRTMjM2NyI6IDIKICAgIH0sCiAgICAic3JjL2NvbXBvbmVudHMvcHJvZHVjdHMvUHJvZHVjdEdyaWQudHN4IjogewogICAgICAiVFMyMzIyIjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9wcm9kdWN0cy9Qcm9kdWN0U3RhdHVzQmFkZ2UudHN4IjogewogICAgICAiVFMyNjc4IjogMgogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9wcm9kdWN0cy9fX3Rlc3RzX18vUHJvZHVjdFN0YXR1c0JhZGdlLnRlc3QudHN4IjogewogICAgICAiVFMyMzIyIjogNgogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9zZWFyY2gvQWR2YW5jZWRTZWFyY2gudHN4IjogewogICAgICAiVFMyMzQ1IjogMQogICAgfSwKICAgICJzcmMvY29tcG9uZW50cy9zZWFyY2gvR2xvYmFsU2VhcmNoUGFsZXR0ZS50c3giOiB7CiAgICAgICJUUzIzMjIiOiAxCiAgICB9LAogICAgInNyYy9jb21wb25lbnRzL3VpL3Nvbm5lci50c3giOiB7CiAgICAgICJUUzIzNjciOiAxCiAgICB9LAogICAgInNyYy9ob29rcy9hZG1pbi91c2VBbGxvd2VkSVBzLnRzIjogewogICAgICAiVFMyMzIyIjogNSwKICAgICAgIlRTMjM0NSI6IDMsCiAgICAgICJUUzIzNTIiOiAxLAogICAgICAiVFMyNzY5IjogNAogICAgfSwKICAgICJzcmMvaG9va3MvYWRtaW4vdXNlRGV2aWNlRGV0ZWN0aW9uLnRzIjogewogICAgICAiVFMyMzUzIjogMQogICAgfSwKICAgICJzcmMvaG9va3MvYWRtaW4vdXNlR2VvQmxvY2tpbmcudHMiOiB7CiAgICAgICJUUzIzNDUiOiAyCiAgICB9LAogICAgInNyYy9ob29rcy9hdXRoL3VzZTJGQS50cyI6IHsKICAgICAgIlRTMjM1MyI6IDEKICAgIH0sCiAgICAic3JjL2hvb2tzL2F1dGgvdXNlQWNjZXNzU2VjdXJpdHkudHMiOiB7CiAgICAgICJUUzIzNDUiOiAxCiAgICB9LAogICAgInNyYy9ob29rcy9jb2xsZWN0aW9ucy91c2VFeHRlcm5hbENvbGxlY3Rpb25zLnRzIjogewogICAgICAiVFMyMzIyIjogMiwKICAgICAgIlRTMjMzOSI6IDMsCiAgICAgICJUUzIzNDUiOiAzLAogICAgICAiVFMyMzUzIjogMSwKICAgICAgIlRTMjc2OSI6IDQKICAgIH0sCiAgICAic3JjL2hvb2tzL2dyYXZhY2FvL3VzZVRlY25pY2FzR3JhdmFjYW8udHMiOiB7CiAgICAgICJUUzIzNDUiOiA2LAogICAgICAiVFMyMzUyIjogMSwKICAgICAgIlRTMjM1MyI6IDEsCiAgICAgICJUUzI3NjkiOiA5CiAgICB9LAogICAgInNyYy9ob29rcy9pbnRlbGxpZ2VuY2UvdXNlU2FsZXNHb2Fscy50cyI6IHsKICAgICAgIlRTMjMyMiI6IDEwLAogICAgICAiVFMyMzQ1IjogNSwKICAgICAgIlRTMjM1MyI6IDEsCiAgICAgICJUUzI3NjkiOiA2CiAgICB9LAogICAgInNyYy9ob29rcy9tb2NrdXAvX190ZXN0c19fL21vY2t1cEdlbmVyYXRpb25TZXJ2aWNlLnRlc3QudHMiOiB7CiAgICAgICJUUzIzMzkiOiAyCiAgICB9LAogICAgInNyYy9ob29rcy9tb2NrdXAvbW9ja3VwR2VuZXJhdGlvblNlcnZpY2UudHMiOiB7CiAgICAgICJUUzIzMjIiOiAxCiAgICB9LAogICAgInNyYy9ob29rcy9tb2NrdXAvdXNlTW9ja3VwR2VuZXJhdG9yLnRzIjogewogICAgICAiVFMyMzM5IjogMTIsCiAgICAgICJUUzIzNDUiOiAxLAogICAgICAiVFM3MDA2IjogMwogICAgfSwKICAgICJzcmMvaG9va3MvcHJvZHVjdHMvdXNlQ2F0YWxvZ1ByZWZldGNoLnRzIjogewogICAgICAiVFMyMzQ1IjogMQogICAgfSwKICAgICJzcmMvaG9va3MvcHJvZHVjdHMvdXNlQ29sb3JFbnJpY2htZW50LnRzIjogewogICAgICAiVFMyMzM5IjogMTAKICAgIH0sCiAgICAic3JjL2hvb2tzL3Byb2R1Y3RzL3VzZUNvbG9yU3lzdGVtLnRzIjogewogICAgICAiVFMyMzQ1IjogMSwKICAgICAgIlRTMjM1MiI6IDEsCiAgICAgICJUUzI3NjkiOiAxCiAgICB9LAogICAgInNyYy9ob29rcy9wcm9kdWN0cy91c2VOb3ZlbHRpZXMudHMiOiB7CiAgICAgICJUUzIzMjIiOiAxLAogICAgICAiVFMyMzM5IjogOSwKICAgICAgIlRTMjM0NSI6IDE0LAogICAgICAiVFMyMzUyIjogMSwKICAgICAgIlRTMjc2OSI6IDE2CiAgICB9LAogICAgInNyYy9ob29rcy9wcm9kdWN0cy91c2VQcm9kdWN0SW5zaWdodHMudHMiOiB7CiAgICAgICJUUzE4MDQ3IjogMSwKICAgICAgIlRTMjUzMSI6IDEKICAgIH0sCiAgICAic3JjL2hvb2tzL3Byb2R1Y3RzL3VzZVByb2R1Y3RTdXBwbGllclNvdXJjZXMudHMiOiB7CiAgICAgICJUUzIzMzkiOiAxLAogICAgICAiVFMyMzQ1IjogMiwKICAgICAgIlRTMjc2OSI6IDMKICAgIH0sCiAgICAic3JjL2hvb2tzL3Byb2R1Y3RzL3VzZVByb2R1Y3RzQ29sb3JzQmF0Y2gudHMiOiB7CiAgICAgICJUUzIzNDUiOiAxLAogICAgICAiVFMyMzUyIjogMSwKICAgICAgIlRTMjc2OSI6IDEKICAgIH0sCiAgICAic3JjL2hvb2tzL3Byb2R1Y3RzL3VzZVByb2R1Y3RzTGlnaHR3ZWlnaHQudHMiOiB7CiAgICAgICJUUzIzNDUiOiAxCiAgICB9LAogICAgInNyYy9ob29rcy9wcm9kdWN0cy91c2VTdXBwbGllckZpc2NhbERhdGEudHMiOiB7CiAgICAgICJUUzIzMjIiOiAzLAogICAgICAiVFMyMzM5IjogMSwKICAgICAgIlRTMjM0NSI6IDMsCiAgICAgICJUUzIzNTIiOiAyLAogICAgICAiVFMyNzY5IjogMgogICAgfSwKICAgICJzcmMvaG9va3MvcHJvZHVjdHMvdXNlU3VwcGxpZXJOYW1lcy50cyI6IHsKICAgICAgIlRTMjM0NSI6IDEKICAgIH0sCiAgICAic3JjL2hvb2tzL3F1b3Rlcy91c2VRdW90ZUJ1aWxkZXJTdGF0ZS50cyI6IHsKICAgICAgIlRTMjM1MiI6IDEKICAgIH0sCiAgICAic3JjL2hvb2tzL3NpbXVsYXRpb24vdXNlRXh0ZXJuYWxTaW11bGF0b3IudHMiOiB7CiAgICAgICJUUzIzMjIiOiAxCiAgICB9LAogICAgInNyYy9ob29rcy9zaW11bGF0aW9uL3VzZUdyYXZhY2FvVjIudHMiOiB7CiAgICAgICJUUzIzMDQiOiAzLAogICAgICAiVFMyMzQ1IjogNCwKICAgICAgIlRTMjU4OSI6IDQsCiAgICAgICJUUzI3NjkiOiA0CiAgICB9LAogICAgInNyYy9ob29rcy9zaW11bGF0aW9uL3VzZVByaW50QXJlYXMudHMiOiB7CiAgICAgICJUUzIzMjIiOiAxLAogICAgICAiVFMyMzQ1IjogNiwKICAgICAgIlRTMjc2OSI6IDQKICAgIH0sCiAgICAic3JjL2hvb2tzL3NpbXVsYXRpb24vdXNlU2ltdWxhdGlvbi50cyI6IHsKICAgICAgIlRTMjM0NSI6IDEsCiAgICAgICJUUzI3NjkiOiAzCiAgICB9LAogICAgInNyYy9ob29rcy9zaW11bGF0aW9uL3VzZVRlY2huaXF1ZVByaWNpbmcudHMiOiB7CiAgICAgICJUUzIzMzkiOiAxMiwKICAgICAgIlRTMjM0NSI6IDEsCiAgICAgICJUUzI3NjkiOiAxCiAgICB9LAogICAgInNyYy9ob29rcy9zaW11bGF0aW9uL3VzZVRlY2huaXF1ZVByaWNpbmdPcHRpb25zLnRzIjogewogICAgICAiVFMyMzQ1IjogMQogICAgfSwKICAgICJzcmMvaG9va3MvdWkvdXNlV29ya3NwYWNlTm90aWZpY2F0aW9ucy50c3giOiB7CiAgICAgICJUUzIzMjIiOiAxCiAgICB9LAogICAgInNyYy9ob29rcy91c2VOYXZpZ2F0aW9uQW5hbHl0aWNzLnRzIjogewogICAgICAiVFMyMzUzIjogMQogICAgfSwKICAgICJzcmMvbGliL2Nsb3VkLXN0YXR1cy50cyI6IHsKICAgICAgIlRTMjMzOSI6IDEsCiAgICAgICJUUzIzNDUiOiAxCiAgICB9LAogICAgInNyYy9saWIvY3JtLWRiLnRzIjogewogICAgICAiVFMyMzIyIjogMQogICAgfSwKICAgICJzcmMvbGliL2RiL3Bvc3RncmVzdC50cyI6IHsKICAgICAgIlRTMjM0NSI6IDMsCiAgICAgICJUUzIzNTIiOiAxLAogICAgICAiVFMyNzY5IjogMwogICAgfSwKICAgICJzcmMvbGliL2V4dGVybmFsLWRiLXByZXdhcm0udHMiOiB7CiAgICAgICJUUzI3NjkiOiAxCiAgICB9LAogICAgInNyYy9saWIvZXh0ZXJuYWwtZGIvcHJvZHVjdHMtZGV0YWlsLnRzIjogewogICAgICAiVFMyMzQ1IjogMQogICAgfSwKICAgICJzcmMvbGliL2V4dGVybmFsLWRiL3Byb2R1Y3RzLnRzIjogewogICAgICAiVFMyMzIyIjogMSwKICAgICAgIlRTMjM0NSI6IDEKICAgIH0sCiAgICAic3JjL2xpYi9wZXJzb25hbGl6YXRpb24vcmVwb3NpdG9yaWVzL3RlY2huaXF1ZS5yZXBvc2l0b3J5LnRzIjogewogICAgICAiVFMyMzIyIjogMSwKICAgICAgIlRTMjMzOSI6IDEKICAgIH0sCiAgICAic3JjL2xpYi9xdWVyeS1jb25maWcudHMiOiB7CiAgICAgICJUUzIzMzkiOiAyCiAgICB9LAogICAgInNyYy9wYWdlcy9hZG1pbi9BZG1pblByb2R1Y3RGb3JtUGFnZS50c3giOiB7CiAgICAgICJUUzIzMjIiOiAyCiAgICB9LAogICAgInNyYy9wYWdlcy9hZG1pbi9BZG1pblRlbWFzUGFnZS50c3giOiB7CiAgICAgICJUUzIzNjciOiAxCiAgICB9LAogICAgInNyYy9wYWdlcy9jb2xsZWN0aW9ucy9Db2xsZWN0aW9uRGV0YWlsUGFnZS50c3giOiB7CiAgICAgICJUUzIzMzkiOiAxCiAgICB9LAogICAgInNyYy9wYWdlcy9jb2xsZWN0aW9ucy9Db2xsZWN0aW9uc1BhZ2UudHN4IjogewogICAgICAiVFMyMzM5IjogMQogICAgfSwKICAgICJzcmMvcGFnZXMvZmlsdGVycy91c2VGaWx0ZXJzUGFnZVN0YXRlLnRzIjogewogICAgICAiVFMyMzUzIjogMQogICAgfSwKICAgICJzcmMvcGFnZXMvcHJvZHVjdHMvRmF2b3JpdGVzUGFnZS50c3giOiB7CiAgICAgICJUUzIzMjIiOiAyCiAgICB9LAogICAgInNyYy9wYWdlcy9wcm9kdWN0cy9zZWxsZXItY2FydHMvQ2FydFNpZGViYXIudHN4IjogewogICAgICAiVFMyMzIyIjogMQogICAgfSwKICAgICJzcmMvc2VydmljZXMvX190ZXN0c19fL3Byb2R1Y3RTZXJ2aWNlLmludGVncmF0aW9uLnRlc3QudHMiOiB7CiAgICAgICJUUzIzNTMiOiA3CiAgICB9LAogICAgInNyYy9zZXJ2aWNlcy9fX3Rlc3RzX18vcHJvZHVjdFNlcnZpY2UudGVzdC50cyI6IHsKICAgICAgIlRTMjM0NSI6IDMKICAgIH0sCiAgICAic3JjL3NlcnZpY2VzL25vdGlmaWNhdGlvblNlcnZpY2UudHMiOiB7CiAgICAgICJUUzIzNTMiOiAxCiAgICB9LAogICAgInNyYy9zZXJ2aWNlcy9wcm9kdWN0U2VydmljZS50cyI6IHsKICAgICAgIlRTMjMzOSI6IDIKICAgIH0KICB9Cn0=
\ No newline at end of file
+{
+ "generatedAt": "2026-06-02T23:38:00.000Z",
+ "totalErrors": 335,
+ "counts": {
+ "src/components/admin/products/ProductMarketingSection.tsx": {
+ "TS2345": 1
+ },
+ "src/components/admin/products/useProductsManager.ts": {
+ "TS2554": 1
+ },
+ "src/components/admin/suppliers-manager/useSuppliersManager.ts": {
+ "TS2554": 1
+ },
+ "src/components/collections/ExternalCollectionCard.tsx": {
+ "TS2339": 7
+ },
+ "src/components/collections/ExternalCollectionTableView.tsx": {
+ "TS2339": 2
+ },
+ "src/components/command/GlobalCommandBar.tsx": {
+ "TS2345": 1
+ },
+ "src/components/dev/__tests__/BridgeMetricsOverlay.test.tsx": {
+ "TS2307": 2
+ },
+ "src/components/dev/__tests__/DevOnlyBridgeOverlay.test.tsx": {
+ "TS2307": 1
+ },
+ "src/components/dev/metrics/BridgeMetricsSummary.tsx": {
+ "TS2307": 1
+ },
+ "src/components/layout/sidebar/__tests__/SidebarNavGroup.shortcut-carrinhos.test.tsx": {
+ "TS2345": 1
+ },
+ "src/components/mockup/approval/OffscreenLayoutCapture.tsx": {
+ "TS2345": 1
+ },
+ "src/components/notifications/NotificationDrawer.tsx": {
+ "TS2322": 1
+ },
+ "src/components/notifications/NotificationPreferences.tsx": {
+ "TS2352": 1
+ },
+ "src/components/novelties/NoveltiesSection.tsx": {
+ "TS2339": 6
+ },
+ "src/components/novelties/NoveltyCards.tsx": {
+ "TS2339": 4
+ },
+ "src/components/novelties/NoveltyProductGrid.tsx": {
+ "TS2740": 1
+ },
+ "src/components/novelties/NoveltyStatsCards.tsx": {
+ "TS2339": 8
+ },
+ "src/components/novelties/VirtualizedNoveltyGrid.tsx": {
+ "TS2322": 1
+ },
+ "src/components/novelties/__tests__/NoveltyProductGrid.integration.test.tsx": {
+ "TS2440": 1
+ },
+ "src/components/pdf/__tests__/PdfGenerationModule.test.ts": {
+ "TS2345": 2
+ },
+ "src/components/products/EnhancedProductCard.tsx": {
+ "TS2322": 2,
+ "TS2339": 10,
+ "TS2367": 2,
+ "TS2551": 1,
+ "TS7006": 2
+ },
+ "src/components/products/ProductCard.tsx": {
+ "TS2448": 1,
+ "TS2454": 1
+ },
+ "src/components/products/ProductCardImage.tsx": {
+ "TS2322": 1,
+ "TS2367": 2
+ },
+ "src/components/products/ProductGrid.tsx": {
+ "TS2322": 1
+ },
+ "src/components/products/ProductStatusBadge.tsx": {
+ "TS2678": 2
+ },
+ "src/components/products/__tests__/ProductStatusBadge.test.tsx": {
+ "TS2322": 6
+ },
+ "src/components/search/AdvancedSearch.tsx": {
+ "TS2345": 1
+ },
+ "src/components/search/GlobalSearchPalette.tsx": {
+ "TS2322": 1
+ },
+ "src/components/ui/sonner.tsx": {
+ "TS2367": 1
+ },
+ "src/hooks/admin/useAllowedIPs.ts": {
+ "TS2322": 5,
+ "TS2345": 3,
+ "TS2352": 1,
+ "TS2769": 4
+ },
+ "src/hooks/admin/useDeviceDetection.ts": {
+ "TS2353": 1
+ },
+ "src/hooks/admin/useGeoBlocking.ts": {
+ "TS2345": 2
+ },
+ "src/hooks/auth/use2FA.ts": {
+ "TS2353": 1
+ },
+ "src/hooks/auth/useAccessSecurity.ts": {
+ "TS2345": 1
+ },
+ "src/hooks/collections/useExternalCollections.ts": {
+ "TS2322": 2,
+ "TS2339": 3,
+ "TS2345": 3,
+ "TS2353": 1,
+ "TS2769": 4
+ },
+ "src/hooks/gravacao/useTecnicasGravacao.ts": {
+ "TS2345": 6,
+ "TS2352": 1,
+ "TS2353": 1,
+ "TS2769": 9
+ },
+ "src/hooks/intelligence/useSalesGoals.ts": {
+ "TS2322": 10,
+ "TS2345": 5,
+ "TS2353": 1,
+ "TS2769": 6
+ },
+ "src/hooks/mockup/__tests__/mockupGenerationService.test.ts": {
+ "TS2339": 2
+ },
+ "src/hooks/mockup/mockupGenerationService.ts": {
+ "TS2322": 1
+ },
+ "src/hooks/mockup/useMockupGenerator.ts": {
+ "TS2339": 12,
+ "TS2345": 1,
+ "TS7006": 3
+ },
+ "src/hooks/products/useCatalogPrefetch.ts": {
+ "TS2345": 1
+ },
+ "src/hooks/products/useColorEnrichment.ts": {
+ "TS2339": 10
+ },
+ "src/hooks/products/useColorSystem.ts": {
+ "TS2345": 1,
+ "TS2352": 1,
+ "TS2769": 1
+ },
+ "src/hooks/products/useNovelties.ts": {
+ "TS2322": 1,
+ "TS2339": 9,
+ "TS2345": 14,
+ "TS2352": 1,
+ "TS2769": 16
+ },
+ "src/hooks/products/useProductInsights.ts": {
+ "TS18047": 1,
+ "TS2531": 1
+ },
+ "src/hooks/products/useProductSupplierSources.ts": {
+ "TS2339": 1,
+ "TS2345": 2,
+ "TS2769": 3
+ },
+ "src/hooks/products/useProductsColorsBatch.ts": {
+ "TS2345": 1,
+ "TS2352": 1,
+ "TS2769": 1
+ },
+ "src/hooks/products/useProductsLightweight.ts": {
+ "TS2345": 1
+ },
+ "src/hooks/products/useSupplierFiscalData.ts": {
+ "TS2322": 3,
+ "TS2339": 1,
+ "TS2345": 3,
+ "TS2352": 2,
+ "TS2769": 2
+ },
+ "src/hooks/products/useSupplierNames.ts": {
+ "TS2345": 1
+ },
+ "src/hooks/quotes/useQuoteBuilderState.ts": {
+ "TS2352": 1
+ },
+ "src/hooks/simulation/useExternalSimulator.ts": {
+ "TS2322": 1
+ },
+ "src/hooks/simulation/useGravacaoV2.ts": {
+ "TS2304": 3,
+ "TS2345": 4,
+ "TS2589": 4,
+ "TS2769": 4
+ },
+ "src/hooks/simulation/usePrintAreas.ts": {
+ "TS2322": 1,
+ "TS2345": 6,
+ "TS2769": 4
+ },
+ "src/hooks/simulation/useSimulation.ts": {
+ "TS2345": 1,
+ "TS2769": 3
+ },
+ "src/hooks/simulation/useTechniquePricing.ts": {
+ "TS2339": 12,
+ "TS2345": 1,
+ "TS2769": 1
+ },
+ "src/hooks/simulation/useTechniquePricingOptions.ts": {
+ "TS2345": 1
+ },
+ "src/hooks/ui/useWorkspaceNotifications.tsx": {
+ "TS2322": 1
+ },
+ "src/hooks/useNavigationAnalytics.ts": {
+ "TS2353": 1
+ },
+ "src/lib/cloud-status.ts": {
+ "TS2339": 1,
+ "TS2345": 1
+ },
+ "src/lib/crm-db.ts": {
+ "TS2322": 1
+ },
+ "src/lib/db/postgrest.ts": {
+ "TS2345": 3,
+ "TS2352": 1,
+ "TS2769": 3
+ },
+ "src/lib/external-db-prewarm.ts": {
+ "TS2769": 1
+ },
+ "src/lib/external-db/products-detail.ts": {
+ "TS2345": 1
+ },
+ "src/lib/external-db/products.ts": {
+ "TS2322": 1,
+ "TS2345": 1
+ },
+ "src/lib/personalization/repositories/technique.repository.ts": {
+ "TS2322": 1,
+ "TS2339": 1
+ },
+ "src/lib/query-config.ts": {
+ "TS2339": 2
+ },
+ "src/pages/admin/AdminProductFormPage.tsx": {
+ "TS2322": 2
+ },
+ "src/pages/admin/AdminTemasPage.tsx": {
+ "TS2367": 1
+ },
+ "src/pages/collections/CollectionDetailPage.tsx": {
+ "TS2339": 1
+ },
+ "src/pages/collections/CollectionsPage.tsx": {
+ "TS2339": 1
+ },
+ "src/pages/filters/useFiltersPageState.ts": {
+ "TS2353": 1
+ },
+ "src/pages/products/FavoritesPage.tsx": {
+ "TS2322": 2
+ },
+ "src/pages/products/seller-carts/CartSidebar.tsx": {
+ "TS2322": 1
+ },
+ "src/services/__tests__/productService.integration.test.ts": {
+ "TS2353": 7
+ },
+ "src/services/__tests__/productService.test.ts": {
+ "TS2345": 3
+ },
+ "src/services/notificationService.ts": {
+ "TS2353": 1
+ },
+ "src/services/productService.ts": {
+ "TS2339": 2
+ }
+ }
+}
diff --git a/public/robots.txt b/public/robots.txt
index 0d8b8170c..c30bca915 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -1 +1,16 @@
-VXNlci1hZ2VudDogR29vZ2xlYm90CkFsbG93OiAvCgpVc2VyLWFnZW50OiBCaW5nYm90CkFsbG93OiAvCgpVc2VyLWFnZW50OiBUd2l0dGVyYm90CkFsbG93OiAvCgpVc2VyLWFnZW50OiBmYWNlYm9va2V4dGVybmFsaGl0CkFsbG93OiAvCgpVc2VyLWFnZW50OiAqCkFsbG93OiAvCgpTaXRlbWFwOiBodHRwczovL3d3dy5wcm9tb2dpZnRzLmNvbS5ici9zaXRlbWFwLnhtbAo=
\ No newline at end of file
+User-agent: Googlebot
+Allow: /
+
+User-agent: Bingbot
+Allow: /
+
+User-agent: Twitterbot
+Allow: /
+
+User-agent: facebookexternalhit
+Allow: /
+
+User-agent: *
+Allow: /
+
+Sitemap: https://www.promogifts.com.br/sitemap.xml
diff --git a/public/sitemap.xml b/public/sitemap.xml
index 551921d30..aae65c111 100644
--- a/public/sitemap.xml
+++ b/public/sitemap.xml
@@ -1 +1,58 @@
-PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHVybHNldCB4bWxucz0iaHR0cDovL3d3dy5zaXRlbWFwcy5vcmcvc2NoZW1hcy9zaXRlbWFwLzAuOSI+CiAgPHVybD4KICAgIDxsb2M+aHR0cHM6Ly93d3cucHJvbW9naWZ0cy5jb20uYnIvPC9sb2M+CiAgICA8Y2hhbmdlZnJlcT5kYWlseTwvY2hhbmdlZnJlcT4KICAgIDxwcmlvcml0eT4xLjA8L3ByaW9yaXR5PgogIDwvdXJsPgogIDx1cmw+CiAgICA8bG9jPmh0dHBzOi8vd3d3LnByb21vZ2lmdHMuY29tLmJyL2F1dGg8L2xvYz4KICAgIDxjaGFuZ2VmcmVxPm1vbnRobHk8L2NoYW5nZWZyZXE+CiAgICA8cHJpb3JpdHk+MC42PC9wcmlvcml0eT4KICA8L3VybD4KICA8dXJsPgogICAgPGxvYz5odHRwczovL3d3dy5wcm9tb2dpZnRzLmNvbS5ici9yZXNldC1wYXNzd29yZDwvbG9jPgogICAgPGNoYW5nZWZyZXE+bW9udGhseTwvY2hhbmdlZnJlcT4KICAgIDxwcmlvcml0eT4wLjM8L3ByaW9yaXR5PgogIDwvdXJsPgogIDx1cmw+CiAgICA8bG9jPmh0dHBzOi8vd3d3LnByb21vZ2lmdHMuY29tLmJyL3Byb2R1dG9zPC9sb2M+CiAgICA8Y2hhbmdlZnJlcT5kYWlseTwvY2hhbmdlZnJlcT4KICAgIDxwcmlvcml0eT4wLjk8L3ByaW9yaXR5PgogIDwvdXJsPgogIDx1cmw+CiAgICA8bG9jPmh0dHBzOi8vd3d3LnByb21vZ2lmdHMuY29tLmJyL25vdmlkYWRlczwvbG9jPgogICAgPGNoYW5nZWZyZXE+ZGFpbHk8L2NoYW5nZWZyZXE+CiAgICA8cHJpb3JpdHk+MC44PC9wcmlvcml0eT4KICA8L3VybD4KICA8dXJsPgogICAgPGxvYz5odHRwczovL3d3dy5wcm9tb2dpZnRzLmNvbS5ici9zaW11bGFkb3ItcHJlY29zPC9sb2M+CiAgICA8Y2hhbmdlZnJlcT53ZWVrbHk8L2NoYW5nZWZyZXE+CiAgICA8cHJpb3JpdHk+MC43PC9wcmlvcml0eT4KICA8L3VybD4KICA8dXJsPgogICAgPGxvYz5odHRwczovL3d3dy5wcm9tb2dpZnRzLmNvbS5ici9zaW11bGFkb3I8L2xvYz4KICAgIDxjaGFuZ2VmcmVxPndlZWtseTwvY2hhbmdlZnJlcT4KICAgIDxwcmlvcml0eT4wLjc8L3ByaW9yaXR5PgogIDwvdXJsPgogIDx1cmw+CiAgICA8bG9jPmh0dHBzOi8vd3d3LnByb21vZ2lmdHMuY29tLmJyL2NvbXBhcmFyPC9sb2M+CiAgICA8Y2hhbmdlZnJlcT53ZWVrbHk8L2NoYW5nZWZyZXE+CiAgICA8cHJpb3JpdHk+MC42PC9wcmlvcml0eT4KICA8L3VybD4KICA8dXJsPgogICAgPGxvYz5odHRwczovL3d3dy5wcm9tb2dpZnRzLmNvbS5ici9vcmNhbWVudG9zPC9sb2M+CiAgICA8Y2hhbmdlZnJlcT5kYWlseTwvY2hhbmdlZnJlcT4KICAgIDxwcmlvcml0eT4wLjg8L3ByaW9yaXR5PgogIDwvdXJsPgogIDx1cmw+CiAgICA8bG9jPmh0dHBzOi8vd3d3LnByb21vZ2lmdHMuY29tLmJyL21vY2t1cC1nZW5lcmF0b3I8L2xvYz4KICAgIDxjaGFuZ2VmcmVxPndlZWtseTwvY2hhbmdlZnJlcT4KICAgIDxwcmlvcml0eT4wLjc8L3ByaW9yaXR5PgogIDwvdXJsPgogIDx1cmw+CiAgICA8bG9jPmh0dHBzOi8vd3d3LnByb21vZ2lmdHMuY29tLmJyL21hZ2ljLXVwPC9sb2M+CiAgICA8Y2hhbmdlZnJlcT53ZWVrbHk8L2NoYW5nZWZyZXE+CiAgICA8cHJpb3JpdHk+MC43PC9wcmlvcml0eT4KICA8L3VybD4KPC91cmxzZXQ+Cg==
\ No newline at end of file
+
+
+
+ https://www.promogifts.com.br/
+ daily
+ 1.0
+
+
+ https://www.promogifts.com.br/auth
+ monthly
+ 0.6
+
+
+ https://www.promogifts.com.br/reset-password
+ monthly
+ 0.3
+
+
+ https://www.promogifts.com.br/produtos
+ daily
+ 0.9
+
+
+ https://www.promogifts.com.br/novidades
+ daily
+ 0.8
+
+
+ https://www.promogifts.com.br/simulador-precos
+ weekly
+ 0.7
+
+
+ https://www.promogifts.com.br/simulador
+ weekly
+ 0.7
+
+
+ https://www.promogifts.com.br/comparar
+ weekly
+ 0.6
+
+
+ https://www.promogifts.com.br/orcamentos
+ daily
+ 0.8
+
+
+ https://www.promogifts.com.br/mockup-generator
+ weekly
+ 0.7
+
+
+ https://www.promogifts.com.br/magic-up
+ weekly
+ 0.7
+
+
diff --git a/supabase/functions/_shared/cors.ts b/supabase/functions/_shared/cors.ts
index 251673df4..cedeaedf2 100644
--- a/supabase/functions/_shared/cors.ts
+++ b/supabase/functions/_shared/cors.ts
@@ -1 +1,255 @@
-Ly8gc3VwYWJhc2UvZnVuY3Rpb25zL19zaGFyZWQvY29ycy50cwovKioKICogQ2VudHJhbGl6ZWQgQ09SUyBjb25maWd1cmF0aW9uIOKAlCByZXN0cmljdCB0byBrbm93biBvcmlnaW5zLgogKgogKiBCVUctMDcgRklYICgyMDI2LTA2LTAyKTogZ2V0QmVzdEFsbG93ZWRPcmlnaW4oKSBmYWxsYmFjayB3YXMgcmV0dXJuaW5nCiAqICAgdGhlIExvdmFibGUgZGV2IFVSTCAoY3JpYXItdG9nZXRoZXItbm93LmxvdmFibGUuYXBwKSBmb3IgdW5rbm93biBvcmlnaW5zLgogKiAgIENoYW5nZWQgdG8gcHJvZHVjdGlvbiBVUkwgKHd3dy5wcm9tb2dpZnRzLmNvbS5icikuCiAqCiAqIEJVRy0wOCBGSVggKDIwMjYtMDYtMDIpOiBwcXBkb2xrYWVxbHl6cGRwYml6by5zdXBhYmFzZS5jbyByZW1vdmVkIGZyb20KICogICBFWEFDVF9BTExPV0VEX09SSUdJTlMuIFRoYXQgcHJvamVjdCBpcyBpbiBGT1JCSURERU5fUkVGUyBpbiBjbGllbnQudHMKICogICBhbmQgbXVzdCBub3QgYmUgZ3JhbnRlZCBDT1JTIGFjY2VzcyB0byBlZGdlIGZ1bmN0aW9ucy4KICovCgovLyAtLS0gQ29uZmlndXJhdGlvbiAtLS0KCmNvbnN0IEVYQUNUX0FMTE9XRURfT1JJR0lOUyA9IG5ldyBTZXQoWwogIC8vIEJVRy0wOCBGSVg6IHBxcGRvbGthZXFseXpwZHBiaXpvLnN1cGFiYXNlLmNvIHJlbW92ZWQgKEZPUkJJRERFTiBwcm9qZWN0KS4KICAvLyBDYW5vbmljYWwgcHJvamVjdCBpcyBkb3Vmc3hxbGZqeXV2eHVlenBsbiDigJQgaXQgbmV2ZXIgbmVlZHMgdG8gY2FsbCBpdHMgb3duCiAgLy8gZWRnZSBmdW5jdGlvbnMgZnJvbSBhIGJyb3dzZXIgY29udGV4dDsgU3VwYWJhc2UgU0RLIGhhbmRsZXMgdGhhdCBpbnRlcm5hbGx5LgogICdodHRwczovL2NyaWFyLXRvZ2V0aGVyLW5vdy5sb3ZhYmxlLmFwcCcsCiAgJ2h0dHBzOi8vaWQtcHJldmlldy0tMWJlMzVhNjUtMWY2NS00YzJiLTlhNzktN2Q1NjM5MzBhYWNkLmxvdmFibGUuYXBwJywKICAnaHR0cHM6Ly8xYmUzNWE2NS0xZjY1LTRjMmItOWE3OS03ZDU2MzkzMGFhY2QubG92YWJsZXByb2plY3QuY29tJywKICAnaHR0cHM6Ly9wcm9tb2dpZnRzLmNvbS5icicsCiAgJ2h0dHBzOi8vd3d3LnByb21vZ2lmdHMuY29tLmJyJywKICAnaHR0cHM6Ly9wcm9tb2dpZnRzLmF0b21pY2Fici5jb20uYnInLAogICdodHRwOi8vbG9jYWxob3N0OjUxNzMnLAogICdodHRwOi8vbG9jYWxob3N0OjgwODAnLAogICdodHRwOi8vbG9jYWxob3N0OjMwMDAnLAogICdodHRwOi8vMTI3LjAuMC4xOjUxNzMnLAogICdodHRwOi8vMTI3LjAuMC4xOjgwODAnLAogICdodHRwOi8vMTI3LjAuMC4xOjMwMDAnLApdKTsKCmNvbnN0IEFMTE9XRURfT1JJR0lOX1BBVFRFUk5TID0gWwogIC9eaHR0cHM6XC9cL1thLXowLTktXStcLmxvdmFibGVcLmFwcCQvaSwKICAvXmh0dHBzOlwvXC9bYS16MC05LV0rXC5sb3ZhYmxlcHJvamVjdFwuY29tJC9pLAogIC9eaHR0cHM6XC9cL1thLXowLTktXStcLmF0b21pY2FiclwuY29tXC5iciQvaSwKICAvXmh0dHBzOlwvXC9bYS16MC05LV0rXC52ZXJjZWxcLmFwcCQvaSwKICAvXmh0dHA6XC9cL2xvY2FsaG9zdCg/OjpcZCspPyQvaSwKICAvXmh0dHA6XC9cLzEyN1wuMFwuMFwuMSg/OjpcZCspPyQvaSwKXTsKCmNvbnN0IEFMTE9XRURfSEVBREVSU19MSVNUID0gWwogICdhdXRob3JpemF0aW9uJywKICAneC1jbGllbnQtaW5mbycsCiAgJ2FwaWtleScsCiAgJ2NvbnRlbnQtdHlwZScsCiAgJ3gtcmVxdWVzdC1pZCcsCiAgJ3gtc3RlcC11cC10b2tlbicsCiAgJ3gtc3VwYWJhc2UtY2xpZW50LXBsYXRmb3JtJywKICAneC1zdXBhYmFzZS1jbGllbnQtcGxhdGZvcm0tdmVyc2lvbicsCiAgJ3gtc3VwYWJhc2UtY2xpZW50LXJ1bnRpbWUnLAogICd4LXN1cGFiYXNlLWNsaWVudC1ydW50aW1lLXZlcnNpb24nLApdOwoKY29uc3QgQUxMT1dFRF9IRUFERVJTX1NFVCA9IG5ldyBTZXQoQUxMT1dFRF9IRUFERVJTX0xJU1QubWFwKChoKSA9PiBoLnRvTG93ZXJDYXNlKCkpKTsKY29uc3QgQUxMT1dFRF9IRUFERVJTX1ZBTFVFID0gQUxMT1dFRF9IRUFERVJTX0xJU1Quam9pbignLCAnKTsKCmNvbnN0IFNFQ1VSSVRZX0hFQURFUlMgPSB7CiAgJ1gtQ29udGVudC1UeXBlLU9wdGlvbnMnOiAnbm9zbmlmZicsCiAgJ1gtRnJhbWUtT3B0aW9ucyc6ICdERU5ZJywKICAnU3RyaWN0LVRyYW5zcG9ydC1TZWN1cml0eSc6ICdtYXgtYWdlPTMxNTM2MDAwOyBpbmNsdWRlU3ViRG9tYWluczsgcHJlbG9hZCcsCiAgJ0NvbnRlbnQtU2VjdXJpdHktUG9saWN5JzogImRlZmF1bHQtc3JjICdzZWxmJzsgc2NyaXB0LXNyYyAnc2VsZicgJ3N0cmljdC1keW5hbWljJzsgb2JqZWN0LXNyYyAnbm9uZSc7IGZyYW1lLWFuY2VzdG9ycyAnbm9uZSc7IGJhc2UtdXJpICdzZWxmJzsgZm9ybS1hY3Rpb24gJ3NlbGYnOyB1cGdyYWRlLWluc2VjdXJlLXJlcXVlc3RzOyIsCn0gYXMgY29uc3Q7Cgpjb25zdCBDT1JTX0hFQURFUlNfQkFTRSA9IHsKICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycyc6IEFMTE9XRURfSEVBREVSU19WQUxVRSwKICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcyc6ICdHRVQsIFBPU1QsIFBVVCwgREVMRVRFLCBPUFRJT05TJywKICAnQWNjZXNzLUNvbnRyb2wtRXhwb3NlLUhlYWRlcnMnOiAneC1yZXF1ZXN0LWlkJywKICAuLi5TRUNVUklUWV9IRUFERVJTLAp9IGFzIGNvbnN0OwoKLy8gLS0tIEludGVybmFsIFV0aWxpdGllcyAtLS0KCmZ1bmN0aW9uIHBhcnNlSGVhZGVyTGlzdChoZWFkZXJTdHJpbmc6IHN0cmluZyB8IG51bGwpOiBzdHJpbmdbXSB7CiAgaWYgKCFoZWFkZXJTdHJpbmcpIHJldHVybiBbXTsKICByZXR1cm4gaGVhZGVyU3RyaW5nCiAgICAuc3BsaXQoJywnKQogICAgLm1hcCgoaCkgPT4gaC50cmltKCkudG9Mb3dlckNhc2UoKSkKICAgIC5maWx0ZXIoQm9vbGVhbik7Cn0KCmZ1bmN0aW9uIGlzQWxsb3dlZE9yaWdpbihvcmlnaW46IHN0cmluZyk6IGJvb2xlYW4gewogIHJldHVybiAoCiAgICBFWEFDVF9BTExPV0VEX09SSUdJTlMuaGFzKG9yaWdpbikgfHwKICAgIEFMTE9XRURfT1JJR0lOX1BBVFRFUk5TLnNvbWUoKHBhdHRlcm4pID0+IHBhdHRlcm4udGVzdChvcmlnaW4pKQogICk7Cn0KCmZ1bmN0aW9uIGdldEJlc3RBbGxvd2VkT3JpZ2luKG9yaWdpbjogc3RyaW5nIHwgbnVsbCk6IHN0cmluZyB7CiAgaWYgKG9yaWdpbiAmJiBpc0FsbG93ZWRPcmlnaW4ob3JpZ2luKSkgcmV0dXJuIG9yaWdpbjsKICAvLyBCVUctMDcgRklYOiBVbmtub3duIG9yaWdpbiBub3cgZmFsbHMgYmFjayB0byB0aGUgUFJPRFVDVElPTiBVUkwgaW5zdGVhZAogIC8vIG9mIHRoZSBMb3ZhYmxlIGRldmVsb3BtZW50IFVSTCAoY3JpYXItdG9nZXRoZXItbm93LmxvdmFibGUuYXBwKS4KICAvLyBUaGUgYnJvd3NlciBzdGlsbCBibG9ja3MgdGhlIHJlc3BvbnNlIGlmIHRoZSBvcmlnaW4gZG9lc24ndCBtYXRjaCBhbnl3YXksCiAgLy8gc28gdGhpcyBvbmx5IG1hdHRlcnMgZm9yIHNhbWUtb3JpZ2luIHJlcXVlc3RzIGFuZCBzZXJ2ZXItc2lkZSBjYWxsZXJzLgogIHJldHVybiAnaHR0cHM6Ly93d3cucHJvbW9naWZ0cy5jb20uYnInOwp9CgovLyAtLS0gU3RydWN0dXJlZCBMb2dnaW5nIC0tLQoKZnVuY3Rpb24gbG9nQ29yc0V2ZW50KGV2ZW50OiBzdHJpbmcsIGZpZWxkczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiB2b2lkIHsKICBjb25zdCBwYXlsb2FkID0gewogICAgc291cmNlOiAnY29ycycsCiAgICBldmVudCwKICAgIHRzOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksCiAgICAuLi5maWVsZHMsCiAgfTsKICBjb25zdCBsaW5lID0gYFtjb3JzXSAke0pTT04uc3RyaW5naWZ5KHBheWxvYWQpfWA7CiAgCiAgaWYgKGV2ZW50LmVuZHNXaXRoKCdfd2FybicpIHx8IGV2ZW50LmVuZHNXaXRoKCdfYmxvY2tlZCcpKSB7CiAgICBjb25zb2xlLndhcm4obGluZSk7CiAgfSBlbHNlIHsKICAgIGNvbnNvbGUubG9nKGxpbmUpOwogIH0KfQoKbGV0IGJvb3RMb2dnZWQgPSBmYWxzZTsKZnVuY3Rpb24gbG9nQm9vdElmTmVlZGVkKCk6IHZvaWQgewogIGlmIChib290TG9nZ2VkKSByZXR1cm47CiAgYm9vdExvZ2dlZCA9IHRydWU7CiAgbG9nQ29yc0V2ZW50KCdjb3JzX2Jvb3QnLCB7CiAgICBhbGxvd19oZWFkZXJzOiBBTExPV0VEX0hFQURFUlNfVkFMVUUsCiAgICBhbGxvd19oZWFkZXJzX2NvdW50OiBBTExPV0VEX0hFQURFUlNfTElTVC5sZW5ndGgsCiAgICBhbGxvd19tZXRob2RzOiBDT1JTX0hFQURFUlNfQkFTRVsnQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcyddLAogICAgZXhwb3NlX2hlYWRlcnM6IENPUlNfSEVBREVSU19CQVNFWydBY2Nlc3MtQ29udHJvbC1FeHBvc2UtSGVhZGVycyddLAogICAgZXhhY3Rfb3JpZ2luc19jb3VudDogRVhBQ1RfQUxMT1dFRF9PUklHSU5TLnNpemUsCiAgICBwYXR0ZXJuX29yaWdpbnNfY291bnQ6IEFMTE9XRURfT1JJR0lOX1BBVFRFUk5TLmxlbmd0aCwKICB9KTsKfQoKLy8gSW5pdGlhbGl6ZSBib290IGxvZyBvbiBtb2R1bGUgbG9hZApsb2dCb290SWZOZWVkZWQoKTsKCmZ1bmN0aW9uIGxvZ1ByZWZsaWdodEZyb21SZXF1ZXN0KHJlcTogUmVxdWVzdCwgb3JpZ2luOiBzdHJpbmcpOiB2b2lkIHsKICBjb25zdCByZXF1ZXN0ZWRIZWFkZXJzUmF3ID0gcmVxLmhlYWRlcnMuZ2V0KCdBY2Nlc3MtQ29udHJvbC1SZXF1ZXN0LUhlYWRlcnMnKSB8fCByZXEuaGVhZGVycy5nZXQoJ2FjY2Vzcy1jb250cm9sLXJlcXVlc3QtaGVhZGVycycpOwogIGNvbnN0IHJlcXVlc3RlZE1ldGhvZCA9IHJlcS5oZWFkZXJzLmdldCgnQWNjZXNzLUNvbnRyb2wtUmVxdWVzdC1NZXRob2QnKSB8fCByZXEuaGVhZGVycy5nZXQoJ2FjY2Vzcy1jb250cm9sLXJlcXVlc3QtbWV0aG9kJyk7CiAgY29uc3QgcmVxdWVzdGVkSGVhZGVycyA9IHBhcnNlSGVhZGVyTGlzdChyZXF1ZXN0ZWRIZWFkZXJzUmF3KTsKICAKICBjb25zdCBtaXNzaW5nSGVhZGVycyA9IHJlcXVlc3RlZEhlYWRlcnMuZmlsdGVyKChoKSA9PiAhQUxMT1dFRF9IRUFERVJTX1NFVC5oYXMoaCkpOwogIGNvbnN0IG9yaWdpbkFsbG93ZWQgPSAhb3JpZ2luIHx8IGlzQWxsb3dlZE9yaWdpbihvcmlnaW4pOwogIGNvbnN0IHJlcXVlc3RJZCA9IHJlcS5oZWFkZXJzLmdldCgneC1yZXF1ZXN0LWlkJykgfHwgcmVxLmhlYWRlcnMuZ2V0KCdYLVJlcXVlc3QtSWQnKTsKCiAgY29uc3QgYmFzZUZpZWxkcyA9IHsKICAgIHJlcXVlc3RfaWQ6IHJlcXVlc3RJZCwKICAgIG9yaWdpbjogb3JpZ2luIHx8IG51bGwsCiAgICBvcmlnaW5fYWxsb3dlZDogb3JpZ2luQWxsb3dlZCwKICAgIHJlcXVlc3RlZF9tZXRob2Q6IHJlcXVlc3RlZE1ldGhvZCwKICAgIHJlcXVlc3RlZF9oZWFkZXJzOiByZXF1ZXN0ZWRIZWFkZXJzLAogICAgbWlzc2luZ19oZWFkZXJzOiBtaXNzaW5nSGVhZGVycywKICB9OwoKICBpZiAoIW9yaWdpbkFsbG93ZWQgfHwgbWlzc2luZ0hlYWRlcnMubGVuZ3RoID4gMCkgewogICAgbG9nQ29yc0V2ZW50KCdjb3JzX3ByZWZsaWdodF93YXJuJywgewogICAgICAuLi5iYXNlRmllbGRzLAogICAgICByZWFzb246ICFvcmlnaW5BbGxvd2VkID8gJ29yaWdpbl9ub3RfYWxsb3dlZCcgOiAnaGVhZGVyX25vdF9hbGxvd2VkJywKICAgICAgaGludDogbWlzc2luZ0hlYWRlcnMubGVuZ3RoID4gMAogICAgICAgID8gYEFkZCB0byBBTExPV0VEX0hFQURFUlNfTElTVCBpbiBfc2hhcmVkL2NvcnMudHM6ICR7bWlzc2luZ0hlYWRlcnMuam9pbignLCAnKX1gCiAgICAgICAgOiAnQWRkIG9yaWdpbiB0byBFWEFDVF9BTExPV0VEX09SSUdJTlMgb3IgQUxMT1dFRF9PUklHSU5fUEFUVEVSTlMnLAogICAgfSk7CiAgfSBlbHNlIHsKICAgIGxvZ0NvcnNFdmVudCgnY29yc19wcmVmbGlnaHRfb2snLCBiYXNlRmllbGRzKTsKICB9Cn0KCi8vIC0tLSBQdWJsaWMgQVBJIC0tLQoKLyoqCiAqIFJldHVybnMgQ09SUyBoZWFkZXJzIHdpdGggb3JpZ2luIHZhbGlkYXRpb24uCiAqIElmIHRoZSByZXF1ZXN0IG9yaWdpbiBpcyBpbiB0aGUgYWxsb3dsaXN0LCBpdCBpcyByZWZsZWN0ZWQgYmFjay4KICovCmV4cG9ydCBmdW5jdGlvbiBnZXRDb3JzSGVhZGVycyhyZXE/OiBSZXF1ZXN0KTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7CiAgY29uc3Qgb3JpZ2luID0gcmVxPy5oZWFkZXJzLmdldCgnb3JpZ2luJykgfHwgcmVxPy5oZWFkZXJzLmdldCgnT3JpZ2luJykgfHwgJyc7CiAgCiAgaWYgKHJlcT8ubWV0aG9kID09PSAnT1BUSU9OUycpIHsKICAgIGxvZ1ByZWZsaWdodEZyb21SZXF1ZXN0KHJlcSwgb3JpZ2luKTsKICB9CgogIHJldHVybiB7CiAgICAuLi5DT1JTX0hFQURFUlNfQkFTRSwKICAgIC4uLlNFQ1VSSVRZX0hFQURFUlMsCiAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJzogZ2V0QmVzdEFsbG93ZWRPcmlnaW4ob3JpZ2luKSwKICB9Owp9CgovKioKICogSGFuZGxlIENPUlMgcHJlZmxpZ2h0IChPUFRJT05TKSByZXF1ZXN0LgogKiBSZXR1cm5zIGEgUmVzcG9uc2UgaWYgaXQncyBhbiBPUFRJT05TIHJlcXVlc3QsIG51bGwgb3RoZXJ3aXNlLgogKi8KZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZUNvcnNQcmVmbGlnaHRJZk5lZWRlZChyZXE6IFJlcXVlc3QpOiBSZXNwb25zZSB8IG51bGwgewogIGlmIChyZXEubWV0aG9kICE9PSAnT1BUSU9OUycpIHJldHVybiBudWxsOwogIHJldHVybiBuZXcgUmVzcG9uc2UobnVsbCwgeyBoZWFkZXJzOiBnZXRDb3JzSGVhZGVycyhyZXEpIH0pOwp9CgpleHBvcnQgaW50ZXJmYWNlIFB1YmxpY0NvcnNPcHRpb25zIHsKICAvKioKICAgKiBFeHRyYSBoZWFkZXIgdG9rZW5zIHRvIGFwcGVuZCB0byBBY2Nlc3MtQ29udHJvbC1BbGxvdy1IZWFkZXJzLgogICAqLwogIGV4dHJhQWxsb3dIZWFkZXJzPzogc3RyaW5nW107CiAgLyoqCiAgICogT3ZlcnJpZGUgQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcyAoZGVmYXVsdDogc2FtZSBhcyByZXN0cmljdGVkIGhlbHBlcikuCiAgICovCiAgYWxsb3dNZXRob2RzPzogc3RyaW5nOwp9CgovKioKICogQnVpbGQgQ09SUyBoZWFkZXJzIGZvciBwdWJsaWMvd2lsZGNhcmQgZW5kcG9pbnRzLgogKi8KZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUHVibGljQ29yc0hlYWRlcnMob3B0czogUHVibGljQ29yc09wdGlvbnMgPSB7fSk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gewogIGNvbnN0IG1lcmdlZCA9IG5ldyBTZXQoQUxMT1dFRF9IRUFERVJTX0xJU1QubWFwKChoKSA9PiBoLnRvTG93ZXJDYXNlKCkpKTsKICBmb3IgKGNvbnN0IGggb2Ygb3B0cy5leHRyYUFsbG93SGVhZGVycyA/PyBbXSkgewogICAgY29uc3QgdCA9IGgudHJpbSgpLnRvTG93ZXJDYXNlKCk7CiAgICBpZiAodCkgbWVyZ2VkLmFkZCh0KTsKICB9CiAgCiAgcmV0dXJuIHsKICAgICdBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4nOiAnKicsCiAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycyc6IEFycmF5LmZyb20obWVyZ2VkKS5qb2luKCcsICcpLAogICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnOiBvcHRzLmFsbG93TWV0aG9kcyA/PyBDT1JTX0hFQURFUlNfQkFTRVsnQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcyddLAogICAgJ0FjY2Vzcy1Db250cm9sLUV4cG9zZS1IZWFkZXJzJzogJ3gtcmVxdWVzdC1pZCcsCiAgICAuLi5TRUNVUklUWV9IRUFERVJTLAogIH07Cn0KCi8qKgogKiBVbmlmaWVkIHByZWZsaWdodCBoYW5kbGVyIOKAlCB3b3JrcyBmb3IgQk9USCBwdWJsaWMtd2lsZGNhcmQgYW5kIG9yaWdpbi1yZXN0cmljdGVkIGVuZHBvaW50cy4KICovCmV4cG9ydCBmdW5jdGlvbiBoYW5kbGVDb3JzUHJlZmxpZ2h0KAogIHJlcTogUmVxdWVzdCwKICBvcHRzOiB7IHB1YmxpYz86IGJvb2xlYW4gfSAmIFB1YmxpY0NvcnNPcHRpb25zID0ge30sCik6IFJlc3BvbnNlIHwgbnVsbCB7CiAgaWYgKHJlcS5tZXRob2QgIT09ICdPUFRJT05TJykgcmV0dXJuIG51bGw7CiAgCiAgaWYgKG9wdHMucHVibGljKSB7CiAgICBjb25zdCBvcmlnaW4gPSByZXEuaGVhZGVycy5nZXQoJ29yaWdpbicpIHx8IHJlcS5oZWFkZXJzLmdldCgnT3JpZ2luJykgfHwgJyc7CiAgICBsb2dQcmVmbGlnaHRGcm9tUmVxdWVzdChyZXEsIG9yaWdpbik7CiAgICByZXR1cm4gbmV3IFJlc3BvbnNlKG51bGwsIHsgaGVhZGVyczogYnVpbGRQdWJsaWNDb3JzSGVhZGVycyhvcHRzKSB9KTsKICB9CiAgCiAgcmV0dXJuIG5ldyBSZXNwb25zZShudWxsLCB7IGhlYWRlcnM6IGdldENvcnNIZWFkZXJzKHJlcSkgfSk7Cn0KCi8qKgogKiBAZGVwcmVjYXRlZCBVc2UgYGJ1aWxkUHVibGljQ29yc0hlYWRlcnMoKWAgb3IgYGhhbmRsZUNvcnNQcmVmbGlnaHQocmVxLCB7IHB1YmxpYzogdHJ1ZSB9KWAuCiAqLwpleHBvcnQgY29uc3QgcHVibGljQ29yc0hlYWRlcnMgPSBPYmplY3QuZnJlZXplKGJ1aWxkUHVibGljQ29yc0hlYWRlcnMoKSk7CgovKioKICogRXhwb3J0ZWQgZm9yIHRlc3RzIC8gaW50cm9zcGVjdGlvbi4KICovCmV4cG9ydCBjb25zdCBDT1JTX0lOVFJPU1BFQ1RJT04gPSBPYmplY3QuZnJlZXplKHsKICBhbGxvd0hlYWRlcnM6IEFMTE9XRURfSEVBREVSU19WQUxVRSwKICBhbGxvd0hlYWRlcnNMaXN0OiBPYmplY3QuZnJlZXplKFsuLi5BTExPV0VEX0hFQURFUlNfTElTVF0pLAogIGFsbG93TWV0aG9kczogQ09SU19IRUFERVJTX0JBU0VbJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnXSwKICBleHBvc2VIZWFkZXJzOiBDT1JTX0hFQURFUlNfQkFTRVsnQWNjZXNzLUNvbnRyb2wtRXhwb3NlLUhlYWRlcnMnXSwKfSk7Cg==
\ No newline at end of file
+// supabase/functions/_shared/cors.ts
+/**
+ * Centralized CORS configuration — restrict to known origins.
+ *
+ * BUG-07 FIX (2026-06-02): getBestAllowedOrigin() fallback was returning
+ * the Lovable dev URL (criar-together-now.lovable.app) for unknown origins.
+ * Changed to production URL (www.promogifts.com.br).
+ *
+ * BUG-08 FIX (2026-06-02): pqpdolkaeqlyzpdpbizo.supabase.co removed from
+ * EXACT_ALLOWED_ORIGINS. That project is in FORBIDDEN_REFS in client.ts
+ * and must not be granted CORS access to edge functions.
+ */
+
+// --- Configuration ---
+
+const EXACT_ALLOWED_ORIGINS = new Set([
+ // BUG-08 FIX: pqpdolkaeqlyzpdpbizo.supabase.co removed (FORBIDDEN project).
+ // Canonical project is doufsxqlfjyuvxuezpln — it never needs to call its own
+ // edge functions from a browser context; Supabase SDK handles that internally.
+ 'https://criar-together-now.lovable.app',
+ 'https://id-preview--1be35a65-1f65-4c2b-9a79-7d563930aacd.lovable.app',
+ 'https://1be35a65-1f65-4c2b-9a79-7d563930aacd.lovableproject.com',
+ 'https://promogifts.com.br',
+ 'https://www.promogifts.com.br',
+ 'https://promogifts.atomicabr.com.br',
+ 'http://localhost:5173',
+ 'http://localhost:8080',
+ 'http://localhost:3000',
+ 'http://127.0.0.1:5173',
+ 'http://127.0.0.1:8080',
+ 'http://127.0.0.1:3000',
+]);
+
+const ALLOWED_ORIGIN_PATTERNS = [
+ /^https:\/\/[a-z0-9-]+\.lovable\.app$/i,
+ /^https:\/\/[a-z0-9-]+\.lovableproject\.com$/i,
+ /^https:\/\/[a-z0-9-]+\.atomicabr\.com\.br$/i,
+ /^https:\/\/[a-z0-9-]+\.vercel\.app$/i,
+ /^http:\/\/localhost(?::\d+)?$/i,
+ /^http:\/\/127\.0\.0\.1(?::\d+)?$/i,
+];
+
+const ALLOWED_HEADERS_LIST = [
+ 'authorization',
+ 'x-client-info',
+ 'apikey',
+ 'content-type',
+ 'x-request-id',
+ 'x-step-up-token',
+ 'x-supabase-client-platform',
+ 'x-supabase-client-platform-version',
+ 'x-supabase-client-runtime',
+ 'x-supabase-client-runtime-version',
+];
+
+const ALLOWED_HEADERS_SET = new Set(ALLOWED_HEADERS_LIST.map((h) => h.toLowerCase()));
+const ALLOWED_HEADERS_VALUE = ALLOWED_HEADERS_LIST.join(', ');
+
+const SECURITY_HEADERS = {
+ 'X-Content-Type-Options': 'nosniff',
+ 'X-Frame-Options': 'DENY',
+ 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
+ 'Content-Security-Policy': "default-src 'self'; script-src 'self' 'strict-dynamic'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests;",
+} as const;
+
+const CORS_HEADERS_BASE = {
+ 'Access-Control-Allow-Headers': ALLOWED_HEADERS_VALUE,
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
+ 'Access-Control-Expose-Headers': 'x-request-id',
+ ...SECURITY_HEADERS,
+} as const;
+
+// --- Internal Utilities ---
+
+function parseHeaderList(headerString: string | null): string[] {
+ if (!headerString) return [];
+ return headerString
+ .split(',')
+ .map((h) => h.trim().toLowerCase())
+ .filter(Boolean);
+}
+
+function isAllowedOrigin(origin: string): boolean {
+ return (
+ EXACT_ALLOWED_ORIGINS.has(origin) ||
+ ALLOWED_ORIGIN_PATTERNS.some((pattern) => pattern.test(origin))
+ );
+}
+
+function getBestAllowedOrigin(origin: string | null): string {
+ if (origin && isAllowedOrigin(origin)) return origin;
+ // BUG-07 FIX: Unknown origin now falls back to the PRODUCTION URL instead
+ // of the Lovable development URL (criar-together-now.lovable.app).
+ // The browser still blocks the response if the origin doesn't match anyway,
+ // so this only matters for same-origin requests and server-side callers.
+ return 'https://www.promogifts.com.br';
+}
+
+// --- Structured Logging ---
+
+function logCorsEvent(event: string, fields: Record): void {
+ const payload = {
+ source: 'cors',
+ event,
+ ts: new Date().toISOString(),
+ ...fields,
+ };
+ const line = `[cors] ${JSON.stringify(payload)}`;
+
+ if (event.endsWith('_warn') || event.endsWith('_blocked')) {
+ console.warn(line);
+ } else {
+ console.log(line);
+ }
+}
+
+let bootLogged = false;
+function logBootIfNeeded(): void {
+ if (bootLogged) return;
+ bootLogged = true;
+ logCorsEvent('cors_boot', {
+ allow_headers: ALLOWED_HEADERS_VALUE,
+ allow_headers_count: ALLOWED_HEADERS_LIST.length,
+ allow_methods: CORS_HEADERS_BASE['Access-Control-Allow-Methods'],
+ expose_headers: CORS_HEADERS_BASE['Access-Control-Expose-Headers'],
+ exact_origins_count: EXACT_ALLOWED_ORIGINS.size,
+ pattern_origins_count: ALLOWED_ORIGIN_PATTERNS.length,
+ });
+}
+
+// Initialize boot log on module load
+logBootIfNeeded();
+
+function logPreflightFromRequest(req: Request, origin: string): void {
+ const requestedHeadersRaw = req.headers.get('Access-Control-Request-Headers') || req.headers.get('access-control-request-headers');
+ const requestedMethod = req.headers.get('Access-Control-Request-Method') || req.headers.get('access-control-request-method');
+ const requestedHeaders = parseHeaderList(requestedHeadersRaw);
+
+ const missingHeaders = requestedHeaders.filter((h) => !ALLOWED_HEADERS_SET.has(h));
+ const originAllowed = !origin || isAllowedOrigin(origin);
+ const requestId = req.headers.get('x-request-id') || req.headers.get('X-Request-Id');
+
+ const baseFields = {
+ request_id: requestId,
+ origin: origin || null,
+ origin_allowed: originAllowed,
+ requested_method: requestedMethod,
+ requested_headers: requestedHeaders,
+ missing_headers: missingHeaders,
+ };
+
+ if (!originAllowed || missingHeaders.length > 0) {
+ logCorsEvent('cors_preflight_warn', {
+ ...baseFields,
+ reason: !originAllowed ? 'origin_not_allowed' : 'header_not_allowed',
+ hint: missingHeaders.length > 0
+ ? `Add to ALLOWED_HEADERS_LIST in _shared/cors.ts: ${missingHeaders.join(', ')}`
+ : 'Add origin to EXACT_ALLOWED_ORIGINS or ALLOWED_ORIGIN_PATTERNS',
+ });
+ } else {
+ logCorsEvent('cors_preflight_ok', baseFields);
+ }
+}
+
+// --- Public API ---
+
+/**
+ * Returns CORS headers with origin validation.
+ * If the request origin is in the allowlist, it is reflected back.
+ */
+export function getCorsHeaders(req?: Request): Record {
+ const origin = req?.headers.get('origin') || req?.headers.get('Origin') || '';
+
+ if (req?.method === 'OPTIONS') {
+ logPreflightFromRequest(req, origin);
+ }
+
+ return {
+ ...CORS_HEADERS_BASE,
+ ...SECURITY_HEADERS,
+ 'Access-Control-Allow-Origin': getBestAllowedOrigin(origin),
+ };
+}
+
+/**
+ * Handle CORS preflight (OPTIONS) request.
+ * Returns a Response if it's an OPTIONS request, null otherwise.
+ */
+export function handleCorsPreflightIfNeeded(req: Request): Response | null {
+ if (req.method !== 'OPTIONS') return null;
+ return new Response(null, { headers: getCorsHeaders(req) });
+}
+
+export interface PublicCorsOptions {
+ /**
+ * Extra header tokens to append to Access-Control-Allow-Headers.
+ */
+ extraAllowHeaders?: string[];
+ /**
+ * Override Access-Control-Allow-Methods (default: same as restricted helper).
+ */
+ allowMethods?: string;
+}
+
+/**
+ * Build CORS headers for public/wildcard endpoints.
+ */
+export function buildPublicCorsHeaders(opts: PublicCorsOptions = {}): Record {
+ const merged = new Set(ALLOWED_HEADERS_LIST.map((h) => h.toLowerCase()));
+ for (const h of opts.extraAllowHeaders ?? []) {
+ const t = h.trim().toLowerCase();
+ if (t) merged.add(t);
+ }
+
+ return {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': Array.from(merged).join(', '),
+ 'Access-Control-Allow-Methods': opts.allowMethods ?? CORS_HEADERS_BASE['Access-Control-Allow-Methods'],
+ 'Access-Control-Expose-Headers': 'x-request-id',
+ ...SECURITY_HEADERS,
+ };
+}
+
+/**
+ * Unified preflight handler — works for BOTH public-wildcard and origin-restricted endpoints.
+ */
+export function handleCorsPreflight(
+ req: Request,
+ opts: { public?: boolean } & PublicCorsOptions = {},
+): Response | null {
+ if (req.method !== 'OPTIONS') return null;
+
+ if (opts.public) {
+ const origin = req.headers.get('origin') || req.headers.get('Origin') || '';
+ logPreflightFromRequest(req, origin);
+ return new Response(null, { headers: buildPublicCorsHeaders(opts) });
+ }
+
+ return new Response(null, { headers: getCorsHeaders(req) });
+}
+
+/**
+ * @deprecated Use `buildPublicCorsHeaders()` or `handleCorsPreflight(req, { public: true })`.
+ */
+export const publicCorsHeaders = Object.freeze(buildPublicCorsHeaders());
+
+/**
+ * Exported for tests / introspection.
+ */
+export const CORS_INTROSPECTION = Object.freeze({
+ allowHeaders: ALLOWED_HEADERS_VALUE,
+ allowHeadersList: Object.freeze([...ALLOWED_HEADERS_LIST]),
+ allowMethods: CORS_HEADERS_BASE['Access-Control-Allow-Methods'],
+ exposeHeaders: CORS_HEADERS_BASE['Access-Control-Expose-Headers'],
+});