Implements Increment 1 of `docs/superpowers/specs/2026-07-04-crucible-depot-core-design.md`: a new stdlib-only `internal/depot` package wired into the dispatcher. - `crucible depot status|push|verify|get|pull` with backends `local`/`cdn`/`bunny`; exit contract `0` clean / `1` drift / `2` unconfirmed-only / `64` usage / `70` internal. - Presence is always probed against the real target (IPv4 1-byte range GET; HEAD is banned with a regression-tripwire test). `unconfirmed` is a distinct state, never collapsed into `missing`. - No prompting anywhere: missing `BUNNY_STORAGE_*` env fails closed (read path included), enforced by a no-stdin test. - Uploads: probe-then-PUT with `Checksum: <UPPER-sha>`; read/write key split (`BUNNY_STORAGE_READ_PASSWORD` falls back to `BUNNY_STORAGE_PASSWORD`). - Field-driven fix included: per-probe transient retry (curl `--retry 2` equivalent) — without it a real 1490-blob CDN sweep reported 1222 false-unconfirmed; with it, 1490/1490 present in 74s, exit 0. - Registry: depot `Wired: true`, joins the interactive menu; stale "(SeaweedFS)" wording removed. Tests: unit + httptest fake-Bunny (probe sequence, Checksum header, key split, 428 throttling → exit 2) + local→bunny integration (drift → push → clean → idempotent no-second-PUT; incremental pull). `make check` green. **Merge ordering:** this merges FIRST; the companion `sow-assets-manifest#crucible-depot-cutover` PR needs its flake input bumped to include this. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #30 Reviewed-by: xtul <mpiasecki720@protonmail.com> Co-authored-by: vickydotbat <vickydotbat@tutamail.com> Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
package depot
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type Config struct {
|
|
CDNBase string
|
|
StorageHost string
|
|
StorageZone string
|
|
ReadKey string
|
|
WriteKey string
|
|
ProbeJobs int
|
|
Jobs int
|
|
ConnectTimeout time.Duration
|
|
ProbeMaxTime time.Duration
|
|
ConfirmRetries int
|
|
ConfirmMax int
|
|
}
|
|
|
|
func LoadConfig(getenv func(string) string) Config {
|
|
cfg := Config{
|
|
CDNBase: "https://cdn-a7f3k9.westgate.pw",
|
|
StorageZone: "sow-assets-depot",
|
|
ProbeJobs: 16,
|
|
Jobs: 16,
|
|
ConnectTimeout: 10 * time.Second,
|
|
ProbeMaxTime: 30 * time.Second,
|
|
ConfirmRetries: 3,
|
|
ConfirmMax: 200,
|
|
}
|
|
|
|
// DEPOT_CDN_BASE || BUNNY_CDN_BASE
|
|
if v := getenv("DEPOT_CDN_BASE"); v != "" {
|
|
cfg.CDNBase = v
|
|
} else if v := getenv("BUNNY_CDN_BASE"); v != "" {
|
|
cfg.CDNBase = v
|
|
}
|
|
|
|
// BUNNY_STORAGE_HOST (no default)
|
|
cfg.StorageHost = getenv("BUNNY_STORAGE_HOST")
|
|
|
|
// BUNNY_STORAGE_ZONE (default "sow-assets-depot")
|
|
if v := getenv("BUNNY_STORAGE_ZONE"); v != "" {
|
|
cfg.StorageZone = v
|
|
}
|
|
|
|
// BUNNY_STORAGE_PASSWORD
|
|
cfg.WriteKey = getenv("BUNNY_STORAGE_PASSWORD")
|
|
|
|
// BUNNY_STORAGE_READ_PASSWORD || BUNNY_STORAGE_PASSWORD
|
|
if v := getenv("BUNNY_STORAGE_READ_PASSWORD"); v != "" {
|
|
cfg.ReadKey = v
|
|
} else {
|
|
cfg.ReadKey = cfg.WriteKey
|
|
}
|
|
|
|
// DEPOT_PROBE_JOBS (default 16)
|
|
if v := getenv("DEPOT_PROBE_JOBS"); v != "" {
|
|
if i, err := strconv.Atoi(v); err == nil {
|
|
cfg.ProbeJobs = i
|
|
}
|
|
}
|
|
|
|
// DEPOT_JOBS (default 16)
|
|
if v := getenv("DEPOT_JOBS"); v != "" {
|
|
if i, err := strconv.Atoi(v); err == nil {
|
|
cfg.Jobs = i
|
|
}
|
|
}
|
|
|
|
// DEPOT_CONNECT_TIMEOUT (default 10s)
|
|
if v := getenv("DEPOT_CONNECT_TIMEOUT"); v != "" {
|
|
if d, err := time.ParseDuration(v + "s"); err == nil {
|
|
cfg.ConnectTimeout = d
|
|
}
|
|
}
|
|
|
|
// DEPOT_PROBE_MAX_TIME (default 30s)
|
|
if v := getenv("DEPOT_PROBE_MAX_TIME"); v != "" {
|
|
if d, err := time.ParseDuration(v + "s"); err == nil {
|
|
cfg.ProbeMaxTime = d
|
|
}
|
|
}
|
|
|
|
// DEPOT_CONFIRM_RETRIES (default 3)
|
|
if v := getenv("DEPOT_CONFIRM_RETRIES"); v != "" {
|
|
if i, err := strconv.Atoi(v); err == nil {
|
|
cfg.ConfirmRetries = i
|
|
}
|
|
}
|
|
|
|
// DEPOT_CONFIRM_MAX (default 200, 0 = unlimited)
|
|
if v := getenv("DEPOT_CONFIRM_MAX"); v != "" {
|
|
if i, err := strconv.Atoi(v); err == nil {
|
|
cfg.ConfirmMax = i
|
|
}
|
|
}
|
|
|
|
return cfg
|
|
}
|