# 架構

HakoRun 的模組層級與一次請求經過的元件。

## 系統概覽

```mermaid
graph TB
    Main[cmd/api 進入點] --> Checker[checker 相依檢查]
    Main --> DB[database 初始化]
    Main --> Slice[sandbox.NewSlice]
    Main --> Router[internal 路由]
    Client[客戶端] --> Router
    Router --> Handler[handler Upload / Run / RunNow]
    Handler --> Store[(ToriiDB / Redis)]
    Handler --> Sandbox[sandbox.SandboxCommand]
    Sandbox --> Wrapper[internal/resource wrapper]
    Wrapper --> Handler
    Handler --> Client
```

## 分層

| 層 | 路徑 | 職責 |
|----|------|------|
| 進入點 | `cmd/api/main.go` | 依序執行相依檢查、儲存初始化、建立 slice、啟動 HTTP；處理訊號與 5 秒關閉 |
| 路由 | `internal/router.go` | 建立 Gin 引擎，註冊 `/upload`、`/run/*targetPath`、`/run-now`，綁定 `HTTP_PORT` |
| Handler | `internal/handler/` | 驗證請求、讀取腳本、選擇一次性或 SSE 執行、標註回應型別 |
| 儲存 | `internal/database/` | `backend` 介面；建置標籤選擇 ToriiDB 或 Redis |
| 沙箱 | `internal/sandbox/` | 依平台組出 `systemd-run` + `bwrap` 或 `sandbox-exec` 指令；Linux 寫入 `hakorun.slice` |
| 相依檢查 | `internal/checker/` | Linux 偵測並安裝執行環境；macOS 為 no-op |
| Wrapper | `internal/resource/` | 各語言從 stdin 讀 `{code, input}` 並執行使用者程式碼 |

## 跨切原則

- 平台差異以 Go build tag 切分（`_linux.go`／`_darwin.go`），不在執行期判斷。
- 儲存後端以 build tag 切分（`!redis`／`redis`），兩者實作同一 `backend` 介面。
- 使用者程式碼一律經 stdin 傳入 wrapper，不寫入檔案系統。
- 每次執行都是新的子行程；不保留暖機行程或狀態。

## 延伸閱讀

- [完整架構圖（模組、資料流、狀態機）](https://github.com/pardnchiu/HakoRun/blob/master/doc/architecture.zh.md)
- [核心概念](/zh/core-concepts)
- [沙箱](/zh/sandbox)
