diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 112a5224e..d63160d26 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -29,14 +29,14 @@ jobs: uses: actions/cache@v3 with: path: deps - key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-mix-6 + key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix-119 - name: Restore _build uses: actions/cache@v3 with: path: _build - key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-mix-6 + key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix-119 - run: mix deps.get - run: mix test - uses: 8398a7/action-slack@v3 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 22999f2e5..8ff370456 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -166,14 +166,14 @@ jobs: uses: actions/cache@v3 with: path: deps - key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-mix-6 + key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix-119 - name: Restore _build uses: actions/cache@v3 with: path: _build - key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-mix-6 + key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix-119 - run: mix deps.get - run: mix test - uses: 8398a7/action-slack@v3 @@ -196,14 +196,14 @@ jobs: uses: actions/cache@v3 with: path: deps - key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-mix-6 + key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix-119 - name: Restore _build uses: actions/cache@v3 with: path: _build - key: ${{ runner.os }}-mix-6-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-mix-6 + key: ${{ runner.os }}-mix-119-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix-119 - name: get dependencies run: mix deps.get - name: update schema diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2b9380f69..78760ffd9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,8 +23,8 @@ stages: build: stage: test - # Align with Dockerfile / .tool-versions (Elixir 1.13.4). Bandit 1.11+ needs this. - image: hexpm/elixir:1.13.4-erlang-24.3-alpine-3.17.0 + # Align with Dockerfile / .tool-versions (Elixir 1.19.4 / OTP 28.5). + image: hexpm/elixir:1.19.4-erlang-28.5-alpine-3.23.4 cache: key: ${CI_COMMIT_REF_SLUG} paths: diff --git a/.tool-versions b/.tool-versions index 72808ec94..ea44d5f1c 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -erlang 24.3.4.17 -elixir 1.13.4 +erlang 28.5 +elixir 1.19.4 diff --git a/Dockerfile b/Dockerfile index 301c88ae2..2bcddcf56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,41 +1,31 @@ -FROM bitwalker/alpine-elixir:1.13.4 AS builder +ARG ELIXIR_VERSION=1.19.4 +ARG OTP_VERSION=28.5 +ARG OS_VARIANT=alpine +ARG OS_VERSION=3.23.4 +ARG RUNNER_IMAGE=alpine:3.23.4 + +FROM hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-${OS_VARIANT}-${OS_VERSION} AS builder -# The following are build arguments used to change variable parts of the image. -# The name of your application/release (required) -ARG APP_NAME -# The environment to build with ARG MIX_ENV=prod -ENV APP_NAME=${APP_NAME} \ - MIX_ENV=${MIX_ENV} +ENV MIX_ENV=${MIX_ENV} -# By convention, /opt is typically used for applications WORKDIR /opt/app -# This step installs all the build tools we'll need -RUN apk update --allow-untrusted && \ - apk upgrade --no-cache && \ - apk add --no-cache \ - git \ - build-base && \ +RUN apk update && apk upgrade --no-cache && \ + apk add --no-cache git build-base curl ca-certificates && \ mix local.rebar --force && \ mix local.hex --force -# This copies our app source code into the build container COPY . . -# needed so that we can get the app version from the git tag RUN git config --global --add safe.directory '/opt/app' RUN mix do deps.get, compile -RUN \ - mkdir -p /opt/built && \ - mix distillery.release --name ${APP_NAME} && \ - cp _build/${MIX_ENV}/rel/${APP_NAME}/releases/*/${APP_NAME}.tar.gz /opt/built && \ - cd /opt/built && \ - tar -xzf ${APP_NAME}.tar.gz && \ - rm ${APP_NAME}.tar.gz +ARG APP_NAME +ENV APP_NAME=${APP_NAME} +RUN mix release ${APP_NAME} FROM alpine:3.21.7 as tools @@ -85,9 +75,8 @@ RUN apk add --update --no-cache curl ca-certificates unzip wget openssl && \ chmod +x /usr/local/bin/helm /usr/local/bin/plural /usr/local/bin/trivy && \ rm -f /tmp/helm.tar.gz /tmp/plural-cli.tar.gz /tmp/trivy.tar.gz -FROM erlang:24.3.4.6-alpine +FROM ${RUNNER_IMAGE} -# The name of your application/release (required) ARG APP_NAME ARG GIT_COMMIT @@ -95,29 +84,25 @@ RUN apk update && \ apk add --no-cache \ bash \ curl \ - busybox=1.35.0-r18 \ - ssl_client=1.35.0-r18 \ + busybox \ openssl-dev \ ca-certificates \ git \ - musl=1.2.3-r4 \ - musl-utils=1.2.3-r4 \ - ncurses=6.3_p20220521-r1 \ - ncurses-libs=6.3_p20220521-r1 \ - ncurses-terminfo=6.3_p20220521-r1 \ - ncurses-terminfo-base=6.3_p20220521-r1 + libstdc++ \ + ncurses-libs -ENV REPLACE_OS_VARS=true \ - APP_NAME=${APP_NAME} \ - GIT_COMMIT=${GIT_COMMIT} +ENV APP_NAME=${APP_NAME} \ + GIT_COMMIT=${GIT_COMMIT} \ + MIX_ENV=prod \ + LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 WORKDIR /opt/app COPY --from=tools /usr/local/bin/plural /usr/local/bin/plural COPY --from=tools /usr/local/bin/helm /usr/local/bin/helm -# COPY --from=tools /usr/local/bin/goon /usr/local/bin/goon -# COPY --from=tools /usr/local/bin/terrascan /usr/local/bin/terrascan COPY --from=tools /usr/local/bin/trivy /usr/local/bin/trivy -COPY --from=builder /opt/built . +COPY --from=builder /opt/app/_build/prod/rel/${APP_NAME} . -CMD trap 'exit' INT; /opt/app/bin/${APP_NAME} foreground +CMD trap 'exit' INT; /opt/app/bin/${APP_NAME} start diff --git a/Makefile b/Makefile index a94118c13..5196528e0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help up-docker down-docker up-docker-www test-docker-www build-docker-www testup testdown test-docker +.PHONY: help up-docker down-docker up-docker-www test-docker-www build-docker-www testup testdown test-docker stack-up stack-down GCP_PROJECT ?= pluralsh APP_NAME ?= plural @@ -19,6 +19,16 @@ up-docker: ## start root dependencies via docker compose (db, cache, queue, etc. down-docker: ## stop and remove root dependencies docker compose stack docker compose -f docker-compose.yml down +stack-up: ## build Mix-release images sequentially, then run api/rtc/worker/cron + docker build --build-arg APP_NAME=plural --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-plural . + docker build --build-arg APP_NAME=rtc --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-rtc . + docker build --build-arg APP_NAME=worker --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-worker . + docker build --build-arg APP_NAME=cron --build-arg TARGETARCH=$(TARGETARCH) --build-arg GIT_COMMIT=local -t plural-stack-cron . + docker compose -f docker-compose.stack.yml up -d + +stack-down: ## stop the local Mix-release stack + docker compose -f docker-compose.stack.yml down + test-docker: ## run backend tests in docker @docker compose -f docker-compose.test.yml up --build --abort-on-container-exit --exit-code-from backend-test; \ status=$$?; \ diff --git a/apps/api/lib/api_web.ex b/apps/api/lib/api_web.ex index 4a9ea1a8c..72592980f 100644 --- a/apps/api/lib/api_web.ex +++ b/apps/api/lib/api_web.ex @@ -19,11 +19,13 @@ defmodule ApiWeb do def controller do quote do - use Phoenix.Controller, namespace: ApiWeb + use Phoenix.Controller, + namespace: ApiWeb, + formats: [html: "View", json: "View"] import Plug.Conn - import ApiWeb.Gettext import ApiWeb.Helpers + use Gettext, backend: ApiWeb.Gettext alias ApiWeb.Router.Helpers, as: Routes action_fallback ApiWeb.FallbackController @@ -43,7 +45,7 @@ defmodule ApiWeb do use Phoenix.HTML import ApiWeb.ErrorHelpers - import ApiWeb.Gettext + use Gettext, backend: ApiWeb.Gettext alias ApiWeb.Router.Helpers, as: Routes end end @@ -59,7 +61,7 @@ defmodule ApiWeb do def channel do quote do use Phoenix.Channel - import ApiWeb.Gettext + use Gettext, backend: ApiWeb.Gettext end end diff --git a/apps/api/lib/api_web/controllers/fallback_controller.ex b/apps/api/lib/api_web/controllers/fallback_controller.ex index 69b521be6..bb91107b9 100644 --- a/apps/api/lib/api_web/controllers/fallback_controller.ex +++ b/apps/api/lib/api_web/controllers/fallback_controller.ex @@ -1,5 +1,5 @@ defmodule ApiWeb.FallbackController do - use Phoenix.Controller + use Phoenix.Controller, formats: [html: "View", json: "View"] require Logger def call(conn, {:error, error}) do diff --git a/apps/api/lib/api_web/gettext.ex b/apps/api/lib/api_web/gettext.ex index 801db9527..5befad6fc 100644 --- a/apps/api/lib/api_web/gettext.ex +++ b/apps/api/lib/api_web/gettext.ex @@ -20,5 +20,5 @@ defmodule ApiWeb.Gettext do See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. """ - use Gettext, otp_app: :api + use Gettext.Backend, otp_app: :api end diff --git a/apps/api/lib/api_web/guardian_pipeline.ex b/apps/api/lib/api_web/guardian_pipeline.ex index 676b650f4..dd7cef892 100644 --- a/apps/api/lib/api_web/guardian_pipeline.ex +++ b/apps/api/lib/api_web/guardian_pipeline.ex @@ -5,7 +5,7 @@ defmodule ApiWeb.GuardianPipeline do plug Api.Plugs.VerifyPersistedToken plug Guardian.Plug.VerifySession - plug Guardian.Plug.VerifyHeader, realm: "Bearer" + plug Guardian.Plug.VerifyHeader, scheme: "Bearer" # plug Guardian.Plug.EnsureAuthenticated plug Guardian.Plug.LoadResource, allow_blank: true end diff --git a/apps/api/lib/api_web/plugs/remote_ip.ex b/apps/api/lib/api_web/plugs/remote_ip.ex index 12ef99e18..d9fc880e4 100644 --- a/apps/api/lib/api_web/plugs/remote_ip.ex +++ b/apps/api/lib/api_web/plugs/remote_ip.ex @@ -1,15 +1,19 @@ defmodule ApiWeb.Plugs.RemoteIp do - alias RemoteIp + @headers ~w[forwarded x-forwarded-for x-client-ip x-real-ip] - def init(opts), do: RemoteIp.init(opts) + def init(opts), do: opts + + def call(%{req_headers: headers} = conn, _opts) do + ips = + headers + |> RemoteIp.Headers.take(@headers) + |> RemoteIp.Headers.parse() + |> Enum.reverse() - def call(%{req_headers: headers} = conn, %RemoteIp.Config{headers: allowed}) do - ips = RemoteIp.Headers.parse(headers, allowed) - |> Enum.reverse() %{conn | remote_ip: find_ip(ips, conn.remote_ip)} end - defp find_ip([_, ip | _], _), do: ip # assume spoof after 2 layers of proxy + defp find_ip([_, ip | _], _), do: ip defp find_ip([ip], _), do: ip defp find_ip(_, ip), do: ip end diff --git a/apps/api/mix.exs b/apps/api/mix.exs index e2965362d..730246079 100644 --- a/apps/api/mix.exs +++ b/apps/api/mix.exs @@ -39,9 +39,8 @@ defmodule Api.MixProject do config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", - elixir: "~> 1.5", + elixir: "~> 1.16", elixirc_paths: elixirc_paths(Mix.env()), - compilers: [:phoenix] ++ Mix.compilers(), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps(), @@ -61,25 +60,26 @@ defmodule Api.MixProject do defp deps do [ - {:sentry, "8.0.6"}, - {:phoenix, "~> 1.6.17"}, + {:sentry, "~> 10.2.0"}, + {:phoenix, "~> 1.5"}, + {:phoenix_view, "~> 2.0"}, {:phoenix_pubsub, "~> 2.0"}, - {:phoenix_ecto, "~> 4.4.0"}, - {:ecto_sql, "~> 3.9.0"}, + {:phoenix_ecto, "~> 4.0"}, + {:ecto_sql, "~> 3.13"}, {:postgrex, ">= 0.0.0"}, - {:phoenix_html, "~> 3.2.0"}, + {:phoenix_html, "~> 3.0"}, {:basic_auth, "~> 2.2.2"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:gettext, "~> 0.20"}, {:jason, "~> 1.0"}, - {:guardian, "~> 1.2.1"}, + {:guardian, "~> 2.4"}, {:cors_plug, "~> 2.0"}, - {:plug_cowboy, "~> 2.8.1", override: true}, - {:reverse_proxy_plug, "~> 2.1.1"}, + {:plug_cowboy, "~> 2.7"}, + {:reverse_proxy_plug, "~> 3.0"}, {:libcluster, "~> 3.3.1"}, {:prometheus_ex, "~> 3.0"}, {:prometheus_plugs, "~> 1.1.1"}, - {:remote_ip, "~> 0.2.0"}, + {:remote_ip, "~> 1.2.0"}, {:hammer_plug, "~> 3.0"}, {:k8s_traffic_plug, git: "https://github.com/pluralsh/k8s_traffic_plug"}, diff --git a/apps/core/lib/core/application.ex b/apps/core/lib/core/application.ex index 90502c529..7f12dadde 100644 --- a/apps/core/lib/core/application.ex +++ b/apps/core/lib/core/application.ex @@ -3,10 +3,14 @@ defmodule Core.Application do def start(_type, _args) do if Application.get_env(:sentry, :dsn) do - Logger.add_backend(Sentry.LoggerBackend) + :logger.add_handler(:sentry_logger, Sentry.LoggerHandler, %{ + config: %{metadata: [:file, :line]} + }) end - Cloudflare.Client.init() + if Application.get_env(:cloudflare, :auth_token) not in [nil, ""] do + Cloudflare.Client.init() + end children = [ Core.Repo, diff --git a/apps/core/lib/core/clients/console.ex b/apps/core/lib/core/clients/console.ex index 3642d1819..76412239f 100644 --- a/apps/core/lib/core/clients/console.ex +++ b/apps/core/lib/core/clients/console.ex @@ -116,7 +116,7 @@ defmodule Core.Clients.Console do {:ok, %Req.Response{body: %{"data" => %{"clusters" => %{"edges" => edges}}}}} -> {:ok, Enum.map(edges, & &1["node"])} res -> - Logger.warn "Failed to fetch clusters: #{inspect(res)}" + Logger.warning "Failed to fetch clusters: #{inspect(res)}" {:error, "could not fetch clusters"} end end @@ -183,7 +183,7 @@ defmodule Core.Clients.Console do {:ok, %Req.Response{body: %{"errors" => [_ | _] = errors}}} -> {:error, errors} {:ok, %Req.Response{body: %{"data" => %{^field => data}}}} -> {:ok, data} res -> - Logger.warn "Failed to fetch #{field}: #{inspect(res)}" + Logger.warning "Failed to fetch #{field}: #{inspect(res)}" {:error, "could not fetch #{field}"} end end @@ -196,7 +196,7 @@ defmodule Core.Clients.Console do case body[field] do %{"id" => id} -> {:ok, id} err -> - Logger.warn "invalid console gql response: #{inspect(err)}" + Logger.warning "invalid console gql response: #{inspect(err)}" {:error, "#{field} query failed"} end end @@ -206,10 +206,8 @@ defmodule Core.Clients.Console do {:error, "console error"} end - defp with_gql(url) do - case String.ends_with?(url, "/gql") do - true -> url - _ -> "#{url}/gql" - end + defp with_gql(url) when is_binary(url) do + if String.ends_with?(url, "/gql"), do: url, else: "#{url}/gql" end + defp with_gql(_), do: nil end diff --git a/apps/core/lib/core/conduit/plug/retry.ex b/apps/core/lib/core/conduit/plug/retry.ex index a2ffe37f7..46bfd5353 100644 --- a/apps/core/lib/core/conduit/plug/retry.ex +++ b/apps/core/lib/core/conduit/plug/retry.ex @@ -71,13 +71,13 @@ defmodule Core.Conduit.Plug.Retry do end defp log_error(:nack, _, wait_time) do - Logger.warn("Message will be retried in #{wait_time}ms because it was nacked") + Logger.warning("Message will be retried in #{wait_time}ms because it was nacked") end defp log_error(error, stacktrace, wait_time) do formatted_error = Exception.format(:error, error, stacktrace) - Logger.warn([ + Logger.warning([ "Message will be retried in #{wait_time}ms because an exception was raised\n", formatted_error ]) diff --git a/apps/core/lib/core/influx.ex b/apps/core/lib/core/influx.ex index b3b3c5a7d..8898f669f 100644 --- a/apps/core/lib/core/influx.ex +++ b/apps/core/lib/core/influx.ex @@ -1,3 +1,88 @@ defmodule Core.Influx do - use Instream.Connection, otp_app: :core + @moduledoc false + + def child_spec(_opts) do + %{ + id: __MODULE__, + start: {Agent, :start_link, [fn -> :ok end, [name: __MODULE__]]} + } + end + + def config(keys \\ nil) do + cfg = Application.get_env(:core, __MODULE__, []) + if keys, do: Access.get(cfg, keys), else: cfg + end + + def write(payload, opts \\ []) do + cfg = config() + query = Instream.Data.Write.query(payload, opts) + points = query.payload[:points] || [] + body = Instream.Encoder.Line.encode(points) + db = Keyword.get(opts, :database) || cfg[:database] + url = "#{base_url(cfg)}/write?#{URI.encode_query(%{"db" => db})}" + + case Req.post(url, headers: headers(cfg, [{"content-type", "text/plain"}]), body: body, retry: false) do + {:ok, %Req.Response{status: status}} when status in 200..299 -> :ok + {:ok, %Req.Response{status: status, body: resp}} -> {:error, {status, resp}} + {:error, reason} -> {:error, reason} + end + end + + def query(sql, opts \\ []) when is_binary(sql) do + cfg = config() + db = Keyword.get(opts, :database) || cfg[:database] + method = Keyword.get(opts, :method, :get) + + params = + %{"db" => db, "q" => sql} + |> maybe_put_json_params(Keyword.get(opts, :params)) + + url = "#{base_url(cfg)}/query?#{URI.encode_query(params)}" + req_opts = [headers: headers(cfg), retry: false] + + result = + case method do + :post -> Req.post(url, req_opts) + _ -> Req.get(url, req_opts) + end + + case result do + {:ok, %Req.Response{status: status, body: body}} when status in 200..299 -> + decode_body(body) + + {:ok, %Req.Response{status: status, body: body}} -> + {:error, {status, body}} + + {:error, reason} -> + {:error, reason} + end + end + + defp maybe_put_json_params(params, map) when is_map(map) do + Map.put(params, "params", Jason.encode!(map)) + end + defp maybe_put_json_params(params, _), do: params + + defp decode_body(body) when is_map(body) do + body + |> Jason.encode!() + |> Jason.decode!(keys: :atoms) + end + defp decode_body(body) when is_binary(body) and body != "" do + Jason.decode!(body, keys: :atoms) + end + defp decode_body(_), do: :ok + + defp base_url(cfg) do + scheme = cfg[:scheme] || "http" + host = cfg[:host] || "localhost" + port = cfg[:port] || 8086 + "#{scheme}://#{host}:#{port}" + end + + defp headers(cfg, extra \\ []) do + Instream.Query.Headers.assemble(cfg) + |> Kernel.++(extra) + |> Enum.map(fn {k, v} -> {String.downcase(to_string(k)), v} end) + end end diff --git a/apps/core/lib/core/schema/account.ex b/apps/core/lib/core/schema/account.ex index 28e8235a8..116dac320 100644 --- a/apps/core/lib/core/schema/account.ex +++ b/apps/core/lib/core/schema/account.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Account do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema import Core.Schema.Validations alias Core.Schema.{User, DomainMapping, PlatformSubscription, Address} diff --git a/apps/core/lib/core/schema/artifact.ex b/apps/core/lib/core/schema/artifact.ex index 825f2adcb..eb04207ae 100644 --- a/apps/core/lib/core/schema/artifact.ex +++ b/apps/core/lib/core/schema/artifact.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Artifact do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.{Repository} defenum Platform, mac: 0, windows: 1, linux: 2, android: 3, freebsd: 4, openbsd: 5, solaris: 6 diff --git a/apps/core/lib/core/schema/crd.ex b/apps/core/lib/core/schema/crd.ex index c246c6edc..d1c31f8c3 100644 --- a/apps/core/lib/core/schema/crd.ex +++ b/apps/core/lib/core/schema/crd.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Crd do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.Version schema "crds" do diff --git a/apps/core/lib/core/schema/file.ex b/apps/core/lib/core/schema/file.ex index 8d4f6acbd..e12bb976c 100644 --- a/apps/core/lib/core/schema/file.ex +++ b/apps/core/lib/core/schema/file.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.File do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.IncidentMessage diff --git a/apps/core/lib/core/schema/integration.ex b/apps/core/lib/core/schema/integration.ex index 747001c6c..2fc431d65 100644 --- a/apps/core/lib/core/schema/integration.ex +++ b/apps/core/lib/core/schema/integration.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Integration do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.{Publisher, Repository, ResourceDefinition, Tag} diff --git a/apps/core/lib/core/schema/publisher.ex b/apps/core/lib/core/schema/publisher.ex index 445566569..2bce4240b 100644 --- a/apps/core/lib/core/schema/publisher.ex +++ b/apps/core/lib/core/schema/publisher.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Publisher do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.{User, Address, Repository, Account} @repo_sideload_limit 5 diff --git a/apps/core/lib/core/schema/repository.ex b/apps/core/lib/core/schema/repository.ex index 0787f7c0f..29a20ece9 100644 --- a/apps/core/lib/core/schema/repository.ex +++ b/apps/core/lib/core/schema/repository.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Repository do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.{ Publisher, Dashboard, diff --git a/apps/core/lib/core/schema/terraform.ex b/apps/core/lib/core/schema/terraform.ex index 5276fe861..dab1b159f 100644 --- a/apps/core/lib/core/schema/terraform.ex +++ b/apps/core/lib/core/schema/terraform.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Terraform do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.{Repository, Dependencies} schema "terraform" do diff --git a/apps/core/lib/core/schema/test_step.ex b/apps/core/lib/core/schema/test_step.ex index 28a64c554..7c7e97d9a 100644 --- a/apps/core/lib/core/schema/test_step.ex +++ b/apps/core/lib/core/schema/test_step.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.TestStep do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.Test schema "test_steps" do diff --git a/apps/core/lib/core/schema/user.ex b/apps/core/lib/core/schema/user.ex index 5cb30f622..b21c780bc 100644 --- a/apps/core/lib/core/schema/user.ex +++ b/apps/core/lib/core/schema/user.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.User do use Piazza.Ecto.Schema, derive_json: false - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.{ Address, Publisher, diff --git a/apps/core/lib/core/schema/version.ex b/apps/core/lib/core/schema/version.ex index 023890475..b8f4bedf1 100644 --- a/apps/core/lib/core/schema/version.ex +++ b/apps/core/lib/core/schema/version.ex @@ -1,6 +1,6 @@ defmodule Core.Schema.Version do use Piazza.Ecto.Schema - use Arc.Ecto.Schema + use Waffle.Ecto.Schema alias Core.Schema.{ Chart, Dependencies, diff --git a/apps/core/lib/core/services/cloud/poller.ex b/apps/core/lib/core/services/cloud/poller.ex index d9b46bf1b..9be4d7744 100644 --- a/apps/core/lib/core/services/cloud/poller.ex +++ b/apps/core/lib/core/services/cloud/poller.ex @@ -38,7 +38,7 @@ defmodule Core.Services.Cloud.Poller do case Console.repo(client, Core.conf(:mgmt_repo)) do {:ok, id} -> {:noreply, %{state | repo: id}} err -> - Logger.warn "failed to find mgmt repo: #{inspect(err)}" + Logger.warning "failed to find mgmt repo: #{inspect(err)}" {:noreply, state} end end @@ -47,7 +47,7 @@ defmodule Core.Services.Cloud.Poller do case Console.project(client, Core.conf(:dedicated_project)) do {:ok, id} -> {:noreply, %{state | project: id}} err -> - Logger.warn "failed to find dedicated project: #{inspect(err)}" + Logger.warning "failed to find dedicated project: #{inspect(err)}" {:noreply, state} end end @@ -66,7 +66,7 @@ defmodule Core.Services.Cloud.Poller do {:ok, pgs} <- Jason.decode(v) do Enum.each(pgs, fn {k, v} -> upsert_pg(k, v) end) else - err -> Logger.warn "failed to fetch cluster info: #{inspect(err)}" + err -> Logger.warning "failed to fetch cluster info: #{inspect(err)}" end {:noreply, state} end diff --git a/apps/core/lib/core/services/storage.ex b/apps/core/lib/core/services/storage.ex index de740c383..03fd7335a 100644 --- a/apps/core/lib/core/services/storage.ex +++ b/apps/core/lib/core/services/storage.ex @@ -1,6 +1,6 @@ defmodule Core.Storage do - use Arc.Definition - use Arc.Ecto.Definition + use Waffle.Definition + use Waffle.Ecto.Definition alias Core.Schema.{ User, Publisher, diff --git a/apps/core/mix.exs b/apps/core/mix.exs index def078677..399b5c6bf 100644 --- a/apps/core/mix.exs +++ b/apps/core/mix.exs @@ -39,7 +39,7 @@ defmodule Core.MixProject do config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", - elixir: "~> 1.9", + elixir: "~> 1.16", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, aliases: aliases(), @@ -62,69 +62,66 @@ defmodule Core.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:sentry, "8.0.6"}, - {:ecto_sql, "~> 3.9.0"}, + {:sentry, "~> 10.2.0"}, + {:ecto_sql, "~> 3.13"}, {:libvault, "~> 0.2.0"}, - {:ecto, "~> 3.9.0", override: true}, - {:postgrex, ">= 0.0.0"}, + {:ecto, "~> 3.13", override: true}, + {:postgrex, "~> 0.22"}, {:ex_machina, "~> 2.7.0", only: :test}, {:comeonin, "~> 5.3.0"}, - {:argon2_elixir, "~> 2.0"}, - {:piazza_core, "~> 0.3.8", git: "https://github.com/michaeljguarino/piazza_core"}, + {:argon2_elixir, "~> 4.1"}, + {:piazza_core, "~> 0.3.9", git: "https://github.com/michaeljguarino/piazza_core", commit: "2a91145d0d567f1aab40d52843d77dfb491c424a", override: true}, {:inet_cidr, "~> 1.0.0"}, {:dns, "~> 2.4.0"}, - {:bamboo, "~> 2.0"}, + {:bamboo, "~> 2.3"}, {:parallax, "~> 1.0"}, {:bourne, "~> 1.1"}, {:mcp_sse, "~> 0.1.0"}, - {:flow, "~> 0.15.0"}, - {:joken, "~> 2.5.0"}, - {:guardian, "~> 1.2.1"}, - {:arc, "~> 0.11.0"}, - {:arc_gcs, "~> 0.2.0"}, + {:flow, "~> 1.2"}, + {:gen_stage, "~> 1.0", override: true}, + {:joken, "~> 2.6"}, + {:guardian, "~> 2.4"}, + {:waffle, "~> 1.1"}, + {:waffle_gcs, "~> 0.1"}, + {:waffle_ecto, "~> 0.0"}, {:porcelain, "~> 2.0"}, - {:ex_aws, "~> 2.4.0"}, + {:ex_aws, "~> 2.7"}, {:ex_aws_s3, "~> 2.3.3"}, {:ex_aws_sts, "~> 2.3.0"}, - {:configparser_ex, "~> 4.0"}, + {:configparser_ex, "~> 5.0"}, {:sweet_xml, "~> 0.7.3"}, - {:arc_ecto, "~> 0.11.3"}, {:dictionary, "~> 0.1.0"}, {:mojito, "~> 0.7.0"}, - {:nebulex, "== 2.4.2"}, - {:castore, "~> 0.1.7"}, - {:plug_crypto, "~> 1.2"}, - {:req, "~> 0.4.14", override: true}, - {:mint, ">= 1.9.0 and < 1.9.2", override: true}, - {:finch, "~> 0.17.0", override: true}, + {:nebulex, "~> 2.6"}, + {:castore, "~> 1.0", override: true}, + {:plug_crypto, "~> 2.2"}, + {:req, "~> 0.7.2", override: true}, + {:mint, "~> 1.6", override: true}, + {:finch, "~> 0.19", override: true}, {:absinthe_client, "~> 0.1.0"}, - {:kazan, "~> 0.11", github: "michaeljguarino/kazan", branch: "k8s-1.23"}, + {:kazan, "~> 0.11", github: "michaeljguarino/kazan", ref: "bbeda162b85c5b49a4f044cee92070aa1670a44e"}, {:workos, "~> 0.1.2"}, - {:decorator, "~> 1.3"}, #=> For using Caching Annotations + {:decorator, "~> 1.3"}, {:botanist, "~> 0.1.0", git: "https://github.com/michaeljguarino/botanist.git", branch: "ecto3"}, - {:x509, "~> 0.8.5"}, - { - :briefly, - git: "https://github.com/CargoSense/briefly", - ref: "b0fd495bf0c5ef2c44de2791a8cc7a20813c7d36" - }, - {:yaml_elixir, "~> 2.4"}, - {:timex, "~> 3.6"}, - {:oauth2, "~> 2.0"}, - {:websockex, "~> 0.4"}, - {:hackney, "~> 1.25.0", override: true}, + {:x509, "~> 0.9.2"}, + {:briefly, "~> 0.5.0"}, + {:yaml_elixir, "~> 2.9"}, + {:timex, "~> 3.7"}, + {:oauth2, "~> 2.1"}, + {:websockex, "~> 0.5.1", override: true}, + {:hackney, "~> 4.0", override: true}, {:tzdata, "~> 1.1.0", override: true}, {:prometheus_ex, "~> 3.0"}, - {:stripity_stripe, "~> 3.2"}, + {:stripity_stripe, "3.2.0"}, {:conduit, "~> 0.12"}, {:conduit_amqp, "~> 0.6.3"}, - {:rabbit_common, "3.12.14", override: true}, - {:amqp, "~> 3.2", override: true}, - {:mime, "~> 1.2"}, + {:amqp, "~> 4.0", override: true}, + {:rabbit_common, "~> 4.0", override: true}, + {:mime, "~> 2.0"}, {:ex_image_info, "~> 0.2.4"}, {:instream, "~> 1.0"}, {:swarm, "~> 3.4.0"}, - {:poison, "~> 3.0"}, + {:poison, "~> 6.0", override: true}, {:cloudflare, "~> 0.2"}, {:mimic, "~> 1.1", only: :test}, {:google_api_iam, "~> 0.40"}, diff --git a/apps/core/test/pubsub/fanout/access_token_test.exs b/apps/core/test/pubsub/fanout/access_token_test.exs index 0c711b9fa..3ca434ad5 100644 --- a/apps/core/test/pubsub/fanout/access_token_test.exs +++ b/apps/core/test/pubsub/fanout/access_token_test.exs @@ -20,7 +20,7 @@ defmodule Core.PubSub.Fanout.AccessTokenTest do assert token.id == id assert Timex.now() - |> Timex.set(minutes: 0, seconds: 0, millisecond: {0, 6}) + |> Timex.set(minute: 0, second: 0, microsecond: {0, 6}) |> Timex.equal?(ts) assert ip == found_ip end diff --git a/apps/cron/lib/cron/digest/base.ex b/apps/cron/lib/cron/digest/base.ex index a12f08a14..52c2ca54a 100644 --- a/apps/cron/lib/cron/digest/base.ex +++ b/apps/cron/lib/cron/digest/base.ex @@ -12,12 +12,13 @@ defmodule Cron.Digest.Base do """ @spec grouped([Notification.t]) :: Flow.t def grouped(notifications, opts \\ []) do - Flow.from_enumerable(notifications, opts) - |> Flow.group_by(& &1.user_id) - |> Flow.map(fn {user_id, notifs} -> + notifications + |> Enum.group_by(& &1.user_id) + |> Enum.map(fn {user_id, notifs} -> notif_groups = Enum.group_by(notifs, & &1.repository_id) compile(user_id, notif_groups) end) + |> Flow.from_enumerable(opts) end @doc """ diff --git a/apps/cron/mix.exs b/apps/cron/mix.exs index ba88297ba..ee12c6900 100644 --- a/apps/cron/mix.exs +++ b/apps/cron/mix.exs @@ -39,7 +39,7 @@ defmodule Cron.MixProject do config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", - elixir: "~> 1.11", + elixir: "~> 1.16", start_permanent: Mix.env() == :prod, deps: deps(), test_coverage: [tool: ExCoveralls] diff --git a/apps/email/lib/email_web.ex b/apps/email/lib/email_web.ex index 25b227065..277d972cb 100644 --- a/apps/email/lib/email_web.ex +++ b/apps/email/lib/email_web.ex @@ -19,10 +19,12 @@ defmodule EmailWeb do def controller do quote do - use Phoenix.Controller, namespace: EmailWeb + use Phoenix.Controller, + namespace: EmailWeb, + formats: [html: "View", json: "View"] import Plug.Conn - import EmailWeb.Gettext + use Gettext, backend: EmailWeb.Gettext alias EmailWeb.Router.Helpers, as: Routes end end @@ -54,7 +56,7 @@ defmodule EmailWeb do def channel do quote do use Phoenix.Channel - import EmailWeb.Gettext + use Gettext, backend: EmailWeb.Gettext end end @@ -67,7 +69,7 @@ defmodule EmailWeb do import Phoenix.View import EmailWeb.ErrorHelpers - import EmailWeb.Gettext + use Gettext, backend: EmailWeb.Gettext alias EmailWeb.Router.Helpers, as: Routes end end diff --git a/apps/email/lib/email_web/gettext.ex b/apps/email/lib/email_web/gettext.ex index ae0b28f24..973b55024 100644 --- a/apps/email/lib/email_web/gettext.ex +++ b/apps/email/lib/email_web/gettext.ex @@ -20,5 +20,5 @@ defmodule EmailWeb.Gettext do See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. """ - use Gettext, otp_app: :email + use Gettext.Backend, otp_app: :email end diff --git a/apps/email/mix.exs b/apps/email/mix.exs index 376ef356a..94aac6039 100644 --- a/apps/email/mix.exs +++ b/apps/email/mix.exs @@ -39,9 +39,8 @@ defmodule Email.MixProject do config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", - elixir: "~> 1.7", + elixir: "~> 1.16", elixirc_paths: elixirc_paths(Mix.env()), - compilers: [:phoenix] ++ Mix.compilers(), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps(), @@ -68,16 +67,17 @@ defmodule Email.MixProject do # Type `mix help deps` for examples and options. defp deps do [ - {:phoenix, "~> 1.6.17"}, - {:phoenix_html, "~> 3.2.0"}, + {:phoenix, "~> 1.5"}, + {:phoenix_view, "~> 2.0"}, + {:phoenix_html, "~> 3.0"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, - {:phoenix_live_dashboard, "~> 0.5.3"}, - {:telemetry_metrics, "~> 0.6.1"}, - {:telemetry_poller, "~> 1.0.0"}, + {:phoenix_live_dashboard, "~> 0.8"}, + {:telemetry_metrics, "~> 1.0"}, + {:telemetry_poller, "~> 1.1"}, {:bamboo_phoenix, "~> 1.0"}, {:gettext, "~> 0.20"}, {:jason, "~> 1.0"}, - {:plug_cowboy, "~> 2.8.1"}, + {:plug_cowboy, "~> 2.7"}, {:core, in_umbrella: true} ] diff --git a/apps/graphql/lib/graphql/middleware/exception_middleware.ex b/apps/graphql/lib/graphql/middleware/exception_middleware.ex index 80b9c9697..fd004071d 100644 --- a/apps/graphql/lib/graphql/middleware/exception_middleware.ex +++ b/apps/graphql/lib/graphql/middleware/exception_middleware.ex @@ -15,7 +15,7 @@ defmodule GraphQl.ExceptionMiddleware do rescue error -> if ExceptionHandler.capture(error) do - Sentry.capture_exception(error, __STACKTRACE__) + Sentry.capture_exception(error, stacktrace: __STACKTRACE__) end Logger.error(Exception.format(:error, error, __STACKTRACE__)) Absinthe.Resolution.put_result(resolution, {:error, ExceptionHandler.message(error)}) diff --git a/apps/graphql/mix.exs b/apps/graphql/mix.exs index 9dc3c7b30..cf4ebc77c 100644 --- a/apps/graphql/mix.exs +++ b/apps/graphql/mix.exs @@ -39,7 +39,7 @@ defmodule Graphql.MixProject do config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", - elixir: "~> 1.9", + elixir: "~> 1.16", start_permanent: Mix.env() == :prod, elixirc_paths: elixirc_paths(Mix.env()), deps: deps(), @@ -60,11 +60,11 @@ defmodule Graphql.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:absinthe, "~> 1.7.10"}, - {:absinthe_relay, "~> 1.5.2"}, - {:absinthe_plug, "~> 1.5.8"}, - {:dataloader, "== 1.0.10", override: true}, - {:apq, "~> 1.2.1"}, + {:absinthe, "~> 1.10"}, + {:absinthe_relay, "~> 1.6"}, + {:absinthe_plug, "~> 1.5"}, + {:dataloader, "~> 2.0"}, + {:apq, "~> 2.0"}, {:hammer, "~> 6.1"}, {:core, in_umbrella: true} diff --git a/apps/rtc/lib/rtc_web.ex b/apps/rtc/lib/rtc_web.ex index 16f11075c..73d902ff3 100644 --- a/apps/rtc/lib/rtc_web.ex +++ b/apps/rtc/lib/rtc_web.ex @@ -19,10 +19,12 @@ defmodule RtcWeb do def controller do quote do - use Phoenix.Controller, namespace: RtcWeb + use Phoenix.Controller, + namespace: RtcWeb, + formats: [html: "View", json: "View"] import Plug.Conn - import RtcWeb.Gettext + use Gettext, backend: RtcWeb.Gettext alias RtcWeb.Router.Helpers, as: Routes end end @@ -54,7 +56,7 @@ defmodule RtcWeb do def channel do quote do use Phoenix.Channel - import RtcWeb.Gettext + use Gettext, backend: RtcWeb.Gettext end end @@ -67,7 +69,7 @@ defmodule RtcWeb do import Phoenix.View import RtcWeb.ErrorHelpers - import RtcWeb.Gettext + use Gettext, backend: RtcWeb.Gettext alias RtcWeb.Router.Helpers, as: Routes end end diff --git a/apps/rtc/lib/rtc_web/gettext.ex b/apps/rtc/lib/rtc_web/gettext.ex index 90bada2ff..8f52ef17f 100644 --- a/apps/rtc/lib/rtc_web/gettext.ex +++ b/apps/rtc/lib/rtc_web/gettext.ex @@ -20,5 +20,5 @@ defmodule RtcWeb.Gettext do See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. """ - use Gettext, otp_app: :rtc + use Gettext.Backend, otp_app: :rtc end diff --git a/apps/rtc/mix.exs b/apps/rtc/mix.exs index 3673840a6..281d5b2e9 100644 --- a/apps/rtc/mix.exs +++ b/apps/rtc/mix.exs @@ -39,9 +39,8 @@ defmodule Rtc.MixProject do config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", - elixir: "~> 1.7", + elixir: "~> 1.16", elixirc_paths: elixirc_paths(Mix.env()), - compilers: [:phoenix] ++ Mix.compilers(), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps(), @@ -68,22 +67,23 @@ defmodule Rtc.MixProject do # Type `mix help deps` for examples and options. defp deps do [ - {:sentry, "8.0.6"}, - {:phoenix, "~> 1.6.17"}, - {:phoenix_html, "~> 3.2.0"}, + {:sentry, "~> 10.2.0"}, + {:phoenix, "~> 1.5"}, + {:phoenix_view, "~> 2.0"}, + {:phoenix_html, "~> 3.0"}, {:phoenix_live_reload, "~> 1.4.0", only: :dev}, - {:telemetry_metrics, "~> 0.6.1"}, - {:telemetry_poller, "~> 1.0.0"}, + {:telemetry_metrics, "~> 1.0"}, + {:telemetry_poller, "~> 1.1"}, {:gettext, "~> 0.20"}, {:jason, "~> 1.0"}, - {:plug_cowboy, "~> 2.8.1", override: true}, - {:absinthe_phoenix, "~> 2.0.2"}, + {:plug_cowboy, "~> 2.7"}, + {:absinthe_phoenix, "~> 2.0"}, {:libcluster, "~> 3.3.1"}, {:prometheus_ex, "~> 3.0"}, {:prometheus_plugs, "~> 1.1.1"}, - {:websockex, "~> 0.4"}, + {:websockex, "~> 0.5.1"}, {:k8s_traffic_plug, git: "https://github.com/pluralsh/k8s_traffic_plug"}, - {:briefly, [env: :prod, git: "https://github.com/CargoSense/briefly", ref: "b0fd495bf0c5ef2c44de2791a8cc7a20813c7d36"]}, + {:briefly, "~> 0.5.0"}, {:core, in_umbrella: true}, {:graphql, in_umbrella: true} diff --git a/apps/worker/lib/worker/application.ex b/apps/worker/lib/worker/application.ex index 8e1347fba..3115b9178 100644 --- a/apps/worker/lib/worker/application.ex +++ b/apps/worker/lib/worker/application.ex @@ -26,7 +26,14 @@ defmodule Worker.Application do def broker() do case Worker.conf(:start_broker) do - true -> [{Worker.Conduit.Broker, []}, Core.Services.Cloud.Poller] + true -> [{Worker.Conduit.Broker, []}] ++ cloud_poller() + _ -> [] + end + end + + defp cloud_poller() do + case Core.conf(:console_url) do + url when is_binary(url) and url != "" -> [Core.Services.Cloud.Poller] _ -> [] end end diff --git a/apps/worker/mix.exs b/apps/worker/mix.exs index 6a94ca376..ba15189e8 100644 --- a/apps/worker/mix.exs +++ b/apps/worker/mix.exs @@ -39,7 +39,7 @@ defmodule Worker.MixProject do config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", - elixir: "~> 1.11", + elixir: "~> 1.16", start_permanent: Mix.env() == :prod, deps: deps(), test_coverage: [tool: ExCoveralls] diff --git a/config/config.exs b/config/config.exs index b2246f48b..b8e619fd4 100644 --- a/config/config.exs +++ b/config/config.exs @@ -46,6 +46,8 @@ config :logger, :console, config :phoenix, :json_library, Jason +config :tesla, disable_deprecated_builder_warning: true + config :reverse_proxy_plug, :http_client, ReverseProxyPlug.HTTPClient.Adapters.HTTPoison config :core, Core.Guardian, @@ -63,8 +65,8 @@ config :botanist, config :core, :connection_draining, shutdown_delay_ms: 1 -config :arc, - storage: Arc.Storage.GCS, +config :waffle, + storage: Waffle.Storage.Google.CloudStorage, bucket: "forge-assets" config :stripity_stripe, diff --git a/config/test.exs b/config/test.exs index a0c191064..40ffc7f10 100644 --- a/config/test.exs +++ b/config/test.exs @@ -4,15 +4,29 @@ config :core, Core.Repo, username: "postgres", password: "postgres", database: "forge_test", - hostname: "localhost", + hostname: System.get_env("DB_HOST") || "localhost", pool: Ecto.Adapters.SQL.Sandbox config :core, Core.Influx, database: "plural", - host: "localhost", + host: System.get_env("INFLUXDB_HOST") || "localhost", auth: [method: :basic, username: "forge", password: "forgepwd"], port: 8086 +rabbit_host = System.get_env("RABBITMQ_HOST") || "localhost" + +config :core, Core.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://rabbitmq:rabbitmq@#{rabbit_host}" + +config :rtc, Rtc.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://rabbitmq:rabbitmq@#{rabbit_host}" + +config :worker, Worker.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://rabbitmq:rabbitmq@#{rabbit_host}" + config :api, ApiWeb.Endpoint, http: [port: 4002], server: false @@ -21,7 +35,7 @@ config :rtc, RtcWeb.Endpoint, http: [port: 4002], server: false -config :logger, level: :warn +config :logger, level: :warning path = __ENV__.file |> Path.dirname() diff --git a/docker-compose.stack.yml b/docker-compose.stack.yml new file mode 100644 index 000000000..7e329d435 --- /dev/null +++ b/docker-compose.stack.yml @@ -0,0 +1,200 @@ +# Local Mix-release stack (api / rtc / worker). +# Does not replace Helm. libcluster, GCS, Cloudflare, Stripe, Hydra, +# chartmuseum, and the www frontend are stubbed or unused. +# +# make stack-up +# +# Build images one APP_NAME at a time (parallel `mix deps.get` can fail Hex DNS). +# +# Cron is a Kubernetes CronJob in prod, not a long-running service: +# docker compose -f docker-compose.stack.yml run --rm -e CRON=Prune.Queues cron +# +# API: http://localhost:4000/health +# RTC: http://localhost:4001/health +# Rabbit UI: http://localhost:15672 (rabbitmq / rabbitmq) + +x-release-env: &release-env + HOST: localhost + POD_IP: 127.0.0.1 + ERLANG_COOKIE: localcookie + PLRL_IGNORE_CLUSTER: "true" + PROVIDER: kind + DBSSL: "false" + POSTGRES_URL: postgresql://postgres:postgres@db:5432/plural + POSTGRES_PASSWORD: postgres + DBHOST: db + RABBIT_USERNAME: rabbitmq + RABBIT_PASSWORD: rabbitmq + RABBIT_NAMESPACE: rabbitmq + INFLUX_PAASSWORD: forgepwd + JWT_SECRET: local-jwt-secret + SECRET_KEY_BASE: 1rkd5+lxJbdTadyxW7qF/n1fNzKPV010PKf8SEGmUrXwMw0iAZyoyZgWEwr6nmCJ + AES_KEY: 1HdFP1DuK7xkkcEBne41yAwUY8NSfJnYfGVylYYCS2U= + BUCKET: local-bucket + NAMESPACE: local + GIT_COMMIT: local + +services: + db: + image: postgres:14 + environment: + POSTGRES_PASSWORD: postgres + POSTGRES_DB: plural + command: + - postgres + - -c + - wal_level=logical + volumes: + - stack_db:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d plural"] + interval: 2s + timeout: 5s + retries: 20 + + rabbit: + image: rabbitmq:3-management + hostname: rabbit1 + environment: + RABBITMQ_DEFAULT_USER: rabbitmq + RABBITMQ_DEFAULT_PASS: rabbitmq + RABBITMQ_DEFAULT_VHOST: / + ports: + - "15672:15672" + networks: + default: + aliases: + - rabbitmq.rabbitmq + healthcheck: + test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] + interval: 5s + timeout: 10s + retries: 20 + + influxdb: + image: influxdb:1.8 + environment: + INFLUXDB_HTTP_AUTH_ENABLED: "true" + INFLUXDB_ADMIN_USER: admin + INFLUXDB_ADMIN_PASSWORD: forgepwd + INFLUXDB_DB: plural + volumes: + - stack_influx:/var/lib/influxdb + networks: + default: + aliases: + - influxdb.influx + + migrate: + image: plural-stack-plural + build: &plural-build + context: . + dockerfile: Dockerfile + args: + APP_NAME: plural + TARGETARCH: amd64 + GIT_COMMIT: local + environment: + <<: *release-env + depends_on: + db: + condition: service_healthy + # Helm's /opt/app/bin/migrate also runs Botanist seeds (admin user, hydra, …). + # Local compose only applies Ecto migrations so the API can boot without Hydra. + command: ["/opt/app/bin/plural", "eval", "Piazza.Ecto.ReleaseTasks.migrate([])"] + restart: "no" + + api: + image: plural-stack-plural + build: *plural-build + environment: + <<: *release-env + ports: + - "4000:4000" + depends_on: + db: + condition: service_healthy + rabbit: + condition: service_healthy + migrate: + condition: service_completed_successfully + healthcheck: + test: ["CMD", "curl", "-fsS", "http://127.0.0.1:4000/health"] + interval: 5s + timeout: 5s + retries: 30 + start_period: 20s + restart: unless-stopped + + rtc: + image: plural-stack-rtc + build: + context: . + dockerfile: Dockerfile + args: + APP_NAME: rtc + TARGETARCH: amd64 + GIT_COMMIT: local + environment: + <<: *release-env + ports: + - "4001:4000" + depends_on: + db: + condition: service_healthy + rabbit: + condition: service_healthy + migrate: + condition: service_completed_successfully + healthcheck: + test: ["CMD", "curl", "-fsS", "http://127.0.0.1:4000/health"] + interval: 5s + timeout: 5s + retries: 30 + start_period: 20s + restart: unless-stopped + + worker: + image: plural-stack-worker + build: + context: . + dockerfile: Dockerfile + args: + APP_NAME: worker + TARGETARCH: amd64 + GIT_COMMIT: local + environment: + <<: *release-env + depends_on: + db: + condition: service_healthy + rabbit: + condition: service_healthy + migrate: + condition: service_completed_successfully + restart: unless-stopped + + cron: + profiles: ["cron"] + image: plural-stack-cron + build: + context: . + dockerfile: Dockerfile + args: + APP_NAME: cron + TARGETARCH: amd64 + GIT_COMMIT: local + environment: + <<: *release-env + depends_on: + db: + condition: service_healthy + rabbit: + condition: service_healthy + migrate: + condition: service_completed_successfully + restart: "no" + +volumes: + stack_db: + stack_influx: diff --git a/dockerfiles/Dockerfile.test b/dockerfiles/Dockerfile.test index 1e93bf119..ace95445f 100644 --- a/dockerfiles/Dockerfile.test +++ b/dockerfiles/Dockerfile.test @@ -1,7 +1,7 @@ -ARG ELIXIR_VERSION=1.13.4 -ARG OTP_VERSION=24.3 +ARG ELIXIR_VERSION=1.19.4 +ARG OTP_VERSION=28.5 ARG OS_VARIANT=alpine -ARG OS_VERSION=3.17.0 +ARG OS_VERSION=3.23.4 FROM hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-${OS_VARIANT}-${OS_VERSION} diff --git a/mix.exs b/mix.exs index b6256e906..d388867c6 100644 --- a/mix.exs +++ b/mix.exs @@ -35,10 +35,17 @@ defmodule Plural.MixProject do [ apps_path: "apps", version: version(), + elixir: "~> 1.16", start_permanent: Mix.env() == :prod, deps: deps(), - test_coverage: [tool: ExCoveralls], - preferred_cli_env: [ + releases: releases(), + test_coverage: [tool: ExCoveralls] + ] + end + + def cli do + [ + preferred_envs: [ coveralls: :test, "coveralls.detail": :test, "coveralls.post": :test, @@ -47,29 +54,56 @@ defmodule Plural.MixProject do ] end + defp releases do + [ + plural: release(:plural, [ + runtime_tools: :permanent, + api: :permanent, + core: :permanent, + email: :permanent, + graphql: :permanent + ]), + rtc: release(:rtc, [ + runtime_tools: :permanent, + rtc: :permanent, + core: :permanent, + graphql: :permanent + ]), + worker: release(:worker, [ + runtime_tools: :permanent, + worker: :permanent, + core: :permanent, + email: :permanent + ]), + cron: release(:cron, [ + runtime_tools: :permanent, + cron: :permanent, + core: :permanent, + email: :permanent + ]) + ] + end + + defp release(name, applications) do + [ + include_executables_for: [:unix], + runtime_config_path: "rel/runtime/#{name}.exs", + applications: applications + ] + end + defp deps do [ - {:distillery, "~> 2.1"}, - {:x509, "~> 0.8.5"}, + {:ecto, "~> 3.13", override: true}, + {:decimal, "~> 3.0", override: true}, + {:hackney, "~> 4.0", override: true}, + {:poison, "~> 6.0", override: true}, + {:httpoison, "~> 3.0", github: "pluralsh/httpoison", branch: "fix-certs", commit: "75f6305ce8c89b39d12574008e596785d65d4d1c", override: true}, + {:x509, "~> 0.9.2"}, + {:req, "~> 0.7.2", override: true}, {:shards, "~> 1.0"}, - {:ecto, "~> 3.9.0", override: true}, - # Security bumps (Elixir 1.13-compatible fixed versions where possible) - {:hackney, "~> 1.25.0", override: true}, - {:mint, ">= 1.9.0 and < 1.9.2", override: true}, - {:tesla, ">= 1.11.0 and < 1.11.2", override: true}, - {:bandit, "~> 1.11.1", override: true}, - {:hpax, "1.0.3", override: true}, - {:jose, ">= 1.11.7 and < 1.11.11", override: true}, - {:plug, "~> 1.18.2", override: true}, - {:plug_cowboy, "~> 2.8.1", override: true}, - {:cowboy, "~> 2.15.0", override: true}, - {:cowlib, "~> 2.16.1", override: true}, - {:phoenix, "1.6.17", override: true}, - {:absinthe, "1.7.10", override: true}, - # Keep postgrex on ecto_sql 3.9's declared range (~> 0.16 or ~> 1.0). - # CVE-2026-32687 needs postgrex 0.22.2 + a newer Ecto stack (Elixir upgrade). - {:rabbit_common, "3.12.14", override: true}, - {:absinthe_plug, "~> 1.5.8", git: "https://github.com/absinthe-graphql/absinthe_plug.git", commit: "3a984cc341ebb32c79e7ae58b4ebd116d5c62f9e", override: true}, + {:goth, "~> 1.4", git: "https://github.com/pluralsh/goth.git", branch: "plrl-cleanup", commit: "4958159d1e9acec2154590ecacc732ecd58f8312", override: true}, + {:absinthe_plug, "~> 1.5", git: "https://github.com/absinthe-graphql/absinthe_plug.git", commit: "3a984cc341ebb32c79e7ae58b4ebd116d5c62f9e", override: true}, {:credo, "~> 1.6", only: [:dev, :test], runtime: false}, {:sobelow, "~> 0.8", only: :dev}, {:excoveralls, "~> 0.10", only: :test}, diff --git a/mix.lock b/mix.lock index 78c3a5be2..06b6fb6f2 100644 --- a/mix.lock +++ b/mix.lock @@ -1,172 +1,165 @@ %{ - "absinthe": {:hex, :absinthe, "1.7.10", "b33471b593260f148d05e4d771d1857e07b70a680f89cfa75184098bef4ec893", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1 or ~> 0.3", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ffda95735364c041a65a4b0e02ffb04eabb1e52ab664fa7eeecefb341449e8c2"}, + "absinthe": {:hex, :absinthe, "1.11.0", "dee6dfa57f86d52b25d8b0f925585b6b047d4921ac703c1075b6e7b8bc2fc83c", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1 or ~> 0.3", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "39b3b4b6e3eb405fa98b449feef0dacff81d89bf01c2866cfa513616c5530ba6"}, "absinthe_client": {:hex, :absinthe_client, "0.1.1", "1e778d587a27b85ecc35e4a5fedc64c85d9fdfd05395745c7af5345564dff54e", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:req, "~> 0.4", [hex: :req, repo: "hexpm", optional: false]}, {:slipstream, "~> 1.0", [hex: :slipstream, repo: "hexpm", optional: false]}], "hexpm", "e75a28c5bb647f485e9c03bbc3a47e7783742794bd4c10f3307a495a9e7273b6"}, - "absinthe_phoenix": {:hex, :absinthe_phoenix, "2.0.2", "e607b438db900049b9b3760f8ecd0591017a46122fffed7057bf6989020992b5", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:absinthe_plug, "~> 1.5", [hex: :absinthe_plug, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.5", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "d36918925c380dc7d2ed7d039c9a3b4182ec36723f7417a68745ade5aab22f8d"}, - "absinthe_plug": {:git, "https://github.com/absinthe-graphql/absinthe_plug.git", "3a984cc341ebb32c79e7ae58b4ebd116d5c62f9e", []}, - "absinthe_relay": {:hex, :absinthe_relay, "1.5.2", "cfb8aed70f4e4c7718d3f1c212332d2ea728f17c7fc0f68f1e461f0f5f0c4b9a", [:mix], [{:absinthe, "~> 1.5.0 or ~> 1.6.0 or ~> 1.7.0", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "0587ee913afa31512e1457a5064ee88427f8fe7bcfbeeecd41c71d9cff0b62b6"}, - "accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm", "11b18c220bcc2eab63b5470c038ef10eb6783bcb1fcdb11aa4137defa5ac1bb8"}, - "amqp": {:hex, :amqp, "3.3.2", "6cad7469957b29c517a26a27474828f1db28278a13bcc2e7970db9854a3d3080", [:mix], [{:amqp_client, "~> 3.9", [hex: :amqp_client, repo: "hexpm", optional: false]}], "hexpm", "f977c41d81b65a21234a9158e6491b2296f8bd5bda48d5b611a64b6e0d2c3f31"}, - "amqp_client": {:hex, :amqp_client, "3.12.14", "2b677bc3f2e2234ba7517042b25d72071a79735042e91f9116bd3c176854b622", [:make, :rebar3], [{:credentials_obfuscation, "3.4.0", [hex: :credentials_obfuscation, repo: "hexpm", optional: false]}, {:rabbit_common, "3.12.14", [hex: :rabbit_common, repo: "hexpm", optional: false]}], "hexpm", "5f70b6c3b1a739790080da4fddc94a867e99f033c4b1edc20d6ff8b8fb4bd160"}, - "apq": {:hex, :apq, "1.2.1", "efcbcbbb32b033b490a8d64d473fa042b4644960acab19a71076d28b263b8f46", [:mix], [{:absinthe_plug, "~> 1.4", [hex: :absinthe_plug, repo: "hexpm", optional: false]}], "hexpm", "4c33ab1e0cadc486597c266fe318f637a104305a21c4d0c306ac341d8bb6de02"}, - "arc": {:hex, :arc, "0.11.0", "ac7a0cc03035317b6fef9fe94c97d7d9bd183a3e7ce1606aa0c175cfa8d1ba6d", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:ex_aws_s3, "~> 2.0", [hex: :ex_aws_s3, repo: "hexpm", optional: true]}, {:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.1", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "e91a8bd676fca716f6e46275ae81fb96c0bbc7a9d5b96cac511ae190588eddd0"}, - "arc_ecto": {:hex, :arc_ecto, "0.11.3", "52f278330fe3a29472ce5d9682514ca09eaed4b33453cbaedb5241a491464f7d", [:mix], [{:arc, "~> 0.11.0", [hex: :arc, repo: "hexpm", optional: false]}, {:ecto, ">= 2.1.0", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "24beed35003707434a778caece7d71e46e911d46d1e82e7787345264fc8e96d0"}, - "arc_gcs": {:hex, :arc_gcs, "0.2.4", "1a499aaa5562019d180dcf9b74999ac647427c9e62c81190139304343a184d1e", [:mix], [{:arc, "~> 0.11", [hex: :arc, repo: "hexpm", optional: false]}, {:google_api_storage, "~> 0.13", [hex: :google_api_storage, repo: "hexpm", optional: false]}, {:goth, "~> 1.0", [hex: :goth, repo: "hexpm", optional: false]}, {:mime, "~> 1.3", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm", "8d59a84f6b06a6f994c0211d10837a37ab1d1cd2d66ca9309531c7856783ef6d"}, - "argon2_elixir": {:hex, :argon2_elixir, "2.0.5", "0073a87d755c7e63fc4f9d08b1d1646585b93f144cecde126e15061b24240b20", [:make, :mix], [{:comeonin, "~> 5.1", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "31d0dc208100fd77a2fc4aa2eb4567308791316c69dfb3d449550fbb058ecb02"}, - "artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm", "514586f4312ef3709a3ccbd8e55f69455add235c1729656687bb781d10d0afdb"}, - "bamboo": {:hex, :bamboo, "2.0.2", "0e2914d2bea0de3b1743384c24ffbe20fbb58094376a49f1cf5d9ed9959abd82", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "058d57cf4fcdac19413aa72732eb43c88954fb151a1cb6a382014e0cddbf6314"}, + "absinthe_phoenix": {:hex, :absinthe_phoenix, "2.0.5", "1fdcfc59db241b1d5e45e4c8c9db162277e64ec5728e0fd6958a3fa491a05b82", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:absinthe_plug, "~> 1.5", [hex: :absinthe_plug, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.5", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.13 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "086c6d4a1c32f7444713130d204c87b1b006169f5159026b73f02f7d38ccd05c"}, + "absinthe_plug": {:git, "https://github.com/absinthe-graphql/absinthe_plug.git", "a20146ead4bdd885f3c22115fbe37b86b4330217", []}, + "absinthe_relay": {:hex, :absinthe_relay, "1.6.0", "73590bdb0dcc192622f39fa11da6fca9df4e339b603c45ec7a93493eb94f1829", [:mix], [{:absinthe, ">= 1.7.10", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "32d6397a7af3fd02678ef9bc8e2f574487f14593cb3e4f9110fb1c695d4d2ac0"}, + "accept": {:hex, :accept, "0.3.7", "cd6e34a2d7e28ca38b2d3cb233734ca0c221efbc1f171f91fec5f162cc2d18da", [:rebar3], [], "hexpm", "ca69388943f5dad2e7232a5478f16086e3c872f48e32b88b378e1885a59f5649"}, + "amqp": {:hex, :amqp, "4.2.1", "c47520b42dfa79e8c6c3647510f6984d9b7981220d1296a5a4192cf561d864af", [:mix], [{:amqp_client, "~> 4.0", [hex: :amqp_client, repo: "hexpm", optional: false]}], "hexpm", "c37ecdd7c03a43816e6160a0e731f340352490ffad7c92af76600291ae660af4"}, + "amqp_client": {:hex, :amqp_client, "4.3.4", "b7ce1678e1e57495d4a170403016faf3808c1301f588325c4024159391797c5a", [:make, :rebar3], [{:credentials_obfuscation, "3.5.0", [hex: :credentials_obfuscation, repo: "hexpm", optional: false]}, {:rabbit_common, "4.3.4", [hex: :rabbit_common, repo: "hexpm", optional: false]}], "hexpm", "61418e1ce1097ad87ce51833929c2c1243782f1ace2e49897d8cc5a85ba53753"}, + "apq": {:hex, :apq, "2.0.1", "955cd8e28ff8213097d54e171764141cb76c2d7977027b3e6697af2bef4c8e29", [:mix], [{:absinthe_plug, "~> 1.5", [hex: :absinthe_plug, repo: "hexpm", optional: false]}], "hexpm", "22d9bb29d61901770275fe2255c3da8bf31552a503ba55558dbbad53a371012c"}, + "argon2_elixir": {:hex, :argon2_elixir, "4.1.3", "4f28318286f89453364d7fbb53e03d4563fd7ed2438a60237eba5e426e97785f", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "7c295b8d8e0eaf6f43641698f962526cdf87c6feb7d14bd21e599271b510608c"}, + "bamboo": {:hex, :bamboo, "2.5.0", "973f5cb1471a1d2d7d9da7b8e4f6096afb6a133f85394631184fd40be8adb8ab", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "35c8635ff6677a81ab7258944ff15739280f3254a041b6f0229dddeb9b90ad3d"}, "bamboo_phoenix": {:hex, :bamboo_phoenix, "1.0.0", "f3cc591ffb163ed0bf935d256f1f4645cd870cf436545601215745fb9cc9953f", [:mix], [{:bamboo, ">= 2.0.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.3.0", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "6db88fbb26019c84a47994bb2bd879c0887c29ce6c559bc6385fd54eb8b37dee"}, - "bandit": {:hex, :bandit, "1.11.1", "1eb33123cc3c17ae0c3447874eb83399ee530f960c39711ed240342fbd4865fa", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d4401016df9abbc6dcd325c0b78b2b193e7c7c96bb68f31e576112be025d84a5"}, - "base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"}, - "basic_auth": {:hex, :basic_auth, "2.2.4", "d8c748237870dd1df3bc5c0f1ab4f1fad6270c75472d7e62b19302ec59e92a79", [:mix], [{:plug, "~> 0.14 or ~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "a595b5f2a07e94cbde7be3dfeba24573e18655c88e74c8eb118364f856642e62"}, + "bandit": {:hex, :bandit, "1.12.5", "af205a8e550f304caae09a97d29fd3c79a7f337526ea7cd772d2ff11d2f7c800", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.5", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "c5684ca062fa407cac115aec3256383f3e2ec9fdced7904d59cf5a7bb7ed6181"}, + "basic_auth": {:hex, :basic_auth, "2.2.5", "ec2c934e4943b63cfc7d6b01c6f3fa51ade2a518ca36c9c0caee18a90bf98c4e", [:mix], [{:plug, "~> 0.14 or ~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "8b5f067bcfe48d7dc02d43c18ad9e9b54e630c2da720667ac8ed46979b54b7cb"}, "botanist": {:git, "https://github.com/michaeljguarino/botanist.git", "10244d96a88c3a5aa4f77f343bbb59643c623986", [branch: "ecto3"]}, "bourne": {:hex, :bourne, "1.1.0", "60a8bb3d5ad533a3a18257de9304e70e6bb2f4d7f354a529ef3f47c327c2dd97", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "81a389611ad067dc305d5ba4674280ea2b99ef012bca5e7de48357545edc05bc"}, - "briefly": {:git, "https://github.com/CargoSense/briefly", "b0fd495bf0c5ef2c44de2791a8cc7a20813c7d36", [ref: "b0fd495bf0c5ef2c44de2791a8cc7a20813c7d36"]}, - "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, - "castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"}, - "certifi": {:hex, :certifi, "2.15.0", "0e6e882fcdaaa0a5a9f2b3db55b1394dba07e8d6d9bcad08318fb604c6839712", [:rebar3], [], "hexpm", "b147ed22ce71d72eafdad94f055165c1c182f61a2ff49df28bcc71d1d5b94a60"}, - "cloudflare": {:hex, :cloudflare, "0.2.0", "e754fab186d5c9cd30cafdd336b8150b227e31e45ea6bd279d3c6cb20ff21ac1", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:restlax, "~> 0.1", [hex: :restlax, repo: "hexpm", optional: false]}], "hexpm", "0c2fced3058d92f8732c9911e309496a2f26f6f6d0f8216b8a2c62c2f8028748"}, + "briefly": {:hex, :briefly, "0.5.1", "ee10d48da7f79ed2aebdc3e536d5f9a0c3e36ff76c0ad0d4254653a152b13a8a", [:mix], [], "hexpm", "bd684aa92ad8b7b4e0d92c31200993c4bc1469fc68cd6d5f15144041bd15cb57"}, + "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, + "castore": {:hex, :castore, "1.0.21", "0a0e8330dc267a40a3b7ad86d39302764bb71758172904e6a59d5ad6443ce307", [:mix], [], "hexpm", "e42e22723e25dbd46876d056a03f685513d6e98f6b5e555dc551321decd76c5c"}, + "certifi": {:hex, :certifi, "2.17.0", "835748414307e15e05b17d0e518190228ce648b08d569a5cc93a85a40f3e5c9b", [:rebar3], [], "hexpm", "8122798a17f0293c80daada25d0f81c7f4d708c73fef782c7c9b1950e26e4d21"}, + "cloudflare": {:hex, :cloudflare, "0.5.0", "c5f13dbe0c9c229856b54e3d4b5329e3d8f6e948b4746ba0e56f92e66317f12b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:restlax, "~> 1.0.1", [hex: :restlax, repo: "hexpm", optional: false]}], "hexpm", "f9f9f5f46ab21e095eab8549e50e7105426c3df2642efd63f233d965ee203f10"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"}, "conduit": {:hex, :conduit, "0.12.10", "48059dae254fa956673ac8a65fc5ecb858816e728f64c4ab5578568ee942256e", [:mix], [{:elixir_uuid, "~> 1.1", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:timex, "~> 3.0", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "5a61cc4aa617cdd8fc0b676071ded3027a5f8b076ca116e867f7dfae40c6c879"}, - "conduit_amqp": {:hex, :conduit_amqp, "0.6.4", "5782fc18414de3c9e75583181a37ffc8d9207f7da168107557ecab719674ab42", [:mix], [{:amqp, "~> 1.0 and >= 1.1.1", [hex: :amqp, repo: "hexpm", optional: false]}, {:conduit, "~> 0.11", [hex: :conduit, repo: "hexpm", optional: false]}, {:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "d33c127a86049d7e06e402f6ed6b20922374960507c546244e62acaf96e06b34"}, - "configparser_ex": {:hex, :configparser_ex, "4.0.0", "17e2b831cfa33a08c56effc610339b2986f0d82a9caa0ed18880a07658292ab6", [:mix], [], "hexpm", "02e6d1a559361a063cba7b75bc3eb2d6ad7e62730c551cc4703541fd11e65e5b"}, + "conduit_amqp": {:hex, :conduit_amqp, "0.6.4", "5782fc18414de3c9e75583181a37ffc8d9207f7da168107557ecab719674ab42", [:mix], [{:amqp, ">= 1.1.1 and < 2.0.0-0", [hex: :amqp, repo: "hexpm", optional: false]}, {:conduit, "~> 0.11", [hex: :conduit, repo: "hexpm", optional: false]}, {:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "d33c127a86049d7e06e402f6ed6b20922374960507c546244e62acaf96e06b34"}, + "configparser_ex": {:hex, :configparser_ex, "5.0.1", "a17cf2bf5b85756eea3d9a18d1fb8b37e81000a756336b5b76a693db4bd5e4a9", [:mix], [], "hexpm", "ba16c7a7a68b79ffbdf61e3079dc6a5fd2fb0c8764ab005439a4591973c519f9"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, - "cors_plug": {:hex, :cors_plug, "2.0.0", "238ddb479f92b38f6dc1ae44b8d81f0387f9519101a6da442d543ab70ee0e482", [:mix], [{:plug, "~> 1.3 or ~> 1.4 or ~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "118162367ef41448c9742ced8c8bc33ae2857d958d6b997e1db26402dd8c6f37"}, - "cowboy": {:hex, :cowboy, "2.15.0", "9cfe86ed7117bf045e10adbedb0170af7be57f2a3637e7be143433d8dd267396", [:make, :rebar3], [{:cowlib, ">= 2.16.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "179fb65140fb440a17b767ad53b755081506f9596c4db5c49c0396d8c8643668"}, + "cors_plug": {:hex, :cors_plug, "2.0.3", "316f806d10316e6d10f09473f19052d20ba0a0ce2a1d910ddf57d663dac402ae", [:mix], [{:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ee4ae1418e6ce117fc42c2ba3e6cbdca4e95ecd2fe59a05ec6884ca16d469aea"}, + "cowboy": {:hex, :cowboy, "2.18.0", "bff388eb4d6356cb3f88c26e65b515976bf04b401b805d31550c3e60eba8fe18", [:make, :rebar3], [{:cowlib, ">= 2.19.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "62d0b26abcf455054972b0da242389c69d5982ce5914afb8c344517f667b9600"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, - "cowlib": {:hex, :cowlib, "2.16.1", "318d385d55f657e9a5005838c4e426e13dcd724a691438384b6165a69687e531", [:make, :rebar3], [], "hexpm", "58f1e425a9e04176f1d30e20116f57c4e90ef0e187552e9741c465bdf4044f70"}, - "credentials_obfuscation": {:hex, :credentials_obfuscation, "3.4.0", "34e18b126b3aefd6e8143776fbe1ceceea6792307c99ac5ee8687911f048cfd7", [:rebar3], [], "hexpm", "738ace0ed5545d2710d3f7383906fc6f6b582d019036e5269c4dbd85dbced566"}, - "credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"}, - "crontab": {:hex, :crontab, "1.1.9", "0cf8053611830bc5a7510ace6e846325b459d94f5325234435a4af7c654502bc", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, - "cutkey": {:git, "https://github.com/potatosalad/cutkey.git", "47640d04fb4db4a0b79168d7fca0df87aaa42751", []}, - "dataloader": {:hex, :dataloader, "1.0.10", "a42f07641b1a0572e0b21a2a5ae1be11da486a6790f3d0d14512d96ff3e3bbe9", [:mix], [{:ecto, ">= 3.4.3 and < 4.0.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "54cd70cec09addf4b2ace14cc186a283a149fd4d3ec5475b155951bf33cd963f"}, - "db_connection": {:hex, :db_connection, "2.4.2", "f92e79aff2375299a16bcb069a14ee8615c3414863a6fef93156aee8e86c2ff3", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4fe53ca91b99f55ea249693a0229356a08f4d1a7931d8ffa79289b145fe83668"}, - "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, + "cowlib": {:hex, :cowlib, "2.19.0", "c9d11c9d035472e27a740c9f327786c61ed209269b4be0260d59d3ec07b8949f", [:make, :rebar3], [], "hexpm", "6dc66e3135b229193ea4dcb14294e79520c923d391315c9c962ef0b4bea72356"}, + "credentials_obfuscation": {:hex, :credentials_obfuscation, "3.5.0", "61e282adfb4439486b3994faaec69543c7ee6cc7e70c6340e8853fd9deaf8219", [:rebar3], [], "hexpm", "843adbe3246861ce0f1a0fa3222f384834eb31defd8d6b9cba7afd2977c957bc"}, + "credo": {:hex, :credo, "1.7.19", "cc52129665fc7c15143d47838fda0f9cd6dac9ceced7bf4da6f85fcbfe64b12a", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "2d8bc95d5a7bb99dd2613621d4f08c6a3575c3fd4b62e6a2b48a100352a557b8"}, + "dataloader": {:hex, :dataloader, "2.0.2", "c45075e0692e68638a315e14f747bd8d7065fb5f38705cf980f62d4cd344401f", [:mix], [{:ecto, ">= 3.4.3 and < 4.0.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:opentelemetry_process_propagator, "~> 0.2.1 or ~> 0.3", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4c6cabc0b55e96e7de74d14bf37f4a5786f0ab69aa06764a1f39dda40079b098"}, + "db_connection": {:hex, :db_connection, "2.10.2", "ae391e803a5adff104da913c2fc1c0c14a37f8b10001dcef568796e1fb7bf95c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "510b14482330f1af6490a2fa0efd8d4f1435d1529b165647df22ac0f2df0fa93"}, + "decimal": {:hex, :decimal, "3.1.1", "430d87b04011ce6cbd4fd205be758311a81f87d552d40904abd00f015935b1d0", [:mix], [], "hexpm", "c5f25f2ced74a0587d03e6023f595db8e924c9d3922c8c8ffd9edfc4498cf1f6"}, "decorator": {:hex, :decorator, "1.4.0", "a57ac32c823ea7e4e67f5af56412d12b33274661bb7640ec7fc882f8d23ac419", [:mix], [], "hexpm", "0a07cedd9083da875c7418dea95b78361197cf2bf3211d743f6f7ce39656597f"}, "dictionary": {:hex, :dictionary, "0.1.1", "fb333a3ee04c514231f0a5e166dd1c27429620b0dabb12fd42e5d28b11657a0a", [:mix], [], "hexpm", "17bae452ab5ecf7bdd75315c6adb44622242de9cf700ab107865ab5557443c2b"}, - "distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"}, "dns": {:hex, :dns, "2.4.0", "44790a0375b28bdc7b59fc894460bfcb03ffeec4c5984e2c3e8b0797b1518327", [:mix], [], "hexpm", "e178e353c469820d02ba889d6a80d01c8c27b47dfcda4016a9cbc6218e3eed64"}, - "earmark": {:hex, :earmark, "1.4.2", "3aa0bd23bc4c61cf2f1e5d752d1bb470560a6f8539974f767a38923bb20e1d7f", [:mix], [], "hexpm", "5e8806285d8a3a8999bd38e4a73c58d28534c856bc38c44818e5ba85bbda16fb"}, - "ecto": {:hex, :ecto, "3.9.6", "2f420c173efcb2e22fa4f8fc41e75e02b3c5bd4cffef12085cae5418c12e530d", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df17bc06ba6f78a7b764e4a14ef877fe5f4499332c5a105ace11fe7013b72c84"}, + "earmark": {:hex, :earmark, "1.4.49", "024521298c2308f0193ba7a5df742a5e901dad03cd44ba57f861d3f0fada5d1b", [:mix], [], "hexpm", "ffad0257b92ac342b236d1744f7f19793da77bbd7281f32ccdfb44c047a05bf2"}, + "ecto": {:hex, :ecto, "3.14.2", "99db28a864293a789c970651de711e3cae184291e0e7ea1166c54055ac41c1f3", [:mix], [{:decimal, "~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "25d60b8c816a07d19d85b80bdf60978bd8b102209dda198d768cd7c6745339a6"}, "ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"}, - "ecto_sql": {:hex, :ecto_sql, "3.9.0", "2bb21210a2a13317e098a420a8c1cc58b0c3421ab8e3acfa96417dab7817918c", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a8f3f720073b8b1ac4c978be25fa7960ed7fd44997420c304a4a2e200b596453"}, - "elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"}, + "ecto_sql": {:hex, :ecto_sql, "3.14.0", "06446ab8410d2f85bfbb80857ee224ab3b693700cbb38f6535d507449a627b2e", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.14.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.8", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f4d8d36faf294c9417b5a37ec7ac8217ee2abdef5fcf197ba690f361548d3949"}, + "elixir_make": {:hex, :elixir_make, "0.10.0", "16577e2583a79bb79237bbff349619ef5d80afffc07eac6e4faf0d00e2ddaf7d", [:mix], [], "hexpm", "dc1f09fb7fa68866b886abd5f0f3c83553b1a19a52359a899e92af1bb3b31982"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, - "ex_aws": {:hex, :ex_aws, "2.4.0", "f2c978e15145722258513907a9d73ef1d81ed92e76331138d42649ae2b1b6eba", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "66dd0bacaa4113d372d61d795c22d78af170672384c81ebab97a42edf4128543"}, + "ex_aws": {:hex, :ex_aws, "2.7.0", "e6bfd4b5fb8c791aa6c7d57fc7c45f050bb89de9576f1f6104aa974b234c01ec", [:mix], [{:configparser_ex, "~> 5.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 4.0", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bfe9d744d4fd4c1f40314ee7fab504d5547d1f01cd377fff1568cbe630b06d65"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.3.3", "61412e524616ea31d3f31675d8bc4c73f277e367dee0ae8245610446f9b778aa", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "0044f0b6f9ce925666021eafd630de64c2b3404d79c85245cc7c8a9a32d7f104"}, "ex_aws_sts": {:hex, :ex_aws_sts, "2.3.0", "ce48c4cba7f1595a7d544458d0202ca313124026dba7b1a0021bbb1baa3d66d0", [:mix], [{:ex_aws, "~> 2.2", [hex: :ex_aws, repo: "hexpm", optional: false]}], "hexpm", "f14e4c7da3454514bf253b331e9422d25825485c211896ab3b81d2a4bdbf62f5"}, "ex_crypto": {:git, "https://github.com/ntrepid8/ex_crypto", "0997a1aaebe701523c0a9b71d4acec4a1819354e", []}, "ex_doc": {:hex, :ex_doc, "0.18.4", "4406b8891cecf1352f49975c6d554e62e4341ceb41b9338949077b0d4a97b949", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm", "9dbe1ce1d711dc5362e3b3280e92989ad61413ce423bc4e9f76d5fcc51ab8d6b"}, - "ex_image_info": {:hex, :ex_image_info, "0.2.4", "610002acba43520a9b1cf1421d55812bde5b8a8aeaf1fe7b1f8823e84e762adb", [:mix], [], "hexpm", "fd1a7e02664e3b14dfd3b231d22fdd48bd3dd694c4773e6272b3a6228f1106bc"}, + "ex_image_info": {:hex, :ex_image_info, "0.2.7", "0460539183b6fd5f4ab2d068839922379d6b27c28b25f11757fdf28a5f5c79b1", [:mix], [], "hexpm", "c17cd937e044e2a26962c37cd8965acc0b31cb5fe7bc8119c721546b943c06ca"}, "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"}, - "excoveralls": {:hex, :excoveralls, "0.15.2", "809c1016660d80b28bbcd8cb7fd761791300def53345c1af5bd97db1330619ad", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f359dda36f15ae885d3259a90919b09ae9318f37c583c403493fe23808b2b882"}, + "excoveralls": {:hex, :excoveralls, "0.18.5", "e229d0a65982613332ec30f07940038fe451a2e5b29bce2a5022165f0c9b157e", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "523fe8a15603f86d64852aab2abe8ddbd78e68579c8525ae765facc5eae01562"}, + "expo": {:hex, :expo, "1.1.1", "4202e1d2ca6e2b3b63e02f69cfe0a404f77702b041d02b58597c00992b601db5", [:mix], [], "hexpm", "5fb308b9cb359ae200b7e23d37c76978673aa1b06e2b3075d814ce12c5811640"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, - "finch": {:hex, :finch, "0.17.0", "17d06e1d44d891d20dbd437335eebe844e2426a0cd7e3a3e220b461127c73f70", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8d014a661bb6a437263d4b5abf0bcbd3cf0deb26b1e8596f2a271d22e48934c7"}, - "flow": {:hex, :flow, "0.15.0", "503717c0e367b5713336181d5305106840f64abbad32c75d7af5ef1bb0908e38", [:mix], [{:gen_stage, "~> 0.14.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "d7ecbd4dd38a188494bc996d5014ef8335f436a0b262140a1f6441ae94714581"}, - "gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm", "8453e2289d94c3199396eb517d65d6715ef26bcae0ee83eb5ff7a84445458d76"}, + "finch": {:hex, :finch, "0.23.0", "e3f9287ac25a8832f848b144c2b57346aac65b205e2e0629a52adfe6507fd837", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.8", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "80e58d3f936f57e3fdf404f83a3642897ae6d9fb642934e46da4d8fe761b99d5"}, + "flow": {:hex, :flow, "1.2.4", "1dd58918287eb286656008777cb32714b5123d3855956f29aa141ebae456922d", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "874adde96368e71870f3510b91e35bc31652291858c86c0e75359cbdd35eb211"}, + "gen_stage": {:hex, :gen_stage, "1.3.2", "7c77e5d1e97de2c6c2f78f306f463bca64bf2f4c3cdd606affc0100b89743b7b", [:mix], [], "hexpm", "0ffae547fa777b3ed889a6b9e1e64566217413d018cabd825f786e843ffe63e7"}, "gen_state_machine": {:hex, :gen_state_machine, "2.1.0", "a38b0e53fad812d29ec149f0d354da5d1bc0d7222c3711f3a0bd5aa608b42992", [:mix], [], "hexpm", "ae367038808db25cee2f2c4b8d0531522ea587c4995eb6f96ee73410a60fa06b"}, - "gettext": {:hex, :gettext, "0.20.0", "75ad71de05f2ef56991dbae224d35c68b098dd0e26918def5bb45591d5c8d429", [:mix], [], "hexpm", "1c03b177435e93a47441d7f681a7040bd2a816ece9e2666d1c9001035121eb3d"}, - "goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm", "99cb4128cffcb3227581e5d4d803d5413fa643f4eb96523f77d9e6937d994ceb"}, - "google_api_cloud_billing": {:hex, :google_api_cloud_billing, "0.23.5", "a406b2c91af46e8935f09d27506db7b1d62d78d3599f4d833c7fa4d0f10b372f", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "6bd03bf7758e003e36f7765b2fe2832769ef088e8571cbf2296792af25444871"}, - "google_api_cloud_resource_manager": {:hex, :google_api_cloud_resource_manager, "0.41.4", "9ffc235f641263491de0df452a6ef06dec4dd8cb18cdfc9e876d1b71b945f582", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "bc3e7a16decb94f2593582238962da0beb58a123c6b11e42a1dfea5754a53526"}, - "google_api_iam": {:hex, :google_api_iam, "0.40.0", "00201bd825e867f58714237f834407a9c7bdd4caedd84ea5e4939aa66afeb4fa", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "a60e581cdee8429b12ccc4f198ffe6d6d56bad382bf171da337333f0fcb1d884"}, - "google_api_service_usage": {:hex, :google_api_service_usage, "0.18.5", "e279eb8743308a0074c802cf83fcf55ca092427a98bfe2e29a2470b8f3595f85", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "f7891e1f47338f3374093fb99d0a66669084a4bf31692dfd82b90dc7aaac1c0f"}, - "google_api_storage": {:hex, :google_api_storage, "0.34.0", "4811461a5065f8a5d59a7fe71efd9c491ba593d20743f0d6f4714153c1dd575f", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "b343f2f1688acd2e8a2302bed399a24d93626f8e8c809b358214bb0fb7d2669a"}, - "google_gax": {:hex, :google_gax, "0.4.1", "310105070626013712c56f8007b6ff7b4ead02ecad1efe7888350c6eaba52783", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:poison, ">= 3.0.0 and < 5.0.0", [hex: :poison, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "aef7dce7e04840c0e611f962475e3223d27d50ebd5e7d8e9e963c5e9e3b1ca79"}, - "goth": {:hex, :goth, "1.3.1", "f3e08a7f23ea8992ab92d2e1d5c72ea1a8fbd2fe3a46ad1b08d0620f71374fdc", [:mix], [{:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:jose, "~> 1.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "90326c2c0a7acda7fb75fc4a4f0cba84945d8fcb22694d36c9967cec8949937c"}, - "guardian": {:hex, :guardian, "1.2.1", "bdc8dd3dbf0fb7216cb6f91c11831faa1a64d39cdaed9a611e37f2413e584983", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "723fc404edfb7bd5cba4cd83329b352037f102aa97468f44e58ac7f47c136a98"}, - "hackney": {:hex, :hackney, "1.25.0", "390e9b83f31e5b325b9f43b76e1a785cbdb69b5b6cd4e079aa67835ded046867", [:rebar3], [{:certifi, "~> 2.15.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.4", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "7209bfd75fd1f42467211ff8f59ea74d6f2a9e81cbcee95a56711ee79fd6b1d4"}, - "hammer": {:hex, :hammer, "6.1.0", "f263e3c3e9946bd410ea0336b2abe0cb6260af4afb3a221e1027540706e76c55", [:make, :mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b47e415a562a6d072392deabcd58090d8a41182cf9044cdd6b0d0faaaf68ba57"}, - "hammer_plug": {:hex, :hammer_plug, "3.0.0", "7b1d000021e3ccc92cc6405c5537d3ec22f8f8f1274a1ae9351a8d98c32a2803", [:mix], [{:hammer, "~> 6.0", [hex: :hammer, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "35275f98f887bef8d84a8e0a3021ba1cd14d0e15c11221f6f8c833a3d43f35d8"}, - "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, - "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, - "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, - "inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"}, + "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, + "google_api_cloud_billing": {:hex, :google_api_cloud_billing, "0.26.0", "6b2f7f9aaabd3eb8d272d101fdac9df3a08a5be511c4a4fbc30e807aecb4c5bf", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "b7f83b99725608bc812ec1acd698e1f950a7eb0cdd6c0ff1daa4a128ca3d8137"}, + "google_api_cloud_resource_manager": {:hex, :google_api_cloud_resource_manager, "0.44.1", "a1d39bfd3202b7a19c46becb19a5adbb4d3df6b2fdad58400de95be850708fc8", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "c49184be3dcbefa8d3e6f5c001d8dc0818632fd551c1c6e24e68284433478455"}, + "google_api_iam": {:hex, :google_api_iam, "0.45.0", "08eeddf383bb02f74f02169a4d509479240622491c71c580229a89412f73e4d9", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "acbce36bab44412c7be4ce1c8fb0283876d5c06ce2b2e938fb927be3e35346e6"}, + "google_api_service_usage": {:hex, :google_api_service_usage, "0.27.0", "578f6b5b9e1f76253d9cf823b5bbba27bf03bffc8fa4adb6f466c44c476763a2", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "89eedd964ae49afb3d6ff0a127f0db3a400dd6ef6c29c848a96db3ffc5846883"}, + "google_api_storage": {:hex, :google_api_storage, "0.46.1", "f944e40828b7fd90d00cef1ddb9ac542acb88adb18d6bc7c2015bafbd696eb6c", [:mix], [{:google_gax, "~> 0.4", [hex: :google_gax, repo: "hexpm", optional: false]}], "hexpm", "a6e162017b51bf1d80ae9d0e5cd47c8a3d246d52d9f025c9ca5e2eb71b1b6f75"}, + "google_gax": {:hex, :google_gax, "0.4.0", "83651f8561c02a295826cb96b4bddde030e2369747bbddc592c4569526bafe94", [:mix], [{:poison, ">= 3.0.0 and < 5.0.0", [hex: :poison, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "a95d36f1dd753ab31268dd8bb6de9911243c911cfda9080f64778f6297b9ac57"}, + "goth": {:git, "https://github.com/pluralsh/goth.git", "4958159d1e9acec2154590ecacc732ecd58f8312", [branch: "plrl-cleanup"]}, + "guardian": {:hex, :guardian, "2.5.0", "dfe9533d734e1ca0341eaf1f7c951513b1c19006db69beaf2bae16cf63845ac2", [:mix], [{:jose, "~> 1.11.9", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "bc75cc9374825194060b0cd3230ce4440df23d8509d1f17472b210d3ee525790"}, + "h2": {:hex, :h2, "0.12.0", "f393539ee2728f8118fb2024b6d5f3e2c45e40ceb31b18b4e9bf5e50d028f80f", [:rebar3], [], "hexpm", "beaafc93c54cdc5d623247334d3970cdf4bc66b6b8b296b74ba1d7c7513c3dfc"}, + "hackney": {:hex, :hackney, "4.7.4", "8fe2ddaa3ca27de99d68e682d72b66d07d2331da680f77c8000580a0122c69e6", [:rebar3], [{:certifi, "~> 2.17.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:h2, "~> 0.12.0", [hex: :h2, repo: "hexpm", optional: false]}, {:idna, "~> 7.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.5", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.2", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:webtransport, "~> 0.4.5", [hex: :webtransport, repo: "hexpm", optional: false]}], "hexpm", "d07d7e1358353ab6cc75132f058c155287f3e013d43f709fbb79d79eeab98195"}, + "ham": {:hex, :ham, "0.3.2", "02ae195f49970ef667faf9d01bc454fb80909a83d6c775bcac724ca567aeb7b3", [:mix], [], "hexpm", "b71cc684c0e5a3d32b5f94b186770551509e93a9ae44ca1c1a313700f2f6a69a"}, + "hammer": {:hex, :hammer, "6.2.1", "5ae9c33e3dceaeb42de0db46bf505bd9c35f259c8defb03390cd7556fea67ee2", [:mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b9476d0c13883d2dc0cc72e786bac6ac28911fba7cc2e04b70ce6a6d9c4b2bdc"}, + "hammer_plug": {:hex, :hammer_plug, "3.2.0", "47db6ed67d5cdf09fb6035f26b0b4b2335c3ae08a7ac061e3303bbb756fe9a09", [:mix], [{:hammer, "~> 6.0", [hex: :hammer, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "1ee7084732414c7a32f467717d13e6fba95c60b70c3f56d51f7c08a4183aadfe"}, + "hpax": {:hex, :hpax, "1.0.4", "777de5d433b0fbdc7c418159c8055910faa8047ffdb3d6b31098d2a46cd7685c", [:mix], [], "hexpm", "afc7cb142ebcc2d01ce7816190b98ce5dd49e799111b24249f3443d730f377ca"}, + "httpoison": {:git, "https://github.com/pluralsh/httpoison.git", "75f6305ce8c89b39d12574008e596785d65d4d1c", [branch: "fix-certs"]}, + "idna": {:hex, :idna, "7.1.0", "1067a13043538129602d2f2ce6899d8713125c7d19734aa557ce2e3ea55bd4f1", [:rebar3], [], "hexpm", "6ae959a025bf36df61a8cab8508d9654891b5426a84c44d82deaffd6ddf8c71f"}, + "inet_cidr": {:hex, :inet_cidr, "1.0.9", "e0ef72a2942529da78c8e4147d53f2ef5f6f5293335c3637b0fdf83c012cc816", [:mix], [], "hexpm", "172da15ff7cf635b1feaf14f5818be28c811b37cc5fb7c5f7c01058c1c1066cc"}, "influxql": {:hex, :influxql, "0.2.1", "71bfd5c0d81bf870f239baf3357bf5226b44fce16e1b9399ba1368203ca71245", [:mix], [], "hexpm", "75faf04960d6830ca0827869eaac1ba092655041c5e96deb2a588bafb601205c"}, "instream": {:hex, :instream, "1.0.0", "e5e848ac0de91ead5a5f04b5fe7d72e1be9cdd8862525b6f5fed27dca58096d2", [:mix], [{:hackney, "~> 1.1", [hex: :hackney, repo: "hexpm", optional: false]}, {:influxql, "~> 0.2.0", [hex: :influxql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "17cead56c5f8cab804bd02d8be207d933078404338171c082df1b0c098a5b24b"}, - "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, - "joken": {:hex, :joken, "2.5.0", "09be497d804b8115eb6f07615cef2e60c2a1008fb89dc0aef0d4c4b4609b99aa", [:mix], [{:jose, "~> 1.11.2", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "22b25c89617c5ed8ca7b31026340a25ea0f9ca7160f9706b79be9ed81fdf74e7"}, - "jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"}, - "jsx": {:hex, :jsx, "2.11.0", "08154624050333919b4ac1b789667d5f4db166dc50e190c4d778d1587f102ee0", [:rebar3], [], "hexpm", "eed26a0d04d217f9eecefffb89714452556cf90eb38f290a27a4d45b9988f8c0"}, - "junit_formatter": {:hex, :junit_formatter, "3.3.1", "c729befb848f1b9571f317d2fefa648e9d4869befc4b2980daca7c1edc468e40", [:mix], [], "hexpm", "761fc5be4b4c15d8ba91a6dafde0b2c2ae6db9da7b8832a55b5a1deb524da72b"}, + "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, + "joken": {:hex, :joken, "2.7.0", "a9fd87805b1b58313435c04b950857d7557f019b157d503dc4783006e4e80ed1", [:mix], [{:jose, "~> 1.11.12", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "ffd0d92e12dbf497311386b75f9b5027d370e32c74f6e5576804d3a9eed668ab"}, + "jose": {:hex, :jose, "1.11.12", "06e62b467b61d3726cbc19e9b5489f7549c37993de846dfb3ee8259f9ed208b3", [:mix, :rebar3], [], "hexpm", "31e92b653e9210b696765cdd885437457de1add2a9011d92f8cf63e4641bab7b"}, + "junit_formatter": {:hex, :junit_formatter, "3.4.0", "d0e8db6c34dab6d3c4154c3b46b21540db1109ae709d6cf99ba7e7a2ce4b1ac2", [:mix], [], "hexpm", "bb36e2ae83f1ced6ab931c4ce51dd3dbef1ef61bb4932412e173b0cfa259dacd"}, "k8s_traffic_plug": {:git, "https://github.com/pluralsh/k8s_traffic_plug", "166f45c84523c8a160369c22a707b3c1765800ba", []}, - "kazan": {:git, "https://github.com/michaeljguarino/kazan.git", "467e259b3316f2e0723a6a28ca199561d536be95", [branch: "k8s-1.23"]}, - "lager": {:hex, :lager, "3.8.0", "3402b9a7e473680ca179fc2f1d827cab88dd37dd1e6113090c6f45ef05228a1c", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm", "f6cb541b688eab60730d8d286eb77256a5a9ad06eac10d43beaf55d07e68bbb6"}, - "libcluster": {:hex, :libcluster, "3.3.1", "e7a4875cd1290cee7a693d6bd46076863e9e433708b01339783de6eff5b7f0aa", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b575ca63c1cd84e01f3fa0fc45e6eb945c1ee7ae8d441d33def999075e9e5398"}, - "libring": {:hex, :libring, "1.4.0", "41246ba2f3fbc76b3971f6bce83119dfec1eee17e977a48d8a9cfaaf58c2a8d6", [:mix], [], "hexpm", "1feaf05ee886815ad047cad7ede17d6910710986148ae09cf73eee2989717b81"}, + "kazan": {:git, "https://github.com/michaeljguarino/kazan.git", "bbeda162b85c5b49a4f044cee92070aa1670a44e", [ref: "bbeda162b85c5b49a4f044cee92070aa1670a44e"]}, + "libcluster": {:hex, :libcluster, "3.3.3", "a4f17721a19004cfc4467268e17cff8b1f951befe428975dd4f6f7b84d927fe0", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "7c0a2275a0bb83c07acd17dab3c3bfb4897b145106750eeccc62d302e3bdfee5"}, + "libring": {:hex, :libring, "1.7.0", "4f245d2f1476cd7ed8f03740f6431acba815401e40299208c7f5c640e1883bda", [:mix], [], "hexpm", "070e3593cb572e04f2c8470dd0c119bc1817a7a0a7f88229f43cf0345268ec42"}, "libvault": {:hex, :libvault, "0.2.4", "3d9a999c222a2d9b8666ef1dbd067f30c9ecead6be27367f84af7ffde7813ee1", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:tesla, "~> 1.3", [hex: :tesla, repo: "hexpm", optional: true]}], "hexpm", "f495afb2b99464b8c1dccccf59744afb361169ca1fc67ba48e71ed35a00315f0"}, - "mcp_sse": {:hex, :mcp_sse, "0.1.4", "5e3409af38e535f2b4a7c848c0c81c7d36689a56e645bd0296ef8bae565bbcdd", [:mix], [{:bandit, "~> 1.5", [hex: :bandit, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "5670d4a5a4ce1797cfb9393d6eff95d9efa01bedb15fdb5b614b68a0e1854e84"}, - "meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, - "mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"}, + "mcp_sse": {:hex, :mcp_sse, "0.1.6", "df0a714e9694599dd3535e05924395fe32870349fd8fcf19688054fe8d058806", [:mix], [{:bandit, "~> 1.5", [hex: :bandit, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "777e4e62e5b223ae892a6c46136570ead18221b7ef5459290a257176835d3f18"}, + "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"}, "mimerl": {:hex, :mimerl, "1.5.0", "f35aca6f23242339b3666e0ac0702379e362b469d0aea167f6cc713547e777ed", [:rebar3], [], "hexpm", "db648ce065bae14ea84ca8b5dd123f42f49417cef693541110bf6f9e9be9ecc4"}, - "mimic": {:hex, :mimic, "1.1.3", "3bad83d5271b4faa7bbfef587417a6605cbbc802a353395d446a1e5f46fe7115", [:mix], [], "hexpm", "0d93cb8fcd00a1013bae56050755879050bb9b8ef0c3d51b6fec5a2f1fc33d66"}, - "mint": {:hex, :mint, "1.9.1", "3bc120b743ed2e99ad920910f2613e9faebabb2257731b0e2ea4d8ccd9eceede", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "831101bd560b086316fab5f7adb21a4f3455717d8e4bc8368b052e09aa9163e0"}, - "mint_web_socket": {:hex, :mint_web_socket, "1.0.4", "0b539116dbb3d3f861cdf5e15e269a933cb501c113a14db7001a3157d96ffafd", [:mix], [{:mint, ">= 1.4.1 and < 2.0.0-0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "027d4c5529c45a4ba0ce27a01c0f35f284a5468519c045ca15f43decb360a991"}, - "mock": {:hex, :mock, "0.3.3", "42a433794b1291a9cf1525c6d26b38e039e0d3a360732b5e467bfc77ef26c914", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, + "mimic": {:hex, :mimic, "1.12.0", "34c9d1fb8e756df09ca5f96861d273f2bb01063df1a6a51a4c101f9ad7f07a9c", [:mix], [{:ham, "~> 0.2", [hex: :ham, repo: "hexpm", optional: false]}], "hexpm", "eaa43d495d6f3bc8099b28886e05a1b09a2a6be083f6385c3abc17599e5e2c43"}, + "mint": {:hex, :mint, "1.9.3", "3337184d69179695c7a9f1714d92c11e629d36c8c037a21cf490131d3d150554", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5f7c9342480c069dbbc4eeac3490303c9e01870ff01a7f1d29b6107054fc1e74"}, + "mint_web_socket": {:hex, :mint_web_socket, "1.0.6", "5ffcf350df5b90f2d7a04adf877165228804993714592512374218d4679e325a", [:mix], [{:mint, ">= 1.4.1 and < 2.0.0-0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "0c360e9012413f1c115a63532601eb5d63731aab7010949178769760686c1698"}, "mojito": {:hex, :mojito, "0.7.12", "0461764ba427e720cc7270a603ac2b157a0c70688ffdf19dd116815eba554576", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mint, "~> 1.1", [hex: :mint, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1fa274d0fab59c6986d1efcb9d40f01d0b1159403968665a141a17601c29daac"}, - "nebulex": {:hex, :nebulex, "2.4.2", "b3d2d86d57b15896fb8e6d6dd49b4a9dee2eedd6eddfb3b69bfdb616a09c2817", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.0", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "c9f888e5770fd47614c95990d0a02c3515216d51dc72e3c830eaf28f5649ba52"}, + "nebulex": {:hex, :nebulex, "2.6.6", "677e27fcfa89eaa085d9509d5e066f305f98c1b2264ce6676eaca6fb08d4939e", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.1", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "8cbf531af6fe407383b6ba410a43a19319af47804929d8a8d1975a780b9952df"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_ownership": {:hex, :nimble_ownership, "0.3.2", "d4fa4056ade0ae33b5a9eb64554a1b3779689282e37513260125d2d6b32e4874", [:mix], [], "hexpm", "28b9a9f4094fda1aa8ca72f732ff3223eb54aa3eda4fed9022254de2c152b138"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, - "oauth2": {:hex, :oauth2, "2.0.0", "338382079fe16c514420fa218b0903f8ad2d4bfc0ad0c9f988867dfa246731b0", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "881b8364ac7385f9fddc7949379cbe3f7081da37233a1aa7aab844670a91e7e7"}, - "openid_connect": {:git, "https://github.com/pluralsh/openid_connect", "c3b2701b9adbe01fd89bbd09816ffa6c9e4a825e", []}, + "oauth2": {:hex, :oauth2, "2.1.1", "3bec9bf49e88e1b0c0ddf9f44c393d71fd0f88e905766f2e2cc5d57e6bcc5352", [:mix], [{:tesla, "~> 1.18", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "1d5997cb1ff1643dac17076b6c00c91e4381d8389f3c49a8c390984606dad439"}, + "openid_connect": {:git, "https://github.com/pluralsh/openid_connect", "58bda539debd81dc1a253139ae9b5cbbd65c8047", []}, "parallax": {:hex, :parallax, "1.0.0", "decfed51b2d41c88ea4398d3bd8fadd2ceb1f913cf0f44ef2cb41e732ace31f5", [:mix], [], "hexpm", "8a8b91685bfacb483ff9370b98844ee01107544a11ee49b5f1d98df0eff2b1e4"}, - "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, - "phoenix": {:hex, :phoenix, "1.6.17", "6f5a6b12263edf94b4c96e1e401df97295d028d8bbc8d028ca8dcee991c2914a", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "82786bdc409b943b58a89c4b105b6095a17171999b685e9a79db19c291cefbeb"}, - "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, - "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, - "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.5.3", "ff153c46aee237dd7244f07e9b98d557fe0d1de7a5916438e634c3be2d13c607", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.16.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "e36e62b1f61c19b645853af78290a5e7900f7cae1e676714ff69f9836e2f2e76"}, - "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.0", "4fe222c0be55fdc3f9c711e24955fc42a7cd9b7a2f5f406f2580a567c335a573", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "bebf0fc2d2113b61cb5968f585367234b7b4c21d963d691de7b4b2dc6cdaae6f"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "0.16.4", "5692edd0bac247a9a816eee7394e32e7a764959c7d0cf9190662fc8b0cd24c97", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.9 or ~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "754ba49aa2e8601afd4f151492c93eb72df69b0b9856bab17711b8397e43bba0"}, - "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, - "phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"}, - "phoenix_view": {:hex, :phoenix_view, "2.0.2", "6bd4d2fd595ef80d33b439ede6a19326b78f0f1d8d62b9a318e3d9c1af351098", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "a929e7230ea5c7ee0e149ffcf44ce7cf7f4b6d2bfe1752dd7c084cdff152d36f"}, - "piazza_core": {:git, "https://github.com/michaeljguarino/piazza_core", "ebbda3cff4f49f5ec647a28c03a3dd3ce03766db", []}, - "plug": {:hex, :plug, "1.18.5", "30922fad9e39df9812cea76e8d00015ec071e8d0a4b8c1eb5736d00564cb7dd1", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f923ffe5b1f8092469ea79b3d9fecd2913d5318874b642f6489995c89ddbc20b"}, - "plug_cowboy": {:hex, :plug_cowboy, "2.8.1", "5aa391a5e8d1ac3192e36a3bcaff12b5fd6ef6c7e29b53a38e63a860783e77d0", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "4c200288673d5bc86a0ab7dc6a2a069176a74e5d573ef62740a1c517458a5f26"}, - "plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"}, - "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"}, + "parse_trans": {:hex, :parse_trans, "3.4.2", "c352ddc1a0d5e54f9b1654d45f9c432eef76f9cea371c55ddff769ef688fdb74", [:rebar3], [], "hexpm", "4c25347de3b7c35732d32e69ab43d1ceee0beae3f3b3ade1b59cbd3dd224d9ca"}, + "phoenix": {:hex, :phoenix, "1.8.13", "e33192826d9bed4022bdb3f5a7b36c04362049d9390fd1b581d5ad6261779268", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 2.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "ad14e24d10e5a52d5f80429053bbe3a5d124311a2868fceb0a01a2e859c44539"}, + "phoenix_ecto": {:hex, :phoenix_ecto, "4.7.0", "75c4b9dfb3efdc42aec2bd5f8bccd978aca0651dbcbc7a3f362ea5d9d43153c6", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "1d75011e4254cb4ddf823e81823a9629559a1be93b4321a6a5f11a5306fbf4cc"}, + "phoenix_html": {:hex, :phoenix_html, "3.3.4", "42a09fc443bbc1da37e372a5c8e6755d046f22b9b11343bf885067357da21cb3", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0249d3abec3714aff3415e7ee3d9786cb325be3151e6c4b3021502c585bf53fb"}, + "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.9.1", "d4786b24bbe1eacc431049dbbb8d377f5359fce57b9d7cdd773bba4ac0af2ef6", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "de25e1a28cfb64413d8bdaf3ba5b64da1a19e0ed44a02320119523cc45da051d"}, + "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "1.2.11", "1c83fdfd007e8d554076baee00ee6f55bb9c87ad9439f33ee520e47ae4a983bb", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c4087267cbd4dc4ed7ac36512a97830af8e9c857ca7cb22557f8640fc5f9d306"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.3.0", "03916bfbc31a5121945b3cfffe5aec647a5c97fe1dc172a319b94428562359c9", [:mix], [], "hexpm", "eec7be6e9cf02e2551d389b558402d6c637cd3973796326e7ba4bb03c6b2e91d"}, + "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, + "phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"}, + "piazza_core": {:git, "https://github.com/michaeljguarino/piazza_core", "2a91145d0d567f1aab40d52843d77dfb491c424a", []}, + "plug": {:hex, :plug, "1.20.3", "56c480c633ec2ce10140e236e15233bf576e1d323887d7c96711bd02ab5160db", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "be266aee1b8536ef6409d58cf39a3121319f0ec47cfa1b24024485aa0e76ad76"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.9.0", "87e21e0d9054ced99c36d128f49e3ea2cd8b745fffb97de50bff99706087af4f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2002bafba4f3a45b55a58e68d70211b153a7ed18d37edb1ceb6e96e7a92c422e"}, + "plug_crypto": {:hex, :plug_crypto, "2.2.0", "144014737daaf485407f5ed77daeaad74d651b216a28c87543f8cc7043f8efc8", [:mix], [], "hexpm", "83a95744ab1c75876542b6fab135fcc176280e0f301a111c1f757fddcec95d2c"}, + "poison": {:hex, :poison, "6.0.0", "9bbe86722355e36ffb62c51a552719534257ba53f3271dacd20fbbd6621a583a", [:mix], [{:decimal, "~> 2.1", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "bb9064632b94775a3964642d6a78281c07b7be1319e0016e1643790704e739a2"}, "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, "porcelain": {:hex, :porcelain, "2.0.3", "2d77b17d1f21fed875b8c5ecba72a01533db2013bd2e5e62c6d286c029150fdc", [:mix], [], "hexpm", "dc996ab8fadbc09912c787c7ab8673065e50ea1a6245177b0c24569013d23620"}, - "postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"}, - "posthog": {:hex, :posthog, "0.1.0", "0abe2af719c0c30fe6a24569a8947a19f0edfa63f6fed61685a219a8d5655786", [:mix], [{:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "ee0426999bd35edf3dfa84141bbd3de17ae07e04d62d269fd5ee581925f1c222"}, - "prometheus": {:hex, :prometheus, "4.6.0", "20510f381db1ccab818b4cf2fac5fa6ab5cc91bc364a154399901c001465f46f", [:mix, :rebar3], [], "hexpm", "4905fd2992f8038eccd7aa0cd22f40637ed618c0bed1f75c05aacec15b7545de"}, - "prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm", "9fd13404a48437e044b288b41f76e64acd9735fb8b0e3809f494811dfa66d0fb"}, + "postgrex": {:hex, :postgrex, "0.22.4", "d271f595dfd25230b6398354e19d17bb5e2d20130fd2d9bdca7e15f125d43552", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "4aae45a2d60e35b04eea2602440be152fae332901f1fc7a60fc7cb7f0f9a9c5a"}, + "prometheus": {:hex, :prometheus, "4.13.0", "4b61c3a98bb5c1d7a12109e34a951bf44be667c104e4df8fb1ca77605e918147", [:rebar3], [{:quantile_estimator, "1.0.2", [hex: :quantile_estimator, repo: "hexpm", optional: false]}], "hexpm", "e5d9e0385ec2f650dcabb8636257ed8b3b4b211188047bd1a34d2b3f92f6420a"}, + "prometheus_ex": {:hex, :prometheus_ex, "3.1.0", "98bdb1e9aea5001bc5f58752259d832447c06dd335cb246e89b497e2c4ec7de6", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm", "bc584d33aabae94ce75d477eb66c7178755b45a09afb7addb253d90eb66021de"}, "prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm", "0273a6483ccb936d79ca19b0ab629aef0dba958697c94782bb728b920dfc6a79"}, - "protobuf": {:hex, :protobuf, "0.5.4", "2e1b8eec211aff034ad8a14e3674220b0158bfb9a3c7128ac9d2a1ed1b3724d3", [:mix], [], "hexpm", "994348a4592408bc99c132603b0fdb686a2b5df0321a8eb1a582ec2bd3495886"}, - "quantum": {:hex, :quantum, "2.3.4", "72a0e8855e2adc101459eac8454787cb74ab4169de6ca50f670e72142d4960e9", [:mix], [{:calendar, "~> 0.17", [hex: :calendar, repo: "hexpm", optional: true]}, {:crontab, "~> 1.1", [hex: :crontab, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.12", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:swarm, "~> 3.3", [hex: :swarm, repo: "hexpm", optional: false]}, {:timex, "~> 3.1", [hex: :timex, repo: "hexpm", optional: true]}], "hexpm"}, - "rabbit_common": {:hex, :rabbit_common, "3.12.14", "466123ee7346a3cdac078c0c302bcd36da4523e8acd678c1b992f7b4df1f7914", [:make, :rebar3], [{:credentials_obfuscation, "3.4.0", [hex: :credentials_obfuscation, repo: "hexpm", optional: false]}, {:recon, "2.5.3", [hex: :recon, repo: "hexpm", optional: false]}, {:thoas, "1.0.0", [hex: :thoas, repo: "hexpm", optional: false]}], "hexpm", "70c31a51f7401cc0204ddef2745d98680c2e0df67e3b0c9e198916881fde3293"}, + "protobuf": {:hex, :protobuf, "0.17.0", "39e24e43c9648e148feba16ed51100b5b2028ea900b55460377b0476f6e10613", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "ca6c91f6f63e2c147b47f03eefd10b80538aa6fc55ff4b12b795efb786b0152f"}, + "quantile_estimator": {:hex, :quantile_estimator, "1.0.2", "ecd281d40110fdd9ba62685531e4435e0839a52fd1058da5564f1763e4642ef7", [:rebar3], [], "hexpm", "db404793d6384995a1ac6dd973e2cee5be9fcc128765bdba53d87c564e296b64"}, + "quic": {:hex, :quic, "1.8.1", "51415525c490d80f97073e39e17d289ebacda5468154cfb661ac04db5b1a5e95", [:rebar3], [], "hexpm", "884a7d30cb048d8d1acb97eb2b905d30d4c29b8928c0db3ab3060de7cdc97688"}, + "rabbit_common": {:hex, :rabbit_common, "4.3.4", "2911b2b563aa6a477c55bb1f4cbf83fcb7accc5412722b3bb5f3ae4e5e33f877", [:make, :rebar3], [{:credentials_obfuscation, "3.5.0", [hex: :credentials_obfuscation, repo: "hexpm", optional: false]}, {:ranch, "2.2.0", [hex: :ranch, repo: "hexpm", optional: false]}, {:recon, "2.5.6", [hex: :recon, repo: "hexpm", optional: false]}, {:thoas, "1.2.1", [hex: :thoas, repo: "hexpm", optional: false]}], "hexpm", "e5fefde66701a0d6ce7cc464133c6975b0b2661b47561d7c622cce6b7420413c"}, "ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"}, "recaptcha": {:git, "https://github.com/samueljseay/recaptcha", "71cd746be987f6834c1a933f5d2f934350e55060", []}, - "recon": {:hex, :recon, "2.5.3", "739107b9050ea683c30e96de050bc59248fd27ec147696f79a8797ff9fa17153", [:mix, :rebar3], [], "hexpm", "6c6683f46fd4a1dfd98404b9f78dcabc7fcd8826613a89dcb984727a8c3099d7"}, - "remote_ip": {:hex, :remote_ip, "0.2.1", "cd27cd8ea54ecaaf3532776ff4c5e353b3804e710302e88c01eadeaaf42e7e24", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:inet_cidr, "~> 1.0", [hex: :inet_cidr, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2e7ab1a461cc3cd5719f37e116a08f45c8b8493923063631b164315d6b7ee8e0"}, - "req": {:hex, :req, "0.4.14", "103de133a076a31044e5458e0f850d5681eef23dfabf3ea34af63212e3b902e2", [:mix], [{:aws_signature, "~> 0.3.2", [hex: :aws_signature, repo: "hexpm", optional: true]}, {:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:nimble_ownership, "~> 0.2.0 or ~> 0.3.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "2ddd3d33f9ab714ced8d3c15fd03db40c14dbf129003c4a3eb80fac2cc0b1b08"}, - "restlax": {:hex, :restlax, "0.1.0", "753e00aff37802f703e6b709d3f85b7816e7740cc5f833c446d677a42ecf4824", [:mix], [{:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gun, "~> 1.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}, {:tesla, "~> 1.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "f1db23c10f7ff06ecd1f7e95380d49393a11194baacf58a1714c1e40a9d61123"}, - "reverse_proxy_plug": {:hex, :reverse_proxy_plug, "2.1.1", "c5494a56c32e47e2f7ca677df4633846aec31a18ba1695928fef51e2d413cb27", [:mix], [{:cowboy, "~> 2.4", [hex: :cowboy, repo: "hexpm", optional: false]}, {:httpoison, "~> 1.2", [hex: :httpoison, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: false]}, {:tesla, "~> 1.4", [hex: :tesla, repo: "hexpm", optional: true]}], "hexpm", "e8f65bdfd35ebffaea2006eb8422c9126cbd899d0bf1552aedf80730c30204b6"}, - "sentry": {:hex, :sentry, "8.0.6", "c8de1bf0523bc120ec37d596c55260901029ecb0994e7075b0973328779ceef7", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "051a2d0472162f3137787c7c9d6e6e4ef239de9329c8c45b1f1bf1e9379e1883"}, - "shards": {:hex, :shards, "1.0.1", "1bdbbf047db27f3c3eb800a829d4a47062c84d5543cbfebcfc4c14d038bf9220", [:make, :rebar3], [], "hexpm", "2c57788afbf053c4024366772892beee89b8b72e884e764fb0a075dfa7442041"}, - "slipstream": {:hex, :slipstream, "1.1.1", "7e56f62f1a9ee81351e3c36f57b9b187e00dc2f470e70ba46ea7ad16e80b061f", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 0.2 or ~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c20e420cde1654329d38ec3aa1c0e4debbd4c91ca421491e7984ad4644e638a6"}, - "sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"}, + "recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"}, + "remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"}, + "req": {:hex, :req, "0.7.4", "23e9ffec17de032a46a4b15ed65c09793893bf4a7c680f4bbf6227fce6bdf74d", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:finch, "~> 0.21", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "4b192d63253e8dcc6221ef992ea9ebef7d3555166e8423aa5b553e86bc3c69a2"}, + "restlax": {:hex, :restlax, "1.0.1", "9e1be31dfc93f7f753cff9ea6109c831fa8c7503642959b508023c3bc2b2a8d6", [:mix], [{:req, ">= 0.4.0 and < 0.4.10", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "43e3e8a5df716d746e7b521c0cb7612bc7df2690df2f42dab586a08b83d8a1d9"}, + "reverse_proxy_plug": {:hex, :reverse_proxy_plug, "3.0.4", "d51709a677081bc24588e388f5103c97becadf1cb0f1830972e4342a9293b126", [:mix], [{:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.4 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: false]}, {:req, "~> 0.3.0 or ~> 0.4.0 or ~> 0.5.0", [hex: :req, repo: "hexpm", optional: true]}, {:tesla, "~> 1.4", [hex: :tesla, repo: "hexpm", optional: true]}], "hexpm", "cb9ee61536b19e210cb00f967339fb766ea5565116acab47004993dfb74bcfc1"}, + "sentry": {:hex, :sentry, "10.2.1", "0450e16d779dc510bef1ff56cdfefb292a56c24c8490c1c205750257a72d255d", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "49f91c7b80f117884ffa12a755eb3ab9037d9a7a16014c776604ae6fe469cbf5"}, + "shards": {:hex, :shards, "1.1.1", "8b42323457d185b26b15d05187784ce6c5d1e181b35c46fca36c45f661defe02", [:make, :rebar3], [], "hexpm", "169a045dae6668cda15fbf86d31bf433d0dbbaec42c8c23ca4f8f2d405ea8eda"}, + "slipstream": {:hex, :slipstream, "1.2.2", "6b07124ac5f62a50327aa38c84edd0284920ac8aba548e04738827838f233ed0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 0.2 or ~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ccb873ddb21aadb37c5c7745014febe6da0aa2cef0c4e73e7d08ce11d18aacd0"}, + "sobelow": {:hex, :sobelow, "0.15.0", "b067d7f8522a9d758fa89cb2bfcbab7ad72c45a0993cb958c989c6fd956fdd56", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "24a800e2d7fa8c3bd21561b6ad8ad4745ed726a09fd606598981d9048708da98"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stripity_stripe": {:hex, :stripity_stripe, "3.2.0", "07c27f5f2ac87006945b5c997b99d1210e009e380ea78d339d025b11c9c745f5", [:mix], [{:hackney, "~> 1.18", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}, {:uri_query, "~> 0.2.0", [hex: :uri_query, repo: "hexpm", optional: false]}], "hexpm", "f797936a9e9538370bae7dc73d73eafd7e44ecdc95b71c88492c43f6df094cb0"}, "swarm": {:hex, :swarm, "3.4.0", "64f8b30055d74640d2186c66354b33b999438692a91be275bb89cdc7e401f448", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:libring, "~> 1.0", [hex: :libring, repo: "hexpm", optional: false]}], "hexpm", "94884f84783fc1ba027aba8fe8a7dae4aad78c98e9f9c76667ec3471585c08c6"}, - "sweet_xml": {:hex, :sweet_xml, "0.7.3", "debb256781c75ff6a8c5cbf7981146312b66f044a2898f453709a53e5031b45b", [:mix], [], "hexpm", "e110c867a1b3fe74bfc7dd9893aa851f0eed5518d0d7cad76d7baafd30e4f5ba"}, - "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, - "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, - "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, - "tesla": {:hex, :tesla, "1.11.1", "902ec0cd9fb06ba534be765f0eb78acd9d0ef70118230dc3a73fdc9afc91d036", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "c02d7dd149633c55c40adfaad6c3ce2615cfc89258b67a7f428c14bb835c398c"}, - "thoas": {:hex, :thoas, "1.0.0", "567c03902920827a18a89f05b79a37b5bf93553154b883e0131801600cf02ce0", [:rebar3], [], "hexpm", "fc763185b932ecb32a554fb735ee03c3b6b1b31366077a2427d2a97f3bd26735"}, + "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, + "telemetry": {:hex, :telemetry, "1.4.2", "a0cb522801dffb1c49fe6e30561badffc7b6d0e180db1300df759faa22062855", [:rebar3], [], "hexpm", "928f6495066506077862c0d1646609eed891a4326bee3126ba54b60af61febb1"}, + "telemetry_metrics": {:hex, :telemetry_metrics, "1.2.0", "7632c19c01d88d8aaca5da1a0e8912f5af39b79e7c08a2c253aeb3c14c2c957e", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "71dde12fc29b58b9c77ec17ec319109e5ca848d010fc1965ed4463bba1837c07"}, + "telemetry_poller": {:hex, :telemetry_poller, "1.3.0", "d5c46420126b5ac2d72bc6580fb4f537d35e851cc0f8dbd571acf6d6e10f5ec7", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "51f18bed7128544a50f75897db9974436ea9bfba560420b646af27a9a9b35211"}, + "tesla": {:hex, :tesla, "1.21.3", "377e74491164595d89ad4e24b738a448c743f830a491a6c638b9e46995bca23d", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.21 or >= 4.0.2 and < 5.0.0-0", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.5.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:mox, "~> 1.0", [hex: :mox, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:opentelemetry_semantic_conventions, "~> 1.27", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "558aca0d763aaed4cba418b6078c290ffd55ddd1b03e58d6163cb7438851855e"}, + "thoas": {:hex, :thoas, "1.2.1", "19a25f31177a17e74004d4840f66d791d4298c5738790fa2cc73731eb911f195", [:rebar3], [], "hexpm", "e38697edffd6e91bd12cea41b155115282630075c2a727e7a6b2947f5408b86a"}, "thousand_island": {:hex, :thousand_island, "1.5.0", "f50a213cac97262b6d5ebb85745aa2c00fec1413191e6e66834788d45425cecb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "708923d40523e43cf99041ab37a0d4b0ec426ac6438fa3716ab23d919eaeb412"}, - "timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "f354efb2400dd7a80fd9eb6c8419068c4f632da4ac47f3d8822d6e33f08bc852"}, - "tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.1", "a48703a25c170eedadca83b11e88985af08d35f37c6f664d6dcfb106a97782fc", [:rebar3], [], "hexpm", "b3a917854ce3ae233619744ad1e0102e05673136776fb2fa76234f3e03b23642"}, + "timex": {:hex, :timex, "3.7.13", "0688ce11950f5b65e154e42b47bf67b15d3bc0e0c3def62199991b8a8079a1e2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.26", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "09588e0522669328e973b8b4fd8741246321b3f0d32735b589f78b136e6d4c54"}, + "tzdata": {:hex, :tzdata, "1.1.4", "989e0855df5ee8c40eb929ad971bedd7a51e2c223f051fd95cc2d2cf56a60c19", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "ab48888699de8ff4a255522fd858abe81bac2e64690a375e6cb590112cf4a24e"}, "uri_query": {:hex, :uri_query, "0.2.0", "0f5e0f7ea6d9e6a7fb4929a81df9ecd756e3c71bdee5c9bc14e57d90069a82f7", [:mix], [], "hexpm", "e99f50a6af7c6643dff948db152a6a420bfe446aaec7f0924cfcdb710c175e63"}, + "waffle": {:hex, :waffle, "1.1.10", "0f847ed6f95349af258a90f0f70ffea02b3d3729c4eb78f6fae7bf776e91779e", [:mix], [{:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:ex_aws_s3, "~> 2.1", [hex: :ex_aws_s3, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "859ba6377b78f0a51bc9596227b194f26241efbbd408bd217450c22b0f359cc4"}, + "waffle_ecto": {:hex, :waffle_ecto, "0.0.13", "b26df69d20db5ed12610e2ebfdb09c73e419c6baa4f349bd2bfa643b236770b8", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:waffle, "~> 1.0 or ~> 2.0-rc", [hex: :waffle, repo: "hexpm", optional: false]}], "hexpm", "5b282325079fd056c177dee11123fe1241eef1a683f098805af8e02e20c31411"}, + "waffle_gcs": {:hex, :waffle_gcs, "0.2.0", "dea6bb5da8da961a2a7a000178b0912cd342c89891c73ec745e19b1841b47fb2", [:mix], [{:google_api_storage, "~> 0.14", [hex: :google_api_storage, repo: "hexpm", optional: false]}, {:goth, "~> 1.1", [hex: :goth, repo: "hexpm", optional: false]}, {:waffle, "~> 1.1", [hex: :waffle, repo: "hexpm", optional: false]}], "hexpm", "5250750957d21cbaa762b88e71ca82014e7d803f3c2759a75ec2bb93fa3a384d"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, - "websockex": {:hex, :websockex, "0.4.3", "92b7905769c79c6480c02daacaca2ddd49de936d912976a4d3c923723b647bf0", [:mix], [], "hexpm", "95f2e7072b85a3a4cc385602d42115b73ce0b74a9121d0d6dbbf557645ac53e4"}, - "workos": {:hex, :workos, "0.1.2", "d4b80b94091b8568cff4aef4ecbcd34b43b4b3b148fe35c21ced88b01fb14297", [:mix], [{:hackney, "~> 1.16.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.4", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "1c119e20729c71dcf86f7559c4ae1af13105bdaaddbba3e1dae8149b378f66a9"}, - "x509": {:hex, :x509, "0.8.5", "22b2c5dfc87b05d46595d3764f41a23fcb7360f891e0464f1a2ec118177cd4e4", [:mix], [], "hexpm", "c63eb89e8bbe8a5e21b6404ad1082faff670e38b74960297f90d023177949e07"}, - "yamerl": {:hex, :yamerl, "0.7.0", "e51dba652dce74c20a88294130b48051ebbbb0be7d76f22de064f0f3ccf0aaf5", [:rebar3], [], "hexpm", "cb5a4481e2e2ad36db83bd9962153e1a9208e2b2484185e33fc2caac6a50b108"}, - "yaml_elixir": {:hex, :yaml_elixir, "2.4.0", "2f444abc3c994c902851fde56b6a9cb82895c291c05a0490a289035c2e62ae71", [:mix], [{:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "4e25a6d5c873e393689c6f1062c5ec90f6cd1be2527b073178ae37eae4c78bee"}, + "websock_adapter": {:hex, :websock_adapter, "0.6.0", "73db5ab8aaefd1a876a97ce3e6afc96562625de69ef17a4e04426e034849d0b8", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "50021a85bce8f203b086705d9e0c5415e2c7eb05d319111b0428fe71f9934617"}, + "websockex": {:hex, :websockex, "0.5.1", "9de28d37bbe34f371eb46e29b79c94c94fff79f93c960d842fbf447253558eb4", [:mix], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8ef39576ed56bc3804c9cd8626f8b5d6b5721848d2726c0ccd4f05385a3c9f14"}, + "webtransport": {:hex, :webtransport, "0.4.5", "0e387202bbe707389fe81373ef8c56faa9d5aa321bb4800fa4765ee7c1399785", [:rebar3], [{:h2, "~> 0.12", [hex: :h2, repo: "hexpm", optional: false]}, {:quic, "~> 1.8.0", [hex: :quic, repo: "hexpm", optional: false]}], "hexpm", "bcb512239e48e551d5bd5c667312a9a7de4f29b89d84b1d33c5af44e1f3f730d"}, + "workos": {:hex, :workos, "0.1.3", "232f9a51262ceeb0a50af9c509b627fa2971489581d521155b11d4d3f214ad90", [:mix], [{:hackney, "~> 1.18.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.4", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "386aeb0f48509888daf69dea5ae76b9e736a46edec70e45e08c4db4cdd04d1d9"}, + "x509": {:hex, :x509, "0.9.2", "a75aa605348abd905990f3d2dc1b155fcde4e030fa2f90c4a91534405dce0f6e", [:mix], [], "hexpm", "4c5ede75697e565d4b0f5be04c3b71bb1fd3a090ea243af4bd7dae144e48cfc7"}, + "yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"}, + "yaml_elixir": {:hex, :yaml_elixir, "2.12.2", "9dd1330fb4cd9a36a7b0f502e5b12486eff632792ee4a5f0eba52a4d4ec32c9c", [:mix], [{:yamerl, "~> 0.10", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "e7c1b10122f973e6558462d51c39026ba0e14afbc6745318e990ea82cfe9e159"}, } diff --git a/plural/helm/plural/templates/migration.yaml b/plural/helm/plural/templates/migration.yaml index 1d78aad26..79ed4e589 100644 --- a/plural/helm/plural/templates/migration.yaml +++ b/plural/helm/plural/templates/migration.yaml @@ -14,7 +14,7 @@ spec: containers: - name: migrator image: "{{ .Values.global.registry }}/{{ .Values.image.repository }}:{{ include "plural.imageTag" . }}" - command: ["/opt/app/bin/plural", "migrate"] + command: ["/opt/app/bin/migrate"] imagePullPolicy: {{ .Values.image.pullPolicy }} envFrom: - secretRef: diff --git a/plural/helm/plural/templates/proxies.yaml b/plural/helm/plural/templates/proxies.yaml index 7b7fe1742..c0d10a643 100644 --- a/plural/helm/plural/templates/proxies.yaml +++ b/plural/helm/plural/templates/proxies.yaml @@ -58,7 +58,7 @@ spec: target: deployment/plural-api shConfig: command: /opt/app/bin/plural - args: [remote_console] + args: [remote] --- apiVersion: platform.plural.sh/v1alpha1 kind: Proxy @@ -71,7 +71,7 @@ spec: target: deployment/plural-rtc shConfig: command: /opt/app/bin/rtc - args: [remote_console] + args: [remote] --- apiVersion: platform.plural.sh/v1alpha1 kind: Proxy @@ -84,4 +84,4 @@ spec: target: deployment/plural-worker shConfig: command: /opt/app/bin/worker - args: [remote_console] \ No newline at end of file + args: [remote] \ No newline at end of file diff --git a/rel/commands/drop.sh b/rel/commands/drop.sh deleted file mode 100644 index b24f6a41e..000000000 --- a/rel/commands/drop.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -release_ctl eval --mfa "Piazza.Ecto.ReleaseTasks.drop/1" --argv -- "$@" diff --git a/rel/commands/migrate.sh b/rel/commands/migrate.sh deleted file mode 100644 index b57d2e38a..000000000 --- a/rel/commands/migrate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -release_ctl eval --mfa "Piazza.Ecto.ReleaseTasks.seed/1" --argv -- "$@" diff --git a/rel/config.exs b/rel/config.exs deleted file mode 100644 index c0d462caf..000000000 --- a/rel/config.exs +++ /dev/null @@ -1,77 +0,0 @@ -~w(rel plugins *.exs) -|> Path.join() -|> Path.wildcard() -|> Enum.map(&Code.eval_file(&1)) - -use Distillery.Releases.Config, - # This sets the default release built by `mix distillery.release` - default_release: :default, - # This sets the default environment used by `mix distillery.release` - default_environment: Mix.env() - -environment :dev do - set dev_mode: true - set include_erts: false - set cookie: :"[0u(BUb%Eh955Mg5V>:Mgxqa8NY`de)3ikLXo:iM]pU6HUy9NC}C4T(5A=|Xau8/" -end - -environment :prod do - set include_erts: true - set include_src: false - set cookie: :"apMPW^f~jR;8CVeiv`d4(6y]Rv`v_Z;ghL:~3&j!1QM)YRG5_TTpz2q2nGu)9>}l" - set vm_args: "rel/vm.args" - set config_providers: [ - {Distillery.Releases.Config.Providers.Elixir, ["${RELEASE_ROOT_DIR}/etc/config.exs"]}, - {Distillery.Releases.Config.Providers.Elixir, ["${RELEASE_ROOT_DIR}/etc/app.exs"]} - ] - set overlays: [ - {:copy, "rel/config/config.exs", "etc/config.exs"}, - {:copy, "rel/config/<%= release_name %>.exs", "etc/app.exs"} - ] -end - -release :plural do - set version: current_version(:api) - set applications: [ - :runtime_tools, - api: :permanent, - core: :permanent, - email: :permanent, - graphql: :load - ] - - set commands: [ - migrate: "rel/commands/migrate.sh", - drop: "rel/commands/drop.sh" - ] -end - -release :rtc do - set version: current_version(:rtc) - set applications: [ - :runtime_tools, - rtc: :permanent, - core: :permanent, - graphql: :load - ] -end - -release :worker do - set version: current_version(:worker) - set applications: [ - :runtime_tools, - worker: :permanent, - core: :permanent, - email: :permanent - ] -end - -release :cron do - set version: current_version(:cron) - set applications: [ - :runtime_tools, - cron: :permanent, - core: :permanent, - email: :permanent - ] -end diff --git a/rel/config/cron.exs b/rel/config/cron.exs deleted file mode 100644 index 60eabf150..000000000 --- a/rel/config/cron.exs +++ /dev/null @@ -1,6 +0,0 @@ -import Config -import System, only: [get_env: 1] - -config :core, start_broker: true - -config :stripity_stripe, api_key: get_env("STRIPE_SECRET") diff --git a/rel/config/plural.exs b/rel/config/plural.exs deleted file mode 100644 index 48ef2ba85..000000000 --- a/rel/config/plural.exs +++ /dev/null @@ -1,46 +0,0 @@ -import Config -import System, only: [get_env: 1] - -config :core, start_broker: true -config :rtc, start_broker: false - -config :core, Core.Guardian, - issuer: "plural", - secret_key: get_env("JWT_SECRET") - -config :stripity_stripe, api_key: get_env("STRIPE_SECRET") - -config :api, ApiWeb.Endpoint, - secret_key_base: get_env("SECRET_KEY_BASE") - -if get_env("CLOUD_SHELL_IMG") do - config :core, :cloud_shell_img, get_env("CLOUD_SHELL_IMG") -end - -if get_env("CLOUD_SHELL_SYSBOX_IMG") do - config :core, :cloud_shell_sysbox_img, get_env("CLOUD_SHELL_SYSBOX_IMG") -end - -if get_env("CLOUD_SHELL_DIND_IMG") do - config :core, :dind_img, get_env("CLOUD_SHELL_DIND_IMG") -end - -if get_env("PRL_GITHUB_APP_PEM") do - config :core, :github_app_pem, get_env("PRL_GITHUB_APP_PEM") -end - -if !get_env("PLRL_IGNORE_CLUSTER") do -config :libcluster, - topologies: [ - api: [ - strategy: Cluster.Strategy.Kubernetes, - config: [ - mode: :ip, - kubernetes_node_basename: "plural", - kubernetes_selector: "app=plural-api", - kubernetes_namespace: get_env("NAMESPACE"), - polling_interval: 10_000 - ] - ] - ] -end diff --git a/rel/config/rtc.exs b/rel/config/rtc.exs deleted file mode 100644 index e3f643856..000000000 --- a/rel/config/rtc.exs +++ /dev/null @@ -1,26 +0,0 @@ -import Config -import System, only: [get_env: 1] - -config :rtc, RtcWeb.Endpoint, - url: [host: get_env("HOST"), port: 80], - check_origin: ["//#{get_env("HOST")}", "//plural-rtc"], - secret_key_base: get_env("SECRET_KEY_BASE"), - server: true - -config :core, broker: Rtc.Conduit.Broker -config :core, start_broker: false -config :rtc, start_broker: true - -config :libcluster, - topologies: [ - rtc: [ - strategy: Cluster.Strategy.Kubernetes, - config: [ - mode: :ip, - kubernetes_node_basename: "rtc", - kubernetes_selector: "app=plural-rtc", - kubernetes_namespace: get_env("NAMESPACE"), - polling_interval: 10_000 - ] - ] - ] diff --git a/rel/config/worker.exs b/rel/config/worker.exs deleted file mode 100644 index e72d6e391..000000000 --- a/rel/config/worker.exs +++ /dev/null @@ -1,11 +0,0 @@ -import Config -import System, only: [get_env: 1] - -config :worker, - registry: get_env("DKR_DNS") - -config :core, start_broker: false -config :worker, start_broker: true -config :core, broker: Worker.Conduit.Broker - -config :stripity_stripe, api_key: get_env("STRIPE_SECRET") diff --git a/rel/env.sh.eex b/rel/env.sh.eex new file mode 100644 index 000000000..2c6bf6d52 --- /dev/null +++ b/rel/env.sh.eex @@ -0,0 +1,5 @@ +#!/bin/sh + +export RELEASE_DISTRIBUTION=name +export RELEASE_NODE=<%= @release.name %>@${POD_IP} +export RELEASE_COOKIE=${ERLANG_COOKIE} diff --git a/rel/overlays/bin/drop b/rel/overlays/bin/drop new file mode 100755 index 000000000..58edaec98 --- /dev/null +++ b/rel/overlays/bin/drop @@ -0,0 +1,19 @@ +#!/bin/sh +set -eu + +cd -P -- "$(dirname -- "$0")" + +rel="" +for candidate in ${APP_NAME:-} plural rtc worker cron; do + if [ -n "$candidate" ] && [ -x "./$candidate" ]; then + rel="./$candidate" + break + fi +done + +if [ -z "$rel" ]; then + echo "could not find Mix release binary in $(pwd)" >&2 + exit 1 +fi + +exec "$rel" eval "Piazza.Ecto.ReleaseTasks.drop([])" diff --git a/rel/overlays/bin/migrate b/rel/overlays/bin/migrate new file mode 100755 index 000000000..7c0bd08da --- /dev/null +++ b/rel/overlays/bin/migrate @@ -0,0 +1,19 @@ +#!/bin/sh +set -eu + +cd -P -- "$(dirname -- "$0")" + +rel="" +for candidate in ${APP_NAME:-} plural rtc worker cron; do + if [ -n "$candidate" ] && [ -x "./$candidate" ]; then + rel="./$candidate" + break + fi +done + +if [ -z "$rel" ]; then + echo "could not find Mix release binary in $(pwd)" >&2 + exit 1 +fi + +exec "$rel" eval "Piazza.Ecto.ReleaseTasks.seed([])" diff --git a/rel/config/config.exs b/rel/runtime/cron.exs similarity index 92% rename from rel/config/config.exs rename to rel/runtime/cron.exs index ce396b4ed..00a6cbf99 100644 --- a/rel/config/config.exs +++ b/rel/runtime/cron.exs @@ -15,20 +15,18 @@ config :core, hostname: host config :email, host: "https://#{host}" config :core, host: "https://#{host}" -config :arc, - storage: Arc.Storage.GCS, +config :waffle, + storage: Waffle.Storage.Google.CloudStorage, bucket: get_env("BUCKET") config :core, Core.Guardian, issuer: "plural", secret_key: get_env("JWT_SECRET") - - if get_env("POSTGRES_URL") do config :core, Core.Repo, url: get_env("POSTGRES_URL"), - ssl: String.to_existing_atom(get_env("DBSSL") || "true"), + ssl: if(get_env("DBSSL") == "false", do: false, else: [verify: :verify_none]), pool_size: 5 else config :core, Core.Repo, @@ -36,7 +34,7 @@ else username: "plural", password: get_env("POSTGRES_PASSWORD"), hostname: get_env("DBHOST") || "plural-postgresql", - ssl: String.to_existing_atom(get_env("DBSSL") || "false"), + ssl: if(get_env("DBSSL") == "true", do: [verify: :verify_none], else: false), pool_size: 5 end @@ -105,7 +103,6 @@ config :core, initial_user: get_env("ADMIN_EMAIL") || "admin@plural.sh", stage: get_env("PLURAL_STAGE") || "prod" - if get_env("VAULT_HOST") do config :core, vault: get_env("VAULT_HOST") end @@ -122,7 +119,6 @@ config :workos, client_id: get_env("WORKOS_CLIENT_ID"), api_key: get_env("WORKOS_API_KEY") - provider = case get_env("PROVIDER") || "google" do "google" -> :gcp "gcp" -> :gcp @@ -136,7 +132,7 @@ end if provider != :gcp do config :goth, disabled: true - config :arc, storage: Arc.Storage.S3 + config :waffle, storage: Waffle.Storage.S3 end if org_id = get_env("GCP_ORG_ID") do @@ -157,5 +153,8 @@ config :core, config :openai, token: get_env("OPENAI_BEARER_TOKEN") - config :tzdata, :autoupdate, :disabled + +config :core, start_broker: true + +config :stripity_stripe, api_key: get_env("STRIPE_SECRET") diff --git a/rel/runtime/plural.exs b/rel/runtime/plural.exs new file mode 100644 index 000000000..5792ad95a --- /dev/null +++ b/rel/runtime/plural.exs @@ -0,0 +1,200 @@ +import Config +import System, only: [get_env: 1] + +host = get_env("HOST") + +config :api, ApiWeb.Endpoint, + url: [host: host, port: 80], + check_origin: ["//#{host}", "//plural-api"] + +config :rtc, RtcWeb.Endpoint, + url: [host: host, port: 80], + check_origin: ["//#{host}", "//plural-rtc"] + +config :core, hostname: host +config :email, host: "https://#{host}" +config :core, host: "https://#{host}" + +config :waffle, + storage: Waffle.Storage.Google.CloudStorage, + bucket: get_env("BUCKET") + +config :core, Core.Guardian, + issuer: "plural", + secret_key: get_env("JWT_SECRET") + +if get_env("POSTGRES_URL") do + config :core, Core.Repo, + url: get_env("POSTGRES_URL"), + ssl: if(get_env("DBSSL") == "false", do: false, else: [verify: :verify_none]), + pool_size: 5 +else + config :core, Core.Repo, + database: "plural", + username: "plural", + password: get_env("POSTGRES_PASSWORD"), + hostname: get_env("DBHOST") || "plural-postgresql", + ssl: if(get_env("DBSSL") == "true", do: [verify: :verify_none], else: false), + pool_size: 5 +end + +config :cloudflare, + auth_token: get_env("CLOUDFLARE_AUTH_TOKEN") + +config :core, Core.Influx, + database: "plural", + host: "influxdb.influx", + auth: [method: :basic, username: "admin", password: get_env("INFLUX_PAASSWORD")], + port: 8086 + +config :core, :jwt, + pk: get_env("JWT_PRIVATE_KEY"), + cert: get_env("JWT_CERT"), + iss: get_env("JWT_ISS"), + aud: get_env("JWT_AUD") + +config :core, Core.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :rtc, Rtc.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :worker, Worker.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :piazza_core, aes_key: get_env("AES_KEY") + +config :core, Core.Clients.Zoom, + client_id: get_env("ZOOM_CLIENT_ID"), + client_secret: get_env("ZOOM_CLIENT_SECRET") + +config :core, + chartmuseum: "http://chartmuseum:8080", + plural_cmd: "/usr/local/bin/plural", + stripe_connect_id: get_env("STRIPE_CONNECT_ID"), + stripe_publishable_key: get_env("STRIPE_PUBLISHABLE_KEY"), + hydra_public_url: get_env("HYDRA_URL") || "https://oidc.plural.sh", + git_commit: get_env("GIT_COMMIT"), + cloudflare_zone: get_env("CLOUDFLARE_ZONE"), + acme_key_id: get_env("ACME_KEY_ID"), + acme_secret: get_env("ACME_SECRET"), + zerossl_access_key: get_env("ZEROSSL_ACCESS_KEY"), + docker_metrics_table: ~s("permanent"."downsampled_docker_pulls"), + workos_webhook: get_env("WORKOS_WEBHOOK_SECRET"), + gcp_identity: get_env("GCP_USER_EMAIL") || "mjg@plural.sh", + openai_token: get_env("OPENAI_BEARER_TOKEN"), + enforce_pricing: get_env("ENFORCE_PRICING"), + stripe_webhook_secret: get_env("STRIPE_WEBHOOK_SECRET"), + github_demo_token: get_env("GITHUB_DEMO_TOKEN"), + console_token: get_env("CONSOLE_SA_TOKEN"), + dedicated_console_token: get_env("CONSOLE_DEDICATED_SA_TOKEN"), + dedicated_project: get_env("CONSOLE_DEDICATED_PROJECT"), + mgmt_cluster: get_env("MGMT_CLUSTER_ID"), + console_url: get_env("CONSOLE_URL"), + mgmt_repo: get_env("CONSOLE_MGMT_REPO"), + stack_id: get_env("CONSOLE_CLOUD_STACK_ID"), + cloud_domain: get_env("CONSOLE_CLOUD_DOMAIN") || "cloud.plural.sh", + base_stripe_product: get_env("STRIPE_PRO_PRODUCT"), + metered_stripe_product: get_env("STRIPE_PRO_CLUSTER_PRODUCT"), + cluster_meter_name: get_env("CLUSTER_METER_NAME") || "pro_clusters", + initial_user: get_env("ADMIN_EMAIL") || "admin@plural.sh", + stage: get_env("PLURAL_STAGE") || "prod" + +if get_env("VAULT_HOST") do + config :core, vault: get_env("VAULT_HOST") +end + +if get_env("SYSBOX_WHITELIST") do + config :core, :sysbox_emails, String.split(get_env("SYSBOX_WHITELIST"), ",") +end + +if get_env("INTERCOM_SALT") do + config :core, intercom_salt: get_env("INTERCOM_SALT") +end + +config :workos, + client_id: get_env("WORKOS_CLIENT_ID"), + api_key: get_env("WORKOS_API_KEY") + +provider = case get_env("PROVIDER") || "google" do + "google" -> :gcp + "gcp" -> :gcp + "aws" -> :aws + "azure" -> :azure + "equinix" -> :equinix + "kind" -> :kind + "generic" -> :generic + _ -> :custom +end + +if provider != :gcp do + config :goth, disabled: true + config :waffle, storage: Waffle.Storage.S3 +end + +if org_id = get_env("GCP_ORG_ID") do + config :core, + gcp_organization: org_id +end + +if get_env("GCP_CREDENTIALS") do + config :goth, + json: {:system, "GCP_CREDENTIALS"}, + project_id: get_env("GCP_PROJECT") || "pluralsh", + disabled: false +end + +config :core, + registry: get_env("DKR_DNS") + +config :openai, + token: get_env("OPENAI_BEARER_TOKEN") + +config :tzdata, :autoupdate, :disabled + +config :core, start_broker: true +config :rtc, start_broker: false + +config :core, Core.Guardian, + issuer: "plural", + secret_key: get_env("JWT_SECRET") + +config :stripity_stripe, api_key: get_env("STRIPE_SECRET") + +config :api, ApiWeb.Endpoint, + secret_key_base: get_env("SECRET_KEY_BASE") + +if get_env("CLOUD_SHELL_IMG") do + config :core, :cloud_shell_img, get_env("CLOUD_SHELL_IMG") +end + +if get_env("CLOUD_SHELL_SYSBOX_IMG") do + config :core, :cloud_shell_sysbox_img, get_env("CLOUD_SHELL_SYSBOX_IMG") +end + +if get_env("CLOUD_SHELL_DIND_IMG") do + config :core, :dind_img, get_env("CLOUD_SHELL_DIND_IMG") +end + +if get_env("PRL_GITHUB_APP_PEM") do + config :core, :github_app_pem, get_env("PRL_GITHUB_APP_PEM") +end + +if !get_env("PLRL_IGNORE_CLUSTER") do + config :libcluster, + topologies: [ + api: [ + strategy: Cluster.Strategy.Kubernetes, + config: [ + mode: :ip, + kubernetes_node_basename: "plural", + kubernetes_selector: "app=plural-api", + kubernetes_namespace: get_env("NAMESPACE"), + polling_interval: 10_000 + ] + ] + ] +end diff --git a/rel/runtime/rtc.exs b/rel/runtime/rtc.exs new file mode 100644 index 000000000..163c5a10e --- /dev/null +++ b/rel/runtime/rtc.exs @@ -0,0 +1,180 @@ +import Config +import System, only: [get_env: 1] + +host = get_env("HOST") + +config :api, ApiWeb.Endpoint, + url: [host: host, port: 80], + check_origin: ["//#{host}", "//plural-api"] + +config :rtc, RtcWeb.Endpoint, + url: [host: host, port: 80], + check_origin: ["//#{host}", "//plural-rtc"] + +config :core, hostname: host +config :email, host: "https://#{host}" +config :core, host: "https://#{host}" + +config :waffle, + storage: Waffle.Storage.Google.CloudStorage, + bucket: get_env("BUCKET") + +config :core, Core.Guardian, + issuer: "plural", + secret_key: get_env("JWT_SECRET") + +if get_env("POSTGRES_URL") do + config :core, Core.Repo, + url: get_env("POSTGRES_URL"), + ssl: if(get_env("DBSSL") == "false", do: false, else: [verify: :verify_none]), + pool_size: 5 +else + config :core, Core.Repo, + database: "plural", + username: "plural", + password: get_env("POSTGRES_PASSWORD"), + hostname: get_env("DBHOST") || "plural-postgresql", + ssl: if(get_env("DBSSL") == "true", do: [verify: :verify_none], else: false), + pool_size: 5 +end + +config :cloudflare, + auth_token: get_env("CLOUDFLARE_AUTH_TOKEN") + +config :core, Core.Influx, + database: "plural", + host: "influxdb.influx", + auth: [method: :basic, username: "admin", password: get_env("INFLUX_PAASSWORD")], + port: 8086 + +config :core, :jwt, + pk: get_env("JWT_PRIVATE_KEY"), + cert: get_env("JWT_CERT"), + iss: get_env("JWT_ISS"), + aud: get_env("JWT_AUD") + +config :core, Core.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :rtc, Rtc.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :worker, Worker.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :piazza_core, aes_key: get_env("AES_KEY") + +config :core, Core.Clients.Zoom, + client_id: get_env("ZOOM_CLIENT_ID"), + client_secret: get_env("ZOOM_CLIENT_SECRET") + +config :core, + chartmuseum: "http://chartmuseum:8080", + plural_cmd: "/usr/local/bin/plural", + stripe_connect_id: get_env("STRIPE_CONNECT_ID"), + stripe_publishable_key: get_env("STRIPE_PUBLISHABLE_KEY"), + hydra_public_url: get_env("HYDRA_URL") || "https://oidc.plural.sh", + git_commit: get_env("GIT_COMMIT"), + cloudflare_zone: get_env("CLOUDFLARE_ZONE"), + acme_key_id: get_env("ACME_KEY_ID"), + acme_secret: get_env("ACME_SECRET"), + zerossl_access_key: get_env("ZEROSSL_ACCESS_KEY"), + docker_metrics_table: ~s("permanent"."downsampled_docker_pulls"), + workos_webhook: get_env("WORKOS_WEBHOOK_SECRET"), + gcp_identity: get_env("GCP_USER_EMAIL") || "mjg@plural.sh", + openai_token: get_env("OPENAI_BEARER_TOKEN"), + enforce_pricing: get_env("ENFORCE_PRICING"), + stripe_webhook_secret: get_env("STRIPE_WEBHOOK_SECRET"), + github_demo_token: get_env("GITHUB_DEMO_TOKEN"), + console_token: get_env("CONSOLE_SA_TOKEN"), + dedicated_console_token: get_env("CONSOLE_DEDICATED_SA_TOKEN"), + dedicated_project: get_env("CONSOLE_DEDICATED_PROJECT"), + mgmt_cluster: get_env("MGMT_CLUSTER_ID"), + console_url: get_env("CONSOLE_URL"), + mgmt_repo: get_env("CONSOLE_MGMT_REPO"), + stack_id: get_env("CONSOLE_CLOUD_STACK_ID"), + cloud_domain: get_env("CONSOLE_CLOUD_DOMAIN") || "cloud.plural.sh", + base_stripe_product: get_env("STRIPE_PRO_PRODUCT"), + metered_stripe_product: get_env("STRIPE_PRO_CLUSTER_PRODUCT"), + cluster_meter_name: get_env("CLUSTER_METER_NAME") || "pro_clusters", + initial_user: get_env("ADMIN_EMAIL") || "admin@plural.sh", + stage: get_env("PLURAL_STAGE") || "prod" + +if get_env("VAULT_HOST") do + config :core, vault: get_env("VAULT_HOST") +end + +if get_env("SYSBOX_WHITELIST") do + config :core, :sysbox_emails, String.split(get_env("SYSBOX_WHITELIST"), ",") +end + +if get_env("INTERCOM_SALT") do + config :core, intercom_salt: get_env("INTERCOM_SALT") +end + +config :workos, + client_id: get_env("WORKOS_CLIENT_ID"), + api_key: get_env("WORKOS_API_KEY") + +provider = case get_env("PROVIDER") || "google" do + "google" -> :gcp + "gcp" -> :gcp + "aws" -> :aws + "azure" -> :azure + "equinix" -> :equinix + "kind" -> :kind + "generic" -> :generic + _ -> :custom +end + +if provider != :gcp do + config :goth, disabled: true + config :waffle, storage: Waffle.Storage.S3 +end + +if org_id = get_env("GCP_ORG_ID") do + config :core, + gcp_organization: org_id +end + +if get_env("GCP_CREDENTIALS") do + config :goth, + json: {:system, "GCP_CREDENTIALS"}, + project_id: get_env("GCP_PROJECT") || "pluralsh", + disabled: false +end + +config :core, + registry: get_env("DKR_DNS") + +config :openai, + token: get_env("OPENAI_BEARER_TOKEN") + +config :tzdata, :autoupdate, :disabled + +config :rtc, RtcWeb.Endpoint, + url: [host: get_env("HOST"), port: 80], + check_origin: ["//#{get_env("HOST")}", "//plural-rtc"], + secret_key_base: get_env("SECRET_KEY_BASE"), + server: true + +config :core, broker: Rtc.Conduit.Broker +config :core, start_broker: false +config :rtc, start_broker: true + +config :libcluster, + topologies: [ + rtc: [ + strategy: Cluster.Strategy.Kubernetes, + config: [ + mode: :ip, + kubernetes_node_basename: "rtc", + kubernetes_selector: "app=plural-rtc", + kubernetes_namespace: get_env("NAMESPACE"), + polling_interval: 10_000 + ] + ] + ] diff --git a/rel/runtime/worker.exs b/rel/runtime/worker.exs new file mode 100644 index 000000000..9c34f26cc --- /dev/null +++ b/rel/runtime/worker.exs @@ -0,0 +1,165 @@ +import Config +import System, only: [get_env: 1] + +host = get_env("HOST") + +config :api, ApiWeb.Endpoint, + url: [host: host, port: 80], + check_origin: ["//#{host}", "//plural-api"] + +config :rtc, RtcWeb.Endpoint, + url: [host: host, port: 80], + check_origin: ["//#{host}", "//plural-rtc"] + +config :core, hostname: host +config :email, host: "https://#{host}" +config :core, host: "https://#{host}" + +config :waffle, + storage: Waffle.Storage.Google.CloudStorage, + bucket: get_env("BUCKET") + +config :core, Core.Guardian, + issuer: "plural", + secret_key: get_env("JWT_SECRET") + +if get_env("POSTGRES_URL") do + config :core, Core.Repo, + url: get_env("POSTGRES_URL"), + ssl: if(get_env("DBSSL") == "false", do: false, else: [verify: :verify_none]), + pool_size: 5 +else + config :core, Core.Repo, + database: "plural", + username: "plural", + password: get_env("POSTGRES_PASSWORD"), + hostname: get_env("DBHOST") || "plural-postgresql", + ssl: if(get_env("DBSSL") == "true", do: [verify: :verify_none], else: false), + pool_size: 5 +end + +config :cloudflare, + auth_token: get_env("CLOUDFLARE_AUTH_TOKEN") + +config :core, Core.Influx, + database: "plural", + host: "influxdb.influx", + auth: [method: :basic, username: "admin", password: get_env("INFLUX_PAASSWORD")], + port: 8086 + +config :core, :jwt, + pk: get_env("JWT_PRIVATE_KEY"), + cert: get_env("JWT_CERT"), + iss: get_env("JWT_ISS"), + aud: get_env("JWT_AUD") + +config :core, Core.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :rtc, Rtc.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :worker, Worker.Conduit.Broker, + adapter: ConduitAMQP, + url: "amqp://#{get_env("RABBIT_USERNAME")}:#{get_env("RABBIT_PASSWORD")}@rabbitmq.#{get_env("RABBIT_NAMESPACE")}" + +config :piazza_core, aes_key: get_env("AES_KEY") + +config :core, Core.Clients.Zoom, + client_id: get_env("ZOOM_CLIENT_ID"), + client_secret: get_env("ZOOM_CLIENT_SECRET") + +config :core, + chartmuseum: "http://chartmuseum:8080", + plural_cmd: "/usr/local/bin/plural", + stripe_connect_id: get_env("STRIPE_CONNECT_ID"), + stripe_publishable_key: get_env("STRIPE_PUBLISHABLE_KEY"), + hydra_public_url: get_env("HYDRA_URL") || "https://oidc.plural.sh", + git_commit: get_env("GIT_COMMIT"), + cloudflare_zone: get_env("CLOUDFLARE_ZONE"), + acme_key_id: get_env("ACME_KEY_ID"), + acme_secret: get_env("ACME_SECRET"), + zerossl_access_key: get_env("ZEROSSL_ACCESS_KEY"), + docker_metrics_table: ~s("permanent"."downsampled_docker_pulls"), + workos_webhook: get_env("WORKOS_WEBHOOK_SECRET"), + gcp_identity: get_env("GCP_USER_EMAIL") || "mjg@plural.sh", + openai_token: get_env("OPENAI_BEARER_TOKEN"), + enforce_pricing: get_env("ENFORCE_PRICING"), + stripe_webhook_secret: get_env("STRIPE_WEBHOOK_SECRET"), + github_demo_token: get_env("GITHUB_DEMO_TOKEN"), + console_token: get_env("CONSOLE_SA_TOKEN"), + dedicated_console_token: get_env("CONSOLE_DEDICATED_SA_TOKEN"), + dedicated_project: get_env("CONSOLE_DEDICATED_PROJECT"), + mgmt_cluster: get_env("MGMT_CLUSTER_ID"), + console_url: get_env("CONSOLE_URL"), + mgmt_repo: get_env("CONSOLE_MGMT_REPO"), + stack_id: get_env("CONSOLE_CLOUD_STACK_ID"), + cloud_domain: get_env("CONSOLE_CLOUD_DOMAIN") || "cloud.plural.sh", + base_stripe_product: get_env("STRIPE_PRO_PRODUCT"), + metered_stripe_product: get_env("STRIPE_PRO_CLUSTER_PRODUCT"), + cluster_meter_name: get_env("CLUSTER_METER_NAME") || "pro_clusters", + initial_user: get_env("ADMIN_EMAIL") || "admin@plural.sh", + stage: get_env("PLURAL_STAGE") || "prod" + +if get_env("VAULT_HOST") do + config :core, vault: get_env("VAULT_HOST") +end + +if get_env("SYSBOX_WHITELIST") do + config :core, :sysbox_emails, String.split(get_env("SYSBOX_WHITELIST"), ",") +end + +if get_env("INTERCOM_SALT") do + config :core, intercom_salt: get_env("INTERCOM_SALT") +end + +config :workos, + client_id: get_env("WORKOS_CLIENT_ID"), + api_key: get_env("WORKOS_API_KEY") + +provider = case get_env("PROVIDER") || "google" do + "google" -> :gcp + "gcp" -> :gcp + "aws" -> :aws + "azure" -> :azure + "equinix" -> :equinix + "kind" -> :kind + "generic" -> :generic + _ -> :custom +end + +if provider != :gcp do + config :goth, disabled: true + config :waffle, storage: Waffle.Storage.S3 +end + +if org_id = get_env("GCP_ORG_ID") do + config :core, + gcp_organization: org_id +end + +if get_env("GCP_CREDENTIALS") do + config :goth, + json: {:system, "GCP_CREDENTIALS"}, + project_id: get_env("GCP_PROJECT") || "pluralsh", + disabled: false +end + +config :core, + registry: get_env("DKR_DNS") + +config :openai, + token: get_env("OPENAI_BEARER_TOKEN") + +config :tzdata, :autoupdate, :disabled + +config :worker, + registry: get_env("DKR_DNS") + +config :core, start_broker: false +config :worker, start_broker: true +config :core, broker: Worker.Conduit.Broker + +config :stripity_stripe, api_key: get_env("STRIPE_SECRET") diff --git a/rel/vm.args b/rel/vm.args deleted file mode 100644 index d2108a099..000000000 --- a/rel/vm.args +++ /dev/null @@ -1,30 +0,0 @@ -## This file provide the arguments provided to the VM at startup -## You can find a full list of flags and their behaviours at -## http://erlang.org/doc/man/erl.html - -## Name of the node --name <%= release_name %>@${POD_IP} - -## Cookie for distributed erlang --setcookie ${ERLANG_COOKIE} - -## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive -## (Disabled by default..use with caution!) -##-heart - -## Enable kernel poll and a few async threads -##+K true -##+A 5 -## For OTP21+, the +A flag is not used anymore, -## +SDio replace it to use dirty schedulers -##+SDio 5 - -## Increase number of concurrent ports/sockets -##-env ERL_MAX_PORTS 4096 - -## Tweak GC to run more often -##-env ERL_FULLSWEEP_AFTER 10 - -# Enable SMP automatically based on availability -# On OTP21+, this is not needed anymore. --smp auto diff --git a/rel/vm.args.eex b/rel/vm.args.eex new file mode 100644 index 000000000..7fe3d9623 --- /dev/null +++ b/rel/vm.args.eex @@ -0,0 +1,6 @@ +## Customize flags given to the VM: https://www.erlang.org/doc/man/erl.html +## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here + ++sbwt none + +-kernel inet_dist_listen_min 6000 inet_dist_listen_max 6000