From b25e0d339e88f18c3cc9c8dced54c841d64db003 Mon Sep 17 00:00:00 2001 From: phillsatellite Date: Tue, 3 Mar 2026 20:58:36 -0500 Subject: [PATCH 1/2] Store API key in Firestore instead of localStorage Replace localStorage-based API key persistence with Firestore. On login, the key is fetched from the user's Firestore document. On submit, it is saved via setDoc with merge. Cypress mock flow still uses localStorage. --- src/App.jsx | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 8c05826..f6fd1ce 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,7 @@ import { useState, useEffect } from "react"; import { onAuthStateChanged, signOut } from "firebase/auth"; -import { auth } from "./utils/firebase"; +import { doc, getDoc, setDoc } from "firebase/firestore"; +import { auth, db } from "./utils/firebase"; import Welcome from "./components/Welcome.jsx"; import AuthScreen from "./components/AuthScreen.jsx"; import ApiKeySetup from "./components/ApiKeySetup.jsx"; @@ -46,17 +47,25 @@ export default function App() { if (mockUser) { setUser(mockUser); setAuthLoading(false); + // In Cypress tests, check localStorage for mock API key const savedKey = localStorage.getItem(`sidekick_apikey_${mockUser.uid}`); if (savedKey) setApiKey(savedKey); return; } - const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => { + const unsubscribe = onAuthStateChanged(auth, async (firebaseUser) => { setUser(firebaseUser); setAuthLoading(false); if (firebaseUser) { - const savedKey = localStorage.getItem(`sidekick_apikey_${firebaseUser.uid}`); - if (savedKey) setApiKey(savedKey); + // Fetch API key from Firestore + try { + const snap = await getDoc(doc(db, "users", firebaseUser.uid)); + if (snap.exists() && snap.data().apiKey) { + setApiKey(snap.data().apiKey); + } + } catch { + // Firestore fetch failed — user will see API key setup screen + } } else { setApiKey(""); } @@ -93,10 +102,14 @@ export default function App() { setShowWelcome(false); }; - const handleKeySubmit = (key) => { + const handleKeySubmit = async (key) => { setApiKey(key); if (user) { - localStorage.setItem(`sidekick_apikey_${user.uid}`, key); + try { + await setDoc(doc(db, "users", user.uid), { apiKey: key }, { merge: true }); + } catch { + // Firestore save failed — key is still in memory for this session + } } }; From 6de70c9eb8ce0d41c15d7a0a62c9ea16fd597ad6 Mon Sep 17 00:00:00 2001 From: phillsatellite Date: Tue, 3 Mar 2026 21:21:06 -0500 Subject: [PATCH 2/2] Fix K-6 test to check app state instead of localStorage The API key is now stored in Firestore, not localStorage. Update the test to verify the main app renders correctly after key submission. --- cypress/e2e/apikey.cy.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cypress/e2e/apikey.cy.js b/cypress/e2e/apikey.cy.js index a1396fb..9c39e5f 100644 --- a/cypress/e2e/apikey.cy.js +++ b/cypress/e2e/apikey.cy.js @@ -43,12 +43,10 @@ describe("API Key Setup", () => { cy.get(".setup-input").should("have.attr", "type", "password"); }); - it("K-6: key persists in localStorage scoped to user UID", () => { - const testKey = "sk-test-key-1234567890"; - cy.get(".setup-input").type(testKey); + it("K-6: submitting key shows main app with mic and sidebar", () => { + cy.get(".setup-input").type("sk-test-key-1234567890"); cy.get(".setup-submit-btn").click(); - cy.window().then((win) => { - expect(win.localStorage.getItem("sidekick_apikey_test-user-123")).to.equal(testKey); - }); + cy.get(".mic-btn").should("be.visible"); + cy.get(".sidebar").should("exist"); }); });