Skip to content

Commit 3a2b2ea

Browse files
authored
Merge pull request lidge-jun#573 from lidge-jun/codex/260728-ssh-loopback-gate
fix(server): treat forwarded loopback ports as loopback
2 parents ece0d9f + e2da6f6 commit 3a2b2ea

21 files changed

Lines changed: 2226 additions & 25 deletions

devlog/_plan/260727_owner_decision_ledger/000_scope.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,18 @@
3838
| `004_pr_decision_ledger.md` | 열린 PR 14건의 오너 결정 지점 |
3939
| `005_open_questions.md` | 인터뷰에서 물을 질문 목록 |
4040
| `006_corrections.md` | 초안 대비 정정 기록 (Mind 감사 결과) |
41+
| `007_delta_260728.md` | **07-28 재측정 델타 — 현재 사실. 충돌 시 이 문서 우선** |
42+
| `008_wsl_ssh_report_intake.md` | WSL/SSH 구두 제보 접수 — 저장소 미등록, 재현 정보 대기 |
43+
| `009_ssh_remote_proxy_rootcause.md` | **SSH 원격 프록시 근본 원인 확정 — 재현 완료** |
44+
| `010_bug_bundle_fixability.md` | **bug 묶음 13건 해결가능성 전수 판정** |
4145

4246
## 원칙
4347

4448
1. 이 라운드에서는 **기록만** 한다. 이슈/PR에 코멘트하거나 라벨을 바꾸지 않는다.
4549
(이 원칙은 이번 라운드 한정이며, 다음 사이클의 실행 권한은 미확정 —
46-
`005_open_questions.md` Q5.)
50+
`005_open_questions.md` **Q6**. 초안이 Q5로 잘못 가리켰던 것을 정정 —
51+
`007_delta_260728.md` §7-C. 또한 이 원칙은 **이 원장 작성자에게만** 적용되며,
52+
같은 시간대에 다른 메인테이너들이 동일 항목을 이미 변경했다 — 같은 문서 §7-D.)
4753
2. 각 항목은 "결정하지 않으면 무슨 일이 일어나는가"를 명시한다. 결정 회피의
4854
비용이 보이지 않으면 인터뷰가 의미 없다.
4955
3. 묶음은 **결정 축이 같은 것끼리** 묶는다. 라벨이나 파일 경로가 아니라.
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# 007 — 원장 델타 (2026-07-28 재측정)
2+
3+
세션: `019fa4fe-96d4-7b80-a25b-33e03186d4cd`
4+
재측정 시각: 2026-07-28 (KST 새벽)
5+
기준: `origin/dev` = `461de3961` (원장 작성 시점 `c05e88fd` 대비 전진)
6+
7+
`000_scope.md`~`006_corrections.md`는 2026-07-27 오후 스냅샷이다. 그 뒤 저장소
8+
상태가 움직였으므로 이 문서가 **현재 사실**이고, 충돌 시 이 문서가 우선한다.
9+
10+
## 1. 총계 변화
11+
12+
| 항목 | 원장(07-27) | 현재(07-28) |
13+
| --- | --- | --- |
14+
| 열린 이슈 | 23 | 23 |
15+
| 열린 PR | 14 (ready 4, draft 10) | 15 (ready 5, draft 10) |
16+
| enhancement 이슈 | 13 | 15 (`+561, +563`) |
17+
| roadmap 이슈 | 7 | 7 (변동 없음) |
18+
| upstream-tracking 이슈 | 5 | 5 (변동 없음) |
19+
| needs-info 이슈 | 4 (`462,509,521,543`) | 3 (`462,543,553`) |
20+
| 라벨 없는 이슈 | 2 (`545,546`) | 0 |
21+
22+
총계가 같아 보이지만 구성이 다르다. 닫힌 것과 새로 온 것이 우연히 상쇄됐다.
23+
24+
ready 5 = `[527, 528, 558, 565, 568]`, draft 10 = `[355, 424, 429, 447, 493,
25+
498, 512, 533, 557, 562]`. (초안이 ready 6으로 잘못 셌던 것을 정정.)
26+
27+
## 2. 신규 — 원장에 없던 항목 8건
28+
29+
### PR 5건
30+
31+
| # | 제목 | 작성자 | 상태 | 규모 | 결정 축 |
32+
| --- | --- | --- | --- | --- | --- |
33+
| 568 | `feat(cli): add ocx opencode launcher` | Wibias | ready, MERGEABLE/UNSTABLE, enhancement | +763/-0, 6f | **Q5 표면 확장**. 닫힌 #461의 대체본 |
34+
| 565 | `feat(codex): add account pause controls and bulk exhaustion action` | Alvin0412 | ready, mergeable UNKNOWN(계산중), enhancement | +819/-34, 34f | **묶음 B(계정 정책)** 신규 유입 |
35+
| 562 | `[codex] Add Modelsell provider preset` | modelsell | draft, MERGEABLE/UNSTABLE, 라벨 없음 | +107/-16, 19f | **묶음 D(프로바이더 기준)** — 이슈 #561과 한 쌍 |
36+
| 558 | `feat(storage): restore quarantined archived sessions (phase 2.1 of #42)` | Wibias | ready, **CONFLICTING/DIRTY** | +3711/-54, 23f | **묶음 G(#42 로드맵)** |
37+
| 557 | `fix(update): harden npm cache recovery preflight logs` | lidge-jun | draft, MERGEABLE/CLEAN | +3192/-97, 23f | **묶음 F(보안 경계)**#533의 메인테이너 인수본 |
38+
39+
### 이슈 3건
40+
41+
| # | 제목 | 라벨 | 결정 축 |
42+
| --- | --- | --- | --- |
43+
| 553 | GitHub Copilot 502 + `ERR_TLS_CERT_ALTNAME_INVALID` | bug, needs-info | 신규 needs-info. 리포터 응답 대기 |
44+
| 561 | Modelsell을 내장 OpenAI-compatible 프로바이더로 | enhancement | **묶음 D**`#540` 기준(공식 인증 경로) 적용 대상 |
45+
| 563 | 메모리 카드에서 graceful drain-and-restart | enhancement | `003_enhancement_ledger.md` 신규 행. #427 후속 |
46+
47+
## 3. 원장 기재 사항 중 무효가 된 것
48+
49+
| 원장 기재 | 현재 사실 |
50+
| --- | --- |
51+
| PR #461 = 표면 확장 단독 결정 | **CLOSED** (07-27 19:10). 동일 기능이 #568로 재제출 — Q5는 유효하되 대상 번호가 바뀜 |
52+
| PR #491 = draft/CONFLICTING, 묶음 F | **MERGED** (07-27 18:59). 묶음 F에서 제외 |
53+
| PR #526 = "그냥 머지 대상" | **MERGED** (07-27 12:05) |
54+
| PR #495 = draft, 묶음 B | **CLOSED** (머지 안 됨). "main 최후 수단" 축은 열린 PR이 없다 |
55+
| PR #533 = ready, CHANGES_REQ | 지금 **draft**. 인수본 #557이 별도 존재 → 묶음 F의 결정은 재리뷰가 아니라 **#533 vs #557 진행선 선택** |
56+
| 이슈 #509 (needs-info, heap watchdog) | **CLOSED** |
57+
| 이슈 #521 (499 client_closed_request) | **CLOSED** |
58+
| 이슈 #546 (Desktop 3P 모델 피커) | **CLOSED**. 묶음 E는 `#545`, `#543` 2건으로 축소 |
59+
| `origin/dev` = `c05e88fd` | `461de3961` |
60+
61+
## 4. 변동 없음이 확인된 것
62+
63+
- 묶음 A(#424 / #355 / #528): 셋 다 열림, 상태 동일. #528만 ready/UNSTABLE,
64+
나머지 둘은 draft/CHANGES_REQUESTED. **Q1 미결**.
65+
- 묶음 C(업스트림 추적): #92, #241, #401, #417, #462 전부 열림. 유효 링크는
66+
여전히 #417 하나.
67+
- 묶음 D 원본(#177, #178, #201)과 기준 #540: 전부 열림. **Q3 미결**.
68+
- PR #527: base가 여전히 `codex/catalog-written-signal`(dev 아님) + CONFLICTING.
69+
- PR #429, #493, #498, #512: 전부 CONFLICTING/DIRTY 유지.
70+
- roadmap 7건(`42,95,177,178,201,294,540`) 라벨 변동 없음 → **Q4 미결**.
71+
72+
## 5. 미결 질문에 미치는 영향
73+
74+
| 질문 | 상태 변화 |
75+
| --- | --- |
76+
| Q1 이미지 백엔드 | 변화 없음. 그대로 유효 |
77+
| Q2 계정 정책 | **범위 재편**#495가 닫히고 #565가 들어와 대상이 `#512, #493, #565` |
78+
| Q3 프로바이더 기준 소급 | **즉시성 상승**#561/#562가 기준 적용을 실시간으로 요구 |
79+
| Q4 로드맵 정직성 | **압력 상승**#558#42를 phase 2.1까지 밀고 있음 |
80+
| Q5 `ocx opencode` | 대상이 #461**#568**. ready 상태라 방치 비용이 더 크다 |
81+
| Q6 실행 권한 | 변화 없음 |
82+
83+
## 6. 이 문서가 하지 않은 것
84+
85+
이슈/PR에 코멘트·라벨·상태 변경을 일절 하지 않았다. `000_scope.md` 원칙 1을
86+
유지한다 — 이번에도 **기록만** 했다.
87+
88+
단, 이 진술의 주어는 **이 원장의 작성자**다. 저장소 전체가 정지해 있었다는
89+
뜻이 아니다 — §7-D 참조.
90+
91+
## 7. Mind 감사 정정 (2026-07-28, 2 Mind 병렬 read-only)
92+
93+
델타 초안을 쓴 뒤 Ontology 렌즈와 Goal/Success 렌즈를 각각 돌렸다. 아래는
94+
**직접 재실측으로 확인된 것만** 옮긴 것이다. 초안이 틀렸던 부분은 위 본문에
95+
반영했고, 원장 본체(001~006)에 대한 지적은 여기에 남긴다.
96+
97+
### 7-A. `stale-needs-info` 워크플로는 지금 **가동 중**이다 (HIGH)
98+
99+
`002_upstream_tracking.md``006_corrections.md` F1은 이 워크플로가
100+
`origin/main`에 없어 "현재 동작하지 않는다"고 확정했다. 실측:
101+
102+
```
103+
git ls-tree origin/main --name-only .github/workflows/ → stale-needs-info.yml 존재
104+
gh api .../actions/workflows → "Close stale needs-info issues | active"
105+
cron "15 6 * * *", only-issue-labels: needs-info,
106+
days-before-issue-stale: 14, days-before-issue-close: 7, close-issue-reason: not_planned
107+
```
108+
109+
`needs-info` 이슈는 **14일 무응답 → 7일 뒤 자동 클로즈**된다. 현재
110+
`needs-info` = `[462, 543, 553]`이고 #462는 07-26 이후 정지 상태다. 원장은
111+
묶음 C/E에 "시한 압박 없음"이라고 적었으나, 실제로는 카운트다운이 돌고 있다.
112+
113+
단, 같은 워크플로에 `remove-stale-when-updated: true`가 있어 **코멘트 한 줄이면
114+
시계가 리셋된다**(2차 감사 정정). 따라서 강제 마감이 아니라 "방치하면 봇이
115+
닫는다" 수준이다 — 결정 순서를 뒤집을 정도는 아니고, 알고 있어야 할 배경이다.
116+
117+
### 7-B. PR #491은 승인 0건으로 머지됐다 (HIGH)
118+
119+
초안은 "MERGED → 묶음 F에서 제외"라고만 적었다. 실측:
120+
121+
```
122+
gh pr view 491 --json reviews → CHANGES_REQUESTED(Wibias) 1건, APPROVED 0건
123+
mergedBy = Wibias, mergedAt = 2026-07-27T18:59:10Z
124+
변경 파일: src/oauth/index.ts, src/oauth/login-cli.ts, src/providers/api-keys.ts, src/router.ts
125+
MAINTAINERS.md:26 "approval from at least one maintainer"
126+
MAINTAINERS.md:31 "Security-sensitive … reviewed by both maintainers"
127+
```
128+
129+
원장이 스스로 "AGENTS.md 최우선 보안 경계"로 분류한 PR이 승인 없이, 그것도
130+
`CHANGES_REQUESTED` 상태에서 머지됐다. 항목을 묶음에서 지울 게 아니라
131+
**게이트가 뚫렸다는 사실로 기록해야 한다**. 이건 Q6(실행 권한)의 직접 증거다.
132+
133+
### 7-C. `000_scope.md` 원칙 1이 잘못된 질문을 가리켰다 (HIGH)
134+
135+
"다음 사이클의 실행 권한은 미확정 — Q5"라고 적혀 있었으나 실행 권한은 **Q6**,
136+
Q5는 `ocx opencode` 표면이다. 수정했다.
137+
138+
### 7-D. "기록만 한다"는 라운드가 아니라 작성자에게만 참이었다 (HIGH)
139+
140+
같은 시간대 실측 타임라인:
141+
142+
| 시각(UTC) | 행위자 | 변경 |
143+
| --- | --- | --- |
144+
| 07-27 10:17 | Ingwannu | 이슈 #546 클로즈 |
145+
| 07-27 10:22 | Ingwannu | #545`bug`, `needs-info` 라벨 부착 |
146+
| 07-27 14:52 | lidge-jun | PR #557 생성 |
147+
| 07-27 14:56 | Ingwannu | #545`provider-compatibility` 부착 |
148+
| 07-27 18:59 | Wibias | PR #491 머지 |
149+
| 07-27 19:10 | Wibias | PR #461 클로즈 → #568로 대체 |
150+
151+
Q6은 실행 권한을 "오너가 에이전트 하나에게 주는 스위치"로 모델링했지만, 실제로는
152+
**세 행위자가 이미 같은 항목을 동시에 바꾸고 있다**. 질문 형태 자체가 현실과
153+
맞지 않는다.
154+
155+
### 7-E. Q3(#540 기준 소급)은 이미 오너가 답한 질문이다 (HIGH)
156+
157+
```
158+
gh issue view 177 → lidge-jun 2026-07-22T06:36:14Z "Warp's public surface is the Oz agent API …"
159+
gh issue view 178 → lidge-jun 2026-07-22T06:36:04Z "Factory's official surface is the Droid Exec/SDK …"
160+
gh issue view 201 → lidge-jun 2026-07-22T06:36:03Z "no documented official API surface … which we avoid"
161+
```
162+
163+
세 건 모두 오너 본인이 #540 기준과 동일한 논리로 **07-22에 이미 판정**했고, 셋 다
164+
"long-term request"로 열어뒀다. Q3의 예상 결과("소급하면 일부는 DECLINE으로
165+
닫힌다")는 실제 이력과 반대다. Q3는 새 질문이 아니라, 이미 내린 판정을 **문서화된
166+
기준으로 승격할지**의 질문으로 다시 써야 한다.
167+
168+
### 7-F. Q1의 규모 수치가 전부 낡았다 (HIGH)
169+
170+
| PR | 원장 기재 | 실측(07-28) | head |
171+
| --- | --- | --- | --- |
172+
| #355 | +1435/-15, 16f | **+2031/-21, 20f** | `df6a7458` |
173+
| #424 | +2333/-59, 22f | +2333/-59, 22f | `5ade2647` (원장 기재 `a8b769c9` 소멸) |
174+
| #528 | +2770/-60, 21f | **+3443/-64, 25f** | `34c6d852` (원장 기재 `553e9afc` 소멸) |
175+
176+
Q1이 파는 "(a) 규모 작음 1435 vs (b) 5100" 대비는 실제로 **2031 vs 5776**이다.
177+
또한 #355는 07-27 15:49에도 기여자가 작업 중이었다 — 초안 §4의 "묶음 A 변화 없음"은
178+
틀렸다. 묶음 A는 상태 라벨만 같고 내용은 계속 움직이고 있다.
179+
180+
### 7-G. Q5는 이미 실행된 결정이다 (HIGH)
181+
182+
PR #568은 메인테이너(Wibias)가 #461을 인수해 재제출한 것이고, 본문에 오너
183+
(`lidge-jun`)의 크리덴셜 수명주기 리뷰를 반영했다고 적혀 있다. 즉 "받을
184+
것인가"는 이미 지나간 질문이다. 남은 실제 미결은 **windows CI 실패**와, 애초에
185+
존재하지 않는 어휘인 "지원 등급"을 새로 만들 것인가다 —
186+
`rg -i "support tier|지원 등급" MAINTAINERS.md AGENTS.md docs-site/` → 0건.
187+
188+
### 7-H. 묶음 경계 자체가 어긋난 곳 (MEDIUM)
189+
190+
| 문제 | 실측 |
191+
| --- | --- |
192+
| 묶음 G(`#95,#386,#414,#415,#42`) ≠ Q4의 roadmap 7건(`42,95,177,178,201,294,540`) | 겹치는 건 `#42, #95` 둘뿐. #386/#414/#415에는 `roadmap` 라벨이 없다 |
193+
| 묶음 C가 #418을 포함 | `#418` 라벨 = `['bug']`. `upstream-tracking` 아님. 같은 문서가 #543은 "라벨이 아니라서" 뺐다 — 같은 기준을 반대로 적용 |
194+
| 묶음 D에 #561/#562 편입 | #540 기준은 **OAuth 사칭/토큰 파일 임포트** 문제다. #561은 사용자가 자기 키를 붙여넣는 문서화된 엔드포인트 — 기준이 적용될 대상이 아니다 |
195+
| 묶음 E = "Desktop 3P" | #546 클로즈 후 남은 건 #545(Desktop 3P)와 #543(**Kiro + Claude Code**). 이름이 절반에만 맞는다 |
196+
| 묶음 B에 #565 편입 | #565 본문: "main 계정 특수 취급보다 일반적인 제어". #495를 대체하며 B의 정의축(`main`의 의미)을 **해소해버리는** PR이다. B의 축은 이제 "네임스페이스 신원 vs 계정별 일시정지 자격"으로 바뀌었다 |
197+
| `#545/#546 라벨 없음``확정` 표에 있음 | 라벨은 원장 작성 **4시간 전**에 이미 붙어 있었다. `확정` 칸은 질문을 없애는 칸이라 오류 비용이 크다 |
198+
| 이슈 23건 전수 배정 | 신규 #553/#561/#563이 어느 묶음에도 안 들어갔다. 커버리지 전제조건이 지금 깨져 있다 |
199+
200+
### 7-I. Success criteria가 검증 불가능하다 (HIGH)
201+
202+
`005`는 done을 "각 묶음에 대해 오너가 방향을 정했는가"로 정의했다. 이건 어떤
203+
오라클로도 확인할 수 없다 — (a)/(b)/(c) 무엇을 말해도, 심지어 자기모순인 답을
204+
해도 통과한다. 이 저장소의 실제 검증자(`enforce-pr-target``ALLOWED_BASES`,
205+
`bun run typecheck/test/privacy:scan`)와 대비된다. 루프 아키타입을 다시
206+
정해야 한다: 이건 **spec 루프가 아니라 결정 유도 루프**이며, done은 "오너가
207+
의견을 냈다"가 아니라 **"각 결정이 저장소에 관측 가능한 상태 변화로 남았다"**
208+
잡아야 검증된다.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# 008 — WSL/SSH 제보 접수 (미등록 항목)
2+
3+
접수: 2026-07-28, 오너 구두 제보 — "Windows WSL에서 SSH가 꼬이는 버그가 있다더라"
4+
상태: **저장소에 등록된 흔적 없음**. 이슈·PR·devlog 어디에도 없다.
5+
6+
> **초안 전면 정정 (Mind 감사, 2026-07-28).** 아래 §정정 이전의 초안은 "SSH를
7+
> 다루는 코드가 없다"는 잘못된 전제 위에 서 있었다. 실측으로 반증됐고, 후보
8+
> 순위도 뒤집혔다. 이 문서는 정정본이다.
9+
10+
## 실측 — 등록 여부
11+
12+
```
13+
gh issue list --state all --search "WSL" → #63(CLOSED, Desktop WSL app-server)만
14+
gh issue list --state all --search "ssh" → #131 [Bug] GUI OAuth login has no manual
15+
redirect URL / code paste fallback (CLOSED 2026-07-15)
16+
```
17+
18+
**미등록이 아니다.** #131이 바로 "원격 GUI·SSH·loopback 차단 환경에서 로그인을
19+
끝낼 방법이 없다"는 이슈이고, 07-15에 닫혔다. 따라서 이번 제보는 둘 중 하나다:
20+
21+
- **#131의 회귀** — 고쳐진 경로가 다시 깨졌다
22+
- **다른 버그**#131이 덮지 않는 별개 증상
23+
24+
어느 쪽인지가 다음 행동을 완전히 가른다.
25+
26+
## 실측 — SSH는 이미 모델링돼 있다 (초안의 오류)
27+
28+
초안은 `rg 'SSH_CLIENT|SSH_TTY|SSH_CONNECTION'` 0건을 근거로 "SSH를 다루는 코드는
29+
없다"고 썼다. **환경변수 이름이 잘못된 프로브였다.** 실제로는 세 곳에서 SSH
30+
세션을 명시적으로 다룬다:
31+
32+
| 위치 | 내용 |
33+
| --- | --- |
34+
| `src/service.ts:1298-1321` | `ensureUserBusEnv()` — "SSH sessions frequently start without `XDG_RUNTIME_DIR`/`DBUS_SESSION_BUS_ADDRESS`". `isSystemd()`가 user-bus 프로브 실패 시 runtime dir 존재로 폴백(F9) |
35+
| `src/oauth/index.ts:610` | "Manual fallback: when the browser cannot reach the loopback callback (**remote GUI, SSH**, blocked localhost)" — `submitManualLoginCode()` 경로 |
36+
| `src/server/management/oauth-account-routes.ts:123` | 같은 폴백의 HTTP 표면 (`/api/oauth/login/code`) |
37+
| `tests/windows-deploy-close-regressions.test.ts:38` | "systemd detection tolerates a no-DBUS SSH session (F9)" — 회귀 테스트 존재 |
38+
39+
즉 "SSH가 꼬인다"는 제보는 **빈 땅이 아니라 이미 설계된 경로 안의 회귀나 구멍**
40+
가능성이 높다. 조사 대상 파일이 초안과 다르다.
41+
42+
## 코드에 실제로 있는 WSL 경로 (조사)
43+
44+
| 경로 | 파일 | 하는 일 |
45+
| --- | --- | --- |
46+
| WSL 런타임 감지 | `src/codex/home.ts:82` `isWslRuntime` | `/proc/version``microsoft\|WSL` 매칭 |
47+
| Windows 홈 탐색 | `src/codex/home.ts:91` `listWslWindowsCodexHomes` | `/mnt/c/Users/*/.codex` 열거 |
48+
| automount 루트 | `src/codex/home.ts` `wslAutomountRoot` | `/etc/wsl.conf``[automount] root` |
49+
| interop shim 거부 | `src/codex/shim.ts:280-316` | Windows쪽 `codex.exe`를 WSL PATH로 잡으면 shim 작성 거부 |
50+
| systemd 안내 | `src/service.ts:1369` | WSL에서 systemd 없을 때 `wsl.conf` 안내 |
51+
| localhost 방향성 진단 | `src/cli/doctor.ts` | WSL2 NAT에서 localhost가 단방향임을 힌트로 안내 |
52+
53+
## 후보 재순위 (정정 후)
54+
55+
| # | 후보 | 근거 | 실제 강도 |
56+
| --- | --- | --- | --- |
57+
| C1 | **#131 회귀** — GUI/CLI 로그인 수동 폴백이 다시 깨짐 | #131이 정확히 이 증상. **PR #491이 07-27 18:59에 `src/oauth/login-cli.ts`를 포함해 승인 0건으로 머지됨** — 제보 12시간 전 | **가장 유력**. 회귀 용의자가 시간·파일 양쪽으로 맞는다 |
58+
| C2 | SSH 포트포워딩으로 원격 프록시 사용 | 저장소가 이 구성을 모델링하지 않음 | 중. 진짜 빈 땅이지만 제보 표현과의 연결이 약함 |
59+
| C3 | WSL2 localhost 단방향 | `doctor.ts:845`가 힌트 제공 | **낮음**. 힌트 안에 `networkingMode=mirrored` 해법이 명시돼 있고, `hostname` 설정 레버도 문서화돼 있다(`docs-site/.../configuration.md:33`) — 발견성 문제지 기능 부재가 아님 |
60+
| C4 | shim interop 거부 | `src/codex/shim.ts:311-314` | **낮음**. 거부 메시지가 복구 명령까지 명시한다. "꼬였다"와 가장 안 맞는다 |
61+
|| ~~브라우저 자동 열기 실패~~ | ~~`open-url.ts`에 폴백 없음~~ | **기각**. 호출 5곳 전부 URL을 먼저 출력하거나 GUI로 반환하고, `gui/src/components/login-url-block.tsx`가 URL 전문·복사·수동 열기를 제공한다. 실패해도 복구 경로가 있다 |
62+
63+
초안이 최우선으로 올렸던 "브라우저가 안 열린다"는 **이미 해결된 문제**다.
64+
`260727_login_url_copy_parity` 계획이 이미 dev에 반영됐다(`040_outcome.md`
65+
커밋 6건, `login-url-block.tsx` 존재).
66+
67+
## 이것이 바꾸는 것
68+
69+
PR #491은 원장이 "보안 경계"로 분류한 PR이고(`007_delta_260728.md` §7-B), 승인
70+
없이 머지됐으며, 하필 이번 제보의 최유력 후보 경로(`src/oauth/login-cli.ts`)를
71+
건드렸다. **007 §7-B와 이 문서는 별개 주제가 아니라 같은 사건일 수 있다.**
72+
73+
## 다음 행동 (미승인)
74+
75+
1. 제보 원문(출처·재현 조건)을 받아 C1인지 C2인지 가른다.
76+
2. C1이면 #491 diff를 `src/oauth/login-cli.ts` 기준으로 읽고 #131의 회귀 여부를
77+
재현으로 확인한다. 이슈는 새로 열지 말고 **#131 재오픈**이 맞을 수 있다.
78+
3. C2면 새 이슈 — 저장소가 모델링하지 않은 유일한 시나리오다.
79+
80+
기록만 했고, 이슈 생성·재오픈·코멘트는 하지 않았다.
81+
82+
## 감사 이력
83+
84+
2026-07-28, `mind_constraint`(read-only) 1회. 이 문서 초안에서 high 4건이
85+
반증됐다: (1) "SSH 코드 없음" 오류, (2) 후보 1 순위 역전, (3) 수정 범위 추정
86+
근거가 이미 완료된 계획, (4) #131 미발견. 전부 반영했다.

0 commit comments

Comments
 (0)