Skip to content

fix(security): combine management-auth and boundary hardening - #5516

Closed
luvs01 wants to merge 13 commits into
stack/c-sec-installfrom
stack/c-sec-mgmt
Closed

luvs01 wants to merge 13 commits into
stack/c-sec-installfrom
stack/c-sec-mgmt

Conversation

@luvs01

@luvs01 luvs01 commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Combine management-plane and boundary hardening from #5326, #5312, #5363, and #5317 into the middle layer of the security stack.

Verification

  • Current head: 245d542edc102f2fba6d33e08eef509c99e1d889. This follow-up changes only documentation and the specific test consumers listed below; production source is byte-identical to the preceding published head 32fa9a8b3d4cd54d90250b09181a4760ff6f4773.
  • Hosted CI exposed structure/runtime.md growing to 602 lines when the branch was combined with newer dev. Two overlapping Remote Workspace descriptions were consolidated without losing their contracts or links. The same patch was verified against both exact failing merge trees (602 to 600) and dev (600 to 598), without raising the 600-line budget. Final combined structure checks passed.
  • Hosted CLI/status and local-management failures were consumers still expecting unbounded health-version strings. The middle-layer fixtures now retain valid semver identity values, project invalid/null/control/overlong inputs to unknown, and verify that raw values are not reflected in JSON or human output. The production security filter is unchanged. Original exact two-file run: 70 passed / 3 failed; corrected run: 76 passed / 0 failed / 385 assertions / 77.72 seconds, pinned Bun 1.4.0. Final fixture bytes match the tested f9ae99bf3579ae24f5bd2c0fa160a54d05cdf2ee commit.
  • Each corrected C2 layer passed typecheck, structure, privacy and file-size checks. These are distinct runs and are not added together. Earlier interrupted whole-auth/four-file runs remain incomplete; current-head hosted results are required before readiness.
  • Full-suite/cross-platform completion, exact updated-head hosted CI and independent security review remain incomplete. No test timeout or safety boundary was weakened. This PR stays draft.

Checklist

  • Scope stays focused and avoids unrelated cleanup.

  • Docs or release notes were updated when needed.

  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Review readiness

  • Local CI is green on this exact head.

  • Branch is based on the current dev commit at preparation time.

  • All correct Codex and CodeRabbit findings are fixed on the combined head.

  • Ready-for-review confirmation.

@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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.

@luvs01
luvs01 added this pull request to stack #5518 September 22, 2026 09:51
@github-actions github-actions Bot added the bug Something isn't working label Sep 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed.

Hygiene

✅ Deterministic PR hygiene checks passed.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 64 / 80

이 PR은 보안 고치기 묶음입니다. 페어링 코드를 쓸 때, 같은 주소를 쓰는 다른 사람이 실패를 많이 내도 진짜 코드는 막히지 않게 했고, 허용되지 않은 브라우저 출처는 실패 횟수 기록도 안 남깁니다. Claude 에이전트 명단에 이상한 글자가 들어오면 파일에 안 넣고, SOCKS5로 받은 gzip이 풀릴 때 32MiB를 넘으면 멈춥니다. ocx sync의 Aside 동기화는 살아 있는 것처럼 보이는 /healthz만 보고 관리자 토큰을 보내지 않고, 실행 중인 프록시를 증명하는 짧은 HMAC 능력으로만 POST합니다. Remote Workspace 쓰기(페어링·세션·프롬프트·기기 삭제)는 운영자가 짝지은 GUI 세션만 되고, 자동으로 생긴 로컬/Tailscale 세션은 읽기만 됩니다. 그 밖에 gh는 믿을 만한 설치 경로만 쓰고, Grok 설정 울타리는 줄 단위로만 찾고, Hermes/Openclaw 설정에 ${...}가 들어 있는 모델 이름은 빼고, /healthz의 version은 semver처럼 생긴 짧은 글자만 진단에 옮깁니다. 문서와 테스트도 같이 왔습니다. base는 선호하는 dev가 아니라 stack/c-sec-install이고, 위로는 #5515 → 이 PR(#5516) → #5517 스택입니다. 제목은 stack/c sec mgmt이고, 설명란은 템플릿만 있어서 비어 있는 상태입니다.

라인 - PR 설명: Summary/Verification이 템플릿 그대로라 enforce-target이 bad description (empty)로 실패합니다. draft도 유지됩니다.
라인 - tests/clients/remote-workspace-activation.test.ts:44 — 여전히 옛 문장 A dashboard session is required...를 기대하는데, 코드는 A paired dashboard session is required...로 바뀌어 CI test 2/4가 깨집니다.
라인 - tests/clients/client-machine-listener.test.ts — 중계 프롬프트가 202를 기대하지만, 짝짓지 않은 GUI 세션이라 403이 나와 test 3/4가 깨집니다. 짝지은 세션 fixture가 필요합니다.
라인 - tests/server/server-auth.test.ts — file-size ratchet이 GREW로 잡힙니다. 인증 테스트 몇 줄을 같은 큰 파일에 더 붙인 결과입니다.
라인 - 같은 고치기가 열린 단독 PR로도 있습니다. #5326(페어링·명단·SOCKS5), #5312(gh/Grok 울타리/설정 보간), #5363(management-auth·Aside), #5317(/healthz version 제한). 이 스택이 그 커밋들을 cherry-pick한 형태입니다.

메인테이너의 판단이 필요한 지점

이 스택(#5515–#5517)을 본선으로 두고 #5326·#5312·#5363·#5317을 닫을지, 아니면 단독 PR을 남기고 스택을 버릴지 정해야 합니다. Remote Workspace를 “아무 GUI 세션”에서 “운영자 페어링 세션만 쓰기”로 좁히는 제품 결정도 맞는지 확인이 필요합니다. 로컬/Tailscale 자동 세션이 예전에 쓰기를 하던 워크플로가 있으면 깨집니다. gh를 고정 경로만 쓰는 것도, 커스텀 PATH에만 gh가 있는 환경에서는 사이드바 star 기능이 조용히 꺼집니다.

너의 추천

보안 방향은 맞습니다. 머지 전에 설명란을 채우고, 위 세 테스트/ratchet을 고친 뒤 CI를 초록으로 만드세요. 스택을 채택한다면 중복 단독 PR(#5326·#5312·#5363·#5317)은 무효로 닫는 편이 낫습니다. types/config 쪼개기·preview deploy는 이번 변경과 무관합니다.

이 댓글은 grok-bot이 작성했습니다

@luvs01 luvs01 changed the title stack/c sec mgmt fix(security): combine management-auth and boundary hardening Sep 22, 2026
luvs01 and others added 5 commits September 22, 2026 19:48
…CKS5 decoding

Three server-side hardening fixes:

- Pairing: look up the submitted grant before consulting the source
  throttle, so callers sharing an observed peer address cannot lock out a
  valid redemption, and skip limiter bookkeeping entirely for browser
  origins that are not allowed.
- Claude agent injection: reject hub-supplied roster entries that are not
  model-id-shaped before they are interpolated into generated agent
  definitions, closing a prompt-injection channel through ocx-* agent
  files.
- SOCKS5 fetch: cap decoded response bodies at 32 MiB so a small coded
  payload cannot expand without bound when a caller buffers it; identity
  bodies keep their existing streaming behavior.

(cherry picked from commit bc28577)
Aside sync: attest the running proxy via the runtime attestation secret and authorize the exact POST with a one-shot PID/port-bound HMAC capability instead of sending the reusable admin token to a listener found through spoofable /healthz liveness.

Remote Workspace: require an operator-paired GUI session for mutations; automatically bootstrapped loopback/Tailscale sessions stay read-only.

(cherry picked from commit d369690)
proxyIdentityAt carried any string the port holder returned as version into LiveProxy/version-skew diagnostics, so a hostile or confused responder could inject newlines or terminal-control sequences (e.g. OSC 52) into human-facing output. Gate it with a shared isHealthzVersion (semver-shaped, <=64 chars) and reuse it for the update restart probe, replacing the module-local isVersionLike.

(cherry picked from commit 3235d61)
… policy

Move the pairing body-bound case to server-management-auth.test.ts so server-auth.test.ts stays under the ratchet cap, update the Remote Workspace refusal text to the paired-dashboard-session contract, and give the hub-relay fixture a pairing-issued hub session so consent-bearing mutations still pass.
The management CORS test can exhaust its 5s body limit during Windows startup,
before its local finally runs. Teardown then removes the home while the real
proxy still owns its spend SQLite transaction.

Give the CORS fixture an abort signal, tracked body and memoized listener stop.
Settle those before restoring seams and homes, retain the existing producer/ACL
drains, and await failed-start rollback when setup throws. Consume both HTTP
response bodies and prove cancellation releases the actual spend owner.

Keep real token ACL creation, HTTP admission and CORS decoration. Isolate native
Codex sync, host service ownership and settings-only runtime/service diagnostic
projections from this fixture, whose assertions concern management CORS headers.
Restore its scoped runtime spy after shutdown. No timeout, skip, ACL policy,
production source or dependency change.
Move CORS setup, request/server lifetime, scoped runtime restoration,
authenticated headers and fixture-state drains into a sibling test helper.
Keep server-auth.test.ts within its existing 4589-line ratchet cap without
changing the baseline or reducing assertions.

The CORS and real spend-lease cancellation bodies are unchanged. Preserve
the real token ACL path, production authentication/CORS behavior, setup
rollback, memoized shutdown, body settlement and existing test deadlines.
Reuse the owned management server fixture for the non-loopback settings test,
keeping its real 0.0.0.0 listener, LAN Host/Origin, missing-token rejection,
authenticated response and CORS assertion.

Prepare real token/ACL state before the HTTP body, isolate only unrelated host
diagnostic projections, track cancellation and consume both response bodies.
Teardown settles the body and actual listener/spend owner before restoring homes.
Rename the helper to its shared management-server role without changing policy,
timeouts, assertions or the file-size baseline.

(cherry picked from commit 73e01d1)
@lidge-jun

Copy link
Copy Markdown
Owner

Carried into #5610 as 52f98dd (squash of this PR's own diff at head 245d542, authorship kept). The shared server-auth test fixtures were merged with the #5512 carry. Review follow-ups in #5610 resolve gh only from the fixed Windows install paths, look up pairing grants by digest (1a5ea56), bound compressed SSE by expansion ratio (6576b84), and add end-to-end tests for the Aside sync capability (d4b2d51). Closing as superseded by #5610. Thanks @luvs01.

@lidge-jun lidge-jun closed this Sep 22, 2026
lidge-jun added a commit that referenced this pull request Sep 23, 2026
)

* fix(service): combine startup ownership, token binding, and slot retention

Carries #5512 by @luvs01 (head a12b2ad), which
consolidates #5477, #5306 and #5357:

- bind the service API token to its owning state, canonicalize qualified-localhost
  binds, and carry WSL ownership state honestly (#5477);
- take a fresh task listing for the second startup ownership decision (#5306);
- retain workflow slots for streaming turns (#5357);
- own server-auth fixture lifetime and project a current-schema config for it.

Squashed from the PR's own diff (origin/dev...a12b2ad) onto current dev.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(server): self-heal a replaced package tree via drain-and-restart

Carries #5513 by @luvs01 (head 4d168f1), which
consolidates #5393 and its scheduler follow-up: detect a replaced installed package
tree, degrade health honestly, and drive a timer-driven, retryable drain-and-restart
whose verify step is deferred past scheduler re-entry. The guard factory lives in
src/server/index/package-tree-guard.ts.

Squashed from the PR's own diff (a12b2ad...4d168f1) onto the #5512 carry.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(security): combine install discovery, credential, and transport hardening

Carries #5515 by @luvs01 (head 843f299), which
consolidates #5359, #5285 and #5322:

- keep selected Codex installation discovery off network filesystems, probe
  oversized wrappers through a held-handle prefix read, and stop a PATH scan at a
  refused probe (#5359);
- exclude npm candidates inside the launch directory subtree (#5285);
- refuse plaintext remote hub origins, fail closed on POSIX chmod for credential
  files, and skip the frame-log write when descriptor hardening fails (#5322).

Squashed from the PR's own diff (origin/dev...843f299) onto the chain carry.
Integration: structure/runtime.md wording reflowed by two lines so the combined
service and security stacks stay within the 600-line structure budget.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(security): combine management-auth and boundary hardening

Carries #5516 by @luvs01 (head 245d542), which
consolidates #5326, #5312, #5363 and #5317:

- harden pairing redemption, agent roster intake, and SOCKS5 decoding (#5326);
- guard gh resolution, anchor the grok managed-region fences to whole lines, and
  bound provider-controlled text (#5312);
- harden management-auth admission and provenance (#5363);
- bound the /healthz version before it reaches diagnostics (#5317).

Squashed from the PR's own diff (843f299...245d542) onto the #5515 carry.
Integration: both stacks rewrote the shared server-auth test fixtures. The carry
keeps the #5512 current-schema fixture projection and config helper (including
its 4 KiB boundary case) and adds this PR's Aside sync capability assertions.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(security): combine adapter argv and upstream-body hardening

Carries #5517 by @luvs01 (head 260a87b), which
consolidates #5315 and #5336:

- stage Qoder and CodeBuddy system prompts in private files instead of
  child-process argv, with exclusive creation and owned cleanup (#5315);
- bound upstream error bodies and resolve account-scoped transports (Copilot,
  Devin) from the same OAuth snapshot as the bearer (#5336).

Squashed from the PR's own diff (245d542...260a87b) onto the #5516 carry.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* feat(codebuddy): integrate capture-only tools with private prompt staging

Carries #5582 by @luvs01 (head 3061ef9), which
integrates the capture-only CodeBuddy tool bridge from #5148 by @mdwsk88 with the
private prompt staging from #5517. Requests with a tool catalog advertise only the
allowed tools through an isolated MCP server that captures calls without executing
them; the client keeps approval, sandboxing and execution. Pre-init, undeclared,
excessive or incomplete calls are rejected, streamed malformed tool arguments are
suppressed, bridge staging failures return a fixed message, and an opt-in live
acceptance harness is included. Design context: #5146.

Squashed from the PR's own diff (260a87b...3061ef9) onto the #5517 carry.

Co-authored-by: mdwsk88 <924038395@qq.com>

* fix(client): bound total hub catalog response lifetime

Carries #5252 by @luvs01 (head 779ef91): give the
hub catalog body read an overall deadline (24x the inactivity window, capped at
120 s) on top of the inactivity window, and release refused, HTTP-error and 304
bodies without awaiting their cancellation.

Squashed from the PR's own diff (origin/dev...779ef91).

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(grok): reserve model aliases only when the written config stays valid

Reimplements #5281 by @luvs01. A user sub-table such as [model.ocx-mine.extra]
only creates an implicit parent, so it no longer forces the generated table to a
suffixed alias. The alias choice is now checked against the bytes actually
written: the unsuffixed alias is used only when the final config (after
model-reference rewriting) parses; otherwise the conservative choice that also
reserves deeper headers is used, and a valid user file for which neither choice
parses is refused without writing. Malformed user TOML keeps the previous
conservative reservation.

The original change reserved only exact two-segment headers, which could emit a
duplicate [model.x] table when the user defines model.x through dotted keys.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(codex-auth): scope Codex OAuth cancellation to the originating flow

Reimplements #4923 by @luvs01 on the current login-state layout (in-flight
controllers moved to src/oauth/login-flow-state.ts in #5220). Cancelling a Codex
login was keyed only by provider, so a stale modal posting an old flowId could
abort a newer attempt, and a cancel without a flowId expired every pending flow.

- Each in-flight controller records the flowId that started it; a cancel whose
  flowId does not match the active attempt is refused before anything aborts.
- POST /api/codex-auth/login/cancel requires a non-empty flowId, rejects unknown
  or non-pending flows with 400 without touching any row, and expires only that
  flow. Provider-wide cancellation through /api/oauth/login/cancel is unchanged.
- ocx account cancel requires --flow for Codex providers and sends no request
  without it.

The dashboard's 409 recovery keeps its code; its ownerless cancel is now refused,
so it ends in the existing "already in progress" message instead of superseding a
flow it does not own.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(socks5): bound compressed event streams by expansion, not total size

Review follow-up to the #5516 carry. The 32 MiB decoded-body cap applied to every
gzip/deflate response, so a long, normally compressed SSE stream through the
SOCKS5 tunnel was cut once its cumulative output crossed the cap. Buffered
responses keep the absolute cap; event streams may continue while decoded bytes
stay within the greater of 32 MiB or 128x the coded bytes consumed, which still
stops high-ratio bombs.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(codex): keep scanning PATH past a missing Windows candidate

Review follow-up to the #5515 carry. The held-handle reader reported a missing
file or directory as open-refused, so the default existence probe stopped the
PATH scan at the first absent PATHEXT candidate (for example codex.com) before it
reached an installed codex.cmd. NtCreateFile's object-name-not-found and
object-path-not-found statuses now map to a distinct not-found result that lets
the scan continue; every other failure still refuses.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(server): require Windows ACL hardening before a frame-log append

Review follow-up to the #5515 carry. On Windows the frame log ignored a failed
permission change and appended anyway. Each append now hardens the target with
the required Windows ACL helper and checks that the path still names the opened
file before writing; any failure writes nothing.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(devin): bind catalog authority to the tenant destination

Review follow-up to the #5517 carry.

- The observe-only OAuth snapshot applied the Copilot-validated apiBaseUrl to
  every provider, so a crafted Devin credential could carry a Copilot host that
  the snapshot claimed as its own. The overlay now applies only to github-copilot.
- Devin's live roster, stale fallback and cooldown were keyed by the token alone
  while discovery also depends on the validated tenant URL. The catalog authority
  and the matching routing-cache resolver now fingerprint the token together with
  the validated destination URL.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(codebuddy): fail closed on unverified bridge turns and staging collisions

Review follow-up to the #5582 carry.

- With the capture-only tool bridge armed, a successful terminal event is no
  longer accepted unless the CLI's system/init frame confirmed the bridge server;
  a turn that ends without it fails with tool_bridge_init_missing.
- A tool_use block that arrives only in the complete assistant message, without
  the partial tool events the bridge captures, now fails the turn instead of
  being dropped silently; partial captures are deduplicated by id.
- The catalog and MCP config staging files are created exclusively (wx, 0600),
  like the prompt file, so a pre-existing file fails before spawn.
- The history-argument repair for a missing JSON object prefix is documented and
  tested as a provider-agnostic contract; other malformed strings keep {}.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
Co-authored-by: mdwsk88 <924038395@qq.com>

* fix(service): keep service-command ownership bound to the recorded home

Review follow-up to the #5512 carry. On WSL with CODEX_HOME unset, the carried
allowance treated a legacy Linux ~/.codex install record as owned when discovery
now selects the Windows profile, so service stop could stop the Linux-home
service and then restore native Codex in the Windows home, and repair could
rewrite the recorded home. Service commands again require the exact recorded
home and name it in the refusal; the unattended startup inspector reaches the
same foreign verdict.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(server): veto a package-tree restart when its server stops or loses ownership

Review follow-up to the #5513 carry.

- A package-tree restart accepted by the guard stayed scheduled after an explicit
  server.stop(), so the drain-and-respawn could reopen a server the caller had
  stopped. The caller that accepted a pending restart now receives a veto, and
  the guard uses it on dispose.
- When running as a supervised service child, the automatic path checks service
  home ownership when accepting and again before the handoff; a mismatch keeps
  the 503 fence and skips the restart.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(security): resolve gh from fixed paths and look up pairing grants by digest

Review follow-ups to the #5516 carry.

- On Windows the automatically polled star-status route derived gh.exe roots from
  ProgramFiles and LOCALAPPDATA, so a process environment could select any
  absolute directory. Windows candidates are now the fixed system install paths,
  and the child PATH is only the resolved executable's directory. Other installs
  report gh as unavailable, which only hides the sidebar star state.
- Pairing redemption looked each guess up by scanning every live grant; the map
  is keyed by the grant digest, so the lookup is now a direct get. A valid grant
  still redeems behind a throttled source.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* test(server): cover the one-shot Aside sync capability end to end

Review follow-up to the #5516 carry, which added a one-shot, HMAC-bound
capability for the default ocx sync path without exercising it. A real listener
now proves single use, refusal on replay, wrong path, query, method, pid or port,
expiry and a bad MAC, and that the CLI default path performs the attestation and
a bodyless POST (through a narrow transport seam).

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* test: register the review follow-up test files in the layout maps

Adds the three new test files from the L4 review follow-ups to both
scripts/test-layout/layout.json and tests/fixtures/test-layout-expected.json.

* test(grok): pin re-injection and strip for a nested user model table

Review follow-up to the #5281 reimplementation: two injections are byte
identical, every intermediate file parses, and strip restores the exact user
content.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(server): harden a Windows frame log once per file identity

Re-review follow-up: requiring Windows ACL hardening on every append spawned
icacls for every relayed frame and could stall the realtime relay. The hardened
file identity (device and inode) is now remembered for the log path; an
unchanged file skips the respawn, and a replaced file at the same path is
hardened again before any write.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* docs(structure): describe the package-tree restart veto and ownership recheck

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(server): stop an automatic restart from handing off after an explicit shutdown

Security review follow-up to the #5513 carry. Once an automatic package-tree
restart entered its drain, an operator shutdown (signal or management stop)
could still be followed by the restart handoff, because the drain cannot tell
its own listener stop from an independent one. Explicit shutdown paths now mark
the process, and an admission-bound restart checks that mark before every
handoff step. Manually requested restarts keep their behavior.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(server): mark a management stop before its asynchronous teardown

Security re-review follow-up: the management stop route marked the explicit
shutdown only after awaiting the shared teardown, so an automatic restart
draining concurrently could reach its handoff in that window. The mark now
precedes the first await after the stop is accepted.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* test(server): allow post-lookup pruning in the pairing digest regression

The digest-lookup regression trapped every iteration of the grant map, so a
valid redemption failed once session minting pruned expired grants after the
lookup (hosted CI test 4/4). The trap now fails only on a scan that precedes the
digest lookup, which is the regression it guards.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix: repair standalone bridge and restart ownership

Use the compiled CLI as the capture-only MCP entrypoint, release automatic restart fences on veto, align Devin discovery, and tighten Windows and local transport handling. Apply the documented Qoder prompt environment for both regions and update focused regressions and operator docs.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

Co-authored-by: mdwsk88 <924038395@qq.com>

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
Co-authored-by: mdwsk88 <924038395@qq.com>
@lidge-jun
lidge-jun deleted the stack/c-sec-mgmt branch September 26, 2026 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants