Skip to content

feat: add app-wide unlock gate#1076

Open
beeman wants to merge 1 commit into
mainfrom
beeman/app-wide-unlock-gate
Open

feat: add app-wide unlock gate#1076
beeman wants to merge 1 commit into
mainfrom
beeman/app-wide-unlock-gate

Conversation

@beeman

@beeman beeman commented May 14, 2026

Copy link
Copy Markdown
Member

Add a shell unlock gate that checks the active wallet key and blocks app content with the shared unlock dialog when needed.

Add shell translations for the locked state and hide PIN input values in the shared unlock dialog.


Open in Devin Review

Summary by CodeRabbit

  • New Features

    • Added a wallet lock protection layer that gates access to the application until the wallet is unlocked.
    • Displays a centered prompt to users when their wallet is locked, requiring unlock action to proceed.
  • Translations

    • Added English and Spanish translation support for wallet unlock messaging.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 72dcfb66-3cab-4946-8dff-3c45658fd724

📥 Commits

Reviewing files that changed from the base of the PR and between 2d8ec5d and 59aca34.

📒 Files selected for processing (7)
  • packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx
  • packages/feature-shell/src/ui/shell-ui-layout.tsx
  • packages/feature-shell/src/ui/shell-ui-unlock-gate.tsx
  • packages/i18n/locales/en/shell.json
  • packages/i18n/locales/es/shell.json
  • packages/i18n/src/resources.d.ts
  • packages/vault-react/src/data-access/use-vault-unlock-provider.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/i18n/locales/es/shell.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/i18n/src/resources.d.ts
  • packages/i18n/locales/en/shell.json
  • packages/feature-shell/src/ui/shell-ui-layout.tsx
  • packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx
  • packages/feature-shell/src/ui/shell-ui-unlock-gate.tsx

📝 Walkthrough

Walkthrough

Adds a shell-level unlock gate: a hook that checks and triggers wallet unlocks, a UI gate wrapping routed content, English/Spanish translations for the prompt, and a small vault-provider credential input type change.

Changes

Shell Unlock Gate

Layer / File(s) Summary
Unlock Gate Hook Contract & Implementation
packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx
New useShellUnlockGate() hook exports ShellUnlockGateState (isChecking, isLocked, isUnlocking, walletName, walletProtectionMode) and ShellUnlockGate contract with actions.unlock() and state. Implements a React Query status check calling context.vault.requireWalletKey, auto-unlocks unsecured wallets via unlockWallet on specific errors, and exposes an unlock mutation that calls requestUnlock, reports errors via toastError, and invalidates the wallet-specific status query on success.
Unlock Gate UI Component & Layout Integration
packages/feature-shell/src/ui/shell-ui-unlock-gate.tsx, packages/feature-shell/src/ui/shell-ui-layout.tsx
Adds ShellUiUnlockGate which shows a full-screen loader while checking, renders children when unlocked, or displays a centered unlock card when locked. The unlock button calls actions.unlock() and is disabled while unlocking. ShellUiLayout now wraps the Outlet with this gate.
Internationalization Strings & Resource Types
packages/i18n/locales/en/shell.json, packages/i18n/locales/es/shell.json, packages/i18n/src/resources.d.ts
Adds unlockGateTitle, unlockGateDescription (with {{walletName}}), and unlockGateAction to English and Spanish locales and updates the Resources.shell TypeScript interface.
Vault Unlock Provider Credential Input Type
packages/vault-react/src/data-access/use-vault-unlock-provider.ts
Changed VaultUnlockDialogState.credentialInputType to always return 'password'.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I guard the shell with gentle hops,
I check the key and stop all clocks,
If unsecured, I nudge it through,
If locked, I kindly ask for you—
Unlock the wallet, then we’ll hop on!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description provides a clear summary of changes and mentions the linked feature, but does not follow the required template structure with explicit 'Description', 'Screenshots', and 'Checklist' sections. Consider restructuring the description to match the template format with explicit sections and completing the checklist items to indicate whether tests and documentation were updated.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add app-wide unlock gate' accurately describes the main change of adding a shell-level unlock gate component to block app content when the wallet is locked.
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 beeman/app-wide-unlock-gate

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


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.

@bundlemon

bundlemon Bot commented May 14, 2026

Copy link
Copy Markdown

BundleMon

Files removed (2)
Status Path Size Limits
apps/extension/.output/chrome-mv3/chunks/useQ
uery-(hash).js
-3.12KB -
apps/web/dist/assets/useQuery-(hash).js
-3.12KB -
Files updated (8)
Status Path Size Limits
apps/web/dist/assets/index-(hash).js
304.95KB (+4.42KB +1.47%) -
apps/extension/.output/chrome-mv3/chunks/clie
nt-(hash).js
280.06KB (+4.32KB +1.57%) -
apps/extension/.output/chrome-mv3/chunks/port
folio-(hash).js
2.67KB (-15B -0.54%) -
apps/web/dist/assets/portfolio-(hash).js
2.67KB (-20B -0.72%) -
apps/web/dist/assets/settings-(hash).js
26.06KB (-25B -0.09%) -
apps/extension/.output/chrome-mv3/chunks/sett
ings-(hash).js
26.06KB (-26B -0.1%) -
apps/extension/.output/chrome-mv3/chunks/tool
s-(hash).js
1.8KB (-41B -2.18%) -
apps/web/dist/assets/tools-(hash).js
1.8KB (-41B -2.17%) -
Unchanged files (65)
Status Path Size Limits
apps/web/dist/assets/combobox-(hash).js
45.75KB -
apps/extension/.output/chrome-mv3/chunks/comb
obox-(hash).js
45.74KB -
apps/web/dist/assets/toggle-(hash).js
27.61KB -
apps/extension/.output/chrome-mv3/chunks/togg
le-(hash).js
27.59KB -
apps/extension/.output/chrome-mv3/chunks/form
-(hash).js
13.17KB -
apps/web/dist/assets/form-(hash).js
13.16KB -
apps/extension/.output/chrome-mv3/chunks/inde
x.browser-(hash).js
9.13KB -
apps/web/dist/assets/select-(hash).js
8.55KB -
apps/extension/.output/chrome-mv3/chunks/sele
ct-(hash).js
8.54KB -
apps/extension/.output/chrome-mv3/chunks/onbo
arding-(hash).js
5.82KB -
apps/web/dist/assets/onboarding-(hash).js
5.82KB -
apps/web/dist/assets/index.browser-(hash).js
4.64KB -
apps/extension/.output/chrome-mv3/chunks/crea
te-(hash).js
4.56KB -
apps/web/dist/assets/create-(hash).js
4.55KB -
apps/extension/.output/chrome-mv3/chunks/cons
tants-(hash).js
3.6KB -
apps/web/dist/assets/constants-(hash).js
3.6KB -
apps/extension/.output/chrome-mv3/chunks/requ
est-(hash).js
2.86KB -
apps/web/dist/assets/request-(hash).js
2.85KB -
apps/extension/.output/chrome-mv3/assets/vani
ty-(hash).js
2.79KB -
apps/web/dist/assets/vanity-(hash).js
2.79KB -
apps/extension/.output/chrome-mv3/chunks/send
-(hash).js
2.46KB -
apps/web/dist/assets/send-(hash).js
2.46KB -
apps/web/dist/assets/dropdown-(hash).js
2.16KB -
apps/extension/.output/chrome-mv3/chunks/drop
down-(hash).js
2.16KB -
apps/extension/.output/chrome-mv3/chunks/chec
kbox-(hash).js
1.89KB -
apps/web/dist/assets/checkbox-(hash).js
1.89KB -
apps/extension/.output/chrome-mv3/chunks/expl
orer-(hash).js
1.52KB -
apps/web/dist/assets/explorer-(hash).js
1.52KB -
apps/web/dist/assets/badge-(hash).js
770B -
apps/extension/.output/chrome-mv3/chunks/badg
e-(hash).js
769B -
apps/extension/.output/chrome-mv3/chunks/zod-
(hash).js
766B -
apps/web/dist/assets/zod-(hash).js
766B -
apps/extension/.output/chrome-mv3/chunks/stan
dard-(hash).js
656B -
apps/web/dist/assets/standard-(hash).js
653B -
apps/extension/.output/chrome-mv3/chunks/tabl
e-(hash).js
596B -
apps/web/dist/assets/table-(hash).js
594B -
apps/web/dist/assets/button-(hash).js
579B -
apps/extension/.output/chrome-mv3/chunks/butt
on-(hash).js
576B -
apps/extension/.output/chrome-mv3/chunks/book
mark-(hash).js
554B -
apps/web/dist/assets/bookmark-(hash).js
551B -
apps/extension/.output/chrome-mv3/chunks/ui-(
hash).js
525B -
apps/web/dist/assets/ui-(hash).js
524B -
apps/extension/.output/chrome-mv3/chunks/text
area-(hash).js
498B -
apps/web/dist/assets/textarea-(hash).js
495B -
apps/extension/.output/chrome-mv3/chunks/dev-
(hash).js
276B -
apps/web/dist/assets/dev-(hash).js
275B -
apps/web/dist/assets/use-(hash).js
227B -
apps/extension/.output/chrome-mv3/chunks/use-
(hash).js
226B -
apps/extension/.output/chrome-mv3/chunks/side
panel-(hash).js
203B -
apps/extension/.output/chrome-mv3/chunks/popu
p-(hash).js
201B -
apps/extension/.output/chrome-mv3/chunks/inde
x-(hash).js
173B -
apps/extension/.output/chrome-mv3/chunks/form
at-(hash).js
166B -
apps/web/dist/assets/format-(hash).js
166B -
apps/web/dist/assets/sol-(hash).js
152B -
apps/extension/.output/chrome-mv3/chunks/sol-
(hash).js
151B -
apps/extension/.output/chrome-mv3/chunks/elli
psify-(hash).js
145B -
apps/web/dist/assets/ellipsify-(hash).js
145B -
apps/extension/.output/chrome-mv3/chunks/chev
ron-(hash).js
143B -
apps/web/dist/assets/chevron-(hash).js
140B -
apps/extension/.output/chrome-mv3/chunks/stri
ngify-(hash).js
138B -
apps/extension/.output/chrome-mv3/chunks/toas
t-(hash).js
138B -
apps/web/dist/assets/stringify-(hash).js
137B -
apps/web/dist/assets/toast-(hash).js
136B -
apps/extension/.output/chrome-mv3/chunks/netw
ork-(hash).js
121B -
apps/web/dist/assets/network-(hash).js
121B -

Total files change +2.32KB +0.25%

Groups updated (2)
Status Path Size Limits
apps/web/dist/**/*-.js
583.75KB (-526B -0.09%) -
apps/extension/.output/chrome-mv3/**/*-
.js
558.36KB (-591B -0.1%) -

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d8ec5d27e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

},
state: {
isChecking: statusQuery.isLoading,
isLocked: statusQuery.data === false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Fail closed while unlock status is unresolved

This gate currently treats every state except data === false as unlocked, while only showing a loader for isLoading. In this app, queries are persisted via PersistQueryClientProvider (packages/feature-shell/src/data-access/shell-providers.tsx), so a previously cached true can be hydrated on startup before requireWalletKey rechecks the new in-memory vault state. That means locked wallets can briefly render routed content (and run child effects) until refetch flips the value, which defeats the purpose of an app-wide lock gate.

Useful? React with 👍 / 👎.

Add a shell unlock gate that checks the active wallet key and blocks app content with the shared unlock dialog when needed.

Add shell translations for the locked state and hide PIN input values in the shared unlock dialog.
@beeman beeman force-pushed the beeman/app-wide-unlock-gate branch from 2d8ec5d to 59aca34 Compare May 14, 2026 13:27
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 14, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
samui-wallet-web 59aca34 Commit Preview URL

Branch Preview URL
May 14 2026, 01:32 PM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 14, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
samui-wallet-api 59aca34 Commit Preview URL

Branch Preview URL
May 14 2026, 01:32 PM

@devin-ai-integration devin-ai-integration 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.

Devin Review found 2 potential issues.

View 3 additional findings in Devin Review.

Open in Devin Review

confirmPasswordLabel: copy.confirmPasswordLabel,
credential,
credentialInputType: pending?.mode === 'pin' ? 'text' : 'password',
credentialInputType: 'password',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 PIN input type changed to 'password', inconsistent with request unlock dialog

The credentialInputType was changed from pending?.mode === 'pin' ? 'text' : 'password' to a hardcoded 'password'. This means PIN-protected wallets now show a masked password input (dots) in the vault unlock dialog instead of visible digits. This is inconsistent with packages/feature-request/src/ui/request-ui-unlock-dialog.tsx:35 which still uses type={state.mode === 'pin' ? 'text' : 'password'} along with inputMode="numeric" and pattern="[0-9]*" for PIN mode. The previous code deliberately differentiated between PIN and password modes; this change removes that distinction.

Suggested change
credentialInputType: 'password',
credentialInputType: pending?.mode === 'pin' ? 'text' : 'password',
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +72 to +73
isChecking: statusQuery.isLoading,
isLocked: statusQuery.data === false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Unlock gate fails open on query error instead of showing locked state

When statusQuery errors (e.g., unlockWallet throws for an unsecured wallet at use-shell-unlock-gate.tsx:41), statusQuery.data is undefined and statusQuery.isLoading is false. This means isChecking is false and isLocked is undefined === falsefalse. The gate then renders children (shell-ui-unlock-gate.tsx:16-17) even though the wallet wasn't actually unlocked. The gate should fail closed (show locked/error state) rather than fail open.

How the error propagates

In the queryFn, the catch block for requireWalletKey does not wrap the unlockWallet call in its own try-catch. If unlockWallet throws, the error propagates out of the queryFn, causing the query to enter an error state with data === undefined. Since the component only checks statusQuery.data === false for the locked state, the undefined value falls through to show content.

Suggested change
isChecking: statusQuery.isLoading,
isLocked: statusQuery.data === false,
isChecking: statusQuery.isLoading,
isLocked: statusQuery.data !== true,
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59aca34318

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +47 to +49
<ShellUiUnlockGate>
<Outlet />
</ShellUiUnlockGate>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate modal routes behind unlock check

ShellUiUnlockGate is applied only around this layout’s <Outlet />, so it protects child routes under ShellUiLayout but not sibling top-level routes like /modals/* (defined in packages/feature-shell/src/create-router.tsx as a sibling of the layout route). As a result, a locked wallet can still navigate directly to modal screens (e.g. receive/send flows), which breaks the new “app-wide unlock gate” behavior and exposes app content outside the lock gate.

Useful? React with 👍 / 👎.

@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

🤖 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/feature-shell/src/data-access/use-shell-unlock-gate.tsx`:
- Around line 72-74: The gate currently treats undefined as unlocked via
`isLocked: statusQuery.data === false`; change this to fail-closed by setting
`isLocked: statusQuery.data !== true` so only an explicit `true` marks unlocked.
While editing use-shell-unlock-gate.tsx, update the `isLocked` assignment that
references `statusQuery.data`, and optionally adjust `isChecking` (which uses
`statusQuery.isLoading`) to include `statusQuery.isError` if you want the UI to
remain in a checking state on query failures; keep `isUnlocking` tied to
`unlockMutation.isPending`.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e2f5c778-b295-424a-ac47-7b63db0e1c52

📥 Commits

Reviewing files that changed from the base of the PR and between 69e4304 and 2d8ec5d.

📒 Files selected for processing (7)
  • packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx
  • packages/feature-shell/src/ui/shell-ui-layout.tsx
  • packages/feature-shell/src/ui/shell-ui-unlock-gate.tsx
  • packages/i18n/locales/en/shell.json
  • packages/i18n/locales/es/shell.json
  • packages/i18n/src/resources.d.ts
  • packages/vault-react/src/data-access/use-vault-unlock-provider.ts

Comment on lines +72 to +74
isChecking: statusQuery.isLoading,
isLocked: statusQuery.data === false,
isUnlocking: unlockMutation.isPending,

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

🧩 Analysis chain

🌐 Web query:

In TanStack React Query v5, when a query function throws (with retry disabled), what are the values of data, isError, and isLoading?

💡 Result:

If a TanStack React Query v5 query function throws (and retries are disabled with retry: false), then after the failed attempt settles: - data: undefined [1] - isError: true [1] - isLoading: false [1] Reasoning: In v5, isError is derived from status === 'error' [1], and data is only available in status === 'success' (otherwise it’s undefined) [1]. Also, isLoading is only true when the first fetch is in-flight, defined as isFetching && isPending [1]; once the query ends in status: 'error', it’s no longer pending/in-flight, so isLoading becomes false.

Citations:


🏁 Script executed:

# Check if file exists and view the relevant lines
if [ -f "packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx" ]; then
  echo "=== File found ==="
  wc -l "packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx"
  echo ""
  echo "=== Lines 60-85 context ==="
  sed -n '60,85p' "packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx"
else
  echo "File not found at specified path"
  # Try to find it
  find . -name "use-shell-unlock-gate.tsx" -type f 2>/dev/null
fi

Repository: samui-build/samui-wallet

Length of output: 682


🏁 Script executed:

head -50 "packages/feature-shell/src/data-access/use-shell-unlock-gate.tsx"

Repository: samui-build/samui-wallet

Length of output: 1740


Fail closed when unlock status is not explicitly true.

isLocked: statusQuery.data === false treats undefined (after query error) as unlocked, exposing app content while lock status is unknown. With retry: false, query failures leave data: undefined, causing the gate to fail open.

💡 Proposed fix
     state: {
       isChecking: statusQuery.isLoading,
-      isLocked: statusQuery.data === false,
+      isLocked: statusQuery.data !== true,
       isUnlocking: unlockMutation.isPending,
       walletName: wallet.name,
       walletProtectionMode: wallet.protectionMode,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
isChecking: statusQuery.isLoading,
isLocked: statusQuery.data === false,
isUnlocking: unlockMutation.isPending,
isChecking: statusQuery.isLoading,
isLocked: statusQuery.data !== true,
isUnlocking: unlockMutation.isPending,
🤖 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/feature-shell/src/data-access/use-shell-unlock-gate.tsx` around
lines 72 - 74, The gate currently treats undefined as unlocked via `isLocked:
statusQuery.data === false`; change this to fail-closed by setting `isLocked:
statusQuery.data !== true` so only an explicit `true` marks unlocked. While
editing use-shell-unlock-gate.tsx, update the `isLocked` assignment that
references `statusQuery.data`, and optionally adjust `isChecking` (which uses
`statusQuery.isLoading`) to include `statusQuery.isError` if you want the UI to
remain in a checking state on query failures; keep `isUnlocking` tied to
`unlockMutation.isPending`.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant