diff --git a/.gitignore b/.gitignore
index 272ea2b5ed..0791a17c71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,14 +42,10 @@ _testmain.go
 coverage.all
 cpu.out
 
-/modules/migration/bindata.go
-/modules/migration/bindata.go.hash
-/modules/options/bindata.go
-/modules/options/bindata.go.hash
-/modules/public/bindata.go
-/modules/public/bindata.go.hash
-/modules/templates/bindata.go
-/modules/templates/bindata.go.hash
+/modules/migration/bindata.*
+/modules/options/bindata.*
+/modules/public/bindata.*
+/modules/templates/bindata.*
 
 *.db
 *.log
diff --git a/Makefile b/Makefile
index d10250bbc7..f67762f8c1 100644
--- a/Makefile
+++ b/Makefile
@@ -120,8 +120,7 @@ WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
 WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
 WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
 
-BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
-BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
+BINDATA_DEST := modules/public/bindata.dat modules/options/bindata.dat modules/templates/bindata.dat
 
 GENERATED_GO_DEST := modules/charset/invisible_gen.go modules/charset/ambiguous_gen.go
 
@@ -149,14 +148,8 @@ SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US
 EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
 
 GO_SOURCES := $(wildcard *.go)
-GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
+GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go")
 GO_SOURCES += $(GENERATED_GO_DEST)
-GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
-
-ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
-	GO_SOURCES += $(BINDATA_DEST)
-	GENERATED_GO_DEST += $(BINDATA_DEST)
-endif
 
 # Force installation of playwright dependencies by setting this flag
 ifdef DEPS_PLAYWRIGHT
@@ -226,7 +219,7 @@ clean-all: clean ## delete backend, frontend and integration files
 
 .PHONY: clean
 clean: ## delete backend and integration files
-	rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \
+	rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) \
 		integrations*.test \
 		e2e*.test \
 		tests/integration/gitea-integration-* \
@@ -268,7 +261,7 @@ endif
 .PHONY: generate-swagger
 generate-swagger: $(SWAGGER_SPEC) ## generate the swagger spec from code comments
 
-$(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA) $(SWAGGER_SPEC_INPUT)
+$(SWAGGER_SPEC): $(GO_SOURCES) $(SWAGGER_SPEC_INPUT)
 	$(GO) run $(SWAGGER_PACKAGE) generate spec --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)'
 
 .PHONY: swagger-check
@@ -373,7 +366,7 @@ lint-go-gitea-vet: ## lint go files with gitea-vet
 .PHONY: lint-go-gopls
 lint-go-gopls: ## lint go files with gopls
 	@echo "Running gopls check..."
-	@GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES_NO_BINDATA)
+	@GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES)
 
 .PHONY: lint-editorconfig
 lint-editorconfig:
diff --git a/build.go b/build.go
index 234579b514..e81ba54690 100644
--- a/build.go
+++ b/build.go
@@ -5,19 +5,10 @@
 
 package main
 
-// Libraries that are included to vendor utilities used during build.
+// Libraries that are included to vendor utilities used during Makefile build.
 // These libraries will not be included in a normal compilation.
 
 import (
-	// for embed
-	_ "github.com/shurcooL/vfsgen"
-
-	// for cover merge
-	_ "golang.org/x/tools/cover"
-
 	// for vet
 	_ "code.gitea.io/gitea-vet"
-
-	// for swagger
-	_ "github.com/go-swagger/go-swagger/cmd/swagger"
 )
diff --git a/build/generate-bindata.go b/build/generate-bindata.go
index 2fcb7c2f2a..2553770762 100644
--- a/build/generate-bindata.go
+++ b/build/generate-bindata.go
@@ -6,87 +6,22 @@
 package main
 
 import (
-	"bytes"
-	"crypto/sha1"
 	"fmt"
-	"log"
-	"net/http"
 	"os"
-	"path/filepath"
-	"strconv"
 
-	"github.com/shurcooL/vfsgen"
+	"code.gitea.io/gitea/modules/assetfs"
 )
 
-func needsUpdate(dir, filename string) (bool, []byte) {
-	needRegen := false
-	_, err := os.Stat(filename)
-	if err != nil {
-		needRegen = true
-	}
-
-	oldHash, err := os.ReadFile(filename + ".hash")
-	if err != nil {
-		oldHash = []byte{}
-	}
-
-	hasher := sha1.New()
-
-	err = filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
-		if err != nil {
-			return err
-		}
-		info, err := d.Info()
-		if err != nil {
-			return err
-		}
-		_, _ = hasher.Write([]byte(d.Name()))
-		_, _ = hasher.Write([]byte(info.ModTime().String()))
-		_, _ = hasher.Write([]byte(strconv.FormatInt(info.Size(), 16)))
-		return nil
-	})
-	if err != nil {
-		return true, oldHash
-	}
-
-	newHash := hasher.Sum([]byte{})
-
-	if bytes.Compare(oldHash, newHash) != 0 {
-		return true, newHash
-	}
-
-	return needRegen, newHash
-}
-
 func main() {
-	if len(os.Args) < 4 {
-		log.Fatal("Insufficient number of arguments. Need: directory packageName filename")
+	if len(os.Args) != 3 {
+		fmt.Println("usage: ./generate-bindata {local-directory} {bindata-filename}")
+		os.Exit(1)
 	}
 
-	dir, packageName, filename := os.Args[1], os.Args[2], os.Args[3]
-	var useGlobalModTime bool
-	if len(os.Args) == 5 {
-		useGlobalModTime, _ = strconv.ParseBool(os.Args[4])
+	dir, filename := os.Args[1], os.Args[2]
+	fmt.Printf("generating bindata for %s to %s\n", dir, filename)
+	if err := assetfs.GenerateEmbedBindata(dir, filename); err != nil {
+		fmt.Printf("failed: %s\n", err.Error())
+		os.Exit(1)
 	}
-
-	update, newHash := needsUpdate(dir, filename)
-
-	if !update {
-		fmt.Printf("bindata for %s already up-to-date\n", packageName)
-		return
-	}
-
-	fmt.Printf("generating bindata for %s\n", packageName)
-	var fsTemplates http.FileSystem = http.Dir(dir)
-	err := vfsgen.Generate(fsTemplates, vfsgen.Options{
-		PackageName:      packageName,
-		BuildTags:        "bindata",
-		VariableName:     "Assets",
-		Filename:         filename,
-		UseGlobalModTime: useGlobalModTime,
-	})
-	if err != nil {
-		log.Fatalf("%v\n", err)
-	}
-	_ = os.WriteFile(filename+".hash", newHash, 0o666)
 }
diff --git a/cmd/embedded.go b/cmd/embedded.go
index 086bc06863..6a2fa07a93 100644
--- a/cmd/embedded.go
+++ b/cmd/embedded.go
@@ -118,7 +118,7 @@ func initEmbeddedExtractor(c *cli.Command) error {
 
 func runList(_ context.Context, c *cli.Command) error {
 	if err := runListDo(c); err != nil {
-		fmt.Fprintf(os.Stderr, "%v\n", err)
+		_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
 		return err
 	}
 	return nil
@@ -126,7 +126,7 @@ func runList(_ context.Context, c *cli.Command) error {
 
 func runView(_ context.Context, c *cli.Command) error {
 	if err := runViewDo(c); err != nil {
-		fmt.Fprintf(os.Stderr, "%v\n", err)
+		_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
 		return err
 	}
 	return nil
@@ -134,7 +134,7 @@ func runView(_ context.Context, c *cli.Command) error {
 
 func runExtract(_ context.Context, c *cli.Command) error {
 	if err := runExtractDo(c); err != nil {
-		fmt.Fprintf(os.Stderr, "%v\n", err)
+		_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
 		return err
 	}
 	return nil
@@ -217,7 +217,7 @@ func runExtractDo(c *cli.Command) error {
 	for _, a := range matchedAssetFiles {
 		if err := extractAsset(destdir, a, overwrite, rename); err != nil {
 			// Non-fatal error
-			fmt.Fprintf(os.Stderr, "%s: %v", a.path, err)
+			_, _ = fmt.Fprintf(os.Stderr, "%s: %v\n", a.path, err)
 		}
 	}
 
diff --git a/go.mod b/go.mod
index 9cffa4885d..9bc93ccd47 100644
--- a/go.mod
+++ b/go.mod
@@ -60,7 +60,6 @@ require (
 	github.com/go-ldap/ldap/v3 v3.4.11
 	github.com/go-redsync/redsync/v4 v4.13.0
 	github.com/go-sql-driver/mysql v1.9.2
-	github.com/go-swagger/go-swagger v0.31.0
 	github.com/go-webauthn/webauthn v0.12.3
 	github.com/gobwas/glob v0.2.3
 	github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
@@ -105,7 +104,6 @@ require (
 	github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
 	github.com/sassoftware/go-rpmutils v0.4.0
 	github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
-	github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
 	github.com/stretchr/testify v1.10.0
 	github.com/syndtr/goleveldb v1.0.0
 	github.com/tstranex/u2f v1.0.0
@@ -126,7 +124,6 @@ require (
 	golang.org/x/sync v0.15.0
 	golang.org/x/sys v0.33.0
 	golang.org/x/text v0.26.0
-	golang.org/x/tools v0.33.0
 	google.golang.org/grpc v1.72.0
 	google.golang.org/protobuf v1.36.6
 	gopkg.in/ini.v1 v1.67.0
@@ -144,15 +141,11 @@ require (
 	git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
 	github.com/DataDog/zstd v1.5.7 // indirect
-	github.com/Masterminds/goutils v1.1.1 // indirect
-	github.com/Masterminds/semver/v3 v3.3.1 // indirect
-	github.com/Masterminds/sprig/v3 v3.3.0 // indirect
 	github.com/Microsoft/go-winio v0.6.2 // indirect
 	github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
 	github.com/andybalholm/brotli v1.1.1 // indirect
 	github.com/andybalholm/cascadia v1.3.3 // indirect
 	github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
-	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
 	github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
@@ -195,7 +188,6 @@ require (
 	github.com/dlclark/regexp2 v1.11.5 // indirect
 	github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
 	github.com/fatih/color v1.18.0 // indirect
-	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/fxamacker/cbor/v2 v2.8.0 // indirect
 	github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
 	github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect
@@ -204,18 +196,6 @@ require (
 	github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect
 	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
 	github.com/go-ini/ini v1.67.0 // indirect
-	github.com/go-openapi/analysis v0.23.0 // indirect
-	github.com/go-openapi/errors v0.22.1 // indirect
-	github.com/go-openapi/inflect v0.21.2 // indirect
-	github.com/go-openapi/jsonpointer v0.21.1 // indirect
-	github.com/go-openapi/jsonreference v0.21.0 // indirect
-	github.com/go-openapi/loads v0.22.0 // indirect
-	github.com/go-openapi/runtime v0.28.0 // indirect
-	github.com/go-openapi/spec v0.21.0 // indirect
-	github.com/go-openapi/strfmt v0.23.0 // indirect
-	github.com/go-openapi/swag v0.23.1 // indirect
-	github.com/go-openapi/validate v0.24.0 // indirect
-	github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
 	github.com/go-webauthn/x v0.1.20 // indirect
 	github.com/goccy/go-json v0.10.5 // indirect
 	github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
@@ -229,7 +209,6 @@ require (
 	github.com/google/go-querystring v1.1.0 // indirect
 	github.com/google/go-tpm v0.9.3 // indirect
 	github.com/gorilla/css v1.0.1 // indirect
-	github.com/gorilla/handlers v1.5.2 // indirect
 	github.com/gorilla/mux v1.8.1 // indirect
 	github.com/gorilla/securecookie v1.1.2 // indirect
 	github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -237,12 +216,9 @@ require (
 	github.com/hashicorp/go-multierror v1.1.1 // indirect
 	github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
 	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
-	github.com/jessevdk/go-flags v1.6.1 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/kevinburke/ssh_config v1.2.0 // indirect
 	github.com/klauspost/pgzip v1.2.6 // indirect
-	github.com/kr/pretty v0.3.1 // indirect
-	github.com/kr/text v0.2.0 // indirect
 	github.com/libdns/libdns v1.0.0-beta.1 // indirect
 	github.com/mailru/easyjson v0.9.0 // indirect
 	github.com/markbates/going v1.0.3 // indirect
@@ -253,19 +229,15 @@ require (
 	github.com/miekg/dns v1.1.65 // indirect
 	github.com/minio/crc64nvme v1.0.1 // indirect
 	github.com/minio/md5-simd v1.1.2 // indirect
-	github.com/mitchellh/copystructure v1.2.0 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
-	github.com/mitchellh/reflectwalk v1.0.2 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
 	github.com/mschoch/smat v0.2.0 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/nwaples/rardecode v1.1.3 // indirect
-	github.com/oklog/ulid v1.3.1 // indirect
 	github.com/olekukonko/tablewriter v0.0.5 // indirect
 	github.com/onsi/ginkgo v1.16.5 // indirect
-	github.com/pelletier/go-toml/v2 v2.2.4 // indirect
 	github.com/pierrec/lz4/v4 v4.1.22 // indirect
 	github.com/pjbgf/sha1cd v0.3.2 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
@@ -274,22 +246,11 @@ require (
 	github.com/prometheus/procfs v0.16.1 // indirect
 	github.com/rhysd/actionlint v1.7.7 // indirect
 	github.com/rivo/uniseg v0.4.7 // indirect
-	github.com/rogpeppe/go-internal v1.14.1 // indirect
 	github.com/rs/xid v1.6.0 // indirect
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
-	github.com/sagikazarmark/locafero v0.9.0 // indirect
-	github.com/shopspring/decimal v1.4.0 // indirect
-	github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/skeema/knownhosts v1.3.1 // indirect
-	github.com/sourcegraph/conc v0.3.0 // indirect
-	github.com/spf13/afero v1.14.0 // indirect
-	github.com/spf13/cast v1.7.1 // indirect
-	github.com/spf13/pflag v1.0.6 // indirect
-	github.com/spf13/viper v1.20.1 // indirect
 	github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
-	github.com/subosito/gotenv v1.6.0 // indirect
-	github.com/toqueteos/webbrowser v1.2.0 // indirect
 	github.com/unknwon/com v1.0.1 // indirect
 	github.com/valyala/fastjson v1.6.4 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
@@ -300,7 +261,6 @@ require (
 	github.com/zeebo/assert v1.3.0 // indirect
 	github.com/zeebo/blake3 v0.2.4 // indirect
 	go.etcd.io/bbolt v1.4.0 // indirect
-	go.mongodb.org/mongo-driver v1.17.3 // indirect
 	go.uber.org/atomic v1.11.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
@@ -308,6 +268,7 @@ require (
 	golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
 	golang.org/x/mod v0.25.0 // indirect
 	golang.org/x/time v0.11.0 // indirect
+	golang.org/x/tools v0.33.0 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
@@ -315,8 +276,6 @@ require (
 
 replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
 
-replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
-
 replace github.com/nektos/act => gitea.com/gitea/act v0.261.6
 
 // TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why
diff --git a/go.sum b/go.sum
index 090a04346d..9810c4a36d 100644
--- a/go.sum
+++ b/go.sum
@@ -62,12 +62,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
 github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE=
 github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
 github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
-github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
-github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
-github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
-github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
-github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
 github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
 github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
@@ -103,8 +97,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
-github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
-github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
 github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
 github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
@@ -274,12 +266,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
 github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
 github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
 github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
-github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
-github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
-github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
-github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
@@ -325,28 +313,6 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
 github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
 github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
 github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
-github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
-github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
-github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU=
-github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
-github.com/go-openapi/inflect v0.21.2 h1:0gClGlGcxifcJR56zwvhaOulnNgnhc4qTAkob5ObnSM=
-github.com/go-openapi/inflect v0.21.2/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
-github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
-github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
-github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
-github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
-github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
-github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
-github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
-github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
-github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
-github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
-github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
-github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
-github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
-github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
-github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
-github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
 github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
 github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI=
@@ -357,13 +323,9 @@ github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkv
 github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ=
 github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
 github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
-github.com/go-swagger/go-swagger v0.31.0 h1:H8eOYQnY2u7vNKWDNykv2xJP3pBhRG/R+SOCAmKrLlc=
-github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/HoaZJ5edupq7po=
 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
 github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
 github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
-github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
-github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE=
 github.com/go-webauthn/webauthn v0.12.3/go.mod h1:4JRe8Z3W7HIw8NGEWn2fnUwecoDzkkeach/NnvhkqGY=
 github.com/go-webauthn/x v0.1.20 h1:brEBDqfiPtNNCdS/peu8gARtq8fIPsHz0VzpPjGvgiw=
@@ -446,8 +408,6 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
 github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
 github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
 github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
-github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
-github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
 github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
 github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
 github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
@@ -497,8 +457,6 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
 github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
 github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
-github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
-github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
 github.com/jhillyerd/enmime v1.3.0 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw=
 github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -540,8 +498,6 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
 github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ=
 github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
-github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 h1:F/3FfGmKdiKFa8kL3YrpZ7pe9H4l4AzA1pbaOUnRvPI=
-github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0/go.mod h1:JEfTc3+2DF9Z4PXhLLvXL42zexJyh8rIq3OzUj/0rAk=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
@@ -577,14 +533,10 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
 github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
 github.com/minio/minio-go/v7 v7.0.91 h1:tWLZnEfo3OZl5PoXQwcwTAPNNrjyWwOh6cbZitW5JQc=
 github.com/minio/minio-go/v7 v7.0.91/go.mod h1:uvMUcGrpgeSAAI6+sD3818508nUyMULw94j2Nxku/Go=
-github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
-github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 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/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
-github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -607,8 +559,6 @@ github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWk
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
-github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
-github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E=
@@ -629,8 +579,6 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
 github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
 github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
-github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
 github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
 github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
 github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
@@ -674,7 +622,6 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
 github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
 github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
 github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
 github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
@@ -682,8 +629,6 @@ github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
-github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
 github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=
@@ -692,10 +637,6 @@ github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLS
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
-github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
-github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
-github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
-github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@@ -707,22 +648,12 @@ github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl
 github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
 github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
 github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
-github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
-github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
-github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
-github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
-github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
-github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
 github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
 github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
 github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc=
@@ -745,13 +676,9 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
 github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
-github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
-github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
 github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
 github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
 github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
-github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
-github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
 github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
 github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@@ -809,8 +736,6 @@ gitlab.com/gitlab-org/api/client-go v0.127.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAj
 go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
 go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
 go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
-go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
-go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
diff --git a/modules/assetfs/embed.go b/modules/assetfs/embed.go
new file mode 100644
index 0000000000..95176372d1
--- /dev/null
+++ b/modules/assetfs/embed.go
@@ -0,0 +1,375 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package assetfs
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io"
+	"io/fs"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+	"sync"
+	"time"
+
+	"code.gitea.io/gitea/modules/json"
+	"code.gitea.io/gitea/modules/util"
+)
+
+type EmbeddedFile interface {
+	io.ReadSeeker
+	fs.ReadDirFile
+	ReadDir(n int) ([]fs.DirEntry, error)
+}
+
+type EmbeddedFileInfo interface {
+	fs.FileInfo
+	fs.DirEntry
+	GetGzipContent() ([]byte, bool)
+}
+
+type decompressor interface {
+	io.Reader
+	Close() error
+	Reset(io.Reader) error
+}
+
+type embeddedFileInfo struct {
+	fs       *embeddedFS
+	fullName string
+	data     []byte
+
+	BaseName   string              `json:"n"`
+	OriginSize int64               `json:"s,omitempty"`
+	DataBegin  int64               `json:"b,omitempty"`
+	DataLen    int64               `json:"l,omitempty"`
+	Children   []*embeddedFileInfo `json:"c,omitempty"`
+}
+
+func (fi *embeddedFileInfo) GetGzipContent() ([]byte, bool) {
+	// when generating the bindata, if the compressed data equals or is larger than the original data, we store the original data
+	if fi.DataLen == fi.OriginSize {
+		return nil, false
+	}
+	return fi.data, true
+}
+
+type EmbeddedFileBase struct {
+	info       *embeddedFileInfo
+	dataReader io.ReadSeeker
+	seekPos    int64
+}
+
+func (f *EmbeddedFileBase) ReadDir(n int) ([]fs.DirEntry, error) {
+	// this method is used to satisfy the "func (f ioFile) ReadDir(...)" in httpfs
+	l, err := f.info.fs.ReadDir(f.info.fullName)
+	if err != nil {
+		return nil, err
+	}
+	if n < 0 || n > len(l) {
+		return l, nil
+	}
+	return l[:n], nil
+}
+
+type EmbeddedOriginFile struct {
+	EmbeddedFileBase
+}
+
+type EmbeddedCompressedFile struct {
+	EmbeddedFileBase
+	decompressor    decompressor
+	decompressorPos int64
+}
+
+type embeddedFS struct {
+	meta func() *EmbeddedMeta
+
+	files   map[string]*embeddedFileInfo
+	filesMu sync.RWMutex
+
+	data []byte
+}
+
+type EmbeddedMeta struct {
+	Root *embeddedFileInfo
+}
+
+func NewEmbeddedFS(data []byte) fs.ReadDirFS {
+	efs := &embeddedFS{data: data, files: make(map[string]*embeddedFileInfo)}
+	efs.meta = sync.OnceValue(func() *EmbeddedMeta {
+		var meta EmbeddedMeta
+		p := bytes.LastIndexByte(data, '\n')
+		if p < 0 {
+			return &meta
+		}
+		if err := json.Unmarshal(data[p+1:], &meta); err != nil {
+			panic("embedded file is not valid")
+		}
+		return &meta
+	})
+	return efs
+}
+
+var _ fs.ReadDirFS = (*embeddedFS)(nil)
+
+func (e *embeddedFS) ReadDir(name string) (l []fs.DirEntry, err error) {
+	fi, err := e.getFileInfo(name)
+	if err != nil {
+		return nil, err
+	}
+	if !fi.IsDir() {
+		return nil, fs.ErrNotExist
+	}
+	l = make([]fs.DirEntry, len(fi.Children))
+	for i, child := range fi.Children {
+		l[i], err = e.getFileInfo(name + "/" + child.BaseName)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return l, nil
+}
+
+func (e *embeddedFS) getFileInfo(fullName string) (*embeddedFileInfo, error) {
+	// no need to do heavy "path.Clean()" because we don't want to support "foo/../bar" or absolute paths
+	fullName = strings.TrimPrefix(fullName, "./")
+	if fullName == "" {
+		fullName = "."
+	}
+
+	e.filesMu.RLock()
+	fi := e.files[fullName]
+	e.filesMu.RUnlock()
+	if fi != nil {
+		return fi, nil
+	}
+
+	fields := strings.Split(fullName, "/")
+	fi = e.meta().Root
+	if fullName != "." {
+		found := true
+		for _, field := range fields {
+			for _, child := range fi.Children {
+				if found = child.BaseName == field; found {
+					fi = child
+					break
+				}
+			}
+			if !found {
+				return nil, fs.ErrNotExist
+			}
+		}
+	}
+
+	e.filesMu.Lock()
+	defer e.filesMu.Unlock()
+	if fi != nil {
+		fi.fs = e
+		fi.fullName = fullName
+		fi.data = e.data[fi.DataBegin : fi.DataBegin+fi.DataLen]
+		e.files[fullName] = fi // do not cache nil, otherwise keeping accessing random non-existing file will cause OOM
+		return fi, nil
+	}
+	return nil, fs.ErrNotExist
+}
+
+func (e *embeddedFS) Open(name string) (fs.File, error) {
+	info, err := e.getFileInfo(name)
+	if err != nil {
+		return nil, err
+	}
+	base := EmbeddedFileBase{info: info}
+	base.dataReader = bytes.NewReader(base.info.data)
+	if info.DataLen != info.OriginSize {
+		decomp, err := gzip.NewReader(base.dataReader)
+		if err != nil {
+			return nil, err
+		}
+		return &EmbeddedCompressedFile{EmbeddedFileBase: base, decompressor: decomp}, nil
+	}
+	return &EmbeddedOriginFile{base}, nil
+}
+
+var (
+	_ EmbeddedFileInfo = (*embeddedFileInfo)(nil)
+	_ EmbeddedFile     = (*EmbeddedOriginFile)(nil)
+	_ EmbeddedFile     = (*EmbeddedCompressedFile)(nil)
+)
+
+func (f *EmbeddedOriginFile) Read(p []byte) (n int, err error) {
+	return f.dataReader.Read(p)
+}
+
+func (f *EmbeddedCompressedFile) Read(p []byte) (n int, err error) {
+	if f.decompressorPos > f.seekPos {
+		if err = f.decompressor.Reset(bytes.NewReader(f.info.data)); err != nil {
+			return 0, err
+		}
+		f.decompressorPos = 0
+	}
+	if f.decompressorPos < f.seekPos {
+		if _, err = io.CopyN(io.Discard, f.decompressor, f.seekPos-f.decompressorPos); err != nil {
+			return 0, err
+		}
+		f.decompressorPos = f.seekPos
+	}
+	n, err = f.decompressor.Read(p)
+	f.decompressorPos += int64(n)
+	f.seekPos = f.decompressorPos
+	return n, err
+}
+
+func (f *EmbeddedFileBase) Seek(offset int64, whence int) (int64, error) {
+	switch whence {
+	case io.SeekStart:
+		f.seekPos = offset
+	case io.SeekCurrent:
+		f.seekPos += offset
+	case io.SeekEnd:
+		f.seekPos = f.info.OriginSize + offset
+	}
+	return f.seekPos, nil
+}
+
+func (f *EmbeddedFileBase) Stat() (fs.FileInfo, error) {
+	return f.info, nil
+}
+
+func (f *EmbeddedOriginFile) Close() error {
+	return nil
+}
+
+func (f *EmbeddedCompressedFile) Close() error {
+	return f.decompressor.Close()
+}
+
+func (fi *embeddedFileInfo) Name() string {
+	return fi.BaseName
+}
+
+func (fi *embeddedFileInfo) Size() int64 {
+	return fi.OriginSize
+}
+
+func (fi *embeddedFileInfo) Mode() fs.FileMode {
+	return util.Iif(fi.IsDir(), fs.ModeDir|0o555, 0o444)
+}
+
+func (fi *embeddedFileInfo) ModTime() time.Time {
+	return getExecutableModTime()
+}
+
+func (fi *embeddedFileInfo) IsDir() bool {
+	return fi.Children != nil
+}
+
+func (fi *embeddedFileInfo) Sys() any {
+	return nil
+}
+
+func (fi *embeddedFileInfo) Type() fs.FileMode {
+	return util.Iif(fi.IsDir(), fs.ModeDir, 0)
+}
+
+func (fi *embeddedFileInfo) Info() (fs.FileInfo, error) {
+	return fi, nil
+}
+
+// getExecutableModTime returns the modification time of the executable file.
+// In bindata, we can't use the ModTime of the files because we need to make the build reproducible
+var getExecutableModTime = sync.OnceValue(func() (modTime time.Time) {
+	exePath, err := os.Executable()
+	if err != nil {
+		return modTime
+	}
+	exePath, err = filepath.Abs(exePath)
+	if err != nil {
+		return modTime
+	}
+	exePath, err = filepath.EvalSymlinks(exePath)
+	if err != nil {
+		return modTime
+	}
+	st, err := os.Stat(exePath)
+	if err != nil {
+		return modTime
+	}
+	return st.ModTime()
+})
+
+func GenerateEmbedBindata(fsRootPath, outputFile string) error {
+	output, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
+	if err != nil {
+		return err
+	}
+	defer output.Close()
+
+	meta := &EmbeddedMeta{}
+	meta.Root = &embeddedFileInfo{}
+	var outputOffset int64
+	var embedFiles func(parent *embeddedFileInfo, fsPath, embedPath string) error
+	embedFiles = func(parent *embeddedFileInfo, fsPath, embedPath string) error {
+		dirEntries, err := os.ReadDir(fsPath)
+		if err != nil {
+			return err
+		}
+		for _, dirEntry := range dirEntries {
+			if err != nil {
+				return err
+			}
+			if dirEntry.IsDir() {
+				child := &embeddedFileInfo{
+					BaseName: dirEntry.Name(),
+					Children: []*embeddedFileInfo{}, // non-nil means it's a directory
+				}
+				parent.Children = append(parent.Children, child)
+				if err = embedFiles(child, filepath.Join(fsPath, dirEntry.Name()), path.Join(embedPath, dirEntry.Name())); err != nil {
+					return err
+				}
+			} else {
+				data, err := os.ReadFile(filepath.Join(fsPath, dirEntry.Name()))
+				if err != nil {
+					return err
+				}
+				var compressed bytes.Buffer
+				gz, _ := gzip.NewWriterLevel(&compressed, gzip.BestCompression)
+				if _, err = gz.Write(data); err != nil {
+					return err
+				}
+				if err = gz.Close(); err != nil {
+					return err
+				}
+
+				// only use the compressed data if it is smaller than the original data
+				outputBytes := util.Iif(len(compressed.Bytes()) < len(data), compressed.Bytes(), data)
+				child := &embeddedFileInfo{
+					BaseName:   dirEntry.Name(),
+					OriginSize: int64(len(data)),
+					DataBegin:  outputOffset,
+					DataLen:    int64(len(outputBytes)),
+				}
+				if _, err = output.Write(outputBytes); err != nil {
+					return err
+				}
+				outputOffset += child.DataLen
+				parent.Children = append(parent.Children, child)
+			}
+		}
+		return nil
+	}
+
+	if err = embedFiles(meta.Root, fsRootPath, ""); err != nil {
+		return err
+	}
+	jsonBuf, err := json.Marshal(meta) // can't use json.NewEncoder here because it writes extra EOL
+	if err != nil {
+		return err
+	}
+	_, _ = output.Write([]byte{'\n'})
+	_, err = output.Write(jsonBuf)
+	return err
+}
diff --git a/modules/assetfs/embed_test.go b/modules/assetfs/embed_test.go
new file mode 100644
index 0000000000..06598da4c4
--- /dev/null
+++ b/modules/assetfs/embed_test.go
@@ -0,0 +1,98 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package assetfs
+
+import (
+	"bytes"
+	"io/fs"
+	"net/http"
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestEmbed(t *testing.T) {
+	tmpDir := t.TempDir()
+	tmpDataDir := tmpDir + "/data"
+	_ = os.MkdirAll(tmpDataDir+"/foo/bar", 0o755)
+	_ = os.WriteFile(tmpDataDir+"/a.txt", []byte("a"), 0o644)
+	_ = os.WriteFile(tmpDataDir+"/foo/bar/b.txt", bytes.Repeat([]byte("a"), 1000), 0o644)
+	_ = os.WriteFile(tmpDataDir+"/foo/c.txt", []byte("c"), 0o644)
+	require.NoError(t, GenerateEmbedBindata(tmpDataDir, tmpDir+"/out.dat"))
+
+	data, err := os.ReadFile(tmpDir + "/out.dat")
+	require.NoError(t, err)
+	efs := NewEmbeddedFS(data)
+
+	// test a non-existing file
+	_, err = fs.ReadFile(efs, "not exist")
+	assert.ErrorIs(t, err, fs.ErrNotExist)
+
+	// test a normal file (no compression)
+	content, err := fs.ReadFile(efs, "a.txt")
+	require.NoError(t, err)
+	assert.Equal(t, "a", string(content))
+	fi, err := fs.Stat(efs, "a.txt")
+	require.NoError(t, err)
+	_, ok := fi.(EmbeddedFileInfo).GetGzipContent()
+	assert.False(t, ok)
+
+	// test a compressed file
+	content, err = fs.ReadFile(efs, "foo/bar/b.txt")
+	require.NoError(t, err)
+	assert.Equal(t, bytes.Repeat([]byte("a"), 1000), content)
+	fi, err = fs.Stat(efs, "foo/bar/b.txt")
+	require.NoError(t, err)
+	assert.False(t, fi.Mode().IsDir())
+	assert.True(t, fi.Mode().IsRegular())
+	gzipContent, ok := fi.(EmbeddedFileInfo).GetGzipContent()
+	assert.True(t, ok)
+	assert.Greater(t, len(gzipContent), 1)
+	assert.Less(t, len(gzipContent), 1000)
+
+	// test list root directory
+	entries, err := fs.ReadDir(efs, ".")
+	require.NoError(t, err)
+	assert.Len(t, entries, 2)
+	assert.Equal(t, "a.txt", entries[0].Name())
+	assert.False(t, entries[0].IsDir())
+
+	// test list subdirectory
+	entries, err = fs.ReadDir(efs, "foo")
+	require.NoError(t, err)
+	require.Len(t, entries, 2)
+	assert.Equal(t, "bar", entries[0].Name())
+	assert.True(t, entries[0].IsDir())
+	assert.Equal(t, "c.txt", entries[1].Name())
+	assert.False(t, entries[1].IsDir())
+
+	// test directory mode
+	fi, err = fs.Stat(efs, "foo")
+	require.NoError(t, err)
+	assert.True(t, fi.IsDir())
+	assert.True(t, fi.Mode().IsDir())
+	assert.False(t, fi.Mode().IsRegular())
+
+	// test httpfs
+	hfs := http.FS(efs)
+	hf, err := hfs.Open("foo/bar/b.txt")
+	require.NoError(t, err)
+	hi, err := hf.Stat()
+	require.NoError(t, err)
+	fiEmbedded, ok := hi.(EmbeddedFileInfo)
+	require.True(t, ok)
+	gzipContent, ok = fiEmbedded.GetGzipContent()
+	assert.True(t, ok)
+	assert.Greater(t, len(gzipContent), 1)
+	assert.Less(t, len(gzipContent), 1000)
+
+	// test httpfs directory listing
+	hf, err = hfs.Open("foo")
+	require.NoError(t, err)
+	dirs, err := hf.Readdir(1)
+	require.NoError(t, err)
+	assert.Len(t, dirs, 1)
+}
diff --git a/modules/assetfs/layered.go b/modules/assetfs/layered.go
index 4f3811ba2b..ce55475bd9 100644
--- a/modules/assetfs/layered.go
+++ b/modules/assetfs/layered.go
@@ -52,8 +52,8 @@ func Local(name, base string, sub ...string) *Layer {
 }
 
 // Bindata returns a new Layer with the given name, it serves files from the given bindata asset.
-func Bindata(name string, fs http.FileSystem) *Layer {
-	return &Layer{name: name, fs: fs}
+func Bindata(name string, fs fs.FS) *Layer {
+	return &Layer{name: name, fs: http.FS(fs)}
 }
 
 // LayeredFS is a layered asset file-system. It works like http.FileSystem, but it can have multiple layers.
diff --git a/modules/migration/schemas_bindata.go b/modules/migration/schemas_bindata.go
index c5db3b3461..695c2c1135 100644
--- a/modules/migration/schemas_bindata.go
+++ b/modules/migration/schemas_bindata.go
@@ -3,6 +3,28 @@
 
 //go:build bindata
 
+//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas bindata.dat
+
 package migration
 
-//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas migration bindata.go
+import (
+	"io"
+	"io/fs"
+	"path"
+	"sync"
+
+	_ "embed"
+
+	"code.gitea.io/gitea/modules/assetfs"
+)
+
+//go:embed bindata.dat
+var bindata []byte
+
+var BuiltinAssets = sync.OnceValue(func() fs.FS {
+	return assetfs.NewEmbeddedFS(bindata)
+})
+
+func openSchema(filename string) (io.ReadCloser, error) {
+	return BuiltinAssets().Open(path.Base(filename))
+}
diff --git a/modules/migration/schemas_static.go b/modules/migration/schemas_static.go
deleted file mode 100644
index 8a0c340a65..0000000000
--- a/modules/migration/schemas_static.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2022 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-//go:build bindata
-
-package migration
-
-import (
-	"io"
-	"path"
-)
-
-func openSchema(filename string) (io.ReadCloser, error) {
-	return Assets.Open(path.Base(filename))
-}
diff --git a/modules/options/options_bindata.go b/modules/options/options_bindata.go
index 29151cb3cb..b2321d7eb5 100644
--- a/modules/options/options_bindata.go
+++ b/modules/options/options_bindata.go
@@ -3,6 +3,21 @@
 
 //go:build bindata
 
+//go:generate go run ../../build/generate-bindata.go ../../options bindata.dat
+
 package options
 
-//go:generate go run ../../build/generate-bindata.go ../../options options bindata.go
+import (
+	"sync"
+
+	_ "embed"
+
+	"code.gitea.io/gitea/modules/assetfs"
+)
+
+//go:embed bindata.dat
+var bindata []byte
+
+var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer {
+	return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata))
+})
diff --git a/modules/options/dynamic.go b/modules/options/options_dynamic.go
similarity index 100%
rename from modules/options/dynamic.go
rename to modules/options/options_dynamic.go
diff --git a/modules/options/static.go b/modules/options/static.go
deleted file mode 100644
index 72b28e990e..0000000000
--- a/modules/options/static.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2022 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-//go:build bindata
-
-package options
-
-import (
-	"code.gitea.io/gitea/modules/assetfs"
-)
-
-func BuiltinAssets() *assetfs.Layer {
-	return assetfs.Bindata("builtin(bindata)", Assets)
-}
diff --git a/modules/public/public.go b/modules/public/public.go
index 7f8ce29056..2bc55b7869 100644
--- a/modules/public/public.go
+++ b/modules/public/public.go
@@ -89,19 +89,16 @@ func handleRequest(w http.ResponseWriter, req *http.Request, fs http.FileSystem,
 	servePublicAsset(w, req, fi, fi.ModTime(), f)
 }
 
-type GzipBytesProvider interface {
-	GzipBytes() []byte
-}
-
 // servePublicAsset serve http content
 func servePublicAsset(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) {
 	setWellKnownContentType(w, fi.Name())
 	httpcache.SetCacheControlInHeader(w.Header(), httpcache.CacheControlForPublicStatic())
 	encodings := parseAcceptEncoding(req.Header.Get("Accept-Encoding"))
-	if encodings.Contains("gzip") {
-		// try to provide gzip content directly from bindata (provided by vfsgen۰CompressedFileInfo)
-		if compressed, ok := fi.(GzipBytesProvider); ok {
-			rdGzip := bytes.NewReader(compressed.GzipBytes())
+	fiEmbedded, _ := fi.(assetfs.EmbeddedFileInfo)
+	if encodings.Contains("gzip") && fiEmbedded != nil {
+		// try to provide gzip content directly from bindata
+		if gzipBytes, ok := fiEmbedded.GetGzipContent(); ok {
+			rdGzip := bytes.NewReader(gzipBytes)
 			// all gzipped static files (from bindata) are managed by Gitea, so we can make sure every file has the correct ext name
 			// then we can get the correct Content-Type, we do not need to do http.DetectContentType on the decompressed data
 			if w.Header().Get("Content-Type") == "" {
diff --git a/modules/public/public_bindata.go b/modules/public/public_bindata.go
index 4878f88ad1..2dcf3e72e4 100644
--- a/modules/public/public_bindata.go
+++ b/modules/public/public_bindata.go
@@ -5,4 +5,19 @@
 
 package public
 
-//go:generate go run ../../build/generate-bindata.go ../../public public bindata.go true
+//go:generate go run ../../build/generate-bindata.go ../../public bindata.dat
+
+import (
+	"sync"
+
+	_ "embed"
+
+	"code.gitea.io/gitea/modules/assetfs"
+)
+
+//go:embed bindata.dat
+var bindata []byte
+
+var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer {
+	return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata))
+})
diff --git a/modules/public/serve_dynamic.go b/modules/public/public_dynamic.go
similarity index 100%
rename from modules/public/serve_dynamic.go
rename to modules/public/public_dynamic.go
diff --git a/modules/public/serve_static.go b/modules/public/serve_static.go
deleted file mode 100644
index e79085021e..0000000000
--- a/modules/public/serve_static.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-//go:build bindata
-
-package public
-
-import (
-	"time"
-
-	"code.gitea.io/gitea/modules/assetfs"
-	"code.gitea.io/gitea/modules/timeutil"
-)
-
-var _ GzipBytesProvider = (*vfsgen۰CompressedFileInfo)(nil)
-
-// GlobalModTime provide a global mod time for embedded asset files
-func GlobalModTime(filename string) time.Time {
-	return timeutil.GetExecutableModTime()
-}
-
-func BuiltinAssets() *assetfs.Layer {
-	return assetfs.Bindata("builtin(bindata)", Assets)
-}
diff --git a/modules/templates/static.go b/modules/templates/static.go
deleted file mode 100644
index b5a7e561ec..0000000000
--- a/modules/templates/static.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-//go:build bindata
-
-package templates
-
-import (
-	"time"
-
-	"code.gitea.io/gitea/modules/assetfs"
-	"code.gitea.io/gitea/modules/timeutil"
-)
-
-// GlobalModTime provide a global mod time for embedded asset files
-func GlobalModTime(filename string) time.Time {
-	return timeutil.GetExecutableModTime()
-}
-
-func BuiltinAssets() *assetfs.Layer {
-	return assetfs.Bindata("builtin(bindata)", Assets)
-}
diff --git a/modules/templates/templates_bindata.go b/modules/templates/templates_bindata.go
index 6f1d3cf539..a919591ecf 100644
--- a/modules/templates/templates_bindata.go
+++ b/modules/templates/templates_bindata.go
@@ -3,6 +3,21 @@
 
 //go:build bindata
 
+//go:generate go run ../../build/generate-bindata.go ../../templates bindata.dat
+
 package templates
 
-//go:generate go run ../../build/generate-bindata.go ../../templates templates bindata.go true
+import (
+	"sync"
+
+	_ "embed"
+
+	"code.gitea.io/gitea/modules/assetfs"
+)
+
+//go:embed bindata.dat
+var bindata []byte
+
+var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer {
+	return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata))
+})
diff --git a/modules/templates/dynamic.go b/modules/templates/templates_dynamic.go
similarity index 100%
rename from modules/templates/dynamic.go
rename to modules/templates/templates_dynamic.go
diff --git a/modules/timeutil/executable.go b/modules/timeutil/executable.go
deleted file mode 100644
index 57ae8b2a9d..0000000000
--- a/modules/timeutil/executable.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2022 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package timeutil
-
-import (
-	"os"
-	"path/filepath"
-	"sync"
-	"time"
-
-	"code.gitea.io/gitea/modules/log"
-)
-
-var (
-	executablModTime     = time.Now()
-	executablModTimeOnce sync.Once
-)
-
-// GetExecutableModTime get executable file modified time of current process.
-func GetExecutableModTime() time.Time {
-	executablModTimeOnce.Do(func() {
-		exePath, err := os.Executable()
-		if err != nil {
-			log.Error("os.Executable: %v", err)
-			return
-		}
-
-		exePath, err = filepath.Abs(exePath)
-		if err != nil {
-			log.Error("filepath.Abs: %v", err)
-			return
-		}
-
-		exePath, err = filepath.EvalSymlinks(exePath)
-		if err != nil {
-			log.Error("filepath.EvalSymlinks: %v", err)
-			return
-		}
-
-		st, err := os.Stat(exePath)
-		if err != nil {
-			log.Error("os.Stat: %v", err)
-			return
-		}
-
-		executablModTime = st.ModTime()
-	})
-	return executablModTime
-}
diff --git a/modules/zstd/zstd_test.go b/modules/zstd/zstd_test.go
index c3ca8e78f7..7fd30484ca 100644
--- a/modules/zstd/zstd_test.go
+++ b/modules/zstd/zstd_test.go
@@ -16,7 +16,7 @@ import (
 )
 
 func TestWriterReader(t *testing.T) {
-	testData := prepareTestData(t, 20_000_000)
+	testData := prepareTestData(t, 1_000_000)
 
 	result := bytes.NewBuffer(nil)
 
@@ -64,7 +64,7 @@ func TestWriterReader(t *testing.T) {
 }
 
 func TestSeekableWriterReader(t *testing.T) {
-	testData := prepareTestData(t, 20_000_000)
+	testData := prepareTestData(t, 2_000_000)
 
 	result := bytes.NewBuffer(nil)
 
@@ -109,7 +109,7 @@ func TestSeekableWriterReader(t *testing.T) {
 		reader, err := NewSeekableReader(assertReader)
 		require.NoError(t, err)
 
-		_, err = reader.Seek(10_000_000, io.SeekStart)
+		_, err = reader.Seek(1_000_000, io.SeekStart)
 		require.NoError(t, err)
 
 		data := make([]byte, 1000)
@@ -117,7 +117,7 @@ func TestSeekableWriterReader(t *testing.T) {
 		require.NoError(t, err)
 		require.NoError(t, reader.Close())
 
-		assert.Equal(t, testData[10_000_000:10_000_000+1000], data)
+		assert.Equal(t, testData[1_000_000:1_000_000+1000], data)
 
 		// Should seek 3 times,
 		// the first two times are for getting the index,