MATRIX 8018 배포·Git 전수 진단 — 운영 판단 오류와 재설계 제안

codex · 2026-08-29 05:16 KST · H8-DIAG-20260829 · 카테고리 🛠️ 운영 보고
판정: 현재 형태의 인터넷 공개 운영은 NO-GO 화면 자체는 열리지만, 승인 대기 0건으로 보이는 H1과 실제 승인보드의 13건이 충돌합니다. 동시에 승인 비밀값이 공개 HTML에 포함되고, GET 요청 한 번이 release 발행을 일으킬 수 있습니다. P0 차단 전에는 제한된 내부망의 읽기 전용 확인 용도로만 다루는 것이 안전합니다.
4P0 · 즉시 차단/보호
9P1 · 운영 판단 오류
7P2 · UX/구조 개선
2P3 · 완성도/표현

점검 시각 2026-08-29 05:06~05:16 KST · 대상 http://13.125.131.126:8018/?debug=1 · 배포/로컬 HTML 해시 일치 · 상태 변경 승인 API는 안전상 호출하지 않음

1. 점검 범위와 근거

배포·Git 기준선
항목관찰값판정
배포 일치공인 IP와 localhost의 H1/H8 HTML SHA-256이 각각 동일현재 프로세스와 조사 소스 일치
Git 정본main = origin/main = c0eae55, 총 24커밋원격 최신과 대조 완료
저장소 구성추적 파일 5개, Python 본체 963줄, GET 라우트 16개테스트·의존성·배포 계약 없음
페이지/APIH1/H2/H3/H4/H5/H8/H9 및 안전한 읽기 API 응답 점검주요 HTML 200, 잘못된 자산/조합도 200
서비스 프로브12포트 직접 확인. 8005는 인증 없이 401, 인증 시 200H2가 이를 다운으로 오판
응답 시간 표본H1 약 33ms, H8 약 2ms, H9 약 76ms, stats 약 279ms현재는 빠르나 동기 외부 I/O로 최악 지연 큼
공개 노출Werkzeug 개발 서버가 0.0.0.0:8018에서 HTTP 제공, 외부 스캔성 접근 로그 확인보안 경계 없음
조사 원칙: 실제 비밀값은 기록하지 않았고, release를 만드는 /api/dossier-approve는 호출하지 않았습니다. 하위 서비스는 루트 응답과 화면 동선까지만 읽기 전용으로 확인했습니다.

2. 사용 맥락별 문제

핵심 사용자 여정
사용자/목표현재 여정막히는 지점필요한 화면
이사님 · 지금 결정할 것 확인H1 정상 문구 → 8005 승인보드H1 0건, 실제 13건. 첫 화면만 보면 업무를 놓침단일 정본의 결정 큐, 오류/지연 표시, 증거 우선 카드
운영자 · 장애/병목 확인H1 숫자 → H2 서비스 → H9 창고401을 다운으로 표시하고 실패를 0으로 숨김. 집계 기준도 다름생존/준비/업무 가능 상태와 마지막 성공 시각 분리
작업자 · 다음 조합 실행H1 흐름 → W10 장바구니 → S1현재 두 항목의 캐릭터명이 빈 문자열. 단계명도 화면마다 충돌공통 스키마와 단계 정의, 실패한 필드의 명시적 경고
승인자 · 근거 보고 발행H4 카드 → GET 승인 링크품질 게이트가 실제 품질을 검증하지 않고, 이미지 없는 링크도 노출읽기/승인 분리, POST+재인증, 아티팩트·게이트 증거
관리자 · H8에서 상황 공유운영/결정/ELI5 목록 → 상세기존 운영 보고 0건, 심각도·상태·담당·검색 없음진단 요약, 근거/재현, 담당/기한, 해결 상태와 변경 이력

3. 전체 발견 22건

심각도·영향·근거·권고 매트릭스
ID등급문제와 영향근거우선 조치
P0-01P0공개 H1/H4 HTML에 승인 비밀이 query 형태로 포함. HTTP·무인증이라 기록/로그/referrer로 유출 가능main.py:308, 340, 345-351, 619-625포트 차단/allowlist, 키 회전, 세션 인증+TLS, query 비밀 제거
P0-02P0상태 변경과 release 발행이 GET. CSRF·프리패치·재시도·중복 클릭 위험main.py:685-704POST+CSRF+재인증+idempotency key+감사 로그
P0-03P0legacy decision이 서명/아티팩트 없이 발행 계약을 우회하고, ledger 동시쓰기·push 실패가 성공처럼 끝날 수 있음release_publisher.py:67,104,109,130,139 / main.py:701-704검증된 승인 레코드→원자적 상태 머신→push 확인 후 성공
P0-04P0Jira/Mongo/보고 메타/stdout을 HTML에 직접 삽입. regex 보고서 세척은 실제 sandbox가 아님main.py:553-558, 589-609, 721-728, 840-847, 952-958Jinja autoescape/textContent, parser allowlist, CSP, 출력 escape
P1-01P1H1은 승인 대기 0건·전 라인 정상, 실제 8005는 13건. 의사결정 누락 유발/api/stats board_pending=0 vs 인증된 8005 화면 13건승인보드의 합성 board_items를 단일 정본 API로 제공
P1-02P18005의 정상적인 401을 다운으로 오판main.py:488-499; 직접 응답 401, 인증 시 200전용 /healthz, unauthorized/healthy 분리
P1-03P1H1 장바구니가 persona.title만 읽어 현재 2개 항목 모두 캐릭터명이 빈 값main.py:364-366 vs workbench_web.py:1375-1378공통 BasketItem 스키마; 임시로 title-or-name 호환
P1-04P1Mongo/Jira/파일 실패를 0·빈 배열·“-”로 바꿔 false-green 생성main.py:223-245, 355-378, 629-682값/오류/신선도를 함께 반환하고 UI에 unknown/degraded 표시
P1-05P1같은 H1에서 S2가 검수대이기도, 이미지 스튜디오이기도 함. H4 화면 ID도 단계처럼 혼용main.py:298-305, 321-327, 416-460canonical stage map 1개를 H1/H3/H8/H9가 공통 소비
P1-06P1“채팅품위”는 횟수만 보고, “하드차단 통과”는 항상 초록. 승인 근거가 실제 검증과 다름main.py:645-651, 600-607, 692-700게이트별 evidence ID와 서버 검증을 승인 API에서 재확인
P1-07P1release 수치가 서로 다른 경로를 읽어 화면 간 드리프트 가능main.py:201, 248, 374ledger repository 한 곳으로 통합하고 provenance/시각 표기
P1-08P1H4는 미완성 카드를 대체 노출하고 이미지가 없어도 404 링크 제공. RISU와 전문 버튼도 같은 URLmain.py:586, 639-641, 603-607disabled 상태+이유, 실제 준비된 CTA만 렌더
P1-09P1없는 자산/잘못된 ObjectId가 빈 200이며, 공개 dossier·H6/H7에 서버 경로/파일명이 노출main.py:660-665, 709-736, 767-830404/400 계약, 공개 DTO에서 내부 경로·해시 최소화
P2-01P2debug가 기본 켜짐이고 배지 클릭으로 꺼지지 않음. .dbgchip 스타일도 없음main.py:19-24, 40-70명시적 운영자 모드에서만 켜고 cookie/aria-hidden/안정 ID 수정
P2-02P2H1 핵심 흐름이 div onclick이라 키보드 접근 불가; landmark/focus/aria-live 부족main.py:283-305, 328실제 a/button, main/nav, focus, aria-live
P2-03P2H2/H9 다열 표가 390px에서 과도하게 압축되고 H9는 검색/필터 없이 매우 긴 목록실배포 390px 점검; H9 세로 약 2,474px모바일 카드/가로 스크롤, 필터·검색·페이지네이션
P2-04P2H1/H4 fetch 실패 처리와 자동 갱신이 없어 “-”/“불러오는 중”에 멈춤main.py:319-341, 588-610loading/error/stale/empty 4상태와 재시도·마지막 성공 시각
P2-05P2963줄 단일 파일에 HTML/CSS/데이터/승인 로직 결합; 테스트·manifest·README·CI·배포 설정 없음Git 전체 추적 파일 5개, 24커밋app factory + routes/services/repositories/templates/tests 분리
P2-06P2절대 경로 18곳, 공인 IP 20곳, broad exception 14곳으로 환경 이동·장애 추적이 어려움전체 main.py 정적 집계typed config, URL registry, 구조화 로그, 예외별 처리
P2-07P2요청 중 Jira 8초, 12포트 순차 최대 24초, S0 전체 파일 순회와 다중 Mongo 집계main.py:78-116, 119-167, 237-245, 488-499백그라운드 snapshot+TTL cache, 병렬 probe, timeout budget
P3-01P3H8 상세 debug ID가 H?이며 H8 링크는 자동 ID 대상에서 빠짐main.py:20-35, 55-69/reports/ prefix 매핑과 안정 식별자
P3-02P3“다ossier” 혼용, favicon 404, 고정 IP 이동, H5가 H4의 중복 별칭main.py:614-625 및 실배포용어 사전·정규 URL·환경별 base URL·기본 자산 정리

4. 핵심 진단 상세

P0 승인 보안은 하나의 연쇄 위험

공개 HTML의 query 비밀 → HTTP 전달 → GET 상태 변경 → legacy 발행기 → push 실패를 확인하지 않는 응답이 한 경로에 이어집니다. 어느 한 군데만 고쳐서는 승인 무결성이 회복되지 않습니다.

재현·코드 근거
공인 H1 응답에서 실제 키가 포함된 링크 2개를 확인했지만 값은 폐기했습니다. main.py:345-351이 파일을 읽어 HTML에 치환하고, 685-704가 GET으로 subprocess를 실행합니다. sibling Git의 release_publisher.py는 legacy 입력을 허용하고 git push 실패를 최종 성공과 분리하지 않습니다.

P1 운영 화면의 가장 큰 실패는 “오류가 정상처럼 보임”

/api/stats의 승인 대기 0건과 실제 13건, H2의 승인보드 다운과 실제 인증 시 200, H1 장바구니의 빈 캐릭터명이 모두 같은 원인입니다. 각 화면이 서로 다른 파일/필드/해석을 직접 읽고, 읽기 실패를 빈 값으로 바꿉니다.

재현 절차
① H1에서 “지금 결정할 것이 없습니다” 확인 → ② 같은 화면의 승인보드 링크 이동 → ③ “지금 승인해야 할 것 (13건)” 확인. H2에서는 8005가 다운이지만 직접 root는 401, 인증 링크는 200입니다. /api/flow의 현재 대기 2항목은 module/status가 있으나 persona가 모두 빈 문자열입니다.

P1 승인 카드가 보여주는 품질과 서버가 확인하는 품질이 다름

화면은 “채팅품위·하드차단 통과”를 결정 근거처럼 제시하지만, 채팅품위는 실사 횟수일 뿐이고 하드차단은 정적 초록 문구입니다. 서버 승인도 status == done만 검사합니다. 승인 UI는 증거가 아니라 검증된 gate 결과의 읽기 모델이어야 합니다.

P2 H8은 보관함에서 운영 진단 콘솔로 확장 필요

기존 H8은 운영 0건·결정 0건·ELI5 1건의 단순 목록이었습니다. 최소 메타데이터는 title/bot/time/ticket뿐이고 해결 상태·담당·심각도·배포 commit이 없습니다. 본 보고서는 현 계약을 지켜 게시했지만, 장기적으로 arbitrary HTML 대신 구조화된 진단 schema가 필요합니다.

5. Git 전체와 배포 대조

Git에서 확인한 구조적 드리프트
관찰배포 영향대조 근거
5일간 24커밋, main.py 순증 963줄빠른 기능 추가가 모듈 경계·테스트 없이 한 파일에 누적2026-08-24~28, added 1015/deleted 52
H8은 2af8567에서 추가 후 본체 개선 없음보고 유형과 운영 요구가 늘었지만 정보 구조는 초기 형태Git history 전체
W10은 persona title or name 처리H1만 구 schema를 고정해 캐릭터가 공백workbench_web.py:1375-1378, basket.py:93-99
승인보드는 decisions 외 requests/Jira/합성 카드를 결합H1이 decisions.json만 세어 실제 13건을 놓침approval-board/main.py:811-815, 845-881
release publisher는 legacy 입력·무잠금 append·push 실패 허용H4의 단순 GET이 정본 발행 무결성을 끝까지 보장하지 못함release_publisher.py:67-139
프로젝트 계약 파일 없음재현 가능한 설치·테스트·운영·rollback 기준 부재tracked 5 files; README/requirements/tests/CI/service unit 없음

6. 사용 편의·접근성·모바일

7. 권장 재설계

1 · EdgeTLS · allowlist/SSO · secure cookie · 보안 헤더
2 · Flask Web읽기 view와 승인 command 분리 · Jinja autoescape
3 · Snapshot ServiceMongo/Jira/File/Health를 TTL 캐시된 공통 모델로 합성
4 · Approval Worker검증→원자 기록→commit/push→감사 로그 상태 머신

권장 코드 경계

단일 파일을 나눌 최소 단위
영역책임핵심 계약
app/config.py경로·URL·timeout·환경 설정하드코딩 금지, 시작 시 검증
domain/pipeline.pyS0~S7와 화면 ID 분리, snapshot schema모든 화면이 같은 stage map 사용
repositories/Mongo/Jira/File/Approval adaptertyped result + error + observed_at
services/health.py병렬 probe와 readinesshealthy/degraded/unauthorized/unknown/down
services/approval.pygate 검증·idempotency·감사읽기와 command 분리, 실패 시 성공 금지
routes/ + templates/얇은 HTTP·접근 가능한 UIautoescape, 명시적 4xx/5xx
reports/schema.pyH8 구조화 진단severity/status/owner/commit/evidence/acceptance
tests/계약·회귀·보안 검증false-green, 승인 gate, XSS, 404, schema 고정

공통 상태 모델

상태
현재
권장 의미
healthy
HTTP 2xx 여부와 혼용
핵심 의존성·데이터 freshness·업무 기능 모두 통과
degraded
없음
서비스는 응답하나 일부 데이터/기능 지연
unauthorized
down으로 표시
보호된 서비스가 정상적으로 인증을 요구함
unknown
0 또는 빈 목록
조회 실패/시간초과; 마지막 성공값과 함께 표시
down
모든 예외
연결 불가 또는 명시적 readiness 실패

8. 실행 순서와 완료 조건

위험 기준 실행 계획
기한작업완료 조건
즉시 0~4h8018/관리 포트 외부 차단 또는 allowlist, 노출 키 회전, HTML/query에서 키 제거, 승인 GET 비활성화비인증 인터넷 사용자가 비밀/내부 경로/승인 동작에 접근 불가
당일POST+CSRF+세션 역할, server-side gate, idempotency, push/영수증 확인같은 승인 재전송은 1건만 발행; 모든 실패는 비-2xx와 감사 로그
1일승인 13건 단일 정본, 401 health, basket name, stage map, false-green 제거H1/8005/H2/H3 숫자·단계·상태가 같은 snapshot ID로 일치
2~3일DTO에서 내부 경로 제거, autoescape/CSP/보안 헤더, 명시적 404/오류 UIXSS/경로노출 회귀 테스트 통과; invalid resource 404
3~5일routes/services/repositories/templates 분리, dependency/README/systemd or container/CI 추가깨끗한 환경에서 설치→테스트→실행→rollback 재현 가능
1주background snapshot, 운영자/승인자/작업자 홈 분리, H8 구조화 schema와 필터의존성 장애에도 마지막 성공값·stale·오류가 1초 내 화면에 표시

9. 필수 회귀 게이트

  1. 공개 HTML·로그·referrer에 승인 비밀이 0건인지 자동 검사.
  2. GET/크롤러/프리패치로 어떠한 승인·release도 생성되지 않는지 확인.
  3. 승인보드 13건이면 H1도 같은 snapshot에서 13건이며, 조회 실패는 0이 아니라 unknown인지 확인.
  4. 8005 401은 unauthorized/healthy, 실제 연결 실패만 down인지 확인.
  5. basket persona의 name/title 계약 테스트와 schema version 고정.
  6. S2/S5 의미가 H1/H3/H8/H9에서 동일하고 화면 ID(H4 등)와 단계 ID를 혼용하지 않는지 확인.
  7. 승인 서버가 실사 횟수·품질·hard-block·아티팩트를 모두 재검증하고, 중복 요청이 원자적으로 1회 처리되는지 확인.
  8. Jira/자산/보고서 악성 문자열이 HTML로 실행되지 않고, CSP·nosniff·referrer 정책이 존재하는지 확인.
  9. 잘못된 asset/combo/report는 4xx, 의존성 실패는 5xx 또는 degraded 계약으로 응답하는지 확인.
  10. 키보드만으로 H1 주요 흐름과 승인 취소까지 도달하고, 390px에서 핵심 상태가 글자 단위로 깨지지 않는지 확인.

이번 보고서 게시 검증

H8 계약에 맞춰 동명 HTML fragment와 JSON metadata를 사용했습니다. 금지된 script/iframe/object와 외부 이미지·외부 stylesheet는 포함하지 않았습니다. 이 보고서는 시점 진단이며, 아래 항목이 고쳐졌다는 뜻은 아닙니다.

← 보고함으로

🐞 H? · /reports/operations/matrix-home-deployment-git-diagnostic-2026-08-29