From 0d99314574d4e4f72aaab3eba3d6efe45db81076 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:17:27 +0000 Subject: [PATCH 01/14] forge: open work branch for runtime-role-matrix-live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f --- ...live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .forge/runtime-role-matrix-live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f.md diff --git a/.forge/runtime-role-matrix-live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f.md b/.forge/runtime-role-matrix-live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f.md new file mode 100644 index 0000000..87ab15b --- /dev/null +++ b/.forge/runtime-role-matrix-live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f.md @@ -0,0 +1,3 @@ +# runtime-role-matrix-live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f + +Forge 이슈 작업 브랜치 `forge/runtime-role-matrix-live-20260714101723-v7-pm-001-attempt-1-run-507b47dae85f`. From 3c1983a8d022d7f3418273db73c9f40e2c63eb50 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:17:34 +0000 Subject: [PATCH 02/14] =?UTF-8?q?PM=20=EC=97=AD=ED=95=A0=20=EC=9D=B8?= =?UTF-8?q?=EC=88=98=EC=9D=B8=EA=B3=84=20=EB=AC=B8=EC=84=9C=20smoke=20(run?= =?UTF-8?q?time-role-matrix-live-20260714101723-v7-pm-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- role-pm/HANDOVER.md | 69 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 role-pm/HANDOVER.md diff --git a/role-pm/HANDOVER.md b/role-pm/HANDOVER.md new file mode 100644 index 0000000..081bb3e --- /dev/null +++ b/role-pm/HANDOVER.md @@ -0,0 +1,69 @@ +# PM 역할 인수인계 문서 + +**프로젝트**: runtime-role-matrix-live-20260714101723-v7 +**작성일**: 2025-07-14 +**버전**: v7 + +--- + +## 1. 프로젝트 목표 + +| 목표 | 설명 | +|------|------| +| 핵심 | 런타임 역할 매트릭스 라이브 데모 시스템 구축 및 운영 | +| 세부 | 역할 기반 접근 제어(RBAC) 매트릭스를 런타임에 동적 렌더링하는 시스템 | +| 기대산출물 | 설정 파일 기반 역할-권한 매핑, 실시간 UI 갱신, smoke 테스트 통과 | + +--- + +## 2. 완료 기준 + +- [ ] 역할 매트릭스 설정 파일(JSON/YAML) 파싱 정상 동작 +- [ ] 런타임 시 역할-권한 매핑 동적 로딩 +- [ ] UI 컴포넌트에서 매트릭스 렌더링 확인 +- [ ] smoke 테스트 100% 통과 +- [ ] 빌드 산출물 생성 및 배포 가능 상태 + +--- + +## 3. 위험 (Risks) + +| ID | 위험 항목 | 영향 | 완화 방안 | +|----|-----------|------|----------| +| R-01 | 역할 매트릭스 설정 변경 시 런타임 반영 지연 | 중간 | 설정 변경 감시(watch) 모드 구현 | +| R-02 | 권한 검증 로직 누락 가능성 | 높음 | 단위 테스트 커버리지 80% 이상 확보 | +| R-03 | 동시 접근 시 데이터 정합성 | 중간 | 락(lock) 또는 트랜잭션 처리 검토 | +| R-04 | 의존성 버전 충돌 | 낮음 | BOM 기반 명시적 버전 관리 | + +--- + +## 4. 다음 액션 (Next Actions) + +| 순서 | 액션 | 담당 | 기한 | +|------|------|------|------| +| 1 | smoke 테스트 실행 및 결과 공유 | PM | D+1 | +| 2 | 역할 매트릭스 설정 파일 스키마 확정 | PM | D+2 | +| 3 | 런타임 갱신 메커니즘 설계안 검토 | PM | D+3 | +| 4 | 위험 R-02 관련 테스트 커버리지 보고서 확인 | PM | D+5 | +| 5 | 인수인계 완료 보고서 제출 | PM | D+7 | + +--- + +## 5. 주요 의사결정 로그 + +| 일자 | 결정 | 사유 | +|------|------|------| +| 2025-07-14 | BOM 기반 의존성 관리 채택 | 일관된 버전 관리 및 충돌 방지 | +| 2025-07-14 | smoke 테스트 우선 통과 전략 | 빠른 피드백 루프 확보 | + +--- + +## 6. 연락처 및 참고자료 + +- **이전 PM**: role-pm 컨텍스트 참조 +- **문서 위치**: `role-pm/HANDOVER.md` +- **테스트 명령**: `mvn test` (Maven 기준) + +--- + +*본 문서는 프로젝트 인수인계 시 작성되며, 후임 PM이 참조해야 할 핵심 정보를 포함함.* From b6cd452b87447ddb391801609448f93c8e671764 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:18:16 +0000 Subject: [PATCH 03/14] forge: open work branch for runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325 --- ...live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325.md diff --git a/.forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325.md b/.forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325.md new file mode 100644 index 0000000..bdf6d0c --- /dev/null +++ b/.forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325.md @@ -0,0 +1,3 @@ +# runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325 + +Forge 이슈 작업 브랜치 `forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-1-run-140dc870c325`. From 24aa9dd3db8a9b74c901601f60f41433fc2270a4 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:18:28 +0000 Subject: [PATCH 04/14] =?UTF-8?q?TA=20=EC=97=AD=ED=95=A0=20Spring=20?= =?UTF-8?q?=EA=B2=BD=EA=B3=84=20smoke=20(runtime-role-matrix-live-20260714?= =?UTF-8?q?101723-v7-ta-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ADR-001-spring-boundary-architecture.md | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 docs/adr/ADR-001-spring-boundary-architecture.md diff --git a/docs/adr/ADR-001-spring-boundary-architecture.md b/docs/adr/ADR-001-spring-boundary-architecture.md new file mode 100644 index 0000000..59b7cae --- /dev/null +++ b/docs/adr/ADR-001-spring-boundary-architecture.md @@ -0,0 +1,113 @@ +# ADR-001: Spring 경계 아키텍처 정의 + +**날짜**: 2026-07-14 +**상태**: 수락됨 +**결정자**: TA 아키텍트 + +--- + +## Context (배경) + +TA 역할 프로젝트는 역할(Role) 기반 접근 제어 시스템을 구현한다. 다중 계층 구조에서 Controller, Service, Repository 각 계층의 책임 범위, 오류 계약, 트랜잭션 경계를 명확히 정의하지 않으면 다음과 같은 문제가 발생한다. + +- **책임 혼재**: 비즈니스 로직이 Controller에 유출되거나, DB 접근 로직이 Service에 직접 작성 +- **일관성 없는 오류 처리**: 각 계층마다 다른 예외 타입과 HTTP 상태 코드를 반환 +- **트랜잭션 누락/과다**: 읽기 전용 쿼리에 불필요한 트랜잭션이 걸리거나, 다중 쓰기 작업이 원자성 없이 실행 +- **테스트 어려움**: 계층 간 결합으로 인해 단위 테스트가 불가능 + +--- + +## Decision (결정) + +### 1. 계층 책임 경계 + +| 계층 | 책임 | 포함 사항 | 금지 사항 | +|------|------|-----------|-----------| +| **Controller** | HTTP 요청/응답 변환, 입력 검증, 라우팅 | `@RequestMapping`, `@Valid`, `@RequestBody` 파싱, 응답 DTO 변환 | 비즈니스 로직 직접 실행, DB 접근, Service 메서드 직접 호출 없이 로직 처리 | +| **Service** | 비즈니스 로직, 트랜잭션 관리, 도메인 조율 | `@Transactional`, 도메인 객체 조작, 다중 Repository 호출, 정책 enforcement | HTTP 요청/응답 직접 처리, SQL 직접 작성, `@Entity` 직접 매핑 반환 | +| **Repository** | 데이터 접근 추상화, 쿼리 실행 | `JpaRepository` 확장, `@Query`, `EntityManager` 직접 사용, Specification 패턴 | 비즈니스 로직, 트랜잭션 경계 설정, 응답 형식 결정 | + +### 2. 오류 계약 (Error Contract) + +모든 계층에서 발생하는 예외는 **단일 예외 계층 구조**로 변환되어 Controller에서 일관된 HTTP 응답을 생성한다. + +``` +BaseException (추상) +├── BusinessException → HTTP 400 (잘못된 요청) +│ ├── RoleNotFoundException +│ ├── DuplicateRoleException +│ └── InvalidRoleStateException +├── AuthorizationException → HTTP 403 (권한 없음) +└── SystemException → HTTP 500 (서버 오류) + ├── DataAccessException + └── ExternalServiceException +``` + +**오류 응답 형식 (RFC 7807 Problem Details)**: +```json +{ + "type": "https://api.example.com/errors/role-not-found", + "title": "Role Not Found", + "status": 404, + "detail": "Role with id '123' does not exist", + "instance": "/api/v1/roles/123", + "timestamp": "2026-07-14T10:17:23Z" +} +``` + +**계약 규칙**: +- Service 계층은 `BusinessException` 하위 타입만 던진다 +- Repository 계층 예외는 Service 계층에서 `SystemException`으로 래핑한다 +- Controller는 `@ControllerAdvice`에서 전역 예외를 처리한다 +- 예외 메시지는 외부 노출용으로 **사용자 친화적**이어야 한다 + +### 3. 트랜잭션 경계 + +| 시나리오 | 전파 방식 | 격리 수준 | 읽기 전용 | +|----------|-----------|-----------|-----------| +| 단일 조회 (findById) | REQUIRED | DEFAULT | true | +| 목록 조회 (findAll) | REQUIRED | DEFAULT | true | +| 단일 생성 (save) | REQUIRED | DEFAULT | false | +| 벌크 업데이트 (bulk update) | REQUIRED | READ_COMMITTED | false | +| 다중 리포지토리 쓰기 | REQUIRED | READ_COMMITTED | false | +| 읽기 전용 조회 (통계/리포트) | REQUIRED_READ_ONLY | DEFAULT | true | + +**트랜잭션 롤백 규칙**: +- `RuntimeException`, `DataAccessException`은 자동 롤백 +- 검사 예외(`Checked Exception`)는 명시적 `rollbackFor` 지정 필요 +- 읽기 전용 트랜잭션에서 쓰기 시도 시 예외 발생 + +--- + +## Alternatives (대안) + +### 대안 1: Service에서 직접 예외 던지기 (현재 미선택) +- 각 Service 메서드가 다양한 예외 타입을 직접 던짐 +- **단점**: Controller에서 예외 타입별 분기 처리 필요, 일관성 유지 어려움 + +### 대안 2: 트랜잭션 없음 (수동 커밋) +- `TransactionTemplate`을 수동으로 사용 +- **단점**: 코드 복잡성 증가, 실수 가능성 높음 + +### 대안 3: Repository에서 비즈니스 로직 포함 +- **단점**: 데이터 접근과 비즈니스 로직 결합, 테스트 어려움, 재사용성 저하 + +--- + +## Consequences (결과) + +### 긍정적 결과 +- **단위 테스트 용이**: 각 계층이 명확히 분리되어 Mock 기반 테스트 가능 +- **유지보수성**: 오류 처리와 트랜잭션 정책이 한 곳에 집중 +- **일관성**: 모든 API가 동일한 오류 응답 형식 제공 +- **확장성**: 새 예외 타입 추가 시 `BaseException` 하위 클래스만 생성 + +### 부정적 결과 +- **초기 개발 시간**: 예외 계층 구조와 `@ControllerAdvice` 설정 필요 +- **학습 곡선**: 개발자가 계층 책임 경계와 트랜잭션 전파 규칙을 숙지해야 함 +- **오버엔지니어링 위험**: 소규모 프로젝트에서는 과한 추상화 가능성 + +### 모니터링 지표 +- 예외 발생 시 `type` 필드로 문제 유형 추적 +- 트랜잭션 경과 시간 로깅으로 성능 병목 탐지 +- 계층 간 호출 횟수 카운터로 불필요한 조회 감지 From d927492ef42fecdc99792aad2cc437d1a4395fb9 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:18:38 +0000 Subject: [PATCH 05/14] forge: open work branch for runtime-role-matrix-live-20260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa --- ...260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .forge/runtime-role-matrix-live-20260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa.md diff --git a/.forge/runtime-role-matrix-live-20260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa.md b/.forge/runtime-role-matrix-live-20260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa.md new file mode 100644 index 0000000..595ee5a --- /dev/null +++ b/.forge/runtime-role-matrix-live-20260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa.md @@ -0,0 +1,3 @@ +# runtime-role-matrix-live-20260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa + +Forge 이슈 작업 브랜치 `forge/runtime-role-matrix-live-20260714101723-v7-developer-001-attempt-1-run-e27e8d6f28aa`. From bf7772d6dfc0dd23279e8bb89a3068be47dd1a63 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:18:46 +0000 Subject: [PATCH 06/14] =?UTF-8?q?Developer=20=EC=97=AD=ED=95=A0=20Spring?= =?UTF-8?q?=20=EA=B3=A8=EA=B2=A9=20smoke=20(runtime-role-matrix-live-20260?= =?UTF-8?q?714101723-v7-developer-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 pom.xml diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8062b34 --- /dev/null +++ b/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + + + com.example + developer-role-smoke + 1.0.0 + Developer Role Smoke Test + Spring Boot smoke application for Developer role + + 17 + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file From db7ead282ca34383ad82247d4482ed386b8b0eaf Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:18:47 +0000 Subject: [PATCH 07/14] =?UTF-8?q?Developer=20=EC=97=AD=ED=95=A0=20Spring?= =?UTF-8?q?=20=EA=B3=A8=EA=B2=A9=20smoke=20(runtime-role-matrix-live-20260?= =?UTF-8?q?714101723-v7-developer-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/developer/DeveloperApplication.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/com/example/developer/DeveloperApplication.java diff --git a/src/main/java/com/example/developer/DeveloperApplication.java b/src/main/java/com/example/developer/DeveloperApplication.java new file mode 100644 index 0000000..668dc45 --- /dev/null +++ b/src/main/java/com/example/developer/DeveloperApplication.java @@ -0,0 +1,12 @@ +package com.example.developer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DeveloperApplication { + + public static void main(String[] args) { + SpringApplication.run(DeveloperApplication.class, args); + } +} From 3ef86bf9bf0cd580136b1c3b758d1913c43dc335 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:18:48 +0000 Subject: [PATCH 08/14] =?UTF-8?q?Developer=20=EC=97=AD=ED=95=A0=20Spring?= =?UTF-8?q?=20=EA=B3=A8=EA=B2=A9=20smoke=20(runtime-role-matrix-live-20260?= =?UTF-8?q?714101723-v7-developer-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/developer/DeveloperService.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/com/example/developer/DeveloperService.java diff --git a/src/main/java/com/example/developer/DeveloperService.java b/src/main/java/com/example/developer/DeveloperService.java new file mode 100644 index 0000000..c0cb8f3 --- /dev/null +++ b/src/main/java/com/example/developer/DeveloperService.java @@ -0,0 +1,15 @@ +package com.example.developer; + +import org.springframework.stereotype.Service; + +@Service +public class DeveloperService { + + public String getRole() { + return "Developer"; + } + + public boolean isValidRole(String role) { + return "Developer".equals(role); + } +} From bd8b77feacf0418eae291d6a27f7627987481ffa Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:18:49 +0000 Subject: [PATCH 09/14] =?UTF-8?q?Developer=20=EC=97=AD=ED=95=A0=20Spring?= =?UTF-8?q?=20=EA=B3=A8=EA=B2=A9=20smoke=20(runtime-role-matrix-live-20260?= =?UTF-8?q?714101723-v7-developer-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../developer/DeveloperServiceTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/java/com/example/developer/DeveloperServiceTest.java diff --git a/src/test/java/com/example/developer/DeveloperServiceTest.java b/src/test/java/com/example/developer/DeveloperServiceTest.java new file mode 100644 index 0000000..e920527 --- /dev/null +++ b/src/test/java/com/example/developer/DeveloperServiceTest.java @@ -0,0 +1,32 @@ +package com.example.developer; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +class DeveloperServiceTest { + + @Autowired + private DeveloperService developerService; + + @Test + void getRole_returnsDeveloper() { + String role = developerService.getRole(); + assertTrue("Developer".equals(role), "Role should be Developer"); + } + + @Test + void isValidRole_withDeveloper_returnsTrue() { + boolean valid = developerService.isValidRole("Developer"); + assertTrue(valid, "Developer role should be valid"); + } + + @Test + void isValidRole_withOtherRole_returnsFalse() { + boolean valid = developerService.isValidRole("Admin"); + assertTrue(!valid, "Admin role should not be valid for DeveloperService"); + } +} From 89d0288b3dfdba6d40f9e1187e75e509c3b70a5d Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:22:22 +0000 Subject: [PATCH 10/14] forge: open work branch for runtime-role-matrix-live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e --- ...live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .forge/runtime-role-matrix-live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e.md diff --git a/.forge/runtime-role-matrix-live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e.md b/.forge/runtime-role-matrix-live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e.md new file mode 100644 index 0000000..2da0252 --- /dev/null +++ b/.forge/runtime-role-matrix-live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e.md @@ -0,0 +1,3 @@ +# runtime-role-matrix-live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e + +Forge 이슈 작업 브랜치 `forge/runtime-role-matrix-live-20260714101723-v7-aa-001-attempt-2-run-b63a6a7e452e`. From 506761b978c32ddb776281cbf7f049750514bed5 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:22:34 +0000 Subject: [PATCH 11/14] =?UTF-8?q?AA=20=EC=97=AD=ED=95=A0=20=EB=A0=88?= =?UTF-8?q?=EA=B1=B0=EC=8B=9C=20=EB=B6=84=EC=84=9D=20smoke=20(runtime-role?= =?UTF-8?q?-matrix-live-20260714101723-v7-aa-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audit/AA_ROLE_LEGACY_ANALYSIS.md | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 audit/AA_ROLE_LEGACY_ANALYSIS.md diff --git a/audit/AA_ROLE_LEGACY_ANALYSIS.md b/audit/AA_ROLE_LEGACY_ANALYSIS.md new file mode 100644 index 0000000..1bf8714 --- /dev/null +++ b/audit/AA_ROLE_LEGACY_ANALYSIS.md @@ -0,0 +1,57 @@ +# AA 역할 레거시 분석 문서 + +## 개요 +- **역할**: AA +- **분석 일자**: 2026-07-14 +- **버전**: v7 +- **분석 목적**: 레거시 전환 분석을 위한 입력 소스, 업무 규칙, 위험 영역, 증적 위치 정리 + +--- + +## 1. 입력 소스 정의 + +| ID | 소스명 | 설명 | 위치 | +|-----|--------|------|------| +| IS-001 | AA_ROLE_SPEC | AA 역할 정의 명세서 | role-aa/specs/aa_role_spec.yaml | +| IS-002 | PERMISSION_MATRIX | 권한 매트릭스 문서 | role-aa/specs/permission_matrix.json | +| IS-003 | WORKFLOW_DEF | 워크플로우 정의 | role-aa/workflows/aa_workflow.yaml | +| IS-004 | API_CONTRACT | API 계약 정의 | role-aa/contracts/aa_api_contract.yaml | + +--- + +## 2. 업무 규칙 + +| 규칙 ID | 규칙 내용 | 입력 소스 | +|---------|----------|----------| +| BR-001 | AA 역할은 관리자 권한을 포함한다 | IS-001, IS-002 | +| BR-002 | AA 역할은 승인 워크플로우를 통과해야 한다 | IS-003 | +| BR-003 | AA 역할의 API 호출은 인증 토큰을 필요로 한다 | IS-004 | + +--- + +## 3. 위험 영역 + +| 위험 ID | 위험 설명 | 영향도 | 입력 소스 | +|---------|----------|--------|----------| +| RI-001 | 권한 상승 위험 | 높음 | IS-001, IS-002 | +| RI-002 | 워크플로우 우회 위험 | 중간 | IS-003 | +| RI-003 | API 인증 우회 위험 | 높음 | IS-004 | + +--- + +## 4. 증적 위치 + +| 증적 ID | 증적 유형 | 위치 | 검증 방법 | +|---------|----------|------|----------| +| EV-001 | 역할 정의 | IS-001 | 스키마 검증 | +| EV-002 | 권한 매트릭스 | IS-002 | 매트릭스 교차 검증 | +| EV-003 | 워크플로우 로그 | IS-003 | 실행 추적 검증 | +| EV-004 | API 호출 로그 | IS-004 | 요청/응답 검증 | + +--- + +## 5. 감사 추적 요구사항 + +- 모든 입력 소스는 버전 관리되어야 함 +- 변경 이력은 추적 가능해야 함 +- 증적은 보존 기간 동안 유지되어야 함 From 0469100bfe0ad905f52e4eff0f1d88a144bd31e6 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:22:35 +0000 Subject: [PATCH 12/14] =?UTF-8?q?AA=20=EC=97=AD=ED=95=A0=20=EB=A0=88?= =?UTF-8?q?=EA=B1=B0=EC=8B=9C=20=EB=B6=84=EC=84=9D=20smoke=20(runtime-role?= =?UTF-8?q?-matrix-live-20260714101723-v7-aa-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audit/AA_ROLE_EVIDENCE_INVENTORY.json | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 audit/AA_ROLE_EVIDENCE_INVENTORY.json diff --git a/audit/AA_ROLE_EVIDENCE_INVENTORY.json b/audit/AA_ROLE_EVIDENCE_INVENTORY.json new file mode 100644 index 0000000..370db4a --- /dev/null +++ b/audit/AA_ROLE_EVIDENCE_INVENTORY.json @@ -0,0 +1,71 @@ +{ + "inventoryId": "AA_ROLE_EVIDENCE_INVENTORY", + "role": "AA", + "version": "v7", + "generatedDate": "2026-07-14", + "inputSources": [ + { + "sourceId": "IS-001", + "sourceName": "AA_ROLE_SPEC", + "description": "AA 역할 정의 명세서", + "location": "role-aa/specs/aa_role_spec.yaml", + "type": "SPECIFICATION", + "version": "1.0.0" + }, + { + "sourceId": "IS-002", + "sourceName": "PERMISSION_MATRIX", + "description": "권한 매트릭스 문서", + "location": "role-aa/specs/permission_matrix.json", + "type": "MATRIX", + "version": "1.0.0" + }, + { + "sourceId": "IS-003", + "sourceName": "WORKFLOW_DEF", + "description": "워크플로우 정의", + "location": "role-aa/workflows/aa_workflow.yaml", + "type": "WORKFLOW", + "version": "1.0.0" + }, + { + "sourceId": "IS-004", + "sourceName": "API_CONTRACT", + "description": "API 계약 정의", + "location": "role-aa/contracts/aa_api_contract.yaml", + "type": "CONTRACT", + "version": "1.0.0" + } + ], + "evidenceLocations": [ + { + "evidenceId": "EV-001", + "sourceId": "IS-001", + "type": "ROLE_DEFINITION", + "verificationMethod": "스키마 검증" + }, + { + "evidenceId": "EV-002", + "sourceId": "IS-002", + "type": "PERMISSION_MATRIX", + "verificationMethod": "매트릭스 교차 검증" + }, + { + "evidenceId": "EV-003", + "sourceId": "IS-003", + "type": "WORKFLOW_LOG", + "verificationMethod": "실행 추적 검증" + }, + { + "evidenceId": "EV-004", + "sourceId": "IS-004", + "type": "API_CALL_LOG", + "verificationMethod": "요청/응답 검증" + } + ], + "auditRequirements": { + "versionControl": true, + "changeTracking": true, + "retentionPeriod": "7years" + } +} From 5a42946820a492df16b523b4c8938ad5328e63b4 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:24:25 +0000 Subject: [PATCH 13/14] forge: open work branch for runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b --- ...live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b.md diff --git a/.forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b.md b/.forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b.md new file mode 100644 index 0000000..0097467 --- /dev/null +++ b/.forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b.md @@ -0,0 +1,3 @@ +# runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b + +Forge 이슈 작업 브랜치 `forge/runtime-role-matrix-live-20260714101723-v7-ta-001-attempt-2-run-8f9fb566223b`. From 376786dd552a6011339cdd8a4ec9d9e58875496a Mon Sep 17 00:00:00 2001 From: forge-bot Date: Tue, 14 Jul 2026 10:24:36 +0000 Subject: [PATCH 14/14] =?UTF-8?q?TA=20=EC=97=AD=ED=95=A0=20Spring=20?= =?UTF-8?q?=EA=B2=BD=EA=B3=84=20smoke=20(runtime-role-matrix-live-20260714?= =?UTF-8?q?101723-v7-ta-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ADR-001-spring-boundary-architecture.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 docs/adr/ADR-001-spring-boundary-architecture.md diff --git a/docs/adr/ADR-001-spring-boundary-architecture.md b/docs/adr/ADR-001-spring-boundary-architecture.md new file mode 100644 index 0000000..e2b2be5 --- /dev/null +++ b/docs/adr/ADR-001-spring-boundary-architecture.md @@ -0,0 +1,49 @@ +# ADR-001: Spring Layer Boundary Architecture + +## Context + +TA 역할의 Spring 기반 마이크로서비스는 역할 매트릭스 관리 기능을 제공한다. Controller-Service-Repository 패턴을 적용하되, 각 계층의 책임과 경계를 명확히 정의하여 응집도를 높이고 결합도를 낮추어야 한다. 또한 오류 처리와 트랜잭션 관리의 일관된 전략이 필요하다. + +## Decision + +### 1. Controller-Service-Repository 경계 + +| Layer | Responsibility | Forbidden Dependencies | +|-------|---------------|------------------------| +| Controller | HTTP 요청/응답 변환, 입력 검증, HTTP 상태 코드 관리 | 직접 Repository 접근 금지 | +| Service | 비즈니스 로직, 도메인 규칙, 트랜잭션 경계 | HTTP Servlet API 직접 사용 금지 | +| Repository | 데이터 접근, JPA 쿼리, 엔티티 매핑 | 비즈니스 로직 포함 금지 | + +### 2. 오류 계약 (Error Contract) + +| Scenario | HTTP Status | Response Body | +|----------|-------------|---------------| +| Validation Error | 400 | `{ "code": "VALIDATION_ERROR", "message": "...", "field": "..." }` | +| Resource Not Found | 404 | `{ "code": "NOT_FOUND", "message": "...", "resourceId": "..." }` | +| Business Rule Violation | 409 | `{ "code": "BUSINESS_ERROR", "message": "..." }` | +| Internal Error | 500 | `{ "code": "INTERNAL_ERROR", "message": "..." }` | + +### 3. 트랜잭션 경계 + +- **시작점**: Service Layer (public method 진입점) +- **종료점**: Service Layer (public method 종료점) +- **전파**: `@Transactional(propagation = REQUIRED)` 기본값 사용 +- **읽기 전용**: 조회 전용 Service Method에 `@Transactional(readOnly = true)` 적용 + +## Alternatives + +1. **TransactionTemplate 사용**: 프로그래밍 방식 트랜잭션 관리로 더 세밀한 제어 가능하나, 선언적 방식 대비 복잡성 증가 +2. **Controller에서 트랜잭션 관리**: 테스트 용이성 감소, 단일 책임 원칙 위반 +3. **Repository에서 비즈니스 로직 포함**: 데이터 접근 계층의 재사용성 저하 + +## Consequences + +### Positive +- 계층별 단일 책임 원칙 준수 +- 일관된 오류 처리로 API consumers 보호 +- 트랜잭션 경계 명확화로 데이터 무결성 보장 +- 테스트 용이성 향상 (Mock 주입 용이) + +### Negative +- 간단한 CRUD 연산에도 Service Layer 필요로 인한 코드 증가 +- 트랜잭션 경계 설정 오류 시 롤백 누락 위험