마케팅 문의를 연락처 기준으로 WARP CRM에 자동 등록 - #49
Conversation
|
@OziinG 마케팅 문의의 WARP CRM 자동 등록 기능에 대해 PR #49 및 Issue #48 검토와 운영 반영 승인을 요청드립니다. 신규 연락처는 성함·연락처를 가진 고객으로 등록하고, 기존 고객 한 명과 연락처가 일치하면 프로필을 유지하며 문의 이력만 추가합니다. 여러 고객과 일치하면 자동 처리를 보류하고, 같은 문의의 재전송은 중복 등록하지 않습니다. 변경본 연동 계약과 변경 내용을 검토하신 뒤 운영 반영 승인 여부를 남겨주세요. 승인 시 전용 |
OziinG
left a comment
There was a problem hiding this comment.
검토 결과, 머지 전에 아래 중복 방지 결함을 수정합니다.
- [P2] 동일 UUID의 대소문자 표기를 같은 문의로 처리해야 합니다.
lib/marketing-inquiries.ts:89는 UUID 검증 시 대소문자를 허용하지만 활동 ID를 만들 때 원문을 해시합니다.ABCDEFAB-CDEF-4ABC-8DEF-ABCDEFABCDEF를 먼저 전송한 후 같은 UUID의 소문자 표기를 재전송하면 두 번째 응답이created: true, duplicate: false이고 활동이 추가됩니다. 합성 SQLite 회귀 테스트에서 재현했습니다. 해시 입력의 원본 UUID를 소문자로 정규화하고 재전송 회귀 테스트를 추가하겠습니다. 작은 수신기 결함이므로 이 PR에서 직접 수정합니다.
현재 확인한 검증: 기존 Python 배포 검사 29개, Node 검사 48개, 연동 계약 7개, 타입 검사, 수정 파일 ESLint, 기존 정책의 보안 감사 통과. 별도 코드/구조 검토와 프로덕션 HTTP 검증은 진행 중입니다.
운영은 현재 main 2874eec1199d5e0e04d2b058bf5b8d631245ddcf이며 /api/readyz가 정확한 Revision과 이미지 digest로 정상 응답합니다. SSM /evn-warp/app-env 버전 202에는 전용 마케팅 연결키가 아직 없습니다. 수신기 배포와 발신측 활성화/실제 고객 등록 확인은 구분해 기록하겠습니다. 비밀값과 고객 자료는 기록하지 않았습니다.
|
추가 검토에서 [P1] 독립 서버/DB 연결 간 동시 수신 시 SQLite 잠금이 남는 문제를 재현했습니다. 기존 동시 요청 테스트는 Prisma 클라이언트 한 개만 사용합니다. 독립 클라이언트 두 개 및 프로덕션 빌드의 별도 서버 프로세스 두 개가 같은 SQLite DB에 동일 문의를 보내면 둘 다 503이 반환되었습니다. 독립 클라이언트 테스트에서는 후속 조회·쓰기까지 P1008로 실패했습니다. 직접 수정 범위는 수신기 트랜잭션에 한정합니다. 조회 전에 행을 바꾸지 않는 UPDATE로 SQLite 쓰기 잠금을 확보하고, 트랜잭션 연결의 busy timeout을 0으로 설정해 기존 비동기 재시도가 Node 이벤트 루프를 막지 않도록 했습니다. 전역 DB 설정·스키마·배포 파이프라인은 변경하지 않습니다. 독립 클라이언트의 동시 요청 및 이후 DB 쓰기 회귀 테스트를 추가했으며 현재 11개 수신기 테스트가 통과했습니다. 별도 서버 프로세스 HTTP 재검증과 독립 코드 재검토를 마친 뒤 머지 여부를 확정하겠습니다. 또한 중복 방지 보장은 수신 활동이 보존되는 동안에 적용된다는 점을 계약에 명시하겠습니다. 사용자의 명시적 고객/활동 삭제 후 재전송까지 영구 차단하는 새 저장소는 이번 범위에 추가하지 않습니다. 실제 발신측 활성화는 발신측 계약/키 확인 후 진행할 별도 운영 단계입니다. |
Reserve the writer before phone lookup so concurrent receiver processes cannot deadlock during a deferred transaction upgrade. Canonicalize source UUID spelling and preserve safe failure diagnostics. Constraint: Blue/Green containers share one SQLite database and callers may use dynamic public IPs. Rejected: New receipt schema or global adapter replacement | Receiver-local locking and retained-record semantics satisfy the current contract. Confidence: high Scope-risk: narrow Directive: Keep the writer reservation before reads and preserve whole-transaction asynchronous retries. Tested: 29 deployment Python tests; 51 Node tests; 7 integration endpoints; typecheck; ESLint; security audit; production build; three-process HTTP smoke. Not-tested: Local marketing sender end-to-end delivery and real CRM readback.
OziinG
left a comment
There was a problem hiding this comment.
최종 검토 승인합니다. 검토 대상은 07224a2209f3089e06a67f44905607f9fe0f1cf1입니다.
UUID 대소문자에 따른 중복 등록과 독립 SQLite 연결의 잠금 교착을 수정했고, 실패 rollback·잠금 해제·안전한 오류 로그까지 검증했습니다. 독립 코드 검토는 APPROVE, 구조 검토는 CLEAR이며 미해결 머지 차단 사항은 없습니다.
Python 29개·Node 51개, 연동 계약 7개, 타입 검사·수정 파일 ESLint·보안 감사·프로덕션 빌드와 3개 독립 프로세스 HTTP 검사 9개가 통과했습니다. 중복 방지의 삭제/보관 경계와 동적 Wi-Fi IP 개발자의 공용 HTTPS+전용키 접속 방법을 문서화했습니다.
정규 release 이후 exact main Revision·digest·SSM 버전·공개 인증 응답과 연속 가용성을 확인합니다. 로컬 마케팅 발신기의 실제 문의 전송/CRM readback은 별도 증거가 필요하며, 이번 검토에서 고객 운영 데이터는 수정하지 않았습니다.
|
WARP 수신기 검토·직접 수정·머지·정규 배포·공개 인증 검증과 배포 후 30분 관찰을 완료했습니다.
소스 검증은 Python 29개·Node 51개, 연동 계약 7개, 타입 검사·수정 파일 ESLint·보안 감사·프로덕션 빌드 통과입니다. 별도 서버 프로세스 3개를 사용한 합성 DB HTTP 검사 9개도 통과했습니다. UUID 대소문자 중복과 SQLite read-to-write 잠금 교착을 직접 수정했고, 독립 코드 검토 APPROVE 및 구조 검토 CLEAR를 받았습니다. 가용성 관찰은 위 공개 HTTP 경로의 검사 결과이며 전체 사용자 업무 화면이나 Docker 재시작/OOM 로그 전수 검증을 의미하지 않습니다. 공개 API:
Issue #48은 로컬 마케팅 발신 담당자가 검토된 계약과 키를 적용해 실제 문의 한 건 전달 → 같은 sourceId 재전송 → CRM 고객/이력 확인을 완료할 때까지 열어 둡니다. 그 후 미전달 문의를 처리합니다. 이번 실행에서 실제 고객 등록·일괄 전송은 하지 않았습니다. |
|
@SUMZ711 검토·수정·배포 결과와 로컬 개발 환경에서 진행할 연동 테스트를 아래에 정리합니다. WARP 수신 API의 운영 배포는 완료됐습니다. 이제 로컬 다만 실제 발신기의 문의 전달·재전송·CRM 반영 확인은 아직 수행하지 않았습니다. 이 확인은 Issue #48에 담당자로 배정했으며, 결과를 남길 때까지 Issue를 열어 둡니다. 기존 구현에서 발견한 두 문제는 WARP 측에서 직접 수정했습니다.
DB 오류를 조용히 숨기지 않도록 안전한 오류 코드와 재시도 가능 여부도 기록합니다. 고객 이름·전화번호·API 키·DB 오류 원문은 로그에 남기지 않습니다. 기존 BUILDUP 공유키, DB 스키마, 전역 DB 설정은 변경하지 않았습니다. 로컬에서 사용할 접속 정보는 다음과 같습니다.
Wi-Fi 연결 시 사용하는 동적 공인 IP로 접근할 수 있습니다. 고정 IP나 EIP, VPN, 운영 서버 SSH 접속은 필요하지 않습니다. 전용키는 WARP 운영 SSM에 설정했고, 실제 공개 API에서 키 인증이 동작하는 것까지 확인했습니다. 발신기에 넣을 키는 OziinG에게 별도 보안 경로로 전달받아 주세요. 기존 BUILDUP 키를 재사용하지 않습니다. 키는 로컬 서버/worker 환경에만 주입하고 브라우저 코드·Git 저장소·GitHub 댓글·실행 로그에 넣지 않습니다. 먼저 CRM에 데이터를 쓰지 않는 연결 검사부터 실행해 주세요.
node --input-type=module <<'JS'
const key = process.env.WARP_MARKETING_API_KEY
if (!key) throw new Error('WARP_MARKETING_API_KEY is required')
const response = await fetch(
'https://warp.cleversystem.ai/api/external/marketing-inquiries',
{
method: 'POST',
headers: {
'content-type': 'application/json',
'x-api-key': key,
},
body: '{}',
signal: AbortSignal.timeout(10000),
},
)
const body = await response.json()
if (response.status !== 400 || body.error !== 'bad_payload') {
throw new Error(`Connection check failed: HTTP ${response.status}`)
}
console.log('인증 및 HTTPS 접근 정상: CRM 데이터는 등록하지 않았습니다.')
JS이 연결 검사의 성공 기준은 HTTP 400 / 빈 JSON을 의도적으로 보내므로, 정상 키로 인증을 통과한 뒤 입력 검증에서 거절되는 응답입니다. 연결 오류가 아니며 고객·문의 이력은 생성하지 않습니다.
접속 확인 후에는 최신 계약을 반영하고, 미전달 실제 문의 한 건부터 확인해 주세요. 발신측 계약 문서를 검토된 WARP 계약과 맞추고, 발신측 계약 검사와 전달 테스트를 실행합니다. 이번 검토에서는 로컬 요청은 아래 9개 필드만 사용하며 모두 문자열입니다.
확인 순서는 아래와 같습니다.
참고로 중복 방지는 수신 활동이 보관돼 있는 동안에 적용됩니다. 고객이나 수신 활동을 명시적으로 삭제하면 중복 방지 기록도 없어지므로, 이후 같은 문의를 보내면 고객 또는 활동이 다시 생성될 수 있습니다. 테스트 후 Issue #48에 아래 결과를 남겨주시면 연동 완료 여부를 확인할 수 있습니다.
결과에는 API 키와 고객 개인정보를 넣지 않습니다. 이번 WARP 배포의 최종 커밋은 |
마케팅 수집기의 문의를 전용 인증키로 받아 WARP CRM에 등록합니다. 신규 기본 연락처는 B2C 잠재고객으로 만들고, 동일 연락처의 기존 고객이 한 명이면 프로필을 보존하며 문의 이력만 추가합니다. 여러 고객의 연락처가 겹치면 409로 보류합니다.
원본 UUID의 대소문자를 정규화해 동일 문의의 재전송이 중복 이력을 만들지 않도록 했습니다. 독립 서버 프로세스가 공유 SQLite에 동시에 쓰는 경우에는 읽기 전에 writer를 확보하고 전체 트랜잭션을 비동기로 재시도합니다. 실패한 append는 원자적으로 rollback하며, 서버 로그에는 허용된 오류 코드와 재시도 여부만 남깁니다.
공용 HTTPS API는 IP 허용목록 없이 전용키로 인증합니다. 로컬 개발자는 동적 Wi-Fi 공인 IP로 접속할 수 있고 고정 IP/EIP는 필요하지 않습니다. 고정된 원본 범위와 16KB 요청 제한을 적용하며 기존 BUILDUP 키·DB 스키마·전역 DB 설정은 변경하지 않습니다. 삭제된 활동의 재전송까지 영구 차단하지 않는 보관 기간 기준의 중복 방지 계약을 명시했습니다.
검증 (
07224a2209f3089e06a67f44905607f9fe0f1cf1):배포는 OziinG 검토 후 정확한 main에서 기존
release파이프라인으로 수행합니다. 배포 Revision·이미지 digest·SSM 버전·공개 인증 검증·관찰 결과는 댓글로 기록합니다. 담당자 연결 안내와 CRM 쓰기 없는 인증 확인 명령은docs/integrations/WARP_MARKETING_INQUIRIES.md에 있습니다.실제 로컬 마케팅 발신기의 문의 전송·재전송·CRM readback 및 미전달 일괄 처리는 발신 담당자의 연동 확인 단계로 남깁니다. 이 PR의 WARP 배포와 실제 수집 완료를 구분하기 위해 Issue #48은 계속 열어 둡니다.
Refs #48