// Package conversion 內部 utility helpers。 // // 此檔收容跨檔共用的小型 helper(log truncate / object key hash 等),原本散落在 // mc_token_client.go / faa_client.go;Phase 0.8b T3 砍上述兩檔後搬到此獨立檔, // 避免被連帶砍除(仍被 converter_client.go / flow.go 的 log 拼接使用)。 // // Phase 0.8b v0.6 conversion (見 ADR-016 / docs/autoflow/04-architecture/conversion.md §2) package conversion import ( "crypto/sha256" "encoding/hex" ) // objectKeyHashLen 是 log 中 object_key 的截短後 hash 長度(前 16 hex chars)。 const objectKeyHashLen = 16 // truncate 把字串截到 max 長度(避免 log 太長)。 func truncate(s string, max int) string { if len(s) <= max { return s } return s[:max] + "...(truncated)" } // hashObjectKey 把 object_key 算 SHA-256 後取前 16 hex chars,當 log 用的穩定 hash。 // // 為什麼不直接 log object_key: // - object_key 可能含路徑("tenant/jobs/uuid/output.nef")— 過長 // - 目前 visionA 的 object_key 不直接含 user 敏感資訊,但保險起見統一 hash // - 16 chars hex(64-bit)對 visionA 內部 job 數量來說碰撞機率極低,足以追蹤單一 request // // **設計約束(重要):此 hash 僅供內部 log / observability 用、不應對外暴露**。 // 具體不應: // - 出現在 HTTP response body / header(frontend 不需要、洩漏內部 storage 結構) // - 拿來組 presigned URL / download URL 的 path(hash 不可逆、不能用來定位物件) // - 寫進使用者可見的錯誤訊息(用 request_id 追蹤即可) // // 用途限定於 slog 欄位(如 `slog.String("object_key_hash", hashObjectKey(...))`), // 配合 request_id 在 log aggregator 內串接同一 NEF 物件在多個 service 之間的流向。 // // Phase 0.8b v0.6(T3):原本定義在 faa_client.go;砍 faa_client.go 時搬到 util.go // (flow.go DownloadStream / PromoteToModels 仍用 hashObjectKey 為 log 加 target_object_key // 標記,方便跨 service 追蹤同一個 NEF 物件)。 func hashObjectKey(objectKey string) string { sum := sha256.Sum256([]byte(objectKey)) return hex.EncodeToString(sum[:])[:objectKeyHashLen] }