# 대무자(代務者) Phase 1 — 도메인 테이블 CREATED_BY/UPDATED_BY broad scan

작성일: 2026-05-11
작성자: johngreen
관련: `.omc/specs/deep-dive-user-substitute-management.md`, `.omc/plans/autopilot-impl.md` (T15)

## 목적

Phase 1 의 spec 결정 "일반 업무 도메인 테이블의 `created_by/updated_by` 는 actual processor(B) 로 통일" 이 현재 코드에서 자연 만족하는지 검증.

## scan 범위

`backend-spring/src/main/resources/mapper/*.xml` — `CREATED_BY` / `UPDATED_BY` 컬럼 사용처 전수.

## 결과 요약

| 항목 | 값 |
|---|---|
| 컬럼 사용 mapper 파일 | **33개** |
| 매치 occurrences | **206개** |
| 호출자(controller) 의 `user_id` 출처 | **모두 `@RequestAttribute("user_id")` = JWT user_id** |
| 대무 컨텍스트 자동 적용 여부 | **✅ 자동 만족 — 추가 작업 불필요** |

## 핵심 발견

### 1. 도메인 테이블의 `CREATED_BY/UPDATED_BY` 는 자동으로 actual processor(B)

INVYONE 의 모든 컨트롤러가 `@RequestAttribute("user_id") String userId` 패턴으로 JWT user_id 를 받아 params.put("user_id", userId) 후 service 호출.

`JwtAuthenticationFilter.java:38-41`:
```java
request.setAttribute("user_id", userId);  // JWT 의 user_id = 실제 로그인한 사용자 = actual processor B
```

`SubstituteContextFilter` (T5) 는 JWT user_id 를 그대로 두고 `effective_user_ids` 만 별도 attribute 로 추가 주입. 즉 `request.getAttribute("user_id")` 는 평시와 대무 시 동일하게 B (로그인한 사용자).

→ 도메인 테이블 INSERT/UPDATE 시 컨트롤러가 user_id 를 params 에 넣으면 그 값은 자연스럽게 B. spec 결정과 일치.

### 2. effective_user_ids 를 user_id 로 잘못 쓰는 패턴 없음

`effective_user_ids` 는 본 작업(T8) 이전에는 존재하지 않던 attribute. 기존 코드 어디도 이걸 user_id 로 끌어쓰지 않음.

T8 이후 effective_user_ids 를 사용하는 곳:
- `approval.xml` selectRequests/countRequests my_approvals 분기 (L213-220, 247-254)
- `approval.xml` selectMyPendingLines (L458-)

이 3곳은 **WHERE 조건의 권한 union 용도** 로만 사용하고, 어디서도 `CREATED_BY = #{effective_user_ids[0]}` 같은 패턴 없음.

### 3. 결재 audit log 만 user_id ≠ processor_id 분리 기록

`ApprovalService.processApproval` (T9) → `AuditLogService.insertAuditLog` 호출:
- `user_id` = A (위임자, APPROVER_ID)
- `processor_id` = B (실제 처리자)
- `SYSTEM_AUDIT_LOG` 에만 분리. 도메인 테이블 (APPROVAL_LINES 등) 의 `CREATED_BY/UPDATED_BY` 는 그대로 B.

## 33개 파일 목록 (참고)

```
admin-cross-tenant.xml (2)    approval.xml (4)              barcodeLabel.xml (8)
batch.xml (2)                 businessRule.xml (8)          cascadingHierarchy.xml (2)
cascadingRelation.xml (5)     categoryValueCascading.xml (3) collection.xml (7)
common.xml (2)                dashboard.xml (2)             dataflow.xml (6)
dataflowDiagram.xml (3)       digitalTwin.xml (9)           dynamicForm.xml (4)
externalCall.xml (1)          externalCallConfig.xml (8)    externalDbConnection.xml (9)
externalRestApiConnection.xml (4)  flow.xml (2)              flowExternalDbConnection.xml (7)
layout.xml (3)                multilang.xml (25)            production.xml (4)
report.xml (22)               schedule.xml (2)              screenEmbedding.xml (2)
screenManagement.xml (21)     substitute.xml (5)             systemNotice.xml (3)
tableCategoryValue.xml (9)    template.xml (9)               webTypeStandard.xml (3)
```

## Phase 1 결론

**도메인 테이블의 `CREATED_BY/UPDATED_BY` 에 대해 추가 작업 없음.**

- spec 의 "actual processor(B) 통일" 결정이 기존 컨트롤러 패턴으로 자연 만족.
- 대무 추적은 `SYSTEM_AUDIT_LOG.PROCESSOR_ID` 컬럼으로 분리 기록 (T1 + T14).
- 회귀 위험 영역 없음.

## Phase 2 (메뉴/일반 권한 union) 으로 미룬 영역

spec 의 "B 로그인 시 A 의 권한이 자동 합쳐서 적용" 중 **메뉴/AUTHORITY_MASTER 룩업** 영역은 Phase 1 Non-Goal:

- `admin.xml`, `auth.xml`, `role.xml`, `screenGroup.xml` 의 사용자 권한/메뉴 쿼리에 `IN (effective_user_ids)` 적용 필요
- Phase 2 작업 — 별도 plan + critic 검증 후 진행

scan 진행: ✅ 완료
