營運與 Root
這頁給 root/營運,不是產品前端。租戶 JWT(get_sandbox_principal)打不到這裡。產品 UI 該讀的是 角色與權限 與 API 端點目錄。
路徑前綴:{BASE}/root/sandbox。認證是 operator auth(get_super_root_key),不是租戶 JWT。
變更類操作必須帶有型別的 reason(8–1024 字元)、寫入 SandboxAuditLog,且永不回傳租戶 secret 值或客戶內容原文。V1 沒有 Binary Authorization break-glass 路由。
滾動/回滾/gate 的完整契約在後端 docs/runbooks/sandbox-operations.md。本頁不複製那份 runbook。
誰擁有什麼
| 表面 | 擁有者 | 產品前端 |
|---|---|---|
| 區域目錄與狀態(註冊/啟用/抽乾/停用/backfill/reconcile) | root | 否 |
| 配額 snapshot 與 preflight | root | 否 |
| 系統策展環境與版本 | root | 租戶可讀/釘策展版本;不可建立或發布 |
| 精確 digest 封鎖與時限例外 | root | 否 |
| 公司離場圍欄(arm/cancel) | root | 否 |
公司設定:保留天數、allowed_regions、policy_version CAS | 租戶 company manager(GET/PUT /settings) | 是 |
| 環境/任務/綁定/secret/執行 | 租戶管理者(見 角色與權限) | 是 |
allowed_regions 只管執行期 Job/Execution 放置,不管建置、validator、Artifact Registry、R2、日誌或控制面駐留。產品 UI 的封閉 V1 確認集合是 GET /public/info/sandbox/regions — 再與租戶 allowed_regions 取交集。不要把 /root/sandbox/regions 當前端目錄。
Kill switch 與「租戶自建其實發不出去」
這是兩件不同的事,不要混成一個開關。
SANDBOX_ENABLED預設true。false才是營運 kill switch。它擋新的租戶管理/提交/派送;GET 狀態、取消、下載、以及控制面 reconcile 仍可用。租戶面回 503sandbox_disabled。tenant_custom_build_enabled不是獨立開關。GET /status從「模組是否開啟 × 是否有 active 區域 × 是否有已確認的區域 Job 定義配額 snapshot」推導。缺區域配額時,有效版本 cap 為 0,租戶發布被拒,錯誤碼 409version_allocation_exhausted。營運看到enabled: false該看blocked_by,不要去找一個不存在的 flag。
blocked_by 可能是:sandbox_disabled、no_active_region、no_confirmed_regional_job_quota。能發布時為空。
GET /status
回報:
sandbox_enabledtenant_custom_build_enabled(上述推導值)blocked_by[]active_regionsregions_with_job_definition_quotagates(live 監督 gates,目前pending)live_proof(目前"pending")break_glass_routes(固定false)
端點目錄
以下 27 條掛在 /root/sandbox。變更類 POST/PUT 帶 reason;本表不展開 request body。
| 方法 | 路徑 | 用途 |
|---|---|---|
GET | /status | Kill switch 與租戶自建是否真能發布 |
GET | /regions | 列區域 |
POST | /regions | 註冊區域(進入 provisioning)。tier 1..3,但 tier 3 只接受地端部署上的 region_code=onprem(其餘回 422) |
POST | /regions/{region_code}/activate | 啟用已就緒區域 |
POST | /regions/{region_code}/drain | 抽乾(擋住新 attempt) |
POST | /regions/{region_code}/disable | 在 reconcile 後停用 |
POST | /regions/{region_code}/backfill | 接受區域 Job backfill 意圖 |
POST | /regions/{region_code}/reconcile | 接受區域 reconcile 意圖(kill switch 下仍保留) |
POST | /quota-preflight | 本地殘差調整後的配額 preflight(不打 provider) |
POST | /quota-snapshots/refresh | 讀 live provider 上限並寫入 snapshot(讓版本 cap 變成正數的那條) |
GET | /quota-snapshots/refreshes/{refresh_id} | 讀取單次 provider 容量 refresh 的持久化狀態(POST /quota-snapshots/refresh 只寫入意圖,用這條輪詢結果) |
GET | /curated-environments | 列系統策展環境 |
POST | /curated-environments | 建立策展環境身分(尚無版本) |
POST | /curated-environments/{environment_id}/versions | 以營運提供的 digest 發布策展版本 |
GET | /curated-environments/{environment_id}/versions | 列該策展環境的版本 |
POST | /security/blocks | 封鎖一個精確映像 digest |
POST | /security/exceptions | 對精確 digest finding 給時限例外 |
POST | /security/exceptions/{exception_id}/revoke | 撤銷例外 |
GET | /companies/{company_id}/offboarding | 讀離場 ticket 與圍欄狀態 |
POST | /companies/{company_id}/offboarding/arm | 武裝真正的離場圍欄 |
POST | /companies/{company_id}/offboarding/cancel | 在尚未做破壞性工作時解除圍欄 |
GET | /companies/{company_id}/policy | 讀取公司的 Sandbox 政策上限(可能建立預設列) |
PUT | /companies/{company_id}/policy | 部分更新這些上限並寫入稽核(環境/版本/run/建置上限、保留天數、逾時上限、exposure、執行期對外網路) |
GET | /queue | **v5.10.11。**依服務順序列出等待(或剛開始佔用)run slot 的工作,以及每個 executor 最後回報的容量。每種部署都是同一路由、同一形狀;雲端的 executors 為空 |
GET | /runner-releases | 後端 ≥ #1162。 已核准跑 task-bundle 的 runner release(表列 + 環境變數 bootstrap 集合 + 生效聯集) |
POST | /runner-releases | 核准一個 runner release(release_sha = 40 hex 的 stage image 來源 commit)。下一個請求即生效、不用重啟;冪等 |
DELETE | /runner-releases/{release_sha} | 撤銷;該 runner 上的 bundle 執行在下一個請求就回 409 task_bundle_runner_unsupported |
Runner release 核准(後端 ≥ #1162)
任務 bundle(隨任務出貨的客戶程式碼)只能在 runner_release(烘進合成映像的 stage image 來源 commit)已核准的環境上執行。核准存在 sandbox_runner_release_approvals 表,每次發佈/執行請求都會讀,所以 POST/DELETE /runner-releases 立即生效。stage image 發佈流程在 controller rollout 成功後會自動核准自己的 commit,新的 runner release 不再讓新建的環境拒絕 bundle 工作。環境變數 SANDBOX_TASK_BUNDLE_RUNNER_RELEASES 只是 bootstrap 備援,正在清空。版本回應多了 runner_release_approved + runner_release_next_action。
地端 provider(v5.10.11)
自架部署設定 SANDBOX_PROVIDER=onprem(空白或 gcp = 託管雲端;其他值會被拒絕)。以下僅供營運參考;租戶可見的差異見雲端與地端部署。安裝套件與 runbook 在後端的 docs/deployment/on-prem/。
- **喚醒與驗證。**地端的
SANDBOX_CONTROL_WAKE預設poll(雲端預設pubsub,且 controller 會拒絕poll);SANDBOX_EXECUTION_AUTH預設onprem_token(executor token),取代gcp_oidc。 - **區域與價格。**地端 poll-mode controller 會建立一個 active 的
onprem區域(tier 3)。名目費率來自SANDBOX_ONPREM_PRICE_CPU_USD_PER_VCPU_SECOND/SANDBOX_ONPREM_PRICE_MEMORY_USD_PER_GIB_SECOND(預設0.000001,必須 > 0)。 - **Executor。**Docker executor 從
/sandbox-control/onprem/work/*(只在地端掛載)領取 run 與建置關卡,每次領取請求都回報剩餘與總 slot 數;佇列預估時間以整個 fleet 的 run slot 數去除。 - 佇列政策。
SANDBOX_ONPREM_MAX_QUEUED_PER_COMPANY(預設 20)與SANDBOX_ONPREM_MAX_QUEUED(預設 200)限制等待中的 run(租戶端 429)。排隊超過SANDBOX_ONPREM_QUEUE_TIMEOUT_SECONDS(預設 3600,最小 60)仍未執行的 run,會被 controller 的佇列 sweeper 判定失敗。GET /root/sandbox/queue顯示佇列的lease_id、priority(0 緊急、1 Quick Run、2 run、3 建置)、vcpu、mem_mib與各 executor 容量。 - 網路與信任。
SANDBOX_ONPREM_EGRESS(預設none,或internet)決定主機上的執行期對外網路。SANDBOX_ONPREM_TENANT_API_ORIGIN只讓部署自己的 API origin 穿過 executor 的網路圍欄,SANDBOX_ONPREM_TENANT_CA_FILE讓租戶容器取得含主機憑證的信任憑證庫。 - **容量更新(v5.21.0)。**controller 的 provider 容量更新,以及
GET /quota-snapshots/refreshes/{refresh_id},會把快照範圍限定在所選的 provider:地端部署是別名onprem(不需要 GCP project),託管雲端是設定好的 sandbox GCP project;在託管雲端,該 project 缺少或格式不對時,狀態路由仍回 409sandbox_gcp_project_unset/sandbox_gcp_project_invalid。 - **建置。**同一條十關建置流程改由 executor 執行;弱點掃描使用
SANDBOX_ONPREM_SCAN(預設trivy),本機 registry 上的簽章與 Binary Authorization 會記為not_applicable。
控制面(人不要打)
/sandbox-control/* 是系統對系統的 OIDC + capability,include_in_schema=False。人不要呼叫。地端的 executor 以地端 executor token 驗證,取代 Google OIDC。