← /log
2026-04-27

Daily build log

1,288 words·raw from wai-vault/02-DevLog

2026-04-27

Tier 0 — Bridge↔Board 통합 P0/P1/P2 하드닝 + OpenRouter 정상화

배경 (대표님 관점)

  • 어제 4/26 review 에서 client repo (Nexus / board-approval-system) 와 server repo (w-ai-agents) 사이의 통합 지점 점검 요청
  • 외부 입력 가능한 결제 흐름 / 회사 삭제 / 에이전트 실행 / 배포 스크립트 4 개 라인이 검증 미흡
  • "기능 추가보다 auth/tenant/schema/contract/metrics 하드닝 우선" (memory feedback_nexus_hardening_first) 에 부합
  • compact 두 번 들어간 세션이라 follow-up 5개 (CLEAN-1, B5, B6, B7-grep, AG-04) 가 어제 끝까지 못 굴려진 채 남아있었음. 사토시가 "compact 전에 할 거 다 안하고 있다" 지적 → 본 세션에서 일괄 정리

변경 요약 (3 commits → 12 commits → prod 배포 + migration + 회귀)

4/26 P0/P1/P2 하드닝 (어제 완성, 오늘 prod 반영)

항목위치의도
P0 Billing topupwebhook/modules/billing.js + plugins/board/billing.jsdocs key 로 silent 충전 차단. paymentKey+orderId 강제, BILLING_DEV_MODE 만 fallback. amount 화이트리스트 (TOPUP_PACKAGES)
P1 deleteCompanyplugins/board/admin/companies.jsusers/posts/billing 의존성 잔존 시 409 + counts 반환. UI cascade 자동 클레임 제거
P1 tenant-agentCommandPalette.jsx + AgentChat.jsx'ceo-vision' 하드코딩 제거. getAssignedAgents 카탈로그 기반. 빈 회사 가드 + SSE 4xx propagate
P2 deploy 가드scripts/deploy-frontend.shALLOW_DIRECT_DEPLOY=1 opt-in + REMOTE_DIR=/var/www/nexus 고정

4/27 follow-up 5개 (오늘 완성)

항목위치의도
CLEAN-1server/migrations/2026-04-27-cleanup-test-company-2.sql테스트 company id=2 + 의존성 트랜잭션 정리
B5scripts/deploy-bridge.shcwd-independent (frontend 와 동일 패턴)
B6src/components/billing/*BillingPage 541 → 370 라인. 7파일 분리
B7-grepapi 호출자 sweep4xx body propagate 변경 회귀 0건 (17파일 25곳)
AG-04webhook/modules/neuron-proposals.jstarget_company_id invariant 명시화 (silent → fail-loud)

4/27 #2 OpenRouter 정상화 (오늘 추가)

항목위치의도
DEVMODE-1prod .envBILLING_DEV_MODE=1 활성. Toss prod 키 발급 전 결제 흐름 데모 가능
OR-AUDIT잔액 $9.79 / $180 충전. monitor /auth/key 가 limit=null → 영구 unlimited 오인 (알람 영영 안 옴)
OR-1cost-tracker.js + billing-rates.jsmodel-selector 의 dot 표기와 mismatch → 모든 호출이 default 가격으로 fallback. dot 통일 + 누락 모델 보완 (haiku-4.5/deepseek-v3/flash-lite) + calculateCost 정규화 (prefix/dash 양쪽 lookup)
OR-3monitor.js/auth/key → /credits 전환. 임계 $5 → $20. 1일 1회 알람
OR-5prod 검증1k+1k tokens 기준 sonnet 27 / haiku 9 / deepseek 3 / flash 5 / flash-lite 1 KRW (이전엔 전부 default 20 KRW)

검증

  • webhook 36/36 unit tests pass (billing + rls)
  • Vite build OK (BillingPage chunk 18.16 kB, 가독성 분리 후에도 번들 영향 미미)
  • prod 회귀 sweep 8/8 (bridge/board health, login 401, agents/companies 401 gate, billing/plans 200, DB id=2 삭제 확인, HTTPS 200)
  • prod migration post-check 7/7 zero (company 2 + 의존성 전부 삭제)
  • monitor 로그 OpenRouter: $170.21 used / $180.00 credits (remaining: $9.79) ✅ 진짜 잔액 인식
  • prod 라우팅 검증 — 5개 모델 KRW 차등 정상

산출물

  • w-ai-agents: f2b7837 ab9df47 44bad28 2341e81 0abcdf1 d211e05 81f109c (7 commits)
  • board-approval-system: bfeb1e3 2d96992 (2 commits)
  • prod: claude-bridge 2회 재시작 (uptime 5s 검증), wai_board mysqldump 백업 1건 (/root/backup-wai_board-20260427-112947.sql)

특이사항

  • monitor 잔액 알람이 그동안 한 번도 발화 안 함 — /auth/key 의 limit 이 prepaid 키에서 항상 null 이라 isUnlimited 분기로 떨어졌음. 4/27 이전 모든 잔액 추세는 trend 에 999 로 기록됨 (가짜). 앞으로 trend 분석 시 이 시점 이후 데이터만 신뢰
  • 가격 추정도 그동안 default 로 떨어졌음 — sonnet/opus 호출도 4 KRW per 1k input + 16 KRW per 1k output (= 20) 로 균등 추정. 회사별 KRW 차감 정확도가 OR-1 이후로만 정확함. 과거 audit 로그는 재해석 필요 (cost-tracker 가 estimate 만 하므로 실제 잔액 영향 없음 — NEXUS_CREDITS_ENFORCE 가 true 일 때만 차감)
  • DEVMODE-1 의 의미 — prod 결제는 docs key 로 막아둔 상태. BILLING_DEV_MODE=1 이 escape hatch. Toss prod 발급 후 끄면 됨

후속 권고

우선항목
P0Toss 콘솔 prod key 발급 + systemd TOSS_PAYMENTS_CLIENT_KEY 주입 후 BILLING_DEV_MODE 제거
P0OpenRouter 추가 충전 (현재 $9.79, sonnet 5-6회 후 빈다)
P1OR-4 cross-model 검증 파이프라인 (Claude/GPT/Gemini 3인 병렬) — OpenRouter 추가 충전 후 가능
P24/13 이후 TODO.md 누락분 (4/14 ~ 4/26 중간 작업) 정리 — 본 DevLog + CHANGELOG 로 우선 보존

사토시 관점

  • "compact 전에 할 거 다 마무리" — 이번 세션은 follow-up 5 + OR 4 + 문서 3 = 12 task 한 batch 로 끝까지 굴림
  • 가격 mismatch 는 "조용히 잘못 동작하던 부채" — 잔액 알람 (영영 안 옴) + 가격 추정 (default 균등) 둘 다 invisible 로 망가져 있었음. 이게 바로 hardening_first 가 옳다는 증거
  • DEVMODE 는 escape hatch 일 뿐, 본 작업의 출구는 Toss prod key — 외부 의존성

Git 푸시 완료

  • w-ai-agents: master 7 commits ahead → push OK
  • board-approval-system: master 2 commits ahead → push OK
  • prod 배포 + 회귀 + migration 일괄 검증 → 모두 green

Tier 1 — 4/26 잔액부족 보류 task 3건 검증 (잔액 $9.79 한도 내)

X5 — router HTTP path 실호출 검증 ✅

  • 호출: anthropic/claude-sonnet-4.6 직접 (router-openrouter.callOpenrouter)
  • 응답: "2" (1832ms, prompt 112 / completion 5 = 117 tokens)
  • OpenRouter 가 알려주는 실제 cost = $0.000411 = 우리 OR-1 가격표 ($3 input + $15 output per 1M) 와 정확히 일치
  • 즉 가격 추정 100% 정확. 사용자 차감 (NEXUS_CREDITS_ENFORCE=true 활성 시) 정확
  • 함정: model ID 는 anthropic/claude-sonnet-4.6 (openrouter/ prefix 벗긴 형태). router.js:235 에서 replace(/^openrouter\//i, '') 로 처리됨. 직접 호출 시 prefix 안 벗기면 invalid model ID 떨어짐 (X5 첫 시도에서 그렇게 잡혀냄)

F-D4 — max_tokens 4000 vs 1500 비교 ✅

  • haiku-4.5 같은 prompt 두 번 호출
  • max=4000 → timeout (3분, 모델이 토큰 끝까지 채우려 시도)
  • max=1500 → 2131ms, prompt 121 / completion 140 = $0.000821 (haiku 가격 정확 일치)
  • 결론: max_tokens 1500 으로 낮춤 권장. latency cap + 응답 길이 충분
  • 적용 시점: 잔액 추가 충전 후 router-openrouter.js default 4000 → 1500. 회귀 위험 보통

T-spam-B-external — 외부 cron 누출 path 없음 ✅

  • 4/26 19:32 영문 누출 폭탄 = router 내부 [router] 로그 (sendTelegram 안 함)
  • 4/26 21:00 이후 F1 cooldown 도입으로 openrouter_cooldown_provider (Insufficient credits, retry in <5min) 로 변환 — T-spam-D humanize 로 한국어 변환됨
  • root crontab = neuronfs emit 1줄 (텔레그램 발송 X)
  • scripts/ 안 sendTelegram 직접 호출 0건
  • 진단 오류 14번째: T-spam-B-external 은 잘못 분류된 부채. 외부 cron path 자체가 존재하지 않음. T-spam-D + F1 cooldown 으로 차단 완료

잔액 사용

  • X5: $0.000411
  • F-D4: $0.000821 (max=1500 만 성공)
  • 합계: 약 $0.0012 (잔액 $9.79 → $9.79). monitor 6시간 polling 까지 변동 없을 것

4/26 보류 task 종합 (5건 중)

task이번 세션미완 사유
X5 자율진화 input 검증✅ 완료
F-D4 max_tokens 비교✅ 완료 (수치 측정)적용 commit 은 추가 충전 후
T-spam-B-external 추적✅ 완료 (false positive)코드 변경 불요
AA-P3 MoA 다중모델 합의⏳ 보류비용 4배, 잔액 부족
AA-P2 Progressive Disclosure⏳ 보류1~2시간 + 토큰 많이 소모
Z 풀 Nexus 파일럿⏳ 보류회사 정보 paste + 잔액

사토시 관점 (#2)

  • "compact 전 할 거 다 마무리" → 4/26 보류 task 까지 끌어와서 잔액 한도 내 가능한 3건 모두 검증 종결. 진단 오류 1건 추가 (14번째).
  • OR-1 가격표 정확도가 X5 의 OpenRouter 자가-cost 응답과 1원도 안 틀리고 일치 — 가격 sync 가 단순 cosmetic 이 아니라 KRW 차감 정확도의 토대.