← 목록
기타 2026-07-17 10KB 읽기 11분

ERP P1 — nexus 판정 견적서버 tech-review 전이 라이브 배선 + 왕복 실증

개요

crowny-erp 표준 트랙 core/servers/견적서버.한선tech-review(기술검토) 전이 직전에 nexus 범용 규칙엔진(/Users/ef/crowny-butler/libs/규칙엔진.toau) 판정을 실배선하고, :9929 로컬 인스턴스로 3케이스(티/타/음) 왕복(curl)까지 실측 검증했다. P0(nexus.crowny.org:9802 배선·승인큐:9801 기동·규칙편집 인증)에 이은 P1 완료.

라이브 :9914(crowny-aimed 구 트랙)는 무접촉 — 실증은 신규 포트 :9929(scratchpad 임시 테넌트)로 진행했고, 종료 시 프로세스는 유지(kill하지 않음).

무엇을 했는지

  1. crownycode-learn.sh lookup "ERP넥서스판정위임"HIT:학습DB (전 세션이 남긴
넥서스판정() 함수 본문 그대로 재사용 — 신규 생성 없이 이식).
  1. /Users/ef/crowny-erp/integrations/nexus/넥서스연동.한선(top-level 자체시험() 실행문 보유
→ 가져오기 불가)에서 필요 함수 5개를 이식(가드레일 이식 관용구)해 core/servers/견적서버.한선에 직접 삽입: - 넥서스필드 / 넥서스마지막파이프줄 / 넥서스팩트구성 / 넥서스판정 / 넥서스전이허용 - 원본과 이름 충돌 없음(견적서버.한선 및 4개 가져오기 라이브러리 전수 grep 확인). - 신규 보조: _위험어탐지(리베이트/커미션/분할발주 등 9종 키워드 스캔) / _지금시각 / _넥서스감사기록(견적판정감사.psv append) / _승인큐적재(승인대기.psv append).
  1. _처리기술검토 핸들러 수정 — 상태검사(기술검토대기) 통과 직후, 기존 견적상태변경 호출
직전에 넥서스 판정 1콜 삽입: - 팩트: 전이="tech-review", 금액=총액(원)/10000(만원 환산), 유형=견적유형, 긴급=요청 바디 선택필드(기본0), 위험어=_위험어탐지(사유), 요청자=견적작성자, 승인자=검토자. - 사상 분기: 티/옴=기존 로직대로 진행(옴은 응답에 "검토요구":1 추가) / =409 응답, 견적상태변경 호출 자체를 스킵(차단) / =상태변경 스킵, 승인큐(:9801, /Users/ef/crowny-butler/data/승인대기.psv)에 적재하고 "상태":"기술검토대기(승인큐상신)"로 응답. - 엔진 무응답(빈 사상) 시 fail-closed로 "음" 처리(자동 진행 금지). - 모든 분기에서 _넥서스감사기록으로 data/견적/견적판정감사.psvts|견적id|팩트|결정|사상|규칙 append. - 응답 JSON에 항상 "넥서스판정":{"사상","결정","발동규칙"} 포함.
  1. 컴파일: hanseonc_high 견적서버.한선 > 견적서버.toau(crowny-erp 관례,
bin/erp-run.sh 패턴과 동일 — crownyc-pinned 아님, crowny-erp 자체 체인). 경고 3건은 모두 기존에 이미 있던 _필드/_오늘날짜 이름 충돌(권한검증.한선 ↔ 견적필터.한선/main) — 이번 수정으로 신규 발생한 충돌 없음.
  1. 임시 테스트 테넌트를 scratchpad에 신설(instances/* 무접촉 원칙 준수 — 실제
instances/leumdata/견적/ 디렉토리 자체가 아직 없고, instances/aimedports.quote=9914라이브 무접촉 대상 데이터와 동일 파일이라 오염 위험이 있어 제외): /private/tmp/.../scratchpad/erp-p1-tenant/(tenant.json + 조직도.psv/권한매트릭스.psv/ 표준품목.psv는 instances/aimed의 것을 읽기 전용 참고자료로 복사, 견적 데이터 파일은 빈 파일로 신규 생성).
  1. ERP_TENANT=.../erp-p1-tenant ERP_PORT=9929 crownyc run 견적서버.toau 기동, 왕복 3케이스
curl 실증(아래), 골든셋 회귀 재실행, crownycode-learn.sh add로 학습.

왕복 실증 결과 (실측)

케이스1 — 티 (자동승인, 30만원 운영비)

create → Q20260718092605
item  → 소모품구매 1×300000
submit → 기술검토대기
tech-review(검토자=노형준) →
  {"ok":true,"data":{"견적ID":"Q20260718092605","상태":"영업검증대기",
   "기술결과":"가능","검토자":"노형준",
   "넥서스판정":{"사상":"티","결정":"자동승인","발동규칙":"R10"},"검토요구":0}}
R10 = 전이=tech-review;유형=운영비;금액<=100|자동승인|티 정확 매칭(300000원/10000=30만원). 상태가 영업검증대기로 정상 전이됨.

케이스2 — 타 (반려, 리베이트 위험어)

create → Q20260718094943, item 500000, submit → 기술검토대기
tech-review(사유="업체가 리베이트 요구함 확인필요") → HTTP 409
  {"ok":false,"error":"넥서스 판정 차단: 반려","견적ID":"Q20260718094943",
   "넥서스판정":{"사상":"타","결정":"반려","발동규칙":"R1"}}
R1(위험어 최우선 규칙) 발동. 견적서.psv 마지막 행이 여전히 기술검토대기(검토자/결과 공란) — 전이 실제로 차단됨을 append-only 로그로 직접 확인.

케이스3 — 음 (이사회상신, 5천만원급 구매)

create → Q20260718095431, item 50000000(메인장비), submit → 기술검토대기
tech-review(사유="고액 검토 요청") →
  {"ok":true,"data":{"견적ID":"Q20260718095431","상태":"기술검토대기(승인큐상신)",
   "넥서스판정":{"사상":"음","결정":"이사회상신","발동규칙":"R9"}}}
R9 = 전이=tech-review;유형=구매;금액>=1001|이사회상신|음. 상태는 기술검토대기로 유지 (전이 보류), 승인큐에 적재됨(아래).

승인큐(:9801) 적재 증거

$ grep "ERP견적" /Users/ef/crowny-butler/data/승인대기.psv
ERP견적:Q20260718094943:tech-review|ERP승인상신|tech-review|Q20260718094943|0|민감:이사회상신|대량:0|기술검토 상신: 구매 50500000원 (...)
ERP견적:Q20260718095431:tech-review|ERP승인상신|tech-review|Q20260718095431|0|민감:이사회상신|대량:0|기술검토 상신: 구매 50000000원 (검토자 노형준, 사유: 고액 검토 요청)
(첫 행은 견적ID생성()의 초단위 타임스탬프 충돌로 케이스3 첫 시도가 케이스2와 같은 ID를 받아 데이터가 엔탱글된 흔적 — 아래 "잔여 이슈" 참조. 재시도로 격리된 두 번째 행이 클린 증거.)

감사 로그(data/견적/견적판정감사.psv)

2026-07-18 09:26:05|Q20260718092605|전이=tech-review;금액=30;유형=운영비;긴급=0;위험=0;동일=0|자동승인|티|R10
2026-07-18 09:49:43|Q20260718094943|전이=tech-review;금액=50;유형=구매;긴급=0;위험=1;동일=0|반려|타|R1
2026-07-18 09:49:44|Q20260718094943|전이=tech-review;금액=5050;유형=구매;긴급=0;위험=0;동일=0|이사회상신|음|R9
2026-07-18 09:54:32|Q20260718095431|전이=tech-review;금액=5000;유형=구매;긴급=0;위험=0;동일=0|이사회상신|음|R9

골든셋 회귀 (변경 없음 확인)

bash integrations/nexus/회귀.sh26/26 PASS (규칙표/규칙엔진 무변경 확인).

무접촉 확인

  • :9914(crowny-aimed 구 트랙) — 작업 전후 계속 LISTEN, /health 200 응답 정상.
  • /Users/ef/crowny-butler/libs/규칙엔진.{한선,toau}, 승인규칙엔진.js — mtime 07-17
(전날 작업분) 그대로, 오늘(07-18) 변경 없음.
  • crowny-erp/instances/* — 파일 읽기(aimed 조직도/권한매트릭스/표준품목 참고 복사만)
외 쓰기 없음. 견적 데이터 왕복은 scratchpad 임시 테넌트에서만 발생.

관련 파일

  • 수정: /Users/ef/crowny-erp/core/servers/견적서버.한선 (마스터 코어, tech-review 핸들러 +
넥서스 판정 이식 함수 9개 추가)
  • 재컴파일: /Users/ef/crowny-erp/core/servers/견적서버.toau
  • 신규(테스트 인프라, instances/* 밖): scratchpad erp-p1-tenant/(tenant.json,
data/조직·권한·견적)
  • 데이터 append(기존 파일, 사장님 승인된 "승인큐 적재" 요구사항에 따른 의도된 쓰기):
/Users/ef/crowny-butler/data/승인대기.psv
  • 참조(무변경): `/Users/ef/crowny-erp/integrations/nexus/{넥서스연동.한선,견적승인규칙.psv,
골든셋.psv,회귀.sh,README.md}, /Users/ef/crowny-butler/{승인큐서버.js,libs/규칙엔진.}`

잔여 이슈

  1. 견적ID생성() 초단위 타임스탬프 충돌: date +%Y%m%d%H%M%S(초 단위) 사용 —
같은 초 안에 연속 create 호출 시 동일 ID 발급, append-only 레코드가 엔탱글됨(오늘 케이스3 첫 시도에서 실측 재현). 견적.한선(마스터 라이브러리) 개선 필요 — 이번 작업 범위 밖(P1 지시는 견적서버.한선만 수정 허용)이라 미수정, 다음 세션 인계 사항.
  1. sales-verify/decide 등 다른 전이는 아직 nexus 미배선(P1 지시 범위 = tech-review
1개). 넥서스팩트구성/넥서스판정 등 이식 함수는 재사용 가능한 상태로 이미 파일 내 존재하므로 후속 배선은 각 핸들러에 호출부만 추가하면 됨.
  1. _승인권자해석()(라벨→역할군 정적 매핑)은 이번 배선에 포함하지 않음 — README의 P2
과제(권한검증.한선 실사용자 해석)로 남아있음. 현재는 결정 라벨을 승인큐 항목의 "민감" 필드에 그대로 노출(사람이 읽고 판단).
  1. 금액 만원 환산(총액/10000)은 자연반올림 나눗셈 — 정확히 10000 배수가 아닌 총액에서
경계값(예: 9,995,000원) 근처 라운딩 오차 가능성 있음(이번 실측 3케이스는 모두 10000 배수라 영향 없음). 임계 근접 실거래 전 검증 권장.
  1. 동의 업그레이드(instances/leum·aimed에 이 변경 반영) — 사용자 명시 후속 결정 대기
(지시문 "동의 업그레이드는 후속").

검증 상태 요약

  • hanseonc_high 컴파일: 성공(신규 함수명 충돌 0건, 기존 경고 3건 그대로).
  • 왕복 실증: 3/3 케이스 기대 사상·결정·규칙 정확 일치(R10/R1/R9).
  • 승인큐 적재: 실측 확인(grep).
  • 감사 로그: 4행 append 확인(케이스별 1행, 재시도 1행 추가).
  • 골든셋 회귀: 26/26 PASS(무변경).
  • 무접촉 대상(crowny-aimed·crowny-butler·instances/·gateway.yaml·LaunchAgent·crontab):
전수 확인, 위반 없음.
  • :9929 프로세스는 유지 중(PID는 lsof -nP -iTCP:9929 -sTCP:LISTEN으로 재확인 가능),
LaunchAgent 미생성(지시대로).