Repository navigation
Description
Client or integration
Other
Area
Platform (Windows / macOS / Linux)
Summary
On Windows, loadConfig() starts an optional, unawaited ACL hardening flight on the OpenCodex config directory (src/config/paths.ts, hardenConfigDir). Writers that create or harden files under that directory can run while that parent flight is still in progress. Parent inheritance work can then drop a freshly applied child grant, and the write fails or leaves the file with an unexpected ACL.
#7777 fixed this for the observed failure class: intercept CA, proxy token and picker secrets, and credential-bearing Claude settings now wait through withConfigDirHardeningSettled before their synchronous write. Other writers under the config root have the same overlap and are not yet gated. Known sites:
- config.json saves (
src/server/management/agent-settings-routes.tsaround line 1590) - Claude Desktop 3p config-library publication (
src/claude/desktop-3p.tsaround lines 845 and 863) - the remote Desktop store hardening and publication (
src/claude/desktop-remote-store-io.tsaround lines 60 and 71)
Expected: every writer that applies a required ACL to a path under the config root waits for overlapping config-root ACL work, like the #7777 writers do, with the same bounded deadline and a clean refusal on timeout.
This predates v2.92.0. The optional flight dates from #3257 and was last changed in #7107. It was scoped out of #7777 and of the v2.93.0 release by the release captain.
Reproduction
Intermittent, not consistently reproducible by hand. The overlap is deterministic with the test seams used by tests/claude-integration/claude-intercept-acl-barrier.test.ts:
- Hold the async icacls runner (
setAsyncIcaclsRunnerForTests) and starthardenConfigDir()so a parent flight is in progress. - Trigger one of the writers above.
- Observe descendant ACL commands for that writer's path while the parent flight is still held.
On hosted Windows CI the same class produced an empty DACL and ca_unavailable for the intercept CA (lane=all run 40389603119, Windows shard 7/9) before #7777.
Version
2.93.0 (dev 42549ba)
Operating system
Windows (hosted windows-latest runners and Windows 11)
Provider and model
No response
Logs or error output
_No response_Screenshots and supporting files
No response
Redacted configuration
_No response_Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
coderabbitai commentedon Oct 27, 2026
🔗 Related PRs
#7777 - fix(claude): drain parent ACL flights before intercept secret writes [open]
#7781 - fix(claude): report a timed-out first-party rollback as incomplete [open]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
revert(integrations): keep catalog refresh admission out of this PR
fix(windows): gate config and Desktop writer phases on config-root AC…
lidge-jun commentedon Oct 28, 2026
Partially addressed on
devby #7826 (6bc511d1b5f74160cf07e7a90a5e28a53d8d59e8). The async management and CLI writer phases now admit throughwithConfigDirHardeningSettled: config saves and partial updates (config-routes.ts,agent-settings-routes.ts), the native Desktop toggle,ocx claude-desktop, and Desktop gateway cleanup. Each callback covers a complete synchronous phase and derives its state inside admission. A timeout refuses before any commit, or goes through the existing rollback and partial-commit reporting after one.Still open here:
saveConfig, the Desktop store I/O) and their other callers;lidge-jun commentedon Oct 28, 2026
Partially addressed on
devby #7869 (fdc6dd8). The local writers that already run behind an async boundary now admit throughwithConfigDirHardeningSettledwith the #7826 contract:ocx config set,unsetandimportocx effortEach covers a complete synchronous phase, and preliminary reads no longer publish recovery backups outside admission. Two related behavior changes came with it:
config.jsonis now refused (CLI usage error, exit 2;write_failedon the Advisor route) with its bytes unchanged, instead of being replaced by defaults.Still open here:
saveConfigand persisted mutation (src/config.ts,src/config/persisted-mutation.ts), Desktop remote store I/O (src/claude/desktop-remote-store-io.ts), management and GUI session tokens (src/server/management-auth.ts,src/server/persistent-gui-session.ts), service secrets (src/service/guards.ts,src/lib/service-secrets.ts), the spend-ledger lease (src/lib/spend-ledger-owner.ts), and the link store and compensation (src/link/store.ts,src/link/compensation.ts). These need an async companion before they can be admitted.src/integrations/catalog-refresh.ts) and the Aside sync route (src/server/management/aside-profile-routes.ts). These need a consumer-visible refusal code and GUI handling for partial results.fix(windows): admit config-root cache writes after the optional confi…
lidge-jun commentedon Oct 30, 2026
Partly addressed by #7998, merged into
devas19ab113945530483f4524ae3e6f8374d16572976. Four timer-driven or async cache writers under the config root now admit their write throughwithConfigDirHardeningSettled, under the same deadline and refusal contract as #7777, #7826 and #7869:A timed-out admission skips the best-effort write, or fails the refresh unpublished. A cancel, clear or reset invalidates a write still waiting for admission.
Still open, unchanged from the earlier breakdown: the synchronous writer APIs that cannot await (
saveConfig, persisted mutation, Desktop remote store I/O, management and GUI session tokens, service secrets, the spend-ledger lease, and the link store and compensation), and the integrations catalog fan-out and Aside sync route.