diff --git a/.github/workflows/cli-go-ci.yml b/.github/workflows/cli-go-ci.yml index a7c311eeb1..8e62d6afb1 100644 --- a/.github/workflows/cli-go-ci.yml +++ b/.github/workflows/cli-go-ci.yml @@ -35,6 +35,19 @@ jobs: go tool gotestsum -- -race -v -count=1 ./... \ -coverpkg="./cmd/...,./internal/...,${pkgs}" -coverprofile=coverage.out + # internal/start (docker-compose/v2, buildx, moby/buildkit, k8s client-go, + # aws-sdk-go-v2, notary, secret-detector) was deleted outright as + # unreachable (CLI-1966) -- this guards against silently reintroducing + # that dependency tree via some other package, since nothing else checks + # the shipped binary's size on every change. + - name: Verify the heavy orchestration dependency tree stays out of the module + run: | + set -euo pipefail + go list -deps . > /tmp/deps.txt + ! grep -Eq \ + 'docker/compose|docker/buildx|moby/buildkit|k8s\.io/client-go|aws-sdk-go-v2' \ + /tmp/deps.txt + - name: Check existing coverage cache id: coverage-cache uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 @@ -65,7 +78,7 @@ jobs: - name: Move coverage report run: cp apps/cli-go/coverage.out coverage.out working-directory: . - - uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7 + - uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2.3.8 with: file: coverage.out format: golang @@ -93,30 +106,6 @@ jobs: only-new-issues: true working-directory: apps/cli-go - start: - name: Start - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 - with: - go-version-file: apps/cli-go/go.mod - cache: true - - run: go build main.go - - run: ./main init - - run: sed -i '/\[db.pooler\]/{n;s/.*/enabled = true/}' supabase/config.toml - - run: ./main start --workdir tests - env: - SUPABASE_INTERNAL_IMAGE_REGISTRY: ghcr.io - - name: Install websocat - run: | - sudo wget -qO /usr/local/bin/websocat https://github.com/vi/websocat/releases/latest/download/websocat.x86_64-unknown-linux-musl - sudo chmod a+x /usr/local/bin/websocat - websocat --version - - run: ./e2e-test.sh ./main - link: name: Link if: ${{ github.event_name == 'merge_group' || (github.event_name == diff --git a/.github/workflows/cli-go-codeql.yml b/.github/workflows/cli-go-codeql.yml index cf4efe76f6..03b4de7418 100644 --- a/.github/workflows/cli-go-codeql.yml +++ b/.github/workflows/cli-go-codeql.yml @@ -67,7 +67,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -95,7 +95,7 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4 with: category: "/language:${{matrix.language}}" defaults: diff --git a/.github/workflows/cli-go-mirror-image.yml b/.github/workflows/cli-go-mirror-image.yml index bc65b14e10..7b68776173 100644 --- a/.github/workflows/cli-go-mirror-image.yml +++ b/.github/workflows/cli-go-mirror-image.yml @@ -38,10 +38,10 @@ jobs: with: role-to-assume: ${{ secrets.PROD_AWS_ROLE }} aws-region: us-east-1 - - uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1 + - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: public.ecr.aws - - uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1 + - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/cli-go-mirror.yml b/.github/workflows/cli-go-mirror.yml index cb302c411f..bba031acf3 100644 --- a/.github/workflows/cli-go-mirror.yml +++ b/.github/workflows/cli-go-mirror.yml @@ -10,8 +10,9 @@ on: # This workflow is the manual/bulk entry point for re-mirroring everything. # Template image bumps are mirrored automatically by mirror-template-images.yml # on push to develop, which backfills any unmirrored tag when the templates - # Dockerfile changes — so develop and PRs rebased on it stop inheriting the - # `manifest unknown` failure in the ghcr.io-pinned `Start` check. + # Dockerfile changes — so anyone pinning SUPABASE_INTERNAL_IMAGE_REGISTRY=ghcr.io + # doesn't inherit a `manifest unknown` failure. (No CI job pins that registry + # anymore -- see mirror-template-images.yml's own comment for why, CLI-1966.) workflow_dispatch: permissions: contents: read diff --git a/.github/workflows/cli-go-pg-prove.yml b/.github/workflows/cli-go-pg-prove.yml index 8de8e60958..530b74de8a 100644 --- a/.github/workflows/cli-go-pg-prove.yml +++ b/.github/workflows/cli-go-pg-prove.yml @@ -45,7 +45,7 @@ jobs: - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 with: endpoint: builders - - uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1 + - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} @@ -67,7 +67,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1 + - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} diff --git a/.github/workflows/cli-go-publish-migra.yml b/.github/workflows/cli-go-publish-migra.yml index 48f5827f07..22ab8a9465 100644 --- a/.github/workflows/cli-go-publish-migra.yml +++ b/.github/workflows/cli-go-publish-migra.yml @@ -45,7 +45,7 @@ jobs: - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 with: endpoint: builders - - uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1 + - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} @@ -67,7 +67,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1 + - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} diff --git a/.github/workflows/mirror-template-images.yml b/.github/workflows/mirror-template-images.yml index dfb589f744..7a8ce0322e 100644 --- a/.github/workflows/mirror-template-images.yml +++ b/.github/workflows/mirror-template-images.yml @@ -8,11 +8,14 @@ name: Mirror template images # # It runs on `push` to develop (not on the PR) on purpose: mirroring needs the # AWS role + packages:write, which a dependabot-triggered `pull_request` run -# cannot be granted, and we deliberately avoid `pull_request_target`. The CI -# `Start` job pins SUPABASE_INTERNAL_IMAGE_REGISTRY=ghcr.io, so it only goes -# green once a bumped tag is mirrored here; this backfill runs as soon as the -# bump lands on develop, repopulating ghcr.io/ECR so develop and any PR rebased -# on it pass `Start` instead of inheriting a `manifest unknown` failure. +# cannot be granted, and we deliberately avoid `pull_request_target`. This +# backfill runs as soon as the bump lands on develop, repopulating ghcr.io/ECR +# so anyone pinning SUPABASE_INTERNAL_IMAGE_REGISTRY=ghcr.io doesn't inherit a +# `manifest unknown` failure. (No CI job pins that registry anymore -- the +# `cli-go-ci.yml` `Start` job that used to made it CI-observable was removed in +# CLI-1966 along with `internal/start`; this mirror now only serves users who +# opt into the mirror directly, and a mirroring failure no longer turns any +# check red.) on: push: @@ -50,7 +53,7 @@ jobs: dependency-firewall-token: ${{ secrets.DF_FIREWALL_TOKEN }} - name: Log in to ghcr.io - uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/release-shared.yml b/.github/workflows/release-shared.yml index cd20b3068b..b0fd987a53 100644 --- a/.github/workflows/release-shared.yml +++ b/.github/workflows/release-shared.yml @@ -426,7 +426,7 @@ jobs: - name: Sync stable release to Linear if: ${{ inputs.channel == 'stable' && env.LINEAR_CLI_STABLE_RELEASE_ACCESS_KEY != '' }} - uses: linear/linear-release-action@3858a5d7892435dc63302ac76b0cdb587435caa9 # v0 + uses: linear/linear-release-action@af56a9a388625921f3757a2f988e4d7aca958377 # v0 with: access_key: ${{ env.LINEAR_CLI_STABLE_RELEASE_ACCESS_KEY }} version: v${{ inputs.version }} @@ -437,7 +437,7 @@ jobs: - name: Sync beta release to Linear if: ${{ inputs.channel == 'beta' && env.LINEAR_CLI_BETA_RELEASE_ACCESS_KEY != '' }} - uses: linear/linear-release-action@3858a5d7892435dc63302ac76b0cdb587435caa9 # v0 + uses: linear/linear-release-action@af56a9a388625921f3757a2f988e4d7aca958377 # v0 with: access_key: ${{ env.LINEAR_CLI_BETA_RELEASE_ACCESS_KEY }} version: v${{ inputs.version }} diff --git a/.gitignore b/.gitignore index f743e832df..9a22f50fc3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules dist coverage/ +.DS_Store .env .env.* !.env.example @@ -22,4 +23,4 @@ packages/cli-*/bin/ # Nx .nx/cache -.nx/workspace-data \ No newline at end of file +.nx/workspace-data diff --git a/apps/cli-e2e/fixtures/scenarios/branches-list-returns-json-output-with-output-json/interactions.json b/apps/cli-e2e/fixtures/scenarios/branches-list-returns-json-output-with-output-json/interactions.json index d5945840c2..7473a87935 100644 --- a/apps/cli-e2e/fixtures/scenarios/branches-list-returns-json-output-with-output-json/interactions.json +++ b/apps/cli-e2e/fixtures/scenarios/branches-list-returns-json-output-with-output-json/interactions.json @@ -23,7 +23,7 @@ }, "body": [ { - "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", + "id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee", "name": "test-branch", "project_ref": "branchrefaaaaaaaaa", "parent_project_ref": "__PROJECT_REF__", diff --git a/apps/cli-e2e/src/tests/live/db-reset-start.live.e2e.test.ts b/apps/cli-e2e/src/tests/live/db-reset-start.live.e2e.test.ts index 9c2ec6f8e7..278b984341 100644 --- a/apps/cli-e2e/src/tests/live/db-reset-start.live.e2e.test.ts +++ b/apps/cli-e2e/src/tests/live/db-reset-start.live.e2e.test.ts @@ -13,9 +13,14 @@ import { testLive } from "./live-context.ts"; // destructive remote reset below is safe against the throwaway per-run project. // --- Local leg: db start + db reset --local against the real Docker socket ----- -// Exercises the hidden `db __db-bootstrap` Go seam end-to-end — the boundary the -// in-process integration suites mock. The start → already-running → reset cycle -// runs in one test so it shares a single booted stack, and `finally` stops it +// Exercises `db start`'s native container-bootstrap sequence (network/volume/container +// bring-up, health wait, the fresh-volume SetupLocalDatabase-equivalent pipeline, and +// `_current_branch`) and `db reset --local`'s container-recreate flow end-to-end — the +// real-Docker boundary the in-process integration suites mock. `db reset --local` still +// delegates its container-recreate flow to the bundled Go binary's hidden +// `db __db-bootstrap --mode recreate` seam (CLI-1955, unclaimed as of CLI-1954); `db start` +// no longer does (see `commands/db/start/start.handler.ts`). The start → already-running → +// reset cycle runs in one test so it shares a single booted stack, and `finally` stops it // (legacy proxies `stop` to Go) so the run never leaves containers behind. describe.skipIf(TARGET === "ts-next")("db start / db reset --local (live, local Docker)", () => { testLive( @@ -25,7 +30,7 @@ describe.skipIf(TARGET === "ts-next")("db start / db reset --local (live, local try { const start = await run(["db", "start"]); expect(start.exitCode, start.stderr).toBe(0); - // Go tees bootstrap progress to stderr (mode-independent). + // Bootstrap progress goes to stderr on every target (Go, and native TS since CLI-1954). expect(`${start.stdout}${start.stderr}`).toMatch(/Starting database|Initialising schema/i); // Second start is a no-op: the db is already running, exit 0. diff --git a/apps/cli-e2e/src/tests/stack.e2e.test.ts b/apps/cli-e2e/src/tests/stack.e2e.test.ts index f86a1e4747..1f47cd0f80 100644 --- a/apps/cli-e2e/src/tests/stack.e2e.test.ts +++ b/apps/cli-e2e/src/tests/stack.e2e.test.ts @@ -142,7 +142,13 @@ describe("start", () => { test.todo("start → status → stop lifecycle"); test.todo("starts with --exclude studio and stops cleanly"); - test.todo("parity: start"); + // Unlike `status`/`stop` above, there is no `testParityStack(["start"])` here, + // and there never will be: Go's `internal/start` was deleted outright as + // unreachable (CLI-1966), so `supabase-go start` is now a permanent stub that + // always fails with a fixed error -- there is no real Go implementation left to + // diff TS's behavior against. Go-parity coverage for `start` instead lives in + // `apps/cli/src/legacy/commands/start/start.live.test.ts` and its siblings, + // asserted against the pre-deletion Go behavior documented in `SIDE_EFFECTS.md`. }); // --------------------------------------------------------------------------- diff --git a/apps/cli-go/.gitignore b/apps/cli-go/.gitignore index 085699240e..32520228b6 100644 --- a/apps/cli-go/.gitignore +++ b/apps/cli-go/.gitignore @@ -9,6 +9,7 @@ *.so *.dylib /cli +/main /supabase-go # Test binary, built with `go test -c` diff --git a/apps/cli-go/cmd/db.go b/apps/cli-go/cmd/db.go index 66df4311cc..f4c80517b1 100644 --- a/apps/cli-go/cmd/db.go +++ b/apps/cli-go/cmd/db.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "errors" "fmt" "os" @@ -271,24 +270,29 @@ var ( }, } - bootstrapMode string - bootstrapSqlPaths []string - bootstrapFromBackup string - bootstrapVersion string - bootstrapNoSeed bool - - // dbBootstrapCmd is a hidden seam used by the native-TypeScript `db start` and - // `db reset --local` commands to drive the container-bootstrap primitives that - // are not yet ported to TypeScript: creating/recreating the local Postgres - // container, applying the initial schema, and the storage health gate. The TS - // caller orchestrates everything else (the "already running?" check and its - // message, version/last resolution, bucket seeding, the git-branch "Finished…" - // line, telemetry, and --output-format shaping); the seam stays in Go only for - // the Docker lifecycle. It mirrors the existing db __shadow seam: it carries no + bootstrapMode string + bootstrapSqlPaths []string + bootstrapVersion string + bootstrapNoSeed bool + + // dbBootstrapCmd is a hidden seam used by the native-TypeScript `db reset --local` + // command to drive the container-bootstrap primitives that are not yet ported to + // TypeScript: recreating the local Postgres container, applying the initial + // schema, and the storage health gate. The TS caller orchestrates everything else + // (version/last resolution, bucket seeding, the git-branch "Finished…" line, + // telemetry, and --output-format shaping); the seam stays in Go only for the + // Docker lifecycle. It mirrors the existing db __shadow seam: it carries no // db-url/local/linked target flags, so it loads supabase/config.toml explicitly // (the root PersistentPreRunE only loads it when a target flag is set). Progress // goes to stderr; the only stdout output is a single machine-parseable marker - // for --mode await-storage ("ready" or "absent"). + // for --mode await-storage ("ready" or "absent"). `db start`'s own container + // bootstrap (--mode start) was removed from this seam by CLI-1954 — it is now a + // fully native TypeScript implementation + // (apps/cli/src/legacy/commands/db/start/start.handler.ts), reusing + // legacy/shared/db-bootstrap/'s already-ported container-bootstrap primitives + // instead of shelling out to this binary. `start.StartDatabase` itself (called + // below by the real, customer-facing `db start` Go command) is untouched — it + // remains the parity oracle this TS port was checked against. dbBootstrapCmd = &cobra.Command{ Use: "__db-bootstrap", Hidden: true, @@ -299,16 +303,6 @@ var ( return err } switch bootstrapMode { - case "start": - // Mirror start.Run minus the "already running?" check, which the TS - // caller performs (and prints "Postgres database is already running."). - if err := start.StartDatabase(cmd.Context(), bootstrapFromBackup, fsys, os.Stderr); err != nil { - if rmErr := utils.DockerRemoveAll(context.Background(), os.Stderr, utils.Config.ProjectId); rmErr != nil { - fmt.Fprintln(os.Stderr, rmErr) - } - return err - } - return nil case "recreate": // The PG14/PG15 container-recreate half of local db reset. The TS // caller has already printed "Resetting local database…" and validated @@ -688,8 +682,7 @@ func init() { dbCmd.AddCommand(dbShadowCmd) // Build hidden container-bootstrap seam command (native db start / db reset) bootstrapFlags := dbBootstrapCmd.Flags() - bootstrapFlags.StringVar(&bootstrapMode, "mode", "start", "Bootstrap mode: start, recreate, or await-storage.") - bootstrapFlags.StringVar(&bootstrapFromBackup, "from-backup", "", "Path to a logical backup file (start mode).") + bootstrapFlags.StringVar(&bootstrapMode, "mode", "recreate", "Bootstrap mode: recreate or await-storage.") bootstrapFlags.StringVar(&bootstrapVersion, "version", "", "Reset up to the specified version (recreate mode).") bootstrapFlags.BoolVar(&bootstrapNoSeed, "no-seed", false, "Skip the seed script after recreate (recreate mode).") bootstrapFlags.StringArrayVar(&bootstrapSqlPaths, "sql-paths", nil, "Override [db.seed].sql_paths for the recreate (recreate mode).") diff --git a/apps/cli-go/cmd/start.go b/apps/cli-go/cmd/start.go index bd1cc1f8ab..2ca8560b45 100644 --- a/apps/cli-go/cmd/start.go +++ b/apps/cli-go/cmd/start.go @@ -1,63 +1,70 @@ package cmd +// internal/start (Go's own `supabase start` implementation) was deleted +// outright (CLI-1966): it is unreachable from the TypeScript CLI, which +// talks to Docker directly for `start` and never delegates to this binary +// for it, and no other still-live TS->Go delegation seam (db test, db +// branch/remote, db diff --use-pgadmin/--use-pg-schema, db pull +// --experimental, the hidden db __db-bootstrap/__shadow/__catalog seams, +// etc.) ever called into internal/start either -- see +// apps/cli/docs/binary-distribution.md § Removed commands for the full +// rationale. This command's registration and flags are kept only so this +// binary's cobra tree / `--help` / `__complete` output stays stable for +// anyone invoking supabase-go directly; RunE is a permanent stub. There is +// no `--exclude` validation here anymore (that lived in the now-deleted +// internal/start.validateExcludedContainers) -- the TS port owns that +// warning now (`legacy/commands/start/start.exclude.ts`). +// +// TODO(CLI-1965): once shell completion is ported to TypeScript and no +// longer needs the `__complete` passthrough into this binary, delete this +// file (and the `startCmd` registration) entirely. + import ( + "errors" "fmt" - "os" - "slices" - "sort" "strings" - "github.com/spf13/afero" "github.com/spf13/cobra" - "github.com/supabase/cli/internal/start" "github.com/supabase/cli/internal/utils" + "github.com/supabase/cli/pkg/config" ) -func validateExcludedContainers(excludedContainers []string) { - // Validate excluded containers - validContainers := start.ExcludableContainers() - var invalidContainers []string - - for _, e := range excludedContainers { - if !slices.Contains(validContainers, e) { - invalidContainers = append(invalidContainers, e) - } - } - - if len(invalidContainers) > 0 { - // Sort the names list so it's easier to visually spot the one you looking for - sort.Strings(validContainers) - warning := fmt.Sprintf("%s The following container names are not valid to exclude: %s\nValid containers to exclude are: %s\n", - utils.Yellow("WARNING:"), - utils.Aqua(strings.Join(invalidContainers, ", ")), - utils.Aqua(strings.Join(validContainers, ", "))) - fmt.Fprint(os.Stderr, warning) +// excludableContainers lists the container names valid for the --exclude +// flag, matching the removed internal/start.ExcludableContainers so the +// flag's help text is unaffected by the deletion. +func excludableContainers() []string { + names := []string{} + for _, image := range config.Images.Services() { + names = append(names, utils.ShortContainerImageName(image)) } + return names } -var ( - allowedContainers = start.ExcludableContainers() - excludedContainers []string - ignoreHealthCheck bool - preview bool - - startCmd = &cobra.Command{ - GroupID: groupLocalDev, - Use: "start", - Short: "Start containers for Supabase local development", - RunE: func(cmd *cobra.Command, args []string) error { - validateExcludedContainers(excludedContainers) - return start.Run(cmd.Context(), afero.NewOsFs(), excludedContainers, ignoreHealthCheck) - }, - } -) +// startCmd's flags are declared without bound vars (StringSliceP/Bool, not +// StringSliceVarP/BoolVar): RunE never reads a real value for any of them -- +// it always fails -- so a bound var would just be a write-only sink left +// over from the deleted internal/start implementation that used to read +// them. The flags still parse and appear in --help/__complete identically. +var startCmd = &cobra.Command{ + GroupID: groupLocalDev, + Use: "start", + Short: "Start containers for Supabase local development", + // The error text is asserted verbatim by TestStartIsUnavailable + // (start_test.go) -- update both together. + RunE: func(cmd *cobra.Command, args []string) error { + // Suppress root's default "--debug to troubleshoot" suggestion: + // this always fails, so --debug can't help. + utils.CmdSuggestion = fmt.Sprintf("Run %s from the Supabase CLI instead of invoking this binary directly.", utils.Aqua("supabase start")) + return errors.New("start is not available in supabase-go; the Supabase CLI's start command talks to Docker directly and does not use this binary") + }, +} func init() { flags := startCmd.Flags() - names := strings.Join(allowedContainers, ",") - flags.StringSliceVarP(&excludedContainers, "exclude", "x", []string{}, "Names of containers to not start. ["+names+"]") - flags.BoolVar(&ignoreHealthCheck, "ignore-health-check", false, "Ignore unhealthy services and exit 0") - flags.BoolVar(&preview, "preview", false, "Connect to feature preview branch") + names := strings.Join(excludableContainers(), ",") + flags.StringSliceP("exclude", "x", nil, "Names of containers to not start. ["+names+"]") + flags.Bool("ignore-health-check", false, "Ignore unhealthy services and exit 0") + flags.Bool("preview", false, "Connect to feature preview branch") cobra.CheckErr(flags.MarkHidden("preview")) rootCmd.AddCommand(startCmd) } diff --git a/apps/cli-go/cmd/start_test.go b/apps/cli-go/cmd/start_test.go new file mode 100644 index 0000000000..d95095612a --- /dev/null +++ b/apps/cli-go/cmd/start_test.go @@ -0,0 +1,48 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/supabase/cli/internal/utils" +) + +// internal/start was deleted outright (CLI-1966): the previous full/bundled +// build split relied on `cli-go-ci.yml`'s "Start" job to verify this error +// text -- and the command/flag/`__complete` surface below -- against a real +// binary. That job is gone along with the split, so this test is now the +// only thing pinning the stub's exact behavior. +func TestStartIsUnavailable(t *testing.T) { + // utils.CmdSuggestion is a shared package global other tests in this + // package also mutate (see TestEnsureLocalPostgresImageCurrent) -- reset + // and restore it so this test neither depends on run order nor leaks its + // suggestion into whatever runs after it. + original := utils.CmdSuggestion + t.Cleanup(func() { utils.CmdSuggestion = original }) + utils.CmdSuggestion = "" + + err := startCmd.RunE(startCmd, nil) + + require.Error(t, err) + assert.EqualError(t, err, "start is not available in supabase-go; the Supabase CLI's start command talks to Docker directly and does not use this binary") + assert.Contains(t, utils.CmdSuggestion, "supabase start") +} + +// Pins the cobra registration/flag surface cmd/start.go keeps around solely +// for --help/__complete parity now that RunE never reads any of these flags. +func TestStartCommandSurface(t *testing.T) { + require.Same(t, rootCmd, startCmd.Parent()) + + excludeFlag := startCmd.Flags().Lookup("exclude") + require.NotNil(t, excludeFlag) + assert.False(t, excludeFlag.Hidden) + + ignoreHealthCheckFlag := startCmd.Flags().Lookup("ignore-health-check") + require.NotNil(t, ignoreHealthCheckFlag) + assert.False(t, ignoreHealthCheckFlag.Hidden) + + previewFlag := startCmd.Flags().Lookup("preview") + require.NotNil(t, previewFlag) + assert.True(t, previewFlag.Hidden) +} diff --git a/apps/cli-go/e2e-test.sh b/apps/cli-go/e2e-test.sh deleted file mode 100755 index 80254f1be7..0000000000 --- a/apps/cli-go/e2e-test.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -eou pipefail - -dotenv=$("${1:-supabase}" --workdir tests status -o env) -export $(echo "$dotenv" | xargs) - -for tc in ./tests/*.sh; do - echo "Running $tc" >&2 - exec "$tc" & -done - -wait -status="$?" - -echo "All tests have completed." >&2 -exit "$status" diff --git a/apps/cli-go/go.mod b/apps/cli-go/go.mod index 3e91d38a67..ecc302ebf5 100644 --- a/apps/cli-go/go.mod +++ b/apps/cli-go/go.mod @@ -15,14 +15,13 @@ require ( github.com/containerd/errdefs v1.0.0 github.com/containers/common v0.64.2 github.com/docker/cli v28.5.2+incompatible - github.com/docker/compose/v2 v2.40.3 github.com/docker/docker v28.5.2+incompatible - github.com/docker/go-connections v0.7.0 + github.com/docker/go-connections v0.8.1 github.com/docker/go-units v0.5.0 github.com/fsnotify/fsnotify v1.10.1 github.com/getsentry/sentry-go v0.48.0 github.com/go-errors/errors v1.5.1 - github.com/go-git/go-git/v5 v5.19.1 + github.com/go-git/go-git/v5 v5.19.2 github.com/go-playground/validator/v10 v10.30.3 github.com/go-viper/mapstructure/v2 v2.5.0 github.com/go-xmlfmt/xmlfmt v1.1.3 @@ -48,7 +47,7 @@ require ( github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 - github.com/stripe/pg-schema-diff v1.0.7 + github.com/stripe/pg-schema-diff v1.0.8 github.com/supabase/cli/pkg v1.0.0 github.com/tidwall/jsonc v0.3.3 github.com/withfig/autocomplete-tools/packages/cobra v1.2.0 @@ -58,7 +57,7 @@ require ( golang.org/x/net v0.57.0 golang.org/x/oauth2 v0.36.0 golang.org/x/term v0.45.0 - google.golang.org/grpc v1.82.1 + google.golang.org/grpc v1.83.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -80,14 +79,12 @@ require ( github.com/Antonboom/testifylint v1.6.4 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/ClickHouse/clickhouse-go-linter v1.2.0 // indirect - github.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e // indirect github.com/Djarvur/go-err113 v0.1.1 // indirect github.com/Masterminds/semver/v3 v3.5.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/MirrexOne/unqueryvet v1.5.4 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/alecthomas/chroma/v2 v2.24.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect @@ -96,24 +93,9 @@ require ( github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect - github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/ashanbrown/forbidigo/v2 v2.3.1 // indirect github.com/ashanbrown/makezero/v2 v2.2.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect - github.com/aws/aws-sdk-go-v2/config v1.32.7 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.19.7 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect - github.com/aws/smithy-go v1.24.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -124,7 +106,6 @@ require ( github.com/bombsimon/wsl/v5 v5.8.0 // indirect github.com/breml/bidichk v0.3.3 // indirect github.com/breml/errchkjson v0.4.1 // indirect - github.com/buger/goterm v1.0.4 // indirect github.com/butuzov/ireturn v0.4.1 // indirect github.com/butuzov/mirror v1.3.0 // indirect github.com/catenacyber/perfsprint v0.10.1 // indirect @@ -145,16 +126,9 @@ require ( github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/cloudflare/circl v1.6.3 // indirect - github.com/containerd/console v1.0.5 // indirect - github.com/containerd/containerd/api v1.10.0 // indirect - github.com/containerd/containerd/v2 v2.2.5 // indirect - github.com/containerd/continuity v0.4.5 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v1.0.0-rc.2 // indirect - github.com/containerd/ttrpc v1.2.7 // indirect - github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/containers/storage v1.59.1 // indirect + github.com/creack/pty v1.1.24 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect github.com/cyphar/filepath-securejoin v0.6.1 // indirect github.com/daixiang0/gci v0.13.7 // indirect @@ -166,16 +140,10 @@ require ( github.com/distribution/reference v0.6.0 // indirect github.com/dlclark/regexp2 v1.12.0 // indirect github.com/dnephin/pflag v1.0.7 // indirect - github.com/docker/buildx v0.29.1 // indirect - github.com/docker/cli-docs-tool v0.10.0 // indirect - github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.5 // indirect - github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect github.com/ecies/go/v2 v2.0.11 // indirect - github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 // indirect - github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/ethereum/go-ethereum v1.17.0 // indirect @@ -184,9 +152,7 @@ require ( github.com/fatih/structtag v1.2.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/firefart/nonamedreturns v1.0.6 // indirect - github.com/fsnotify/fsevents v0.2.0 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect - github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/getkin/kin-openapi v0.136.0 // indirect @@ -197,22 +163,9 @@ require ( github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.22.4 // indirect - github.com/go-openapi/jsonreference v0.21.4 // indirect - github.com/go-openapi/swag v0.25.4 // indirect - github.com/go-openapi/swag/cmdutils v0.25.4 // indirect - github.com/go-openapi/swag/conv v0.25.4 // indirect - github.com/go-openapi/swag/fileutils v0.25.4 // indirect github.com/go-openapi/swag/jsonname v0.25.4 // indirect - github.com/go-openapi/swag/jsonutils v0.25.4 // indirect - github.com/go-openapi/swag/loading v0.25.4 // indirect - github.com/go-openapi/swag/mangling v0.25.4 // indirect - github.com/go-openapi/swag/netutils v0.25.4 // indirect - github.com/go-openapi/swag/stringutils v0.25.4 // indirect - github.com/go-openapi/swag/typeutils v0.25.4 // indirect - github.com/go-openapi/swag/yamlutils v0.25.4 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-sql-driver/mysql v1.9.3 // indirect github.com/go-test/deep v1.1.1 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect @@ -226,9 +179,7 @@ require ( github.com/godbus/dbus/v5 v5.2.2 // indirect github.com/godoc-lint/godoc-lint v0.11.2 // indirect github.com/gofrs/flock v0.13.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20260401084720-c99c5cf5c202 // indirect github.com/golangci/go-printf-func-name v0.1.1 // indirect @@ -241,31 +192,21 @@ require ( github.com/golangci/rowserrcheck v0.0.0-20260419091836-c5f79b8a11ba // indirect github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect - github.com/google/certificate-transparency-go v1.3.2 // indirect - github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/gorilla/css v1.0.1 // indirect - github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect github.com/gostaticanalysis/nilerr v0.1.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-version v1.9.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/in-toto/attestation v1.1.2 // indirect - github.com/in-toto/in-toto-golang v0.11.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 // indirect @@ -275,9 +216,7 @@ require ( github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jgautheron/goconst v1.10.0 // indirect github.com/jjti/go-spancheck v0.6.5 // indirect - github.com/jonboulle/clockwork v0.5.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/julz/importas v0.2.0 // indirect github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect @@ -314,30 +253,16 @@ require ( github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mgechev/revive v1.15.0 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect - github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/mithrandie/csvq v1.18.1 // indirect github.com/mithrandie/go-file/v2 v2.1.0 // indirect github.com/mithrandie/go-text v1.6.0 // indirect github.com/mithrandie/ternary v1.1.1 // indirect - github.com/moby/buildkit v0.26.3 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/go-archive v0.1.0 // indirect - github.com/moby/locker v1.0.1 // indirect - github.com/moby/patternmatcher v0.6.1 // indirect - github.com/moby/spdystream v0.5.1 // indirect github.com/moby/sys/atomicwriter v0.1.0 // indirect - github.com/moby/sys/capability v0.4.0 // indirect - github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/sequential v0.6.0 // indirect - github.com/moby/sys/signal v0.7.1 // indirect - github.com/moby/sys/symlink v0.3.0 // indirect - github.com/moby/sys/user v0.4.0 // indirect - github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.2 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/moricho/tparallel v0.3.2 // indirect github.com/morikuni/aec v1.1.0 // indirect @@ -345,7 +270,6 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect @@ -359,12 +283,11 @@ require ( github.com/olekukonko/ll v0.1.6 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect + github.com/otiai10/copy v1.14.1 // indirect github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pjbgf/sha1cd v0.6.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect @@ -387,15 +310,11 @@ require ( github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect - github.com/secure-systems-lab/go-securesystemslib v0.10.0 // indirect github.com/securego/gosec/v2 v2.26.1 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b // indirect - github.com/shibumi/go-pathspec v1.3.0 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect - github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/sonatard/noctx v0.5.1 // indirect github.com/sourcegraph/go-diff v0.8.0 // indirect github.com/speakeasy-api/jsonpath v0.6.3 // indirect @@ -407,23 +326,16 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect github.com/tetafro/godot v1.5.6 // indirect github.com/theupdateframework/notary v0.7.0 // indirect - github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 // indirect github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4 // indirect github.com/timonwong/loggercheck v0.11.0 // indirect github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect - github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect - github.com/tonistiigi/fsutil v0.0.0-20251211185533-a2aa163d723f // indirect - github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect - github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect - github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.1 // indirect github.com/uudashr/iface v1.4.2 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.4.0 // indirect - github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -436,18 +348,14 @@ require ( github.com/ykadowak/zerologlint v0.1.5 // indirect github.com/yuin/goldmark v1.7.13 // indirect github.com/yuin/goldmark-emoji v1.0.6 // indirect - github.com/zclconf/go-cty v1.17.0 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.14.0 // indirect go-simpler.org/sloglint v0.12.0 // indirect go.augendre.info/arangolint v0.4.0 // indirect go.augendre.info/fatcontext v0.9.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.39.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect @@ -465,30 +373,15 @@ require ( golang.org/x/sync v0.22.0 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/text v0.40.0 // indirect - golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.47.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gotest.tools/gotestsum v1.12.2 // indirect honnef.co/go/tools v0.7.0 // indirect - k8s.io/api v0.34.1 // indirect - k8s.io/apimachinery v0.34.1 // indirect - k8s.io/client-go v0.34.1 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect mvdan.cc/gofumpt v0.9.2 // indirect mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect - sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect - sigs.k8s.io/yaml v1.6.0 // indirect - tags.cncf.io/container-device-interface v1.1.0 // indirect ) replace github.com/supabase/cli/pkg v1.0.0 => ./pkg diff --git a/apps/cli-go/go.sum b/apps/cli-go/go.sum index d3685b0515..2271dbf731 100644 --- a/apps/cli-go/go.sum +++ b/apps/cli-go/go.sum @@ -8,22 +8,16 @@ codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6M codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= codeberg.org/polyfloyd/go-errorlint v1.9.0 h1:VkdEEmA1VBpH6ecQoMR4LdphVI3fA4RrCh2an7YmodI= codeberg.org/polyfloyd/go-errorlint v1.9.0/go.mod h1:GPRRu2LzVijNn4YkrZYJfatQIdS+TrcK8rL5Xs24qw8= -cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= -cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= 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/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= -filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= -filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= 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.7/go.mod h1:K0DkBeOebJ4VyOICFdppB23Q0YMOgVafM0zYW0n9lF4= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= 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/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY= @@ -41,8 +35,6 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ClickHouse/clickhouse-go-linter v1.2.0 h1:zbm174up3hTKjp0wKZVnTzRiG7tSF5XZF0FJG/MuCBI= github.com/ClickHouse/clickhouse-go-linter v1.2.0/go.mod h1:pLorS7ffPTfuUV9M0SJgfHA/h/WQPQUk2FWG9x74cQ4= -github.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e h1:rd4bOvKmDIx0WeTv9Qz+hghsgyjikFiPrseXHlKepO0= -github.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e/go.mod h1:blbwPQh4DTlCZEfk1BLU4oMIhLda2U+A840Uag9DsZw= github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= @@ -51,8 +43,6 @@ github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lpr 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= -github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs= -github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM= github.com/MirrexOne/unqueryvet v1.5.4 h1:38QOxShO7JmMWT+eCdDMbcUgGCOeJphVkzzRgyLJgsQ= github.com/MirrexOne/unqueryvet v1.5.4/go.mod h1:fs9Zq6eh1LRIhsDIsxf9PONVUjYdFHdtkHIgZdJnyPU= github.com/Netflix/go-env v0.1.2 h1:0DRoLR9lECQ9Zqvkswuebm3jJ/2enaDX6Ei8/Z+EnK0= @@ -62,10 +52,7 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgz github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= -github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d h1:hi6J4K6DKrR4/ljxn6SF6nURyu785wKMuQcjt7H3VCQ= github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= -github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= 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/chroma/v2 v2.24.1 h1:m5ffpfZbIb++k8AqFEKy9uVgY12xIQtBsQlc6DfZJQM= @@ -86,16 +73,12 @@ github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQ github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc= -github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= github.com/andybalholm/brotli v1.2.2 h1:HzTuoo2ErYQqf5qvcJInB8uvqSVxRttzkFexPWtnceM= github.com/andybalholm/brotli v1.2.2/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 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/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= -github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= 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/ashanbrown/forbidigo/v2 v2.3.1 h1:KAZijvQ7zeIBKbhikT4jCm0TLYXC4u78bTiLh/8JROI= @@ -104,34 +87,6 @@ github.com/ashanbrown/makezero/v2 v2.2.1 h1:A7uU8dgB1PA9aelTxHMfHIQ8Qev8AB3JLxJU github.com/ashanbrown/makezero/v2 v2.2.1/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU= -github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= -github.com/aws/aws-sdk-go-v2/config v1.32.7 h1:vxUyWGUwmkQ2g19n7JY/9YL8MfAIl7bTesIUykECXmY= -github.com/aws/aws-sdk-go-v2/config v1.32.7/go.mod h1:2/Qm5vKUU/r7Y+zUk/Ptt2MDAEKAfUtKc1+3U1Mo3oY= -github.com/aws/aws-sdk-go-v2/credentials v1.19.7 h1:tHK47VqqtJxOymRrNtUXN5SP/zUTvZKeLx4tH6PGQc8= -github.com/aws/aws-sdk-go-v2/credentials v1.19.7/go.mod h1:qOZk8sPDrxhf+4Wf4oT2urYJrYt3RejHSzgAquYeppw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 h1:v6EiMvhEYBoHABfbGB4alOYmCIrcgyPPiBE1wZAEbqk= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.9/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 h1:gd84Omyu9JLriJVCbGApcLzVR3XtmC4ZDPcAI6Ftvds= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= -github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= -github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= 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/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= @@ -161,13 +116,8 @@ 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/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s= -github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY= -github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= -github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/butuzov/ireturn v0.4.1 h1:vWb3NO4t77iku/sjCQ/2pHTQeOmxEhjIriJqRLg1Y+I= github.com/butuzov/ireturn v0.4.1/go.mod h1:q+DXKzTDV5guNuXLnIab9fKXizTn2miZHLhxH7V/GB4= @@ -222,47 +172,19 @@ github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSE 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/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= -github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= github.com/compose-spec/compose-go/v2 v2.9.1 h1:8UwI+ujNU+9Ffkf/YgAm/qM9/eU7Jn8nHzWG721W4rs= github.com/compose-spec/compose-go/v2 v2.9.1/go.mod h1:Oky9AZGTRB4E+0VbTPZTUu4Kp+oEMMuwZXZtPPVT1iE= -github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8EhrHa4= -github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= -github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= -github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= -github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM= -github.com/containerd/containerd/v2 v2.2.5 h1:KTFzB02LviYmmfRmz8r9UFd+n6YlddVFK+5lbgQXUTU= -github.com/containerd/containerd/v2 v2.2.5/go.mod h1:5t2+xFv2dGd/iDYp9Z8DXB4cmWrWQi1XqxGJPS2gBzU= -github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= -github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= -github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/nydus-snapshotter v0.15.4 h1:l59kGRVMtwMLDLh322HsWhEsBCkRKMkGWYV5vBeLYCE= -github.com/containerd/nydus-snapshotter v0.15.4/go.mod h1:eRJqnxQDr48HNop15kZdLZpFF5B6vf6Q11Aq1K0E4Ms= -github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4= -github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= -github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= -github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= -github.com/containerd/stargz-snapshotter v0.17.0 h1:djNS4KU8ztFhLdEDZ1bsfzOiYuVHT6TgSU5qwRk+cNc= -github.com/containerd/stargz-snapshotter/estargz v0.17.0 h1:+TyQIsR/zSFI1Rm31EQBwpAA1ovYgIKHy7kctL3sLcE= -github.com/containerd/stargz-snapshotter/estargz v0.17.0/go.mod h1:s06tWAiJcXQo9/8AReBCIo/QxcXFZ2n4qfsRnpl71SM= -github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= -github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= -github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containers/common v0.64.2 h1:1xepE7QwQggUXxmyQ1Dbh6Cn0yd7ktk14sN3McSWf5I= github.com/containers/common v0.64.2/go.mod h1:o29GfYy4tefUuShm8mOn2AiL5Mpzdio+viHI7n24KJ4= github.com/containers/storage v1.59.1 h1:11Zu68MXsEQGBBd+GadPrHPpWeqjKS8hJDGiAHgIqDs= @@ -301,14 +223,8 @@ github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk= github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= -github.com/docker/buildx v0.29.1 h1:58hxM5Z4mnNje3G5NKfULT9xCr8ooM8XFtlfUK9bKaA= -github.com/docker/buildx v0.29.1/go.mod h1:J4EFv6oxlPiV1MjO0VyJx2u5tLM7ImDEl9zyB8d4wPI= github.com/docker/cli v28.5.2+incompatible h1:XmG99IHcBmIAoC1PPg9eLBZPlTrNUAijsHLm8PjhBlg= github.com/docker/cli v28.5.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli-docs-tool v0.10.0 h1:bOD6mKynPQgojQi3s2jgcUWGp/Ebqy1SeCr9VfKQLLU= -github.com/docker/cli-docs-tool v0.10.0/go.mod h1:5EM5zPnT2E7yCLERZmrDA234Vwn09fzRHP4aX1qwp1U= -github.com/docker/compose/v2 v2.40.3 h1:XeYkQu1svDtyfZPv5nTwFryQ25ZJMkIlc4pz9HalMPI= -github.com/docker/compose/v2 v2.40.3/go.mod h1:iNY1tvoHTyN3C3QHCuWAgj3OjR2T6mGkk/qxfbBF/4M= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -319,14 +235,13 @@ github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6 github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= -github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-connections v0.8.1 h1:JibmG5hULs5qXSr/cp/w3Pw5fZuStt4MOHMUExb29/M= +github.com/docker/go-connections v0.8.1/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= @@ -334,12 +249,8 @@ github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5ql github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= github.com/ecies/go/v2 v2.0.11 h1:xYhtMdLiqNi02oLirFmLyNbVXw6250h3WM6zJryQdiM= github.com/ecies/go/v2 v2.0.11/go.mod h1:LPRzoefP0Tam+1uesQOq3Gtb6M2OwlFUnXBTtBAKfDQ= -github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg= -github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= -github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= @@ -365,8 +276,6 @@ github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx5 github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= -github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= @@ -389,8 +298,8 @@ github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmm github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00= -github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= +github.com/go-git/go-git/v5 v5.19.2 h1:wkfn7vOlUBu8ivAWKBWisTiwJK4jYHzTF8Ndv1LyGqY= +github.com/go-git/go-git/v5 v5.19.2/go.mod h1:QqCBE1EFN5ddFmrliLQ3/ntRCUjZU3EJuwuB/jWEHjk= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -403,36 +312,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4= github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80= -github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8= -github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4= -github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= -github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= -github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= -github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= -github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4= -github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU= -github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y= -github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= -github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA= -github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM= -github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s= -github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE= -github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48= -github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= -github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0= -github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= -github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8= -github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= -github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw= -github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= -github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw= -github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc= -github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= -github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -446,8 +327,6 @@ github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6 github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -492,8 +371,6 @@ github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPh github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -538,10 +415,6 @@ github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4 github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/certificate-transparency-go v1.3.2 h1:9ahSNZF2o7SYMaKaXhAumVEzXB2QaayzII9C8rv7v+A= -github.com/google/certificate-transparency-go v1.3.2/go.mod h1:H5FpMUaGa5Ab2+KCYsxg6sELw3Flkl7pGZzWdBoYLXs= -github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= -github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -574,8 +447,6 @@ github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= -github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= @@ -594,17 +465,9 @@ github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 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-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -616,15 +479,9 @@ 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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/in-toto/attestation v1.1.2 h1:MBFn6lsMq6dptQZJBhalXTcWMb/aJy3V+GX3VYj/V1E= -github.com/in-toto/attestation v1.1.2/go.mod h1:gYFddHMZj3DiQ0b62ltNi1Vj5rC879bTmBbrv9CRHpM= -github.com/in-toto/in-toto-golang v0.11.0 h1:nfidMYBFx+E0lnmX5KUnN2Pdm8zdNKal1ayjJuzzRoA= -github.com/in-toto/in-toto-golang v0.11.0/go.mod h1:u3PjTnwFKjp5a1YCcw8SJg0G+tMeKfVoWsWeFMDCMtw= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= -github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -682,23 +539,17 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jgautheron/goconst v1.10.0 h1:Ptt+OoE4NaEWKhLrWrrN3IpZdGLiqaf7WLnEX/iv4Jw= github.com/jgautheron/goconst v1.10.0/go.mod h1:0p+wv1lFOiUr0IlNNT1nrm6+8DB8u2sU6KHGzFRXHDc= -github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= -github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 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/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= -github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -708,7 +559,6 @@ github.com/karamaru-alpha/copyloopvar v1.2.2 h1:yfNQvP9YaGQR7VaWLYcfZUlRP2eo2vhE github.com/karamaru-alpha/copyloopvar v1.2.2/go.mod h1:oY4rGZqZ879JkJMtX3RRkcXRkmUvH0x35ykgaKgsgJY= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.10.0 h1:Lvs/YAHP24YKg08LA8oDw2z9fJVme090RAXd90S+rrw= github.com/kisielk/errcheck v1.10.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -819,44 +669,18 @@ github.com/mithrandie/go-text v1.6.0 h1:8gOXTMPbMY8DJbKMTv8kHhADcJlDWXqS/YQH4SyW github.com/mithrandie/go-text v1.6.0/go.mod h1:xCgj1xiNbI/d4xA9sLVvXkjh5B2tNx2ZT2/3rpmh8to= github.com/mithrandie/ternary v1.1.1 h1:k/joD6UGVYxHixYmSR8EGgDFNONBMqyD373xT4QRdC4= github.com/mithrandie/ternary v1.1.1/go.mod h1:0D9Ba3+09K2TdSZO7/bFCC0GjSXetCvYuYq0u8FY/1g= -github.com/moby/buildkit v0.26.3 h1:D+ruZVAk/3ipRq5XRxBH9/DIFpRjSlTtMbghT5gQP9g= -github.com/moby/buildkit v0.26.3/go.mod h1:4T4wJzQS4kYWIfFRjsbJry4QoxDBjK+UGOEOs1izL7w= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= -github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= -github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= -github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y= -github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= -github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= -github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= -github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= -github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= -github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= -github.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU= -github.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0= -github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= -github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= -github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= 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= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= -github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= @@ -876,8 +700,6 @@ github.com/multigres/multigres v0.0.0-20260126223308-f5a52171bbc4/go.mod h1:UvLR github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= @@ -933,11 +755,6 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= -github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE= -github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= @@ -948,8 +765,6 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= -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/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= @@ -965,8 +780,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/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/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= @@ -1037,17 +850,11 @@ github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84d github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/secure-systems-lab/go-securesystemslib v0.10.0 h1:l+H5ErcW0PAehBNrBxoGv1jjNpGYdZ9RcheFkB2WI14= -github.com/secure-systems-lab/go-securesystemslib v0.10.0/go.mod h1:MRKONWmRoFzPNQ9USRF9i1mc7MvAVvF1LlW8X5VWDvk= github.com/securego/gosec/v2 v2.26.1 h1:gdkttGhQFVehqRJ8grKH4DrpqM/QlPKNHBnl8QgcEC4= github.com/securego/gosec/v2 v2.26.1/go.mod h1:57UW4p0uoP3kxoTkhoo3axLdVAi+OWrLg/Ax/kdqtPE= 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/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b h1:h+3JX2VoWTFuyQEo87pStk/a99dzIO1mM9KxIyLPGTU= -github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= -github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= -github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -1062,14 +869,10 @@ github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+W github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/sonatard/noctx v0.5.1 h1:wklWg9c9ZYugOAk7qG4yP4PBrlQsmSLPTvW1K4PRQMs= github.com/sonatard/noctx v0.5.1/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= github.com/sourcegraph/go-diff v0.8.0 h1:ipIyu4cTsLbIrln4l0qtHA3r0a7gyK4ntKjtQytHhvY= github.com/sourcegraph/go-diff v0.8.0/go.mod h1:hWlcO7Al+UZStZAP8rBumHpCK5ZHQ5BXsMls8p4+F5E= -github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk= -github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE= github.com/speakeasy-api/jsonpath v0.6.3 h1:c+QPwzAOdrWvzycuc9HFsIZcxKIaWcNpC+xhOW9rJxU= github.com/speakeasy-api/jsonpath v0.6.3/go.mod h1:2cXloNuQ+RSXi5HTRaeBh7JEmjRXTiaKpFTdZiL7URI= github.com/speakeasy-api/openapi v1.19.2 h1:md90tE71/M8jS3cuRlsuWP5Aed4xoG5PSRvXeZgCv/M= @@ -1113,8 +916,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/stripe/pg-schema-diff v1.0.7 h1:aVMFqjsnPSeh46hlJnexGPm28nZJUvZK0bEyk6rdFVE= -github.com/stripe/pg-schema-diff v1.0.7/go.mod h1:3IctPaAqm+0LtWw/GiwyRoRlU1/N/+00+eXVk0KZIHs= +github.com/stripe/pg-schema-diff v1.0.8 h1:37WUa2S2VqBT/xU7bDPCvA6egPn2iBTdtybqVFljl7Q= +github.com/stripe/pg-schema-diff v1.0.8/go.mod h1:3IctPaAqm+0LtWw/GiwyRoRlU1/N/+00+eXVk0KZIHs= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= @@ -1127,8 +930,6 @@ github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4D github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= github.com/tidwall/jsonc v0.3.3 h1:RVQqL3xFfDkKKXIDsrBiVQiEpBtxoKbmMXONb2H/y2w= github.com/tidwall/jsonc v0.3.3/go.mod h1:dw+3CIxqHi+t8eFSpzzMlcVYxKp08UP5CD8/uSFCyJE= -github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA= -github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g= github.com/timakin/bodyclose v0.0.0-20260129054331-73d1f95b84b4 h1:SiHe5XLTn9sFWJ5pBwJ5FN/4j34q9ZlOAD//kMoMYp0= 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= @@ -1137,16 +938,6 @@ github.com/tomarrell/wrapcheck/v2 v2.12.0 h1:H/qQ1aNWz/eeIhxKAFvkfIA+N7YDvq6TWVF github.com/tomarrell/wrapcheck/v2 v2.12.0/go.mod h1:AQhQuZd0p7b6rfW+vUwHm5OMCGgp63moQ9Qr/0BpIWo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= -github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK56l8WPequOaR3i9LBqfPtEdXIQbUTzT55iqT4= -github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY= -github.com/tonistiigi/fsutil v0.0.0-20251211185533-a2aa163d723f h1:Z4NEQ86qFl1mHuCu9gwcE+EYCwDKfXAYXZbdIXyxmEA= -github.com/tonistiigi/fsutil v0.0.0-20251211185533-a2aa163d723f/go.mod h1:BKdcez7BiVtBvIcef90ZPc6ebqIWr4JWD7+EvLm6J98= -github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 h1:2f304B10LaZdB8kkVEaoXvAMVan2tl9AiK4G0odjQtE= -github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE= -github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= -github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= -github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw= -github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= @@ -1157,16 +948,12 @@ github.com/uudashr/gocognit v1.2.1 h1:CSJynt5txTnORn/DkhiB4mZjwPuifyASC8/6Q0I/QS github.com/uudashr/gocognit v1.2.1/go.mod h1:acaubQc6xYlXFEMb9nWX2dYBzJ/bIjEkc1zzvyIZg5Q= github.com/uudashr/iface v1.4.2 h1:06Vq5RKVYThBsj0Bnw4oasMjD1r+7CE/bcKOA8dVSvg= github.com/uudashr/iface v1.4.2/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg= -github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= -github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= github.com/withfig/autocomplete-tools/packages/cobra v1.2.0 h1:MzD3XeOOSO3mAjOPpF07jFteSKZxsRHvlIcAR9RQzKM= github.com/withfig/autocomplete-tools/packages/cobra v1.2.0/go.mod h1:RoXh7+7qknOXL65uTzdzE1mPxqcPwS7FLCE9K5GfmKo= github.com/woodsbury/decimal128 v1.4.0 h1:xJATj7lLu4f2oObouMt2tgGiElE5gO6mSWUjQsBgUlc= github.com/woodsbury/decimal128 v1.4.0/go.mod h1:BP46FUrVjVhdTbKT+XuQh2xfQaGki9LMIRJSFuh6THU= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= @@ -1190,7 +977,6 @@ github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+ github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -1201,8 +987,6 @@ github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9 github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= github.com/zalando/go-keyring v0.2.8 h1:6sD/Ucpl7jNq10rM2pgqTs0sZ9V3qMrqfIIy5YPccHs= github.com/zalando/go-keyring v0.2.8/go.mod h1:tsMo+VpRq5NGyKfxoBVjCuMrG47yj8cmakZDO5QGii0= -github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0= -github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= @@ -1216,22 +1000,14 @@ go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR5 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.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 h1:RN3ifU8y4prNWeEnQp2kRRHz8UwonAEYZl8tUzHEXAk= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0/go.mod h1:habDz3tEWiFANTo6oUE99EmaFUrCNYAAg3wiVmusm70= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0 h1:2pn7OzMewmYRiNtv1doZnLo3gONcnMHlFnmOR8Vgt+8= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.63.0/go.mod h1:rjbQTDEPQymPE0YnRQp9/NuPwwtL0sesz/fnqRW/v84= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ= go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.39.0 h1:cEf8jF6WbuGQWUVcqgyWtTR0kOOAWY1DYZ+UhvdmQPw= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.39.0/go.mod h1:k1lzV5n5U3HkGvTCJHraTAGJ7MqsgL1wrGwTj1Isfiw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0 h1:RuynHbfU8JUEw7DyONgkVYg2SVtsoF28y0LGIr69jgA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0/go.mod h1:qZF+/lBs71APw8mlnEZcqZHMzqrYrsFiJOv83lX1OGo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 h1:in9O8ESIOlwJAEGTkkf34DesGRAc/Pn8qJ7k3r/42LM= @@ -1256,8 +1032,6 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= -go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -1367,7 +1141,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1375,11 +1148,9 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc 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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1417,10 +1188,8 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= @@ -1445,8 +1214,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -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.83.0 h1:JeNZEKJFbQxArAMl+hiytHauacDNqJUllNfmIMmpqnQ= +google.golang.org/grpc v1.83.0/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1459,7 +1228,6 @@ google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBN google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1468,16 +1236,9 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -1500,29 +1261,7 @@ gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU= honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc= -k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= -k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= -k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= -k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= -k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI= mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15/go.mod h1:4M5MMXl2kW6fivUT6yRGpLLPNfuGtU2Z0cPvFquGDYU= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= -sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= -sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= -sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= -sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= -tags.cncf.io/container-device-interface v1.1.0 h1:RnxNhxF1JOu6CJUVpetTYvrXHdxw9j9jFYgZpI+anSY= -tags.cncf.io/container-device-interface v1.1.0/go.mod h1:76Oj0Yqp9FwTx/pySDc8Bxjpg+VqXfDb50cKAXVJ34Q= diff --git a/apps/cli-go/internal/db/reset/reset.go b/apps/cli-go/internal/db/reset/reset.go index 765153d6d7..742fd6d413 100644 --- a/apps/cli-go/internal/db/reset/reset.go +++ b/apps/cli-go/internal/db/reset/reset.go @@ -1,6 +1,7 @@ package reset import ( + "bytes" "context" _ "embed" "fmt" @@ -265,13 +266,59 @@ func restartServices(ctx context.Context) error { return nil }) // Do not wait for service healthy as those services may be excluded from starting - return errors.Join(result...) + if err := errors.Join(result...); err != nil { + return err + } + return reloadKong(ctx) } func listServicesToRestart() []string { return []string{utils.StorageId, utils.GotrueId, utils.RealtimeId, utils.PoolerId} } +// reloadKong reloads Kong after the restarts above so its nginx re-resolves each +// upstream container's address. Kong caches resolved addresses for the life of a +// worker process, and a restarted container can come back on a different one, +// leaving the gateway returning 502 for that route until Kong restarts. An +// in-place reload (the `functions serve` pattern) keeps the gateway serving +// throughout. https://github.com/supabase/cli/issues/6016 +func reloadKong(ctx context.Context) error { + resp, err := utils.Docker.ContainerInspect(ctx, utils.KongId) + if errdefs.IsNotFound(err) { + // Kong may be excluded from the stack. + return nil + } else if err != nil { + return suggestKongRecovery(errors.Errorf("failed to inspect kong: %w", err)) + } + if !resp.State.Running { + // A stopped gateway has no stale cache to flush. + return nil + } + var out bytes.Buffer + // Reload re-renders nginx.conf from Kong's default template, so it needs the + // template bring-up wrote (start.go:589-592) handed back — otherwise it drops + // that template's email_templates server. https://github.com/supabase/cli/issues/6059 + if err := utils.DockerExecOnceWithStream(ctx, utils.KongId, "", nil, []string{"kong", "reload", "--nginx-conf", "/home/kong/custom_nginx.template"}, &out, &out); err != nil { + if msg := strings.TrimSpace(out.String()); len(msg) > 0 { + return suggestKongRecovery(errors.Errorf("failed to reload kong: %w:\n%s", err, msg)) + } + return suggestKongRecovery(errors.Errorf("failed to reload kong: %w", err)) + } + return nil +} + +// suggestKongRecovery decorates a gateway-left-unconfirmed failure with the +// advisory next step; the caller-neutral wording also covers branch switch, +// which shares RestartDatabase. +func suggestKongRecovery(err error) error { + utils.CmdSuggestion = fmt.Sprintf( + "Local services restarted, but API routes may return 502 until the gateway reloads.\nTry restarting it with %s, and check %s if the failure persists.", + utils.Aqua("docker restart "+utils.KongId), + utils.Aqua("docker logs "+utils.KongId), + ) + return err +} + func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error { msg := "Do you want to reset the remote database?" if shouldReset, err := utils.NewConsole().PromptYesNo(ctx, msg, false); err != nil { diff --git a/apps/cli-go/internal/db/reset/reset_test.go b/apps/cli-go/internal/db/reset/reset_test.go index 80dbce2a80..5d672ec15f 100644 --- a/apps/cli-go/internal/db/reset/reset_test.go +++ b/apps/cli-go/internal/db/reset/reset_test.go @@ -2,6 +2,7 @@ package reset import ( "context" + "encoding/json" "errors" "io" "net/http" @@ -73,11 +74,19 @@ func TestResetCommand(t *testing.T) { utils.GotrueId = "test-auth" utils.RealtimeId = "test-realtime" utils.PoolerId = "test-pooler" + utils.KongId = "test-kong" for _, container := range listServicesToRestart() { gock.New(utils.Docker.DaemonHost()). Post("/v" + utils.Docker.ClientVersion() + "/containers/" + container + "/restart"). Reply(http.StatusOK) } + // Kong is not running so the reload is skipped (a successful exec attach is not gock-mockable, see TestExecOnce) + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.KongId + "/json"). + Reply(http.StatusOK). + JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ + State: &container.State{Running: false}, + }}) // Seeds storage gock.New(utils.Docker.DaemonHost()). Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.StorageId + "/json"). @@ -308,11 +317,19 @@ func TestRestartDatabase(t *testing.T) { utils.GotrueId = "test-auth" utils.RealtimeId = "test-realtime" utils.PoolerId = "test-pooler" + utils.KongId = "test-kong" for _, container := range listServicesToRestart() { gock.New(utils.Docker.DaemonHost()). Post("/v" + utils.Docker.ClientVersion() + "/containers/" + container + "/restart"). Reply(http.StatusOK) } + // Kong is not running so the reload is skipped (a successful exec attach is not gock-mockable, see TestExecOnce) + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.KongId + "/json"). + Reply(http.StatusOK). + JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ + State: &container.State{Running: false}, + }}) // Run test err := RestartDatabase(context.Background(), io.Discard) // Check error @@ -360,6 +377,152 @@ func TestRestartDatabase(t *testing.T) { assert.Empty(t, apitest.ListUnmatchedRequests()) }) + t.Run("skips kong reload when kong is not running", func(t *testing.T) { + utils.DbId = "test-reset" + // Setup mock docker + require.NoError(t, apitest.MockDocker(utils.Docker)) + defer gock.OffAll() + // Restarts postgres + gock.New(utils.Docker.DaemonHost()). + Post("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/restart"). + Reply(http.StatusOK) + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/json"). + Reply(http.StatusOK). + JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ + State: &container.State{ + Running: true, + Health: &container.Health{Status: types.Healthy}, + }, + }}) + // Restarts services + utils.StorageId = "test-storage" + utils.GotrueId = "test-auth" + utils.RealtimeId = "test-realtime" + utils.PoolerId = "test-pooler" + utils.KongId = "test-kong" + for _, container := range listServicesToRestart() { + gock.New(utils.Docker.DaemonHost()). + Post("/v" + utils.Docker.ClientVersion() + "/containers/" + container + "/restart"). + Reply(http.StatusOK) + } + // Kong is excluded from the stack: no exec follows + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.KongId + "/json"). + Reply(http.StatusNotFound) + // Run test + err := RestartDatabase(context.Background(), io.Discard) + // Check error + assert.NoError(t, err) + assert.Empty(t, apitest.ListUnmatchedRequests()) + }) + + t.Run("throws error on kong inspect failure", func(t *testing.T) { + utils.DbId = "test-reset" + // Setup mock docker + require.NoError(t, apitest.MockDocker(utils.Docker)) + defer gock.OffAll() + // Restarts postgres + gock.New(utils.Docker.DaemonHost()). + Post("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/restart"). + Reply(http.StatusOK) + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/json"). + Reply(http.StatusOK). + JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ + State: &container.State{ + Running: true, + Health: &container.Health{Status: types.Healthy}, + }, + }}) + // Restarts services + utils.StorageId = "test-storage" + utils.GotrueId = "test-auth" + utils.RealtimeId = "test-realtime" + utils.PoolerId = "test-pooler" + utils.KongId = "test-kong" + for _, container := range listServicesToRestart() { + gock.New(utils.Docker.DaemonHost()). + Post("/v" + utils.Docker.ClientVersion() + "/containers/" + container + "/restart"). + Reply(http.StatusOK) + } + // A daemon error is not the excluded-kong skip case + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.KongId + "/json"). + Reply(http.StatusServiceUnavailable) + // Run test + err := RestartDatabase(context.Background(), io.Discard) + // Check error + assert.ErrorContains(t, err, "failed to inspect kong") + assert.Contains(t, utils.CmdSuggestion, "API routes may return 502") + assert.Contains(t, utils.CmdSuggestion, "docker restart test-kong") + t.Cleanup(func() { utils.CmdSuggestion = "" }) + assert.Empty(t, apitest.ListUnmatchedRequests()) + }) + + t.Run("throws error on kong reload failure", func(t *testing.T) { + utils.DbId = "test-reset" + // Setup mock docker + require.NoError(t, apitest.MockDocker(utils.Docker)) + defer gock.OffAll() + // Restarts postgres + gock.New(utils.Docker.DaemonHost()). + Post("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/restart"). + Reply(http.StatusOK) + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/json"). + Reply(http.StatusOK). + JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ + State: &container.State{ + Running: true, + Health: &container.Health{Status: types.Healthy}, + }, + }}) + // Restarts services + utils.StorageId = "test-storage" + utils.GotrueId = "test-auth" + utils.RealtimeId = "test-realtime" + utils.PoolerId = "test-pooler" + utils.KongId = "test-kong" + for _, container := range listServicesToRestart() { + gock.New(utils.Docker.DaemonHost()). + Post("/v" + utils.Docker.ClientVersion() + "/containers/" + container + "/restart"). + Reply(http.StatusOK) + } + // Kong is up but the reload exec fails + gock.New(utils.Docker.DaemonHost()). + Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.KongId + "/json"). + Reply(http.StatusOK). + JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ + State: &container.State{Running: true}, + }}) + gock.New(utils.Docker.DaemonHost()). + Post("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.KongId + "/exec"). + Reply(http.StatusServiceUnavailable) + // The reload must carry bring-up's template — see reloadKong (#6059). + execPath := "/v" + utils.Docker.ClientVersion() + "/containers/" + utils.KongId + "/exec" + observed := 0 + gock.Observe(func(r *http.Request, mock gock.Mock) { + if r.URL.Path != execPath { + return + } + observed += 1 + var body container.ExecOptions + assert.NoError(t, json.NewDecoder(r.Body).Decode(&body)) + assert.Equal(t, []string{"kong", "reload", "--nginx-conf", "/home/kong/custom_nginx.template"}, body.Cmd) + }) + t.Cleanup(func() { gock.Observe(nil) }) + // Run test + err := RestartDatabase(context.Background(), io.Discard) + // Check error + assert.Equal(t, 1, observed) + assert.ErrorContains(t, err, "failed to reload kong") + assert.Contains(t, utils.CmdSuggestion, "API routes may return 502") + assert.Contains(t, utils.CmdSuggestion, "docker restart test-kong") + t.Cleanup(func() { utils.CmdSuggestion = "" }) + assert.Empty(t, apitest.ListUnmatchedRequests()) + }) + t.Run("throws error on db restart failure", func(t *testing.T) { utils.DbId = "test-reset" // Setup mock docker diff --git a/apps/cli-go/internal/functions/download/download.go b/apps/cli-go/internal/functions/download/download.go index 3e3737ba1e..635296dd8f 100644 --- a/apps/cli-go/internal/functions/download/download.go +++ b/apps/cli-go/internal/functions/download/download.go @@ -116,7 +116,7 @@ func downloadFunction(ctx context.Context, projectRef, slug, extractScriptPath s resBuf := bytes.NewReader(resp.Body) funcDir := filepath.Join(utils.FunctionsDir, slug) - args := []string{"run", "-A", extractScriptPath, funcDir, *meta.EntrypointPath} + args := []string{"run", "-A", extractScriptPath, funcDir, *meta.EntrypointPath, utils.FunctionsDir} cmd := exec.CommandContext(ctx, denoPath, args...) var errBuf bytes.Buffer cmd.Stdin = resBuf diff --git a/apps/cli-go/internal/functions/serve/serve.go b/apps/cli-go/internal/functions/serve/serve.go index 2534d69f91..60190387bb 100644 --- a/apps/cli-go/internal/functions/serve/serve.go +++ b/apps/cli-go/internal/functions/serve/serve.go @@ -126,7 +126,7 @@ func restartEdgeRuntime(ctx context.Context, envFilePath string, noVerifyJWT *bo return err } // 4. Reload Kong to refresh DNS cache for the new Edge Runtime container IP. - if err := utils.DockerExecOnceWithStream(ctx, utils.KongId, "", nil, []string{"kong", "reload"}, os.Stderr, os.Stderr); err != nil { + if err := utils.DockerExecOnceWithStream(ctx, utils.KongId, "", nil, []string{"kong", "reload", "--nginx-conf", "/home/kong/custom_nginx.template"}, os.Stderr, os.Stderr); err != nil { fmt.Fprintln(os.Stderr, "Warning: failed to reload Kong:", err) } return nil diff --git a/apps/cli-go/internal/functions/serve/templates/main.bundled.js b/apps/cli-go/internal/functions/serve/templates/main.bundled.js index 79ff317891..3ed2811dca 100644 --- a/apps/cli-go/internal/functions/serve/templates/main.bundled.js +++ b/apps/cli-go/internal/functions/serve/templates/main.bundled.js @@ -1,4 +1,4 @@ -var m={OK:200,Unauthorized:401,NotFound:404,InternalServerError:500,ServiceUnavailable:503},j={[m.OK]:"OK",[m.Unauthorized]:"Unauthorized",[m.NotFound]:"Not Found",[m.InternalServerError]:"Internal Server Error",[m.ServiceUnavailable]:"Service Unavailable"};function ze(e){let t=e.startsWith("/"),r=[];for(let n of e.split("/"))if(!(n===""||n===".")){if(n===".."){r.length>0&&r[r.length-1]!==".."?r.pop():t||r.push("..");continue}r.push(n)}let o=r.join("/");return t?"/"+o:o===""?".":o}function Q(...e){let t=e.filter(r=>r.length>0).join("/");return t===""?".":ze(t)}function ee(e){if(e.length===0)return".";let t=e.length;for(;t>1&&e[t-1]==="/";)t-=1;let r=e.slice(0,t),o=r.lastIndexOf("/");return o===-1?".":o===0?"/":r.slice(0,o)}function Ze(e){return e.replace(/\s/g,t=>`%${t.charCodeAt(0).toString(16).padStart(2,"0").toUpperCase()}`)}function ye(e){if(!e.startsWith("/"))throw new TypeError(`Path must be absolute: received "${e}"`);let t=new URL("file:///");return t.pathname=Ze(e.replace(/%/g,"%25").replace(/\\/g,"%5C")),t}var L=new TextEncoder,A=new TextDecoder,Ht=2**32;function Se(...e){let t=e.reduce((n,{length:i})=>n+i,0),r=new Uint8Array(t),o=0;for(let n of e)r.set(n,o),o+=n.length;return r}function F(e){let t=new Uint8Array(e.length);for(let r=0;r127)throw new TypeError("non-ASCII string encountered in encode()");t[r]=o}return t}function Ee(e){if(Uint8Array.fromBase64)return Uint8Array.fromBase64(e);let t=atob(e),r=new Uint8Array(t.length);for(let o=0;onew TypeError(`CryptoKey does not support this operation, its ${t} must be ${e}`),I=(e,t)=>e.name===t;function je(e){return parseInt(e.name.slice(4),10)}function te(e,t){if(je(e.hash)!==t)throw K(`SHA-${t}`,"algorithm.hash")}function Qe(e){switch(e){case"ES256":return"P-256";case"ES384":return"P-384";case"ES512":return"P-521";default:throw new Error("unreachable")}}function et(e,t){if(t&&!e.usages.includes(t))throw new TypeError(`CryptoKey does not support this operation, its usages must include ${t}.`)}function ge(e,t,r){switch(t){case"HS256":case"HS384":case"HS512":{if(!I(e.algorithm,"HMAC"))throw K("HMAC");te(e.algorithm,parseInt(t.slice(2),10));break}case"RS256":case"RS384":case"RS512":{if(!I(e.algorithm,"RSASSA-PKCS1-v1_5"))throw K("RSASSA-PKCS1-v1_5");te(e.algorithm,parseInt(t.slice(2),10));break}case"PS256":case"PS384":case"PS512":{if(!I(e.algorithm,"RSA-PSS"))throw K("RSA-PSS");te(e.algorithm,parseInt(t.slice(2),10));break}case"Ed25519":case"EdDSA":{if(!I(e.algorithm,"Ed25519"))throw K("Ed25519");break}case"ML-DSA-44":case"ML-DSA-65":case"ML-DSA-87":{if(!I(e.algorithm,t))throw K(t);break}case"ES256":case"ES384":case"ES512":{if(!I(e.algorithm,"ECDSA"))throw K("ECDSA");let o=Qe(t);if(e.algorithm.namedCurve!==o)throw K(o,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}et(e,r)}function Ae(e,t,...r){if(r=r.filter(Boolean),r.length>2){let o=r.pop();e+=`one of type ${r.join(", ")}, or ${o}.`}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t=="function"&&t.name?e+=` Received function ${t.name}`:typeof t=="object"&&t!=null&&t.constructor?.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var we=(e,...t)=>Ae("Key must be ",e,...t),re=(e,t,...r)=>Ae(`Key for the ${e} algorithm must be `,t,...r);var h=class extends Error{static code="ERR_JOSE_GENERIC";code="ERR_JOSE_GENERIC";constructor(t,r){super(t,r),this.name=this.constructor.name,Error.captureStackTrace?.(this,this.constructor)}},g=class extends h{static code="ERR_JWT_CLAIM_VALIDATION_FAILED";code="ERR_JWT_CLAIM_VALIDATION_FAILED";claim;reason;payload;constructor(t,r,o="unspecified",n="unspecified"){super(t,{cause:{claim:o,reason:n,payload:r}}),this.claim=o,this.reason=n,this.payload=r}},H=class extends h{static code="ERR_JWT_EXPIRED";code="ERR_JWT_EXPIRED";claim;reason;payload;constructor(t,r,o="unspecified",n="unspecified"){super(t,{cause:{claim:o,reason:n,payload:r}}),this.claim=o,this.reason=n,this.payload=r}},k=class extends h{static code="ERR_JOSE_ALG_NOT_ALLOWED";code="ERR_JOSE_ALG_NOT_ALLOWED"},l=class extends h{static code="ERR_JOSE_NOT_SUPPORTED";code="ERR_JOSE_NOT_SUPPORTED"};var u=class extends h{static code="ERR_JWS_INVALID";code="ERR_JWS_INVALID"},x=class extends h{static code="ERR_JWT_INVALID";code="ERR_JWT_INVALID"};var M=class extends h{static code="ERR_JWKS_INVALID";code="ERR_JWKS_INVALID"},W=class extends h{static code="ERR_JWKS_NO_MATCHING_KEY";code="ERR_JWKS_NO_MATCHING_KEY";constructor(t="no applicable key found in the JSON Web Key Set",r){super(t,r)}},$=class extends h{[Symbol.asyncIterator];static code="ERR_JWKS_MULTIPLE_MATCHING_KEYS";code="ERR_JWKS_MULTIPLE_MATCHING_KEYS";constructor(t="multiple matching keys found in the JSON Web Key Set",r){super(t,r)}},V=class extends h{static code="ERR_JWKS_TIMEOUT";code="ERR_JWKS_TIMEOUT";constructor(t="request timed out",r){super(t,r)}},G=class extends h{static code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED";code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED";constructor(t="signature verification failed",r){super(t,r)}};var oe=e=>{if(e?.[Symbol.toStringTag]==="CryptoKey")return!0;try{return e instanceof CryptoKey}catch{return!1}},ne=e=>e?.[Symbol.toStringTag]==="KeyObject",ie=e=>oe(e)||ne(e);function se(e,t,r){try{return w(e)}catch{throw new r(`Failed to base64url decode the ${t}`)}}var tt=e=>typeof e=="object"&&e!==null;function y(e){if(!tt(e)||Object.prototype.toString.call(e)!=="[object Object]")return!1;if(Object.getPrototypeOf(e)===null)return!0;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function be(...e){let t=e.filter(Boolean);if(t.length===0||t.length===1)return!0;let r;for(let o of t){let n=Object.keys(o);if(!r||r.size===0){r=new Set(n);continue}for(let i of n){if(r.has(i))return!1;r.add(i)}}return!0}var B=e=>y(e)&&typeof e.kty=="string",Te=e=>e.kty!=="oct"&&(e.kty==="AKP"&&typeof e.priv=="string"||typeof e.d=="string"),Re=e=>e.kty!=="oct"&&e.d===void 0&&e.priv===void 0,Ke=e=>e.kty==="oct"&&typeof e.k=="string";function ot(e,t){if(e.startsWith("RS")||e.startsWith("PS")){let{modulusLength:r}=t.algorithm;if(typeof r!="number"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}}function nt(e,t){let r=`SHA-${e.slice(-3)}`;switch(e){case"HS256":case"HS384":case"HS512":return{hash:r,name:"HMAC"};case"PS256":case"PS384":case"PS512":return{hash:r,name:"RSA-PSS",saltLength:parseInt(e.slice(-3),10)>>3};case"RS256":case"RS384":case"RS512":return{hash:r,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return{hash:r,name:"ECDSA",namedCurve:t.namedCurve};case"Ed25519":case"EdDSA":return{name:"Ed25519"};case"ML-DSA-44":case"ML-DSA-65":case"ML-DSA-87":return{name:e};default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}async function it(e,t,r){if(t instanceof Uint8Array){if(!e.startsWith("HS"))throw new TypeError(we(t,"CryptoKey","KeyObject","JSON Web Key"));return crypto.subtle.importKey("raw",t,{hash:`SHA-${e.slice(-3)}`,name:"HMAC"},!1,[r])}return ge(t,e,r),t}async function _e(e,t,r,o){let n=await it(e,t,"verify");ot(e,n);let i=nt(e,n.algorithm);try{return await crypto.subtle.verify(i,n,r,o)}catch{return!1}}var X='Invalid or unsupported JWK "alg" (Algorithm) Parameter value';function st(e){let t,r;switch(e.kty){case"AKP":{switch(e.alg){case"ML-DSA-44":case"ML-DSA-65":case"ML-DSA-87":t={name:e.alg},r=e.priv?["sign"]:["verify"];break;default:throw new l(X)}break}case"RSA":{switch(e.alg){case"PS256":case"PS384":case"PS512":t={name:"RSA-PSS",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":t={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":t={name:"RSA-OAEP",hash:`SHA-${parseInt(e.alg.slice(-3),10)||1}`},r=e.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new l(X)}break}case"EC":{switch(e.alg){case"ES256":case"ES384":case"ES512":t={name:"ECDSA",namedCurve:{ES256:"P-256",ES384:"P-384",ES512:"P-521"}[e.alg]},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:"ECDH",namedCurve:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l(X)}break}case"OKP":{switch(e.alg){case"Ed25519":case"EdDSA":t={name:"Ed25519"},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l(X)}break}default:throw new l('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return{algorithm:t,keyUsages:r}}async function v(e){if(!e.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');let{algorithm:t,keyUsages:r}=st(e),o={...e};return o.kty!=="AKP"&&delete o.alg,delete o.use,crypto.subtle.importKey("jwk",o,t,e.ext??!(e.d||e.priv),e.key_ops??r)}var O="given KeyObject instance cannot be used for this algorithm",J,Pe=async(e,t,r,o=!1)=>{J||=new WeakMap;let n=J.get(e);if(n?.[r])return n[r];let i=await v({...t,alg:r});return o&&Object.freeze(e),n?n[r]=i:J.set(e,{[r]:i}),i},at=(e,t)=>{J||=new WeakMap;let r=J.get(e);if(r?.[t])return r[t];let o=e.type==="public",n=!!o,i;if(e.asymmetricKeyType==="x25519"){switch(t){case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":break;default:throw new TypeError(O)}i=e.toCryptoKey(e.asymmetricKeyType,n,o?[]:["deriveBits"])}if(e.asymmetricKeyType==="ed25519"){if(t!=="EdDSA"&&t!=="Ed25519")throw new TypeError(O);i=e.toCryptoKey(e.asymmetricKeyType,n,[o?"verify":"sign"])}switch(e.asymmetricKeyType){case"ml-dsa-44":case"ml-dsa-65":case"ml-dsa-87":{if(t!==e.asymmetricKeyType.toUpperCase())throw new TypeError(O);i=e.toCryptoKey(e.asymmetricKeyType,n,[o?"verify":"sign"])}}if(e.asymmetricKeyType==="rsa"){let s;switch(t){case"RSA-OAEP":s="SHA-1";break;case"RS256":case"PS256":case"RSA-OAEP-256":s="SHA-256";break;case"RS384":case"PS384":case"RSA-OAEP-384":s="SHA-384";break;case"RS512":case"PS512":case"RSA-OAEP-512":s="SHA-512";break;default:throw new TypeError(O)}if(t.startsWith("RSA-OAEP"))return e.toCryptoKey({name:"RSA-OAEP",hash:s},n,o?["encrypt"]:["decrypt"]);i=e.toCryptoKey({name:t.startsWith("PS")?"RSA-PSS":"RSASSA-PKCS1-v1_5",hash:s},n,[o?"verify":"sign"])}if(e.asymmetricKeyType==="ec"){let f=new Map([["prime256v1","P-256"],["secp384r1","P-384"],["secp521r1","P-521"]]).get(e.asymmetricKeyDetails?.namedCurve);if(!f)throw new TypeError(O);let d={ES256:"P-256",ES384:"P-384",ES512:"P-521"};d[t]&&f===d[t]&&(i=e.toCryptoKey({name:"ECDSA",namedCurve:f},n,[o?"verify":"sign"])),t.startsWith("ECDH-ES")&&(i=e.toCryptoKey({name:"ECDH",namedCurve:f},n,o?[]:["deriveBits"]))}if(!i)throw new TypeError(O);return r?r[t]=i:J.set(e,{[t]:i}),i};async function Ce(e,t){if(e instanceof Uint8Array||oe(e))return e;if(ne(e)){if(e.type==="secret")return e.export();if("toCryptoKey"in e&&typeof e.toCryptoKey=="function")try{return at(e,t)}catch(o){if(o instanceof TypeError)throw o}let r=e.export({format:"jwk"});return Pe(e,r,t)}if(B(e))return e.k?w(e.k):Pe(e,e,t,!0);throw new Error("unreachable")}async function Ie(e,t,r){if(!y(e))throw new TypeError("JWK must be an object");let o;switch(t??=e.alg,o??=r?.extractable??e.ext,e.kty){case"oct":if(typeof e.k!="string"||!e.k)throw new TypeError('missing "k" (Key Value) Parameter value');return w(e.k);case"RSA":if("oth"in e&&e.oth!==void 0)throw new l('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');return v({...e,alg:t,ext:o});case"AKP":{if(typeof e.alg!="string"||!e.alg)throw new TypeError('missing "alg" (Algorithm) Parameter value');if(t!==void 0&&t!==e.alg)throw new TypeError("JWK alg and alg option value mismatch");return v({...e,ext:o})}case"EC":case"OKP":return v({...e,alg:t,ext:o});default:throw new l('Unsupported "kty" (Key Type) Parameter value')}}function xe(e,t,r,o,n){if(n.crit!==void 0&&o?.crit===void 0)throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');if(!o||o.crit===void 0)return new Set;if(!Array.isArray(o.crit)||o.crit.length===0||o.crit.some(s=>typeof s!="string"||s.length===0))throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let i;r!==void 0?i=new Map([...Object.entries(r),...t.entries()]):i=t;for(let s of o.crit){if(!i.has(s))throw new l(`Extension Header Parameter "${s}" is not recognized`);if(n[s]===void 0)throw new e(`Extension Header Parameter "${s}" is missing`);if(i.get(s)&&o[s]===void 0)throw new e(`Extension Header Parameter "${s}" MUST be integrity protected`)}return new Set(o.crit)}function We(e,t){if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!="string")))throw new TypeError(`"${e}" option must be an array of strings`);if(t)return new Set(t)}var N=e=>e?.[Symbol.toStringTag],ae=(e,t,r)=>{if(t.use!==void 0){let o;switch(r){case"sign":case"verify":o="sig";break;case"encrypt":case"decrypt":o="enc";break}if(t.use!==o)throw new TypeError(`Invalid key for this operation, its "use" must be "${o}" when present`)}if(t.alg!==void 0&&t.alg!==e)throw new TypeError(`Invalid key for this operation, its "alg" must be "${e}" when present`);if(Array.isArray(t.key_ops)){let o;switch(!0){case(r==="sign"||r==="verify"):case e==="dir":case e.includes("CBC-HS"):o=r;break;case e.startsWith("PBES2"):o="deriveBits";break;case/^A\d{3}(?:GCM)?(?:KW)?$/.test(e):!e.includes("GCM")&&e.endsWith("KW")?o=r==="encrypt"?"wrapKey":"unwrapKey":o=r;break;case(r==="encrypt"&&e.startsWith("RSA")):o="wrapKey";break;case r==="decrypt":o=e.startsWith("RSA")?"unwrapKey":"deriveBits";break}if(o&&t.key_ops?.includes?.(o)===!1)throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${o}" when present`)}return!0},ct=(e,t,r)=>{if(!(t instanceof Uint8Array)){if(B(t)){if(Ke(t)&&ae(e,t,r))return;throw new TypeError('JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present')}if(!ie(t))throw new TypeError(re(e,t,"CryptoKey","KeyObject","JSON Web Key","Uint8Array"));if(t.type!=="secret")throw new TypeError(`${N(t)} instances for symmetric algorithms must be of type "secret"`)}},ft=(e,t,r)=>{if(B(t))switch(r){case"decrypt":case"sign":if(Te(t)&&ae(e,t,r))return;throw new TypeError("JSON Web Key for this operation must be a private JWK");case"encrypt":case"verify":if(Re(t)&&ae(e,t,r))return;throw new TypeError("JSON Web Key for this operation must be a public JWK")}if(!ie(t))throw new TypeError(re(e,t,"CryptoKey","KeyObject","JSON Web Key"));if(t.type==="secret")throw new TypeError(`${N(t)} instances for asymmetric algorithms must not be of type "secret"`);if(t.type==="public")switch(r){case"sign":throw new TypeError(`${N(t)} instances for asymmetric algorithm signing must be of type "private"`);case"decrypt":throw new TypeError(`${N(t)} instances for asymmetric algorithm decryption must be of type "private"`)}if(t.type==="private")switch(r){case"verify":throw new TypeError(`${N(t)} instances for asymmetric algorithm verifying must be of type "public"`);case"encrypt":throw new TypeError(`${N(t)} instances for asymmetric algorithm encryption must be of type "public"`)}};function ve(e,t,r){switch(e.substring(0,2)){case"A1":case"A2":case"di":case"HS":case"PB":ct(e,t,r);break;default:ft(e,t,r)}}async function Oe(e,t,r){if(!y(e))throw new u("Flattened JWS must be an object");if(e.protected===void 0&&e.header===void 0)throw new u('Flattened JWS must have either of the "protected" or "header" members');if(e.protected!==void 0&&typeof e.protected!="string")throw new u("JWS Protected Header incorrect type");if(e.payload===void 0)throw new u("JWS Payload missing");if(typeof e.signature!="string")throw new u("JWS Signature missing or incorrect type");if(e.header!==void 0&&!y(e.header))throw new u("JWS Unprotected Header incorrect type");let o={};if(e.protected)try{let z=w(e.protected);o=JSON.parse(A.decode(z))}catch{throw new u("JWS Protected Header is invalid")}if(!be(o,e.header))throw new u("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let n={...o,...e.header},i=xe(u,new Map([["b64",!0]]),r?.crit,o,n),s=!0;if(i.has("b64")&&(s=o.b64,typeof s!="boolean"))throw new u('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:f}=n;if(typeof f!="string"||!f)throw new u('JWS "alg" (Algorithm) Header Parameter missing or invalid');let d=r&&We("algorithms",r.algorithms);if(d&&!d.has(f))throw new k('"alg" (Algorithm) Header Parameter value not allowed');if(s){if(typeof e.payload!="string")throw new u("JWS Payload must be a string")}else if(typeof e.payload!="string"&&!(e.payload instanceof Uint8Array))throw new u("JWS Payload must be a string or an Uint8Array instance");let a=!1;typeof t=="function"&&(t=await t(o,e),a=!0),ve(f,t,"verify");let c=Se(e.protected!==void 0?F(e.protected):new Uint8Array,F("."),typeof e.payload=="string"?s?F(e.payload):L.encode(e.payload):e.payload),S=se(e.signature,"signature",u),P=await Ce(t,f);if(!await _e(f,P,S,c))throw new G;let E;s?E=se(e.payload,"payload",u):typeof e.payload=="string"?E=L.encode(e.payload):E=e.payload;let R={payload:E};return e.protected!==void 0&&(R.protectedHeader=o),e.header!==void 0&&(R.unprotectedHeader=e.header),a?{...R,key:P}:R}async function Je(e,t,r){if(e instanceof Uint8Array&&(e=A.decode(e)),typeof e!="string")throw new u("Compact JWS must be a string or Uint8Array");let{0:o,1:n,2:i,length:s}=e.split(".");if(s!==3)throw new u("Invalid Compact JWS");let f=await Oe({payload:n,protected:o,signature:i},t,r),d={payload:f.payload,protectedHeader:f.protectedHeader};return typeof t=="function"?{...d,key:f.key}:d}var ut=e=>Math.floor(e.getTime()/1e3),Ue=60,Le=Ue*60,ce=Le*24,dt=ce*7,pt=ce*365.25,lt=/^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;function Ne(e){let t=lt.exec(e);if(!t||t[4]&&t[1])throw new TypeError("Invalid time period format");let r=parseFloat(t[2]),o=t[3].toLowerCase(),n;switch(o){case"sec":case"secs":case"second":case"seconds":case"s":n=Math.round(r);break;case"minute":case"minutes":case"min":case"mins":case"m":n=Math.round(r*Ue);break;case"hour":case"hours":case"hr":case"hrs":case"h":n=Math.round(r*Le);break;case"day":case"days":case"d":n=Math.round(r*ce);break;case"week":case"weeks":case"w":n=Math.round(r*dt);break;default:n=Math.round(r*pt);break}return t[1]==="-"||t[4]==="ago"?-n:n}var De=e=>e.includes("/")?e.toLowerCase():`application/${e.toLowerCase()}`,ht=(e,t)=>typeof e=="string"?t.includes(e):Array.isArray(e)?t.some(Set.prototype.has.bind(new Set(e))):!1;function He(e,t,r={}){let o;try{o=JSON.parse(A.decode(t))}catch{}if(!y(o))throw new x("JWT Claims Set must be a top-level JSON object");let{typ:n}=r;if(n&&(typeof e.typ!="string"||De(e.typ)!==De(n)))throw new g('unexpected "typ" JWT header value',o,"typ","check_failed");let{requiredClaims:i=[],issuer:s,subject:f,audience:d,maxTokenAge:a}=r,c=[...i];a!==void 0&&c.push("iat"),d!==void 0&&c.push("aud"),f!==void 0&&c.push("sub"),s!==void 0&&c.push("iss");for(let E of new Set(c.reverse()))if(!(E in o))throw new g(`missing required "${E}" claim`,o,E,"missing");if(s&&!(Array.isArray(s)?s:[s]).includes(o.iss))throw new g('unexpected "iss" claim value',o,"iss","check_failed");if(f&&o.sub!==f)throw new g('unexpected "sub" claim value',o,"sub","check_failed");if(d&&!ht(o.aud,typeof d=="string"?[d]:d))throw new g('unexpected "aud" claim value',o,"aud","check_failed");let S;switch(typeof r.clockTolerance){case"string":S=Ne(r.clockTolerance);break;case"number":S=r.clockTolerance;break;case"undefined":S=0;break;default:throw new TypeError("Invalid clockTolerance option type")}let{currentDate:P}=r,C=ut(P||new Date);if((o.iat!==void 0||a)&&typeof o.iat!="number")throw new g('"iat" claim must be a number',o,"iat","invalid");if(o.nbf!==void 0){if(typeof o.nbf!="number")throw new g('"nbf" claim must be a number',o,"nbf","invalid");if(o.nbf>C+S)throw new g('"nbf" claim timestamp check failed',o,"nbf","check_failed")}if(o.exp!==void 0){if(typeof o.exp!="number")throw new g('"exp" claim must be a number',o,"exp","invalid");if(o.exp<=C-S)throw new H('"exp" claim timestamp check failed',o,"exp","check_failed")}if(a){let E=C-o.iat,R=typeof a=="number"?a:Ne(a);if(E-S>R)throw new H('"iat" claim timestamp check failed (too far in the past)',o,"iat","check_failed");if(E<0-S)throw new g('"iat" claim timestamp check failed (it should be in the past)',o,"iat","check_failed")}return o}async function Y(e,t,r){let o=await Je(e,t,r);if(o.protectedHeader.crit?.includes("b64")&&o.protectedHeader.b64===!1)throw new x("JWTs MUST NOT use unencoded payload");let i={payload:He(o.protectedHeader,o.payload,r),protectedHeader:o.protectedHeader};return typeof t=="function"?{...i,key:o.key}:i}function mt(e){switch(typeof e=="string"&&e.slice(0,2)){case"RS":case"PS":return"RSA";case"ES":return"EC";case"Ed":return"OKP";case"ML":return"AKP";default:throw new l('Unsupported "alg" value for a JSON Web Key Set')}}function yt(e){return e&&typeof e=="object"&&Array.isArray(e.keys)&&e.keys.every(St)}function St(e){return y(e)}var fe=class{#r;#s=new WeakMap;constructor(t){if(!yt(t))throw new M("JSON Web Key Set malformed");this.#r=structuredClone(t)}jwks(){return this.#r}async getKey(t,r){let{alg:o,kid:n}={...t,...r?.header},i=mt(o),s=this.#r.keys.filter(a=>{let c=i===a.kty;if(c&&typeof n=="string"&&(c=n===a.kid),c&&(typeof a.alg=="string"||i==="AKP")&&(c=o===a.alg),c&&typeof a.use=="string"&&(c=a.use==="sig"),c&&Array.isArray(a.key_ops)&&(c=a.key_ops.includes("verify")),c)switch(o){case"ES256":c=a.crv==="P-256";break;case"ES384":c=a.crv==="P-384";break;case"ES512":c=a.crv==="P-521";break;case"Ed25519":case"EdDSA":c=a.crv==="Ed25519";break}return c}),{0:f,length:d}=s;if(d===0)throw new W;if(d!==1){let a=new $,c=this.#s;throw a[Symbol.asyncIterator]=async function*(){for(let S of s)try{yield await Me(c,S,o)}catch{}},a}return Me(this.#s,f,o)}};async function Me(e,t,r){let o=e.get(t)||e.set(t,{}).get(t);if(o[r]===void 0){let n=await Ie({...t,ext:!0},r);if(n instanceof Uint8Array||n.type!=="public")throw new M("JSON Web Key Set members must be public keys");o[r]=n}return o[r]}function D(e){let t=new fe(e),r=async(o,n)=>t.getKey(o,n);return Object.defineProperties(r,{jwks:{value:()=>structuredClone(t.jwks()),enumerable:!1,configurable:!1,writable:!1}}),r}function Et(){return typeof WebSocketPair<"u"||typeof navigator<"u"&&navigator.userAgent==="Cloudflare-Workers"||typeof EdgeRuntime<"u"&&EdgeRuntime==="vercel"}var ue;(typeof navigator>"u"||!navigator.userAgent?.startsWith?.("Mozilla/5.0 "))&&(ue="jose/v6.2.3");var Be=Symbol();async function gt(e,t,r,o=fetch){let n=await o(e,{method:"GET",signal:r,redirect:"manual",headers:t}).catch(i=>{throw i.name==="TimeoutError"?new V:i});if(n.status!==200)throw new h("Expected 200 OK from the JSON Web Key Set HTTP response");try{return await n.json()}catch{throw new h("Failed to parse the JSON Web Key Set HTTP response as JSON")}}var q=Symbol();function At(e,t){return!(typeof e!="object"||e===null||!("uat"in e)||typeof e.uat!="number"||Date.now()-e.uat>=t||!("jwks"in e)||!y(e.jwks)||!Array.isArray(e.jwks.keys)||!Array.prototype.every.call(e.jwks.keys,y))}var de=class{#r;#s;#c;#a;#o;#e;#t;#f;#n;#i;constructor(t,r){if(!(t instanceof URL))throw new TypeError("url must be an instance of URL");this.#r=new URL(t.href),this.#s=typeof r?.timeoutDuration=="number"?r?.timeoutDuration:5e3,this.#c=typeof r?.cooldownDuration=="number"?r?.cooldownDuration:3e4,this.#a=typeof r?.cacheMaxAge=="number"?r?.cacheMaxAge:6e5,this.#t=new Headers(r?.headers),ue&&!this.#t.has("User-Agent")&&this.#t.set("User-Agent",ue),this.#t.has("accept")||(this.#t.set("accept","application/json"),this.#t.append("accept","application/jwk-set+json")),this.#f=r?.[Be],r?.[q]!==void 0&&(this.#i=r?.[q],At(r?.[q],this.#a)&&(this.#o=this.#i.uat,this.#n=D(this.#i.jwks)))}pendingFetch(){return!!this.#e}coolingDown(){return typeof this.#o=="number"?Date.now(){this.#n=D(t),this.#i&&(this.#i.uat=Date.now(),this.#i.jwks=t),this.#o=Date.now(),this.#e=void 0}).catch(t=>{throw this.#e=void 0,t}),await this.#e}};function pe(e,t){let r=new de(e,t),o=async(n,i)=>r.getKey(n,i);return Object.defineProperties(o,{coolingDown:{get:()=>r.coolingDown(),enumerable:!0,configurable:!1},fresh:{get:()=>r.fresh(),enumerable:!0,configurable:!1},reload:{value:()=>r.reload(),enumerable:!0,configurable:!1,writable:!1},reloading:{get:()=>r.pendingFetch(),enumerable:!0,configurable:!1},jwks:{value:()=>r.jwks(),enumerable:!0,configurable:!1,writable:!1}}),o}function le(e){let t;if(typeof e=="string"){let r=e.split(".");(r.length===3||r.length===5)&&([t]=r)}else if(typeof e=="object"&&e)if("protected"in e)t=e.protected;else throw new TypeError("Token does not contain a Protected Header");try{if(typeof t!="string"||!t)throw new Error;let r=JSON.parse(A.decode(w(t)));if(!y(r))throw new Error;return r}catch{throw new TypeError("Invalid Token or Protected Header formatting")}}var T={BootError:m.ServiceUnavailable,InvalidWorkerResponse:m.InternalServerError,WorkerLimit:546},bt={[T.BootError]:"BOOT_ERROR",[T.InvalidWorkerResponse]:"WORKER_ERROR",[T.WorkerLimit]:"WORKER_LIMIT"},Tt={[T.BootError]:"Worker failed to boot (please check logs)",[T.InvalidWorkerResponse]:"Function exited due to an error (please check logs)",[T.WorkerLimit]:"Worker failed to respond due to a resource limit (please check logs)"},Rt=["HOME","HOSTNAME","PATH","PWD"],Ge=Deno.env.get("SUPABASE_INTERNAL_HOST_PORT"),Kt=Deno.env.get("SUPABASE_INTERNAL_JWT_SECRET"),_t=new URL("/auth/v1/.well-known/jwks.json",Deno.env.get("SUPABASE_URL")),Pt=Deno.env.get("SUPABASE_INTERNAL_DEBUG")==="true",Ct=Deno.env.get("SUPABASE_INTERNAL_FUNCTIONS_CONFIG"),Fe=Deno.env.get("SUPABASE_INTERNAL_PUBLISHABLE_KEY"),ke=Deno.env.get("SUPABASE_INTERNAL_SECRET_KEY"),$e=parseInt(Deno.env.get("SUPABASE_INTERNAL_WALLCLOCK_LIMIT_SEC")),It=new Map([[Deno.errors.InvalidWorkerCreation,T.BootError],[Deno.errors.InvalidWorkerResponse,T.InvalidWorkerResponse],[Deno.errors.WorkerRequestCancelled,T.WorkerLimit]]),Ve=`Serving functions on http://127.0.0.1:${Ge}/functions/v1/`,xt=(i=>(i.MissingAuthHeader="UNAUTHORIZED_NO_AUTH_HEADER",i.InvalidLegacyJWT="UNAUTHORIZED_LEGACY_JWT",i.InvalidAsymmetricJWT="UNAUTHORIZED_ASYMMETRIC_JWT",i.InvalidTokenFormat="UNAUTHORIZED_INVALID_JWT_FORMAT",i.UnsupportedTokenAlgorithm="UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM",i))(xt||{});function U(e,t,r={}){let o={...r},n=null;return e&&(typeof e=="object"?(o["Content-Type"]="application/json",n=JSON.stringify(e)):typeof e=="string"?(o["Content-Type"]="text/plain",n=e):n=null),new Response(n,{status:t,headers:o})}function he({code:e,message:t="Invalid JWT"}){return U({code:e,message:t,msg:t},m.Unauthorized,{"sb-error-code":e,"Access-Control-Expose-Headers":"sb-error-code"})}var _=(()=>{try{let e=JSON.parse(Ct);return Pt&&console.log("Functions config:",JSON.stringify(e,null,2)),e}catch(e){throw new Error("Failed to parse functions config",{cause:e})}})();function Wt(e){let t=e.split(" "),[r,o]=t;return r!=="Bearer"||t.length!==2?null:o}function vt(e){let t=e.headers.get("authorization"),o=e.headers.get("sb-api-key")?.replace("Bearer","")?.trim();if(!t&&!o)return{code:"UNAUTHORIZED_NO_AUTH_HEADER",message:"Missing authorization header"};let n=Wt(t??""),i=!n||n.startsWith("sb_")?o:n;return i||{code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"}}async function Ot(e,t){let o=new TextEncoder().encode(e);try{await Y(t,o)}catch(n){return console.error("Symmetric Legacy JWT verification error",n),{code:"UNAUTHORIZED_LEGACY_JWT"}}return null}var me=(()=>{try{return D(JSON.parse(Deno.env.get("SUPABASE_JWKS")))}catch{return null}})();async function Jt(e,t){try{me||(me=pe(new URL(e))),await Y(t,me)}catch(r){return console.error("Asymmetric JWT verification error",r),{code:"UNAUTHORIZED_ASYMMETRIC_JWT"}}return null}async function Nt(e,t,r){let o;try{o=le(r).alg}catch(n){return console.error("JWT format error",n),{code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"}}return o?o==="HS256"?(console.log(`Legacy token type detected, attempting ${o} verification.`),await Ot(e,r)):o==="ES256"||o==="RS256"?await Jt(t,r):{code:"UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM",message:`Unsupported JWT algorithm ${o}`}:{code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"}}async function Dt({entrypointPath:e,importMapPath:t}){if(t)return!1;let r=Q(ee(e),"package.json");try{await Deno.lstat(r)}catch(o){if(o instanceof Deno.errors.NotFound)return!1}return!0}function Ut(e){let t=new URL(e.url),r=e.headers.get("x-forwarded-host");t.hostname=r??t.hostname;let o=new Request(t,e.clone());return o.headers.delete("sb-api-key"),EdgeRuntime.applySupabaseTag(e,o),o}Deno.serve({handler:async e=>{let t=new URL(e.url),{pathname:r}=t;if(r==="/_internal/health")return U({message:"ok"},m.OK);if(r==="/_internal/metric"){let p=await EdgeRuntime.getRuntimeMetrics();return Response.json(p)}let n=r.split("/")[1];if(!n||!(n in _))return U("Function not found",m.NotFound);if(e.method!=="OPTIONS"&&_[n].verifyJWT)try{let p=vt(e);if(typeof p!="string")return he(p);let b=await Nt(Kt,_t,p);if(b)return he(b)}catch(p){return console.error(p),he({code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"})}let i=ee(_[n].entrypointPath);console.error(`serving the request with ${i}`);let s=256,f=isFinite($e)?$e*1e3:400*1e3,d=!1,a={...Deno.env.toObject(),...Object.fromEntries(Object.entries(_[n].env??{}).filter(([p,b])=>!p.startsWith("SUPABASE_")))};Fe&&(a.SUPABASE_PUBLISHABLE_KEYS=JSON.stringify({default:Fe})),ke&&(a.SUPABASE_SECRET_KEYS=JSON.stringify({default:ke}));let c=Object.entries(a).filter(([p,b])=>!Rt.includes(p)&&!p.startsWith("SUPABASE_INTERNAL_")),S=!1,P="",C=1e3,E=2e3,R="tc39",z=Q(Deno.cwd(),_[n].entrypointPath),Xe=ye(z).href,Ye=await Dt(_[n]),qe=_[n].staticFiles;try{let p=await EdgeRuntime.userWorkers.create({servicePath:i,memoryLimitMb:s,workerTimeoutMs:f,noModuleCache:d,noNpm:!Ye,importMapPath:_[n].importMapPath,envVars:c,forceCreate:S,customModuleRoot:P,cpuTimeSoftLimitMs:C,cpuTimeHardLimitMs:E,decoratorType:R,maybeEntrypoint:Xe,context:{useReadSyncFileAPI:!0},staticPatterns:qe}),b=Ut(e);return await p.fetch(b)}catch(p){console.error(p);for(let[b,Z]of It.entries())if(b!==void 0&&p instanceof b)return U({code:bt[Z],message:Tt[Z]},Z);return U({code:j[m.InternalServerError],message:"Request failed due to an internal server error",trace:JSON.stringify(p.stack)},m.InternalServerError)}},onListen:()=>{try{let e=Deno.env.get("SUPABASE_INTERNAL_FUNCTIONS_CONFIG");if(e){let r=JSON.parse(e),o=Object.keys(r),i=o.slice(0,5).map(f=>` - http://127.0.0.1:${Ge}/functions/v1/${f}`),s=o.length>0?` +var m={OK:200,Unauthorized:401,NotFound:404,InternalServerError:500,ServiceUnavailable:503},j={[m.OK]:"OK",[m.Unauthorized]:"Unauthorized",[m.NotFound]:"Not Found",[m.InternalServerError]:"Internal Server Error",[m.ServiceUnavailable]:"Service Unavailable"};function ze(e){let t=e.startsWith("/"),r=[];for(let n of e.split("/"))if(!(n===""||n===".")){if(n===".."){r.length>0&&r[r.length-1]!==".."?r.pop():t||r.push("..");continue}r.push(n)}let o=r.join("/");return t?"/"+o:o===""?".":o}function Q(...e){let t=e.filter(r=>r.length>0).join("/");return t===""?".":ze(t)}function ee(e){if(e.length===0)return".";let t=e.length;for(;t>1&&e[t-1]==="/";)t-=1;let r=e.slice(0,t),o=r.lastIndexOf("/");return o===-1?".":o===0?"/":r.slice(0,o)}function Ze(e){return e.replace(/\s/g,t=>`%${t.charCodeAt(0).toString(16).padStart(2,"0").toUpperCase()}`)}function ye(e){if(!e.startsWith("/"))throw new TypeError(`Path must be absolute: received "${e}"`);let t=new URL("file:///");return t.pathname=Ze(e.replace(/%/g,"%25").replace(/\\/g,"%5C")),t}var L=new TextEncoder,A=new TextDecoder,Ht=2**32;function Se(...e){let t=e.reduce((n,{length:i})=>n+i,0),r=new Uint8Array(t),o=0;for(let n of e)r.set(n,o),o+=n.length;return r}function F(e){let t=new Uint8Array(e.length);for(let r=0;r127)throw new TypeError("non-ASCII string encountered in encode()");t[r]=o}return t}function Ee(e){if(Uint8Array.fromBase64)return Uint8Array.fromBase64(e);let t=atob(e),r=new Uint8Array(t.length);for(let o=0;onew TypeError(`CryptoKey does not support this operation, its ${t} must be ${e}`),I=(e,t)=>e.name===t;function je(e){return parseInt(e.name.slice(4),10)}function te(e,t){if(je(e.hash)!==t)throw K(`SHA-${t}`,"algorithm.hash")}function Qe(e){switch(e){case"ES256":return"P-256";case"ES384":return"P-384";case"ES512":return"P-521";default:throw new Error("unreachable")}}function et(e,t){if(t&&!e.usages.includes(t))throw new TypeError(`CryptoKey does not support this operation, its usages must include ${t}.`)}function ge(e,t,r){switch(t){case"HS256":case"HS384":case"HS512":{if(!I(e.algorithm,"HMAC"))throw K("HMAC");te(e.algorithm,parseInt(t.slice(2),10));break}case"RS256":case"RS384":case"RS512":{if(!I(e.algorithm,"RSASSA-PKCS1-v1_5"))throw K("RSASSA-PKCS1-v1_5");te(e.algorithm,parseInt(t.slice(2),10));break}case"PS256":case"PS384":case"PS512":{if(!I(e.algorithm,"RSA-PSS"))throw K("RSA-PSS");te(e.algorithm,parseInt(t.slice(2),10));break}case"Ed25519":case"EdDSA":{if(!I(e.algorithm,"Ed25519"))throw K("Ed25519");break}case"ML-DSA-44":case"ML-DSA-65":case"ML-DSA-87":{if(!I(e.algorithm,t))throw K(t);break}case"ES256":case"ES384":case"ES512":{if(!I(e.algorithm,"ECDSA"))throw K("ECDSA");let o=Qe(t);if(e.algorithm.namedCurve!==o)throw K(o,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}et(e,r)}function Ae(e,t,...r){if(r=r.filter(Boolean),r.length>2){let o=r.pop();e+=`one of type ${r.join(", ")}, or ${o}.`}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t=="function"&&t.name?e+=` Received function ${t.name}`:typeof t=="object"&&t!=null&&t.constructor?.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var we=(e,...t)=>Ae("Key must be ",e,...t),re=(e,t,...r)=>Ae(`Key for the ${e} algorithm must be `,t,...r);var h=class extends Error{static code="ERR_JOSE_GENERIC";code="ERR_JOSE_GENERIC";constructor(t,r){super(t,r),this.name=this.constructor.name,Error.captureStackTrace?.(this,this.constructor)}},g=class extends h{static code="ERR_JWT_CLAIM_VALIDATION_FAILED";code="ERR_JWT_CLAIM_VALIDATION_FAILED";claim;reason;payload;constructor(t,r,o="unspecified",n="unspecified"){super(t,{cause:{claim:o,reason:n,payload:r}}),this.claim=o,this.reason=n,this.payload=r}},H=class extends h{static code="ERR_JWT_EXPIRED";code="ERR_JWT_EXPIRED";claim;reason;payload;constructor(t,r,o="unspecified",n="unspecified"){super(t,{cause:{claim:o,reason:n,payload:r}}),this.claim=o,this.reason=n,this.payload=r}},k=class extends h{static code="ERR_JOSE_ALG_NOT_ALLOWED";code="ERR_JOSE_ALG_NOT_ALLOWED"},l=class extends h{static code="ERR_JOSE_NOT_SUPPORTED";code="ERR_JOSE_NOT_SUPPORTED"};var u=class extends h{static code="ERR_JWS_INVALID";code="ERR_JWS_INVALID"},x=class extends h{static code="ERR_JWT_INVALID";code="ERR_JWT_INVALID"};var M=class extends h{static code="ERR_JWKS_INVALID";code="ERR_JWKS_INVALID"},W=class extends h{static code="ERR_JWKS_NO_MATCHING_KEY";code="ERR_JWKS_NO_MATCHING_KEY";constructor(t="no applicable key found in the JSON Web Key Set",r){super(t,r)}},$=class extends h{[Symbol.asyncIterator];static code="ERR_JWKS_MULTIPLE_MATCHING_KEYS";code="ERR_JWKS_MULTIPLE_MATCHING_KEYS";constructor(t="multiple matching keys found in the JSON Web Key Set",r){super(t,r)}},V=class extends h{static code="ERR_JWKS_TIMEOUT";code="ERR_JWKS_TIMEOUT";constructor(t="request timed out",r){super(t,r)}},G=class extends h{static code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED";code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED";constructor(t="signature verification failed",r){super(t,r)}};var oe=e=>{if(e?.[Symbol.toStringTag]==="CryptoKey")return!0;try{return e instanceof CryptoKey}catch{return!1}},ne=e=>e?.[Symbol.toStringTag]==="KeyObject",ie=e=>oe(e)||ne(e);function se(e,t,r){try{return w(e)}catch{throw new r(`Failed to base64url decode the ${t}`)}}var tt=e=>typeof e=="object"&&e!==null;function y(e){if(!tt(e)||Object.prototype.toString.call(e)!=="[object Object]")return!1;if(Object.getPrototypeOf(e)===null)return!0;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function be(...e){let t=e.filter(Boolean);if(t.length===0||t.length===1)return!0;let r;for(let o of t){let n=Object.keys(o);if(!r||r.size===0){r=new Set(n);continue}for(let i of n){if(r.has(i))return!1;r.add(i)}}return!0}var B=e=>y(e)&&typeof e.kty=="string",Te=e=>e.kty!=="oct"&&(e.kty==="AKP"&&typeof e.priv=="string"||typeof e.d=="string"),Re=e=>e.kty!=="oct"&&e.d===void 0&&e.priv===void 0,Ke=e=>e.kty==="oct"&&typeof e.k=="string";function ot(e,t){if(e.startsWith("RS")||e.startsWith("PS")){let{modulusLength:r}=t.algorithm;if(typeof r!="number"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}}function nt(e,t){let r=`SHA-${e.slice(-3)}`;switch(e){case"HS256":case"HS384":case"HS512":return{hash:r,name:"HMAC"};case"PS256":case"PS384":case"PS512":return{hash:r,name:"RSA-PSS",saltLength:parseInt(e.slice(-3),10)>>3};case"RS256":case"RS384":case"RS512":return{hash:r,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return{hash:r,name:"ECDSA",namedCurve:t.namedCurve};case"Ed25519":case"EdDSA":return{name:"Ed25519"};case"ML-DSA-44":case"ML-DSA-65":case"ML-DSA-87":return{name:e};default:throw new l(`alg ${e} is not supported either by JOSE or your javascript runtime`)}}async function it(e,t,r){if(t instanceof Uint8Array){if(!e.startsWith("HS"))throw new TypeError(we(t,"CryptoKey","KeyObject","JSON Web Key"));return crypto.subtle.importKey("raw",t,{hash:`SHA-${e.slice(-3)}`,name:"HMAC"},!1,[r])}return ge(t,e,r),t}async function _e(e,t,r,o){let n=await it(e,t,"verify");ot(e,n);let i=nt(e,n.algorithm);try{return await crypto.subtle.verify(i,n,r,o)}catch{return!1}}var X='Invalid or unsupported JWK "alg" (Algorithm) Parameter value';function st(e){let t,r;switch(e.kty){case"AKP":{switch(e.alg){case"ML-DSA-44":case"ML-DSA-65":case"ML-DSA-87":t={name:e.alg},r=e.priv?["sign"]:["verify"];break;default:throw new l(X)}break}case"RSA":{switch(e.alg){case"PS256":case"PS384":case"PS512":t={name:"RSA-PSS",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":t={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${e.alg.slice(-3)}`},r=e.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":t={name:"RSA-OAEP",hash:`SHA-${parseInt(e.alg.slice(-3),10)||1}`},r=e.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new l(X)}break}case"EC":{switch(e.alg){case"ES256":case"ES384":case"ES512":t={name:"ECDSA",namedCurve:{ES256:"P-256",ES384:"P-384",ES512:"P-521"}[e.alg]},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:"ECDH",namedCurve:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l(X)}break}case"OKP":{switch(e.alg){case"Ed25519":case"EdDSA":t={name:"Ed25519"},r=e.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":t={name:e.crv},r=e.d?["deriveBits"]:[];break;default:throw new l(X)}break}default:throw new l('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return{algorithm:t,keyUsages:r}}async function v(e){if(!e.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');let{algorithm:t,keyUsages:r}=st(e),o={...e};return o.kty!=="AKP"&&delete o.alg,delete o.use,crypto.subtle.importKey("jwk",o,t,e.ext??!(e.d||e.priv),e.key_ops??r)}var O="given KeyObject instance cannot be used for this algorithm",J,Pe=async(e,t,r,o=!1)=>{J||=new WeakMap;let n=J.get(e);if(n?.[r])return n[r];let i=await v({...t,alg:r});return o&&Object.freeze(e),n?n[r]=i:J.set(e,{[r]:i}),i},at=(e,t)=>{J||=new WeakMap;let r=J.get(e);if(r?.[t])return r[t];let o=e.type==="public",n=!!o,i;if(e.asymmetricKeyType==="x25519"){switch(t){case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":break;default:throw new TypeError(O)}i=e.toCryptoKey(e.asymmetricKeyType,n,o?[]:["deriveBits"])}if(e.asymmetricKeyType==="ed25519"){if(t!=="EdDSA"&&t!=="Ed25519")throw new TypeError(O);i=e.toCryptoKey(e.asymmetricKeyType,n,[o?"verify":"sign"])}switch(e.asymmetricKeyType){case"ml-dsa-44":case"ml-dsa-65":case"ml-dsa-87":{if(t!==e.asymmetricKeyType.toUpperCase())throw new TypeError(O);i=e.toCryptoKey(e.asymmetricKeyType,n,[o?"verify":"sign"])}}if(e.asymmetricKeyType==="rsa"){let s;switch(t){case"RSA-OAEP":s="SHA-1";break;case"RS256":case"PS256":case"RSA-OAEP-256":s="SHA-256";break;case"RS384":case"PS384":case"RSA-OAEP-384":s="SHA-384";break;case"RS512":case"PS512":case"RSA-OAEP-512":s="SHA-512";break;default:throw new TypeError(O)}if(t.startsWith("RSA-OAEP"))return e.toCryptoKey({name:"RSA-OAEP",hash:s},n,o?["encrypt"]:["decrypt"]);i=e.toCryptoKey({name:t.startsWith("PS")?"RSA-PSS":"RSASSA-PKCS1-v1_5",hash:s},n,[o?"verify":"sign"])}if(e.asymmetricKeyType==="ec"){let f=new Map([["prime256v1","P-256"],["secp384r1","P-384"],["secp521r1","P-521"]]).get(e.asymmetricKeyDetails?.namedCurve);if(!f)throw new TypeError(O);let d={ES256:"P-256",ES384:"P-384",ES512:"P-521"};d[t]&&f===d[t]&&(i=e.toCryptoKey({name:"ECDSA",namedCurve:f},n,[o?"verify":"sign"])),t.startsWith("ECDH-ES")&&(i=e.toCryptoKey({name:"ECDH",namedCurve:f},n,o?[]:["deriveBits"]))}if(!i)throw new TypeError(O);return r?r[t]=i:J.set(e,{[t]:i}),i};async function Ce(e,t){if(e instanceof Uint8Array||oe(e))return e;if(ne(e)){if(e.type==="secret")return e.export();if("toCryptoKey"in e&&typeof e.toCryptoKey=="function")try{return at(e,t)}catch(o){if(o instanceof TypeError)throw o}let r=e.export({format:"jwk"});return Pe(e,r,t)}if(B(e))return e.k?w(e.k):Pe(e,e,t,!0);throw new Error("unreachable")}async function Ie(e,t,r){if(!y(e))throw new TypeError("JWK must be an object");let o;switch(t??=e.alg,o??=r?.extractable??e.ext,e.kty){case"oct":if(typeof e.k!="string"||!e.k)throw new TypeError('missing "k" (Key Value) Parameter value');return w(e.k);case"RSA":if("oth"in e&&e.oth!==void 0)throw new l('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');return v({...e,alg:t,ext:o});case"AKP":{if(typeof e.alg!="string"||!e.alg)throw new TypeError('missing "alg" (Algorithm) Parameter value');if(t!==void 0&&t!==e.alg)throw new TypeError("JWK alg and alg option value mismatch");return v({...e,ext:o})}case"EC":case"OKP":return v({...e,alg:t,ext:o});default:throw new l('Unsupported "kty" (Key Type) Parameter value')}}function xe(e,t,r,o,n){if(n.crit!==void 0&&o?.crit===void 0)throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');if(!o||o.crit===void 0)return new Set;if(!Array.isArray(o.crit)||o.crit.length===0||o.crit.some(s=>typeof s!="string"||s.length===0))throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let i;r!==void 0?i=new Map([...Object.entries(r),...t.entries()]):i=t;for(let s of o.crit){if(!i.has(s))throw new l(`Extension Header Parameter "${s}" is not recognized`);if(n[s]===void 0)throw new e(`Extension Header Parameter "${s}" is missing`);if(i.get(s)&&o[s]===void 0)throw new e(`Extension Header Parameter "${s}" MUST be integrity protected`)}return new Set(o.crit)}function We(e,t){if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!="string")))throw new TypeError(`"${e}" option must be an array of strings`);if(t)return new Set(t)}var N=e=>e?.[Symbol.toStringTag],ae=(e,t,r)=>{if(t.use!==void 0){let o;switch(r){case"sign":case"verify":o="sig";break;case"encrypt":case"decrypt":o="enc";break}if(t.use!==o)throw new TypeError(`Invalid key for this operation, its "use" must be "${o}" when present`)}if(t.alg!==void 0&&t.alg!==e)throw new TypeError(`Invalid key for this operation, its "alg" must be "${e}" when present`);if(Array.isArray(t.key_ops)){let o;switch(!0){case(r==="sign"||r==="verify"):case e==="dir":case e.includes("CBC-HS"):o=r;break;case e.startsWith("PBES2"):o="deriveBits";break;case/^A\d{3}(?:GCM)?(?:KW)?$/.test(e):!e.includes("GCM")&&e.endsWith("KW")?o=r==="encrypt"?"wrapKey":"unwrapKey":o=r;break;case(r==="encrypt"&&e.startsWith("RSA")):o="wrapKey";break;case r==="decrypt":o=e.startsWith("RSA")?"unwrapKey":"deriveBits";break}if(o&&t.key_ops?.includes?.(o)===!1)throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${o}" when present`)}return!0},ct=(e,t,r)=>{if(!(t instanceof Uint8Array)){if(B(t)){if(Ke(t)&&ae(e,t,r))return;throw new TypeError('JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present')}if(!ie(t))throw new TypeError(re(e,t,"CryptoKey","KeyObject","JSON Web Key","Uint8Array"));if(t.type!=="secret")throw new TypeError(`${N(t)} instances for symmetric algorithms must be of type "secret"`)}},ft=(e,t,r)=>{if(B(t))switch(r){case"decrypt":case"sign":if(Te(t)&&ae(e,t,r))return;throw new TypeError("JSON Web Key for this operation must be a private JWK");case"encrypt":case"verify":if(Re(t)&&ae(e,t,r))return;throw new TypeError("JSON Web Key for this operation must be a public JWK")}if(!ie(t))throw new TypeError(re(e,t,"CryptoKey","KeyObject","JSON Web Key"));if(t.type==="secret")throw new TypeError(`${N(t)} instances for asymmetric algorithms must not be of type "secret"`);if(t.type==="public")switch(r){case"sign":throw new TypeError(`${N(t)} instances for asymmetric algorithm signing must be of type "private"`);case"decrypt":throw new TypeError(`${N(t)} instances for asymmetric algorithm decryption must be of type "private"`)}if(t.type==="private")switch(r){case"verify":throw new TypeError(`${N(t)} instances for asymmetric algorithm verifying must be of type "public"`);case"encrypt":throw new TypeError(`${N(t)} instances for asymmetric algorithm encryption must be of type "public"`)}};function ve(e,t,r){switch(e.substring(0,2)){case"A1":case"A2":case"di":case"HS":case"PB":ct(e,t,r);break;default:ft(e,t,r)}}async function Oe(e,t,r){if(!y(e))throw new u("Flattened JWS must be an object");if(e.protected===void 0&&e.header===void 0)throw new u('Flattened JWS must have either of the "protected" or "header" members');if(e.protected!==void 0&&typeof e.protected!="string")throw new u("JWS Protected Header incorrect type");if(e.payload===void 0)throw new u("JWS Payload missing");if(typeof e.signature!="string")throw new u("JWS Signature missing or incorrect type");if(e.header!==void 0&&!y(e.header))throw new u("JWS Unprotected Header incorrect type");let o={};if(e.protected)try{let z=w(e.protected);o=JSON.parse(A.decode(z))}catch{throw new u("JWS Protected Header is invalid")}if(!be(o,e.header))throw new u("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let n={...o,...e.header},i=xe(u,new Map([["b64",!0]]),r?.crit,o,n),s=!0;if(i.has("b64")&&(s=o.b64,typeof s!="boolean"))throw new u('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:f}=n;if(typeof f!="string"||!f)throw new u('JWS "alg" (Algorithm) Header Parameter missing or invalid');let d=r&&We("algorithms",r.algorithms);if(d&&!d.has(f))throw new k('"alg" (Algorithm) Header Parameter value not allowed');if(s){if(typeof e.payload!="string")throw new u("JWS Payload must be a string")}else if(typeof e.payload!="string"&&!(e.payload instanceof Uint8Array))throw new u("JWS Payload must be a string or an Uint8Array instance");let a=!1;typeof t=="function"&&(t=await t(o,e),a=!0),ve(f,t,"verify");let c=Se(e.protected!==void 0?F(e.protected):new Uint8Array,F("."),typeof e.payload=="string"?s?F(e.payload):L.encode(e.payload):e.payload),S=se(e.signature,"signature",u),P=await Ce(t,f);if(!await _e(f,P,S,c))throw new G;let E;s?E=se(e.payload,"payload",u):typeof e.payload=="string"?E=L.encode(e.payload):E=e.payload;let R={payload:E};return e.protected!==void 0&&(R.protectedHeader=o),e.header!==void 0&&(R.unprotectedHeader=e.header),a?{...R,key:P}:R}async function Je(e,t,r){if(e instanceof Uint8Array&&(e=A.decode(e)),typeof e!="string")throw new u("Compact JWS must be a string or Uint8Array");let{0:o,1:n,2:i,length:s}=e.split(".");if(s!==3)throw new u("Invalid Compact JWS");let f=await Oe({payload:n,protected:o,signature:i},t,r),d={payload:f.payload,protectedHeader:f.protectedHeader};return typeof t=="function"?{...d,key:f.key}:d}var ut=e=>Math.floor(e.getTime()/1e3),Ue=60,Le=Ue*60,ce=Le*24,dt=ce*7,pt=ce*365.25,lt=/^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;function Ne(e){let t=lt.exec(e);if(!t||t[4]&&t[1])throw new TypeError("Invalid time period format");let r=parseFloat(t[2]),o=t[3].toLowerCase(),n;switch(o){case"sec":case"secs":case"second":case"seconds":case"s":n=Math.round(r);break;case"minute":case"minutes":case"min":case"mins":case"m":n=Math.round(r*Ue);break;case"hour":case"hours":case"hr":case"hrs":case"h":n=Math.round(r*Le);break;case"day":case"days":case"d":n=Math.round(r*ce);break;case"week":case"weeks":case"w":n=Math.round(r*dt);break;default:n=Math.round(r*pt);break}return t[1]==="-"||t[4]==="ago"?-n:n}var De=e=>e.includes("/")?e.toLowerCase():`application/${e.toLowerCase()}`,ht=(e,t)=>typeof e=="string"?t.includes(e):Array.isArray(e)?t.some(Set.prototype.has.bind(new Set(e))):!1;function He(e,t,r={}){let o;try{o=JSON.parse(A.decode(t))}catch{}if(!y(o))throw new x("JWT Claims Set must be a top-level JSON object");let{typ:n}=r;if(n&&(typeof e.typ!="string"||De(e.typ)!==De(n)))throw new g('unexpected "typ" JWT header value',o,"typ","check_failed");let{requiredClaims:i=[],issuer:s,subject:f,audience:d,maxTokenAge:a}=r,c=[...i];a!==void 0&&c.push("iat"),d!==void 0&&c.push("aud"),f!==void 0&&c.push("sub"),s!==void 0&&c.push("iss");for(let E of new Set(c.reverse()))if(!(E in o))throw new g(`missing required "${E}" claim`,o,E,"missing");if(s&&!(Array.isArray(s)?s:[s]).includes(o.iss))throw new g('unexpected "iss" claim value',o,"iss","check_failed");if(f&&o.sub!==f)throw new g('unexpected "sub" claim value',o,"sub","check_failed");if(d&&!ht(o.aud,typeof d=="string"?[d]:d))throw new g('unexpected "aud" claim value',o,"aud","check_failed");let S;switch(typeof r.clockTolerance){case"string":S=Ne(r.clockTolerance);break;case"number":S=r.clockTolerance;break;case"undefined":S=0;break;default:throw new TypeError("Invalid clockTolerance option type")}let{currentDate:P}=r,C=ut(P||new Date);if((o.iat!==void 0||a)&&typeof o.iat!="number")throw new g('"iat" claim must be a number',o,"iat","invalid");if(o.nbf!==void 0){if(typeof o.nbf!="number")throw new g('"nbf" claim must be a number',o,"nbf","invalid");if(o.nbf>C+S)throw new g('"nbf" claim timestamp check failed',o,"nbf","check_failed")}if(o.exp!==void 0){if(typeof o.exp!="number")throw new g('"exp" claim must be a number',o,"exp","invalid");if(o.exp<=C-S)throw new H('"exp" claim timestamp check failed',o,"exp","check_failed")}if(a){let E=C-o.iat,R=typeof a=="number"?a:Ne(a);if(E-S>R)throw new H('"iat" claim timestamp check failed (too far in the past)',o,"iat","check_failed");if(E<0-S)throw new g('"iat" claim timestamp check failed (it should be in the past)',o,"iat","check_failed")}return o}async function Y(e,t,r){let o=await Je(e,t,r);if(o.protectedHeader.crit?.includes("b64")&&o.protectedHeader.b64===!1)throw new x("JWTs MUST NOT use unencoded payload");let i={payload:He(o.protectedHeader,o.payload,r),protectedHeader:o.protectedHeader};return typeof t=="function"?{...i,key:o.key}:i}function mt(e){switch(typeof e=="string"&&e.slice(0,2)){case"RS":case"PS":return"RSA";case"ES":return"EC";case"Ed":return"OKP";case"ML":return"AKP";default:throw new l('Unsupported "alg" value for a JSON Web Key Set')}}function yt(e){return e&&typeof e=="object"&&Array.isArray(e.keys)&&e.keys.every(St)}function St(e){return y(e)}var fe=class{#r;#s=new WeakMap;constructor(t){if(!yt(t))throw new M("JSON Web Key Set malformed");this.#r=structuredClone(t)}jwks(){return this.#r}async getKey(t,r){let{alg:o,kid:n}={...t,...r?.header},i=mt(o),s=this.#r.keys.filter(a=>{let c=i===a.kty;if(c&&typeof n=="string"&&(c=n===a.kid),c&&(typeof a.alg=="string"||i==="AKP")&&(c=o===a.alg),c&&typeof a.use=="string"&&(c=a.use==="sig"),c&&Array.isArray(a.key_ops)&&(c=a.key_ops.includes("verify")),c)switch(o){case"ES256":c=a.crv==="P-256";break;case"ES384":c=a.crv==="P-384";break;case"ES512":c=a.crv==="P-521";break;case"Ed25519":case"EdDSA":c=a.crv==="Ed25519";break}return c}),{0:f,length:d}=s;if(d===0)throw new W;if(d!==1){let a=new $,c=this.#s;throw a[Symbol.asyncIterator]=async function*(){for(let S of s)try{yield await Me(c,S,o)}catch{}},a}return Me(this.#s,f,o)}};async function Me(e,t,r){let o=e.get(t)||e.set(t,{}).get(t);if(o[r]===void 0){let n=await Ie({...t,ext:!0},r);if(n instanceof Uint8Array||n.type!=="public")throw new M("JSON Web Key Set members must be public keys");o[r]=n}return o[r]}function D(e){let t=new fe(e),r=async(o,n)=>t.getKey(o,n);return Object.defineProperties(r,{jwks:{value:()=>structuredClone(t.jwks()),enumerable:!1,configurable:!1,writable:!1}}),r}function Et(){return typeof WebSocketPair<"u"||typeof navigator<"u"&&navigator.userAgent==="Cloudflare-Workers"||typeof EdgeRuntime<"u"&&EdgeRuntime==="vercel"}var ue;(typeof navigator>"u"||!navigator.userAgent?.startsWith?.("Mozilla/5.0 "))&&(ue="jose/v6.2.4");var Be=Symbol();async function gt(e,t,r,o=fetch){let n=await o(e,{method:"GET",signal:r,redirect:"manual",headers:t}).catch(i=>{throw i.name==="TimeoutError"?new V:i});if(n.status!==200)throw new h("Expected 200 OK from the JSON Web Key Set HTTP response");try{return await n.json()}catch{throw new h("Failed to parse the JSON Web Key Set HTTP response as JSON")}}var q=Symbol();function At(e,t){return!(typeof e!="object"||e===null||!("uat"in e)||typeof e.uat!="number"||Date.now()-e.uat>=t||!("jwks"in e)||!y(e.jwks)||!Array.isArray(e.jwks.keys)||!Array.prototype.every.call(e.jwks.keys,y))}var de=class{#r;#s;#c;#a;#o;#e;#t;#f;#n;#i;constructor(t,r){if(!(t instanceof URL))throw new TypeError("url must be an instance of URL");this.#r=new URL(t.href),this.#s=typeof r?.timeoutDuration=="number"?r?.timeoutDuration:5e3,this.#c=typeof r?.cooldownDuration=="number"?r?.cooldownDuration:3e4,this.#a=typeof r?.cacheMaxAge=="number"?r?.cacheMaxAge:6e5,this.#t=new Headers(r?.headers),ue&&!this.#t.has("User-Agent")&&this.#t.set("User-Agent",ue),this.#t.has("accept")||(this.#t.set("accept","application/json"),this.#t.append("accept","application/jwk-set+json")),this.#f=r?.[Be],r?.[q]!==void 0&&(this.#i=r?.[q],At(r?.[q],this.#a)&&(this.#o=this.#i.uat,this.#n=D(this.#i.jwks)))}pendingFetch(){return!!this.#e}coolingDown(){return typeof this.#o=="number"?Date.now(){this.#n=D(t),this.#i&&(this.#i.uat=Date.now(),this.#i.jwks=t),this.#o=Date.now(),this.#e=void 0}).catch(t=>{throw this.#e=void 0,t}),await this.#e}};function pe(e,t){let r=new de(e,t),o=async(n,i)=>r.getKey(n,i);return Object.defineProperties(o,{coolingDown:{get:()=>r.coolingDown(),enumerable:!0,configurable:!1},fresh:{get:()=>r.fresh(),enumerable:!0,configurable:!1},reload:{value:()=>r.reload(),enumerable:!0,configurable:!1,writable:!1},reloading:{get:()=>r.pendingFetch(),enumerable:!0,configurable:!1},jwks:{value:()=>r.jwks(),enumerable:!0,configurable:!1,writable:!1}}),o}function le(e){let t;if(typeof e=="string"){let r=e.split(".");(r.length===3||r.length===5)&&([t]=r)}else if(typeof e=="object"&&e)if("protected"in e)t=e.protected;else throw new TypeError("Token does not contain a Protected Header");try{if(typeof t!="string"||!t)throw new Error;let r=JSON.parse(A.decode(w(t)));if(!y(r))throw new Error;return r}catch{throw new TypeError("Invalid Token or Protected Header formatting")}}var T={BootError:m.ServiceUnavailable,InvalidWorkerResponse:m.InternalServerError,WorkerLimit:546},bt={[T.BootError]:"BOOT_ERROR",[T.InvalidWorkerResponse]:"WORKER_ERROR",[T.WorkerLimit]:"WORKER_LIMIT"},Tt={[T.BootError]:"Worker failed to boot (please check logs)",[T.InvalidWorkerResponse]:"Function exited due to an error (please check logs)",[T.WorkerLimit]:"Worker failed to respond due to a resource limit (please check logs)"},Rt=["HOME","HOSTNAME","PATH","PWD"],Ge=Deno.env.get("SUPABASE_INTERNAL_HOST_PORT"),Kt=Deno.env.get("SUPABASE_INTERNAL_JWT_SECRET"),_t=new URL("/auth/v1/.well-known/jwks.json",Deno.env.get("SUPABASE_URL")),Pt=Deno.env.get("SUPABASE_INTERNAL_DEBUG")==="true",Ct=Deno.env.get("SUPABASE_INTERNAL_FUNCTIONS_CONFIG"),Fe=Deno.env.get("SUPABASE_INTERNAL_PUBLISHABLE_KEY"),ke=Deno.env.get("SUPABASE_INTERNAL_SECRET_KEY"),$e=parseInt(Deno.env.get("SUPABASE_INTERNAL_WALLCLOCK_LIMIT_SEC")),It=new Map([[Deno.errors.InvalidWorkerCreation,T.BootError],[Deno.errors.InvalidWorkerResponse,T.InvalidWorkerResponse],[Deno.errors.WorkerRequestCancelled,T.WorkerLimit]]),Ve=`Serving functions on http://127.0.0.1:${Ge}/functions/v1/`,xt=(i=>(i.MissingAuthHeader="UNAUTHORIZED_NO_AUTH_HEADER",i.InvalidLegacyJWT="UNAUTHORIZED_LEGACY_JWT",i.InvalidAsymmetricJWT="UNAUTHORIZED_ASYMMETRIC_JWT",i.InvalidTokenFormat="UNAUTHORIZED_INVALID_JWT_FORMAT",i.UnsupportedTokenAlgorithm="UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM",i))(xt||{});function U(e,t,r={}){let o={...r},n=null;return e&&(typeof e=="object"?(o["Content-Type"]="application/json",n=JSON.stringify(e)):typeof e=="string"?(o["Content-Type"]="text/plain",n=e):n=null),new Response(n,{status:t,headers:o})}function he({code:e,message:t="Invalid JWT"}){return U({code:e,message:t,msg:t},m.Unauthorized,{"sb-error-code":e,"Access-Control-Expose-Headers":"sb-error-code"})}var _=(()=>{try{let e=JSON.parse(Ct);return Pt&&console.log("Functions config:",JSON.stringify(e,null,2)),e}catch(e){throw new Error("Failed to parse functions config",{cause:e})}})();function Wt(e){let t=e.split(" "),[r,o]=t;return r!=="Bearer"||t.length!==2?null:o}function vt(e){let t=e.headers.get("authorization"),o=e.headers.get("sb-api-key")?.replace("Bearer","")?.trim();if(!t&&!o)return{code:"UNAUTHORIZED_NO_AUTH_HEADER",message:"Missing authorization header"};let n=Wt(t??""),i=!n||n.startsWith("sb_")?o:n;return i||{code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"}}async function Ot(e,t){let o=new TextEncoder().encode(e);try{await Y(t,o)}catch(n){return console.error("Symmetric Legacy JWT verification error",n),{code:"UNAUTHORIZED_LEGACY_JWT"}}return null}var me=(()=>{try{return D(JSON.parse(Deno.env.get("SUPABASE_JWKS")))}catch{return null}})();async function Jt(e,t){try{me||(me=pe(new URL(e))),await Y(t,me)}catch(r){return console.error("Asymmetric JWT verification error",r),{code:"UNAUTHORIZED_ASYMMETRIC_JWT"}}return null}async function Nt(e,t,r){let o;try{o=le(r).alg}catch(n){return console.error("JWT format error",n),{code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"}}return o?o==="HS256"?(console.log(`Legacy token type detected, attempting ${o} verification.`),await Ot(e,r)):o==="ES256"||o==="RS256"?await Jt(t,r):{code:"UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM",message:`Unsupported JWT algorithm ${o}`}:{code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"}}async function Dt({entrypointPath:e,importMapPath:t}){if(t)return!1;let r=Q(ee(e),"package.json");try{await Deno.lstat(r)}catch(o){if(o instanceof Deno.errors.NotFound)return!1}return!0}function Ut(e){let t=new URL(e.url),r=e.headers.get("x-forwarded-host");t.hostname=r??t.hostname;let o=new Request(t,e.clone());return o.headers.delete("sb-api-key"),EdgeRuntime.applySupabaseTag(e,o),o}Deno.serve({handler:async e=>{let t=new URL(e.url),{pathname:r}=t;if(r==="/_internal/health")return U({message:"ok"},m.OK);if(r==="/_internal/metric"){let p=await EdgeRuntime.getRuntimeMetrics();return Response.json(p)}let n=r.split("/")[1];if(!n||!(n in _))return U("Function not found",m.NotFound);if(e.method!=="OPTIONS"&&_[n].verifyJWT)try{let p=vt(e);if(typeof p!="string")return he(p);let b=await Nt(Kt,_t,p);if(b)return he(b)}catch(p){return console.error(p),he({code:"UNAUTHORIZED_INVALID_JWT_FORMAT",message:"Invalid JWT format"})}let i=ee(_[n].entrypointPath);console.error(`serving the request with ${i}`);let s=256,f=isFinite($e)?$e*1e3:400*1e3,d=!1,a={...Deno.env.toObject(),...Object.fromEntries(Object.entries(_[n].env??{}).filter(([p,b])=>!p.startsWith("SUPABASE_")))};Fe&&(a.SUPABASE_PUBLISHABLE_KEYS=JSON.stringify({default:Fe})),ke&&(a.SUPABASE_SECRET_KEYS=JSON.stringify({default:ke}));let c=Object.entries(a).filter(([p,b])=>!Rt.includes(p)&&!p.startsWith("SUPABASE_INTERNAL_")),S=!1,P="",C=1e3,E=2e3,R="tc39",z=Q(Deno.cwd(),_[n].entrypointPath),Xe=ye(z).href,Ye=await Dt(_[n]),qe=_[n].staticFiles;try{let p=await EdgeRuntime.userWorkers.create({servicePath:i,memoryLimitMb:s,workerTimeoutMs:f,noModuleCache:d,noNpm:!Ye,importMapPath:_[n].importMapPath,envVars:c,forceCreate:S,customModuleRoot:P,cpuTimeSoftLimitMs:C,cpuTimeHardLimitMs:E,decoratorType:R,maybeEntrypoint:Xe,context:{useReadSyncFileAPI:!0},staticPatterns:qe}),b=Ut(e);return await p.fetch(b)}catch(p){console.error(p);for(let[b,Z]of It.entries())if(b!==void 0&&p instanceof b)return U({code:bt[Z],message:Tt[Z]},Z);return U({code:j[m.InternalServerError],message:"Request failed due to an internal server error",trace:JSON.stringify(p.stack)},m.InternalServerError)}},onListen:()=>{try{let e=Deno.env.get("SUPABASE_INTERNAL_FUNCTIONS_CONFIG");if(e){let r=JSON.parse(e),o=Object.keys(r),i=o.slice(0,5).map(f=>` - http://127.0.0.1:${Ge}/functions/v1/${f}`),s=o.length>0?` ${i.join(` `)}${o.length>5?` ... and ${o.length-5} more functions`:""}`:"";console.log(`${Ve}${s} diff --git a/apps/cli-go/internal/start/start.go b/apps/cli-go/internal/start/start.go deleted file mode 100644 index 6264016e79..0000000000 --- a/apps/cli-go/internal/start/start.go +++ /dev/null @@ -1,1509 +0,0 @@ -package start - -import ( - "bytes" - "context" - _ "embed" - "encoding/json" - "fmt" - "io" - "net" - "net/url" - "os" - "path" - "path/filepath" - "slices" - "strconv" - "strings" - "text/template" - "time" - - "github.com/cenkalti/backoff/v4" - "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/cli/cli/command" - dockerFlags "github.com/docker/cli/cli/flags" - "github.com/docker/compose/v2/pkg/api" - "github.com/docker/compose/v2/pkg/compose" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/client" - "github.com/docker/go-connections/nat" - "github.com/go-errors/errors" - "github.com/jackc/pgconn" - "github.com/jackc/pgx/v4" - "github.com/spf13/afero" - - "github.com/supabase/cli/internal/db/start" - "github.com/supabase/cli/internal/functions/serve" - "github.com/supabase/cli/internal/seed/buckets" - "github.com/supabase/cli/internal/services" - "github.com/supabase/cli/internal/status" - phtelemetry "github.com/supabase/cli/internal/telemetry" - "github.com/supabase/cli/internal/utils" - "github.com/supabase/cli/internal/utils/flags" - "github.com/supabase/cli/pkg/config" -) - -func Run(ctx context.Context, fsys afero.Fs, excludedContainers []string, ignoreHealthCheck bool) error { - // Sanity checks. - { - if err := flags.LoadConfig(fsys); err != nil { - return err - } - if err := utils.AssertSupabaseDbIsRunning(); err == nil { - fmt.Fprintln(os.Stderr, utils.Aqua("supabase start")+" is already running.") - names := status.CustomName{} - return status.Run(ctx, names, utils.OutputPretty, fsys, ignoreHealthCheck, excludedContainers...) - } else if !errors.Is(err, utils.ErrNotRunning) { - return err - } - if err := flags.LoadProjectRef(fsys); err == nil { - _ = services.CheckVersions(ctx, fsys) - } - } - - dbConfig := pgconn.Config{ - Host: utils.DbId, - Port: 5432, - User: "postgres", - Password: utils.Config.Db.Password, - Database: "postgres", - } - if err := run(ctx, fsys, excludedContainers, dbConfig, ignoreHealthCheck); err != nil { - if ignoreHealthCheck && start.IsUnhealthyError(err) { - fmt.Fprintln(os.Stderr, err) - } else { - if err := utils.DockerRemoveAll(context.Background(), os.Stderr, utils.Config.ProjectId); err != nil { - fmt.Fprintln(os.Stderr, err) - } - return err - } - } - - fmt.Fprintf(os.Stderr, "Started %s local development setup.\n\n", utils.Aqua("supabase")) - status.PrettyPrint(os.Stdout, excludedContainers...) - printSecurityNotice() - return nil -} - -type kongConfig struct { - GotrueId string - RestId string - RealtimeId string - StorageId string - StudioId string - PgmetaId string - EdgeRuntimeId string - LogflareId string - PoolerId string - ApiHost string - ApiPort uint16 - BearerToken string - QueryToken string -} - -var ( - //go:embed templates/kong.yml - kongConfigEmbed string - kongConfigTemplate = template.Must(template.New("kongConfig").Parse(kongConfigEmbed)) - - //go:embed templates/custom_nginx.template - nginxConfigEmbed string - // Hardcoded configs which match nginxConfigEmbed - nginxEmailTemplateDir = "/home/kong/templates/email" - nginxTemplateServerPort = 8088 -) - -type vectorConfig struct { - ApiKey string - VectorId string - LogflareId string - KongId string - GotrueId string - RestId string - RealtimeId string - StorageId string - EdgeRuntimeId string - DbId string -} - -func shouldMountRootDockerSocket(host string) bool { - return strings.HasSuffix(host, "/.docker/run/docker.sock") || - strings.HasSuffix(host, "/.docker/desktop/docker.sock") || - (strings.Contains(host, "/.colima/") && strings.HasSuffix(host, "/docker.sock")) || - strings.HasSuffix(host, "/.colima/docker.sock") -} - -var ( - //go:embed templates/vector.yaml - vectorConfigEmbed string - vectorConfigTemplate = template.Must(template.New("vectorConfig").Parse(vectorConfigEmbed)) -) - -type poolerTenant struct { - DbHost string - DbPort uint16 - DbDatabase string - DbPassword string - ExternalId string - ModeType config.PoolMode - DefaultMaxClients uint - DefaultPoolSize uint -} - -var ( - //go:embed templates/pooler.exs - poolerTenantEmbed string - poolerTenantTemplate = template.Must(template.New("poolerTenant").Parse(poolerTenantEmbed)) -) - -var serviceTimeout = 30 * time.Second - -// RetryClient wraps a Docker client to add retry logic for image pulls -type RetryClient struct { - *client.Client -} - -func isPermanentError(err error) bool { - if err == nil { - return false - } - // Rate limited errors can be recovered by retry - if msg := err.Error(); strings.Contains(msg, "toomanyrequests:") { - return false - } - return true -} - -// ImagePull wraps the Docker client's ImagePull with retry logic and registry auth -func (cli *RetryClient) ImagePull(ctx context.Context, refStr string, options image.PullOptions) (io.ReadCloser, error) { - if len(options.RegistryAuth) == 0 { - options.RegistryAuth = utils.GetRegistryAuthForImage(refStr) - } - pull := func() (io.ReadCloser, error) { - resp, err := cli.Client.ImagePull(ctx, refStr, options) - if isPermanentError(err) { - return resp, &backoff.PermanentError{Err: err} - } - return resp, err - } - policy := utils.NewBackoffPolicy(ctx) - return backoff.RetryWithData(pull, policy) -} - -// Also retry ImageInspect: https://github.com/docker/compose/blob/main/pkg/compose/pull.go#L174 -func (cli *RetryClient) ImageInspect(ctx context.Context, refStr string, options ...client.ImageInspectOption) (image.InspectResponse, error) { - pull := func() (image.InspectResponse, error) { - resp, err := cli.Client.ImageInspect(ctx, refStr, options...) - if isPermanentError(err) { - return resp, &backoff.PermanentError{Err: err} - } - return resp, err - } - policy := utils.NewBackoffPolicy(ctx) - return backoff.RetryWithData(pull, policy) -} - -// pullImagesUsingCompose pulls all required images using docker-compose service -func pullImagesUsingCompose(ctx context.Context, project types.Project) error { - // Create Docker CLI - cli, err := command.NewDockerCli() - if err != nil { - return errors.Errorf("failed to create Docker CLI: %w", err) - } - // Initialize Docker CLI - opt := command.WithAPIClient(&RetryClient{Client: utils.Docker}) - if err := cli.Initialize(&dockerFlags.ClientOptions{}, opt); err != nil { - return errors.Errorf("failed to initialize Docker CLI: %w", err) - } - service := compose.NewComposeService(cli) - // Fallback to regular image pull by ignoring failures - return service.Pull(ctx, &project, api.PullOptions{IgnoreFailures: true}) -} - -// ensureImagesCached guarantees every image required by the project is present in -// the local Docker cache before any container is started. The compose pre-pull is -// best effort (PullOptions.IgnoreFailures) and only targets the primary registry, -// so any image it skips would otherwise be pulled lazily by DockerStart while -// containers are already starting. Resolving each image here, using the same -// multi-registry fallback as DockerStart, keeps all pulls ahead of container start. -// -// project.Services[*].Image is the registry-normalized URL produced by GetServices -// (via GetRegistryImageUrl), which DockerResolveImageIfNotCached expands back into -// the same candidate set DockerStart later resolves against. On a warm cache this -// is one ImageInspect per image (no pull, no output); that cost is intentional and -// bounded by the fixed service count. -func ensureImagesCached(ctx context.Context, project types.Project) error { - seen := make(map[string]struct{}, len(project.Services)) - var images []string - for _, service := range project.Services { - if service.Image == "" { - continue - } - if _, ok := seen[service.Image]; ok { - continue - } - seen[service.Image] = struct{}{} - images = append(images, service.Image) - } - result := utils.WaitAll(images, func(image string) error { - _, err := utils.DockerResolveImageIfNotCached(ctx, image) - return err - }) - // Set the install hint once, sequentially, after the concurrent resolve - // finishes, rather than from inside DockerResolveImageIfNotCached where the - // WaitAll goroutines would race on the CmdSuggestion global. - if err := errors.Join(result...); err != nil { - utils.SuggestDockerInstallIfConnectionFailed(err) - return err - } - return nil -} - -func run(ctx context.Context, fsys afero.Fs, excludedContainers []string, dbConfig pgconn.Config, ignoreHealthCheck bool, options ...func(*pgx.ConnConfig)) error { - excluded := make(map[string]bool) - for _, name := range excludedContainers { - excluded[name] = true - } - notExcluded := func(sc types.ServiceConfig) bool { - val, ok := excluded[sc.Name] - return !val || !ok - } - - jwks, err := utils.Config.Auth.ResolveJWKS(ctx) - if err != nil { - return err - } - - // TODO: start services using compose up - project := types.Project{ - Name: "supabase-cli", - Services: utils.GetServices().Filter(notExcluded), - } - if err := pullImagesUsingCompose(ctx, project); err != nil { - return err - } - // Pull any images the best-effort compose pre-pull skipped, so that all pulls - // finish before containers start (https://github.com/supabase/cli/issues/5068). - if err := ensureImagesCached(ctx, project); err != nil { - return err - } - - // Start Postgres. - if dbConfig.Host == utils.DbId { - if err := start.StartDatabase(ctx, "", fsys, os.Stderr, options...); err != nil { - return err - } - } - - var started []string - isStorageEnabled := utils.Config.Storage.Enabled && !isContainerExcluded(utils.Config.Storage.Image, excluded) - isImgProxyEnabled := utils.Config.Storage.ImageTransformation != nil && - utils.Config.Storage.ImageTransformation.Enabled && !isContainerExcluded(utils.Config.Storage.ImgProxyImage, excluded) - isS3ProtocolEnabled := utils.Config.Storage.S3Protocol != nil && utils.Config.Storage.S3Protocol.Enabled - isVectorBucketsEnabled := utils.Config.Storage.VectorBuckets.Enabled - fmt.Fprintln(os.Stderr, "Starting containers...") - - workdir, err := os.Getwd() - if err != nil { - return errors.Errorf("failed to get working directory: %w", err) - } - - // Start Logflare - if utils.Config.Analytics.Enabled && !isContainerExcluded(utils.Config.Analytics.Image, excluded) { - env := []string{ - "DB_DATABASE=_supabase", - "DB_HOSTNAME=" + dbConfig.Host, - fmt.Sprintf("DB_PORT=%d", dbConfig.Port), - "DB_SCHEMA=_analytics", - "DB_USERNAME=" + utils.SUPERUSER_ROLE, - "DB_PASSWORD=" + dbConfig.Password, - "LOGFLARE_MIN_CLUSTER_SIZE=1", - "LOGFLARE_SINGLE_TENANT=true", - "LOGFLARE_SUPABASE_MODE=true", - "LOGFLARE_PRIVATE_ACCESS_TOKEN=" + utils.Config.Analytics.ApiKey, - "LOGFLARE_LOG_LEVEL=warn", - "LOGFLARE_NODE_HOST=127.0.0.1", - "LOGFLARE_FEATURE_FLAG_OVERRIDE='multibackend=true'", - "RELEASE_COOKIE=cookie", - } - bind := []string{} - - switch utils.Config.Analytics.Backend { - case config.LogflareBigQuery: - hostJwtPath := filepath.Join(workdir, utils.Config.Analytics.GcpJwtPath) - bind = append(bind, hostJwtPath+":/opt/app/rel/logflare/bin/gcloud.json") - // This is hardcoded in studio frontend - env = append(env, - "GOOGLE_DATASET_ID_APPEND=_prod", - "GOOGLE_PROJECT_ID="+utils.Config.Analytics.GcpProjectId, - "GOOGLE_PROJECT_NUMBER="+utils.Config.Analytics.GcpProjectNumber, - ) - case config.LogflarePostgres: - env = append(env, - fmt.Sprintf("POSTGRES_BACKEND_URL=postgresql://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, "_supabase"), - "POSTGRES_BACKEND_SCHEMA=_analytics", - ) - } - - if _, err := utils.DockerStart( - ctx, - container.Config{ - Hostname: "127.0.0.1", - Image: utils.Config.Analytics.Image, - Env: env, - // Original entrypoint conflicts with healthcheck due to 15 seconds sleep: - // https://github.com/Logflare/logflare/blob/staging/run.sh#L35 - Entrypoint: []string{"sh", "-c", `cat <<'EOF' > run.sh && sh run.sh -./logflare eval Logflare.Release.migrate -./logflare start --sname logflare -EOF -`}, - Healthcheck: &container.HealthConfig{ - Test: []string{ - "CMD", "curl", "-sSfL", "--head", "-o", "/dev/null", - "http://127.0.0.1:4000/health", - }, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - StartPeriod: 10 * time.Second, - }, - ExposedPorts: nat.PortSet{"4000/tcp": {}}, - }, - container.HostConfig{ - Binds: bind, - PortBindings: nat.PortMap{"4000/tcp": []nat.PortBinding{{ - HostPort: strconv.FormatUint(uint64(utils.Config.Analytics.Port), 10), - }}}, - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.LogflareAliases, - }, - }, - }, - utils.LogflareId, - ); err != nil { - return err - } - started = append(started, utils.LogflareId) - } - - // Start vector - if utils.Config.Analytics.Enabled && !isContainerExcluded(utils.Config.Analytics.VectorImage, excluded) { - var vectorConfigBuf bytes.Buffer - if err := vectorConfigTemplate.Option("missingkey=error").Execute(&vectorConfigBuf, vectorConfig{ - ApiKey: utils.Config.Analytics.ApiKey, - VectorId: utils.VectorId, - LogflareId: utils.LogflareId, - KongId: utils.KongId, - GotrueId: utils.GotrueId, - RestId: utils.RestId, - RealtimeId: utils.RealtimeId, - StorageId: utils.StorageId, - EdgeRuntimeId: utils.EdgeRuntimeId, - DbId: utils.DbId, - }); err != nil { - return errors.Errorf("failed to exec template: %w", err) - } - var binds, env, securityOpts []string - // Special case for GitLab pipeline - parsed, err := client.ParseHostURL(utils.Docker.DaemonHost()) - if err != nil { - return errors.Errorf("failed to parse docker host: %w", err) - } - // Ref: https://vector.dev/docs/reference/configuration/sources/docker_logs/#docker_host - dindHost := &url.URL{Scheme: "http", Host: net.JoinHostPort(utils.DinDHost, "2375")} - switch parsed.Scheme { - case "tcp": - if _, port, err := net.SplitHostPort(parsed.Host); err == nil { - dindHost.Host = net.JoinHostPort(utils.DinDHost, port) - } - env = append(env, "DOCKER_HOST="+dindHost.String()) - case "npipe": - const dockerDaemonNeededErr = "Analytics on Windows requires Docker daemon exposed on tcp://localhost:2375.\nSee https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=windows#running-supabase-locally for more details." - fmt.Fprintln(os.Stderr, utils.Yellow("WARNING:"), dockerDaemonNeededErr) - env = append(env, "DOCKER_HOST="+dindHost.String()) - case "unix": - if dindHost, err = client.ParseHostURL(client.DefaultDockerHost); err != nil { - return errors.Errorf("failed to parse default host: %w", err) - } else if shouldMountRootDockerSocket(parsed.Host) { - // Docker will not mount rootless socket directly; - // instead, specify root socket to have it handled under the hood - binds = append(binds, fmt.Sprintf("%[1]s:%[1]s:ro", dindHost.Host)) - } else { - // Podman and OrbStack can mount root-less socket without issue - binds = append(binds, fmt.Sprintf("%s:%s:ro", parsed.Host, dindHost.Host)) - securityOpts = append(securityOpts, "label:disable") - } - } - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Analytics.VectorImage, - Env: env, - Entrypoint: []string{"sh", "-c", `cat <<'EOF' > /etc/vector/vector.yaml -` + vectorConfigBuf.String() + ` -EOF -until wget --no-verbose --tries=1 --spider http://` + utils.LogflareId + `:4000/health 2>/dev/null; do sleep 2; done -vector --config /etc/vector/vector.yaml -`}, - Healthcheck: &container.HealthConfig{ - Test: []string{ - "CMD", "wget", "--no-verbose", "--tries=1", "--spider", - "http://127.0.0.1:9001/health", - }, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - Binds: binds, - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - SecurityOpt: securityOpts, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.VectorAliases, - }, - }, - }, - utils.VectorId, - ); err != nil { - return err - } - if parsed.Scheme != "npipe" { - started = append(started, utils.VectorId) - } - } - - // Start Kong. - if !isContainerExcluded(utils.Config.Api.KongImage, excluded) { - var kongConfigBuf bytes.Buffer - if err := kongConfigTemplate.Option("missingkey=error").Execute(&kongConfigBuf, kongConfig{ - GotrueId: utils.GotrueId, - RestId: utils.RestId, - RealtimeId: utils.Config.Realtime.TenantId, - StorageId: utils.StorageId, - StudioId: utils.StudioId, - PgmetaId: utils.PgmetaId, - EdgeRuntimeId: utils.EdgeRuntimeId, - LogflareId: utils.LogflareId, - PoolerId: utils.PoolerId, - ApiHost: utils.Config.Hostname, - ApiPort: utils.Config.Api.Port, - BearerToken: fmt.Sprintf( - // If Authorization header is set to a self-minted JWT, we want to pass it down. - // Legacy supabase-js may set Authorization header to Bearer . We must remove it - // to avoid failing JWT validation. - // If Authorization header is missing, we want to match against apikey header to set the - // default JWT for downstream services. - // Finally, the apikey header may be set to a legacy JWT. In that case, we want to copy - // it to Authorization header for backwards compatibility. - `$((headers.authorization ~= nil and headers.authorization:sub(1, 10) ~= 'Bearer sb_' and headers.authorization) or (headers.apikey == '%s' and 'Bearer %s') or (headers.apikey == '%s' and 'Bearer %s') or headers.apikey)`, - utils.Config.Auth.SecretKey.Value, - utils.Config.Auth.ServiceRoleKey.Value, - utils.Config.Auth.PublishableKey.Value, - utils.Config.Auth.AnonKey.Value, - ), - QueryToken: fmt.Sprintf( - `$((query_params.apikey == '%s' and '%s') or (query_params.apikey == '%s' and '%s') or query_params.apikey)`, - utils.Config.Auth.SecretKey.Value, - utils.Config.Auth.ServiceRoleKey.Value, - utils.Config.Auth.PublishableKey.Value, - utils.Config.Auth.AnonKey.Value, - ), - }); err != nil { - return errors.Errorf("failed to exec template: %w", err) - } - - binds := []string{} - mountEmailTemplates := func(id, contentPath string) error { - if len(contentPath) == 0 { - return nil - } - hostPath := contentPath - if !filepath.IsAbs(contentPath) { - var err error - hostPath, err = filepath.Abs(hostPath) - if err != nil { - return errors.Errorf("failed to resolve absolute path: %w", err) - } - } - dockerPath := path.Join(nginxEmailTemplateDir, id+filepath.Ext(hostPath)) - binds = append(binds, fmt.Sprintf("%s:%s:rw", hostPath, dockerPath)) - return nil - } - - for id, tmpl := range utils.Config.Auth.Email.Template { - err := mountEmailTemplates(id, tmpl.ContentPath) - if err != nil { - return err - } - } - - for id, tmpl := range utils.Config.Auth.Email.Notification { - if tmpl.Enabled { - err := mountEmailTemplates(id+"_notification", tmpl.ContentPath) - if err != nil { - return err - } - } - } - - dockerPort := uint16(8000) - if utils.Config.Api.Tls.Enabled { - dockerPort = 8443 - } - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Api.KongImage, - Env: []string{ - "KONG_DATABASE=off", - "KONG_DECLARATIVE_CONFIG=/home/kong/kong.yml", - "KONG_DNS_ORDER=LAST,A,CNAME", // https://github.com/supabase/cli/issues/14 - "KONG_PLUGINS=request-transformer,cors", - fmt.Sprintf("KONG_PORT_MAPS=%d:8000", utils.Config.Api.Port), - // Need to increase the nginx buffers in kong to avoid it rejecting the rather - // sizeable response headers azure can generate - // Ref: https://github.com/Kong/kong/issues/3974#issuecomment-482105126 - "KONG_NGINX_PROXY_PROXY_BUFFER_SIZE=160k", - "KONG_NGINX_PROXY_PROXY_BUFFERS=64 160k", - // Default to a single nginx worker to minimize the local stack's - // memory usage (Ref: #1271). Operators who need more throughput can - // override this from their shell, e.g. KONG_NGINX_WORKER_PROCESSES=auto - // for one worker per CPU core. - envOrDefault("KONG_NGINX_WORKER_PROCESSES", "1"), - // Use modern TLS certificate - "KONG_SSL_CERT=/home/kong/localhost.crt", - "KONG_SSL_CERT_KEY=/home/kong/localhost.key", - }, - Entrypoint: []string{"sh", "-c", `cat <<'EOF' > /home/kong/kong.yml && \ -cat <<'EOF' > /home/kong/custom_nginx.template && \ -cat <<'EOF' > /home/kong/localhost.crt && \ -cat <<'EOF' > /home/kong/localhost.key && \ -./docker-entrypoint.sh kong docker-start --nginx-conf /home/kong/custom_nginx.template -` + kongConfigBuf.String() + ` -EOF -` + nginxConfigEmbed + ` -EOF -` + string(utils.Config.Api.Tls.CertContent) + ` -EOF -` + string(utils.Config.Api.Tls.KeyContent) + ` -EOF -`}, - ExposedPorts: nat.PortSet{ - "8000/tcp": {}, - "8443/tcp": {}, - nat.Port(fmt.Sprintf("%d/tcp", nginxTemplateServerPort)): {}, - }, - }, - container.HostConfig{ - Binds: binds, - PortBindings: nat.PortMap{nat.Port(fmt.Sprintf("%d/tcp", dockerPort)): []nat.PortBinding{{ - HostPort: strconv.FormatUint(uint64(utils.Config.Api.Port), 10), - }}}, - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.KongAliases, - }, - }, - }, - utils.KongId, - ); err != nil { - return err - } - started = append(started, utils.KongId) - } - - // Start GoTrue. - if utils.Config.Auth.Enabled && !isContainerExcluded(utils.Config.Auth.Image, excluded) { - env := buildGotrueEnv(dbConfig) - - // Serialise default or custom signing keys - if keys, err := json.Marshal(utils.Config.Auth.SigningKeys); err == nil { - env = append(env, "GOTRUE_JWT_KEYS="+string(keys)) - // TODO: deprecate HS256 when it's no longer supported - // TODO: remove VALIDMETHODS after a while to avoid breaking changes - env = append(env, "GOTRUE_JWT_VALIDMETHODS=HS256,RS256,ES256") - env = append(env, "GOTRUE_JWT_VALID_METHODS=HS256,RS256,ES256") - } - - if utils.Config.Auth.Email.Smtp != nil && utils.Config.Auth.Email.Smtp.Enabled { - env = append(env, - fmt.Sprintf("GOTRUE_RATE_LIMIT_EMAIL_SENT=%v", utils.Config.Auth.RateLimit.EmailSent), - fmt.Sprintf("GOTRUE_SMTP_HOST=%s", utils.Config.Auth.Email.Smtp.Host), - fmt.Sprintf("GOTRUE_SMTP_PORT=%d", utils.Config.Auth.Email.Smtp.Port), - fmt.Sprintf("GOTRUE_SMTP_USER=%s", utils.Config.Auth.Email.Smtp.User), - fmt.Sprintf("GOTRUE_SMTP_PASS=%s", utils.Config.Auth.Email.Smtp.Pass.Value), - fmt.Sprintf("GOTRUE_SMTP_ADMIN_EMAIL=%s", utils.Config.Auth.Email.Smtp.AdminEmail), - fmt.Sprintf("GOTRUE_SMTP_SENDER_NAME=%s", utils.Config.Auth.Email.Smtp.SenderName), - ) - } else if utils.Config.Inbucket.Enabled { - env = append(env, - "GOTRUE_SMTP_HOST="+utils.InbucketId, - "GOTRUE_SMTP_PORT=1025", - fmt.Sprintf("GOTRUE_SMTP_ADMIN_EMAIL=%s", utils.Config.Inbucket.AdminEmail), - fmt.Sprintf("GOTRUE_SMTP_SENDER_NAME=%s", utils.Config.Inbucket.SenderName), - ) - } - - if utils.Config.Auth.Sessions.Timebox > 0 { - env = append(env, fmt.Sprintf("GOTRUE_SESSIONS_TIMEBOX=%v", utils.Config.Auth.Sessions.Timebox)) - } - if utils.Config.Auth.Sessions.InactivityTimeout > 0 { - env = append(env, fmt.Sprintf("GOTRUE_SESSIONS_INACTIVITY_TIMEOUT=%v", utils.Config.Auth.Sessions.InactivityTimeout)) - } - - addMailerEnvVars := func(id, contentPath string, subject *string) { - if len(contentPath) > 0 { - env = append(env, fmt.Sprintf("GOTRUE_MAILER_TEMPLATES_%s=http://%s:%d/email/%s", - strings.ToUpper(id), - utils.KongId, - nginxTemplateServerPort, - id+filepath.Ext(contentPath), - )) - } - if subject != nil { - env = append(env, fmt.Sprintf("GOTRUE_MAILER_SUBJECTS_%s=%s", - strings.ToUpper(id), - *subject, - )) - } - } - - for id, tmpl := range utils.Config.Auth.Email.Template { - addMailerEnvVars(id, tmpl.ContentPath, tmpl.Subject) - } - - for id, tmpl := range utils.Config.Auth.Email.Notification { - if tmpl.Enabled { - env = append(env, fmt.Sprintf("GOTRUE_MAILER_NOTIFICATIONS_%s_ENABLED=true", strings.ToUpper(id))) - addMailerEnvVars(id+"_notification", tmpl.ContentPath, tmpl.Subject) - } - } - - switch { - case utils.Config.Auth.Sms.Twilio.Enabled: - env = append( - env, - "GOTRUE_SMS_PROVIDER=twilio", - "GOTRUE_SMS_TWILIO_ACCOUNT_SID="+utils.Config.Auth.Sms.Twilio.AccountSid, - "GOTRUE_SMS_TWILIO_AUTH_TOKEN="+utils.Config.Auth.Sms.Twilio.AuthToken.Value, - "GOTRUE_SMS_TWILIO_MESSAGE_SERVICE_SID="+utils.Config.Auth.Sms.Twilio.MessageServiceSid, - ) - case utils.Config.Auth.Sms.TwilioVerify.Enabled: - env = append( - env, - "GOTRUE_SMS_PROVIDER=twilio_verify", - "GOTRUE_SMS_TWILIO_VERIFY_ACCOUNT_SID="+utils.Config.Auth.Sms.TwilioVerify.AccountSid, - "GOTRUE_SMS_TWILIO_VERIFY_AUTH_TOKEN="+utils.Config.Auth.Sms.TwilioVerify.AuthToken.Value, - "GOTRUE_SMS_TWILIO_VERIFY_MESSAGE_SERVICE_SID="+utils.Config.Auth.Sms.TwilioVerify.MessageServiceSid, - ) - case utils.Config.Auth.Sms.Messagebird.Enabled: - env = append( - env, - "GOTRUE_SMS_PROVIDER=messagebird", - "GOTRUE_SMS_MESSAGEBIRD_ACCESS_KEY="+utils.Config.Auth.Sms.Messagebird.AccessKey.Value, - "GOTRUE_SMS_MESSAGEBIRD_ORIGINATOR="+utils.Config.Auth.Sms.Messagebird.Originator, - ) - case utils.Config.Auth.Sms.Textlocal.Enabled: - env = append( - env, - "GOTRUE_SMS_PROVIDER=textlocal", - "GOTRUE_SMS_TEXTLOCAL_API_KEY="+utils.Config.Auth.Sms.Textlocal.ApiKey.Value, - "GOTRUE_SMS_TEXTLOCAL_SENDER="+utils.Config.Auth.Sms.Textlocal.Sender, - ) - case utils.Config.Auth.Sms.Vonage.Enabled: - env = append( - env, - "GOTRUE_SMS_PROVIDER=vonage", - "GOTRUE_SMS_VONAGE_API_KEY="+utils.Config.Auth.Sms.Vonage.ApiKey, - "GOTRUE_SMS_VONAGE_API_SECRET="+utils.Config.Auth.Sms.Vonage.ApiSecret.Value, - "GOTRUE_SMS_VONAGE_FROM="+utils.Config.Auth.Sms.Vonage.From, - ) - } - - if captcha := utils.Config.Auth.Captcha; captcha != nil { - env = append( - env, - fmt.Sprintf("GOTRUE_SECURITY_CAPTCHA_ENABLED=%v", captcha.Enabled), - fmt.Sprintf("GOTRUE_SECURITY_CAPTCHA_PROVIDER=%v", captcha.Provider), - fmt.Sprintf("GOTRUE_SECURITY_CAPTCHA_SECRET=%v", captcha.Secret.Value), - ) - } - - if hook := utils.Config.Auth.Hook.MFAVerificationAttempt; hook != nil && hook.Enabled { - env = append( - env, - "GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_ENABLED=true", - "GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_URI="+hook.URI, - "GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_SECRETS="+hook.Secrets.Value, - ) - } - if hook := utils.Config.Auth.Hook.PasswordVerificationAttempt; hook != nil && hook.Enabled { - env = append( - env, - "GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_ENABLED=true", - "GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_URI="+hook.URI, - "GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_SECRETS="+hook.Secrets.Value, - ) - } - if hook := utils.Config.Auth.Hook.CustomAccessToken; hook != nil && hook.Enabled { - env = append( - env, - "GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_ENABLED=true", - "GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_URI="+hook.URI, - "GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_SECRETS="+hook.Secrets.Value, - ) - } - if hook := utils.Config.Auth.Hook.SendSMS; hook != nil && hook.Enabled { - env = append( - env, - "GOTRUE_HOOK_SEND_SMS_ENABLED=true", - "GOTRUE_HOOK_SEND_SMS_URI="+hook.URI, - "GOTRUE_HOOK_SEND_SMS_SECRETS="+hook.Secrets.Value, - ) - } - if hook := utils.Config.Auth.Hook.SendEmail; hook != nil && hook.Enabled { - env = append( - env, - "GOTRUE_HOOK_SEND_EMAIL_ENABLED=true", - "GOTRUE_HOOK_SEND_EMAIL_URI="+hook.URI, - "GOTRUE_HOOK_SEND_EMAIL_SECRETS="+hook.Secrets.Value, - ) - } - if hook := utils.Config.Auth.Hook.BeforeUserCreated; hook != nil && hook.Enabled { - env = append( - env, - "GOTRUE_HOOK_BEFORE_USER_CREATED_ENABLED=true", - "GOTRUE_HOOK_BEFORE_USER_CREATED_URI="+hook.URI, - "GOTRUE_HOOK_BEFORE_USER_CREATED_SECRETS="+hook.Secrets.Value, - ) - } - - if utils.Config.Auth.MFA.Phone.EnrollEnabled || utils.Config.Auth.MFA.Phone.VerifyEnabled { - env = append( - env, - "GOTRUE_MFA_PHONE_TEMPLATE="+utils.Config.Auth.MFA.Phone.Template, - fmt.Sprintf("GOTRUE_MFA_PHONE_OTP_LENGTH=%v", utils.Config.Auth.MFA.Phone.OtpLength), - fmt.Sprintf("GOTRUE_MFA_PHONE_MAX_FREQUENCY=%v", utils.Config.Auth.MFA.Phone.MaxFrequency), - ) - } - - env = appendGotruePasskeyEnv(env) - env = appendGotrueExternalProviderEnv(env) - env = append(env, - fmt.Sprintf("GOTRUE_EXTERNAL_WEB3_SOLANA_ENABLED=%v", utils.Config.Auth.Web3.Solana.Enabled), - fmt.Sprintf("GOTRUE_EXTERNAL_WEB3_ETHEREUM_ENABLED=%v", utils.Config.Auth.Web3.Ethereum.Enabled), - ) - - // OAuth server configuration - if utils.Config.Auth.OAuthServer.Enabled { - env = append(env, - fmt.Sprintf("GOTRUE_OAUTH_SERVER_ENABLED=%v", utils.Config.Auth.OAuthServer.Enabled), - "GOTRUE_OAUTH_SERVER_AUTHORIZATION_PATH="+utils.Config.Auth.OAuthServer.AuthorizationUrlPath, - fmt.Sprintf("GOTRUE_OAUTH_SERVER_ALLOW_DYNAMIC_REGISTRATION=%v", utils.Config.Auth.OAuthServer.AllowDynamicRegistration), - ) - } - - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Auth.Image, - Env: env, - ExposedPorts: nat.PortSet{"9999/tcp": {}}, - Healthcheck: &container.HealthConfig{ - Test: []string{ - "CMD", "wget", "--no-verbose", "--tries=1", "--spider", - "http://127.0.0.1:9999/health", - }, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.GotrueAliases, - }, - }, - }, - utils.GotrueId, - ); err != nil { - return err - } - started = append(started, utils.GotrueId) - } - - // Start Mailpit - if utils.Config.Inbucket.Enabled && !isContainerExcluded(utils.Config.Inbucket.Image, excluded) { - inbucketPortBindings := nat.PortMap{"8025/tcp": []nat.PortBinding{{ - HostPort: strconv.FormatUint(uint64(utils.Config.Inbucket.Port), 10), - }}} - if utils.Config.Inbucket.SmtpPort != 0 { - inbucketPortBindings["1025/tcp"] = []nat.PortBinding{{ - HostPort: strconv.FormatUint(uint64(utils.Config.Inbucket.SmtpPort), 10), - }} - } - if utils.Config.Inbucket.Pop3Port != 0 { - inbucketPortBindings["1110/tcp"] = []nat.PortBinding{{ - HostPort: strconv.FormatUint(uint64(utils.Config.Inbucket.Pop3Port), 10), - }} - } - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Inbucket.Image, - Env: []string{ - // Disable reverse DNS lookups in Mailpit to avoid slow/delayed DNS resolution - "MP_SMTP_DISABLE_RDNS=true", - }, - Healthcheck: &container.HealthConfig{ - Test: []string{"CMD", "/mailpit", "readyz"}, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - // StartPeriod taken from upstream Dockerfile - StartPeriod: 10 * time.Second, - }, - }, - container.HostConfig{ - PortBindings: inbucketPortBindings, - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.InbucketAliases, - }, - }, - }, - utils.InbucketId, - ); err != nil { - return err - } - started = append(started, utils.InbucketId) - } - - // Start Realtime. - if utils.Config.Realtime.Enabled && !isContainerExcluded(utils.Config.Realtime.Image, excluded) { - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Realtime.Image, - Env: []string{ - "PORT=4000", - "DB_HOST=" + dbConfig.Host, - fmt.Sprintf("DB_PORT=%d", dbConfig.Port), - "DB_USER=" + utils.SUPERUSER_ROLE, - "DB_PASSWORD=" + dbConfig.Password, - "DB_NAME=" + dbConfig.Database, - "DB_AFTER_CONNECT_QUERY=SET search_path TO _realtime", - "DB_ENC_KEY=" + utils.Config.Realtime.EncryptionKey, - "API_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, - fmt.Sprintf("API_JWT_JWKS=%s", jwks), - "METRICS_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, - "APP_NAME=realtime", - "SECRET_KEY_BASE=" + utils.Config.Realtime.SecretKeyBase, - "ERL_AFLAGS=" + utils.ToRealtimeEnv(utils.Config.Realtime.IpVersion), - "DNS_NODES=''", - "RLIMIT_NOFILE=", - "SEED_SELF_HOST=true", - "RUN_JANITOR=true", - fmt.Sprintf("MAX_HEADER_LENGTH=%d", utils.Config.Realtime.MaxHeaderLength), - }, - ExposedPorts: nat.PortSet{"4000/tcp": {}}, - Healthcheck: &container.HealthConfig{ - // Podman splits command by spaces unless it's quoted, but curl header can't be quoted. - Test: []string{ - "CMD", "curl", "-sSfL", "--head", "-o", "/dev/null", - "-H", "Host:" + utils.Config.Realtime.TenantId, - "http://127.0.0.1:4000/api/ping", - }, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.RealtimeAliases, - }, - }, - }, - utils.RealtimeId, - ); err != nil { - return err - } - started = append(started, utils.RealtimeId) - } - - // Start PostgREST. - if utils.Config.Api.Enabled && !isContainerExcluded(utils.Config.Api.Image, excluded) { - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Api.Image, - Env: []string{ - fmt.Sprintf("PGRST_DB_URI=postgresql://authenticator:%s@%s:%d/%s", dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database), - "PGRST_DB_SCHEMAS=" + strings.Join(utils.Config.Api.Schemas, ","), - "PGRST_DB_EXTRA_SEARCH_PATH=" + strings.Join(utils.Config.Api.ExtraSearchPath, ","), - fmt.Sprintf("PGRST_DB_MAX_ROWS=%d", utils.Config.Api.MaxRows), - "PGRST_DB_ANON_ROLE=anon", - fmt.Sprintf("PGRST_JWT_SECRET=%s", jwks), - "PGRST_ADMIN_SERVER_PORT=3001", - }, - // PostgREST does not expose a shell for health check - }, - container.HostConfig{ - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.RestAliases, - }, - }, - }, - utils.RestId, - ); err != nil { - return err - } - started = append(started, utils.RestId) - } - - // Start Storage. - if isStorageEnabled { - dockerStoragePath := "/mnt" - storageEnv := []string{ - "DB_MIGRATIONS_FREEZE_AT=" + utils.Config.Storage.TargetMigration, - "ANON_KEY=" + utils.Config.Auth.AnonKey.Value, - "SERVICE_KEY=" + utils.Config.Auth.ServiceRoleKey.Value, - "AUTH_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, - fmt.Sprintf("JWT_JWKS=%s", jwks), - fmt.Sprintf("DATABASE_URL=postgresql://supabase_storage_admin:%s@%s:%d/%s", dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database), - fmt.Sprintf("FILE_SIZE_LIMIT=%v", utils.Config.Storage.FileSizeLimit), - "STORAGE_BACKEND=file", - "FILE_STORAGE_BACKEND_PATH=" + dockerStoragePath, - "TENANT_ID=stub", - // TODO: https://github.com/supabase/storage-api/issues/55 - "STORAGE_S3_REGION=" + utils.Config.Storage.S3Credentials.Region, - "GLOBAL_S3_BUCKET=stub", - fmt.Sprintf("ENABLE_IMAGE_TRANSFORMATION=%t", isImgProxyEnabled), - fmt.Sprintf("IMGPROXY_URL=http://%s:5001", utils.ImgProxyId), - "TUS_URL_PATH=/storage/v1/upload/resumable", - fmt.Sprintf("S3_PROTOCOL_ENABLED=%t", isS3ProtocolEnabled), - "S3_PROTOCOL_ACCESS_KEY_ID=" + utils.Config.Storage.S3Credentials.AccessKeyId, - "S3_PROTOCOL_ACCESS_KEY_SECRET=" + utils.Config.Storage.S3Credentials.SecretAccessKey, - "S3_PROTOCOL_PREFIX=/storage/v1", - "UPLOAD_FILE_SIZE_LIMIT=52428800000", - "UPLOAD_FILE_SIZE_LIMIT_STANDARD=5242880000", - "SIGNED_UPLOAD_URL_EXPIRATION_TIME=7200", - } - if isVectorBucketsEnabled { - storageEnv = appendStorageVectorEnv(storageEnv, dbConfig) - } - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Storage.Image, - Env: storageEnv, - Healthcheck: &container.HealthConfig{ - // For some reason, localhost resolves to IPv6 address on GitPod which breaks healthcheck. - Test: []string{ - "CMD", "wget", "--no-verbose", "--tries=1", "--spider", - "http://127.0.0.1:5000/status", - }, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - Binds: []string{utils.StorageId + ":" + dockerStoragePath}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.StorageAliases, - }, - }, - }, - utils.StorageId, - ); err != nil { - return err - } - started = append(started, utils.StorageId) - } - - // Start Storage ImgProxy. - if isStorageEnabled && isImgProxyEnabled { - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Storage.ImgProxyImage, - Env: []string{ - "IMGPROXY_BIND=:5001", - "IMGPROXY_LOCAL_FILESYSTEM_ROOT=/", - "IMGPROXY_USE_ETAG=/", - "IMGPROXY_MAX_SRC_RESOLUTION=50", - "IMGPROXY_MAX_SRC_FILE_SIZE=25000000", - "IMGPROXY_MAX_ANIMATION_FRAMES=60", - "IMGPROXY_ENABLE_WEBP_DETECTION=true", - "IMGPROXY_PRESETS=default=width:3000/height:8192", - "IMGPROXY_FORMAT_QUALITY=jpeg=80,avif=62,webp=80", - }, - Healthcheck: &container.HealthConfig{ - Test: []string{"CMD", "imgproxy", "health"}, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - VolumesFrom: []string{utils.StorageId}, - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.ImgProxyAliases, - }, - }, - }, - utils.ImgProxyId, - ); err != nil { - return err - } - started = append(started, utils.ImgProxyId) - } - - // Start all functions. - if utils.Config.EdgeRuntime.Enabled && !isContainerExcluded(utils.Config.EdgeRuntime.Image, excluded) { - dbUrl := fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database) - if err := serve.ServeFunctions(ctx, "", nil, "", dbUrl, serve.RuntimeOption{}, fsys); err != nil { - return err - } - started = append(started, utils.EdgeRuntimeId) - } - - // Start pg-meta. - if utils.Config.Studio.Enabled && !isContainerExcluded(utils.Config.Studio.PgmetaImage, excluded) { - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Studio.PgmetaImage, - Env: []string{ - "PG_META_PORT=8080", - "PG_META_DB_HOST=" + dbConfig.Host, - "PG_META_DB_NAME=" + dbConfig.Database, - "PG_META_DB_USER=" + dbConfig.User, - fmt.Sprintf("PG_META_DB_PORT=%d", dbConfig.Port), - "PG_META_DB_PASSWORD=" + dbConfig.Password, - }, - Healthcheck: &container.HealthConfig{ - Test: []string{"CMD-SHELL", `node --eval="fetch('http://127.0.0.1:8080/health').then((r) => {if (!r.ok) throw new Error(r.status)})"`}, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.PgmetaAliases, - }, - }, - }, - utils.PgmetaId, - ); err != nil { - return err - } - started = append(started, utils.PgmetaId) - } - - // Start Studio. - if utils.Config.Studio.Enabled && !isContainerExcluded(utils.Config.Studio.Image, excluded) { - binds, _, err := serve.PopulatePerFunctionConfigs(workdir, "", nil, fsys) - if err != nil { - return err - } - - // Mount snippets directory for Studio to access - hostSnippetsPath := filepath.Join(workdir, utils.SnippetsDir) - containerSnippetsPath := utils.ToDockerPath(hostSnippetsPath) - binds = append(binds, fmt.Sprintf("%s:%s:rw", hostSnippetsPath, containerSnippetsPath)) - binds = utils.RemoveDuplicates(binds) - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Studio.Image, - Env: buildStudioEnv(dbConfig, workdir, containerSnippetsPath), - Healthcheck: &container.HealthConfig{ - Test: []string{"CMD-SHELL", `node --eval="fetch('http://127.0.0.1:3000/api/platform/profile').then((r) => {if (!r.ok) throw new Error(r.status)})"`}, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - Binds: binds, - PortBindings: nat.PortMap{"3000/tcp": []nat.PortBinding{{ - HostPort: strconv.FormatUint(uint64(utils.Config.Studio.Port), 10), - }}}, - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.StudioAliases, - }, - }, - }, - utils.StudioId, - ); err != nil { - return err - } - started = append(started, utils.StudioId) - } - - // Start pooler. - if utils.Config.Db.Pooler.Enabled && !isContainerExcluded(utils.Config.Db.Pooler.Image, excluded) { - portSession := uint16(5432) - portTransaction := uint16(6543) - dockerPort := portTransaction - if utils.Config.Db.Pooler.PoolMode == config.SessionMode { - dockerPort = portSession - } - // Create pooler tenant - var poolerTenantBuf bytes.Buffer - if err := poolerTenantTemplate.Option("missingkey=error").Execute(&poolerTenantBuf, poolerTenant{ - DbHost: dbConfig.Host, - DbPort: dbConfig.Port, - DbDatabase: dbConfig.Database, - DbPassword: dbConfig.Password, - ExternalId: utils.Config.Db.Pooler.TenantId, - ModeType: utils.Config.Db.Pooler.PoolMode, - DefaultMaxClients: utils.Config.Db.Pooler.MaxClientConn, - DefaultPoolSize: utils.Config.Db.Pooler.DefaultPoolSize, - }); err != nil { - return errors.Errorf("failed to exec template: %w", err) - } - if _, err := utils.DockerStart( - ctx, - container.Config{ - Image: utils.Config.Db.Pooler.Image, - Env: []string{ - "PORT=4000", - fmt.Sprintf("PROXY_PORT_SESSION=%d", portSession), - fmt.Sprintf("PROXY_PORT_TRANSACTION=%d", portTransaction), - fmt.Sprintf("DATABASE_URL=ecto://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, "_supabase"), - "CLUSTER_POSTGRES=true", - "SECRET_KEY_BASE=" + utils.Config.Db.Pooler.SecretKeyBase, - "VAULT_ENC_KEY=" + utils.Config.Db.Pooler.EncryptionKey, - "API_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, - "METRICS_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, - "REGION=local", - "RUN_JANITOR=true", - "ERL_AFLAGS=-proto_dist inet_tcp", - "RLIMIT_NOFILE=", - }, - Cmd: []string{ - "/bin/sh", "-c", - fmt.Sprintf("/app/bin/migrate && /app/bin/supavisor eval '%s' && /app/bin/server", poolerTenantBuf.String()), - }, - ExposedPorts: nat.PortSet{ - "4000/tcp": {}, - nat.Port(fmt.Sprintf("%d/tcp", portSession)): {}, - nat.Port(fmt.Sprintf("%d/tcp", portTransaction)): {}, - }, - Healthcheck: &container.HealthConfig{ - Test: []string{"CMD", "curl", "-sSfL", "--head", "-o", "/dev/null", "http://127.0.0.1:4000/api/health"}, - Interval: 10 * time.Second, - Timeout: 2 * time.Second, - Retries: 3, - }, - }, - container.HostConfig{ - PortBindings: nat.PortMap{nat.Port(fmt.Sprintf("%d/tcp", dockerPort)): []nat.PortBinding{{ - HostPort: strconv.FormatUint(uint64(utils.Config.Db.Pooler.Port), 10), - }}}, - RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyUnlessStopped}, - }, - network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - utils.NetId: { - Aliases: utils.PoolerAliases, - }, - }, - }, - utils.PoolerId, - ); err != nil { - return err - } - started = append(started, utils.PoolerId) - } - - fmt.Fprintln(os.Stderr, "Waiting for health checks...") - if err := start.WaitForHealthyService(ctx, serviceTimeout, started...); err != nil { - if ignoreHealthCheck && utils.NoBackupVolume && slices.Contains(started, utils.StorageId) { - if storageErr := start.WaitForHealthyService(ctx, serviceTimeout, utils.StorageId); storageErr == nil { - if seedErr := buckets.Run(ctx, "", false, fsys); seedErr != nil { - return seedErr - } - } - } - return err - } - if utils.NoBackupVolume && slices.Contains(started, utils.StorageId) { - // Disable prompts when seeding - if err := buckets.Run(ctx, "", false, fsys); err != nil { - return err - } - } - _ = phtelemetry.FromContext(ctx).Capture(ctx, phtelemetry.EventStackStarted, nil, nil) - return nil -} - -func isContainerExcluded(imageName string, excluded map[string]bool) bool { - short := utils.ShortContainerImageName(imageName) - val, ok := excluded[short] - return ok && val -} - -func ExcludableContainers() []string { - names := []string{} - for _, image := range config.Images.Services() { - names = append(names, utils.ShortContainerImageName(image)) - } - return names -} - -func formatMapForEnvConfig(input map[string]string, output *bytes.Buffer) { - numOfKeyPairs := len(input) - i := 0 - for k, v := range input { - output.WriteString(k) - output.WriteString(":") - output.WriteString(v) - i++ - if i < numOfKeyPairs { - output.WriteString(",") - } - } -} - -func buildStudioEnv(dbConfig pgconn.Config, workdir, containerSnippetsPath string) []string { - return []string{ - "CURRENT_CLI_VERSION=" + utils.Version, - "STUDIO_PG_META_URL=http://" + utils.PgmetaId + ":8080", - "POSTGRES_PASSWORD=" + dbConfig.Password, - "SUPABASE_URL=http://" + utils.KongId + ":8000", - "SUPABASE_PUBLIC_URL=" + utils.Config.Studio.ApiUrl, - "AUTH_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, - "SUPABASE_ANON_KEY=" + utils.Config.Auth.AnonKey.Value, - "SUPABASE_SERVICE_KEY=" + utils.Config.Auth.ServiceRoleKey.Value, - "SUPABASE_PUBLISHABLE_KEY=" + utils.Config.Auth.PublishableKey.Value, - "SUPABASE_SECRET_KEY=" + utils.Config.Auth.SecretKey.Value, - "S3_PROTOCOL_ACCESS_KEY_ID=" + utils.Config.Storage.S3Credentials.AccessKeyId, - "S3_PROTOCOL_ACCESS_KEY_SECRET=" + utils.Config.Storage.S3Credentials.SecretAccessKey, - "LOGFLARE_PRIVATE_ACCESS_TOKEN=" + utils.Config.Analytics.ApiKey, - "OPENAI_API_KEY=" + utils.Config.Studio.OpenaiApiKey.Value, - "PGRST_DB_SCHEMAS=" + strings.Join(utils.Config.Api.Schemas, ","), - "PGRST_DB_EXTRA_SEARCH_PATH=" + strings.Join(utils.Config.Api.ExtraSearchPath, ","), - fmt.Sprintf("PGRST_DB_MAX_ROWS=%d", utils.Config.Api.MaxRows), - fmt.Sprintf("LOGFLARE_URL=http://%v:4000", utils.LogflareId), - fmt.Sprintf("NEXT_PUBLIC_ENABLE_LOGS=%v", utils.Config.Analytics.Enabled), - fmt.Sprintf("NEXT_ANALYTICS_BACKEND_PROVIDER=%v", utils.Config.Analytics.Backend), - "EDGE_FUNCTIONS_MANAGEMENT_FOLDER=" + utils.ToDockerPath(filepath.Join(workdir, utils.FunctionsDir)), - "SNIPPETS_MANAGEMENT_FOLDER=" + containerSnippetsPath, - // Ref: https://github.com/vercel/next.js/issues/51684#issuecomment-1612834913 - "HOSTNAME=0.0.0.0", - "POSTGRES_USER_READ_WRITE=postgres", - } -} - -func buildGotrueEnv(dbConfig pgconn.Config) []string { - var testOTP bytes.Buffer - if len(utils.Config.Auth.Sms.TestOTP) > 0 { - formatMapForEnvConfig(utils.Config.Auth.Sms.TestOTP, &testOTP) - } - mailerVerifyURL := strings.TrimRight(utils.Config.AuthExternalURL(), "/") + "/verify" - - return []string{ - "API_EXTERNAL_URL=" + utils.Config.AuthExternalURL(), - - "GOTRUE_API_HOST=0.0.0.0", - "GOTRUE_API_PORT=9999", - - "GOTRUE_DB_DRIVER=postgres", - fmt.Sprintf("GOTRUE_DB_DATABASE_URL=postgresql://supabase_auth_admin:%s@%s:%d/%s", dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database), - - "GOTRUE_SITE_URL=" + utils.Config.Auth.SiteUrl, - "GOTRUE_URI_ALLOW_LIST=" + strings.Join(utils.Config.Auth.AdditionalRedirectUrls, ","), - fmt.Sprintf("GOTRUE_DISABLE_SIGNUP=%v", !utils.Config.Auth.EnableSignup), - - "GOTRUE_JWT_ADMIN_ROLES=service_role", - "GOTRUE_JWT_AUD=authenticated", - "GOTRUE_JWT_DEFAULT_GROUP_NAME=authenticated", - fmt.Sprintf("GOTRUE_JWT_EXP=%v", utils.Config.Auth.JwtExpiry), - "GOTRUE_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value, - "GOTRUE_JWT_ISSUER=" + utils.Config.Auth.JwtIssuer, - - fmt.Sprintf("GOTRUE_EXTERNAL_EMAIL_ENABLED=%v", utils.Config.Auth.Email.EnableSignup), - fmt.Sprintf("GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED=%v", utils.Config.Auth.Email.DoubleConfirmChanges), - fmt.Sprintf("GOTRUE_MAILER_AUTOCONFIRM=%v", !utils.Config.Auth.Email.EnableConfirmations), - fmt.Sprintf("GOTRUE_MAILER_OTP_LENGTH=%v", utils.Config.Auth.Email.OtpLength), - fmt.Sprintf("GOTRUE_MAILER_OTP_EXP=%v", utils.Config.Auth.Email.OtpExpiry), - "GOTRUE_MAILER_TEMPLATE_RELOADING_ENABLED=true", - - fmt.Sprintf("GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED=%v", utils.Config.Auth.EnableAnonymousSignIns), - - fmt.Sprintf("GOTRUE_SMTP_MAX_FREQUENCY=%v", utils.Config.Auth.Email.MaxFrequency), - - "GOTRUE_MAILER_URLPATHS_INVITE=" + mailerVerifyURL, - "GOTRUE_MAILER_URLPATHS_CONFIRMATION=" + mailerVerifyURL, - "GOTRUE_MAILER_URLPATHS_RECOVERY=" + mailerVerifyURL, - "GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=" + mailerVerifyURL, - "GOTRUE_RATE_LIMIT_EMAIL_SENT=360000", - - fmt.Sprintf("GOTRUE_EXTERNAL_PHONE_ENABLED=%v", utils.Config.Auth.Sms.EnableSignup), - fmt.Sprintf("GOTRUE_SMS_AUTOCONFIRM=%v", !utils.Config.Auth.Sms.EnableConfirmations), - fmt.Sprintf("GOTRUE_SMS_MAX_FREQUENCY=%v", utils.Config.Auth.Sms.MaxFrequency), - "GOTRUE_SMS_OTP_EXP=6000", - "GOTRUE_SMS_OTP_LENGTH=6", - fmt.Sprintf("GOTRUE_SMS_TEMPLATE=%v", utils.Config.Auth.Sms.Template), - "GOTRUE_SMS_TEST_OTP=" + testOTP.String(), - - fmt.Sprintf("GOTRUE_PASSWORD_MIN_LENGTH=%v", utils.Config.Auth.MinimumPasswordLength), - fmt.Sprintf("GOTRUE_PASSWORD_REQUIRED_CHARACTERS=%v", utils.Config.Auth.PasswordRequirements.ToChar()), - fmt.Sprintf("GOTRUE_SECURITY_REFRESH_TOKEN_ROTATION_ENABLED=%v", utils.Config.Auth.EnableRefreshTokenRotation), - fmt.Sprintf("GOTRUE_SECURITY_REFRESH_TOKEN_REUSE_INTERVAL=%v", utils.Config.Auth.RefreshTokenReuseInterval), - fmt.Sprintf("GOTRUE_SECURITY_MANUAL_LINKING_ENABLED=%v", utils.Config.Auth.EnableManualLinking), - fmt.Sprintf("GOTRUE_SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION=%v", utils.Config.Auth.Email.SecurePasswordChange), - fmt.Sprintf("GOTRUE_MFA_PHONE_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.Phone.EnrollEnabled), - fmt.Sprintf("GOTRUE_MFA_PHONE_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.Phone.VerifyEnabled), - fmt.Sprintf("GOTRUE_MFA_TOTP_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.TOTP.EnrollEnabled), - fmt.Sprintf("GOTRUE_MFA_TOTP_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.TOTP.VerifyEnabled), - fmt.Sprintf("GOTRUE_MFA_WEB_AUTHN_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.WebAuthn.EnrollEnabled), - fmt.Sprintf("GOTRUE_MFA_WEB_AUTHN_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.WebAuthn.VerifyEnabled), - fmt.Sprintf("GOTRUE_MFA_MAX_ENROLLED_FACTORS=%v", utils.Config.Auth.MFA.MaxEnrolledFactors), - - fmt.Sprintf("GOTRUE_RATE_LIMIT_ANONYMOUS_USERS=%v", utils.Config.Auth.RateLimit.AnonymousUsers), - fmt.Sprintf("GOTRUE_RATE_LIMIT_TOKEN_REFRESH=%v", utils.Config.Auth.RateLimit.TokenRefresh), - fmt.Sprintf("GOTRUE_RATE_LIMIT_OTP=%v", utils.Config.Auth.RateLimit.SignInSignUps), - fmt.Sprintf("GOTRUE_RATE_LIMIT_VERIFY=%v", utils.Config.Auth.RateLimit.TokenVerifications), - fmt.Sprintf("GOTRUE_RATE_LIMIT_SMS_SENT=%v", utils.Config.Auth.RateLimit.SmsSent), - fmt.Sprintf("GOTRUE_RATE_LIMIT_WEB3=%v", utils.Config.Auth.RateLimit.Web3), - } -} - -// appendGotruePasskeyEnv wires the Auth container with passkey/WebAuthn -// settings from the [auth.passkey] and [auth.webauthn] config sections. Both -// sections are optional (nil when unset), so each block is guarded. -func appendGotruePasskeyEnv(env []string) []string { - if utils.Config.Auth.Passkey != nil { - env = append(env, fmt.Sprintf("GOTRUE_PASSKEY_ENABLED=%v", utils.Config.Auth.Passkey.Enabled)) - } - if w := utils.Config.Auth.Webauthn; w != nil { - env = append( - env, - "GOTRUE_WEBAUTHN_RP_ID="+w.RpId, - "GOTRUE_WEBAUTHN_RP_DISPLAY_NAME="+w.RpDisplayName, - "GOTRUE_WEBAUTHN_RP_ORIGINS="+strings.Join(w.RpOrigins, ","), - ) - } - return env -} - -func appendGotrueExternalProviderEnv(env []string) []string { - for name, config := range utils.Config.Auth.External { - redirectUri := config.RedirectUri - if redirectUri == "" { - redirectUri = utils.Config.Auth.JwtIssuer + "/callback" - } - env = append( - env, - fmt.Sprintf("GOTRUE_EXTERNAL_%s_ENABLED=%v", strings.ToUpper(name), config.Enabled), - fmt.Sprintf("GOTRUE_EXTERNAL_%s_CLIENT_ID=%s", strings.ToUpper(name), config.ClientId), - fmt.Sprintf("GOTRUE_EXTERNAL_%s_SECRET=%s", strings.ToUpper(name), config.Secret.Value), - fmt.Sprintf("GOTRUE_EXTERNAL_%s_SKIP_NONCE_CHECK=%t", strings.ToUpper(name), config.SkipNonceCheck), - fmt.Sprintf("GOTRUE_EXTERNAL_%s_EMAIL_OPTIONAL=%t", strings.ToUpper(name), config.EmailOptional), - fmt.Sprintf("GOTRUE_EXTERNAL_%s_REDIRECT_URI=%s", strings.ToUpper(name), redirectUri), - ) - if config.Url != "" { - env = append(env, fmt.Sprintf("GOTRUE_EXTERNAL_%s_URL=%s", strings.ToUpper(name), config.Url)) - } - } - return env -} - -// envOrDefault formats a "KEY=value" container env entry, preferring the -// operator's shell value for key when set and otherwise falling back to def. -func envOrDefault(key, def string) string { - if v, ok := os.LookupEnv(key); ok { - return key + "=" + v - } - return key + "=" + def -} - -// appendStorageVectorEnv wires the storage container with the vector-bucket -// env contract from supabase/storage#1094. The CLI provides three CLI-owned -// defaults that the operator can override from their shell environment: -// -// - VECTOR_BUCKET_PROVIDER selects the local provider; pgvector is the only -// locally-available implementation. -// - VECTOR_STORE_MIGRATIONS_ENABLED tells storage to run its vector-store -// migrations on boot. Defaults on so a fresh stack is usable, but operators -// who run those migrations out of band can disable it. -// - VECTOR_DATABASE_URL hands storage a connection string with createdb -// permission so it can manage its own vectors database. We default to the -// postgres superuser on the local stack, mirroring the existing DATABASE_URL -// credentials, but operators are expected to override this to reach an -// external postgres in self-hosted setups. -func appendStorageVectorEnv(env []string, dbConfig pgconn.Config) []string { - defaultVectorURL := fmt.Sprintf( - "postgresql://postgres:%s@%s:%d/%s", - dbConfig.Password, - dbConfig.Host, - dbConfig.Port, - dbConfig.Database, - ) - return append(env, - envOrDefault("VECTOR_ENABLED", "true"), - envOrDefault("VECTOR_BUCKET_PROVIDER", "pgvector"), - envOrDefault("VECTOR_STORE_MIGRATIONS_ENABLED", "true"), - envOrDefault("VECTOR_DATABASE_URL", defaultVectorURL), - ) -} - -func printSecurityNotice() { - fmt.Fprintln(os.Stderr, utils.Yellow("Local dev security notice")) - fmt.Fprintln(os.Stderr, "All services bind to 0.0.0.0 (network-accessible, not just localhost)") - fmt.Fprintln(os.Stderr, "API keys and JWT secrets are shared defaults. Do not use in production") - fmt.Fprintln(os.Stderr, "Studio, pgMeta (/pg/*), and analytics have no authentication") - fmt.Fprintln(os.Stderr) -} diff --git a/apps/cli-go/internal/start/start_test.go b/apps/cli-go/internal/start/start_test.go deleted file mode 100644 index a69f7bd8bc..0000000000 --- a/apps/cli-go/internal/start/start_test.go +++ /dev/null @@ -1,623 +0,0 @@ -package start - -import ( - "bytes" - "context" - "errors" - "net/http" - "regexp" - "strings" - "testing" - "time" - - composeTypes "github.com/compose-spec/compose-go/v2/types" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/volume" - "github.com/h2non/gock" - "github.com/jackc/pgconn" - "github.com/spf13/afero" - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - phtelemetry "github.com/supabase/cli/internal/telemetry" - "github.com/supabase/cli/internal/testing/apitest" - "github.com/supabase/cli/internal/testing/helper" - "github.com/supabase/cli/internal/utils" - supabaseapi "github.com/supabase/cli/pkg/api" - "github.com/supabase/cli/pkg/config" - "github.com/supabase/cli/pkg/pgtest" - "github.com/supabase/cli/pkg/storage" -) - -type fakeAnalytics struct { - enabled bool - captures []captureCall -} - -type captureCall struct { - distinctID string - event string - properties map[string]any - groups map[string]string -} - -func (f *fakeAnalytics) Enabled() bool { return f.enabled } -func (f *fakeAnalytics) Capture(distinctID string, event string, properties map[string]any, groups map[string]string) error { - f.captures = append(f.captures, captureCall{distinctID: distinctID, event: event, properties: properties, groups: groups}) - return nil -} -func (f *fakeAnalytics) Identify(distinctID string, properties map[string]any) error { return nil } -func (f *fakeAnalytics) Alias(distinctID string, alias string) error { return nil } -func (f *fakeAnalytics) GroupIdentify(groupType string, groupKey string, properties map[string]any) error { - return nil -} -func (f *fakeAnalytics) Close() error { return nil } - -func TestStartCommand(t *testing.T) { - t.Run("throws error on malformed config", func(t *testing.T) { - // Setup in-memory fs - fsys := afero.NewMemMapFs() - require.NoError(t, afero.WriteFile(fsys, utils.ConfigPath, []byte("malformed"), 0644)) - // Run test - err := Run(context.Background(), fsys, []string{}, false) - // Check error - assert.ErrorContains(t, err, "toml: expected = after a key, but the document ends there") - }) - - t.Run("throws error on missing docker", func(t *testing.T) { - // Setup in-memory fs - fsys := afero.NewMemMapFs() - require.NoError(t, utils.WriteConfig(fsys, false)) - // Setup mock docker - require.NoError(t, apitest.MockDocker(utils.Docker)) - defer gock.OffAll() - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers"). - ReplyError(errors.New("network error")) - // Run test - err := Run(context.Background(), fsys, []string{}, false) - // Check error - assert.ErrorContains(t, err, "network error") - assert.Empty(t, apitest.ListUnmatchedRequests()) - }) - - t.Run("show status if database is already running", func(t *testing.T) { - var running []container.Summary - for _, name := range utils.GetDockerIds() { - running = append(running, container.Summary{ - Names: []string{name + "_test"}, - }) - } - // Setup in-memory fs - fsys := afero.NewMemMapFs() - require.NoError(t, utils.WriteConfig(fsys, false)) - // Setup mock docker - require.NoError(t, apitest.MockDocker(utils.Docker)) - defer gock.OffAll() - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers"). - Reply(http.StatusOK). - JSON(container.InspectResponse{}) - - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers/supabase_db_start/json"). - Reply(http.StatusOK). - JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ - State: &container.State{ - Running: true, - }, - }}) - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers/json"). - Reply(http.StatusOK). - JSON(running) - // Run test - err := Run(context.Background(), fsys, []string{}, false) - // Check error - assert.NoError(t, err) - assert.Empty(t, apitest.ListUnmatchedRequests()) - }) - - t.Run("show status without health check if database is already running and ignored", func(t *testing.T) { - var running []container.Summary - for _, name := range utils.GetDockerIds() { - running = append(running, container.Summary{ - Names: []string{name + "_test"}, - }) - } - // Setup in-memory fs - fsys := afero.NewMemMapFs() - require.NoError(t, utils.WriteConfig(fsys, false)) - // Setup mock docker - require.NoError(t, apitest.MockDocker(utils.Docker)) - defer gock.OffAll() - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers"). - Reply(http.StatusOK). - JSON(container.InspectResponse{}) - - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers/supabase_db_start/json"). - Reply(http.StatusOK). - JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ - State: &container.State{ - Running: true, - Health: &container.Health{ - Status: types.Unhealthy, - }, - }, - }}) - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers/json"). - Reply(http.StatusOK). - JSON(running) - // Run test - err := Run(context.Background(), fsys, []string{}, true) - // Check error - assert.NoError(t, err) - assert.Empty(t, apitest.ListUnmatchedRequests()) - }) -} - -func TestShouldMountRootDockerSocket(t *testing.T) { - t.Run("returns true for Docker Desktop and Colima sockets", func(t *testing.T) { - assert.True(t, shouldMountRootDockerSocket("/Users/test/.docker/run/docker.sock")) - assert.True(t, shouldMountRootDockerSocket("/Users/test/.docker/desktop/docker.sock")) - assert.True(t, shouldMountRootDockerSocket("/Users/test/.colima/default/docker.sock")) - assert.True(t, shouldMountRootDockerSocket("/Users/test/.colima/local/docker.sock")) - assert.True(t, shouldMountRootDockerSocket("/Users/test/.colima/docker.sock")) - }) - - t.Run("returns false for directly mountable sockets", func(t *testing.T) { - assert.False(t, shouldMountRootDockerSocket("/Users/test/.orbstack/run/docker.sock")) - }) -} - -func TestDatabaseStart(t *testing.T) { - t.Run("starts database locally", func(t *testing.T) { - // Setup in-memory fs - fsys := afero.NewMemMapFs() - t.Setenv("SUPABASE_HOME", "/tmp/supabase-home") - analytics := &fakeAnalytics{enabled: true} - service, err := phtelemetry.NewService(fsys, phtelemetry.Options{ - Analytics: analytics, - Now: func() time.Time { return time.Date(2026, time.April, 1, 12, 0, 0, 0, time.UTC) }, - }) - require.NoError(t, err) - require.NoError(t, phtelemetry.SaveLinkedProject(supabaseapi.V1ProjectWithDatabaseResponse{ - Ref: "proj_123", - OrganizationId: "org_123", - }, fsys)) - ctx := phtelemetry.WithService(context.Background(), service) - // Setup mock docker - require.NoError(t, apitest.MockDocker(utils.Docker)) - defer gock.OffAll() - gock.New(utils.Docker.DaemonHost()). - Head("/_ping"). - Reply(http.StatusOK) - gock.New(utils.Docker.DaemonHost()). - Post("/v" + utils.Docker.ClientVersion() + "/networks/create"). - Reply(http.StatusCreated). - JSON(network.CreateResponse{}) - // Caches all dependencies. Each image is inspected several times during start: - // the compose pre-pull, the ensureImagesCached completeness pass, and the - // per-container DockerStart. Persist the inspect mocks so every lookup is a hit. - imageUrl := utils.GetRegistryImageUrl(utils.Config.Db.Image) - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/images/" + imageUrl + "/json"). - Persist(). - Reply(http.StatusOK). - JSON(image.InspectResponse{}) - for _, img := range config.Images.Services() { - service := utils.GetRegistryImageUrl(img) - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/images/" + service + "/json"). - Persist(). - Reply(http.StatusOK). - JSON(image.InspectResponse{}) - } - // Start postgres - utils.DbId = "test-postgres" - utils.Config.Db.Port = 54322 - utils.Config.Db.MajorVersion = 15 - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.DbId). - Reply(http.StatusNotFound) - apitest.MockDockerStart(utils.Docker, imageUrl, utils.DbId) - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Realtime.Image), "test-realtime") - require.NoError(t, apitest.MockDockerLogs(utils.Docker, "test-realtime", "")) - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Storage.Image), "test-storage") - require.NoError(t, apitest.MockDockerLogs(utils.Docker, "test-storage", "")) - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Auth.Image), "test-auth") - require.NoError(t, apitest.MockDockerLogs(utils.Docker, "test-auth", "")) - // Start services - utils.KongId = "test-kong" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Api.KongImage), utils.KongId) - utils.GotrueId = "test-gotrue" - utils.Config.Auth.EnableSignup = true - utils.Config.Auth.Email.EnableSignup = true - utils.Config.Auth.Email.DoubleConfirmChanges = true - utils.Config.Auth.Email.EnableConfirmations = true - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Auth.Image), utils.GotrueId) - utils.InbucketId = "test-inbucket" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Inbucket.Image), utils.InbucketId) - utils.RealtimeId = "test-realtime" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Realtime.Image), utils.RealtimeId) - utils.RestId = "test-rest" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Api.Image), utils.RestId) - utils.StorageId = "test-storage" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Storage.Image), utils.StorageId) - utils.ImgProxyId = "test-imgproxy" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Storage.ImgProxyImage), utils.ImgProxyId) - utils.EdgeRuntimeId = "test-edge-runtime" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.EdgeRuntime.Image), utils.EdgeRuntimeId) - utils.PgmetaId = "test-pgmeta" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Studio.PgmetaImage), utils.PgmetaId) - utils.StudioId = "test-studio" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Studio.Image), utils.StudioId) - utils.LogflareId = "test-logflare" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Analytics.Image), utils.LogflareId) - utils.VectorId = "test-vector" - apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.Config.Analytics.VectorImage), utils.VectorId) - // Setup mock postgres: with auto_expose_new_tables unset, the default Data API GRANTs - // are revoked by default during database setup. - conn := pgtest.NewConn() - defer conn.Close(t) - helper.MockApiPrivilegesRevoke(conn) - // Setup health probes - started := []string{ - utils.DbId, utils.KongId, utils.GotrueId, utils.InbucketId, utils.RealtimeId, - utils.StorageId, utils.ImgProxyId, utils.EdgeRuntimeId, utils.PgmetaId, utils.StudioId, - utils.LogflareId, utils.RestId, utils.VectorId, - } - for _, c := range started { - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers/" + c + "/json"). - Reply(http.StatusOK). - JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ - State: &container.State{ - Running: true, - Health: &container.Health{Status: types.Healthy}, - }, - }}) - } - gock.New(utils.Config.Api.ExternalUrl). - Head("/rest-admin/v1/ready"). - Reply(http.StatusOK) - gock.New(utils.Config.Api.ExternalUrl). - Head("/functions/v1/_internal/health"). - Reply(http.StatusOK) - // Seed tenant services - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.StorageId + "/json"). - Reply(http.StatusOK). - JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ - State: &container.State{ - Running: true, - Health: &container.Health{Status: types.Healthy}, - }, - }}) - gock.New(utils.Config.Api.ExternalUrl). - Get("/storage/v1/bucket"). - Reply(http.StatusOK). - JSON([]storage.BucketResponse{}) - gock.New(utils.Config.Api.ExternalUrl). - Post("/storage/v1/vector/ListVectorBuckets"). - Reply(http.StatusOK). - JSON(storage.ListVectorBucketsResponse{}) - // Run test - err = run(ctx, fsys, []string{}, pgconn.Config{Host: utils.DbId}, false, conn.Intercept) - // Check error - assert.NoError(t, err) - assert.Empty(t, apitest.ListUnmatchedRequests()) - require.Len(t, analytics.captures, 1) - assert.Equal(t, phtelemetry.EventStackStarted, analytics.captures[0].event) - assert.Equal(t, map[string]string{ - phtelemetry.GroupOrganization: "org_123", - phtelemetry.GroupProject: "proj_123", - }, analytics.captures[0].groups) - }) - - t.Run("skips excluded containers", func(t *testing.T) { - // Setup in-memory fs - fsys := afero.NewMemMapFs() - // Setup mock docker - require.NoError(t, apitest.MockDocker(utils.Docker)) - defer gock.OffAll() - gock.New(utils.Docker.DaemonHost()). - Head("/_ping"). - Reply(http.StatusOK) - gock.New(utils.Docker.DaemonHost()). - Post("/v" + utils.Docker.ClientVersion() + "/networks/create"). - Reply(http.StatusCreated). - JSON(network.CreateResponse{}) - // Caches all dependencies. The db image is inspected by the compose pre-pull, - // the ensureImagesCached completeness pass, and DockerStart, so persist the mock. - imageUrl := utils.GetRegistryImageUrl(utils.Config.Db.Image) - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/images/" + imageUrl + "/json"). - Persist(). - Reply(http.StatusOK). - JSON(image.InspectResponse{}) - // Start postgres - utils.DbId = "test-postgres" - utils.Config.Db.Port = 54322 - utils.Config.Db.MajorVersion = 15 - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.DbId). - Reply(http.StatusOK). - JSON(volume.Volume{}) - apitest.MockDockerStart(utils.Docker, imageUrl, utils.DbId) - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/json"). - Reply(http.StatusOK). - JSON(container.InspectResponse{ContainerJSONBase: &container.ContainerJSONBase{ - State: &container.State{ - Running: true, - Health: &container.Health{Status: types.Healthy}, - }, - }}) - // Run test - exclude := ExcludableContainers() - exclude = append(exclude, "invalid", exclude[0]) - err := run(context.Background(), fsys, exclude, pgconn.Config{Host: utils.DbId}, false) - // Check error - assert.NoError(t, err) - assert.Empty(t, apitest.ListUnmatchedRequests()) - }) -} - -func TestEnsureImagesCached(t *testing.T) { - // Force a single registry candidate per image so the resolved URL is the raw - // image name, keeping the mocks simple. The multi-registry fallback itself is - // covered by utils.TestPullImage. - viper.Set("INTERNAL_IMAGE_REGISTRY", "docker.io") - t.Cleanup(func() { viper.Set("INTERNAL_IMAGE_REGISTRY", "") }) - - t.Run("pulls images the best-effort pre-pull skipped", func(t *testing.T) { - // Setup mock docker - require.NoError(t, apitest.MockDocker(utils.Docker)) - defer gock.OffAll() - cached := utils.GetRegistryImageUrl("test-image-cached") - missing := utils.GetRegistryImageUrl("test-image-missing") - // Already cached locally: resolved without a pull. - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/images/" + cached + "/json"). - Reply(http.StatusOK). - JSON(image.InspectResponse{}) - // Missed by the compose pre-pull: must be pulled before ensureImagesCached returns. - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/images/" + missing + "/json"). - Reply(http.StatusNotFound) - gock.New(utils.Docker.DaemonHost()). - Post("/v"+utils.Docker.ClientVersion()+"/images/create"). - MatchParam("fromImage", missing). - MatchParam("tag", "latest"). - Reply(http.StatusAccepted) - // Run test - project := composeTypes.Project{ - Name: "supabase-cli", - Services: composeTypes.Services{ - "cached": {Name: "cached", Image: cached}, - "missing": {Name: "missing", Image: missing}, - }, - } - err := ensureImagesCached(context.Background(), project) - // Check error: gock.IsDone proves the missed image's images/create mock was - // consumed, i.e. the pull happened before ensureImagesCached returned. A no-op - // completeness pass would leave it pending and fail this assertion. - assert.NoError(t, err) - assert.True(t, gock.IsDone()) - assert.Empty(t, apitest.ListUnmatchedRequests()) - }) - - t.Run("returns an error when an image cannot be resolved", func(t *testing.T) { - // Setup mock docker - require.NoError(t, apitest.MockDocker(utils.Docker)) - defer gock.OffAll() - broken := utils.GetRegistryImageUrl("test-image-broken") - gock.New(utils.Docker.DaemonHost()). - Get("/v" + utils.Docker.ClientVersion() + "/images/" + broken + "/json"). - Reply(http.StatusServiceUnavailable) - // Run test - project := composeTypes.Project{ - Name: "supabase-cli", - Services: composeTypes.Services{ - "broken": {Name: "broken", Image: broken}, - }, - } - err := ensureImagesCached(context.Background(), project) - // Check error: a failed resolve must propagate so run() aborts before any - // container is created. - assert.Error(t, err) - assert.Empty(t, apitest.ListUnmatchedRequests()) - }) -} - -func TestBuildGotrueEnv(t *testing.T) { - original := utils.Config - t.Cleanup(func() { - utils.Config = original - }) - - t.Run("uses auth scoped external url and absolute mailer verify urls", func(t *testing.T) { - utils.Config = config.NewConfig() - utils.Config.Api.ExternalUrl = "http://127.0.0.1:54321" - utils.Config.Auth.ExternalUrl = "http://127.0.0.1:54321/auth/v1" - utils.Config.Auth.JwtIssuer = utils.Config.Auth.ExternalUrl - utils.Config.Auth.SiteUrl = "http://127.0.0.1:3000" - provider := utils.Config.Auth.External["github"] - provider.Enabled = true - provider.ClientId = "client-id" - provider.Secret.Value = "secret" - utils.Config.Auth.External["github"] = provider - - env := envToMap(appendGotrueExternalProviderEnv(buildGotrueEnv(pgconn.Config{ - Host: "db", - Port: 5432, - Database: "postgres", - Password: "postgres", - }))) - - assert.Equal(t, "http://127.0.0.1:54321/auth/v1", env["API_EXTERNAL_URL"]) - assert.Equal(t, "http://127.0.0.1:54321/auth/v1", env["GOTRUE_JWT_ISSUER"]) - assert.Equal(t, "http://127.0.0.1:54321/auth/v1/verify", env["GOTRUE_MAILER_URLPATHS_INVITE"]) - assert.Equal(t, "http://127.0.0.1:54321/auth/v1/verify", env["GOTRUE_MAILER_URLPATHS_CONFIRMATION"]) - assert.Equal(t, "http://127.0.0.1:54321/auth/v1/verify", env["GOTRUE_MAILER_URLPATHS_RECOVERY"]) - assert.Equal(t, "http://127.0.0.1:54321/auth/v1/verify", env["GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE"]) - assert.Equal(t, "http://127.0.0.1:54321/auth/v1/callback", env["GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI"]) - }) - - t.Run("preserves explicit provider redirect override", func(t *testing.T) { - utils.Config = config.NewConfig() - utils.Config.Api.ExternalUrl = "http://127.0.0.1:54321" - utils.Config.Auth.ExternalUrl = "http://127.0.0.1:54321/auth/v1" - utils.Config.Auth.JwtIssuer = "https://issuer.example.com/auth/v1" - utils.Config.Auth.SiteUrl = "http://127.0.0.1:3000" - provider := utils.Config.Auth.External["azure"] - provider.Enabled = true - provider.RedirectUri = "https://example.com/custom/callback" - utils.Config.Auth.External["azure"] = provider - - env := envToMap(appendGotrueExternalProviderEnv(buildGotrueEnv(pgconn.Config{}))) - - assert.Equal(t, "http://127.0.0.1:54321/auth/v1", env["API_EXTERNAL_URL"]) - assert.Equal(t, "https://issuer.example.com/auth/v1", env["GOTRUE_JWT_ISSUER"]) - assert.Equal(t, "http://127.0.0.1:54321/auth/v1/verify", env["GOTRUE_MAILER_URLPATHS_INVITE"]) - assert.Equal(t, "https://example.com/custom/callback", env["GOTRUE_EXTERNAL_AZURE_REDIRECT_URI"]) - }) - - t.Run("wires passkey and webauthn settings", func(t *testing.T) { - utils.Config = config.NewConfig() - utils.Config.Auth.Passkey = &config.Passkey{Enabled: true} - utils.Config.Auth.Webauthn = &config.Webauthn{ - RpDisplayName: "Supabase", - RpId: "localhost", - RpOrigins: []string{"http://127.0.0.1:5173", "http://localhost:5173"}, - } - - env := envToMap(appendGotruePasskeyEnv(buildGotrueEnv(pgconn.Config{}))) - - assert.Equal(t, "true", env["GOTRUE_PASSKEY_ENABLED"]) - assert.Equal(t, "localhost", env["GOTRUE_WEBAUTHN_RP_ID"]) - assert.Equal(t, "Supabase", env["GOTRUE_WEBAUTHN_RP_DISPLAY_NAME"]) - assert.Equal(t, "http://127.0.0.1:5173,http://localhost:5173", env["GOTRUE_WEBAUTHN_RP_ORIGINS"]) - }) - - t.Run("omits passkey and webauthn env when sections are unset", func(t *testing.T) { - utils.Config = config.NewConfig() - - env := envToMap(appendGotruePasskeyEnv(buildGotrueEnv(pgconn.Config{}))) - - _, hasPasskey := env["GOTRUE_PASSKEY_ENABLED"] - _, hasRpId := env["GOTRUE_WEBAUTHN_RP_ID"] - assert.False(t, hasPasskey) - assert.False(t, hasRpId) - }) -} - -func TestBuildStudioEnv(t *testing.T) { - originalConfig := utils.Config - originalKongId := utils.KongId - originalPgmetaId := utils.PgmetaId - originalLogflareId := utils.LogflareId - originalVersion := utils.Version - t.Cleanup(func() { - utils.Config = originalConfig - utils.KongId = originalKongId - utils.PgmetaId = originalPgmetaId - utils.LogflareId = originalLogflareId - utils.Version = originalVersion - }) - - utils.Config = config.NewConfig() - utils.Config.Studio.ApiUrl = "http://127.0.0.1:54321" - utils.Config.Auth.JwtSecret.Value = "jwt-secret" - utils.Config.Auth.AnonKey.Value = "anon-key" - utils.Config.Auth.ServiceRoleKey.Value = "service-role-key" - utils.Config.Auth.PublishableKey.Value = "sb_publishable_test" - utils.Config.Auth.SecretKey.Value = "sb_secret_test" - utils.Config.Storage.S3Credentials.AccessKeyId = "s3-access-key" - utils.Config.Storage.S3Credentials.SecretAccessKey = "s3-secret-key" - utils.KongId = "test-kong" - utils.PgmetaId = "test-pgmeta" - utils.LogflareId = "test-logflare" - utils.Version = "test-version" - - env := envToMap(buildStudioEnv( - pgconn.Config{Password: "postgres"}, - "/project", - "/project/supabase/.temp/snippets", - )) - - assert.Equal(t, "anon-key", env["SUPABASE_ANON_KEY"]) - assert.Equal(t, "service-role-key", env["SUPABASE_SERVICE_KEY"]) - assert.Equal(t, "sb_publishable_test", env["SUPABASE_PUBLISHABLE_KEY"]) - assert.Equal(t, "sb_secret_test", env["SUPABASE_SECRET_KEY"]) - assert.Equal(t, "s3-access-key", env["S3_PROTOCOL_ACCESS_KEY_ID"]) - assert.Equal(t, "s3-secret-key", env["S3_PROTOCOL_ACCESS_KEY_SECRET"]) - assert.Equal(t, "http://test-kong:8000", env["SUPABASE_URL"]) - assert.Equal(t, "http://test-pgmeta:8080", env["STUDIO_PG_META_URL"]) -} - -func TestFormatMapForEnvConfig(t *testing.T) { - t.Run("It produces the correct format and removes the trailing comma", func(t *testing.T) { - testcases := []struct { - key string - value string - expected string - }{ - { - key: "123456", - value: "123456", - expected: `^\w{6}:\w{6}$`, - }, - { - key: "234567", - value: "234567", - expected: `^\w{6}:\w{6},\w{6}:\w{6}$`, - }, - { - key: "345678", - value: "345678", - expected: `^\w{6}:\w{6},\w{6}:\w{6},\w{6}:\w{6}$`, - }, - { - key: "456789", - value: "456789", - expected: `^\w{6}:\w{6},\w{6}:\w{6},\w{6}:\w{6},\w{6}:\w{6}$`, - }, - } - - output := bytes.Buffer{} - input := map[string]string{} - formatMapForEnvConfig(input, &output) - if len(output.Bytes()) > 0 { - t.Error("No values should be expected when empty map is provided") - } - - for _, c := range testcases { - output.Reset() - input[c.key] = c.value - formatMapForEnvConfig(input, &output) - result := output.String() - r, err := regexp.Compile(c.expected) - require.NoError(t, err) - assert.Regexp(t, r, result) - } - }) -} - -func envToMap(env []string) map[string]string { - result := make(map[string]string, len(env)) - for _, item := range env { - key, value, ok := strings.Cut(item, "=") - if ok { - result[key] = value - } - } - return result -} diff --git a/apps/cli-go/internal/start/templates/custom_nginx.template b/apps/cli-go/internal/start/templates/custom_nginx.template deleted file mode 100644 index e1417cc5ba..0000000000 --- a/apps/cli-go/internal/start/templates/custom_nginx.template +++ /dev/null @@ -1,29 +0,0 @@ -pid pids/nginx.pid; # this setting is mandatory -error_log logs/error.log ${{LOG_LEVEL}}; # can be set by kong.conf - -daemon ${{NGINX_DAEMON}}; # can be set by kong.conf -worker_processes ${{NGINX_WORKER_PROCESSES}}; # can be set by kong.conf - -events { - multi_accept on; -} - -http { - # here, we declare our custom location serving our website - # (or API portal) which we can optimize for serving static assets - server { - server_name email_templates; - listen 0.0.0.0:8088 reuseport backlog=16384; - - access_log logs/email_templates_access.log; - error_log logs/error.log notice; - - location /email { - autoindex on; - root /home/kong/templates; - } - } - - # include default Kong Nginx config - include 'nginx-kong.conf'; -} diff --git a/apps/cli-go/internal/start/templates/kong.yml b/apps/cli-go/internal/start/templates/kong.yml deleted file mode 100644 index 4ff1b36043..0000000000 --- a/apps/cli-go/internal/start/templates/kong.yml +++ /dev/null @@ -1,240 +0,0 @@ -_format_version: "1.1" -services: - # Tenant project endpoints - - name: auth-v1-open - _comment: "GoTrue external /auth/v1/verify* -> internal root /verify*" - url: http://{{ .GotrueId }}:9999/verify - routes: - - name: auth-v1-open - strip_path: true - paths: - - /auth/v1/verify - plugins: - - name: cors - - name: auth-v1-open-callback - _comment: "GoTrue external /auth/v1/callback* -> internal root /callback*" - url: http://{{ .GotrueId }}:9999/callback - routes: - - name: auth-v1-open-callback - strip_path: true - paths: - - /auth/v1/callback - plugins: - - name: cors - - name: auth-v1-open-authorize - _comment: "GoTrue external /auth/v1/authorize* -> internal root /authorize*" - url: http://{{ .GotrueId }}:9999/authorize - routes: - - name: auth-v1-open-authorize - strip_path: true - paths: - - /auth/v1/authorize - plugins: - - name: cors - - name: auth-v1 - _comment: "GoTrue external /auth/v1/* -> internal root /*" - url: http://{{ .GotrueId }}:9999/ - routes: - - name: auth-v1-all - strip_path: true - paths: - - /auth/v1/ - plugins: - - name: cors - - name: request-transformer - config: - add: - headers: - - "Authorization: {{ .BearerToken }}" - replace: - headers: - - "Authorization: {{ .BearerToken }}" - - name: rest-v1 - _comment: "PostgREST: /rest/v1/* -> http://rest:3000/*" - url: http://{{ .RestId }}:3000/ - routes: - - name: rest-v1-all - strip_path: true - paths: - - /rest/v1/ - plugins: - - name: cors - - name: request-transformer - config: - add: - headers: - - "Authorization: {{ .BearerToken }}" - replace: - headers: - - "Authorization: {{ .BearerToken }}" - - name: rest-admin-v1 - _comment: "PostgREST: /rest-admin/v1/* -> http://rest:3001/*" - url: http://{{ .RestId }}:3001/ - routes: - - name: rest-admin-v1-all - strip_path: true - paths: - - /rest-admin/v1/ - plugins: - - name: cors - # TODO: validate apikey - - name: graphql-v1 - _comment: "PostgREST: /graphql/v1 -> http://rest:3000/rpc/graphql" - url: http://{{ .RestId }}:3000/rpc/graphql - routes: - - name: graphql-v1-all - strip_path: true - paths: - - /graphql/v1 - plugins: - - name: cors - - name: request-transformer - config: - add: - headers: - - "Content-Profile: graphql_public" - - "Authorization: {{ .BearerToken }}" - replace: - headers: - - "Authorization: {{ .BearerToken }}" - - name: realtime-v1-ws - _comment: "Realtime: /realtime/v1/* -> ws://realtime:4000/socket/websocket" - url: http://{{ .RealtimeId }}:4000/socket - protocol: ws - routes: - - name: realtime-v1-ws - strip_path: true - paths: - - /realtime/v1/ - plugins: - - name: cors - - name: request-transformer - config: - replace: - querystring: - - "apikey:{{ .QueryToken }}" - - name: realtime-v1-rest - _comment: "Realtime: /realtime/v1/* -> http://realtime:4000/api/*" - url: http://{{ .RealtimeId }}:4000/api - protocol: http - routes: - - name: realtime-v1-rest - strip_path: true - paths: - - /realtime/v1/api - plugins: - - name: cors - - name: request-transformer - config: - add: - headers: - - "Authorization: {{ .BearerToken }}" - replace: - headers: - - "Authorization: {{ .BearerToken }}" - # S3-compatible storage endpoint (no Authorization header transformation) - - name: storage-v1-s3 - _comment: "Storage S3: /storage/v1/s3/* -> http://storage-api:5000/s3/*" - url: http://{{ .StorageId }}:5000/s3 - routes: - - name: storage-v1-s3-all - strip_path: true - paths: - - /storage/v1/s3/ - plugins: - - name: cors - # Note: No request-transformer plugin for Authorization header - # S3 presigned URLs require the original AWS signature in the Authorization header - # Adding/replacing with Bearer token would break S3 signature validation - # Regular storage API endpoint (with Authorization header transformation) - - name: storage-v1 - _comment: "Storage API: /storage/v1/* -> http://storage-api:5000/*" - url: http://{{ .StorageId }}:5000/ - routes: - - name: storage-v1-all - strip_path: true - paths: - - /storage/v1/ - plugins: - - name: cors - - name: request-transformer - config: - add: - headers: - - "Authorization: {{ .BearerToken }}" - replace: - headers: - - "Authorization: {{ .BearerToken }}" - - name: functions-v1 - _comment: "Functions: /functions/v1/* -> http://edge-runtime:8081/*" - url: http://{{ .EdgeRuntimeId }}:8081/ - # Set request idle timeout to 150s to match hosted project - # Ref: https://supabase.com/docs/guides/functions/limits - read_timeout: 150000 - routes: - - name: functions-v1-all - strip_path: true - paths: - - /functions/v1/ - plugins: - - name: cors - - name: request-transformer - config: - add: - headers: - - "sb-api-key: {{ .BearerToken }}" - replace: - headers: - - "sb-api-key: {{ .BearerToken }}" - # Management API endpoints - - name: well-known-oauth - _comment: "GoTrue: /.well-known/oauth-authorization-server -> http://auth:9999/.well-known/oauth-authorization-server" - url: http://{{ .GotrueId }}:9999/.well-known/oauth-authorization-server - routes: - - name: well-known-oauth - strip_path: true - paths: - - /.well-known/oauth-authorization-server - plugins: - - name: cors - - name: pg-meta - _comment: "pg-meta: /pg/* -> http://pg-meta:8080/*" - url: http://{{ .PgmetaId }}:8080/ - routes: - - name: pg-meta-all - strip_path: true - paths: - - /pg/ - plugins: - - name: cors - - name: analytics-v1 - _comment: "Analytics: /analytics/v1/* -> http://logflare:4000/*" - url: http://{{ .LogflareId }}:4000/ - routes: - - name: analytics-v1-all - strip_path: true - paths: - - /analytics/v1/ - plugins: - - name: cors - - name: pooler-v2-ws - _comment: "Pooler: /pooler/v2/* -> ws://pooler:4000/v2/*" - url: http://{{ .PoolerId }}:4000/v2 - protocol: ws - routes: - - name: pooler-v2-ws - strip_path: true - paths: - - /pooler/v2/ - plugins: - - name: cors - - name: mcp - _comment: "MCP: /mcp -> http://studio:3000/api/mcp" - url: http://{{ .StudioId }}:3000/api/mcp - routes: - - name: mcp - strip_path: true - paths: - - /mcp - plugins: - - name: cors diff --git a/apps/cli-go/internal/start/templates/pooler.exs b/apps/cli-go/internal/start/templates/pooler.exs deleted file mode 100644 index 3766d64b52..0000000000 --- a/apps/cli-go/internal/start/templates/pooler.exs +++ /dev/null @@ -1,30 +0,0 @@ -{:ok, _} = Application.ensure_all_started(:supavisor) - -{:ok, version} = - case Supavisor.Repo.query!("select version()") do - %{rows: [[ver]]} -> Supavisor.Helpers.parse_pg_version(ver) - _ -> nil - end - -params = %{ - "external_id" => "{{ .ExternalId }}", - "db_host" => "{{ .DbHost }}", - "db_port" => {{ .DbPort }}, - "db_database" => "{{ .DbDatabase }}", - "require_user" => false, - "auth_query" => "SELECT * FROM pgbouncer.get_auth($1)", - "default_max_clients" => {{ .DefaultMaxClients }}, - "default_pool_size" => {{ .DefaultPoolSize }}, - "default_parameter_status" => %{"server_version" => version}, - "users" => [%{ - "db_user" => "pgbouncer", - "db_password" => "{{ .DbPassword }}", - "mode_type" => "{{ .ModeType }}", - "pool_size" => {{ .DefaultPoolSize }}, - "is_manager" => true - }] -} - -if !Supavisor.Tenants.get_tenant_by_external_id(params["external_id"]) do - {:ok, _} = Supavisor.Tenants.create_tenant(params) -end diff --git a/apps/cli-go/internal/start/templates/vector.yaml b/apps/cli-go/internal/start/templates/vector.yaml deleted file mode 100644 index bf06984735..0000000000 --- a/apps/cli-go/internal/start/templates/vector.yaml +++ /dev/null @@ -1,252 +0,0 @@ -api: - enabled: true - address: 0.0.0.0:9001 - -sources: - docker_host: - type: docker_logs - exclude_containers: - - "{{ .VectorId }}" - -transforms: - project_logs: - type: remap - inputs: - - docker_host - source: |- - .project = "default" - .event_message = del(.message) - .appname = del(.container_name) - del(.container_created_at) - del(.container_id) - del(.source_type) - del(.stream) - del(.label) - del(.image) - del(.host) - del(.stream) - router: - type: route - inputs: - - project_logs - route: - kong: '.appname == "{{ .KongId }}"' - auth: '.appname == "{{ .GotrueId }}"' - rest: '.appname == "{{ .RestId }}"' - realtime: '.appname == "{{ .RealtimeId }}"' - storage: '.appname == "{{ .StorageId }}"' - functions: '.appname == "{{ .EdgeRuntimeId }}"' - db: '.appname == "{{ .DbId }}"' - # Ignores non nginx errors since they are related with kong booting up - kong_logs: - type: remap - inputs: - - router.kong - source: |- - req, err = parse_nginx_log(.event_message, "combined") - if err == null { - .timestamp = req.timestamp - .metadata.request.headers.referer = req.referer - .metadata.request.headers.user_agent = req.agent - .metadata.request.headers.cf_connecting_ip = req.client - .metadata.response.status_code = req.status - url, split_err = split(req.request, " ") - if split_err == null { - .metadata.request.method = url[0] - .metadata.request.path = url[1] - .metadata.request.protocol = url[2] - } - } - if err != null { - abort - } - # Ignores non nginx errors since they are related with kong booting up - kong_err: - type: remap - inputs: - - router.kong - source: |- - .metadata.request.method = "GET" - .metadata.response.status_code = 200 - parsed, err = parse_nginx_log(.event_message, "error") - if err == null { - .timestamp = parsed.timestamp - .severity = parsed.severity - .metadata.request.host = parsed.host - .metadata.request.headers.cf_connecting_ip = parsed.client - url, err = split(parsed.request, " ") - if err == null { - .metadata.request.method = url[0] - .metadata.request.path = url[1] - .metadata.request.protocol = url[2] - } - } - if err != null { - abort - } - # Gotrue logs are structured json strings which frontend parses directly. But we keep metadata for consistency. - auth_logs: - type: remap - inputs: - - router.auth - source: |- - parsed, err = parse_json(.event_message) - if err == null { - .metadata.timestamp = parsed.time - .metadata = merge!(.metadata, parsed) - } - # PostgREST logs are structured so we separate timestamp from message using regex - rest_logs: - type: remap - inputs: - - router.rest - source: |- - parsed, err = parse_regex(.event_message, r'^(?P