Skip to content

Commit c48a6ee

Browse files
authored
test(usage): give the rolling-file bound test room on Windows (#614)
* docs(devlog): live state sync unit for 2026-07-28 (branches, PRs, issues) Measured snapshot of origin/dev=7710185c0, 15 open PRs, 27 open issues, and the delta against the 260727 owner-decision ledger and 260728 bug-bundle plan. The audit round demoted two items the first draft got wrong: #570 is only partially fixed (items 1a/2 of its six-item hardening plan; the myhost.lan alias case still 403s), and #612 is credential-handling work under MAINTAINERS.md's security-review rule rather than a decision-free patch. * docs(devlog): rebuild-unit roadmap — screen 16 open PRs, lock 4 work-phases Two audit rounds moved this a long way from the draft. The conflict set for #576 was inverted (logic files, not i18n), the proposed usage-debug size gate would have elided 0.9% of reads, and #610's P1 turned out to be author-resolved while the same defect survived on dev's own test. * docs(devlog): record the WP2 measurement — the #610 P1 does not reproduce PATH="" never reaches the child because runCodexDebugModels calls execFile without an env option, so the launcher keeps working and the catalog loads. The isolation that line intends is decorative; the test stays safe through CODEX_CLI_PATH instead. Closing WP2 as NOOP with the observation sent to #610. * test(usage): give the rolling-file bound test room on Windows The 325 appends this test needs cost ~1,954 synchronous fs calls (measured: mkdir 325, chmod 652, append 325, exists 325, read 325, write 2). On windows-latest under full-suite load that took 13.6s and tripped the 5s default, while ubuntu and macos stayed well under it. The cost is per-open rather than per-byte, so removing one of the six calls would not close a 2.7x overshoot. Reducing the append count would trade away coverage -- 325 is already the minimum that crosses the rotate threshold twice. Both assertions and the rotation contract are unchanged. * docs(devlog): record the #576 rebase outcome and the regression it surfaced The three conflicts were the predicted logic files. What the audit caught was separate: the pre-rebase commit already deleted dev's grokSyncFailureMessage and its three handlers, and no test in the repo asserts that string, so a full green suite would not have stopped it.
1 parent 7710185 commit c48a6ee

9 files changed

Lines changed: 1083 additions & 1 deletion

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# 000 — 라이브 상태 재동기화 유닛 계획
2+
3+
세션: `019fa826-aba9-7032-8b43-9fc0fbcb56f1`
4+
goalplan: `opencodex-2026-07-28-devlog-260728-live-state-sy`
5+
기준: `origin/dev` = `7710185c0`, 로컬 `dev` = `7710185c0` (FF 정렬 완료)
6+
측정 시각: 2026-07-28 (KST 저녁)
7+
8+
## 목표
9+
10+
리모트/브랜치/PR/이슈의 현재 사실을 실측하고, 오너 판단 없이 처리할 수 있는 것을
11+
실제로 처리한다. 처리 = 이미 고쳐진 이슈 클로즈, 미해결 항목 상태 코멘트,
12+
결정 불요 버그 판정 보고.
13+
14+
## 선행 문서 (재조사 금지, 델타만 기록)
15+
16+
| 문서 | 상태 |
17+
| --- | --- |
18+
| `260727_owner_decision_ledger/007_delta_260728.md` | 기준 `origin/dev`=`461de3961`. **stale** — 4단계 전진 |
19+
| `260728_bug_bundle_resolution/000_plan.md` | 기준 `origin/dev`=`f195e90bc`. **stale** — WP2(#573) 머지 완료 |
20+
21+
두 문서의 결론은 유효하되 번호·상태는 `010_live_snapshot.md`가 우선한다.
22+
23+
## 제약
24+
25+
- 브랜치: `main` 직접 변경 금지, force push 금지, 타인 PR 강제 머지 금지.
26+
- git: FF 외 이력 조작 금지. 다른 worktree 11곳의 더티 작업 보존.
27+
- 이슈 클로즈: **코드 근거**(머지 커밋 + 테스트)가 있는 것만. 추정 클로즈 금지.
28+
- 보안 경계: `.github/CODEOWNERS`가 지정한 경로(`src/oauth/`,
29+
`src/server/auth-cors.ts`, `src/codex/auth-context.ts`,
30+
`src/server/management-api.ts`, `/.github/`, `scripts/release.ts`,
31+
`package.json`, `bun.lock`)는 두 메인테이너 리뷰 대상 → `NEEDS_HUMAN`.
32+
- 프라이버시: 코멘트에 토큰·계정 식별자·요청 본문 금지.
33+
34+
## 스코프 밖
35+
36+
| 항목 | 이유 |
37+
| --- | --- |
38+
| 프로바이더 채택 (#561, #562, #611, #540, #177, #178, #201) | 채택 기준은 오너 정책 |
39+
| 로드맵 라벨 정직성 (#42, #95, #294) | 오너 판단 |
40+
| PR #533 / #557 진행선 선택 | 의존성 설치 경계 + 오너 결정 |
41+
| 업스트림 추적 (#92, #241, #417, #462) | 우리가 닫을 수 없음 |
42+
| 커뮤니티 PR 머지 (#611, #610, #607, #599, #583, #582, #581, #569, #565, #562, #512) | 리뷰/머지 권한은 사람 |
43+
44+
## work-phase 맵 (의존 순, PHASE-SPLIT-01)
45+
46+
측정이 먼저다. 무엇이 이미 고쳐졌는지 모르면 클로즈 판단이 불가능하고,
47+
클로즈 판단이 서지 않으면 "결정 불요 버그" 목록도 허구가 된다.
48+
49+
| # | decade doc | 대상 | 계층 |
50+
| --- | --- | --- | --- |
51+
| WP1 | `010_live_snapshot.md` | 브랜치/PR/이슈 실측 + 원장 델타 | 측정 (최하부) |
52+
| WP2 | `020_issue_disposition.md` | 이슈 클로즈 + 상태 코멘트 | 외부 상태 변경 |
53+
| WP3 | `030_no_decision_bugs.md` | 결정 불요 버그 판정 보고 | 판정/보고 |
54+
55+
WP1은 이 문서를 포함한 docs-only 사이클이다 (LOOP-DOCS-FIRST-01).
56+
57+
## 성공 기준
58+
59+
| id | 시나리오 | 증거 |
60+
| --- | --- | --- |
61+
| c1 | 로컬 `dev` == `origin/dev`, FF 외 조작 없음 | `git rev-parse` 출력 |
62+
| c2 | 이 유닛에 000 + 010/020/030이 존재하고 커밋됨 | `ls` + 커밋 해시 |
63+
| c3 | 클로즈 대상이 있으면 증거 코멘트와 함께 CLOSED. 없으면 **무클로즈 판정 근거**가 이슈별로 문서화 | `gh issue view --json state` 또는 020 §A/§B 판정표 |
64+
| c4 | 닫지 않은 항목에 현재 상태 코멘트 존재 | 코멘트 URL |
65+
| c5 | 결정 불요 버그 목록이 이슈번호·코드경로·경계 판정과 함께 문서화 | 문서 경로 + 커밋 해시 |
66+
67+
## SoT 동기화 대상 (SOT-SYNC-01)
68+
69+
이 유닛은 코드 변경이 없다. `docs-site/`·`structure/` 패치 대상 없음.
70+
코드 변경이 발생하면 그 시점에 해당 work-phase가 SoT 대상을 지명한다.
71+
72+
## 터미널 판정 기준
73+
74+
- `DONE` — 문서 커밋 + 이슈 상태 변화(또는 무변경 판정 근거) + 보고서 작성
75+
- `BLOCKED` — 리포터/업스트림 응답 대기
76+
- `NEEDS_HUMAN` — CODEOWNERS 보안 경계 또는 오너 정책 판단
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# 010 — 라이브 상태 실측 스냅샷 (WP1)
2+
3+
측정: 2026-07-28 KST 저녁, `gh` + `git` 실측. 기억이나 이전 원장 인용 아님.
4+
5+
## 1. 브랜치 / 리모트
6+
7+
`git fetch origin --prune` 후:
8+
9+
| 브랜치 | 로컬 | origin | 관계 |
10+
| --- | --- | --- | --- |
11+
| `dev` | `7710185c0` | `7710185c0` | 동일 (FF 4커밋 적용) |
12+
| `main` | `7cb15bff4` | `7cb15bff4` | 동일 |
13+
| `preview` | `b04b8729e` | `b04b8729e` | 동일 |
14+
| `dev2-go` | `2bdb748e1` | `2bdb748e1` | 동일 |
15+
16+
`origin/dev` 기준 ahead/behind (`git rev-list --left-right --count origin/dev...<b>`):
17+
18+
| 브랜치 | origin/dev만 가진 것 | 해당 브랜치만 가진 것 |
19+
| --- | --- | --- |
20+
| `main` | 42 | 3 |
21+
| `preview` | 42 | 4 |
22+
| `dev2-go` | 188 | 335 |
23+
24+
`main`/`preview``origin/dev`에 없는 3~4 커밋을 가진 건 릴리스 프로모션 이력이라
25+
정상이다. `dev2-go`의 335는 Go 포트 라인 고유 작업이다.
26+
27+
### FF로 흡수한 4커밋
28+
29+
```
30+
7710185c0 fix stale update jobs and combo quota fallback
31+
d482086bf fix(windows): grant owner ACE before ACL inheritance removal (#601)
32+
406a522fe refactor(responses): single-pass SSE payload rewrite composition (#602)
33+
c380ef72a feat(auth): account pool round-robin and fill-first strategies (#593)
34+
```
35+
36+
45파일 +3407/-331. rebase/reset 없이 `git merge --ff-only`만 사용했다.
37+
38+
### 워크트리 (11개, 전부 보존)
39+
40+
`260727-live-triage`, `260727-pr533-current`, `260727-pr551-image-relay`,
41+
`260728-pr527`, `260728-preview`, `404d`(main), `6cce`(dev2-go),
42+
`e4f5`(go-tray-daemon), 그리고 detached 2개 + macos-app.
43+
이 유닛은 메인 워크트리에서만 작업한다.
44+
45+
## 2. 열린 PR — 15건 실측
46+
47+
| # | base<-head | mergeable | state | 실패 체크 | 작성자 |
48+
| --- | --- | --- | --- | --- | --- |
49+
| 611 | dev<-feat/volcengine-providers | MERGEABLE | UNSTABLE || yrooogerg |
50+
| 610 | dev<-fix/catalog-runtime-probe-cache | MERGEABLE | UNSTABLE || mihneaptu |
51+
| 607 | dev<-fix/gui-chrome-forms (draft) | MERGEABLE | UNSTABLE | ubuntu, macos | Wibias |
52+
| 599 | dev<-fix/codex-spark-quota-scope | MERGEABLE | UNSTABLE || akrock |
53+
| 583 | dev<-chore/agent-guidance-hardening | MERGEABLE | CLEAN || Wibias |
54+
| 582 | dev<-feat/video-bridge-v2 (draft) | MERGEABLE | CLEAN || tizerluo |
55+
| 581 | dev<-feat/zh-tw-localization | CONFLICTING | DIRTY || letr1n1ty |
56+
| 576 | dev<-codex/pr527-rebase | CONFLICTING | DIRTY | windows | lidge-jun |
57+
| 575 | dev<-codex/260728-tls-altname-diagnosis | MERGEABLE | CLEAN || lidge-jun |
58+
| 569 | dev<-agent/macos-post-sync-readiness (draft) | CONFLICTING | DIRTY || diegocantarero |
59+
| 565 | dev<-agent/codex-account-pause | CONFLICTING | DIRTY || Alvin0412 |
60+
| 562 | dev<-feat/modelsell-provider (draft) | MERGEABLE | UNSTABLE || modelsell |
61+
| 557 | dev<-codex/pr533-update-recovery-hardening (draft) | CONFLICTING | DIRTY || lidge-jun |
62+
| 533 | dev<-fix/gui-update-install-failure-recovery (draft) | CONFLICTING | DIRTY | CHANGES_REQ | WZBbiao |
63+
| 512 | dev<-split/426-01-namespace-foundation | MERGEABLE | CLEAN || chrisae9 |
64+
65+
전부 base=`dev`. 잘못 타깃된 PR 없음 → AGENTS.md 브랜치 타깃 규칙 위반 0건.
66+
67+
> A 게이트 정정: 최초 측정에서 #569/#562/#512`UNKNOWN`으로 잡혔던 것은 GitHub이
68+
> mergeable을 비동기 계산 중이었기 때문이다. 재폴링 결과를 위 표에 반영했다.
69+
70+
우리 소유 PR 3건: #575(CLEAN, 머지 대기), #576(CONFLICTING + windows 체크 실패),
71+
#557(draft, CONFLICTING).
72+
73+
## 3. 열린 이슈 — 27건, `--label bug` 필터로 14건
74+
75+
```
76+
612 608 606 604 591 586 570 553 545 543 418 417 241 92
77+
```
78+
79+
enhancement/roadmap/upstream 계열 13건은 이 유닛의 처리 대상이 아니다.
80+
81+
## 4. 원장 델타 — 이전 문서가 틀린 것
82+
83+
| 이전 기재 | 현재 사실 |
84+
| --- | --- |
85+
| `260728_bug_bundle_resolution` WP2 = 진행 예정 | **완료**. `e2da6f6df` → PR #573 머지 (`3a2b2ea8c`) |
86+
| `007_delta` 기준 `origin/dev`=`461de3961` | `7710185c0` (그 뒤 다수 머지) |
87+
| 열린 PR 15 (ready 5 / draft 10) | 열린 PR 15 (ready 9 / draft 6) — 구성이 다름 |
88+
| 열린 이슈 23 | 27 |
89+
| needs-info 3 (`462,543,553`) | **4** (`591,553,543,462`). #462`upstream-tracking`**추가로** 얻었을 뿐 `needs-info`를 잃지 않았고, #591도 이미 needs-info다 |
90+
91+
### 07-27 저녁 이후 머지된 PR 20건
92+
93+
`602 601 600 597 595 594 593 589 588 585 580 579 578 577 574 573 571 568 567 566`
94+
95+
### 07-27 저녁 이후 클로즈된 이슈 (해결 완료) 주요 항목
96+
97+
`609 605 603 598 596 592 590 587 584 563 560 549 548 547 546 542 541 539 538`
98+
99+
## 5. 이슈 ↔ 코드 대조 결과
100+
101+
| 이슈 | 코드 현황 | 판정 |
102+
| --- | --- | --- |
103+
| #570 | `src/server/auth-cors.ts:51` `isLoopbackRequestHost`가 포트 비교를 제거하고 hostname만 검사. `tests/server-loopback-host-gate.test.ts:16``localhost:20100`/`127.0.0.1:20100`/`[::1]:20100`을 통과로 고정 | **부분 해결 — 6항목 중 1(a)/2만. alias(항목 4)는 여전히 403. 클로즈는 `NEEDS_HUMAN``020_issue_disposition.md` §A** |
104+
| #612 | `src/lib/windows-secret-acl.ts:79` 여전히 `Bun.spawnSync(["icacls.exe"...])` 동기 호출 | 미해결 |
105+
| #608 | `src/service.ts:1080``taskXmlString()`(`"``&quot;`)로 이스케이프한 문자열과 원문 XML을 `includes()` 비교 | 미해결, 원인 확정 |
106+
| #606 | `src/codex/catalog/bundled.ts:146` `loadBundledCodexCatalog`가 캐시 히트 판정 전에 `resolveAndPersistCodexRuntime`(→ `--version` 프로브, `timeout: 8_000`)를 호출. cacheKey 자체가 프로브 결과로 만들어지는 구조 | 미해결, PR #610이 이미 제출됨 |
107+
| #586 | `src/server/management/provider-routes.ts:137` PATCH 엔드포인트 존재. GUI에는 `CodexAuth.tsx` 배너만 있고 전환 컨트롤 없음 | 미해결 |
108+
| #604 | 재현 정보가 Cursor Auto + PowerShell 5.1 환경 의존 | 리포터 대기 |
109+
| #591 | `schtasks.exe /create` 권한 거부. 리포터는 **관리자 권한으로는 설치에 성공**했고 그 이후 사용에서 문제가 남는다고 후속 코멘트에 적었다. Ingwannu가 이미 ccswitch 충돌 부정 + 추가 정보 요청 코멘트를 남겼고 `needs-info` 라벨도 붙어 있다 | 리포터 응답 대기 (추가 코멘트 불필요) |
110+
| #553 | PR #575(OPEN, MERGEABLE/CLEAN)가 진단 메시지 **분류**를 분리. TLS altname 불일치 자체는 미해결 | PR 대기 + 잔여 결함 |
111+
| #545 | 메인테이너가 OAuth identity 제거를 안전하지 않다고 판정 | NEEDS_HUMAN |
112+
| #543 #418 | 리포터 캡처 대기 | BLOCKED |
113+
| #92 #241 #417 | 업스트림 | BLOCKED |
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# 020 — 이슈 처분 (WP2)
2+
3+
`010_live_snapshot.md` §5의 대조 결과를 실제 GitHub 상태 변경으로 옮긴다.
4+
5+
## 원칙
6+
7+
클로즈는 **머지된 커밋 + 그 동작을 고정하는 테스트**가 둘 다 있을 때만.
8+
"고쳐졌을 것 같다"는 클로즈 사유가 아니다. 나머지는 현재 상태 코멘트만 남기고
9+
열어 둔다 — 침묵보다 낫고, 오판 클로즈보다 훨씬 낫다.
10+
11+
## A. 클로즈 후보 → **오너 판단으로 이관** (A 게이트 정정)
12+
13+
### #570 Port-remapped tunnels rejected by the loopback Host check
14+
15+
근거 체인:
16+
17+
| 항목 ||
18+
| --- | --- |
19+
| 수정 커밋 | `e2da6f6df` fix(server): treat forwarded loopback ports as loopback |
20+
| 머지 커밋 | `3a2b2ea8c` Merge pull request #573 |
21+
| 브랜치 | `origin/dev` 포함 확인 (`git branch --contains e2da6f6df`) |
22+
| 코드 | `src/server/auth-cors.ts:37-52` — 포트 비교 제거, hostname만 신뢰 경계 |
23+
| 테스트 | `tests/server-loopback-host-gate.test.ts:16-26` |
24+
25+
테스트가 고정하는 것: `localhost:20100`, `127.0.0.1:20100`, `[::1]:20100`이 전부
26+
loopback으로 통과하고, 비루프백 hostname은 여전히 거부된다.
27+
28+
### 왜 닫지 않는가 — A 게이트 블로커 1 (High)
29+
30+
#570은 단일 결함 리포트가 아니라 **6항목 하드닝 계획**이다. 머지된 것은 항목
31+
1(a)과 항목 2뿐이다.
32+
33+
| 항목 | 상태 |
34+
| --- | --- |
35+
| 1(a) Host를 Origin과 정렬 | **머지됨** (`e2da6f6df`) |
36+
| 1(b) `trustedRequestHosts` 허용목록 | 미착수 — 설계 결정 |
37+
| 1(c) 루프백 바인드 인증 opt-in | 미착수 — 설계 결정 |
38+
| 2 회귀 테스트 | **머지됨** |
39+
| 3 base URL 보고 (`api-access.ts:72-75`, `api-keys-utils.ts:18-24`) | 미착수 |
40+
| 4 hostname alias (`myhost.lan`) | **여전히 403**`auth-cors.ts:51`이 hostname만 보고 alias는 loopback이 아님 |
41+
| 5 docs "Remote access" SSH 레시피 | 미착수 |
42+
| 6 터널 위 OAuth (`CALLBACK_PORT = 1455`) | 미착수 |
43+
44+
리포터가 측정한 `ALIAS | Host=myhost.lan:56030 -> 403`은 지금도 재현된다.
45+
게다가 `src/server/auth-cors.ts`는 CODEOWNERS 인증 경계이고 항목 4는 이슈 본문이
46+
"Decide explicitly whether ... are in scope"라고 적은 **오너 결정**이다.
47+
48+
→ 처분: 상태 코멘트만 남기고 **열어 둔다**. 클로즈 여부는 `NEEDS_HUMAN`.
49+
50+
코멘트 골자 (영문, 리뷰 언어 규칙):
51+
52+
- 항목 1(a)/2가 `e2da6f6df` (PR #573)로 머지됐고 `origin/dev`에 있다
53+
- 바뀐 predicate와 이유 (포트는 신뢰 경계가 아니다), 회귀 테스트 파일:라인
54+
- 항목 3/4/5/6은 미해결이며 alias 케이스는 여전히 403이라는 점을 명시
55+
- 잔여 항목을 별도 이슈로 쪼갤지, 이 이슈를 열어 둘지는 메인테이너 결정
56+
57+
## B. 상태 코멘트만 — 클로즈하지 않음
58+
59+
| 이슈 | 코멘트 내용 | 클로즈 안 하는 이유 |
60+
| --- | --- | --- |
61+
| #606 | PR #610이 프로브 **재사용/메모이제이션**을 고친다 (cacheKey 도출 순서는 저자가 의도적으로 유지 — PR 본문 "I left the ordering alone to keep this change minimal"). 측정된 개선: warm 6300ms → ~25ms | 수정 미머지 |
62+
| #608 | `src/service.ts:1080` + `taskXmlString()` 이스케이프 불일치를 근본 원인으로 확인, 결정 불요 수정으로 분류 | 수정 미작성 |
63+
| #612 | `src/lib/windows-secret-acl.ts:79` 동기 spawnSync 확인, tmp 경로 키잉 문제도 재현 | 수정 미작성 |
64+
| #586 | PATCH `/api/providers?name=openai`는 존재(`provider-routes.ts:137-167`), GUI 컨트롤만 부재 | GUI 설계 결정 필요 |
65+
| ~~#591~~ | **코멘트하지 않음** — Ingwannu가 이미 ccswitch 충돌 부정 + 정보 요청 코멘트를 남겼고 `needs-info` 라벨도 있다. 리포터는 관리자 권한 설치에 이미 성공했다고 답했으므로 "관리자로 재시도" 안내는 틀린 조언이다 | 중복 코멘트 회피 |
66+
| #553 | PR #575(OPEN, MERGEABLE/CLEAN)는 오류 **귀속**만 개선한다 — 연결 불가와 TLS hostname 불일치를 구분해 보여줄 뿐, `ERR_TLS_CERT_ALTNAME_INVALID` 자체는 그대로다. #575가 머지돼도 이 이슈는 닫히지 않는다 | 머지 대기 + 잔여 결함 |
67+
68+
## C. 손대지 않음
69+
70+
`#604`(리포터 캡처 대기), `#543` `#418`(리포터 대기), `#545`(오너 판정),
71+
`#92` `#241` `#417` `#462`(업스트림). 이미 각 이슈에 최신 트리아지 코멘트가 있다.
72+
73+
## 검증
74+
75+
`gh issue view 570 --json state,closedAt` 및 각 코멘트 URL 회수.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# 030 — 오너 결정 없이 고칠 수 있는 버그 (WP3)
2+
3+
"결정 불요"의 정의: 동작이 무엇이어야 하는지에 이견이 없고, 수정 범위가 국소적이며,
4+
CODEOWNERS 보안 경계 밖이고, 회귀 테스트를 쓸 수 있는 것. 셋 중 하나라도 어긋나면
5+
오너 판단 항목으로 분류한다.
6+
7+
## 판정 기준표
8+
9+
|| 통과 조건 |
10+
| --- | --- |
11+
| 기대 동작 | 명세·주석·기존 테스트가 정답을 이미 규정 |
12+
| 범위 | 단일 모듈, 공개 계약 변경 없음 |
13+
| 경계 | `.github/CODEOWNERS` 보호 경로가 아니고, `MAINTAINERS.md`의 주제별 보안 리뷰 대상(인증·크리덴셜 처리·GitHub Actions·릴리스 자동화·의존성 설치)도 아님 |
14+
| 검증 | 분기를 실제로 발화시키는 테스트 작성 가능 (C-ACTIVATION-GROUNDING-01) |
15+
16+
## 결정 불요 — 1건 (A 게이트에서 3 → 1로 축소)
17+
18+
### 1. #608 Windows scheduler task가 영구 stale로 보고됨
19+
20+
| 항목 ||
21+
| --- | --- |
22+
| 원인 | `src/service.ts:1080` — 등록 XML을 `taskXmlString()`으로 이스케이프한 문자열과 `includes()` 비교. `taskXmlString`(`:886`)은 `"``&quot;`로 바꾸지만 Task Scheduler 내보내기는 리터럴 `"`를 준다 |
23+
| 기대 동작 | 이견 없음. 등록한 값과 같으면 healthy |
24+
| 범위 | `src/service.ts` 단일 함수. `taskXmlOptionalValueEquals`(#432 수정)와 같은 층 |
25+
| 경계 | CODEOWNERS 밖 |
26+
| 수정 | `<Arguments>` 텍스트를 XML 언이스케이프한 뒤 비교하는 헬퍼 추가 (`&quot;`/`&amp;`/`&lt;`/`&gt;`/`&apos;` 역변환) |
27+
| 활성화 증거 | 이스케이프된 XML과 canonical XML 둘 다 healthy=true, 실제로 다른 launcher 경로면 false |
28+
| 영향 | stale 래치 → `viable=false` → 스케줄러 백엔드 포기. 사용자가 재설치로 못 고침 |
29+
30+
## 결정 필요 — 오너 몫
31+
32+
### #612 Windows ACL 하드닝이 이벤트 루프를 막음 — `NEEDS_HUMAN` (A 게이트 블로커 3)
33+
34+
원인 분석 자체는 유효하다: `src/lib/windows-secret-acl.ts:79``Bun.spawnSync`
35+
`hardenSecretPath`(`:311`) → `atomicWriteFile` 경로에서 동기 실행되고, 타임아웃
36+
캐시가 매번 달라지는 임시 파일명으로 키잉된다.
37+
38+
그런데 결정 불요가 아니다:
39+
40+
- `hardenSecretPath`는 크리덴셜 파일 보호 장치다. `MAINTAINERS.md`가 "Authentication,
41+
credential handling ... require explicit security review"라고 규정한 주제에 정확히
42+
해당한다. 경로 글로브만 보고 CODEOWNERS 밖이라 판정한 것이 오류였다.
43+
- 초안이 제안한 "캐시 키를 대상 디렉터리로 완화"는 이슈 본문이 명시적으로 거부한
44+
방향이다: 부모 디렉터리가 더 넓은 ACE를 허용할 수 있어 파일 단위 하드닝을 건너뛰면
45+
안 된다고 리포터가 적었다.
46+
- 리포터가 제안한 안전한 방향(비동기 ACL 러너 + single-flight 큐 + 종료 시 flush)은
47+
네 단계짜리 설계 변경이다.
48+
49+
→ 수정 자체는 가치가 있으나 착수 전에 보안 리뷰 결정이 필요하다.
50+
51+
### #606 — 중복 구현 금지, PR #610 리뷰가 정답
52+
53+
`src/codex/catalog/bundled.ts:146-170`에서 cacheKey가 프로브 결과로 만들어지는
54+
구조는 사실이다. 다만 PR #610이 고치는 것은 그 **순서**가 아니라 프로브 메모이제이션이다
55+
(저자 본문: "I left the ordering alone to keep this change minimal"). 저자가 순서
56+
변경을 후속 제안으로 따로 적어 두었으므로, 우리가 별도 수정을 얹는 것은 충돌만 만든다.
57+
58+
### 그 밖에 오너 결정이 필요한 항목
59+
60+
| 이슈 | 필요한 결정 |
61+
| --- | --- |
62+
| #586 | Providers 페이지에 모드 전환 UI를 넣을지 / Codex Auth 배너를 컨트롤로 승격할지 — GUI 정보구조 결정 |
63+
| #545 | Anthropic OAuth identity 블록 처리 — 메인테이너가 이미 "안전한 수정 아님" 판정 |
64+
| #604 | Cursor Auto 루프 — 재현 환경 확보 + 어댑터 정책 결정 |
65+
| #591 | 관리자 권한 설치는 이미 성공. 그 이후 실패 원인 미상 — 리포터 응답 대기 |
66+
| #553 | PR #575 머지 여부 (진단 메시지 정책) |
67+
| #570 | 항목 1(a)/2만 머지됨. alias(항목 4)·base URL(항목 3)·터널 OAuth(항목 6)는 미해결이고 인증 경계 결정 |
68+
69+
## 보안 경계 확인
70+
71+
경계 판정은 두 축으로 한다. `.github/CODEOWNERS`**경로 글로브**
72+
`MAINTAINERS.md`**주제별 보안 리뷰 규정**(인증·크리덴셜 처리·GitHub Actions·
73+
릴리스 자동화·의존성 설치). 경로만 보면 놓친다 — #612가 그 사례였다.
74+
75+
| 항목 | 경로 경계 | 주제 경계 | 결론 |
76+
| --- | --- | --- | --- |
77+
| #608 `src/service.ts` || 밖 (Task Scheduler XML 비교) | 결정 불요 |
78+
| #612 `src/lib/windows-secret-acl.ts` || **** (크리덴셜 파일 보호) | NEEDS_HUMAN |
79+
| #570 `src/server/auth-cors.ts` | **** | **** | NEEDS_HUMAN |

0 commit comments

Comments
 (0)