feat(admin): add atomic task claim leases

This commit is contained in:
QiuSW
2026-08-04 22:33:16 +08:00
parent 526af1eb31
commit 5f060f60ee
20 changed files with 2923 additions and 49 deletions
+29
View File
@@ -2,6 +2,8 @@
package config
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"os"
@@ -23,6 +25,8 @@ const (
maxTaskQuantityEnv = "CMBUYER_MAX_TASK_QUANTITY"
maxTotalPriceEnv = "CMBUYER_MAX_TOTAL_PRICE"
evidenceDirectoryEnv = "CMBUYER_EVIDENCE_DIR"
claimTokenSecretEnv = "CMBUYER_CLAIM_TOKEN_SECRET"
claimLeaseTTLEnv = "CMBUYER_CLAIM_LEASE_TTL"
minimumSecretLength = 32
)
@@ -37,6 +41,8 @@ type Config struct {
MaxTaskQuantity int
MaxTotalPrice string
EvidenceDirectory string
ClaimTokenSecret []byte
ClaimLeaseTTL time.Duration
}
// LoadFromEnv 从进程环境读取配置。错误只指出缺失或非法的变量名,绝不回显秘密。
@@ -112,6 +118,27 @@ func Load(lookup func(string) (string, bool)) (Config, error) {
if strings.TrimSpace(evidenceDirectory) != evidenceDirectory || !filepath.IsAbs(evidenceDirectory) {
return Config{}, fmt.Errorf("%s must be an absolute path without surrounding whitespace", evidenceDirectoryEnv)
}
claimSecretText, err := required(lookup, claimTokenSecretEnv)
if err != nil {
return Config{}, err
}
claimSecret, err := hex.DecodeString(claimSecretText)
if err != nil || len(claimSecret) != 32 || hex.EncodeToString(claimSecret) != claimSecretText {
return Config{}, fmt.Errorf("%s must be exactly 64 lowercase hexadecimal characters", claimTokenSecretEnv)
}
// Claim ownership, admin sessions and device authentication are separate security domains.
// Reject both identical configuration text and identical effective key bytes.
if claimSecretText == secret || bytes.Equal(claimSecret, []byte(secret)) {
return Config{}, fmt.Errorf("%s must be isolated from %s", claimTokenSecretEnv, sessionSecretEnv)
}
claimTTLText, err := required(lookup, claimLeaseTTLEnv)
if err != nil {
return Config{}, err
}
claimTTL, err := time.ParseDuration(claimTTLText)
if err != nil || claimTTL <= 0 || claimTTL >= ttl {
return Config{}, fmt.Errorf("%s must be positive and shorter than %s", claimLeaseTTLEnv, authorizationTTLEnv)
}
return Config{
AdminUsername: username,
@@ -121,6 +148,8 @@ func Load(lookup func(string) (string, bool)) (Config, error) {
DatabaseSource: databaseSource,
AuthorizationTTL: ttl, MaxTaskQuantity: maxQuantity, MaxTotalPrice: maxPrice,
EvidenceDirectory: evidenceDirectory,
ClaimTokenSecret: claimSecret,
ClaimLeaseTTL: claimTTL,
}, nil
}