mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-08-23 12:24:57 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
272e6d9040 |
||
|
|
c1f09e7921 |
||
|
|
17446b419f |
||
|
|
5cdbc89ed4 |
||
|
|
1a814c7e1f |
||
|
|
12ad4ecefc |
31 changed files with 728 additions and 1629 deletions
|
|
@ -39,7 +39,7 @@ proxy/
|
||||||
│ │ └── queries.go # CRUD operations
|
│ │ └── queries.go # CRUD operations
|
||||||
│ ├── storage/ # Artifact file storage
|
│ ├── storage/ # Artifact file storage
|
||||||
│ │ ├── storage.go # Storage interface
|
│ │ ├── storage.go # Storage interface
|
||||||
│ │ └── filesystem.go # Local filesystem impl
|
│ │ └── blob.go # gocloud.dev/blob backends (file, S3, Azure)
|
||||||
│ ├── upstream/ # Upstream registry clients
|
│ ├── upstream/ # Upstream registry clients
|
||||||
│ │ ├── fetcher.go # HTTP artifact fetching
|
│ │ ├── fetcher.go # HTTP artifact fetching
|
||||||
│ │ └── resolver.go # Download URL resolution
|
│ │ └── resolver.go # Download URL resolution
|
||||||
|
|
@ -72,7 +72,7 @@ Key types:
|
||||||
|
|
||||||
### `internal/storage`
|
### `internal/storage`
|
||||||
|
|
||||||
Artifact file storage abstraction. Currently implements local filesystem storage. Designed to allow future backends (S3, GCS).
|
Artifact file storage abstraction backed by `gocloud.dev/blob`. Supports local filesystem (`file://`), S3 (`s3://`), and Azure (`azblob://`) URLs.
|
||||||
|
|
||||||
Interface:
|
Interface:
|
||||||
```go
|
```go
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,10 @@ func runServe() {
|
||||||
logger := setupLogger(cfg.Log.Level, cfg.Log.Format)
|
logger := setupLogger(cfg.Log.Level, cfg.Log.Format)
|
||||||
|
|
||||||
// Create and start server
|
// Create and start server
|
||||||
srv, err := server.New(cfg, logger)
|
srv, err := server.New(cfg, logger, server.BuildInfo{
|
||||||
|
Version: Version,
|
||||||
|
Commit: Commit,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to create server", "error", err)
|
logger.Error("failed to create server", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
||||||
161
go.mod
161
go.mod
|
|
@ -1,6 +1,6 @@
|
||||||
module github.com/git-pkgs/proxy
|
module github.com/git-pkgs/proxy
|
||||||
|
|
||||||
go 1.25.6
|
go 1.26.0
|
||||||
|
|
||||||
toolchain go1.26.6
|
toolchain go1.26.6
|
||||||
|
|
||||||
|
|
@ -10,9 +10,10 @@ require (
|
||||||
github.com/git-pkgs/archives v0.5.1
|
github.com/git-pkgs/archives v0.5.1
|
||||||
github.com/git-pkgs/cooldown v0.1.1
|
github.com/git-pkgs/cooldown v0.1.1
|
||||||
github.com/git-pkgs/enrichment v0.6.5
|
github.com/git-pkgs/enrichment v0.6.5
|
||||||
|
github.com/git-pkgs/integrity v0.1.1
|
||||||
github.com/git-pkgs/magic v0.2.0
|
github.com/git-pkgs/magic v0.2.0
|
||||||
github.com/git-pkgs/purl v0.1.16
|
github.com/git-pkgs/purl v0.1.17
|
||||||
github.com/git-pkgs/registries v0.7.0
|
github.com/git-pkgs/registries v0.8.1
|
||||||
github.com/git-pkgs/spdx v0.3.1
|
github.com/git-pkgs/spdx v0.3.1
|
||||||
github.com/git-pkgs/vers v0.3.1
|
github.com/git-pkgs/vers v0.3.1
|
||||||
github.com/git-pkgs/vulns v0.2.2
|
github.com/git-pkgs/vulns v0.2.2
|
||||||
|
|
@ -31,45 +32,48 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
4d63.com/gocheckcompilerdirectives v1.3.0 // indirect
|
4d63.com/gocheckcompilerdirectives v1.4.0 // indirect
|
||||||
4d63.com/gochecknoglobals v0.2.2 // indirect
|
4d63.com/gochecknoglobals v0.2.2 // indirect
|
||||||
cloud.google.com/go/auth v0.18.2 // indirect
|
charm.land/lipgloss/v2 v2.0.6 // indirect
|
||||||
|
cloud.google.com/go/auth v0.21.0 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||||
codeberg.org/chavacava/garif v0.2.0 // indirect
|
codeberg.org/chavacava/garif v0.2.0 // indirect
|
||||||
codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect
|
codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect
|
||||||
dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect
|
dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect
|
||||||
dev.gaijin.team/go/golib v0.6.0 // indirect
|
dev.gaijin.team/go/exhaustruct/v5 v5.0.3 // indirect
|
||||||
|
dev.gaijin.team/go/golib v0.8.1 // indirect
|
||||||
github.com/4meepo/tagalign v1.4.3 // indirect
|
github.com/4meepo/tagalign v1.4.3 // indirect
|
||||||
github.com/Abirdcfly/dupword v0.1.7 // indirect
|
github.com/Abirdcfly/dupword v0.1.8 // indirect
|
||||||
github.com/AdminBenni/iota-mixing v1.0.0 // indirect
|
github.com/AdminBenni/iota-mixing v1.0.0 // indirect
|
||||||
github.com/AlwxSin/noinlineerr v1.0.5 // indirect
|
github.com/AlwxSin/noinlineerr v1.0.6 // indirect
|
||||||
github.com/Antonboom/errname v1.1.1 // indirect
|
github.com/Antonboom/errname v1.1.2 // indirect
|
||||||
github.com/Antonboom/nilnil v1.1.1 // indirect
|
github.com/Antonboom/nilnil v1.1.2 // indirect
|
||||||
github.com/Antonboom/testifylint v1.6.4 // indirect
|
github.com/Antonboom/testifylint v1.6.4 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 // indirect
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.0 // indirect
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.0 // indirect
|
||||||
|
github.com/ClickHouse/clickhouse-go-linter v1.2.1 // indirect
|
||||||
github.com/Djarvur/go-err113 v0.1.1 // indirect
|
github.com/Djarvur/go-err113 v0.1.1 // indirect
|
||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
github.com/Masterminds/semver/v3 v3.5.0 // indirect
|
||||||
github.com/MirrexOne/unqueryvet v1.5.3 // indirect
|
github.com/MirrexOne/unqueryvet v1.5.4 // indirect
|
||||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect
|
github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
github.com/alecthomas/chroma/v2 v2.23.1 // indirect
|
github.com/alecthomas/chroma/v2 v2.27.0 // indirect
|
||||||
github.com/alecthomas/go-check-sumtype v0.3.1 // indirect
|
github.com/alecthomas/go-check-sumtype v0.3.1 // indirect
|
||||||
github.com/alexkohler/nakedret/v2 v2.0.6 // indirect
|
github.com/alexkohler/nakedret/v2 v2.0.6 // indirect
|
||||||
github.com/alexkohler/prealloc v1.0.2 // indirect
|
github.com/alexkohler/prealloc v1.1.0 // indirect
|
||||||
github.com/alfatraining/structtag v1.0.0 // indirect
|
github.com/alfatraining/structtag v1.0.0 // indirect
|
||||||
github.com/alingse/asasalint v0.0.11 // indirect
|
github.com/alingse/asasalint v0.0.11 // indirect
|
||||||
github.com/alingse/nilnesserr v0.2.0 // indirect
|
github.com/alingse/nilnesserr v0.2.0 // indirect
|
||||||
github.com/anchore/go-struct-converter v0.1.0 // indirect
|
github.com/anchore/go-struct-converter v0.1.0 // indirect
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||||
github.com/ashanbrown/forbidigo/v2 v2.3.0 // indirect
|
github.com/ashanbrown/forbidigo/v2 v2.3.1 // indirect
|
||||||
github.com/ashanbrown/makezero/v2 v2.1.0 // indirect
|
github.com/ashanbrown/makezero/v2 v2.2.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.41.9 // indirect
|
github.com/aws/aws-sdk-go-v2 v1.41.9 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.11 // indirect
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.11 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.32.20 // indirect
|
github.com/aws/aws-sdk-go-v2/config v1.32.20 // indirect
|
||||||
|
|
@ -89,48 +93,49 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.2 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.42.3 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.42.3 // indirect
|
||||||
github.com/aws/smithy-go v1.26.0 // indirect
|
github.com/aws/smithy-go v1.26.0 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bkielbasa/cyclop v1.2.3 // indirect
|
github.com/bkielbasa/cyclop v1.2.3 // indirect
|
||||||
github.com/blizzy78/varnamelen v0.8.0 // indirect
|
github.com/blizzy78/varnamelen v0.8.0 // indirect
|
||||||
github.com/bombsimon/wsl/v4 v4.7.0 // indirect
|
github.com/bombsimon/wsl/v4 v4.7.0 // indirect
|
||||||
github.com/bombsimon/wsl/v5 v5.6.0 // indirect
|
github.com/bombsimon/wsl/v5 v5.9.0 // indirect
|
||||||
github.com/breml/bidichk v0.3.3 // indirect
|
github.com/breml/bidichk v0.3.3 // indirect
|
||||||
github.com/breml/errchkjson v0.4.1 // indirect
|
github.com/breml/errchkjson v0.4.1 // indirect
|
||||||
github.com/butuzov/ireturn v0.4.0 // indirect
|
github.com/butuzov/ireturn v0.4.1 // indirect
|
||||||
github.com/butuzov/mirror v1.3.0 // indirect
|
github.com/butuzov/mirror v1.3.3 // indirect
|
||||||
github.com/catenacyber/perfsprint v0.10.1 // indirect
|
github.com/catenacyber/perfsprint v0.10.1 // indirect
|
||||||
github.com/ccojocar/zxcvbn-go v1.0.4 // indirect
|
github.com/ccojocar/zxcvbn-go v1.0.4 // indirect
|
||||||
github.com/cenk/backoff v2.2.1+incompatible // indirect
|
github.com/cenk/backoff v2.2.1+incompatible // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/charithe/durationcheck v0.0.11 // indirect
|
github.com/charithe/durationcheck v0.0.11 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
||||||
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
github.com/charmbracelet/x/ansi v0.11.8 // indirect
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
|
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
github.com/charmbracelet/x/termios v0.1.1 // indirect
|
||||||
|
github.com/charmbracelet/x/windows v0.2.2 // indirect
|
||||||
github.com/ckaznocha/intrange v0.3.1 // indirect
|
github.com/ckaznocha/intrange v0.3.1 // indirect
|
||||||
|
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||||
github.com/curioswitch/go-reassign v0.3.0 // indirect
|
github.com/curioswitch/go-reassign v0.3.0 // indirect
|
||||||
github.com/daixiang0/gci v0.13.7 // indirect
|
github.com/daixiang0/gci v0.13.7 // indirect
|
||||||
github.com/dave/dst v0.27.3 // indirect
|
github.com/dave/dst v0.27.3 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
|
||||||
github.com/denis-tingaikin/go-header v0.5.0 // indirect
|
github.com/denis-tingaikin/go-header v0.5.0 // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
github.com/dlclark/regexp2/v2 v2.2.1 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/ecosyste-ms/ecosystems-go v0.4.0 // indirect
|
github.com/ecosyste-ms/ecosystems-go v0.4.0 // indirect
|
||||||
github.com/ettle/strcase v0.2.0 // indirect
|
github.com/ettle/strcase v0.2.0 // indirect
|
||||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
|
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
|
||||||
github.com/fatih/color v1.18.0 // indirect
|
github.com/fatih/color v1.19.0 // indirect
|
||||||
github.com/fatih/structtag v1.2.0 // indirect
|
github.com/fatih/structtag v1.2.0 // indirect
|
||||||
github.com/firefart/nonamedreturns v1.0.6 // indirect
|
github.com/firefart/nonamedreturns v1.0.8 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
github.com/fzipp/gocyclo v0.6.0 // indirect
|
github.com/fzipp/gocyclo v0.6.0 // indirect
|
||||||
github.com/ghostiam/protogetter v0.3.20 // indirect
|
github.com/ghostiam/protogetter v0.3.21 // indirect
|
||||||
github.com/git-pkgs/packageurl-go v0.3.1 // indirect
|
github.com/git-pkgs/packageurl-go v0.3.1 // indirect
|
||||||
github.com/git-pkgs/pom v0.1.5 // indirect
|
github.com/git-pkgs/pom v0.1.5 // indirect
|
||||||
github.com/github/go-spdx/v2 v2.7.0 // indirect
|
github.com/github/go-spdx/v2 v2.7.0 // indirect
|
||||||
github.com/go-critic/go-critic v0.14.3 // indirect
|
github.com/go-critic/go-critic v0.14.4 // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
|
|
@ -151,83 +156,82 @@ require (
|
||||||
github.com/gofrs/flock v0.13.0 // indirect
|
github.com/gofrs/flock v0.13.0 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||||
github.com/golangci/asciicheck v0.5.0 // indirect
|
github.com/golangci/asciicheck v0.5.0 // indirect
|
||||||
github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect
|
github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202 // indirect
|
||||||
github.com/golangci/go-printf-func-name v0.1.1 // indirect
|
github.com/golangci/go-printf-func-name v0.1.1 // indirect
|
||||||
github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect
|
github.com/golangci/gofmt v0.0.0-20260820135601-e84e05053792 // indirect
|
||||||
github.com/golangci/golangci-lint/v2 v2.10.1 // indirect
|
github.com/golangci/golangci-lint/v2 v2.13.1 // indirect
|
||||||
github.com/golangci/golines v0.15.0 // indirect
|
github.com/golangci/golines v0.15.0 // indirect
|
||||||
github.com/golangci/misspell v0.8.0 // indirect
|
github.com/golangci/misspell v0.8.0 // indirect
|
||||||
github.com/golangci/plugin-module-register v0.1.2 // indirect
|
github.com/golangci/plugin-module-register v0.1.2 // indirect
|
||||||
github.com/golangci/revgrep v0.8.0 // indirect
|
github.com/golangci/revgrep v0.8.0 // indirect
|
||||||
|
github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba // indirect
|
||||||
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect
|
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect
|
||||||
github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect
|
github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect
|
||||||
github.com/google/go-cmp v0.7.0 // indirect
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
github.com/google/s2a-go v0.1.9 // indirect
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/google/wire v0.7.0 // indirect
|
github.com/google/wire v0.7.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.18 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.19.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.23.0 // indirect
|
||||||
github.com/gordonklaus/ineffassign v0.2.0 // indirect
|
github.com/gordonklaus/ineffassign v0.2.0 // indirect
|
||||||
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
|
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
|
||||||
github.com/gostaticanalysis/comment v1.5.0 // indirect
|
github.com/gostaticanalysis/comment v1.5.0 // indirect
|
||||||
github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect
|
github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect
|
||||||
github.com/gostaticanalysis/nilerr v0.1.2 // indirect
|
github.com/gostaticanalysis/nilerr v0.1.2 // indirect
|
||||||
github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
|
github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
|
||||||
github.com/hashicorp/go-version v1.8.0 // indirect
|
github.com/hashicorp/go-version v1.9.0 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/hexops/gotextdiff v1.0.3 // indirect
|
github.com/hexops/gotextdiff v1.0.3 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jgautheron/goconst v1.8.2 // indirect
|
github.com/jgautheron/goconst v1.11.0 // indirect
|
||||||
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
|
|
||||||
github.com/jjti/go-spancheck v0.6.5 // indirect
|
github.com/jjti/go-spancheck v0.6.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/julz/importas v0.2.0 // indirect
|
github.com/julz/importas v0.2.0 // indirect
|
||||||
github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect
|
github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect
|
||||||
github.com/kisielk/errcheck v1.9.0 // indirect
|
github.com/kisielk/errcheck v1.20.0 // indirect
|
||||||
github.com/kkHAIKE/contextcheck v1.1.6 // indirect
|
github.com/kkHAIKE/contextcheck v1.1.6 // indirect
|
||||||
github.com/kulti/thelper v0.7.1 // indirect
|
github.com/kulti/thelper v0.7.1 // indirect
|
||||||
github.com/kunwardeep/paralleltest v1.0.15 // indirect
|
github.com/kunwardeep/paralleltest v1.0.15 // indirect
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/lasiar/canonicalheader v1.1.2 // indirect
|
github.com/lasiar/canonicalheader v1.1.2 // indirect
|
||||||
github.com/ldez/exptostd v0.4.5 // indirect
|
github.com/ldez/exptostd v0.4.5 // indirect
|
||||||
github.com/ldez/gomoddirectives v0.8.0 // indirect
|
github.com/ldez/gomoddirectives v0.9.0 // indirect
|
||||||
github.com/ldez/grignotin v0.10.1 // indirect
|
github.com/ldez/grignotin v0.10.1 // indirect
|
||||||
github.com/ldez/structtags v0.6.1 // indirect
|
github.com/ldez/structtags v0.6.1 // indirect
|
||||||
github.com/ldez/tagliatelle v0.7.2 // indirect
|
github.com/ldez/tagliatelle v0.7.2 // indirect
|
||||||
github.com/ldez/usetesting v0.5.0 // indirect
|
github.com/ldez/usetesting v0.5.0 // indirect
|
||||||
github.com/leonklingele/grouper v1.1.2 // indirect
|
github.com/leonklingele/grouper v1.1.2 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.4.1 // indirect
|
||||||
github.com/macabu/inamedparam v0.2.0 // indirect
|
github.com/macabu/inamedparam v0.2.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.6 // indirect
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect
|
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect
|
||||||
github.com/manuelarte/funcorder v0.5.0 // indirect
|
github.com/manuelarte/funcorder v0.6.0 // indirect
|
||||||
github.com/maratori/testableexamples v1.0.1 // indirect
|
github.com/maratori/testableexamples v1.0.1 // indirect
|
||||||
github.com/maratori/testpackage v1.1.2 // indirect
|
github.com/maratori/testpackage v1.1.2 // indirect
|
||||||
github.com/matoous/godox v1.1.0 // indirect
|
github.com/matoous/godox v1.1.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.24 // indirect
|
github.com/mattn/go-isatty v0.0.24 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||||
github.com/mgechev/revive v1.14.0 // indirect
|
github.com/mgechev/revive v1.15.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/moricho/tparallel v0.3.2 // indirect
|
github.com/moricho/tparallel v0.3.2 // indirect
|
||||||
github.com/muesli/termenv v0.16.0 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/nakabonne/nestif v0.3.1 // indirect
|
github.com/nakabonne/nestif v0.3.1 // indirect
|
||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||||
github.com/nishanths/exhaustive v0.12.0 // indirect
|
github.com/nishanths/exhaustive v0.12.0 // indirect
|
||||||
github.com/nishanths/predeclared v0.2.2 // indirect
|
github.com/nishanths/predeclared v0.2.2 // indirect
|
||||||
github.com/nunnatsa/ginkgolinter v0.23.0 // indirect
|
github.com/nunnatsa/ginkgolinter v0.24.0 // indirect
|
||||||
github.com/oapi-codegen/nullable v1.2.0 // indirect
|
github.com/oapi-codegen/nullable v1.2.0 // indirect
|
||||||
github.com/oapi-codegen/runtime v1.6.0 // indirect
|
github.com/oapi-codegen/runtime v1.6.0 // indirect
|
||||||
github.com/package-url/packageurl-go v0.1.6 // indirect
|
github.com/package-url/packageurl-go v0.1.6 // indirect
|
||||||
github.com/pandatix/go-cvss v0.6.2 // indirect
|
github.com/pandatix/go-cvss v0.6.2 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.4.3 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
|
||||||
github.com/prometheus/common v0.70.1 // indirect
|
github.com/prometheus/common v0.70.1 // indirect
|
||||||
github.com/prometheus/procfs v0.21.1 // indirect
|
github.com/prometheus/procfs v0.21.1 // indirect
|
||||||
github.com/quasilyte/go-ruleguard v0.4.5 // indirect
|
github.com/quasilyte/go-ruleguard v0.4.5 // indirect
|
||||||
|
|
@ -235,24 +239,25 @@ require (
|
||||||
github.com/quasilyte/gogrep v0.5.0 // indirect
|
github.com/quasilyte/gogrep v0.5.0 // indirect
|
||||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
||||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
|
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
|
||||||
github.com/raeperd/recvcheck v0.2.0 // indirect
|
github.com/raeperd/recvcheck v0.3.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
github.com/rogpeppe/go-internal v1.16.0 // indirect
|
||||||
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 // indirect
|
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 // indirect
|
||||||
github.com/rubyist/circuitbreaker v2.2.1+incompatible // indirect
|
github.com/rubyist/circuitbreaker v2.2.1+incompatible // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/ryancurrah/gomodguard v1.4.1 // indirect
|
github.com/ryancurrah/gomodguard v1.4.1 // indirect
|
||||||
github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
|
github.com/ryancurrah/gomodguard/v2 v2.1.3 // indirect
|
||||||
|
github.com/ryanrolds/sqlclosecheck v0.6.0 // indirect
|
||||||
github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
|
github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 // indirect
|
||||||
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
|
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
|
||||||
github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect
|
github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect
|
||||||
github.com/securego/gosec/v2 v2.23.0 // indirect
|
github.com/securego/gosec/v2 v2.28.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
github.com/sirupsen/logrus v1.10.1 // indirect
|
||||||
github.com/sivchari/containedctx v1.0.3 // indirect
|
github.com/sivchari/containedctx v1.0.3 // indirect
|
||||||
github.com/sonatard/noctx v0.4.0 // indirect
|
github.com/sonatard/noctx v0.5.1 // indirect
|
||||||
github.com/sourcegraph/go-diff v0.7.0 // indirect
|
github.com/sourcegraph/go-diff v0.8.0 // indirect
|
||||||
github.com/spf13/afero v1.15.0 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/cobra v1.10.2 // indirect
|
github.com/spf13/cobra v1.10.2 // indirect
|
||||||
|
|
@ -261,11 +266,11 @@ require (
|
||||||
github.com/spf13/viper v1.12.0 // indirect
|
github.com/spf13/viper v1.12.0 // indirect
|
||||||
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
|
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
|
||||||
github.com/stbenjam/no-sprintf-host-port v0.3.1 // indirect
|
github.com/stbenjam/no-sprintf-host-port v0.3.1 // indirect
|
||||||
github.com/stretchr/objx v0.5.2 // indirect
|
github.com/stretchr/objx v0.5.3 // indirect
|
||||||
github.com/stretchr/testify v1.11.1 // indirect
|
github.com/stretchr/testify v1.12.1 // indirect
|
||||||
github.com/subosito/gotenv v1.4.1 // indirect
|
github.com/subosito/gotenv v1.4.1 // indirect
|
||||||
github.com/tetafro/godot v1.5.4 // indirect
|
github.com/tetafro/godot v1.5.6 // indirect
|
||||||
github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect
|
github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4 // indirect
|
||||||
github.com/timonwong/loggercheck v0.11.0 // indirect
|
github.com/timonwong/loggercheck v0.11.0 // indirect
|
||||||
github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect
|
github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect
|
||||||
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
|
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
|
||||||
|
|
@ -273,8 +278,8 @@ require (
|
||||||
github.com/ultraware/funlen v0.2.0 // indirect
|
github.com/ultraware/funlen v0.2.0 // indirect
|
||||||
github.com/ultraware/whitespace v0.2.0 // indirect
|
github.com/ultraware/whitespace v0.2.0 // indirect
|
||||||
github.com/urfave/cli/v2 v2.3.0 // indirect
|
github.com/urfave/cli/v2 v2.3.0 // indirect
|
||||||
github.com/uudashr/gocognit v1.2.0 // indirect
|
github.com/uudashr/gocognit v1.2.1 // indirect
|
||||||
github.com/uudashr/iface v1.4.1 // indirect
|
github.com/uudashr/iface v1.5.0 // indirect
|
||||||
github.com/xen0n/gosmopolitan v1.3.0 // indirect
|
github.com/xen0n/gosmopolitan v1.3.0 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
github.com/yagipy/maintidx v1.0.0 // indirect
|
||||||
|
|
@ -282,9 +287,9 @@ require (
|
||||||
github.com/ykadowak/zerologlint v0.1.5 // indirect
|
github.com/ykadowak/zerologlint v0.1.5 // indirect
|
||||||
gitlab.com/bosi/decorder v0.4.2 // indirect
|
gitlab.com/bosi/decorder v0.4.2 // indirect
|
||||||
go-simpler.org/musttag v0.14.0 // indirect
|
go-simpler.org/musttag v0.14.0 // indirect
|
||||||
go-simpler.org/sloglint v0.11.1 // indirect
|
go-simpler.org/sloglint v0.12.0 // indirect
|
||||||
go.augendre.info/arangolint v0.4.0 // indirect
|
go.augendre.info/arangolint v0.4.0 // indirect
|
||||||
go.augendre.info/fatcontext v0.9.0 // indirect
|
go.augendre.info/fatcontext v0.10.0 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
go.opentelemetry.io/otel v1.44.0 // indirect
|
go.opentelemetry.io/otel v1.44.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.44.0 // indirect
|
go.opentelemetry.io/otel/metric v1.44.0 // indirect
|
||||||
|
|
@ -294,28 +299,28 @@ require (
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.1 // indirect
|
go.uber.org/zap v1.27.1 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||||
golang.org/x/crypto v0.54.0 // indirect
|
golang.org/x/crypto v0.55.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect
|
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect
|
||||||
golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect
|
golang.org/x/exp/typeparams v0.0.0-20260811152304-ee035b5b010f // indirect
|
||||||
golang.org/x/mod v0.37.0 // indirect
|
golang.org/x/mod v0.40.0 // indirect
|
||||||
golang.org/x/net v0.57.0 // indirect
|
golang.org/x/net v0.58.0 // indirect
|
||||||
golang.org/x/oauth2 v0.36.0 // indirect
|
golang.org/x/oauth2 v0.36.0 // indirect
|
||||||
golang.org/x/sys v0.47.0 // indirect
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
golang.org/x/text v0.40.0 // indirect
|
golang.org/x/text v0.41.0 // indirect
|
||||||
golang.org/x/tools v0.47.0 // indirect
|
golang.org/x/tools v0.49.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||||
google.golang.org/api v0.272.0 // indirect
|
google.golang.org/api v0.288.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800 // indirect
|
||||||
google.golang.org/grpc v1.82.1 // indirect
|
google.golang.org/grpc v1.82.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
honnef.co/go/tools v0.7.0 // indirect
|
honnef.co/go/tools v0.8.0 // indirect
|
||||||
modernc.org/libc v1.74.4 // indirect
|
modernc.org/libc v1.74.4 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/memory v1.11.0 // indirect
|
||||||
mvdan.cc/gofumpt v0.9.2 // indirect
|
mvdan.cc/gofumpt v0.11.0 // indirect
|
||||||
mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect
|
mvdan.cc/unparam v0.0.0-20260818115549-3f964bcb5673 // indirect
|
||||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
377
go.sum
377
go.sum
|
|
@ -1,13 +1,15 @@
|
||||||
4d63.com/gocheckcompilerdirectives v1.3.0 h1:Ew5y5CtcAAQeTVKUVFrE7EwHMrTO6BggtEj8BZSjZ3A=
|
4d63.com/gocheckcompilerdirectives v1.4.0 h1:ZLq62rbGWVmQhiZ8kuNVIT/M09xCSTdJz9K3xOdT/CY=
|
||||||
4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY=
|
4d63.com/gocheckcompilerdirectives v1.4.0/go.mod h1:9ZOAiMOjqC/nRwci2fcUXVHUNLG/cH6r6rhUh+jTFtQ=
|
||||||
4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU=
|
4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU=
|
||||||
4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0=
|
4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0=
|
||||||
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
|
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
|
||||||
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
||||||
|
charm.land/lipgloss/v2 v2.0.6 h1:EaGKeuA8FvF+v2BT5VmZd2LoYLaMZJXA5n34th8nCIQ=
|
||||||
|
charm.land/lipgloss/v2 v2.0.6/go.mod h1:ipDDJNSGa1hlwDtSfW1s2/xR8Vdhbut4PXh2zEKZd0Q=
|
||||||
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
||||||
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||||
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
|
cloud.google.com/go/auth v0.21.0 h1:g/QwYfYb2Ai6HH8oomAOyBaIHLbscZ4+T/F/f5JZHkE=
|
||||||
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
|
cloud.google.com/go/auth v0.21.0/go.mod h1:M9o2Oz+YI2jAfxewJgb1vyI3vceHF+eohmxyzmrl+9s=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||||
|
|
@ -24,23 +26,25 @@ codeberg.org/polyfloyd/go-errorlint v1.9.0 h1:VkdEEmA1VBpH6ecQoMR4LdphVI3fA4RrCh
|
||||||
codeberg.org/polyfloyd/go-errorlint v1.9.0/go.mod h1:GPRRu2LzVijNn4YkrZYJfatQIdS+TrcK8rL5Xs24qw8=
|
codeberg.org/polyfloyd/go-errorlint v1.9.0/go.mod h1:GPRRu2LzVijNn4YkrZYJfatQIdS+TrcK8rL5Xs24qw8=
|
||||||
dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y=
|
dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y=
|
||||||
dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI=
|
dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI=
|
||||||
dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo=
|
dev.gaijin.team/go/exhaustruct/v5 v5.0.3 h1:yOeA7DNjlT8y4yfmN6nWWYYggA13N523YAj9/TXbuTM=
|
||||||
dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE=
|
dev.gaijin.team/go/exhaustruct/v5 v5.0.3/go.mod h1:KwtBsX8nHHH1YxhxkpiBq6bfsmw5WnazWpNvJPHgY9Y=
|
||||||
|
dev.gaijin.team/go/golib v0.8.1 h1:JYju4x9BSo+QD/AYeHULVDcvEhiFg8wOi6pT0IaZF5E=
|
||||||
|
dev.gaijin.team/go/golib v0.8.1/go.mod h1:c5fu7t1RSGMxSQgcUYO1sODbzsYnOCXJLmHeNG1Eb+0=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
|
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
|
||||||
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
|
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
|
||||||
github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8=
|
github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8=
|
||||||
github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c=
|
github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c=
|
||||||
github.com/Abirdcfly/dupword v0.1.7 h1:2j8sInznrje4I0CMisSL6ipEBkeJUJAmK1/lfoNGWrQ=
|
github.com/Abirdcfly/dupword v0.1.8 h1:SrhcUuGsROBuChFxHALRYzyyPODWn9zwghmzPvD9Cd8=
|
||||||
github.com/Abirdcfly/dupword v0.1.7/go.mod h1:K0DkBeOebJ4VyOICFdppB23Q0YMOgVafM0zYW0n9lF4=
|
github.com/Abirdcfly/dupword v0.1.8/go.mod h1:XZrhVnI7YGpsTiWZANSQaBJ4QpL/Tq5vIEdKJJAs9WI=
|
||||||
github.com/AdminBenni/iota-mixing v1.0.0 h1:Os6lpjG2dp/AE5fYBPAA1zfa2qMdCAWwPMCgpwKq7wo=
|
github.com/AdminBenni/iota-mixing v1.0.0 h1:Os6lpjG2dp/AE5fYBPAA1zfa2qMdCAWwPMCgpwKq7wo=
|
||||||
github.com/AdminBenni/iota-mixing v1.0.0/go.mod h1:i4+tpAaB+qMVIV9OK3m4/DAynOd5bQFaOu+2AhtBCNY=
|
github.com/AdminBenni/iota-mixing v1.0.0/go.mod h1:i4+tpAaB+qMVIV9OK3m4/DAynOd5bQFaOu+2AhtBCNY=
|
||||||
github.com/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY=
|
github.com/AlwxSin/noinlineerr v1.0.6 h1:KAvuxunTe9QxvqrFB7nZTdb/7Wzas4AvifslTnG0Ld8=
|
||||||
github.com/AlwxSin/noinlineerr v1.0.5/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc=
|
github.com/AlwxSin/noinlineerr v1.0.6/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc=
|
||||||
github.com/Antonboom/errname v1.1.1 h1:bllB7mlIbTVzO9jmSWVWLjxTEbGBVQ1Ff/ClQgtPw9Q=
|
github.com/Antonboom/errname v1.1.2 h1:dxwONZJua3VB8Xh/VaCjqAcqF645sWWv7xj26zy7tdQ=
|
||||||
github.com/Antonboom/errname v1.1.1/go.mod h1:gjhe24xoxXp0ScLtHzjiXp0Exi1RFLKJb0bVBtWKCWQ=
|
github.com/Antonboom/errname v1.1.2/go.mod h1:YeZIpgLMxT+SNkruGgYkLhzq/9vs3fsolTZegKaKDZI=
|
||||||
github.com/Antonboom/nilnil v1.1.1 h1:9Mdr6BYd8WHCDngQnNVV0b554xyisFioEKi30sksufQ=
|
github.com/Antonboom/nilnil v1.1.2 h1:aNlFuJhaEseXe4fHO3xbjXlSeEiQVYa2lEkWD2s2hAY=
|
||||||
github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V2oYQa8II=
|
github.com/Antonboom/nilnil v1.1.2/go.mod h1:0ynwvphOLmAuMwTNDyBnDZmSwZoDpcFXmUHmzoHH2WA=
|
||||||
github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ=
|
github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ=
|
||||||
github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4=
|
github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28=
|
||||||
|
|
@ -62,6 +66,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.7.0/go.mod h1:HKpQ
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
|
github.com/ClickHouse/clickhouse-go-linter v1.2.1 h1:zGEKIyd5YL08ieWG/LOUmlau2DxbxPVOfAeo+4Jz3ck=
|
||||||
|
github.com/ClickHouse/clickhouse-go-linter v1.2.1/go.mod h1:pLorS7ffPTfuUV9M0SJgfHA/h/WQPQUk2FWG9x74cQ4=
|
||||||
github.com/CycloneDX/cyclonedx-go v0.11.0 h1:GokP8FiRC+foiuwWhSSLpSD5H4hSWtGnR3wo7apkBFI=
|
github.com/CycloneDX/cyclonedx-go v0.11.0 h1:GokP8FiRC+foiuwWhSSLpSD5H4hSWtGnR3wo7apkBFI=
|
||||||
github.com/CycloneDX/cyclonedx-go v0.11.0/go.mod h1:vUvbCXQsEm48OI6oOlanxstwNByXjCZ2wuleUlwGEO8=
|
github.com/CycloneDX/cyclonedx-go v0.11.0/go.mod h1:vUvbCXQsEm48OI6oOlanxstwNByXjCZ2wuleUlwGEO8=
|
||||||
github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g=
|
github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g=
|
||||||
|
|
@ -74,10 +80,10 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapp
|
||||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc=
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc=
|
||||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
github.com/MirrexOne/unqueryvet v1.5.3 h1:LpT3rsH+IY3cQddWF9bg4C7jsbASdGnrOSofY8IPEiw=
|
github.com/MirrexOne/unqueryvet v1.5.4 h1:38QOxShO7JmMWT+eCdDMbcUgGCOeJphVkzzRgyLJgsQ=
|
||||||
github.com/MirrexOne/unqueryvet v1.5.3/go.mod h1:fs9Zq6eh1LRIhsDIsxf9PONVUjYdFHdtkHIgZdJnyPU=
|
github.com/MirrexOne/unqueryvet v1.5.4/go.mod h1:fs9Zq6eh1LRIhsDIsxf9PONVUjYdFHdtkHIgZdJnyPU=
|
||||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4=
|
github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4=
|
||||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo=
|
github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo=
|
||||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||||
|
|
@ -87,16 +93,16 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
|
||||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||||
github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
|
github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs=
|
||||||
github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
|
github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8=
|
||||||
github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU=
|
github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU=
|
||||||
github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E=
|
github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E=
|
||||||
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
||||||
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ=
|
github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ=
|
||||||
github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q=
|
github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q=
|
||||||
github.com/alexkohler/prealloc v1.0.2 h1:MPo8cIkGkZytq7WNH9UHv3DIX1mPz1RatPXnZb0zHWQ=
|
github.com/alexkohler/prealloc v1.1.0 h1:cKGRBqlXw5iyQGLYhrXrDlcHxugXpTq4tQ5c91wkf8M=
|
||||||
github.com/alexkohler/prealloc v1.0.2/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig=
|
github.com/alexkohler/prealloc v1.1.0/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig=
|
||||||
github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc=
|
github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc=
|
||||||
github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus=
|
github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus=
|
||||||
github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw=
|
github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw=
|
||||||
|
|
@ -107,10 +113,10 @@ github.com/anchore/go-struct-converter v0.1.0 h1:2rDRssAl6mgKBSLNiVCMADgZRhoqtw9
|
||||||
github.com/anchore/go-struct-converter v0.1.0/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
|
github.com/anchore/go-struct-converter v0.1.0/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||||
github.com/ashanbrown/forbidigo/v2 v2.3.0 h1:OZZDOchCgsX5gvToVtEBoV2UWbFfI6RKQTir2UZzSxo=
|
github.com/ashanbrown/forbidigo/v2 v2.3.1 h1:KAZijvQ7zeIBKbhikT4jCm0TLYXC4u78bTiLh/8JROI=
|
||||||
github.com/ashanbrown/forbidigo/v2 v2.3.0/go.mod h1:5p6VmsG5/1xx3E785W9fouMxIOkvY2rRV9nMdWadd6c=
|
github.com/ashanbrown/forbidigo/v2 v2.3.1/go.mod h1:2QDkLTzU6TV937eFROamXrW92M3paehdae4HCDCOZCM=
|
||||||
github.com/ashanbrown/makezero/v2 v2.1.0 h1:snuKYMbqosNokUKm+R6/+vOPs8yVAi46La7Ck6QYSaE=
|
github.com/ashanbrown/makezero/v2 v2.2.1 h1:A7uU8dgB1PA9aelTxHMfHIQ8Qev8AB3JLxJUBUsejqM=
|
||||||
github.com/ashanbrown/makezero/v2 v2.1.0/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY=
|
github.com/ashanbrown/makezero/v2 v2.2.1/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.41.9 h1:/rYeyO2+HrMztAmxAq9++XJtFMqSIpSsNA0yDGALYq4=
|
github.com/aws/aws-sdk-go-v2 v1.41.9 h1:/rYeyO2+HrMztAmxAq9++XJtFMqSIpSsNA0yDGALYq4=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.41.9/go.mod h1:+HsoOEX80qAVUitj1A2DhCNTjmb3edVyuDypb6LNEeo=
|
github.com/aws/aws-sdk-go-v2 v1.41.9/go.mod h1:+HsoOEX80qAVUitj1A2DhCNTjmb3edVyuDypb6LNEeo=
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.11 h1:h5+3VT69KUBK24grGuuA5saDJTj2IIjLb9au668Fo5I=
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.11 h1:h5+3VT69KUBK24grGuuA5saDJTj2IIjLb9au668Fo5I=
|
||||||
|
|
@ -149,8 +155,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.42.3 h1:ErklX/7uhSbkAAeyQD/Y1OoQ9hO3
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.42.3/go.mod h1:ULe4HCzfKPiR6R3HEurE3b1upEkuk8AkMrOKtaOxKO8=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.42.3/go.mod h1:ULe4HCzfKPiR6R3HEurE3b1upEkuk8AkMrOKtaOxKO8=
|
||||||
github.com/aws/smithy-go v1.26.0 h1:9ouqbi+NyKP7fV3Te7UElCwdAb6Y8uk7LGwPE5tVe/s=
|
github.com/aws/smithy-go v1.26.0 h1:9ouqbi+NyKP7fV3Te7UElCwdAb6Y8uk7LGwPE5tVe/s=
|
||||||
github.com/aws/smithy-go v1.26.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
github.com/aws/smithy-go v1.26.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
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/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w=
|
github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w=
|
||||||
|
|
@ -160,18 +164,18 @@ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkAp
|
||||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||||
github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ=
|
github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ=
|
||||||
github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg=
|
github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg=
|
||||||
github.com/bombsimon/wsl/v5 v5.6.0 h1:4z+/sBqC5vUmSp1O0mS+czxwH9+LKXtCWtHH9rZGQL8=
|
github.com/bombsimon/wsl/v5 v5.9.0 h1:WCrgZ7RQnZO5oEwbVTlYgBdU3wL294kR1BSWV8vTfsU=
|
||||||
github.com/bombsimon/wsl/v5 v5.6.0/go.mod h1:Uqt2EfrMj2NV8UGoN1f1Y3m0NpUVCsUdrNCdet+8LvU=
|
github.com/bombsimon/wsl/v5 v5.9.0/go.mod h1:kjo4HiAV5FDkHC8/uzJq9mBffEEd6WT/nvN7DoMovDM=
|
||||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
|
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
|
||||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
|
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
|
||||||
github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE=
|
github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE=
|
||||||
github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE=
|
github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE=
|
||||||
github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg=
|
github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg=
|
||||||
github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s=
|
github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s=
|
||||||
github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E=
|
github.com/butuzov/ireturn v0.4.1 h1:vWb3NO4t77iku/sjCQ/2pHTQeOmxEhjIriJqRLg1Y+I=
|
||||||
github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70=
|
github.com/butuzov/ireturn v0.4.1/go.mod h1:q+DXKzTDV5guNuXLnIab9fKXizTn2miZHLhxH7V/GB4=
|
||||||
github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc=
|
github.com/butuzov/mirror v1.3.3 h1:v0RsWBhfFc1RQqE/f3sHpSttKDtodFn0gFmtYyD4/hA=
|
||||||
github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI=
|
github.com/butuzov/mirror v1.3.3/go.mod h1:h9BzzwYnTiHO0GzgvaTqIg7VSsOUhdIv51cHFFBmX1w=
|
||||||
github.com/catenacyber/perfsprint v0.10.1 h1:u7Riei30bk46XsG8nknMhKLXG9BcXz3+3tl/WpKm0PQ=
|
github.com/catenacyber/perfsprint v0.10.1 h1:u7Riei30bk46XsG8nknMhKLXG9BcXz3+3tl/WpKm0PQ=
|
||||||
github.com/catenacyber/perfsprint v0.10.1/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc=
|
github.com/catenacyber/perfsprint v0.10.1/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc=
|
||||||
github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc=
|
github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc=
|
||||||
|
|
@ -182,18 +186,24 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/charithe/durationcheck v0.0.11 h1:g1/EX1eIiKS57NTWsYtHDZ/APfeXKhye1DidBcABctk=
|
github.com/charithe/durationcheck v0.0.11 h1:g1/EX1eIiKS57NTWsYtHDZ/APfeXKhye1DidBcABctk=
|
||||||
github.com/charithe/durationcheck v0.0.11/go.mod h1:x5iZaixRNl8ctbM+3B2RrPG5t856TxRyVQEnbIEM2X4=
|
github.com/charithe/durationcheck v0.0.11/go.mod h1:x5iZaixRNl8ctbM+3B2RrPG5t856TxRyVQEnbIEM2X4=
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 h1:rdnVWKgJpTVXKuKuJyxDJ+NFJdUaUqGvyGy61OcvlbA=
|
||||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886/go.mod h1:nAw0d9PhFp1qdzi2xhQU5YOu5sVpDIHWlaW2Uz/bCro=
|
||||||
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
|
github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ=
|
||||||
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
|
||||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
|
||||||
|
github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
|
||||||
|
github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
|
||||||
github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs=
|
github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs=
|
||||||
github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk=
|
github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk=
|
||||||
|
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
|
||||||
|
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
|
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
|
||||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4=
|
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4=
|
||||||
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-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
|
@ -209,12 +219,15 @@ github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEy
|
||||||
github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo=
|
github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo=
|
||||||
github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
|
github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/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/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8=
|
github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8=
|
||||||
github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY=
|
github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY=
|
||||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8=
|
||||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
|
github.com/dlclark/regexp2/v2 v2.2.1 h1:mf4KkFUj0gJuarK8P+LgiS+Lit7m9N1yAwEfPbee7R0=
|
||||||
|
github.com/dlclark/regexp2/v2 v2.2.1/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
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/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/ecosyste-ms/ecosystems-go v0.4.0 h1:5A+zF+XWT8sYYYjlc2/tI1SmiDGzbHLyT9CapVc5dGA=
|
github.com/ecosyste-ms/ecosystems-go v0.4.0 h1:5A+zF+XWT8sYYYjlc2/tI1SmiDGzbHLyT9CapVc5dGA=
|
||||||
|
|
@ -228,38 +241,40 @@ github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q=
|
||||||
github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A=
|
github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A=
|
||||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
|
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
|
||||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA=
|
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA=
|
||||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
|
||||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE=
|
||||||
github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E=
|
github.com/firefart/nonamedreturns v1.0.8 h1:iB32Dl17zJl1zlVEj/WlUWgx0HiRyQ85OUw1WHa4/II=
|
||||||
github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo=
|
github.com/firefart/nonamedreturns v1.0.8/go.mod h1:vxFNvm5AfP/8rgAKFzYmnqx0yp1HjrYsErZ9pHPTznA=
|
||||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
|
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
|
||||||
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
|
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
|
||||||
github.com/ghostiam/protogetter v0.3.20 h1:oW7OPFit2FxZOpmMRPP9FffU4uUpfeE/rEdE1f+MzD0=
|
github.com/ghostiam/protogetter v0.3.21 h1:EeWTGvL/Eyosp653hiWb6Byx4b69iJC4/E+za7vQHoI=
|
||||||
github.com/ghostiam/protogetter v0.3.20/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI=
|
github.com/ghostiam/protogetter v0.3.21/go.mod h1:iAKSpyoHwYzay+OpjoWgwzRtPFthEfuUvmlomTThck0=
|
||||||
github.com/git-pkgs/archives v0.5.1 h1:qwu/vsoerQZF1iysRtfcxpy1KIUSJJSpXJ5JNxzNoQw=
|
github.com/git-pkgs/archives v0.5.1 h1:qwu/vsoerQZF1iysRtfcxpy1KIUSJJSpXJ5JNxzNoQw=
|
||||||
github.com/git-pkgs/archives v0.5.1/go.mod h1:AKpkxnts49R9uAt1mL2ULYcHrmYujCDVu24IsFvW9so=
|
github.com/git-pkgs/archives v0.5.1/go.mod h1:AKpkxnts49R9uAt1mL2ULYcHrmYujCDVu24IsFvW9so=
|
||||||
github.com/git-pkgs/cooldown v0.1.1 h1:9OqqzCB8gANz/y44SmqGD0Jp8Qtu81D1sCbKl6Ehg7w=
|
github.com/git-pkgs/cooldown v0.1.1 h1:9OqqzCB8gANz/y44SmqGD0Jp8Qtu81D1sCbKl6Ehg7w=
|
||||||
github.com/git-pkgs/cooldown v0.1.1/go.mod h1:v7APuK/UouTiu8mWQZbdDmj7DfxxkGUeuhjaRB5gv9E=
|
github.com/git-pkgs/cooldown v0.1.1/go.mod h1:v7APuK/UouTiu8mWQZbdDmj7DfxxkGUeuhjaRB5gv9E=
|
||||||
github.com/git-pkgs/enrichment v0.6.5 h1:U0SPzWVGoK4R8TwojCTASBRTEV+QSs0IitdLmzI/g/k=
|
github.com/git-pkgs/enrichment v0.6.5 h1:U0SPzWVGoK4R8TwojCTASBRTEV+QSs0IitdLmzI/g/k=
|
||||||
github.com/git-pkgs/enrichment v0.6.5/go.mod h1:Vt2PLMvWPOio9DLyC8Gdhh1yxsHwcRcG+L2Kkc9+kak=
|
github.com/git-pkgs/enrichment v0.6.5/go.mod h1:Vt2PLMvWPOio9DLyC8Gdhh1yxsHwcRcG+L2Kkc9+kak=
|
||||||
|
github.com/git-pkgs/integrity v0.1.1 h1:nHQ7SktOiGM1dOb5BFnkdtttG/6FCgE6r5ru6QnsGts=
|
||||||
|
github.com/git-pkgs/integrity v0.1.1/go.mod h1:hxu24lcd230377hCF28JQW7sGcCbuNLqo/0ULeb+F1Q=
|
||||||
github.com/git-pkgs/magic v0.2.0 h1:c7HqVxnP8c88EaVMH0/KraDFVTcmiXckRiSvNZEnvMQ=
|
github.com/git-pkgs/magic v0.2.0 h1:c7HqVxnP8c88EaVMH0/KraDFVTcmiXckRiSvNZEnvMQ=
|
||||||
github.com/git-pkgs/magic v0.2.0/go.mod h1:3ndidt+yvFaI1M0aEkkzkOlFnLPkeVQASIUojazcxCI=
|
github.com/git-pkgs/magic v0.2.0/go.mod h1:3ndidt+yvFaI1M0aEkkzkOlFnLPkeVQASIUojazcxCI=
|
||||||
github.com/git-pkgs/packageurl-go v0.3.1 h1:WM3RBABQZLaRBxgKyYughc3cVBE8KyQxbSC6Jt5ak7M=
|
github.com/git-pkgs/packageurl-go v0.3.1 h1:WM3RBABQZLaRBxgKyYughc3cVBE8KyQxbSC6Jt5ak7M=
|
||||||
github.com/git-pkgs/packageurl-go v0.3.1/go.mod h1:rcIxiG37BlQLB6FZfgdj9Fm7yjhRQd3l+5o7J0QPAk4=
|
github.com/git-pkgs/packageurl-go v0.3.1/go.mod h1:rcIxiG37BlQLB6FZfgdj9Fm7yjhRQd3l+5o7J0QPAk4=
|
||||||
github.com/git-pkgs/pom v0.1.5 h1:TGT8Az2OMxGWsXnSagtUMGzZm7Oax8HrSCteA+mi0qY=
|
github.com/git-pkgs/pom v0.1.5 h1:TGT8Az2OMxGWsXnSagtUMGzZm7Oax8HrSCteA+mi0qY=
|
||||||
github.com/git-pkgs/pom v0.1.5/go.mod h1:ufdMBe1lKzqOeP9IUb9NPZ458xKV8E8NvuyBMxOfwIk=
|
github.com/git-pkgs/pom v0.1.5/go.mod h1:ufdMBe1lKzqOeP9IUb9NPZ458xKV8E8NvuyBMxOfwIk=
|
||||||
github.com/git-pkgs/purl v0.1.16 h1:VAX6tv0hhdTENbkrGMoPZbOAl1Y8U1/ZnzoCsYuNBYM=
|
github.com/git-pkgs/purl v0.1.17 h1:oRSd8tqllTLl74Wa4WnuqU500hXd9OdUnImOEswQUVE=
|
||||||
github.com/git-pkgs/purl v0.1.16/go.mod h1:7u7ora8tQdrkS7Auclr5v8dCJdjN4ej6AbrvYZi2b7k=
|
github.com/git-pkgs/purl v0.1.17/go.mod h1:7u7ora8tQdrkS7Auclr5v8dCJdjN4ej6AbrvYZi2b7k=
|
||||||
github.com/git-pkgs/registries v0.7.0 h1:+LbOOMHbvjmXGfsi88hcGH+SfTXYsXA3UY5KYI5mB7s=
|
github.com/git-pkgs/registries v0.8.1 h1:Yf2FFdARQ1HcdtZfWBYa5OZFwZHzhFYStiz7qbTDDUU=
|
||||||
github.com/git-pkgs/registries v0.7.0/go.mod h1:VCD4q+ZW0fInopzseg9rAmBEL553R2JQe60UHXtv26w=
|
github.com/git-pkgs/registries v0.8.1/go.mod h1:5dc3V7rOhAI5755L/bDtjtYV4D5XV4J/4ZtyIXSEs0U=
|
||||||
github.com/git-pkgs/spdx v0.3.1 h1:58JPY5X9pYpXvnzzZIgehItlBykeOOw52pNc4OBcS+c=
|
github.com/git-pkgs/spdx v0.3.1 h1:58JPY5X9pYpXvnzzZIgehItlBykeOOw52pNc4OBcS+c=
|
||||||
github.com/git-pkgs/spdx v0.3.1/go.mod h1:cqRoZcvl530s/W+oGNvwjt4ODN8T1W6D/20MUZEFdto=
|
github.com/git-pkgs/spdx v0.3.1/go.mod h1:cqRoZcvl530s/W+oGNvwjt4ODN8T1W6D/20MUZEFdto=
|
||||||
github.com/git-pkgs/vers v0.3.1 h1:jy/ht2wIRJI5zQrccm6GTeYr+hGFwe2z8LV1HOr4Wco=
|
github.com/git-pkgs/vers v0.3.1 h1:jy/ht2wIRJI5zQrccm6GTeYr+hGFwe2z8LV1HOr4Wco=
|
||||||
|
|
@ -270,8 +285,8 @@ github.com/github/go-spdx/v2 v2.7.0 h1:GzfXx4wFdlilARxmFRXW/mgUy3A4vSqZocCMFV6XF
|
||||||
github.com/github/go-spdx/v2 v2.7.0/go.mod h1:Ftc45YYG1WzpzwEPKRVm9Jv8vDqOrN4gWoCkK+bHer0=
|
github.com/github/go-spdx/v2 v2.7.0/go.mod h1:Ftc45YYG1WzpzwEPKRVm9Jv8vDqOrN4gWoCkK+bHer0=
|
||||||
github.com/go-chi/chi/v5 v5.3.1 h1:3j4HZLGZQ3JpMCrPJF/Jl3mYJfWLKBfNJ6quurUGCf8=
|
github.com/go-chi/chi/v5 v5.3.1 h1:3j4HZLGZQ3JpMCrPJF/Jl3mYJfWLKBfNJ6quurUGCf8=
|
||||||
github.com/go-chi/chi/v5 v5.3.1/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
|
github.com/go-chi/chi/v5 v5.3.1/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
|
||||||
github.com/go-critic/go-critic v0.14.3 h1:5R1qH2iFeo4I/RJU8vTezdqs08Egi4u5p6vOESA0pog=
|
github.com/go-critic/go-critic v0.14.4 h1:dSX4C3pWSeuMVxvQh6yG8U0ReSf3YOmKi4nwX5q7n/8=
|
||||||
github.com/go-critic/go-critic v0.14.3/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ=
|
github.com/go-critic/go-critic v0.14.4/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
|
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-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.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
|
@ -289,8 +304,8 @@ github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||||
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
|
github.com/go-quicktest/qt v1.102.0 h1:HSQxCeh5YZH3EL3W39ixjtyaEhcWSXQHtHnMBzSs474=
|
||||||
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
|
github.com/go-quicktest/qt v1.102.0/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI=
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||||
|
|
@ -331,14 +346,14 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0=
|
github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0=
|
||||||
github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ=
|
github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ=
|
||||||
github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw=
|
github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202 h1:CbTB8KpqnViI6lIXxp03Oclc4VFHi3K4BWC1TacsZ+A=
|
||||||
github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E=
|
github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E=
|
||||||
github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarogrvjO9AfiW3B4U=
|
github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarogrvjO9AfiW3B4U=
|
||||||
github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss=
|
github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss=
|
||||||
github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE=
|
github.com/golangci/gofmt v0.0.0-20260820135601-e84e05053792 h1:WL8YKrt3UbOBqSRU7GpP5BTtQTMWtVtj+mfPijgZeIg=
|
||||||
github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY=
|
github.com/golangci/gofmt v0.0.0-20260820135601-e84e05053792/go.mod h1:te5hX0dW4C5r6YbXs+6ysNr8Q5UTmdIqGbb+mlFiYmA=
|
||||||
github.com/golangci/golangci-lint/v2 v2.10.1 h1:flhw5Px6ojbLyEFzXvJn5B2HEdkkRlkhE1SnmCbQBiE=
|
github.com/golangci/golangci-lint/v2 v2.13.1 h1:RuM4OcluM4xFQcGuRE6R7jA33pqxK/W1EsBxpugdZjg=
|
||||||
github.com/golangci/golangci-lint/v2 v2.10.1/go.mod h1:dBsrOk6zj0vDhlTv+IiJGqkDokR24IVTS7W3EVfPTQY=
|
github.com/golangci/golangci-lint/v2 v2.13.1/go.mod h1:HwX7mDzqHbcSxlhrTygjX1GJbAfQ3sJAqOx41qQlhDE=
|
||||||
github.com/golangci/golines v0.15.0 h1:Qnph25g8Y1c5fdo1X7GaRDGgnMHgnxh4Gk4VfPTtRx0=
|
github.com/golangci/golines v0.15.0 h1:Qnph25g8Y1c5fdo1X7GaRDGgnMHgnxh4Gk4VfPTtRx0=
|
||||||
github.com/golangci/golines v0.15.0/go.mod h1:AZjXd23tbHMpowhtnGlj9KCNsysj72aeZVVHnVcZx10=
|
github.com/golangci/golines v0.15.0/go.mod h1:AZjXd23tbHMpowhtnGlj9KCNsysj72aeZVVHnVcZx10=
|
||||||
github.com/golangci/misspell v0.8.0 h1:qvxQhiE2/5z+BVRo1kwYA8yGz+lOlu5Jfvtx2b04Jbg=
|
github.com/golangci/misspell v0.8.0 h1:qvxQhiE2/5z+BVRo1kwYA8yGz+lOlu5Jfvtx2b04Jbg=
|
||||||
|
|
@ -347,6 +362,8 @@ github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3H
|
||||||
github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw=
|
github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw=
|
||||||
github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s=
|
github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s=
|
||||||
github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k=
|
github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k=
|
||||||
|
github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba h1:lqtcnSMDuuJdu/LrKWi5RJzpSNLOJXYe/nzQutTI5kg=
|
||||||
|
github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba/go.mod h1:sCBNcpRmhJCtbFGz49+IM3ETTFf7QdJ30AeYCd43NKk=
|
||||||
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM=
|
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM=
|
||||||
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s=
|
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s=
|
||||||
github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM=
|
github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM=
|
||||||
|
|
@ -370,10 +387,10 @@ 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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
|
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
|
||||||
github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18=
|
github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8=
|
github.com/googleapis/enterprise-certificate-proxy v0.3.18 h1:hvVi34VucdrV1IIsiWuqYM8kutw/92MxNEFxCJZEh0k=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
|
github.com/googleapis/enterprise-certificate-proxy v0.3.18/go.mod h1:rSEsBUemEBZEexP2y6jPp16LUmUbjmSbcPMQizR0o4k=
|
||||||
github.com/googleapis/gax-go/v2 v2.19.0 h1:fYQaUOiGwll0cGj7jmHT/0nPlcrZDFPrZRhTsoCr8hE=
|
github.com/googleapis/gax-go/v2 v2.23.0 h1:Tchl7qkvE7Ip3y+ztvNufYFvkfqTe7NfLTYGIdJRLuE=
|
||||||
github.com/googleapis/gax-go/v2 v2.19.0/go.mod h1:w2ROXVdfGEVFXzmlciUU4EdjHgWvB5h2n6x/8XSTTJA=
|
github.com/googleapis/gax-go/v2 v2.23.0/go.mod h1:rBQKOVJCdb8IFEzg+FCwlt1LP/xMDGuqUXhUG+XMXEg=
|
||||||
github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs=
|
github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs=
|
||||||
github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw=
|
github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw=
|
||||||
github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk=
|
github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk=
|
||||||
|
|
@ -393,8 +410,8 @@ github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1T
|
||||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
|
github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA=
|
||||||
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
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/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
|
|
@ -403,10 +420,8 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq
|
||||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4=
|
github.com/jgautheron/goconst v1.11.0 h1:KgN90z5qXt5f0Uzf3cWXev3hfMMFUyNeKdpkSBRvLDk=
|
||||||
github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako=
|
github.com/jgautheron/goconst v1.11.0/go.mod h1:0p+wv1lFOiUr0IlNNT1nrm6+8DB8u2sU6KHGzFRXHDc=
|
||||||
github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs=
|
|
||||||
github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c=
|
|
||||||
github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8=
|
github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8=
|
||||||
github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU=
|
github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU=
|
||||||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||||
|
|
@ -420,8 +435,8 @@ github.com/karamaru-alpha/copyloopvar v1.2.2 h1:yfNQvP9YaGQR7VaWLYcfZUlRP2eo2vhE
|
||||||
github.com/karamaru-alpha/copyloopvar v1.2.2/go.mod h1:oY4rGZqZ879JkJMtX3RRkcXRkmUvH0x35ykgaKgsgJY=
|
github.com/karamaru-alpha/copyloopvar v1.2.2/go.mod h1:oY4rGZqZ879JkJMtX3RRkcXRkmUvH0x35ykgaKgsgJY=
|
||||||
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
|
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
|
||||||
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
|
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
|
||||||
github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M=
|
github.com/kisielk/errcheck v1.20.0 h1:9rwHBNKzd4wkDWcROy3DvFGNqEPlkxBg305rvk7HabI=
|
||||||
github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8=
|
github.com/kisielk/errcheck v1.20.0/go.mod h1:O+f80MKNwX8Oor2jwgpeQ9An7uJm+hRSgT+h22knRJU=
|
||||||
github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE=
|
github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE=
|
||||||
github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg=
|
github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg=
|
||||||
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
|
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
|
||||||
|
|
@ -443,8 +458,8 @@ github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0
|
||||||
github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI=
|
github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI=
|
||||||
github.com/ldez/exptostd v0.4.5 h1:kv2ZGUVI6VwRfp/+bcQ6Nbx0ghFWcGIKInkG/oFn1aQ=
|
github.com/ldez/exptostd v0.4.5 h1:kv2ZGUVI6VwRfp/+bcQ6Nbx0ghFWcGIKInkG/oFn1aQ=
|
||||||
github.com/ldez/exptostd v0.4.5/go.mod h1:QRjHRMXJrCTIm9WxVNH6VW7oN7KrGSht69bIRwvdFsM=
|
github.com/ldez/exptostd v0.4.5/go.mod h1:QRjHRMXJrCTIm9WxVNH6VW7oN7KrGSht69bIRwvdFsM=
|
||||||
github.com/ldez/gomoddirectives v0.8.0 h1:JqIuTtgvFC2RdH1s357vrE23WJF2cpDCPFgA/TWDGpk=
|
github.com/ldez/gomoddirectives v0.9.0 h1:2YV/EX7nVlWL4jySusYTzBKHuE3D2fgcRsQuMa3yIoo=
|
||||||
github.com/ldez/gomoddirectives v0.8.0/go.mod h1:jutzamvZR4XYJLr0d5Honycp4Gy6GEg2mS9+2YX3F1Q=
|
github.com/ldez/gomoddirectives v0.9.0/go.mod h1:DdZzfm9MdXCjn2/UGYXCFfo+tzrp2Ib4iD2Q0kIJkwE=
|
||||||
github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o=
|
github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o=
|
||||||
github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas=
|
github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas=
|
||||||
github.com/ldez/structtags v0.6.1 h1:bUooFLbXx41tW8SvkfwfFkkjPYvFFs59AAMgVg6DUBk=
|
github.com/ldez/structtags v0.6.1 h1:bUooFLbXx41tW8SvkfwfFkkjPYvFFs59AAMgVg6DUBk=
|
||||||
|
|
@ -458,8 +473,8 @@ github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFB
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ=
|
github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ=
|
||||||
github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
|
github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
github.com/lucasb-eyer/go-colorful v1.4.1 h1:1EO+WB73+EH8EVbzlrG3KLAfEypQWVHIBqlTf+2hNss=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.4.1/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE=
|
github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE=
|
||||||
github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U=
|
github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U=
|
||||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||||
|
|
@ -471,8 +486,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww=
|
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww=
|
||||||
github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM=
|
github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM=
|
||||||
github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8=
|
github.com/manuelarte/funcorder v0.6.0 h1:0hBngc4fa1IgNiI65A7sFGkMvoMCc878RjqB5V7rWP0=
|
||||||
github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA=
|
github.com/manuelarte/funcorder v0.6.0/go.mod h1:id3NDhXdQBmeqXH7eVC6Z89xS6JxvZ8kF9xUxpArU/g=
|
||||||
github.com/maratori/testableexamples v1.0.1 h1:HfOQXs+XgfeRBJ+Wz0XfH+FHnoY9TVqL6Fcevpzy4q8=
|
github.com/maratori/testableexamples v1.0.1 h1:HfOQXs+XgfeRBJ+Wz0XfH+FHnoY9TVqL6Fcevpzy4q8=
|
||||||
github.com/maratori/testableexamples v1.0.1/go.mod h1:XE2F/nQs7B9N08JgyRmdGjYVGqxWwClLPCGSQhXQSrQ=
|
github.com/maratori/testableexamples v1.0.1/go.mod h1:XE2F/nQs7B9N08JgyRmdGjYVGqxWwClLPCGSQhXQSrQ=
|
||||||
github.com/maratori/testpackage v1.1.2 h1:ffDSh+AgqluCLMXhM19f/cpvQAKygKAJXFl9aUjmbqs=
|
github.com/maratori/testpackage v1.1.2 h1:ffDSh+AgqluCLMXhM19f/cpvQAKygKAJXFl9aUjmbqs=
|
||||||
|
|
@ -481,24 +496,24 @@ github.com/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4=
|
||||||
github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs=
|
github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs=
|
||||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
||||||
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/mgechev/revive v1.14.0 h1:CC2Ulb3kV7JFYt+izwORoS3VT/+Plb8BvslI/l1yZsc=
|
github.com/mgechev/revive v1.15.0 h1:vJ0HzSBzfNyPbHKolgiFjHxLek9KUijhqh42yGoqZ8Q=
|
||||||
github.com/mgechev/revive v1.14.0/go.mod h1:MvnujelCZBZCaoDv5B3foPo6WWgULSSFxvfxp7GsPfo=
|
github.com/mgechev/revive v1.15.0/go.mod h1:LlAKO3QQe9OJ0pVZzI2GPa8CbXGZ/9lNpCGvK4T/a8A=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
|
github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
|
||||||
github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
|
github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
|
||||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U=
|
github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U=
|
||||||
|
|
@ -510,16 +525,16 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK
|
||||||
github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs=
|
github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs=
|
||||||
github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk=
|
github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk=
|
||||||
github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c=
|
github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c=
|
||||||
github.com/nunnatsa/ginkgolinter v0.23.0 h1:x3o4DGYOWbBMP/VdNQKgSj+25aJKx2Pe6lHr8gBcgf8=
|
github.com/nunnatsa/ginkgolinter v0.24.0 h1:Mp0EagluLFP98JatP6nqp/gGEoljNG97uf9AcxcBVy8=
|
||||||
github.com/nunnatsa/ginkgolinter v0.23.0/go.mod h1:9qN1+0akwXEccwV1CAcCDfcoBlWXHB+ML9884pL4SZ4=
|
github.com/nunnatsa/ginkgolinter v0.24.0/go.mod h1:2ZMRuzX6+3XXyY6UZOwb6n+MCocVGbkIsDBC4vuWz5c=
|
||||||
github.com/oapi-codegen/nullable v1.2.0 h1:VflFkDW980KhBPiFF7nWSyjg+r4Obqj8lXipV0UkP5w=
|
github.com/oapi-codegen/nullable v1.2.0 h1:VflFkDW980KhBPiFF7nWSyjg+r4Obqj8lXipV0UkP5w=
|
||||||
github.com/oapi-codegen/nullable v1.2.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY=
|
github.com/oapi-codegen/nullable v1.2.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY=
|
||||||
github.com/oapi-codegen/runtime v1.6.0 h1:7Xx+GlueD6nRuyKoCPzL434Jfi3BetbiJOrzCHp/VPU=
|
github.com/oapi-codegen/runtime v1.6.0 h1:7Xx+GlueD6nRuyKoCPzL434Jfi3BetbiJOrzCHp/VPU=
|
||||||
github.com/oapi-codegen/runtime v1.6.0/go.mod h1:GwV7hC2hviaMzj+ITfHVRESK5J2W/GefVwIND/bMGvU=
|
github.com/oapi-codegen/runtime v1.6.0/go.mod h1:GwV7hC2hviaMzj+ITfHVRESK5J2W/GefVwIND/bMGvU=
|
||||||
github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
|
github.com/onsi/ginkgo/v2 v2.32.0 h1:Hw7s2pVrQo/8Yz5N77qdnpHaoc+c6cC9WIV1Jce+J6E=
|
||||||
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
|
github.com/onsi/ginkgo/v2 v2.32.0/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44=
|
||||||
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
|
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
|
||||||
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
|
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
|
||||||
github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
|
github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
|
||||||
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||||
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||||
|
|
@ -533,16 +548,17 @@ github.com/pandatix/go-cvss v0.6.2 h1:TFiHlzUkT67s6UkelHmK6s1INKVUG7nlKYiWWDTITG
|
||||||
github.com/pandatix/go-cvss v0.6.2/go.mod h1:jDXYlQBZrc8nvrMUVVvTG8PhmuShOnKrxP53nOFkt8Q=
|
github.com/pandatix/go-cvss v0.6.2/go.mod h1:jDXYlQBZrc8nvrMUVVvTG8PhmuShOnKrxP53nOFkt8Q=
|
||||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea h1:sKwxy1H95npauwu8vtF95vG/syrL0p8fSZo/XlDg5gk=
|
github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea h1:sKwxy1H95npauwu8vtF95vG/syrL0p8fSZo/XlDg5gk=
|
||||||
github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea/go.mod h1:1VcHEd3ro4QMoHfiNl/j7Jkln9+KQuorp0PItHMJYNg=
|
github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea/go.mod h1:1VcHEd3ro4QMoHfiNl/j7Jkln9+KQuorp0PItHMJYNg=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
|
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
|
||||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU=
|
github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU=
|
||||||
github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE=
|
github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE=
|
||||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
|
|
@ -561,15 +577,14 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl
|
||||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
|
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
|
||||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs=
|
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs=
|
||||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ=
|
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ=
|
||||||
github.com/raeperd/recvcheck v0.2.0 h1:GnU+NsbiCqdC2XX5+vMZzP+jAJC5fht7rcVTAhX74UI=
|
github.com/raeperd/recvcheck v0.3.0 h1:PM+XYvyxIj3bo+kobJfFTdTuU3Lmfu96mKDbyHDbRt8=
|
||||||
github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU=
|
github.com/raeperd/recvcheck v0.3.0/go.mod h1:PZNwG+HztFYMH2ZPq0Hu3QgkV2yiA6VrtNz9c1fXWJo=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
|
||||||
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 h1:18kd+8ZUlt/ARXhljq+14TwAoKa61q6dX8jtwOf6DH8=
|
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 h1:18kd+8ZUlt/ARXhljq+14TwAoKa61q6dX8jtwOf6DH8=
|
||||||
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA=
|
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA=
|
||||||
github.com/rubyist/circuitbreaker v2.2.1+incompatible h1:KUKd/pV8Geg77+8LNDwdow6rVCAYOp8+kHUyFvL6Mhk=
|
github.com/rubyist/circuitbreaker v2.2.1+incompatible h1:KUKd/pV8Geg77+8LNDwdow6rVCAYOp8+kHUyFvL6Mhk=
|
||||||
|
|
@ -579,31 +594,31 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g=
|
github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g=
|
||||||
github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I=
|
github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I=
|
||||||
github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU=
|
github.com/ryancurrah/gomodguard/v2 v2.1.3 h1:E7sz3PJwE9Ba1reVxSpF6XLCPJZ74Kfw/LabTNM4GIA=
|
||||||
github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ=
|
github.com/ryancurrah/gomodguard/v2 v2.1.3/go.mod h1:CQicdLGatWMxLX53JzoBjYlsNZhHbmLv2AVa0s2aivU=
|
||||||
|
github.com/ryanrolds/sqlclosecheck v0.6.0 h1:pEyL9okISdg1F1SEpJNlrEotkTGerv5BMk7U4AG0eVg=
|
||||||
|
github.com/ryanrolds/sqlclosecheck v0.6.0/go.mod h1:xyX16hsDaCMXHrMJ3JMzGf5OpDfHTOTTQrT7HOFUmeU=
|
||||||
github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0=
|
github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0=
|
||||||
github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4=
|
github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 h1:1EYB5IzjZawrrnELUi78f9fPu57HuXjmddZPjrls/28=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.3/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||||
github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw=
|
github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw=
|
||||||
github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ=
|
github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ=
|
||||||
github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ=
|
github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ=
|
||||||
github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8=
|
github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8=
|
||||||
github.com/securego/gosec/v2 v2.23.0 h1:h4TtF64qFzvnkqvsHC/knT7YC5fqyOCItlVR8+ptEBo=
|
github.com/securego/gosec/v2 v2.28.0 h1:ZsSdiDb0AtTpLFVol5z91gbMei9ZiLEPG/pZjZujp7c=
|
||||||
github.com/securego/gosec/v2 v2.23.0/go.mod h1:qRHEgXLFuYUDkI2T7W7NJAmOkxVhkR0x9xyHOIcMNZ0=
|
github.com/securego/gosec/v2 v2.28.0/go.mod h1:lb4/9AHe+lJy/kjWmWRWWsEipvbwGKuxf+tY1Pmjdnk=
|
||||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
|
||||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
github.com/sirupsen/logrus v1.10.1 h1:xi4336Zh11WpU14fXR6I67V3yaTPQYwRx2WEtHbRg4Q=
|
||||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
github.com/sirupsen/logrus v1.10.1/go.mod h1:vsQHnG7xzNsxk3NrwboUiWPnIC3dmbjcGPykD7+tiHk=
|
||||||
github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE=
|
github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE=
|
||||||
github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4=
|
github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4=
|
||||||
github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o=
|
github.com/sonatard/noctx v0.5.1 h1:wklWg9c9ZYugOAk7qG4yP4PBrlQsmSLPTvW1K4PRQMs=
|
||||||
github.com/sonatard/noctx v0.4.0/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas=
|
github.com/sonatard/noctx v0.5.1/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas=
|
||||||
github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0=
|
github.com/sourcegraph/go-diff v0.8.0 h1:ipIyu4cTsLbIrln4l0qtHA3r0a7gyK4ntKjtQytHhvY=
|
||||||
github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
|
github.com/sourcegraph/go-diff v0.8.0/go.mod h1:hWlcO7Al+UZStZAP8rBumHpCK5ZHQ5BXsMls8p4+F5E=
|
||||||
github.com/spdx/tools-golang v0.5.7 h1:+sWcKGnhwp3vLdMqPcLdA6QK679vd86cK9hQWH3AwCg=
|
github.com/spdx/tools-golang v0.5.7 h1:+sWcKGnhwp3vLdMqPcLdA6QK679vd86cK9hQWH3AwCg=
|
||||||
github.com/spdx/tools-golang v0.5.7/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw=
|
github.com/spdx/tools-golang v0.5.7/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw=
|
||||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||||
|
|
@ -628,14 +643,14 @@ github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRk
|
||||||
github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g=
|
github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g=
|
||||||
github.com/stbenjam/no-sprintf-host-port v0.3.1/go.mod h1:ODbZesTCHMVKthBHskvUUexdcNHAQRXk9NpSsL8p/HQ=
|
github.com/stbenjam/no-sprintf-host-port v0.3.1/go.mod h1:ODbZesTCHMVKthBHskvUUexdcNHAQRXk9NpSsL8p/HQ=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
|
||||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||||
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
|
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
|
||||||
|
|
@ -646,10 +661,10 @@ github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpR
|
||||||
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
|
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
|
||||||
github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo=
|
github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo=
|
||||||
github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
|
github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
|
||||||
github.com/tetafro/godot v1.5.4 h1:u1ww+gqpRLiIA16yF2PV1CV1n/X3zhyezbNXC3E14Sg=
|
github.com/tetafro/godot v1.5.6 h1:IEkrFCwXaYHlOn4mGzGS3F3dkP6m9t0jpwqBFPIkKiA=
|
||||||
github.com/tetafro/godot v1.5.4/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU=
|
github.com/tetafro/godot v1.5.6/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU=
|
||||||
github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk=
|
github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4 h1:SiHe5XLTn9sFWJ5pBwJ5FN/4j34q9ZlOAD//kMoMYp0=
|
||||||
github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460=
|
github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4/go.mod h1:sDHLK7rb/59v/ZxZ7KtymgcoxuUMxjXq8gtu9VMOK8M=
|
||||||
github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M=
|
github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M=
|
||||||
github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8=
|
github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8=
|
||||||
github.com/tomarrell/wrapcheck/v2 v2.12.0 h1:H/qQ1aNWz/eeIhxKAFvkfIA+N7YDvq6TWVFL27Of9is=
|
github.com/tomarrell/wrapcheck/v2 v2.12.0 h1:H/qQ1aNWz/eeIhxKAFvkfIA+N7YDvq6TWVFL27Of9is=
|
||||||
|
|
@ -664,10 +679,10 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW
|
||||||
github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8=
|
github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8=
|
||||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA=
|
github.com/uudashr/gocognit v1.2.1 h1:CSJynt5txTnORn/DkhiB4mZjwPuifyASC8/6Q0I/QS4=
|
||||||
github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU=
|
github.com/uudashr/gocognit v1.2.1/go.mod h1:acaubQc6xYlXFEMb9nWX2dYBzJ/bIjEkc1zzvyIZg5Q=
|
||||||
github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU=
|
github.com/uudashr/iface v1.5.0 h1:PgdMt4uAettGG8K/Kbamc4B9FABgUgnS3TLbl6fnjEk=
|
||||||
github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg=
|
github.com/uudashr/iface v1.5.0/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||||
|
|
@ -687,7 +702,6 @@ github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/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.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.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo=
|
gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo=
|
||||||
|
|
@ -696,20 +710,20 @@ go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ=
|
||||||
go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28=
|
go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28=
|
||||||
go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo=
|
go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo=
|
||||||
go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE=
|
go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE=
|
||||||
go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s=
|
go-simpler.org/sloglint v0.12.0 h1:UzWDlLWNE5FLqsvyq3tWYHuQMbqrervOhT8qPl4Mmw4=
|
||||||
go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ=
|
go-simpler.org/sloglint v0.12.0/go.mod h1:jBjjC2bm8rYrs88oTRlFX497kWjJsyZWYoNaXkGRI6I=
|
||||||
go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR50=
|
go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR50=
|
||||||
go.augendre.info/arangolint v0.4.0/go.mod h1:l+f/b4plABuFISuKnTGD4RioXiCCgghv2xqst/xOvAA=
|
go.augendre.info/arangolint v0.4.0/go.mod h1:l+f/b4plABuFISuKnTGD4RioXiCCgghv2xqst/xOvAA=
|
||||||
go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE=
|
go.augendre.info/fatcontext v0.10.0 h1:HhFopmivh8U1+AU7f0kuwUeg2eiIns7YsGQOMHwSJ90=
|
||||||
go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw=
|
go.augendre.info/fatcontext v0.10.0/go.mod h1:pqpGvA9GlrXy+aXkp8L2dKz12Zp4g2FhzcAtwToU+2w=
|
||||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
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/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU=
|
go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU=
|
||||||
go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs=
|
go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs=
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04=
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04=
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0/go.mod h1:NoUCKYWK+3ecatC4HjkRktREheMeEtrXoQxrqYFeHSc=
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0/go.mod h1:NoUCKYWK+3ecatC4HjkRktREheMeEtrXoQxrqYFeHSc=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
|
||||||
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
|
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
|
||||||
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
|
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
|
||||||
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
|
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
|
||||||
|
|
@ -730,51 +744,43 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
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/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=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||||
gocloud.dev v0.46.0 h1:niIuZwSjMtBx8K+ITB2s5kZullB13PGOS2ZoQPZxQ4Q=
|
gocloud.dev v0.46.0 h1:niIuZwSjMtBx8K+ITB2s5kZullB13PGOS2ZoQPZxQ4Q=
|
||||||
gocloud.dev v0.46.0/go.mod h1:ACQe+2qO+hEO+pdcvvsM+RB63r8TyGD1W3ESCLFyzvM=
|
gocloud.dev v0.46.0/go.mod h1:ACQe+2qO+hEO+pdcvvsM+RB63r8TyGD1W3ESCLFyzvM=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
|
||||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
|
||||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
|
||||||
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
|
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
|
||||||
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
|
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 h1:qWFG1Dj7TBjOjOvhEOkmyGPVoquqUKnIU0lEVLp8xyk=
|
golang.org/x/exp/typeparams v0.0.0-20260811152304-ee035b5b010f h1:+lI8cDJ4uceLipg2f1ODay7fEuLkk0BIHXd6PB8icxo=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms=
|
golang.org/x/exp/typeparams v0.0.0-20260811152304-ee035b5b010f/go.mod h1:PqrXSW65cXDZH0k4IeUbhmg/bcAZDbzNz3byBpKCsXo=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/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.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
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.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=
|
||||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=
|
||||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
|
||||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
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.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
|
||||||
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
|
||||||
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
|
||||||
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
|
||||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
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/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|
@ -784,8 +790,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
|
||||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
|
||||||
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||||
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
|
@ -794,10 +798,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
@ -805,27 +807,19 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|
||||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
|
||||||
golang.org/x/text v0.3.0/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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||||
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
|
||||||
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
|
||||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
@ -834,14 +828,11 @@ golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWc
|
||||||
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
|
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
|
||||||
golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
|
golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
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.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
|
||||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
||||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
|
||||||
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
|
||||||
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
|
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
|
||||||
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
||||||
|
|
@ -854,14 +845,14 @@ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhS
|
||||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
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 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||||
google.golang.org/api v0.272.0 h1:eLUQZGnAS3OHn31URRf9sAmRk3w2JjMx37d2k8AjJmA=
|
google.golang.org/api v0.288.0 h1:glhO/J88obKP5I269W3hB73dvBKrjU56ZfmNlNXpgTU=
|
||||||
google.golang.org/api v0.272.0/go.mod h1:wKjowi5LNJc5qarNvDCvNQBn3rVK8nSy6jg2SwRwzIA=
|
google.golang.org/api v0.288.0/go.mod h1:lM2kYRzYUCBY91P9h6VF1PYmvhxii3O5hji37qRvIcY=
|
||||||
google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE=
|
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0=
|
||||||
google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw=
|
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260630182238-925bb5da69e7 h1:jQ9p21COKWjP3VwuFrNRiiOTMh3mPpN45R7SLrH/HUU=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260630182238-925bb5da69e7/go.mod h1:KqHwBx2upmfa1XSi1WuRvC+2VGCLtooKkfmyvRbUmqA=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800 h1:qEHAMpSaUhtD0p3NbEEI83HwNGFxEwaSJ1G9PLnCBZE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||||
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
||||||
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
||||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||||
|
|
@ -881,8 +872,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU=
|
honnef.co/go/tools v0.8.0 h1:UacpzPr7D6i5BAjTkA7sNVcx4kIbhAZcQ4zYtKiXx68=
|
||||||
honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc=
|
honnef.co/go/tools v0.8.0/go.mod h1:XA+OnlRA9EDh/ukGvXMNSZNKGwFQJ+5dER0ioUkOxks=
|
||||||
modernc.org/cc/v4 v4.29.1 h1:MKgdCV3WykTSPqpVrnxdEDS0HEd2FHpKZDzxzU5LyeI=
|
modernc.org/cc/v4 v4.29.1 h1:MKgdCV3WykTSPqpVrnxdEDS0HEd2FHpKZDzxzU5LyeI=
|
||||||
modernc.org/cc/v4 v4.29.1/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
|
modernc.org/cc/v4 v4.29.1/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
|
||||||
modernc.org/ccgo/v4 v4.34.6 h1:sBgfIwyN0TQ9C5hwIeuqyeAKyMWnbvj2fvpF4L11uzU=
|
modernc.org/ccgo/v4 v4.34.6 h1:sBgfIwyN0TQ9C5hwIeuqyeAKyMWnbvj2fvpF4L11uzU=
|
||||||
|
|
@ -911,9 +902,9 @@ modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4=
|
mvdan.cc/gofumpt v0.11.0 h1:0H01XB95PnN2QgCSR9ELdZyTlJqNZ7181B0BTMh5VZc=
|
||||||
mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s=
|
mvdan.cc/gofumpt v0.11.0/go.mod h1:BeT5wCsOJt6J9zT2MZIOGszjUHzFkn1/l9g6xAzqsXo=
|
||||||
mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI=
|
mvdan.cc/unparam v0.0.0-20260818115549-3f964bcb5673 h1:dEE6li4OPIE54oojY2qaayFS1fSp17G14si0gXRxl0U=
|
||||||
mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15/go.mod h1:4M5MMXl2kW6fivUT6yRGpLLPNfuGtU2Z0cPvFquGDYU=
|
mvdan.cc/unparam v0.0.0-20260818115549-3f964bcb5673/go.mod h1:62roFV3D3nYOWIXv3PfGO4UYEKAotz2WgLywT87ONd8=
|
||||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||||
|
|
|
||||||
|
|
@ -928,8 +928,7 @@ func ParseSize(s string) (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s2 := range suffixes {
|
for _, s2 := range suffixes {
|
||||||
if strings.HasSuffix(s, s2.suffix) {
|
if numStr, ok := strings.CutSuffix(s, s2.suffix); ok {
|
||||||
numStr := strings.TrimSuffix(s, s2.suffix)
|
|
||||||
num, err := strconv.ParseFloat(numStr, 64)
|
num, err := strconv.ParseFloat(numStr, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("invalid number %q", numStr)
|
return 0, fmt.Errorf("invalid number %q", numStr)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testContentHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||||
|
testIntegrity = "sha512-z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg=="
|
||||||
|
)
|
||||||
|
|
||||||
func TestCreateAndOpen(t *testing.T) {
|
func TestCreateAndOpen(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
dbPath := filepath.Join(dir, "test.db")
|
dbPath := filepath.Join(dir, "test.db")
|
||||||
|
|
@ -132,7 +137,7 @@ func TestVersionCRUD(t *testing.T) {
|
||||||
v := &Version{
|
v := &Version{
|
||||||
PURL: "pkg:npm/lodash@4.17.21",
|
PURL: "pkg:npm/lodash@4.17.21",
|
||||||
PackagePURL: "pkg:npm/lodash",
|
PackagePURL: "pkg:npm/lodash",
|
||||||
Integrity: sql.NullString{String: "sha512-abc123", Valid: true},
|
Integrity: sql.NullString{String: testIntegrity, Valid: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.UpsertVersion(v)
|
err = db.UpsertVersion(v)
|
||||||
|
|
@ -200,7 +205,7 @@ func TestArtifactCRUD(t *testing.T) {
|
||||||
t.Error("expected artifact to not be cached yet")
|
t.Error("expected artifact to not be cached yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.MarkArtifactCached(versionPURL, "lodash-4.17.21.tgz", "/cache/npm/lodash-4.17.21.tgz", "sha256-abc", 12345, "application/gzip")
|
err = db.MarkArtifactCached(versionPURL, "lodash-4.17.21.tgz", "/cache/npm/lodash-4.17.21.tgz", testContentHash, 12345, "application/gzip")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("MarkArtifactCached failed: %v", err)
|
t.Fatalf("MarkArtifactCached failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +262,7 @@ func TestGetCachedArtifact(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.MarkArtifactCached(versionPURL, filename, "/cache/npm/"+filename,
|
if err := db.MarkArtifactCached(versionPURL, filename, "/cache/npm/"+filename,
|
||||||
"sha256-abc", 12345, "application/gzip"); err != nil {
|
testContentHash, 12345, "application/gzip"); err != nil {
|
||||||
t.Fatalf("MarkArtifactCached failed: %v", err)
|
t.Fatalf("MarkArtifactCached failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +279,7 @@ func TestGetCachedArtifact(t *testing.T) {
|
||||||
if cached.StoragePath != "/cache/npm/"+filename {
|
if cached.StoragePath != "/cache/npm/"+filename {
|
||||||
t.Errorf("expected cached storage path, got %q", cached.StoragePath)
|
t.Errorf("expected cached storage path, got %q", cached.StoragePath)
|
||||||
}
|
}
|
||||||
if cached.ContentHash.String != "sha256-abc" {
|
if cached.ContentHash.String != testContentHash {
|
||||||
t.Errorf("expected cached content hash, got %q", cached.ContentHash.String)
|
t.Errorf("expected cached content hash, got %q", cached.ContentHash.String)
|
||||||
}
|
}
|
||||||
if cached.Size.Int64 != 12345 {
|
if cached.Size.Int64 != 12345 {
|
||||||
|
|
@ -283,7 +288,7 @@ func TestGetCachedArtifact(t *testing.T) {
|
||||||
if cached.ContentType.String != "application/gzip" {
|
if cached.ContentType.String != "application/gzip" {
|
||||||
t.Errorf("expected cached content type, got %q", cached.ContentType.String)
|
t.Errorf("expected cached content type, got %q", cached.ContentType.String)
|
||||||
}
|
}
|
||||||
if cached.Integrity.String != "sha512-abc123" {
|
if cached.Integrity.String != testIntegrity {
|
||||||
t.Errorf("expected cached integrity, got %q", cached.Integrity.String)
|
t.Errorf("expected cached integrity, got %q", cached.Integrity.String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,7 +311,7 @@ func seedCachedArtifactTestData(t *testing.T, db *DB, packagePURL, versionPURL,
|
||||||
if err := db.UpsertVersion(&Version{
|
if err := db.UpsertVersion(&Version{
|
||||||
PURL: versionPURL,
|
PURL: versionPURL,
|
||||||
PackagePURL: packagePURL,
|
PackagePURL: packagePURL,
|
||||||
Integrity: sql.NullString{String: "sha512-abc123", Valid: true},
|
Integrity: sql.NullString{String: testIntegrity, Valid: true},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
t.Fatalf("UpsertVersion failed: %v", err)
|
t.Fatalf("UpsertVersion failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,43 +201,6 @@ func (s *Service) CheckVulnerabilities(ctx context.Context, ecosystem, name, ver
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BulkCheckVulnerabilities queries vulnerabilities for multiple package versions.
|
|
||||||
func (s *Service) BulkCheckVulnerabilities(ctx context.Context, packages []struct{ Ecosystem, Name, Version string }) (map[string][]VulnInfo, error) {
|
|
||||||
purls := make([]*purl.PURL, len(packages))
|
|
||||||
for i, pkg := range packages {
|
|
||||||
purls[i] = purl.MakePURL(pkg.Ecosystem, pkg.Name, pkg.Version)
|
|
||||||
}
|
|
||||||
|
|
||||||
vulnResults, err := s.vulnSource.QueryBatch(ctx, purls)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make(map[string][]VulnInfo, len(packages))
|
|
||||||
for i, vulnList := range vulnResults {
|
|
||||||
pkg := packages[i]
|
|
||||||
key := purl.MakePURLString(pkg.Ecosystem, pkg.Name, pkg.Version)
|
|
||||||
|
|
||||||
var infos []VulnInfo
|
|
||||||
for _, v := range vulnList {
|
|
||||||
info := VulnInfo{
|
|
||||||
ID: v.ID,
|
|
||||||
Summary: v.Summary,
|
|
||||||
Severity: v.SeverityLevel(),
|
|
||||||
CVSSScore: v.CVSSScore(),
|
|
||||||
FixedVersion: v.FixedVersion(pkg.Ecosystem, pkg.Name),
|
|
||||||
}
|
|
||||||
for _, ref := range v.References {
|
|
||||||
info.References = append(info.References, ref.URL)
|
|
||||||
}
|
|
||||||
infos = append(infos, info)
|
|
||||||
}
|
|
||||||
result[key] = infos
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOutdated checks if a version is older than the latest version.
|
// IsOutdated checks if a version is older than the latest version.
|
||||||
func (s *Service) IsOutdated(currentVersion, latestVersion string) bool {
|
func (s *Service) IsOutdated(currentVersion, latestVersion string) bool {
|
||||||
if latestVersion == "" || currentVersion == "" {
|
if latestVersion == "" || currentVersion == "" {
|
||||||
|
|
@ -288,19 +251,6 @@ func (s *Service) CategorizeLicense(license string) LicenseCategory {
|
||||||
return LicenseUnknown
|
return LicenseUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormalizeLicense normalizes a license string to SPDX format.
|
|
||||||
func (s *Service) NormalizeLicense(license string) string {
|
|
||||||
if license == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if normalized, err := spdx.NormalizeExpressionLax(license); err == nil {
|
|
||||||
return normalized
|
|
||||||
}
|
|
||||||
|
|
||||||
return license
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnrichmentResult contains all enrichment data for a package version.
|
// EnrichmentResult contains all enrichment data for a package version.
|
||||||
type EnrichmentResult struct {
|
type EnrichmentResult struct {
|
||||||
Package *PackageInfo
|
Package *PackageInfo
|
||||||
|
|
|
||||||
|
|
@ -74,25 +74,3 @@ func TestCategorizeLicense(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNormalizeLicense(t *testing.T) {
|
|
||||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
||||||
svc := New(logger)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{"MIT", "MIT"},
|
|
||||||
{"Apache 2", "Apache-2.0"},
|
|
||||||
{"Apache-2.0", "Apache-2.0"},
|
|
||||||
{"", ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tests {
|
|
||||||
result := svc.NormalizeLicense(tc.input)
|
|
||||||
if result != tc.expected {
|
|
||||||
t.Errorf("NormalizeLicense(%q) = %q, want %q", tc.input, result, tc.expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -482,8 +482,9 @@ func TestContainerHandler_BlobHead_DirectServeRedirects(t *testing.T) {
|
||||||
if got := w.Header().Get("Location"); got != store.signedURL {
|
if got := w.Header().Get("Location"); got != store.signedURL {
|
||||||
t.Errorf("Location = %q, want %q", got, store.signedURL)
|
t.Errorf("Location = %q, want %q", got, store.signedURL)
|
||||||
}
|
}
|
||||||
if got := w.Header().Get("ETag"); got != `"abc123"` {
|
wantETag := `"` + sha256Hex("cached blob") + `"`
|
||||||
t.Errorf("ETag = %q, want %q", got, `"abc123"`)
|
if got := w.Header().Get("ETag"); got != wantETag {
|
||||||
|
t.Errorf("ETag = %q, want %q", got, wantETag)
|
||||||
}
|
}
|
||||||
if w.Body.Len() != 0 {
|
if w.Body.Len() != 0 {
|
||||||
t.Errorf("HEAD response body length = %d, want 0", w.Body.Len())
|
t.Errorf("HEAD response body length = %d, want 0", w.Body.Len())
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func seedPackageWithPURL(t *testing.T, db *database.DB, store *mockStorage, ecos
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
UpstreamURL: "https://example.com/" + filename,
|
UpstreamURL: "https://example.com/" + filename,
|
||||||
StoragePath: sql.NullString{String: storagePath, Valid: true},
|
StoragePath: sql.NullString{String: storagePath, Valid: true},
|
||||||
ContentHash: sql.NullString{String: "abc123", Valid: true},
|
ContentHash: sql.NullString{String: sha256Hex(content), Valid: true},
|
||||||
Size: sql.NullInt64{Int64: int64(len(content)), Valid: true},
|
Size: sql.NullInt64{Int64: int64(len(content)), Valid: true},
|
||||||
ContentType: sql.NullString{String: "application/octet-stream", Valid: true},
|
ContentType: sql.NullString{String: "application/octet-stream", Valid: true},
|
||||||
FetchedAt: sql.NullTime{Time: time.Now(), Valid: true},
|
FetchedAt: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,7 @@ var artifactCopyBufferPool = sync.Pool{ //nolint:gochecknoglobals // shared acro
|
||||||
// canonicalPackagePURL returns a versionless PURL in canonical form so cooldown
|
// canonicalPackagePURL returns a versionless PURL in canonical form so cooldown
|
||||||
// lookups match keys produced by config.CooldownConfig.NormalizedPackages.
|
// lookups match keys produced by config.CooldownConfig.NormalizedPackages.
|
||||||
func canonicalPackagePURL(ecosystem, name string) string {
|
func canonicalPackagePURL(ecosystem, name string) string {
|
||||||
p := purl.MakePURL(ecosystem, name, "")
|
return purl.MakePURLString(ecosystem, name, "")
|
||||||
_ = p.Normalize()
|
|
||||||
return p.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentTypeJSON = "application/json"
|
const contentTypeJSON = "application/json"
|
||||||
|
|
@ -196,6 +194,11 @@ func (p *Proxy) checkCache(ctx context.Context, pkgPURL, versionPURL, filename s
|
||||||
if artifact == nil {
|
if artifact == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
checks, err := newIntegrityChecks(artifact.ContentHash.String, artifact.Integrity.String)
|
||||||
|
if err != nil {
|
||||||
|
p.rejectUnusableCacheRecord(artifact, versionPURL, filename, err)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
result := &CacheResult{
|
result := &CacheResult{
|
||||||
Size: artifact.Size.Int64,
|
Size: artifact.Size.Int64,
|
||||||
|
|
@ -227,16 +230,21 @@ func (p *Proxy) checkCache(ctx context.Context, pkgPURL, versionPURL, filename s
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Reader = newVerifyingReader(reader, artifact.ContentHash.String, artifact.Integrity.String,
|
result.Reader, err = checks.wrap(reader,
|
||||||
func(reason string) {
|
func(reason string) {
|
||||||
p.Logger.Error("cached artifact failed integrity check",
|
p.Logger.Error("cached artifact failed integrity check",
|
||||||
"purl", versionPURL, "filename", filename,
|
"purl", versionPURL, "filename", filename,
|
||||||
"path", artifact.StoragePath, "reason", reason)
|
"path", artifact.StoragePath, "reason", reason)
|
||||||
metrics.RecordIntegrityFailure(artifact.Ecosystem)
|
metrics.RecordIntegrityFailure(purl.NormalizeEcosystem(artifact.Ecosystem))
|
||||||
if err := p.DB.ClearArtifactCache(versionPURL, filename); err != nil {
|
if err := p.DB.ClearArtifactCache(versionPURL, filename); err != nil {
|
||||||
p.Logger.Warn("failed to clear corrupt artifact from cache", "error", err)
|
p.Logger.Warn("failed to clear corrupt artifact from cache", "error", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
_ = reader.Close()
|
||||||
|
p.rejectUnusableCacheRecord(artifact, versionPURL, filename, err)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
p.recordCacheHit(artifact.Ecosystem, versionPURL, filename)
|
p.recordCacheHit(artifact.Ecosystem, versionPURL, filename)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
@ -266,6 +274,16 @@ func (p *Proxy) recordCacheHit(ecosystem, versionPURL, filename string) {
|
||||||
metrics.RecordCacheHit(ecosystem)
|
metrics.RecordCacheHit(ecosystem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Proxy) rejectUnusableCacheRecord(artifact *database.CachedArtifact, versionPURL, filename string, cause error) {
|
||||||
|
p.Logger.Warn("cached artifact has unusable integrity metadata",
|
||||||
|
"purl", versionPURL, "filename", filename,
|
||||||
|
"path", artifact.StoragePath, "error", cause)
|
||||||
|
metrics.RecordIntegrityFailure(purl.NormalizeEcosystem(artifact.Ecosystem))
|
||||||
|
if err := p.DB.ClearArtifactCache(versionPURL, filename); err != nil {
|
||||||
|
p.Logger.Warn("failed to clear unusable artifact from cache", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Proxy) fetchAndCache(ctx context.Context, ecosystem, name, version, filename, pkgPURL, versionPURL string) (*CacheResult, error) {
|
func (p *Proxy) fetchAndCache(ctx context.Context, ecosystem, name, version, filename, pkgPURL, versionPURL string) (*CacheResult, error) {
|
||||||
// Resolve download URL
|
// Resolve download URL
|
||||||
info, err := p.Resolver.Resolve(ctx, ecosystem, name, version)
|
info, err := p.Resolver.Resolve(ctx, ecosystem, name, version)
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,7 @@ package handler
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
@ -46,8 +44,7 @@ func (s *mockStorage) Store(_ context.Context, path string, r io.Reader) (int64,
|
||||||
return 0, "", err
|
return 0, "", err
|
||||||
}
|
}
|
||||||
s.files[path] = data
|
s.files[path] = data
|
||||||
digest := sha256.Sum256(data)
|
return int64(len(data)), sha256Hex(string(data)), nil
|
||||||
return int64(len(data)), hex.EncodeToString(digest[:]), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *mockStorage) Open(_ context.Context, path string) (io.ReadCloser, error) {
|
func (s *mockStorage) Open(_ context.Context, path string) (io.ReadCloser, error) {
|
||||||
|
|
@ -182,7 +179,7 @@ func seedPackage(t testing.TB, db *database.DB, store *mockStorage, ecosystem, n
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
UpstreamURL: "https://example.com/" + filename,
|
UpstreamURL: "https://example.com/" + filename,
|
||||||
StoragePath: sql.NullString{String: storagePath, Valid: true},
|
StoragePath: sql.NullString{String: storagePath, Valid: true},
|
||||||
ContentHash: sql.NullString{String: "abc123", Valid: true},
|
ContentHash: sql.NullString{String: sha256Hex(content), Valid: true},
|
||||||
Size: sql.NullInt64{Int64: int64(len(content)), Valid: true},
|
Size: sql.NullInt64{Int64: int64(len(content)), Valid: true},
|
||||||
ContentType: sql.NullString{String: "application/octet-stream", Valid: true},
|
ContentType: sql.NullString{String: "application/octet-stream", Valid: true},
|
||||||
FetchedAt: sql.NullTime{Time: time.Now(), Valid: true},
|
FetchedAt: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
|
|
@ -271,8 +268,74 @@ func TestGetOrFetchArtifact_CacheHit(t *testing.T) {
|
||||||
if result.ContentType != "application/octet-stream" {
|
if result.ContentType != "application/octet-stream" {
|
||||||
t.Errorf("got content type %q, want %q", result.ContentType, "application/octet-stream")
|
t.Errorf("got content type %q, want %q", result.ContentType, "application/octet-stream")
|
||||||
}
|
}
|
||||||
if result.Hash != "abc123" {
|
if result.Hash != sha256Hex("cached content") {
|
||||||
t.Errorf("got hash %q, want %q", result.Hash, "abc123")
|
t.Errorf("got hash %q, want %q", result.Hash, sha256Hex("cached content"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetCachedArtifactRejectsMalformedIntegrityMetadata(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
malformedHash string
|
||||||
|
malformedIntegrity string
|
||||||
|
}{
|
||||||
|
{name: "content hash", malformedHash: "abc123"},
|
||||||
|
{name: "native integrity", malformedIntegrity: "sha512-abc123"},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
assertMalformedCacheRejected(t, test.malformedHash, test.malformedIntegrity)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertMalformedCacheRejected(t *testing.T, malformedHash, malformedIntegrity string) {
|
||||||
|
t.Helper()
|
||||||
|
proxy, db, store, _ := setupTestProxy(t)
|
||||||
|
const (
|
||||||
|
packageName = "broken"
|
||||||
|
version = "1.0.0"
|
||||||
|
filename = "broken-1.0.0.tgz"
|
||||||
|
)
|
||||||
|
seedPackage(t, db, store, "npm", packageName, version, filename, "cached content")
|
||||||
|
versionPURL := purl.MakePURLString("npm", packageName, version)
|
||||||
|
|
||||||
|
if malformedHash != "" {
|
||||||
|
artifact, err := db.GetArtifact(versionPURL, filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
artifact.ContentHash = sql.NullString{String: malformedHash, Valid: true}
|
||||||
|
if err := db.UpsertArtifact(artifact); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if malformedIntegrity != "" {
|
||||||
|
versionRecord := &database.Version{
|
||||||
|
PURL: versionPURL,
|
||||||
|
PackagePURL: purl.MakePURLString("npm", packageName, ""),
|
||||||
|
Integrity: sql.NullString{String: malformedIntegrity, Valid: true},
|
||||||
|
}
|
||||||
|
if err := db.UpsertVersion(versionRecord); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.DirectServe = true
|
||||||
|
store.signedURL = "https://cache.example/broken"
|
||||||
|
result, err := proxy.GetCachedArtifact(context.Background(), "npm", packageName, version, filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetCachedArtifact: %v", err)
|
||||||
|
}
|
||||||
|
if result != nil {
|
||||||
|
t.Errorf("GetCachedArtifact = %+v, want nil", result)
|
||||||
|
}
|
||||||
|
artifact, err := db.GetArtifact(versionPURL, filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if artifact.StoragePath.Valid {
|
||||||
|
t.Error("unusable cache record retained its storage path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,7 +370,7 @@ func TestGetOrFetchArtifactFromURL_CacheMiss_StorageMissing(t *testing.T) {
|
||||||
Filename: "missing-1.0.0.tgz",
|
Filename: "missing-1.0.0.tgz",
|
||||||
UpstreamURL: "https://example.com/missing.tgz",
|
UpstreamURL: "https://example.com/missing.tgz",
|
||||||
StoragePath: sql.NullString{String: "nonexistent/path.tgz", Valid: true},
|
StoragePath: sql.NullString{String: "nonexistent/path.tgz", Valid: true},
|
||||||
ContentHash: sql.NullString{String: "hash", Valid: true},
|
ContentHash: sql.NullString{String: sha256Hex("missing content"), Valid: true},
|
||||||
Size: sql.NullInt64{Int64: 100, Valid: true},
|
Size: sql.NullInt64{Int64: 100, Valid: true},
|
||||||
ContentType: sql.NullString{String: "application/octet-stream", Valid: true},
|
ContentType: sql.NullString{String: "application/octet-stream", Valid: true},
|
||||||
FetchedAt: sql.NullTime{Time: time.Now(), Valid: true},
|
FetchedAt: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
|
|
|
||||||
|
|
@ -1,140 +1,100 @@
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"crypto/subtle"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
|
"github.com/git-pkgs/integrity"
|
||||||
)
|
)
|
||||||
|
|
||||||
// parseSRI parses a Subresource Integrity string (e.g. "sha512-abc==") into
|
type integrityChecks struct {
|
||||||
// an algorithm name and raw digest bytes. Returns ok=false for empty,
|
contentHash integrity.SRI
|
||||||
// malformed, or unsupported entries. Only the first hash in a multi-hash
|
native integrity.SRI
|
||||||
// SRI string is considered.
|
algorithms []integrity.Algorithm
|
||||||
func parseSRI(s string) (algo string, digest []byte, ok bool) {
|
}
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
if s == "" {
|
func newIntegrityChecks(contentHash, native string) (integrityChecks, error) {
|
||||||
return "", nil, false
|
checks := integrityChecks{}
|
||||||
|
|
||||||
|
if contentHash != "" {
|
||||||
|
digest, err := integrity.ParseHex(integrity.SHA256, contentHash)
|
||||||
|
if err != nil {
|
||||||
|
return integrityChecks{}, fmt.Errorf("parse content_hash: %w", err)
|
||||||
|
}
|
||||||
|
checks.contentHash = integrity.SRI{digest}
|
||||||
|
checks.algorithms = append(checks.algorithms, integrity.SHA256)
|
||||||
}
|
}
|
||||||
if i := strings.IndexByte(s, ' '); i >= 0 {
|
|
||||||
s = s[:i]
|
if native != "" {
|
||||||
|
digests, err := integrity.ParseSRI(native)
|
||||||
|
if err != nil {
|
||||||
|
return integrityChecks{}, fmt.Errorf("parse integrity: %w", err)
|
||||||
|
}
|
||||||
|
checks.native = digests
|
||||||
|
for _, digest := range digests {
|
||||||
|
checks.algorithms = append(checks.algorithms, digest.Algorithm())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
algo, b64, found := strings.Cut(s, "-")
|
|
||||||
if !found {
|
return checks, nil
|
||||||
return "", nil, false
|
}
|
||||||
|
|
||||||
|
func (c integrityChecks) wrap(source io.ReadCloser, onMismatch func(string)) (io.ReadCloser, error) {
|
||||||
|
if len(c.algorithms) == 0 {
|
||||||
|
return source, nil
|
||||||
}
|
}
|
||||||
d, err := base64.StdEncoding.DecodeString(b64)
|
reader, err := integrity.NewReader(source, c.algorithms...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, false
|
return nil, fmt.Errorf("create integrity reader: %w", err)
|
||||||
}
|
|
||||||
switch algo {
|
|
||||||
case "sha256", "sha384", "sha512":
|
|
||||||
return algo, d, true
|
|
||||||
default:
|
|
||||||
return "", nil, false
|
|
||||||
}
|
}
|
||||||
|
return &verifyingReader{
|
||||||
|
source: source,
|
||||||
|
reader: reader,
|
||||||
|
checks: c,
|
||||||
|
onMismatch: onMismatch,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSRIHash(algo string) hash.Hash {
|
// verifyingReader forwards Close to its source and reports completed digest
|
||||||
switch algo {
|
// mismatches after its shared integrity reader observes EOF.
|
||||||
case "sha256":
|
|
||||||
return sha256.New()
|
|
||||||
case "sha384":
|
|
||||||
return sha512.New384()
|
|
||||||
case "sha512":
|
|
||||||
return sha512.New()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// verifyingReader wraps an io.ReadCloser and computes SHA256 (and optionally
|
|
||||||
// a second SRI hash) as bytes are read. When the underlying reader reaches
|
|
||||||
// EOF it compares the digests against the expected values and calls
|
|
||||||
// onMismatch for each failure. Verification is skipped if the stream was
|
|
||||||
// not fully consumed (e.g. client disconnect) to avoid false positives.
|
|
||||||
type verifyingReader struct {
|
type verifyingReader struct {
|
||||||
r io.ReadCloser
|
source io.ReadCloser
|
||||||
sha256 hash.Hash
|
reader *integrity.Reader
|
||||||
wantSHA256 string
|
checks integrityChecks
|
||||||
sri hash.Hash
|
|
||||||
sriAlgo string
|
|
||||||
wantSRI []byte
|
|
||||||
onMismatch func(reason string)
|
onMismatch func(reason string)
|
||||||
eof bool
|
|
||||||
verified bool
|
verified bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVerifyingReader(r io.ReadCloser, contentHash, sri string, onMismatch func(string)) io.ReadCloser {
|
func (r *verifyingReader) Read(p []byte) (int, error) {
|
||||||
if contentHash == "" && sri == "" {
|
n, err := r.reader.Read(p)
|
||||||
return r
|
|
||||||
}
|
|
||||||
v := &verifyingReader{
|
|
||||||
r: r,
|
|
||||||
onMismatch: onMismatch,
|
|
||||||
}
|
|
||||||
if contentHash != "" {
|
|
||||||
v.sha256 = sha256.New()
|
|
||||||
v.wantSHA256 = contentHash
|
|
||||||
}
|
|
||||||
if algo, digest, ok := parseSRI(sri); ok {
|
|
||||||
v.sri = newSRIHash(algo)
|
|
||||||
v.sriAlgo = algo
|
|
||||||
v.wantSRI = digest
|
|
||||||
}
|
|
||||||
if v.sha256 == nil && v.sri == nil {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *verifyingReader) Read(p []byte) (int, error) {
|
|
||||||
n, err := v.r.Read(p)
|
|
||||||
if n > 0 {
|
|
||||||
if v.sha256 != nil {
|
|
||||||
v.sha256.Write(p[:n])
|
|
||||||
}
|
|
||||||
if v.sri != nil {
|
|
||||||
v.sri.Write(p[:n])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
v.eof = true
|
r.verify()
|
||||||
v.verify()
|
|
||||||
}
|
}
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *verifyingReader) Close() error {
|
func (r *verifyingReader) Close() error {
|
||||||
if v.eof {
|
return r.source.Close()
|
||||||
v.verify()
|
|
||||||
}
|
|
||||||
return v.r.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *verifyingReader) verify() {
|
func (r *verifyingReader) verify() {
|
||||||
if v.verified {
|
if r.verified {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.verified = true
|
||||||
|
result := r.reader.Result()
|
||||||
|
if !result.Complete {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v.verified = true
|
|
||||||
|
|
||||||
if v.sha256 != nil {
|
if len(r.checks.contentHash) > 0 {
|
||||||
got := hex.EncodeToString(v.sha256.Sum(nil))
|
if err := result.Verify(r.checks.contentHash); err != nil {
|
||||||
if subtle.ConstantTimeCompare([]byte(got), []byte(v.wantSHA256)) != 1 {
|
r.onMismatch("content_hash: " + err.Error())
|
||||||
v.onMismatch(fmt.Sprintf("content_hash mismatch: stored=%s computed=%s", v.wantSHA256, got))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v.sri != nil {
|
if len(r.checks.native) > 0 {
|
||||||
got := v.sri.Sum(nil)
|
if err := result.Verify(r.checks.native); err != nil {
|
||||||
if subtle.ConstantTimeCompare(got, v.wantSRI) != 1 {
|
r.onMismatch("integrity: " + err.Error())
|
||||||
v.onMismatch(fmt.Sprintf("integrity mismatch: %s expected=%s computed=%s",
|
|
||||||
v.sriAlgo,
|
|
||||||
base64.StdEncoding.EncodeToString(v.wantSRI),
|
|
||||||
base64.StdEncoding.EncodeToString(got)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -15,42 +16,68 @@ func sha256Hex(data string) string {
|
||||||
return hex.EncodeToString(sum[:])
|
return hex.EncodeToString(sum[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sha256SRI(data string) string {
|
||||||
|
sum := sha256.Sum256([]byte(data))
|
||||||
|
return "sha256-" + base64.StdEncoding.EncodeToString(sum[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func sha384SRI(data string) string {
|
||||||
|
sum := sha512.Sum384([]byte(data))
|
||||||
|
return "sha384-" + base64.StdEncoding.EncodeToString(sum[:])
|
||||||
|
}
|
||||||
|
|
||||||
func sha512SRI(data string) string {
|
func sha512SRI(data string) string {
|
||||||
sum := sha512.Sum512([]byte(data))
|
sum := sha512.Sum512([]byte(data))
|
||||||
return "sha512-" + base64.StdEncoding.EncodeToString(sum[:])
|
return "sha512-" + base64.StdEncoding.EncodeToString(sum[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseSRI(t *testing.T) {
|
func wrapIntegrityReader(t *testing.T, source io.ReadCloser, contentHash, native string, onMismatch func(string)) io.ReadCloser {
|
||||||
tests := []struct {
|
t.Helper()
|
||||||
name string
|
checks, err := newIntegrityChecks(contentHash, native)
|
||||||
input string
|
if err != nil {
|
||||||
algo string
|
t.Fatalf("newIntegrityChecks: %v", err)
|
||||||
ok bool
|
|
||||||
}{
|
|
||||||
{"sha512", sha512SRI("hello"), "sha512", true},
|
|
||||||
{"sha256", "sha256-" + base64.StdEncoding.EncodeToString([]byte("0123456789012345678901234567890123456789")), "sha256", true},
|
|
||||||
{"empty", "", "", false},
|
|
||||||
{"no dash", "sha512abc", "", false},
|
|
||||||
{"bad base64", "sha512-not!base64", "", false},
|
|
||||||
{"unsupported algo", "md5-" + base64.StdEncoding.EncodeToString([]byte("x")), "", false},
|
|
||||||
{"multi hash takes first", sha512SRI("a") + " " + sha512SRI("b"), "sha512", true},
|
|
||||||
{"whitespace", " " + sha512SRI("x") + " ", "sha512", true},
|
|
||||||
}
|
}
|
||||||
|
reader, err := checks.wrap(source, onMismatch)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("wrap: %v", err)
|
||||||
|
}
|
||||||
|
return reader
|
||||||
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
func TestNewIntegrityChecksCollectsAlgorithms(t *testing.T) {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
checks, err := newIntegrityChecks(
|
||||||
algo, digest, ok := parseSRI(tt.input)
|
sha256Hex("hello"),
|
||||||
if ok != tt.ok {
|
strings.Join([]string{sha256SRI("first"), sha512SRI("second"), sha384SRI("third"), sha512SRI("alternative")}, " "),
|
||||||
t.Fatalf("ok = %v, want %v", ok, tt.ok)
|
)
|
||||||
}
|
if err != nil {
|
||||||
if !tt.ok {
|
t.Fatal(err)
|
||||||
return
|
}
|
||||||
}
|
if len(checks.algorithms) != 5 {
|
||||||
if algo != tt.algo {
|
t.Fatalf("algorithms = %v, want 5 entries", checks.algorithms)
|
||||||
t.Errorf("algo = %q, want %q", algo, tt.algo)
|
}
|
||||||
}
|
if len(checks.native) != 4 {
|
||||||
if len(digest) == 0 {
|
t.Errorf("native digests = %d, want 4", len(checks.native))
|
||||||
t.Error("digest is empty")
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewIntegrityChecksRejectsMalformedMetadata(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
contentHash string
|
||||||
|
native string
|
||||||
|
}{
|
||||||
|
{name: "short content hash", contentHash: "abc123"},
|
||||||
|
{name: "non-hex content hash", contentHash: strings.Repeat("z", sha256.Size*2)},
|
||||||
|
{name: "missing SRI separator", native: "sha512"},
|
||||||
|
{name: "malformed SRI base64", native: "sha512-not!base64"},
|
||||||
|
{name: "wrong SRI length", native: "sha512-" + base64.StdEncoding.EncodeToString([]byte("short"))},
|
||||||
|
{name: "unsupported SRI algorithm", native: "md5-1B2M2Y8AsgTpgAmY7PhCfg=="},
|
||||||
|
{name: "invalid SRI alternative", native: sha512SRI("valid") + " sha384-nope"},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
if _, err := newIntegrityChecks(test.contentHash, test.native); err == nil {
|
||||||
|
t.Fatal("newIntegrityChecks returned nil error")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -67,69 +94,156 @@ func TestVerifyingReader(t *testing.T) {
|
||||||
sri string
|
sri string
|
||||||
wantCalls int
|
wantCalls int
|
||||||
}{
|
}{
|
||||||
{"both match", goodSHA, goodSRI, 0},
|
{name: "both match", hash: goodSHA, sri: goodSRI},
|
||||||
{"sha256 only match", goodSHA, "", 0},
|
{name: "SHA-256 only match", hash: goodSHA},
|
||||||
{"sri only match", "", goodSRI, 0},
|
{name: "SRI only match", sri: goodSRI},
|
||||||
{"sha256 mismatch", sha256Hex("other"), "", 1},
|
{name: "SHA-256 mismatch", hash: sha256Hex("other"), wantCalls: 1},
|
||||||
{"sri mismatch", "", sha512SRI("other"), 1},
|
{name: "SRI mismatch", sri: sha512SRI("other"), wantCalls: 1},
|
||||||
{"both mismatch", sha256Hex("other"), sha512SRI("other"), 2},
|
{name: "both mismatch", hash: sha256Hex("other"), sri: sha512SRI("other"), wantCalls: 2},
|
||||||
{"no checks", "", "", 0},
|
{name: "no checks"},
|
||||||
{"unparseable sri ignored", goodSHA, "garbage", 0},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, test := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
var calls []string
|
var calls []string
|
||||||
r := newVerifyingReader(io.NopCloser(strings.NewReader(data)), tt.hash, tt.sri,
|
reader := wrapIntegrityReader(t, io.NopCloser(strings.NewReader(data)), test.hash, test.sri,
|
||||||
func(reason string) { calls = append(calls, reason) })
|
func(reason string) { calls = append(calls, reason) })
|
||||||
|
|
||||||
got, err := io.ReadAll(r)
|
got, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ReadAll: %v", err)
|
t.Fatalf("ReadAll: %v", err)
|
||||||
}
|
}
|
||||||
if string(got) != data {
|
if string(got) != data {
|
||||||
t.Errorf("data corrupted: got %q", got)
|
t.Errorf("data corrupted: got %q", got)
|
||||||
}
|
}
|
||||||
if err := r.Close(); err != nil {
|
if err := reader.Close(); err != nil {
|
||||||
t.Fatalf("Close: %v", err)
|
t.Fatalf("Close: %v", err)
|
||||||
}
|
}
|
||||||
|
if len(calls) != test.wantCalls {
|
||||||
if len(calls) != tt.wantCalls {
|
t.Errorf("onMismatch called %d times, want %d: %v", len(calls), test.wantCalls, calls)
|
||||||
t.Errorf("onMismatch called %d times, want %d: %v", len(calls), tt.wantCalls, calls)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyingReaderPassthrough(t *testing.T) {
|
func TestVerifyingReaderUsesStrongestNativeAlgorithm(t *testing.T) {
|
||||||
src := io.NopCloser(strings.NewReader("x"))
|
const data = "artifact"
|
||||||
r := newVerifyingReader(src, "", "", func(string) { t.Fatal("should not be called") })
|
tests := []struct {
|
||||||
if r != src {
|
name string
|
||||||
t.Error("expected passthrough when no hashes provided")
|
native string
|
||||||
|
wantCalls int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "weaker match does not override stronger mismatch",
|
||||||
|
native: sha256SRI(data) + " " + sha512SRI("other"),
|
||||||
|
wantCalls: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "stronger match ignores weaker mismatch",
|
||||||
|
native: sha256SRI("other") + " " + sha512SRI(data),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "same algorithm alternative matches",
|
||||||
|
native: sha512SRI("other") + " " + sha512SRI(data),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
var calls int
|
||||||
|
reader := wrapIntegrityReader(t, io.NopCloser(strings.NewReader(data)), "", test.native, func(string) { calls++ })
|
||||||
|
if _, err := io.Copy(io.Discard, reader); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if calls != test.wantCalls {
|
||||||
|
t.Errorf("onMismatch called %d times, want %d", calls, test.wantCalls)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyingReaderPartialRead(t *testing.T) {
|
func TestVerifyingReaderMismatchMessages(t *testing.T) {
|
||||||
var calls int
|
const data = "actual"
|
||||||
r := newVerifyingReader(io.NopCloser(strings.NewReader("hello world")),
|
wantHash := sha256Hex("expected")
|
||||||
sha256Hex("hello world"), "", func(string) { calls++ })
|
wantSRI := sha512SRI("expected")
|
||||||
|
var reasons []string
|
||||||
|
reader := wrapIntegrityReader(t, io.NopCloser(strings.NewReader(data)), wantHash, wantSRI,
|
||||||
|
func(reason string) { reasons = append(reasons, reason) })
|
||||||
|
if _, err := io.Copy(io.Discard, reader); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(reasons) != 2 {
|
||||||
|
t.Fatalf("reasons = %v, want two", reasons)
|
||||||
|
}
|
||||||
|
wantContentReason := "content_hash: integrity mismatch: expected " + sha256SRI("expected") + ", calculated " + sha256SRI(data)
|
||||||
|
if reasons[0] != wantContentReason {
|
||||||
|
t.Errorf("content reason = %q, want %q", reasons[0], wantContentReason)
|
||||||
|
}
|
||||||
|
wantNativeReason := "integrity: integrity mismatch: expected " + wantSRI + ", calculated " + sha512SRI(data)
|
||||||
|
if reasons[1] != wantNativeReason {
|
||||||
|
t.Errorf("native reason = %q, want %q", reasons[1], wantNativeReason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buf := make([]byte, 5)
|
func TestVerifyingReaderPassthrough(t *testing.T) {
|
||||||
_, _ = r.Read(buf)
|
source := io.NopCloser(strings.NewReader("x"))
|
||||||
_ = r.Close()
|
reader := wrapIntegrityReader(t, source, "", "", func(string) { t.Fatal("should not be called") })
|
||||||
|
if reader != source {
|
||||||
|
t.Error("expected passthrough when no hashes were provided")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type closeTrackingReader struct {
|
||||||
|
io.Reader
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *closeTrackingReader) Close() error {
|
||||||
|
r.closed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerifyingReaderPartialRead(t *testing.T) {
|
||||||
|
source := &closeTrackingReader{Reader: strings.NewReader("hello world")}
|
||||||
|
var calls int
|
||||||
|
reader := wrapIntegrityReader(t, source, sha256Hex("other"), "", func(string) { calls++ })
|
||||||
|
|
||||||
|
buffer := make([]byte, 5)
|
||||||
|
_, _ = reader.Read(buffer)
|
||||||
|
_ = reader.Close()
|
||||||
|
|
||||||
if calls != 0 {
|
if calls != 0 {
|
||||||
t.Errorf("onMismatch called %d times for partial read, want 0", calls)
|
t.Errorf("onMismatch called %d times for partial read, want 0", calls)
|
||||||
}
|
}
|
||||||
|
if !source.closed {
|
||||||
|
t.Error("Close was not forwarded to the source")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerifyingReaderNonEOFError(t *testing.T) {
|
||||||
|
var calls int
|
||||||
|
reader := wrapIntegrityReader(t, io.NopCloser(errorFixtureReader{}), sha256Hex("data"), "", func(string) { calls++ })
|
||||||
|
if _, err := io.ReadAll(reader); !errors.Is(err, errIntegrityReadFixture) {
|
||||||
|
t.Fatalf("ReadAll error = %v", err)
|
||||||
|
}
|
||||||
|
if calls != 0 {
|
||||||
|
t.Errorf("onMismatch called %d times after non-EOF error", calls)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var errIntegrityReadFixture = errors.New("integrity read fixture")
|
||||||
|
|
||||||
|
type errorFixtureReader struct{}
|
||||||
|
|
||||||
|
func (errorFixtureReader) Read(p []byte) (int, error) {
|
||||||
|
return copy(p, "data"), errIntegrityReadFixture
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyingReaderVerifyOnce(t *testing.T) {
|
func TestVerifyingReaderVerifyOnce(t *testing.T) {
|
||||||
var calls int
|
var calls int
|
||||||
r := newVerifyingReader(io.NopCloser(strings.NewReader("x")), sha256Hex("y"), "",
|
reader := wrapIntegrityReader(t, io.NopCloser(strings.NewReader("x")), sha256Hex("y"), "", func(string) { calls++ })
|
||||||
func(string) { calls++ })
|
_, _ = io.ReadAll(reader)
|
||||||
_, _ = io.ReadAll(r)
|
_ = reader.Close()
|
||||||
_ = r.Close()
|
_ = reader.Close()
|
||||||
_ = r.Close()
|
|
||||||
if calls != 1 {
|
if calls != 1 {
|
||||||
t.Errorf("onMismatch called %d times, want 1", calls)
|
t.Errorf("onMismatch called %d times, want 1", calls)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package mirror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RegistrySource enumerates all packages in a registry for full mirroring.
|
|
||||||
// Registry enumeration is not yet implemented for any ecosystem.
|
|
||||||
type RegistrySource struct {
|
|
||||||
Ecosystem string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RegistrySource) Enumerate(_ context.Context, _ func(PackageVersion) error) error {
|
|
||||||
return fmt.Errorf("registry enumeration is not yet implemented for ecosystem %q", s.Ecosystem)
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
package mirror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRegistrySourceUnsupported(t *testing.T) {
|
|
||||||
source := &RegistrySource{Ecosystem: "golang"}
|
|
||||||
err := source.Enumerate(context.Background(), func(pv PackageVersion) error {
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error for unsupported ecosystem")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegistrySourceNPMNotImplemented(t *testing.T) {
|
|
||||||
source := &RegistrySource{Ecosystem: "npm"}
|
|
||||||
err := source.Enumerate(context.Background(), func(pv PackageVersion) error {
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected not-implemented error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegistrySourcePyPINotImplemented(t *testing.T) {
|
|
||||||
source := &RegistrySource{Ecosystem: "pypi"}
|
|
||||||
err := source.Enumerate(context.Background(), func(pv PackageVersion) error {
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected not-implemented error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegistrySourceCargoNotImplemented(t *testing.T) {
|
|
||||||
source := &RegistrySource{Ecosystem: "cargo"}
|
|
||||||
err := source.Enumerate(context.Background(), func(pv PackageVersion) error {
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected not-implemented error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -430,6 +430,10 @@ func TestHandleBrowseSourcePage(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(body, "proxy test-version (test-commit)") {
|
||||||
|
t.Error("browse source footer should contain proxy build information, not the package version")
|
||||||
|
}
|
||||||
|
|
||||||
// Check that the escapeHTML function is present for XSS protection
|
// Check that the escapeHTML function is present for XSS protection
|
||||||
if !strings.Contains(body, "function escapeHTML(str)") {
|
if !strings.Contains(body, "function escapeHTML(str)") {
|
||||||
t.Error("browse source page missing escapeHTML function for XSS protection")
|
t.Error("browse source page missing escapeHTML function for XSS protection")
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"github.com/git-pkgs/proxy/internal/storage"
|
"github.com/git-pkgs/proxy/internal/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupEvictionTest(t *testing.T) (*database.DB, *storage.Filesystem) {
|
func setupEvictionTest(t *testing.T) (*database.DB, *storage.Blob) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
|
|
@ -27,7 +27,7 @@ func setupEvictionTest(t *testing.T) (*database.DB, *storage.Filesystem) {
|
||||||
t.Fatalf("failed to create database: %v", err)
|
t.Fatalf("failed to create database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
store, err := storage.NewFilesystem(storagePath)
|
store, err := storage.OpenBucket(context.Background(), "file://"+storagePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = db.Close()
|
_ = db.Close()
|
||||||
t.Fatalf("failed to create storage: %v", err)
|
t.Fatalf("failed to create storage: %v", err)
|
||||||
|
|
@ -243,7 +243,7 @@ func TestStartEvictionLoop_UnlimitedSkips(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer func() { _ = db.Close() }()
|
defer func() { _ = db.Close() }()
|
||||||
|
|
||||||
store, err := storage.NewFilesystem(storagePath)
|
store, err := storage.OpenBucket(context.Background(), "file://"+storagePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create storage: %v", err)
|
t.Fatalf("failed to create storage: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -280,7 +280,7 @@ func defaultTestConfig(storagePath, dbPath string) *config.Config {
|
||||||
return &config.Config{
|
return &config.Config{
|
||||||
Listen: ":8080",
|
Listen: ":8080",
|
||||||
BaseURL: "http://localhost:8080",
|
BaseURL: "http://localhost:8080",
|
||||||
Storage: config.StorageConfig{Path: storagePath, MaxSize: ""},
|
Storage: config.StorageConfig{URL: "file://" + storagePath, MaxSize: ""},
|
||||||
Database: config.DatabaseConfig{
|
Database: config.DatabaseConfig{
|
||||||
Driver: "sqlite",
|
Driver: "sqlite",
|
||||||
Path: dbPath,
|
Path: dbPath,
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ type fakeStorage struct {
|
||||||
// Failure injection.
|
// Failure injection.
|
||||||
storeErr error
|
storeErr error
|
||||||
openErr error
|
openErr error
|
||||||
readErr error // returned by the io.ReadCloser.Read after partial bytes
|
readErr error // returned by the io.ReadCloser.Read after partial bytes
|
||||||
deleteErr error
|
deleteErr error
|
||||||
|
|
||||||
// Misbehavior knobs.
|
// Misbehavior knobs.
|
||||||
|
|
@ -132,8 +132,8 @@ func (f *fakeStorage) SignedURL(ctx context.Context, path string, expiry time.Du
|
||||||
return "", storage.ErrSignedURLUnsupported
|
return "", storage.ErrSignedURLUnsupported
|
||||||
}
|
}
|
||||||
func (f *fakeStorage) UsedSpace(ctx context.Context) (int64, error) { return 0, nil }
|
func (f *fakeStorage) UsedSpace(ctx context.Context) (int64, error) { return 0, nil }
|
||||||
func (f *fakeStorage) URL() string { return "fake://" }
|
func (f *fakeStorage) URL() string { return "fake://" }
|
||||||
func (f *fakeStorage) Close() error { return nil }
|
func (f *fakeStorage) Close() error { return nil }
|
||||||
|
|
||||||
// --- Tests follow. First test: happy path ---
|
// --- Tests follow. First test: happy path ---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,24 @@ package server
|
||||||
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
|
||||||
// Layout carries per-request fields consumed by the shared base template
|
// BuildInfo identifies the running proxy binary.
|
||||||
// (canonical URL, og:url). It is embedded in every page data struct so that
|
type BuildInfo struct {
|
||||||
// templates can reference {{.UIBaseURL}} and {{.CanonicalPath}} alongside the
|
Version string
|
||||||
// page's own fields.
|
Commit string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout carries shared fields consumed by the base template. It is embedded
|
||||||
|
// in every page data struct so templates can access canonical URL and build
|
||||||
|
// information alongside the page's own fields.
|
||||||
type Layout struct {
|
type Layout struct {
|
||||||
|
BuildInfo BuildInfo
|
||||||
UIBaseURL string
|
UIBaseURL string
|
||||||
CanonicalPath string
|
CanonicalPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) layoutFor(r *http.Request) Layout {
|
func (s *Server) layoutFor(r *http.Request) Layout {
|
||||||
return Layout{
|
return Layout{
|
||||||
|
BuildInfo: s.buildInfo,
|
||||||
UIBaseURL: s.cfg.UIBaseURL,
|
UIBaseURL: s.cfg.UIBaseURL,
|
||||||
CanonicalPath: r.URL.Path,
|
CanonicalPath: r.URL.Path,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,17 +92,3 @@ func requestEcosystem(path string) string {
|
||||||
return "other"
|
return "other"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActiveRequestsMiddleware tracks the number of active requests using Prometheus metrics.
|
|
||||||
func ActiveRequestsMiddleware(next http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// Don't track metrics endpoint itself
|
|
||||||
if r.URL.Path == "/metrics" {
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implemented in server.go where metrics package is imported
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -73,36 +73,6 @@ func TestGetRequestID(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestActiveRequestsMiddleware(t *testing.T) {
|
|
||||||
handler := ActiveRequestsMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}))
|
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "/test", nil)
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
|
|
||||||
handler.ServeHTTP(rec, req)
|
|
||||||
|
|
||||||
if rec.Code != http.StatusOK {
|
|
||||||
t.Errorf("expected status 200, got %d", rec.Code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestActiveRequestsMiddleware_SkipsMetricsEndpoint(t *testing.T) {
|
|
||||||
handler := ActiveRequestsMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}))
|
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
|
|
||||||
handler.ServeHTTP(rec, req)
|
|
||||||
|
|
||||||
if rec.Code != http.StatusOK {
|
|
||||||
t.Errorf("expected status 200, got %d", rec.Code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLoggerMiddleware(t *testing.T) {
|
func TestLoggerMiddleware(t *testing.T) {
|
||||||
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
||||||
s := &Server{logger: logger}
|
s := &Server{logger: logger}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ type Server struct {
|
||||||
db *database.DB
|
db *database.DB
|
||||||
storage storage.Storage
|
storage storage.Storage
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
|
buildInfo BuildInfo
|
||||||
http *http.Server
|
http *http.Server
|
||||||
templates *Templates
|
templates *Templates
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
@ -100,7 +101,7 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Server with the given configuration.
|
// New creates a new Server with the given configuration.
|
||||||
func New(cfg *config.Config, logger *slog.Logger) (*Server, error) {
|
func New(cfg *config.Config, logger *slog.Logger, buildInfo BuildInfo) (*Server, error) {
|
||||||
var activityLog *accesslog.Logger
|
var activityLog *accesslog.Logger
|
||||||
if cfg.AccessLog.Path != "" {
|
if cfg.AccessLog.Path != "" {
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -169,6 +170,7 @@ func New(cfg *config.Config, logger *slog.Logger) (*Server, error) {
|
||||||
db: db,
|
db: db,
|
||||||
storage: store,
|
storage: store,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
buildInfo: buildInfo,
|
||||||
templates: &Templates{},
|
templates: &Templates{},
|
||||||
healthCache: hc,
|
healthCache: hc,
|
||||||
accessLog: activityLog,
|
accessLog: activityLog,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -51,7 +52,7 @@ func newTestServer(t *testing.T) *testServer {
|
||||||
t.Fatalf("failed to create database: %v", err)
|
t.Fatalf("failed to create database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
store, err := storage.NewFilesystem(storagePath)
|
store, err := storage.OpenBucket(context.Background(), "file://"+storagePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = db.Close()
|
_ = db.Close()
|
||||||
_ = os.RemoveAll(tempDir)
|
_ = os.RemoveAll(tempDir)
|
||||||
|
|
@ -65,7 +66,7 @@ func newTestServer(t *testing.T) *testServer {
|
||||||
|
|
||||||
cfg := &config.Config{
|
cfg := &config.Config{
|
||||||
BaseURL: "http://localhost:8080",
|
BaseURL: "http://localhost:8080",
|
||||||
Storage: config.StorageConfig{Path: storagePath},
|
Storage: config.StorageConfig{URL: "file://" + storagePath},
|
||||||
Database: config.DatabaseConfig{Path: dbPath},
|
Database: config.DatabaseConfig{Path: dbPath},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,6 +105,7 @@ func newTestServer(t *testing.T) *testServer {
|
||||||
db: db,
|
db: db,
|
||||||
storage: store,
|
storage: store,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
buildInfo: BuildInfo{Version: "test-version", Commit: "test-commit"},
|
||||||
templates: &Templates{},
|
templates: &Templates{},
|
||||||
healthCache: hc,
|
healthCache: hc,
|
||||||
}
|
}
|
||||||
|
|
@ -313,6 +315,9 @@ func TestDashboard(t *testing.T) {
|
||||||
if !strings.Contains(body, "Cached Artifacts") {
|
if !strings.Contains(body, "Cached Artifacts") {
|
||||||
t.Error("dashboard should contain stats")
|
t.Error("dashboard should contain stats")
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(body, "proxy test-version (test-commit)") {
|
||||||
|
t.Error("dashboard footer should contain build information")
|
||||||
|
}
|
||||||
if !strings.Contains(body, "Popular Packages") {
|
if !strings.Contains(body, "Popular Packages") {
|
||||||
t.Error("dashboard should contain popular packages section")
|
t.Error("dashboard should contain popular packages section")
|
||||||
}
|
}
|
||||||
|
|
@ -598,6 +603,9 @@ func TestVersionShowWithHitCount(t *testing.T) {
|
||||||
if !strings.Contains(body, "42 cache hits") {
|
if !strings.Contains(body, "42 cache hits") {
|
||||||
t.Error("expected page to show hit count")
|
t.Error("expected page to show hit count")
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(body, "proxy test-version (test-commit)") {
|
||||||
|
t.Error("version show footer should contain proxy build information, not the package version")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchWithNullValues(t *testing.T) {
|
func TestSearchWithNullValues(t *testing.T) {
|
||||||
|
|
@ -1327,10 +1335,14 @@ func TestNewServer_StorageConnectivityCheck(t *testing.T) {
|
||||||
|
|
||||||
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
||||||
|
|
||||||
srv, err := New(cfg, logger)
|
buildInfo := BuildInfo{Version: "test-version", Commit: "test-commit"}
|
||||||
|
srv, err := New(cfg, logger, buildInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("New() failed: %v", err)
|
t.Fatalf("New() failed: %v", err)
|
||||||
}
|
}
|
||||||
|
if srv.buildInfo != buildInfo {
|
||||||
|
t.Errorf("build info = %#v, want %#v", srv.buildInfo, buildInfo)
|
||||||
|
}
|
||||||
|
|
||||||
// On Windows, OpenBucket normalises to file:///C:/path; on Unix the
|
// On Windows, OpenBucket normalises to file:///C:/path; on Unix the
|
||||||
// absolute path already starts with /, so file:// + /path == file:///path.
|
// absolute path already starts with /, so file:// + /path == file:///path.
|
||||||
|
|
@ -1348,13 +1360,13 @@ func TestNewServer_InvalidAccessLogFailsBeforeDatabaseInit(t *testing.T) {
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
dbPath := filepath.Join(tempDir, "test.db")
|
dbPath := filepath.Join(tempDir, "test.db")
|
||||||
cfg := &config.Config{
|
cfg := &config.Config{
|
||||||
Storage: config.StorageConfig{Path: filepath.Join(tempDir, "artifacts")},
|
Storage: config.StorageConfig{URL: "file://" + filepath.Join(tempDir, "artifacts")},
|
||||||
Database: config.DatabaseConfig{Path: dbPath},
|
Database: config.DatabaseConfig{Path: dbPath},
|
||||||
AccessLog: config.AccessLogConfig{Path: filepath.Join(tempDir, "missing", "access.jsonl")},
|
AccessLog: config.AccessLogConfig{Path: filepath.Join(tempDir, "missing", "access.jsonl")},
|
||||||
}
|
}
|
||||||
|
|
||||||
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
||||||
if _, err := New(cfg, logger); err == nil {
|
if _, err := New(cfg, logger, BuildInfo{}); err == nil {
|
||||||
t.Fatal("New() succeeded with invalid access log path")
|
t.Fatal("New() succeeded with invalid access log path")
|
||||||
} else if !strings.Contains(err.Error(), "initializing access log") {
|
} else if !strings.Contains(err.Error(), "initializing access log") {
|
||||||
t.Fatalf("New() error = %v, want access log initialization error", err)
|
t.Fatalf("New() error = %v, want access log initialization error", err)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@
|
||||||
<i data-lucide="github" class="w-4 h-4"></i><span>github.com/git-pkgs/proxy</span>
|
<i data-lucide="github" class="w-4 h-4"></i><span>github.com/git-pkgs/proxy</span>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
{{if .BuildInfo.Version}}
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-500 mt-2">
|
||||||
|
proxy {{.BuildInfo.Version}}{{if .BuildInfo.Commit}} ({{.BuildInfo.Commit}}){{end}}
|
||||||
|
</p>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3">Resources</h3>
|
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3">Resources</h3>
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,64 @@ func TestRenderEmitsCanonicalAndOG(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFooterUsesBuildInfoWhenPageDefinesVersion(t *testing.T) {
|
||||||
|
templates := &Templates{}
|
||||||
|
buildInfo := BuildInfo{Version: "proxy-build-1.2.3", Commit: "abc123def"}
|
||||||
|
wantFooter := "proxy proxy-build-1.2.3 (abc123def)"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
page string
|
||||||
|
data any
|
||||||
|
shadow string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "version show page",
|
||||||
|
page: "version_show",
|
||||||
|
data: VersionShowData{
|
||||||
|
Layout: Layout{BuildInfo: buildInfo},
|
||||||
|
Package: &database.Package{
|
||||||
|
PURL: "pkg:npm/lodash",
|
||||||
|
Ecosystem: "npm",
|
||||||
|
Name: "lodash",
|
||||||
|
},
|
||||||
|
Version: &database.Version{
|
||||||
|
PURL: "pkg:npm/lodash@9.9.9",
|
||||||
|
PackagePURL: "pkg:npm/lodash",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shadow: "9.9.9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "browse source page",
|
||||||
|
page: "browse_source",
|
||||||
|
data: BrowseSourceData{
|
||||||
|
Layout: Layout{BuildInfo: buildInfo},
|
||||||
|
Ecosystem: "npm",
|
||||||
|
PackageName: "lodash",
|
||||||
|
Version: "9.9.9",
|
||||||
|
},
|
||||||
|
shadow: "9.9.9",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
if err := templates.Render(w, tt.page, tt.data); err != nil {
|
||||||
|
t.Fatalf("Render(%q) failed: %v", tt.page, err)
|
||||||
|
}
|
||||||
|
body := w.Body.String()
|
||||||
|
if !strings.Contains(body, wantFooter) {
|
||||||
|
t.Errorf("footer missing build info %q", wantFooter)
|
||||||
|
}
|
||||||
|
if strings.Contains(body, "proxy "+tt.shadow) {
|
||||||
|
t.Errorf("footer used page Version %q instead of BuildInfo", tt.shadow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRenderOmitsCanonicalWhenUIBaseURLUnset(t *testing.T) {
|
func TestRenderOmitsCanonicalWhenUIBaseURLUnset(t *testing.T) {
|
||||||
templates := &Templates{}
|
templates := &Templates{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,277 +0,0 @@
|
||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
fsys "io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Filesystem implements Storage using the local filesystem.
|
|
||||||
type Filesystem struct {
|
|
||||||
root string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFilesystem creates a new filesystem storage rooted at the given directory.
|
|
||||||
// The directory will be created if it does not exist.
|
|
||||||
func NewFilesystem(root string) (*Filesystem, error) {
|
|
||||||
absRoot, err := filepath.Abs(root)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("resolving root path: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.MkdirAll(absRoot, dirPermissions); err != nil {
|
|
||||||
return nil, fmt.Errorf("creating root directory: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Filesystem{root: absRoot}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) fullPath(path string) (string, error) {
|
|
||||||
localPath, err := cleanStoragePath(path)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return filepath.Join(fs.root, localPath), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) prefixPath(prefix string) (string, error) {
|
|
||||||
if prefix == "" {
|
|
||||||
return fs.root, nil
|
|
||||||
}
|
|
||||||
return fs.fullPath(prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanStoragePath(path string) (string, error) {
|
|
||||||
if path == "." || strings.Contains(path, `\`) || !filepath.IsLocal(path) {
|
|
||||||
return "", fmt.Errorf("%w: invalid storage path", ErrNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
localPath, err := filepath.Localize(path)
|
|
||||||
if err != nil || localPath == "." || !filepath.IsLocal(localPath) {
|
|
||||||
return "", fmt.Errorf("%w: invalid storage path", ErrNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
return localPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) Store(ctx context.Context, path string, r io.Reader) (int64, string, error) {
|
|
||||||
fullPath, err := fs.fullPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return 0, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
dir := filepath.Dir(fullPath)
|
|
||||||
if err := os.MkdirAll(dir, dirPermissions); err != nil {
|
|
||||||
return 0, "", fmt.Errorf("creating directory: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write to temp file first for atomic operation
|
|
||||||
tmpFile, err := os.CreateTemp(dir, ".tmp-*")
|
|
||||||
if err != nil {
|
|
||||||
return 0, "", fmt.Errorf("creating temp file: %w", err)
|
|
||||||
}
|
|
||||||
tmpPath := tmpFile.Name()
|
|
||||||
|
|
||||||
// Clean up temp file on error
|
|
||||||
success := false
|
|
||||||
defer func() {
|
|
||||||
if !success {
|
|
||||||
_ = tmpFile.Close()
|
|
||||||
_ = os.Remove(tmpPath)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Write content and compute hash
|
|
||||||
h := sha256.New()
|
|
||||||
w := io.MultiWriter(tmpFile, h)
|
|
||||||
|
|
||||||
size, err := io.Copy(w, r)
|
|
||||||
if err != nil {
|
|
||||||
return 0, "", fmt.Errorf("writing content: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tmpFile.Close(); err != nil {
|
|
||||||
return 0, "", fmt.Errorf("closing temp file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Atomic rename
|
|
||||||
if err := os.Rename(tmpPath, fullPath); err != nil {
|
|
||||||
return 0, "", fmt.Errorf("renaming temp file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
success = true
|
|
||||||
hash := hex.EncodeToString(h.Sum(nil))
|
|
||||||
return size, hash, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) Open(ctx context.Context, path string) (io.ReadCloser, error) {
|
|
||||||
fullPath, err := fs.fullPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return nil, ErrNotFound
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("opening file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) Exists(ctx context.Context, path string) (bool, error) {
|
|
||||||
fullPath, err := fs.fullPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = os.Stat(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, fmt.Errorf("checking file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) Delete(ctx context.Context, path string) error {
|
|
||||||
fullPath, err := fs.fullPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.Remove(fullPath)
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
return fmt.Errorf("removing file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to clean up empty parent directories
|
|
||||||
dir := filepath.Dir(fullPath)
|
|
||||||
for dir != fs.root {
|
|
||||||
if err := os.Remove(dir); err != nil {
|
|
||||||
break // Directory not empty or other error
|
|
||||||
}
|
|
||||||
dir = filepath.Dir(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) SignedURL(_ context.Context, _ string, _ time.Duration) (string, error) {
|
|
||||||
return "", ErrSignedURLUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) Size(ctx context.Context, path string) (int64, error) {
|
|
||||||
fullPath, err := fs.fullPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := os.Stat(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return 0, ErrNotFound
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("stat file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.Size(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) UsedSpace(ctx context.Context) (int64, error) {
|
|
||||||
var total int64
|
|
||||||
|
|
||||||
err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !info.IsDir() {
|
|
||||||
total += info.Size()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return 0, fmt.Errorf("walking directory: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return total, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListPrefix returns object metadata for paths under a prefix.
|
|
||||||
func (fs *Filesystem) ListPrefix(ctx context.Context, prefix string) ([]ObjectInfo, error) {
|
|
||||||
searchRoot, err := fs.prefixPath(prefix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(searchRoot); err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return []ObjectInfo{}, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("stat prefix: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
objects := make([]ObjectInfo, 0)
|
|
||||||
err = filepath.WalkDir(searchRoot, func(path string, entry fsys.DirEntry, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if entry.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := entry.Info()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
relPath, err := filepath.Rel(fs.root, path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
objects = append(objects, ObjectInfo{
|
|
||||||
Path: filepath.ToSlash(relPath),
|
|
||||||
Size: info.Size(),
|
|
||||||
ModTime: info.ModTime(),
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("walking prefix: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return objects, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Root returns the root directory of the storage.
|
|
||||||
func (fs *Filesystem) Root() string {
|
|
||||||
return fs.root
|
|
||||||
}
|
|
||||||
|
|
||||||
// FullPath returns the full filesystem path for a storage path.
|
|
||||||
// Useful for serving files directly or debugging.
|
|
||||||
// Returns an error if the resulting path would escape the storage root.
|
|
||||||
func (fs *Filesystem) FullPath(path string) (string, error) {
|
|
||||||
return fs.fullPath(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) URL() string {
|
|
||||||
return "file://" + filepath.ToSlash(fs.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs *Filesystem) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,331 +0,0 @@
|
||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNewFilesystem(t *testing.T) {
|
|
||||||
dir := t.TempDir()
|
|
||||||
root := filepath.Join(dir, "cache")
|
|
||||||
|
|
||||||
fs, err := NewFilesystem(root)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystem failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(root); err != nil {
|
|
||||||
t.Errorf("root directory not created: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fs.Root() != root {
|
|
||||||
t.Errorf("Root() = %q, want %q", fs.Root(), root)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemStore(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
content := "test content for storage"
|
|
||||||
|
|
||||||
size, hash, err := fs.Store(ctx, "npm/lodash/4.17.21/lodash.tgz", strings.NewReader(content))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Store failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if size != int64(len(content)) {
|
|
||||||
t.Errorf("size = %d, want %d", size, len(content))
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha256.Sum256([]byte(content))
|
|
||||||
wantHash := hex.EncodeToString(h[:])
|
|
||||||
if hash != wantHash {
|
|
||||||
t.Errorf("hash = %s, want %s", hash, wantHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify file exists on disk
|
|
||||||
fullPath, err := fs.FullPath("npm/lodash/4.17.21/lodash.tgz")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("FullPath failed: %v", err)
|
|
||||||
}
|
|
||||||
data, err := os.ReadFile(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("reading stored file: %v", err)
|
|
||||||
}
|
|
||||||
if string(data) != content {
|
|
||||||
t.Errorf("stored content = %q, want %q", string(data), content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemStoreAtomic(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// Store initial content
|
|
||||||
_, _, err := fs.Store(ctx, "test/file.txt", strings.NewReader("initial"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("initial Store failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite with new content
|
|
||||||
_, _, err = fs.Store(ctx, "test/file.txt", strings.NewReader("updated"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("update Store failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify updated content
|
|
||||||
r, err := fs.Open(ctx, "test/file.txt")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Open failed: %v", err)
|
|
||||||
}
|
|
||||||
defer func() { _ = r.Close() }()
|
|
||||||
|
|
||||||
data, _ := io.ReadAll(r)
|
|
||||||
if string(data) != "updated" {
|
|
||||||
t.Errorf("content = %q, want %q", string(data), "updated")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemOpen(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
content := "readable content"
|
|
||||||
|
|
||||||
_, _, _ = fs.Store(ctx, "test/read.txt", strings.NewReader(content))
|
|
||||||
|
|
||||||
r, err := fs.Open(ctx, "test/read.txt")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Open failed: %v", err)
|
|
||||||
}
|
|
||||||
defer func() { _ = r.Close() }()
|
|
||||||
|
|
||||||
data, err := io.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadAll failed: %v", err)
|
|
||||||
}
|
|
||||||
if string(data) != content {
|
|
||||||
t.Errorf("content = %q, want %q", string(data), content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemOpenNotFound(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
_, err := fs.Open(ctx, "does/not/exist.txt")
|
|
||||||
if !errors.Is(err, ErrNotFound) {
|
|
||||||
t.Errorf("Open non-existent = %v, want ErrNotFound", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemExists(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
exists, err := fs.Exists(ctx, "test/exists.txt")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Exists failed: %v", err)
|
|
||||||
}
|
|
||||||
if exists {
|
|
||||||
t.Error("Exists returned true for non-existent file")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, _ = fs.Store(ctx, "test/exists.txt", strings.NewReader("content"))
|
|
||||||
|
|
||||||
exists, err = fs.Exists(ctx, "test/exists.txt")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Exists after store failed: %v", err)
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
t.Error("Exists returned false for existing file")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemDelete(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
_, _, _ = fs.Store(ctx, "test/delete/nested/file.txt", strings.NewReader("content"))
|
|
||||||
|
|
||||||
err := fs.Delete(ctx, "test/delete/nested/file.txt")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Delete failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
exists, _ := fs.Exists(ctx, "test/delete/nested/file.txt")
|
|
||||||
if exists {
|
|
||||||
t.Error("file still exists after delete")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty parent directories should be cleaned up
|
|
||||||
nestedDir, err := fs.FullPath("test/delete/nested")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("FullPath failed: %v", err)
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(nestedDir); !os.IsNotExist(err) {
|
|
||||||
t.Error("empty nested directory not cleaned up")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemDeleteNotFound(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// Delete non-existent file should not error
|
|
||||||
err := fs.Delete(ctx, "does/not/exist.txt")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Delete non-existent = %v, want nil", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemSize(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
content := "size test content"
|
|
||||||
|
|
||||||
_, _, _ = fs.Store(ctx, "test/size.txt", strings.NewReader(content))
|
|
||||||
|
|
||||||
size, err := fs.Size(ctx, "test/size.txt")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Size failed: %v", err)
|
|
||||||
}
|
|
||||||
if size != int64(len(content)) {
|
|
||||||
t.Errorf("Size = %d, want %d", size, len(content))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemSizeNotFound(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
_, err := fs.Size(ctx, "does/not/exist.txt")
|
|
||||||
if !errors.Is(err, ErrNotFound) {
|
|
||||||
t.Errorf("Size non-existent = %v, want ErrNotFound", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemUsedSpace(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// Empty storage
|
|
||||||
used, err := fs.UsedSpace(ctx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("UsedSpace failed: %v", err)
|
|
||||||
}
|
|
||||||
if used != 0 {
|
|
||||||
t.Errorf("UsedSpace empty = %d, want 0", used)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add some files
|
|
||||||
_, _, _ = fs.Store(ctx, "a.txt", strings.NewReader("aaaa")) // 4 bytes
|
|
||||||
_, _, _ = fs.Store(ctx, "b.txt", strings.NewReader("bbbbbb")) // 6 bytes
|
|
||||||
_, _, _ = fs.Store(ctx, "c/d.txt", strings.NewReader("ccccc")) // 5 bytes
|
|
||||||
|
|
||||||
used, err = fs.UsedSpace(ctx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("UsedSpace failed: %v", err)
|
|
||||||
}
|
|
||||||
if used != 15 {
|
|
||||||
t.Errorf("UsedSpace = %d, want 15", used)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemLargeFile(t *testing.T) {
|
|
||||||
assertLargeFileRoundTrip(t, createTestFilesystem(t))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemRejectsInvalidPaths(t *testing.T) {
|
|
||||||
tmp := t.TempDir()
|
|
||||||
fs, err := NewFilesystem(tmp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for _, p := range []string{
|
|
||||||
"",
|
|
||||||
".",
|
|
||||||
"../etc/passwd",
|
|
||||||
"../../etc/passwd",
|
|
||||||
"a/../../etc/passwd",
|
|
||||||
"/etc/passwd",
|
|
||||||
"test//file.txt",
|
|
||||||
"test/./file.txt",
|
|
||||||
"test/../file.txt",
|
|
||||||
`test\..\file.txt`,
|
|
||||||
} {
|
|
||||||
name := p
|
|
||||||
if name == "" {
|
|
||||||
name = "empty"
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
if _, err := fs.FullPath(p); !errors.Is(err, ErrNotFound) {
|
|
||||||
t.Errorf("FullPath(%q) = %v, want ErrNotFound", p, err)
|
|
||||||
}
|
|
||||||
if _, err := fs.Open(ctx, p); err == nil {
|
|
||||||
t.Errorf("Open(%q) should reject invalid path", p)
|
|
||||||
}
|
|
||||||
if _, _, err := fs.Store(ctx, p, strings.NewReader("x")); err == nil {
|
|
||||||
t.Errorf("Store(%q) should reject invalid path", p)
|
|
||||||
}
|
|
||||||
if _, err := fs.Exists(ctx, p); err == nil {
|
|
||||||
t.Errorf("Exists(%q) should reject invalid path", p)
|
|
||||||
}
|
|
||||||
if err := fs.Delete(ctx, p); err == nil {
|
|
||||||
t.Errorf("Delete(%q) should reject invalid path", p)
|
|
||||||
}
|
|
||||||
if _, err := fs.Size(ctx, p); err == nil {
|
|
||||||
t.Errorf("Size(%q) should reject invalid path", p)
|
|
||||||
}
|
|
||||||
if _, err := fs.ListPrefix(ctx, p); p != "" && err == nil {
|
|
||||||
t.Errorf("ListPrefix(%q) should reject invalid path", p)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemListPrefixAllowsEmptyPrefix(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
_, _, _ = fs.Store(ctx, "a.txt", strings.NewReader("aaaa"))
|
|
||||||
_, _, _ = fs.Store(ctx, "c/d.txt", strings.NewReader("ccccc"))
|
|
||||||
|
|
||||||
objects, err := fs.ListPrefix(ctx, "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ListPrefix empty prefix failed: %v", err)
|
|
||||||
}
|
|
||||||
if len(objects) != 2 {
|
|
||||||
t.Fatalf("ListPrefix empty prefix returned %d objects, want 2", len(objects))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilesystemSignedURLUnsupported(t *testing.T) {
|
|
||||||
fs := createTestFilesystem(t)
|
|
||||||
|
|
||||||
_, err := fs.SignedURL(context.Background(), "test/file.txt", time.Minute)
|
|
||||||
if !errors.Is(err, ErrSignedURLUnsupported) {
|
|
||||||
t.Errorf("SignedURL = %v, want ErrSignedURLUnsupported", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTestFilesystem(t *testing.T) *Filesystem {
|
|
||||||
t.Helper()
|
|
||||||
dir := t.TempDir()
|
|
||||||
|
|
||||||
fs, err := NewFilesystem(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystem failed: %v", err)
|
|
||||||
}
|
|
||||||
return fs
|
|
||||||
}
|
|
||||||
|
|
@ -11,8 +11,6 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -80,42 +78,3 @@ func ArtifactPath(ecosystem, namespace, name, version, filename string) string {
|
||||||
}
|
}
|
||||||
return ecosystem + "/" + name + "/" + version + "/" + filename
|
return ecosystem + "/" + name + "/" + version + "/" + filename
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashingReader wraps a reader and computes SHA256 hash as content is read.
|
|
||||||
type HashingReader struct {
|
|
||||||
r io.Reader
|
|
||||||
hash []byte
|
|
||||||
h interface{ Sum([]byte) []byte }
|
|
||||||
size int64
|
|
||||||
done bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHashingReader(r io.Reader) *HashingReader {
|
|
||||||
h := sha256.New()
|
|
||||||
return &HashingReader{
|
|
||||||
r: io.TeeReader(r, h),
|
|
||||||
h: h,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hr *HashingReader) Read(p []byte) (n int, err error) {
|
|
||||||
n, err = hr.r.Read(p)
|
|
||||||
hr.size += int64(n)
|
|
||||||
if err == io.EOF {
|
|
||||||
hr.done = true
|
|
||||||
hr.hash = hr.h.Sum(nil)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hr *HashingReader) Sum() string {
|
|
||||||
if !hr.done {
|
|
||||||
hr.hash = hr.h.Sum(nil)
|
|
||||||
hr.done = true
|
|
||||||
}
|
|
||||||
return hex.EncodeToString(hr.hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hr *HashingReader) Size() int64 {
|
|
||||||
return hr.size
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -35,30 +34,6 @@ func TestArtifactPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHashingReader(t *testing.T) {
|
|
||||||
content := "hello world"
|
|
||||||
r := NewHashingReader(strings.NewReader(content))
|
|
||||||
|
|
||||||
data, err := io.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadAll failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(data) != content {
|
|
||||||
t.Errorf("got content %q, want %q", string(data), content)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.Size() != int64(len(content)) {
|
|
||||||
t.Errorf("got size %d, want %d", r.Size(), len(content))
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha256.Sum256([]byte(content))
|
|
||||||
wantHash := hex.EncodeToString(h[:])
|
|
||||||
if r.Sum() != wantHash {
|
|
||||||
t.Errorf("got hash %s, want %s", r.Sum(), wantHash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// assertLargeFileRoundTrip stores a 1MB file in the given storage, verifies size and
|
// assertLargeFileRoundTrip stores a 1MB file in the given storage, verifies size and
|
||||||
// hash, then reads it back and confirms the content matches.
|
// hash, then reads it back and confirms the content matches.
|
||||||
func assertLargeFileRoundTrip(t *testing.T, s Storage) {
|
func assertLargeFileRoundTrip(t *testing.T, s Storage) {
|
||||||
|
|
|
||||||
|
|
@ -1,296 +0,0 @@
|
||||||
# Package repository support issues
|
|
||||||
|
|
||||||
These drafts are grouped by the repository where the work belongs. The proxy
|
|
||||||
issues are already open. The remaining drafts have not been posted.
|
|
||||||
|
|
||||||
Helm, Chef, and Vagrant are listed as candidate PURL types. Helm has an open
|
|
||||||
upstream pull request, while Chef and Vagrant still need upstream type
|
|
||||||
definitions. Their registry clients should follow the accepted definitions
|
|
||||||
when exposing package identities through shared APIs.
|
|
||||||
|
|
||||||
## `git-pkgs/proxy`
|
|
||||||
|
|
||||||
Already open:
|
|
||||||
|
|
||||||
- [#261 Add Helm repository proxy support](https://github.com/git-pkgs/proxy/issues/261)
|
|
||||||
- [#262 Add Alpine APK repository proxy support](https://github.com/git-pkgs/proxy/issues/262)
|
|
||||||
- [#263 Add Arch Linux package repository proxy support](https://github.com/git-pkgs/proxy/issues/263)
|
|
||||||
- [#264 Add Chef Supermarket proxy support](https://github.com/git-pkgs/proxy/issues/264)
|
|
||||||
- [#265 Add Vagrant box repository proxy support](https://github.com/git-pkgs/proxy/issues/265)
|
|
||||||
|
|
||||||
## `package-url/purl-spec`
|
|
||||||
|
|
||||||
Helm type work is already open as
|
|
||||||
[#236](https://github.com/package-url/purl-spec/pull/236). The pull request
|
|
||||||
needs to be updated to the current JSON type-definition format. Do not open a
|
|
||||||
second Helm proposal.
|
|
||||||
|
|
||||||
### Define the Chef PURL type
|
|
||||||
|
|
||||||
Chef is listed as a candidate PURL type, but it has no type definition or
|
|
||||||
tracking issue.
|
|
||||||
|
|
||||||
Define how Chef cookbooks map to PURL components. Cover cookbook names,
|
|
||||||
versions, Supermarket hosts, private Supermarket instances, and source
|
|
||||||
repositories. Include type tests and examples for the public Supermarket and
|
|
||||||
a configured private server.
|
|
||||||
|
|
||||||
### Define the Vagrant PURL type
|
|
||||||
|
|
||||||
Vagrant is listed as a candidate PURL type, but it has no type definition or
|
|
||||||
tracking issue.
|
|
||||||
|
|
||||||
Define how Vagrant boxes map to PURL components. Cover namespaces, box names,
|
|
||||||
versions, providers, architectures, catalog URLs, and checksums. Include type
|
|
||||||
tests and examples for Vagrant Cloud and a configured private catalog.
|
|
||||||
|
|
||||||
## `git-pkgs/purl`
|
|
||||||
|
|
||||||
### Add Helm, Chef, and Vagrant PURL type support
|
|
||||||
|
|
||||||
The upstream specification lists Helm, Chef, and Vagrant as candidate types.
|
|
||||||
Helm has an open type proposal, while Chef and Vagrant still need definitions.
|
|
||||||
|
|
||||||
After each definition is accepted upstream, add it to the local type catalog
|
|
||||||
and implement any required normalization, validation, version handling, and
|
|
||||||
OSV mappings. Add construction, parsing, normalization, and round-trip tests
|
|
||||||
using the upstream examples.
|
|
||||||
|
|
||||||
## `git-pkgs/manifests`
|
|
||||||
|
|
||||||
### Add Helm chart manifest and lockfile support
|
|
||||||
|
|
||||||
Add parsers for `Chart.yaml` and `Chart.lock`.
|
|
||||||
|
|
||||||
`Chart.yaml` should report the chart name, version, declared dependencies,
|
|
||||||
repository URLs, and dependency version constraints. `Chart.lock` should
|
|
||||||
report the resolved dependency set and digest without treating the generated
|
|
||||||
timestamp as package identity.
|
|
||||||
|
|
||||||
Tests should cover aliased repositories, OCI repository URLs, conditions,
|
|
||||||
tags, and charts with no dependencies.
|
|
||||||
|
|
||||||
### Add Chef cookbook manifest support
|
|
||||||
|
|
||||||
Add static parsers for Chef `metadata.rb` and `Berksfile` files. Do not execute
|
|
||||||
Ruby while parsing them.
|
|
||||||
|
|
||||||
The metadata parser should report the cookbook name, version, license, and
|
|
||||||
`depends` declarations. The Berksfile parser should report cookbook sources,
|
|
||||||
version constraints, and git or path sources when they are static string
|
|
||||||
literals.
|
|
||||||
|
|
||||||
Tests should cover unconstrained dependencies, pessimistic constraints,
|
|
||||||
custom Supermarket sources, and dynamic Ruby expressions that must be skipped
|
|
||||||
without failing the whole file.
|
|
||||||
|
|
||||||
### Add Vagrant box declarations from Vagrantfile
|
|
||||||
|
|
||||||
Add a static `Vagrantfile` parser for box dependencies. Do not execute the
|
|
||||||
Ruby configuration file.
|
|
||||||
|
|
||||||
Recognize literal values assigned to `config.vm.box`, `box_version`,
|
|
||||||
`box_url`, `box_download_checksum`, and `box_download_checksum_type`. Return
|
|
||||||
the box as a direct dependency with its version, source URL, and integrity
|
|
||||||
metadata when available.
|
|
||||||
|
|
||||||
Tests should cover namespaced boxes, version constraints, custom catalog URLs,
|
|
||||||
checksums, and dynamic expressions that cannot be resolved safely.
|
|
||||||
|
|
||||||
Alpine `APKBUILD` and Arch `PKGBUILD` parsing already exist, so they do not
|
|
||||||
need new manifest issues.
|
|
||||||
|
|
||||||
## `git-pkgs/registries`
|
|
||||||
|
|
||||||
### Add Helm HTTP repository metadata support
|
|
||||||
|
|
||||||
Add a registry client for HTTP Helm repositories backed by `index.yaml`.
|
|
||||||
|
|
||||||
Map charts and chart releases to the shared package and version types. Include
|
|
||||||
creation time, digest, deprecation status, home and source links,
|
|
||||||
dependencies, maintainers, and absolute or relative artifact URLs when those
|
|
||||||
fields are present.
|
|
||||||
|
|
||||||
Require a configured repository URL because Helm has no single default HTTP
|
|
||||||
repository. Tests should cover multiple chart versions, relative URLs,
|
|
||||||
deprecated charts, missing optional fields, and custom authenticated
|
|
||||||
repositories.
|
|
||||||
|
|
||||||
This issue depends on an accepted Helm PURL type definition. Track
|
|
||||||
[purl-spec#236](https://github.com/package-url/purl-spec/pull/236).
|
|
||||||
|
|
||||||
### Add OCI registry metadata support
|
|
||||||
|
|
||||||
Add a registry client for `pkg:oci` packages. Support tag listing, manifest
|
|
||||||
retrieval by tag or digest, OCI indexes, annotations, and Bearer authentication
|
|
||||||
challenges.
|
|
||||||
|
|
||||||
Preserve the artifact type and layer media types so callers can distinguish
|
|
||||||
container images, Helm charts, and other OCI artifacts. Tests should include
|
|
||||||
the Helm config and chart layer media types as well as ordinary image
|
|
||||||
manifests.
|
|
||||||
|
|
||||||
### Add Alpine APK repository metadata support
|
|
||||||
|
|
||||||
Add an `apk` registry client for configured Alpine repositories. There is no
|
|
||||||
single default repository, so `repository_url` should identify a concrete
|
|
||||||
release, repository, and architecture location.
|
|
||||||
|
|
||||||
Read package names, versions, descriptions, licenses, dependencies, build
|
|
||||||
times, maintainers, architectures, and checksums from v2 `APKINDEX.tar.gz` and
|
|
||||||
v3 `Packages.adb` indexes. Keep namespace handling compatible with standard
|
|
||||||
`pkg:apk` PURLs.
|
|
||||||
|
|
||||||
Tests should cover v2 and v3 indexes, multiple architectures, versioned PURLs,
|
|
||||||
missing optional fields, and authenticated repositories.
|
|
||||||
|
|
||||||
### Add Arch Linux repository metadata support
|
|
||||||
|
|
||||||
Add an `alpm` registry client for configured pacman repositories. There is no
|
|
||||||
single default repository, so `repository_url` should identify the repository
|
|
||||||
and architecture location.
|
|
||||||
|
|
||||||
Parse repository database entries into package metadata, versions,
|
|
||||||
dependencies, licenses, build dates, packagers, architectures, and SHA-256
|
|
||||||
checksums. Keep namespace handling compatible with standard `pkg:alpm` PURLs.
|
|
||||||
|
|
||||||
Tests should cover compressed repository databases, epoch and package-release
|
|
||||||
versions, architecture qualifiers, missing optional fields, and authenticated
|
|
||||||
repositories.
|
|
||||||
|
|
||||||
### Add Chef Supermarket registry support
|
|
||||||
|
|
||||||
Add a Chef Supermarket registry client using `/universe` and the cookbook API.
|
|
||||||
|
|
||||||
Return cookbook metadata, available versions, publication times,
|
|
||||||
dependencies, maintainers, source links, and versioned download locations.
|
|
||||||
Support the public Supermarket and configured private Supermarket servers.
|
|
||||||
|
|
||||||
Tests should cover dependency graphs, version metadata, custom base URLs,
|
|
||||||
authentication, redirects, and missing cookbooks.
|
|
||||||
|
|
||||||
This issue depends on an accepted Chef PURL type definition.
|
|
||||||
|
|
||||||
### Add Vagrant box catalog registry support
|
|
||||||
|
|
||||||
Add a Vagrant registry client that reads box catalog metadata and supports
|
|
||||||
Vagrant Cloud catalog responses.
|
|
||||||
|
|
||||||
Return box descriptions, versions, providers, architectures, download URLs,
|
|
||||||
checksums, and release timestamps when available. Support custom catalog URLs
|
|
||||||
and configured credentials.
|
|
||||||
|
|
||||||
Tests should cover multiple providers and architectures, legacy catalog
|
|
||||||
entries without architecture fields, checksum types, redirects, private
|
|
||||||
catalogs, and missing boxes.
|
|
||||||
|
|
||||||
This issue depends on an accepted Vagrant PURL type definition.
|
|
||||||
|
|
||||||
## `git-pkgs/archives`
|
|
||||||
|
|
||||||
### Handle real Alpine APK v2 and v3 packages
|
|
||||||
|
|
||||||
The archive reader currently routes Alpine `.apk` files to the shared gzip
|
|
||||||
and tar reader. Signed APK v2 packages contain concatenated gzip streams for
|
|
||||||
the signature, control metadata, and payload. A standard tar reader stops after
|
|
||||||
the first tar stream, so it cannot reliably browse or extract the package
|
|
||||||
payload. APK v3 adds the ADB format.
|
|
||||||
|
|
||||||
Add format-aware APK readers that expose package metadata and payload files
|
|
||||||
without confusing Android APK ZIP files. Preserve the existing decompression
|
|
||||||
and path safety limits.
|
|
||||||
|
|
||||||
Tests should use signed v2 and v3 fixtures and cover listing, extraction,
|
|
||||||
malformed stream boundaries, decompression limits, and Android APK detection.
|
|
||||||
|
|
||||||
Arch `.pkg.tar.zst` support is already tracked by
|
|
||||||
[archives#23](https://github.com/git-pkgs/archives/issues/23), so do not open a
|
|
||||||
duplicate zstd issue. Helm charts, Chef cookbooks, and Vagrant boxes use
|
|
||||||
physical archive formats the module can already detect.
|
|
||||||
|
|
||||||
## `git-pkgs/magic`
|
|
||||||
|
|
||||||
### Detect Alpine APK v3 ADB data
|
|
||||||
|
|
||||||
Add byte-signature detection for Alpine APK v3 ADB indexes and packages. Keep
|
|
||||||
the result at the physical format level, consistent with the existing gzip,
|
|
||||||
zstd, tar, and ZIP classifications.
|
|
||||||
|
|
||||||
Tests should cover valid ADB prefixes, short input, malformed headers, and
|
|
||||||
nearby byte sequences that must remain unclassified.
|
|
||||||
|
|
||||||
## `git-pkgs/integrity`
|
|
||||||
|
|
||||||
### Add verification-only MD5 and SHA-1 checksums
|
|
||||||
|
|
||||||
Vagrant box catalogs may publish MD5 or SHA-1 checksums as well as SHA-256,
|
|
||||||
SHA-384, and SHA-512. Add MD5 and SHA-1 algorithms for checking bytes against
|
|
||||||
publisher-supplied metadata.
|
|
||||||
|
|
||||||
Keep the weak algorithms out of SRI parsing and formatting, and document that
|
|
||||||
they are provided only for compatibility verification. They must not be
|
|
||||||
selected for newly generated integrity metadata when a stronger algorithm is
|
|
||||||
available.
|
|
||||||
|
|
||||||
Add reader, hexadecimal parsing, length validation, verification, and failure
|
|
||||||
tests for both algorithms.
|
|
||||||
|
|
||||||
## `git-pkgs/managers`
|
|
||||||
|
|
||||||
These command definitions are useful for client integration and broader tool
|
|
||||||
support, but they do not block the proxy handlers.
|
|
||||||
|
|
||||||
### Add apk package manager commands
|
|
||||||
|
|
||||||
Add an `apk` manager definition for Alpine packages. Cover install, add,
|
|
||||||
remove, list, outdated, update, resolve, and path operations where apk exposes
|
|
||||||
a suitable command.
|
|
||||||
|
|
||||||
Tests should verify generated commands, repository arguments, versioned
|
|
||||||
packages, non-interactive flags, and operations that require elevated
|
|
||||||
permissions.
|
|
||||||
|
|
||||||
### Add pacman package manager commands
|
|
||||||
|
|
||||||
Add a `pacman` manager definition for Arch packages. Cover install, add,
|
|
||||||
remove, list, outdated, update, resolve, and path operations where pacman
|
|
||||||
exposes a suitable command.
|
|
||||||
|
|
||||||
Tests should verify generated commands, repository refresh behavior,
|
|
||||||
versioned packages, non-interactive flags, and operations that require
|
|
||||||
elevated permissions.
|
|
||||||
|
|
||||||
### Add Berkshelf commands
|
|
||||||
|
|
||||||
Add a `berks` manager definition for Chef cookbook dependencies. Cover
|
|
||||||
install, list, outdated, update, resolve, and vendor operations.
|
|
||||||
|
|
||||||
Tests should verify generated commands, frozen or locked installs, custom
|
|
||||||
Berksfile paths, and JSON or machine-readable output where Berkshelf provides
|
|
||||||
it.
|
|
||||||
|
|
||||||
### Add Vagrant box commands
|
|
||||||
|
|
||||||
Add a `vagrant` manager definition for box operations. Cover box add, remove,
|
|
||||||
list, outdated, update, and path operations where Vagrant exposes a suitable
|
|
||||||
command.
|
|
||||||
|
|
||||||
Tests should verify namespaced boxes, versions, providers, architectures,
|
|
||||||
custom catalog URLs, checksums, and non-interactive flags.
|
|
||||||
|
|
||||||
Helm manager support already exists.
|
|
||||||
|
|
||||||
## `git-pkgs/enrichment`
|
|
||||||
|
|
||||||
### Expose new package registry clients through enrichment
|
|
||||||
|
|
||||||
After the registry clients and PURL conventions land, update `enrichment` to
|
|
||||||
expose metadata for Helm, Alpine, Arch, Chef, and Vagrant packages through the
|
|
||||||
direct and hybrid clients.
|
|
||||||
|
|
||||||
Add dependency updates and conversion tests for package metadata, versions,
|
|
||||||
publication times, integrity values, status fields, and custom
|
|
||||||
`repository_url` values. Alpine and Arch vulnerability PURL translation
|
|
||||||
already exists and should remain covered.
|
|
||||||
|
|
||||||
This issue should wait until the corresponding `registries` work is available.
|
|
||||||
Loading…
Reference in a new issue