Skip to content

Feat: 添加应用锁屏功能 - #1609

Open
Ryanisgood wants to merge 84 commits into
binaricat:mainfrom
Ryanisgood:feature/app-lock-screen
Open

Feat: 添加应用锁屏功能#1609
Ryanisgood wants to merge 84 commits into
binaricat:mainfrom
Ryanisgood:feature/app-lock-screen

Conversation

@Ryanisgood

@Ryanisgood Ryanisgood commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

变更内容

新增 Netcatty 应用锁屏能力:应用可以在主界面渲染前锁定,也可以从顶部标签栏手动锁定,并支持空闲超时、隐藏到后台、重新打开等场景下的锁定/恢复。

本 PR 目前覆盖的是完整 App Lock 链路:

  • 新增锁屏密码 verifier 创建、密码修改、禁用/重置 App Lock、锁屏设置持久化。
  • 新增 AppLockGate 启动 gate,避免启动锁定时主界面先渲染到锁屏背后。
  • 新增锁屏 Overlay,支持密码解锁、系统认证解锁、错误提示、自动聚焦和重开后的状态刷新。
  • 顶部标签栏新增手动锁定入口;设置页新增 App Lock 配置区。
  • 新增空闲活动记录和空闲超时锁定,支持禁用空闲自动锁定。
  • 主进程新增 App Lock 生命周期处理:隐藏到后台、退出前处理、激活/重开、主窗口崩溃后的恢复、终端弹窗 route ownership。
  • 新增 renderer/main IPC bridge:设置读取/更新、runtime state、reset、lock/unlock、activity report、系统解锁状态等。
  • 新增系统解锁能力:
    • macOS 通过 Electron systemPreferences 使用 Touch ID。
    • Windows 通过打包的 native helper 使用 Windows Hello。
  • 新增 Windows Hello helper 构建与打包:
    • per-arch helper 输出。
    • PE machine 架构校验。
    • MSVC 开发环境初始化。
    • Windows 打包架构处理,避免 x64 打包误触发 arm64 helper。
  • 补充 App Lock 相关多语言文案。
  • 补充功能所需的开发/构建适配:dev CSP、jsdom runtime 测试、CI Windows MSVC setup。

给 Reviewer 的说明

这个 PR 的 diff 比“添加锁屏”听起来大,因为它不是单个 UI Overlay,而是跨 renderer gate、Electron 生命周期、持久化设置、IPC、安全认证、Windows native helper 打包和回归测试的一整套功能。

当前 PR 统计:

  • 69 个文件,+8888/-220。
  • 测试和 test support 约 +4554 行。
  • Renderer/UI/state 约 +1813 行。
  • Electron main/bridge/packaging 约 +1424 行。
  • Windows Hello helper/build script 约 +324 行。
  • package.json / package-lock.json 约 +505 行。

Windows Hello/helper 打包相关内容包含在这个 PR 里,是因为 UI 已经暴露了系统解锁入口,而 Windows 需要 native helper 才能完成该路径。如果希望降低 review 面积,可以把本 PR 收敛为“密码锁屏核心”,再把系统解锁/Windows Hello 拆成后续 PR。

行为细节

  • 只有在 App Lock 已启用且存在 password verifier 时才真正锁定。
  • 启动锁定会 gate 主 renderer,防止解锁前看到主界面内容。
  • 空闲锁定支持关闭;timeout 为 disabled/0 时不会自动空闲锁定。
  • 禁用 App Lock 会删除当前 password verifier;后续重新启用必须创建新密码。
  • reset 需要当前密码,成功后会关闭 App Lock、清空 verifier 并解锁当前 runtime。
  • Overlay 保留隐藏重置入口,避免忘记密码后完全锁死。
  • 系统解锁的“支持/可用”和“设置中启用”分开判断。
  • reset/unlock bridge 缺失或失败时不会乐观解锁,避免假解锁。
  • 重开/聚焦时会重新同步 runtime lock state,避免窗口恢复后显示旧状态。

安全与锁死风险处理

  • 正确密码解锁后,主进程更新 runtime state 并广播到相关窗口。
  • App Lock 已关闭或 verifier 已清空时,解锁请求会直接放行,避免设置状态与 UI 状态不一致导致锁死。
  • reset IPC 缺失或失败时保持锁屏并提示错误,不会直接放行。
  • 系统解锁失败、取消、不可用会返回明确状态,不会影响密码解锁路径。
  • Windows Hello helper 构建产物会校验目标架构,避免打包错误架构的 exe。
  • 退出前 dirty editor 检查和后台锁定保持兼容,避免退出流程被锁屏状态打断。

验证

合并最新 upstream/main 后已在本地验证:

  • git diff --name-only --diff-filter=U:无未解决冲突。
  • git diff --cached --check:提交 merge 前通过。
  • npm run lint:通过,0 errors,2 个已有 warnings。
  • npm run generate:capability-tools + generated JSON diff check:无 drift。
  • npm test:4007 tests,4004 passed,0 failed,3 skipped。
  • npm run build:通过。

冲突解决后已推送当前 head commit,并重新触发 CI。

关联 Issue

关联 #672
关联 #955

@Ryanisgood Ryanisgood changed the title 添加应用锁屏与应急重置机制 添加应用锁屏功能 Jun 24, 2026

@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: 5be97aa5e0

ℹ️ 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".

notifyRendererReady: boolean;
renderChildren: boolean;
}): boolean {
return input.notifyRendererReady && input.renderChildren;

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 Keep startup deep links queued while locked

When Netcatty is launched from an ssh:// link with App Lock enabled, renderChildren stays false on the startup lock screen, so this suppresses rendererReady until the user unlocks. deliverSshDeepLink waits on sendWhenRendererReady with a 15s timeout after the URL has already been shifted from the pending queue, so taking longer than that to enter the password drops the deep link instead of connecting after unlock. Consider keeping the deep link queued/buffered while locked or separating renderer readiness from app-content mounting.

Useful? React with 👍 / 👎.

The overlay helper import was accidentally inserted inside open named
import lists, which broke TypeScript parsing. Move it to a top-level
import statement in SnippetsManager and SFTP keyboard shortcuts.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 01d91f55a7

ℹ️ 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 thread index.tsx
<TooltipProvider delayDuration={300}>
<AppLockGate
notifyRendererReady={false}
forceRenderChildren

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 terminal popup startup while locked

When a terminal popup is opened while the shared app-lock runtime is locked, this forceRenderChildren path mounts TerminalPopupPage before unlock; after the buffered config arrives it renders <Terminal>, whose mount effects start/reuse the terminal backend and can run the popup startup command with saved credentials behind the lock overlay. Keep only the config listener mounted while locked, or defer rendering/starting the terminal until appLock.locked is false.

Useful? React with 👍 / 👎.

Keep forceRenderChildren so popup config IPC still registers while locked,
but do not mark the popup ready (or mount Terminal/startup commands) until
allowTerminalStart is true after unlock.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 1e0988d5f0

ℹ️ 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 thread components/TerminalPopupPage.tsx Outdated
const ready = Boolean(config && host && vaultInitialized);
// Defer backend start while app-locked so startup commands/credentials do not
// run behind the overlay (Codex P2). Config listener still mounts above.
const ready = Boolean(config && host && vaultInitialized && allowTerminalStart);

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 Keep running terminal popups mounted while locked

When App Lock engages after a terminal popup has already started, allowTerminalStart flips to false and this makes ready false, so the render switches from <Terminal> to the spinner. That unmounts Terminal, whose unmount path tears down and closes the backend session, so an idle/background lock can disconnect the popup and then start a fresh session or rerun the startup command after unlock. Track whether the popup terminal has already been mounted and only use the lock state to block the initial start.

Useful? React with 👍 / 👎.

Only defer the initial Terminal start while locked. After a popup session
has begun, keep ready true so re-lock does not unmount the live terminal.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 4e6c323559

ℹ️ 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 +64 to +67
// Hidden prewarm windows (e.g. Settings) keep the process alive but are
// not a user session — do not block fresh-session re-lock (Codex P2).
if (typeof win.isVisible === "function" && !win.isVisible()) {
return 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.

P2 Badge Count minimized user windows as active sessions

When the only remaining app UI is a user-created auxiliary window that is minimized, such as a terminal popup or Settings window, isVisible() is false here so createAndShowMainWindow() treats the next Dock reopen as a fresh session and calls ensureAppLockForFreshSession(). That broadcasts a startup lock into an existing active window even though not all app UI was closed; exclude only known hidden prewarm windows, or count minimized user windows as usable.

Useful? React with 👍 / 👎.

isVisible is false for minimized BrowserWindows, which made Dock reopen
re-lock while a minimized main/session window was still open. Treat
isMinimized() as a live session, while still ignoring hidden prewarm
windows.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 79603979ef

ℹ️ 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".


async function save(nextSettings) {
const normalized = normalizeAppLockSettings(nextSettings);
await writeFile(filePath, `${JSON.stringify(normalized, null, 2)}\n`, { mode: 0o600 });

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 Persist app-lock settings atomically

If Netcatty or the machine stops while this writeFile has truncated the existing file but has not finished writing JSON, the next startup catches the parse failure in load() and replaces the state with DEFAULT_APP_LOCK_SETTINGS, silently disabling an enabled lock. Any timeout, password, or system-unlock change rewrites this security-critical file, so preserve the previous valid verifier by writing and syncing a sibling temporary file before atomically renaming it.

Useful? React with 👍 / 👎.

Menu,
app,
isMac,
isAppLocked: typeof options.isAppLocked === "function"

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 Apply the lock check to native close actions

Fresh evidence after the App.tsx command-close guard is that the new isAppLocked callback is consulted only by Reload and DevTools: closeFocusedWindow below still calls closeBrowserWindow directly for non-main auxiliary windows. With a locked terminal popup focused, Cmd/Ctrl+W from the application menu can therefore destroy the popup, and Terminal teardown closes its running backend session behind the overlay; return early from native close roles while locked and gate the Settings close IPC path as well.

Useful? React with 👍 / 👎.

Write app-lock settings via temp file + rename to avoid truncating the
verifier on crash. Gate application-menu Close and window:close IPC while
locked so popups are not destroyed behind the overlay.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 81a62b7ae2

ℹ️ 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".

const appLockSection = source.slice(appLockSectionStart, nextSectionStart);

assert.match(source, /appLockSystemUnlockStatus\?\.available \|\| appLockSettings\.systemUnlockEnabled/);
assert.match(appLockSection, /disabled=\{isSavingAppLockSystemUnlock \|\| !appLockSystemUnlockStatus\.available\}/);

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 Update the stale system-unlock assertion

This assertion still expects the toggle to be disabled whenever system authentication is unavailable, but the implementation intentionally keeps an already-enabled toggle clickable via !appLockSystemUnlockStatus.available && !appLockSettings.systemUnlockEnabled. The targeted test run therefore always fails at this line; update the expectation to include the enabled-state exception so the test suite can pass.

Useful? React with 👍 / 👎.

Comment on lines +207 to +210
if (typeof rename === "function") {
const tmpPath = `${filePath}.tmp`;
await writeFile(tmpPath, payload, { mode: 0o600 });
await rename(tmpPath, filePath);

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 Serialize app-lock settings writes

When two app-lock mutations overlap—for example, changing the timeout while a system-unlock save is pending—both save() calls write and rename the same .tmp path after independently reading the current snapshot. The first rename can remove that path before the second rename, causing an ENOENT, and stale snapshots can also make the later mutation overwrite unrelated fields; renderer callers commonly swallow these rejections. Serialize mutations and use a unique temporary path per write so concurrent settings changes cannot fail or be lost.

Useful? React with 👍 / 👎.

Queue app-lock save mutations and use unique temp paths so concurrent
writes cannot ENOENT or clobber. Update the system-unlock toggle test to
match the already-enabled-while-unavailable disable path.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 820587b4f5

ℹ️ 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 +542 to +544
const nextState = runtimeBridge.lock(reason);
syncIdleTimer();
broadcast("netcatty:appLock:runtimeStateChanged", nextState);

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 Close already-open DevTools when locking

Fresh evidence after the View-menu guard is that it only prevents a new toggleDevTools click; setLocked() does not close DevTools that were opened before an idle, background, or manual lock. Detached or docked DevTools remain outside the DOM overlay, so someone arriving after the lock can use the existing console to inspect the mounted application state and invoke privileged renderer bridges without unlocking. Close DevTools for every app window as part of the lock transition.

Useful? React with 👍 / 👎.

Comment on lines +375 to +376
async function saveSettings(nextSettings) {
const saved = await settingsStore.save(nextSettings);

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 Serialize the complete settings mutations

Fresh evidence after the writeChain fix is that only settingsStore.save(nextSettings) is queued; each controller mutation still calls getSettings() and constructs nextSettings before entering that queue. If a timeout or system-unlock change overlaps another pending save, both requests can capture the same old snapshot, and the later queued write can revert the first request's field or restore an old password verifier. Queue the read-modify-write operation itself, or merge each mutation against the latest snapshot inside the serialized section.

Useful? React with 👍 / 👎.

return { ok: false, error: "unsupported" };
}

const result = await systemAuthBridge.requestUnlock();

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 Deduplicate system-auth prompts across windows

When multiple app windows are visible during an idle/manual lock, each AppLockGate receives the shared lock broadcast and independently auto-prompts, but this main-process path has no shared in-flight guard. A main window plus Settings or a terminal popup can therefore launch concurrent Touch ID/Windows Hello requests; later requests may show additional prompts or fail as device-busy and surface errors in the other windows. Reuse one controller-level authentication promise and broadcast its result to all locked renderers.

Useful? React with 👍 / 👎.

…tem unlock

Close open DevTools when locking, queue full RMW settings mutations, and share
one in-flight system-auth prompt across windows.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 851e772026

ℹ️ 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 +470 to +474
const saved = await saveSettings({
...current,
enabled: current.enabled || !current.passwordVerifier,
passwordVerifier,
});

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 Queue password changes with all settings mutations

Fresh evidence after the mutation-chain fix is that requestPasswordChange() still snapshots current outside mutateSettings() and writes it directly. If the user changes the timeout while password replacement is deriving/verifying a hash, the queued timeout mutation can capture the old verifier and save it after this write, silently restoring the old password even though the password-change request reported success. Put the entire password read-verify-write operation on the same mutation chain.

Useful? React with 👍 / 👎.

};
}

const nextState = runtimeBridge.unlock();

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 Reject stale system-auth results after a re-lock

When Touch ID or Windows Hello is pending and a newer lock transition occurs before the prompt resolves—for example, an idle-locked window starts authentication and is then hidden, changing the lock to background—this unconditional unlock() clears that newer lock. A successful stale prompt can therefore leave the hidden app unlocked when it is reopened; capture the runtime version at prompt start and only unlock if the same lock presentation is still current.

Useful? React with 👍 / 👎.

Comment on lines +126 to +129
unsubscribeAppLockRuntime = appLockController.subscribe((state) => {
if (state?.locked === false) {
flushPendingPortForwardToggles();
}

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 Hide cached tray details while locked

When App Lock engages on Linux with close-to-tray enabled, this subscription does nothing on the locked transition, so the native tray context menu built by buildTrayMenuTemplate() continues displaying cached host labels, session status, and port-forward endpoints outside the lock overlay. Anyone at the machine can inspect those details without unlocking; rebuild/redact the native tray menu when state.locked becomes true and restore it after unlock.

Useful? React with 👍 / 👎.

Password-change saves go through the settings mutation queue. System unlock
re-checks locked state after the OS prompt so a re-lock during the dialog
cannot unlock from a stale auth success.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 7c5b811c27

ℹ️ 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 +423 to +427
const saved = await saveSettings({
enabled: false,
timeoutMinutes: current.timeoutMinutes,
passwordVerifier: null,
});

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 Queue disable with the settings mutations

Fresh evidence after the mutation-chain fixes is that requestDisable() still calls saveSettings() directly. If the user changes the timeout while the disable write is pending—the dropdown remains enabled during isDisablingAppLocksetTimeoutMinutes() can snapshot the still-enabled settings and enqueue its save after the disable, restoring the old verifier and re-enabling App Lock even though disabling reported success. Put the complete disable read/verify/write operation on the same controller mutation queue.

Useful? React with 👍 / 👎.

Comment on lines +627 to +629
if (runtimeBridge.getState().locked !== true) {
return { ok: false, error: "not-locked" };
}

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 Compare lock versions before applying system auth

Fresh evidence after the stale-result fix is that this check only tests the locked boolean. If authentication began for an idle lock and the app is hidden before the prompt resolves, setLocked("background") leaves locked true while advancing the runtime version and changing the reason, so the old prompt still passes this check and unlocks the newer background lock; the hidden app is then already unlocked when reopened. Capture the runtime version at prompt start and require the same lock presentation before calling unlock().

Useful? React with 👍 / 👎.

While the runtime is locked, tray panel/menu data is redacted to empty
sessions and port-forwards so cached host details are not visible.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@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: 90b05946d0

ℹ️ 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".


const onWindowCapture = (event: KeyboardEvent) => {
// Suppress other window-level keydown handlers registered after us.
event.stopImmediatePropagation();

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 Let password keystrokes reach the lock form

Fresh evidence after the earlier key-blocker revisions is this unconditional stopImmediatePropagation() on the window capture listener: stopping propagation at window prevents the event from continuing down to the password input, so typed characters and Enter never reach the lock form. Whenever password unlock is required, users cannot type their password and may be unable to unlock unless system authentication or a mouse-driven paste is available; block underlying shortcuts without stopping the event before its target.

Useful? React with 👍 / 👎.

Comment thread index.tsx
locked; defer starting the terminal until unlock (Codex P2). */}
<LazyTerminalPopupPage
settings={settings}
allowTerminalStart={!appLock.locked}

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 Wait for lock initialization before starting popup terminals

Fresh evidence after the popup startup guard is that forceRenderChildren renders this route before the runtime IPC resolves, while the initial app-lock state is initialized: false, locked: false; therefore this expression initially passes true. If a popup is created while the shared runtime is locked, or the app locks while that popup is loading, its buffered config and vault initialization can make TerminalPopupPage start the backend and startup command before the locked state arrives. Require appLock.initialized && !appLock.locked for the initial start.

Useful? React with 👍 / 👎.

Put requestDisable/requestReset on the settings mutation queue so concurrent
timeout changes cannot re-enable App Lock after a successful disable. Capture
the runtime lock version before system auth and reject the prompt if the lock
epoch advanced (idle→background re-lock) while the dialog was open.
@binaricat

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: c85ab87262

ℹ️ 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".

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.

2 participants