From 1e424c51b75367a98629589a272ed45b100b0487 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 01:57:27 +0200 Subject: [PATCH 01/16] chore(deps): pin go-libp2p to libp2p/go-libp2p#3509 Picks up websocket.WithFallbackHTTPHandler so a /ws or /tls/ws listener can serve a caller-supplied http.Handler for non-upgrade requests. Required by the HTTPProvider feature in subsequent commits. --- docs/examples/kubo-as-a-library/go.mod | 2 +- docs/examples/kubo-as-a-library/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- test/dependencies/go.mod | 2 +- test/dependencies/go.sum | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index 278e1fe8ca3..a9a20a4df0f 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -9,7 +9,7 @@ replace github.com/ipfs/kubo => ./../../.. require ( github.com/ipfs/boxo v0.39.1-0.20260515000232-c8708232456f github.com/ipfs/kubo v0.0.0-00010101000000-000000000000 - github.com/libp2p/go-libp2p v0.48.0 + github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 github.com/multiformats/go-multiaddr v0.16.1 ) diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index adfa657ccf5..ccd9aee912e 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -488,8 +488,8 @@ github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZ github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784= github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= -github.com/libp2p/go-libp2p v0.48.0 h1:h2BrLAgrj7X8bEN05K7qmrjpNHYA+6tnsGRdprjTnvo= -github.com/libp2p/go-libp2p v0.48.0/go.mod h1:Q1fBZNdmC2Hf82husCTfkKJVfHm2we5zk+NWmOGEmWk= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 h1:OhAw63jluTw3tAXLJklhZF0bkjULKo3wABYGcfzFytg= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088/go.mod h1:+zGTonNiePk+PlraDn51k+8grAbHh9df7IIAVOMwqZo= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= diff --git a/go.mod b/go.mod index 4b260cadc17..3d1c957e28e 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/julienschmidt/httprouter v1.3.0 github.com/libp2p/go-doh-resolver v0.5.0 - github.com/libp2p/go-libp2p v0.48.0 + github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 github.com/libp2p/go-libp2p-http v0.5.0 github.com/libp2p/go-libp2p-kad-dht v0.39.3-0.20260513140308-b73e1e814f5f github.com/libp2p/go-libp2p-kbucket v0.8.0 diff --git a/go.sum b/go.sum index b4d0b0dae9e..3b050054551 100644 --- a/go.sum +++ b/go.sum @@ -539,8 +539,8 @@ github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZ github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784= github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= -github.com/libp2p/go-libp2p v0.48.0 h1:h2BrLAgrj7X8bEN05K7qmrjpNHYA+6tnsGRdprjTnvo= -github.com/libp2p/go-libp2p v0.48.0/go.mod h1:Q1fBZNdmC2Hf82husCTfkKJVfHm2we5zk+NWmOGEmWk= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 h1:OhAw63jluTw3tAXLJklhZF0bkjULKo3wABYGcfzFytg= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088/go.mod h1:+zGTonNiePk+PlraDn51k+8grAbHh9df7IIAVOMwqZo= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index cf3632e7fd4..c49b42405c7 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -181,7 +181,7 @@ require ( github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-doh-resolver v0.5.0 // indirect github.com/libp2p/go-flow-metrics v0.3.0 // indirect - github.com/libp2p/go-libp2p v0.48.0 // indirect + github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-libp2p-kad-dht v0.39.3-0.20260513140308-b73e1e814f5f // indirect github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index e0790627c1f..c1c6046853a 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -578,8 +578,8 @@ github.com/libp2p/go-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+s github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU= github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784= github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= -github.com/libp2p/go-libp2p v0.48.0 h1:h2BrLAgrj7X8bEN05K7qmrjpNHYA+6tnsGRdprjTnvo= -github.com/libp2p/go-libp2p v0.48.0/go.mod h1:Q1fBZNdmC2Hf82husCTfkKJVfHm2we5zk+NWmOGEmWk= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 h1:OhAw63jluTw3tAXLJklhZF0bkjULKo3wABYGcfzFytg= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088/go.mod h1:+zGTonNiePk+PlraDn51k+8grAbHh9df7IIAVOMwqZo= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-kad-dht v0.39.3-0.20260513140308-b73e1e814f5f h1:PH/bOCidYs4UHu3EtHxqQvxMyWHMMXeSJUlM4wcpK28= From fd7c9350bad3a7c72724869852a7cfea321120b7 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 02:06:26 +0200 Subject: [PATCH 02/16] refactor(httpprovider): rename WSSFallback, add config, deprecate old flag Renames the lazy fallback handler from WSSFallback to HTTPProvider across the kubo tree. The new name reflects the role this peer plays on the network: an HTTP-native source for trustless-gateway block retrieval, discoverable through identify/DHT alongside libp2p transports. - new HTTPProvider config struct with Enabled/Libp2p/Cleartext/ AnnounceMultiaddrs flags and matching Default* constants - IpfsNode.WSSFallback field, FX param, file/struct/test renames; the libp2p-stream gateway function becomes serveHTTPProviderOverLibp2p - Experimental.GatewayOverLibp2p marked deprecated; daemon refuses to start when it is set, with a one-line migration error pointing at HTTPProvider.Enabled and HTTPProvider.Libp2p - libp2p-stream gateway gating switches from the deprecated flag to HTTPProvider.{Enabled,Libp2p} - test/cli/http_gateway_over_libp2p_test.go renamed to http_provider_over_libp2p_test.go, subtests + config keys updated to match the new naming --- cmd/ipfs/kubo/daemon.go | 22 +++++- config/config.go | 1 + config/experiments.go | 2 +- config/httpprovider.go | 73 +++++++++++++++++++ core/core.go | 6 ++ core/node/groups.go | 10 +++ core/node/libp2p/httpprovider.go | 46 ++++++++++++ core/node/libp2p/httpprovider_test.go | 54 ++++++++++++++ core/node/libp2p/transport.go | 22 ++++-- ...t.go => http_provider_over_libp2p_test.go} | 14 +++- 10 files changed, 235 insertions(+), 15 deletions(-) create mode 100644 config/httpprovider.go create mode 100644 core/node/libp2p/httpprovider.go create mode 100644 core/node/libp2p/httpprovider_test.go rename test/cli/{http_gateway_over_libp2p_test.go => http_provider_over_libp2p_test.go} (86%) diff --git a/cmd/ipfs/kubo/daemon.go b/cmd/ipfs/kubo/daemon.go index 25a50c64539..cd4e8d6a692 100644 --- a/cmd/ipfs/kubo/daemon.go +++ b/cmd/ipfs/kubo/daemon.go @@ -398,6 +398,17 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment return err } + // Reject the removed Experimental.GatewayOverLibp2p flag at startup so + // stale configs surface a clear migration error instead of silently + // running the wrong feature set. + if cfg.Experimental.GatewayOverLibp2p { + return errors.New( + "Experimental.GatewayOverLibp2p has been removed. " + + "Set HTTPProvider.Enabled=true and HTTPProvider.Libp2p=true instead, " + + "then unset Experimental.GatewayOverLibp2p.", + ) + } + // Validate autoconf setup - check for private network conflict swarmKey, _ := repo.SwarmKey() isPrivateNetwork := swarmKey != nil || pnet.ForcePrivateNetwork @@ -696,7 +707,7 @@ take effect. } // add trustless gateway over libp2p - p2pGwErrc, err := serveTrustlessGatewayOverLibp2p(cctx) + p2pGwErrc, err := serveHTTPProviderOverLibp2p(cctx) if err != nil { return err } @@ -1167,17 +1178,20 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e const gatewayProtocolID protocol.ID = "/ipfs/gateway" // FIXME: specify https://github.com/ipfs/specs/issues/433 -func serveTrustlessGatewayOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { +func serveHTTPProviderOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { node, err := cctx.ConstructNode() if err != nil { - return nil, fmt.Errorf("serveHTTPGatewayOverLibp2p: ConstructNode() failed: %s", err) + return nil, fmt.Errorf("serveHTTPProviderOverLibp2p: ConstructNode() failed: %s", err) } cfg, err := node.Repo.Config() if err != nil { return nil, fmt.Errorf("could not read config: %w", err) } - if !cfg.Experimental.GatewayOverLibp2p { + // Gate on HTTPProvider.Enabled and the libp2p sub-toggle. + enableHTTPProvider := cfg.HTTPProvider.Enabled.WithDefault(config.DefaultHTTPProviderEnabled) + enableLibp2pStream := cfg.HTTPProvider.Libp2p.WithDefault(config.DefaultHTTPProviderLibp2p) + if !enableHTTPProvider || !enableLibp2pStream { errCh := make(chan error) close(errCh) return errCh, nil diff --git a/config/config.go b/config/config.go index 0952e0d3173..c24c52b9086 100644 --- a/config/config.go +++ b/config/config.go @@ -39,6 +39,7 @@ type Config struct { Provider Provider // Deprecated: use Provide. Will be removed in a future release. Reprovider Reprovider // Deprecated: use Provide. Will be removed in a future release. HTTPRetrieval HTTPRetrieval + HTTPProvider HTTPProvider Experimental Experiments Plugins Plugins Pinning Pinning diff --git a/config/experiments.go b/config/experiments.go index 6c43ac04f07..a635420781d 100644 --- a/config/experiments.go +++ b/config/experiments.go @@ -9,7 +9,7 @@ type Experiments struct { StrategicProviding bool `json:",omitempty"` // removed, use Provider.Enabled instead OptimisticProvide bool OptimisticProvideJobsPoolSize int - GatewayOverLibp2p bool `json:",omitempty"` + GatewayOverLibp2p bool `json:",omitempty"` // Deprecated: use HTTPProvider.Enabled instead. GraphsyncEnabled graphsyncEnabled `json:",omitempty"` AcceleratedDHTClient experimentalAcceleratedDHTClient `json:",omitempty"` diff --git a/config/httpprovider.go b/config/httpprovider.go new file mode 100644 index 00000000000..b55fb3af9d3 --- /dev/null +++ b/config/httpprovider.go @@ -0,0 +1,73 @@ +package config + +// HTTPProvider configures kubo's role as an HTTP-native source of +// trustless-gateway block retrieval. When Enabled, the local trustless +// gateway handler (NoFetch, raw blocks + CARs only, content-addressed +// verification client-side) is exposed for HTTP retrieval clients such as +// boxo/bitswap/network/httpnet. +// +// This is the server side of the HTTP retrieval story; the client side +// lives separately and is configured under HTTPRetrieval. +type HTTPProvider struct { + // Enabled is the master switch. Default: false. When true (and other + // prerequisites are met), the trustless gateway handler is registered + // and the transport sub-toggles default to true unless explicitly set + // to false. + Enabled Flag `json:",omitempty"` + + // Libp2p exposes the trustless gateway over a libp2p stream, as + // specified by the libp2p Gateway spec + // (https://specs.ipfs.tech/http-gateways/libp2p-gateway/). The + // handler is mounted under the /ipfs/gateway protocol ID and + // advertised via .well-known/libp2p/protocols on the libp2p+HTTP + // host. Default: true when Enabled is true. + Libp2p Flag `json:",omitempty"` + + // Cleartext auto-appends a plaintext /ws listener to each /tcp/N + // already in Addresses.Swarm, unless a cleartext /ws listener is + // already present. The new /ws shares the existing TCP port via the + // shared-TCP demuxer, so no extra socket is opened. + // + // Intended for deployments where the operator handles TLS termination + // for /ws and /http themselves, typically a reverse proxy (Caddy, + // Traefik, nginx, etc.) sitting in front of kubo and forwarding either + // HTTP/1.1 or HTTP/2 cleartext (h2c) to this node. With AutoTLS, kubo + // already serves /tls/ws and /tls/http directly with a Let's Encrypt + // cert, so adding a cleartext path is unnecessary and would expose the + // trustless gateway and WebSocket upgrade unencrypted on the public + // network. Off by default for that reason; flip it on knowingly. + // + // The corresponding network advertisement (/http multiaddr beside + // /ws) is controlled by AnnounceMultiaddrs. + // + // Default: false. + Cleartext Flag `json:",omitempty"` + + // AnnounceMultiaddrs derives an HTTP-flavored multiaddr from each of + // this peer's WebSocket listeners and includes it in the announced + // address set: /ws -> /http, /tls/ws -> /tls/http, + // /tls/sni//ws -> /tls/sni//http. The HTTP endpoint shares + // the same TCP port and TLS certificate as the WebSocket listener, so + // this is purely an announcement (no extra socket is opened). Lets + // HTTP retrieval clients (e.g. boxo/bitswap/network/httpnet) discover + // this peer as an HTTP source through identify, the DHT, and IPNI + // without any out-of-band knowledge. + // + // Subject to Addresses.NoAnnounce filters, just like every other + // announced multiaddr. + // + // Default: true when Enabled is true. + AnnounceMultiaddrs Flag `json:",omitempty"` +} + +// HTTPProvider defaults. The master switch is off; when on, the libp2p +// transport and the network advertisement default to on (zero-config +// "be discoverable as an HTTP source for what's already exposed"), while +// the cleartext path stays off and must be flipped on explicitly. See +// the per-field doc comments for why. +const ( + DefaultHTTPProviderEnabled = false + DefaultHTTPProviderLibp2p = true + DefaultHTTPProviderCleartext = false + DefaultHTTPProviderAnnounceMultiaddrs = true +) diff --git a/core/core.go b/core/core.go index 5f37c287116..9dda377bef7 100644 --- a/core/core.go +++ b/core/core.go @@ -122,6 +122,12 @@ type IpfsNode struct { P2P *p2p.P2P `optional:"true"` + // HTTPProvider receives the trustless gateway handler that the WebSocket + // transport routes non-WebSocket requests to. Set when HTTPProvider and + // AutoTLS are both enabled. See + // `cmd/ipfs/kubo/daemon.go:serveHTTPProviderOverLibp2p`. + HTTPProvider *libp2p.HTTPProviderHandler `optional:"true"` + ctx context.Context stop func() error diff --git a/core/node/groups.go b/core/node/groups.go index 62aa463d5e5..e5aa5562bd7 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -120,6 +120,8 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part enableRelayClient := cfg.Swarm.RelayClient.Enabled.WithDefault(enableRelayTransport) enableAutoTLS := cfg.AutoTLS.Enabled.WithDefault(config.DefaultAutoTLSEnabled) enableAutoWSS := cfg.AutoTLS.AutoWSS.WithDefault(config.DefaultAutoWSS) + // HTTPProvider master switch. + enableHTTPProvider := cfg.HTTPProvider.Enabled.WithDefault(config.DefaultHTTPProviderEnabled) atlsLog := log.Logger("autotls") // Log error when relay subsystem could not be initialized due to missing dependency @@ -200,6 +202,14 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part fx.Provide(libp2p.ResourceManager(bcfg.Repo.Path(), cfg.Swarm, userResourceOverrides)), maybeProvide(libp2p.P2PForgeCertMgr(bcfg.Repo.Path(), cfg.AutoTLS, atlsLog), enableAutoTLS), maybeInvoke(libp2p.StartP2PAutoTLS, enableAutoTLS), + // When HTTPProvider is enabled, register a placeholder fallback + // handler so the WebSocket transport can route non-upgrade requests + // on every /ws or /tls/ws listener to the trustless gateway. The + // real handler is installed by daemon.go once IpfsNode is up. The + // gate is intentionally independent of AutoTLS because cleartext + // /ws (manual or HTTPProvider.Cleartext-derived) needs the handler + // too. + maybeProvide(libp2p.NewHTTPProviderHandler, enableHTTPProvider), fx.Provide(libp2p.AddrFilters(cfg.Swarm.AddrFilters)), fx.Invoke(libp2p.MonitorDeadListeners(cfg.Swarm.AddrFilters, cfg.Addresses.NoAnnounce)), fx.Provide(libp2p.AddrsFactory(cfg.Addresses.Announce, cfg.Addresses.AppendAnnounce, cfg.Addresses.NoAnnounce)), diff --git a/core/node/libp2p/httpprovider.go b/core/node/libp2p/httpprovider.go new file mode 100644 index 00000000000..50f9eeec607 --- /dev/null +++ b/core/node/libp2p/httpprovider.go @@ -0,0 +1,46 @@ +package libp2p + +import ( + "net/http" + "sync/atomic" +) + +// HTTPProviderHandler is an http.Handler whose target can be set after the +// libp2p host is constructed. We need this because the WebSocket transport +// option is wired into the host at FX init time (before *core.IpfsNode and +// the trustless gateway handler exist), but the handler we want to expose +// behind the AutoTLS cert is only available later, once IpfsNode is up. +// +// Used by the HTTPProvider feature that exposes the trustless gateway +// (NoFetch, raw blocks + CAR only) on the same TCP port as the /tls/ws +// AutoWSS listener. See `cmd/ipfs/kubo/daemon.go:serveHTTPProviderOverLibp2p` +// for the install site. +// +// Until Set is called, the handler responds 503 Service Unavailable, which +// is the correct signal for the small race between Accept and handler-install +// during daemon startup. +type HTTPProviderHandler struct { + target atomic.Pointer[http.Handler] +} + +// NewHTTPProviderHandler returns an empty handler. Call Set once the real +// handler is built. +func NewHTTPProviderHandler() *HTTPProviderHandler { + return &HTTPProviderHandler{} +} + +// Set installs the handler that should serve incoming non-WebSocket requests. +// Safe to call concurrently with ServeHTTP. +func (l *HTTPProviderHandler) Set(h http.Handler) { + l.target.Store(&h) +} + +// ServeHTTP forwards to the installed handler, or returns 503 if none has been +// installed yet. +func (l *HTTPProviderHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if h := l.target.Load(); h != nil { + (*h).ServeHTTP(w, r) + return + } + http.Error(w, "gateway not ready yet", http.StatusServiceUnavailable) +} diff --git a/core/node/libp2p/httpprovider_test.go b/core/node/libp2p/httpprovider_test.go new file mode 100644 index 00000000000..10d14844d54 --- /dev/null +++ b/core/node/libp2p/httpprovider_test.go @@ -0,0 +1,54 @@ +package libp2p + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" +) + +func TestHTTPProviderHandler_Unset(t *testing.T) { + fb := NewHTTPProviderHandler() + rec := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodGet, "/", nil) + + fb.ServeHTTP(rec, req) + + if rec.Code != http.StatusServiceUnavailable { + t.Fatalf("want 503 before Set, got %d", rec.Code) + } +} + +func TestHTTPProviderHandler_Set(t *testing.T) { + fb := NewHTTPProviderHandler() + fb.Set(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusTeapot) + _, _ = io.WriteString(w, "served") + })) + + rec := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodGet, "/x", nil) + fb.ServeHTTP(rec, req) + + if rec.Code != http.StatusTeapot { + t.Fatalf("want 418 after Set, got %d", rec.Code) + } + if got := rec.Body.String(); got != "served" { + t.Fatalf("unexpected body: %q", got) + } +} + +// TestHTTPProviderHandler_Reset confirms Set replaces the previous handler; +// useful in case the gateway needs to be swapped during reconfiguration. +func TestHTTPProviderHandler_Reset(t *testing.T) { + fb := NewHTTPProviderHandler() + fb.Set(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(200) })) + fb.Set(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(500) })) + + rec := httptest.NewRecorder() + fb.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil)) + if rec.Code != 500 { + t.Fatalf("want second handler (500), got %d", rec.Code) + } +} + diff --git a/core/node/libp2p/transport.go b/core/node/libp2p/transport.go index 62ff907043b..e434bd92e05 100644 --- a/core/node/libp2p/transport.go +++ b/core/node/libp2p/transport.go @@ -20,8 +20,9 @@ import ( func Transports(tptConfig config.Transports) any { return func(params struct { fx.In - Fprint PNetFingerprint `optional:"true"` - ForgeMgr *client.P2PForgeCertMgr `optional:"true"` + Fprint PNetFingerprint `optional:"true"` + ForgeMgr *client.P2PForgeCertMgr `optional:"true"` + HTTPProvider *HTTPProviderHandler `optional:"true"` }, ) (opts Libp2pOpts, err error) { privateNetworkEnabled := params.Fprint != nil @@ -34,11 +35,20 @@ func Transports(tptConfig config.Transports) any { } if wsEnabled { - if params.ForgeMgr == nil { - opts.Opts = append(opts.Opts, libp2p.Transport(websocket.New)) - } else { - opts.Opts = append(opts.Opts, libp2p.Transport(websocket.New, websocket.WithTLSConfig(params.ForgeMgr.TLSConfig()))) + var wsOpts []any + if params.ForgeMgr != nil { + wsOpts = append(wsOpts, websocket.WithTLSConfig(params.ForgeMgr.TLSConfig())) + } + // HTTPProvider: when the master switch is on (and AutoTLS is on), + // expose the trustless gateway handler on the same TCP port as + // /tls/ws by routing non-WebSocket requests to a fallback handler. + // The handler itself is wired post-construction by daemon.go + // because it needs the fully constructed *core.IpfsNode. + // See HTTPProviderHandler. + if params.HTTPProvider != nil { + wsOpts = append(wsOpts, websocket.WithFallbackHTTPHandler(params.HTTPProvider)) } + opts.Opts = append(opts.Opts, libp2p.Transport(websocket.New, wsOpts...)) } if tcpEnabled && wsEnabled && os.Getenv("LIBP2P_TCP_MUX") != "false" { diff --git a/test/cli/http_gateway_over_libp2p_test.go b/test/cli/http_provider_over_libp2p_test.go similarity index 86% rename from test/cli/http_gateway_over_libp2p_test.go rename to test/cli/http_provider_over_libp2p_test.go index 58ab0217ba0..c6f11fc3ec6 100644 --- a/test/cli/http_gateway_over_libp2p_test.go +++ b/test/cli/http_provider_over_libp2p_test.go @@ -19,7 +19,12 @@ import ( "github.com/stretchr/testify/require" ) -func TestGatewayOverLibp2p(t *testing.T) { +// TestHTTPProviderOverLibp2p exercises the libp2p-stream transport of the +// HTTPProvider feature: the trustless gateway handler reachable via the +// /ipfs/gateway protocol over a libp2p stream. The peer hosting the data +// also mounts an HTTP-to-libp2p proxy listener so requests can be made by +// stock HTTP clients. +func TestHTTPProviderOverLibp2p(t *testing.T) { t.Parallel() nodes := harness.NewT(t).NewNodes(2).Init() @@ -58,13 +63,14 @@ func TestGatewayOverLibp2p(t *testing.T) { p2pProxyNodeHTTPListenAddr, err := manet.ToNetAddr(p2pProxyNodeHTTPListenMA) require.NoError(t, err) - t.Run("DoesNotWorkWithoutExperimentalConfig", func(t *testing.T) { + t.Run("DoesNotWorkWithoutHTTPProvider", func(t *testing.T) { _, err := http.Get(fmt.Sprintf("http://%s/ipfs/%s?format=raw", p2pProxyNodeHTTPListenAddr, cidDataOnGatewayNode)) require.Error(t, err) }) - // Enable the experimental feature and reconnect the nodes - gwNode.IPFS("config", "--json", "Experimental.GatewayOverLibp2p", "true") + // Enable HTTPProvider and the libp2p-stream transport, then reconnect. + gwNode.IPFS("config", "--json", "HTTPProvider.Enabled", "true") + gwNode.IPFS("config", "--json", "HTTPProvider.Libp2p", "true") gwNode.StopDaemon().StartDaemon() t.Cleanup(func() { gwNode.StopDaemon() }) nodes.Connect() From 8b71576068a56faec981f46739cd904dc4a207e9 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 02:07:09 +0200 Subject: [PATCH 03/16] feat(httpprovider): expose trustless gateway over AutoTLS HTTPS Mounts the same trustless-gateway handler that already serves the libp2p-stream transport on the AutoTLS WebSocket port via the new go-libp2p WithFallbackHTTPHandler hook, so any HTTP/2 client can fetch blocks directly with the AutoTLS-issued cert and no libp2p stack. Two pieces: - RequireHTTP2OverTLS wraps the handler so HTTPS requests must speak HTTP/2; HTTP/1.1 over TLS gets 426 Upgrade Required, with an Upgrade: h2,websocket hint. HTTP/1.1 stays reserved for the WebSocket upgrade dance, and bitswap-httpnet gets the multiplexing it needs. Cleartext requests pass through regardless of HTTP version, so reverse-proxy deployments are unaffected. - The HTTPS mux also serves /.well-known/libp2p/protocols (libp2p Gateway spec) via a fresh WellKnownHandler, mirroring what p2phttp.Host already auto-mounts on the libp2p-stream path. A bitswap-httpnet client hitting the AutoTLS hostname can discover the /ipfs/gateway protocol with one HTTPS GET, no libp2p stream needed. The serveHTTPProviderOverLibp2p doc comment now points at https://specs.ipfs.tech/http-gateways/libp2p-gateway/ and replaces the stale FIXME on gatewayProtocolID. --- cmd/ipfs/kubo/daemon.go | 55 ++++++++++++++++++++++++++- core/node/libp2p/httpprovider.go | 28 ++++++++++++++ core/node/libp2p/httpprovider_test.go | 48 +++++++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/cmd/ipfs/kubo/daemon.go b/cmd/ipfs/kubo/daemon.go index cd4e8d6a692..dd2d2bd18fd 100644 --- a/cmd/ipfs/kubo/daemon.go +++ b/cmd/ipfs/kubo/daemon.go @@ -1176,8 +1176,35 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e return errc, nil } -const gatewayProtocolID protocol.ID = "/ipfs/gateway" // FIXME: specify https://github.com/ipfs/specs/issues/433 +// gatewayProtocolID is the libp2p protocol ID under which the trustless +// gateway HTTP semantics are exposed over a libp2p stream, per the +// libp2p Gateway specification: +// https://specs.ipfs.tech/http-gateways/libp2p-gateway/ +const gatewayProtocolID protocol.ID = "/ipfs/gateway" + +// newGatewayWellKnown builds a fresh WellKnownHandler populated with the +// libp2p Gateway protocol meta. Used to publish /.well-known/libp2p/protocols +// on the HTTPProvider HTTPS path so clients can discover that the endpoint +// speaks the libp2p Gateway protocol. The libp2p-stream path uses its own +// WellKnownHandler attached to p2phttp.Host; both report the same metadata. +func newGatewayWellKnown() *p2phttp.WellKnownHandler { + wk := &p2phttp.WellKnownHandler{} + wk.AddProtocolMeta(gatewayProtocolID, p2phttp.ProtocolMeta{Path: "/"}) + return wk +} +// serveHTTPProviderOverLibp2p starts the libp2p-stream transport of the +// HTTPProvider feature. It implements the libp2p Gateway specification +// (https://specs.ipfs.tech/http-gateways/libp2p-gateway/) by mounting the +// trustless gateway handler under the /ipfs/gateway libp2p protocol ID and +// advertising it through the .well-known/libp2p/protocols document on the +// libp2p+HTTP host. +// +// The handler is the same one used for every HTTPProvider transport: +// NoFetch (only blocks already in the local blockstore), no DNSLink, no +// HTML errors, raw blocks and CARs only. Deserialized UnixFS responses are +// not served, so clients always get content-addressed bytes they can +// verify against the requested CID. func serveHTTPProviderOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { node, err := cctx.ConstructNode() if err != nil { @@ -1208,14 +1235,38 @@ func serveHTTPProviderOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { return nil, err } + // HTTPProvider: also expose the same trustless handler on the AutoTLS + // WSS port. FX provided the placeholder HTTPProvider handler when both + // HTTPProvider.Enabled and AutoTLS are on; we install the real handler + // now that IpfsNode is fully constructed. Unlike the libp2p-stream + // gateway above, this is reachable from any HTTPS client via the + // AutoTLS cert. + // + // The HTTPS mux also serves /.well-known/libp2p/protocols so HTTPS + // clients can discover that this peer speaks /ipfs/gateway (and any + // other libp2p protocols mounted in the future), per the libp2p+HTTP + // spec (https://specs.ipfs.tech/http-gateways/libp2p-gateway/). + // + // Wrap with RequireHTTP2OverTLS so the HTTPS path is h2-only (matches + // modern public HTTPS endpoints, gives bitswap-httpnet multiplexing) + // while the plain /ws path stays permissive for reverse-proxy interop. + if node.HTTPProvider != nil { + httpsMux := http.NewServeMux() + httpsMux.Handle("/", handler) + httpsMux.Handle(p2phttp.WellKnownProtocols, newGatewayWellKnown()) + node.HTTPProvider.Set(libp2p.RequireHTTP2OverTLS(httpsMux)) + log.Info("HTTPProvider: trustless gateway exposed via AutoWSS port (h2 required over TLS, h1+h2c allowed cleartext, .well-known/libp2p/protocols served)") + } + if node.PeerHost == nil { return nil, fmt.Errorf("cannot create libp2p gateway: node PeerHost is nil (this should not happen and likely indicates an FX dependency injection issue or race condition)") } + // libp2p-stream gateway. p2phttp.Host.Serve registers + // /.well-known/libp2p/protocols on h.ServeMux for us. h := p2phttp.Host{ StreamHost: node.PeerHost, } - h.WellKnownHandler.AddProtocolMeta(gatewayProtocolID, p2phttp.ProtocolMeta{Path: "/"}) h.ServeMux = http.NewServeMux() h.ServeMux.Handle("/", handler) diff --git a/core/node/libp2p/httpprovider.go b/core/node/libp2p/httpprovider.go index 50f9eeec607..40f5f3bfec5 100644 --- a/core/node/libp2p/httpprovider.go +++ b/core/node/libp2p/httpprovider.go @@ -44,3 +44,31 @@ func (l *HTTPProviderHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) } http.Error(w, "gateway not ready yet", http.StatusServiceUnavailable) } + +// RequireHTTP2OverTLS wraps an http.Handler so that requests arriving over +// TLS with HTTP/1.1 are rejected with 426 Upgrade Required. Cleartext +// requests pass through regardless of HTTP version, so reverse-proxy +// deployments that forward HTTP/1.1 to the backend keep working. +// +// Why this lives in kubo and not in the go-libp2p WS transport: the +// transport's WithFallbackHTTPHandler is intentionally interop-maximal +// (accepts every HTTP version on every listener) and leaves application +// policy to the caller. The HTTP-over-TLS path here is the public-facing +// AutoTLS endpoint we want to keep looking like a modern HTTPS server +// (multiplexing for bitswap-httpnet, smaller fingerprint surface for +// censors). The plain /ws path stays permissive so reverse proxies that +// only speak HTTP/1.1 to the backend keep working. +// +// HTTP/2 is detected via r.ProtoMajor; TLS via r.TLS != nil. Both fields +// are populated by net/http before the handler runs. +func RequireHTTP2OverTLS(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.TLS != nil && r.ProtoMajor < 2 { + w.Header().Set("Connection", "Upgrade") + w.Header().Set("Upgrade", "h2,websocket") + http.Error(w, "this endpoint requires HTTP/2 over TLS; HTTP/1.1 is reserved for the WebSocket upgrade", http.StatusUpgradeRequired) + return + } + h.ServeHTTP(w, r) + }) +} diff --git a/core/node/libp2p/httpprovider_test.go b/core/node/libp2p/httpprovider_test.go index 10d14844d54..d62fc6f226b 100644 --- a/core/node/libp2p/httpprovider_test.go +++ b/core/node/libp2p/httpprovider_test.go @@ -1,6 +1,7 @@ package libp2p import ( + "crypto/tls" "io" "net/http" "net/http/httptest" @@ -52,3 +53,50 @@ func TestHTTPProviderHandler_Reset(t *testing.T) { } } +// TestRequireHTTP2OverTLS exercises the four (TLS yes/no × h1/h2) cases. +func TestRequireHTTP2OverTLS(t *testing.T) { + hits := 0 + wrapped := RequireHTTP2OverTLS(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + hits++ + w.WriteHeader(http.StatusOK) + })) + + tlsState := &tls.ConnectionState{} + + cases := []struct { + name string + tls *tls.ConnectionState + protoMajor int + wantStatus int + wantHits int + }{ + {"TLS_h1_rejected", tlsState, 1, http.StatusUpgradeRequired, 0}, + {"TLS_h2_allowed", tlsState, 2, http.StatusOK, 1}, + {"cleartext_h1_allowed", nil, 1, http.StatusOK, 1}, + {"cleartext_h2_allowed", nil, 2, http.StatusOK, 1}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + hits = 0 + req := httptest.NewRequest(http.MethodGet, "/x", nil) + req.TLS = c.tls + req.ProtoMajor = c.protoMajor + + rec := httptest.NewRecorder() + wrapped.ServeHTTP(rec, req) + + if rec.Code != c.wantStatus { + t.Fatalf("status: want %d, got %d", c.wantStatus, rec.Code) + } + if hits != c.wantHits { + t.Fatalf("handler invocations: want %d, got %d", c.wantHits, hits) + } + if c.wantStatus == http.StatusUpgradeRequired { + if got := rec.Header().Get("Upgrade"); got != "h2,websocket" { + t.Fatalf("Upgrade header: want %q, got %q", "h2,websocket", got) + } + } + }) + } +} From dc07518c97539bd2e4ade000d5f53a92543ab7e0 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 02:07:51 +0200 Subject: [PATCH 04/16] feat(httpprovider): announce /http multiaddrs and auto-append cleartext /ws Two changes that turn this peer into a discoverable HTTP source for any client following the libp2p+HTTP discovery model. Announcement: HTTPProvider.AnnounceMultiaddrs (default true) derives an HTTP-flavored sibling for every announced WebSocket multiaddr: /ws becomes /http, /tls/ws becomes /tls/http, /tls/sni//ws becomes /tls/sni//http. The /http entries share the same TCP port and TLS cert as their /ws siblings, so this is purely an announcement; no extra socket is opened. The derivation runs after p2p-forge resolves the wildcard SNI and before the Addresses.NoAnnounce filter, so derived addresses inherit the same filtering as everything else. boxo/bitswap/network/httpnet picks them up through identify, the DHT, and IPNI. Cleartext: HTTPProvider.Cleartext (default false) auto-appends a plaintext /ws listener to each /tcp/N already in Addresses.Swarm, unless one is configured. Intended for reverse-proxy deployments where TLS is terminated upstream and the proxy forwards either HTTP/1.1 or h2c to kubo. Off by default because a node running AutoTLS does not need a public cleartext path. The check excludes /wss and /tls/ws (both TLS forms), so flipping it on alongside AutoTLS still adds cleartext where the operator wants it. The FX gate for the HTTPProviderHandler relaxes from "AutoTLS && HTTPProvider" to just "HTTPProvider", because cleartext /ws (manual or Cleartext-derived) needs the handler too. --- core/node/groups.go | 40 +++++++++++++- core/node/libp2p/addrs.go | 71 +++++++++++++++++++++---- core/node/libp2p/addrs_test.go | 96 ++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 10 deletions(-) diff --git a/core/node/groups.go b/core/node/groups.go index e5aa5562bd7..e0e2e7735cf 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -191,6 +191,39 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part enableAutoTLS = false } + // HTTPProvider.Cleartext: auto-append a plaintext /ws listener to each + // /tcp/N already in Addresses.Swarm so the HTTPProvider handler is + // reachable over cleartext (typical reverse-proxy deployment). The new + // /ws shares the existing TCP socket via tcpreuse; AutoWSS-installed + // /tls/sni//ws covers the TLS path and is left untouched. + // + // Skipped only when the user has a *cleartext* /ws listener already + // configured. /wss and /tls/ws are TLS-WebSocket forms, not cleartext, + // so they do not pre-empt the cleartext auto-append. + enableHTTPProviderCleartext := cfg.HTTPProvider.Cleartext.WithDefault(config.DefaultHTTPProviderCleartext) + if enableHTTPProvider && enableHTTPProviderCleartext && enableTCPTransport && enableWebsocketTransport { + plainWsRegex := regexp.MustCompile(`/tcp/\d+/ws$`) // cleartext only; excludes /wss and /tls/ws + tcpRegex := regexp.MustCompile(`/tcp/\d+$`) + plainWsPresent := false + var tcpListeners []string + for _, listener := range cfg.Addresses.Swarm { + if plainWsRegex.MatchString(listener) { + plainWsPresent = true + break + } + if tcpRegex.MatchString(listener) { + tcpListeners = append(tcpListeners, listener) + } + } + if !plainWsPresent { + for _, tcpListener := range tcpListeners { + wsListener := tcpListener + "/ws" + cfg.Addresses.Swarm = append(cfg.Addresses.Swarm, wsListener) + atlsLog.Infof("HTTPProvider.Cleartext: appended cleartext /ws listener: %s", wsListener) + } + } + } + // Gather all the options opts := fx.Options( BaseLibP2P, @@ -212,7 +245,12 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part maybeProvide(libp2p.NewHTTPProviderHandler, enableHTTPProvider), fx.Provide(libp2p.AddrFilters(cfg.Swarm.AddrFilters)), fx.Invoke(libp2p.MonitorDeadListeners(cfg.Swarm.AddrFilters, cfg.Addresses.NoAnnounce)), - fx.Provide(libp2p.AddrsFactory(cfg.Addresses.Announce, cfg.Addresses.AppendAnnounce, cfg.Addresses.NoAnnounce)), + fx.Provide(libp2p.AddrsFactory( + cfg.Addresses.Announce, + cfg.Addresses.AppendAnnounce, + cfg.Addresses.NoAnnounce, + enableHTTPProvider && cfg.HTTPProvider.AnnounceMultiaddrs.WithDefault(config.DefaultHTTPProviderAnnounceMultiaddrs), + )), fx.Provide(libp2p.SmuxTransport(cfg.Swarm.Transports)), fx.Provide(libp2p.RelayTransport(enableRelayTransport)), fx.Provide(libp2p.RelayService(enableRelayService, cfg.Swarm.RelayService)), diff --git a/core/node/libp2p/addrs.go b/core/node/libp2p/addrs.go index b6a5c4ddee4..d8273842000 100644 --- a/core/node/libp2p/addrs.go +++ b/core/node/libp2p/addrs.go @@ -275,31 +275,84 @@ func makeAddrsFactory(announce []string, appendAnnounce []string, noAnnounce []s }, nil } -func AddrsFactory(announce []string, appendAnnounce []string, noAnnounce []string) any { +func AddrsFactory(announce []string, appendAnnounce []string, noAnnounce []string, announceHTTPProvider bool) any { return func(params struct { fx.In ForgeMgr *p2pforge.P2PForgeCertMgr `optional:"true"` }, ) (opts Libp2pOpts, err error) { - var addrsFactory p2pbhost.AddrsFactory announceAddrsFactory, err := makeAddrsFactory(announce, appendAnnounce, noAnnounce) if err != nil { return opts, err } - if params.ForgeMgr == nil { - addrsFactory = announceAddrsFactory - } else { - addrsFactory = func(multiaddrs []ma.Multiaddr) []ma.Multiaddr { - forgeProcessing := params.ForgeMgr.AddressFactory()(multiaddrs) - announceProcessing := announceAddrsFactory(forgeProcessing) - return announceProcessing + // The factory pipeline runs in this order so each step sees the + // output of the previous one: + // 1. ForgeMgr substitutes the wildcard SNI in /tls/sni/*./ws + // with the real per-peer hostname (or its short form). + // 2. HTTPProvider derives an HTTP-flavored multiaddr from each /ws + // so HTTP retrieval clients can discover this peer; runs after + // ForgeMgr so the SNI value in /tls/sni//http is already + // the resolved one, not the wildcard. + // 3. announceAddrsFactory applies Addresses.Announce/AppendAnnounce + // and drops anything matching Addresses.NoAnnounce, so the + // derived addresses are filtered just like every other one. + addrsFactory := func(multiaddrs []ma.Multiaddr) []ma.Multiaddr { + if params.ForgeMgr != nil { + multiaddrs = params.ForgeMgr.AddressFactory()(multiaddrs) + } + if announceHTTPProvider { + multiaddrs = appendHTTPProviderAddrs(multiaddrs) } + return announceAddrsFactory(multiaddrs) } opts.Opts = append(opts.Opts, libp2p.AddrsFactory(addrsFactory)) return } } +// httpComponent is the /http multiaddr protocol component that pairs with +// /ws on the same TCP port. We never listen on it; it is only ever appended +// to announced multiaddrs to advertise the HTTPProvider endpoint. +var httpComponent, _ = ma.NewComponent("http", "") + +// appendHTTPProviderAddrs returns a slice that contains every input +// multiaddr plus, for each one ending in /ws, an additional copy with /ws +// replaced by /http. Order is preserved; the /http variant immediately +// follows its /ws sibling. Multiaddrs that do not end in /ws pass through +// unchanged. Duplicates (which would arise if both /ws and /http were +// already in the input) are dropped. +func appendHTTPProviderAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { + out := make([]ma.Multiaddr, 0, len(addrs)*2) + seen := make(map[string]struct{}, len(addrs)*2) + for _, a := range addrs { + if _, ok := seen[string(a.Bytes())]; !ok { + out = append(out, a) + seen[string(a.Bytes())] = struct{}{} + } + http, ok := wsToHTTP(a) + if !ok { + continue + } + if _, ok := seen[string(http.Bytes())]; !ok { + out = append(out, http) + seen[string(http.Bytes())] = struct{}{} + } + } + return out +} + +// wsToHTTP returns m with its trailing /ws component replaced by /http, +// and a boolean indicating whether the input ended in /ws. Everything +// before the trailing /ws (including any /tls and /tls/sni/ +// components) is preserved unchanged. +func wsToHTTP(m ma.Multiaddr) (ma.Multiaddr, bool) { + prefix, last := ma.SplitLast(m) + if last == nil || last.Protocol().Code != ma.P_WS { + return nil, false + } + return prefix.AppendComponent(httpComponent), true +} + func ListenOn(addresses []string) any { return func() (opts Libp2pOpts) { return Libp2pOpts{ diff --git a/core/node/libp2p/addrs_test.go b/core/node/libp2p/addrs_test.go index 0db847dbbfe..94a62688b01 100644 --- a/core/node/libp2p/addrs_test.go +++ b/core/node/libp2p/addrs_test.go @@ -19,6 +19,102 @@ func mustMultiaddrs(t *testing.T, addrs ...string) []ma.Multiaddr { return out } +// mustMultiaddrStrings is the inverse of mustMultiaddrs: a slice of strings +// for stable comparison in test expectations. +func mustMultiaddrStrings(addrs []ma.Multiaddr) []string { + out := make([]string, len(addrs)) + for i, a := range addrs { + out[i] = a.String() + } + return out +} + +func TestAppendHTTPProviderAddrs(t *testing.T) { + cases := []struct { + name string + in []string + want []string + }{ + { + name: "cleartext_ws", + in: []string{"/ip4/1.2.3.4/tcp/4001/ws"}, + want: []string{"/ip4/1.2.3.4/tcp/4001/ws", "/ip4/1.2.3.4/tcp/4001/http"}, + }, + { + name: "tls_ws", + in: []string{"/ip4/1.2.3.4/tcp/4001/tls/ws"}, + want: []string{"/ip4/1.2.3.4/tcp/4001/tls/ws", "/ip4/1.2.3.4/tcp/4001/tls/http"}, + }, + { + name: "tls_sni_ws", + in: []string{"/ip4/1.2.3.4/tcp/4001/tls/sni/example.libp2p.direct/ws"}, + want: []string{ + "/ip4/1.2.3.4/tcp/4001/tls/sni/example.libp2p.direct/ws", + "/ip4/1.2.3.4/tcp/4001/tls/sni/example.libp2p.direct/http", + }, + }, + { + name: "dns_tls_ws", + in: []string{"/dns4/example.com/tcp/443/tls/ws"}, + want: []string{"/dns4/example.com/tcp/443/tls/ws", "/dns4/example.com/tcp/443/tls/http"}, + }, + { + name: "non_ws_addr_unchanged", + in: []string{ + "/ip4/1.2.3.4/tcp/4001", + "/ip4/1.2.3.4/udp/4001/quic-v1", + }, + want: []string{ + "/ip4/1.2.3.4/tcp/4001", + "/ip4/1.2.3.4/udp/4001/quic-v1", + }, + }, + { + name: "mixed_preserves_order", + in: []string{ + "/ip4/1.2.3.4/tcp/4001", + "/ip4/1.2.3.4/tcp/4001/tls/ws", + "/ip4/1.2.3.4/udp/4001/quic-v1", + }, + want: []string{ + "/ip4/1.2.3.4/tcp/4001", + "/ip4/1.2.3.4/tcp/4001/tls/ws", + "/ip4/1.2.3.4/tcp/4001/tls/http", + "/ip4/1.2.3.4/udp/4001/quic-v1", + }, + }, + { + name: "preexisting_http_not_duplicated", + in: []string{ + "/ip4/1.2.3.4/tcp/4001/tls/ws", + "/ip4/1.2.3.4/tcp/4001/tls/http", + }, + want: []string{ + "/ip4/1.2.3.4/tcp/4001/tls/ws", + "/ip4/1.2.3.4/tcp/4001/tls/http", + }, + }, + { + name: "ws_appears_only_once_when_repeated", + in: []string{ + "/ip4/1.2.3.4/tcp/4001/tls/ws", + "/ip4/1.2.3.4/tcp/4001/tls/ws", + }, + want: []string{ + "/ip4/1.2.3.4/tcp/4001/tls/ws", + "/ip4/1.2.3.4/tcp/4001/tls/http", + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + got := appendHTTPProviderAddrs(mustMultiaddrs(t, c.in...)) + require.Equal(t, c.want, mustMultiaddrStrings(got)) + }) + } +} + func TestFindDeadListeners(t *testing.T) { cases := []struct { name string From 220d327c27a969dfc92e206fe4c08e948fa1928b Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 20:58:39 +0200 Subject: [PATCH 05/16] chore(deps): bump p2p-forge to v0.8.1 Picks up client.WithHTTPClient and client.WithResolver, used by the new ?dial=/?dns= AutoTLS.RegistrationEndpoint overrides in a follow-up commit. --- go.mod | 6 +++--- go.sum | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 3d1c957e28e..f73743f7591 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 github.com/fsnotify/fsnotify v1.10.0 github.com/google/uuid v1.6.0 + github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 github.com/hanwen/go-fuse/v2 v2.10.1 github.com/hashicorp/go-version v1.9.0 github.com/ipfs-shipyard/nopfs v0.0.14 @@ -46,7 +47,7 @@ require ( github.com/ipld/go-car/v2 v2.16.0 github.com/ipld/go-codec-dagpb v1.7.0 github.com/ipld/go-ipld-prime v0.23.0 - github.com/ipshipyard/p2p-forge v0.8.0 + github.com/ipshipyard/p2p-forge v0.8.1 github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/julienschmidt/httprouter v1.3.0 github.com/libp2p/go-doh-resolver v0.5.0 @@ -90,6 +91,7 @@ require ( golang.org/x/crypto v0.50.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f golang.org/x/mod v0.35.0 + golang.org/x/net v0.53.0 golang.org/x/sync v0.20.0 golang.org/x/sys v0.44.0 golang.org/x/term v0.43.0 @@ -146,7 +148,6 @@ require ( github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect github.com/google/gopacket v1.1.19 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/guillaumemichel/reservedpool v0.3.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect @@ -257,7 +258,6 @@ require ( go.uber.org/zap/exp v0.3.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/net v0.53.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa // indirect golang.org/x/text v0.36.0 // indirect diff --git a/go.sum b/go.sum index 3b050054551..ac9cc20154d 100644 --- a/go.sum +++ b/go.sum @@ -473,8 +473,8 @@ github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= -github.com/ipshipyard/p2p-forge v0.8.0 h1:yMg3UcAIVV0FDBMMbyZxlUnE6TYew0I+tBPzX6Y2OWM= -github.com/ipshipyard/p2p-forge v0.8.0/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= +github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= From 99eac130717fee87b6515b39d892af4be5b79ef3 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 20:58:40 +0200 Subject: [PATCH 06/16] feat(autotls): add test/debug config affordances Three knobs that make end-to-end tests against a private ACME/forge stack practical without polluting production paths: - AutoTLS.TrustedCARootsPEM: trust a private CA bundle for the ACME directory HTTPS call. Already documented as accepting a Pebble or self-hosted root. - AutoTLS.AllowPrivateForgeAddrs: lift the public-IP gate on cert requests so a loopback-only test node can complete a forge handshake. - AutoTLS.SelfSignedForTests: skip the forge handshake entirely and hand the WebSocket transport an in-memory self-signed cert. Pure test escape hatch; off by default. The SelfSignedForTests path lives in core/node/libp2p/autotls_selfsigned.go behind a constructor wired into the libp2p host setup only when the flag is on. Production builds with the flag off are unaffected. --- config/autotls.go | 29 ++++++++ core/node/groups.go | 4 ++ core/node/libp2p/autotls_selfsigned.go | 73 +++++++++++++++++++++ core/node/libp2p/autotls_selfsigned_test.go | 47 +++++++++++++ core/node/libp2p/transport.go | 16 +++-- 5 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 core/node/libp2p/autotls_selfsigned.go create mode 100644 core/node/libp2p/autotls_selfsigned_test.go diff --git a/config/autotls.go b/config/autotls.go index 4d90b717166..cd33118e3c7 100644 --- a/config/autotls.go +++ b/config/autotls.go @@ -40,6 +40,34 @@ type AutoTLS struct { // Optional, controls if features like AutoWSS should generate shorter /dnsX instead of /ipX/../sni/.. ShortAddrs Flag `json:",omitempty"` + + // SelfSignedForTests is a test-only escape hatch. When true, the daemon + // skips the AutoTLS / p2p-forge / ACME pipeline entirely and provides + // the WebSocket transport with an in-memory self-signed TLS config. + // Test clients pair this with tls.Config{InsecureSkipVerify: true} to + // drive the /tls/ws and /tls/http paths without real ACME issuance. + // + // Never set this in a production config. The cert is regenerated on + // every daemon start and is not trusted by any browser or CA. + SelfSignedForTests Flag `json:",omitempty"` + + // TrustedCARootsPEM is an optional PEM-encoded bundle of CA + // certificates that the ACME client trusts in addition to the system + // trust store. Set this when AutoTLS.CAEndpoint points at a CA whose + // root is not in the system store: private or self-hosted ACME + // deployments, and the in-process Pebble used by the AutoTLS E2E test + // in test/autotls/. + TrustedCARootsPEM *OptionalString `json:",omitempty"` + + // AllowPrivateForgeAddrs lifts the p2p-forge client's requirement that + // the libp2p host report a publicly reachable address before requesting + // a certificate. Set this for private/intranet libp2p deployments + // (where reachability is asymmetric or implicit) and for the AutoTLS + // E2E test in test/autotls/, which runs entirely on loopback. + // + // Leave this off in normal public deployments; the default behavior + // avoids wasting ACME issuance on a node that no one can reach. + AllowPrivateForgeAddrs Flag `json:",omitempty"` } const ( @@ -51,4 +79,5 @@ const ( DefaultAutoTLSShortAddrs = true // requires AutoTLS.Enabled DefaultAutoTLSSkipDNSLookup = true // skip network DNS for p2p-forge domains DefaultAutoTLSRegistrationDelay = 1 * time.Hour + DefaultAutoTLSSelfSignedForTests = false ) diff --git a/core/node/groups.go b/core/node/groups.go index e0e2e7735cf..0bdb8d5507a 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -235,6 +235,10 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part fx.Provide(libp2p.ResourceManager(bcfg.Repo.Path(), cfg.Swarm, userResourceOverrides)), maybeProvide(libp2p.P2PForgeCertMgr(bcfg.Repo.Path(), cfg.AutoTLS, atlsLog), enableAutoTLS), maybeInvoke(libp2p.StartP2PAutoTLS, enableAutoTLS), + // AutoTLS.SelfSignedForTests: bypass the entire AutoTLS / p2p-forge + // pipeline and hand the WebSocket transport an in-memory self-signed + // cert. Test escape hatch only. + maybeProvide(libp2p.NewSelfSignedTestTLSConfig, cfg.AutoTLS.SelfSignedForTests.WithDefault(config.DefaultAutoTLSSelfSignedForTests)), // When HTTPProvider is enabled, register a placeholder fallback // handler so the WebSocket transport can route non-upgrade requests // on every /ws or /tls/ws listener to the trustless gateway. The diff --git a/core/node/libp2p/autotls_selfsigned.go b/core/node/libp2p/autotls_selfsigned.go new file mode 100644 index 00000000000..9a275eafe6b --- /dev/null +++ b/core/node/libp2p/autotls_selfsigned.go @@ -0,0 +1,73 @@ +package libp2p + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "fmt" + "math/big" + "net" + "time" +) + +// SelfSignedTestTLSConfig is a *tls.Config carrying a freshly generated +// self-signed cert. Wrapped in a named type so FX can disambiguate it from +// any other *tls.Config value in the dependency graph. +type SelfSignedTestTLSConfig struct { + *tls.Config +} + +// NewSelfSignedTestTLSConfig generates an in-memory self-signed certificate +// and returns it wrapped as the FX-friendly SelfSignedTestTLSConfig. +// +// The cert covers `localhost`, `127.0.0.1`, and `::1`, plus the AutoTLS +// wildcard `*.libp2p.direct` so /tls/sni//ws listeners that the test +// configures by hand still match. The key is freshly generated each daemon +// start. Test clients must use tls.Config{InsecureSkipVerify: true} since +// no public CA signs this certificate. +// +// This provider is wired only when AutoTLS.SelfSignedForTests is true. +// It is a test escape hatch and must not be used in production. +func NewSelfSignedTestTLSConfig() (*SelfSignedTestTLSConfig, error) { + cert, err := generateSelfSignedTestCert() + if err != nil { + return nil, fmt.Errorf("self-signed test cert: %w", err) + } + return &SelfSignedTestTLSConfig{ + Config: &tls.Config{ + Certificates: []tls.Certificate{cert}, + }, + }, nil +} + +func generateSelfSignedTestCert() (tls.Certificate, error) { + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return tls.Certificate{}, err + } + serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + if err != nil { + return tls.Certificate{}, err + } + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{Organization: []string{"kubo test"}}, + NotBefore: time.Now().Add(-time.Hour), + NotAfter: time.Now().Add(24 * time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}, + DNSNames: []string{"localhost", "*.libp2p.direct"}, + } + der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &priv.PublicKey, priv) + if err != nil { + return tls.Certificate{}, err + } + return tls.Certificate{ + Certificate: [][]byte{der}, + PrivateKey: priv, + }, nil +} diff --git a/core/node/libp2p/autotls_selfsigned_test.go b/core/node/libp2p/autotls_selfsigned_test.go new file mode 100644 index 00000000000..bdf832e1f52 --- /dev/null +++ b/core/node/libp2p/autotls_selfsigned_test.go @@ -0,0 +1,47 @@ +package libp2p + +import ( + "crypto/x509" + "net" + "slices" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +// TestSelfSignedTestTLSConfig spot-checks that the test-only cert covers +// the SANs the test harness depends on (loopback IPs and the AutoTLS +// wildcard) and is valid for at least the minute it takes a test to run. +func TestSelfSignedTestTLSConfig(t *testing.T) { + cfg, err := NewSelfSignedTestTLSConfig() + require.NoError(t, err) + require.NotNil(t, cfg) + require.Len(t, cfg.Certificates, 1) + + leaf, err := x509.ParseCertificate(cfg.Certificates[0].Certificate[0]) + require.NoError(t, err) + + require.True(t, leaf.NotAfter.After(time.Now().Add(time.Minute)), + "cert should be valid past the test window") + require.True(t, leaf.NotBefore.Before(time.Now()), + "cert should already be valid") + + require.True(t, ipAddressesContain(leaf.IPAddresses, "127.0.0.1"), + "cert must cover loopback IPv4") + require.True(t, ipAddressesContain(leaf.IPAddresses, "::1"), + "cert must cover loopback IPv6") + require.True(t, slices.Contains(leaf.DNSNames, "localhost")) + require.True(t, slices.Contains(leaf.DNSNames, "*.libp2p.direct"), + "cert must cover the AutoTLS wildcard so /tls/sni//ws listeners work in tests") +} + +func ipAddressesContain(haystack []net.IP, needle string) bool { + target := net.ParseIP(needle) + for _, ip := range haystack { + if ip.Equal(target) { + return true + } + } + return false +} diff --git a/core/node/libp2p/transport.go b/core/node/libp2p/transport.go index e434bd92e05..ea4fe5ff0e8 100644 --- a/core/node/libp2p/transport.go +++ b/core/node/libp2p/transport.go @@ -20,9 +20,10 @@ import ( func Transports(tptConfig config.Transports) any { return func(params struct { fx.In - Fprint PNetFingerprint `optional:"true"` - ForgeMgr *client.P2PForgeCertMgr `optional:"true"` - HTTPProvider *HTTPProviderHandler `optional:"true"` + Fprint PNetFingerprint `optional:"true"` + ForgeMgr *client.P2PForgeCertMgr `optional:"true"` + HTTPProvider *HTTPProviderHandler `optional:"true"` + SelfSignedTLS *SelfSignedTestTLSConfig `optional:"true"` }, ) (opts Libp2pOpts, err error) { privateNetworkEnabled := params.Fprint != nil @@ -36,7 +37,14 @@ func Transports(tptConfig config.Transports) any { if wsEnabled { var wsOpts []any - if params.ForgeMgr != nil { + // Test escape hatch wins when set: skip the AutoTLS pipeline + // and feed the WebSocket transport an in-memory self-signed + // cert. Production paths use ForgeMgr; both are wired + // optional so only one provider fires per build. + switch { + case params.SelfSignedTLS != nil: + wsOpts = append(wsOpts, websocket.WithTLSConfig(params.SelfSignedTLS.Config)) + case params.ForgeMgr != nil: wsOpts = append(wsOpts, websocket.WithTLSConfig(params.ForgeMgr.TLSConfig())) } // HTTPProvider: when the master switch is on (and AutoTLS is on), From 05cf8a9981eaab1d325652f3c45b5bd0a201c134 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 21:00:47 +0200 Subject: [PATCH 07/16] feat(autotls): add ?dial=/?dns= URL overrides AutoTLS.RegistrationEndpoint now accepts two optional query parameters: - ?dial=host:port reroutes the TCP dial of the registration POST while leaving the URL Kubo advertises (and signs over for PeerID-auth) unchanged. Lets a local p2p-forge instance on a non-privileged loopback port answer requests whose Host header must still match the production registration hostname. - ?dns=host:port points the DNS-01 propagation pre-flight check at this DNS server instead of the system resolver. Needed when the forge's domain suffix is not in public DNS, e.g. a private .test suffix used in end-to-end tests. The daemon strips both parameters before handing the URL to p2p-forge; unrelated query parameters are preserved. Parsing and dispatch live in parseForgeOverrides + forgeDialOverrideClient + forgeDNSOverrideResolver. Covered by TestParseForgeOverrides; documented under AutoTLS.RegistrationEndpoint. --- core/node/libp2p/addrs.go | 108 ++++++++++++++++++++++++++++++++- core/node/libp2p/addrs_test.go | 88 +++++++++++++++++++++++++++ 2 files changed, 193 insertions(+), 3 deletions(-) diff --git a/core/node/libp2p/addrs.go b/core/node/libp2p/addrs.go index d8273842000..40efacf66eb 100644 --- a/core/node/libp2p/addrs.go +++ b/core/node/libp2p/addrs.go @@ -2,7 +2,11 @@ package libp2p import ( "context" + "crypto/x509" "fmt" + "net" + "net/http" + "net/url" "os" "path/filepath" "time" @@ -382,18 +386,48 @@ func P2PForgeCertMgr(repoPath string, cfg config.AutoTLS, atlsLog *logging.ZapEv registrationDelay = 0 * time.Second } + // Pull the optional ?dial= and ?dns= test/debug overrides off the + // URL before handing it to p2p-forge. See docs/config.md. + regEndpoint, overrides, err := parseForgeOverrides(cfg.RegistrationEndpoint.WithDefault(config.DefaultRegistrationEndpoint)) + if err != nil { + return nil, fmt.Errorf("AutoTLS.RegistrationEndpoint: %w", err) + } + certStorage := &certmagic.FileStorage{Path: storagePath} - certMgr, err := p2pforge.NewP2PForgeCertMgr( + opts := []p2pforge.P2PForgeCertMgrOptions{ p2pforge.WithLogger(rawLogger.Sugar()), p2pforge.WithForgeDomain(cfg.DomainSuffix.WithDefault(config.DefaultDomainSuffix)), - p2pforge.WithForgeRegistrationEndpoint(cfg.RegistrationEndpoint.WithDefault(config.DefaultRegistrationEndpoint)), + p2pforge.WithForgeRegistrationEndpoint(regEndpoint), p2pforge.WithRegistrationDelay(registrationDelay), p2pforge.WithCAEndpoint(cfg.CAEndpoint.WithDefault(config.DefaultCAEndpoint)), p2pforge.WithForgeAuth(cfg.RegistrationToken.WithDefault(os.Getenv(p2pforge.ForgeAuthEnv))), p2pforge.WithUserAgent(version.GetUserAgentVersion()), p2pforge.WithCertificateStorage(certStorage), p2pforge.WithShortForgeAddrs(cfg.ShortAddrs.WithDefault(config.DefaultAutoTLSShortAddrs)), - ) + } + // AutoTLS.TrustedCARootsPEM: optional CA bundle for private or + // self-hosted ACME deployments (including the in-process Pebble + // used by the AutoTLS E2E test). + if pem := cfg.TrustedCARootsPEM.WithDefault(""); pem != "" { + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM([]byte(pem)) { + return nil, fmt.Errorf("AutoTLS.TrustedCARootsPEM did not contain any parseable certificate") + } + opts = append(opts, p2pforge.WithTrustedRoots(pool)) + } + // AutoTLS.AllowPrivateForgeAddrs: lift the "must be publicly + // reachable" gate on cert requests, for private/intranet + // deployments and the AutoTLS E2E test (loopback only). + if cfg.AllowPrivateForgeAddrs.WithDefault(false) { + opts = append(opts, p2pforge.WithAllowPrivateForgeAddrs()) + } + if overrides.dial != "" { + opts = append(opts, p2pforge.WithHTTPClient(forgeDialOverrideClient(overrides.dial))) + } + if overrides.dns != "" { + opts = append(opts, p2pforge.WithResolver(forgeDNSOverrideResolver(overrides.dns))) + } + certMgr, err := p2pforge.NewP2PForgeCertMgr(opts...) if err != nil { return nil, err } @@ -402,6 +436,74 @@ func P2PForgeCertMgr(repoPath string, cfg config.AutoTLS, atlsLog *logging.ZapEv } } +// forgeOverrides holds the test/debug overrides parsed off +// AutoTLS.RegistrationEndpoint. All fields are empty when the URL carries no +// overrides. See docs/config.md for the user-facing description. +type forgeOverrides struct { + dial string // ?dial=host:port: forces the registration POST to dial here + dns string // ?dns=host:port: forces DNS-01 pre-flight lookups to this server +} + +// parseForgeOverrides strips the recognized ?dial= and ?dns= query parameters +// from raw, returning the cleaned URL and the parsed overrides. Unrelated +// query parameters are preserved. +func parseForgeOverrides(raw string) (cleanURL string, ov forgeOverrides, err error) { + u, err := url.Parse(raw) + if err != nil { + return "", forgeOverrides{}, err + } + q := u.Query() + for _, p := range []struct { + key string + dst *string + }{ + {"dial", &ov.dial}, + {"dns", &ov.dns}, + } { + v := q.Get(p.key) + if v == "" { + continue + } + if _, _, err := net.SplitHostPort(v); err != nil { + return "", forgeOverrides{}, fmt.Errorf("%s=%q must be host:port: %w", p.key, v, err) + } + *p.dst = v + q.Del(p.key) + } + // Return raw unchanged when no override was set, so a no-op call + // doesn't reorder unrelated query parameters via Query().Encode(). + if ov == (forgeOverrides{}) { + return raw, ov, nil + } + u.RawQuery = q.Encode() + return u.String(), ov, nil +} + +// forgeDialOverrideClient returns an *http.Client whose Transport always dials +// dialAddr, ignoring the request URL's host. Used by the ?dial= override. +func forgeDialOverrideClient(dialAddr string) *http.Client { + dialer := &net.Dialer{} + return &http.Client{ + Transport: &http.Transport{ + DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { + return dialer.DialContext(ctx, "tcp", dialAddr) + }, + }, + } +} + +// forgeDNSOverrideResolver returns a *net.Resolver that sends every lookup to +// dnsAddr instead of the system resolver. Used by the ?dns= override. +func forgeDNSOverrideResolver(dnsAddr string) *net.Resolver { + dialer := &net.Dialer{} + return &net.Resolver{ + PreferGo: true, + Dial: func(ctx context.Context, network, _ string) (net.Conn, error) { + return dialer.DialContext(ctx, network, dnsAddr) + }, + } +} + func StartP2PAutoTLS(lc fx.Lifecycle, certMgr *p2pforge.P2PForgeCertMgr, h host.Host) { lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { diff --git a/core/node/libp2p/addrs_test.go b/core/node/libp2p/addrs_test.go index 94a62688b01..c2028310e7c 100644 --- a/core/node/libp2p/addrs_test.go +++ b/core/node/libp2p/addrs_test.go @@ -261,3 +261,91 @@ func TestMakeAddrsFactoryDropsEmptyMultiaddrs(t *testing.T) { } } } + +// TestParseForgeOverrides exercises the ?dial=/?dns= query-string syntax used +// to redirect the forge registration request and DNS-01 propagation lookup +// during tests and local debugging. Both overrides are stripped from the URL +// handed back to p2p-forge; malformed values are rejected up-front. +func TestParseForgeOverrides(t *testing.T) { + t.Parallel() + for _, tc := range []struct { + name string + input string + wantURL string + wantDial string + wantDNS string + wantErrSub string + }{ + { + name: "no query", + input: "https://registration.libp2p.direct", + wantURL: "https://registration.libp2p.direct", + }, + { + name: "unrelated query preserved", + input: "https://registration.libp2p.direct?foo=bar", + wantURL: "https://registration.libp2p.direct?foo=bar", + }, + { + name: "dial only is stripped", + input: "http://registration.libp2p.test/?dial=127.0.0.1:42013", + wantURL: "http://registration.libp2p.test/", + wantDial: "127.0.0.1:42013", + }, + { + name: "dns only is stripped", + input: "http://registration.libp2p.test/?dns=127.0.0.1:5353", + wantURL: "http://registration.libp2p.test/", + wantDNS: "127.0.0.1:5353", + }, + { + name: "dial and dns together, both stripped", + input: "http://registration.libp2p.test/?dial=127.0.0.1:42013&dns=127.0.0.1:5353", + wantURL: "http://registration.libp2p.test/", + wantDial: "127.0.0.1:42013", + wantDNS: "127.0.0.1:5353", + }, + { + name: "overrides alongside unrelated params", + input: "http://example.test/?foo=bar&dial=127.0.0.1:9000&baz=qux&dns=127.0.0.1:5353", + wantURL: "http://example.test/?baz=qux&foo=bar", + wantDial: "127.0.0.1:9000", + wantDNS: "127.0.0.1:5353", + }, + { + name: "ipv6 addresses", + input: "http://example.test/?dial=[::1]:9000&dns=[::1]:5353", + wantURL: "http://example.test/", + wantDial: "[::1]:9000", + wantDNS: "[::1]:5353", + }, + { + name: "malformed dial rejected", + input: "http://example.test/?dial=not-a-host-port", + wantErrSub: `dial="not-a-host-port"`, + }, + { + name: "malformed dns rejected", + input: "http://example.test/?dns=not-a-host-port", + wantErrSub: `dns="not-a-host-port"`, + }, + { + name: "empty override values treated as absent", + input: "http://example.test/?dial=&dns=", + wantURL: "http://example.test/?dial=&dns=", + }, + } { + t.Run(tc.name, func(t *testing.T) { + gotURL, ov, err := parseForgeOverrides(tc.input) + if tc.wantErrSub != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.wantErrSub) + return + } + require.NoError(t, err) + require.Equal(t, tc.wantURL, gotURL) + require.Equal(t, tc.wantDial, ov.dial) + require.Equal(t, tc.wantDNS, ov.dns) + }) + } +} From 51350d170e8d8f2c3f4cadbc70e33bfa42b372e6 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 21:00:54 +0200 Subject: [PATCH 08/16] test(autotls): add E2E canary sub-module Adds test/autotls/ as a dedicated Go sub-module with its own go.mod, so the heavy test dependencies (Pebble, CoreDNS, p2p-forge) do not leak into kubo's main module or vulnerability-scanning surface. The canary brings up an in-process Pebble (ACME test server) and the full p2p-forge service (CoreDNS-based DNS + HTTP registration endpoint), points a real kubo daemon at them via the new AutoTLS knobs and the ?dial=/?dns= overrides, and walks the chain end-to-end: registration POST, DNS-01 validation, cert install, /tls/http announcement, HTTP/2 fetch of a real block. One canary covers every link. Run with: make test_autotls (or `cd test/autotls && go test ./...`). Wired into CI as the autotls-tests job in gotest.yml. --- .github/workflows/gotest.yml | 22 + AGENTS.md | 2 +- Rules.mk | 1 + mk/golang.mk | 13 + test/autotls/canary_test.go | 223 +++++++ test/autotls/doc.go | 43 ++ test/autotls/go.mod | 218 +++++++ test/autotls/go.sum | 1114 ++++++++++++++++++++++++++++++++++ test/autotls/harness.go | 264 ++++++++ 9 files changed, 1899 insertions(+), 1 deletion(-) create mode 100644 test/autotls/canary_test.go create mode 100644 test/autotls/doc.go create mode 100644 test/autotls/go.mod create mode 100644 test/autotls/go.sum create mode 100644 test/autotls/harness.go diff --git a/.github/workflows/gotest.yml b/.github/workflows/gotest.yml index f40d2172e6b..e8be7d6d534 100644 --- a/.github/workflows/gotest.yml +++ b/.github/workflows/gotest.yml @@ -202,6 +202,28 @@ jobs: fusermount3 -uz "$mp" 2>/dev/null || fusermount -uz "$mp" 2>/dev/null || true done + # AutoTLS end-to-end canary (in-process Pebble + p2p-forge). + # Isolated sub-module (test/autotls); heavy CoreDNS + Pebble deps stay + # out of the main go.mod. + autotls-tests: + if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' + runs-on: ${{ fromJSON(github.repository == 'ipfs/kubo' && '["self-hosted", "linux", "x64", "2xlarge"]' || '"ubuntu-latest"') }} + timeout-minutes: 8 + env: + GOTRACEBACK: all + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 + with: + go-version-file: 'go.mod' + - name: Build kubo binary + run: make build + - name: Run AutoTLS end-to-end canary + run: make test_autotls + # Example tests (kubo-as-a-library) example-tests: if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch' diff --git a/AGENTS.md b/AGENTS.md index 637c2dafb34..61d37c2db04 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,7 +81,7 @@ make -O test_go_lint # run linter (use this instead of golangci-lint directly) If you modify `go.mod` (add/remove/update dependencies), you must run `make mod_tidy` first, before building or testing. Use `make mod_tidy` instead of `go mod tidy` directly, as the project has multiple `go.mod` files. -If you modify any `.go` files outside of `test/`, you must run `make build` before running integration tests. +If you modify any `.go` files outside of `test/`, you must run `make build` before running integration tests. Integration tests spawn a real `ipfs daemon` from `cmd/ipfs/ipfs` and `go test ./test/cli/...` does not rebuild that binary, so daemon-side changes (config schema, FX providers, transport options, default values) appear to be silently ignored when the binary is stale. Common symptoms: a new config flag has no effect, an expected listener never binds, an FX-injected handler is nil. If a CLI test behaves differently from a manual `cmd/ipfs/ipfs daemon` run, suspect a stale binary first. ## Testing diff --git a/Rules.mk b/Rules.mk index 418aec15b15..db44137d9df 100644 --- a/Rules.mk +++ b/Rules.mk @@ -139,6 +139,7 @@ help: @echo ' test_unit - Run unit tests with coverage (excludes test/cli)' @echo ' test_cli - Run CLI integration tests (requires built binary)' @echo ' test_fuse - Run FUSE tests (requires /dev/fuse and fusermount)' + @echo ' test_autotls - Run AutoTLS end-to-end canary (in-process Pebble + p2p-forge)' @echo ' test_go_fmt - Check Go source formatting' @echo ' test_go_build - Build kubo for all platforms from .github/build-platforms.yml' @echo ' test_go_lint - Run golangci-lint' diff --git a/mk/golang.mk b/mk/golang.mk index 0551cb78622..31fa0c60b1d 100644 --- a/mk/golang.mk +++ b/mk/golang.mk @@ -101,6 +101,19 @@ test_examples: cd docs/examples/kubo-as-a-library && go test -v -timeout=$(TEST_EXAMPLES_TIMEOUT) ./... && cp go.mod go.mod.bak && cp go.sum go.sum.bak && (go mod edit -replace github.com/ipfs/kubo=./../../.. && go mod tidy && go test -v -timeout=$(TEST_EXAMPLES_TIMEOUT) ./...; ret=$$?; mv go.mod.bak go.mod; mv go.sum.bak go.sum; exit $$ret) .PHONY: test_examples +# AutoTLS end-to-end canary (separate module under test/autotls). +# Spins up an in-process Pebble ACME server and the p2p-forge service +# (CoreDNS-based) to exercise kubo's full AutoTLS chain. Heavy deps +# (Pebble + CoreDNS, ~350 indirect modules) live in the sub-module's +# go.mod so kubo's main module stays clean. +TEST_AUTOTLS_TIMEOUT ?= 4m +test_autotls: cmd/ipfs/ipfs test/bin/gotestsum $$(DEPS_GO) + cd test/autotls && rm -f autotls-tests.json && \ + PATH="$(CURDIR)/cmd/ipfs:$(CURDIR)/test/bin:$$PATH" \ + gotestsum $(GOTESTSUM_NOCOLOR) --jsonfile autotls-tests.json -- \ + -v -timeout=$(TEST_AUTOTLS_TIMEOUT) ./... +.PHONY: test_autotls + # Build kubo for all platforms from .github/build-platforms.yml test_go_build: bin/test-go-build-platforms diff --git a/test/autotls/canary_test.go b/test/autotls/canary_test.go new file mode 100644 index 00000000000..7962c2b8722 --- /dev/null +++ b/test/autotls/canary_test.go @@ -0,0 +1,223 @@ +package autotls + +import ( + "crypto/tls" + "crypto/x509" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/ipfs/go-cid" + "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/test/cli/harness" + "github.com/multiformats/go-multiaddr" + "github.com/stretchr/testify/require" + "golang.org/x/net/http2" +) + +// TestACMEEndToEnd drives kubo's full AutoTLS chain in-process: +// +// 1. p2p-forge registration (PeerID-auth POST) +// 2. certmagic ACME order against an in-process Pebble +// 3. DNS-01 challenge validated through the p2p-forge DNS plugin +// 4. cert installation into the WebSocket transport +// 5. HTTP/2 fetch of a real block via the announced /tls/http multiaddr +// +// Every link above is load-bearing for any AutoTLS-enabled kubo node, so one +// canary covers all of them. Heavy deps (Pebble, CoreDNS) live in this +// sub-module's go.mod and stay out of kubo's main module; CI runs the canary +// as a dedicated autotls-tests job. See doc.go. +func TestACMEEndToEnd(t *testing.T) { + t.Parallel() + + stack := NewStack(t) + + // The kubo harness finds the binary by walking up to the nearest + // go.mod, but this sub-module has its own go.mod, so the walk stops + // here. Point IPFSBin at the real kubo build at the repo root + // (../../cmd/ipfs/ipfs from this sub-module's perspective). + h := harness.NewT(t) + h.IPFSBin = mustAbs(t, "../../cmd/ipfs/ipfs") + node := h.NewNode().Init() + node.UpdateConfig(func(cfg *config.Config) { + // HTTPProvider exposes the trustless gateway over /tls/ws and + // /tls/http using the AutoTLS cert. + cfg.HTTPProvider.Enabled = config.True + + // Point AutoTLS at the in-process Pebble + p2p-forge. + cfg.AutoTLS.Enabled = config.True + cfg.AutoTLS.DomainSuffix = config.NewOptionalString(stack.ForgeDomain) + cfg.AutoTLS.RegistrationEndpoint = config.NewOptionalString(stack.ForgeRegistrationEndpoint) + cfg.AutoTLS.RegistrationToken = config.NewOptionalString(stack.ForgeAuthToken) + cfg.AutoTLS.CAEndpoint = config.NewOptionalString(stack.ACMEEndpoint) + cfg.AutoTLS.TrustedCARootsPEM = config.NewOptionalString(stack.PebbleCAPEM) + cfg.AutoTLS.AllowPrivateForgeAddrs = config.True + // Skip the production registration-delay so the test doesn't + // have to wait for the libp2p reachability event. + cfg.AutoTLS.RegistrationDelay = config.NewOptionalDuration(0) + + // AutoWSS adds /tls/sni/*.libp2p.test/ws to each /tcp/N, which + // is what HTTPProvider's /tls/http announcement is derived from. + cfg.AutoTLS.AutoWSS = config.True + }) + + node.StartDaemon() + defer node.StopDaemon() + + // Wait for AutoTLS to obtain a cert and the resulting /tls/http + // multiaddr to show up in the announced address set. + defer func() { + if t.Failed() { + t.Logf("daemon stderr (tail):\n%s", tailString(node.Daemon.Stderr.String(), 20000)) + } + }() + announced := waitForTLSHTTPMultiaddr(t, node, 60*time.Second, stack.ForgeDomain) + + // Translate the /tls/http multiaddr into an HTTPS URL and a dial + // address (raw IP:port we actually connect to; SNI carries the + // forge-issued hostname). + hostname, port := splitTLSHTTPAddr(t, announced) + addInfo := node.IPFSAddStr("hello world") + addCID := cid.MustParse(addInfo) + url := fmt.Sprintf("https://%s:%s/ipfs/%s?format=raw", hostname, port, addCID) + + // Build an HTTP/2 client that trusts Pebble's ACME issuance root. + // Cert chain validation goes all the way: Pebble-signed end-entity + // cert, chained from Pebble's issuance root, served from a hostname + // under stack.ForgeDomain. + pool := x509.NewCertPool() + require.True(t, pool.AppendCertsFromPEM([]byte(stack.PebbleIssuanceRootPEM)), + "failed to parse Pebble issuance root PEM") + client := &http.Client{ + Transport: &http2.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: pool, + ServerName: hostname, + }, + DialTLS: func(network, _ string, cfg *tls.Config) (net.Conn, error) { + raw, err := net.Dial(network, net.JoinHostPort("127.0.0.1", port)) + if err != nil { + return nil, err + } + c := tls.Client(raw, cfg) + if err := c.Handshake(); err != nil { + _ = raw.Close() + return nil, err + } + return c, nil + }, + }, + Timeout: 15 * time.Second, + } + + resp, err := client.Get(url) + require.NoError(t, err, "fetch /ipfs/%s via %s", addCID, url) + defer resp.Body.Close() + + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, "HTTP/2.0", resp.Proto) + require.Equal(t, "application/vnd.ipld.raw", resp.Header.Get("Content-Type")) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + // `ipfs add` of a small string produces a UnixFS file, so the raw + // block is a UnixFS protobuf with the literal payload embedded. We + // don't unmarshal it here; the canary's job is to prove the AutoTLS + // path round-trips real block bytes, not to re-test UnixFS. + require.Contains(t, string(body), "hello world", + "raw block payload should embed the added bytes") +} + +// waitForTLSHTTPMultiaddr polls `ipfs id` until a multiaddr that ends in +// /tls/http and references the forge domain appears, or the deadline +// expires. Pebble's cert issuance takes a second or two on the first run; +// the AddrsFactory derivation of /tls/http happens once the AutoTLS cert +// is installed and the libp2p host's listen addresses are re-evaluated. +func waitForTLSHTTPMultiaddr(t *testing.T, n *harness.Node, timeout time.Duration, forgeDomain string) multiaddr.Multiaddr { + t.Helper() + deadline := time.Now().Add(timeout) + for time.Now().Before(deadline) { + for _, a := range readAnnouncedAddrs(t, n) { + s := a.String() + if !strings.HasSuffix(s, "/tls/http") { + continue + } + if !strings.Contains(s, forgeDomain) { + continue + } + return a + } + time.Sleep(500 * time.Millisecond) + } + t.Fatalf("no /tls/http multiaddr appeared within %s; announced=%v", + timeout, readAnnouncedAddrs(t, n)) + return nil +} + +// readAnnouncedAddrs returns the multiaddrs the node advertises via +// identify (output of `ipfs id`). This is what other peers see, and +// includes the /tls/http addresses derived by HTTPProvider. +func readAnnouncedAddrs(t *testing.T, n *harness.Node) []multiaddr.Multiaddr { + t.Helper() + out := n.IPFS("id", "--enc=json").Stdout.String() + var idDoc struct { + Addresses []string `json:"Addresses"` + } + require.NoError(t, json.Unmarshal([]byte(out), &idDoc)) + addrs := make([]multiaddr.Multiaddr, 0, len(idDoc.Addresses)) + for _, s := range idDoc.Addresses { + if i := strings.Index(s, "/p2p/"); i >= 0 { + s = s[:i] + } + a, err := multiaddr.NewMultiaddr(s) + if err != nil { + t.Fatalf("parse announced addr %q: %v", s, err) + } + addrs = append(addrs, a) + } + return addrs +} + +// splitTLSHTTPAddr extracts (hostname, port) from a /dns*//tcp// +// tls/sni//http or similar multiaddr. The hostname is what SNI must +// be set to; the port is what we actually dial on 127.0.0.1. +func splitTLSHTTPAddr(t *testing.T, m multiaddr.Multiaddr) (host, port string) { + t.Helper() + // SNI component (if present) wins for the hostname, otherwise the + // /dns* value. Both forms appear depending on AutoTLS.ShortAddrs. + for _, code := range []int{multiaddr.P_SNI, multiaddr.P_DNS, multiaddr.P_DNS4, multiaddr.P_DNS6, multiaddr.P_DNSADDR} { + v, err := m.ValueForProtocol(code) + if err == nil && v != "" { + host = v + break + } + } + require.NotEmpty(t, host, "no hostname component in %s", m) + p, err := m.ValueForProtocol(multiaddr.P_TCP) + require.NoError(t, err, "no tcp port in %s", m) + return host, p +} + +// mustAbs returns the absolute path of rel, panicking via require if the +// filesystem call fails. Used to compute the kubo binary location from +// this sub-module's cwd. +func mustAbs(t *testing.T, rel string) string { + t.Helper() + abs, err := filepath.Abs(rel) + require.NoError(t, err) + return abs +} + +// tailString returns the last n bytes of s, prefixed with "...". +func tailString(s string, n int) string { + if len(s) <= n { + return s + } + return "... (truncated)\n" + s[len(s)-n:] +} + diff --git a/test/autotls/doc.go b/test/autotls/doc.go new file mode 100644 index 00000000000..df3f1ac6f34 --- /dev/null +++ b/test/autotls/doc.go @@ -0,0 +1,43 @@ +// Package autotls contains end-to-end tests for the AutoTLS / p2p-forge +// / ACME issuance chain. +// +// # Why a separate Go module +// +// These tests need to run an in-process Pebble (ACME test server) and the +// full p2p-forge service (CoreDNS-based DNS server + HTTP registration +// endpoint). Pulling those into kubo's main go.mod brings ~350 transitive +// dependencies, including AWS, Azure, GCP, DataDog, and Kubernetes SDKs +// (because CoreDNS supports DNS plugins for all of them). None of that +// belongs in the production `ipfs` binary or in the main module's +// vulnerability-scanning surface. +// +// Isolating the heavy test deps behind their own go.mod keeps: +// +// - kubo's main module clean: `go build ./cmd/ipfs/` and `go mod tidy` at +// the repo root are unaffected. +// - Vulnerability scanning focused: Dependabot does not gain ~350 noisy +// advisories about cloud SDKs that production code does not use. +// - `go test ./...` at the repo root fast: this module is not picked up +// by default. Run it via `make test_autotls` from the repo root, +// or directly with `cd test/autotls && go test ./...`. +// +// The pattern matches the existing test sub-module in this repo: +// `test/dependencies/go.mod`. +// +// # CI +// +// This module is exercised by a dedicated GitHub Actions job +// (`autotls-tests` in `.github/workflows/gotest.yml`), parallel to the +// main `test_cli` job. The `test_cli` target intentionally does not invoke +// this module, so the CLI suite's compile time stays unaffected by Pebble +// and CoreDNS. +// +// # TODO: consider promoting test/cli to its own module +// +// A cleaner long-term separation would promote the entire `test/cli` tree +// to its own go.mod (with a `replace github.com/ipfs/kubo => ../..` +// directive). That move would isolate every test-only dependency from the +// production module, not just this canary's heavy deps. The cost is +// touching every existing CLI test file and every Makefile / CI target +// that references `test_cli`. Worth doing as its own focused PR. +package autotls diff --git a/test/autotls/go.mod b/test/autotls/go.mod new file mode 100644 index 00000000000..f65898aff28 --- /dev/null +++ b/test/autotls/go.mod @@ -0,0 +1,218 @@ +module github.com/ipfs/kubo/test/autotls + +go 1.26.2 + +// Use the parent kubo tree, not a published version. +replace github.com/ipfs/kubo => ../.. + +require ( + github.com/coredns/caddy v1.1.4 + github.com/coredns/coredns v1.14.3 + github.com/ipfs/go-cid v0.6.1 + github.com/ipfs/kubo v0.0.0-00010101000000-000000000000 + github.com/ipshipyard/p2p-forge v0.8.1 + github.com/letsencrypt/pebble/v2 v2.10.1 + github.com/multiformats/go-multiaddr v0.16.1 + github.com/stretchr/testify v1.11.1 + golang.org/x/net v0.54.0 +) + +require ( + filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5 // indirect + filippo.io/keygen v0.0.0-20260114151900-8e2790ea4c5b // indirect + github.com/DataDog/zstd v1.5.7 // indirect + github.com/Jorropo/jsync v1.0.1 // indirect + github.com/RaduBerinde/axisds v0.1.0 // indirect + github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54 // indirect + github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect + github.com/apparentlymart/go-cidr v1.1.0 // indirect + github.com/aws/aws-sdk-go v1.55.6 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/caddyserver/certmagic v0.23.0 // indirect + github.com/caddyserver/zerossl v0.1.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cockroachdb/crlib v0.0.0-20241112164430-1264a2edc35b // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble/v2 v2.1.5 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/swiss v0.0.0-20251224182025-b0f6560f979b // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect + github.com/dgraph-io/badger/v4 v4.5.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect + github.com/dunglas/httpsfv v1.1.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/filecoin-project/go-clock v0.1.0 // indirect + github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect + github.com/flynn/noise v1.1.0 // indirect + github.com/fsnotify/fsnotify v1.10.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.13 // indirect + github.com/gaissmai/bart v0.26.0 // indirect + github.com/gammazero/chanqueue v1.1.2 // indirect + github.com/gammazero/deque v1.2.1 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect + github.com/google/flatbuffers v24.12.23+incompatible // indirect + github.com/google/gopacket v1.1.19 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect + github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/huin/goupnp v1.3.0 // indirect + github.com/ipfs/bbloom v0.1.0 // indirect + github.com/ipfs/boxo v0.39.1-0.20260515000232-c8708232456f // indirect + github.com/ipfs/go-bitfield v1.1.0 // indirect + github.com/ipfs/go-block-format v0.2.3 // indirect + github.com/ipfs/go-cidutil v0.1.1 // indirect + github.com/ipfs/go-datastore v0.9.1 // indirect + github.com/ipfs/go-ds-badger4 v0.1.8 // indirect + github.com/ipfs/go-ds-dynamodb v0.2.2 // indirect + github.com/ipfs/go-dsqueue v0.2.0 // indirect + github.com/ipfs/go-ipfs-cmds v0.16.1 // indirect + github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect + github.com/ipfs/go-ipld-cbor v0.2.1 // indirect + github.com/ipfs/go-ipld-format v0.6.3 // indirect + github.com/ipfs/go-ipld-legacy v0.3.0 // indirect + github.com/ipfs/go-log/v2 v2.9.2 // indirect + github.com/ipfs/go-metrics-interface v0.3.0 // indirect + github.com/ipfs/go-unixfsnode v1.10.4 // indirect + github.com/ipld/go-car/v2 v2.16.0 // indirect + github.com/ipld/go-codec-dagpb v1.7.0 // indirect + github.com/ipld/go-ipld-prime v0.23.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/klauspost/compress v1.18.4 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/koron/go-ssdp v0.0.6 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/letsencrypt/challtestsrv v1.4.2 // indirect + github.com/libdns/libdns v1.0.0-beta.1 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-cidranger v1.1.0 // indirect + github.com/libp2p/go-doh-resolver v0.5.0 // indirect + github.com/libp2p/go-flow-metrics v0.3.0 // indirect + github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 // indirect + github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect + github.com/libp2p/go-libp2p-kad-dht v0.39.3-0.20260513140308-b73e1e814f5f // indirect + github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect + github.com/libp2p/go-libp2p-record v0.3.1 // indirect + github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect + github.com/libp2p/go-msgio v0.3.0 // indirect + github.com/libp2p/go-netroute v0.4.0 // indirect + github.com/libp2p/go-reuseport v0.4.0 // indirect + github.com/libp2p/go-yamux/v5 v5.0.1 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect + github.com/mattn/go-isatty v0.0.22 // indirect + github.com/mdlayher/socket v0.5.1 // indirect + github.com/mdlayher/vsock v1.2.1 // indirect + github.com/mholt/acmez/v3 v3.1.2 // indirect + github.com/miekg/dns v1.1.72 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/minlz v1.0.1-0.20250507153514-87eb42fe8882 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect + github.com/mr-tron/base58 v1.3.0 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr-dns v0.5.0 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.3.0 // indirect + github.com/multiformats/go-multicodec v0.10.0 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-multistream v0.6.1 // indirect + github.com/multiformats/go-varint v0.1.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect + github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect + github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v3 v3.1.2 // indirect + github.com/pion/ice/v4 v4.0.10 // indirect + github.com/pion/interceptor v0.1.40 // indirect + github.com/pion/logging v0.2.4 // indirect + github.com/pion/mdns/v2 v2.0.7 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.16 // indirect + github.com/pion/rtp v1.8.19 // indirect + github.com/pion/sctp v1.8.39 // indirect + github.com/pion/sdp/v3 v3.0.18 // indirect + github.com/pion/srtp/v3 v3.0.6 // indirect + github.com/pion/stun/v3 v3.1.1 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect + github.com/pion/transport/v4 v4.0.1 // indirect + github.com/pion/turn/v4 v4.0.2 // indirect + github.com/pion/webrtc/v4 v4.1.2 // indirect + github.com/pires/go-proxyproto v0.11.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/exporter-toolkit v0.16.0 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.59.0 // indirect + github.com/quic-go/webtransport-go v0.10.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/slok/go-http-metrics v0.13.0 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb // indirect + github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect + github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect + github.com/whyrusleeping/cbor-gen v0.3.1 // indirect + github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect + github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect + github.com/wlynxg/anet v0.0.5 // indirect + github.com/zeebo/blake3 v0.2.4 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect + go.uber.org/dig v1.19.0 // indirect + go.uber.org/fx v1.24.0 // indirect + go.uber.org/mock v0.5.2 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.28.0 // indirect + go.uber.org/zap/exp v0.3.0 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect + golang.org/x/mod v0.35.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa // indirect + golang.org/x/text v0.37.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/tools v0.44.0 // indirect + golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect + gonum.org/v1/gonum v0.17.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect + google.golang.org/grpc v1.80.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/blake3 v1.4.1 // indirect +) diff --git a/test/autotls/go.sum b/test/autotls/go.sum new file mode 100644 index 00000000000..7cd704abe95 --- /dev/null +++ b/test/autotls/go.sum @@ -0,0 +1,1114 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5 h1:JA0fFr+kxpqTdxR9LOBiTWpGNchqmkcsgmdeJZRclZ0= +filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5/go.mod h1:OjOXDNlClLblvXdwgFFOQFJEocLhhtai8vGLy0JCZlI= +filippo.io/keygen v0.0.0-20260114151900-8e2790ea4c5b h1:REI1FbdW71yO56Are4XAxD+OS/e+BQsB3gE4mZRQEXY= +filippo.io/keygen v0.0.0-20260114151900-8e2790ea4c5b/go.mod h1:9nnw1SlYHYuPSo/3wjQzNjSbeHlq2NsKo5iEtfJPWP0= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE= +github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Jorropo/jsync v1.0.1 h1:6HgRolFZnsdfzRUj+ImB9og1JYOxQoReSywkHOGSaUU= +github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ= +github.com/RaduBerinde/axisds v0.1.0 h1:YItk/RmU5nvlsv/awo2Fjx97Mfpt4JfgtEVAGPrLdz8= +github.com/RaduBerinde/axisds v0.1.0/go.mod h1:UHGJonU9z4YYGKJxSaC6/TNcLOBptpmM5m2Cksbnw0Y= +github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54 h1:bsU8Tzxr/PNz75ayvCnxKZWEYdLMPDkUgticP4a4Bvk= +github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54/go.mod h1:0tr7FllbE9gJkHq7CVeeDDFAFKQVy5RnCSSNBOvdqbc= +github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f h1:JjxwchlOepwsUWcQwD2mLUAGE9aCp0/ehy6yCHFBOvo= +github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f/go.mod h1:tMDTce/yLLN/SK8gMOxQfnyeMeCg8KGzp0D1cbECEeo= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= +github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= +github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU= +github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4= +github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= +github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3 h1:oe6fCvaEpkhyW3qAicT0TnGtyht/UrgvOwMcEgLb7Aw= +github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3/go.mod h1:qdP0gaj0QtgX2RUZhnlVrceJ+Qln8aSlDyJwelLLFeM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/crlib v0.0.0-20241112164430-1264a2edc35b h1:SHlYZ/bMx7frnmeqCu+xm0TCxXLzX3jQIVuFbnFGtFU= +github.com/cockroachdb/crlib v0.0.0-20241112164430-1264a2edc35b/go.mod h1:Gq51ZeKaFCXk6QwuGM0w1dnaOqc/F5zKT2zA9D6Xeac= +github.com/cockroachdb/datadriven v1.0.3-0.20250407164829-2945557346d5 h1:UycK/E0TkisVrQbSoxvU827FwgBBcZ95nRRmpj/12QI= +github.com/cockroachdb/datadriven v1.0.3-0.20250407164829-2945557346d5/go.mod h1:jsaKMvD3RBCATk1/jbUZM8C9idWBJME9+VRZ5+Liq1g= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895 h1:XANOgPYtvELQ/h4IrmPAohXqe2pWA8Bwhejr3VQoZsA= +github.com/cockroachdb/metamorphic v0.0.0-20231108215700-4ba948b56895/go.mod h1:aPd7gM9ov9M8v32Yy5NJrDyOcD8z642dqs+F0CeNXfA= +github.com/cockroachdb/pebble/v2 v2.1.5 h1:1ziHpaSau6qCXnFpQX3EBOH14yPHA8W66vKxsyrgXgs= +github.com/cockroachdb/pebble/v2 v2.1.5/go.mod h1:Reo1RTniv1UjVTAu/Fv74y5i3kJ5gmVrPhO9UtFiKn8= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/swiss v0.0.0-20251224182025-b0f6560f979b h1:VXvSNzmr8hMj8XTuY0PT9Ane9qZGul/p67vGYwl9BFI= +github.com/cockroachdb/swiss v0.0.0-20251224182025-b0f6560f979b/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/coredns/caddy v1.1.4 h1:+Lls5xASB0QsA2jpCroCOwpPlb5GjIGlxdjXxdX0XVo= +github.com/coredns/caddy v1.1.4/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= +github.com/coredns/coredns v1.14.3 h1:hWWoTdONblKIWhC8QPkxLEGIbewhR5xyTedqLVPsvvE= +github.com/coredns/coredns v1.14.3/go.mod h1:15BWsGGxupagKQ3p09pIIZ5kcgmyawquey6gqNWRaEI= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= +github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf h1:dwGgBWn84wUS1pVikGiruW+x5XM4amhjaZO20vCjay4= +github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= +github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= +github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= +github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU= +github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= +github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.10.0 h1:Xx/5Ydg9CeBDX/wi4VJqStNtohYjitZhhlHt4h3St1M= +github.com/fsnotify/fsnotify v1.10.0/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= +github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gaissmai/bart v0.26.0 h1:xOZ57E9hJLBiQaSyeZa9wgWhGuzfGACgqp4BE77OkO0= +github.com/gaissmai/bart v0.26.0/go.mod h1:GREWQfTLRWz/c5FTOsIw+KkscuFkIV5t8Rp7Nd1Td5c= +github.com/gammazero/chanqueue v1.1.2 h1:dZEsxlyANZMyeTRemABqZF8QM9BnE4NBI43Oh3y5fIU= +github.com/gammazero/chanqueue v1.1.2/go.mod h1:XDN1X/jjAbmSceNFOQbtKToeSkxtdVdpKu90LiEdBEE= +github.com/gammazero/deque v1.2.1 h1:9fnQVFCCZ9/NOc7ccTNqzoKd1tCWOqeI05/lPqFPMGQ= +github.com/gammazero/deque v1.2.1/go.mod h1:5nSFkzVm+afG9+gy0VIowlqVAW4N8zNcMne+CMQVD2g= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9 h1:r5GgOLGbza2wVHRzK7aAj6lWZjfbAwiu/RDCVOKjRyM= +github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc= +github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= +github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/ipfs/bbloom v0.1.0 h1:nIWwfIE3AaG7RCDQIsrUonGCOTp7qSXzxH7ab/ss964= +github.com/ipfs/bbloom v0.1.0/go.mod h1:lDy3A3i6ndgEW2z1CaRFvDi5/ZTzgM1IxA/pkL7Wgts= +github.com/ipfs/boxo v0.39.1-0.20260515000232-c8708232456f h1:gLeZpSeenmziHSu41hV0ztWpH4eFzzcA3HxdZ4mz6/A= +github.com/ipfs/boxo v0.39.1-0.20260515000232-c8708232456f/go.mod h1:o+77q6sNLx04X1pWLTICgi+MimNAKFy9HJ2qfhNUTRs= +github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= +github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= +github.com/ipfs/go-cid v0.6.1 h1:T5TnNb08+ueovG76Z5gx1L4Y7QOaGTXHg1F6raWFxIc= +github.com/ipfs/go-cid v0.6.1/go.mod h1:zrY0SwOhjrrIdfPQ/kf+k1sXyJ0QE7cMxfCployLBs0= +github.com/ipfs/go-cidutil v0.1.1 h1:COuby6H8C2ml0alvHYX3WdbFM4F07YtbY0UlT5j+sgI= +github.com/ipfs/go-cidutil v0.1.1/go.mod h1:SCoUftGEUgoXe5Hjeyw5CiLZF8cwYn/TbtpFQXJCP6k= +github.com/ipfs/go-datastore v0.9.1 h1:67Po2epre/o0UxrmkzdS9ZTe2GFGODgTd2odx8Wh6Yo= +github.com/ipfs/go-datastore v0.9.1/go.mod h1:zi07Nvrpq1bQwSkEnx3bfjz+SQZbdbWyCNvyxMh9pN0= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-ds-badger4 v0.1.8 h1:frNczf5CjCVm62RJ5mW5tD/oLQY/9IKAUpKviRV9QAI= +github.com/ipfs/go-ds-badger4 v0.1.8/go.mod h1:FdqSLA5TMsyqooENB/Hf4xzYE/iH0z/ErLD6ogtfMrA= +github.com/ipfs/go-ds-dynamodb v0.2.2 h1:tPuSMWoBPsDcg0KnUL3B8hGPctC+Ffpc+nsFsmkrQE8= +github.com/ipfs/go-ds-dynamodb v0.2.2/go.mod h1:ghG0ObKeNjGT4Zc0p0ADELXJX8jVqb18n/+BfavwPF0= +github.com/ipfs/go-ds-leveldb v0.5.2 h1:6nmxlQ2zbp4LCNdJVsmHfs9GP0eylfBNxpmY1csp0x0= +github.com/ipfs/go-ds-leveldb v0.5.2/go.mod h1:2fAwmcvD3WoRT72PzEekHBkQmBDhc39DJGoREiuGmYo= +github.com/ipfs/go-dsqueue v0.2.0 h1:MBi9w3oSiX98Xc+Y7NuJ9G8MI6mAT4IGdO9dHEMCZzU= +github.com/ipfs/go-dsqueue v0.2.0/go.mod h1:8FfNQC4DMF/KkzBXRNB9Rb3MKDW0Sh98HMtXYl1mLQE= +github.com/ipfs/go-ipfs-cmds v0.16.1 h1:O3xV6v2LN52wL0odvXX6jqlt7G2scuHzQYl80OJ+TOA= +github.com/ipfs/go-ipfs-cmds v0.16.1/go.mod h1:UkHLmJ2MlbLPuUJ0wmuF1R91+DGnwKvcCoEW3MR5CNg= +github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= +github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-pq v0.0.4 h1:U7jjENWJd1jhcrR8X/xHTaph14PTAK9O+yaLJbjqgOw= +github.com/ipfs/go-ipfs-pq v0.0.4/go.mod h1:9UdLOIIb99IFrgT0Fc53pvbvlJBhpUb4GJuAQf3+O2A= +github.com/ipfs/go-ipfs-redirects-file v0.1.2 h1:QCK7VtL91FH17KROVVy5KrzDx2hu68QvB2FTWk08ZQk= +github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw= +github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E= +github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A= +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= +github.com/ipfs/go-ipld-legacy v0.3.0 h1:7XhFKkRyCvP5upOlQfKUFIqL3S5DEZnbUE4bQmQ/tNE= +github.com/ipfs/go-ipld-legacy v0.3.0/go.mod h1:Ukef9ARQiX+RVetwH2XiReLgJvQDEXcUPszrZ1KRjKI= +github.com/ipfs/go-log/v2 v2.9.2 h1:O/5BB0elpkRILvT24rCJ5976wWd7u0nJ436T3rdYdc4= +github.com/ipfs/go-log/v2 v2.9.2/go.mod h1:RziRwwXWhndlk8L75RnEe0zeAYaq2heKtEMc3jqUov0= +github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU= +github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY= +github.com/ipfs/go-peertaskqueue v0.8.3 h1:tBPpGJy+A92RqtRFq5amJn0Uuj8Pw8tXi0X3eHfHM8w= +github.com/ipfs/go-peertaskqueue v0.8.3/go.mod h1:OqVync4kPOcXEGdj/LKvox9DCB5mkSBeXsPczCxLtYA= +github.com/ipfs/go-test v0.3.0 h1:0Y4Uve3tp9HI+2lIJjfOliOrOgv/YpXg/l1y3P4DEYE= +github.com/ipfs/go-test v0.3.0/go.mod h1:JK+U8pRpATZb7lsYNSJlCj3WYB3cFfWIbI6nWRM/GFk= +github.com/ipfs/go-unixfsnode v1.10.4 h1:cMmMyOrSjQkPVQbQvt8trErIn6jhayNf9pBA9oOwfxY= +github.com/ipfs/go-unixfsnode v1.10.4/go.mod h1:Vu1e/s7ToALBBRo38sJ8DwUVWmSeQMTdxk5/rcHl7d0= +github.com/ipld/go-car/v2 v2.16.0 h1:LWe0vmN/QcQmUU4tr34W5Nv5mNraW+G6jfN2s+ndBco= +github.com/ipld/go-car/v2 v2.16.0/go.mod h1:RqFGWN9ifcXVmCrTAVnfnxiWZk1+jIx67SYhenlmL34= +github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0= +github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM= +github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE27eE= +github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= +github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= +github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= +github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= +github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= +github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU= +github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk= +github.com/letsencrypt/pebble/v2 v2.10.1 h1:oKHx3lgN4e5Nno2LKTMrVx+b+NkDptkO9aDireiBDGE= +github.com/letsencrypt/pebble/v2 v2.10.1/go.mod h1:KtYhQ4YTjT5MtoCZ6RTCXlbrrz6cKyXROCuTpIUDJFY= +github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= +github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+skhePFdE= +github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU= +github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784= +github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088 h1:OhAw63jluTw3tAXLJklhZF0bkjULKo3wABYGcfzFytg= +github.com/libp2p/go-libp2p v0.48.1-0.20260515215300-a72c0588b088/go.mod h1:+zGTonNiePk+PlraDn51k+8grAbHh9df7IIAVOMwqZo= +github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= +github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= +github.com/libp2p/go-libp2p-kad-dht v0.39.3-0.20260513140308-b73e1e814f5f h1:PH/bOCidYs4UHu3EtHxqQvxMyWHMMXeSJUlM4wcpK28= +github.com/libp2p/go-libp2p-kad-dht v0.39.3-0.20260513140308-b73e1e814f5f/go.mod h1:iLUjII47u3/HjxyhucI2lhsl29lrzlAs/ym16+H40jE= +github.com/libp2p/go-libp2p-kbucket v0.8.0 h1:QAK7RzKJpYe+EuSEATAaaHYMYLkPDGC18m9jxPLnU8s= +github.com/libp2p/go-libp2p-kbucket v0.8.0/go.mod h1:JMlxqcEyKwO6ox716eyC0hmiduSWZZl6JY93mGaaqc4= +github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg= +github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E= +github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI= +github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98= +github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= +github.com/libp2p/go-netroute v0.4.0 h1:sZZx9hyANYUx9PZyqcgE/E1GUG3iEtTZHUEvdtXT7/Q= +github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= +github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= +github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= +github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= +github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/marcopolo/simnet v0.0.4 h1:50Kx4hS9kFGSRIbrt9xUS3NJX33EyPqHVmpXvaKLqrY= +github.com/marcopolo/simnet v0.0.4/go.mod h1:tfQF1u2DmaB6WHODMtQaLtClEf3a296CKQLq5gAsIS0= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= +github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= +github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= +github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= +github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= +github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= +github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/minlz v1.0.1-0.20250507153514-87eb42fe8882 h1:0lgqHvJWHLGW5TuObJrfyEi6+ASTKDBWikGvPqy9Yiw= +github.com/minio/minlz v1.0.1-0.20250507153514-87eb42fe8882/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.3.0 h1:K6Y13R2h+dku0wOqKtecgRnBUBPrZzLZy5aIj8lCcJI= +github.com/mr-tron/base58 v1.3.0/go.mod h1:2BuubE67DCSWwVfx37JWNG8emOC0sHEU4/HpcYgCLX8= +github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= +github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= +github.com/multiformats/go-multiaddr-dns v0.5.0 h1:p/FTyHKX0nl59f+S+dEUe8HRK+i5Ow/QHMw8Nh3gPCo= +github.com/multiformats/go-multiaddr-dns v0.5.0/go.mod h1:yJ349b8TPIAANUyuOzn1oz9o22tV9f+06L+cCeMxC14= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.3.0 h1:8helZD2+4Db7NNWFiktk2NePbF0boolBe6bDQvM4r68= +github.com/multiformats/go-multibase v0.3.0/go.mod h1:MoBLQPCkRTOL3eveIPO81860j2AQY8JwcnNlRkGRUfI= +github.com/multiformats/go-multicodec v0.10.0 h1:UpP223cig/Cx8J76jWt91njpK3GTAO1w02sdcjZDSuc= +github.com/multiformats/go-multicodec v0.10.0/go.mod h1:wg88pM+s2kZJEQfRCKBNU+g32F5aWBEjyFHXvZLTcLI= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ= +github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw= +github.com/multiformats/go-varint v0.1.0 h1:i2wqFp4sdl3IcIxfAonHQV9qU5OsZ4Ts9IOoETFs5dI= +github.com/multiformats/go-varint v0.1.0/go.mod h1:5KVAVXegtfmNQQm/lCY+ATvDzvJJhSkUlGQV9wgObdI= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= +github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= +github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= +github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc= +github.com/pion/dtls/v3 v3.1.2/go.mod h1:Hw/igcX4pdY69z1Hgv5x7wJFrUkdgHwAn/Q/uo7YHRo= +github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= +github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= +github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= +github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= +github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= +github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= +github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= +github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo= +github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo= +github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c= +github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= +github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= +github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= +github.com/pion/sdp/v3 v3.0.18 h1:l0bAXazKHpepazVdp+tPYnrsy9dfh7ZbT8DxesH5ZnI= +github.com/pion/sdp/v3 v3.0.18/go.mod h1:ZREGo6A9ZygQ9XkqAj5xYCQtQpif0i6Pa81HOiAdqQ8= +github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= +github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= +github.com/pion/stun/v3 v3.1.1 h1:CkQxveJ4xGQjulGSROXbXq94TAWu8gIX2dT+ePhUkqw= +github.com/pion/stun/v3 v3.1.1/go.mod h1:qC1DfmcCTQjl9PBaMa5wSn3x9IPmKxSdcCsxBcDBndM= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/transport/v4 v4.0.1 h1:sdROELU6BZ63Ab7FrOLn13M6YdJLY20wldXW2Cu2k8o= +github.com/pion/transport/v4 v4.0.1/go.mod h1:nEuEA4AD5lPdcIegQDpVLgNoDGreqM/YqmEx3ovP4jM= +github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= +github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= +github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= +github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= +github.com/pires/go-proxyproto v0.11.0 h1:gUQpS85X/VJMdUsYyEgyn59uLJvGqPhJV5YvG68wXH4= +github.com/pires/go-proxyproto v0.11.0/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a h1:cgqrm0F3zwf9IPzca7xN4w+Zy6MC9ZkPvAC8QEWa/iQ= +github.com/polydawn/refmt v0.89.1-0.20231129105047-37766d95467a/go.mod h1:ocZfO/tLSHqfScRDNTJbAJR1by4D1lewauX9OwTaPuY= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/exporter-toolkit v0.16.0 h1:xT/j7L2XKF+VJd6B4fpUw6xWabHrSmsUf6mYmFqyu0s= +github.com/prometheus/exporter-toolkit v0.16.0/go.mod h1:d1EL8Z9674xQe/iWhwP2wDyCEoBPbXVeqDbqAUsgJWY= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= +github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/slok/go-http-metrics v0.13.0 h1:lQDyJJx9wKhmbliyUsZ2l6peGnXRHjsjoqPt5VYzcP8= +github.com/slok/go-http-metrics v0.13.0/go.mod h1:HIr7t/HbN2sJaunvnt9wKP9xoBBVZFo1/KiHU3b0w+4= +github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb h1:Ywfo8sUltxogBpFuMOFRrrSifO788kAFxmvVw31PtQQ= +github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb/go.mod h1:ikPs9bRWicNw3S7XpJ8sK/smGwU9WcSVU3dy9qahYBM= +github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= +github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= +github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= +github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= +github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= +github.com/whyrusleeping/cbor-gen v0.3.1 h1:82ioxmhEYut7LBVGhGq8xoRkXPLElVuh5mV67AFfdv0= +github.com/whyrusleeping/cbor-gen v0.3.1/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= +github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= +github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= +github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= +github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= +github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= +github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= +github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= +github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= +go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= +go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= +go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= +go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= +go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U= +go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa h1:efT73AJZfAAUV7SOip6pWGkwJDzIGiKBZGVzHYa+ve4= +golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa/go.mod h1:kHjTxDEnAu6/Nl9lDkzjWpR+bmKfxeiRuSDlsMb70gE= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= +lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/test/autotls/harness.go b/test/autotls/harness.go new file mode 100644 index 00000000000..bce92f3547f --- /dev/null +++ b/test/autotls/harness.go @@ -0,0 +1,264 @@ +package autotls + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "log" + "math/big" + "net" + "net/http" + "os" + "testing" + "time" + + "github.com/coredns/caddy" + "github.com/coredns/coredns/core/dnsserver" + + pebbleCA "github.com/letsencrypt/pebble/v2/ca" + pebbleDB "github.com/letsencrypt/pebble/v2/db" + pebbleVA "github.com/letsencrypt/pebble/v2/va" + pebbleWFE "github.com/letsencrypt/pebble/v2/wfe" + + p2pforge "github.com/ipshipyard/p2p-forge/client" + + // Load CoreDNS + p2p-forge plugins (ipparser, acme). + _ "github.com/ipshipyard/p2p-forge/plugins" +) + +// Stack is an in-process pairing of Pebble (ACME server) and p2p-forge +// (registration HTTP endpoint + DNS server). It exists so the AutoTLS E2E +// canary can drive a real kubo daemon through the full cert-issuance flow +// without touching the public internet. +// +// Lifetimes are owned by the test: call Close (registered via t.Cleanup) +// when done. +type Stack struct { + // ForgeRegistrationEndpoint goes into AutoTLS.RegistrationEndpoint. + // The URL carries the production-shaped hostname (so the PeerID-auth + // signature scope matches what the forge server checks) plus the + // ?dial=/?dns= overrides that point the daemon at our loopback + // listeners. See docs/config.md for the full syntax. + ForgeRegistrationEndpoint string + + // ACMEEndpoint is Pebble's directory URL, for AutoTLS.CAEndpoint. + ACMEEndpoint string + + // PebbleCAPEM is the trust anchor for Pebble's HTTPS listener, for + // AutoTLS.TrustedCARootsPEM. Different from the issuance root below; + // kubo uses this only to authenticate the ACME directory connection. + PebbleCAPEM string + + // PebbleIssuanceRootPEM is the trust anchor for the certs Pebble + // issues. The canary's HTTPS client uses it to verify the AutoTLS + // cert kubo serves on /tls/http. + PebbleIssuanceRootPEM string + + // ForgeDomain is the suffix p2p-forge issues certs under. The canary + // uses a private .test suffix to avoid colliding with public DNS. + ForgeDomain string + + // ForgeAuthToken is the value of the registration endpoint's bearer + // token, also published to the forge process via p2pforge.ForgeAuthEnv. + ForgeAuthToken string + + close func() // shuts down both servers; idempotent via Stack.Close. +} + +// Close shuts down both servers. Safe to call multiple times. +func (s *Stack) Close() { + if s.close != nil { + s.close() + s.close = nil + } +} + +// NewStack stands up Pebble and p2p-forge on free local ports. Returns a +// Stack populated with the endpoint URLs and trust material the kubo +// daemon needs to talk to them. The setup mirrors the canonical pattern +// used in p2p-forge's own end-to-end test (e2e_test.go in that repo) so a +// regression in either layer surfaces here. +func NewStack(t *testing.T) *Stack { + t.Helper() + + const ( + forgeDomain = "libp2p.test" + forgeRegHost = "registration.libp2p.test" + forgeAuthToken = "test-token" + ) + + // p2p-forge reads its auth token from this env var. Pebble skips its + // random 0-15s VA sleep when PEBBLE_VA_NOSLEEP is set; without that + // the canary spends most of its budget idle. We restore both on + // cleanup so other parallel tests don't observe a leak. + prevAuth, hadAuth := setEnv(t, p2pforge.ForgeAuthEnv, forgeAuthToken) + prevNoSleep, hadNoSleep := setEnv(t, "PEBBLE_VA_NOSLEEP", "1") + + // Reserve a port for the forge HTTP registration endpoint. The + // acme plugin will bind it a moment later; reserving up-front lets + // the Corefile reference a known port. + tmpListener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("reserve forge http port: %v", err) + } + httpPort := tmpListener.Addr().(*net.TCPAddr).Port + _ = tmpListener.Close() + + // Reserve one port for DNS so CoreDNS binds the same port on UDP and + // TCP. With .:0 the OS hands each protocol an independent random + // port, and Pebble's VA fails when it retries TXT lookups over TCP. + tmpUDP, err := net.ListenPacket("udp", "127.0.0.1:0") + if err != nil { + t.Fatalf("reserve forge dns port: %v", err) + } + dnsPort := tmpUDP.LocalAddr().(*net.UDPAddr).Port + _ = tmpUDP.Close() + + // Configure the CoreDNS instance p2p-forge runs on. The ipparser + // plugin resolves . from the embedded IP; the + // acme plugin owns the DNS-01 TXT records and the HTTP registration + // endpoint. + tmpDir := t.TempDir() + dnsserver.Directives = []string{"log", "whoami", "startup", "shutdown", "ipparser", "acme"} + corefile := fmt.Sprintf(`.:%[5]d { + log + ipparser %[1]s + acme %[1]s { + registration-domain %[2]s listen-address=:%[3]d external-tls=true + database-type badger %[4]s + } + }`, forgeDomain, forgeRegHost, httpPort, tmpDir, dnsPort) + dnsInstance, err := caddy.Start(&corefileInput{body: []byte(corefile)}) + if err != nil { + t.Fatalf("start p2p-forge (caddy): %v", err) + } + // dnsAddr is what Pebble's VA and the kubo daemon's pre-flight check + // both dial; same port on UDP and TCP (see reservation above). + dnsAddr := fmt.Sprintf("127.0.0.1:%d", dnsPort) + + // Stand up Pebble. The VA needs the forge DNS server's address so it + // can resolve the DNS-01 TXT records p2p-forge publishes. + pebbleLogger := log.New(os.Stderr, "pebble: ", log.LstdFlags) + db := pebbleDB.NewMemoryStore() + // ocspResponderURL="" (none), keyAlg="ecdsa" (Pebble panics on + // empty), 1 alternate root, chain length 1 (Pebble requires at + // least one intermediate). One issuance profile so wfe.NewOrder's + // random-profile pick doesn't Intn(0)-panic. + profiles := map[string]pebbleCA.Profile{ + "shortlived": { + Description: "Pebble test profile", + ValidityPeriod: 7 * 24 * 60 * 60, // seconds + }, + } + ca := pebbleCA.New(pebbleLogger, db, "", "ecdsa", 1, 1, profiles) + va := pebbleVA.New(pebbleLogger, 0, 0, false, dnsAddr, db) + // nil caaIdentities skips CAA checks (we have no DNS CAA records for + // libp2p.test anyway). strict=false, requireEAB=false, retryAfter + // values match Pebble's defaults. + wfe := pebbleWFE.New(pebbleLogger, db, va, ca, nil, false, false, 3, 5) + + // Pebble's ACME endpoint must speak HTTPS. The self-signed cert + // below is what AutoTLS.TrustedCARootsPEM teaches kubo's certmagic + // to trust. + pebbleCertPEM, pebbleKeyPEM, err := generateLoopbackCert("127.0.0.1") + if err != nil { + t.Fatalf("pebble self-signed cert: %v", err) + } + pebbleCert, err := tls.X509KeyPair(pebbleCertPEM, pebbleKeyPEM) + if err != nil { + t.Fatalf("load pebble cert: %v", err) + } + acmeListener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("listen pebble: %v", err) + } + tlsListener := tls.NewListener(acmeListener, &tls.Config{Certificates: []tls.Certificate{pebbleCert}}) + acmeServer := &http.Server{Handler: wfe.Handler()} + go func() { _ = acmeServer.Serve(tlsListener) }() + + stack := &Stack{ + ForgeRegistrationEndpoint: fmt.Sprintf("http://%s/?dial=127.0.0.1:%d&dns=%s", forgeRegHost, httpPort, dnsAddr), + ACMEEndpoint: fmt.Sprintf("https://%s%s", acmeListener.Addr(), pebbleWFE.DirectoryPath), + PebbleCAPEM: string(pebbleCertPEM), + PebbleIssuanceRootPEM: string(ca.GetRootCert(0).PEM()), + ForgeDomain: forgeDomain, + ForgeAuthToken: forgeAuthToken, + close: func() { + _ = acmeServer.Close() + _ = dnsInstance.Stop() + dnsInstance.Wait() + restoreEnv(p2pforge.ForgeAuthEnv, prevAuth, hadAuth) + restoreEnv("PEBBLE_VA_NOSLEEP", prevNoSleep, hadNoSleep) + }, + } + t.Cleanup(stack.Close) + return stack +} + +// setEnv sets key=val for the duration of the test, returning the previous +// value (if any) so a paired restoreEnv call can put it back on cleanup. We +// roll our own instead of t.Setenv because the canary uses t.Parallel. +func setEnv(t *testing.T, key, val string) (prev string, had bool) { + t.Helper() + prev, had = os.LookupEnv(key) + if err := os.Setenv(key, val); err != nil { + t.Fatalf("set %s: %v", key, err) + } + return prev, had +} + +// restoreEnv puts an environment variable back to the value setEnv saw. +func restoreEnv(key, prev string, had bool) { + if had { + _ = os.Setenv(key, prev) + } else { + _ = os.Unsetenv(key) + } +} + +// generateLoopbackCert produces a self-signed cert + private key covering +// the supplied IP. Used for Pebble's HTTPS listener; kubo's certmagic +// trusts this cert via AutoTLS.TrustedCARootsPEM. +func generateLoopbackCert(ipAddr string) ([]byte, []byte, error) { + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, nil, err + } + serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + if err != nil { + return nil, nil, err + } + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{Organization: []string{"kubo autotls e2e"}}, + NotBefore: time.Now().Add(-time.Hour), + NotAfter: time.Now().Add(24 * time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IPAddresses: []net.IP{net.ParseIP(ipAddr)}, + } + der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &priv.PublicKey, priv) + if err != nil { + return nil, nil, err + } + certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}) + keyDER, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return nil, nil, err + } + keyPEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER}) + return certPEM, keyPEM, nil +} + +// corefileInput implements the caddy.Input interface around a raw Corefile. +type corefileInput struct{ body []byte } + +func (i *corefileInput) Body() []byte { return i.body } +func (i *corefileInput) Path() string { return "Corefile" } +func (i *corefileInput) ServerType() string { return "dns" } From c05a05325ac833ac86ef08963f3576dbe958f71f Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 21:36:35 +0200 Subject: [PATCH 09/16] test(httpprovider): CLI tests + migrate flag Adds two CLI test files exercising the HTTPProvider transports: - TestHTTPProvider covers the plain-HTTP and h2c paths on the swarm port (HTTP/1.1, h2c, WSS upgrade still works, well-known/libp2p/protocols, refusal to serve deserialized responses). - TestHTTPProviderAutoTLS covers the AutoTLS HTTPS path: h2 over TLS, rejection of h1 over TLS, well-known served, /tls/http multiaddr announced. Also migrates the two pre-existing tests that still set the removed Experimental.GatewayOverLibp2p flag (which the daemon now refuses to start with) over to HTTPProvider.Enabled + HTTPProvider.Libp2p, and renames the GatewayOverLibp2p subtest in content_blocking_test.go to HTTPProviderLibp2p. --- test/cli/content_blocking_test.go | 22 +- test/cli/daemon_test.go | 7 +- test/cli/http_provider_autotls_test.go | 218 +++++++++++++++++++ test/cli/http_provider_test.go | 284 +++++++++++++++++++++++++ 4 files changed, 517 insertions(+), 14 deletions(-) create mode 100644 test/cli/http_provider_autotls_test.go create mode 100644 test/cli/http_provider_test.go diff --git a/test/cli/content_blocking_test.go b/test/cli/content_blocking_test.go index 27618d7d616..32966768ce0 100644 --- a/test/cli/content_blocking_test.go +++ b/test/cli/content_blocking_test.go @@ -71,11 +71,12 @@ func TestContentBlocking(t *testing.T) { os.Setenv("IPFS_NS_MAP", "blocked-cid.example.com:/ipfs/"+blockedCID+",blocked-dnslink.example.com/ipns/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn") defer os.Unsetenv("IPFS_NS_MAP") - // Enable GatewayOverLibp2p as we want to test denylist there too - node.IPFS("config", "--json", "Experimental.GatewayOverLibp2p", "true") + // Enable HTTPProvider.Libp2p so the denylist is exercised on that transport too. + node.IPFS("config", "--json", "HTTPProvider.Enabled", "true") + node.IPFS("config", "--json", "HTTPProvider.Libp2p", "true") // Start daemon, it should pick up denylist from $IPFS_PATH/denylists/test.deny - node.StartDaemon() // we need online mode for GatewayOverLibp2p tests + node.StartDaemon() // online mode is needed for HTTPProvider.Libp2p tests t.Cleanup(func() { node.StopDaemon() }) client := node.GatewayClient() @@ -304,14 +305,13 @@ func TestContentBlocking(t *testing.T) { client = node.GatewayClient() }) - // We need to confirm denylist is active on the - // trustless gateway exposed over libp2p - // when Experimental.GatewayOverLibp2p=true - // (https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#http-gateway-over-libp2p) - // NOTE: this type of gateway is hardcoded to be NoFetch: it does not fetch - // data that is not in local store, so we only need to run it once: a - // simple smoke-test for allowed CID and blockedCID. - t.Run("GatewayOverLibp2p", func(t *testing.T) { + // Confirm the denylist is active on the trustless gateway exposed + // over libp2p when HTTPProvider.Libp2p=true (see + // https://github.com/ipfs/kubo/blob/master/docs/config.md#httpproviderlibp2p). + // This transport is hardcoded to NoFetch: it does not fetch data that + // is not in the local blockstore, so a single smoke test of an + // allowed CID and the blockedCID is enough. + t.Run("HTTPProviderLibp2p", func(t *testing.T) { t.Parallel() // Create libp2p client that connects to our node over diff --git a/test/cli/daemon_test.go b/test/cli/daemon_test.go index f87a2165148..6f3090b7f7c 100644 --- a/test/cli/daemon_test.go +++ b/test/cli/daemon_test.go @@ -41,9 +41,10 @@ func TestDaemon(t *testing.T) { // Enable experimental features and pubsub via config node.UpdateConfig(func(cfg *config.Config) { - cfg.Pubsub.Enabled = config.True // Instead of --enable-pubsub-experiment - cfg.Experimental.P2pHttpProxy = true // Enable P2P HTTP proxy - cfg.Experimental.GatewayOverLibp2p = true // Enable gateway over libp2p + cfg.Pubsub.Enabled = config.True // Instead of --enable-pubsub-experiment + cfg.Experimental.P2pHttpProxy = true // Enable P2P HTTP proxy + cfg.HTTPProvider.Enabled = config.True + cfg.HTTPProvider.Libp2p = config.True // Serve gateway over libp2p stream }) node.StartDaemon("--enable-gc") diff --git a/test/cli/http_provider_autotls_test.go b/test/cli/http_provider_autotls_test.go new file mode 100644 index 00000000000..b29b6d4c779 --- /dev/null +++ b/test/cli/http_provider_autotls_test.go @@ -0,0 +1,218 @@ +package cli + +import ( + "crypto/tls" + "encoding/json" + "fmt" + "net" + "net/http" + "strings" + "testing" + "time" + + gws "github.com/gorilla/websocket" + "github.com/ipfs/go-cid" + "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/test/cli/harness" + "github.com/multiformats/go-multiaddr" + "github.com/stretchr/testify/require" + "golang.org/x/net/http2" +) + +// TestHTTPProviderAutoTLS exercises the AutoTLS HTTPS path of HTTPProvider +// using a self-signed test cert (AutoTLS.SelfSignedForTests=true). Test +// clients pair this with InsecureSkipVerify to skip cert chain validation. +// +// The full p2p-forge + ACME chain is covered separately by the canary in +// http_provider_autotls_e2e_test.go; the cases here focus on listener +// wiring, the kubo-side h2-over-TLS policy, and the multiaddr/well-known +// surfaces that browsers and HTTP retrieval clients depend on. +func TestHTTPProviderAutoTLS(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init() + gwNode := nodes[0] + otherNode := nodes[1] + + // Add a /tls/ws listener. AutoWSS normally adds /tls/sni//ws + // for AutoTLS; the test bypasses AutoTLS in favour of the + // SelfSignedForTests path, so a plain /tls/ws is enough. The client + // uses InsecureSkipVerify, so SNI is decorative. + gwNode.UpdateConfig(func(cfg *config.Config) { + cfg.Addresses.Swarm = append(cfg.Addresses.Swarm, + "/ip4/127.0.0.1/tcp/0/tls/ws") + cfg.AutoTLS.Enabled = config.False + cfg.AutoTLS.SelfSignedForTests = config.True + cfg.HTTPProvider.Enabled = config.True + }) + + nodes.StartDaemons().Connect() + defer nodes.StopDaemons() + t.Cleanup(func() { gwNode.StopDaemon() }) + + cidLocal := cid.MustParse(gwNode.IPFSAddStr("Hello AutoTLS HTTPProvider!")) + expectedRawBlock := []byte(gwNode.GatewayClient().Get( + fmt.Sprintf("/ipfs/%s?format=raw", cidLocal), + ).Body) + cidRemote := cid.MustParse(otherNode.IPFSAddStr("not on the gateway")) + + hostPort := findTLSWSListenHostPort(t, gwNode) + // SNI must match the cert's wildcard SAN; the listener was configured + // to match the example.libp2p.direct subdomain. + const tlsServerName = "example.libp2p.direct" + baseURL := "https://" + tlsServerName + ":" + portOf(t, hostPort) + dialAddr := hostPort // raw IP:port we actually dial + + t.Run("ServeBlock_HTTPSh2", func(t *testing.T) { + // h2 over TLS: the gateway handler returns the raw block. + resp := mustGetHTTPS(t, baseURL+"/ipfs/"+cidLocal.String()+"?format=raw", + []string{"h2", "http/1.1"}, dialAddr, tlsServerName) + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, "HTTP/2.0", resp.Proto) + require.Equal(t, "application/vnd.ipld.raw", resp.Header.Get("Content-Type")) + require.Equal(t, expectedRawBlock, mustReadBody(t, resp)) + }) + + t.Run("HTTP1OverTLSRejected", func(t *testing.T) { + // kubo's RequireHTTP2OverTLS policy: HTTP/1.1 over TLS is + // reserved for the WebSocket upgrade. Plain h1 GET gets 426 + // with an Upgrade header pointing the client at h2 or + // websocket. + resp := mustGetHTTPS(t, baseURL+"/ipfs/"+cidLocal.String()+"?format=raw", + []string{"http/1.1"}, dialAddr, tlsServerName) + require.Equal(t, http.StatusUpgradeRequired, resp.StatusCode) + require.Contains(t, resp.Header.Values("Upgrade"), "h2,websocket") + }) + + t.Run("WSSUpgradeStillWorks", func(t *testing.T) { + // Browser-equivalent path: ALPN http/1.1 only, classic + // WebSocket Upgrade. Must complete with 101 Switching + // Protocols even when the listener also serves HTTP/2 GETs. + dialer := gws.Dialer{ + NetDial: func(network, _ string) (net.Conn, error) { + return net.Dial(network, dialAddr) + }, + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + ServerName: tlsServerName, + NextProtos: []string{"http/1.1"}, + }, + HandshakeTimeout: 5 * time.Second, + } + conn, resp, err := dialer.Dial("wss://"+tlsServerName+":"+portOf(t, hostPort)+"/", nil) + require.NoError(t, err) + require.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode) + require.NoError(t, conn.Close()) + }) + + t.Run("WillNotServeRemoteContent", func(t *testing.T) { + resp := mustGetHTTPS(t, baseURL+"/ipfs/"+cidRemote.String()+"?format=raw", + []string{"h2"}, dialAddr, tlsServerName) + require.Equal(t, http.StatusNotFound, resp.StatusCode) + }) + + t.Run("ServesWellKnownProtocolsOverHTTPS", func(t *testing.T) { + resp := mustGetHTTPS(t, baseURL+"/.well-known/libp2p/protocols", + []string{"h2"}, dialAddr, tlsServerName) + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, "application/json", resp.Header.Get("Content-Type")) + var doc map[string]map[string]string + require.NoError(t, json.Unmarshal(mustReadBody(t, resp), &doc)) + require.Contains(t, doc, "/ipfs/gateway") + }) + + t.Run("AnnouncesTLSHTTPMultiaddr", func(t *testing.T) { + announced := announcedAddrs(t, gwNode) + var tlsWS, tlsHTTP []multiaddr.Multiaddr + for _, a := range announced { + s := a.String() + switch { + case strings.HasSuffix(s, "/tls/ws") || + strings.Contains(s, "/tls/sni/") && strings.HasSuffix(s, "/ws"): + tlsWS = append(tlsWS, a) + case strings.HasSuffix(s, "/tls/http") || + strings.Contains(s, "/tls/sni/") && strings.HasSuffix(s, "/http"): + tlsHTTP = append(tlsHTTP, a) + } + } + require.NotEmpty(t, tlsWS, "expected at least one /tls/ws in announced addrs") + require.Equal(t, len(tlsWS), len(tlsHTTP), + "every announced /tls/ws should have a sibling /tls/http (ws=%v http=%v)", + addrStrings(tlsWS), addrStrings(tlsHTTP)) + }) +} + +// findTLSWSListenHostPort returns "host:port" for a /tls/ws listener (in any +// of its forms: /tls/ws, /tls/sni//ws). The TCP port is what we dial; +// the SNI is set separately on the TLS client config. +func findTLSWSListenHostPort(t *testing.T, n *harness.Node) string { + t.Helper() + for _, a := range n.SwarmAddrs() { + s := a.String() + if !strings.HasSuffix(s, "/ws") || !strings.Contains(s, "/tls/") { + continue + } + host, err := a.ValueForProtocol(multiaddr.P_IP4) + require.NoError(t, err) + port, err := a.ValueForProtocol(multiaddr.P_TCP) + require.NoError(t, err) + return net.JoinHostPort(host, port) + } + t.Fatalf("no /tls/ws listener found on node %d; addrs=%v", n.ID, addrStrings(n.SwarmAddrs())) + return "" +} + +// portOf extracts the port from a host:port string. +func portOf(t *testing.T, hostPort string) string { + t.Helper() + _, port, err := net.SplitHostPort(hostPort) + require.NoError(t, err) + return port +} + +// mustGetHTTPS issues a TLS GET, dialing dialAddr (raw IP:port) but +// presenting tlsServerName as SNI and Host. ALPN is restricted to +// nextProtos so tests can pin which HTTP version they want negotiated. +// InsecureSkipVerify is on because the daemon serves a self-signed cert. +func mustGetHTTPS(t *testing.T, url string, nextProtos []string, dialAddr, tlsServerName string) *http.Response { + t.Helper() + tlsConf := &tls.Config{ + InsecureSkipVerify: true, + ServerName: tlsServerName, + NextProtos: nextProtos, + } + dialContext := func(network, _ string) (net.Conn, error) { + return net.Dial(network, dialAddr) + } + var rt http.RoundTripper + switch { + case len(nextProtos) > 0 && nextProtos[0] == "h2": + // HTTP/2 only. + rt = &http2.Transport{ + TLSClientConfig: tlsConf, + DialTLS: func(network, _ string, cfg *tls.Config) (net.Conn, error) { + raw, err := dialContext(network, "") + if err != nil { + return nil, err + } + tlsConn := tls.Client(raw, cfg) + if err := tlsConn.Handshake(); err != nil { + _ = raw.Close() + return nil, err + } + return tlsConn, nil + }, + } + default: + // HTTP/1.1 (or h2/h1 with ALPN selection). + rt = &http.Transport{ + ForceAttemptHTTP2: false, + TLSClientConfig: tlsConf, + Dial: dialContext, + } + } + c := &http.Client{Transport: rt, Timeout: 10 * time.Second} + resp, err := c.Get(url) + require.NoError(t, err) + t.Cleanup(func() { _ = resp.Body.Close() }) + return resp +} diff --git a/test/cli/http_provider_test.go b/test/cli/http_provider_test.go new file mode 100644 index 00000000000..de1e977aaa3 --- /dev/null +++ b/test/cli/http_provider_test.go @@ -0,0 +1,284 @@ +package cli + +import ( + "context" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "strings" + "testing" + "time" + + gws "github.com/gorilla/websocket" + "github.com/ipfs/go-cid" + "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/test/cli/harness" + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/peer" + libp2phttp "github.com/libp2p/go-libp2p/p2p/http" + "github.com/multiformats/go-multiaddr" + "github.com/stretchr/testify/require" + "golang.org/x/net/http2" +) + +// TestHTTPProvider exercises the cleartext HTTP transport of the HTTPProvider +// feature: the trustless gateway handler reachable over plain /ws and /http +// on the same TCP port shared with libp2p WebSocket traffic. The TLS path is +// covered separately in http_provider_autotls_test.go. +func TestHTTPProvider(t *testing.T) { + t.Parallel() + nodes := harness.NewT(t).NewNodes(2).Init() + gwNode := nodes[0] + otherNode := nodes[1] + + // Add a cleartext /ws listener on the gateway node so the HTTPProvider + // handler has somewhere to live without needing AutoTLS in this test. + // Sharing port 0 with the existing /tcp/0 means tcpreuse routes raw + // libp2p, plain HTTP, and h2c into the same socket — the production + // layout, just without TLS. + gwNode.UpdateConfig(func(cfg *config.Config) { + cfg.Addresses.Swarm = append(cfg.Addresses.Swarm, "/ip4/127.0.0.1/tcp/0/ws") + }) + + nodes.StartDaemons().Connect() + defer nodes.StopDaemons() + + // Add data on the gateway node and capture the local raw block so + // later byte-by-byte comparisons are exact. + cidLocal := cid.MustParse(gwNode.IPFSAddStr("Hello HTTPProvider!")) + expectedRawBlock := []byte(gwNode.GatewayClient().Get( + fmt.Sprintf("/ipfs/%s?format=raw", cidLocal), + ).Body) + + // And on the other node, so we have a CID the gateway does NOT have + // locally for the NoFetch test. + cidRemote := cid.MustParse(otherNode.IPFSAddStr("not on the gateway")) + + wsHostPort := findWSListenHostPort(t, gwNode) + baseURL := "http://" + wsHostPort + + t.Run("DoesNotWorkWithoutHTTPProvider", func(t *testing.T) { + // HTTPProvider is off by default; the listener answers 404 for + // non-WebSocket requests because no fallback handler is wired. + resp := mustGetH1(t, baseURL+"/ipfs/"+cidLocal.String()+"?format=raw") + require.Equal(t, http.StatusNotFound, resp.StatusCode, + "non-upgrade HTTP requests must 404 until HTTPProvider is enabled") + }) + + // Enable HTTPProvider and restart so FX picks up the handler. + gwNode.IPFS("config", "--json", "HTTPProvider.Enabled", "true") + gwNode.StopDaemon().StartDaemon() + t.Cleanup(func() { gwNode.StopDaemon() }) + nodes.Connect() + + // Refresh: the random port may differ across daemon restarts. + wsHostPort = findWSListenHostPort(t, gwNode) + baseURL = "http://" + wsHostPort + + t.Run("WillNotServeRemoteContent", func(t *testing.T) { + // NoFetch invariant: the gateway node does not have cidRemote + // locally and must not reach out to fetch it. + resp := mustGetH1(t, baseURL+"/ipfs/"+cidRemote.String()+"?format=raw") + require.Equal(t, http.StatusNotFound, resp.StatusCode) + }) + + t.Run("WillNotServeDeserializedResponses", func(t *testing.T) { + // DeserializedResponses=false invariant: a request without + // ?format=raw|car asks for deserialized UnixFS, which the + // trustless gateway refuses. + resp := mustGetH1(t, baseURL+"/ipfs/"+cidLocal.String()) + require.Equal(t, http.StatusNotAcceptable, resp.StatusCode) + }) + + t.Run("ServeBlock_HTTP1", func(t *testing.T) { + resp := mustGetH1(t, baseURL+"/ipfs/"+cidLocal.String()+"?format=raw") + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, "HTTP/1.1", resp.Proto) + require.Equal(t, "application/vnd.ipld.raw", resp.Header.Get("Content-Type")) + require.Equal(t, expectedRawBlock, mustReadBody(t, resp)) + }) + + t.Run("ServeBlock_H2C", func(t *testing.T) { + // Reverse-proxy interop: h2c gives multiplexing without TLS. + resp := mustGetH2C(t, baseURL+"/ipfs/"+cidLocal.String()+"?format=raw") + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, "HTTP/2.0", resp.Proto) + require.Equal(t, "application/vnd.ipld.raw", resp.Header.Get("Content-Type")) + require.Equal(t, expectedRawBlock, mustReadBody(t, resp)) + }) + + t.Run("ServesWellKnownProtocols", func(t *testing.T) { + // libp2p Gateway spec advertisement, reachable from any HTTP + // client without opening a libp2p stream. + resp := mustGetH1(t, baseURL+"/.well-known/libp2p/protocols") + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, "application/json", resp.Header.Get("Content-Type")) + var doc map[string]map[string]string + require.NoError(t, json.Unmarshal(mustReadBody(t, resp), &doc)) + require.Contains(t, doc, "/ipfs/gateway") + require.Equal(t, "/", doc["/ipfs/gateway"]["path"]) + }) + + t.Run("WSUpgradeStillWorks", func(t *testing.T) { + // The fallback handler must not break the original libp2p WS + // upgrade. A 101 Switching Protocols is enough; we don't + // complete the libp2p multistream handshake here. + dialer := gws.Dialer{HandshakeTimeout: 5 * time.Second} + conn, resp, err := dialer.Dial("ws://"+wsHostPort+"/", nil) + require.NoError(t, err) + require.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode) + require.NoError(t, conn.Close()) + }) + + t.Run("AnnouncesHTTPMultiaddr", func(t *testing.T) { + // /http must appear next to every announced /ws. + // AnnounceMultiaddrs defaults to true when HTTPProvider.Enabled + // is true. Read announced (not just listening) addresses via + // `ipfs id`; the /http multiaddr is purely an announcement and + // has no socket of its own. + announced := announcedAddrs(t, gwNode) + var wsAddrs, httpAddrs []multiaddr.Multiaddr + for _, a := range announced { + s := a.String() + switch { + case strings.HasSuffix(s, "/ws"): + wsAddrs = append(wsAddrs, a) + case strings.HasSuffix(s, "/http"): + httpAddrs = append(httpAddrs, a) + } + } + require.NotEmpty(t, wsAddrs, "expected at least one /ws in announced addrs") + require.Equal(t, len(wsAddrs), len(httpAddrs), + "every announced /ws should have a sibling /http (ws=%v http=%v)", + addrStrings(wsAddrs), addrStrings(httpAddrs)) + }) + + t.Run("ServesWellKnownOverLibp2pStream", func(t *testing.T) { + // Sanity check that the libp2p-stream gateway also lands the + // gateway handler over the discovered protocol path. Mirrors + // http_provider_over_libp2p_test.go's libp2p-client subtest + // but uses libp2phttp's NamespacedClient discovery. + clientHost, err := libp2p.New(libp2p.NoListenAddrs) + require.NoError(t, err) + t.Cleanup(func() { _ = clientHost.Close() }) + require.NoError(t, clientHost.Connect(context.Background(), peer.AddrInfo{ + ID: gwNode.PeerID(), + Addrs: gwNode.SwarmAddrs(), + })) + client, err := (&libp2phttp.Host{StreamHost: clientHost}). + NamespacedClient("/ipfs/gateway", peer.AddrInfo{ID: gwNode.PeerID()}) + require.NoError(t, err) + resp, err := client.Get(fmt.Sprintf("/ipfs/%s?format=raw", cidLocal)) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, http.StatusOK, resp.StatusCode) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + require.Equal(t, expectedRawBlock, body) + }) +} + +// findWSListenHostPort returns "host:port" for any /tcp/N/ws listener bound +// by the node. Auto-appended /ws shares the TCP port with raw /tcp/N via +// tcpreuse, so any matching listener is a fine target. +func findWSListenHostPort(t *testing.T, n *harness.Node) string { + t.Helper() + for _, a := range n.SwarmAddrs() { + s := a.String() + // Match exactly /tcp//ws (cleartext); skip /tls/ws etc. + if !strings.HasSuffix(s, "/ws") || strings.Contains(s, "/tls/") || strings.Contains(s, "/wss") { + continue + } + host, err := a.ValueForProtocol(multiaddr.P_IP4) + require.NoError(t, err) + port, err := a.ValueForProtocol(multiaddr.P_TCP) + require.NoError(t, err) + return net.JoinHostPort(host, port) + } + t.Fatalf("no cleartext /ws listener found on node %d; addrs=%v", n.ID, addrStrings(n.SwarmAddrs())) + return "" +} + +// announcedAddrs returns the multiaddrs this node advertises via identify +// (output of `ipfs id`), which is what other peers see in the DHT and via +// peer-routing. Differs from SwarmAddrs() in that it includes addresses +// that are advertised but not bound (the HTTPProvider /http multiaddr is +// the canonical example). +func announcedAddrs(t *testing.T, n *harness.Node) []multiaddr.Multiaddr { + t.Helper() + out := n.IPFS("id", "--enc=json").Stdout.String() + var idDoc struct { + Addresses []string `json:"Addresses"` + } + require.NoError(t, json.Unmarshal([]byte(out), &idDoc)) + addrs := make([]multiaddr.Multiaddr, 0, len(idDoc.Addresses)) + for _, s := range idDoc.Addresses { + // Strip the trailing /p2p/ wrapper for easier suffix + // matching downstream. + if i := strings.Index(s, "/p2p/"); i >= 0 { + s = s[:i] + } + a, err := multiaddr.NewMultiaddr(s) + if err != nil { + t.Fatalf("parse announced addr %q: %s", s, err) + } + addrs = append(addrs, a) + } + return addrs +} + +// addrStrings is a small log-friendly view of a multiaddr slice. +func addrStrings(addrs []multiaddr.Multiaddr) []string { + out := make([]string, len(addrs)) + for i, a := range addrs { + out[i] = a.String() + } + return out +} + +// mustGetH1 performs a plain HTTP/1.1 GET. Caller must close resp.Body. +func mustGetH1(t *testing.T, url string) *http.Response { + t.Helper() + tr := &http.Transport{ + // Force HTTP/1.1: an empty NextProtos in TLS skips ALPN, but + // for cleartext h1 is the default. + } + defer tr.CloseIdleConnections() + c := &http.Client{Transport: tr, Timeout: 10 * time.Second} + resp, err := c.Get(url) + require.NoError(t, err) + t.Cleanup(func() { _ = resp.Body.Close() }) + return resp +} + +// mustGetH2C performs a prior-knowledge HTTP/2 cleartext (h2c) GET. The +// AllowHTTP+DialTLSContext combo is the canonical way to drive h2c from a +// Go client — it tells http2.Transport to skip ALPN negotiation and assume +// the server speaks h2c on the wire. +func mustGetH2C(t *testing.T, url string) *http.Response { + t.Helper() + tr := &http2.Transport{ + AllowHTTP: true, + DialTLSContext: func(_ context.Context, network, addr string, _ *tls.Config) (net.Conn, error) { + return net.Dial(network, addr) + }, + } + defer tr.CloseIdleConnections() + c := &http.Client{Transport: tr, Timeout: 10 * time.Second} + resp, err := c.Get(url) + require.NoError(t, err) + t.Cleanup(func() { _ = resp.Body.Close() }) + return resp +} + +// mustReadBody drains and returns the response body. +func mustReadBody(t *testing.T, resp *http.Response) []byte { + t.Helper() + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + return body +} + From 552aea946c53e5df81eacd4ae8e68f101c7d9f82 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 21:41:59 +0200 Subject: [PATCH 10/16] fix(httpprovider): always install AutoWSS handler serveHTTPProviderOverLibp2p early-returned when HTTPProvider.Libp2p was off and so skipped installing the trustless gateway handler into the AutoWSS-port placeholder. Any node with HTTPProvider.Enabled=true and Libp2p=false (typical for HTTPProvider.Cleartext-only setups) ended up serving permanent 503 Service Unavailable on /ws and /tls/ws even though the listener was up and the placeholder was wired. Restructure so the function does two independent jobs: 1. Always install the handler on the AutoWSS-port placeholder when HTTPProvider.Enabled=true. Covers AutoTLS, manually configured /ws, and HTTPProvider.Cleartext-derived /ws. 2. Then optionally start the libp2p-stream transport when HTTPProvider.Libp2p=true. Also renames the local error channel from p2pGwErrc to httpProviderErrc and replaces the now-stale "add trustless gateway over libp2p" comment. --- cmd/ipfs/kubo/daemon.go | 69 +++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/cmd/ipfs/kubo/daemon.go b/cmd/ipfs/kubo/daemon.go index dd2d2bd18fd..5a52cce473d 100644 --- a/cmd/ipfs/kubo/daemon.go +++ b/cmd/ipfs/kubo/daemon.go @@ -706,8 +706,8 @@ take effect. return err } - // add trustless gateway over libp2p - p2pGwErrc, err := serveHTTPProviderOverLibp2p(cctx) + // start the HTTPProvider libp2p-stream transport + httpProviderErrc, err := serveHTTPProviderOverLibp2p(cctx) if err != nil { return err } @@ -828,7 +828,7 @@ take effect. // collect long-running errors and block for shutdown // TODO(cryptix): our fuse currently doesn't follow this pattern for graceful shutdown var errs []error - for err := range merge(apiErrc, gwErrc, gcErrc, p2pGwErrc, pluginErrc, unmountErrc) { + for err := range merge(apiErrc, gwErrc, gcErrc, httpProviderErrc, pluginErrc, unmountErrc) { if err != nil { errs = append(errs, err) } @@ -1193,18 +1193,20 @@ func newGatewayWellKnown() *p2phttp.WellKnownHandler { return wk } -// serveHTTPProviderOverLibp2p starts the libp2p-stream transport of the -// HTTPProvider feature. It implements the libp2p Gateway specification -// (https://specs.ipfs.tech/http-gateways/libp2p-gateway/) by mounting the -// trustless gateway handler under the /ipfs/gateway libp2p protocol ID and -// advertising it through the .well-known/libp2p/protocols document on the -// libp2p+HTTP host. +// serveHTTPProviderOverLibp2p installs the HTTPProvider feature's transports +// once IpfsNode is fully constructed. It always installs the trustless +// gateway handler on the AutoWSS-port placeholder (the shared TCP path used +// by both AutoTLS and HTTPProvider.Cleartext) when HTTPProvider is enabled, +// and additionally starts the libp2p-stream transport when +// HTTPProvider.Libp2p is on, mounting the same handler under the +// /ipfs/gateway libp2p protocol ID per the libp2p Gateway specification +// (https://specs.ipfs.tech/http-gateways/libp2p-gateway/). // -// The handler is the same one used for every HTTPProvider transport: -// NoFetch (only blocks already in the local blockstore), no DNSLink, no -// HTML errors, raw blocks and CARs only. Deserialized UnixFS responses are -// not served, so clients always get content-addressed bytes they can -// verify against the requested CID. +// The handler itself is the same across transports: NoFetch (only blocks +// already in the local blockstore), no DNSLink, no HTML errors, raw blocks +// via ?format=raw only. Deserialized UnixFS responses are not served, so +// clients always get content-addressed bytes they can verify against the +// requested CID. func serveHTTPProviderOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { node, err := cctx.ConstructNode() if err != nil { @@ -1215,13 +1217,14 @@ func serveHTTPProviderOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { return nil, fmt.Errorf("could not read config: %w", err) } - // Gate on HTTPProvider.Enabled and the libp2p sub-toggle. - enableHTTPProvider := cfg.HTTPProvider.Enabled.WithDefault(config.DefaultHTTPProviderEnabled) - enableLibp2pStream := cfg.HTTPProvider.Libp2p.WithDefault(config.DefaultHTTPProviderLibp2p) - if !enableHTTPProvider || !enableLibp2pStream { + noop := func() <-chan error { errCh := make(chan error) close(errCh) - return errCh, nil + return errCh + } + + if !cfg.HTTPProvider.Enabled.WithDefault(config.DefaultHTTPProviderEnabled) { + return noop(), nil } opts := []corehttp.ServeOption{ @@ -1235,12 +1238,12 @@ func serveHTTPProviderOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { return nil, err } - // HTTPProvider: also expose the same trustless handler on the AutoTLS - // WSS port. FX provided the placeholder HTTPProvider handler when both - // HTTPProvider.Enabled and AutoTLS are on; we install the real handler - // now that IpfsNode is fully constructed. Unlike the libp2p-stream - // gateway above, this is reachable from any HTTPS client via the - // AutoTLS cert. + // Install the trustless handler on the AutoWSS-port placeholder. This + // path serves the gateway on the shared TCP port behind any /ws or + // /tls/ws listener: AutoTLS-issued /tls/http, manually configured /ws, + // and HTTPProvider.Cleartext-derived /ws. The placeholder is provided + // by FX whenever HTTPProvider.Enabled is true (see core/node/groups.go), + // independently of HTTPProvider.Libp2p below. // // The HTTPS mux also serves /.well-known/libp2p/protocols so HTTPS // clients can discover that this peer speaks /ipfs/gateway (and any @@ -1251,11 +1254,17 @@ func serveHTTPProviderOverLibp2p(cctx *oldcmds.Context) (<-chan error, error) { // modern public HTTPS endpoints, gives bitswap-httpnet multiplexing) // while the plain /ws path stays permissive for reverse-proxy interop. if node.HTTPProvider != nil { - httpsMux := http.NewServeMux() - httpsMux.Handle("/", handler) - httpsMux.Handle(p2phttp.WellKnownProtocols, newGatewayWellKnown()) - node.HTTPProvider.Set(libp2p.RequireHTTP2OverTLS(httpsMux)) - log.Info("HTTPProvider: trustless gateway exposed via AutoWSS port (h2 required over TLS, h1+h2c allowed cleartext, .well-known/libp2p/protocols served)") + mux := http.NewServeMux() + mux.Handle("/", handler) + mux.Handle(p2phttp.WellKnownProtocols, newGatewayWellKnown()) + node.HTTPProvider.Set(libp2p.RequireHTTP2OverTLS(mux)) + log.Info("HTTPProvider: trustless gateway exposed on /ws and /tls/ws TCP ports (h2 required over TLS, h1+h2c allowed cleartext, .well-known/libp2p/protocols served)") + } + + // libp2p-stream transport. Gated by the Libp2p sub-toggle, independent + // of the AutoWSS-port install above. + if !cfg.HTTPProvider.Libp2p.WithDefault(config.DefaultHTTPProviderLibp2p) { + return noop(), nil } if node.PeerHost == nil { From 04b7c9f095bc2fe7f83b1470173f3962b81741ab Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 21:42:00 +0200 Subject: [PATCH 11/16] docs(httpprovider): clarify role and changelog Documents HTTPProvider in docs/config.md (it had no section before) and adds a v0.43 changelog highlight. Two related cleanups: - Spell out the HTTPProvider vs Gateway mental model: server side (raw blocks via ?format=raw, NoFetch, swarm port, no recursion) versus the recursive loopback Gateway on 127.0.0.1:8080. Mirror "client side" framing onto HTTPRetrieval. - Replace stale "raw blocks + CARs only" doc strings in config/httpprovider.go, core/corehttp/gateway.go, and core/node/libp2p/httpprovider.go with "raw blocks via ?format=raw only". HTTPProvider does not serve CARs. Adds the gateway-conformance-http-provider-cleartext CI job and migrates the existing gateway-conformance-libp2p-experiment job off the removed Experimental.GatewayOverLibp2p flag. Updates docs/experimental-features.md to point at HTTPProvider.Libp2p (the GraphSync section's cross-reference too). --- .github/workflows/gateway-conformance.yml | 91 ++++++++++++++++++++++- config/httpprovider.go | 6 +- core/corehttp/gateway.go | 4 +- core/node/libp2p/httpprovider.go | 6 +- docs/changelogs/v0.43.md | 10 +++ docs/config.md | 87 +++++++++++++++++++++- docs/examples/kubo-as-a-library/go.mod | 2 +- docs/examples/kubo-as-a-library/go.sum | 4 +- docs/experimental-features.md | 44 ++--------- test/dependencies/go.mod | 2 +- test/dependencies/go.sum | 4 +- 11 files changed, 203 insertions(+), 57 deletions(-) diff --git a/.github/workflows/gateway-conformance.yml b/.github/workflows/gateway-conformance.yml index 20ec4c7ffda..6a289fa561b 100644 --- a/.github/workflows/gateway-conformance.yml +++ b/.github/workflows/gateway-conformance.yml @@ -151,7 +151,8 @@ jobs: run: | ./ipfs init --profile=test ./ipfs config --json Gateway.PublicGateways "$GATEWAY_PUBLIC_GATEWAYS" - ./ipfs config --json Experimental.GatewayOverLibp2p true + ./ipfs config --json HTTPProvider.Enabled true + ./ipfs config --json HTTPProvider.Libp2p true ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/8080" ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/5001" working-directory: kubo-gateway/cmd/ipfs @@ -224,3 +225,91 @@ jobs: with: name: gateway-conformance-libp2p.json path: output.json + + # Testing the trustless gateway subset exposed by HTTPProvider over plain + # HTTP/2 (h2c) on the swarm port. HTTPProvider.Cleartext auto-appends a /ws + # listener to each /tcp listener in Addresses.Swarm; HTTPProvider then + # shares the same TCP port via the shared-TCP demuxer and serves /http + # there. No libp2p proxy is needed: the conformance client connects to the + # swarm port directly. Complements the libp2p job above so both + # HTTPProvider transports are exercised end-to-end. + gateway-conformance-http-provider-cleartext: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + # 1. Download the gateway-conformance fixtures + - name: Download gateway-conformance fixtures + uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.13 + with: + output: fixtures + + # 2. Build the kubo-gateway + - name: Checkout kubo-gateway + uses: actions/checkout@v6 + with: + path: kubo-gateway + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: 'kubo-gateway/go.mod' + cache: true + cache-dependency-path: kubo-gateway/go.sum + - name: Build kubo-gateway + run: make build + working-directory: kubo-gateway + + # 3. Init the kubo-gateway with HTTPProvider.Cleartext on the swarm + # port. Libp2p is off; Cleartext is the only HTTPProvider transport + # exercised by this job. + - name: Init kubo-gateway + run: | + ./ipfs init --profile=test + ./ipfs config --json Gateway.PublicGateways "$GATEWAY_PUBLIC_GATEWAYS" + ./ipfs config --json HTTPProvider.Enabled true + ./ipfs config --json HTTPProvider.Libp2p false + ./ipfs config --json HTTPProvider.Cleartext true + ./ipfs config --json Addresses.Swarm '["/ip4/127.0.0.1/tcp/4001"]' + ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/8080" + ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/5001" + working-directory: kubo-gateway/cmd/ipfs + + # 4. Populate the Kubo gateway with the gateway-conformance fixtures + - name: Import fixtures + run: | + # Import car files + find ./fixtures -name '*.car' -exec kubo-gateway/cmd/ipfs/ipfs dag import --pin-roots=false {} \; + + # 5. Start the kubo-gateway + - name: Start kubo-gateway + run: | + ( ./ipfs daemon & ) | sed '/Daemon is ready/q' + while [[ "$(./ipfs id | jq '.Addresses | length')" == '0' ]]; do sleep 1; done + working-directory: kubo-gateway/cmd/ipfs + + # 6. Run the gateway-conformance tests over plain HTTP/2 (h2c) on the swarm port + - name: Run gateway-conformance tests over h2c + uses: ipfs/gateway-conformance/.github/actions/test@v0.13 + with: + gateway-url: http://127.0.0.1:4001 + args: --specs "trustless-gateway,-trustless-ipns-gateway" -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length' + json: output.json + xml: output.xml + html: output.html + markdown: output.md + + # 7. Upload the results + - name: Upload MD summary + if: failure() || success() + run: cat output.md >> $GITHUB_STEP_SUMMARY + - name: Upload HTML report + if: failure() || success() + uses: actions/upload-artifact@v7 + with: + name: gateway-conformance-http-provider-cleartext.html + path: output.html + - name: Upload JSON report + if: failure() || success() + uses: actions/upload-artifact@v7 + with: + name: gateway-conformance-http-provider-cleartext.json + path: output.json diff --git a/config/httpprovider.go b/config/httpprovider.go index b55fb3af9d3..6cee80038ad 100644 --- a/config/httpprovider.go +++ b/config/httpprovider.go @@ -2,9 +2,9 @@ package config // HTTPProvider configures kubo's role as an HTTP-native source of // trustless-gateway block retrieval. When Enabled, the local trustless -// gateway handler (NoFetch, raw blocks + CARs only, content-addressed -// verification client-side) is exposed for HTTP retrieval clients such as -// boxo/bitswap/network/httpnet. +// gateway handler (NoFetch, raw blocks via ?format=raw only, +// content-addressed verification client-side) is exposed for HTTP +// retrieval clients such as boxo/bitswap/network/httpnet. // // This is the server side of the HTTP retrieval story; the client side // lives separately and is configured under HTTPRetrieval. diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index 43452cdd9b6..89c40ee86f3 100644 --- a/core/corehttp/gateway.go +++ b/core/corehttp/gateway.go @@ -99,8 +99,8 @@ func Libp2pGatewayOption() ServeOption { bserv := blockservice.New(n.Blocks.Blockstore(), offline.Exchange(n.Blocks.Blockstore())) backend, err := gateway.NewBlocksBackend(bserv, - // GatewayOverLibp2p only returns things that are in local blockstore - // (same as Gateway.NoFetch=true), we have to pass offline path resolver + // HTTPProvider only returns blocks already in the local blockstore + // (same as Gateway.NoFetch=true), so we hand it the offline path resolver. gateway.WithResolver(n.OfflineUnixFSPathResolver), ) if err != nil { diff --git a/core/node/libp2p/httpprovider.go b/core/node/libp2p/httpprovider.go index 40f5f3bfec5..14a74d052aa 100644 --- a/core/node/libp2p/httpprovider.go +++ b/core/node/libp2p/httpprovider.go @@ -12,9 +12,9 @@ import ( // behind the AutoTLS cert is only available later, once IpfsNode is up. // // Used by the HTTPProvider feature that exposes the trustless gateway -// (NoFetch, raw blocks + CAR only) on the same TCP port as the /tls/ws -// AutoWSS listener. See `cmd/ipfs/kubo/daemon.go:serveHTTPProviderOverLibp2p` -// for the install site. +// (NoFetch, raw blocks via ?format=raw only) on the same TCP port as the +// /tls/ws AutoWSS listener. See +// `cmd/ipfs/kubo/daemon.go:serveHTTPProviderOverLibp2p` for the install site. // // Until Set is called, the handler responds 503 Service Unavailable, which // is the correct signal for the small race between Accept and handler-install diff --git a/docs/changelogs/v0.43.md b/docs/changelogs/v0.43.md index f1f649e0037..54a874a114f 100644 --- a/docs/changelogs/v0.43.md +++ b/docs/changelogs/v0.43.md @@ -17,6 +17,16 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team. ### 🔦 Highlights +#### 🌐 Experimental `HTTPProvider`: serve local data over plain HTTP/2 + +Kubo now ships an experimental, opt-in `HTTPProvider`: the **server** side of HTTP retrieval. Enable it on a publicly diallable node and the local trustless gateway becomes reachable over plain HTTP/2 alongside the existing libp2p path, on the same swarm port (`4001` by default). Kubo reuses the certificate it already obtains through [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls), so no extra TLS setup is required. + +`HTTPProvider` is read-only: it serves raw blocks (`?format=raw`) from the local blockstore and does not fetch missing data from the network. It is **not** the same as [`Gateway`](https://github.com/ipfs/kubo/blob/master/docs/config.md#gateway), which stays on loopback `127.0.0.1:8080` and is the recursive, deserializing interface for local browsing. + +This is a meaningful step toward broader IPFS interoperability: a stock HTTP client, a browser, `curl`, or any HTTP library can fetch verifiable blocks from a Kubo node without a libp2p stack. It pairs with the existing [`HTTPRetrieval`](https://github.com/ipfs/kubo/blob/master/docs/config.md#httpretrieval) (the client side). + +Off by default. See [`HTTPProvider`](https://github.com/ipfs/kubo/blob/master/docs/config.md#httpprovider) for the available settings and how to turn it on. + ### 📝 Changelog ### 👨‍👩‍👧‍👦 Contributors diff --git a/docs/config.md b/docs/config.md index d932027f4d6..976af4d84bd 100644 --- a/docs/config.md +++ b/docs/config.md @@ -228,6 +228,11 @@ config file at runtime. - [`DNS`](#dns) - [`DNS.Resolvers`](#dnsresolvers) - [`DNS.MaxCacheTTL`](#dnsmaxcachettl) + - [`HTTPProvider`](#httpprovider) + - [`HTTPProvider.Enabled`](#httpproviderenabled) + - [`HTTPProvider.Libp2p`](#httpproviderlibp2p) + - [`HTTPProvider.Cleartext`](#httpprovidercleartext) + - [`HTTPProvider.AnnounceMultiaddrs`](#httpproviderannouncemultiaddrs) - [`HTTPRetrieval`](#httpretrieval) - [`HTTPRetrieval.Enabled`](#httpretrievalenabled) - [`HTTPRetrieval.Allowlist`](#httpretrievalallowlist) @@ -833,6 +838,18 @@ Do not change this unless you self-host [p2p-forge] under own domain. > (proving ownership of PeerID), probes if your Kubo node can correctly answer to a [libp2p Identify](https://github.com/libp2p/specs/tree/master/identify) query. > This ensures only a correctly configured, publicly dialable Kubo can initiate [ACME DNS-01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) for `peerid.libp2p.direct`. +> [!TIP] +> Two optional query parameters help with local debugging and end-to-end tests. Kubo strips them before handing the URL to [p2p-forge] and preserves any unrelated query parameters. Both expect a literal `host:port`; bracket IPv6 hosts, e.g. `[::1]:9000`. +> +> - `?dial=host:port` sends the registration request to `host:port` while keeping the URL Kubo advertises (and signs over for PeerID-auth) unchanged. This lets a local [p2p-forge] instance on a loopback port answer requests whose `Host` header must still match the production registration hostname. +> - `?dns=host:port` points the DNS-01 propagation pre-flight check at this DNS server instead of the system resolver. Needed when the forge's domain is not in public DNS (e.g. a private `.test` suffix used in tests). +> +> Both overrides apply only to the forge registration request and its DNS-01 pre-flight check. They do not affect `AutoTLS.CAEndpoint` or any other URL. Example combining both: +> +> ``` +> http://registration.libp2p.test/?dial=127.0.0.1:42013&dns=127.0.0.1:5353 +> ``` + Default: `https://registration.libp2p.direct` (public good run by [Interplanetary Shipyard](https://ipshipyard.com)) Type: `optionalString` @@ -3902,11 +3919,75 @@ Default: Respect DNS Response TTL Type: `optionalDuration` +## `HTTPProvider` + +`HTTPProvider` is the **server** side of HTTP retrieval in Kubo. It exposes the local trustless gateway (in [`NoFetch`](#gatewaynofetch) mode) over plain HTTP/2 so any standard HTTP client (a browser, `curl`, or any HTTP library) can fetch verifiable blocks from this node without a libp2p stack. The matching **client** side lives under [`HTTPRetrieval`](#httpretrieval). + +### Mental model: `HTTPProvider` vs `Gateway` + +`HTTPProvider` and [`Gateway`](#gateway) serve different audiences with different rules. Keep them straight: + +- `HTTPProvider` serves **raw data to the network**. It runs on Kubo's swarm port (`4001` by default), reads only from the local blockstore, and returns only raw blocks (`?format=raw`). It does **not** trigger network retrieval for missing data, and it does **not** deserialize content. Other peers fetch from it. +- [`Gateway`](#gateway) serves **deserialized data to the local user**. It runs on a loopback port (`127.0.0.1:8080` by default), walks DAGs, deserializes UnixFS, follows redirects, and fetches missing data from the network. You (or a local app on your machine) browse with it. + +The split is intentional. A public-facing HTTP source on the swarm port should not deserialize content for unknown clients or recurse out to the network on their behalf. A recursive browser endpoint should stay on loopback, not be exposed to the open internet. + +### How the HTTP listener is wired up + +- The HTTP listener reuses the same `/tcp` socket as the `/ws` listener through Kubo's shared-TCP demuxer. No extra port is opened. +- Today the HTTP listener requires a WebSocket listener on the same TCP port to exist. When `/ws` is present, Kubo adds the matching `/http` multiaddr to the announced address set automatically. +- When [`AutoTLS.AutoWSS`](#autotlsautowss) is enabled, Kubo also adds a `/tls/http` listener on the same host and port as the `/tls/ws` listener, reusing the same AutoTLS certificate. No separate TLS setup is required. + +> [!IMPORTANT] +> Experimental and off by default. Enable it on publicly diallable nodes where you want plain-HTTP clients to fetch blocks directly. + +Default: `{}` + +Type: `object` + +### `HTTPProvider.Enabled` + +Master switch for `HTTPProvider`. When `true`, Kubo registers the trustless gateway handler and (unless overridden) defaults the transport sub-toggles below to `true`. + +Default: `false` + +Type: `flag` + +### `HTTPProvider.Libp2p` + +Exposes the trustless gateway over a libp2p stream, as specified by the [libp2p Gateway spec](https://specs.ipfs.tech/http-gateways/libp2p-gateway/). The handler is mounted under the `/ipfs/gateway` protocol ID and advertised via `.well-known/libp2p/protocols`. + +Default: `true` when `HTTPProvider.Enabled=true` + +Type: `flag` + +### `HTTPProvider.Cleartext` + +Auto-appends a plaintext `/ws` listener to each `/tcp/N` already in [`Addresses.Swarm`](#addressesswarm). The new `/ws` shares the existing TCP port via the shared-TCP demuxer, so no extra socket is opened. + +Intended for deployments where the operator handles TLS termination upstream: a reverse proxy such as Caddy, Traefik, or nginx sits in front of Kubo and forwards either HTTP/1.1 or HTTP/2 cleartext to this node. With [`AutoTLS`](#autotls), Kubo already serves `/tls/ws` and `/tls/http` directly with a real certificate, so a cleartext path is unnecessary and would expose the trustless gateway and WebSocket upgrade unencrypted on the public network. Flip it on knowingly. + +The corresponding `/http` announcement is controlled by [`HTTPProvider.AnnounceMultiaddrs`](#httpproviderannouncemultiaddrs). + +Default: `false` + +Type: `flag` + +### `HTTPProvider.AnnounceMultiaddrs` + +Derives an HTTP-flavored multiaddr from each WebSocket listener on this peer and includes it in the announced address set: `/ws` becomes `/http`, `/tls/ws` becomes `/tls/http`, `/tls/sni//ws` becomes `/tls/sni//http`. The HTTP endpoint shares the same TCP port and TLS certificate as the WebSocket listener, so this is purely an announcement; no extra socket is opened. + +This is what lets [`HTTPRetrieval`](#httpretrieval) clients discover this peer as an HTTP source through identify, the DHT, and IPNI without out-of-band knowledge. + +Subject to [`Addresses.NoAnnounce`](#addressesnoannounce) filters, like any other announced multiaddr. + +Default: `true` when `HTTPProvider.Enabled=true` + +Type: `flag` + ## `HTTPRetrieval` -`HTTPRetrieval` is configuration for pure HTTP retrieval based on Trustless HTTP Gateways' -[Block Responses (`application/vnd.ipld.raw`)](https://specs.ipfs.tech/http-gateways/trustless-gateway/#block-responses-application-vnd-ipld-raw) -which can be used in addition to or instead of retrieving blocks with [Bitswap over Libp2p](#bitswap). +`HTTPRetrieval` is the **client** side of HTTP retrieval in Kubo. It lets the node fetch blocks from peers that advertise an HTTP gateway endpoint, using pure HTTP requests based on the Trustless Gateway [Block Responses (`application/vnd.ipld.raw`)](https://specs.ipfs.tech/http-gateways/trustless-gateway/#block-responses-application-vnd-ipld-raw) spec. HTTP fetches can run in addition to or instead of [Bitswap over Libp2p](#bitswap). The matching **server** side lives under [`HTTPProvider`](#httpprovider). Default: `{}` diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index a9a20a4df0f..31a01bbbd75 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -104,7 +104,7 @@ require ( github.com/ipld/go-car/v2 v2.16.0 // indirect github.com/ipld/go-codec-dagpb v1.7.0 // indirect github.com/ipld/go-ipld-prime v0.23.0 // indirect - github.com/ipshipyard/p2p-forge v0.8.0 // indirect + github.com/ipshipyard/p2p-forge v0.8.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/klauspost/compress v1.18.0 // indirect diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index ccd9aee912e..d3ebd486577 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -431,8 +431,8 @@ github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= -github.com/ipshipyard/p2p-forge v0.8.0 h1:yMg3UcAIVV0FDBMMbyZxlUnE6TYew0I+tBPzX6Y2OWM= -github.com/ipshipyard/p2p-forge v0.8.0/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= +github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 76cbc82435d..eab35723550 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -471,7 +471,7 @@ Replaced by [`Provide.Enabled`](https://github.com/ipfs/kubo/blob/master/docs/co Removed, no plans to reintegrate either as experimental or stable feature. -[Trustless Gateway over Libp2p](#http-gateway-over-libp2p) should be easier to use for unixfs usecases and support basic wildcard car streams for non unixfs. +The libp2p-stream transport in [`HTTPProvider.Libp2p`](https://github.com/ipfs/kubo/blob/master/docs/config.md#httpproviderlibp2p) is easier to use for UnixFS use cases and supports basic wildcard CAR streams for non-UnixFS. See https://github.com/ipfs/kubo/pull/9747 for more information. @@ -558,49 +558,15 @@ ipfs config --json Experimental.OptimisticProvideJobsPoolSize 120 ## HTTP Gateway over Libp2p -### In Version - -0.23.0 - -### State - -Experimental, disabled by default. - -Enables serving a subset of the [IPFS HTTP Gateway](https://specs.ipfs.tech/http-gateways/) semantics over libp2p `/http/1.1` protocol. - -Notes: -- This feature only about serving verifiable gateway requests over libp2p: - - Deserialized responses are not supported. - - Only operate on `/ipfs` resources (no `/ipns` atm) - - Only support requests for `application/vnd.ipld.raw` and - `application/vnd.ipld.car` (from [Trustless Gateway Specification](https://specs.ipfs.tech/http-gateways/trustless-gateway/), - where data integrity can be verified). - - Only serve data that is already local to the node (i.e. similar to a - [`Gateway.NoFetch`](https://github.com/ipfs/kubo/blob/master/docs/config.md#gatewaynofetch)) -- While Kubo currently mounts the gateway API at the root (i.e. `/`) of the - libp2p `/http/1.1` protocol, that is subject to change. - - The way to reliably discover where a given HTTP protocol is mounted on a - libp2p endpoint is via the `.well-known/libp2p` resource specified in the - [http+libp2p specification](https://github.com/libp2p/specs/pull/508) - - The identifier of the protocol mount point under `/http/1.1` listener is - `/ipfs/gateway`, as noted in - [ipfs/specs#434](https://github.com/ipfs/specs/pull/434). +This feature has moved out of `Experimental` and now lives at [`HTTPProvider.Libp2p`](https://github.com/ipfs/kubo/blob/master/docs/config.md#httpproviderlibp2p), the libp2p-stream transport of the broader [`HTTPProvider`](https://github.com/ipfs/kubo/blob/master/docs/config.md#httpprovider) feature. -### How to enable - -Modify your ipfs config: +The previous `Experimental.GatewayOverLibp2p` setting has been removed. Kubo now refuses to start when it is set; replace it with: ``` -ipfs config --json Experimental.GatewayOverLibp2p true +ipfs config --json HTTPProvider.Enabled true +ipfs config --json HTTPProvider.Libp2p true ``` -### Road to being a real feature - -- [ ] Needs more people to use and report on how well it works -- [ ] Needs UX work for exposing non-recursive "HTTP transport" (NoFetch) over both libp2p and plain TCP (and sharing the configuration) -- [ ] Needs a mechanism for HTTP handler to signal supported features ([IPIP-425](https://github.com/ipfs/specs/pull/425)) -- [ ] Needs an option for Kubo to detect peers that have it enabled and prefer HTTP transport before falling back to bitswap (and use CAR if peer supports dag-scope=entity from [IPIP-402](https://specs.ipfs.tech/ipips/ipip-0402/)) - ## Accelerated DHT Client This feature now lives at [`Routing.AcceleratedDHTClient`](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtclient). diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index c49b42405c7..1b81858b51b 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -152,7 +152,7 @@ require ( github.com/ipld/go-car/v2 v2.16.0 // indirect github.com/ipld/go-codec-dagpb v1.7.0 // indirect github.com/ipld/go-ipld-prime v0.23.0 // indirect - github.com/ipshipyard/p2p-forge v0.8.0 // indirect + github.com/ipshipyard/p2p-forge v0.8.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jgautheron/goconst v1.7.1 // indirect diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index c1c6046853a..4aa0ad90160 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -508,8 +508,8 @@ github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= -github.com/ipshipyard/p2p-forge v0.8.0 h1:yMg3UcAIVV0FDBMMbyZxlUnE6TYew0I+tBPzX6Y2OWM= -github.com/ipshipyard/p2p-forge v0.8.0/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= +github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= From 23f52539cde2f141c1fb936ebc00ceb43260dca7 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 22:07:08 +0200 Subject: [PATCH 12/16] fix(ci): unbreak autotls-tests + drop noise from conformance jobs Three small CI cleanups surfaced by the first PR run: - mk/golang.mk: collapse the test_autotls recipe to a single line. The backslash line continuations worked locally with bash-as-sh but failed under dash on the GHA runner, which executed each line separately and tried to run the trailing backslashes as commands. Matches the single-line style already used by test_examples. - .github/workflows/gateway-conformance.yml: drop Gateway.PublicGateways from the libp2p-experiment and cleartext jobs. Both run only the trustless-gateway conformance subset, which does not exercise subdomain routing, so the example.com / localhost public gateway config was unused. - .gitignore: ignore test/autotls/autotls-tests.json (gotestsum jsonfile output), matching the existing rules for the cli and fuse test artifacts. --- .github/workflows/gateway-conformance.yml | 10 ++++++---- .gitignore | 1 + mk/golang.mk | 5 +---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/gateway-conformance.yml b/.github/workflows/gateway-conformance.yml index 6a289fa561b..b9c9c2ec1ff 100644 --- a/.github/workflows/gateway-conformance.yml +++ b/.github/workflows/gateway-conformance.yml @@ -146,11 +146,12 @@ jobs: run: make build working-directory: kubo-gateway - # 3. Init the kubo-gateway + # 3. Init the kubo-gateway. The trustless subset this job runs does + # not exercise subdomain routing, so Gateway.PublicGateways is + # unnecessary here. - name: Init kubo-gateway run: | ./ipfs init --profile=test - ./ipfs config --json Gateway.PublicGateways "$GATEWAY_PUBLIC_GATEWAYS" ./ipfs config --json HTTPProvider.Enabled true ./ipfs config --json HTTPProvider.Libp2p true ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/8080" @@ -260,11 +261,12 @@ jobs: # 3. Init the kubo-gateway with HTTPProvider.Cleartext on the swarm # port. Libp2p is off; Cleartext is the only HTTPProvider transport - # exercised by this job. + # exercised by this job. The trustless subset run below does not + # exercise subdomain routing, so Gateway.PublicGateways is + # unnecessary here. - name: Init kubo-gateway run: | ./ipfs init --profile=test - ./ipfs config --json Gateway.PublicGateways "$GATEWAY_PUBLIC_GATEWAYS" ./ipfs config --json HTTPProvider.Enabled true ./ipfs config --json HTTPProvider.Libp2p false ./ipfs config --json HTTPProvider.Cleartext true diff --git a/.gitignore b/.gitignore index 09c29ed3d09..e77594bbe68 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ docs/examples/go-ipfs-as-a-library/example-folder/Qm* /test/cli/cli-tests.json /test/fuse/fuse-unit-tests.json /test/fuse/fuse-cli-tests.json +/test/autotls/autotls-tests.json # ignore build output from snapcraft /ipfs_*.snap diff --git a/mk/golang.mk b/mk/golang.mk index 31fa0c60b1d..2efae123d4a 100644 --- a/mk/golang.mk +++ b/mk/golang.mk @@ -108,10 +108,7 @@ test_examples: # go.mod so kubo's main module stays clean. TEST_AUTOTLS_TIMEOUT ?= 4m test_autotls: cmd/ipfs/ipfs test/bin/gotestsum $$(DEPS_GO) - cd test/autotls && rm -f autotls-tests.json && \ - PATH="$(CURDIR)/cmd/ipfs:$(CURDIR)/test/bin:$$PATH" \ - gotestsum $(GOTESTSUM_NOCOLOR) --jsonfile autotls-tests.json -- \ - -v -timeout=$(TEST_AUTOTLS_TIMEOUT) ./... + cd test/autotls && rm -f autotls-tests.json && PATH="$(CURDIR)/cmd/ipfs:$(CURDIR)/test/bin:$$PATH" gotestsum $(GOTESTSUM_NOCOLOR) --jsonfile autotls-tests.json -- -v -timeout=$(TEST_AUTOTLS_TIMEOUT) ./... .PHONY: test_autotls # Build kubo for all platforms from .github/build-platforms.yml From 53c71cac72f2c7a6c64b145590e80ef05e16eb78 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 22:08:39 +0200 Subject: [PATCH 13/16] ci(gateway-conformance): pin unique ports per job Each of the three conformance jobs now sets Addresses.Swarm, Gateway, and API explicitly to ports unique across the matrix: - full gateway suite: 14001 / 18080 / 15001 - libp2p (gateway node): 24001 / 28080 / 25001 - libp2p (proxy node): 24002 / 28081 / 25002, http-forward 28092 - cleartext HTTPProvider: 34001 / 38080 / 35001 Leading 1/2/3 identifies the job at a glance. No job inherits the kubo defaults, so every port in a CI log unambiguously names the job it belongs to and the jobs can safely share a runner if matrix scheduling ever puts them there. --- .github/workflows/gateway-conformance.yml | 46 ++++++++++++++--------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/.github/workflows/gateway-conformance.yml b/.github/workflows/gateway-conformance.yml index b9c9c2ec1ff..e16a7977a37 100644 --- a/.github/workflows/gateway-conformance.yml +++ b/.github/workflows/gateway-conformance.yml @@ -60,11 +60,17 @@ jobs: run: make build working-directory: kubo-gateway - # 3. Init the kubo-gateway + # 3. Init the kubo-gateway. Every Addresses.* port is set explicitly + # and chosen unique across all three conformance jobs (leading 1xxxx + # for this one, 2xxxx and 3xxxx for the libp2p and cleartext jobs) + # so each job's footprint is unambiguous. - name: Init kubo-gateway run: | ./ipfs init -e ./ipfs config --json Gateway.PublicGateways "$GATEWAY_PUBLIC_GATEWAYS" + ./ipfs config --json Addresses.Swarm '["/ip4/127.0.0.1/tcp/14001"]' + ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/18080" + ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/15001" working-directory: kubo-gateway/cmd/ipfs # 4. Populate the Kubo gateway with the gateway-conformance fixtures @@ -95,8 +101,8 @@ jobs: - name: Run gateway-conformance tests uses: ipfs/gateway-conformance/.github/actions/test@v0.13 with: - gateway-url: http://127.0.0.1:8080 - subdomain-url: http://localhost:8080 + gateway-url: http://127.0.0.1:18080 + subdomain-url: http://localhost:18080 args: -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length' json: output.json xml: output.xml @@ -148,14 +154,17 @@ jobs: # 3. Init the kubo-gateway. The trustless subset this job runs does # not exercise subdomain routing, so Gateway.PublicGateways is - # unnecessary here. + # unnecessary here. Ports are in the 2xxxx range so each conformance + # job's footprint is unambiguous (1xxxx for the full job, 3xxxx for + # the cleartext job). - name: Init kubo-gateway run: | ./ipfs init --profile=test ./ipfs config --json HTTPProvider.Enabled true ./ipfs config --json HTTPProvider.Libp2p true - ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/8080" - ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/5001" + ./ipfs config --json Addresses.Swarm '["/ip4/127.0.0.1/tcp/24001"]' + ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/28080" + ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/25001" working-directory: kubo-gateway/cmd/ipfs # 4. Populate the Kubo gateway with the gateway-conformance fixtures @@ -178,8 +187,9 @@ jobs: run: | ./ipfs init --profile=test -e ./ipfs config --json Experimental.Libp2pStreamMounting true - ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/8081" - ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/5002" + ./ipfs config --json Addresses.Swarm '["/ip4/127.0.0.1/tcp/24002"]' + ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/28081" + ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/25002" working-directory: kubo-gateway/cmd/ipfs # 7. Start the kubo http-p2p-proxy @@ -194,16 +204,16 @@ jobs: # 8. Start forwarding data from the http-p2p-proxy to the node serving the Gateway API over libp2p - name: Start http-over-libp2p forwarding proxy run: | - gatewayNodeId=$(./ipfs --api=/ip4/127.0.0.1/tcp/5001 id -f="") - ./ipfs --api=/ip4/127.0.0.1/tcp/5002 swarm connect $(./ipfs --api=/ip4/127.0.0.1/tcp/5001 swarm addrs local --id | head -n 1) - ./ipfs --api=/ip4/127.0.0.1/tcp/5002 p2p forward --allow-custom-protocol /http/1.1 /ip4/127.0.0.1/tcp/8092 /p2p/$gatewayNodeId + gatewayNodeId=$(./ipfs --api=/ip4/127.0.0.1/tcp/25001 id -f="") + ./ipfs --api=/ip4/127.0.0.1/tcp/25002 swarm connect $(./ipfs --api=/ip4/127.0.0.1/tcp/25001 swarm addrs local --id | head -n 1) + ./ipfs --api=/ip4/127.0.0.1/tcp/25002 p2p forward --allow-custom-protocol /http/1.1 /ip4/127.0.0.1/tcp/28092 /p2p/$gatewayNodeId working-directory: kubo-gateway/cmd/ipfs # 9. Run the gateway-conformance tests over libp2p - name: Run gateway-conformance tests over libp2p uses: ipfs/gateway-conformance/.github/actions/test@v0.13 with: - gateway-url: http://127.0.0.1:8092 + gateway-url: http://127.0.0.1:28092 args: --specs "trustless-gateway,-trustless-ipns-gateway" -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length' json: output.json xml: output.xml @@ -263,16 +273,18 @@ jobs: # port. Libp2p is off; Cleartext is the only HTTPProvider transport # exercised by this job. The trustless subset run below does not # exercise subdomain routing, so Gateway.PublicGateways is - # unnecessary here. + # unnecessary here. Ports are in the 3xxxx range so each + # conformance job's footprint is unambiguous (1xxxx for the full + # job, 2xxxx for the libp2p job). - name: Init kubo-gateway run: | ./ipfs init --profile=test ./ipfs config --json HTTPProvider.Enabled true ./ipfs config --json HTTPProvider.Libp2p false ./ipfs config --json HTTPProvider.Cleartext true - ./ipfs config --json Addresses.Swarm '["/ip4/127.0.0.1/tcp/4001"]' - ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/8080" - ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/5001" + ./ipfs config --json Addresses.Swarm '["/ip4/127.0.0.1/tcp/34001"]' + ./ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/38080" + ./ipfs config Addresses.API "/ip4/127.0.0.1/tcp/35001" working-directory: kubo-gateway/cmd/ipfs # 4. Populate the Kubo gateway with the gateway-conformance fixtures @@ -292,7 +304,7 @@ jobs: - name: Run gateway-conformance tests over h2c uses: ipfs/gateway-conformance/.github/actions/test@v0.13 with: - gateway-url: http://127.0.0.1:4001 + gateway-url: http://127.0.0.1:34001 args: --specs "trustless-gateway,-trustless-ipns-gateway" -skip 'TestGatewayCar/GET_response_for_application/vnd.ipld.car/Header_Content-Length' json: output.json xml: output.xml From 19107ed64ff672bff95d2fe2f582b40f3a019b99 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sat, 16 May 2026 22:15:16 +0200 Subject: [PATCH 14/16] fix(ci): commit zone file, gofmt nits, and stylecheck nit Three follow-ups to the first PR run: - test/autotls/zones/libp2p.test was used by the canary locally but never committed; the p2p-forge ipparser plugin reads it at CoreDNS startup. Without the file CI's canary failed before any test ran. The root .gitignore's *.test rule (intended for Go test binaries) matched the zone file, hence the per-directory .gitignore exception. - gofmt: config/autotls.go const block alignment, trailing blank line at the end of test/cli/http_provider_test.go, harness.go const block, canary_test.go trailing blank line. - stylecheck ST1005: the GatewayOverLibp2p migration error string ended with a period; reworded so it no longer does. --- cmd/ipfs/kubo/daemon.go | 6 +++--- config/autotls.go | 16 ++++++++-------- test/autotls/canary_test.go | 1 - test/autotls/harness.go | 6 +++--- test/autotls/zones/.gitignore | 5 +++++ test/autotls/zones/libp2p.test | 18 ++++++++++++++++++ test/cli/http_provider_test.go | 1 - 7 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 test/autotls/zones/.gitignore create mode 100644 test/autotls/zones/libp2p.test diff --git a/cmd/ipfs/kubo/daemon.go b/cmd/ipfs/kubo/daemon.go index 5a52cce473d..ffe399ae9ed 100644 --- a/cmd/ipfs/kubo/daemon.go +++ b/cmd/ipfs/kubo/daemon.go @@ -403,9 +403,9 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment // running the wrong feature set. if cfg.Experimental.GatewayOverLibp2p { return errors.New( - "Experimental.GatewayOverLibp2p has been removed. " + - "Set HTTPProvider.Enabled=true and HTTPProvider.Libp2p=true instead, " + - "then unset Experimental.GatewayOverLibp2p.", + "Experimental.GatewayOverLibp2p has been removed; " + + "set HTTPProvider.Enabled=true and HTTPProvider.Libp2p=true instead, " + + "then unset Experimental.GatewayOverLibp2p", ) } diff --git a/config/autotls.go b/config/autotls.go index cd33118e3c7..616c97532cb 100644 --- a/config/autotls.go +++ b/config/autotls.go @@ -71,13 +71,13 @@ type AutoTLS struct { } const ( - DefaultAutoTLSEnabled = true // with DefaultAutoTLSRegistrationDelay, unless explicitly enabled in config - DefaultDomainSuffix = p2pforge.DefaultForgeDomain - DefaultRegistrationEndpoint = p2pforge.DefaultForgeEndpoint - DefaultCAEndpoint = p2pforge.DefaultCAEndpoint - DefaultAutoWSS = true // requires AutoTLS.Enabled - DefaultAutoTLSShortAddrs = true // requires AutoTLS.Enabled - DefaultAutoTLSSkipDNSLookup = true // skip network DNS for p2p-forge domains - DefaultAutoTLSRegistrationDelay = 1 * time.Hour + DefaultAutoTLSEnabled = true // with DefaultAutoTLSRegistrationDelay, unless explicitly enabled in config + DefaultDomainSuffix = p2pforge.DefaultForgeDomain + DefaultRegistrationEndpoint = p2pforge.DefaultForgeEndpoint + DefaultCAEndpoint = p2pforge.DefaultCAEndpoint + DefaultAutoWSS = true // requires AutoTLS.Enabled + DefaultAutoTLSShortAddrs = true // requires AutoTLS.Enabled + DefaultAutoTLSSkipDNSLookup = true // skip network DNS for p2p-forge domains + DefaultAutoTLSRegistrationDelay = 1 * time.Hour DefaultAutoTLSSelfSignedForTests = false ) diff --git a/test/autotls/canary_test.go b/test/autotls/canary_test.go index 7962c2b8722..6028f912eac 100644 --- a/test/autotls/canary_test.go +++ b/test/autotls/canary_test.go @@ -220,4 +220,3 @@ func tailString(s string, n int) string { } return "... (truncated)\n" + s[len(s)-n:] } - diff --git a/test/autotls/harness.go b/test/autotls/harness.go index bce92f3547f..346668a3b0a 100644 --- a/test/autotls/harness.go +++ b/test/autotls/harness.go @@ -87,9 +87,9 @@ func NewStack(t *testing.T) *Stack { t.Helper() const ( - forgeDomain = "libp2p.test" - forgeRegHost = "registration.libp2p.test" - forgeAuthToken = "test-token" + forgeDomain = "libp2p.test" + forgeRegHost = "registration.libp2p.test" + forgeAuthToken = "test-token" ) // p2p-forge reads its auth token from this env var. Pebble skips its diff --git a/test/autotls/zones/.gitignore b/test/autotls/zones/.gitignore new file mode 100644 index 00000000000..eaf6a47ac57 --- /dev/null +++ b/test/autotls/zones/.gitignore @@ -0,0 +1,5 @@ +# The forge canary's DNS zone file is literally named after the forge +# domain (libp2p.test) so the p2p-forge ipparser plugin can find it. +# Override the root *.test rule (intended for Go test binaries) for this +# one directory. +!libp2p.test diff --git a/test/autotls/zones/libp2p.test b/test/autotls/zones/libp2p.test new file mode 100644 index 00000000000..0d4c9c27967 --- /dev/null +++ b/test/autotls/zones/libp2p.test @@ -0,0 +1,18 @@ +; Minimal DNS zone for the AutoTLS E2E canary. +; The p2p-forge ipparser plugin reads this at CoreDNS startup; it needs +; an SOA + NS record for the forge domain. We don't need glue records +; or A/AAAA entries: ipparser synthesises per-peer subdomains from the +; embedded IP in .libp2p.test hostnames at query time. +$TTL 300 +$ORIGIN libp2p.test. + +@ 86400 IN SOA ns1.libp2p.test. admin.libp2p.test. ( + 2026010101 ; serial + 86400 ; refresh + 2400 ; retry + 604800 ; expire + 86400 ; minimum +) + +libp2p.test. 86400 IN NS ns1.libp2p.test. +ns1.libp2p.test. 86400 IN A 127.0.0.1 diff --git a/test/cli/http_provider_test.go b/test/cli/http_provider_test.go index de1e977aaa3..3fb85cd3c12 100644 --- a/test/cli/http_provider_test.go +++ b/test/cli/http_provider_test.go @@ -281,4 +281,3 @@ func mustReadBody(t *testing.T, resp *http.Response) []byte { require.NoError(t, err) return body } - From 35acb9b01185dceacce815bccf48b3ba581ca6ad Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Wed, 27 May 2026 17:26:43 +0200 Subject: [PATCH 15/16] chore(deps): bump p2p-forge to v0.9.0 Pulls in pebble v2.10 API changes. The autotls harness now mirrors what p2p-forge's own e2e suite did for v0.9.0: pebble VA dials CoreDNS's TCP listener (pebble v2.10 forces TCP for ACME DNS lookups), and pebbleCA.New uses keyAlg="rsa" since pebble's GetRootKey only handles RSA. --- docs/examples/kubo-as-a-library/go.mod | 24 ++++---- docs/examples/kubo-as-a-library/go.sum | 58 ++++++++++-------- go.mod | 25 ++++---- go.sum | 58 ++++++++++-------- test/autotls/go.mod | 38 ++++++++---- test/autotls/go.sum | 84 ++++++++++++++++++-------- test/autotls/harness.go | 58 +++++++++++------- test/dependencies/go.mod | 16 ++--- test/dependencies/go.sum | 44 ++++++++------ 9 files changed, 243 insertions(+), 162 deletions(-) diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index 31a01bbbd75..4f5f1c1b93d 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -26,8 +26,8 @@ require ( github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/caddyserver/certmagic v0.23.0 // indirect - github.com/caddyserver/zerossl v0.1.3 // indirect + github.com/caddyserver/certmagic v0.25.3 // indirect + github.com/caddyserver/zerossl v0.1.5 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/ceramicnetwork/go-dag-jose v0.1.1 // indirect @@ -51,12 +51,12 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/filecoin-project/go-clock v0.1.0 // indirect github.com/flynn/noise v1.1.0 // indirect - github.com/fsnotify/fsnotify v1.10.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gammazero/chanqueue v1.1.2 // indirect github.com/gammazero/deque v1.2.1 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect - github.com/go-jose/go-jose/v4 v4.1.3 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -104,15 +104,15 @@ require ( github.com/ipld/go-car/v2 v2.16.0 // indirect github.com/ipld/go-codec-dagpb v1.7.0 // indirect github.com/ipld/go-ipld-prime v0.23.0 // indirect - github.com/ipshipyard/p2p-forge v0.8.1 // indirect + github.com/ipshipyard/p2p-forge v0.9.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.4 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/koron/go-ssdp v0.0.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/libdns/libdns v1.0.0-beta.1 // indirect + github.com/libdns/libdns v1.1.1 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-doh-resolver v0.5.0 // indirect @@ -132,7 +132,7 @@ require ( github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-isatty v0.0.22 // indirect - github.com/mholt/acmez/v3 v3.1.2 // indirect + github.com/mholt/acmez/v3 v3.1.6 // indirect github.com/miekg/dns v1.1.72 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect @@ -204,7 +204,7 @@ require ( go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/dig v1.19.0 // indirect go.uber.org/fx v1.24.0 // indirect - go.uber.org/mock v0.5.2 // indirect + go.uber.org/mock v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.28.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect @@ -218,13 +218,13 @@ require ( golang.org/x/sys v0.44.0 // indirect golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa // indirect golang.org/x/text v0.36.0 // indirect - golang.org/x/time v0.14.0 // indirect + golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.44.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect - google.golang.org/grpc v1.79.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect + google.golang.org/grpc v1.80.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.4.1 // indirect diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index d3ebd486577..f87e8151f66 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -36,6 +36,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE= +code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5 h1:JA0fFr+kxpqTdxR9LOBiTWpGNchqmkcsgmdeJZRclZ0= filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5/go.mod h1:OjOXDNlClLblvXdwgFFOQFJEocLhhtai8vGLy0JCZlI= @@ -84,10 +86,10 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU= -github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4= -github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= -github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/caddyserver/certmagic v0.25.3 h1:mGf5ba8F7xA4c5jfDZZbK2buY1VEkbnwpMDixaju94A= +github.com/caddyserver/certmagic v0.25.3/go.mod h1:YVs43D5+H/Dckt4bTga1KSO/xYfFBfVZainGDywYPAA= +github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE= +github.com/caddyserver/zerossl v0.1.5/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3 h1:oe6fCvaEpkhyW3qAicT0TnGtyht/UrgvOwMcEgLb7Aw= github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3/go.mod h1:qdP0gaj0QtgX2RUZhnlVrceJ+Qln8aSlDyJwelLLFeM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -157,8 +159,8 @@ github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70d github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -186,8 +188,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.10.0 h1:Xx/5Ydg9CeBDX/wi4VJqStNtohYjitZhhlHt4h3St1M= -github.com/fsnotify/fsnotify v1.10.0/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gammazero/chanqueue v1.1.2 h1:dZEsxlyANZMyeTRemABqZF8QM9BnE4NBI43Oh3y5fIU= @@ -205,8 +207,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= -github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -431,8 +433,8 @@ github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= -github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= -github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/ipshipyard/p2p-forge v0.9.0 h1:Mp/bZ8BX7sxNTyzN5BXbYpOPbggrUbn+Dr5XnJ2kj0s= +github.com/ipshipyard/p2p-forge v0.9.0/go.mod h1:1keK1MRRCu5oNe9uFKfNIIZXOFEF9hgD1iK1DUsjsXQ= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= @@ -454,8 +456,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= @@ -474,8 +476,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= -github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU= +github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk= +github.com/letsencrypt/pebble/v2 v2.10.1 h1:oKHx3lgN4e5Nno2LKTMrVx+b+NkDptkO9aDireiBDGE= +github.com/letsencrypt/pebble/v2 v2.10.1/go.mod h1:KtYhQ4YTjT5MtoCZ6RTCXlbrrz6cKyXROCuTpIUDJFY= +github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U= +github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= @@ -540,8 +546,8 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= -github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= +github.com/mholt/acmez/v3 v3.1.6 h1:eGVQNObP0pBN4sxqrXeg7MYqTOWyoiYpQqITVWlrevk= +github.com/mholt/acmez/v3 v3.1.6/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= @@ -861,8 +867,8 @@ go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -1104,8 +1110,8 @@ golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1248,8 +1254,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0= google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1270,8 +1276,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/go.mod b/go.mod index f73743f7591..25786cbf6fd 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( contrib.go.opencensus.io/exporter/prometheus v0.4.2 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 github.com/blang/semver/v4 v4.0.0 - github.com/caddyserver/certmagic v0.23.0 + github.com/caddyserver/certmagic v0.25.3 github.com/cenkalti/backoff/v4 v4.3.0 github.com/ceramicnetwork/go-dag-jose v0.1.1 github.com/cheggaaa/pb v1.0.29 @@ -15,7 +15,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302 github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 - github.com/fsnotify/fsnotify v1.10.0 + github.com/fsnotify/fsnotify v1.10.1 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 github.com/hanwen/go-fuse/v2 v2.10.1 @@ -47,7 +47,7 @@ require ( github.com/ipld/go-car/v2 v2.16.0 github.com/ipld/go-codec-dagpb v1.7.0 github.com/ipld/go-ipld-prime v0.23.0 - github.com/ipshipyard/p2p-forge v0.8.1 + github.com/ipshipyard/p2p-forge v0.9.0 github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/julienschmidt/httprouter v1.3.0 github.com/libp2p/go-doh-resolver v0.5.0 @@ -110,7 +110,7 @@ require ( github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/caddyserver/zerossl v0.1.3 // indirect + github.com/caddyserver/zerossl v0.1.5 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -127,7 +127,6 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect github.com/dgraph-io/badger v1.6.2 // indirect github.com/dgraph-io/ristretto v0.0.2 // indirect - github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dunglas/httpsfv v1.1.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -137,7 +136,7 @@ require ( github.com/gammazero/chanqueue v1.1.2 // indirect github.com/gammazero/deque v1.2.1 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect - github.com/go-jose/go-jose/v4 v4.1.3 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.3 // indirect @@ -162,12 +161,12 @@ require ( github.com/ipfs/go-libdht v0.5.0 // indirect github.com/ipfs/go-peertaskqueue v0.8.3 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.4 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/koron/go-ssdp v0.0.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/libdns/libdns v1.0.0-beta.1 // indirect + github.com/libdns/libdns v1.1.1 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.3.0 // indirect @@ -184,7 +183,7 @@ require ( github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect - github.com/mholt/acmez/v3 v3.1.2 // indirect + github.com/mholt/acmez/v3 v3.1.6 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/minlz v1.0.1-0.20250507153514-87eb42fe8882 // indirect @@ -253,7 +252,7 @@ require ( go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/proto/otlp v1.9.0 // indirect - go.uber.org/mock v0.5.2 // indirect + go.uber.org/mock v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect @@ -261,13 +260,13 @@ require ( golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa // indirect golang.org/x/text v0.36.0 // indirect - golang.org/x/time v0.14.0 // indirect + golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.44.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect - google.golang.org/grpc v1.79.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect + google.golang.org/grpc v1.80.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.4.1 // indirect diff --git a/go.sum b/go.sum index ac9cc20154d..b315f99e303 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE= +code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM= contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -97,10 +99,10 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU= -github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4= -github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= -github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/caddyserver/certmagic v0.25.3 h1:mGf5ba8F7xA4c5jfDZZbK2buY1VEkbnwpMDixaju94A= +github.com/caddyserver/certmagic v0.25.3/go.mod h1:YVs43D5+H/Dckt4bTga1KSO/xYfFBfVZainGDywYPAA= +github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE= +github.com/caddyserver/zerossl v0.1.5/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3 h1:oe6fCvaEpkhyW3qAicT0TnGtyht/UrgvOwMcEgLb7Aw= github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3/go.mod h1:qdP0gaj0QtgX2RUZhnlVrceJ+Qln8aSlDyJwelLLFeM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -175,8 +177,8 @@ github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrV github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -211,8 +213,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.10.0 h1:Xx/5Ydg9CeBDX/wi4VJqStNtohYjitZhhlHt4h3St1M= -github.com/fsnotify/fsnotify v1.10.0/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gammazero/chanqueue v1.1.2 h1:dZEsxlyANZMyeTRemABqZF8QM9BnE4NBI43Oh3y5fIU= @@ -230,8 +232,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= -github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -473,8 +475,8 @@ github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= -github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= -github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/ipshipyard/p2p-forge v0.9.0 h1:Mp/bZ8BX7sxNTyzN5BXbYpOPbggrUbn+Dr5XnJ2kj0s= +github.com/ipshipyard/p2p-forge v0.9.0/go.mod h1:1keK1MRRCu5oNe9uFKfNIIZXOFEF9hgD1iK1DUsjsXQ= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= @@ -503,8 +505,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= @@ -525,8 +527,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= -github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU= +github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk= +github.com/letsencrypt/pebble/v2 v2.10.1 h1:oKHx3lgN4e5Nno2LKTMrVx+b+NkDptkO9aDireiBDGE= +github.com/letsencrypt/pebble/v2 v2.10.1/go.mod h1:KtYhQ4YTjT5MtoCZ6RTCXlbrrz6cKyXROCuTpIUDJFY= +github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U= +github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= @@ -608,8 +614,8 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= -github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= +github.com/mholt/acmez/v3 v3.1.6 h1:eGVQNObP0pBN4sxqrXeg7MYqTOWyoiYpQqITVWlrevk= +github.com/mholt/acmez/v3 v3.1.6/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= @@ -997,8 +1003,8 @@ go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -1260,8 +1266,8 @@ golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1404,8 +1410,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0= google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1426,8 +1432,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/test/autotls/go.mod b/test/autotls/go.mod index f65898aff28..643d246faff 100644 --- a/test/autotls/go.mod +++ b/test/autotls/go.mod @@ -10,7 +10,7 @@ require ( github.com/coredns/coredns v1.14.3 github.com/ipfs/go-cid v0.6.1 github.com/ipfs/kubo v0.0.0-00010101000000-000000000000 - github.com/ipshipyard/p2p-forge v0.8.1 + github.com/ipshipyard/p2p-forge v0.9.0 github.com/letsencrypt/pebble/v2 v2.10.1 github.com/multiformats/go-multiaddr v0.16.1 github.com/stretchr/testify v1.11.1 @@ -26,11 +26,28 @@ require ( github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54 // indirect github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/apparentlymart/go-cidr v1.1.0 // indirect - github.com/aws/aws-sdk-go v1.55.6 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.7 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.17 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.16 // indirect + github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.20.39 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3 // indirect + github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.32.16 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 // indirect + github.com/aws/smithy-go v1.25.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/caddyserver/certmagic v0.23.0 // indirect - github.com/caddyserver/zerossl v0.1.3 // indirect + github.com/caddyserver/certmagic v0.25.3 // indirect + github.com/caddyserver/zerossl v0.1.5 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/crlib v0.0.0-20241112164430-1264a2edc35b // indirect github.com/cockroachdb/errors v1.11.3 // indirect @@ -53,9 +70,9 @@ require ( github.com/filecoin-project/go-clock v0.1.0 // indirect github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect github.com/flynn/noise v1.1.0 // indirect - github.com/fsnotify/fsnotify v1.10.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect - github.com/gaissmai/bart v0.26.0 // indirect + github.com/gaissmai/bart v0.28.0 // indirect github.com/gammazero/chanqueue v1.1.2 // indirect github.com/gammazero/deque v1.2.1 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect @@ -81,7 +98,7 @@ require ( github.com/ipfs/go-cidutil v0.1.1 // indirect github.com/ipfs/go-datastore v0.9.1 // indirect github.com/ipfs/go-ds-badger4 v0.1.8 // indirect - github.com/ipfs/go-ds-dynamodb v0.2.2 // indirect + github.com/ipfs/go-ds-dynamodb v0.3.0 // indirect github.com/ipfs/go-dsqueue v0.2.0 // indirect github.com/ipfs/go-ipfs-cmds v0.16.1 // indirect github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect @@ -96,7 +113,6 @@ require ( github.com/ipld/go-ipld-prime v0.23.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/klauspost/compress v1.18.4 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect @@ -104,7 +120,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/letsencrypt/challtestsrv v1.4.2 // indirect - github.com/libdns/libdns v1.0.0-beta.1 // indirect + github.com/libdns/libdns v1.1.1 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-doh-resolver v0.5.0 // indirect @@ -123,7 +139,7 @@ require ( github.com/mattn/go-isatty v0.0.22 // indirect github.com/mdlayher/socket v0.5.1 // indirect github.com/mdlayher/vsock v1.2.1 // indirect - github.com/mholt/acmez/v3 v3.1.2 // indirect + github.com/mholt/acmez/v3 v3.1.6 // indirect github.com/miekg/dns v1.1.72 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect @@ -193,7 +209,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/dig v1.19.0 // indirect go.uber.org/fx v1.24.0 // indirect - go.uber.org/mock v0.5.2 // indirect + go.uber.org/mock v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.28.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect diff --git a/test/autotls/go.sum b/test/autotls/go.sum index 7cd704abe95..86e90ec9ad0 100644 --- a/test/autotls/go.sum +++ b/test/autotls/go.sum @@ -36,6 +36,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE= +code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5 h1:JA0fFr+kxpqTdxR9LOBiTWpGNchqmkcsgmdeJZRclZ0= filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5/go.mod h1:OjOXDNlClLblvXdwgFFOQFJEocLhhtai8vGLy0JCZlI= @@ -61,18 +63,52 @@ github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/Y github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= -github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= +github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= +github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU= +github.com/aws/aws-sdk-go-v2/config v1.32.17/go.mod h1:OXqUMzgXytfoF9JaKkhrOYsyh72t9G+MJH8mMRaexOE= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16 h1:r3RJBuU7X9ibt8RHbMjWE6y60QbKBiII6wSrXnapxSU= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16/go.mod h1:6cx7zqDENJDbBIIWX6P8s0h6hqHC8Avbjh9Dseo27ug= +github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.20.39 h1:Suq0L+BsHm+5QD9bOXTkMTYNqgwhevA2Ggo1ApRqukE= +github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.20.39/go.mod h1:JX+/lB8RXleUNZ3Uw6o7FnE8t4CkKT8gDHEmlF8qZfI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23/go.mod h1:xYWD6BS9ywC5bS3sz9Xh04whO/hzK2plt2Zkyrp4JuA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueOw02f/duEPTMK59Q4QMAoTTtTo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3 h1:XgjzLEE8CrNYnr4Xmi1W5PfKsKMjp4Pu1rWkJNO43JI= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.3/go.mod h1:r7sfLXEN8RUA89tAHy1E7lCtVOOWIkqVy/FbnUdxW1E= +github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.32.16 h1:nWMRNW3SFeJCdK7OsZ9lmbl1AAEAs8s6w5Gsa3MQqNo= +github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.32.16/go.mod h1:IMigEAstzWVC+mYsWLjZB/ZBJBLWON/Fl0zLHxZ18Qk= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9/go.mod h1:w7wZ/s9qK7c8g4al+UyoF1Sp/Z45UwMGcqIzLWVQHWk= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.23 h1:3Eo/PBBnjFi1+gYfaL286dpmFSW3mTfodBIybq36Qv4= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.11.23/go.mod h1:3oh+5xGSd1iuxonVb3Qbm+WJYlbhczT9kbzr6doJLzY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 h1:pbrxO/kuIwgEsOPLkaHu0O+m4fNgLU8B3vxQ+72jTPw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23/go.mod h1:/CMNUqoj46HpS3MNRDEDIwcgEnrtZlKRaHNaHxIFpNA= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 h1:+1Kl1zx6bWi4X7cKi3VYh29h8BvsCoHQEQ6ST9X8w7w= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio= +github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI= +github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU= -github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4= -github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= -github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/caddyserver/certmagic v0.25.3 h1:mGf5ba8F7xA4c5jfDZZbK2buY1VEkbnwpMDixaju94A= +github.com/caddyserver/certmagic v0.25.3/go.mod h1:YVs43D5+H/Dckt4bTga1KSO/xYfFBfVZainGDywYPAA= +github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE= +github.com/caddyserver/zerossl v0.1.5/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3 h1:oe6fCvaEpkhyW3qAicT0TnGtyht/UrgvOwMcEgLb7Aw= github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3/go.mod h1:qdP0gaj0QtgX2RUZhnlVrceJ+Qln8aSlDyJwelLLFeM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -132,8 +168,8 @@ github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56 github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -159,12 +195,12 @@ github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwU github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.10.0 h1:Xx/5Ydg9CeBDX/wi4VJqStNtohYjitZhhlHt4h3St1M= -github.com/fsnotify/fsnotify v1.10.0/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= -github.com/gaissmai/bart v0.26.0 h1:xOZ57E9hJLBiQaSyeZa9wgWhGuzfGACgqp4BE77OkO0= -github.com/gaissmai/bart v0.26.0/go.mod h1:GREWQfTLRWz/c5FTOsIw+KkscuFkIV5t8Rp7Nd1Td5c= +github.com/gaissmai/bart v0.28.0 h1:89yZLo8NmyqD0RYgJ3QO9HhqqGGw+oWhf90cZm69Lko= +github.com/gaissmai/bart v0.28.0/go.mod h1:GREWQfTLRWz/c5FTOsIw+KkscuFkIV5t8Rp7Nd1Td5c= github.com/gammazero/chanqueue v1.1.2 h1:dZEsxlyANZMyeTRemABqZF8QM9BnE4NBI43Oh3y5fIU= github.com/gammazero/chanqueue v1.1.2/go.mod h1:XDN1X/jjAbmSceNFOQbtKToeSkxtdVdpKu90LiEdBEE= github.com/gammazero/deque v1.2.1 h1:9fnQVFCCZ9/NOc7ccTNqzoKd1tCWOqeI05/lPqFPMGQ= @@ -324,8 +360,8 @@ github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger4 v0.1.8 h1:frNczf5CjCVm62RJ5mW5tD/oLQY/9IKAUpKviRV9QAI= github.com/ipfs/go-ds-badger4 v0.1.8/go.mod h1:FdqSLA5TMsyqooENB/Hf4xzYE/iH0z/ErLD6ogtfMrA= -github.com/ipfs/go-ds-dynamodb v0.2.2 h1:tPuSMWoBPsDcg0KnUL3B8hGPctC+Ffpc+nsFsmkrQE8= -github.com/ipfs/go-ds-dynamodb v0.2.2/go.mod h1:ghG0ObKeNjGT4Zc0p0ADELXJX8jVqb18n/+BfavwPF0= +github.com/ipfs/go-ds-dynamodb v0.3.0 h1:Zh947W14wvZYEDF5g42PJPEvHWKxD8k+TqCp7tO84Fk= +github.com/ipfs/go-ds-dynamodb v0.3.0/go.mod h1:Y+0KOICCda/1Nme0eV2T24pPvcNhhKYGgk67PPMAvJ8= github.com/ipfs/go-ds-leveldb v0.5.2 h1:6nmxlQ2zbp4LCNdJVsmHfs9GP0eylfBNxpmY1csp0x0= github.com/ipfs/go-ds-leveldb v0.5.2/go.mod h1:2fAwmcvD3WoRT72PzEekHBkQmBDhc39DJGoREiuGmYo= github.com/ipfs/go-dsqueue v0.2.0 h1:MBi9w3oSiX98Xc+Y7NuJ9G8MI6mAT4IGdO9dHEMCZzU= @@ -362,16 +398,12 @@ github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= -github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= -github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/ipshipyard/p2p-forge v0.9.0 h1:Mp/bZ8BX7sxNTyzN5BXbYpOPbggrUbn+Dr5XnJ2kj0s= +github.com/ipshipyard/p2p-forge v0.9.0/go.mod h1:1keK1MRRCu5oNe9uFKfNIIZXOFEF9hgD1iK1DUsjsXQ= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -402,8 +434,8 @@ github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk= github.com/letsencrypt/pebble/v2 v2.10.1 h1:oKHx3lgN4e5Nno2LKTMrVx+b+NkDptkO9aDireiBDGE= github.com/letsencrypt/pebble/v2 v2.10.1/go.mod h1:KtYhQ4YTjT5MtoCZ6RTCXlbrrz6cKyXROCuTpIUDJFY= -github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= -github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U= +github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= @@ -447,8 +479,8 @@ github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= -github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= -github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= +github.com/mholt/acmez/v3 v3.1.6 h1:eGVQNObP0pBN4sxqrXeg7MYqTOWyoiYpQqITVWlrevk= +github.com/mholt/acmez/v3 v3.1.6/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= @@ -698,8 +730,8 @@ go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= diff --git a/test/autotls/harness.go b/test/autotls/harness.go index 346668a3b0a..d4831951f86 100644 --- a/test/autotls/harness.go +++ b/test/autotls/harness.go @@ -109,45 +109,41 @@ func NewStack(t *testing.T) *Stack { httpPort := tmpListener.Addr().(*net.TCPAddr).Port _ = tmpListener.Close() - // Reserve one port for DNS so CoreDNS binds the same port on UDP and - // TCP. With .:0 the OS hands each protocol an independent random - // port, and Pebble's VA fails when it retries TXT lookups over TCP. - tmpUDP, err := net.ListenPacket("udp", "127.0.0.1:0") - if err != nil { - t.Fatalf("reserve forge dns port: %v", err) - } - dnsPort := tmpUDP.LocalAddr().(*net.UDPAddr).Port - _ = tmpUDP.Close() - // Configure the CoreDNS instance p2p-forge runs on. The ipparser // plugin resolves . from the embedded IP; the // acme plugin owns the DNS-01 TXT records and the HTTP registration - // endpoint. + // endpoint. `.:0` lets CoreDNS pick free UDP and TCP ports; the + // running instance reports both via Servers()[0] below. tmpDir := t.TempDir() dnsserver.Directives = []string{"log", "whoami", "startup", "shutdown", "ipparser", "acme"} - corefile := fmt.Sprintf(`.:%[5]d { + corefile := fmt.Sprintf(`.:0 { log ipparser %[1]s acme %[1]s { registration-domain %[2]s listen-address=:%[3]d external-tls=true database-type badger %[4]s } - }`, forgeDomain, forgeRegHost, httpPort, tmpDir, dnsPort) + }`, forgeDomain, forgeRegHost, httpPort, tmpDir) dnsInstance, err := caddy.Start(&corefileInput{body: []byte(corefile)}) if err != nil { t.Fatalf("start p2p-forge (caddy): %v", err) } - // dnsAddr is what Pebble's VA and the kubo daemon's pre-flight check - // both dial; same port on UDP and TCP (see reservation above). - dnsAddr := fmt.Sprintf("127.0.0.1:%d", dnsPort) + // CoreDNS's default DNS server type exposes the UDP packet conn via + // LocalAddr() and the TCP listener via Addr(). Pebble v2.10 forces + // TCP for ACME DNS lookups, so its VA must dial the TCP listener; + // the kubo daemon's pre-flight check uses Go's net.Resolver with + // PreferGo, which sends TXT queries over UDP. + dnsUDPAddr, dnsTCPAddr := dnsServerAddresses(t, dnsInstance.Servers()[0]) // Stand up Pebble. The VA needs the forge DNS server's address so it // can resolve the DNS-01 TXT records p2p-forge publishes. pebbleLogger := log.New(os.Stderr, "pebble: ", log.LstdFlags) db := pebbleDB.NewMemoryStore() - // ocspResponderURL="" (none), keyAlg="ecdsa" (Pebble panics on - // empty), 1 alternate root, chain length 1 (Pebble requires at - // least one intermediate). One issuance profile so wfe.NewOrder's + // ocspResponderURL="" (none), keyAlg="rsa" (matches p2p-forge's + // own e2e setup; pebble's GetRootKey only handles RSA so an ECDSA + // CA would panic if pebble's internal flows ever call it), 1 + // alternate root, chain length 1 (Pebble requires at least one + // intermediate). One issuance profile so wfe.NewOrder's // random-profile pick doesn't Intn(0)-panic. profiles := map[string]pebbleCA.Profile{ "shortlived": { @@ -155,8 +151,8 @@ func NewStack(t *testing.T) *Stack { ValidityPeriod: 7 * 24 * 60 * 60, // seconds }, } - ca := pebbleCA.New(pebbleLogger, db, "", "ecdsa", 1, 1, profiles) - va := pebbleVA.New(pebbleLogger, 0, 0, false, dnsAddr, db) + ca := pebbleCA.New(pebbleLogger, db, "", "rsa", 1, 1, profiles) + va := pebbleVA.New(pebbleLogger, 0, 0, false, dnsTCPAddr, db) // nil caaIdentities skips CAA checks (we have no DNS CAA records for // libp2p.test anyway). strict=false, requireEAB=false, retryAfter // values match Pebble's defaults. @@ -182,7 +178,7 @@ func NewStack(t *testing.T) *Stack { go func() { _ = acmeServer.Serve(tlsListener) }() stack := &Stack{ - ForgeRegistrationEndpoint: fmt.Sprintf("http://%s/?dial=127.0.0.1:%d&dns=%s", forgeRegHost, httpPort, dnsAddr), + ForgeRegistrationEndpoint: fmt.Sprintf("http://%s/?dial=127.0.0.1:%d&dns=%s", forgeRegHost, httpPort, dnsUDPAddr), ACMEEndpoint: fmt.Sprintf("https://%s%s", acmeListener.Addr(), pebbleWFE.DirectoryPath), PebbleCAPEM: string(pebbleCertPEM), PebbleIssuanceRootPEM: string(ca.GetRootCert(0).PEM()), @@ -200,6 +196,24 @@ func NewStack(t *testing.T) *Stack { return stack } +// dnsServerAddresses returns the UDP and TCP listener addresses from a +// CoreDNS ServerListener. The default DNS server type binds the UDP packet +// conn to LocalAddr() and the TCP listener to Addr(); a swap to +// DoH/DoT/DoQ/gRPC would fail one of the assertions loudly. Mirrors the +// helper in p2p-forge's own e2e test. +func dnsServerAddresses(t *testing.T, srv caddy.ServerListener) (udpAddr, tcpAddr string) { + t.Helper() + pkt := srv.LocalAddr() + if pkt == nil || pkt.Network() != "udp" { + t.Fatalf("expected UDP packet conn on CoreDNS server, got %v", pkt) + } + l := srv.Addr() + if l == nil || l.Network() != "tcp" { + t.Fatalf("expected TCP listener on CoreDNS server, got %v", l) + } + return pkt.String(), l.String() +} + // setEnv sets key=val for the duration of the test, returning the previous // value (if any) so a paired restoreEnv call can put it back on cleanup. We // roll our own instead of t.Setenv because the canary uses t.Parallel. diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index 1b81858b51b..d50aa21655f 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -54,8 +54,8 @@ require ( github.com/breml/errchkjson v0.4.0 // indirect github.com/butuzov/ireturn v0.3.1 // indirect github.com/butuzov/mirror v1.3.0 // indirect - github.com/caddyserver/certmagic v0.23.0 // indirect - github.com/caddyserver/zerossl v0.1.3 // indirect + github.com/caddyserver/certmagic v0.25.3 // indirect + github.com/caddyserver/zerossl v0.1.5 // indirect github.com/catenacyber/perfsprint v0.8.2 // indirect github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -87,7 +87,7 @@ require ( github.com/filecoin-project/go-clock v0.1.0 // indirect github.com/firefart/nonamedreturns v1.0.5 // indirect github.com/flynn/noise v1.1.0 // indirect - github.com/fsnotify/fsnotify v1.10.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gammazero/chanqueue v1.1.2 // indirect @@ -152,7 +152,7 @@ require ( github.com/ipld/go-car/v2 v2.16.0 // indirect github.com/ipld/go-codec-dagpb v1.7.0 // indirect github.com/ipld/go-ipld-prime v0.23.0 // indirect - github.com/ipshipyard/p2p-forge v0.8.1 // indirect + github.com/ipshipyard/p2p-forge v0.9.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jgautheron/goconst v1.7.1 // indirect @@ -162,7 +162,7 @@ require ( github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect github.com/kisielk/errcheck v1.9.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.4 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/koron/go-ssdp v0.0.6 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -176,7 +176,7 @@ require ( github.com/ldez/tagliatelle v0.7.1 // indirect github.com/ldez/usetesting v0.4.2 // indirect github.com/leonklingele/grouper v1.1.2 // indirect - github.com/libdns/libdns v1.0.0-beta.1 // indirect + github.com/libdns/libdns v1.1.1 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-doh-resolver v0.5.0 // indirect @@ -200,7 +200,7 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mgechev/revive v1.7.0 // indirect - github.com/mholt/acmez/v3 v3.1.2 // indirect + github.com/mholt/acmez/v3 v3.1.6 // indirect github.com/miekg/dns v1.1.72 // indirect github.com/minio/minlz v1.0.1-0.20250507153514-87eb42fe8882 // indirect github.com/minio/sha256-simd v1.0.1 // indirect @@ -333,7 +333,7 @@ require ( golang.org/x/sys v0.44.0 // indirect golang.org/x/term v0.43.0 // indirect golang.org/x/text v0.36.0 // indirect - golang.org/x/time v0.14.0 // indirect + golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.44.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.17.0 // indirect diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index 4aa0ad90160..ac6d97630f7 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -40,6 +40,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE= +code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5 h1:JA0fFr+kxpqTdxR9LOBiTWpGNchqmkcsgmdeJZRclZ0= filippo.io/bigmod v0.1.1-0.20260103110540-f8a47775ebe5/go.mod h1:OjOXDNlClLblvXdwgFFOQFJEocLhhtai8vGLy0JCZlI= @@ -128,10 +130,10 @@ github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= -github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU= -github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4= -github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= -github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= +github.com/caddyserver/certmagic v0.25.3 h1:mGf5ba8F7xA4c5jfDZZbK2buY1VEkbnwpMDixaju94A= +github.com/caddyserver/certmagic v0.25.3/go.mod h1:YVs43D5+H/Dckt4bTga1KSO/xYfFBfVZainGDywYPAA= +github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE= +github.com/caddyserver/zerossl v0.1.5/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= github.com/catenacyber/perfsprint v0.8.2 h1:+o9zVmCSVa7M4MvabsWvESEhpsMkhfE7k0sHNGL95yw= github.com/catenacyber/perfsprint v0.8.2/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= @@ -233,8 +235,8 @@ github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwU github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.10.0 h1:Xx/5Ydg9CeBDX/wi4VJqStNtohYjitZhhlHt4h3St1M= -github.com/fsnotify/fsnotify v1.10.0/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= @@ -257,6 +259,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -508,8 +512,8 @@ github.com/ipld/go-ipld-prime v0.23.0 h1:csqdPZH60BsTC+AZrv7fpa27v+09I/oTqyHYYYE github.com/ipld/go-ipld-prime v0.23.0/go.mod h1:46YCFSFNFBJHPjB0pfMuv7Ly7df2eChpkpyPo5SE0bA= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714 h1:cqNk8PEwHnK0vqWln+U/YZhQc9h2NB3KjUjDPZo5Q2s= github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20250821084354-a425e60cd714/go.mod h1:ZEUdra3CoqRVRYgAX/jAJO9aZGz6SKtKEG628fHHktY= -github.com/ipshipyard/p2p-forge v0.8.1 h1:wqgosJKNcmwCRj9A1wRXxhHt9nsuvkLAgTvTDUtfSWE= -github.com/ipshipyard/p2p-forge v0.8.1/go.mod h1:XIyBqyuMGFDYO8wJ6wcbylLvsXbMnTgYPFkydkrVgQM= +github.com/ipshipyard/p2p-forge v0.9.0 h1:Mp/bZ8BX7sxNTyzN5BXbYpOPbggrUbn+Dr5XnJ2kj0s= +github.com/ipshipyard/p2p-forge v0.9.0/go.mod h1:1keK1MRRCu5oNe9uFKfNIIZXOFEF9hgD1iK1DUsjsXQ= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= @@ -535,8 +539,8 @@ github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE= github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= @@ -568,8 +572,12 @@ github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= -github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU= +github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk= +github.com/letsencrypt/pebble/v2 v2.10.1 h1:oKHx3lgN4e5Nno2LKTMrVx+b+NkDptkO9aDireiBDGE= +github.com/letsencrypt/pebble/v2 v2.10.1/go.mod h1:KtYhQ4YTjT5MtoCZ6RTCXlbrrz6cKyXROCuTpIUDJFY= +github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U= +github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= @@ -630,8 +638,8 @@ github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebG github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= -github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= -github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= +github.com/mholt/acmez/v3 v3.1.6 h1:eGVQNObP0pBN4sxqrXeg7MYqTOWyoiYpQqITVWlrevk= +github.com/mholt/acmez/v3 v3.1.6/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= @@ -1006,8 +1014,8 @@ go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -1252,8 +1260,8 @@ golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 23e144b38ec7b550abdd62a1d3091ebff2909992 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Wed, 27 May 2026 22:23:20 +0200 Subject: [PATCH 16/16] fix(httpprovider): default /http announcement to off HTTPProvider.Enabled stays off by default; once enabled, the libp2p-stream transport comes up automatically (it is the in-band path .well-known already advertises) while Cleartext and the /http multiaddr announcement stay off until the operator opts in explicitly. The const block carries the default rationale; field godocs no longer restate default values. --- config/httpprovider.go | 83 ++++++++++++-------------- docs/config.md | 6 +- test/autotls/canary_test.go | 5 +- test/cli/http_provider_autotls_test.go | 2 + test/cli/http_provider_test.go | 12 ++-- 5 files changed, 55 insertions(+), 53 deletions(-) diff --git a/config/httpprovider.go b/config/httpprovider.go index 6cee80038ad..45150d18244 100644 --- a/config/httpprovider.go +++ b/config/httpprovider.go @@ -7,67 +7,62 @@ package config // retrieval clients such as boxo/bitswap/network/httpnet. // // This is the server side of the HTTP retrieval story; the client side -// lives separately and is configured under HTTPRetrieval. +// lives separately under HTTPRetrieval. +// +// Defaults live on the DefaultHTTPProvider* constants below. type HTTPProvider struct { - // Enabled is the master switch. Default: false. When true (and other - // prerequisites are met), the trustless gateway handler is registered - // and the transport sub-toggles default to true unless explicitly set - // to false. + // Enabled is the master switch. When true, the trustless gateway + // handler is registered for the libp2p-stream transport (see + // Libp2p). Cleartext and AnnounceMultiaddrs gate further surfaces + // and must each be set explicitly. Enabled Flag `json:",omitempty"` - // Libp2p exposes the trustless gateway over a libp2p stream, as - // specified by the libp2p Gateway spec - // (https://specs.ipfs.tech/http-gateways/libp2p-gateway/). The - // handler is mounted under the /ipfs/gateway protocol ID and + // Libp2p exposes the trustless gateway over a libp2p stream, per the + // libp2p Gateway spec (https://specs.ipfs.tech/http-gateways/libp2p-gateway/). + // The handler mounts under the /ipfs/gateway protocol ID and is // advertised via .well-known/libp2p/protocols on the libp2p+HTTP - // host. Default: true when Enabled is true. + // host. Libp2p Flag `json:",omitempty"` - // Cleartext auto-appends a plaintext /ws listener to each /tcp/N - // already in Addresses.Swarm, unless a cleartext /ws listener is - // already present. The new /ws shares the existing TCP port via the - // shared-TCP demuxer, so no extra socket is opened. - // - // Intended for deployments where the operator handles TLS termination - // for /ws and /http themselves, typically a reverse proxy (Caddy, - // Traefik, nginx, etc.) sitting in front of kubo and forwarding either - // HTTP/1.1 or HTTP/2 cleartext (h2c) to this node. With AutoTLS, kubo - // already serves /tls/ws and /tls/http directly with a Let's Encrypt - // cert, so adding a cleartext path is unnecessary and would expose the - // trustless gateway and WebSocket upgrade unencrypted on the public - // network. Off by default for that reason; flip it on knowingly. + // Cleartext auto-appends a plaintext /ws listener to each /tcp/N in + // Addresses.Swarm, unless one is already present. The new /ws shares + // the existing TCP port via the shared-TCP demuxer, so no extra + // socket is opened. // - // The corresponding network advertisement (/http multiaddr beside - // /ws) is controlled by AnnounceMultiaddrs. + // Intended for deployments where a reverse proxy (Caddy, Traefik, + // nginx, etc.) terminates TLS in front of kubo and forwards HTTP/1.1 + // or h2c to this node. With AutoTLS, kubo already serves /tls/ws and + // /tls/http with a Let's Encrypt cert, so a cleartext path would + // expose the trustless gateway and WebSocket upgrade unencrypted on + // the public network. Turn it on knowingly. // - // Default: false. + // The matching /http multiaddr announcement is controlled by + // AnnounceMultiaddrs. Cleartext Flag `json:",omitempty"` - // AnnounceMultiaddrs derives an HTTP-flavored multiaddr from each of - // this peer's WebSocket listeners and includes it in the announced - // address set: /ws -> /http, /tls/ws -> /tls/http, - // /tls/sni//ws -> /tls/sni//http. The HTTP endpoint shares - // the same TCP port and TLS certificate as the WebSocket listener, so - // this is purely an announcement (no extra socket is opened). Lets - // HTTP retrieval clients (e.g. boxo/bitswap/network/httpnet) discover + // AnnounceMultiaddrs derives an HTTP-flavored multiaddr from each + // WebSocket listener and adds it to the announced address set: + // /ws to /http, /tls/ws to /tls/http, /tls/sni//ws to + // /tls/sni//http. The HTTP endpoint shares the WebSocket + // listener's TCP port and TLS cert; no extra socket is opened. HTTP + // retrieval clients (e.g. boxo/bitswap/network/httpnet) then discover // this peer as an HTTP source through identify, the DHT, and IPNI - // without any out-of-band knowledge. - // - // Subject to Addresses.NoAnnounce filters, just like every other - // announced multiaddr. + // without out-of-band knowledge. // - // Default: true when Enabled is true. + // Subject to Addresses.NoAnnounce filters, like any other announced + // multiaddr. AnnounceMultiaddrs Flag `json:",omitempty"` } -// HTTPProvider defaults. The master switch is off; when on, the libp2p -// transport and the network advertisement default to on (zero-config -// "be discoverable as an HTTP source for what's already exposed"), while -// the cleartext path stays off and must be flipped on explicitly. See -// the per-field doc comments for why. +// HTTPProvider defaults. The master switch is off, so the feature is +// inert until an operator opts in. Once Enabled, the libp2p-stream +// transport comes up automatically because the .well-known descriptor +// already advertises that path; the cleartext listener and the /http +// announcement stay off so operators broadcast HTTP availability on +// purpose, not by accident. const ( DefaultHTTPProviderEnabled = false DefaultHTTPProviderLibp2p = true DefaultHTTPProviderCleartext = false - DefaultHTTPProviderAnnounceMultiaddrs = true + DefaultHTTPProviderAnnounceMultiaddrs = false ) diff --git a/docs/config.md b/docs/config.md index 976af4d84bd..ced4eafe32f 100644 --- a/docs/config.md +++ b/docs/config.md @@ -3947,7 +3947,7 @@ Type: `object` ### `HTTPProvider.Enabled` -Master switch for `HTTPProvider`. When `true`, Kubo registers the trustless gateway handler and (unless overridden) defaults the transport sub-toggles below to `true`. +Master switch for `HTTPProvider`. When `true`, Kubo registers the trustless gateway handler and defaults [`HTTPProvider.Libp2p`](#httpproviderlibp2p) to `true`. The [`HTTPProvider.Cleartext`](#httpprovidercleartext) and [`HTTPProvider.AnnounceMultiaddrs`](#httpproviderannouncemultiaddrs) sub-toggles stay off until set explicitly. Default: `false` @@ -3981,7 +3981,9 @@ This is what lets [`HTTPRetrieval`](#httpretrieval) clients discover this peer a Subject to [`Addresses.NoAnnounce`](#addressesnoannounce) filters, like any other announced multiaddr. -Default: `true` when `HTTPProvider.Enabled=true` +Off by default even when [`HTTPProvider.Enabled`](#httpproviderenabled) is `true`: turning the gateway handler on does not automatically broadcast this node as an HTTP source. Flip this on once you are ready to advertise. + +Default: `false` Type: `flag` diff --git a/test/autotls/canary_test.go b/test/autotls/canary_test.go index 6028f912eac..70668a8df3f 100644 --- a/test/autotls/canary_test.go +++ b/test/autotls/canary_test.go @@ -47,8 +47,11 @@ func TestACMEEndToEnd(t *testing.T) { node := h.NewNode().Init() node.UpdateConfig(func(cfg *config.Config) { // HTTPProvider exposes the trustless gateway over /tls/ws and - // /tls/http using the AutoTLS cert. + // /tls/http using the AutoTLS cert. The canary waits for the + // /tls/http multiaddr in identify output, so enable the + // announcement. cfg.HTTPProvider.Enabled = config.True + cfg.HTTPProvider.AnnounceMultiaddrs = config.True // Point AutoTLS at the in-process Pebble + p2p-forge. cfg.AutoTLS.Enabled = config.True diff --git a/test/cli/http_provider_autotls_test.go b/test/cli/http_provider_autotls_test.go index b29b6d4c779..600649419a5 100644 --- a/test/cli/http_provider_autotls_test.go +++ b/test/cli/http_provider_autotls_test.go @@ -43,6 +43,8 @@ func TestHTTPProviderAutoTLS(t *testing.T) { cfg.AutoTLS.Enabled = config.False cfg.AutoTLS.SelfSignedForTests = config.True cfg.HTTPProvider.Enabled = config.True + // AnnouncesTLSHTTPMultiaddr below needs the /tls/http announcement. + cfg.HTTPProvider.AnnounceMultiaddrs = config.True }) nodes.StartDaemons().Connect() diff --git a/test/cli/http_provider_test.go b/test/cli/http_provider_test.go index 3fb85cd3c12..ef67ec567fa 100644 --- a/test/cli/http_provider_test.go +++ b/test/cli/http_provider_test.go @@ -68,8 +68,10 @@ func TestHTTPProvider(t *testing.T) { "non-upgrade HTTP requests must 404 until HTTPProvider is enabled") }) - // Enable HTTPProvider and restart so FX picks up the handler. + // AnnouncesHTTPMultiaddr below needs both Enabled and + // AnnounceMultiaddrs. Restart so FX picks up the handler. gwNode.IPFS("config", "--json", "HTTPProvider.Enabled", "true") + gwNode.IPFS("config", "--json", "HTTPProvider.AnnounceMultiaddrs", "true") gwNode.StopDaemon().StartDaemon() t.Cleanup(func() { gwNode.StopDaemon() }) nodes.Connect() @@ -134,11 +136,9 @@ func TestHTTPProvider(t *testing.T) { }) t.Run("AnnouncesHTTPMultiaddr", func(t *testing.T) { - // /http must appear next to every announced /ws. - // AnnounceMultiaddrs defaults to true when HTTPProvider.Enabled - // is true. Read announced (not just listening) addresses via - // `ipfs id`; the /http multiaddr is purely an announcement and - // has no socket of its own. + // /http must appear next to every announced /ws. The /http + // multiaddr is purely an announcement and has no socket of + // its own, so read it via `ipfs id` rather than SwarmAddrs. announced := announcedAddrs(t, gwNode) var wsAddrs, httpAddrs []multiaddr.Multiaddr for _, a := range announced {