Files
llm-wiki/raw/branch-notes/feature-sample-portfolio-public-access.md
T

14 KiB

title, source_type, status, branch, parent_branch, related_projects, tags, created, target_merge, status_label, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, contract_packet_sha256
title source_type status branch parent_branch related_projects tags created target_merge status_label id kind project work_item inherits refines overrides depends_on contract_packet contract_packet_sha256
branch / feature-sample-portfolio-public-access branch-note raw feature-sample-portfolio-public-access
ca-tmpl
branch
ca-tmpl
security
testing
spring-boot
spring-security
component-scan
2026-07-03 in-progress BR-CA-SKELETON-OPERATIONAL-CONTRACT-057 project-work-item ca-skeleton-operational-contract WI-CA-SKELETON-OPERATIONAL-CONTRACT-057
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MODULE-LAYOUT-001@1
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-FRAMEWORK-001@1
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-TEST-001@1
WI-CA-SKELETON-OPERATIONAL-CONTRACT-048
WI-CA-SKELETON-OPERATIONAL-CONTRACT-021
1 48cb041d3ff0bcd03ab8fb89745313d975a25f44f39b64d8eb849eb1d466e501

branch: feature-sample-portfolio-public-access

Layer: raw/branch-notes/ — sample-portfolio standalone demo URL 공개 정책과 관련 테스트 보정 기록.

부모 (필수)

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: sample public endpoint allowlist와 authenticated endpoint negative test가 명시된다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MODULE-LAYOUT-001@1 Gradle multi-module에서 domain-core·application-core·adapter-*·shared-contract·app-bootstrap·sample-portfolio 책임을 분리한다 Work Item 완료 조건에 적용 raw/project-notes/ca-skeleton-operational-contract
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-FRAMEWORK-001@1 framework는 Spring Boot 3.5.14다 Work Item 완료 조건에 적용 raw/project-notes/ca-skeleton-operational-contract
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-TEST-001@1 test framework는 JUnit 5다 Work Item 완료 조건에 적용 raw/project-notes/ca-skeleton-operational-contract

브랜치 지역 결정

기존 branch-local 결정은 아래 ## Decision Evidence Map / 결정-근거 매핑의 D-row가 소유하며 이 packet에서 복제하지 않는다.

Decision ID Decision Relation Supporting Claims Status

선언한 예외

Override ID Overrides Reason Approval Status

목표

  • 이슈: sample-portfolio는 별도 로그인/IdP 플로우가 없는 참고 구현인데, URL 확인 시 JWT와 method-security가 같이 걸려 데모 접근성이 떨어졌다.
  • PR: 없음.

범위

포함 범위

  • sample-portfolio standalone composition root에서 production JWT SecurityConfigMethodSecurityConfig를 스캔 제외한다.
  • sample-portfolio 전용 SecurityFilterChain을 추가해 모든 demo URL을 permitAll로 공개한다.
  • sample actuator chain도 sample-local 정책으로 전체 permitAll 처리한다.
  • 기존 :sample-portfolio:test 포트 충돌을 막기 위해 web integration test의 management.server.port를 랜덤 포트로 둔다.

제외 범위

  • production adapter-web JWT/authz 정책 변경.
  • app-bootstrap production actuator 보안 정책 변경.
  • sample에 실제 로그인/IdP 플로우 추가.

근거 (필수, 최소 1개+)

Source 정당화하는 결정
raw/official-docs/spring-security-authorization-architecture method security가 AOP 기반으로 service/use case 호출을 가로채므로 sample runtime에서 URL 공개만으로는 write endpoint가 완전히 열리지 않는다는 판단
raw/official-docs/actuator-endpoint-exposure-spring-official custom SecurityFilterChain이 있으면 actuator auto-security에 의존할 수 없으므로 sample-local actuator chain을 명시해야 한다는 판단
raw/official-docs/actuator-management-port-spring-official management.server.port가 별도 HTTP port로 설정 가능하므로 테스트에서는 0으로 격리할 수 있다는 판단

TODO

  • sample runtime에서 production JWT SecurityConfig 스캔 제외 — 등급: actually-implemented
  • sample runtime에서 production MethodSecurityConfig 스캔 제외 — 등급: actually-implemented
  • sample 전용 public SecurityFilterChain 추가 — 등급: actually-implemented
  • sample actuator chain 전체 공개 — 등급: actually-implemented
  • sample web integration tests의 management port collision 제거 — 등급: locally-verified

진행 중 메모

  • SecurityFilterChain만 공개하면 HTTP 필터는 통과하지만, @RequiresPermission이 붙은 sample use case는 MethodSecurityConfig AOP advisor에 의해 여전히 unauthenticated/unauthorized로 막힌다.
  • 따라서 sample standalone runtime에서는 production authn/authz configuration을 composition root에서 제외해야 한다.
  • 기존 권한 계약 테스트(WorkLogAuthorizationContractTest, WorkLogAuthorizationE2ETest)는 MethodSecurityConfig를 직접 import하는 보안 프레임워크 fixture로 유지했다.

결정 사항

  • 2026-07-03: sample-portfolio standalone app은 로그인/IdP 없는 공개 데모로 취급하고 모든 sample URL을 permit-all로 연다. / 이유: 사용자가 브라우저/URL 접근으로 sample API를 확인할 수 있어야 한다. / 검토한 대안: public-paths에 sample 경로 열거, mock/demo login 추가, production security 그대로 유지. / 근거: UNSUPPORTED_DECISION — 제품 정책 판단이며 외부 공식 문서가 직접 정당화하지 않는다.
  • 2026-07-03: SecurityConfig뿐 아니라 MethodSecurityConfig도 sample component scan에서 제외한다. / 이유: method security AOP가 write use case를 필터 이후에도 막기 때문이다. / 근거: raw/official-docs/spring-security-authorization-architecture
  • 2026-07-03: test-only web contexts는 management.server.port=0을 명시한다. / 이유: local process가 9001을 사용 중이어도 :sample-portfolio:test가 deterministic하게 통과해야 한다. / 근거: raw/official-docs/actuator-management-port-spring-official

결정-근거 매핑

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 sample-portfolio standalone URL은 전부 공개한다. 로그인/IdP 없는 sample demo일 때 이 결정. 운영 서비스나 민감 actuator가 있는 앱이면 production security 정책 유지. UNSUPPORTED_DECISION project-policy sample을 운영 배포하면 actuator/loggers까지 공개되므로 별도 production profile 또는 sample 제거 필요
D2 sample composition root에서 SecurityConfigMethodSecurityConfig를 제외하고 sample-local permit-all chain을 둔다. sample runtime에서 write endpoint까지 열어야 할 때 이 결정. authz contract fixture는 별도 test import로 유지. raw/official-docs/spring-security-authorization-architecture.md#SS-AUTHZ-ARCH-C2, raw/official-docs/spring-security-authorization-architecture.md#SS-AUTHZ-ARCH-C3 official-vendor-doc + UNSUPPORTED_DECISION Spring Security auto-config 조건 변화 시 sample chain 조건 재검증 필요
D3 sample actuator chain은 sample-local로 전체 permitAll한다. sample demo 확인성이 우선인 local/reference app일 때 이 결정. production actuator는 app-bootstrap 정책 유지. raw/official-docs/actuator-endpoint-exposure-spring-official.md#SB-ACT-EXP-C2, raw/official-docs/actuator-endpoint-exposure-spring-official.md#SB-ACT-EXP-C3 official-vendor-doc + project-policy sample config를 운영에 재사용하면 노출 위험
D4 web integration tests는 management.server.port=0으로 격리한다. test context가 management server를 띄우고 local fixed port 충돌 가능성이 있을 때 이 결정. runtime default port는 유지. raw/official-docs/actuator-management-port-spring-official.md#SB-ACT-PORT-C3 official-vendor-doc parallel test에서 다른 fixed port가 남아 있으면 별도 격리 필요

구현 가이드

1. sample runtime security override

Trace: D1, D2.

  • UNSUPPORTED_IMPL_DECISION: sample config class/package naming은 repo local convention (bootstrap.security)에 맞춘 결정.
File Implementation
src/sample-portfolio/src/main/java/dev/caskeleton/sample/portfolio/SamplePortfolioApplication.java @ComponentScan exclude filter에 SecurityConfig, MethodSecurityConfig 추가
src/sample-portfolio/src/main/java/dev/caskeleton/sample/portfolio/bootstrap/security/SamplePublicAccessSecurityConfig.java servlet web app일 때만 /** matcher, CSRF disable, stateless, anyRequest().permitAll() chain 등록
src/sample-portfolio/src/main/java/dev/caskeleton/sample/portfolio/bootstrap/management/SampleManagementSecurityConfig.java servlet web app일 때 actuator endpoint chain 전체 permitAll()

2. test port isolation

Trace: D4.

  • UNSUPPORTED_IMPL_DECISION: affected tests에 property를 직접 붙이는 방식은 가장 좁은 변경을 위한 repo-local 판단.
File Implementation
OpenApiSnapshotTest management.server.port=0
OpenApiDriftContractTest management.server.port=0
DateHeaderContractTest management.server.port=0
VirtualThreadMdcE2ETest management.server.port=0

엣지·실패·의존

  • 실패·엣지 경로: webEnvironment=NONE context에는 HttpSecurity가 없으므로 sample security configs는 @ConditionalOnWebApplication(SERVLET)로 제한해야 한다.
  • 실패·엣지 경로: sample URL 공개는 method-security 제외 없이는 write endpoint까지 보장하지 못한다.
  • 다른 계약 의존: raw/branch-notes/feature-authentication-authorization-contract — production authn/authz contract는 변경하지 않고 sample fixture에서만 우회한다.
  • 다른 계약 의존: raw/branch-notes/feature-management-actuator-security-contract — production actuator posture는 app-bootstrap 소유로 유지한다.

검증해야 할 주장

Claim Why uncertain How to verify Status
sample write endpoint가 Authorization 헤더 없이 통과한다. filter-chain 공개와 method-security 제외가 함께 필요하다. ./gradlew :sample-portfolio:test --tests dev.caskeleton.sample.portfolio.bootstrap.security.SamplePublicAccessSecurityConfigTest locally-verified
sample full context는 webEnvironment NONE에서도 뜬다. HttpSecurity가 없는 context에서 security config bean 생성이 실패할 수 있다. ./gradlew :sample-portfolio:test --tests dev.caskeleton.sample.portfolio.SampleApplicationContextTest --tests dev.caskeleton.sample.portfolio.bootstrap.security.SamplePublicAccessSecurityConfigTest locally-verified
sample-portfolio 전체 테스트가 fixed management port 충돌 없이 통과한다. local 9001 process가 떠 있으면 기존 test가 실패했다. ./gradlew :sample-portfolio:test locally-verified
전체 repository check가 통과한다. sample change가 ArchUnit/Spotless/Checkstyle/SpotBugs와 충돌할 수 있다. ./gradlew check locally-verified

마주친 문제

  • SamplePublicAccessSecurityConfigTest 작성 직후 SamplePublicAccessSecurityConfig가 없어서 컴파일 실패했다. TDD red 단계로 의도된 실패.
  • @WebMvcTest에서 HttpSecurity가 제공되지 않아 테스트 부트스트랩을 최소 @SpringBootTest로 전환했다.
  • SampleApplicationContextTestwebEnvironment=NONE이라 sample security configs에 servlet web app 조건을 추가했다.
  • ./gradlew check 1차 재실행은 Spotless import/indent 위반으로 실패했고 :sample-portfolio:spotlessApply 후 통과했다.
  • 기존 포트 충돌은 raw/errors/sample-portfolio-tomcat-port-in-use-check-2026-07-03 로 분리 기록했다.

묶음 (이 branch에서 파생된 자료)

Sub-branches (세부 작업)

  • 없음.

오류 기록 (이 branch 작업 중 발생)

면접 준비 (이 작업에서 나올 수 있는 면접 질문)

  • 없음 — 별도 면접 질문으로 추출할 만큼 독립적인 새 개념 없음.

강의 (이 작업을 위해 학습한 강의)

  • 없음.

job-posting tie-ins (이 작업에서 파생된 글감)

  • 추출할 별도 글감 없음.

관련 일일 노트

  • 없음 — 2026-07-03 daily note가 아직 없어 broken wikilink를 만들지 않음.

완료 후 정리

  • PR 링크:
  • 리뷰 메모:
  • 머지 결과 / 배포 환경: local verification only.
  • wiki 추출 대상:
    • actually-implemented 항목: sample runtime public access override.
    • locally-verified 항목: sample-portfolio tests and full check.
  • 추출하지 않을 항목:
    • production security posture 변경 없음.