Skip to content

fix(shared,client): harden passkey recovery#556

Open
Oba-One wants to merge 7 commits into
developfrom
codex/account-recovery-hardening
Open

fix(shared,client): harden passkey recovery#556
Oba-One wants to merge 7 commits into
developfrom
codex/account-recovery-hardening

Conversation

@Oba-One

@Oba-One Oba-One commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds Pimlico passkey-server registration and recovery behind VITE_PASSKEY_SERVER_ENABLED, defaulting off for staging-first rollout and rollback.
  • Preserves local passkey cache as same-device fallback while adding normalized username/ENS recovery context, expected smart-account address continuity checks, and privacy-safe telemetry.
  • Updates the client recovery UI, i18n, docs, and Account Recovery Hardening plan handoff for PRD-537, PRD-538, and PRD-540 readiness.

Validation

  • bun run --cwd packages/shared test -- src/__tests__/config/passkeyServer.test.ts src/__tests__/workflows/authServices.test.ts src/__tests__/modules/session.test.ts src/__tests__/workflows/authMachine.test.ts src/__tests__/hooks/useAuth.test.ts
  • bun run --cwd packages/client test -- src/__tests__/views/Login.test.tsx
  • bun run build:shared
  • bun run --cwd packages/client build
  • bun run lint:vocab
  • bun run check:design-md
  • bun run check:design-tokens
  • Browser proof for no-local-cache recovery, failed recovery retry/fallback, and guarded separate-account confirmation at https://127.0.0.1:5173/home/login?presentation=pwa
  • Pre-push hook completed successfully; it emitted existing contract-script lint warnings but ended with Pre-push checks passed.

Known unrelated validation blockers:

  • bun run check:design-generated fails on stale generated client PWA token audit docs.
  • node scripts/harness/plan-hub.mjs validate fails on malformed active sentry-stack-observability hub metadata.

Linear: PRD-537, PRD-538, PRD-540, PRD-505, PRD-507

Adds Pimlico passkey-server registration and recovery behind a default-off flag, preserves local fallback metadata, and updates guarded recovery UI for PRD-537 and PRD-538.
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
green-goods Building Building Preview, Comment Jun 9, 2026 2:57am
green-goods-admin Building Building Preview, Comment Jun 9, 2026 2:57am
green-goods-design Building Building Preview, Comment Jun 9, 2026 2:57am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Optional hosted passkey recovery (server-backed) — gated off by default — with username/ENS lookup, recovery-first UI, separate-account creation, and address-continuity checks.
  • UX Improvements
    • Smoother login/splash username input, clearer recovery flows, and unsupported in-app browser guidance.
  • Documentation
    • Updated onboarding and sequence diagrams to show hosted passkey and fallback behavior.
  • Localization
    • English, Spanish, and Portuguese UI copy updated for passkey/recovery flows and errors.
  • Tests
    • Expanded passkey and session test coverage and end-to-end recovery scenarios.

Walkthrough

Adds an optional Pimlico-hosted passkey-server recovery flow (gated by VITE_PASSKEY_SERVER_ENABLED=false by default), server-first registration/authentication with local-storage fallbacks, expected smart-account address persistence, progressive recovery UI/state, unified passkey telemetry, tests, i18n, docs, and plan/status artifacts.

Changes

Hosted Passkey Server Recovery Flow

Layer / File(s) Summary
Config, env, exports, and passkey-server API
.env.template, packages/shared/src/config/*, packages/shared/src/__tests__/config/*, packages/shared/src/index.ts
Adds VITE_PASSKEY_SERVER_ENABLED, refactors RP ID resolver, introduces createPasskeyServerClient, isPasskeyServerEnabled, normalizePasskeyAccountIdentifier and related helpers, and updates re-exports and tests.
Auth services: server-first flows, fallbacks, and tests
packages/shared/src/workflows/authServices.ts, packages/shared/src/__tests__/workflows/*
Implements server-backed registration/authentication, strict credential decoding, challenge/ArrayBuffer helpers, classified error handling that drives legacy fallback eligibility, smart-account address continuity enforcement, and extensive server-enabled & fallback tests.
Session storage, analytics, and error classification
packages/shared/src/modules/auth/session.ts, packages/shared/src/modules/app/analytics-events.ts, packages/shared/src/utils/errors/*
Adds SMART_ACCOUNT_ADDRESS_STORAGE_KEY and get/set/clear helpers, updates clearAllAuth and debug output, introduces AuthPasskeyTelemetry/types and updates tracker signatures, and tightens wallet-expiry detection with new regex and tests.
Login/Splash UI, flows, and client tests
packages/client/src/views/Login/*, packages/client/src/components/Layout/Splash.tsx, packages/client/src/__tests__/views/*, docs/.../packages/client-pwa-token-audit.generated.md
Updates Splash accessibility/reveal behavior and UsernameInputConfig; extends Login with missing-local-cache recovery-first flow, unsupported-browser gating, friendly error mapping, separate-account confirmation, and corresponding/refactored tests.
Documentation, i18n, and planning/status updates
docs/.../sequence-diagrams.mdx, docs/.../journeys/onboarding.mdx, packages/shared/src/i18n/*, .plans/..., .plans/.../status.json
Documents hosted-server conditional flows and localStorage caching, updates onboarding and builder notes, revises i18n across locales for passkey recovery flows, and records plan/status/QA evidence and rollout gating notes.

Sequence Diagram(s)

sequenceDiagram
  participant LoginView
  participant AuthServices
  participant PimlicoPasskeyServer
  participant WebAuthn
  participant SessionStorage
  LoginView->>AuthServices: handlePasskeyLogin(userName)
  AuthServices->>PimlicoPasskeyServer: startAuthentication(recoveryContext)
  PimlicoPasskeyServer-->>AuthServices: credential + challenge or empty
  AuthServices->>WebAuthn: perform assertion (challenge, credentialId)
  WebAuthn-->>AuthServices: assertion response
  AuthServices->>PimlicoPasskeyServer: verifyAuthentication(response)
  AuthServices->>SessionStorage: setStoredSmartAccountAddress(address)
  AuthServices-->>LoginView: emit session or fallback/error
Loading

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs:

"A rabbit hops through recovery code,
Caches and servers stitched in gentle mode,
Fail-closed on mismatch, guarded the way,
Docs and tests to prove the play,
QA gate waits before the flag's bestowed."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(shared,client): harden passkey recovery' is directly related to the main changeset, which adds Pimlico passkey-server registration/recovery hardening with address continuity checks and fallback flows across both shared and client packages.
Description check ✅ Passed The description is well-related to the changeset, explaining the addition of Pimlico passkey-server support, local fallback preservation, normalized recovery context, address continuity checks, and UI/i18n updates with detailed validation evidence.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/account-recovery-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/shared/src/workflows/authServices.ts (1)

393-401: 💤 Low value

Unsafe cast of WebAuthn response to P256Credential["raw"].

The authResponse from navigator.credentials.get() is a CredentialRequestOptions result (a PublicKeyCredential), but you're casting it directly to P256Credential["raw"] on line 399. This works in the happy path because PublicKeyCredential is structurally compatible, but the cast bypasses type checking. The earlier server registration flow (line 350) correctly passes createdCredential.raw because createWebAuthnCredential returns a properly typed object.

Consider extracting the raw credential consistently or documenting why this cast is safe for server authentication.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/workflows/authServices.ts` around lines 393 - 401, The
code unsafely casts authResponse to P256Credential["raw"]; instead, convert the
PublicKeyCredential returned from navigator.credentials.get() into the same
typed shape used during registration (use the helper that produced
createdCredential.raw) and pass that typed raw to toVerifiedCredential;
specifically, replace the direct cast of authResponse with a call that builds a
P256Credential from the PublicKeyCredential (e.g., use the existing
createWebAuthnCredential/creation helper or a small extractor that takes
authResponse (PublicKeyCredential) and returns its typed .raw) and then call
toVerifiedCredential(verification, typedRaw, "Passkey server authentication
failed") to avoid bypassing type checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/client/src/views/Login/index.tsx`:
- Around line 68-74: The error branch in Login/index.tsx that checks the
variable msg (the block using msg.includes("expected account") ||
msg.includes("address")) is too broad and should be tightened to only match the
exact backend recovery phrases so it doesn't override more specific states;
update the condition(s) to test for explicit full phrases (e.g., the exact
recovery messages returned by the backend such as "expected account address" or
"address unavailable for recovery") instead of single words like "address" or
"unavailable", and apply the same tightening to the similar branch around lines
89-95 so the intl.formatMessage call for id "app.login.error.addressMismatch"
only runs for those explicit messages.
- Around line 587-615: The tertiaryAction currently exposes
handleStartSeparateAccount in the fallback branch, allowing users to create a
separate account before recovery is attempted; change the tertiaryAction logic
so that browserGuidanceTertiaryAction is returned if present, otherwise only
show the "connect wallet" action when recoveryAttempted && loginError, and do
NOT render the create-separate-account action in the tertiary fallback — instead
return walletAction or null/undefined; update the tertiaryAction conditional
(the expression referencing browserGuidanceTertiaryAction, recoveryAttempted,
loginError, handleWalletLogin, and handleStartSeparateAccount) so
createSeparateAccount is only ever shown when recoveryAttempted && loginError
(as already done in secondaryAction).

In `@packages/shared/src/config/passkeyServer.ts`:
- Around line 159-161: Normalize the VITE_PASSKEY_RP_ID value before returning
to avoid rp_origin_mismatch by trimming whitespace and lowercasing the host;
replace the direct return of envRpId (from env.VITE_PASSKEY_RP_ID) with a
normalized form such as envRpId.trim().toLowerCase() in the function that reads
envRpId so callers (the RP ID logic around rp_origin_mismatch) always get a
normalized hostname.

In `@packages/shared/src/modules/auth/session.ts`:
- Around line 105-111: Change the smart-account and embedded address storage
helpers to use viem's Address type instead of plain string: import Address from
'viem' (or import type { Address } from 'viem') and update the signatures of
setStoredSmartAccountAddress and getStoredSmartAccountAddress (and
setEmbeddedAddress/getEmbeddedAddress) so setters accept Address and getters
return Address | null; keep the same localStorage keys and JSON/string handling
but ensure the returned value is typed as Address | null and any callers are
updated to accept the stronger type.

---

Nitpick comments:
In `@packages/shared/src/workflows/authServices.ts`:
- Around line 393-401: The code unsafely casts authResponse to
P256Credential["raw"]; instead, convert the PublicKeyCredential returned from
navigator.credentials.get() into the same typed shape used during registration
(use the helper that produced createdCredential.raw) and pass that typed raw to
toVerifiedCredential; specifically, replace the direct cast of authResponse with
a call that builds a P256Credential from the PublicKeyCredential (e.g., use the
existing createWebAuthnCredential/creation helper or a small extractor that
takes authResponse (PublicKeyCredential) and returns its typed .raw) and then
call toVerifiedCredential(verification, typedRaw, "Passkey server authentication
failed") to avoid bypassing type checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b68cd4bf-0f2c-4e9a-9f87-350445d46449

📥 Commits

Reviewing files that changed from the base of the PR and between 6026f8b and 0f683ba.

📒 Files selected for processing (27)
  • .env.template
  • .plans/active/account-recovery-hardening/handoffs/codex-state-api.md
  • .plans/active/account-recovery-hardening/plan.todo.md
  • .plans/active/account-recovery-hardening/status.json
  • docs/docs/builders/architecture/sequence-diagrams.mdx
  • docs/docs/builders/journeys/onboarding.mdx
  • docs/docs/builders/packages/client-pwa-token-audit.generated.md
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/config/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/i18n/en.json
  • packages/shared/src/i18n/es.json
  • packages/shared/src/i18n/pt.json
  • packages/shared/src/index.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/workflows/authServices.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Test
  • GitHub Check: Test
  • GitHub Check: Build Docs
  • GitHub Check: Test
  • GitHub Check: Playwright Client CI
  • GitHub Check: CI Gate
  • GitHub Check: Storybook
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (35)
packages/shared/**

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

@green-goods/shared is the only home for reusable hooks, providers, stores, modules, types, i18n, and shared UI primitives

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/i18n/es.json
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/i18n/en.json
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/workflows/authServices.ts
  • packages/shared/src/i18n/pt.json
packages/shared/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

Use centralized queryKeys, event-driven invalidation, useCurrentChain() or DEFAULT_CHAIN_ID, logger, and typed domain models such as Address in @green-goods/shared

Keep reusable hooks, providers, stores, modules, and shared UI primitives in @green-goods/shared

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/workflows/authServices.ts
packages/shared/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

Shared UI primitive changes should ship with tests, barrel updates, and Storybook coverage in the same change when applicable

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/workflows/authServices.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Default to single-chain behavior through getDefaultChain() or DEFAULT_CHAIN_ID
Use logger from shared instead of console.log
Use bun run format:check && bun lint for code quality checks

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use the Address type for Ethereum addresses instead of raw string types

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
**/*.{json,ts,tsx}?(locales|i18n|translations|lang)

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Add every new user-facing string to en, es, and pt language files

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/i18n/es.json
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/i18n/en.json
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
  • packages/shared/src/i18n/pt.json
packages/shared/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/shared/AGENTS.md)

packages/shared/**/*.{ts,tsx}: Use centralized query keys from queryKeys in packages/shared. Do not invent ad-hoc query arrays.
Use useCurrentChain() or DEFAULT_CHAIN_ID for application defaults in packages/shared, not wallet chain state.
Prefer event-driven invalidation over polling in packages/shared hooks and queries.
Use logger and typed domain models (Address, discriminated unions, unknown for untrusted data) in packages/shared code.

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/workflows/authServices.ts
packages/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use Address type (not string) for Ethereum addresses in TypeScript across all packages

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/workflows/authServices.ts
packages/{shared,client,admin}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Never swallow errors — use parseContractError() + USER_FRIENDLY_ERRORS for contract errors, use createMutationErrorHandler() in shared mutation hooks, use logger from shared (not console.log)

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/**/*.{ts,tsx}: Use queryKeys.* helpers from shared for React Query key serialization — serialize objects in query keys
Do not use banned vocabulary in i18n strings (enforced by bun run lint:vocab): never use streak, countdown, leaderboard, FOMO, or growth-hacking language (urgent, limited time, re-engagement, retention hook)

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{contracts,agent,admin,shared}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use the Address type for Ethereum addresses.

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/workflows/authServices.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Use logger from shared, never console.log.

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin,shared}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Remixicon (Ri*Line), never lucide.

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin,shared}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Any new user-facing string must be added to en, es, and pt.

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin,shared}/src/**/*.{ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

packages/{client,admin,shared}/src/**/*.{ts,tsx,css}: Treat Baseline Widely Available as the baseline target for frontend changes. Use repo-installed Modern Web Guidance through bun run agentic:guidance before frontend, UI, CSS, accessibility, browser proof, or web-design changes.
Prefer semantic HTML, native controls, platform CSS, and browser primitives before custom JavaScript.

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin,shared}/src/**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Banned vocabulary for any surface: streak, countdown, leaderboard, FOMO.

Files:

  • packages/shared/src/config/index.ts
  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/index.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/utils/errors/contract-errors.ts
  • packages/shared/src/i18n/es.json
  • packages/shared/src/modules/app/analytics-events.ts
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/modules/auth/session.ts
  • packages/shared/src/i18n/en.json
  • packages/shared/src/modules/index.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
  • packages/shared/src/i18n/pt.json
{.github/workflows/**,**/*.test.{js,ts,jsx,tsx},**/*.spec.{js,ts,jsx,tsx}}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use bun run test, never bun test

Files:

  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use bun run test for running tests

Files:

  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Use bun run test instead of bun test for running tests — bun test uses bun's built-in runner (ignores vitest config), while bun run test runs the package.json script with proper vitest environment

Files:

  • packages/shared/src/__tests__/modules/session.test.ts
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/utils/errors/__tests__/contract-errors.test.ts
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/shared/src/index.ts

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

Export public APIs through package barrels; do not normalize deep imports as the public contract in @green-goods/shared

Files:

  • packages/shared/src/index.ts
packages/shared/src/i18n/{en,es,pt}.json

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

New user-facing strings must be added to src/i18n/en.json, src/i18n/es.json, and src/i18n/pt.json

Files:

  • packages/shared/src/i18n/es.json
  • packages/shared/src/i18n/en.json
  • packages/shared/src/i18n/pt.json
packages/shared/src/i18n/*.json

📄 CodeRabbit inference engine (packages/shared/AGENTS.md)

Add every new user-facing string to src/i18n/en.json, src/i18n/es.json, and src/i18n/pt.json in the shared package. Do not hardcode user-facing strings.

Files:

  • packages/shared/src/i18n/es.json
  • packages/shared/src/i18n/en.json
  • packages/shared/src/i18n/pt.json
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Remixicon (Ri*Line), never lucide for UI icons

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/shared/src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Tailwind v4 does not scan packages/shared/src/ from admin/client builds due to content scanning limitations — do NOT add utility classes (mx-4, w-max, self-center, justify-self-center) directly to JSX in shared components; instead use inline styles for layout or CSS overrides in the consuming package

Files:

  • packages/shared/src/providers/Auth.tsx
packages/{client,admin,shared}/src/**/*.{tsx,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Design System: Load design skill (direction) + ui skill (implementation) explicitly when paradigm, layout composition, new view, tokens, or PR review is at stake — for trivial edits (padding, copy, single component touch), use the rules in CLAUDE.md

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin,shared}/src/**/*.{css,scss,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Design tokens: never hardcode cubic-bezier, duration, or raw color/radius values — use --spring-* (6 motion tokens), --color-*, --radius-*, --color-material-* + --blur-material-* from theme.css

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
.env*

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

.env*: Use the root .env only; do not add package-level .env files
Keep .env* files human-governed even when Copilot review runs automatically

Files:

  • .env.template
packages/client/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/instructions/client.instructions.md)

packages/client/**/*.{ts,tsx,js,jsx}: Hooks, providers, and most business logic should come from @green-goods/shared in packages/client
Do not add local hooks or providers when the logic belongs in shared
Preserve the offline-first queue flow for work submission; do not bypass the queue for passkey users
Keep authentication branches on shared auth APIs and shared default-chain helpers instead of wallet chain state
Manage blob URLs through shared utilities such as mediaResourceManager; do not leave orphaned URL.createObjectURL values behind
Prefer event-driven invalidation over polling

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/client/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/client/AGENTS.md)

packages/client/**/*.{ts,tsx}: Do not create local hooks or providers in the client package when the logic belongs in @green-goods/shared
Work submission must preserve the offline-first queue flow; do not bypass the queue for passkey users
Prefer event-driven invalidation over polling
Manage blob URLs through shared utilities such as mediaResourceManager; do not leave orphaned URL.createObjectURL values behind
Authentication branches must go through shared auth APIs; do not treat wallet chain state as the source of truth for app defaults

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/client/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/client/AGENTS.md)

New user-facing strings must be translated in all three locale files

Client-only banned vocabulary (never use in client PWA): operator cockpit, utility copy, KPI tile, dashboard, Plus Jakarta Sans

Client only: do not use operator cockpit, utility copy, Plus Jakarta Sans, KPI tile, dashboard.

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/{client,admin}/src/**/*.{ts,tsx}: ALL React hooks MUST live in @green-goods/shared — client and admin packages must not define their own hooks and should import hooks from the shared package
Import hooks from @green-goods/shared using barrel imports: import { useAuth, useGardens } from '@green-goods/shared' — never use deep paths like @green-goods/shared/src/hooks/useAuth
Contract integration: Import deployment artifacts from ../../../contracts/deployments/11155111-latest.json (or appropriate chain ID), never hardcode Ethereum addresses in code
Use isGreenWillDeployed(chainId?) from @green-goods/shared to detect when a feature contract is undeployed (zero-address) on the active chain — render a 'not available on this network' branch instead of a generic empty state
When a useMemo depends on a value written to localStorage in the same tab (e.g., pending-join membership), include usePendingJoinsVersion() from @green-goods/shared in its useMemo deps — this returns an incrementing counter that ticks on every in-tab pending-join change

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin}/src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

When debugging user-observed UI regressions, start from the rendered surface before tracing data flow — inspect DOM geometry, computed styles (bounding rect, width/height, opacity, display, pointer-events, z-index, overflow, disabled state, selected classes, border/ring), verify click/tap changes state, then trace visible element → component → state setter

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/client/src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Client PWA uses @green-goods/shared primitives + presentation-mode loaders/PublicShell/PwaRuntime/AppShell/SiteHeader/AppBar — do not invent component names; flag missing primitives instead

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{client,admin}/src/**/*.{tsx,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Volume hierarchy: canvas 80–90% / ink 8–15% / stone 3–5% / accent green 1–3% — flooding the screen with green is the #1 design failure mode

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
packages/{contracts,agent,client,admin}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Default to single-chain behavior through getDefaultChain() or DEFAULT_CHAIN_ID.

Files:

  • packages/client/src/components/Layout/Splash.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/__tests__/views/AccountInfo.test.tsx
🪛 ast-grep (0.43.0)
packages/shared/src/modules/auth/session.ts

[warning] 105-105: Sensitive information detected in localStorage. Storing sensitive data like emails, usernames, or personal information in localStorage exposes it to malicious scripts and XSS attacks. Use secure storage alternatives or avoid storing sensitive data client-side.
Context: localStorage.setItem(SMART_ACCOUNT_ADDRESS_STORAGE_KEY, address)
Note: [CWE-312] Cleartext Storage of Sensitive Information

(local-storage-sensitive-information)

🪛 LanguageTool
.plans/active/account-recovery-hardening/handoffs/codex-state-api.md

[grammar] ~40-~40: Use a hyphen to join words.
Context: ... ### Implemented - Added shared Pimlico hosted passkey-server helpers in `packag...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (31)
packages/shared/src/modules/app/analytics-events.ts (1)

24-36: LGTM!

Also applies to: 139-145, 147-169, 182-184

packages/shared/src/workflows/authServices.ts (4)

118-142: LGTM!


160-215: LGTM!

Also applies to: 240-252


326-356: LGTM!

Also applies to: 358-405, 407-449


463-515: LGTM!

Also applies to: 529-576, 590-666

packages/shared/src/utils/errors/contract-errors.ts (1)

471-491: LGTM!

packages/shared/src/utils/errors/__tests__/contract-errors.test.ts (1)

193-199: LGTM!

packages/shared/src/__tests__/workflows/authServices.test.ts (4)

119-134: LGTM!

Also applies to: 142-171, 177-186


200-217: LGTM!

Also applies to: 293-303


481-572: LGTM!


660-858: LGTM!

packages/client/src/__tests__/views/Login.test.tsx (1)

24-34: LGTM!

Also applies to: 43-45, 69-69, 93-94, 103-104, 114-114, 163-188, 196-202, 214-248, 255-265, 275-300, 305-306, 309-369, 378-380, 421-422

packages/client/src/__tests__/views/AccountInfo.test.tsx (1)

82-86: LGTM!

Also applies to: 93-93, 101-101, 113-113, 119-119

docs/docs/builders/packages/client-pwa-token-audit.generated.md (1)

94-99: LGTM!

docs/docs/builders/architecture/sequence-diagrams.mdx (1)

221-221: LGTM!

Also applies to: 227-227, 234-242, 245-245, 261-271, 281-283

docs/docs/builders/journeys/onboarding.mdx (1)

72-72: LGTM!

Also applies to: 82-85, 100-103

packages/client/src/components/Layout/Splash.tsx (1)

26-31: LGTM!

Also applies to: 74-83, 89-103, 111-176, 186-187, 257-277

packages/shared/src/i18n/en.json (1)

1848-1850: LGTM!

Also applies to: 1875-1894, 1902-1902, 1905-1913, 1922-1924

packages/shared/src/i18n/es.json (1)

1848-1850: LGTM!

Also applies to: 1875-1890, 1902-1902, 1905-1913, 1922-1924

.plans/active/account-recovery-hardening/handoffs/codex-state-api.md (1)

36-99: LGTM!

.plans/active/account-recovery-hardening/plan.todo.md (1)

35-43: LGTM!

Also applies to: 113-130, 154-158

.plans/active/account-recovery-hardening/status.json (1)

13-13: LGTM!

Also applies to: 82-113, 223-255

.env.template (1)

89-93: LGTM!

packages/shared/src/config/passkeyServer.ts (1)

10-147: LGTM!

Also applies to: 154-158, 164-175

packages/shared/src/config/index.ts (1)

57-72: LGTM!

packages/shared/src/index.ts (1)

225-237: LGTM!

packages/shared/src/__tests__/config/passkeyServer.test.ts (1)

1-130: LGTM!

packages/shared/src/modules/auth/session.ts (1)

38-40: LGTM!

Also applies to: 157-157, 180-203

packages/shared/src/modules/index.ts (1)

130-130: LGTM!

Also applies to: 132-132, 137-137, 139-139

packages/shared/src/providers/Auth.tsx (1)

50-51: LGTM!

Also applies to: 444-448, 475-479

packages/shared/src/__tests__/modules/session.test.ts (1)

44-54: LGTM!

Also applies to: 126-148, 154-161

Comment thread packages/client/src/views/Login/index.tsx Outdated
Comment thread packages/client/src/views/Login/index.tsx
Comment thread packages/shared/src/config/passkeyServer.ts Outdated
Comment thread packages/shared/src/modules/auth/session.ts Outdated
@github-project-automation github-project-automation Bot moved this from Backlog to In progress in Green Goods Jun 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/shared/src/modules/auth/session.ts (1)

111-112: 💤 Low value

Consider adding runtime validation for the type assertion.

The type assertion as Address | null is safe when inputs are controlled, but localStorage can be manually edited or corrupted. Adding a lightweight hex-string validation check would make this more defensive.

♻️ Optional defensive validation
 export function getStoredSmartAccountAddress(): Address | null {
-  return localStorage.getItem(SMART_ACCOUNT_ADDRESS_STORAGE_KEY) as Address | null;
+  const stored = localStorage.getItem(SMART_ACCOUNT_ADDRESS_STORAGE_KEY);
+  if (!stored) return null;
+  // Lightweight validation: check if it looks like a hex address
+  if (!/^0x[0-9a-fA-F]{40}$/.test(stored)) {
+    logger.warn("[Session] Invalid smart-account address in storage, clearing...");
+    localStorage.removeItem(SMART_ACCOUNT_ADDRESS_STORAGE_KEY);
+    return null;
+  }
+  return stored as Address;
 }

This matches the defensive pattern used for credential parsing at lines 254-266.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/modules/auth/session.ts` around lines 111 - 112,
getStoredSmartAccountAddress currently casts
localStorage.getItem(SMART_ACCOUNT_ADDRESS_STORAGE_KEY) to Address | null
without validating user-editable storage; add a lightweight runtime validation
(e.g., ensure value is a string, matches a hex-address pattern like
/^0x[0-9a-fA-F]{40}$/ or other project-specific Address format) and return null
when invalid so the function only returns a valid Address or null; update
getStoredSmartAccountAddress to perform this check before returning the value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/shared/src/modules/auth/session.ts`:
- Around line 111-112: getStoredSmartAccountAddress currently casts
localStorage.getItem(SMART_ACCOUNT_ADDRESS_STORAGE_KEY) to Address | null
without validating user-editable storage; add a lightweight runtime validation
(e.g., ensure value is a string, matches a hex-address pattern like
/^0x[0-9a-fA-F]{40}$/ or other project-specific Address format) and return null
when invalid so the function only returns a valid Address or null; update
getStoredSmartAccountAddress to perform this check before returning the value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1d127f57-03e9-4ca7-8942-8f40ccbe3cf1

📥 Commits

Reviewing files that changed from the base of the PR and between 0f683ba and a323a8a.

📒 Files selected for processing (5)
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/__tests__/config/passkeyServer.test.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/shared/src/modules/auth/session.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/shared/src/tests/config/passkeyServer.test.ts
  • packages/shared/src/config/passkeyServer.ts
  • packages/client/src/tests/views/Login.test.tsx
  • packages/client/src/views/Login/index.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Test
  • GitHub Check: CI Gate
  • GitHub Check: Storybook
  • GitHub Check: Playwright Admin CI
  • GitHub Check: Test
  • GitHub Check: Test
  • GitHub Check: Build Docs
  • GitHub Check: Playwright Client CI
  • GitHub Check: Lint And Build
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (16)
packages/shared/**

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

@green-goods/shared is the only home for reusable hooks, providers, stores, modules, types, i18n, and shared UI primitives

Files:

  • packages/shared/src/modules/auth/session.ts
packages/shared/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

Use centralized queryKeys, event-driven invalidation, useCurrentChain() or DEFAULT_CHAIN_ID, logger, and typed domain models such as Address in @green-goods/shared

Keep reusable hooks, providers, stores, modules, and shared UI primitives in @green-goods/shared

Files:

  • packages/shared/src/modules/auth/session.ts
packages/shared/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

Shared UI primitive changes should ship with tests, barrel updates, and Storybook coverage in the same change when applicable

Files:

  • packages/shared/src/modules/auth/session.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Default to single-chain behavior through getDefaultChain() or DEFAULT_CHAIN_ID
Use logger from shared instead of console.log
Use bun run format:check && bun lint for code quality checks

Files:

  • packages/shared/src/modules/auth/session.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use the Address type for Ethereum addresses instead of raw string types

Files:

  • packages/shared/src/modules/auth/session.ts
**/*.{json,ts,tsx}?(locales|i18n|translations|lang)

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Add every new user-facing string to en, es, and pt language files

Files:

  • packages/shared/src/modules/auth/session.ts
packages/shared/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/shared/AGENTS.md)

packages/shared/**/*.{ts,tsx}: Use centralized query keys from queryKeys in packages/shared. Do not invent ad-hoc query arrays.
Use useCurrentChain() or DEFAULT_CHAIN_ID for application defaults in packages/shared, not wallet chain state.
Prefer event-driven invalidation over polling in packages/shared hooks and queries.
Use logger and typed domain models (Address, discriminated unions, unknown for untrusted data) in packages/shared code.

Files:

  • packages/shared/src/modules/auth/session.ts
packages/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use Address type (not string) for Ethereum addresses in TypeScript across all packages

Files:

  • packages/shared/src/modules/auth/session.ts
packages/{shared,client,admin}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Never swallow errors — use parseContractError() + USER_FRIENDLY_ERRORS for contract errors, use createMutationErrorHandler() in shared mutation hooks, use logger from shared (not console.log)

Files:

  • packages/shared/src/modules/auth/session.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/**/*.{ts,tsx}: Use queryKeys.* helpers from shared for React Query key serialization — serialize objects in query keys
Do not use banned vocabulary in i18n strings (enforced by bun run lint:vocab): never use streak, countdown, leaderboard, FOMO, or growth-hacking language (urgent, limited time, re-engagement, retention hook)

Files:

  • packages/shared/src/modules/auth/session.ts
packages/{contracts,agent,admin,shared}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use the Address type for Ethereum addresses.

Files:

  • packages/shared/src/modules/auth/session.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Use logger from shared, never console.log.

Files:

  • packages/shared/src/modules/auth/session.ts
packages/{client,admin,shared}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Remixicon (Ri*Line), never lucide.

Files:

  • packages/shared/src/modules/auth/session.ts
packages/{client,admin,shared}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Any new user-facing string must be added to en, es, and pt.

Files:

  • packages/shared/src/modules/auth/session.ts
packages/{client,admin,shared}/src/**/*.{ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

packages/{client,admin,shared}/src/**/*.{ts,tsx,css}: Treat Baseline Widely Available as the baseline target for frontend changes. Use repo-installed Modern Web Guidance through bun run agentic:guidance before frontend, UI, CSS, accessibility, browser proof, or web-design changes.
Prefer semantic HTML, native controls, platform CSS, and browser primitives before custom JavaScript.

Files:

  • packages/shared/src/modules/auth/session.ts
packages/{client,admin,shared}/src/**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Banned vocabulary for any surface: streak, countdown, leaderboard, FOMO.

Files:

  • packages/shared/src/modules/auth/session.ts
🪛 ast-grep (0.43.0)
packages/shared/src/modules/auth/session.ts

[warning] 106-106: Sensitive information detected in localStorage. Storing sensitive data like emails, usernames, or personal information in localStorage exposes it to malicious scripts and XSS attacks. Use secure storage alternatives or avoid storing sensitive data client-side.
Context: localStorage.setItem(SMART_ACCOUNT_ADDRESS_STORAGE_KEY, address)
Note: [CWE-312] Cleartext Storage of Sensitive Information

(local-storage-sensitive-information)


[warning] 128-128: Sensitive information detected in localStorage. Storing sensitive data like emails, usernames, or personal information in localStorage exposes it to malicious scripts and XSS attacks. Use secure storage alternatives or avoid storing sensitive data client-side.
Context: localStorage.setItem(EMBEDDED_ADDRESS_KEY, address)
Note: [CWE-312] Cleartext Storage of Sensitive Information

(local-storage-sensitive-information)

🔇 Additional comments (6)
packages/shared/src/modules/auth/session.ts (6)

17-17: LGTM!


39-40: LGTM!


105-118: LGTM!


128-134: LGTM!


158-158: LGTM!


203-203: LGTM!

…tion, and restore

Production-readiness review fixes for the account-recovery-hardening lane:

- Tag hosted passkey-server lookup failures by call phase
  (PasskeyServerLookupError) so viem HttpRequestError/TimeoutError shapes
  reach the legacy local fallback during outages; classify WebAuthn
  cancellations and transport failures by error name, not message text.
- Skip the expected-address continuity assert during registration: a
  confirmed separate account is a new address by design, and stale
  expected-address state must not dead-end account creation or burn a
  recovery name server-side.
- Fail closed in session restore when the stored credential rebuilds a
  different address than expected (reason-coded telemetry, nothing cleared).
- Stop fabricating a "user" placeholder username in one-tap login and
  switch-to-passkey; empty routes straight to the local path instead of a
  hosted-server lookup for a literal placeholder name.
- Add a guarded "Recover with username" entry for returning users that
  never exposes separate-account creation, with en/es/pt strings.
- Narrow telemetry address_mismatch matching; add QA notes for RP-blocked
  tunnel domains and HTTP-5xx/timeout outage simulation.

Validation: targeted shared suites green (5 files, 103 tests), client Login
and AccountInfo green (31 tests), shared+client tsc --noEmit clean, oxlint
0 errors, lint:vocab clean, en/es/pt parity verified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Oba-One

Oba-One commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

Production-readiness review fixes landed in c8589809f (review of this lane against .plans/active/account-recovery-hardening/ release gates):

  • Hosted-server lookup failures are now tagged by call phase (PasskeyServerLookupError), so viem HttpRequestError/TimeoutError shapes reach the legacy local fallback during outages — previously only keyword-matching messages (fetch/network/timeout/unavailable) did, and real 5xx/timeout failures locked out users with valid local credentials. Cancellations/transport failures now classify by error name.
  • Registration no longer enforces the expected-address continuity assert — a confirmed separate account is a new address by design; stale expected-address state (e.g. after a corrupted-credential cache clear) could previously dead-end account creation after the WebAuthn ceremony and burn the recovery name server-side.
  • restoreSessionService now fails closed (returns unauthenticated, reason-coded telemetry, nothing cleared) on address drift instead of silently adopting the rebuilt address.
  • One-tap login / switch-to-passkey no longer fabricate a "user" placeholder username — under the flag that triggered a hosted-server lookup for the literal name user on every one-tap.
  • Returning users get a guarded "Recover with username" tertiary (flag-on only) that never exposes separate-account creation.
  • Telemetry address_mismatch matching narrowed; QA notes added for RP-blocked tunnel domains and 5xx/timeout outage simulation.

Validation: 103 shared + 31 client targeted tests green, shared+client tsc --noEmit clean, oxlint 0 errors, lint:vocab clean, en/es/pt parity verified. QA pass 1 (PRD-540) should simulate server-unavailable with HTTP-5xx/timeout shapes, not only network-off.

🤖 Generated with Claude Code

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/shared/src/providers/Auth.tsx (1)

448-452: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Explicit sign-out is no longer durable for passkey users.

This keeps the cached credential, username, and expected smart-account address, but packages/shared/src/workflows/authServices.ts still restores a passkey session whenever authMode is null. After signOut(), a refresh/remount can silently rehydrate the prior passkey account again, which defeats sign-out on shared devices. Preserve recovery metadata behind a separate signed-out sentinel or separate recovery cache so explicit sign-out suppresses automatic restore until the user opts back in.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/providers/Auth.tsx` around lines 448 - 452, Currently
signOut only calls clearAuthMode() and clearEmbeddedAddress() but leaves passkey
recovery metadata intact so authServices.ts will auto-restore a passkey session
when authMode is null; update signOut to persist a "signed-out" sentinel (e.g.,
setPasskeyRecoveryDisabled or write a signedOutRecovery flag) or move recovery
metadata into a separate recovery cache and mark it suppressed, and then modify
the restore path in packages/shared/src/workflows/authServices.ts (the routine
that rehydrates passkey sessions) to check that sentinel/flag before restoring;
ensure any functions reading recovery data (the restore routine) skip recovery
while the sentinel is present and provide a clear opt-in path to remove the
sentinel when the user explicitly signs back in.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/shared/src/providers/Auth.tsx`:
- Around line 382-386: The code uses logical OR to derive finalUserName (const
finalUserName = userName || getStoredUsername() || ""), which treats an explicit
empty string from the caller as falsy and incorrectly falls back to stored
username; change this to use nullish coalescing so only undefined/null falls
back: use userName ?? getStoredUsername() ?? "" for finalUserName, and make the
same change for the other username derivation later (the similar
userName/getStoredUsername expression around lines 433-435) so an explicit "" is
preserved and local one-tap routing remains intact.

---

Outside diff comments:
In `@packages/shared/src/providers/Auth.tsx`:
- Around line 448-452: Currently signOut only calls clearAuthMode() and
clearEmbeddedAddress() but leaves passkey recovery metadata intact so
authServices.ts will auto-restore a passkey session when authMode is null;
update signOut to persist a "signed-out" sentinel (e.g.,
setPasskeyRecoveryDisabled or write a signedOutRecovery flag) or move recovery
metadata into a separate recovery cache and mark it suppressed, and then modify
the restore path in packages/shared/src/workflows/authServices.ts (the routine
that rehydrates passkey sessions) to check that sentinel/flag before restoring;
ensure any functions reading recovery data (the restore routine) skip recovery
while the sentinel is present and provide a clear opt-in path to remove the
sentinel when the user explicitly signs back in.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fa16b58c-348f-4816-9a8b-5651d3a08254

📥 Commits

Reviewing files that changed from the base of the PR and between a323a8a and c858980.

📒 Files selected for processing (10)
  • .plans/active/account-recovery-hardening/plan.todo.md
  • .plans/active/account-recovery-hardening/status.json
  • packages/client/src/__tests__/views/Login.test.tsx
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
  • packages/shared/src/i18n/en.json
  • packages/shared/src/i18n/es.json
  • packages/shared/src/i18n/pt.json
  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/workflows/authServices.ts
✅ Files skipped from review due to trivial changes (2)
  • .plans/active/account-recovery-hardening/plan.todo.md
  • packages/shared/src/i18n/en.json
🚧 Files skipped from review as they are similar to previous changes (6)
  • .plans/active/account-recovery-hardening/status.json
  • packages/client/src/tests/views/Login.test.tsx
  • packages/shared/src/workflows/authServices.ts
  • packages/client/src/views/Login/index.tsx
  • packages/shared/src/i18n/es.json
  • packages/shared/src/i18n/pt.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Test
  • GitHub Check: CI Gate
  • GitHub Check: Playwright Client CI
  • GitHub Check: Test
  • GitHub Check: Test
  • GitHub Check: Storybook
  • GitHub Check: Build Docs
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (23)
packages/shared/**

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

@green-goods/shared is the only home for reusable hooks, providers, stores, modules, types, i18n, and shared UI primitives

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/shared/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

Use centralized queryKeys, event-driven invalidation, useCurrentChain() or DEFAULT_CHAIN_ID, logger, and typed domain models such as Address in @green-goods/shared

Keep reusable hooks, providers, stores, modules, and shared UI primitives in @green-goods/shared

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/shared/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/instructions/shared.instructions.md)

Shared UI primitive changes should ship with tests, barrel updates, and Storybook coverage in the same change when applicable

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Default to single-chain behavior through getDefaultChain() or DEFAULT_CHAIN_ID
Use logger from shared instead of console.log
Use bun run format:check && bun lint for code quality checks

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use the Address type for Ethereum addresses instead of raw string types

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Remixicon (Ri*Line), never lucide for UI icons

Files:

  • packages/shared/src/providers/Auth.tsx
**/*.{json,ts,tsx}?(locales|i18n|translations|lang)

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Add every new user-facing string to en, es, and pt language files

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/shared/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/shared/AGENTS.md)

packages/shared/**/*.{ts,tsx}: Use centralized query keys from queryKeys in packages/shared. Do not invent ad-hoc query arrays.
Use useCurrentChain() or DEFAULT_CHAIN_ID for application defaults in packages/shared, not wallet chain state.
Prefer event-driven invalidation over polling in packages/shared hooks and queries.
Use logger and typed domain models (Address, discriminated unions, unknown for untrusted data) in packages/shared code.

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/{shared,client,admin}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Never swallow errors — use parseContractError() + USER_FRIENDLY_ERRORS for contract errors, use createMutationErrorHandler() in shared mutation hooks, use logger from shared (not console.log)

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/**/*.{ts,tsx}: Use queryKeys.* helpers from shared for React Query key serialization — serialize objects in query keys
Do not use banned vocabulary in i18n strings (enforced by bun run lint:vocab): never use streak, countdown, leaderboard, FOMO, or growth-hacking language (urgent, limited time, re-engagement, retention hook)

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/shared/src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Tailwind v4 does not scan packages/shared/src/ from admin/client builds due to content scanning limitations — do NOT add utility classes (mx-4, w-max, self-center, justify-self-center) directly to JSX in shared components; instead use inline styles for layout or CSS overrides in the consuming package

Files:

  • packages/shared/src/providers/Auth.tsx
packages/{client,admin,shared}/src/**/*.{tsx,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Design System: Load design skill (direction) + ui skill (implementation) explicitly when paradigm, layout composition, new view, tokens, or PR review is at stake — for trivial edits (padding, copy, single component touch), use the rules in CLAUDE.md

Files:

  • packages/shared/src/providers/Auth.tsx
packages/{client,admin,shared}/src/**/*.{css,scss,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Design tokens: never hardcode cubic-bezier, duration, or raw color/radius values — use --spring-* (6 motion tokens), --color-*, --radius-*, --color-material-* + --blur-material-* from theme.css

Files:

  • packages/shared/src/providers/Auth.tsx
packages/{contracts,agent,admin,shared}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use the Address type for Ethereum addresses.

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Use logger from shared, never console.log.

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/{client,admin,shared}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Remixicon (Ri*Line), never lucide.

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/{client,admin,shared}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Any new user-facing string must be added to en, es, and pt.

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/{client,admin,shared}/src/**/*.{ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

packages/{client,admin,shared}/src/**/*.{ts,tsx,css}: Treat Baseline Widely Available as the baseline target for frontend changes. Use repo-installed Modern Web Guidance through bun run agentic:guidance before frontend, UI, CSS, accessibility, browser proof, or web-design changes.
Prefer semantic HTML, native controls, platform CSS, and browser primitives before custom JavaScript.

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/{client,admin,shared}/src/**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Banned vocabulary for any surface: streak, countdown, leaderboard, FOMO.

Files:

  • packages/shared/src/providers/Auth.tsx
  • packages/shared/src/__tests__/workflows/authServices.test.ts
{.github/workflows/**,**/*.test.{js,ts,jsx,tsx},**/*.spec.{js,ts,jsx,tsx}}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use bun run test, never bun test

Files:

  • packages/shared/src/__tests__/workflows/authServices.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use bun run test for running tests

Files:

  • packages/shared/src/__tests__/workflows/authServices.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Use bun run test instead of bun test for running tests — bun test uses bun's built-in runner (ignores vitest config), while bun run test runs the package.json script with proper vitest environment

Files:

  • packages/shared/src/__tests__/workflows/authServices.test.ts
packages/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use Address type (not string) for Ethereum addresses in TypeScript across all packages

Files:

  • packages/shared/src/__tests__/workflows/authServices.test.ts

Comment on lines +382 to +386
// Get stored username or use provided. An empty username routes the
// auth service straight to the local one-tap path — never fabricate a
// placeholder, because under the passkey-server flag any truthy name
// triggers a hosted-server lookup for that literal username.
const finalUserName = userName || getStoredUsername() || "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve an explicit empty username here.

userName || getStoredUsername() || "" turns a caller-supplied "" back into the cached username, so a blank recovery field no longer reaches the intended local one-tap path. Under the server flag that can send a stale recovery name to hosted lookup instead of staying local. Use nullish coalescing so only undefined falls back to storage.

Suggested fix
-      const finalUserName = userName || getStoredUsername() || "";
+      const finalUserName = userName ?? getStoredUsername() ?? "";
-      const finalUserName = userName || getStoredUsername() || "";
+      const finalUserName = userName ?? getStoredUsername() ?? "";

Also applies to: 433-435

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/providers/Auth.tsx` around lines 382 - 386, The code uses
logical OR to derive finalUserName (const finalUserName = userName ||
getStoredUsername() || ""), which treats an explicit empty string from the
caller as falsy and incorrectly falls back to stored username; change this to
use nullish coalescing so only undefined/null falls back: use userName ??
getStoredUsername() ?? "" for finalUserName, and make the same change for the
other username derivation later (the similar userName/getStoredUsername
expression around lines 433-435) so an explicit "" is preserved and local
one-tap routing remains intact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated/codex PR opened by Codex

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

1 participant