From 356b473ea9d6b84961c27a701d775798157a5a85 Mon Sep 17 00:00:00 2001 From: swrring Date: Wed, 15 Apr 2026 10:03:26 +0900 Subject: [PATCH] =?UTF-8?q?fix(permissions):=20=EC=9E=90=EC=8B=9D=20?= =?UTF-8?q?=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20settings.json=20?= =?UTF-8?q?=EC=A0=84=ED=8C=8C=20+=20deny=20=ED=8C=A8=ED=84=B4=20=EC=8A=A4?= =?UTF-8?q?=ED=8E=99=20=EA=B5=90=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 근본 원인 2종 해소: 1. .claude/ 계층 auto-merge 미지원 문제 - Claude Code는 .claude/ 폴더 1개만 프로젝트 루트로 인식, 부모 auto-merge 안 함 - 개발실/.claude/·기획실/.claude/ 이미 존재 → 자식 디렉토리 세션에서 루트 settings.json 무시됨 - 기획실보다 작업량이 2~4배 복잡한 개발실에서 승인 요구 폭발적으로 드러남 - 해결: 루트 SOT → 부서 2개 복제 배치 + setup_windows.ps1에 자동 동기화 로직 추가 2. deny 패턴 리터럴 매칭 문제 - 'Bash(rm -rf /*)'는 glob이 아닌 리터럴로 해석되어 실제 rm -rf /home/foo 차단 불가 - prefix 기반 'Bash(rm:*)' 'Bash(rmdir:*)' 'Bash(chown:*)' 등으로 교정 - 추가 deny: shutdown/reboot/chmod 777/Windows 시스템 디렉토리 쓰기 memory/org/feedback_permissions_portability.md 보강: - "자식 디렉토리 전파 원칙" 섹션 신설 - SOT(루트) + 파생(부서 2개) + 동기화 메커니즘 명시 세션 재시작 후 적용됨. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/settings.json | 25 ++++--- .../org/feedback_permissions_portability.md | 12 +++ setup/setup_windows.ps1 | 20 +++++ 개발실/.claude/settings.json | 75 +++++++++++++++++++ 기획실/.claude/settings.json | 75 +++++++++++++++++++ 5 files changed, 196 insertions(+), 11 deletions(-) create mode 100644 개발실/.claude/settings.json create mode 100644 기획실/.claude/settings.json diff --git a/.claude/settings.json b/.claude/settings.json index 02aa846..17c104d 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,11 +1,10 @@ { - "_description": "너드나비스 조직 공용 Claude Code permission 설정. PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개별 PC 예외·실험적 명령은 .claude/settings.local.json(gitignore)에 기록.", + "_description": "너드나비스 조직 공용 Claude Code permission 설정 (SOT). PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개발실/·기획실/에도 동일 사본이 배치되어야 자식 디렉토리에서 세션을 시작해도 동일 권한이 적용됨 (Claude Code는 .claude/ 계층 auto-merge 미지원). 동기화는 setup_windows.ps1이 수행.", "permissions": { "allow": [ "Read", "Glob", "Grep", - "LS", "TodoWrite", "Edit", "Write", @@ -40,8 +39,9 @@ "Bash(false)", "Bash(powershell.exe:*)", "Bash(powershell:*)", - "Bash(fsutil reparsepoint:*)", - "Bash(npm run:*)", + "Bash(fsutil:*)", + "Bash(cmd:*)", + "Bash(npm:*)", "Bash(npx:*)", "Bash(node:*)", "Bash(python:*)", @@ -52,21 +52,24 @@ "WebSearch" ], "deny": [ - "Bash(rm -rf /*)", - "Bash(rm -rf ~*)", - "Bash(rm -rf $HOME*)", + "Bash(rm:*)", + "Bash(rmdir:*)", "Bash(sudo:*)", - "Bash(chmod 777:*)", - "Bash(format:*)", "Bash(dd:*)", "Bash(mkfs:*)", - "Bash(:(){ :|:& };:)", + "Bash(format:*)", + "Bash(chmod 777:*)", + "Bash(chown:*)", + "Bash(shutdown:*)", + "Bash(reboot:*)", "Write(/etc/**)", "Write(/System/**)", "Write(C:/Windows/**)", + "Write(C:\\Windows\\**)", "Edit(/etc/**)", "Edit(/System/**)", - "Edit(C:/Windows/**)" + "Edit(C:/Windows/**)", + "Edit(C:\\Windows\\**)" ] } } diff --git a/memory/org/feedback_permissions_portability.md b/memory/org/feedback_permissions_portability.md index abc7543..9bec899 100644 --- a/memory/org/feedback_permissions_portability.md +++ b/memory/org/feedback_permissions_portability.md @@ -19,6 +19,18 @@ Claude Code의 승인 체계는 **2계층**으로 분리되어 있다: **결론**: 조직 공용 permission은 반드시 `.claude/settings.json`(프로젝트 루트)에 선언·커밋해야 PC 독립성이 보장된다. +## 자식 디렉토리 전파 원칙 (너드나비스 구조 특수사항) + +Claude Code는 `.claude/` 폴더 1개만 프로젝트 루트로 인식하며 **부모 방향 auto-merge를 지원하지 않는다**. 너드나비스 조직 레포는 루트 외에 `개발실/.claude/`·`기획실/.claude/`가 이미 존재(agents·commands·skill-modules 용). 이 때문에 자식 디렉토리에서 세션을 시작하면 루트의 settings.json이 무시된다. + +**해결 구조**: +- **SOT**: `.claude/settings.json` (루트). 모든 변경은 이 파일을 먼저 편집. +- **파생**: `개발실/.claude/settings.json`·`기획실/.claude/settings.json` — 루트 SOT의 복사본. +- **동기화**: `setup/setup_windows.ps1`이 루트 SOT → 두 부서로 자동 복제. 셋업 스크립트 실행 시마다 갱신. +- **수동 동기화 (스크립트 미실행 환경)**: 루트 settings.json 수정 후 두 부서 파일에도 동일 내용 반영 후 일괄 커밋. + +**검증법**: 각 부서 디렉토리에서 `.claude/settings.json` 존재 여부 확인. 파일이 같은 내용인지 diff로 점검. + ## 권장 구성 ```json diff --git a/setup/setup_windows.ps1 b/setup/setup_windows.ps1 index eb8fd5d..0ece6c8 100644 --- a/setup/setup_windows.ps1 +++ b/setup/setup_windows.ps1 @@ -98,4 +98,24 @@ if ($hashDirs.Count -eq 0) { Write-Warning "Claude 프로젝트 해시 폴더를 찾지 못했습니다. 수동 연결 필요." } +# 4. .claude/settings.json 부서 동기화 (루트 SOT → 개발실/기획실 복제) +# Claude Code는 .claude/ 계층 auto-merge를 지원하지 않으므로 자식 디렉토리에서 세션 시작 시 +# 루트 settings.json을 인식하지 못함. 이를 우회하기 위해 루트 settings.json을 부서 디렉토리로 복제. +$rootSettings = Join-Path $NerdNavisRoot ".claude\settings.json" +if (Test-Path $rootSettings) { + $deptPaths = @("개발실", "기획실") + foreach ($dept in $deptPaths) { + $deptClaudeDir = Join-Path $NerdNavisRoot "$dept\.claude" + $deptSettings = Join-Path $deptClaudeDir "settings.json" + if (-not (Test-Path $deptClaudeDir)) { + New-Item -ItemType Directory -Path $deptClaudeDir -Force | Out-Null + } + Copy-Item -Path $rootSettings -Destination $deptSettings -Force + Write-Host "settings.json 동기화: $dept/.claude/settings.json" + } +} else { + Write-Warning "루트 .claude/settings.json 미발견. 부서 동기화 생략." +} + Write-Host "셋업 완료. 'git pull'로 최신 상태 유지 권장." +Write-Host "※ .claude/settings.json 변경사항은 세션 재시작 후 적용됨." diff --git a/개발실/.claude/settings.json b/개발실/.claude/settings.json new file mode 100644 index 0000000..17c104d --- /dev/null +++ b/개발실/.claude/settings.json @@ -0,0 +1,75 @@ +{ + "_description": "너드나비스 조직 공용 Claude Code permission 설정 (SOT). PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개발실/·기획실/에도 동일 사본이 배치되어야 자식 디렉토리에서 세션을 시작해도 동일 권한이 적용됨 (Claude Code는 .claude/ 계층 auto-merge 미지원). 동기화는 setup_windows.ps1이 수행.", + "permissions": { + "allow": [ + "Read", + "Glob", + "Grep", + "TodoWrite", + "Edit", + "Write", + "MultiEdit", + "NotebookEdit", + "Bash(git:*)", + "Bash(gh:*)", + "Bash(ls:*)", + "Bash(cat:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(grep:*)", + "Bash(rg:*)", + "Bash(find:*)", + "Bash(echo:*)", + "Bash(pwd)", + "Bash(cd:*)", + "Bash(mkdir:*)", + "Bash(touch:*)", + "Bash(cp:*)", + "Bash(mv:*)", + "Bash(diff:*)", + "Bash(wc:*)", + "Bash(sort:*)", + "Bash(uniq:*)", + "Bash(tr:*)", + "Bash(sed:*)", + "Bash(awk:*)", + "Bash(xxd:*)", + "Bash(printf:*)", + "Bash(true)", + "Bash(false)", + "Bash(powershell.exe:*)", + "Bash(powershell:*)", + "Bash(fsutil:*)", + "Bash(cmd:*)", + "Bash(npm:*)", + "Bash(npx:*)", + "Bash(node:*)", + "Bash(python:*)", + "Bash(python3:*)", + "Bash(pytest:*)", + "Bash(dotnet:*)", + "WebFetch", + "WebSearch" + ], + "deny": [ + "Bash(rm:*)", + "Bash(rmdir:*)", + "Bash(sudo:*)", + "Bash(dd:*)", + "Bash(mkfs:*)", + "Bash(format:*)", + "Bash(chmod 777:*)", + "Bash(chown:*)", + "Bash(shutdown:*)", + "Bash(reboot:*)", + "Write(/etc/**)", + "Write(/System/**)", + "Write(C:/Windows/**)", + "Write(C:\\Windows\\**)", + "Edit(/etc/**)", + "Edit(/System/**)", + "Edit(C:/Windows/**)", + "Edit(C:\\Windows\\**)" + ] + } +} diff --git a/기획실/.claude/settings.json b/기획실/.claude/settings.json new file mode 100644 index 0000000..17c104d --- /dev/null +++ b/기획실/.claude/settings.json @@ -0,0 +1,75 @@ +{ + "_description": "너드나비스 조직 공용 Claude Code permission 설정 (SOT). PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개발실/·기획실/에도 동일 사본이 배치되어야 자식 디렉토리에서 세션을 시작해도 동일 권한이 적용됨 (Claude Code는 .claude/ 계층 auto-merge 미지원). 동기화는 setup_windows.ps1이 수행.", + "permissions": { + "allow": [ + "Read", + "Glob", + "Grep", + "TodoWrite", + "Edit", + "Write", + "MultiEdit", + "NotebookEdit", + "Bash(git:*)", + "Bash(gh:*)", + "Bash(ls:*)", + "Bash(cat:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(grep:*)", + "Bash(rg:*)", + "Bash(find:*)", + "Bash(echo:*)", + "Bash(pwd)", + "Bash(cd:*)", + "Bash(mkdir:*)", + "Bash(touch:*)", + "Bash(cp:*)", + "Bash(mv:*)", + "Bash(diff:*)", + "Bash(wc:*)", + "Bash(sort:*)", + "Bash(uniq:*)", + "Bash(tr:*)", + "Bash(sed:*)", + "Bash(awk:*)", + "Bash(xxd:*)", + "Bash(printf:*)", + "Bash(true)", + "Bash(false)", + "Bash(powershell.exe:*)", + "Bash(powershell:*)", + "Bash(fsutil:*)", + "Bash(cmd:*)", + "Bash(npm:*)", + "Bash(npx:*)", + "Bash(node:*)", + "Bash(python:*)", + "Bash(python3:*)", + "Bash(pytest:*)", + "Bash(dotnet:*)", + "WebFetch", + "WebSearch" + ], + "deny": [ + "Bash(rm:*)", + "Bash(rmdir:*)", + "Bash(sudo:*)", + "Bash(dd:*)", + "Bash(mkfs:*)", + "Bash(format:*)", + "Bash(chmod 777:*)", + "Bash(chown:*)", + "Bash(shutdown:*)", + "Bash(reboot:*)", + "Write(/etc/**)", + "Write(/System/**)", + "Write(C:/Windows/**)", + "Write(C:\\Windows\\**)", + "Edit(/etc/**)", + "Edit(/System/**)", + "Edit(C:/Windows/**)", + "Edit(C:\\Windows\\**)" + ] + } +}