UVision.Hosting 0.4.0

dotnet add package UVision.Hosting --version 0.4.0
                    
NuGet\Install-Package UVision.Hosting -Version 0.4.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="UVision.Hosting" Version="0.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="UVision.Hosting" Version="0.4.0" />
                    
Directory.Packages.props
<PackageReference Include="UVision.Hosting" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add UVision.Hosting --version 0.4.0
                    
#r "nuget: UVision.Hosting, 0.4.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package UVision.Hosting@0.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=UVision.Hosting&version=0.4.0
                    
Install as a Cake Addin
#tool nuget:?package=UVision.Hosting&version=0.4.0
                    
Install as a Cake Tool

UVision.Hosting

제조 현장용 AI 비전 검사 PWA + API를 ASP.NET Core 앱으로 띄우는 라이브러리. 태블릿 카메라가 정지 감지로 자동 촬영 → VLM이 시나리오 기준으로 OK/NG 판정. 빌드된 PWA가 패키지(어셈블리)에 임베드되어 있어 별도 정적 파일 배포가 필요 없다.

  • PWA 가 BasePath(기본 /u-vision)에 마운트
  • API 가 ApiBasePath(기본 /api/u-vision)에 마운트
  • 기본 VLM provider 는 mock → API 키 없이 바로 동작(연동 확인용)
  • 단일 조직 셀프호스트 전제(멀티테넌시·계정 시스템 없음)

패턴: AddUVision() + UseUVision() + MapUVisionEndpoints(). 단독 서버(server/src/UVision.Api)가 이 세 줄로 지어진다.

어떻게 연동하나 — 엔진은 별도 앱으로

U-Vision 은 자기 프로세스에서 도는 엔진 서버로 쓰는 것이 기본이다. 다른 시스템(MES · 업무 앱)은 그 서버의 HTTP API(OpenAPI 계약)와 판정 사건 웹훅으로 붙고, 화면이 필요하면 호스트의 리버스 프록시가 PWA 경로를 같은 출처로 실어 준다(samples/SameOriginMount). 프로세스 경계는 라이선스 경계이기도 하다(아래 «라이선스»).

이 패키지를 기존 업무 앱의 프로세스 안에 넣는 방식은 이미 그렇게 쓰는 소비자를 위한 이행기 호환 경로다 — 새 연동에는 권하지 않는다. 옮겨 갈 수단은 엔진 서버 + UVision.Client(계약에서 생성한 HTTP 클라이언트) + 같은 출처 마운트이고, 지금 이 방식으로 쓰는 소비자가 옮긴 판의 다음 minor 에서 없앤다(CHANGELOG 로 알린다).

설치

dotnet add package UVision.Hosting

최소 통합 (3줄 와이어링)

Program.cs:

using UVision.Api;
using UVision.Api.Endpoints;

var builder = WebApplication.CreateBuilder(args);

// 1) 코어 서비스 등록 — 설정 섹션 "UVision"에서 바인딩, 스토리지를 contentRoot 아래로 절대화.
builder.Services.AddUVision(builder.Configuration, builder.Environment.ContentRootPath);

var app = builder.Build();

// 2) PWA(BasePath) + 정적 에셋 + 런타임 config 주입.  ※ 호스트의 라우팅/엔드포인트보다 먼저 둔다.
app.UseUVision();

// 3) API(ApiBasePath) 엔드포인트 매핑.
app.MapUVisionEndpoints(app.Services.GetRequiredService<UVisionOptions>().ApiBasePath);

app.Run();

설정 없이도 동작한다(기본값: provider mock, 스토리지 ./data, PWA /u-vision, API /api/u-vision). 브라우저로 https://<host>/u-vision/ 접속 → PWA 로드. GET /api/u-vision/health → {"status":"ok","provider":"mock"}.

getUserMedia(카메라)·Wake Lock 은 secure context 필수 — 운영 시 HTTPS(또는 localhost)로 서빙한다.

전체 동작 예제: 단독 서버 server/src/UVision.Api/Program.cs. 다른 앱에서 엔진을 부르는 예제는 samples/ClientIntegration(UVision.Client).

설정 (config 섹션 UVision)

appsettings.json:

{
  "UVision": {
    "Vlm": {
      "Provider": "mock",      // mock | openai-compatible | openai | google
      "Model": "gpt-4o",
      "ApiKey": "",            // openai/google
      "Endpoint": "",          // openai-compatible 서버 주소(/v1 은 자동으로 붙는다)
      "MaxUploadSizeMb": 10
    },
    "Ml": {
      "Provider": "none",      // none(VLM 단독) | mock | mloop — 전용 ML 분류기(신뢰성 플라이휠 ②~③)
      "Endpoint": "",          // mloop serve base URL(예: http://host:5000)
      "Model": "default",      // 학습 모델 이름
      "Token": "",             // mloop serve JWT Bearer
      "ImageColumn": "ImagePath",
      "ReviewConfidenceThreshold": 0.0  // ③ 2중체크: VLM/ML 신뢰도가 이 값 미만이면 requires_review(0=불일치만)
    },
    "Storage": {
      "DataPath": "data",                // 상대경로는 호스트 ContentRoot 기준
      "IdempotencyRetentionHours": 168   // Idempotency-Key 재전송 응답 보존 시간(0 이하 = 지우지 않음)
    },
    "Events": {                          // 판정 사건 웹훅(CloudEvents · Standard Webhooks 서명) — 비우면 비활성
      "Webhooks": [ { "Name": "mes", "Url": "https://receiver.example/hook", "Secret": "whsec_..." } ]
    },
    "AdminPin": null,                     // 미설정 시 관리(쓰기)는 503 + 파일시스템 부트스트랩으로 최초 설정(아래 참고)
    "BasePath": "/u-vision",              // PWA 마운트 경로 (⚠️ 아래 제약 참고)
    "ApiBasePath": "/api/u-vision",       // API 네임스페이스
    "Title": "U-Vision"                   // 런타임 config로 SPA에 주입
  }
}

실제 VLM provider 연동 예(OpenAI 호환 셀프호스트 서버 — GPUStack · vLLM · Ollama 등):

"Vlm": { "Provider": "openai-compatible", "Model": "qwen2.5-vl", "Endpoint": "http://gpu-host:8080" }

③ 2중체크 (VLM + 전용 ML 교차검증)

Ml.Provider 가 none 이 아니면 /inspect 가 VLM·ML 을 병렬 호출(Task.WhenAll)해 교차검증하고, 응답·저장 레코드에 additive 필드를 덧붙인다(ML none이면 필드 전체 생략 = 기존 wire 보존):

{
  "verdict": "OK", "findings": "", "confidence": 0.95, "timestamp": "...", "image_id": "...",
  "ml": { "label": "ok", "confidence": 0.98 },  // 전용 ML 교차검증
  "agreement": true,                              // VLM·ML 일치 여부
  "requires_review": false                        // 불일치/저신뢰 → 사람·오라클 검토(③→④)
}

VLM verdict 가 여전히 주 판정이고 ML 은 교차검증이다. ML 호출 실패는 판정을 막지 않는다(degrade — VLM 단독 응답).

인증 모델

  • 운영/읽기 무인증: GET /api/u-vision/scenarios, 결과·기준이미지 조회·서빙, POST /api/u-vision/inspect · POST /api/u-vision/v2/inspect.
  • 관리/쓰기는 PIN: 시나리오 생성·수정·삭제, 기준이미지 업로드·삭제는 헤더 X-Admin-Pin 필요.
  • UVision:AdminPin 미설정 → 관리 엔드포인트는 503 {setup_required}(운영은 정상)이고, 데이터 디렉토리의 일회용 admin-setup-token.txt 로 POST /admin/setup 에서 첫 PIN 을 정한다(PBKDF2 해시 저장). 설정값 PIN 이 있으면 이 경로는 꺼진다. 계정·세션·역할 시스템은 의도적으로 없다.

관리자 PIN 최초 설정 (first-run bootstrap)

계정 시스템이 없으므로 신규 설치가 서버 파일 수정·재시작 없이 UI 만으로 첫 PIN 을 정할 수 있게 한다. 우선순위: 명시적 config PIN(UVision:AdminPin/ADMIN_PIN) > 파일 부트스트랩({DataPath}/admin-pin.json).

  • config PIN 설정 시: 부트스트랩 완전 비활성 — setup-token 미생성, POST /admin/setup 은 410, 파일 미조회. 기존 동작과 byte-identical.
  • config PIN 미설정 시: 부팅 시 일회용 setup-token 을 {DataPath}/admin-setup-token.txt 에 생성하고 경로를 로그에 남긴다. 서버 머신 파일시스템 접근 = 신뢰 루트(네트워크상 선점 탈취 방지). 관리 콘솔이 PIN 미설정을 감지하면 최초 설정 화면을 띄운다 — 토큰과 새 PIN 을 제출하면 PBKDF2 해시를 admin-pin.json 에 원자적 기록하고 토큰을 삭제한다. 이후 재시작 없이 즉시 관리 기능 사용 가능.
  • PIN 분실 복구: 서버에서 {DataPath}/admin-pin.json 삭제 → 재시작 → 재부트스트랩(새 setup-token 생성).

API 표면 ({ApiBasePath} 하위, 기본 /api/u-vision)

전체 계약(요청 · 응답 · 오류)의 정본은 OpenAPI 문서다 — 리포의 server/openapi/u-vision.json, 호스트가 AddOpenApi() 를 부르면 같은 문서가 U-Vision 태그로 나온다. 아래는 지도다.

메서드 경로 인증
GET /health -
GET /admin/status (PIN 설정 상태) -
POST /admin/setup (최초 PIN 설정) setup-token
POST /inspect (multipart) · /v2/inspect (결과 v2 — 오투입 확인은 expected_part · observed_code). 헤더 Idempotency-Key 를 주면 같은 키의 재전송은 첫 응답을 그대로 받는다 -
GET /results, /results/dates, /results/image -
PUT/DELETE/GET /results/label, /results/labels (사람 라벨) · /results/audit-sample, /results/audit (블라인드 감사) -
GET /scenarios, /scenarios/{id} · /scenarios/{id}/references... · /scenarios/{id}/authority · /scenarios/{id}/models -
POST/PUT/DELETE /scenarios... · references · authority promote/demote · models 등록 · promote · rollback PIN
GET /datasets, /datasets/{exportId}/manifest -
POST /datasets/export (라벨→ML 학습입력 스냅샷) PIN
GET /metrics (관측 메트릭 집계) · /events/status (웹훅 outbox 상태) -

JSON wire 는 snake_case(image_id, scenario_id, ng_label), verdict 는 "OK"/"NG". 이 계약은 DTO [JsonPropertyName]이 보유하므로 호스트의 전역 JSON 정책과 무관(호스트 JSON casing 을 오염시키지 않는다).

미들웨어 배치

UseUVision()은 {BasePath}/**(GET/HEAD)와 {ApiBasePath}/**만 처리하고 나머지는 통과시킨다(/u-vision-admin 같은 형제 경로도 삼키지 않음). 호스트의 catch-all/SPA fallback 보다 앞에 두면 안전하다. CORS 는 호스트 책임 — PWA 를 같은 호스트에서 서빙하면 불필요하다.

⚠️ 제약: BasePath 는 클라이언트 빌드와 결합

BasePath 기본값 /u-vision 은 임베드된 PWA 빌드의 base 와 일치한다. 다른 경로로 마운트하려면 클라이언트를 그 경로의 VITE_BASE 로 재빌드해야 한다 — service worker scope·manifest·번들 에셋이 빌드타임 base 를 baked 하기 때문이다(미들웨어는 index.html 만 best-effort 치환). 기본 /u-vision 사용을 권장한다.

스토리지

순수 파일시스템(DB 없음). {ContentRoot}/{UVision:Storage:DataPath}/{scenario}/... 아래에 시나리오 정의·기준 이미지·캡처·판정 결과가 누적된다. 단일 조직 셀프호스트의 진실의 원천.


라이선스

0.4.0 부터 AGPL-3.0-or-later(0.3.0 이하 게시본은 MIT 그대로). 이 패키지를 앱 안에 넣으면 그 앱 전체가 AGPL 조건을 따라야 한다 — AGPL 로 공개할 수 없는 앱은 엔진을 별도 서버로 띄워 HTTP 로 연동하거나 상용 라이선스를 받는다.

소스·이슈: https://github.com/iyulab/U-Vision · © 2026 iyulab.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.4.0 6 10/23/2026
0.3.0 43 10/22/2026
0.1.1 158 6/9/2026
0.1.0 127 6/8/2026