Skip to content

fix: Demo Seed의 RLS 호환 트랜잭션 경계를 정리 - #205

Merged
krestar merged 1 commit into
mainfrom
fix/204-demo-seed-rls-compatibility
Aug 17, 2026
Merged

fix: Demo Seed의 RLS 호환 트랜잭션 경계를 정리#205
krestar merged 1 commit into
mainfrom
fix/204-demo-seed-rls-compatibility

Conversation

@krestar

@krestar krestar commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

왜 필요한가요?

PR #135에서 PostgreSQL RLS를 활성화하면 현재 배포 환경의 DEMO_SEED_ENABLED=true 조건과 기존 Demo Seed 실행 방식이 충돌할 수 있습니다.

기존 Demo Seed runner는 Demo/Test 회사를 하나의 큰 transaction 안에서 처리하고, 기존 company 조회 전에 transaction-local tenant context를 설정하지 않았습니다.
이 상태에서 RLS가 활성화되면 기존 Demo/Test company 행이 보이지 않아 신규 insert를 시도하고, RLS WITH CHECK에 의해 SQLSTATE 42501로 startup이 실패할 수 있습니다.

또한 RLS migration은 Seed runner보다 먼저 commit되므로, startup 실패 후 애플리케이션 이미지만 rollback해도 DB에는 RLS가 활성화된 상태가 남을 수 있습니다.

이 PR은 Demo Seed도 실제 Runtime과 같은 tenant isolation 원칙을 따르도록 transaction과 tenant context 경계를 정리합니다.

  • Demo/Test Seed를 회사별 REQUIRES_NEW transaction으로 분리합니다.
  • 각 회사 transaction 시작 직후 기존 TenantDatabaseContext로 tenant context를 설정합니다.
  • 회사 bootstrap부터 운영 fixture 처리까지 제한 Runtime Role에서도 조회·생성·재기동이 멱등하게 동작하도록 합니다.
  • 한 회사 Seed가 실패하면 해당 회사 transaction만 rollback하고, 앞서 성공한 회사의 commit은 유지합니다.
  • 기존 DB의 RLS 전환, 제한 Runtime Role 재기동, tenant 격리와 파일 fixture 멱등성을 PostgreSQL 통합 테스트로 검증할 수 있도록 보강합니다.

이 PR은 PR #135의 선행 작업입니다.

Closes #204

무엇이 바뀌나요?

  • API·도메인·DB 변경:

    • API 계약과 도메인 모델 변경은 없습니다.
    • Flyway migration과 DB schema 변경은 없습니다.
    • 공용 TenantTransactionExecutor를 추가해 회사별 작업을 REQUIRES_NEW transaction으로 실행합니다.
    • transaction 시작 직후 기존 TenantDatabaseContext를 설정하고 그 뒤에 Seed callback을 실행합니다.
    • DemoAuthSeedRunner, DemoWorkerSeedRunner, DemoOperationalSeedRunnerrun() 전체 @Transactional을 제거하고 Demo/Test 회사를 각각 독립 transaction으로 처리합니다.
    • 기존 runner 실행 순서 @Order(0) → @Order(1) → @Order(2)와 기존 fixture 의미·멱등성 로직은 유지합니다.
  • 권한·Workflow 변경:

    • Runtime Role의 SUPERUSER, BYPASSRLS, table ownership 같은 우회 권한을 추가하지 않습니다.
    • Seed도 transaction-local app.company_id tenant context를 사용합니다.
    • Demo company transaction이 성공한 뒤 Test company transaction이 실패하면 Demo commit은 유지하고 Test만 rollback되며 startup 전체에는 실패가 전파됩니다.
    • 일반 Task Workflow 상태 전이 규칙은 변경하지 않습니다.
  • AI·외부 연동 변경:

    • 없습니다.
    • AI Prompt, Provider SDK, 모델 routing, 외부 API 계약을 변경하지 않습니다.
  • 문서·배포 변경:

    • 별도 문서나 환경변수 추가는 없습니다.
    • PR #135의 RLS 활성화 전에 이 변경을 먼저 배포하고, 현재 DB/PVC를 유지한 상태에서 DEMO_SEED_ENABLED=true 재기동 회귀를 확인하는 것이 전제입니다.

어떻게 검증했나요?

  • 변경 범위 단위·통합 테스트
  • PostgreSQL 16에서 RLS 활성화 및 제한 Runtime Role 재기동 시나리오
  • RLS OFF인 main 기준 DB에서 ./gradlew.bat clean test 실행(전체 성공은 아님)
    • 총 691개 중 690개 통과
    • 변경 범위 밖의 NotificationEventHandlerIntegrationTest.manualTaskCreationDoesNotCreateNotification() 1건 실패
    • 자동 Outbox scheduler가 테스트의 수동 processAvailable() 호출 전에 이벤트를 처리할 수 있는 기존 경쟁 조건으로 추정
  • ./gradlew build
  • 배포 환경 Smoke Test

추가·보강한 주요 테스트:

TenantTransactionExecutorTest
DemoAuthSeedRunnerTest
DemoWorkerSeedRunnerTest
DemoOperationalSeedRunnerTest
DemoAuthSeedIntegrationTest
DemoSeedPostgreSqlApplicationIntegrationTest

검증하도록 추가한 핵심 시나리오:

  • TenantTransactionExecutor가 tenant context를 callback보다 먼저 설정하는지
  • Demo/Test Seed가 각각 별도 REQUIRES_NEW transaction에서 실행되는지
  • 앞선 회사 transaction은 commit되고 실패한 회사 transaction만 rollback되는지
  • 기존 DB에서 RLS를 활성화한 뒤 제한 Runtime Role로 같은 DB를 재기동해도 기존 fixture를 정상 재사용하는지
  • context 없는 Runtime connection에서 tenant row가 보이지 않는지
  • transaction 종료 후 app.company_id가 pool connection에 남지 않는지
  • 동일 DB 추가 재기동 시 fixture가 중복되지 않는지
  • 동일 파일 저장소의 경로·크기·SHA-256이 재기동 전후 동일한지
  • RLS ON 상태의 빈 seed 데이터에서도 최초 생성과 추가 재기동이 가능한지

관련 테스트 실행 예시:

./gradlew.bat test `
  --tests "com.fowoco.server.common.security.TenantTransactionExecutorTest" `
  --tests "com.fowoco.server.auth.infrastructure.seed.DemoAuthSeedRunnerTest" `
  --tests "com.fowoco.server.worker.infrastructure.seed.DemoWorkerSeedRunnerTest" `
  --tests "com.fowoco.server.demo.infrastructure.seed.DemoOperationalSeedRunnerTest" `
  --tests "com.fowoco.server.auth.infrastructure.seed.DemoAuthSeedIntegrationTest"

PostgreSQL 16 통합 테스트:

$env:POSTGRES_TEST_ENABLED = "true"
$env:POSTGRES_TEST_URL = "jdbc:postgresql://localhost:5432/fowoco_test"
$env:POSTGRES_TEST_USERNAME = "<postgres-test-admin-or-migration-user>"
$env:POSTGRES_TEST_PASSWORD = "<password>"

./gradlew.bat test `
  --tests "com.fowoco.server.demo.infrastructure.seed.DemoSeedPostgreSqlApplicationIntegrationTest"

전체 clean test는 RLS OFF인 main 기준 DB에서 실행했으며, #204와 무관한 알림 통합 테스트 1건을 제외하고 통과했습니다.
PR #135 merge 전에는 #204 배포 후 현재 dev DB/PVC 재기동 검증과 별도 PostgreSQL 환경에서 #204 + #135 결합 검증이 필요합니다.

보안·개인정보

  • DTO·로그·AI 입력에 불필요한 개인정보가 없습니다.
  • JWT, Worker Link 원본 토큰, API Key, 비밀번호가 없습니다.
  • 변경된 Demo Seed 데이터 접근에 company_id 범위를 적용합니다.
    • Demo Seed transaction도 기존 TenantDatabaseContext의 transaction-local app.company_id 계약을 사용합니다.
  • AI 결과가 자동 승인·발송되지 않습니다.
    • AI 동작 자체를 변경하지 않습니다.
  • 기존 AuditLog와 request_id 동작을 변경하지 않습니다.
    • Seed audit fixture의 의미도 유지합니다.
  • 새 ADR이 필요한 설계 변경이 없습니다.
    • 기존 tenant isolation 및 Migration/Runtime Role 분리 원칙을 유지합니다.
  • Server에 Prompt Builder·Provider SDK·모델 routing을 추가하지 않았습니다.

API·DB·운영 영향

  • API 계약 변경이 없습니다.
    • Swagger/OpenAPI, Notion 계약 및 Client 공지가 필요하지 않습니다.
  • DB schema 변경이 없습니다.
    • 이 PR은 Flyway migration을 추가하지 않으며, RLS 활성화 migration은 후속 PR #135에서 처리합니다.
  • 신규 환경변수가 없습니다.
    • .env.example 변경이 필요하지 않습니다.
  • 배포 후 Smoke Test와 롤백 방법을 적었습니다.
    • 이 PR을 PR #135보다 먼저 배포합니다.
    • 현재 dev DB/PVC를 유지하고 DEMO_SEED_ENABLED=true 상태에서 재기동 성공, Demo/Test 로그인과 주요 fixture 중복 여부를 확인합니다.
    • [Demo][Reliability] RLS 환경에서 Demo Seed tenant context·transaction 경계 호환 #204 배포 자체에 문제가 생기고 아직 RLS가 활성화되지 않았다면 이전 정상 Server image로 rollback합니다.
    • 후속 PR #135의 RLS 활성화 이후 장애 대응은 #135의 forward-only RLS rollback 절차를 따릅니다.

화면 또는 응답 예시

API 응답과 화면 변경은 없습니다.

이 PR은 Demo Seed의 transaction/tenant context 경계와 RLS 호환성을 수정하는 서버 내부 변경입니다.

- Demo/Test Seed를 회사별 REQUIRES_NEW 트랜잭션으로 분리하고 시작 직후 tenant context를 설정한다.
- 회사 bootstrap부터 운영 fixture 처리까지 제한 Runtime Role에서도 조회·생성·재기동이 멱등하게 동작하도록 한다.
- 한 회사의 실패는 해당 회사만 rollback하고 앞서 완료된 회사의 commit은 유지한다.
- 기존 DB의 RLS 전환, 제한 Role 재기동, tenant 격리와 파일 fixture 멱등성을 PostgreSQL 테스트로 검증한다.
@krestar
krestar merged commit 25fa32d into main Aug 17, 2026
4 checks passed
@krestar
krestar deleted the fix/204-demo-seed-rls-compatibility branch August 17, 2026 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Demo][Reliability] RLS 환경에서 Demo Seed tenant context·transaction 경계 호환

1 participant