# 관리자 RBAC 실행 인수인계 (2026-10-22)

새 세션은 이 문서부터 읽는다. 사용자 지시: PRD `.claude/prds/admin-rbac.prd.md` 의 모든 마일스톤을 workflow 로 끝까지(중간 보고 없이). 마일스톤마다 mccp 체인 — 계획 게이트(라운드 상한 3) → `/mccp:prp-implement`(커밋 금지) → **다른 workflow 세션**에서 `/mccp:code-review` → `/mccp:prp-commit` → fable · codex 최종 리뷰. 마일스톤별 PR 없음, `feat/admin-rbac` 한 브랜치, 원격 push 없음. **작업이 끝나면 mccp 를 다시 제거한다**(아래 「끝낼 때」).

## 새 세션 시작점 (2026-11-02)

**`.claude/notes/rbac-redesign/18-admin-consolidation-handoff.md` 부터 읽는다.** 다음 작업은 Admin · Corp · Sales 화면 통합의 상세 분석이다(구현 지시 아직 없음). 10-28~29 권한 재설계 뒤 최종 HEAD 는 서버 fd1a9ae0 · 관리자 842da1cf · 사이트 fc8872a1, push 없음. 아래 절들은 그 전의 경위이고, 그중 「최종 HEAD」 · 「다음 세션이 할 일」 · 스택 설명의 일부는 낡았다 — 18 문서와 `rbac-redesign/14-decisions-1029.md` 가 우선한다.

## 지금 상태 (2026-10-27 — 실행 종료)

| 마일스톤 | 상태 | 마지막 계획 · 기록 |
|---|---|---|
| 1 ~ 5 | complete | `.claude/notes/admin-rbac-m1.md` ~ `-m5.md` |
| 6 범위 정책 | complete | m6 · m6b · m6c · m6d |
| 7 프런트 호환 | complete | m7 · m7b · m7c |
| 8 토큰 권한 버전 | complete | m8 · m8b |
| 9 영역별 강제 | complete | m9 · m9b ~ m9f (m9f 는 동결 완료 조건 C1~C4) |
| 10 권한 관리 화면 · 가드레일 | complete | m10 |
| 11 정리 | complete | m11 |
| 전체 최종 리뷰 | 끝 | `.claude/notes/admin-rbac-final-review.md` (fable · codex 영역 3 × 2, 수정 R1 · R2, 검토 R2 HIGH 0) |

최종 HEAD: 서버 860e4805 · 관리자 01bed554 · 사이트 fc8872a1 · 부모 이 커밋. 원격 push · PR 없음. 영역 · 범위 상수 · 메뉴 스위치 · 권한 관리 화면 스위치는 OFF. mccp 는 이 커밋 뒤 「끝낼 때」 절차로 제거했다.

남은 것은 사람 몫이다(각 마일스톤 notes 「마감 요약」 의 (미검증) · 사용자 몫 표): 복제 환경 1회 재생 · 스위치 ON 결정과 이미지 재배포 · 0036 DDL 선행 적용 · 영역별 would-deny 판단 표 운영본 · R2(지정 없음 · 칸 없음 상태 정책 — 백로그 2131 잔여) · R7 · R10 · R16(CSRF 뒤 새 쓰기 경로 등록) · R19 · R20(차량 열람 이관 대상 · 그룹 이름 · 승인, env 삭제 커밋) · MOK 외부 서명 키 · 실외부 전달 · 부하 실측 · push · PR.

### 실동작 확인 스택 (2026-10-27 기동, 다음 세션은 여기부터)

사용자가 브라우저로 RBAC 실제 동작을 확인하려고 띄운 격리 스택이다. 합성 데이터만 쓰고 운영 · stg 에 닿지 않는다. 산출 · 비밀은 저장소 밖 `.git/worktrees/admin-rbac/live/`(이하 L) 에만 있다.

- 상태 · 기동 · 내리기: `bash L/status.sh` · `bash L/up.sh` · `bash L/down.sh` (`--remove-worktrees` 를 주면 임시 워크트리도 지운다). 프로세스는 `systemd-run --user` 유닛 6개(`rbac-live-{srv,adm,proxy}-{off,on}`)라 세션이 끝나도 남는다. DB · Redis 는 docker `rbac-live-mysql` · `rbac-live-redis`.
- 접속: VSCode SSH 포트 포워딩 5197 · 5297 → 브라우저 `http://localhost:5197`(OFF = 커밋 상태, 배포될 동작) · `http://localhost:5297`(ON = 영역 강제 3 · 범위 · 메뉴 파생 · 권한 관리 화면 스위치를 켠 임시 워크트리 빌드). 모든 포트는 127.0.0.1 바인드. 관리자 쿠키 `_aaT` 가 secure 라 http IP 로는 로그인이 안 붙는다.
- 계정 8개(최고관리자 · 내부 관리자 권한 있음/거의 없음 · 기업 A/B · 조직관리자 · 영업 A/B)와 비밀번호: `L/accounts.txt`(0600, up.sh 처음 실행 때 생성). 확인 시나리오 · ON 에서 달라지는 것 · 알려진 한계: `L/README.md`.
- 임시 워크트리: `.worktrees/rbac-live-{off,on}-{srv,adm}` (저장소 추적 파일은 바꾸지 않는다). ON 편집 패치 기록 `L/on-build-{srv,adm}.patch`.
- 알려진 한계: 새 쓰기 경로 `/admin/permission/*` 는 모듈 미등록(R16 전)이라 404 — ON 권한 관리 화면의 쓰기는 비어 있다(켜는 방법 README 6절). 메뉴는 정적 경로로 만든 합성 트리, 분석 데이터는 대부분 빈 응답. 서버 요청 로그(L/logs)에 쿠키 · 로그인 본문이 평문으로 남는다.
- 기동 때 고친 것: main.ts 가 `PORT` env 를 먼저 읽어 listen preload 의 7200 치환이 안 걸려 서버가 `*:7201/7202` 로 열렸다 — `L/listen-preload.cjs` 가 GK_PORT 로 들어온 listen 도 127.0.0.1 로 묶게 고치고 재기동, LAN IP 접속 거부 확인.
- 다음 세션이 할 일: 사용자의 확인 결과(화면 · 응답 지적)를 받아 고친다. mccp 는 제거됐으므로 mccp 체인 없이 직접 고치고(시험 → 수정 → 반사실 → 커밋), 서버 · 관리자 코드를 바꾸면 OFF 스택은 `.worktrees/rbac-live-off-*` 를 새 HEAD 로 옮기고 `down.sh` → `up.sh` 로 다시 띄운다. 확인이 끝나면 `bash L/down.sh --remove-worktrees`.

운영 배포 때 알릴 동작 변화: 지정 행이 있는 환경에서 비최고관리자의 계정 삭제 · 생성은 403(E0827, PRD R2). 계정 생성 · 수정의 가드레일 판정은 스위치와 무관하게 상시 적용된다(PRD 결정 B · 행 10 의도 — 최종 리뷰 관찰). 조직 경로 없는 조직관리자의 회원 쓰기는 403(M6 편차 26).

## 도구

- 오케스트레이션 스크립트: `/home/madsc/work/insuniverse-temp/.git/worktrees/admin-rbac/mccp-gatekit/milestone.js` — `Workflow({scriptPath, args})`.
  - 공통 args: `{"wt": "/home/madsc/work/insuniverse-temp/.worktrees/admin-rbac", "gatekit": "/home/madsc/work/insuniverse-temp/.git/worktrees/admin-rbac/mccp-gatekit", "plugin": "/home/madsc/.claude/plugins/cache/mccp/mccp/1.33.6", "today": "<YYYY-MM-DD>"}`
  - `stage`: `build`(계획 → 게이트 → 구현) · `review`(code-review, 최대 3라운드) · `finish`(커밋 → 최종 리뷰 → 마감) · `implement-resume`(도중에 끊긴 구현 잇기, `maxLegs` 로 이어달리기 · 계획 receipt 가 skip 이면 `skip: true`) · `repair-close`(보류된 마감: `checks` · `env` · `questions` 로 재검증 + fable · codex 판정 + 마감).
  - 보완 계획: `{"m": "6c", "base": 6, "scope": "<범위 못박기>"}`. 재개 플래그: `resumePre`(계획 커밋됨 · pre.sh 부터) · `resumeRound`(라운드 라벨) · `resumePost`(L2 끝 · L3 부터) · `resumeCap` · `skipToImplement`(상한 처리 끝 · 구현부터) · `skipCommit` + `commits`(finish 에서 커밋 건너뛰기).
- gate-kit(같은 디렉터리): pre.sh · post-a.sh · l3-run/poll · post-b.sh · seal-converged.sh · status.sh · validate.sh · codex-ask.sh(Codex 단발 질의) · verify-user-directive.sh · README.md.

## 꼭 지킬 것 (실측으로 생긴 규칙)

1. **마지막 라운드 skip-receipt**(사용자 지시 2026-10-19, 원문은 `verify-user-directive.sh` 로 확인): 상한 3 의 마지막 라운드에 CRITICAL 이 없으면 계획 receipt 를 쓰지 않고 구현 진입 preflight 만 `MCCP_SKIP_RECEIPT=1` 로 넘긴다(명령 단위 — 세션 · 설정에 두지 않는다). HIGH 는 backlog `→ 다음 계획 반영 대상`.
2. **라운드 원장이 10-21 에 사라졌다**(`.claude/state` 하위 디렉터리 소실, 원인 미확정). mccp 원장 숫자를 믿지 말고 스크립트 라벨(`resumeRound`)로 상한 3 을 지킨다. m6c 는 새 계획이라 R1 부터.
3. **운영 검증은 복제 환경 1회 실행**(사용자 지시 2026-10-21, PRD 결정 로그 2026-10-21 절): 배포 뒤 장기 관측 조건을 쓰지 않는다. 개발 실행은 격리 DB 로 같은 절차를 미리 돌리고, 복제본 1회 재생은 사용자 몫.
4. **격리 DB**: `/home/madsc/work/security-review/insuniverse-isolated/initdb/02-schema.sql` + `01-functions.sql`. 컨테이너는 `m<N>-iso-` 접두로만 띄우고 내린다. 운영 DB · stg DB 쓰기 금지.
5. **포맷이 편집 뒤 저절로 바뀐다**: 미커밋 변경이 `git show HEAD:<f> | npx prettier --stdin-filepath <f> | cmp -s - <f>` 로 같으면 순수 포맷 → `style` 커밋.
6. **workflow 레인이 null 이면 통과가 아니다**(사용량 한도 실측) — 스크립트가 `final-lane-failed` · `close-failed` 로 멈춘다. 그때는 `finish` + `skipCommit` 으로 다시.
7. 세션 폭주 상한은 gate-kit env.sh 에서 220(남은 몫 기준). 소진되면 남은 몫만큼만 올린다.
8. 마감 판정: 코드 · 격리 환경으로 할 수 있는데 안 한 항목이 있으면 in-progress, 배포 · 운영 데이터 · 사람 확인만 남으면 (미검증)으로 적고 complete.

## 다음 한 걸음 (그대로 실행)

```
Workflow({scriptPath: "/home/madsc/work/insuniverse-temp/.git/worktrees/admin-rbac/mccp-gatekit/milestone.js",
  args: {"m": "6c", "base": 6, "stage": "build", <공통 args>,
    "scope": "근거: .claude/notes/admin-rbac-m6b.md 맨 위 「마감 요약」 의 PRD 미달 4건 · backlog `보완 계획 admin-rbac-m6bb` 줄. 계획서 초안 .claude/PRPs/plans/admin-rbac-m6c.plan.md(미커밋)가 이미 있다 — 읽고 다듬어 규약 · lint 를 맞춘 뒤 커밋하고 게이트에 진입한다. 1) 단건 3의미 분리(judgeSingleScope 를 실제 단건 핸들러에 · 신원별 단건 키 · 기업 행 조직관리자 판정 확정) 2) 쓰기 검사 · 변경 같은 트랜잭션 잔여(결제 취소 · 회원 지정 적립 · 환불 · 조직 권한 업로드) + 소속 쓰기 · 조직 삭제 잠금 순서 한 방향(경합 itspec 두 순서 실측) 3) 일괄 전건 검사(판정 없는 일괄 경로 전부 · 격리 DB 시험으로 전건 거부 증명) 4) 증명 6 행 「다른 기업 행 0」 을 이행표 목록 · count · 집계 · 내보내기 전 행으로 넓힌 격리 측정. 강제 상수 OFF(M9 몫). defer-unverified: 복제본 1회 재생 · R5 업무 확인 · 레거시 예외표 책임자 기입."}})
```

## 끝낼 때 (mccp 제거 — 사용자 지시)

1. `cd /home/madsc/work/insuniverse-temp/.worktrees/admin-rbac && claude plugin uninstall mccp@mccp --scope project`
2. `claude plugin marketplace remove mccp`
3. `git update-index --no-skip-worktree .claude/settings.json && git checkout -- .claude/settings.json`
4. `git diff HEAD -- .claude/settings.json` 가 비었는지 확인(설치가 이 추적 파일을 다시 써서 skip-worktree 로 숨겨 두었다).

## 사용자 몫 (누적, 이 실행이 할 수 없는 것)

운영 DB 조회 R7(ath_id NULL 수 · tn_auth · tn_menu_auth_map) · R8 운영 JWT 수명 env · DDL 0036 운영 적용 · 복제 환경 1회 재생(M2 실패 모드 전환 · M5/M6/M9 would-deny 표) · 메뉴 파생 스위치 ON(R7 뒤) · 실 배포 번들 확인 · 혼재 배포 런북 적용 · R5 · R19 · R10 · R16 · R20 · 원격 push / PR.
