Skip to content

[Settings] 회사 설정 조회·수정 및 사업장 구성원 조회 API 구현` - #124

Merged
krestar merged 15 commits into
mainfrom
feat/16-company-settings
Aug 9, 2026
Merged

[Settings] 회사 설정 조회·수정 및 사업장 구성원 조회 API 구현`#124
krestar merged 15 commits into
mainfrom
feat/16-company-settings

Conversation

@krestar

@krestar krestar commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

왜 필요한가요?

사업장별 운영 정책을 조회·수정하고, 같은 사업장의 구성원을 역할·활성 상태·승인 가능 여부로 조회할 수 있는 Server 계약이 필요합니다.

기존에는 Worker Link 만료시간, 승인·반려 권한, 업무 완료 증빙, 감사 조회 범위를 회사 단위 설정으로 관리하거나 일관되게 소비할 수 없었습니다. 또한 구성원 선택 UI가 사용할 tenant-safe 조회 API가 없었습니다.

무엇이 바뀌나요?

  • API·도메인·DB 변경:
    • GET /api/v1/settings 회사 설정 조회 API를 추가했습니다.
    • PATCH /api/v1/settings ADMIN 전용 부분 수정 API를 추가했습니다.
    • PATCH에서 omitted field와 explicit null을 구분하고, expected_version 기반 낙관적 잠금을 적용했습니다.
    • GET /api/v1/company-members 사업장 구성원 조회 API와 role, approval_capable, active_only query를 추가했습니다.
    • 단일 UserAccount.role을 응답의 singleton roles로 매핑하고 activeapproval_permission을 파생 값으로 제공합니다.
    • company_settings 테이블, 기존 회사 기본 설정 backfill, PostgreSQL RLS 준비 migration(V35·V36)을 추가했습니다.
    • 신규 회사와 Demo Seed 회사 생성 시 기본 설정 row를 같은 transaction에서 생성합니다.
  • 권한·Workflow 변경:
    • 설정 조회는 ADMIN·HR·VIEWER, 설정 수정은 ADMIN만 허용합니다.
    • VIEWER의 구성원 응답은 user_id, display_name만 제공하며 제한 query 사용을 거부합니다.
    • approval_policy를 승인·반려 권한에 적용했습니다.
    • evidence_rules를 기존 업무 완료 증빙 baseline에 추가되는 회사 규칙으로 적용했습니다.
    • audit_visibility를 회사 전체 Audit 검색 권한에 적용했습니다.
    • 설정 변경 필드별 before/after compact diff를 Audit Event로 기록합니다.
  • AI·외부 연동 변경:
    • link_expiry_hours를 Worker Link 기본 만료시간으로 적용하며 요청의 expires_in_hours가 있으면 요청값을 우선합니다.
    • 기존 발급 링크에는 설정 변경을 소급 적용하지 않습니다.
    • ai_log_retention_daysai_attempt 상세 데이터 보유 계약만 저장하며 이번 PR에서 삭제 job이나 Provider 연동은 추가하지 않습니다.
    • file_retention_days도 이번 PR에서는 설정 계약과 영속화만 제공하며 파일 삭제 job은 추가하지 않습니다.
  • 문서·배포 변경:
    • 설정 조회·수정과 구성원 조회의 Swagger/OpenAPI schema, 권한 설명, 오류 응답, 실제 요청·응답 예시를 추가했습니다.
    • Notion의 관련 API 계약 3개를 frozen 후보 기준으로 갱신했습니다.
    • 새 환경변수는 없습니다.

어떻게 검증했나요?

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

검증 결과:

  • ./gradlew clean test: 성공
  • 설정·구성원 API security integration test와 OpenAPI contract test: 성공
  • PATCH omitted/explicit null, unknown field, 범위, no-op, stale/concurrent version을 검증했습니다.
  • ADMIN·HR·VIEWER 권한과 다른 사업장 데이터 비노출을 검증했습니다.
  • PostgreSQL RLS 전용 테스트는 관련 환경변수가 없는 실행에서는 조건부 skip되며, 별도 PostgreSQL test fixture에서 실행할 수 있습니다.
  • Demo Seed 기동 중 발견된 DemoCaseSeeder의 PostgreSQL Instant 바인딩 문제는 Issue [Settings] 사업장 설정 조회·수정 API 구현 #16 변경과 무관하며, 별도 브랜치 fix/94-demo-seed-golden-flow7665c2a에서 수정되어 있습니다. 해당 수정의 main 병합 후 Demo Seed smoke를 다시 수행합니다.

보안·개인정보

  • DTO·로그·AI 입력에 불필요한 개인정보가 없습니다.
  • JWT, Worker Link 원본 토큰, API Key, 비밀번호가 없습니다.
  • 모든 사업장 데이터 접근에 company_id 범위를 검사합니다.
  • AI 결과가 자동 승인·발송되지 않습니다.
  • 중요한 변경이 AuditLog와 request_id로 추적됩니다.
  • 관련 Accepted ADR을 지켰거나 필요한 새 ADR을 이 PR에서 Proposed로 작성했습니다.
  • Server에 Prompt Builder·Provider SDK·모델 routing을 추가하지 않았습니다.

구성원 응답에는 이메일·계정 상태 원문·비밀번호·토큰을 포함하지 않습니다.
activeAccountStatus에서, approval_permission은 role·active 상태·회사 승인 정책에서 계산합니다.
Repository query와 PostgreSQL RLS가 모두 tenant 경계를 적용합니다.

API·DB·운영 영향

  • Swagger/OpenAPI와 Notion 계약을 갱신했습니다.
  • Client에 알려야 할 호환성 변경을 적었습니다.
  • DB 변경에 Flyway migration이 있습니다.
  • migration 번호와 소유 Issue를 확인했고 다른 기능의 테이블을 미리 만들지 않았습니다.
  • 환경변수는 이름만 .env.example에 적었습니다.
  • 배포 후 Smoke Test와 롤백 방법을 적었습니다.

Client 전달 사항:

  • 외부 JSON과 query 이름은 snake_case입니다.
  • 구성원 조회 query는 approval_capable, 상세 응답 필드는 approval_permission입니다.
  • roles는 현재 단일 role의 singleton 배열입니다.
  • VIEWER에게는 구성원 최소 projection만 반환됩니다.
  • PATCH는 ADMIN만 사용할 수 있고 항상 expected_version이 필요합니다.
  • 설정 변경 충돌 시 최신 설정을 다시 조회한 후 재시도해야 합니다.

배포 후 Smoke Test:

  1. GET /health200 OK인지 확인합니다.
  2. ADMIN으로 로그인해 설정 GET·PATCH와 구성원 조회를 확인합니다.
  3. HR·VIEWER의 설정 GET 성공과 PATCH 403을 확인합니다.
  4. VIEWER 구성원 최소 projection과 제한 query 403을 확인합니다.
  5. Test Company 계정으로 조회해 Demo Company 구성원이 노출되지 않는지 확인합니다.
  6. 설정 변경 후 SETTINGS_UPDATED Audit Event와 request ID를 확인합니다.

롤백:

  • 애플리케이션은 이전 버전으로 되돌릴 수 있으며, 추가된 company_settings 테이블은 이전 버전이 참조하지 않아 그대로 두어도 됩니다.
  • Flyway migration은 자동 downgrade하지 않습니다.
  • DB 구조 제거가 반드시 필요하면 백업과 별도 승인된 forward migration으로 처리합니다.

화면 또는 응답 예시

개인정보를 제거한 예시입니다.

{
  "approval_policy": "ADMIN_OR_HR",
  "link_expiry_hours": 72,
  "evidence_rules": {},
  "file_retention_days": 365,
  "ai_log_retention_days": 90,
  "audit_visibility": "ADMIN_ONLY",
  "version": 0
}
{
  "expected_version": 0,
  "link_expiry_hours": 48,
  "audit_visibility": "ADMIN_AND_HR"
}
{
  "items": [
    {
      "user_id": "7e2722bb-3c72-4aa0-b37c-28931c4f8e53",
      "display_name": "구성원 예시",
      "roles": ["HR"],
      "active": true,
      "approval_permission": true
    }
  ]
}

주의점

krestar added 15 commits August 8, 2026 20:11
- CompanySettings 도메인과 MVP 기본값 및 검증 범위를 정의한다
- 회사 설정 JPA 영속화와 evidence_rules JSON 변환을 추가한다
- 기존 회사 설정 backfill과 tenant RLS migration을 추가한다
- 회원가입과 데모 회사 생성 시 기본 설정을 같은 트랜잭션에서 생성한다
- auth와 settings 사이를 application port로 분리한다
- 도메인, migration, RLS 및 회원가입 연동 테스트를 추가한다
- ADMIN, HR, VIEWER가 회사 설정을 조회할 수 있는 API 추가
- tenant context와 애플리케이션 계층 권한 검증 적용
- 회사 설정 공개 응답 DTO 및 OpenAPI 계약 정의
- 역할별 조회, tenant 격리, 인증 실패 및 설정 누락 테스트 추가
- ADMIN 전용 회사 설정 PATCH API 추가
- omitted 필드와 explicit null을 구분하는 부분 수정 계약 적용
- expected_version 기반 낙관적 잠금과 no-op 처리 구현
- 변경 필드의 compact before/after 감사 이벤트 기록
- 권한, 입력 검증, tenant 격리, 동시 수정 및 OpenAPI 계약 테스트 추가
- 회사 설정 변경 Audit action을 SETTINGS_UPDATED 계약으로 통일
- scalar 설정은 변경 필드별로 감사 이벤트 생성
- evidence_rules는 변경된 TaskType별 전후 값을 기록
- aggregate version 전이와 request ID 감사 검증 추가
- 감사 저장 실패 시 설정 변경이 rollback되는 통합 테스트 추가
- 사업장별 구성원 조회와 역할·활성·승인 가능 필터 추가
- ADMIN/HR 전체 projection과 VIEWER 최소 projection 분리
- role, AccountStatus, approval_policy 기반 승인 권한 계산
- auth application directory 경계와 tenant 격리 적용
- OpenAPI, 권한, 민감정보 제한 및 PostgreSQL RLS 테스트 추가
- evidence_rules 요청 배열의 중복 값을 검증하도록 변경
- 검증된 EvidenceType 목록을 도메인 Set 계약으로 변환
- 중복 증빙 유형 요청에 대한 회귀 테스트 추가
- expires_in_hours 생략 시 회사 설정의 기본 만료시간 적용
- 명시적 요청값 우선순위와 1..168 범위 검증 추가
- OpenAPI 만료시간 계약 보완
- 회사 기본값, 요청값 우선, 범위 오류 통합 테스트 추가
- Outbox 수동 재시도 시각을 DB 마이크로초 정밀도로 정규화
- Worker Link 생성 및 응답 처리 시각을 동일한 정밀도로 정규화
- 업데이트 시각이 생성 시각보다 이전이 되지 않도록 보장
- Outbox 및 WorkerLink 통합 테스트의 간헐 실패 방지
- 회사 설정의 approval_policy를 승인 및 반려 권한 판정에 적용
- ADMIN_ONLY 정책에서 HR의 승인·반려를 거부하고 ADMIN만 허용
- 승인 요청 등 기존 HR 쓰기 권한 범위는 유지
- 통합 테스트에 회사 설정 fixture와 정책별 승인·반려 검증 추가
- 테스트 종료 후 fixture를 정리하여 테스트 간 데이터 간섭 방지
- 기존 필수 증빙 baseline 유지
- TaskType별 회사 추가 EvidenceType 충족 여부 검사
- tenant 범위 내 기록된 증빙 종류 조회
- 필수 증빙 누락 시 EVIDENCE_REQUIRED 반환
- 기본 설정 및 복수 필수 증빙 통합 테스트 추가
- 만료시간 검증 하한을 DB의 마이크로초 정밀도로 정규화
- 나노초 단위 차이로 발생하던 간헐 실패 방지
- ADMIN_ONLY에서는 ADMIN만 회사 전체 Audit 검색 허용
- ADMIN_AND_HR에서는 ADMIN과 HR에 검색 허용
- application layer에서 현재 tenant의 audit_visibility 최종 판정
- VIEWER 차단 및 기존 Task 활동 조회 계약 유지
- OpenAPI 설명과 권한별 통합 테스트 보완
- 동일 시각 Audit 이벤트의 비결정적 보조 정렬을 고려해 테스트 안정화
- 회사 설정 PATCH의 실제 부분 수정 요청 예시를 공개한다
- 수정 성공 시 반환되는 전체 설정 응답 예시를 추가한다
- OpenAPI 계약 테스트로 요청 및 응답 예시를 고정한다
@krestar krestar added area:server Spring Boot API·도메인·DB·tenant·Task Workflow 영역; Prompt·모델·Provider 구현 제외 priority:P1 핵심 작업 다음으로 처리할 중요 작업 security:privacy 개인정보·접근권한·토큰·보안 영향이 있는 작업 status:in-review 구현을 마치고 리뷰 또는 병합을 기다리는 작업 type:feature 사용자 또는 Agent가 사용하는 기능 개발 labels Aug 8, 2026

@hywznn hywznn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅇㅣㅅㅏㅇㅇㅓㅂㅅㅅㅡㅂㄴㅣㄷㅏ ㅇㅣㅓㄱ ㅋㅣㅂㅗㄷㅡㄱㅏ ㅇㅣㄹㄷㅏㄴ ㅇㅣㅅㅏㅇㅎㅐㅅㅓ ㅇㅣㄹㅓㅎㄱㅔ ㅂㅗㄴㅐㄷㅗ ㄷㅗㅣㄹㄲㅏㅇㅛ

@krestar
krestar merged commit 9772369 into main Aug 9, 2026
4 checks passed
@krestar
krestar deleted the feat/16-company-settings branch August 9, 2026 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:server Spring Boot API·도메인·DB·tenant·Task Workflow 영역; Prompt·모델·Provider 구현 제외 priority:P1 핵심 작업 다음으로 처리할 중요 작업 security:privacy 개인정보·접근권한·토큰·보안 영향이 있는 작업 status:in-review 구현을 마치고 리뷰 또는 병합을 기다리는 작업 type:feature 사용자 또는 Agent가 사용하는 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Settings] 사업장 설정 조회·수정 API 구현

2 participants