keeper-out 1만원 게이트 통합 설계v3

2026-05-05 23:55 (승인 2026-05-06) · 24h 휴먼 승인 큐 + TM 1차 / 자동님 2차 fallback · 상태 ✅ 자동님 승인 — 대시보드 에이전트 작업 진입 가능 · in-repo entry docs/keeper-out/anti-abuse/06-p3-implementation-brief.md
✅ 승인 (2026-05-06)

자동님 한 줄 회신 verbatim: "오키 좋다. 지금 승인하고 문서화하면 얘네가 보면될거같아"

★ v2 → v3 핵심 변경 (자동님 2026-05-05 23:30 결정)

목차

  1. 한 줄 요약 (v3)
  2. 왜 휴먼 승인이 필요한가 — 해커 위협 모델 갱신
  3. 24h 큐 — 정확한 timeline + 정책
  4. 휴먼 승인 흐름 — 누가 / 어떻게 / 어디서
  5. UX — 사장님 / TM / 자동님 / ALL HOLD
  6. 검증 차원 V1~V12 (V12 휴먼 승인 신설)
  7. 3-layer 통합 스키마 (v2 유지)
  8. 병렬 세션 진척 (P1 박힘)
  9. P3 마이그레이션 — 누락 zero
  10. P3 API endpoint 명세
  11. P3 admin UI — 신규 페이지 + 섹션
  12. 대시보드 에이전트 작업 룰 (필독)
  13. Phase 분할 — P1·P1.5·P2·P3·P4
  14. 측정 KPI
  15. 결정 6건 누적
  16. 미해결 정책 결정 1건
  17. 참조 — 보고서 체인 + in-repo 문서

01.한 줄 요약 (v3)

1만원 N페이는 자동 즉시 발송 X → 24시간 내 휴먼 승인 후 발송으로 바뀐다. 영업원 출장 종료 시점에 진단은 pending_review 상태로 큐 진입, TM(콜센터)가 사장님께 routine follow-up 콜을 거치며 통화 결과를 admin에 입력하면 그 시점에 [💸 발송 확인] 버튼 활성화되고 클릭 → Giftishow 발송. TM이 6시간 안에 처리 못한 건은 자동님 admin pending 큐로 escalate되어 일괄 검토. 공격 발생 시 자동님이 [ALL HOLD] 1클릭으로 모든 발송 일시 정지. 이 방식은 키퍼메이트의 ①룰(연락 가능)·③룰(도입 의향)을 콜로 자연 검증하면서, 해커 침투·잔액 노출 시 인간이 끼어들 시간을 확보한다.

02.왜 휴먼 승인이 필요한가 — 해커 위협 모델 갱신

v1·v2까지의 위협 모델은 어뷰징 위주(사례비 헌터, 봇, 영업원 본인 어뷰징). 어뷰징은 단가 높고 빈도 낮아 자동 게이트로 충분.

⚠ T11 — 해커 침투 (v3 신규)

특성: 어뷰징과 다른 클래스. 단가는 작지만(건당 1만원) 빈도가 폭발적(분당 N건). API key leak·관리자 세션 탈취·SIM swap 시:

★ 자동 게이트의 한계

위협 모델 v3 — Actor × Scenario 갱신

IDActor시나리오v1·v2 차단v3 차단
T1외부 사례비 헌터폰 N개로 무한 제출V3·V4+ V12 휴먼 승인
T2외부 봇/스크립트API 자동 POSTV3·V5+ V12 휴먼 승인
T3영업원 본인 어뷰징본인/지인 폰 5대V3·V7+ V12 (TM이 모르는 폰 콜 시 발견)
T4·T5실수/사장 어뷰징중복V4+ V12
T6·T7매장 미방문/거짓 데이터V2·V6V2·V6+ V12 (TM 콜 안 받음)
T9·T10잔액 cross-bleed/사일런트 실패V5V5 + 승인 직전 재확인강화
T11 ★ 신규해커 침투API leak로 잔액 빼내기막을 수 없음V12 휴먼 승인 + ALL HOLD

03.24h 큐 — 정확한 timeline + 정책

T0 (영업원 출장 종료 + 사장님 진단 완료)
큐 진입
모든 게이트(V1 OTP, V2 GPS, V3 영업원 코드, V4 unique, V5 잔액, V8 place 실재성) 통과. leads INSERT, payouts.naver_pay_10k status='pending_review', funnel_event 'review.queued'. 사장님께 안내 SMS 발송 (다음 §05 참조).
T+0 ~ T+6h (TM 콜센터 routine)
1차 승인 — TM follow-up 콜
TM이 admin /keeper-out/admin/pending 큐 카드 보고 사장님께 콜. 통화 outcome 입력 → outcome 'confirmed' 시 [💸 발송 확인] 버튼 활성화 → Giftishow 호출.
T+6h ~ T+20h (TM 미처리 건 escalate)
자동님 admin fallback 큐
6h 안에 TM이 outcome 입력 못한 건은 자동님 admin pending 큐로 자동 이동. 자동님이 일괄 검토 + 일괄 [✓ 승인] 또는 [⨯ 거부].
T+20h ~ T+24h (24h 임박)
최종 처리
자동님 텔레그램 alarm — "X건 24h 임박, 미승인". 자동님이 마지막 처리. 20~24h 미승인 건 정책 (자동님 결정 대기):
(a) 자동 dispatch fallback — 다른 게이트 모두 통과 + 패턴 정상 시 자동 발송
(b) 사장님께 "추가 확인 필요" 안내 + 영업원 재방문 요청
T+24h+ (사후 검수 dual-layer 시작)
영업원 30k 인센 회수 윈도우
v2 §07의 dual-layer. GET /v1/account/admin/users?phone={leads.phone} → ②룰(가입) + ③룰(subscribes) 통과 시 payouts.lead_30k status='confirmed'. 미통과 시 영업원 invalid률 누적 + 7일/30일 후 final invalidate.

큐 cap (해커 차단)

cap 종류임계값위반 시
분당 발송≥ 10건자동 ALL HOLD + 자동님 텔레그램 즉시 alarm
시간당 승인≥ 30건승인 일시정지 30분 + admin alarm
일별 승인≥ 200건당일 승인 차단 (영업원 7명 × 25/일 = 175 base + buffer)
잔액 임계< ₩50,000승인 차단 + 자동님 충전 요청
같은 IP 1h≥ 5건해당 IP 진단 신규 진입 차단
같은 agent 24hinvalid률 > 30%agent.active=false 자동 + admin alarm

04.휴먼 승인 흐름 — 누가 / 어떻게 / 어디서

1차 승인자 — TM 콜센터 (이서경 등 발레리온 직원)

2차 승인자 — 자동님 admin fallback (TM 6h 미처리 건)

TM이 처리 못한 건은 자동님 admin /keeper-out/admin/fallback 큐로 escalate. 자동님은 일괄 [✓ 모두 승인] 또는 카드별 검토. 자동님 부담 절감 — TM 정상 운영 시 fallback 큐는 거의 비어있어야 함.

거부 사유 enum (TM·admin 공통)

outcome 값의미다음 액션
confirmed사장님 본인 + 진단 인지 + 도입 의향[💸 발송 확인] 버튼 활성화
no_answer3회 콜 무응답4시간 후 재시도 큐 / 자동님 escalate
not_owner본인 매장 아님 / 진단 모름거부 + 영업원 alarm + V7 fraud_signal 'wrong_owner'
rejected관심 없음 명시 + 발송 거부거부 + payouts invalid + 영업원 invalid률 누적
fraud_suspect의심스러운 응답 패턴거부 + V7 fraud_signal 'tm_suspect' + 자동님 alarm
wrong_phone틀린 폰번호 / 전화 불통거부 + 영업원 데이터 입력 오류 alarm

05.UX — 사장님 / TM / 자동님 / ALL HOLD

5-1. 사장님 진단 종료 화면

사장님 — /diagnose 종료 직후
✅ 진단 완료! 매장 보안 진단에 협조해 주셔서 감사합니다. 📞 본사 콜센터에서 곧 연락드릴 예정이에요 "진단 잘 받으셨어요?" 짧은 확인 통화입니다 💸 1만원 N페이 (입력하신 010-XXXX-XXXX번호) 본사 확인 콜 종료 후 24시간 내 발송됩니다 🔒 보안을 위해 자동 즉시 발송이 아닌 본사 확인 후 발송하는 정책으로 운영하고 있어요 [확인]

5-2. 사장님 안내 SMS (T0 직후 발송)

사장님 폰 SMS — balerion.cloud SMS proxy
[키퍼] 진단 협조 감사합니다. 본사 콜센터 확인 후 24시간 내 1만원 네이버페이를 입력하신 폰으로 보내드릴 예정이에요. 문의: 1670-5772 [수신거부 080-XXX-XXXX]

5-3. TM 화면 — admin /keeper-out/admin/pending

TM (이서경 등 발레리온 콜센터)
📋 1만원 발송 대기 큐 — 24h 내 처리 (45건) ───────────────────────────────────────── ☐ 이정희 사장님 · 아지트 (구리시) 📞 010-3111-1165 · 영업원 K9bR2(원희연) 진단 시작 1h 23m 전 · 카메라 5대 ₩395k/월 pain: 출동지연·앱불편 [📞 콜 시작] [📋 사장님 진단 미리보기] ───────────────────────────────────────── ☐ 송진학 사장님 · 돈락 (대전) 📞 010-6427-8756 · 영업원 m2K9b(조세종) 진단 5h 12m 전 · ⚠ 5h 경과 (1h 후 escalate) [📞 콜 시작] [📋 미리보기] ───────────────────────────────────────── [💸 일괄 발송 확인 (1건 선택됨)] [ALL HOLD ⏸] (관리자만)

5-4. TM 콜 outcome 입력 모달

TM — 통화 종료 후
📞 통화 결과 입력 — 이정희 사장님 콜 진행 시간: 2분 14초 통화 결과: ⦿ confirmed — 사장님 본인 + 진단 인지 + 도입 의향 ○ no_answer — 3회 무응답 ○ not_owner — 본인 매장 아님 ○ rejected — 관심 없음 ○ fraud_suspect — 의심 ○ wrong_phone — 틀린 번호 메모 (50자): [ "통화 완료, 견적 안내 받기 OK" __________ ] [💸 1만원 발송 확인] [취소]

5-5. 자동님 admin fallback 화면

자동님 (또는 PM) — /keeper-out/admin/fallback
📋 자동님 fallback 큐 — TM 6h 미처리 (12건) ───────────────────────────────────────── ☑ 김수지 사장님 · 스튜디오수지 (김해) 📞 010-3018-0254 · 영업원 K9bR2(원희연) T+8h 12m 경과 · TM 무응답 3회 ───────────────────────────────────────── ☑ 채정연 사장님 · 스마일 (대구) 📞 010-6864-1296 · 영업원 m2K9b(조세종) T+10h 03m 경과 · TM 무응답 3회 ───────────────────────────────────────── ☐ 강홍원 사장님 · 빅파이브 먹골역점 (서울) 📞 010-5000-8858 · ⚠ V7 패턴 alarm: 같은 IP 3건 ───────────────────────────────────────── [✓ 선택 2건 일괄 승인] [⨯ 선택 거부] [ALL HOLD ⏸ — 발송 일시 정지]

5-6. ALL HOLD — 비상 정지 메커니즘

⏸ ALL HOLD 정확한 동작

06.검증 차원 V1~V12 (V12 휴먼 승인 신설)

V이름막는 위협티어
V1본인성 — SMS OTPT1·T2·T3·T5MUST
V2현장성 #1 — GPS × place ≤200mT2·T4·T6MUST
V3영업원 이름+5자리 코드 (지원금 받기 클릭 후)T3·T6·T7MUST
V4유일성 — naver_place_id NOT NULL + phone uniqueT5·T8MUST
V5예산 — 잔액 preflight + cap (승인 직전 재확인)T2·T9·T10MUST
V6사진 EXIF 시간 검증T6·T7SHOULD
V7패턴 이상치 탐지 cron + admin alarmT3·T7 누적·T11SHOULD
V8매장 실재성 외부 검증T6·T8SHOULD
V9디바이스/IP 핑거프린팅 (기록만)T2·T11NICE
V10CAPTCHA / TurnstileT2OUT (인바운드만)
V11사업자번호 NICE/홈택스T6OUT
V12 ★ v3 신규휴먼 승인 (TM 1차 + 자동님 2차)T11 + 모든 위협 일괄 차단MUST
★ V12가 다른 차원과 직교한 이유

07.3-layer 통합 스키마 (v2 유지)

┌─────────────────────────────────────────────────────────────────────────────┐ │ L1 — keeper-out 자체 DB Supabase hvcrbdpjxfszhwrtcygq │ │ keeper_outbound_leads │ │ pain_points · photo_urls · agent_1/2/3 FK · place_id · owner_id │ │ payout_status = pending_review/pending_dispatch/sent/invalid ★ v3 │ │ tm_outcome · tm_called_at · approved_by · approved_at ★ v3 신규 │ │ │ │ │ ├──→ agents · payouts · funnel_events │ │ ├──→ visit_logs · places · owners (P2) │ │ └──→ otp_sessions · fraud_signals · approval_queue (P3) │ └──────────────┬──────────────────────────────────────────────────────────────┘ │ phone match (사후 검수 ②③룰) ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ L2 — 키퍼 admin api-account.keeperplatform.com 권한 ceo@bizdirect │ │ User OWNER (4136명) → mobile · subscribes · shopName │ │ Order (42건) → status (접수→일시확정→완료) │ └──────────────┬──────────────────────────────────────────────────────────────┘ │ ?ref={code} URL attribution ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ L3 — Referio referio.puzl.co.kr 자동님 코드 86Af9 │ │ Partner · 보상 1.5만+2만 / 4티어 / 어뷰징 정책 차용 │ └─────────────────────────────────────────────────────────────────────────────┘

08.병렬 세션 진척 (P1 박힘)

e8f22edfeat(keeper-out/admin): lead detail view P1 (8섹션)
+654 줄 — LeadDetailClient.tsx + page.tsx + PipelineRow + AppHeader
dc4d9a0feat(keeper-out/admin): lead GET endpoint with PostgREST embed
+47 줄 — lead/[id]/route.ts (GET) + types.ts (LeadDetail)
dbba9d1feat(keeper-out): /diagnose pain_points·pain_note 백엔드
+18 줄 — migration + types.ts + diagnose/route.ts

P1.5/P2 대기, P3(휴먼 승인)가 이번 v3에서 신규.

09.P3 마이그레이션 — 누락 zero

-- supabase/migrations/2026MMDD_keeper_outbound_anti_abuse_v3.sql
-- v3: 휴먼 승인 큐 + 어뷰징 가드 풀 박기

-- ============================================================
-- 1. agents 테이블 — 영업원 코드 + Referio 매핑 + invalid률
-- ============================================================
alter table public.keeper_outbound_agents
  add column if not exists code text,                   -- ★ 5자리 영숫자 mixed case (예: K9bR2)
  add column if not exists referio_partner_id text,      -- 86Af9 매핑
  add column if not exists keeper_partner_id int,         -- 향후 키퍼 partners 통합
  add column if not exists kakao_user_id text,           -- 향후 SSO
  add column if not exists invalid_rate_30d numeric default 0,
  add column if not exists day_cap_count int default 0,
  add column if not exists week_cap_count int default 0,
  add column if not exists last_active_at timestamptz;

create unique index if not exists uniq_agent_code
  on public.keeper_outbound_agents(code) where code is not null;

-- ============================================================
-- 2. leads 테이블 — V4 강화 + 휴먼 승인 컬럼 + 핑거프린팅
-- ============================================================
alter table public.keeper_outbound_leads
  -- V4 유일성
  alter column naver_place_id set not null,                -- 자동완성 통과 강제

  -- 휴먼 승인 트래킹
  add column if not exists tm_called_at timestamptz,
  add column if not exists tm_outcome text check (tm_outcome in
    ('confirmed','no_answer','not_owner','rejected','fraud_suspect','wrong_phone')),
  add column if not exists tm_note text,
  add column if not exists approved_by uuid references auth.users(id),
  add column if not exists approved_at timestamptz,
  add column if not exists approval_tier int,                  -- 1=TM, 2=admin fallback, 3=auto-fallback

  -- 핑거프린팅 (V9)
  add column if not exists ip_address inet,
  add column if not exists user_agent text,

  -- L2 매칭 캐시 (사후 검수)
  add column if not exists external_user_id int,
  add column if not exists external_subscribed_at timestamptz,
  add column if not exists external_checked_at timestamptz;

-- phone unique lifetime (V4)
create unique index if not exists uniq_leads_phone
  on public.keeper_outbound_leads(phone);

-- ============================================================
-- 3. payouts — payout_status 확장
-- ============================================================
alter table public.keeper_outbound_payouts
  drop constraint if exists keeper_outbound_payouts_status_check,
  add constraint keeper_outbound_payouts_status_check check (status in
    ('pending','pending_review','pending_dispatch','sent','failed','invalid','on_hold'));

-- ============================================================
-- 4. OTP 세션 (V1)
-- ============================================================
create table if not exists public.keeper_outbound_otp_sessions (
  id uuid primary key default gen_random_uuid(),
  phone text not null,
  code char(6) not null,
  expires_at timestamptz not null,
  attempts int default 0,
  verified_at timestamptz,
  ip_address inet,
  user_agent text,
  created_at timestamptz default now()
);
create index idx_otp_phone_active on public.keeper_outbound_otp_sessions(phone)
  where verified_at is null;

-- ============================================================
-- 5. 어뷰징 신호 (V7)
-- ============================================================
create table if not exists public.keeper_outbound_fraud_signals (
  id uuid primary key default gen_random_uuid(),
  lead_id uuid references public.keeper_outbound_leads(id) on delete cascade,
  agent_id uuid references public.keeper_outbound_agents(id),
  rule text not null,                                  -- self_referral / unknown_responses /
                                                          --   cluster / wrong_owner / tm_suspect / all_hold
  severity text check (severity in ('low','med','high')),
  payload jsonb,
  resolved_at timestamptz,
  resolved_by uuid references auth.users(id),
  resolution_note text,
  flagged_at timestamptz default now()
);
create index idx_fraud_lead on public.keeper_outbound_fraud_signals(lead_id);
create index idx_fraud_unresolved
  on public.keeper_outbound_fraud_signals(severity, flagged_at desc)
  where resolved_at is null;

-- ============================================================
-- 6. 시스템 캡 (해커 차단 + 운영 안전)
-- ============================================================
create table if not exists public.keeper_outbound_system_state (
  key text primary key,                                 -- 'all_hold' / 'minute_count' / 'hour_count' /
                                                          --   'day_count' / 'last_balance_check_at'
  value jsonb not null,
  updated_at timestamptz default now()
);

-- ============================================================
-- 7. RLS
-- ============================================================
alter table public.keeper_outbound_otp_sessions enable row level security;
alter table public.keeper_outbound_fraud_signals enable row level security;
alter table public.keeper_outbound_system_state enable row level security;

create policy "service_all_otp" on public.keeper_outbound_otp_sessions
  for all to service_role using (true) with check (true);
create policy "service_all_fraud" on public.keeper_outbound_fraud_signals
  for all to service_role using (true) with check (true);
create policy "service_all_system" on public.keeper_outbound_system_state
  for all to service_role using (true) with check (true);

10.P3 API endpoint 명세

methodpath역할auth
POST/api/keeper-out/diagnose/request-otpV3·V4·V5·V8·V2 통과 시 OTP 발송익명 (RLS)
POST/api/keeper-out/diagnose/verifyV1·V6 통과 시 leads INSERT + 큐 진입익명
GET/api/keeper-out/admin/pendingTM 큐 조회 (24h 내 미처리)admin
POST/api/keeper-out/admin/leads/[id]/tm-callTM 통화 outcome 입력admin
POST/api/keeper-out/admin/leads/[id]/dispatch승인 후 Giftishow 발송 (잔액 재확인)admin
POST/api/keeper-out/admin/leads/[id]/reject거부 (사유 enum)admin
GET/api/keeper-out/admin/fallback자동님 fallback 큐 (TM 6h 미처리)admin (PM+)
POST/api/keeper-out/admin/dispatch/all-holdALL HOLD on/offadmin (PM+)
GET/api/keeper-out/admin/leads/[id]/externalL2 admin User phone match (사후 검수)admin
POST/api/keeper-out/cron/recheck-completion24h cron — 외부 매칭 + payouts 확정service
POST/api/keeper-out/cron/escalate-fallback6h cron — TM 미처리 → fallback 큐service
POST/api/keeper-out/cron/auto-dispatch20~24h 미승인 처리 (정책 a 채택 시)service

request-otp 명세

// POST /api/keeper-out/diagnose/request-otp
// Body
{
  payload: DiagnoseSubmitPayload,    // 진단 데이터 전체 (clinet 임시 보관)
  agent_name: string,                // V3 영업원 이름
  agent_code: string,                // V3 5자리 영숫자
}
// 게이트 순서 (모두 통과 시 OTP 발송)
1. V3: agents.code + agents.name 매칭 + active=true + day_cap·week_cap 미달
2. V4: payload.naver_place_id NOT NULL + DB 미존재
3. V4: payload.phone DB 미존재 (lifetime unique)
4. V5: system_state.minute_count·hour_count·day_count 미달 + system_state.all_hold !== true
5. V5: Giftishow checkBalance() ≥ ₩50,000
6. V8: place 실재성 (Naver Place API)
7. V2: GPS × place 거리 ≤ 200m
8. await sendOtp(phone)  // balerion SMS proxy
9. INSERT otp_sessions (5분 만료, attempts=0)
// Response
{ ok: true, otp_session_id: uuid }   // 클라이언트가 verify로 다시 보냄

verify 명세

// POST /api/keeper-out/diagnose/verify
{
  otp_session_id: uuid,
  otp_code: string,                  // 6자리
  payload: DiagnoseSubmitPayload,    // request-otp와 동일
  agent_code: string,
}
// 게이트
1. V1: otp_sessions row 매칭 + expires_at > now() + attempts < 3
2. V6: photo EXIF 검증 (soft, agent confirm 옵션)
3. INSERT leads (agent_id resolved, payout_status='pending_review', ip_address, user_agent)
4. INSERT payouts × 3 (naver_pay_10k status='pending_review', lead_30k 2건 status='pending')
5. funnel_event 'review.queued'
6. balerion SMS — 사장님 안내 SMS 발송
// Response
{ ok: true, lead_id: uuid, expected_dispatch_within: '24h' }

tm-call + dispatch 명세

// POST /api/keeper-out/admin/leads/[id]/tm-call
{
  outcome: 'confirmed' | 'no_answer' | 'not_owner' | ...,
  note: string,
}
// → leads.tm_outcome + tm_called_at + tm_note 갱신
// → outcome === 'fraud_suspect' 시 fraud_signal INSERT + admin alarm

// POST /api/keeper-out/admin/leads/[id]/dispatch
{ approval_tier: 1 | 2 | 3 }   // 1=TM, 2=admin, 3=auto-fallback
// 게이트
1. payout_status === 'pending_review'
2. system_state.all_hold !== true
3. cap 재확인 (분당/시간당/일별)
4. Giftishow checkBalance() 재확인
5. await sendNaverPayCoupon(...)
6. payouts.naver_pay_10k status='sent' + leads.approved_by + approved_at + approval_tier
7. funnel_event 'payout.dispatched'

11.P3 admin UI — 신규 페이지 + 섹션

신규 페이지 2건

경로역할담당자
app/keeper-out/admin/pending/page.tsxTM 큐 (24h 내 미처리)TM (이서경 등)
app/keeper-out/admin/fallback/page.tsx자동님 fallback 큐 (TM 6h 미처리)자동님·PM

LeadDetailClient (이미 박힌 P1)에 추가할 섹션 4개

#섹션표시 데이터Phase
9방문 로그visit_logsP2
10점주 다른 매장other_leadsP2
11매장 마스터placeP2
13메모 폼visits POSTP2
14★ 검증 결과otp_session(언제·통과여부) / agent_attribution / fraud_signals[]P3
15★ 키퍼 admin 매칭external_user (subscribes 비교) → ②③룰 통과 표시P3
16★ 승인 이력 (TM/admin)tm_outcome / tm_note / approved_by / approval_tierP3
17★ 발송 액션[💸 발송 확인] / [⨯ 거부] / [📞 콜 outcome 입력]P3

신규 컴포넌트 5건

12.대시보드 에이전트 작업 룰 (필독)

다른 Claude/Codex 세션이 P3 진입 시 따라야 할 룰. 위반 시 PM 검증 fail.

✗ 절대 금지 (위반 시 fail)

커밋 단위 (P3 — 권장 8 commits)

  1. feat(keeper-out): migration v3 — agent code, leads approval columns, otp/fraud/system_state tables
  2. feat(keeper-out): /diagnose request-otp + verify endpoints + AgentGateModal + OtpVerifyModal
  3. feat(keeper-out/admin): pending queue page + TM call API
  4. feat(keeper-out/admin): dispatch + reject API + balance preflight + cap check
  5. feat(keeper-out/admin): fallback queue page (TM 6h escalate)
  6. feat(keeper-out/admin): ALL HOLD toggle + system_state CRUD
  7. feat(keeper-out/admin): LeadDetailClient sections 14·15·16·17 (검증/외부매칭/승인/액션)
  8. feat(keeper-out): cron — recheck-completion + escalate-fallback (24h dual-layer)

13.Phase 분할 — P1·P1.5·P2·P3·P4

P1
★ 박힘
완료 (오늘 22:50) — pain_points 백엔드 + GET endpoint + 8섹션 (Hero/고객/보안/Pain/사진/영업자/지급/타임라인). 3 commits, PM 검증 6/6 PASS.
P1.5
대기
admin layout 분리 — 마케팅 헤더 격리. 1 commit, ~15분.
P2
대기
4섹션 추가 (visit_logs / 점주 다른 매장 / 매장 마스터 / 메모 폼). 3 commits, ~90분.
P3
★ v3 신설
휴먼 승인 시스템 통합 — V1 OTP / V3 agent gate / V5 잔액 preflight + cap / V12 TM·자동님 승인 / dual-layer 사후 검수. /diagnose 진입점 + admin pending/fallback 페이지 신설 + LeadDetail 섹션 14~17 추가. 8 commits, ~2일.
P4
운영
텔레그램 alarm 통합 + V7 야간 cron 패턴 룰 + invalid률 누적 자동 active=false + 키퍼메이트 ?ref={code} URL 흐름 wire-up. 운영 도구 layer.

14.측정 KPI

KPI목표측정 방법
OTP 5분 내 입력 성공률≥ 95%otp_sessions verified_at IS NOT NULL / 전체
TM 6h 내 처리율≥ 80%tm_called_at IS NOT NULL within 6h / 전체
자동님 fallback 접수율≤ 20%approval_tier=2 / 전체 dispatched
24h 내 dispatch율≥ 95%approved_at - created_at < 24h / 전체
cap 발동 빈도주 ≤ 1회system_state minute/hour 위반 alarm
fraud_signals 미해결≤ 3건resolved_at IS NULL count
Giftishow 발송 실패율≤ 1%payouts status='failed' / 전체 dispatch
L2 phone match 성공률 (사후)≥ 70%external_user_id IS NOT NULL within 24h
영업원 invalid률 평균≤ 10%agents.invalid_rate_30d 평균

15.결정 6건 누적

Q결정출처
agent.code 형식5자리 영숫자 mixed casev1
ref URL 패턴?ref={code}v1
UX — 영업원 코드 시점"지원금 받기" 클릭 후 모달v1 (자동님 5/5 정정)
코드 수정 보류계획 끝난 후 추후 지시v1
v2 통합 보고서대부분 수용 + 병렬 세션 합본v2
★ v3 24h 큐 + 휴먼 승인TM 1차 + 자동님 2차 fallback 채택v3 (이번 결정)

16.미해결 정책 결정 1건

★ T+20~24h 미승인 건 정책 — 결정 필요
옵션설명장단점
(a) 자동 dispatch fallback 다른 게이트 모두 통과 + 패턴 정상 시 자동 발송 + 사장님 기대 24h 충족
− 휴먼 검증 우회
(b) "추가 확인 필요" 안내 사장님께 "추가 확인 필요해요" SMS + 영업원 재방문 요청 + 100% 휴먼 검증 보장
− 사장님 기대 미달 / 영업 흐름 부담
(c) 하이브리드 ★ 추천 패턴 정상 + cap 미달 + V7 hit 0건이면 자동 dispatch, 그 외엔 (b) 안전한 케이스만 자동 / 의심스러운 건은 사람 확인

비결정 5건 (v1~v2 이월)

  1. OTP 발송 채널 — balerion SMS proxy / KISA / NICE / NHN
  2. 영업원 우회로 — 관리자 PIN 백도어 / 코드 없는 진단 거부
  3. review-on과 잔액 격리 — Giftishow 키 별도 / 모니터링만 분리
  4. agent.code 발급 운영 — 본사 admin 수동 / 자율가입 후 승인 / Referio 매핑
  5. 05-policy.md 어뷰징 정책 명문화 별도 문서 — 만들까?

17.참조 — 보고서 체인 + in-repo 문서

보고서 체인 (시간순)

in-repo 문서 (4건)

주요 식별자

Supabase 프로젝트hvcrbdpjxfszhwrtcygq
키퍼 admin 권한ceo@bizdirect.co.kr (group=13 "키퍼 아웃바운드")
Referio 자동님 코드86Af9 (Authorized)
balerion SMS proxybalerion.cloud:4000 (BALERION_API_KEY)
Giftishow callback01034333385 (자동님 본인)
현재 productionwww.keeper-direct.ceo (sha a1da85d → P1 미배포)