<a id="frontend-screens"></a>
# 프런트엔드 27개 화면과 API 소비 지도

Next.js `page.tsx` 27개를 독립 분모로 잡고 각 page가 import하는 local component/hook을 재귀 추적해 `api.*` 호출과 `EventSource`를 backend operation에 연결했다. 공용 `(main)` layout은 화면별 subtree와 분리했다. 동적 import·runtime 분기는 실행하지 않았으므로 **호출 가능성**을 나타내며 화면을 열 때 모든 operation이 항상 실행된다는 뜻은 아니다. [API client](evidence:web-api-client) [auth shell](evidence:web-auth-shell)

## 공통 shell·auth·오류 계약

- `/login`, `/setup`을 뺀 main 화면은 `(main)/layout.tsx` client gate가 `localStorage` token을 검사한다. token이 없으면 cookie까지 지우고 `/login`으로 보낸다. non-static Next 실행에서는 `proxy.ts`가 cookie를 기준으로 같은 gate를 앞단에서 수행하며 mock mode는 우회한다.
- `lib/api.ts`는 token을 `Authorization: Bearer`로 넣고 401이면 localStorage/cookie를 제거한 뒤 `/login`으로 이동한다. EventSource는 header를 지정할 수 없어 `sseUrl`이 query `token`을 붙인다. backend에서는 auth/init/login/health만 middleware-exempt이고 change-password는 handler가 JWT를 다시 검증한다.
- 공용 main shell이 호출하는 wrapper: `changePassword`, `health`, `interceptPending`, `checkUpdate`. 화면별 표의 operation 수에는 이 shell 호출을 넣지 않았다. 모든 main 화면에는 이 소비가 추가될 수 있다.
- 오류는 API client의 `{error:string}` 파싱/HTTP status fallback 뒤 reject, 화면의 toast·inline error·재시도/다음 poll, SSE `onerror`의 reconnect 상태로 나뉜다. 각 화면의 집계는 component subtree에서 발견한 처리 지점 수이며 사용자에게 항상 표시된다는 보장은 아니다.

## 화면 색인

| URL | page subtree API | SSE | 상태/오류 요약 |
|---|---:|---:|---|
| [`/login`](#screen-login) | 2 op / 2 wrapper | 0 | state 7, store 0; toast 0/inline 5/catch 1 |
| [`/setup`](#screen-setup) | 2 op / 2 wrapper | 0 | state 5, store 0; toast 0/inline 5/catch 2 |
| [`/`](#screen-root) | 0 op / 0 wrapper | 0 | state 0, store 0; toast 0/inline 0/catch 0 |
| [`/chat`](#screen-chat) | 23 op / 24 wrapper | 1 | state 65, store 1; toast 17/inline 20/catch 31 |
| [`/dashboard`](#screen-dashboard) | 16 op / 16 wrapper | 0 | state 19, store 0; toast 0/inline 0/catch 0 |
| [`/function/assets`](#screen-function-assets) | 7 op / 9 wrapper | 0 | state 27, store 0; toast 11/inline 3/catch 8 |
| [`/function/commands`](#screen-function-commands) | 2 op / 2 wrapper | 0 | state 12, store 0; toast 0/inline 0/catch 2 |
| [`/function/findings/detail`](#screen-function-findings-detail) | 14 op / 16 wrapper | 0 | state 30, store 0; toast 8/inline 13/catch 14 |
| [`/function/findings`](#screen-function-findings) | 11 op / 12 wrapper | 0 | state 42, store 0; toast 9/inline 0/catch 13 |
| [`/function/llm-records`](#screen-function-llm-records) | 6 op / 6 wrapper | 0 | state 20, store 0; toast 0/inline 0/catch 5 |
| [`/function/sync`](#screen-function-sync) | 5 op / 5 wrapper | 0 | state 16, store 0; toast 8/inline 0/catch 5 |
| [`/function/tasks/detail`](#screen-function-tasks-detail) | 65 op / 66 wrapper | 2 | state 149, store 1; toast 23/inline 28/catch 65 |
| [`/function/tasks`](#screen-function-tasks) | 29 op / 30 wrapper | 0 | state 64, store 0; toast 33/inline 0/catch 28 |
| [`/function/traffic`](#screen-function-traffic) | 8 op / 8 wrapper | 0 | state 37, store 0; toast 2/inline 4/catch 6 |
| [`/function/workspace`](#screen-function-workspace) | 7 op / 7 wrapper | 0 | state 6, store 0; toast 7/inline 0/catch 7 |
| [`/system/agents/detail`](#screen-system-agents-detail) | 19 op / 19 wrapper | 0 | state 49, store 0; toast 15/inline 0/catch 22 |
| [`/system/agents`](#screen-system-agents) | 22 op / 22 wrapper | 0 | state 56, store 0; toast 17/inline 0/catch 25 |
| [`/system/intercept/approvals`](#screen-system-intercept-approvals) | 6 op / 6 wrapper | 0 | state 17, store 1; toast 3/inline 8/catch 4 |
| [`/system/intercept/assets`](#screen-system-intercept-assets) | 5 op / 5 wrapper | 0 | state 6, store 0; toast 5/inline 0/catch 3 |
| [`/system/intercept`](#screen-system-intercept) | 12 op / 12 wrapper | 0 | state 17, store 0; toast 12/inline 0/catch 8 |
| [`/system/llm`](#screen-system-llm) | 11 op / 11 wrapper | 0 | state 33, store 0; toast 13/inline 0/catch 9 |
| [`/system/logs`](#screen-system-logs) | 1 op / 0 wrapper | 1 | state 6, store 0; toast 0/inline 0/catch 0 |
| [`/system/mcp`](#screen-system-mcp) | 8 op / 8 wrapper | 0 | state 11, store 0; toast 8/inline 0/catch 8 |
| [`/system/notify`](#screen-system-notify) | 9 op / 9 wrapper | 0 | state 17, store 0; toast 11/inline 0/catch 10 |
| [`/system/settings`](#screen-system-settings) | 8 op / 7 wrapper | 1 | state 28, store 1; toast 18/inline 0/catch 19 |
| [`/system/skills`](#screen-system-skills) | 16 op / 15 wrapper | 0 | state 28, store 0; toast 11/inline 0/catch 15 |
| [`/system/tools`](#screen-system-tools) | 9 op / 9 wrapper | 0 | state 18, store 0; toast 10/inline 0/catch 8 |

## 화면별 소비 계약

<a id="screen-login"></a>
### `/login`

**entry** · `web/src/app/(auth)/login/page.tsx` · **auth** · 공개 auth bootstrap endpoint; token 발급 뒤 저장

**API wrapper** · `authStatus`, `login`

**backend operation** · [`GET /api/auth/status`](system-operations.md#op-get-api-auth-status), [`POST /api/auth/login`](system-operations.md#op-post-api-auth-login)

**SSE** · 없음

**state** · React local `password`, `error`, `loading`, `checking`, `agreed`, `termsOpen`, `readToEnd`; store 없음; persistence `cookie`, `localStorage`

**error path** · `toast.error` 0, inline error setter 5, catch/rejection handler 1, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-setup"></a>
### `/setup`

**entry** · `web/src/app/(auth)/setup/page.tsx` · **auth** · 공개 auth bootstrap endpoint; token 발급 뒤 저장

**API wrapper** · `authStatus`, `initPassword`

**backend operation** · [`GET /api/auth/status`](system-operations.md#op-get-api-auth-status), [`POST /api/auth/init`](system-operations.md#op-post-api-auth-init)

**SSE** · 없음

**state** · React local `password`, `confirm`, `error`, `loading`, `checking`; store 없음; persistence `cookie`, `localStorage`

**error path** · `toast.error` 0, inline error setter 5, catch/rejection handler 2, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-root"></a>
### `/`

**entry** · `web/src/app/(external)/page.tsx` · **auth** · page는 redirect만 수행; destination main gate 적용

**API wrapper** · 없음

**backend operation** · page subtree에서 backend operation을 찾지 못했다.

**SSE** · 없음

**state** · React local 없음; store 없음; persistence 없음

**error path** · `toast.error` 0, inline error setter 0, catch/rejection handler 0, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-chat"></a>
### `/chat`

**entry** · `web/src/app/(main)/chat/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `interceptGetOne`, `interceptDecide`, `activityDetail`, `interceptExecution`, `chatMentions`, `interceptDetail`, `interceptTaskPage`, `interceptHistoryPage`, `interceptPending`, `createConversation`, `sendConversationMessage`, `chatUpload`, `updateConversationProfile`, `conversationMsgDetail`, `conversationHistory`, `conversationMessages`, `stopConversation`, `conversations`, `agents`, `llmProfiles`, `deleteConversation`, `deleteConversations`, `pinConversation`, `renameConversation`

**backend operation** · [`GET /api/intercept/pending/{id}`](system-operations.md#op-get-api-intercept-pending-id), [`POST /api/intercept/pending/{id}/decide`](system-operations.md#op-post-api-intercept-pending-id-decide), [`GET /api/exploration/activity/{seq}`](findings-traffic.md#op-get-api-exploration-activity-seq), [`GET /api/intercept/history/{id}/execution`](system-operations.md#op-get-api-intercept-history-id-execution), [`GET /api/chat/mentions`](agents-tools.md#op-get-api-chat-mentions), [`GET /api/intercept/history/{id}`](system-operations.md#op-get-api-intercept-history-id), [`GET /api/intercept/task/{taskID}`](system-operations.md#op-get-api-intercept-task-taskid), [`GET /api/intercept/history`](system-operations.md#op-get-api-intercept-history), [`GET /api/intercept/pending`](system-operations.md#op-get-api-intercept-pending), [`POST /api/conversations`](agents-tools.md#op-post-api-conversations), [`POST /api/conversations/{id}/messages`](agents-tools.md#op-post-api-conversations-id-messages), [`POST /api/chat/upload`](agents-tools.md#op-post-api-chat-upload), [`PATCH /api/conversations/{id}/profile`](agents-tools.md#op-patch-api-conversations-id-profile), [`GET /api/conversations/{id}/messages/{seq}`](agents-tools.md#op-get-api-conversations-id-messages-seq), [`GET /api/conversations/{id}/messages`](agents-tools.md#op-get-api-conversations-id-messages), [`POST /api/conversations/{id}/stop`](agents-tools.md#op-post-api-conversations-id-stop), [`GET /api/conversations`](agents-tools.md#op-get-api-conversations), [`GET /api/agents`](agents-tools.md#op-get-api-agents), [`GET /api/llm/profiles`](agents-tools.md#op-get-api-llm-profiles), [`DELETE /api/conversations/{id}`](agents-tools.md#op-delete-api-conversations-id), [`POST /api/conversations/delete/batch`](agents-tools.md#op-post-api-conversations-delete-batch), [`PATCH /api/conversations/{id}`](agents-tools.md#op-patch-api-conversations-id), [`GET /api/side-questions/{requestID}/events`](agents-tools.md#op-get-api-side-questions-requestid-events)

**SSE** · `/api/side-questions/${runningID}/events` (`web/src/hooks/use-side-questions.ts`)

**state** · React local `isMobile`, `open`, `loading`, `err`, `inView`, `detail`, `decided`, `deciding`, `expanded`, `pending`, `statusError`, `retry`, `full`, `focusPadding`, `stateParent`, `items`, `snapshot`, `draft` 외 47개; store `useSyncExternalStore`; persistence `localStorage`

**error path** · `toast.error` 17, inline error setter 20, catch/rejection handler 31, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-dashboard"></a>
### `/dashboard`

**entry** · `web/src/app/(main)/dashboard/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `tasks`, `findings`, `stats`, `settings`, `interceptPending`, `activity`, `tokenStats`, `conversationTokens`, `traffic`, `assetCounts`, `agents`, `mcpServers`, `skills`, `tools`, `llmProfiles`, `usageStats`

**backend operation** · [`GET /api/tasks`](tasks-exploration.md#op-get-api-tasks), [`GET /api/exploration/findings`](findings-traffic.md#op-get-api-exploration-findings), [`GET /api/stats`](system-operations.md#op-get-api-stats), [`GET /api/settings`](system-operations.md#op-get-api-settings), [`GET /api/intercept/pending`](system-operations.md#op-get-api-intercept-pending), [`GET /api/exploration/activity`](findings-traffic.md#op-get-api-exploration-activity), [`GET /api/exploration/tokens`](findings-traffic.md#op-get-api-exploration-tokens), [`GET /api/tokens/conversations`](system-operations.md#op-get-api-tokens-conversations), [`GET /api/traffic`](findings-traffic.md#op-get-api-traffic), [`GET /api/assets/counts`](findings-traffic.md#op-get-api-assets-counts), [`GET /api/agents`](agents-tools.md#op-get-api-agents), [`GET /api/mcp`](agents-tools.md#op-get-api-mcp), [`GET /api/skills`](agents-tools.md#op-get-api-skills), [`GET /api/tools`](agents-tools.md#op-get-api-tools), [`GET /api/llm/profiles`](agents-tools.md#op-get-api-llm-profiles), [`GET /api/tokens/usage`](system-operations.md#op-get-api-tokens-usage)

**SSE** · 없음

**state** · React local `tasks`, `findings`, `stats`, `settings`, `pending`, `activity`, `tokens`, `convTokens`, `usageStats`, `assetCounts`, `traffic`, `agents`, `mcpServers`, `skills`, `tools`, `llmProfiles`, `tokenVersion`, `tokenTab` 외 1개; store 없음; persistence 없음

**error path** · `toast.error` 0, inline error setter 0, catch/rejection handler 0, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-assets"></a>
### `/function/assets`

**entry** · `web/src/app/(main)/function/assets/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `companies`, `assetCounts`, `deleteAssets`, `deleteCompany`, `searchAssets`, `assets`, `createCompany`, `updateCompanyScope`, `addCompanyScope`

**backend operation** · [`GET /api/companies`](findings-traffic.md#op-get-api-companies), [`GET /api/assets/counts`](findings-traffic.md#op-get-api-assets-counts), [`DELETE /api/assets`](findings-traffic.md#op-delete-api-assets), [`DELETE /api/companies/{id}`](findings-traffic.md#op-delete-api-companies-id), [`GET /api/assets`](findings-traffic.md#op-get-api-assets), [`POST /api/companies`](findings-traffic.md#op-post-api-companies), [`POST /api/companies/{id}/scope`](findings-traffic.md#op-post-api-companies-id-scope)

**SSE** · 없음

**state** · React local `rows`, `total`, `companies`, `counts`, `tab`, `query`, `loaded`, `loading`, `page`, `size`, `dslError`, `refreshKey`, `rowsTab`, `selected`, `deleteIds`, `deleteOpen`, `deleting`, `companyDeleteTarget` 외 9개; store 없음; persistence 없음

**error path** · `toast.error` 11, inline error setter 3, catch/rejection handler 8, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-commands"></a>
### `/function/commands`

**entry** · `web/src/app/(main)/function/commands/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `commands`, `commandStats`

**backend operation** · [`GET /api/commands`](system-operations.md#op-get-api-commands), [`GET /api/commands/stats`](system-operations.md#op-get-api-commands-stats)

**SSE** · 없음

**state** · React local `page`, `size`, `query`, `queryQ`, `taskFilter`, `commands`, `total`, `loading`, `statsOpen`, `stats`, `statsLoading`, `selected`; store 없음; persistence 없음

**error path** · `toast.error` 0, inline error setter 0, catch/rejection handler 2, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-findings-detail"></a>
### `/function/findings/detail`

**entry** · `web/src/app/(main)/function/findings/detail/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `findingTrafficDetail`, `findingTrafficBody`, `downloadFindingTrafficBody`, `trafficExchange`, `traffic`, `bindFindingTraffic`, `startFindingRetest`, `findingLineage`, `getFinding`, `setFindingSeverity`, `setFindingStatus`, `findingRetests`, `findingTraffic`, `orderFindingTraffic`, `removeFindingTraffic`, `editFindingTraffic`

**backend operation** · [`GET /api/exploration/findings/{id}/traffic/{binding_id}`](findings-traffic.md#op-get-api-exploration-findings-id-traffic-binding-id), [`GET /api/exploration/findings/{id}/traffic/{binding_id}/body`](findings-traffic.md#op-get-api-exploration-findings-id-traffic-binding-id-body), [`GET /api/traffic/exchange`](findings-traffic.md#op-get-api-traffic-exchange), [`GET /api/traffic`](findings-traffic.md#op-get-api-traffic), [`POST /api/exploration/findings/{id}/traffic`](findings-traffic.md#op-post-api-exploration-findings-id-traffic), [`POST /api/exploration/findings/{id}/retests`](findings-traffic.md#op-post-api-exploration-findings-id-retests), [`GET /api/exploration/findings/{id}/lineage`](findings-traffic.md#op-get-api-exploration-findings-id-lineage), [`GET /api/exploration/findings/{id}`](findings-traffic.md#op-get-api-exploration-findings-id), [`PATCH /api/exploration/findings/{id}`](findings-traffic.md#op-patch-api-exploration-findings-id), [`GET /api/exploration/findings/{id}/retests`](findings-traffic.md#op-get-api-exploration-findings-id-retests), [`GET /api/exploration/findings/{id}/traffic`](findings-traffic.md#op-get-api-exploration-findings-id-traffic), [`PUT /api/exploration/findings/{id}/traffic/order`](findings-traffic.md#op-put-api-exploration-findings-id-traffic-order), [`DELETE /api/exploration/findings/{id}/traffic/{binding_id}`](findings-traffic.md#op-delete-api-exploration-findings-id-traffic-binding-id), [`PATCH /api/exploration/findings/{id}/traffic/{binding_id}`](findings-traffic.md#op-patch-api-exploration-findings-id-traffic-binding-id)

**SSE** · 없음

**state** · React local `detail`, `error`, `busy`, `host`, `method`, `query`, `page`, `data`, `selected`, `preview`, `loading`, `isMobile`, `notes`, `submitting`, `nodes`, `edges`, `loaded`, `openMobile` 외 12개; store 없음; persistence `URL query`, `cookie`

**error path** · `toast.error` 8, inline error setter 13, catch/rejection handler 14, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-findings"></a>
### `/function/findings`

**entry** · `web/src/app/(main)/function/findings/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `activeFindingRetests`, `exportFindings`, `findingsPage`, `findingAssetTree`, `findingGroups`, `findingStats`, `setFindingStatus`, `getFinding`, `updateFinding`, `deleteFinding`, `deepenFinding`, `startFindingRetest`

**backend operation** · [`GET /api/exploration/findings/retests/active`](findings-traffic.md#op-get-api-exploration-findings-retests-active), [`GET /api/exploration/findings/export`](findings-traffic.md#op-get-api-exploration-findings-export), [`GET /api/exploration/findings/{id}`](findings-traffic.md#op-get-api-exploration-findings-id), [`GET /api/exploration/findings`](findings-traffic.md#op-get-api-exploration-findings), [`GET /api/exploration/findings/asset-tree`](findings-traffic.md#op-get-api-exploration-findings-asset-tree), [`GET /api/exploration/findings/groups`](findings-traffic.md#op-get-api-exploration-findings-groups), [`GET /api/exploration/findings/stats`](findings-traffic.md#op-get-api-exploration-findings-stats), [`PATCH /api/exploration/findings/{id}`](findings-traffic.md#op-patch-api-exploration-findings-id), [`DELETE /api/exploration/findings/{id}`](findings-traffic.md#op-delete-api-exploration-findings-id), [`POST /api/exploration/findings/{id}/deepen`](findings-traffic.md#op-post-api-exploration-findings-id-deepen), [`POST /api/exploration/findings/{id}/retests`](findings-traffic.md#op-post-api-exploration-findings-id-retests)

**SSE** · 없음

**state** · React local `view`, `severity`, `status`, `vulnclass`, `task`, `sort`, `search`, `query`, `expanded`, `flat`, `flatPage`, `flatPageSize`, `assetTree`, `assetScope`, `groups`, `groupTotal`, `expandedGroups`, `groupFindings` 외 24개; store 없음; persistence 없음

**error path** · `toast.error` 9, inline error setter 0, catch/rejection handler 13, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-llm-records"></a>
### `/function/llm-records`

**entry** · `web/src/app/(main)/function/llm-records/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `settings`, `setSettings`, `llmRecords`, `llmTasks`, `llmRecordsDeleteTask`, `llmRecordDetail`

**backend operation** · [`GET /api/settings`](system-operations.md#op-get-api-settings), [`PUT /api/settings`](system-operations.md#op-put-api-settings), [`GET /api/llm/records`](agents-tools.md#op-get-api-llm-records), [`GET /api/llm/records/tasks`](agents-tools.md#op-get-api-llm-records-tasks), [`GET /api/llm/records/{id}`](agents-tools.md#op-get-api-llm-records-id), [`DELETE /api/llm/records`](agents-tools.md#op-delete-api-llm-records)

**SSE** · 없음

**state** · React local `copied`, `page`, `size`, `session`, `sessionQ`, `model`, `records`, `total`, `loading`, `recEnabled`, `recBusy`, `selected`, `detail`, `detailLoading`, `rawView`, `tasks`, `pickedTask`, `deleteOpen` 외 2개; store 없음; persistence 없음

**error path** · `toast.error` 0, inline error setter 0, catch/rejection handler 5, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-sync"></a>
### `/function/sync`

**entry** · `web/src/app/(main)/function/sync/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `ssStatus`, `ssDatasource`, `ssProjects`, `ssTasks`, `ssSync`

**backend operation** · [`GET /api/sync/scopesentry/status`](system-operations.md#op-get-api-sync-scopesentry-status), [`POST /api/sync/scopesentry/datasource`](system-operations.md#op-post-api-sync-scopesentry-datasource), [`GET /api/sync/scopesentry/projects`](system-operations.md#op-get-api-sync-scopesentry-projects), [`GET /api/sync/scopesentry/tasks`](system-operations.md#op-get-api-sync-scopesentry-tasks), [`POST /api/sync/scopesentry/sync`](system-operations.md#op-post-api-sync-scopesentry-sync)

**SSE** · 없음

**state** · React local `status`, `loadingStatus`, `url`, `apiKey`, `busy`, `dimension`, `assetTypes`, `createCompany`, `projects`, `tasks`, `loading`, `search`, `page`, `selected`, `syncing`, `result`; store 없음; persistence 없음

**error path** · `toast.error` 8, inline error setter 0, catch/rejection handler 5, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-tasks-detail"></a>
### `/function/tasks/detail`

**entry** · `web/src/app/(main)/function/tasks/detail/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `registerTaskAssetScopes`, `searchTaskAssets`, `taskAssets`, `assetCounts`, `detachTaskAsset`, `startFindingRetest`, `interceptGetOne`, `interceptDecide`, `activityDetail`, `findingRetests`, `findings`, `setFindingStatus`, `explorationGraph`, `interceptExecution`, `chatMentions`, `explorationNodes`, `interceptDetail`, `interceptTaskPage`, `interceptHistoryPage`, `interceptPending`, `chatUpload`, `newMainSession`, `controlIntent`, `activity`, `activityHistory`, `tokenStats`, `chatStatus`, `taskLLMResolution`, `interceptTask`, `mainSessions` 외 36개

**backend operation** · [`POST /api/tasks/{id}/assets`](tasks-exploration.md#op-post-api-tasks-id-assets), [`GET /api/assets`](findings-traffic.md#op-get-api-assets), [`GET /api/assets/counts`](findings-traffic.md#op-get-api-assets-counts), [`DELETE /api/tasks/{id}/assets/{assetID}`](tasks-exploration.md#op-delete-api-tasks-id-assets-assetid), [`POST /api/exploration/findings/{id}/retests`](findings-traffic.md#op-post-api-exploration-findings-id-retests), [`GET /api/intercept/pending/{id}`](system-operations.md#op-get-api-intercept-pending-id), [`POST /api/intercept/pending/{id}/decide`](system-operations.md#op-post-api-intercept-pending-id-decide), [`GET /api/exploration/activity/{seq}`](findings-traffic.md#op-get-api-exploration-activity-seq), [`GET /api/exploration/findings/{id}/retests`](findings-traffic.md#op-get-api-exploration-findings-id-retests), [`GET /api/exploration/findings`](findings-traffic.md#op-get-api-exploration-findings), [`PATCH /api/exploration/findings/{id}`](findings-traffic.md#op-patch-api-exploration-findings-id), [`GET /api/exploration/graph`](findings-traffic.md#op-get-api-exploration-graph), [`GET /api/intercept/history/{id}/execution`](system-operations.md#op-get-api-intercept-history-id-execution), [`GET /api/chat/mentions`](agents-tools.md#op-get-api-chat-mentions), [`GET /api/exploration/nodes`](findings-traffic.md#op-get-api-exploration-nodes), [`GET /api/intercept/history/{id}`](system-operations.md#op-get-api-intercept-history-id), [`GET /api/intercept/task/{taskID}`](system-operations.md#op-get-api-intercept-task-taskid), [`GET /api/intercept/history`](system-operations.md#op-get-api-intercept-history), [`GET /api/intercept/pending`](system-operations.md#op-get-api-intercept-pending), [`POST /api/chat/upload`](agents-tools.md#op-post-api-chat-upload), [`POST /api/exploration/main-session/new`](findings-traffic.md#op-post-api-exploration-main-session-new), [`POST /api/tasks/{id}/intents/{iid}/control`](tasks-exploration.md#op-post-api-tasks-id-intents-iid-control), [`GET /api/exploration/activity`](findings-traffic.md#op-get-api-exploration-activity), [`GET /api/exploration/activity/history`](findings-traffic.md#op-get-api-exploration-activity-history), [`GET /api/exploration/tokens`](findings-traffic.md#op-get-api-exploration-tokens), [`GET /api/tasks/{id}/chat/status`](tasks-exploration.md#op-get-api-tasks-id-chat-status), [`GET /api/tasks/{id}/llm/resolution`](tasks-exploration.md#op-get-api-tasks-id-llm-resolution), [`GET /api/exploration/main-sessions`](findings-traffic.md#op-get-api-exploration-main-sessions), [`GET /api/tasks/{id}/intent-assets`](tasks-exploration.md#op-get-api-tasks-id-intent-assets), [`GET /api/exploration/intents`](findings-traffic.md#op-get-api-exploration-intents), [`POST /api/tasks/{id}/chat/stop`](tasks-exploration.md#op-post-api-tasks-id-chat-stop), [`POST /api/chat`](agents-tools.md#op-post-api-chat), [`POST /api/tasks/{id}/intents/{iid}/messages`](tasks-exploration.md#op-post-api-tasks-id-intents-iid-messages), [`GET /api/llm/records/by-model`](agents-tools.md#op-get-api-llm-records-by-model), [`GET /api/llm/records/{id}`](agents-tools.md#op-get-api-llm-records-id), [`GET /api/tasks/{id}/scope`](tasks-exploration.md#op-get-api-tasks-id-scope), [`GET /api/tasks/{id}/goals`](tasks-exploration.md#op-get-api-tasks-id-goals), [`POST /api/tasks/{id}/goals`](tasks-exploration.md#op-post-api-tasks-id-goals), [`PATCH /api/tasks/{id}/goals/{gid}`](tasks-exploration.md#op-patch-api-tasks-id-goals-gid), [`DELETE /api/tasks/{id}/goals/{gid}`](tasks-exploration.md#op-delete-api-tasks-id-goals-gid), [`GET /api/tasks/{id}/constraints`](tasks-exploration.md#op-get-api-tasks-id-constraints), [`POST /api/tasks/{id}/constraints`](tasks-exploration.md#op-post-api-tasks-id-constraints), [`PATCH /api/tasks/{id}/constraints/{cid}`](tasks-exploration.md#op-patch-api-tasks-id-constraints-cid), [`DELETE /api/tasks/{id}/constraints/{cid}`](tasks-exploration.md#op-delete-api-tasks-id-constraints-cid), [`POST /api/tasks/{id}/scope`](tasks-exploration.md#op-post-api-tasks-id-scope), [`DELETE /api/tasks/{id}/scope/{sid}`](tasks-exploration.md#op-delete-api-tasks-id-scope-sid), [`POST /api/tasks/{id}/intents/{iid}/rerun`](tasks-exploration.md#op-post-api-tasks-id-intents-iid-rerun), [`POST /api/tasks/{id}/intents/rerun-blocked`](tasks-exploration.md#op-post-api-tasks-id-intents-rerun-blocked), [`GET /api/tasks/{id}`](tasks-exploration.md#op-get-api-tasks-id), [`GET /api/stats`](system-operations.md#op-get-api-stats), [`GET /api/tasks/{id}/coverage`](tasks-exploration.md#op-get-api-tasks-id-coverage), [`GET /api/tasks/{id}/intercept-rules`](tasks-exploration.md#op-get-api-tasks-id-intercept-rules), [`POST /api/tasks/{id}/intercept-rules`](tasks-exploration.md#op-post-api-tasks-id-intercept-rules), [`PUT /api/tasks/{id}/intercept-rules/{rid}`](tasks-exploration.md#op-put-api-tasks-id-intercept-rules-rid), [`DELETE /api/tasks/{id}/intercept-rules/{rid}`](tasks-exploration.md#op-delete-api-tasks-id-intercept-rules-rid), [`POST /api/tasks/{id}/intercept-rules/{rid}/toggle`](tasks-exploration.md#op-post-api-tasks-id-intercept-rules-rid-toggle), [`PUT /api/tasks/{id}/llm`](tasks-exploration.md#op-put-api-tasks-id-llm), [`GET /api/llm/profiles`](agents-tools.md#op-get-api-llm-profiles), [`POST /api/tasks/{id}/control`](tasks-exploration.md#op-post-api-tasks-id-control), [`POST /api/tasks/{id}/archive`](tasks-exploration.md#op-post-api-tasks-id-archive), [`GET /api/tasks/{id}/asset-refs`](tasks-exploration.md#op-get-api-tasks-id-asset-refs), [`GET /api/tasks/{id}/coverage-graph`](tasks-exploration.md#op-get-api-tasks-id-coverage-graph), [`GET /api/report`](findings-traffic.md#op-get-api-report), [`GET /api/side-questions/{requestID}/events`](agents-tools.md#op-get-api-side-questions-requestid-events), [`GET /api/exploration/activity/stream`](findings-traffic.md#op-get-api-exploration-activity-stream)

**SSE** · `/api/side-questions/${runningID}/events` (`web/src/hooks/use-side-questions.ts`); `/api/exploration/activity/stream?task=${encodeURIComponent(taskId)}&since=${snapshotRef.current}` (`web/src/app/(main)/function/tasks/detail/_tabs/sessions-tab.tsx`)

**state** · React local `scopeText`, `saving`, `rows`, `total`, `counts`, `loaded`, `tab`, `page`, `size`, `query`, `loading`, `dslError`, `refreshKey`, `addOpen`, `removeTarget`, `removing`, `isMobile`, `notes` 외 131개; store `useSyncExternalStore`; persistence `URL query`, `cookie`, `localStorage`

**error path** · `toast.error` 23, inline error setter 28, catch/rejection handler 65, SSE `onerror` 1. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-tasks"></a>
### `/function/tasks`

**entry** · `web/src/app/(main)/function/tasks/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `taskCategories`, `createTaskTemplate`, `updateTaskTemplate`, `deleteTaskTemplate`, `taskTemplates`, `tasks`, `deleteTask`, `controlTask`, `renameTask`, `pinTask`, `archiveTask`, `archiveTasks`, `controlTasksBatch`, `updateTasksCategory`, `settings`, `setSettings`, `taskArchives`, `taskArchive`, `restoreTaskArchive`, `restoreTaskArchives`, `deleteTaskArchive`, `deleteTaskArchives`, `createTaskCategory`, `renameTaskCategory`, `deleteTaskCategory`, `updateTaskCategory`, `llmProfiles`, `companies`, `chatUpload`, `createTask`

**backend operation** · [`GET /api/task-categories`](tasks-exploration.md#op-get-api-task-categories), [`POST /api/task-templates`](tasks-exploration.md#op-post-api-task-templates), [`PATCH /api/task-templates/{id}`](tasks-exploration.md#op-patch-api-task-templates-id), [`DELETE /api/task-templates/{id}`](tasks-exploration.md#op-delete-api-task-templates-id), [`GET /api/task-templates`](tasks-exploration.md#op-get-api-task-templates), [`GET /api/tasks`](tasks-exploration.md#op-get-api-tasks), [`DELETE /api/tasks/{id}`](tasks-exploration.md#op-delete-api-tasks-id), [`POST /api/tasks/{id}/control`](tasks-exploration.md#op-post-api-tasks-id-control), [`PATCH /api/tasks/{id}`](tasks-exploration.md#op-patch-api-tasks-id), [`POST /api/tasks/{id}/archive`](tasks-exploration.md#op-post-api-tasks-id-archive), [`POST /api/tasks/archive/batch`](tasks-exploration.md#op-post-api-tasks-archive-batch), [`POST /api/tasks/control/batch`](tasks-exploration.md#op-post-api-tasks-control-batch), [`POST /api/tasks/category/batch`](tasks-exploration.md#op-post-api-tasks-category-batch), [`GET /api/settings`](system-operations.md#op-get-api-settings), [`PUT /api/settings`](system-operations.md#op-put-api-settings), [`GET /api/task-archives`](tasks-exploration.md#op-get-api-task-archives), [`GET /api/task-archives/{id}`](tasks-exploration.md#op-get-api-task-archives-id), [`POST /api/task-archives/{id}/restore`](tasks-exploration.md#op-post-api-task-archives-id-restore), [`POST /api/task-archives/restore/batch`](tasks-exploration.md#op-post-api-task-archives-restore-batch), [`DELETE /api/task-archives/{id}`](tasks-exploration.md#op-delete-api-task-archives-id), [`POST /api/task-archives/delete/batch`](tasks-exploration.md#op-post-api-task-archives-delete-batch), [`POST /api/task-categories`](tasks-exploration.md#op-post-api-task-categories), [`PATCH /api/task-categories/{id}`](tasks-exploration.md#op-patch-api-task-categories-id), [`DELETE /api/task-categories/{id}`](tasks-exploration.md#op-delete-api-task-categories-id), [`PATCH /api/tasks/{id}/category`](tasks-exploration.md#op-patch-api-tasks-id-category), [`GET /api/llm/profiles`](agents-tools.md#op-get-api-llm-profiles), [`GET /api/companies`](findings-traffic.md#op-get-api-companies), [`POST /api/chat/upload`](agents-tools.md#op-post-api-chat-upload), [`POST /api/tasks`](tasks-exploration.md#op-post-api-tasks)

**SSE** · 없음

**state** · React local `selectedID`, `draft`, `saving`, `deleteOpen`, `deleting`, `categories`, `templates`, `loading`, `templateInputValue`, `pendingTemplate`, `managerOpen`, `managerSeed`, `activeTab`, `tasks`, `categoriesLoaded`, `query`, `statusFilter`, `categoryFilter` 외 46개; store 없음; persistence 없음

**error path** · `toast.error` 33, inline error setter 0, catch/rejection handler 28, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-traffic"></a>
### `/function/traffic`

**entry** · `web/src/app/(main)/function/traffic/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `findingsPage`, `bindFindingTraffic`, `traffic`, `trafficHosts`, `trafficDeleteAll`, `trafficDeleteHosts`, `trafficDeleteHost`, `trafficExchange`

**backend operation** · [`GET /api/exploration/findings`](findings-traffic.md#op-get-api-exploration-findings), [`POST /api/exploration/findings/{id}/traffic`](findings-traffic.md#op-post-api-exploration-findings-id-traffic), [`GET /api/traffic`](findings-traffic.md#op-get-api-traffic), [`GET /api/traffic/hosts`](findings-traffic.md#op-get-api-traffic-hosts), [`DELETE /api/traffic/all`](findings-traffic.md#op-delete-api-traffic-all), [`DELETE /api/traffic/hosts`](findings-traffic.md#op-delete-api-traffic-hosts), [`DELETE /api/traffic`](findings-traffic.md#op-delete-api-traffic), [`GET /api/traffic/exchange`](findings-traffic.md#op-get-api-traffic-exchange)

**SSE** · 없음

**state** · React local `query`, `page`, `data`, `selected`, `error`, `busy`, `loading`, `wrapLines`, `copied`, `selectedFlows`, `linking`, `size`, `host`, `hostQ`, `queryQ`, `method`, `body`, `bodyQ` 외 19개; store 없음; persistence 없음

**error path** · `toast.error` 2, inline error setter 4, catch/rejection handler 6, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-function-workspace"></a>
### `/function/workspace`

**entry** · `web/src/app/(main)/function/workspace/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `workspaceList`, `workspaceRead`, `workspaceWrite`, `workspaceDelete`, `workspaceUpload`, `workspaceMkdir`, `workspaceDownload`

**backend operation** · [`GET /api/workspace/list`](system-operations.md#op-get-api-workspace-list), [`GET /api/workspace/read`](system-operations.md#op-get-api-workspace-read), [`POST /api/workspace/write`](system-operations.md#op-post-api-workspace-write), [`DELETE /api/workspace/delete`](system-operations.md#op-delete-api-workspace-delete), [`POST /api/workspace/upload`](system-operations.md#op-post-api-workspace-upload), [`POST /api/workspace/mkdir`](system-operations.md#op-post-api-workspace-mkdir), [`GET /api/workspace/download`](system-operations.md#op-get-api-workspace-download)

**SSE** · 없음

**state** · React local `path`, `entries`, `loading`, `edit`, `mkdirOpen`, `mkdirName`; store 없음; persistence 없음

**error path** · `toast.error` 7, inline error setter 0, catch/rejection handler 7, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-agents-detail"></a>
### `/system/agents/detail`

**entry** · `web/src/app/(main)/system/agents/detail/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `mcpServers`, `skills`, `tools`, `settings`, `getAgent`, `previewAgentPrompt`, `saveAgentPrompt`, `resetAgentPrompt`, `saveAgentWrapup`, `resetAgentWrapup`, `saveAgentTaskTimeoutWrapup`, `resetAgentTaskTimeoutWrapup`, `saveAgentConfig`, `setAgentVisibility`, `saveTool`, `agentTriggers`, `updateTrigger`, `createTrigger`, `deleteTrigger`

**backend operation** · [`GET /api/mcp`](agents-tools.md#op-get-api-mcp), [`GET /api/skills`](agents-tools.md#op-get-api-skills), [`GET /api/tools`](agents-tools.md#op-get-api-tools), [`GET /api/settings`](system-operations.md#op-get-api-settings), [`GET /api/agents/{key}`](agents-tools.md#op-get-api-agents-key), [`POST /api/agents/{key}/prompt/preview`](agents-tools.md#op-post-api-agents-key-prompt-preview), [`PUT /api/agents/{key}/prompt`](agents-tools.md#op-put-api-agents-key-prompt), [`POST /api/agents/{key}/prompt/reset`](agents-tools.md#op-post-api-agents-key-prompt-reset), [`PUT /api/agents/{key}/wrapup`](agents-tools.md#op-put-api-agents-key-wrapup), [`POST /api/agents/{key}/wrapup/reset`](agents-tools.md#op-post-api-agents-key-wrapup-reset), [`PUT /api/agents/{key}/wrapup/task-timeout`](agents-tools.md#op-put-api-agents-key-wrapup-task-timeout), [`POST /api/agents/{key}/wrapup/task-timeout/reset`](agents-tools.md#op-post-api-agents-key-wrapup-task-timeout-reset), [`PUT /api/agents/{key}/config`](agents-tools.md#op-put-api-agents-key-config), [`PUT /api/agents/{key}/visibility`](agents-tools.md#op-put-api-agents-key-visibility), [`PUT /api/tools/{key}`](agents-tools.md#op-put-api-tools-key), [`GET /api/agents/{key}/triggers`](agents-tools.md#op-get-api-agents-key-triggers), [`PATCH /api/triggers/{id}`](system-operations.md#op-patch-api-triggers-id), [`POST /api/agents/{key}/triggers`](agents-tools.md#op-post-api-agents-key-triggers), [`DELETE /api/triggers/{id}`](system-operations.md#op-delete-api-triggers-id)

**SSE** · 없음

**state** · React local `detail`, `versions`, `variables`, `mcp`, `skills`, `tools`, `loaded`, `viewVer`, `diffVer`, `prompt`, `mcpVisible`, `skillVisible`, `preview`, `maxTurns`, `runSecs`, `llmProfileId`, `llmProfiles`, `webSearch` 외 31개; store 없음; persistence `URL query`

**error path** · `toast.error` 15, inline error setter 0, catch/rejection handler 22, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-agents"></a>
### `/system/agents`

**entry** · `web/src/app/(main)/system/agents/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `deleteAgent`, `createAgent`, `agents`, `mcpServers`, `skills`, `tools`, `settings`, `getAgent`, `previewAgentPrompt`, `saveAgentPrompt`, `resetAgentPrompt`, `saveAgentWrapup`, `resetAgentWrapup`, `saveAgentTaskTimeoutWrapup`, `resetAgentTaskTimeoutWrapup`, `saveAgentConfig`, `setAgentVisibility`, `saveTool`, `agentTriggers`, `updateTrigger`, `createTrigger`, `deleteTrigger`

**backend operation** · [`DELETE /api/agents/{key}`](agents-tools.md#op-delete-api-agents-key), [`POST /api/agents`](agents-tools.md#op-post-api-agents), [`GET /api/agents`](agents-tools.md#op-get-api-agents), [`GET /api/mcp`](agents-tools.md#op-get-api-mcp), [`GET /api/skills`](agents-tools.md#op-get-api-skills), [`GET /api/tools`](agents-tools.md#op-get-api-tools), [`GET /api/settings`](system-operations.md#op-get-api-settings), [`GET /api/agents/{key}`](agents-tools.md#op-get-api-agents-key), [`POST /api/agents/{key}/prompt/preview`](agents-tools.md#op-post-api-agents-key-prompt-preview), [`PUT /api/agents/{key}/prompt`](agents-tools.md#op-put-api-agents-key-prompt), [`POST /api/agents/{key}/prompt/reset`](agents-tools.md#op-post-api-agents-key-prompt-reset), [`PUT /api/agents/{key}/wrapup`](agents-tools.md#op-put-api-agents-key-wrapup), [`POST /api/agents/{key}/wrapup/reset`](agents-tools.md#op-post-api-agents-key-wrapup-reset), [`PUT /api/agents/{key}/wrapup/task-timeout`](agents-tools.md#op-put-api-agents-key-wrapup-task-timeout), [`POST /api/agents/{key}/wrapup/task-timeout/reset`](agents-tools.md#op-post-api-agents-key-wrapup-task-timeout-reset), [`PUT /api/agents/{key}/config`](agents-tools.md#op-put-api-agents-key-config), [`PUT /api/agents/{key}/visibility`](agents-tools.md#op-put-api-agents-key-visibility), [`PUT /api/tools/{key}`](agents-tools.md#op-put-api-tools-key), [`GET /api/agents/{key}/triggers`](agents-tools.md#op-get-api-agents-key-triggers), [`PATCH /api/triggers/{id}`](system-operations.md#op-patch-api-triggers-id), [`POST /api/agents/{key}/triggers`](agents-tools.md#op-post-api-agents-key-triggers), [`DELETE /api/triggers/{id}`](system-operations.md#op-delete-api-triggers-id)

**SSE** · 없음

**state** · React local `open`, `key`, `name`, `description`, `busy`, `agents`, `editKey`, `detail`, `versions`, `variables`, `mcp`, `skills`, `tools`, `loaded`, `viewVer`, `diffVer`, `prompt`, `mcpVisible` 외 38개; store 없음; persistence 없음

**error path** · `toast.error` 17, inline error setter 0, catch/rejection handler 25, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-intercept-approvals"></a>
### `/system/intercept/approvals`

**entry** · `web/src/app/(main)/system/intercept/approvals/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `interceptExecution`, `interceptDetail`, `interceptTaskPage`, `interceptHistoryPage`, `interceptPending`, `interceptDecide`

**backend operation** · [`GET /api/intercept/history/{id}/execution`](system-operations.md#op-get-api-intercept-history-id-execution), [`GET /api/intercept/history/{id}`](system-operations.md#op-get-api-intercept-history-id), [`GET /api/intercept/task/{taskID}`](system-operations.md#op-get-api-intercept-task-taskid), [`GET /api/intercept/history`](system-operations.md#op-get-api-intercept-history), [`GET /api/intercept/pending`](system-operations.md#op-get-api-intercept-pending), [`POST /api/intercept/pending/{id}/decide`](system-operations.md#op-post-api-intercept-pending-id-decide)

**SSE** · 없음

**state** · React local `locating`, `detail`, `error`, `retry`, `more`, `expanded`, `rows`, `pendingRows`, `page`, `pageSize`, `total`, `filter`, `loading`, `refreshing`, `pendingError`, `deciding`, `revision`; store `useSyncExternalStore`; persistence 없음

**error path** · `toast.error` 3, inline error setter 8, catch/rejection handler 4, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-intercept-assets"></a>
### `/system/intercept/assets`

**entry** · `web/src/app/(main)/system/intercept/assets/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `assetInterceptRules`, `updateAssetInterceptRule`, `createAssetInterceptRule`, `deleteAssetInterceptRule`, `toggleAssetInterceptRule`

**backend operation** · [`GET /api/asset-intercept/rules`](system-operations.md#op-get-api-asset-intercept-rules), [`PUT /api/asset-intercept/rules/{id}`](system-operations.md#op-put-api-asset-intercept-rules-id), [`POST /api/asset-intercept/rules`](system-operations.md#op-post-api-asset-intercept-rules), [`DELETE /api/asset-intercept/rules/{id}`](system-operations.md#op-delete-api-asset-intercept-rules-id), [`POST /api/asset-intercept/rules/{id}/toggle`](system-operations.md#op-post-api-asset-intercept-rules-id-toggle)

**SSE** · 없음

**state** · React local `rules`, `loading`, `open`, `editing`, `form`, `saving`; store 없음; persistence 없음

**error path** · `toast.error` 5, inline error setter 0, catch/rejection handler 3, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-intercept"></a>
### `/system/intercept`

**entry** · `web/src/app/(main)/system/intercept/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `interceptJudgeUsage`, `interceptGetJudgeConfig`, `llmProfiles`, `interceptSetJudgeConfig`, `interceptGetToolConfig`, `interceptRules`, `updateInterceptRule`, `createInterceptRule`, `deleteInterceptRule`, `toggleInterceptRule`, `tools`, `interceptSetToolConfig`

**backend operation** · [`GET /api/intercept/judge/usage`](system-operations.md#op-get-api-intercept-judge-usage), [`GET /api/intercept/judge`](system-operations.md#op-get-api-intercept-judge), [`GET /api/llm/profiles`](agents-tools.md#op-get-api-llm-profiles), [`PUT /api/intercept/judge`](system-operations.md#op-put-api-intercept-judge), [`GET /api/intercept/tool-config`](system-operations.md#op-get-api-intercept-tool-config), [`GET /api/intercept/rules`](system-operations.md#op-get-api-intercept-rules), [`PUT /api/intercept/rules/{id}`](system-operations.md#op-put-api-intercept-rules-id), [`POST /api/intercept/rules`](system-operations.md#op-post-api-intercept-rules), [`DELETE /api/intercept/rules/{id}`](system-operations.md#op-delete-api-intercept-rules-id), [`POST /api/intercept/rules/{id}/toggle`](system-operations.md#op-post-api-intercept-rules-id-toggle), [`GET /api/tools`](agents-tools.md#op-get-api-tools), [`PUT /api/intercept/tool-config`](system-operations.md#op-put-api-intercept-tool-config)

**SSE** · 없음

**state** · React local `cfg`, `profiles`, `loading`, `saving`, `usage`, `rules`, `open`, `editing`, `form`, `regexErr`, `regexWarn`, `scopeOpen`, `allTools`, `enabledTools`, `scopeLoading`, `scopeSaving`, `scopeTools`; store 없음; persistence 없음

**error path** · `toast.error` 12, inline error setter 0, catch/rejection handler 8, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-llm"></a>
### `/system/llm`

**entry** · `web/src/app/(main)/system/llm/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `llmRetryPolicy`, `saveLLMRetryPolicy`, `setSettings`, `resetLLMPool`, `fetchLLMModels`, `testLLM`, `saveLLMProfile`, `llmPool`, `llmProfiles`, `activateLLMProfile`, `deleteLLMProfile`

**backend operation** · [`GET /api/llm/retry-policy`](agents-tools.md#op-get-api-llm-retry-policy), [`POST /api/llm/retry-policy`](agents-tools.md#op-post-api-llm-retry-policy), [`PUT /api/settings`](system-operations.md#op-put-api-settings), [`POST /api/llm/pool/reset`](agents-tools.md#op-post-api-llm-pool-reset), [`POST /api/llm/models`](agents-tools.md#op-post-api-llm-models), [`POST /api/llm/test`](agents-tools.md#op-post-api-llm-test), [`POST /api/llm/profiles`](agents-tools.md#op-post-api-llm-profiles), [`GET /api/llm/pool`](agents-tools.md#op-get-api-llm-pool), [`GET /api/llm/profiles`](agents-tools.md#op-get-api-llm-profiles), [`POST /api/llm/profiles/active`](agents-tools.md#op-post-api-llm-profiles-active), [`DELETE /api/llm/profiles/{id}`](agents-tools.md#op-delete-api-llm-profiles-id)

**SSE** · 없음

**state** · React local `text`, `policy`, `loading`, `saving`, `busy`, `name`, `format`, `model`, `baseUrl`, `proxy`, `apiKey`, `keyHint`, `rps`, `rpm`, `cw`, `thinkingType`, `effort`, `priority` 외 15개; store 없음; persistence 없음

**error path** · `toast.error` 13, inline error setter 0, catch/rejection handler 9, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-logs"></a>
### `/system/logs`

**entry** · `web/src/app/(main)/system/logs/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · 없음

**backend operation** · [`GET /api/logs/stream`](system-operations.md#op-get-api-logs-stream)

**SSE** · `/api/logs/stream?since=0` (`web/src/app/(main)/system/logs/page.tsx`)

**state** · React local `lines`, `q`, `level`, `paused`, `loadingHistory`, `hasMore`; store 없음; persistence 없음

**error path** · `toast.error` 0, inline error setter 0, catch/rejection handler 0, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-mcp"></a>
### `/system/mcp`

**entry** · `web/src/app/(main)/system/mcp/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `agents`, `mcpServers`, `resourceVisibility`, `mcpTools`, `saveMcpServer`, `refreshMcpServer`, `deleteMcpServer`, `toggleVisibility`

**backend operation** · [`GET /api/agents`](agents-tools.md#op-get-api-agents), [`GET /api/mcp`](agents-tools.md#op-get-api-mcp), [`GET /api/visibility/{kind}/{id}`](agents-tools.md#op-get-api-visibility-kind-id), [`GET /api/mcp/{id}/tools`](agents-tools.md#op-get-api-mcp-id-tools), [`POST /api/mcp`](agents-tools.md#op-post-api-mcp), [`POST /api/mcp/{id}/refresh`](agents-tools.md#op-post-api-mcp-id-refresh), [`DELETE /api/mcp/{id}`](agents-tools.md#op-delete-api-mcp-id), [`POST /api/visibility/toggle`](agents-tools.md#op-post-api-visibility-toggle)

**SSE** · 없음

**state** · React local `servers`, `agents`, `visibility`, `open`, `editing`, `tab`, `form`, `saving`, `tools`, `toolsLoading`, `refreshing`; store 없음; persistence 없음

**error path** · `toast.error` 8, inline error setter 0, catch/rejection handler 8, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-notify"></a>
### `/system/notify`

**entry** · `web/src/app/(main)/system/notify/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `notifyMeta`, `notifyChannels`, `notifyUpdateChannel`, `notifyCreateChannel`, `notifyTestChannel`, `notifyDeleteChannel`, `setSettings`, `notifyDeliveries`, `notifyRetryDelivery`

**backend operation** · [`GET /api/notify/meta`](system-operations.md#op-get-api-notify-meta), [`GET /api/notify/channels`](system-operations.md#op-get-api-notify-channels), [`PATCH /api/notify/channels/{id}`](system-operations.md#op-patch-api-notify-channels-id), [`POST /api/notify/channels`](system-operations.md#op-post-api-notify-channels), [`POST /api/notify/channels/{id}/test`](system-operations.md#op-post-api-notify-channels-id-test), [`DELETE /api/notify/channels/{id}`](system-operations.md#op-delete-api-notify-channels-id), [`PUT /api/settings`](system-operations.md#op-put-api-settings), [`GET /api/notify/deliveries`](system-operations.md#op-get-api-notify-deliveries), [`POST /api/notify/deliveries/{id}/retry`](system-operations.md#op-post-api-notify-deliveries-id-retry)

**SSE** · 없음

**state** · React local `meta`, `channels`, `tab`, `open`, `editing`, `form`, `saving`, `testing`, `globalSaving`, `baseURL`, `digestMin`, `rows`, `total`, `page`, `channelID`, `state`, `loading`; store 없음; persistence 없음

**error path** · `toast.error` 11, inline error setter 0, catch/rejection handler 10, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-settings"></a>
### `/system/settings`

**entry** · `web/src/app/(main)/system/settings/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `setSettings`, `detectPython`, `settings`, `testWebSearch`, `checkUpdate`, `applyUpdate`, `rollbackUpdate`

**backend operation** · [`PUT /api/settings`](system-operations.md#op-put-api-settings), [`POST /api/settings/python/detect`](system-operations.md#op-post-api-settings-python-detect), [`GET /api/settings`](system-operations.md#op-get-api-settings), [`POST /api/settings/web-search/test`](system-operations.md#op-post-api-settings-web-search-test), [`GET /api/update/check`](system-operations.md#op-get-api-update-check), [`POST /api/update/apply`](system-operations.md#op-post-api-update-apply), [`POST /api/update/rollback`](system-operations.md#op-post-api-update-rollback), [`GET /api/update/stream`](system-operations.md#op-get-api-update-stream)

**SSE** · `/api/update/stream` (`web/src/app/(main)/system/settings/_components/update-card.tsx`)

**state** · React local `trafficCapture`, `agentTrafficBinding`, `webSearch`, `backend`, `braveKeySet`, `braveKeyInput`, `tavilyKeySet`, `tavilyKeyInput`, `savingTavilyKey`, `proxyInput`, `savingProxy`, `globalProxyInput`, `savingGlobalProxy`, `testing`, `loaded`, `saving`, `savingKey`, `pyInterp` 외 10개; store `useSyncExternalStore`; persistence `localStorage`

**error path** · `toast.error` 18, inline error setter 0, catch/rejection handler 19, SSE `onerror` 1. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-skills"></a>
### `/system/skills`

**entry** · `web/src/app/(main)/system/skills/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `skills`, `agents`, `mcpServers`, `missingSkills`, `skillVisibility`, `uploadSkill`, `skillUsage`, `readSkillFile`, `createSkillDir`, `writeSkillFile`, `deleteSkillPath`, `deleteSkill`, `updateSkillMeta`, `toggleSkillVisibility`, `createSkill`

**backend operation** · [`GET /api/skills`](agents-tools.md#op-get-api-skills), [`GET /api/agents`](agents-tools.md#op-get-api-agents), [`GET /api/mcp`](agents-tools.md#op-get-api-mcp), [`GET /api/skills/missing`](agents-tools.md#op-get-api-skills-missing), [`GET /api/visibility/{kind}/{id}`](agents-tools.md#op-get-api-visibility-kind-id), [`GET /api/visibility/skill/{name}`](agents-tools.md#op-get-api-visibility-skill-name), [`POST /api/skills/upload`](agents-tools.md#op-post-api-skills-upload), [`GET /api/skills/{name}/usage`](agents-tools.md#op-get-api-skills-name-usage), [`GET /api/skills/{name}/files/{file...}`](agents-tools.md#op-get-api-skills-name-files-file), [`POST /api/skills/{name}/dirs`](agents-tools.md#op-post-api-skills-name-dirs), [`PUT /api/skills/{name}/files/{file...}`](agents-tools.md#op-put-api-skills-name-files-file), [`DELETE /api/skills/{name}/files/{file...}`](agents-tools.md#op-delete-api-skills-name-files-file), [`DELETE /api/skills/{name}`](agents-tools.md#op-delete-api-skills-name), [`PUT /api/skills/{name}/meta`](agents-tools.md#op-put-api-skills-name-meta), [`POST /api/visibility/skill/toggle`](agents-tools.md#op-post-api-visibility-skill-toggle), [`POST /api/skills`](agents-tools.md#op-post-api-skills)

**SSE** · 없음

**state** · React local `skills`, `agents`, `selected`, `visibility`, `expanded`, `fileContent`, `fileLoading`, `dirty`, `saving`, `creating`, `newEntryName`, `newOpen`, `newName`, `newDesc`, `newLicense`, `newCompat`, `newInst`, `newMcps` 외 10개; store 없음; persistence 없음

**error path** · `toast.error` 11, inline error setter 0, catch/rejection handler 15, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

<a id="screen-system-tools"></a>
### `/system/tools`

**entry** · `web/src/app/(main)/system/tools/page.tsx` · **auth** · main client token gate + Bearer/401 redirect; SSE query token

**API wrapper** · `saveTool`, `resetTool`, `tools`, `agents`, `settings`, `createCustomTool`, `updateCustomTool`, `deleteCustomTool`, `testCustomTool`

**backend operation** · [`PUT /api/tools/{key}`](agents-tools.md#op-put-api-tools-key), [`POST /api/tools/{key}/reset`](agents-tools.md#op-post-api-tools-key-reset), [`GET /api/tools`](agents-tools.md#op-get-api-tools), [`GET /api/agents`](agents-tools.md#op-get-api-agents), [`GET /api/settings`](system-operations.md#op-get-api-settings), [`POST /api/tools/custom`](agents-tools.md#op-post-api-tools-custom), [`PUT /api/tools/custom/{key}`](agents-tools.md#op-put-api-tools-custom-key), [`DELETE /api/tools/custom/{key}`](agents-tools.md#op-delete-api-tools-custom-key), [`POST /api/tools/custom/test`](agents-tools.md#op-post-api-tools-custom-test)

**SSE** · 없음

**state** · React local `description`, `bound`, `enabled`, `rows`, `saving`, `tools`, `agents`, `captureOn`, `selectedKey`, `customEdit`, `query`, `key`, `kind`, `ex`, `schemaText`, `deferred`, `paramsText`, `testing`; store 없음; persistence 없음

**error path** · `toast.error` 10, inline error setter 0, catch/rejection handler 8, SSE `onerror` 0. 401 공통 처리는 API client가 담당한다.

## 정적 매핑의 미확인

- 27/27 `page.tsx` entry와 네 SSE 소비 위치를 확인했다(C). API wrapper 호출은 local static import graph 기준이며 조건부 render와 실제 request 발생은 실행 미확인(A).
- wrapper 내부에서 동적으로 조립한 path는 명시 보정한 upload/download/export/config를 포함한다. operation으로 해석하지 못한 문자열은 미확정으로 유지했다.
- React state 이름과 error-handler 수는 UI 의미 완결성의 대체 지표가 아니다. URL query, component props와 server response가 만드는 화면 상태의 runtime 조합은 브라우저 관찰 전 U다.

