Skip to content

chore: Worker Link tenant 무결성과 PostgreSQL RLS 보강 - #90

Open
krestar wants to merge 7 commits into
mainfrom
feat/34-worker-link-rls
Open

chore: Worker Link tenant 무결성과 PostgreSQL RLS 보강#90
krestar wants to merge 7 commits into
mainfrom
feat/34-worker-link-rls

Conversation

@krestar

@krestar krestar commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

왜 필요한가요?

Worker Link 관련 자식 테이블은 기존 단일 FK만으로 응답·파일·멱등성 기록이 서로 다른 사업장에 연결되는 것을 DB에서 완전히 차단하지 못했습니다.

PR #87에서 추가된 worker_document.task_id 또한 (task_id, company_id) FK만으로는 같은 사업장에 속한 다른 근로자의 Task를 WorkerDocument에 연결할 수 있었습니다.

또한 Worker Link RLS 정책과 token bootstrap을 실제 Worker Link 스키마에 맞게 완성하고, 제한 runtime role에서 tenant 격리가 유지되는지 PostgreSQL로 검증할 필요가 있습니다.

#34의 실제 runtime/migration role 구성, 최소 GRANT, Secret 주입, RLS 활성화 및 staging smoke는 #9와 연계된 후속 작업으로 남습니다. 따라서 이 PR은 #34를 자동으로 닫지 않습니다.

무엇이 바뀌나요?

  • API·도메인·DB 변경:

    • V16 공통 migration에서 worker_response_uploadworker_document_upload_idempotencycompany_id를 추가합니다.
    • 기존 데이터를 신뢰 가능한 부모 관계에서 backfill한 뒤 NOT NULL로 전환합니다.
    • Worker Link, Worker Response, StoredFile 및 자식 테이블에 tenant-aware 복합 UNIQUE·FK를 적용합니다.
    • worker_link.replaces_link_id를 동일 사업장 복합 FK와 ON DELETE RESTRICT로 전환합니다.
    • 동일 StoredFile이 여러 Worker Response에 연결되지 않도록 복합 UNIQUE를 추가합니다.
    • worker_document(task_id, worker_id, company_id) 복합 FK로 같은 사업장의 다른 근로자 Task 연결을 차단합니다.
    • 문서 등록 시 Task 존재 여부와 Task–Worker 일치 여부를 Application Service에서도 검증합니다.
    • Worker Response 업로드와 문서 업로드 멱등성 저장·조회 경로에 company_id를 전달합니다.
  • 권한·Workflow 변경:

    • Worker Link 발급 transaction에서 ActorContext.companyId를 PostgreSQL tenant context에 바인딩합니다.
    • V17 PostgreSQL migration에서 Worker Response Upload 정책을 직접 company_id 비교 방식으로 전환합니다.
    • Worker Document Upload Idempotency 테이블에 tenant RLS 정책을 추가합니다.
    • Worker Link bootstrap은 token hash가 일치하면서 ACTIVE이고 DB 시각 기준 미만료인 링크만 company_id를 반환합니다.
    • V17에서는 ENABLE ROW LEVEL SECURITY를 실행하지 않습니다.
  • AI·외부 연동 변경:

    • 변경 없음
  • 문서·배포 변경:

    • PostgreSQL RLS rollout 문서에 V16 최초 배포 전제와 V17 적용 범위를 기록합니다.
    • V16은 pre-V16 애플리케이션과 동시에 같은 DB에 쓰는 상황에 backward-compatible하지 않습니다.
    • 현재는 운영 DB·운영 트래픽·구버전 Pod가 없는 최초 배포 전이므로 해당 전제를 충족합니다.
    • 실제 role·GRANT·Secret·RLS 활성화와 staging smoke는 #9와 연계합니다.
    • RLS 활성화는 조건 충족 후 별도의 forward-only Flyway migration으로 수행하며 버전 번호를 현재 예약하지 않습니다.

어떻게 검증했나요?

  • .\gradlew.bat clean test
  • .\gradlew.bat build
  • /health와 Swagger UI 확인
  • 정상 요청
  • 잘못된 입력
  • 권한 부족
  • 다른 사업장 접근 차단
  • 필요한 상태 전이·Idempotency

Demo Seed 활성/비활성(clean Docker psql DB 환경) run 정상 작동도 확인하였습니다.

실행한 주요 PostgreSQL 테스트:

.\gradlew.bat test `
  --tests "com.fowoco.server.PostgreSqlMigrationTests" `
  --tests "com.fowoco.server.common.security.PostgreSqlRlsIsolationTest"

검증 결과:

  • V16 기존 데이터 backfill과 NOT NULL 전환
  • NULL·orphan·교차 tenant 관계가 있는 migration 실패
  • 같은 사업장 다른 근로자의 Task 연결 차단
  • StoredFile의 다중 Worker Response 연결 차단
  • 제한 runtime role에서 tenant context 누락 시 fail-closed
  • company A context에서 company B 행 조회·생성 차단
  • Worker Response Upload와 업로드 멱등성 테이블 RLS 차단
  • transaction 종료 후 tenant context 비누수
  • ACTIVE·미만료 Worker Link만 bootstrap 성공
  • REVOKED·실제 만료·미등록 token hash bootstrap 차단
  • migration 적용 후에도 RLS가 비활성 상태임을 확인

보안·개인정보

  • DTO·로그·AI 입력에 불필요한 개인정보가 없습니다.
  • JWT, Worker Link 원본 토큰, API Key, 비밀번호가 없습니다.
  • 모든 사업장 데이터 접근에 company_id 범위를 검사합니다.
  • AI 결과가 자동 승인·발송되지 않습니다.
  • 기존 Worker Link 중요 변경은 AuditLog와 request_id로 추적됩니다.
  • ADR-0004의 단계적 RLS 도입 계약을 유지합니다.
  • Server에 Prompt Builder·Provider SDK·모델 routing을 추가하지 않았습니다.

API·DB·운영 영향

  • 외부 API 계약 변경이 없어 Swagger/OpenAPI·Notion 갱신이 필요하지 않습니다.
  • V16의 배포 호환성 전제를 본문과 rollout 문서에 명시했습니다.
  • DB 변경에 Flyway V16·V17 migration이 있습니다.
  • migration 번호와 소유 Issue를 확인했고 다른 기능의 테이블을 미리 만들지 않았습니다.
  • 새로운 credential이나 Secret을 저장소에 추가하지 않았습니다.
  • 배포 후 Smoke Test와 forward-only 복구 절차를 rollout 문서에 기록했습니다.

배포 주의사항

  • V16과 대응 애플리케이션 코드는 같은 릴리스로 배포해야 합니다.
  • pre-V16 애플리케이션과 V16 스키마의 동시 쓰기는 지원하지 않습니다.
  • V17은 정책과 bootstrap만 준비하며 RLS를 활성화하지 않습니다.
  • 실제 RLS 활성화는 #9의 runtime role·최소 GRANT·Secret·staging 검증이 끝난 뒤 별도 migration으로 진행합니다.

화면 또는 응답 예시

외부 API 응답 형식 변경은 없습니다.

krestar added 7 commits August 5, 2026 12:59
- Worker Link 발급 서비스가 ActorContext를 tenant 신뢰 원본으로 사용하도록 변경
- 첫 Repository 접근 전에 transaction-local company_id 설정
- 발급 Command에서 companyId와 issuedBy 제거
- tenant context가 Repository보다 먼저 설정되는 순서 테스트 추가
- Worker Link 자식 테이블에 company_id를 backfill하고 NOT NULL로 전환
- Worker Response, 업로드 파일 및 멱등성 기록에 tenant-aware 복합 FK 적용
- Worker Link 대체 관계를 동일 사업장 복합 FK와 RESTRICT 정책으로 변경
- WorkerDocument와 Task의 근로자·사업장 복합 무결성 적용
- 문서 등록 시 Task 존재 여부와 Task–Worker 일치 검증
- Worker Link persistence 쓰기·조회 경로에 companyId 전달
- V16 migration 실패 조건과 최초 배포 비호환 전제를 문서화
- H2 기능 테스트와 PostgreSQL migration 계약 테스트 보강
- 응답 업로드 파일에 사업장 단위 복합 UNIQUE 제약 추가
- 업로드 멱등성 파일 복합 FK 조회 인덱스 추가
- 동시 연결 시 발생한 특정 UNIQUE 위반을 도메인 오류로 변환
- 다른 데이터 무결성 오류가 잘못 변환되지 않도록 제약 이름과 SQLSTATE 검증
- V16 migration 및 PostgreSQL 스키마 계약 테스트 보강
- 업로드 중복 연결 예외를 application.port에서 application.error로 이동
- Worker Response Upload 정책을 직접 company_id 비교 방식으로 전환
- Worker Document Upload 멱등성 테이블에 tenant 격리 정책 추가
- V17에서는 RLS를 활성화하지 않고 정책만 준비
- PostgreSQL migration 정책 계약 테스트 보강
- 제한 runtime role의 Worker Link tenant 격리 테스트 추가
- RLS rollout 문서에 V17 적용 범위 반영
- Worker Link bootstrap이 ACTIVE 상태의 링크만 사업장을 반환하도록 제한
- DB 현재 시각을 기준으로 만료된 링크의 tenant bootstrap 차단
- ACTIVE, REVOKED, 만료 및 미등록 token hash PostgreSQL 테스트 추가
- Worker Response Upload의 교차 tenant INSERT 차단 테스트 보강
- PostgreSQL RLS rollout 문서에 bootstrap 조건 반영
본 커밋에서 다룬 문제점은 Demo 환경 테스트 중 발견 되었습니다.
테스트의 원활함을 위해 PR과는 무관한 주제지만, fix 조치 하였습니다.

- 예약된 데모 파일의 내용이 변경되면 현재 classpath fixture로 원자적으로 교체
- 일반 파일이 아닌 storage key 경로는 덮어쓰지 않고 거부
- 동일 크기 변조 및 크기가 다른 구버전 fixture 복구 테스트 추가
- 데모 fixture 재실행 계약 문서화
@krestar krestar added area:server Spring Boot API·도메인·DB·tenant·Task Workflow 영역; Prompt·모델·Provider 구현 제외 area:infra Server Dockerfile·DB 설정·CI hook·배포 가능성 영역; 통합 인프라 운영은 infra 저장소와 조율 priority:P1 핵심 작업 다음으로 처리할 중요 작업 security:privacy 개인정보·접근권한·토큰·보안 영향이 있는 작업 status:in-review 구현을 마치고 리뷰 또는 병합을 기다리는 작업 type:chore 저장소 설정·의존성·유지보수 작업 labels Aug 5, 2026
@krestar krestar changed the title feat: Worker Link tenant 무결성과 PostgreSQL RLS 보강 chore: Worker Link tenant 무결성과 PostgreSQL RLS 보강 Aug 5, 2026
@hywznn

hywznn commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

미안해요 재성님 제가 나중에 머지했어야했네요 ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:infra Server Dockerfile·DB 설정·CI hook·배포 가능성 영역; 통합 인프라 운영은 infra 저장소와 조율 area:server Spring Boot API·도메인·DB·tenant·Task Workflow 영역; Prompt·모델·Provider 구현 제외 priority:P1 핵심 작업 다음으로 처리할 중요 작업 security:privacy 개인정보·접근권한·토큰·보안 영향이 있는 작업 status:in-review 구현을 마치고 리뷰 또는 병합을 기다리는 작업 type:chore 저장소 설정·의존성·유지보수 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants