[{"data":1,"prerenderedAt":2531},["ShallowReactive",2],{"doc:\u002Fpages\u002Fcontract":3},{"id":4,"title":5,"body":6,"description":221,"extension":2524,"meta":2525,"navigation":2526,"path":2527,"seo":2528,"stem":2529,"__hash__":2530},"docs\u002Fpages\u002FCONTRACT.md","\u002Faccount\u002Fcontract — 계약 관리 기획·로직 정본",{"type":7,"value":8,"toc":2463},"minimark",[9,18,69,72,77,198,200,204,207,212,222,232,236,242,251,255,261,288,292,301,323,329,331,335,339,353,461,465,472,482,595,598,621,629,681,687,739,765,773,777,783,789,871,887,891,897,901,907,916,933,952,958,972,974,978,1117,1119,1123,1130,1190,1199,1201,1205,1211,1217,1225,1231,1234,1263,1265,1269,1273,1291,1295,1315,1319,1395,1399,1425,1429,1443,1447,1474,1478,1514,1518,1532,1534,1538,1542,1620,1624,1711,1725,1729,1735,1790,1797,1801,1852,1855,1857,1861,1867,1972,1980,1986,2040,2059,2066,2073,2075,2079,2315,2317,2321,2325,2339,2343,2374,2378,2410,2414,2459],[10,11,13,17],"h1",{"id":12},"accountcontract-계약-관리-기획로직-정본",[14,15,16],"code",{},"\u002Faccount\u002Fcontract"," — 계약 관리 기획·로직 정본",[19,20,21,41,63],"blockquote",{},[22,23,24,28,29,32,33,36,37,40],"p",{},[25,26,27],"strong",{},"목적",": 사업자등록증 등록·심사·이용계약 전자체결·가입 서류 첨부를 한 화면에서 관리.\n회원가입한 사업자(",[14,30,31],{},"corp","\u002F",[14,34,35],{},"sole",")의 ",[25,38,39],{},"미승인 상태 메인 진입점"," + 승인 후 계약 갱신·서류 관리 화면.",[22,42,43,46,47,52,53,57,58,62],{},[25,44,45],{},"연관",": ",[48,49,51],"a",{"href":50},".\u002FSIGNUP",".\u002FSIGNUP.md"," §3·§4 \u002F ",[48,54,56],{"href":55},"..\u002FMEMBERSHIP","..\u002FMEMBERSHIP.md"," §1.2·§2·§8 \u002F\n",[48,59,61],{"href":60},"..\u002Fhistory\u002Fhistory.20260602","..\u002Fhistory\u002Fhistory.20260602.md"," §7·§10·§11·§12·§13·§14·§15",[22,64,65,68],{},[25,66,67],{},"마지막 현행화",": 2026-06-02 (§15 반영)",[70,71],"hr",{},[73,74,76],"h2",{"id":75},"_1-페이지-개요","1. 페이지 개요",[78,79,80,93],"table",{},[81,82,83],"thead",{},[84,85,86,90],"tr",{},[87,88,89],"th",{},"항목",[87,91,92],{},"값",[94,95,96,106,119,133,167,181],"tbody",{},[84,97,98,102],{},[99,100,101],"td",{},"라우트",[99,103,104],{},[14,105,16],{},[84,107,108,111],{},[99,109,110],{},"파일",[99,112,113],{},[48,114,116],{"href":115},"..\u002F..\u002Fapp\u002Fpages\u002Faccount\u002Fcontract.vue",[14,117,118],{},"app\u002Fpages\u002Faccount\u002Fcontract.vue",[84,120,121,124],{},[99,122,123],{},"메인 컴포넌트",[99,125,126,132],{},[48,127,129],{"href":128},"..\u002F..\u002Fapp\u002Fcomponents\u002FAppContractPanel.vue",[14,130,131],{},"AppContractPanel"," (~770 라인)",[84,134,135,138],{},[99,136,137],{},"보조 컴포넌트",[99,139,140,146,147,153,154,160,161],{},[48,141,143],{"href":142},"..\u002F..\u002Fapp\u002Fcomponents\u002FAppContractViewDialog.vue",[14,144,145],{},"AppContractViewDialog"," — 계약서 미리보기 \u002F ",[48,148,150],{"href":149},"..\u002F..\u002Fapp\u002Fcomponents\u002FAppContractSignDialog.vue",[14,151,152],{},"AppContractSignDialog"," — 본인인증 + 전자서명 3-스텝 위저드 (~700 라인) \u002F ",[48,155,157],{"href":156},"..\u002F..\u002Fapp\u002Fcomponents\u002FAppUploadGuideDialog.vue",[14,158,159],{},"AppUploadGuideDialog"," \u002F ",[48,162,164],{"href":163},"..\u002F..\u002Fapp\u002Fcomponents\u002FAppFilePreviewDialog.vue",[14,165,166],{},"AppFilePreviewDialog",[84,168,169,172],{},[99,170,171],{},"공통 셸",[99,173,174,180],{},[48,175,177],{"href":176},"..\u002F..\u002Fapp\u002Fcomponents\u002FAppMyPageShell.vue",[14,178,179],{},"AppMyPageShell"," — 나의 페이지 좌측 메뉴 + 본문 슬롯",[84,182,183,186],{},[99,184,185],{},"접근 권한",[99,187,188,189,160,191,193,194,197],{},"인증된 사업자(",[14,190,31],{},[14,192,35],{},")만 — 개인(",[14,195,196],{},"personal",")은 메뉴 미노출(후속)",[70,199],{},[73,201,203],{"id":202},"_2-진입-경로-4가지","2. 진입 경로 — 4가지",[22,205,206],{},"미승인 상태의 사업자가 이 화면에 도달하는 경로 4가지가 모두 정합되어 있어야 한다.",[208,209,211],"h3",{"id":210},"_21-회원가입-직후-자동","2.1 회원가입 직후 (자동)",[213,214,219],"pre",{"className":215,"code":217,"language":218},[216],"language-text","\u002Fsignup Step 5 → \"계약 관리로 이동\" 버튼\n  → if isBusiness: navigateTo('\u002Faccount\u002Fcontract')\n     else: navigateTo('\u002Fhome')\n","text",[14,220,217],{"__ignoreMap":221},"",[22,223,224,225],{},"코드: ",[48,226,228,229],{"href":227},"..\u002F..\u002Fapp\u002Fpages\u002Fsignup.vue#L456","signup.vue ",[14,230,231],{},"finish()",[208,233,235],{"id":234},"_22-로그인-직후-자동","2.2 로그인 직후 (자동)",[213,237,240],{"className":238,"code":239,"language":218},[216],"\u002Flogin → loginByEmail() → fetchMe()\n  → if approvalState !== 'approved': navigateTo('\u002Faccount\u002Fcontract')\n     else: navigateTo(redirect ?? '\u002Fhome')\n",[14,241,239],{"__ignoreMap":221},[22,243,224,244],{},[48,245,247,248],{"href":246},"..\u002F..\u002Fapp\u002Fpages\u002Flogin\u002Findex.vue#L44","login\u002Findex.vue ",[14,249,250],{},"onLogin()",[208,252,254],{"id":253},"_23-미들웨어-리다이렉트-다른-차단-페이지-시도","2.3 미들웨어 리다이렉트 (다른 차단 페이지 시도)",[213,256,259],{"className":257,"code":258,"language":218},[216],"\u002Fhome·\u002Fsend\u002F*·\u002Fcontacts·… 진입 시도\n  → middleware\u002Fapproval.global.ts\n  → if approvalState !== 'approved' && path ∉ ALLOWED_PREFIXES:\n       return navigateTo('\u002Faccount\u002Fcontract')\n",[14,260,258],{"__ignoreMap":221},[22,262,263,264,267,268,267,271,267,274,267,277,267,280,283,284],{},"허용 경로: ",[14,265,266],{},"\u002Faccount\u002F*"," · ",[14,269,270],{},"\u002Fhelp",[14,272,273],{},"\u002Fguide",[14,275,276],{},"\u002Fwbs",[14,278,279],{},"\u002Finquiry",[14,281,282],{},"meta.auth: false","\n코드: ",[48,285,287],{"href":286},"..\u002F..\u002Fapp\u002Fmiddleware\u002Fapproval.global.ts","middleware\u002Fapproval.global.ts",[208,289,291],{"id":290},"_24-글로벌-띠-cta-수동","2.4 글로벌 띠 CTA (수동)",[22,293,294,300],{},[48,295,297],{"href":296},"..\u002F..\u002Fapp\u002Fcomponents\u002FAppApprovalBanner.vue",[14,298,299],{},"AppApprovalBanner"," (모든 페이지 layout 최상단) — CTA 클릭 시:",[302,303,304,311,317],"ul",{},[305,306,307,310],"li",{},[14,308,309],{},"pending"," → \"사업자등록증 등록\"",[305,312,313,316],{},[14,314,315],{},"reviewing"," → \"진행 상태 보기\"",[305,318,319,322],{},[14,320,321],{},"rejected"," → \"다시 제출하기\"",[22,324,325,326,328],{},"→ 모두 ",[14,327,16],{},"로 이동.",[70,330],{},[73,332,334],{"id":333},"_3-화면-구성-3-영역","3. 화면 구성 — 3 영역",[208,336,338],{"id":337},"_31-패널-상단-상태-카드-12-신규","3.1 패널 상단 상태 카드 (§12 신규)",[22,340,341,342,32,344,32,346,348,349,352],{},"미승인 상태(",[14,343,309],{},[14,345,315],{},[14,347,321],{},")일 때만 노출. 회사 ",[14,350,351],{},"approval_state","에 따라 톤·아이콘·메시지 분기:",[78,354,355,374],{},[81,356,357],{},[84,358,359,362,365,368,371],{},[87,360,361],{},"state",[87,363,364],{},"톤",[87,366,367],{},"아이콘",[87,369,370],{},"헤더",[87,372,373],{},"본문",[94,375,376,396,416,444],{},[84,377,378,382,385,390,393],{},[99,379,380],{},[14,381,309],{},[99,383,384],{},"warning",[99,386,387],{},[14,388,389],{},"i-lucide-clock",[99,391,392],{},"\"사업자등록증을 등록해 주세요\"",[99,394,395],{},"\"가입서류 첨부 영역에서 사업자등록증(PDF, 최대 10MB)을 업로드하시면 심사가 시작됩니다.\"",[84,397,398,402,405,410,413],{},[99,399,400],{},[14,401,315],{},[99,403,404],{},"info",[99,406,407],{},[14,408,409],{},"i-lucide-loader-circle",[99,411,412],{},"\"사업자등록증 심사 중입니다\"",[99,414,415],{},"\"영업일 기준 1~2일 내에 심사 결과를 안내드립니다. 추가 서류 첨부가 필요하면 가입서류 영역에서 진행할 수 있습니다.\"",[84,417,418,422,425,430,433],{},[99,419,420],{},[14,421,321],{},[99,423,424],{},"danger",[99,426,427],{},[14,428,429],{},"i-lucide-circle-x",[99,431,432],{},"\"사업자등록증 심사가 반려되었습니다\"",[99,434,435,436,443],{},"\"반려 사유: ",[437,438,439],"em",{},[440,441],"binding",{"value":442},"rejectedReason"," · 사업자등록증을 새로 첨부하면 심사가 다시 시작됩니다.\"",[84,445,446,451,454,456,459],{},[99,447,448],{},[14,449,450],{},"approved",[99,452,453],{},"—",[99,455,453],{},[99,457,458],{},"카드 자체 비표시",[99,460,453],{},[208,462,464],{"id":463},"_32-이용계약-체결","3.2 이용계약 체결",[22,466,467,468,471],{},"전자계약 방식의 이용계약서 카드 리스트. 데이터 소스: ",[14,469,470],{},"GET \u002Fcontracts"," (§11).",[22,473,474,477,478,481],{},[25,475,476],{},"상태 4종"," (",[14,479,480],{},"TB_CONTRACT.contract_state","):",[78,483,484,503],{},[81,485,486],{},[84,487,488,490,493,495,500],{},[87,489,361],{},[87,491,492],{},"라벨",[87,494,367],{},[87,496,497],{},[14,498,499],{},"canSign",[87,501,502],{},"의미",[94,504,505,526,555,575],{},[84,506,507,512,515,520,523],{},[99,508,509],{},[14,510,511],{},"initial",[99,513,514],{},"최초계약",[99,516,517],{},[14,518,519],{},"square-pen",[99,521,522],{},"✅",[99,524,525],{},"가입 직후 자동 생성된 1건 (signup auto-create §11 + lazy backfill §13)",[84,527,528,533,536,541,544],{},[99,529,530],{},[14,531,532],{},"done",[99,534,535],{},"체결완료",[99,537,538],{},[14,539,540],{},"circle-check",[99,542,543],{},"❌",[99,545,546,547,550,551,554],{},"정상 체결 — 서명자·체결일(",[14,548,549],{},"signed_at",")·만료일(",[14,552,553],{},"expires_at = signed_at + 2y",") 표시",[84,556,557,562,565,570,572],{},[99,558,559],{},[14,560,561],{},"renew",[99,563,564],{},"계약갱신",[99,566,567],{},[14,568,569],{},"circle-alert",[99,571,522],{},[99,573,574],{},"운영자가 신규 계약서 배포, 갱신 필요 (현재 운영자단 미구현)",[84,576,577,582,585,590,592],{},[99,578,579],{},[14,580,581],{},"expired",[99,583,584],{},"만료",[99,586,587],{},[14,588,589],{},"archive",[99,591,543],{},[99,593,594],{},"갱신 계약 체결 시 백엔드가 같은 회사의 다른 done 계약을 자동 expired로 전이",[22,596,597],{},"각 카드 액션:",[302,599,600,609],{},[305,601,602,605,606,608],{},[25,603,604],{},"계약서 확인"," (모든 상태) → ",[14,607,145],{}," 모달 (요약본 — 약관 정본 하드코딩)",[305,610,611,477,614,617,618,620],{},[25,612,613],{},"계약체결하기",[14,615,616],{},"canSign=true","일 때만) → ",[14,619,152],{}," (본인인증 + 3-스텝 위저드, §15)",[622,623,625,626,628],"h4",{"id":624},"전자서명-위저드-appcontractsigndialog","전자서명 위저드 (",[48,627,152],{"href":149},")",[78,630,631,643],{},[81,632,633],{},[84,634,635,638,640],{},[87,636,637],{},"Step",[87,639,492],{},[87,641,642],{},"내용",[94,644,645,656,667],{},[84,646,647,650,653],{},[99,648,649],{},"1",[99,651,652],{},"제1장 · 총칙 및 서류",[99,654,655],{},"제1조~제8조 — 목적·정의·계약 성립·서류 등 (끝까지 스크롤해야 다음 단계)",[84,657,658,661,664],{},[99,659,660],{},"2",[99,662,663],{},"제2장 · 이용요금 및 결제",[99,665,666],{},"단가표·청구주기·연체·환불 등 (끝까지 스크롤)",[84,668,669,672,675],{},[99,670,671],{},"3",[99,673,674],{},"제3장 · 전자서명",[99,676,677,680],{},[25,678,679],{},"휴대폰 본인인증 sub-step"," (§15) → 통과 시 정보 테이블 + 캔버스 노출",[22,682,683,686],{},[25,684,685],{},"STEP 3 본인인증 흐름"," (§15):",[688,689,690,697,703,714,721,728],"ol",{},[305,691,692,693,696],{},"Dialog open watcher에서 ",[14,694,695],{},"auth.fetchMe()"," 호출 → 휴대폰 최신화",[305,698,699,700,628],{},"회원 휴대폰을 마스킹 표시(",[14,701,702],{},"010-****-1111",[305,704,705,706,709,710,713],{},"\"인증번호 받기\" → ",[14,707,708],{},"POST \u002Fauth\u002Fphone-code\u002Fsend"," (purpose=",[14,711,712],{},"contract_sign",", 백엔드 §15.1)",[305,715,716,717,720],{},"6자리 입력 → ",[14,718,719],{},"POST \u002Fauth\u002Fphone-code\u002Fverify"," → 통과 시 카드 success 톤 + 캔버스 셋업",[305,722,723,724,727],{},"서명자명(기본값 ",[14,725,726],{},"auth.user.name",") + 캔버스 ink → \"서명 완료\"",[305,729,730,731,734,735,738],{},"부모에 ",[14,732,733],{},"completed"," emit → ",[14,736,737],{},"POST \u002Fcontracts\u002F:id\u002Fsign"," (§11)",[22,740,741,742,745,746,745,749,745,752,755,756,758,759,761,762,764],{},"체결 완료 → 백엔드가 ",[14,743,744],{},"contractState='done'"," + ",[14,747,748],{},"signer_user_id=ctx.userId",[14,750,751],{},"signed_at=now",[14,753,754],{},"expires_at=+2y"," UPDATE. ",[14,757,561],{},"였다면 같은 회사의 다른 ",[14,760,532],{},"은 자동 ",[14,763,581],{},".",[19,766,767],{},[22,768,769,772],{},[25,770,771],{},"삭제됨 (§15)",": 공인인증서 탭 — STEP 3은 본인인증 → 전자서명 단일 흐름.",[208,774,776],{"id":775},"_33-가입서류-첨부","3.3 가입서류 첨부",[22,778,779,780,471],{},"PDF만 첨부 가능, 최대 10MB. 데이터 소스: ",[14,781,782],{},"GET \u002Fcontracts\u002Ffiles",[22,784,785,788],{},[25,786,787],{},"서류 3종",":",[78,790,791,810],{},[81,792,793],{},[84,794,795,797,800,803],{},[87,796,492],{},[87,798,799],{},"배지",[87,801,802],{},"활성화 조건",[87,804,805,806,809],{},"DB ",[14,807,808],{},"name"," 접두사",[94,811,812,832,852],{},[84,813,814,819,824,827],{},[99,815,816],{},[25,817,818],{},"사업자등록증",[99,820,821],{},[14,822,823],{},"필수",[99,825,826],{},"항상 노출",[99,828,829],{},[14,830,831],{},"사업자등록증_",[84,833,834,839,844,847],{},[99,835,836],{},[25,837,838],{},"대부업등록증",[99,840,841],{},[14,842,843],{},"해당업체",[99,845,846],{},"체크박스 \"대부업 해당\" 활성 시 (첨부 있으면 자동 활성)",[99,848,849],{},[14,850,851],{},"대부업등록증_",[84,853,854,859,863,866],{},[99,855,856],{},[25,857,858],{},"지급이행보증보험증권",[99,860,861],{},[14,862,843],{},[99,864,865],{},"체크박스 \"후불 정산 해당\" 활성 시 (첨부 있으면 자동 활성)",[99,867,868],{},[14,869,870],{},"지급이행보증보험증권_",[22,872,873,876,877,880,881,886],{},[14,874,875],{},"TB_CONTRACT_FILE","에 ",[14,878,879],{},"kind"," 컬럼이 없어 ",[25,882,883,885],{},[14,884,808],{}," 접두사로 종류 구분"," (§11 결정).",[622,888,890],{"id":889},"파일-첨부-흐름","파일 첨부 흐름",[213,892,895],{"className":893,"code":894,"language":218},[216],"[사업자등록증 업로드] 클릭\n  → AppUploadGuideDialog (\"PDF · 10MB · …\")\n  → 확인 → input[type=file] 트리거\n  → pickFile(): MIME=application\u002Fpdf, size ≤ 10MB 검증\n  → activeContractId가 없으면 토스트 \"활성 계약을 찾을 수 없습니다\"\n  → FormData 멀티파트 POST \u002Fcontracts\u002Ffiles\n       form: contractId \u002F kind ∈ {biz, loan, insurance} \u002F file\n  → loadFiles() 재호출 → 화면 갱신\n  → kind=biz면 auth.fetchMe() 호출 → 글로벌 띠·페이지 배너가 즉시 \"심사 중\"으로 전환 (§12)\n  → 토스트 \"사업자등록증이 제출되었습니다. 심사가 진행됩니다.\"\n",[14,896,894],{"__ignoreMap":221},[622,898,900],{"id":899},"파일-행-표시-14","파일 행 표시 (§14)",[213,902,905],{"className":903,"code":904,"language":218},[216],"[아이콘] [이름·메타]      [심사 상태 배지]   [확인]   [(반려 시) 삭제]\n",[14,906,904],{"__ignoreMap":221},[22,908,909,912,913,915],{},[25,910,911],{},"심사 상태 배지"," (사업자등록증만, ",[14,914,309],{},"은 파일 없음이라 미표시):",[302,917,918,923,928],{},[305,919,920,922],{},[14,921,315],{}," → info 톤 + 로딩 아이콘 + \"심사 중\"",[305,924,925,927],{},[14,926,450],{}," → success 톤 + 체크 + \"승인\"",[305,929,930,932],{},[14,931,321],{}," → danger 톤 + X + \"반려\"",[22,934,935,938,939,941,942,945,946,948,949,951],{},[25,936,937],{},"삭제 버튼","은 ",[14,940,321],{}," 상태에서만 노출 → ",[14,943,944],{},"DELETE \u002Fcontracts\u002Ffiles\u002F:id",".\n삭제 후에도 회사는 ",[14,947,321],{}," 유지(운영자 결정 보존). 새 파일 첨부 시 백엔드(§12)가 자동 ",[14,950,315],{},"으로 전이.",[622,953,955,956,628],{"id":954},"미리보기-appfilepreviewdialog","미리보기 (",[14,957,166],{},[22,959,960,961,964,965,968,969,764],{},"iframe은 Authorization 헤더를 못 싣기 때문에 ",[14,962,963],{},"useApi\u003CBlob>('\u002Fcontracts\u002Ffiles\u002F:id\u002Fdownload', { responseType: 'blob' })"," 호출 → ",[14,966,967],{},"URL.createObjectURL()"," → iframe src. 모달 닫힐 때 ",[14,970,971],{},"revokeObjectURL",[70,973],{},[73,975,977],{"id":976},"_4-사용자-액션-매트릭스","4. 사용자 액션 매트릭스",[78,979,980,993],{},[81,981,982],{},[84,983,984,987,990],{},[87,985,986],{},"액션",[87,988,989],{},"호출",[87,991,992],{},"결과",[94,994,995,1009,1025,1040,1053,1068,1083,1100],{},[84,996,997,999,1004],{},[99,998,604],{},[99,1000,1001],{},[14,1002,1003],{},"viewContract(c)",[99,1005,1006,1008],{},[14,1007,145],{}," 모달 — 요약본",[84,1010,1011,1013,1018],{},[99,1012,613],{},[99,1014,1015],{},[14,1016,1017],{},"signContract(c)",[99,1019,1020,1022,1023],{},[14,1021,152],{}," (본인인증 + 3-스텝) → 완료 시 ",[14,1024,737],{},[84,1026,1027,1030,1035],{},[99,1028,1029],{},"서류 업로드 클릭",[99,1031,1032],{},[14,1033,1034],{},"requestUpload(target)",[99,1036,1037,1039],{},[14,1038,159],{}," → 파일 선택",[84,1041,1042,1045,1050],{},[99,1043,1044],{},"파일 선택",[99,1046,1047],{},[14,1048,1049],{},"pickFile(target, e)",[99,1051,1052],{},"MIME·크기 검증 → FormData POST → 목록 갱신 + (biz일 때) fetchMe",[84,1054,1055,1058,1063],{},[99,1056,1057],{},"서류 확인",[99,1059,1060],{},[14,1061,1062],{},"openPreview(label, f)",[99,1064,1065,1066],{},"인증 fetch → blob → object URL → ",[14,1067,166],{},[84,1069,1070,1073,1078],{},[99,1071,1072],{},"서류 삭제",[99,1074,1075],{},[14,1076,1077],{},"removeFile(f.id)",[99,1079,1080,1082],{},[14,1081,944],{}," (rejected 상태에서만 버튼 노출)",[84,1084,1085,1088,1097],{},[99,1086,1087],{},"대부업\u002F후불 해당 토글",[99,1089,1090,1093,1094],{},[14,1091,1092],{},"loanApplicable","·",[14,1095,1096],{},"insuranceApplicable",[99,1098,1099],{},"업로드 인터페이스 활성\u002F비활성",[84,1101,1102,1105,1110],{},[99,1103,1104],{},"저장하기",[99,1106,1107],{},[14,1108,1109],{},"save()",[99,1111,1112,1113,1116],{},"현재는 토스트만 — 회사 전화번호 등은 별도 ",[14,1114,1115],{},"\u002Faccount\u002Fsettings","에서",[70,1118],{},[73,1120,1122],{"id":1121},"_5-회원-유형별-서류-요구사항","5. 회원 유형별 서류 요구사항",[22,1124,1125,1129],{},[48,1126,1128],{"href":1127},".\u002FSIGNUP#2-%ED%95%B5%EC%8B%AC-%EC%B0%A8%EC%9D%B4-%ED%95%9C%EB%88%88%EC%97%90","SIGNUP.md §2"," 정책 표 기반:",[78,1131,1132,1145],{},[81,1133,1134],{},[84,1135,1136,1139,1142],{},[87,1137,1138],{},"가입 유형",[87,1140,1141],{},"카드 충전 시",[87,1143,1144],{},"후불 정산 시",[94,1146,1147,1162,1175],{},[84,1148,1149,1156,1159],{},[99,1150,1151,477,1154,628],{},[25,1152,1153],{},"법인사업자",[14,1155,31],{},[99,1157,1158],{},"사업자등록증 + (대부업등록증)",[99,1160,1161],{},"위 + 지급이행보증보험증권 + 통장사본",[84,1163,1164,1171,1173],{},[99,1165,1166,477,1169,628],{},[25,1167,1168],{},"개인사업자",[14,1170,35],{},[99,1172,1158],{},[99,1174,1161],{},[84,1176,1177,1184,1187],{},[99,1178,1179,477,1182,628],{},[25,1180,1181],{},"개인",[14,1183,196],{},[99,1185,1186],{},"(가입신청서만 — 본 화면 미진입)",[99,1188,1189],{},"❌ 후불 미지원",[19,1191,1192],{},[22,1193,1194,1195,1198],{},"⚠️ ",[25,1196,1197],{},"회원 유형에 따른 분기는 후속"," — 현재는 모든 사업자에게 동일 폼 노출. 대부업·후불 옵션 자동 분기는 P1.",[70,1200],{},[73,1202,1204],{"id":1203},"_6-상태-모델","6. 상태 모델",[208,1206,1208,1209,628],{"id":1207},"_61-이용계약-tb_contractcontract_state","6.1 이용계약 (",[14,1210,480],{},[213,1212,1215],{"className":1213,"code":1214,"language":218},[216],"            ┌──────────────┐\n            │  initial     │  ← signup auto-create (§11) 또는 lazy backfill (§13)\n            └──────┬───────┘\n          POST \u002Fcontracts\u002F:id\u002Fsign\n                   ▼\n            ┌──────────────┐    운영자가 신규 약관 배포(미구현)\n            │  done        │ ─────────────────────────┐\n            └──────────────┘                          ▼\n                                              ┌──────────────┐\n                                              │  renew       │\n                                              └──────┬───────┘\n                                       POST \u002Fcontracts\u002F:id\u002Fsign\n                                                     ▼\n                                              ┌──────────────┐\n        같은 회사의 다른 done ──→ 자동       │  done        │\n        expired (sign 핸들러에서 일괄)        └──────────────┘\n                                                     │\n                                              만료 cron(미구현)\n                                                     ▼\n                                              ┌──────────────┐\n                                              │  expired     │\n                                              └──────────────┘\n",[14,1216,1214],{"__ignoreMap":221},[208,1218,1220,1221,1224],{"id":1219},"_62-회사-승인-상태-tb_companyapproval_state-4단계-712","6.2 회사 승인 상태 (",[14,1222,1223],{},"TB_COMPANY.approval_state",") — 4단계 (§7·§12)",[213,1226,1229],{"className":1227,"code":1228,"language":218},[216],"  ┌──────────┐  biz 첨부(§12)   ┌────────────┐  운영자 승인     ┌──────────┐\n  │ pending  │ ───────────────► │ reviewing  │ ───────────────► │ approved │\n  └──────────┘                  └────────────┘                  └──────────┘\n                                       │                              ▲\n                                       │ 운영자 반려                  │\n                                       ▼                              │\n                                  ┌──────────┐  biz 재첨부(§12)        │\n                                  │ rejected │ ──────────────────────►│ reviewing\n                                  └──────────┘                        (자동)\n",[14,1230,1228],{"__ignoreMap":221},[22,1232,1233],{},"코드:",[302,1235,1236,1244,1251],{},[305,1237,1238,1239,1243],{},"첨부 시 자동 전이: ",[48,1240,1242],{"href":1241},"..\u002F..\u002F..\u002Fmalgn-noti-api\u002Fsrc\u002Froutes\u002Fcontracts.ts","contracts.ts POST \u002Ffiles"," §12",[305,1245,1246,1247,1250],{},"자동 회복: ",[48,1248,1249],{"href":1241},"GET \u002Ffiles lazy backfill"," §13",[305,1252,1253,1254,1258,1259,1262],{},"미들웨어 차단: ",[48,1255,1257],{"href":1256},"..\u002F..\u002F..\u002Fmalgn-noti-api\u002Fsrc\u002Fmiddleware\u002Fapproval.ts","middleware\u002Fapproval.ts"," ",[14,1260,1261],{},"state !== 'approved'","이면 403",[70,1264],{},[73,1266,1268],{"id":1267},"_7-정책-결정-사항","7. 정책 결정 사항",[208,1270,1272],{"id":1271},"_71-미승인-사용자의-메인-진입점","7.1 미승인 사용자의 메인 진입점",[302,1274,1275,1282],{},[305,1276,1277,1278,1281],{},"회원가입한 사업자는 ",[25,1279,1280],{},"반드시"," 본 화면에서 사업자등록증을 등록해야 운영자 심사 → 승인 → 서비스 이용.",[305,1283,341,1284,32,1286,32,1288,1290],{},[14,1285,309],{},[14,1287,315],{},[14,1289,321],{},")에서는 GNB·홈·발송·주소록 등 어떤 페이지에 가도 미들웨어가 본 화면으로 리다이렉트.",[208,1292,1294],{"id":1293},"_72-카드-충전-vs-후불-정산","7.2 카드 충전 vs 후불 정산",[302,1296,1297,1303,1312],{},[305,1298,1299,1302],{},[25,1300,1301],{},"카드 충전",": 사업자등록증 + (대부업등록증) — 등록 후 운영자 승인 → 즉시 카드 등록·충전·발송 가능.",[305,1304,1305,1308,1309,1311],{},[25,1306,1307],{},"후불 정산",": 위 + ",[25,1310,858],{}," + 통장사본 — 운영자가 추가 검수 → 신용 한도 부여.",[305,1313,1314],{},"현재 화면은 두 경로의 서류를 모두 표시하고 사용자가 \"후불 정산 해당\" 체크로 선택.",[208,1316,1318],{"id":1317},"_73-상태별-안내-메시지-71214","7.3 상태별 안내 메시지 (§7·§12·§14)",[78,1320,1321,1336],{},[81,1322,1323],{},[84,1324,1325,1327,1330,1333],{},[87,1326,361],{},[87,1328,1329],{},"메시지 (글로벌 띠)",[87,1331,1332],{},"메시지 (이 화면 상단 카드)",[87,1334,1335],{},"메시지 (파일 행 배지)",[94,1337,1338,1352,1366,1380],{},[84,1339,1340,1344,1347,1349],{},[99,1341,1342],{},[14,1343,309],{},[99,1345,1346],{},"사업자등록증을 등록해 주세요",[99,1348,1346],{},[99,1350,1351],{},"(파일 없음 — 미표시)",[84,1353,1354,1358,1361,1363],{},[99,1355,1356],{},[14,1357,315],{},[99,1359,1360],{},"사업자등록증 심사 중입니다",[99,1362,1360],{},[99,1364,1365],{},"\"심사 중\" (info)",[84,1367,1368,1372,1375,1377],{},[99,1369,1370],{},[14,1371,450],{},[99,1373,1374],{},"(배너 미노출)",[99,1376,1374],{},[99,1378,1379],{},"\"승인\" (success)",[84,1381,1382,1386,1389,1392],{},[99,1383,1384],{},[14,1385,321],{},[99,1387,1388],{},"사업자등록증 심사 반려 + 사유",[99,1390,1391],{},"사업자등록증 심사가 반려되었습니다",[99,1393,1394],{},"\"반려\" (danger) + 삭제 버튼",[208,1396,1398],{"id":1397},"_74-이용계약-자동-생성-11","7.4 이용계약 자동 생성 (§11)",[22,1400,1401,1402,1405,1406,1409,1410,1413,1414,1417,1418,1417,1421,1424],{},"가입 시점에 백엔드 ",[14,1403,1404],{},"POST \u002Fauth\u002Fsignup"," 핸들러가 NICE 세션 consume 직후 ",[14,1407,1408],{},"companyType ∈ {corp, sole}","이면 ",[14,1411,1412],{},"TB_CONTRACT"," 1건 자동 INSERT(",[14,1415,1416],{},"title='최초 이용계약 온라인체결'",", ",[14,1419,1420],{},"version='신규'",[14,1422,1423],{},"contract_state='initial'","). signup 이전에 가입한 사업자는 §13의 lazy backfill로 GET 시점에 자동 생성.",[208,1426,1428],{"id":1427},"_75-갱신-계약-체결-시-기존-계약-자동-만료-11","7.5 갱신 계약 체결 시 기존 계약 자동 만료 (§11)",[22,1430,1431,1433,1434,758,1437,1439,1440,1442],{},[14,1432,737],{}," 핸들러가 ",[14,1435,1436],{},"contract_state='renew'",[14,1438,532],{}," 계약을 한 번에 ",[14,1441,581],{},"로 일괄 UPDATE — 이중 유효 계약 방지.",[208,1444,1446],{"id":1445},"_76-사업자등록증-첨부-시-회사-상태-자동-전이-12","7.6 사업자등록증 첨부 시 회사 상태 자동 전이 (§12)",[22,1448,1449,1452,1453,1456,1457,1459,1460,1409,1462,1464,1465,1468,1469,32,1471,1473],{},[14,1450,1451],{},"POST \u002Fcontracts\u002Ffiles"," 핸들러에서 ",[14,1454,1455],{},"kind=biz"," 업로드 후 회사 상태가 ",[14,1458,309],{}," 또는 ",[14,1461,321],{},[14,1463,315],{},"으로 UPDATE. ",[14,1466,1467],{},"rejected_reason","은 그대로 둠(운영자가 새 심사에서 결정). ",[14,1470,315],{},[14,1472,450],{},"는 변동 없음.",[208,1475,1477],{"id":1476},"_77-파일-제약","7.7 파일 제약",[302,1479,1480,1489,1495,1505],{},[305,1481,1482,46,1485,1488],{},[25,1483,1484],{},"MIME",[14,1486,1487],{},"application\u002Fpdf"," 만 허용 (백엔드에서 재검증)",[305,1490,1491,1494],{},[25,1492,1493],{},"최대 크기",": 10MB (Cloudflare Workers 요청 크기 제한 내)",[305,1496,1497,1500,1501,1504],{},[25,1498,1499],{},"권한",": 본 회사의 계약·파일만 접근. ",[14,1502,1503],{},"companyId"," 매칭 안 되면 404.",[305,1506,1507,46,1510,1513],{},[25,1508,1509],{},"R2 키 패턴",[14,1511,1512],{},"contracts\u002F\u003CcompanyId>\u002F\u003CcontractId>\u002F\u003Cunix>_\u003CsafeName>"," — 회사·계약별 prefix 분리.",[208,1515,1517],{"id":1516},"_78-미승인-사용자의-본-화면-예외-11","7.8 미승인 사용자의 본 화면 예외 (§11)",[22,1519,1520,1523,1524,1527,1528,1531],{},[14,1521,1522],{},"\u002Fcontracts"," 라우트는 ",[14,1525,1526],{},"requireApproved"," 미들웨어를 ",[25,1529,1530],{},"적용하지 않음"," — 미승인 사용자가 사업자등록증을 제출하는 화면이 본 화면이므로 의도된 예외. 다른 도메인 라우트는 §8에서 모두 차단.",[70,1533],{},[73,1535,1537],{"id":1536},"_8-api-엔드포인트-구현됨-11","8. API 엔드포인트 — 구현됨 (§11)",[208,1539,1541],{"id":1540},"_81-계약","8.1 계약",[78,1543,1544,1560],{},[81,1545,1546],{},[84,1547,1548,1551,1554,1557],{},[87,1549,1550],{},"메서드",[87,1552,1553],{},"경로",[87,1555,1556],{},"역할",[87,1558,1559],{},"비고",[94,1561,1562,1583],{},[84,1563,1564,1569,1573,1580],{},[99,1565,1566],{},[14,1567,1568],{},"GET",[99,1570,1571],{},[14,1572,1522],{},[99,1574,1575,1576,1579],{},"본 회사 계약 목록 (",[14,1577,1578],{},"status=1"," + id 오름차순)",[99,1581,1582],{},"§13 lazy auto-create 포함",[84,1584,1585,1590,1595,1617],{},[99,1586,1587],{},[14,1588,1589],{},"POST",[99,1591,1592],{},[14,1593,1594],{},"\u002Fcontracts\u002F:id\u002Fsign",[99,1596,1597,1598,1600,1601,1600,1604,1600,1606,1608,1609,1611,1612,1614,1615],{},"전자서명 완료 → ",[14,1599,532],{},"+",[14,1602,1603],{},"signer_user_id",[14,1605,549],{},[14,1607,754],{},". ",[14,1610,561],{},"였다면 기존 ",[14,1613,532],{}," 일괄 ",[14,1616,581],{},[99,1618,1619],{},"§11",[208,1621,1623],{"id":1622},"_82-가입-서류-r2-db","8.2 가입 서류 (R2 + DB)",[78,1625,1626,1638],{},[81,1627,1628],{},[84,1629,1630,1632,1634,1636],{},[87,1631,1550],{},[87,1633,1553],{},[87,1635,1556],{},[87,1637,1559],{},[94,1639,1640,1657,1673,1693],{},[84,1641,1642,1646,1651,1654],{},[99,1643,1644],{},[14,1645,1568],{},[99,1647,1648],{},[14,1649,1650],{},"\u002Fcontracts\u002Ffiles",[99,1652,1653],{},"본 회사 파일 목록 (contract JOIN으로 회사 단위 좁힘)",[99,1655,1656],{},"§13 자동 회복 포함",[84,1658,1659,1663,1667,1670],{},[99,1660,1661],{},[14,1662,1589],{},[99,1664,1665],{},[14,1666,1650],{},[99,1668,1669],{},"멀티파트 업로드 → R2 put + DB insert",[99,1671,1672],{},"§11 — PDF·10MB·접두사 + §12 auto reviewing",[84,1674,1675,1679,1684,1690],{},[99,1676,1677],{},[14,1678,1568],{},[99,1680,1681],{},[14,1682,1683],{},"\u002Fcontracts\u002Ffiles\u002F:id\u002Fdownload",[99,1685,1686,1687,1689],{},"R2 stream → ",[14,1688,1487],{}," 응답",[99,1691,1692],{},"inline disposition",[84,1694,1695,1700,1705,1708],{},[99,1696,1697],{},[14,1698,1699],{},"DELETE",[99,1701,1702],{},[14,1703,1704],{},"\u002Fcontracts\u002Ffiles\u002F:id",[99,1706,1707],{},"R2 delete(swallow) + DB delete",[99,1709,1710],{},"§14 — 반려 상태에서만 호출",[22,1712,1713,1714,160,1717,1720,1721],{},"OpenAPI: ",[14,1715,1716],{},"Contract",[14,1718,1719],{},"ContractFile"," 스키마 + 위 5 path. ",[48,1722,1724],{"href":1723},"..\u002F..\u002F..\u002Fmalgn-noti-api\u002Fsrc\u002Fopenapi.ts","openapi.ts",[208,1726,1728],{"id":1727},"_83-휴대폰-본인인증-15","8.3 휴대폰 본인인증 (§15)",[22,1730,1731,1732,1734],{},"기존 phone-code 인프라 재사용 + ",[14,1733,712],{}," purpose 추가:",[78,1736,1737,1747],{},[81,1738,1739],{},[84,1740,1741,1743,1745],{},[87,1742,1550],{},[87,1744,1553],{},[87,1746,1556],{},[94,1748,1749,1770],{},[84,1750,1751,1755,1760],{},[99,1752,1753],{},[14,1754,1589],{},[99,1756,1757],{},[14,1758,1759],{},"\u002Fauth\u002Fphone-code\u002Fsend",[99,1761,1762,1765,1766,1769],{},[14,1763,1764],{},"{phone, purpose: 'contract_sign'}"," → SMS 발송 (mock 모드면 ",[14,1767,1768],{},"mockCode"," 응답에 노출)",[84,1771,1772,1776,1781],{},[99,1773,1774],{},[14,1775,1589],{},[99,1777,1778],{},[14,1779,1780],{},"\u002Fauth\u002Fphone-code\u002Fverify",[99,1782,1783,1786,1787],{},[14,1784,1785],{},"{phone, purpose: 'contract_sign', code}"," → 200 ",[14,1788,1789],{},"{verified: true}",[22,1791,1792,1793,1796],{},"TTL 10분, 5회 시도 제한, 재발송 시 직전 코드 무효화, 소비 후 재사용 차단. SHA-256(",[14,1794,1795],{},"phone|purpose|code",") 해시 저장.",[208,1798,1800],{"id":1799},"_84-운영자-검수-운영자단-미구현","8.4 운영자 검수 (운영자단 — 미구현)",[78,1802,1803,1811],{},[81,1804,1805],{},[84,1806,1807,1809],{},[87,1808,1553],{},[87,1810,1556],{},[94,1812,1813,1823,1836],{},[84,1814,1815,1820],{},[99,1816,1817],{},[14,1818,1819],{},"GET \u002Fadmin\u002Fcompanies\u002F{id}\u002Fcontracts",[99,1821,1822],{},"운영자가 회사별 계약·서류 조회",[84,1824,1825,1830],{},[99,1826,1827],{},[14,1828,1829],{},"POST \u002Fadmin\u002Fcompanies\u002F{id}\u002Fapprove",[99,1831,1832,1833],{},"승인 → ",[14,1834,1835],{},"approval_state='approved'",[84,1837,1838,1843],{},[99,1839,1840],{},[14,1841,1842],{},"POST \u002Fadmin\u002Fcompanies\u002F{id}\u002Freject {reason}",[99,1844,1845,1846,745,1849,1851],{},"반려 → ",[14,1847,1848],{},"approval_state='rejected'",[14,1850,1467],{}," 적재",[22,1853,1854],{},"현재는 라이브 DB UPDATE만 가능.",[70,1856],{},[73,1858,1860],{"id":1859},"_9-db-테이블-라이브-schemats-정의-11","9. DB 테이블 (라이브 + schema.ts 정의 §11)",[208,1862,1864,1865],{"id":1863},"_91-tb_contract","9.1 ",[14,1866,1412],{},[213,1868,1872],{"className":1869,"code":1870,"language":1871,"meta":221,"style":221},"language-sql shiki shiki-themes github-light github-dark","TB_CONTRACT (\n  id              BIGINT UNSIGNED PK AUTO_INCREMENT,\n  company_id      BIGINT UNSIGNED NOT NULL,    -- FK → TB_COMPANY\n  title           VARCHAR(160)   NOT NULL,\n  version         VARCHAR(20)    NOT NULL,     -- '신규' \u002F 'v2.0' 등\n  contract_state  VARCHAR(20)    NOT NULL DEFAULT 'initial',  -- initial\u002Fdone\u002Frenew\u002Fexpired\n  status          INT            NOT NULL DEFAULT 1,\n  signer_user_id  BIGINT UNSIGNED,             -- FK → TB_USER (서명자)\n  signed_at       DATETIME,\n  expires_at      DATETIME,                    -- 보통 signed_at + 2y\n  created_at      DATETIME       NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at      DATETIME       NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  INDEX idx_contract_company (company_id, contract_state),\n  CONSTRAINT fk_contract_company FOREIGN KEY (company_id) REFERENCES TB_COMPANY(id),\n  CONSTRAINT fk_contract_signer  FOREIGN KEY (signer_user_id) REFERENCES TB_USER(id)\n)\n","sql",[14,1873,1874,1882,1888,1894,1900,1906,1912,1918,1924,1930,1936,1942,1948,1954,1960,1966],{"__ignoreMap":221},[1875,1876,1879],"span",{"class":1877,"line":1878},"line",1,[1875,1880,1881],{},"TB_CONTRACT (\n",[1875,1883,1885],{"class":1877,"line":1884},2,[1875,1886,1887],{},"  id              BIGINT UNSIGNED PK AUTO_INCREMENT,\n",[1875,1889,1891],{"class":1877,"line":1890},3,[1875,1892,1893],{},"  company_id      BIGINT UNSIGNED NOT NULL,    -- FK → TB_COMPANY\n",[1875,1895,1897],{"class":1877,"line":1896},4,[1875,1898,1899],{},"  title           VARCHAR(160)   NOT NULL,\n",[1875,1901,1903],{"class":1877,"line":1902},5,[1875,1904,1905],{},"  version         VARCHAR(20)    NOT NULL,     -- '신규' \u002F 'v2.0' 등\n",[1875,1907,1909],{"class":1877,"line":1908},6,[1875,1910,1911],{},"  contract_state  VARCHAR(20)    NOT NULL DEFAULT 'initial',  -- initial\u002Fdone\u002Frenew\u002Fexpired\n",[1875,1913,1915],{"class":1877,"line":1914},7,[1875,1916,1917],{},"  status          INT            NOT NULL DEFAULT 1,\n",[1875,1919,1921],{"class":1877,"line":1920},8,[1875,1922,1923],{},"  signer_user_id  BIGINT UNSIGNED,             -- FK → TB_USER (서명자)\n",[1875,1925,1927],{"class":1877,"line":1926},9,[1875,1928,1929],{},"  signed_at       DATETIME,\n",[1875,1931,1933],{"class":1877,"line":1932},10,[1875,1934,1935],{},"  expires_at      DATETIME,                    -- 보통 signed_at + 2y\n",[1875,1937,1939],{"class":1877,"line":1938},11,[1875,1940,1941],{},"  created_at      DATETIME       NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[1875,1943,1945],{"class":1877,"line":1944},12,[1875,1946,1947],{},"  updated_at      DATETIME       NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[1875,1949,1951],{"class":1877,"line":1950},13,[1875,1952,1953],{},"  INDEX idx_contract_company (company_id, contract_state),\n",[1875,1955,1957],{"class":1877,"line":1956},14,[1875,1958,1959],{},"  CONSTRAINT fk_contract_company FOREIGN KEY (company_id) REFERENCES TB_COMPANY(id),\n",[1875,1961,1963],{"class":1877,"line":1962},15,[1875,1964,1965],{},"  CONSTRAINT fk_contract_signer  FOREIGN KEY (signer_user_id) REFERENCES TB_USER(id)\n",[1875,1967,1969],{"class":1877,"line":1968},16,[1875,1970,1971],{},")\n",[22,1973,1974,1975,1979],{},"schema.ts 정의: ",[48,1976,1978],{"href":1977},"..\u002F..\u002F..\u002Fmalgn-noti-api\u002Fsrc\u002Fdb\u002Fschema.ts","src\u002Fdb\u002Fschema.ts"," §11.",[208,1981,1983,1984],{"id":1982},"_92-tb_contract_file","9.2 ",[14,1985,875],{},[213,1987,1989],{"className":1869,"code":1988,"language":1871,"meta":221,"style":221},"TB_CONTRACT_FILE (\n  id            BIGINT UNSIGNED PK AUTO_INCREMENT,\n  contract_id   BIGINT UNSIGNED NOT NULL,      -- FK → TB_CONTRACT\n  name          VARCHAR(255)    NOT NULL,      -- 한국어 접두사 포함 ('사업자등록증_...')\n  size_bytes    BIGINT UNSIGNED NOT NULL,\n  r2_key        VARCHAR(255)    NOT NULL,      -- contracts\u002F\u003Cco>\u002F\u003Ccontract>\u002F\u003Cts>_\u003Cname>\n  uploaded_at   DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  INDEX idx_contractfile_contract (contract_id),\n  CONSTRAINT fk_contractfile_contract FOREIGN KEY (contract_id) REFERENCES TB_CONTRACT(id)\n)\n",[14,1990,1991,1996,2001,2006,2011,2016,2021,2026,2031,2036],{"__ignoreMap":221},[1875,1992,1993],{"class":1877,"line":1878},[1875,1994,1995],{},"TB_CONTRACT_FILE (\n",[1875,1997,1998],{"class":1877,"line":1884},[1875,1999,2000],{},"  id            BIGINT UNSIGNED PK AUTO_INCREMENT,\n",[1875,2002,2003],{"class":1877,"line":1890},[1875,2004,2005],{},"  contract_id   BIGINT UNSIGNED NOT NULL,      -- FK → TB_CONTRACT\n",[1875,2007,2008],{"class":1877,"line":1896},[1875,2009,2010],{},"  name          VARCHAR(255)    NOT NULL,      -- 한국어 접두사 포함 ('사업자등록증_...')\n",[1875,2012,2013],{"class":1877,"line":1902},[1875,2014,2015],{},"  size_bytes    BIGINT UNSIGNED NOT NULL,\n",[1875,2017,2018],{"class":1877,"line":1908},[1875,2019,2020],{},"  r2_key        VARCHAR(255)    NOT NULL,      -- contracts\u002F\u003Cco>\u002F\u003Ccontract>\u002F\u003Cts>_\u003Cname>\n",[1875,2022,2023],{"class":1877,"line":1914},[1875,2024,2025],{},"  uploaded_at   DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,\n",[1875,2027,2028],{"class":1877,"line":1920},[1875,2029,2030],{},"  INDEX idx_contractfile_contract (contract_id),\n",[1875,2032,2033],{"class":1877,"line":1926},[1875,2034,2035],{},"  CONSTRAINT fk_contractfile_contract FOREIGN KEY (contract_id) REFERENCES TB_CONTRACT(id)\n",[1875,2037,2038],{"class":1877,"line":1932},[1875,2039,1971],{},[22,2041,2042,2047,2048,2050,2051,1093,2053,1093,2055,2058],{},[25,2043,2044,2046],{},[14,2045,879],{}," 컬럼 없음"," (§11 결정) — 파일 종류는 ",[14,2049,808],{}," 접두사로 구분.\nR2 메타데이터에는 ",[14,2052,879],{},[14,2054,1503],{},[14,2056,2057],{},"contractId","를 customMetadata로 함께 저장.",[208,2060,2062,2063],{"id":2061},"_93-미구현-tb_contract_template","9.3 (미구현) ",[14,2064,2065],{},"TB_CONTRACT_TEMPLATE",[22,2067,2068,2069,2072],{},"운영자가 배포하는 약관 정본 + chapter·article JSON. 신규 배포 시 회사별 ",[14,2070,2071],{},"TB_CONTRACT.contract_state='renew'","로 자동 마이그레이션. P2.",[70,2074],{},[73,2076,2078],{"id":2077},"_10-현재-구현-상태","10. 현재 구현 상태",[78,2080,2081,2093],{},[81,2082,2083],{},[84,2084,2085,2088,2091],{},[87,2086,2087],{},"영역",[87,2089,2090],{},"상태",[87,2092,1559],{},[94,2094,2095,2107,2120,2132,2147,2157,2167,2177,2187,2197,2207,2217,2227,2237,2249,2262,2274,2288,2300],{},[84,2096,2097,2100,2102],{},[99,2098,2099],{},"이용계약 카드 리스트",[99,2101,522],{},[99,2103,2104,2106],{},[14,2105,470],{}," 실 API (§11)",[84,2108,2109,2114,2117],{},[99,2110,2111,2112,628],{},"계약서 확인 모달 (",[14,2113,145],{},[99,2115,2116],{},"🟢 UI",[99,2118,2119],{},"약관 정본 하드코딩 (백엔드 템플릿 없음)",[84,2121,2122,2125,2127],{},[99,2123,2124],{},"전자서명 위저드 (3-스텝)",[99,2126,522],{},[99,2128,2129,2130,738],{},"본인인증(§15) + ",[14,2131,737],{},[84,2133,2134,2136,2138],{},[99,2135,679],{},[99,2137,522],{},[99,2139,2140,2143,2144,2146],{},[14,2141,2142],{},"phone-code"," purpose=",[14,2145,712],{}," (§15)",[84,2148,2149,2152,2154],{},[99,2150,2151],{},"갱신 → 기존 만료 자동 전이",[99,2153,522],{},[99,2155,2156],{},"백엔드 sign 핸들러에서 일괄 UPDATE (§11)",[84,2158,2159,2162,2164],{},[99,2160,2161],{},"가입서류 첨부 (PDF\u002F10MB 검증)",[99,2163,522],{},[99,2165,2166],{},"백엔드 R2 + DB 적재 (§11)",[84,2168,2169,2172,2174],{},[99,2170,2171],{},"사업자등록증 첨부 시 reviewing 자동 전이",[99,2173,522],{},[99,2175,2176],{},"백엔드 `pending",[84,2178,2179,2182,2184],{},[99,2180,2181],{},"§11 이전 가입자 \u002F §12 이전 첨부자 lazy 회복",[99,2183,522],{},[99,2185,2186],{},"GET 시점 자동 보정 (§13)",[84,2188,2189,2192,2194],{},[99,2190,2191],{},"파일 행 심사 상태 배지",[99,2193,522],{},[99,2195,2196],{},"reviewing\u002Fapproved\u002Frejected 3분기 (§14)",[84,2198,2199,2202,2204],{},[99,2200,2201],{},"반려 시 삭제 버튼 + DELETE",[99,2203,522],{},[99,2205,2206],{},"rejected 상태에서만 노출 (§14)",[84,2208,2209,2212,2214],{},[99,2210,2211],{},"대부업·후불 체크박스 토글",[99,2213,2116],{},[99,2215,2216],{},"첨부 있으면 자동 활성, 정책 분기는 없음",[84,2218,2219,2222,2224],{},[99,2220,2221],{},"첨부 서류 미리보기",[99,2223,522],{},[99,2225,2226],{},"인증 fetch → blob → object URL (§11)",[84,2228,2229,2232,2234],{},[99,2230,2231],{},"패널 상단 상태 카드 (pending\u002Freviewing\u002Frejected)",[99,2233,522],{},[99,2235,2236],{},"3분기 톤·메시지 (§12)",[84,2238,2239,2241,2243],{},[99,2240,1104],{},[99,2242,2116],{},[99,2244,2245,2246,2248],{},"토스트만 (회사 전화번호 등은 ",[14,2247,1115],{}," 사용)",[84,2250,2251,2256,2259],{},[99,2252,2253],{},[25,2254,2255],{},"회원 유형별 서류 분기",[99,2257,2258],{},"⚪",[99,2260,2261],{},"현재 모든 사업자에게 동일 폼",[84,2263,2264,2269,2271],{},[99,2265,2266],{},[25,2267,2268],{},"운영자 승인 트리거",[99,2270,2258],{},[99,2272,2273],{},"운영자단 미개발 — DB 직접 UPDATE만 가능",[84,2275,2276,2281,2283],{},[99,2277,2278],{},[25,2279,2280],{},"약관 템플릿 정본 관리",[99,2282,2258],{},[99,2284,2285,2287],{},[14,2286,145],{}," 약관 본문 하드코딩",[84,2289,2290,2295,2297],{},[99,2291,2292],{},[25,2293,2294],{},"체결 서명 PDF 보존",[99,2296,2258],{},[99,2298,2299],{},"캔버스 ink 이미지가 백엔드에 저장 안 됨",[84,2301,2302,2307,2309],{},[99,2303,2304],{},[25,2305,2306],{},"계약 갱신 cron",[99,2308,2258],{},[99,2310,2311,2312,2314],{},"만료 1개월 전 ",[14,2313,561],{}," 자동 생성 미구현",[70,2316],{},[73,2318,2320],{"id":2319},"_11-알려진-한계-후속-작업","11. 알려진 한계 \u002F 후속 작업",[208,2322,2324],{"id":2323},"p0-가입-후-폐쇄-루프-완성","P0 — 가입 후 폐쇄 루프 완성",[688,2326,2327,2333],{},[305,2328,2329,2332],{},[25,2330,2331],{},"운영자단 사업자 승인 화면"," (§7.7 \u002F §11.10 \u002F §12.6) — 현재 라이브 DB UPDATE로만 승인\u002F반려. 운영자가 본 페이지의 업로드 파일을 보고 승인\u002F반려(사유 입력) 처리 가능해야 함. WBS 5-4-3.",[305,2334,2335,2338],{},[25,2336,2337],{},"NHN Notification Hub 자격증명 + 어댑터 재작성"," (§16) — 승인\u002F반려 결정 시 사용자에게 알림 메일·SMS 자동 발송. User Access Key 수령 대기.",[208,2340,2342],{"id":2341},"p1-ux-정합화","P1 — UX 정합화",[688,2344,2345,2355,2366],{"start":1890},[305,2346,2347,2350,2351,2354],{},[25,2348,2349],{},"회원 유형별 폼 분기"," — ",[14,2352,2353],{},"auth.tenant.companyType","에 따라 대부업·후불 옵션 노출 여부 결정.",[305,2356,2357,2350,2360,2362,2363,2365],{},[25,2358,2359],{},"개인 가입자의 메뉴 숨김",[14,2361,16],{}," 항목 자체를 LNB·",[14,2364,179],{},"에서 미노출.",[305,2367,2368,2373],{},[25,2369,2370,2372],{},[14,2371,315],{}," 상태에서 잘못 올린 biz 파일 정정"," (§14.4) — 현재는 삭제 버튼이 안 보임. 정책상 \"심사 중 변경 불가\"가 안전하나 사용자가 답답할 수 있음. 운영자단 심사 화면 도입 시 같은 곳에서 정정 가능하도록.",[208,2375,2377],{"id":2376},"p2-약관계약-정본-관리","P2 — 약관·계약 정본 관리",[688,2379,2380,2390,2400],{"start":1908},[305,2381,2382,2386,2387,2389],{},[25,2383,2384],{},[14,2385,2065],{}," — 운영자가 약관 본문 정본 등록·버전 관리·일괄 ",[14,2388,561],{}," 배포.",[305,2391,2392,2395,2396,2399],{},[25,2393,2394],{},"전자서명 인증 강화 옵션"," — 현재 휴대폰 SMS OTP. 법적 강도를 더 높이려면 NICE 본인확인(",[14,2397,2398],{},"\u002Fauth\u002Fnice\u002F*",") 재호출 또는 공인인증서 연계.",[305,2401,2402,2405,2406,2409],{},[25,2403,2404],{},"계약서 PDF 생성·보존"," — 체결 완료 시 캔버스 ink(PNG) + 서명자·시간·IP·UA 메타가 들어간 PDF 자동 생성 → R2 저장(",[14,2407,2408],{},"TB_CONTRACT.signed_image_r2_key"," 컬럼 추가) → 사용자가 다운로드.",[208,2411,2413],{"id":2412},"p3-위생적-작업","P3 — 위생적 작업",[688,2415,2416,2424,2436,2444,2453],{"start":1926},[305,2417,2418,2420,2421,2423],{},[25,2419,2306],{}," (§11.10) — 만료 1개월 전 자동 ",[14,2422,561],{}," 계약 row 생성. Workers Cron Trigger.",[305,2425,2426,2432,2433,2435],{},[25,2427,2428,2429,2431],{},"반려 후 재첨부 시 ",[14,2430,1467],{}," 처리"," (§12.6) — 현재는 그대로 둔 채 ",[14,2434,315],{}," 전이. 정책상 더 명확히 하려면 재첨부 시 NULL 정리.",[305,2437,2438,2350,2441,2443],{},[25,2439,2440],{},"갱신 알림",[14,2442,561],{}," 상태가 되면 사용자에게 이메일·SMS·인앱 알림.",[305,2445,2446,2350,2449,2452],{},[25,2447,2448],{},"체결마감일 임박 경고",[14,2450,2451],{},"renew.metas[].danger=true"," 외에 GNB 띠로 일주일 전부터 강조.",[305,2454,2455,2458],{},[25,2456,2457],{},"사업자등록증 OCR 자동 검증"," (§11.10) — 운영자 부담 경감. NHN OCR API 또는 외부 서비스.",[2460,2461,2462],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":221,"searchDepth":1890,"depth":1890,"links":2464},[2465,2466,2472,2485,2486,2487,2493,2503,2509,2517,2518],{"id":75,"depth":1884,"text":76},{"id":202,"depth":1884,"text":203,"children":2467},[2468,2469,2470,2471],{"id":210,"depth":1890,"text":211},{"id":234,"depth":1890,"text":235},{"id":253,"depth":1890,"text":254},{"id":290,"depth":1890,"text":291},{"id":333,"depth":1884,"text":334,"children":2473},[2474,2475,2479],{"id":337,"depth":1890,"text":338},{"id":463,"depth":1890,"text":464,"children":2476},[2477],{"id":624,"depth":1896,"text":2478},"전자서명 위저드 (AppContractSignDialog)",{"id":775,"depth":1890,"text":776,"children":2480},[2481,2482,2483],{"id":889,"depth":1896,"text":890},{"id":899,"depth":1896,"text":900},{"id":954,"depth":1896,"text":2484},"미리보기 (AppFilePreviewDialog)",{"id":976,"depth":1884,"text":977},{"id":1121,"depth":1884,"text":1122},{"id":1203,"depth":1884,"text":1204,"children":2488},[2489,2491],{"id":1207,"depth":1890,"text":2490},"6.1 이용계약 (TB_CONTRACT.contract_state)",{"id":1219,"depth":1890,"text":2492},"6.2 회사 승인 상태 (TB_COMPANY.approval_state) — 4단계 (§7·§12)",{"id":1267,"depth":1884,"text":1268,"children":2494},[2495,2496,2497,2498,2499,2500,2501,2502],{"id":1271,"depth":1890,"text":1272},{"id":1293,"depth":1890,"text":1294},{"id":1317,"depth":1890,"text":1318},{"id":1397,"depth":1890,"text":1398},{"id":1427,"depth":1890,"text":1428},{"id":1445,"depth":1890,"text":1446},{"id":1476,"depth":1890,"text":1477},{"id":1516,"depth":1890,"text":1517},{"id":1536,"depth":1884,"text":1537,"children":2504},[2505,2506,2507,2508],{"id":1540,"depth":1890,"text":1541},{"id":1622,"depth":1890,"text":1623},{"id":1727,"depth":1890,"text":1728},{"id":1799,"depth":1890,"text":1800},{"id":1859,"depth":1884,"text":1860,"children":2510},[2511,2513,2515],{"id":1863,"depth":1890,"text":2512},"9.1 TB_CONTRACT",{"id":1982,"depth":1890,"text":2514},"9.2 TB_CONTRACT_FILE",{"id":2061,"depth":1890,"text":2516},"9.3 (미구현) TB_CONTRACT_TEMPLATE",{"id":2077,"depth":1884,"text":2078},{"id":2319,"depth":1884,"text":2320,"children":2519},[2520,2521,2522,2523],{"id":2323,"depth":1890,"text":2324},{"id":2341,"depth":1890,"text":2342},{"id":2376,"depth":1890,"text":2377},{"id":2412,"depth":1890,"text":2413},"md",{},true,"\u002Fpages\u002Fcontract",{"title":5,"description":221},"pages\u002FCONTRACT","nNaei9_64ZqRCqK9CGsM0HlMo7H92B5HJnLdrSpVrc0",1780638909353]