Create a dialog that appears when the app loads and detects encrypted credentials in localStorage.
UX flow:
- App loads → AuthProvider reads localStorage
- If stored value is an
EncryptedTokenPayload (has method field + ciphertext):
- For
method: "password": show a password input field + submit button + "Reset vault" link
- For
method: "webauthn": show a "Unlock with biometrics" button + "Reset vault" link
- On successful unlock:
- Derive/decrypt key via token-vault utils
- Decrypt token
- Cache derived key in sessionStorage (for silent re-encryption of refreshed tokens)
- Set token in AuthProvider state → GitHubProvider initializes Octokit automatically
- On "Reset vault": clear the encrypted payload, fall back to unauthenticated state (user re-authenticates)
Detection logic (in AuthProvider initial state):
const raw = localStorage.getItem("pulldash_github_token");
let encryptedPayload: EncryptedTokenPayload | null = null;
try { encryptedPayload = JSON.parse(raw); } catch {}
if (encryptedPayload?.method) {
// needs unlock
}
Same for pulldash_github_refresh_token.
Integration:
- Add
needsUnlock: boolean to AuthState
- Add
unlockToken(password) and unlockWithBiometrics() methods to AuthProvider
- Render unlock dialog in
WelcomeDialog when needsUnlock && !isAuthenticated
Part of #318
Create a dialog that appears when the app loads and detects encrypted credentials in localStorage.
UX flow:
EncryptedTokenPayload(hasmethodfield +ciphertext):method: "password": show a password input field + submit button + "Reset vault" linkmethod: "webauthn": show a "Unlock with biometrics" button + "Reset vault" linkDetection logic (in AuthProvider initial state):
Same for
pulldash_github_refresh_token.Integration:
needsUnlock: booleantoAuthStateunlockToken(password)andunlockWithBiometrics()methods to AuthProviderWelcomeDialogwhenneedsUnlock && !isAuthenticatedPart of #318