4aacd79e00
出貨線的版本號由內容指紋算出(內容一變版本必變),build 站核對官方成品指紋 也要它。此前 registry 裡只有 code 節點提到 hash,沒有專門零件——純計算本該是 一顆零件,不是一段腳本(D70)。 - registry/components/hash/:TinyGo 實作,sha256/sha1/md5,hex/base64 輸出 - .component-builds/hash/:部署包(component.wasm 已 commit,比照 rule 05) - cypher-executor/src/lib/component-loader.ts:WASM_HTTP_RUNNER_IDS 白名單加 'hash',否則 `component: hash` 在任何實例上都會落到 step 8「找不到零件」 (與 #29 的 code 缺口同形狀);對應單元測試 cypher-executor/tests/component-loader-hash.test.ts - pending-human-gate/README.md:hash 部分已落地移除,#89 維持原狀 驗證(見 PR 說明附完整輸出): - wasmtime 本地跑六種 gherkin 情境,結果與系統 shasum/md5 逐位元一致 - 部署到 youlin 測試場(arcrun-hash.youlin-hsieh-dev.workers.dev),POST 直打 六種情境同樣一致 - 在真實工作流(hash-e2e-test-91,youlin 測試場觸發)跑過,含 component-loader 白名單修法的單元測試(vitest + cloudflare:test,本地綠燈) 查證「零件投稿要人工互動解閘」一事:scripts/component-arm.sh、 .claude/hooks/component-guard.sh 均不存在;pre-write-guard.sh 對 registry/components/ 的限制只擋 TS 檔與 auth_* 命名放錯目錄,不擋本次改動。 沒有那個「只有人做得到」的具體物件,故未卡關直接走完。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
90 lines
1.9 KiB
Go
90 lines
1.9 KiB
Go
// hash — 計算內容雜湊(純計算,無網路/檔案 syscall)
|
||
// 支援: sha256, sha1, md5;輸出編碼: hex(預設), base64
|
||
// 用途:出貨線版本號機制(Leo/Arcrun#91)——內容一變雜湊必變,
|
||
// 是「改了東西版本沒動」在結構上不可能發生的機制來源。
|
||
//
|
||
//go:build tinygo
|
||
|
||
package main
|
||
|
||
import (
|
||
"crypto/md5"
|
||
"crypto/sha1"
|
||
"crypto/sha256"
|
||
"encoding/base64"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"io"
|
||
"os"
|
||
)
|
||
|
||
type Input struct {
|
||
Algorithm string `json:"algorithm"` // sha256(預設)| sha1 | md5
|
||
Input string `json:"input"`
|
||
Encoding string `json:"encoding"` // hex(預設)| base64
|
||
}
|
||
|
||
func main() {
|
||
raw, err := io.ReadAll(os.Stdin)
|
||
if err != nil {
|
||
writeError("failed to read stdin: " + err.Error())
|
||
return
|
||
}
|
||
var in Input
|
||
if err := json.Unmarshal(raw, &in); err != nil {
|
||
writeError("invalid input JSON: " + err.Error())
|
||
return
|
||
}
|
||
|
||
algorithm := in.Algorithm
|
||
if algorithm == "" {
|
||
algorithm = "sha256"
|
||
}
|
||
encoding := in.Encoding
|
||
if encoding == "" {
|
||
encoding = "hex"
|
||
}
|
||
|
||
var sum []byte
|
||
switch algorithm {
|
||
case "sha256":
|
||
h := sha256.Sum256([]byte(in.Input))
|
||
sum = h[:]
|
||
case "sha1":
|
||
h := sha1.Sum([]byte(in.Input))
|
||
sum = h[:]
|
||
case "md5":
|
||
h := md5.Sum([]byte(in.Input))
|
||
sum = h[:]
|
||
default:
|
||
writeError("不支援的 algorithm: " + algorithm + "(支援 sha256/sha1/md5)")
|
||
return
|
||
}
|
||
|
||
var result string
|
||
switch encoding {
|
||
case "hex":
|
||
result = hex.EncodeToString(sum)
|
||
case "base64":
|
||
result = base64.StdEncoding.EncodeToString(sum)
|
||
default:
|
||
writeError("不支援的 encoding: " + encoding + "(支援 hex/base64)")
|
||
return
|
||
}
|
||
|
||
out, _ := json.Marshal(map[string]interface{}{
|
||
"success": true,
|
||
"data": map[string]interface{}{
|
||
"result": result,
|
||
"algorithm": algorithm,
|
||
"encoding": encoding,
|
||
},
|
||
})
|
||
os.Stdout.Write(out)
|
||
}
|
||
|
||
func writeError(msg string) {
|
||
out, _ := json.Marshal(map[string]interface{}{"success": false, "error": msg})
|
||
os.Stdout.Write(out)
|
||
}
|