Image rights / copyright detection system: SQLite store, HTTP app, search integrations (Naver, Google Custom Search, Google Cloud Vision web detection), image analysis (fingerprints, face/person detection, evidence enrichment, risk scoring), an admin/review layer, governance and retention policies, batch jobs, and a browser-based operator GUI. This baseline incorporates a full code-review remediation pass (46 fixes; 358 tests passing). Highlights: CRITICAL - Prevent evidence cascade-delete during the schema-constraint migration by disabling FK enforcement around the table rebuild. Security - Sandbox served media (neutralize stored XSS from uploaded/collected SVGs) via CSP + nosniff on the untrusted media routes. - Strip embedded EXIF/GPS from external image derivatives before they are sent to third-party APIs. - Return a clean 404 (not an uncaught StopIteration) for PATCH on an unknown provider. Correctness - LLM-summary failures no longer add +30 to the risk score. - Decode only explicit JS escapes so Korean image URLs are not mangled. - Consume search quota only after a successful request. - Naver/Google adapters map responses inside the failure boundary, so a malformed response degrades to evidence instead of crashing enrichment. - Domain-aware provider attribution; face-box IoU de-duplication; count searches (not result items); per-box crop isolation; clamp evidence confidence and Google CSE num; real submittedEpoch; and more. Robustness - Offline LLM connect fast-fails (short connect timeout) so seed/reload requests are not stalled; full read timeout preserved for generation. - Malformed numeric env vars fall back to defaults instead of crashing startup. Performance - Per-submission evidence reads (no full-table scan per rescore), audit-log LIMIT, lazy active-store lookup, hoisted timestamps. Tests - ~24 regression tests added pinning the above fixes. Runtime data (data/, outputs/, *.sqlite3, *.log), secrets (.env), and node_modules are gitignored.
57 lines
3.9 KiB
XML
57 lines
3.9 KiB
XML
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="560" viewBox="0 0 1280 560" role="img" aria-labelledby="loop-title loop-desc">
|
|
<title id="loop-title">보류 반려 케이스의 주의 후보 피드백 루프</title>
|
|
<desc id="loop-desc">증거 상태 표시와 케이스 판정을 분리하고 보류 반려 판정에서 주의 후보를 생성해 다음 제출의 내부 유사도 분석에 사용한 뒤 확정 DB 편입 또는 오탐 제외로 관리하는 흐름</desc>
|
|
<defs>
|
|
<marker id="loop-arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
<path d="M0,0 L0,6 L9,3 z" fill="#2f6272"/>
|
|
</marker>
|
|
<style>
|
|
.label{font-family:"Segoe UI","Malgun Gothic",sans-serif;font-size:22px;font-weight:800;fill:#172124}
|
|
.small{font-family:"Segoe UI","Malgun Gothic",sans-serif;font-size:15px;font-weight:700;fill:#4a5558}
|
|
.node{fill:#fff;stroke:#8aa0a6;stroke-width:2}
|
|
.node-key{fill:#fff7df;stroke:#d6a33a;stroke-width:2}
|
|
.node-good{fill:#ecf8f0;stroke:#2f6d50;stroke-width:2}
|
|
.node-risk{fill:#fff0ed;stroke:#a63f35;stroke-width:2}
|
|
.edge{fill:none;stroke:#2f6272;stroke-width:3;marker-end:url(#loop-arrow)}
|
|
</style>
|
|
</defs>
|
|
<rect width="1280" height="560" fill="#f8f5ef"/>
|
|
<text x="44" y="44" class="small">Mermaid flowchart · decision-loop</text>
|
|
<rect x="74" y="128" width="190" height="82" rx="14" class="node"/>
|
|
<text x="169" y="162" text-anchor="middle" class="label">증거 상태</text>
|
|
<text x="169" y="190" text-anchor="middle" class="label">표시</text>
|
|
<path d="M264 169 L344 169" class="edge"/>
|
|
<rect x="344" y="123" width="180" height="92" rx="14" class="node"/>
|
|
<text x="434" y="158" text-anchor="middle" class="label">케이스</text>
|
|
<text x="434" y="186" text-anchor="middle" class="label">판정</text>
|
|
<path d="M524 169 L590 169 L590 95 L650 95" class="edge"/>
|
|
<path d="M524 169 L590 169 L590 244 L650 244" class="edge"/>
|
|
<rect x="650" y="54" width="160" height="82" rx="14" class="node-good"/>
|
|
<text x="730" y="102" text-anchor="middle" class="label">승인</text>
|
|
<rect x="650" y="203" width="160" height="82" rx="14" class="node-key"/>
|
|
<text x="730" y="237" text-anchor="middle" class="label">보류</text>
|
|
<text x="730" y="264" text-anchor="middle" class="label">반려</text>
|
|
<path d="M810 95 L902 95" class="edge"/>
|
|
<rect x="902" y="54" width="230" height="82" rx="14" class="node-good"/>
|
|
<text x="1017" y="102" text-anchor="middle" class="label">자동 후보 없음</text>
|
|
<path d="M810 244 L902 244" class="edge"/>
|
|
<rect x="902" y="203" width="230" height="82" rx="14" class="node-key"/>
|
|
<text x="1017" y="237" text-anchor="middle" class="label">주의 후보</text>
|
|
<text x="1017" y="264" text-anchor="middle" class="label">생성</text>
|
|
<path d="M1017 285 L1017 350 L310 350 L310 398" class="edge"/>
|
|
<rect x="205" y="398" width="210" height="86" rx="14" class="node"/>
|
|
<text x="310" y="431" text-anchor="middle" class="label">다음 제출</text>
|
|
<text x="310" y="459" text-anchor="middle" class="label">유사도 분석</text>
|
|
<path d="M415 441 L535 441" class="edge"/>
|
|
<rect x="535" y="398" width="230" height="86" rx="14" class="node-key"/>
|
|
<text x="650" y="431" text-anchor="middle" class="label">주의 후보 근거</text>
|
|
<text x="650" y="459" text-anchor="middle" class="label">별도 표시</text>
|
|
<path d="M765 429 L865 429" class="edge"/>
|
|
<path d="M765 455 L1060 455" class="edge"/>
|
|
<rect x="865" y="398" width="160" height="86" rx="14" class="node-good"/>
|
|
<text x="945" y="431" text-anchor="middle" class="label">확정 DB</text>
|
|
<text x="945" y="459" text-anchor="middle" class="label">편입</text>
|
|
<rect x="1060" y="398" width="160" height="86" rx="14" class="node-risk"/>
|
|
<text x="1140" y="431" text-anchor="middle" class="label">오탐</text>
|
|
<text x="1140" y="459" text-anchor="middle" class="label">제외</text>
|
|
</svg>
|