內容、Digest 與下載
前端對「位元組」的接觸只有三處:提供 source_digest、送出執行 input、下載產出物。實際的位元組搬運與持久化上傳都在控制面(見 架構)。
1. 建置內容:提供 source_digest
建立環境版本時,前端提供一個內容雜湊,宣告這份建置內容是什麼:
- 欄位:
source_digest,必填,格式^sha256:[0-9a-f]{64}$。 - 前端(或上游)在本地打包建置內容 tarball、算出
sha256,把sha256:<hex>傳進POST /environments/{id}/versions。 - 前端不會呼叫任何
init upload/ 拿上傳 capability。把位元組實際放進儲存,是控制面的事。
若產品需要「瀏覽器直接上傳建置內容」的路徑,該路徑目前不在租戶 API 內,需與後端團隊確認。
2. 執行輸入:canonical JSON
提交執行時,input 欄位是任意 JSON,但會被 canonical JSON 驗證(parse_canonical_json):
| 限制 | 值 |
|---|---|
| UTF-8 大小 | ≤ 1 MiB(MAX_INPUT_JSON_UTF8_BYTES) |
| 巢狀深度 | ≤ 64(MAX_JSON_DEPTH) |
| 節點數 | ≤ 100,000(MAX_JSON_NODES) |
| 其他 | 不可有 NUL、不可有重複 key |
超過會回 422。另外提交端點有先於讀取 body 的大小防護:Content-Length 過大直接回 413 request_too_large(不會 buffer 1 GiB body)。
3. 下載產出物:capability token,不是 URL
取一個 run 的產出物時,前端不會拿到原始 R2 key 或 presigned URL。流程是:
GET /chatrooms/{id}/runs/{run_id}/content→ 回布林旗標has_input/has_output/has_log/has_artifact_bundle(+input_digest)。只有旗標,沒有內容本體。state可能是"missing"(尚無內容列)。GET /chatrooms/{id}/runs/{run_id}/artifacts→ 列出產出物(relative_path、byte_size、digest、deletion_state、declared_content_type…)。POST /chatrooms/{id}/runs/{run_id}/artifacts/{artifact_id}/download→ 回一張短效capability_token+expires_at+content_type/content_disposition/x_content_type_options: nosniff。- 前端用這張 capability 去取實際位元組(由 capability 授權的串流層提供 range 讀取;不是可轉發的 URL)。
規則:
- 授權一律以
artifact_id(+公司/聊天室歸屬),不是 key。 deletion_state != active的產出物,download 一律 404。- capability 是短效的(
_DOWNLOAD_CAPABILITY_TTL);過期就重新換一張。
Digest 與內容定址(給要對照的人)
Owned object 的儲存 key 由後端產生、全域永不重用,形如 sandbox/{company_id}/{object_kind}/{token};object_kind ∈ context / input / output / log / artifact_bundle / report。前端拿不到、也不需要這些 key——一律以資源 id 授權。
Last updated on