fix: 하네스 제거 및 keycloak 문서 보강

This commit is contained in:
DongHyeonka
2026-07-25 12:53:13 +09:00
parent 6c53ded9cb
commit d71669eb59
2329 changed files with 138239 additions and 172816 deletions
-1
View File
@@ -1 +0,0 @@
../../vault/50-journal/daily-notes/2026-05-27.md
+142
View File
@@ -0,0 +1,142 @@
---
title: 2026-05-27 일일 노트
source_type: daily-note
status: raw
tags: [daily, ca-tmpl, ca-skeleton, clean-architecture]
date: 2026-05-27
branches: [
feature-skeleton-package-blueprint-contract
]
---
# 2026-05-27
> Layer: `raw/daily-notes/` — 그날의 혼합 일일 기록. 그 자체는 wiki로 옮기지 않으며, `/ingest`가 promotable 항목만 추출.
## 활성 브랜치
ca-tmpl Phase C2 실 코드 진입을 위한 첫 착수 브랜치. 오늘은 전체 roadmap 구현이 아니라, 첫 브랜치 범위를 확정하고 시작 조건을 정리한다.
- `feature-skeleton-package-blueprint-contract` (planned) — [[raw/branch-notes/feature-skeleton-package-blueprint-contract]]
## 오늘의 계획
- [ ] [ca-tmpl] Phase C2 전체 구현 순서를 dependency-first roadmap으로 고정한다.
- [ ] [feature-skeleton-package-blueprint-contract] 오늘 실제 착수 범위를 package/module skeleton으로 제한한다.
- [ ] [feature-skeleton-package-blueprint-contract] 완료 조건을 `actually-implemented``locally-verified` 증거로 갱신할 수 있게 정의한다.
## 구현 순서 메모 / Phase C2 roadmap
> 아래 목록은 오늘 하루 작업량이 아니라 Phase C2 전체 roadmap이다. 오늘은 1단계의 첫 브랜치 착수까지만 현실적인 범위로 둔다.
### 0. 전제
- ca-tmpl은 현재 Phase A-E 문서/설계 완료, Phase C2 실 코드 미진입 상태다.
- `wiki/projects/ca-tmpl.md` 기준으로 모든 16개 의사결정 문서는 `documented-only`다.
- 따라서 개발 브랜치는 "기능 추가"가 아니라 `documented-only` 결정을 실제 코드와 테스트 증거로 승급시키는 작업이다.
### 1. Foundation / package skeleton
1. `feature-skeleton-package-blueprint-contract`
2. `feature-architecture-enforcement-rules`
3. `feature-application-port-usecase-contract`
이 단계에서 module/package layout, use case/port 기본 타입, ArchUnit boundary rule을 먼저 만든다. 이후 작업은 이 구조를 기준으로 파일 위치와 의존 방향을 맞춘다.
### 2. API boundary + error envelope
1. `feature-boundary-validation-mapping-contract`
2. `feature-api-contract-baseline`
3. `feature-operational-error-observability-foundation`
Controller DTO validation, request/response mapper, structured success/error envelope, exception ownership을 먼저 고정한다. 이후 persistence/outbound/runtime 오류도 같은 envelope와 category로 흘려보낼 수 있어야 한다.
### 3. Observability baseline
1. `feature-log-management-contract`
2. `feature-distributed-tracing-contract`
3. `feature-metrics-alerting-contract`
4. `feature-operational-runbook-contract`
로그/MDC/trace/metric key는 후속 adapter와 background job에서 공통으로 소비한다. runbook은 stub로 먼저 두고, 실제 장애 재현이 생기면 갱신한다.
### 4. Config + optional adapter switch
1. `feature-env-driven-runtime-configuration`
2. `feature-secrets-config-source-contract`
3. `feature-integration-adapter-templates`
4. `feature-outbound-http-client-baseline`
환경 변수와 secret 분류, adapter on/off 조건, outbound timeout/retry 기본값을 묶는다. 이 단계가 끝나야 DB/cache/message adapter를 같은 방식으로 붙일 수 있다.
### 5. Data consistency + sample domain fixture
1. `feature-persistence-failure-baseline`
2. `feature-transaction-concurrency-contract`
3. `feature-cache-consistency-contract`
4. `feature-domain-event-outbox-contract`
5. `feature-sample-domain-contract-fixture`
sample-ticket fixture를 사용해 persistence failure, transaction boundary, cache degradation, outbox publish 흐름을 검증한다. 이때 sample은 비즈니스 기능이 아니라 contract 검증 fixture로만 둔다.
### 6. Security + tenant + idempotency
1. `feature-security-operational-baseline`
2. `feature-management-actuator-security-contract`
3. `feature-tenant-context-policy`
4. `feature-repository-access-permission-contract`
5. `feature-rate-limit-idempotency-contract`
인증/인가/actuator 분리, tenant context propagation, repository access capability, idempotency key 저장소를 묶어 검증한다.
### 7. Runtime + lifecycle + migration
1. `feature-runtime-health-lifecycle-contract`
2. `feature-migration-startup-contract`
3. `feature-container-runtime-contract`
4. `feature-background-job-async-contract`
health endpoint, readiness/startup, migration ordering, container shutdown, async context propagation을 검증한다. 로컬 docker-compose에서 재현 가능한 확인 절차를 남긴다.
### 8. Governance + CI quality gate
1. `feature-contract-registry-governance`
2. `feature-contract-verification-test-suite`
3. `feature-ci-quality-gates-contract`
4. `feature-build-release-supply-chain-contract`
5. `feature-developer-experience-contract`
6. `feature-implementation-readiness-scorecard`
registry yaml 기반 generated constants, contract test suite, CI gate, supply chain metadata, README/onboarding, readiness scorecard를 마지막에 묶는다. 앞 단계의 산출물이 있어야 gate가 실제로 검증할 대상이 생긴다.
## 한 일
- [ca-tmpl] branch-note 기반 Phase C2 구현 순서 초안을 daily-note에 기록했다.
- [ca-tmpl] 오늘 하루 범위와 Phase C2 전체 roadmap을 분리했다.
## 배운 점
> wiki/concepts/로 promotable 후보
- ca-tmpl의 다음 단계는 새 설계가 아니라 `documented-only` 결정을 코드와 로컬 검증 증거로 승급시키는 단계다.
- 구현 순서는 domain feature가 아니라 contract dependency 순서로 잡아야 한다.
## 트러블슈팅
- 없음. 오늘 기록은 개발 진입 순서 정리이며 코드 실행은 아직 하지 않음.
## 면접·포트폴리오로 옮길 만한 것
> 후보 표기만. daily-note에서 `wiki/interview/` 또는 `wiki/portfolio/`를 직접 만들지 않는다.
- "documented-only 설계를 actually-implemented로 승급시키는 절차" → `wiki/projects/ca-tmpl.md` 갱신 후 파생 가능.
- "Clean Architecture skeleton에서 구현 순서를 contract dependency 기준으로 잡은 이유" → Phase C2 로컬 검증 후 portfolio 후보.
## 내일로 넘긴 것
- [ca-tmpl] `/home/donghyeon/workspace/ca-tmpl/`에서 `feature-skeleton-package-blueprint-contract` 구현 시작.
- [ca-tmpl] 첫 구현 브랜치 완료 후 `wiki/projects/ca-tmpl/clean-architecture-package-layout.md`의 evidence section 갱신.
## 잡담 / 회의 / 기타
- 사용자가 "시간이 너무 지나서 개발 단계로 들어가야 한다"고 판단. 오늘 기록은 그 전환점을 남기는 목적이다.
-1
View File
@@ -1 +0,0 @@
../../vault/50-journal/daily-notes/2026-05-28.md
+65
View File
@@ -0,0 +1,65 @@
---
title: 2026-05-28 일일 노트
source_type: daily-note
status: raw
tags: [daily, ca-tmpl, ca-skeleton, clean-architecture, archunit]
date: 2026-05-28
branches: [
feature-architecture-enforcement-rules
]
---
# 2026-05-28
> Layer: `raw/daily-notes/` — 그날의 **혼합 일일 기록**. 그 자체는 wiki로 옮기지 않으며, `/ingest`가 promotable 항목만 추출해 다른 wiki 영역으로 보낸다. 원본은 raw에 영구 보관.
## 활성 브랜치
`feature-skeleton-package-blueprint-contract` 다음으로 이어서 개발할 브랜치는 `feature-architecture-enforcement-rules`다. 오늘은 Phase C2 전체 roadmap을 처리하지 않고, 방금 구현된 multi-module skeleton의 경계가 깨지지 않도록 architecture enforcement를 실제 코드와 테스트로 붙이는 데 집중한다.
- `feature-architecture-enforcement-rules` (local-verified, not merged) — [[raw/branch-notes/feature-architecture-enforcement-rules]]
## 오늘의 계획
브랜치별 항목은 `[branch-name]` 프리픽스. 오늘 개발 범위는 아래 3개로 제한한다.
- [x] [feature-architecture-enforcement-rules] ca-tmpl repo의 현재 module dependency graph를 확인하고, 허용/금지 dependency matrix를 `domain-core`, `application-core`, `adapter-*`, `app-bootstrap`, `shared-contract`, `sample-ticket` 기준으로 확정한다.
- [x] [feature-architecture-enforcement-rules] Gradle dependency guardrail을 구현해서 `domain-core -> Spring/adapter`, `application-core -> adapter-*`, production module -> `sample-ticket` 의존을 차단한다.
- [x] [feature-architecture-enforcement-rules] ArchUnit test를 추가해서 forbidden import/annotation 규칙을 검증하고, 최소한 architecture test와 관련 Gradle verification task를 로컬에서 실행한다.
## 한 일
- ca-tmpl `src/build.gradle``verifyCleanArchitectureDependencies`를 보강해 declared module coverage와 forbidden project dependency 메시지를 강화했다.
- ca-tmpl `CleanArchitectureTest`에 application `@Transactional` 금지, controller direct domain response 금지, mapper boundary, shared-contract package allowlist 규칙을 추가했다.
- 임시 위반 코드로 신규 ArchUnit 규칙 실패를 확인한 뒤 제거했다.
- 임시 `app-bootstrap -> sample-ticket` 의존으로 Gradle dependency verifier 실패를 확인한 뒤 제거했다.
- `cd src && ./gradlew :app-bootstrap:test verifyCleanArchitectureDependencies`, `cd src && ./gradlew test`를 실행해 로컬 검증을 마쳤다.
## 배운 점
> wiki/concepts/로 promotable 후보
- multi-module Clean Architecture에서는 package 위치보다 module dependency direction이 1차 경계다.
- `sample-ticket`은 template fixture/reference module로 유지하되, production module이 sample에 의존하지 못하도록 enforcement rule이 필요하다.
## 트러블슈팅
> raw/errors/ 또는 wiki/projects/ 또는 관련 branch-note의 "마주친 문제" 섹션으로 promotable 후보
- Gradle wrapper가 `~/.gradle` lock 파일을 쓰려 하면서 sandbox 기본 실행에서는 `Read-only file system` 오류가 났다. 검증 명령은 승인된 escalated 실행으로 재수행했다. 상세: [[raw/errors/gradle-wrapper-readonly-cache-2026-05-28]]
- repo 내부 `docs/superpowers/plans/2026-05-28-architecture-enforcement-rules.md``.gitignore``/docs` 규칙 때문에 git 변경 목록에 잡히지 않는다. 최종 wiki 기록은 [[raw/branch-notes/feature-architecture-enforcement-rules]]에 반영했다.
## 면접·포트폴리오로 옮길 만한 것
> 후보 표기만. daily-note에서 `wiki/interview/` 또는 `wiki/portfolio/`를 직접 만들지 않는다.
- Clean Architecture skeleton에서 module boundary를 문서가 아니라 Gradle/ArchUnit rule로 강제한 이유. 글감 raw note: [[raw/blog-topics/clean-architecture-boundary-enforcement-2026-05-28]]. 예상 질문 raw note: [[raw/interviews/clean-architecture-boundary-enforcement]]. 실제 로컬 검증 후 `wiki/projects/ca-tmpl/clean-architecture-package-layout` 또는 별도 architecture enforcement canonical 문서로 승급 후보.
## 내일로 넘긴 것
- [feature-application-port-usecase-contract] architecture enforcement가 통과한 뒤 `application/port/in`, `application/port/out`, transaction runner, repository port 위치를 정리한다.
- [feature-sample-removal-adoption-contract] architecture enforcement에 production module -> `sample-ticket` 금지 rule이 반영된 뒤 sample-off runtime isolation 구현 범위를 구체화한다.
## 잡담 / 회의 / 기타
- 오늘 daily-note는 `feature-skeleton-package-blueprint-contract` 다음 개발 착수 범위를 제한하기 위한 계획이다.
-1
View File
@@ -1 +0,0 @@
../../vault/50-journal/daily-notes/2026-06-14.md
+55
View File
@@ -0,0 +1,55 @@
---
title: 2026-06-14 일일 노트
source_type: daily-note
status: raw
tags: [daily, ca-tmpl, ca-skeleton, clean-architecture, logging, observability]
date: 2026-06-14
branches: [
feature-log-management-contract
]
---
# 2026-06-14
> Layer: `raw/daily-notes/` — 그날의 혼합 일일 기록. 그 자체는 wiki로 옮기지 않으며, `/ingest`가 promotable 항목만 추출.
## 활성 브랜치
- `feature-log-management-contract` (implemented) — [[raw/branch-notes/feature-log-management-contract]]
## 한 일
feature-log-management-contract Phase C2 전면 구현 — 문서화돼 있던 DRIFT-1~6 + sampling 전부 코드로 해소.
- 사용자 결정 2건 확정: **Q1**=dependency 실패 레벨 어댑터종류 분리(optional fail-open WARN / core HTTP ERROR), **Q2**=full HMAC pseudonymization.
- DRIFT-2 Layer 1 masking: `LogMaskingPatterns`(정규식 SSOT) → `SecretMaskingJsonGeneratorDecorator`(JSON) + `SecretMaskingMessageConverter`(`%maskedMsg`).
- DRIFT-1/D10: `logback-spring.xml` `<springProfile>` 분기(local/dev pattern vs prod JSON).
- DRIFT-3: `RequestLoggingFilter` uri_template.
- DRIFT-4: `OutboundDependencyLogger` snake_case + dependency_type + WARN + 5 callers.
- DRIFT-5: `MetricsAsyncAppender``log.appender.dropped.total`.
- DRIFT-6: `UserPrincipalPseudonymizer`(port) + `HmacUserPrincipalPseudonymizer`(adapter-identifier) + `PseudonymizationConfig`/`PrivacySettings`(app-bootstrap) + filter 배선.
- sampling: `SamplingTurboFilter`.
- 오케스트레이션: Task 1~4 는 `ca-implementer` 디스패치, Task 5(logback XML/custom appender/turbofilter/masking)는 API 검증(MaskingJsonGeneratorDecorator, AsyncAppenderBase, springProfile) 후 메인 에이전트 직접 구현. 리뷰 체인 3단계 ALL PASS.
## 배운 점
- `LogstashEncoder`(JSON)는 PatternLayout 을 우회 → `%replace` 마스킹 무력. JSON 은 `MaskingJsonGeneratorDecorator` 필요. → [[raw/blog-topics/logback-layer1-secret-masking-json-vs-pattern-2026-06-14]]
- `AsyncAppender` 드롭 결정론 테스트: `discardingThreshold > queueSize` 트릭. → [[raw/interviews/deterministic-logback-asyncappender-drop-metric-test-2026-06-14]]
## 트러블슈팅
- `@Component` 필터에 생성자 의존성 추가 → `@WebMvcTest` 슬라이스(`OperationalContractRuntimeTest`) 컨텍스트 로드 실패. `@Import(PseudonymizationConfig.class)` 로 해소. → [[raw/errors/webmvctest-component-filter-constructor-dep-breaks-slice-2026-06-14]]
- `ca-implementer` Task 4 디스패치가 중간 truncate(5 callers 중 2개만 수정) → 메인 에이전트가 잔여 3 callers + 4 test 단언을 직접 마무리.
- local profile 실행 시 logback status 경고 3종 발견. (1)`<conversionRule converterClass=...>` deprecated → `class` 로 교체(내 변경, 수정 완료 + `SecretMaskingMessageConverterTest``class` 등록 + 마스킹 검증). (2)`<if>`-in-`<root>` + (3)`<if condition=...>` 속성 deprecated **해소(2026-06-14, 사용자 재요청)**: Janino `<if condition='property(K).equals(V)'>` 6곳 → logback 1.5.20+ 내장 `<condition class="ch.qos.logback.core.boolex.PropertyEqualityCondition"><key>K</key><value>V</value>` (조회 경로 `OptionHelper.propertyLookup(local,context)` 가 Janino 와 동일 → `<springProperty scope=context>` 값 그대로 읽어 동작 무변경). `<root>``<if>` 3개는 logback 권고대로 `<root>` 를 top-level `<condition>+<if>` 로 감싸 un-nest(ASYNC×FILE 2×2, 한 번에 하나만 활성). **janino 의존성(build.gradle) 제거** — dead dep(소스 `condition=` 0건) + Janino 동적 코드 컴파일 보안취약(2027 제거예정) 해소. 검증: logback-core 1.5.34(`dependencyInsight`) + `bootRun`(local) `|-WARN/|-ERROR` 0건 + 정상 기동(Tomcat:8080) + local PatternLayout 분기 정상. **owner 정정**: 토글 구조는 base-template 커밋 f9ad280("ca 구조 변경") 유래, 파일 owner 는 [[raw/branch-notes/feature-log-management-contract]] (D4 logging 바인딩, 최신 touch d10a751) — 직전 `migration-startup-contract D8` 귀속은 conflation(D8 은 build.gradle 인접 `logstash-logback-encoder` 줄을 govern). 기록: owner § Audit & Findings DRIFT-7. local=human-readable PatternLayout 분기(D10)는 의도대로 동작.
## 면접·포트폴리오로 옮길 만한 것
- [[raw/interviews/deterministic-logback-asyncappender-drop-metric-test-2026-06-14]]
- [[raw/blog-topics/logback-layer1-secret-masking-json-vs-pattern-2026-06-14]]
## 내일로 넘긴 것
- D9 전용 audit appender(생산자 부재 + retention은 data-retention 소유 → 보류).
- ~~pre-existing ArchUnit 실패(`OutboundHttpSettings` B7 false-positive, commit d702572)~~ **해결(사용자 요청)**: `CleanArchitectureTest` B7 규칙 `outbound_adapter_method_returns_only_domain_or_primitives``@ConfigurationProperties` 제외 추가(기존 `@Configuration` 제외와 동일 패턴). 세팅 홀더는 외부 응답 매핑 surface 가 아니라 config 바인딩 타입 → ACL 누출 대상 아님. 규칙의 실제 보호(외부 응답 타입 누출 차단)는 그대로 — 순수 filter narrowing. `:app-bootstrap:test` 0 실패.
- ~~logback `<if>`-in-`<root>` / `condition` 속성 deprecation 정리(사용자 재요청)~~ **해결(2026-06-14)**: 트러블슈팅 §(2)/(3) — Janino→내장 `PropertyEqualityCondition` + `<root>` un-nest + janino dep 제거, `bootRun` 검증 완료.
- 사용자 커밋 대기.
-1
View File
@@ -1 +0,0 @@
../../vault/50-journal/daily-notes/2026-06-30.md
+55
View File
@@ -0,0 +1,55 @@
---
title: 2026-06-30 일일 노트
source_type: daily-note
status: raw
tags: [daily]
date: 2026-06-30
branches: [develop]
---
# 2026-06-30
> Layer: `raw/daily-notes/` — 그날의 **혼합 일일 기록**. 그 자체는 wiki로 옮기지 않으며, `/ingest`가 promotable 항목만 추출해 다른 wiki 영역으로 보냅니다. 원본은 raw에 영구 보관.
## 활성 브랜치
오늘 작업한 브랜치 목록과 진행 상태. 브랜치 노트로 양방향 링크.
- `develop` (review) — [[raw/branch-notes/feature-developer-experience-contract]]
## 오늘의 계획
- [x] [develop] CleanArchitectureTest.java의 자원 누수 경고 해결
- [x] [develop] README.md에서 누락되었던 feature-developer-experience-contract 식별자 복구로 테스트 통과 확인
- [x] [develop] Spring Boot 3.5.x EOL 경고 무시를 위한 VS Code settings.json 설정 반영
- [x] [develop] Spring Boot 4.x & Testcontainers 2.0 마이그레이션 호환성 평가 및 명세서 작성
## 한 일
- [develop] CleanArchitectureTest.java에서 `callTransactionPortMethodRequiredByCapability` 메소드에 `@SuppressWarnings("resource")`를 추가하여 ECJ의 자원 누수 오탐지 경고 해결.
- [develop] CleanArchitectureTest.java의 internal FQCN 임포트 스타일 정리 및 spotless 적용.
- [develop] README.md에 `feature-developer-experience-contract` 문자열을 추가하여 DeveloperExperienceContractTest의 계약 실패 검증 통과.
- [develop] Spring Boot Tools의 EOL 경고 무시를 위해 `.vscode/settings.json``spring-boot.ls.problem.version-validation.SUPPORTED_OSS_VERSION` 등의 설정을 추가.
- [develop] Spring Boot 4.x 및 Testcontainers 2.0로 업그레이드 시 발생하는 빌드 의존성 좌표 변경, 패키지 리로케이션 및 autoconfiguration 호환성을 평가하고 마이그레이션 가이드 문서(docs/superpowers/specs/2026-06-30-testcontainers-2-0-migration-spec.md)를 설계 및 작성.
## 배운 점
- Eclipse Compiler for Java (ECJ)는 anonymous inner class의 리턴 형태나 인스턴스화 위치에 따라 리소스 누수를 잘못 오탐지할 수 있으며, 이 경우 `@SuppressWarnings("resource")`를 적합하게 활용하여 코드를 깨끗하게 유지할 수 있다.
- VS Code Spring Boot Tools 확장 프로그램의 Spring Boot EOL 지원 경고는 `.vscode/settings.json`을 사용하여 워크스페이스 레벨에서 개별 무시(IGNORE)가 가능하다.
- Testcontainers 2.0.0 버전에서 모듈명 접두사 표준화(testcontainers-*) 및 패키지 리로케이션(org.testcontainers.<module> 형태로 이동) 등의 중대한 변경사항이 존재하며, 이로 인해 Spring Boot 3.5.x와 혼용 시 @ServiceConnection 바인딩 관련 ClassNotFoundException 위험이 있음을 확인.
## 트러블슈팅
- 없음.
## 면접·포트폴리오로 옮길 만한 것
- 없음.
## 내일로 넘긴 것
- 없음.
## 잡담 / 회의 / 기타
- 로컬 빌드 및 전체 테스트를 무사히 통과시키고 마크다운 및 리소스 경고 문제를 매끄럽게 처리함.