작업 이력 — 2026-06-16
기획 (planner)
A. 요구사항 정의서 정본화 — docs/REQUIREMENTS.md 신규
분산돼 있던 요구사항(CLAUDE.md·ROADMAP.md·ADMIN-PLAN.md·PROJECT-INQUIRY-ANALYSIS.md)을 단일 정본으로 집약. 분산 문서는 대체하지 않고 요약·상호참조(링크).
- 기능 요구사항 FR-1~FR-12 (각 수용기준 AC 포함), 비기능 요구사항 NFR-1~NFR-8.
- 안전가드(NFR-1)는 운영 MySQL
hp_settingsafety 시드값과 일치 — 근거:malgn-helper-api/migrations/002_admin_console.sqlINSERT 4-4 (라인 128~134). 값:confidence_threshold=0.6·escalate_on_low=true·pii_masking=truepii_patterns=주민번호·전화·이메일 정규식 3종(JSON) ·blocked_words="비방","욕설","스팸","광고"
- Phase 1/2 범위 경계, 표준답변 우선(FR-1)·출처 인용(FR-2)·"모름"/에스컬레이션(FR-3)·비공개 자료 비노출(FR-10) 정책 명문화.
- 추적성 매트릭스(요구사항↔화면/데이터/로드맵), 정책 결정/미정 TODO 5건(Q1~Q5), 후속 핸드오프.
발견한 불일치(Q2): hp_service 시드 슬러그(step/lms-general/lms-mixed/lms-private/lms-public-security/lms-global)와 ADMIN-PLAN §4-3-1·use-bots.ts(lms-general/-refund/-public/-security/-hybrid/-global)가 불일치. 정본 슬러그 세트 확정 필요(DBA+기획).
B. bots/ 화면 기획 결정 — docs/ADMIN-PLAN.md §4-13 신설
malgn-helper-admin/pages/bots/{index,[id]}.vue + use-bots.ts(use-admin-menu.ts:39 메뉴)로 기획 없이 선구현된 "봇 관리" 화면 검토.
- 결정: 정식 편입 + 백엔드 완성 전까지 메뉴 숨김. 봇 단위 거버넌스(서비스별 말투·답변범위·"모름" 강도·에스컬레이션 임계값·가시성·학습소스)는 분류 정책·P2 다중 챗봇과 정합해 가치 있음. 단 현재 localStorage 데모뿐(
hp_bot/hp_bot_source·/admin/bots부재)이라 노출 시 오인 위험 → 백엔드 게이트. - ADMIN-PLAN 반영: IA 트리·§3-2 메뉴표(2.0, 숨김 표기)·§4-13 화면 명세·§5-3 API(
/admin/bots)·§9 결정 로그. - 후속(api-developer·DBA):
hp_bot(페르소나·답변범위·모델 파라미터)·hp_bot_source(bot↔material/standard_answer 다대다) 신설 +GET/POST/PATCH/DELETE /admin/bots(requireRole('admin','developer')).use-bots.ts가 이미 해당 스키마에 1:1 매핑.
핸드오프
- DBA: Q2 슬러그 정합, FR-12 편입 시
hp_bot/hp_bot_sourceDDL. - api-developer:
/admin/botsCRUD, safety 설정값 실제 적용 검증(NFR-1 AC). - QA: NFR-1(safety 화면=시드)·FR-2(출처 누락 차단)·FR-3(저신뢰 분기) 테스트.
- 개인정보보호관리자: Q3 비공개 자료·PII 노출 규칙 확정.
생성/수정 파일
- 신규:
docs/REQUIREMENTS.md - 수정:
docs/ADMIN-PLAN.md(IA 트리·메뉴표·§4-13·§5-3·§9)
보안 수정 (security-reviewer → deployer)
무인증 노출 라우트 차단 + 디버그 라우트 제거. api/admin 2개 레포 배포.
malgn-helper-api — Cloudflare Workers
- 커밋:
41d6f6a/ Version ID:31dbb92a-f503-4e76-965a-3d60fe73a885 - URL: https://malgn-helper-api.malgnsoft.workers.dev
- 무인증 노출 라우트에
requireAuth/requireRole가드 추가:/admin/kpi·/admin/cost·/admin/evals·/image-assets(GET·/:id)·/standard-answers(GET·/:id·PATCH·DELETE). 가드 정의 블록 TDZ 회피 위해 파일 상단으로 이전. - 무인증 디버그/일회용 라우트 6개 삭제:
GET /db/ping·/db/whoami·/db/tables·/db/columns/:table·/db/sample/:table,POST /admin/migrate/hp_image_asset. - 빌드:
tsc --noEmit11 baseline(신규 0, working↔HEAD 동일 확인),wrangler deploy --dry-run번들 정상. - 검증(무인증 curl):
/admin/kpi·/admin/evals·/admin/cost·/image-assets·/standard-answers→ 모두 401(이전 200 차단)./db/sample/tb_user·/db/tables·/db/ping→ 모두 404(제거 확인). 루트/→ 200.
malgn-helper-admin — Cloudflare Pages
- 커밋:
f1a4b20/ production: https://malgn-helper-admin.pages.dev / alias: https://e9c060c8.malgn-helper-admin.pages.dev / buildId:21f06fa3-6824-4219-a009-30b1865b479e index.vue·cost.vue·qa-evals.vue·images.vuefetch에credentials:'include'추가(api 가드와 정합).pages/forbidden.vue신설.- 빌드:
nuxt build통과(forbidden신규 chunk 산출 확인). - 검증(curl): prod
/200(buildId 마커 확인)./forbidden→ 200(이전 404 해소, alias도 200). 연동 4페이지/·/cost·/qa-evals·/images→ 모두 200(SSR 셸).
정합
- 두 레포 working tree clean,
origin/main동기화 완료(미푸시였던 직전 배포 커밋9cefd48·2d1acf9도 함께 푸시되어 origin↔live 일치). - 경계 준수: mng(docs)·pms 미변경.
서비스토큰 관찰모드 (security-reviewer → deployer)
PMS→API 서비스토큰 가드 + LLM rate limit 관찰모드(SERVICE_TOKEN_ENFORCE=0) 점진 도입. api/pms 2개 레포 동시 배포 + 시크릿 양쪽 등록. 하드차단(1) 아님 — 회귀 없음.
시크릿/환경 등록
- 강한 랜덤 토큰(
openssl rand -hex 32, 64 hex, prefixa999ed…) 1개를 양쪽에 동일 등록(값 비노출). - api:
wrangler secret put PMS_SERVICE_TOKEN(Worker) — secret list 확인. - pms:
wrangler pages secret put NUXT_PMS_SERVICE_TOKEN— Production + Preview 양쪽 등록 확인(Value Encrypted).
malgn-helper-api — Cloudflare Workers
- 커밋:
85025ce/ Version ID:aced5319-a03b-470c-87b1-8483a12e592d - URL: https://malgn-helper-api.malgnsoft.workers.dev
requireServiceToken(관찰:X-Service-Token-Status: missing|mismatch헤더만, ENFORCE≠1이면 통과) +rateLimitLlm(route+IP 키) 미들웨어 신설.- 적용: LLM generate 4종(
/pms/projects/:id/briefing/generate·/pms/posts/:id/announce-eval/generate·/pms/posts/:id/eval/generate·/pms/projects/:id/standard-answer-suggestions)에 guard+ratelimit,/standard-answers(POST)·/standard-answers/:id/use에 guard. wrangler.jsonc:[[ratelimits]] RL_LLM(12/60s),vars.SERVICE_TOKEN_ENFORCE="0".- 배포 바인딩 확인:
env.RL_LLM (12 requests/60s),env.SERVICE_TOKEN_ENFORCE ("0").
malgn-helper-pms — Cloudflare Pages
- 커밋:
e4b54f7/ production: https://malgn-helper-pms.pages.dev / alias: https://db098a98.malgn-helper-pms.pages.dev / deployment:db098a98-97b8-4f45-90af-7eeee4274b3d server/utils/forward.ts(서버 전용 투명 프록시,x-service-token서버 주입) + 서버 프록시 라우트 5종(/api/standard-answers,/api/pms/...generate4종).nuxt.config.tsruntimeConfig.pmsServiceToken(envNUXT_PMS_SERVICE_TOKEN, public 아님). 호출부 6곳을 프록시 경유로 전환 + 안내글평가 UI(AnnounceEvalCard.vue·eval.vue·types/announce-eval.ts).- 빌드:
nuxt build통과, 서버 프록시 5 chunk 산출 sanity OK, project-name=malgn-helper-pms 일치.
검증
- 회귀 없음: pms prod
/→ 200. pms 프록시POST /api/standard-answers(빈 바디) → 400(핸들러 validation 도달=토큰 일치, 가드 통과). 프록시는x-service-token-status미전파(정상, forward가 content-type/status/body만 전달). - 관찰모드: api 무인증
POST /standard-answers·/pms/.../briefing/generate→ 400(핸들러 validation, 401 아님=관찰 통과) + 헤더X-Service-Token-Status: missing. 잘못된 토큰 →mismatch. 가드가 missing/mismatch 구분 + 둘 다 통과(ENFORCE=0). - rate limit:
RL_LLM(12/60s)바인딩 등록·active 확인. 단 합성 burst(순차 14·병렬 20)에서 429 미발생 — Cloudflare rate-limiting 바인딩은 best-effort/eventually-consistent(버스트 언더카운트 가능). 미들웨어 배선(handler 앞)·바인딩은 정상. ENFORCE=1 전환 전 실트래픽 로그로 재확인 권장.
정합
- api·pms 두 레포 working tree clean,
origin/main동기화. mng은 이번 단계 비대상(이 history 항목만 별도 커밋 예정). - 경계 준수:
SERVICE_TOKEN_ENFORCE는0(관찰) 유지 — 하드차단(1) 미전환.
배포
배포 시각·커밋 로그(워크스페이스
deploy.sh기록, helper repo에서 이관).
21:57 — malgn-helper-api → Cloudflare Workers
- 커밋:
41d6f6a(신규 커밋: yes) - 메시지: fix(security): guard admin/kpi·cost·evals·image-assets·standard-answers + remove unauth /db debug routes
21:58 — malgn-helper-admin → Cloudflare Pages
- 커밋:
f1a4b20(신규 커밋: yes) - 메시지: fix(security): send credentials on kpi/cost/evals/images + add /forbidden page
22:18 — malgn-helper-api → Cloudflare Workers
- 커밋:
85025ce(신규 커밋: yes) - 메시지: feat(security): service-token guard + LLM rate limit on PMS routes (observe mode)
22:19 — malgn-helper-pms → Cloudflare Pages
- 커밋:
e4b54f7(신규 커밋: yes) - 메시지: feat: service-token server proxy + announce-eval UI