---
phase: implementation
agent: implementation-advisor
agent_version: 1
generated_at: 2026-06-23T00:00:00Z
workstream: W1-거버넌스/RBAC
concerns: []
concerns_checked: true
workers_spawned: 22
planned_workers: 24
actual_workers: 22
self_verification:
  checklist_passed: true
  unused_diagnostics: 0
  full_test: "BUILD SUCCESS — 65 tests, 0 failures, 0 errors, 0 skipped"
---

# W1 구현 로그 — 거버넌스/RBAC

## 구현 순서 (설계 의존 준수)
U-SCHEMA → U-DOMAIN → U-GATE(+verifier) → {U-CONSOLE, U-ABSORB, U-SESSION} → 테스트.
의존 있는 파일(PermissionGate 소비 컨트롤러/테스트)은 선행 완료 후 spawn(병렬 충돌 0).

## worker 분할 (1파일 1worker, 소유권 겹침 0)
| worker | 파일 | 유형 | 결과 |
|---|---|---|---|
| w-001 migration-writer | docs/rbac-ddl.sql, db/bootstrap-admin.sql, db/schema.sql | create×2/modify | OK (멱등 DDL, 글롭 분리 검증) |
| w-002 | security/PermissionKeys.java | create | OK (3멤버+isValid) |
| w-003 | security/Roles.java | create | OK |
| w-004 | data/PermissionData.java | create | OK |
| w-005 | data/OperatorView.java | create | OK |
| w-006 | mapper/PermissionsMapper.java | create | OK (alias 큰따옴표, ON CONFLICT) |
| w-007 | mapper/UserPermissionsMapper.java | create | OK (#{} only) |
| w-008 | mapper/RbacAuditMapper.java | create | OK |
| w-009 | mapper/UsersMapper.java | modify | OK (epoch/role/listOperators, alias 큰따옴표) |
| w-010 | config/PermissionCatalogVerifier.java | create | OK (+advisor null-guard 보강) |
| w-011 | security/PermissionGate.java | create | OK (+advisor isAdmin/isAuthenticated 추가) |
| w-012 | security/RbacInterceptor.java | create | OK (401/403/redirect 분기) |
| w-013 | config/InterceptorConfig.java | create | OK (/admin/**) |
| w-014 | controller/AdminConsoleController.java | create | OK (5엔드포인트, CSRF×3, bump×3, audit 4종) |
| w-015 | webapp/.../admin-console.jsp | create | OK (scriptlet+HtmlUtils escape, CSRF) |
| w-016 | controller/api/GameCommentController.java | modify | OK (흡수, isOperator/ROLE_ADMIN/sessionRole 삭제) |
| w-017 | controller/api/GameReviewController.java | modify | OK (흡수, 동일) |
| w-018 | controller/api/UserController.java | modify | OK (세션 권한 스냅샷, 생성자 +UserPermissionsMapper) |
| w-019 | data/UserData.java | modify | OK (permissionsEpoch) |
| w-020 | test/BibimbapApplicationTests.java | modify | OK (@MockBean ×4 추가) |
| w-021 | test/AdminConsoleControllerTest.java | create | OK (13 케이스) |
| w-022 | test/security/PermissionGateTest.java | create | OK (7 케이스, AC-2 회수) |
| w-023 | test/GameCommentControllerTest.java | modify | OK (게이트 mock + SUBADMIN 신규) |
| w-024 | test/GameReviewControllerTest.java | modify | OK (동일) |

## advisor 직접 처리 (worker 미spawn — planned 24 vs actual 22)
1. **PermissionGate.isAdmin/isAuthenticated 추가** (w-011 산출 후 advisor Edit): 인터셉터가 ADMIN-only 게이트를 epoch 모델로 단일 소스화하려면 게이트에 메서드가 필요. 단일 파일·소수 라인 편집이라 신규 worker spawn 불필요(계량: 1파일 <20줄).
2. **PermissionCatalogVerifier null-guard** (advisor Edit): mock listActiveKeys() null 반환 시 contextLoads NPE 방지. 1파일 3줄.
3. **UserControllerCsrfTest 생성자 인자 보정** (advisor Edit): 영향 맵 밖 발견 파일(discovered dependency). UserController 생성자 변경(+UserPermissionsMapper)으로 기존 테스트 `new UserController(2-arg)` 컴파일 깨짐 → 3-arg + @Mock 추가. 2파일 위치 <4줄 기계적 수정 → advisor 직접(계량: <500줄, 파일<8).

## Bash 단계 (advisor 직접)
- `./mvnw -o compile` (중간 검증, U-DOMAIN+gate 후) → EXIT 0.
- `./mvnw -o test` (full) → **BUILD SUCCESS, 65 tests, 0 fail/error/skip**.
  - PermissionGateTest 7, AdminConsoleControllerTest 13, GameCommentControllerTest 18, GameReviewControllerTest 21, UserControllerCsrfTest 5, BibimbapApplicationTests(contextLoads) 1.
- 빌드 경고: `@MockBean` deprecation(Spring Boot 3.4+)만 — 기존 8필드에도 이미 존재하는 프로젝트 관례. unused/dead 경고 0.
- 환경: JAVA_HOME=/opt/homebrew/opt/openjdk@21 (셸 PATH 미설정 → export 로 해결).

## 설계 concerns 처리 결과 (구현 점검 항목)
1. **시그니처 inflate(concern 1)**: PermissionGate `has`/`canModerate` 의 `request` 파라미터 **제거 확정**. 게이트는 boolean 만 반환, 거부응답은 호출자(인터셉터/컨트롤러)가 작성. 흡수 호출지점 `permissionGate.canModerate(session)` (request 없음). `HttpServletRequest` import 0 (grep 확인). dead parameter 0.
2. **@MockBean / full-test(concern 2)**: BibimbapApplicationTests 에 PermissionsMapper/UserPermissionsMapper/RbacAuditMapper/PermissionGate @MockBean 4개 등록. full `./mvnw -o test` 실행 — contextLoads NoSuchBeanDefinitionException 없음(verifier null-guard 로 ApplicationRunner NPE 도 방지).
3. **DB-방언 L2(concern 3)**: 신규 매퍼 camelCase alias 전부 큰따옴표(`AS "permissionKey"` 등). `${}` 0건(PermissionsMapper/UserPermissionsMapper/RbacAuditMapper/UsersMapper 신규분 grep). dev DB contract 실행 검증은 verification-advisor + DDL 적용 후 가능(기존 open item).
4. **users 스키마 권위 수준(concern 4)**: DDL 멱등(IF NOT EXISTS / DO $$ guard). docs/rbac-ddl.sql 권위, db/schema.sql 사본 반영. bootstrap seed 는 글롭 밖(db/bootstrap-admin.sql) 수동 전용.

## 정적 AC 게이트 (구현 시점 self-check — 최종 판정은 verification)
- AC-T1: PermissionKeys 멤버 3 (grep -c = 3).
- AC-T2: AdminConsoleController CsrfTokens.isValid = 3 (appoint/toggle/demote).
- AC-T4: bumpPermissionsEpoch = 3 (동일 핸들러).
- AC-T3/AC-8: audit action 리터럴 APPOINT/DEMOTE/GRANT/REVOKE 4종 전수.
- AC-T5/AC-9: 신규 매퍼 4파일 `${` = 0.

## DDL 적용 대기 (orchestrator 게이트 필요)
- `db/apply-local-ddl.sh` **미실행**(금지 준수). docs/rbac-ddl.sql 작성까지만.
- orchestrator 가 게이트 후: `db/apply-local-ddl.sh docs/rbac-ddl.sql` (자동 글롭) + 최초 ADMIN 은 `psql -v admin_email=... -f db/bootstrap-admin.sql` 수동.

## 미해결 이슈
없음. 컴파일·full test 통과. DDL 실DB 적용/방언 L2 실행 검증은 orchestrator 게이트 + verification-advisor 영역.
