PreprocessorService::run | end - {"stack":"HTTPError: Response code 403 (Forbidden)
RCA: PreprocessorService::run | HTTPError 403 (Forbidden) on BIM mesh download
Overview#
What Happened#
2026-04-28 16:03:28 UTC, cupixworks-deviation-preprocessor-agent 서비스에서 deviation job 1040523 처리 중 BIM 19181의 mesh 파일 다운로드 시 Tesla 내부 API로부터 403 Forbidden 응답을 받아 전체 job이 실패했다. 단건 발생이며 사용자 msullivan@sebastiancg.com (team: sebastiancg)의 세션으로 인증된 상태에서 발생했다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | HTTPError |
| exception.message | Response code 403 (Forbidden) |
| top_frame | got/dist/source/core/index.js:913 (library), actual call site: BasePreprocessorRunner::downloadFile |
| env | production, us-west-2 |
Timeline#
- 16:03:28.235Z — SQS 메시지 수신, job 1040523 처리 시작
- 16:03:28.294Z — 세션 인증 완료 (session_id: d871516f...)
- 16:03:28.500Z — deviation 9878 로드 완료, BIM mesh 다운로드 단계 진입
- 16:03:28.766Z — BIM 19181 mesh download에서 403 Forbidden 발생
- 16:03:28.767Z —
PreprocessorService::run에러 전파, job 실패 처리 - 16:03:28.972Z — workspace 정리 완료, SQS 메시지 삭제 (재시도 없음)
Error Log#
PreprocessorService::run | end - {"stack":"HTTPError: Response code 403 (Forbidden)
at Request._onResponseBase (/tmp/agent/dist/node_modules/got/dist/source/core/index.js:913:31)
at Request._onResponse (/tmp/agent/dist/node_modules/got/dist/source/core/index.js:948:24)
at ClientRequest.<anonymous> (/tmp/agent/dist/node_modules/got/dist/source/core/index.js:962:23)
...","message":"Response code 403 (Forbidden)","name":"HTTPError","code":"ERR_NON_2XX_3XX_RESPONSE"}
Impact#
- Service:
cupixworks-deviation-preprocessor-agent - Team: sebastiancg
- 발생 횟수: 1
- 최초 발생: 2026-04-28T16:03:28.767Z
- 최근 발생: 2026-04-28T16:03:28.767Z
Root Cause Summary#
사용자 msullivan@sebastiancg.com의 세션 토큰으로 인증된 deviation preprocessor agent가 BIM 19181의 mesh 파일을 Tesla 내부 API(/api/v1/bims/19181/resources/mesh/download)에서 다운로드하려 했으나, 해당 사용자에게 이 BIM 리소스에 대한 read 권한이 없어 Pundit policy check에서 PermissionDenied (403)가 반환되었다. Agent는 SQS 메시지에 포함된 사용자 세션으로 인증하므로, 사용자의 BIM 접근 권한이 없거나 제거된 경우 이 에러가 발생한다.
Technical Analysis#
Code Path#
- Entry point:
base-service.ts:153—runByMessageSQS 메시지 처리 - Authentication:
base-service.ts:194—authenticateByMessage사용자 세션 토큰으로 인증
private authenticateByMessage = async (msgObject: any): Promise<void> => {
logger.debug('BaseService::authenticateByMessage | begin');
this.cupixAuth.setAuthParams({
encodedAuthParams: msgObject.encoded_auth_params,
session: msgObject.session
});
await this.cupixAuth.startSession();
logger.debug('BaseService::authenticateByMessage | end');
};
- Token construction:
cupix-auth.ts:192— 세션 정보로_sessionToken생성
get accessToken(): string | undefined { return this._sessionToken ? this._sessionToken : this.currentToken?.access_token; }
// ...
this._sessionToken = `session_token:${params.session.token},session_id:${params.session.id}`;
- Download URL 구성:
cpbim.ts:61— BIM ID로 다운로드 URL 생성
private initialize = (): void => {
const idStr = this.id.toString();
this._meshArchiveFileDownloadUrl = CPX_API_ENDPOINT + '/bims/' + idStr + '/resources/mesh/download';
// ...
};
- Failure point:
base-preprocessor-runner.ts:114—got.stream.get으로 다운로드 요청
const downloadStream = got.stream.get(downloadItem.url, {
isStream: true,
headers: {
'X-CUPIX-AUTH': accessToken
}
} as any);
- Tesla API authorization:
application_policy.rb:38-73— Punditread?policy에서applied_permission확인
def read?
return true if user.member_of_admin_groups?(%w[administrator senior_editing_engineers])
if record.has_attribute?(:applied_permission)
if record.applied_permission[1] == 1 || record.applied_permission[0] == 1 || record.applied_permission[4] == 1
true
else
false
end
end
end
기대 동작: 사용자 세션으로 BIM mesh를 다운로드할 수 있어야 함. 실제 동작: Tesla API가 해당 사용자에게 BIM 19181 리소스에 대한 read 권한이 없다고 판단하여 403 반환.
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-deviation-preprocessor-agent status:error @environment:production
service:cupixworks-deviation-preprocessor-agent @environment:production
핵심 에러 로그 (16:03:28.766Z):
{
"message": "BasePreprocessorRunner::downloadFile | error_download",
"url": "http://api-tesla.cupix.internal/api/v1/bims/19181/resources/mesh/download",
"path": "/tmp/workspace/9878/input_data/bim_model/19181/mesh.zip",
"error": "HTTPError: Response code 403 (Forbidden)",
"code": "ERR_NON_2XX_3XX_RESPONSE"
}
컨텍스트 속성:
{
"job.id": 1040523,
"deviation.id": 9878,
"bim.id": 19181,
"team.id": 1184,
"team.domain": "sebastiancg",
"user.id": 45497,
"user.email": "msullivan@sebastiancg.com",
"session.id": "d871516f2f950c57a54e5ee826b17d86d5071d27"
}
타임라인 핵심 포인트:
- 16:03:28.294Z — 세션 인증 성공 (세션 자체는 유효)
- 16:03:28.537Z — deviation 9878 조회 성공 (deviation 접근 권한 있음)
- 16:03:28.766Z — BIM 19181 mesh download 실패 (BIM 리소스 접근 권한 없음)
이 패턴은 deviation에 연결된 BIM이 사용자가 접근할 수 없는 workspace/facility에 속하거나, 해당 BIM의 review 또는 facility-level 권한이 제거된 경우에 발생한다.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | 사용자에게 BIM 19181에 대한 read 권한 부족 (Pundit policy applied_permission 미충족) |
세션 인증 성공 (16:03:28.294Z), deviation 조회 성공 (16:03:28.537Z), but BIM download만 403. Tesla API는 Pundit.policy(current_user, model).read? false 시 403 반환. |
— | Confirmed |
| H2 | 세션 토큰 만료 또는 무효 | — | CupixAuth::setSession 로그에서 세션 성공, deviation API 호출도 성공. 토큰 만료였다면 모든 API 호출이 실패했을 것. |
Rejected |
| H3 | BIM 19181 리소스(mesh)가 존재하지 않아 404 반환 | — | 응답 코드가 403이지 404가 아님. Tesla는 리소스 미존재 시 revision == 0 체크로 404를 반환함. |
Rejected |
| H4 | Agent가 X-CUPIX-AUTH 헤더를 잘못 설정 |
downloadFile에서 accessToken을 직접 전달 (base-preprocessor-runner.ts:117) |
accessToken getter가 유효한 _sessionToken을 반환함 (세션 인증 성공으로 확인). 다른 API 호출은 정상 동작. |
Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
- 데이터 확인: BIM 19181이 사용자 45497 (team 1184)가 접근 가능한 facility/workspace에 속하는지 Tesla DB에서 확인 필요.
- 이 에러는 사용자 권한 문제로, agent 코드 버그가 아닌 데이터/권한 설정 이슈일 가능성이 높다. 사용자에게 BIM 접근 권한을 부여하면 즉시 해결될 수 있다.
단기 개선 (1주 이내)#
DeviationReportRunner::downloadFiles에서 403 에러 발생 시 어떤 BIM/리소스가 권한 부족인지 명확한 에러 메시지를 로깅하도록 개선. 현재는 genericerror_download로그만 남겨 디버깅이 어렵다.preprocessor-service.ts:93-96의 catch 블록에서 403 에러를 별도 처리하여warn레벨로 "permission denied for BIM {id}" 메시지를 남기고,updateErrorActionJob시 구체적인 에러 코드를 전달하는 방향 검토.
장기 개선 (재발 방지)#
- Deviation 생성/큐잉 시점에 참조된 모든 BIM 리소스에 대한 사용자 권한을 사전 검증(pre-flight check)하여, 권한 없는 리소스가 포함된 job이 agent까지 도달하지 않도록 방지.
- Agent에서 사용자 세션 대신 시스템 서비스 계정(admin token)으로 파일 다운로드를 수행하는 아키텍처 검토. 현재 사용자 세션 기반 인증은 사용자 권한 변동에 취약하다.
Monitoring#
- 추가할 메트릭: BIM download 403 발생 빈도 by team/user
- Datadog 쿼리:
service:cupixworks-deviation-preprocessor-agent "error_download" "403"
- 동일 패턴 반복 시 특정 team/user의 권한 설정 문제를 사전 탐지 가능.
Risk Assessment#
- Risk level: low
- 예상 복잡도: trivial
- 단건 발생이며 특정 사용자의 권한 이슈로 판단. 시스템 전반에 영향을 주는 버그가 아니라 데이터/권한 설정 문제.