You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Express/SSE bootstrap + localhost/LAN opt-in 보안 가드 + src/routes/* registrar + mounted sub-router 등록.
현재 라이브 surface는 총 253개 route handler이며, 이 중 /를 제외한 API 엔드포인트는 252개다.
mutation route(POST/PUT/DELETE)는 모두 requireAuth를 거친다. 단, requireAuth()는 loopback 요청을 토큰 없이 통과시키고, lanAllowed()가 true일 때 private IP도 LAN bypass로 통과시킨다.
GET /api/auth/token은 Bearer bootstrap 전용이며 Sec-Fetch-Site가 same-origin 또는 none이 아닐 때 403을 반환한다.
public/dist/index.html이 있으면 Vite build를 서빙, 없으면 static fallback
GET
/api/health
{ ok, version, uptime }
GET
/api/slack/manifest
설정 페이지 "매니페스트 복사"용 canonical Slack 앱 매니페스트. 선택 ?name=은 1~35자 앱 표시명을 받고 봇 표시명은 자동 파생한다. { ok, data: { yaml, json, botDisplayName } } (비밀값 없음, unauthenticated)
POST
/api/channels/validate
온보딩 마법사 라이브 크리덴셜 검증 { channel, botToken, appToken?, guildId? } → { ok, identity?, teamId? } 또는 { ok:false, error }. 저장하지 않고 검증만 수행
GET
/api/session
현재 main session row 반환
GET
/api/messages
`includeTrace=1
GET
/api/messages/search
메시지 본문 검색 결과 반환. ?q=, ?days=N(1-365), ?recent=N(1-5000), ?context=N(0-5), ?limit=N(1-50)
GET
/api/messages/latest
가장 최근 메시지 스냅샷 반환
GET
/api/runtime
uptime, activeAgent, queuePending
GET
/api/auth/token
same-origin/CLI용 Bearer token bootstrap
POST
/api/command
slash command 실행
GET
/api/commands
인터페이스별 command palette 데이터
POST
/api/message
일반 프롬프트 제출. Optional target: RemoteTarget when Dashboard hub forwards a forum topic message (origin:'telegram'). Shape validated by isValidHubTarget + validateTarget. Optional external: true — manager/preview relay 등 외부 주입 표시; new_message broadcast에 실려 web UI가 유저 말풍선을 라이브 렌더 (devlog 260705).
POST
/api/elicitation/callback
Telegram Hub inline-keyboard elic:* callback relay. Hub bot forwards the tap to the mapped worker; worker completes handleElicitationCallback() and re-submits the combined answer via submitMessage() when all answers are collected.
POST
/api/stop
현재 실행 중 agent 모두 종료
POST
/api/clear
UI-only clear broadcast, DB 메시지는 유지
POST
/api/session/reset
메시지 삭제 + session reset
GET
/media/:filename
미디어 파일 서빙
GET
/api/image?path=<absolute path>
requireAuth + assertSendFilePath() realpath guard로 JAW_HOME/workingDir/projectDirs 아래 이미지·비디오를 서빙. PNG/JPEG/GIF/WebP/MP4/WebM/MOV/OGG만 허용하고 SVG는 제외한다. 잘못된 입력·확장자는 400, 허용 루트 밖은 403, 미해결 경로·디렉터리는 404; 성공 응답은 no-store + nosniff.
GET
/api/instance/lock
인스턴스 잠금 상태 조회
POST
/api/instance/lock
인스턴스 잠금 (stopAll 보호)
DELETE
/api/instance/lock
인스턴스 잠금 해제
GET
/api/chat-sessions
채팅 세션 목록
POST
/api/chat-sessions
새 채팅 세션 생성
POST
/api/chat-sessions/:id/switch
활성 세션 전환
DELETE
/api/chat-sessions/:id
세션 삭제 — 'default' 400, 진행 중/원격 바인딩 409, 성공 시 메시지 동시 삭제 (071)
GET
/api/search
통합 검색 — corpus=chat|memory|wiki|all, 세션 횡단 기본 + sessionFilter, cursor 페이지네이션 (031)
GET
/api/wiki/status
위키 상태 — enabled/root/promptDigest/provider. 기본 OFF, 디스크를 만들지 않는다 (040)
POST
/api/wiki/enable
위키 활성화 — scaffold 후 provider ready 확인이 끝나야 설정을 기록한다 (040)
GET
/api/wiki/entities
위키 entity 인덱스 (읽기 전용) — disabled면 디스크를 만지지 않고, root가 옮겨졌으면 부분 결과 대신 error다 (041)
GET /api/wiki/statusGET /api/wiki/entitiesPOST /api/wiki/enablePOST /api/wiki/configure
Avatar
GET /api/avatarPOST /api/avatar/:target/uploadDELETE /api/avatar/:target/imageGET /api/avatar/:target/image
Traces
GET /api/traces/:runIdGET /api/traces/:runId/eventsGET /api/traces/:runId/events/:seq
Debug
GET /api/debug/mem
Link Preview
GET /api/link-preview?url=GET /api/link-preview/image?url=
Dashboard Board
GET /api/dashboard/board/tasksPOST /api/dashboard/board/tasksPATCH /api/dashboard/board/tasks/:idDELETE /api/dashboard/board/tasks/:idPOST /api/dashboard/board/tasks/from-message
Dashboard Schedule
GET /api/dashboard/schedule/workPOST /api/dashboard/schedule/workPATCH /api/dashboard/schedule/work/:idDELETE /api/dashboard/schedule/work/:idPOST /api/dashboard/schedule/work/:id/dispatch
i18n
GET /api/i18n/languagesGET /api/i18n/:lang
실제 코드(server.ts + src/routes/*.ts + mounted runtime/security/Jaw CEO/dashboard sub-router)에서 추출한 총 253개 route handler 기준이다. 이 중 API 엔드포인트는 252개이고, 나머지 1개는 / 엔트리이다. Browser API 43개는 src/routes/browser.ts에서 등록된다. Jaw CEO 20개는 src/routes/jaw-ceo.ts에서 sub-router로 등록된다.
POST /api/channel/send에서 channel은 telegram|discord|slack|active transport다. 대화 ID는 chat_id 또는 target.targetId에 넣는다. Slack thread를 명시할 때 target.threadId는 reply ts가 아닌 parent message ts다. target을 생략하면 검증된 현재 대화와 thread를 사용한다. 빈 slack.channelIds는 임의 explicit channel을 열지 않으며, 이미 저장·검증된 lastActive/latestSeen과 같은 conversation/thread만 명시적으로 재사용할 수 있다.
Security / Guards
네트워크 가드
기본 서버 bind는 127.0.0.1이지만 settings.network.bindHost, JAW_LAN_MODE=1, reverse-proxy mode에 따라 0.0.0.0 bind가 가능하다.
ALLOWED_HOSTS/ALLOWED_ORIGINS는 loopback을 기본 허용하고, LAN mode/bypass가 켜졌을 때 private network origin/host를 허용한다.
Legacy/client fallback WebSocket paths and manager-side note WebSocket surfaces must apply the same host/origin guard model; the current core public event path is SSE.
인증
mutation route는 모두 requireAuth로 보호된다.
다만 로컬 동일 머신 사용성을 위해 loopback 요청은 Bearer 없이 허용된다. LAN bypass가 켜진 private IP 요청도 토큰 없이 통과할 수 있으므로 trusted network 전용이다.
/api/auth/token은 cross-origin token theft 방지를 위해 Sec-Fetch-Site를 검사한다.
/api/image는 path가 단일 절대경로인지 먼저 검사한 뒤 guard를 실행한다. 존재하지 않아 canonicalize할 수 없는 경로는 404, JAW_HOME/workingDir/projectDirs 밖 또는 symlink 탈출은 403이며, guard 통과 뒤에도 allowlist와 regular-file 검사를 거친다.
기타
Rate limit: in-memory, IP 기준 120 req/min.
helmet() 사용, CSP/COEP는 현재 비활성.
Selected Route Notes
/api/command
body text를 WEB_COMMAND_TEXT_LIMIT(30,000자)까지 자른 뒤 parseCommand()로 해석한다.
locale은 body/query/Accept-Language/settings 순으로 정해지고 Content-Language가 세팅된다.
command가 아니면 400 { code: 'not_command' }.
/api/elicitation/callback
Dashboard Telegram Hub의 bot.callbackQuery(/^elic:/)가 mapped instance로 POST /api/elicitation/callback을 호출한다.
body { chatId, callbackData, target? }를 받아 handleElicitationCallback(chatId, callbackData)로 pending single-select 답변을 갱신한다.
GET /api/goal returns { ok, goal, pauseGate }; pauseGate is derived from active + agentPauseCount >= 1 and stays present with armed:false when no goal is active.
POST /api/goal body { action } 분기: set, refine-objective, update, done, cancel, pause, resume, clear, reset.
set may receive goalMode: "plan" and planHint; plan-mode stores a pending objective and rejects normal checkpoint updates until refine-objective replaces it with a concrete objective.
agent pause 첫 번째 audited 시도는 409와 pauseGate:{ armed:true, reason:"pause_gate_pending" }를 반환한다. 두 번째 audited 시도는 goal을 paused로 전환하고, productive update는 pending gate를 해제한다.
resume action은 이미 active이면 { alreadyActive:true }를 반환하고, paused goal을 resume하면 kickGoalContinuation()을 즉시 트리거한다.
/api/orchestrate/dispatch/pending
POST는 일반 requireAuth 클라이언트가 action-scoped dispatch를 제출하는 전용 경로다. 응답은 202 { jti, digest, expiresAt }이며 bearer나 boss token을 반환하지 않는다.
서버는 설정된 dispatchApproval.operators의 Slack/Telegram/Discord 운영자 DM에 target, project root, task digest, mutable scope, fan-out cap, server-instance audience, JTI, digest, expiry를 보낸다. allowlist가 비거나 설정된 운영자 전달 중 하나라도 실패하면 pending을 취소하고 fail-closed 한다.
승인은 HTTP로 받지 않는다. 검증된 Socket Mode/polling/gateway 이벤트에서 운영자가 approve <jti> <digest>를 보내야 한다. pending은 기본 120초, 최대 300초, 부팅 세대별, 원자적 single-use다. settings API는 300초 초과를 거부하고 store 경계도 300초로 clamp한다.
GET /api/orchestrate/dispatch/pending/:jti는 CLI polling용 상태/결과 조회이며 승인 기능은 없다.
/api/orchestrate/dispatch
boss-scoped x-jaw-boss-token이 필수다. employee spawn 환경에서는 이 토큰이 제거되므로 직원이 다시 dispatch하는 흐름은 서버에서 403으로 막힌다.
body는 정확히 하나의 target을 받는다: { agent, task } 또는 { virtual, task, role?, cli?, model? }.
virtual target은 src/core/employees.ts의 security/testing 프리셋 또는 자유 role 문자열로 SyntheticEmployeeRow를 만들고, DB employee row로 저장하지 않는다.
virtual dispatch에서 cli/model이 생략되면 현재 CLI와 src/cli/registry.ts의 registry default model을 사용한다.
현재 plan이 있으면 dispatch body 상단에 ## Approved Plan으로 자동 주입된다.
wait:false async dispatch 202, worker_busy409, and result polling payloads include both stable agentId and per-dispatch runId. The agentId remains the same-employee concurrency guard; runId identifies a specific worker run in memory progress history.
GET /api/orchestrate/worker-runs* exposes durable worker-run safe metadata/events and bounded raw output reads. List/get/events are safe-only and include both native status plus shared statusCategory (running|succeeded|failed|cancelled|orphaned) for comparison with background tasks; /output is the only raw-text worker-run route and requires explicit runId plus offset/limit. jaw worker read <runId> is the CLI consumer of that explicit raw-output route; worker status/watch remain safe-summary surfaces.
GET/POST /api/bgtask and GET/DELETE /api/bgtask/:id keep the existing background-task schema and add statusCategory to public task payloads. statusCategory is additive; bgtask storage and worker-run storage remain separate and no bgtask migration is performed.
POST /api/orchestrate/dispatch/batch는 같은 boss token으로 여러 직원/virtual task를 병렬 dispatch한다. 각 entry는 agent 또는 virtual 중 하나를 가진다. 응답은 full worker text를 기본 포함하지 않고 { agent, ok, runId, status, preview, recoveryCommand, outputBytes, error? } 형태의 safe summary metadata를 반환한다. raw output은 runId로 /api/orchestrate/worker-runs/:runId/output 또는 jaw worker read <runId>에서 명시적으로 읽는다. 구버전 manager가 이 route 없이 HTML 404를 반환하면 jaw dispatch --batch는 JSON parse 예외 대신 stale/missing route 진단을 출력한다.
/api/jaw-ceo/*
requireAuth 보호 sub-router로 /api/jaw-ceo 아래 마운트.
Core: state read, message send, query (dashboard/cli_readonly/web/github_read source), docs edit.
Settings: OpenAI API key management for voice.
Events: ingest manager events, refresh with port/cursor filter.
pi는 Settings의 Pi profile registration을 통해 endpoint/model/key를 검증하고, quota 자체는 auth/status-only로 표시한다.
agy는 src/routes/quota-agy-reverse.ts의 fetchAgyUsage()를 통해 Antigravity quota snapshot을 읽는다.
antigravity-usage --json이 remainingPercentage를 정밀 소수점 대신 0/1로만 반환하면 AGY window는 precision: "binary"와 status: "available" | "exhausted"를 포함한다. backend의 percent는 호환 필드일 뿐이며, UI는 exact percent bar 대신 Available / Exhausted 상태 텍스트를 표시해야 한다. upstream이 다시 정밀 퍼센트를 주면 기존 fractional path가 그대로 사용된다.
cursor는 src/routes/quota-cursor-dashboard.ts의 fetchCursorUsage()를 통해 dashboard session/usage를 읽는다.
grok은 ~/.grok/auth.json의 OIDC key를 우선 읽고 https://grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig gRPC-web 응답으로 SuperGrok weekly usage pool window를 만든다. 실패하면 legacy cli-chat-proxy.grok.com/v1/billing monthly credits window로 fallback한다.
kiro-code는 src/routes/quota-kiro-reverse.ts의 fetchKiroUsage()를 통해 CodeWhisperer GetUsageLimits API를 reverse-engineer 호출한다.
Wiki lifecycle ownership
wiki.enabled and wiki.root are owned by POST /api/wiki/enable and POST /api/wiki/configure. The enable route scaffolds the vault, verifies provider readiness, and only then persists the lifecycle configuration.
Generic PUT /api/settings rejects either lifecycle field with 409 wiki_configuration_requires_wiki_route; wiki.promptDigest remains writable there. External settings.json reloads ignore the two lifecycle fields and emit a warning instead of bypassing the wiki routes.
At server startup, a persisted enabled vault whose provider is not ready emits [jaw:wiki] enabled but unavailable at startup (...) without logging the vault path. Repair it through POST /api/wiki/enable, or disable it through POST /api/wiki/configure.
/api/project/git-summary
GET /api/project/git-summary는 Settings의 projectDirs[0]만 읽는 read-only header helper다.
POST /api/settings/runtime-default-migration은 requireAuth 뒤에서 정확히 { "action": "accept" | "keep" }만 받는다. settingsSchemaVersion과 runtimeDefaultMigration은 server-owned라 generic PUT /api/settings에 포함하면 400이다. 이미 terminal인 migration은 409 runtime_default_migration_terminal과 최신 settings snapshot을 반환한다. 성공 200과 conflict 409의 snapshot은 모두 GET/PUT /api/settings와 같은 redaction을 거친다.
POST /api/settings/multi-session-default-migration은 같은 계약을 따르며 다중 세션 기본 ON 전환(schema v3)을 소유한다. multiSessionDefaultMigration도 server-owned이므로 generic PUT에 포함하면 400이고, terminal이면 409 multi_session_default_migration_terminal이다. 런타임 migration과 별도 route인 이유는 두 전환이 서로 다른 시점에 서로 다른 이유로 롤백될 수 있고, v1 문서는 둘이 동시에 pending이기 때문이다 — 한 쪽 응답이 다른 쪽 답으로 읽히면 안 된다. accept는 enabled:true와, 현재 maxConcurrent가 1일 때 2를 함께 적용한다(동의 문구가 그 둘을 말한다). 1이 아닌 유효 값은 그대로 둔다.
Slack 연결 환경변수(SLACK_BOT_TOKEN, SLACK_APP_TOKEN, SLACK_TEAM_ID, SLACK_CHANNEL_IDS)는 각자 대응하는 설정 필드를 런타임에서 소유한다. SLACK_BOT_TOKEN은 enabled|botToken, SLACK_APP_TOKEN은 appToken, SLACK_TEAM_ID는 teamId, SLACK_CHANNEL_IDS는 channelIds를 소유한다. GET /api/settings는 slackEnvironmentVariables에 변수 이름만 싣고 연결값을 redaction한다. generic PUT은 요청에 포함된 env-owned path만 409 slack_connection_managed_by_environment로 거부하며, 전체 연결을 비우는 POST /api/settings/slack/reset은 환경변수가 하나라도 있으면 계속 409다. Settings UI와 CLI setup도 혼합 변경을 보수적으로 막는다. 직렬화는 env-owned 필드만 제거하므로 환경값이 settings.json으로 복사되지 않고 metadata-only override가 파일 토큰을 지우지 않는다. 동작 설정(forwardAll, allowBots, mentionOnly, replyInThread)은 계속 저장할 수 있다.
runtime.codexApp.multiplex는 사용자 소유 boolean gate이며 실행 기본값은 false다. raw settings에 키가 없으면 GET /api/settings의 실행 snapshot은 false를 제공하지만 다음 저장에서도 키와 그 결과 비는 codexApp/runtime container를 만들지 않는다. explicit false/true는 보존한다. generic PUT /api/settings에서 문자열·숫자·null은 400 invalid_settings_field, host probe 소유인 runtime.codexApp.laneMode는 값과 무관하게 기존 호환 오류 400 server_owned_settings_field로 거부한다.
GET /api/cli-status는 cold에서 nullable probeState:"checking", stale에서 즉시 이전 snapshot을 반환한다. binary/PATH, auth, capability detection은 request event loop가 아니라 finite-lifetime child worker에서 수행된다.
probe가 실패하면 probeState:"failing" + probeError/probeFailures/nextRetryAt을 실어 보낸다. failing은 "포기"가 아니라 "계속 실패 중, 사유는 이것"이며 캐시는 재시도를 이어간다 (첫 재시도 즉시, 이후 지수 백오프 최대 5분). 실패 기록은 남아 있는 snapshot보다 우선한다 — 그래야 동작하는 것처럼 보이는 stale 응답으로 실패를 감추지 않는다 (#277).
GET /api/cli-status?force=1은 백오프 창을 건너뛴다. 재시도는 타이머가 아니라 요청 시점에 일어나므로, 원인을 고친 사용자가 새로고침을 눌러도 백오프가 끝날 때까지 낡은 실패를 계속 보게 되는 것을 막는다.
응답은 legacy Web UI header의 compact git status 전용이다: branch/hash, tracked modified count, untracked count.
project root가 없거나, home 밖 경로거나, git repository가 아니거나, git 호출이 실패하면 mutation 없이 { available:false, reason } 형태로 조용히 숨길 수 있는 payload를 반환한다.
status count는 git status --porcelain=v1 -z --untracked-files=all 기반이며 ignored entry는 표시하지 않는다.
/api/pi/*
POST /api/pi/profiles/register — body의 provider/endpoint/model/key/mode를 normalizePiProfile()로 정규화하고, isolated PI_CODING_AGENT_DIR 아래 models.json + settings.json을 만든 뒤 pi --offline --list-models <profile>로 등록 모델이 실제 Pi model list에 나타나는지 검증한다. 성공 시 applySettings()를 통해 settings.pi와 perCli.pi.provider/model을 함께 저장한다.
GET /api/pi/models?profile=<id> — 저장된 Pi profile 설정으로 모델 목록을 재발견하고, settings.pi.discoveredModels[profile] 및 Settings UI dropdown 갱신에 사용할 배열을 반환한다.
Pi 응답은 API key를 직접 반환하지 않고 apiKeySet, apiKeyLast4, apiKeySource만 노출한다.
/api/runtime-context
GET — 모든 entry를 반환하며 각 entry에 expired boolean을 추가한다.
POST — body { text, label?, expiresAt? }. text는 필수(max 2000자). 201 + 생성된 entry 반환.
DELETE /:id — 단일 entry 삭제. 없으면 404.
DELETE / — 전체 삭제. { cleared: <count> } 반환.
/api/security-audit/*
GET /entries — audit log entries (limit param, max 500).
GET /verify — integrity verification of audit chain.
WebSocket Events
이 heading은 structure/check-doc-drift.sh의 anchor로 유지한다. X-01 이후 current server는 public browser events를 WebSocket으로 broadcast하지 않는다. 아래 catalog는 broadcast()가 발행하는 event type 전체다. 기본 audience인 public 항목은 src/core/bus.ts → src/core/event-bus.ts → GET /api/events로 전달되는 SSE surface이고, broadcast(..., 'internal')로 발행되는 항목은 audience gate에서 SSE로 나가지 않고 in-process listener만 받으므로 해당 행에 internal audience로 명시한다. WebSocket은 public/js/ws.ts와 bin/commands/tui/channel.ts가 /api/events를 한 번도 열 수 없는 pre-X-01 server에 붙을 때만 fallback path로 사용한다. Current Web UI는 reconnect 시 REST snapshot hydration으로 agent_status, queue_update, 비-IDLE orc_state 상태를 보강한다.
PABCD 상태 변경 + taskAnchor/resolvedSelection/interview 컨텍스트
orchestrate_done / orchestrate_warning
orchestration 완료/실패 + 비차단 경고
request_settled
요청 하나의 최종 결말 (completed|steered|merged|failed|cancelled|dropped|skipped). src/orchestrator/request-registry.ts의 settleOnce()가 멱등이라 요청당 정확히 한 번 발생한다. orchestrate_done을 대체하지 않고 보완한다 — steer 성공처럼 완료 이벤트가 없는 경로를 덮기 위한 것. 전체 payload 스키마는 structure/stream-events.md 참고 (#276)
steer_started
/steer 또는 pending queue steer가 새 프롬프트를 accepted 상태로 전환
goal pause 2-tap gate 감지 및 pending gate continuation suppression
session_switched / session_created / session_list
multi-session state update
schedule_wakeup / schedule_wakeup_failed
ScheduleWakeup continuation scheduling lifecycle
bgtask_update
background task lifecycle/status update for manager/runtime monitors; running and changed entries include native status plus shared statusCategory
widget_updated
file-backed diagram widget changed on disk; payload {chatId, widgetId} for targeted iframe refetch
policy_verdict
internal audience 전용 — runtime policy hook 판정 broadcast (src/core/policy-hooks.tsemitVerdict). broadcast(..., 'internal')이므로 src/core/bus.ts의 audience gate에서 SSE로 발행되지 않고 in-process listener만 받는다. payload는 verdict + optional channel
Manager Dashboard Server Surface
jaw dashboard serve가 띄우는 별도 manager 서버(src/manager/server.ts, 992L)는 core server.ts route count에 포함하지 않는다. Manager instance state는 src/manager/instance-registry.ts(120L)가 cached scan + diff event source로 제공한다. Manager React UI는 /api/manager/events, /api/dashboard/instances, /i/:port/api/messages/latest 계열 HTTP polling으로 상태를 읽고, manager server는 src/manager/worker-events.ts + src/manager/worker-sse-client.ts를 통해 각 worker instance의 GET /api/events를 server-side로 구독해 latest-message cache를 갱신한다. #233부터 worker의 settings:settings_change(cli/model/projectDirs 변경)는 worker_settings_change로 재발행되어 GET /api/manager/events/stream(SSE)으로 manager UI에 live 전달되고, UI(useManagerEventStream)는 해당 instance row를 즉시 재조회한다. Code mode의 goal/PABCD/background/worker monitors는 child Jaw instance가 아니라 manager-local src/manager/routes/runtime-monitor.ts를 통해 /api/manager/runtime-status, /api/bgtask, /api/orchestrate/worker-progress JSON API를 직접 읽는다. #260 이후 per-instance Jaw sidebar에는 worker progress monitor가 렌더링되지 않고, Code/CEO runtime observability lane에서만 표시된다. /api/bgtask의 preset: "web-ai" path는 native web-ai watcher가 진행하는 session id를 session-status probe로 관찰하고 session-answer extractor로 완료 결과를 전달한다. 이 bridge는 BrowserPanel tab state나 Code session transcript ownership으로 승격하지 않는다. background_tasks.notified_at 변경도 bgtask_update를 발행하므로 Manager monitor는 completion transition 뒤 별도 reload 없이 notification handoff 상태를 재조회할 수 있다.
Surface
Endpoints
Manager health/scan
GET /api/dashboard/healthGET /api/dashboard/instancesGET /api/dashboard/instances/:portPOST /api/dashboard/instances/:port/messagePOST /api/dashboard/instances/:port/project/pick
Manager events/logs
GET /api/manager/eventsGET /api/manager/events/stream (SSE) GET /api/manager/health-history/:portGET /api/manager/instance-logs/:port
Runtime monitors
GET /api/manager/runtime-statusGET/POST /api/bgtaskGET/DELETE /api/bgtask/:idGET /api/orchestrate/worker-progressGET /api/orchestrate/worker-progress/:agentId
Registry
GET /api/dashboard/registryPATCH /api/dashboard/registry
Lifecycle
POST /api/dashboard/lifecycle/:action (start/stop/restart/perm/unperm)
Process control
GET /api/dashboard/process-controlPOST /api/dashboard/process-control/adoptPOST /api/dashboard/process-control/stop-managedPOST /api/dashboard/process-control/force-release
Desktop/Electron
GET /api/dashboard/desktop-statusGET/POST /api/dashboard/electron-metrics
POST /api/dashboard/connector/boardPATCH /api/dashboard/connector/board/:idPOST /api/dashboard/connector/remindersPATCH /api/dashboard/connector/reminders/:idPOST /api/dashboard/connector/notesGET /api/dashboard/connector/audit
Git diff/status/worktrees
POST /api/dashboard/git/repo-candidatesPOST /api/dashboard/git/diff-summaryPOST /api/dashboard/git/file-diffPOST /api/dashboard/git/status-mapPOST /api/dashboard/git/scm-snapshotPOST /api/dashboard/git/scm-operationPOST /api/dashboard/git/worktreesPOST /api/dashboard/git/worktree-operation-previewPOST /api/dashboard/git/worktree-operation
Memory federation
GET /api/dashboard/memory/instancesGET /api/dashboard/memory/searchGET /api/dashboard/memory/readGET /api/dashboard/memory/chat/search (?format=envelope로 세션 provenance 포함 envelope opt-in — 033)
Memory embedding
GET /api/dashboard/memory/embed-configPOST /api/dashboard/memory/embed-configPOST /api/dashboard/memory/reindexGET /api/dashboard/memory/embed-stateGET /api/dashboard/memory/embed-estimateGET /api/dashboard/memory/reindex-stream (SSE)
Wiki (읽기 전용 프록시)
GET /api/dashboard/wiki/statusGET /api/dashboard/wiki/entities (?port= 필수). Notes와 같은 preflight+auth pair를 지나고, 포트 범위는 isDashboardProxyPortAllowed를 호출해 판정하며, 미등록·오프라인·upstream 실패는 전부 503 wiki_core_unavailable 하나로 답한다 (041-C). /i 프록시로 대체하지 말 것 — 그 경로는 loopback으로 접속해 인스턴스의 requireAuth가 토큰 검사 전에 통과시키므로 인증 경계가 사라진다