sxe-analysis

Sentivex Evolution Engine API

GET/sxe/analysis

analysis_id → {incident_uid, affected_hosts} (index-pm external_ref pull 백필, #189)

index-pm 백필 진입점 (sit #189, 2026-06-29). 목적(왜 존재): external_ref=sxe:<analysis_id> 만 가진 index-pm issue 가 incident_uid 와 affected_hosts 를 한 번에 pull 하도록 analysis_id → {incident_uid, affected_hosts} 를 반환. index-pm 인입 시 incident_uid 누락(결손) 보정 + 호스트 동시 채움(멱등 백필). 배경(실측 2026-06-29): SEE sxe.analyses 는 incident_uid NULL 이 0건 — 즉 index-pm 의 '222건 incident_uid 없음'은 SEE 결손이 아니라 index-pm 인입 누락이다. analysis_id PK 로 역조회하면 incident_uid 가 항상 나온다(이 라우트가 그 역조회를 노출). 공통화: 호스트 복원은 기존 /sxe/analysis/{uid} 핸들러(sxe_load_analysis)를 그대로 호출 → 로직 드리프트 0. 라우트 주의: /sxe/analysis/{incident_uid:path} 보다 먼저 선언해야 한다(쿼리형 vs 경로형 구분). @param analysis_id: sxe.analyses PK (external_ref 의 sxe:<NNN> 의 NNN) @returns: {found, analysis_id, incident_uid, source, affected_hosts:[str], affected_hosts_detail:[{...}]}. 미존재=found:false. 호스트 미복원이면 affected_hosts=[] (정직 빈 — 가짜 0 금지).

Query parameters

analysis_idintegerrequired

Responses

200 Successful Response422 Validation Error
object
cURL
curl -X GET https://see.in-bridge.com/sxe/analysis?analysis_id=0
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/analysis", {
  method: "GET"
});
const data = await res.json();
Response 200
{}
POST/sxe/analysis

Sxe Save Analysis

UI Phase 9 done 직후 또는 wrapper 가 분석 결과 저장. 같은 UID 여러 분석 가능 (이력 추적). 자동 집계 컬럼은 raw_phases 에서 추출. G0: body.analysis_id 가 있으면 그 row 를 UPDATE(early-save 갱신) — INSERT 안 함(중복 방지).

Request body

incident_uidstringrequired
sourcestringrequired
incident_namestring | null
started_atstringrequired
completed_atstring | null
invoked_bystring
measurement_enabledboolean
raw_phasesobject
errorsobject[]
total_cost_usdnumber | null
config_hashstring | null
phase_reachedinteger | null
statusstring | null
analysis_idinteger | null

Responses

200 Successful Response422 Validation Error
object
cURL
curl -X POST https://see.in-bridge.com/sxe/analysis \
  -H "Content-Type: application/json" \
  -d '{"incident_uid":"string","source":"string","incident_name":"string","started_at":"string","completed_at":"string","invoked_by":"string","measurement_enabled":true,"raw_phases":null,"errors":[null],"total_cost_usd":0,"config_hash":"string","phase_reached":0}'
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/analysis", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "incident_uid": "string",
    "source": "string",
    "incident_name": "string",
    "started_at": "string",
    "completed_at": "string",
    "invoked_by": "string",
    "measurement_enabled": true,
    "raw_phases": null,
    "errors": [
      null
    ],
    "total_cost_usd": 0,
    "config_hash": "string",
    "phase_reached": 0
  })
});
const data = await res.json();
Response 200
{}
GET/sxe/analysis/{incident_uid}

Sxe Load Analysis

캐시 load — 같은 UID 의 최근 분석 1건 + 전체 이력 목록. latest=true (default) → 정규화 reconstitute 한 raw_phases 포함. analysis_id 지정 시 그 분석의 raw_phases.

Path parameters

incident_uidstringrequired

Query parameters

latestboolean
with_rawboolean
analysis_idinteger | null

Responses

200 Successful Response422 Validation Error
object
cURL
curl -X GET https://see.in-bridge.com/sxe/analysis/{incident_uid}?latest=true&with_raw=true&analysis_id=0
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/analysis/{incident_uid}", {
  method: "GET"
});
const data = await res.json();
Response 200
{}
GET/sxe/analyses

분석 이력 목록 (페이징·필터) — 보고서 1차 데이터 소스

분석 이력 list (페이징 + 필터).

Query parameters

sourcestring | null
invoked_bystring | null
measurementboolean | null
limitinteger
offsetinteger

Responses

200 Successful Response422 Validation Error
totalintegerrequired
returnedintegerrequired
limitintegerrequired
offsetintegerrequired
itemsAnalysisListItem[]required
analysis_idintegerrequired
incident_uidstringrequired
sourcestring | null
started_atstring | null
invoked_bystring | null
measurement_enabledboolean | null
final_verdictstring | null

benign|malicious|suspicious|info|unknown|unsupported

final_severitystring | null

Low|Medium|High|Critical

total_elapsed_snumber | null
config_hashstring | null

평가 버전 분리 composite hash

phase_reachedinteger | null
statusstring | null

주의: stale 가능 — 완료는 analysis_state/completed_at 로 판정(#103)

completed_atstring | null

완주 시각. NULL=미완주(G0 early-save 됐으나 리포터 phase7 hang/cap-kill) → §5 측정·skip 은 완주분만(#97)

total_cost_usdnumber | null
vendor_labelstring | null
tenant_refstring | null

라우팅키 stable slug. resolve 불가시 null (#157)

tenant_namestring | null
cURL
curl -X GET https://see.in-bridge.com/sxe/analyses?source=string&invoked_by=string&measurement=true
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/analyses", {
  method: "GET"
});
const data = await res.json();
Response 200
{
  "total": 0,
  "returned": 0,
  "limit": 0,
  "offset": 0,
  "items": [
    {
      "analysis_id": 0,
      "incident_uid": "string",
      "source": "string",
      "started_at": "string",
      "invoked_by": "string",
      "measurement_enabled": true,
      "final_verdict": "string",
      "final_severity": "string"
    }
  ]
}
GET/sxe/analysis_state/{incident_uid}

Sxe Analysis State

단일 진실 분석 (M2) — 한 incident_uid 의 현재 상태 통합 조회. state ∈ {before, queued, running, done} done : PG sxe.analyses 에 row 존재 → 캐시된 분석 결과 사용. analysis_id + verdict + severity 반환. running : 최근 ~30s 안에 session_id=incident_uid 의 feed 이벤트 → live watch mode 진입. phases_seen / current_phase / last_event_ago_sec 포함. queued : _pending_analysis_queue 에 있고 아직 worker 가 처리 안함. before : 그 외 — 정적 incident 상세 (lab OS) 표시 + [분석 시작] 버튼. 먼저 running 체크 → queued → done → before 순서로 평가. 이유: 같은 UID 의 과거 분석 row 가 PG 에 있어도 (e.g. 3일 전 결과), 지금 새 분석이 진행 중이면 그쪽이 사용자가 보고 싶은 화면임. running 을 우선시함. 단일 진실 = 어느 페이지/브라우저에서 같은 UID 로 접속해도 같은 화면을 봐야 한다 (사용자 2026-05-28).

Path parameters

incident_uidstringrequired

Responses

200 Successful Response422 Validation Error
object
cURL
curl -X GET https://see.in-bridge.com/sxe/analysis_state/{incident_uid}
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/analysis_state/{incident_uid}", {
  method: "GET"
});
const data = await res.json();
Response 200
{}
POST/sxe/analysis_progress

Sxe Analysis Progress

Request body

incident_uidstringrequired
phase_reachedinteger | null
statusstring | null
stall_reasonstring | null
tsnumber | null

Responses

200 Successful Response422 Validation Error
object
cURL
curl -X POST https://see.in-bridge.com/sxe/analysis_progress \
  -H "Content-Type: application/json" \
  -d '{"incident_uid":"string","phase_reached":0,"status":"string","stall_reason":"string","ts":0}'
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/analysis_progress", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "incident_uid": "string",
    "phase_reached": 0,
    "status": "string",
    "stall_reason": "string",
    "ts": 0
  })
});
const data = await res.json();
Response 200
{}
GET/sxe/stalled

중단(stalled) 분석 목록 — completed_at 미설정 재분석 대상

Query parameters

limitinteger

Responses

200 Successful Response422 Validation Error
okbooleanrequired
countintegerrequired
reapedintegerrequired
itemsStalledItem[]required
incident_uidstringrequired
phase_reachedinteger | null
statusstring | null
started_atstring | null
stalled_atstring | null
stall_reasonstring | null
invoked_bystring | null
final_verdictstring | null
cURL
curl -X GET https://see.in-bridge.com/sxe/stalled?limit=0
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/stalled", {
  method: "GET"
});
const data = await res.json();
Response 200
{
  "ok": true,
  "count": 0,
  "reaped": 0,
  "items": [
    {
      "incident_uid": "string",
      "phase_reached": 0,
      "status": "string",
      "started_at": "string",
      "stalled_at": "string",
      "stall_reason": "string",
      "invoked_by": "string",
      "final_verdict": "string"
    }
  ]
}
POST/sxe/analyze

프런트 직접 분석 트리거 (비동기 잡 A) — 즉시반환, 진행=WS, 결과=GET /sxe/analysis/{uid}

#118 동기 분석 API (설계 A=비동기 잡). 러너 ~4분이라 블로킹하지 않고 worker 큐에 넣고 즉시 반환. 왜 enqueue 인가: enrich 는 컨테이너(node 없음) → 러너(node) 직접 spawn 불가. host worker(systemd, BACKEND_RUNNER)가 pop→spawn 하므로 큐가 유일·견고한 경로. 진행: WS `/sxe/feed/ws` (phase 브로드캐스트, 기존 인프라 재사용). 결과: `GET /sxe/analysis/{uid}` · 상태: `GET /sxe/analysis_state/{uid}`. 중복가드: 이미 처리(running/done)·큐대기면 재enqueue 안 함(현재 status 반환). options.force=true 면 우회. side-effects: _pending_analysis_queue append, feed 이벤트 발행.

Request body

incident_uidstringrequired
sourcestring | null
optionsobject | null

Responses

200 Successful Response422 Validation Error
object
cURL
curl -X POST https://see.in-bridge.com/sxe/analyze \
  -H "Content-Type: application/json" \
  -d '{"incident_uid":"string","source":"string","options":null}'
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/analyze", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "incident_uid": "string",
    "source": "string",
    "options": null
  })
});
const data = await res.json();
Response 200
{}
GET/sxe/lab/incidents_page

Sxe Lab Incidents Page

dashboard-v2 #incidents 의 모든 데이터 한 번에. - KPI (severity 4 + status 5) - MITRE Top 5/5 (Tactic + Technique) - 시간별 분포 (24h) - 심각도 동향 (7d) - 최근 인시던트 10건 - 인시던트 카드 grid (limit 건) sxe.analyses 의 분석 결과 join (verdict / elapsed / processed_at).

Query parameters

limitinteger
range_hoursinteger

Responses

200 Successful Response422 Validation Error
object
cURL
curl -X GET https://see.in-bridge.com/sxe/lab/incidents_page?limit=0&range_hours=0
JavaScript
const res = await fetch("https://see.in-bridge.com/sxe/lab/incidents_page", {
  method: "GET"
});
const data = await res.json();
Response 200
{}