Concat · TO-BE — ADR-0013
아이티데일리 E2E MVP — TO-BE 가이드
TO-BE 재설계(PR #25)가 무엇을 바꿨는지, AS-IS 가이드와 짝을 이뤄 비교로 정리했습니다. 파일럿 완료가 「배관 검증」에서 「수집 → 재구성 → 검수 → 발행 → REST 제공」 서비스 실증으로 넓어집니다.
📌 AS-IS 가이드(같은 날 작성)의 짝 문서입니다. 회색 점선 카드가 AS-IS, 초록 카드가 TO-BE입니다. 코드는 아직 0줄 — PR #25는 문서(설계·계획)만 바꿉니다.
한눈 비교 — 무엇이 바뀌나
6개 축에서 갈립니다. 왼쪽(AS-IS)은 어제까지의 계획, 오른쪽(TO-BE)이 새 기준입니다.
배관 검증 — 수집 원문이 매거진 raw_items에 도달하면 파일럿 완료. AC 7술어, 발행 술어 0개
서비스 실증 — 재구성·검수·발행·REST 제공·파트너 어드민까지. AC 12술어 (배관 7 승계 + 발행 5 신설)
아이티데일리 원문뿐 — GCS 원본 HTML · engine.articles · raw_items 사본. 재구성 기사 0건
원문 + 발행된 재구성 기사 — Cloud SQL 행 + GCS 발행 스냅샷 + /v1/published 응답
MVP 범위 안에 LLM 호출 0건 — 재구성은 "이후 운영"
재구성(LLM)이 MVP 안 — 단, 위치는 그대로 매거진 계층. 엔진 코어 LLM 0은 불변(검사기 강제)
인스턴스 2개 계획 — 엔진(서울, 실물) + 매거진(도쿄, 미생성)
서울 인스턴스 1개 + DB 2개 — postgres(engine)·magazine(신설). 매거진 코드 무수정(DSN 교체뿐)
표면 2개로 분리 — 엔진 Pull API(MVP 안) / 매거진 서빙 API는 web/에 별도(M7, 미착수·MVP 밖)
apps/api 하나로 통합 — /v1/articles(원문) + /v1/published(발행 기사). web/은 휴면
파트너 접수구는 구글 폼 수준(M4) · 검수는 SQL 콘솔(전이 규칙을 우회하는 raw UPDATE)
계정 로그인형 파트너 어드민(삭제 즉시 반영·정정 접수) + 내부 검수·발행 UI(transitions.py 경유 — 우회 갭 해소)
완료 기준 — AC 7술어 → 12술어
배관 7개는 문면 그대로 승계됩니다(설계 근거 3가지도 유효). 발행 5개가 새로 붙습니다. 문면의 단일 출처는 ADR-0012 rev4 = ADR-0013이고, CLAUDE.md와 바이트 동일하게 유지됩니다.
itdaily-kr.yaml이 load_source_configs() 검증 통과 — contract_note 실재 = 계약 반입의 기계적 증명engine.sources에서 slug='itdaily'의 enabled=trueengine.articles 행 1건raw_items 행 1건 + suppression 시 매거진 기사 unpublished 전이parse_status='empty' 행 1건 + 알림 발화 — 문면 정정: 구 문면 'failed'는 현재 코드로 재현 불가(파서는 empty를 냄, PR #24 의미 확정 반영)body_hash 변경writer_mode='reconstruct') → in_review 도달published 전이 (transitions.py 경유 — 불변 원칙 4)vertical-news-published, body_md + 메타 JSON)GET /v1/published가 해당 기사 반환 — publisher·source_url·ai_notice 3필드 포함in_review 재진입발행이 MVP에 들어와도 approved 없이 published 불가(불변 원칙 4)는 그대로입니다.
달라지는 것은 수단 — 지금 검수는 SQL 콘솔의 raw UPDATE라 전이 규칙을 우회하는데,
⑨의 검수 UI는 transitions.py를 경유해 그 알려진 갭을 닫습니다.
TO-BE E2E 워크플로우 — 경계선이 내려간다
AS-IS 가이드의 그 그림에서 달라진 것은 하나입니다 — MVP 경계선의 위치. 구 경계(회색 유령선)는 어댑터 뒤에 있었고, 새 경계는 파트너 어드민까지 내려갑니다.
OIDC로 worker를 깨움 — AS-IS와 동일.
기사 1건 = 태스크 1건, 1 req/s — AS-IS와 동일.
AS-IS와 동일 — 규칙 기반 파싱, 모델 호출 없음.
/v1/articles를 당겨 raw_items에 적재. 이제 같은 인스턴스 안에서의 이동이다(§4).
30분 사이클이 raw_items를 집어 KR+contract 라우팅 → reconstruct/(PR #23 품질) → in_review.
코드 0줄 재사용 — 어댑터가 넣으면 기존 사이클이 그대로 돈다.
in_review 큐 → 본문·verify_detail·batch_stats 확인 → 승인/반려.
SQL 콘솔 대신 transitions.py 경유.
published 전이(publish.py 첫 실호출) + 발행본 JSON 스냅샷 —
불변 증빙·서빙 캐시 원본. ISR revalidate는 대상이 없어 스냅샷+API가 대체.
비즈크러시 등 소비 서비스가 커서로 당겨감. publisher·source_url·ai_notice 3필드 포함.
제휴 언론사 로그인 → 자사 기사 삭제(즉시 suppress+unpublish)·정정 요청. 기존 takedown 배관의 첫 실호출자.
인프라 — 2리전 계획에서 서울 단일로
도쿄 인스턴스는 실물이 만들어진 적이 없습니다 — 제거는 지우는 작업이 아니라 계획에서 빼는 것입니다.
AS-IS 계획 — 인스턴스 2개 · 리전 2개
어댑터가 리전을 건너 써야 했고, "문서 도쿄 vs 실물 서울" 미결이 걸려 있었다
TO-BE — 인스턴스 1개 · DB 2개 (서울)
매거진 코드는 스키마 접두 없이 짜여 있어 코드 무수정 — DATABASE_URL 교체뿐.
격리는 DB 단위 계정·GRANT로 유지(킥오프 #1을 인스턴스→DB 분리로 완화, ADR-0008 rev4)
같은 인스턴스에 얹는 방법이 둘이었습니다. mag 스키마 방식은 search_path 설정 또는
전 쿼리 수정이 필요했고, 별 DB 방식은 코드 0줄입니다. 매거진 워커 Job이 이미 서울에
배포돼 있어(PAUSED) 리전 정합도 이것으로 확정됩니다.
서빙·어드민 — 금지 하나를 해제하고, 폼을 어드민으로 승격
"엔진 api에 매거진 라우터 금지"는 DB 물리 분리가 전제였던 규칙입니다 — 전제가 §4로 사라져 함께 개정됐습니다(ADR-0008 rev4).
apps/api — FastAPI 하나, 표면 둘
| 엔드포인트 | 데이터 | DB | 소비자 |
|---|---|---|---|
GET /v1/articles | 수집 원문 (M2 설계 승계) | postgres/engine | 어댑터 (내부) |
GET /v1/published NEW | 재구성 발행 기사 + 3필드 | magazine (published_articles 뷰) | 비즈크러시 등 외부 서비스 |
| admin 라우트 NEW | 검수·발행·파트너 인증·정정 접수 | 둘 다 (라우트별 DSN 분리) | admin-web (DB 직결 금지) |
apps/admin-web — 화면 6개, 사용자군 2개
| 화면 | 사용자 | 기능 |
|---|---|---|
/login | 공통 | 이메일+비밀번호(bcrypt) · 세션 쿠키 · engine.partner_accounts(소스 스코프) |
/my/articles | 파트너 | 자사 기사 목록 — 수집 원문 + 발행 기사, 스코프 강제 |
/my/articles/[id] | 파트너 | 삭제 = 즉시 takedown→suppress→unpublish · 정정 = 접수→재파싱+재구성→재검수 |
/my/requests | 파트너 | 요청 이력·처리 상태 |
/review | 내부 | in_review 큐 → 승인/반려 |
/review/[id] | 내부 | 발행 버튼 · unpublish (전부 transitions.py 경유) |
삭제 경로(takedown_requests → article_suppressions → unpublished 전이)는 DDL·전이
함수까지 전부 구현돼 있고 호출자만 0이었습니다. 파트너 어드민의 삭제 버튼과 검수 UI의
발행 버튼이 unpublish_article·publish_and_revalidate의 첫 실호출자가 됩니다.
마일스톤 — M 체계에서 T0~T6으로
260811 계획서의 M0~M6을 승계·재편했습니다 (M0·M1→T0·T1 / M2→T2 / M3→T3 / M6→T4·T6 / M4·M5→T5). T1·T2·T3은 병행 가능하고, T2는 테크월드(epnc) 시드로 T0 완료 전에도 착수할 수 있습니다.
UA 사전 공유 메일(🔴 유일한 전역 블로커) → robots.txt → M0 셀렉터 실측 → 임베딩 계약 판단 → 파트너 계정 정책. 코드가 아니라서 재설계로도 없어지지 않는다.
magazine DB 신설 + 계정 2종 → 마이그레이션 0001~0017 적용 → 시드. 게이트: DSN만 바꾸고 매거진 pytest 전량 그린(코드 무수정 증명).
M2 지시서 §3~§5 전량 승계 + /v1/published·admin 라우트 추가. 게이트: 로컬 e2e — published 반환→unpublish 시 소거까지.
Cloud Run Service 3 + Job 2(기존 pipeline-worker는 import) + Scheduler 2 + vertical-news-published 버킷 + CI 2레인. 게이트: plan drift 0 → 승인 apply.
Pull 폴링→raw_items(게이트 seam 경유) · suppressions 역추적→unpublish · 발행 버튼→publish.py+GCS 스냅샷. 재구성 자체는 코드 0줄.
화면 6개 + 계약 이행 6건 체크리스트(발행이 MVP에 들어와 함께 크리티컬 패스가 됐다). 게이트: 스코프 침범 403 · 미승인 발행 거부.
AC 12술어 스테이징 1회 실증 + 되돌림 확인 → docs/audit/ 기록. 곽팀장 참관.
바뀌지 않는 것 · 대기 중인 것
원문 차단 모듈 경계(재구성은 원래 계약 경로) · ND 차단 · 팩트 무결성 · 검수 게이트. 엔진 코어 LLM 0도 검사기 그대로.
UA 사전 공유 메일이 여전히 모든 네트워크 요청을 막고 있고, M0 실측 없는 시드는 침묵 실패(부록 A 그대로 유효)다.
① 파트너 어드민 공개(대외 표면) ② 킥오프 #1 개정(인스턴스→DB 분리). 확인 즉시 Accepted 전환.
apps/ 골격·가드·UA 정정과 M2 지시서가 그 브랜치에 있다 — T2의 전제.
JP 트랙은 T6까지 보류(테스트 그린·langpack/ja 동결 유지) · digest 발행은 인공지능신문 계약 대기(ADR-0009) · 테크월드는 enabled=false로 유지.
세션·비밀번호·소스 스코프 강제가 데모 수준이면 안 됩니다. T5 게이트에 스코프 침범 403 테스트가 명시된 이유이고, 계약 이행 의무 6건(출처 블록·표시 시안·성과 공유 계측 등)도 발행과 함께 MVP 크리티컬 패스로 들어왔습니다.