ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto

fix: use browser.cookies API in Firefox extension for session

- Extension now reads session cookie using browser.cookies.get()
- Passes session as query parameter to work around SameSite=Lax
- Firefox cookie partitioning prevents credentials:include from working
- Works for both development and production cookie names

byarielm.fyi c393643d 18f4ca70

verified
Changed files
+113 -23
docs
packages
extension
src
+15 -15
docs/git-history.json
··· 1 1 [ 2 2 { 3 - "hash": "bb14ec5fb6426bbf4a7bc8bf1661bfbad29f16bd", 4 - "short_hash": "bb14ec5", 3 + "hash": "15b67054a684ebb2a21761a1774ba15f9b1c29e2", 4 + "short_hash": "15b6705", 5 5 "author": "Ariel M. Lighty", 6 - "date": "2025-12-28T20:32:16-05:00", 7 - "message": "fix: add Firefox extension CORS support\n\n- Added moz-extension:// origin detection to CORS handler\n- Added cookies permission to Firefox manifest for credentialed requests\n- Functions now properly reflect Firefox extension origins with credentials", 6 + "date": "2025-12-28T20:38:38-05:00", 7 + "message": "fix: add health check function for extension server detection\n\n- Created /health function endpoint with CORS support\n- Updated checkServerHealth to use function endpoint instead of root URL\n- Fixes Firefox extension server detection with proper CORS headers", 8 8 "files_changed": 5 9 9 }, 10 10 { ··· 24 24 "files_changed": 5 25 25 }, 26 26 { 27 - "hash": "d07180cd3a19328b82b35118e525b59d4e2e060b", 28 - "short_hash": "d07180c", 27 + "hash": "bd3aabb75abb1875aef125610fcdccb14967a8e3", 28 + "short_hash": "bd3aabb", 29 29 "author": "Ariel M. Lighty", 30 - "date": "2025-12-27T18:38:39-05:00", 31 - "message": "feat: add Tailwind CSS to extension\n\nReplaced 299 lines of vanilla CSS with Tailwind for design consistency with web app. Production build minified to 13KB.", 32 - "files_changed": 9 30 + "date": "2025-12-27T22:10:11-05:00", 31 + "message": "fix: extension dark mode and build mode messaging\n\n- Changed darkMode from 'class' to 'media' for automatic system preference detection\n- Made server offline message conditional on build mode (dev vs prod)\n- Hide dev server instructions in production builds", 32 + "files_changed": 5 33 33 }, 34 34 { 35 35 "hash": "d07180cd3a19328b82b35118e525b59d4e2e060b", ··· 160 160 "files_changed": 3 161 161 }, 162 162 { 163 - "hash": "32cdee3aeac7ef986df47e0fff786b5f7471e55b", 164 - "short_hash": "32cdee3", 163 + "hash": "ba29fd68872913ba0a587aa7f29f97b3d373a732", 164 + "short_hash": "ba29fd6", 165 165 "author": "Ariel M. Lighty", 166 166 "date": "2025-12-25T13:22:32-05:00", 167 167 "message": "configure Netlify dev for monorepo with --filter flag\n\nFixed Netlify CLI monorepo detection issue by using --filter flag:\n- Updated root package.json scripts to use 'npx netlify-cli dev --filter @atlast/web'\n- Updated netlify.toml [dev] section to use npm with --prefix for framework command\n- Added monorepo development instructions to CLAUDE.md\n- Documented Windows Git Bash compatibility issue with netlify command\n\nSolution: Use 'npx netlify-cli dev --filter @atlast/web' to bypass monorepo\nproject selection prompt and specify which workspace package to run.\n\nDev server now runs successfully at http://localhost:8888 with all backend\nfunctions loaded.", 168 - "files_changed": 4 168 + "files_changed": 5 169 169 }, 170 170 { 171 - "hash": "ba29fd68872913ba0a587aa7f29f97b3d373a732", 172 - "short_hash": "ba29fd6", 171 + "hash": "32cdee3aeac7ef986df47e0fff786b5f7471e55b", 172 + "short_hash": "32cdee3", 173 173 "author": "Ariel M. Lighty", 174 174 "date": "2025-12-25T13:22:32-05:00", 175 175 "message": "configure Netlify dev for monorepo with --filter flag\n\nFixed Netlify CLI monorepo detection issue by using --filter flag:\n- Updated root package.json scripts to use 'npx netlify-cli dev --filter @atlast/web'\n- Updated netlify.toml [dev] section to use npm with --prefix for framework command\n- Added monorepo development instructions to CLAUDE.md\n- Documented Windows Git Bash compatibility issue with netlify command\n\nSolution: Use 'npx netlify-cli dev --filter @atlast/web' to bypass monorepo\nproject selection prompt and specify which workspace package to run.\n\nDev server now runs successfully at http://localhost:8888 with all backend\nfunctions loaded.", 176 - "files_changed": 5 176 + "files_changed": 4 177 177 }, 178 178 { 179 179 "hash": "c3e7afad396d130791d801a85cbfc9643bcd6309",
+72 -6
docs/graph-data.json
··· 4296 4296 "node_type": "observation", 4297 4297 "title": "Health endpoint gets CORS headers correctly (moz-extension detected). Session endpoint error middleware doesn't pass event to errorResponse, returns wildcard CORS. Need to fix error middleware to pass event.", 4298 4298 "description": null, 4299 - "status": "pending", 4299 + "status": "completed", 4300 4300 "created_at": "2025-12-28T20:55:32.024834200-05:00", 4301 - "updated_at": "2025-12-28T20:55:32.024834200-05:00", 4301 + "updated_at": "2025-12-28T21:38:14.729731500-05:00", 4302 4302 "metadata_json": "{\"branch\":\"master\",\"confidence\":95}" 4303 4303 }, 4304 4304 { ··· 4307 4307 "node_type": "action", 4308 4308 "title": "Fixed error middleware to pass event to errorResponse for proper CORS headers on errors", 4309 4309 "description": null, 4310 - "status": "pending", 4310 + "status": "completed", 4311 4311 "created_at": "2025-12-28T20:56:38.876266200-05:00", 4312 - "updated_at": "2025-12-28T20:56:38.876266200-05:00", 4312 + "updated_at": "2025-12-28T21:38:14.888627800-05:00", 4313 4313 "metadata_json": "{\"branch\":\"master\",\"confidence\":95}" 4314 4314 }, 4315 4315 { ··· 4318 4318 "node_type": "outcome", 4319 4319 "title": "Fixed Firefox extension CORS completely. Error middleware now passes event to errorResponse so Firefox extension origin is properly reflected in error responses with credentials. Debug logging removed.", 4320 4320 "description": null, 4321 + "status": "completed", 4322 + "created_at": "2025-12-28T21:37:22.780953600-05:00", 4323 + "updated_at": "2025-12-28T21:38:15.071425500-05:00", 4324 + "metadata_json": "{\"branch\":\"master\",\"confidence\":95}" 4325 + }, 4326 + { 4327 + "id": 394, 4328 + "change_id": "3b0dea7a-c3cd-45a8-ba1a-f1040aa4e1d9", 4329 + "node_type": "observation", 4330 + "title": "CORS fully working - Firefox extension origin properly reflected with credentials. But cookies not sent from extension despite credentials:include. Cookie set in web context not accessible from extension context due to Firefox cookie partitioning.", 4331 + "description": null, 4321 4332 "status": "pending", 4322 - "created_at": "2025-12-28T21:37:22.780953600-05:00", 4323 - "updated_at": "2025-12-28T21:37:22.780953600-05:00", 4333 + "created_at": "2025-12-28T21:46:45.822343200-05:00", 4334 + "updated_at": "2025-12-28T21:46:45.822343200-05:00", 4335 + "metadata_json": "{\"branch\":\"master\",\"confidence\":95}" 4336 + }, 4337 + { 4338 + "id": 395, 4339 + "change_id": "8a93413f-a09c-4cc1-8693-4fe90dc055c4", 4340 + "node_type": "action", 4341 + "title": "Updated extension checkSession to read cookie via browser.cookies API and pass as query parameter. Workaround for Firefox SameSite=Lax cookie partitioning.", 4342 + "description": null, 4343 + "status": "pending", 4344 + "created_at": "2025-12-28T21:52:22.059862700-05:00", 4345 + "updated_at": "2025-12-28T21:52:22.059862700-05:00", 4346 + "metadata_json": "{\"branch\":\"master\",\"confidence\":95}" 4347 + }, 4348 + { 4349 + "id": 396, 4350 + "change_id": "864dd973-5f15-4e31-a7da-c548dbbe1f0e", 4351 + "node_type": "outcome", 4352 + "title": "Extension now uses browser.cookies.get() API to read session cookie and pass as query parameter. Workaround for Firefox SameSite=Lax cookie partitioning in extensions. Extension rebuilt successfully.", 4353 + "description": null, 4354 + "status": "pending", 4355 + "created_at": "2025-12-28T22:51:31.578965200-05:00", 4356 + "updated_at": "2025-12-28T22:51:31.578965200-05:00", 4324 4357 "metadata_json": "{\"branch\":\"master\",\"confidence\":95}" 4325 4358 } 4326 4359 ], ··· 8603 8636 "weight": 1.0, 8604 8637 "rationale": "Complete fix with cleanup", 8605 8638 "created_at": "2025-12-28T21:37:27.704906300-05:00" 8639 + }, 8640 + { 8641 + "id": 390, 8642 + "from_node_id": 393, 8643 + "to_node_id": 394, 8644 + "from_change_id": "aafd9977-8800-4152-9f7f-b817db6df573", 8645 + "to_change_id": "3b0dea7a-c3cd-45a8-ba1a-f1040aa4e1d9", 8646 + "edge_type": "leads_to", 8647 + "weight": 1.0, 8648 + "rationale": "New issue - cookie partitioning", 8649 + "created_at": "2025-12-28T21:46:48.417911400-05:00" 8650 + }, 8651 + { 8652 + "id": 391, 8653 + "from_node_id": 394, 8654 + "to_node_id": 395, 8655 + "from_change_id": "3b0dea7a-c3cd-45a8-ba1a-f1040aa4e1d9", 8656 + "to_change_id": "8a93413f-a09c-4cc1-8693-4fe90dc055c4", 8657 + "edge_type": "leads_to", 8658 + "weight": 1.0, 8659 + "rationale": "Workaround using browser.cookies API", 8660 + "created_at": "2025-12-28T21:52:52.704792400-05:00" 8661 + }, 8662 + { 8663 + "id": 392, 8664 + "from_node_id": 395, 8665 + "to_node_id": 396, 8666 + "from_change_id": "8a93413f-a09c-4cc1-8693-4fe90dc055c4", 8667 + "to_change_id": "864dd973-5f15-4e31-a7da-c548dbbe1f0e", 8668 + "edge_type": "leads_to", 8669 + "weight": 1.0, 8670 + "rationale": "Complete workaround", 8671 + "created_at": "2025-12-28T22:51:33.159870400-05:00" 8606 8672 } 8607 8673 ] 8608 8674 }
+26 -2
packages/extension/src/lib/api-client.ts
··· 116 116 avatar?: string; 117 117 } | null> { 118 118 try { 119 - const response = await fetch(`${ATLAST_API_URL}/.netlify/functions/session`, { 119 + // Try to get session cookie using browser.cookies API 120 + // This works around Firefox's cookie partitioning for extensions 121 + let sessionId: string | null = null; 122 + 123 + try { 124 + const cookieName = __BUILD_MODE__ === 'production' ? 'atlast_session' : 'atlast_session_dev'; 125 + const cookie = await browser.cookies.get({ 126 + url: ATLAST_API_URL, 127 + name: cookieName 128 + }); 129 + 130 + if (cookie) { 131 + sessionId = cookie.value; 132 + console.log('[API Client] Found session cookie:', cookieName); 133 + } 134 + } catch (cookieError) { 135 + console.log('[API Client] Could not read cookie:', cookieError); 136 + } 137 + 138 + // Build URL with session parameter if we have one 139 + const url = sessionId 140 + ? `${ATLAST_API_URL}/.netlify/functions/session?session=${sessionId}` 141 + : `${ATLAST_API_URL}/.netlify/functions/session`; 142 + 143 + const response = await fetch(url, { 120 144 method: 'GET', 121 - credentials: 'include', // Include cookies 145 + credentials: 'include', // Include cookies as fallback 122 146 headers: { 123 147 'Accept': 'application/json' 124 148 }