Initial commit on Forgejo
All checks were successful
CI and deploy / Test (push) Successful in 4m52s
CI and deploy / Deploy production (push) Successful in 23s

Fresh repository history for elektrine/tarakan hosted at
https://git.elektrine.com/elektrine/tarakan.
This commit is contained in:
Maxfield Luke 2026-07-29 04:43:40 -04:00
commit af6077b9c3
455 changed files with 78366 additions and 0 deletions

209
config/config.exs Normal file
View file

@ -0,0 +1,209 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
# General application configuration
import Config
config :tarakan, secure_cookies: true
# Contact published in /.well-known/security.txt; overridden in prod runtime.
config :tarakan, security_contact: "security@example.com"
config :tarakan, :scopes,
account: [
default: true,
module: Tarakan.Accounts.Scope,
assign_key: :current_scope,
access_path: [:account, :id],
schema_key: :account_id,
schema_type: :id,
schema_table: :accounts,
test_data_fixture: Tarakan.AccountsFixtures,
test_setup_helper: :register_and_log_in_account
]
config :tarakan,
ecto_repos: [Tarakan.Repo],
generators: [timestamp_type: :utc_datetime],
github_client: Tarakan.GitHub.HTTPClient,
github_bulk_client: Tarakan.GitHub.GraphQLClient,
github_oauth_client: Tarakan.GitHub.OAuth.HTTPClient,
gitlab_oauth_client: Tarakan.GitLab.OAuth.HTTPClient,
# Finding-kind Request complete requires a Review Format document (Findings path).
# Legacy prose remains for write_fix / verify_findings and for tests that opt into dual mode.
request_completion_mode: :document_required,
stripe_api: Tarakan.Billing.Stripe.API,
stripe_secret_key: nil,
stripe_webhook_secret: nil,
# Placeholder plan prices; real ids come from runtime env in prod.
stripe_price_enterprise: "price_enterprise_placeholder",
# Platform share of bounties, snapshotted onto each bounty at creation.
market_take_rate: 0.10
config :tarakan, :github,
api_version: "2026-03-10",
client_id: nil,
client_secret: nil,
api_token: nil
config :tarakan, Tarakan.RepositoryCode,
global_upstream_limit: 240,
repository_upstream_limit: 60,
upstream_window_seconds: 60,
identity_cache_ttl_ms: 3_000,
identity_revalidation_ttl_ms: 86_400_000,
head_cache_ttl_ms: 12_000,
immutable_cache_ttl_ms: 86_400_000
# Public aggregate queries (posture, badges, model analytics, the suppression
# corpus). Short enough that the record still reads as live; long enough that
# an unauthenticated endpoint cannot replay the query on demand.
config :tarakan, Tarakan.AnalyticsCache, ttl_ms: 60_000
config :tarakan, Tarakan.RepositoryMirror,
enabled: true,
# Production code browse uses git mirrors only (no GitHub REST for objects).
rest_fallback: false,
root: "priv/mirrors"
config :tarakan, Tarakan.HostedRepositories,
root: "priv/hosted",
max_push_bytes: 262_144_000,
quota_bytes: 1_073_741_824
config :tarakan, Tarakan.GitSSH,
enabled: false,
port: 2222,
host_key_dir: "priv/ssh"
# Cap concurrent git upload-pack/receive-pack processes (HTTP RPC + SSH).
config :tarakan, Tarakan.Git.Concurrency, max_concurrent: 32
config :tarakan, Oban,
engine: Oban.Engines.Basic,
repo: Tarakan.Repo,
# infestations: 1 keeps DB pool pressure low (compose POOL_SIZE default is 5).
queues: [sync: 5, mirror: 3, infestations: 1, credits: 1, market: 1, billing: 1],
plugins: [
{Oban.Plugins.Pruner, max_age: 7 * 24 * 60 * 60},
{Oban.Plugins.Cron,
crontab: [
{"0 3 * * *", Tarakan.Sync.RepositorySweep},
{"30 3 * * *", Tarakan.Infestations.Reconcile},
# No-op until :swarm_sweep names an actor; runs after the reconcile so
# it sees the rollups that pass refreshed.
{"45 3 * * *", Tarakan.Infestations.SwarmSweep},
{"0 4 * * 0", Tarakan.Sync.HostedRepositoryGC},
{"0 * * * *", Tarakan.Infestations.RecomputeWindows},
{"15 * * * *", Tarakan.Market.SweepWorker},
{"0 9 * * *", Tarakan.Billing.AlertWorker}
]}
]
# The nightly swarm sweep fans check jobs onto other contributors' agents, so
# it stays inert until an operator names the account it opens them as.
config :tarakan, :swarm_sweep,
actor_handle: nil,
patterns_per_run: 25,
jobs_per_run: 40,
max_jobs_per_pattern: 8,
min_repos: 3,
days: 90
# Infestation rollups: async projection + dual-read. Tests set sync_refresh: true.
config :tarakan, :infestations,
read_from_rollup: true,
refresh_async: true,
sync_refresh: false
config :tarakan, :gitlab,
base_url: "https://gitlab.com",
client_id: nil,
client_secret: nil
# Configure the endpoint
config :tarakan, TarakanWeb.Endpoint,
url: [host: "localhost"],
adapter: Bandit.PhoenixAdapter,
render_errors: [
formats: [html: TarakanWeb.ErrorHTML, json: TarakanWeb.ErrorJSON],
layout: false
],
pubsub_server: Tarakan.PubSub,
live_view: [signing_salt: "Ht50NGTc"]
# Configure LiveView
config :phoenix_live_view,
# the attribute set on all root tags. Used for Phoenix.LiveView.ColocatedCSS.
root_tag_attribute: "phx-r"
# Configure the mailer
#
# By default it uses the "Local" adapter which stores the emails
# locally. You can see the emails in your browser, at "/dev/mailbox".
#
# For production it's recommended to configure a different adapter
# at the `config/runtime.exs`.
config :tarakan, Tarakan.Mailer, adapter: Swoosh.Adapters.Local
# Configure esbuild (the version is required)
config :esbuild,
version: "0.25.4",
tarakan: [
args:
~w(js/app.js --bundle --target=es2022 --format=esm --splitting --outdir=../priv/static/assets/js --external:/fonts/* --external:/images/* --alias:@=.),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => [Path.expand("../deps", __DIR__), Mix.Project.build_path()]}
],
# Separate profile because this one must ship as a classic script: it runs
# blocking in <head> before first paint, and a module is always deferred.
theme: [
args:
~w(js/theme.js --bundle --target=es2017 --format=iife --outdir=../priv/static/assets/js),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => [Path.expand("../deps", __DIR__), Mix.Project.build_path()]}
]
# Configure tailwind (the version is required)
config :tailwind,
version: "4.3.0",
tarakan: [
args: ~w(
--input=assets/css/app.css
--output=priv/static/assets/css/app.css
),
cd: Path.expand("..", __DIR__),
env: %{"NODE_PATH" => [Path.expand("../deps", __DIR__), Mix.Project.build_path()]}
]
# Configure Elixir's Logger
config :logger, :default_formatter,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]
# Use Jason for JSON parsing in Phoenix
config :phoenix,
json_library: Jason,
filter_parameters: [
"authorization",
"code",
"credential",
"description",
"document",
"evidence",
"findings",
"findings_json",
"notes",
"password",
"reason",
"secret",
"summary",
"token"
]
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"

83
config/dev.exs Normal file
View file

@ -0,0 +1,83 @@
import Config
config :tarakan, secure_cookies: false
# Configure your database
config :tarakan, Tarakan.Repo,
username: "postgres",
password: "postgres",
hostname: "localhost",
database: "tarakan_dev",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 10
# For development, we disable any cache and enable
# debugging and code reloading.
#
# The watchers configuration can be used to run external
# watchers to your application. For example, we can use it
# to bundle .js and .css sources.
config :tarakan, TarakanWeb.Endpoint,
# Binding to loopback ipv4 address prevents access from other machines.
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
http: [ip: {127, 0, 0, 1}, port: String.to_integer(System.get_env("PORT", "4000"))],
check_origin: false,
code_reloader: true,
debug_errors: true,
secret_key_base: "HDyyZ5E8CpuKZUBimoGQjpMpP2wuQhCcClvcF7MECB4q+PhgGE7B2wxbtlhzgdLp",
watchers: [
esbuild: {Esbuild, :install_and_run, [:tarakan, ~w(--sourcemap=inline --watch)]},
tailwind: {Tailwind, :install_and_run, [:tarakan, ~w(--watch)]}
]
# ## SSL Support
#
# In order to use HTTPS in development, a self-signed
# certificate can be generated by running the following
# Mix task:
#
# mix phx.gen.cert
#
# Run `mix help phx.gen.cert` for more information.
#
# The `http:` config above can be replaced with:
#
# https: [
# port: 4001,
# cipher_suite: :strong,
# keyfile: "priv/cert/selfsigned_key.pem",
# certfile: "priv/cert/selfsigned.pem"
# ],
#
# If desired, both `http:` and `https:` keys can be
# configured to run both http and https servers on
# different ports.
# Enable dev routes for dashboard and mailbox
config :tarakan, dev_routes: true
# Do not include metadata nor timestamps in development logs
config :logger, :default_formatter, format: "[$level] $message\n"
# Set a higher stacktrace during development. Avoid configuring such
# in production as building large stacktraces may be expensive.
config :phoenix, :stacktrace_depth, 20
# Initialize plugs at runtime for faster development compilation
config :phoenix, :plug_init_mode, :runtime
config :phoenix_live_view,
# Include debug annotations and locations in rendered markup.
# Changing this configuration will require mix clean and a full recompile.
debug_heex_annotations: true,
debug_attributes: true,
# Enable helpful, but potentially expensive runtime checks
enable_expensive_runtime_checks: true
# Disable swoosh api client as it is only required for production adapters.
config :swoosh, :api_client, false
# Git-over-SSH daemon for local development:
# git clone ssh://git@localhost:2222/<handle>/<name>.git
config :tarakan, Tarakan.GitSSH, enabled: true, port: 2222, host_key_dir: "priv/ssh"

35
config/prod.exs Normal file
View file

@ -0,0 +1,35 @@
import Config
# Note we also include the path to a cache manifest
# containing the digested version of static files. This
# manifest is generated by the `mix assets.deploy` task,
# which you should run after static files are built and
# before starting your production server.
config :tarakan, TarakanWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json"
# Force using SSL in production. This also sets the "strict-security-transport" header,
# known as HSTS. If you have a health check endpoint, you may want to exclude it below.
# The endpoint plugs TarakanWeb.Plugs.ForwardedProto before Plug.SSL so the
# X-Forwarded-Proto scheme rewrite only applies to trusted proxies (see
# :trusted_proxies in runtime.exs), which is why this uses :trusted_ssl rather
# than Phoenix's :force_ssl. Note it is required to be set at compile-time.
config :tarakan, TarakanWeb.Endpoint,
trusted_ssl: [
host: {TarakanWeb.Endpoint, :host, []},
exclude: [
# paths: ["/health"],
hosts: ["localhost", "127.0.0.1"]
]
]
# Configure Swoosh API Client
config :swoosh, api_client: Swoosh.ApiClient.Req
# Disable Swoosh Local Memory Storage
config :swoosh, local: false
# Do not print debug messages in production
config :logger, level: :info
# Runtime production configuration, including reading
# of environment variables, is done on config/runtime.exs.

251
config/runtime.exs Normal file
View file

@ -0,0 +1,251 @@
import Config
# config/runtime.exs is executed for all environments, including
# during releases. It is executed after compilation and before the
# system starts, so it is typically used to load production configuration
# and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration.
# ## Using releases
#
# If you use `mix release`, you need to explicitly enable the server
# by passing the PHX_SERVER=true when you start it:
#
# PHX_SERVER=true bin/tarakan start
#
# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
# script that automatically sets the env var above.
if System.get_env("PHX_SERVER") do
config :tarakan, TarakanWeb.Endpoint, server: true
end
config :tarakan, TarakanWeb.Endpoint,
http: [port: String.to_integer(System.get_env("PORT", "4000"))]
github_runtime_config =
[
client_id: System.get_env("GITHUB_CLIENT_ID"),
client_secret: System.get_env("GITHUB_CLIENT_SECRET"),
api_token: System.get_env("GITHUB_TOKEN")
]
|> Enum.reject(fn {_key, value} -> is_nil(value) end)
if github_runtime_config != [] do
config :tarakan, :github, github_runtime_config
end
if mirror_dir = System.get_env("MIRROR_DIR") do
config :tarakan, Tarakan.RepositoryMirror, root: mirror_dir
end
if hosted_dir = System.get_env("HOSTED_DIR") do
config :tarakan, Tarakan.HostedRepositories, root: hosted_dir
end
git_ssh_runtime_config =
[
enabled: System.get_env("GIT_SSH_ENABLED") in ~w(true 1),
port: System.get_env("GIT_SSH_PORT") && String.to_integer(System.get_env("GIT_SSH_PORT")),
host_key_dir: System.get_env("GIT_SSH_HOST_KEY_DIR")
]
|> Enum.reject(fn {_key, value} -> is_nil(value) end)
if System.get_env("GIT_SSH_ENABLED") do
config :tarakan, Tarakan.GitSSH, git_ssh_runtime_config
end
gitlab_runtime_config =
[
base_url: System.get_env("GITLAB_URL"),
client_id: System.get_env("GITLAB_CLIENT_ID"),
client_secret: System.get_env("GITLAB_CLIENT_SECRET")
]
|> Enum.reject(fn {_key, value} -> is_nil(value) end)
if gitlab_runtime_config != [] do
config :tarakan, :gitlab, gitlab_runtime_config
end
# The OAuth client posts the client_secret and user bearer tokens to the
# GitLab base URL, so in prod it must use TLS. Plain http stays allowed in
# dev/test for local self-hosted instances.
if config_env() == :prod do
case System.get_env("GITLAB_URL") do
nil ->
:ok
"https://" <> _rest ->
:ok
url ->
raise """
environment variable GITLAB_URL must use an https:// URL in prod, got: #{inspect(url)}
"""
end
end
if config_env() == :dev do
# Reload browser tabs when matching files change.
config :tarakan, TarakanWeb.Endpoint,
live_reload: [
web_console_logger: true,
patterns: [
# Static assets, except user uploads
~r"priv/static/(?!uploads/).*\.(js|css|png|jpeg|jpg|gif|svg)$"E,
# Gettext translations
~r"priv/gettext/.*\.po$"E,
# Router, Controllers, LiveViews and LiveComponents
~r"lib/tarakan_web/router\.ex$"E,
~r"lib/tarakan_web/(controllers|live|components)/.*\.(ex|heex)$"E
]
]
end
if config_env() == :prod do
database_url =
System.get_env("DATABASE_URL") ||
raise """
environment variable DATABASE_URL is missing.
For example: ecto://USER:PASS@HOST/DATABASE
"""
maybe_ipv6 = if System.get_env("ECTO_IPV6") in ~w(true 1), do: [:inet6], else: []
# verify_peer TLS to Postgres, on by default in prod (system CAs). Set
# DATABASE_SSL=false for a co-located DB on a private network (docker compose).
repo_ssl? = System.get_env("DATABASE_SSL", "true") in ~w(true 1)
repo_opts = [
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
# For machines with several cores, consider starting multiple pools of `pool_size`
# pool_count: 4,
socket_options: maybe_ipv6
]
repo_opts =
if repo_ssl? do
Keyword.merge(repo_opts,
ssl: true,
ssl_opts: [verify: :verify_peer, cacerts: :public_key.cacerts_get()]
)
else
repo_opts
end
config :tarakan, Tarakan.Repo, repo_opts
# The secret key base is used to sign/encrypt cookies and other secrets.
# A default value is used in config/dev.exs and config/test.exs but you
# want to use a different value for prod and you most likely don't want
# to check this value into version control, so we use an environment
# variable instead.
secret_key_base =
System.get_env("SECRET_KEY_BASE") ||
raise """
environment variable SECRET_KEY_BASE is missing.
You can generate one by calling: mix phx.gen.secret
"""
host = System.get_env("PHX_HOST") || "example.com"
# Published in /.well-known/security.txt (RFC 9116).
config :tarakan, :security_contact, System.get_env("SECURITY_CONTACT") || "security@#{host}"
config :tarakan, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
# Comma-separated IPs/CIDRs of reverse proxies allowed to set X-Forwarded-*
# headers. Example: TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12
# Loopback is always trusted: the Caddy deployment proxies from the same
# host and must be able to assert X-Forwarded-Proto/For.
trusted_proxies =
Tarakan.TrustedProxies.parse(System.get_env("TRUSTED_PROXIES")) ++
Tarakan.TrustedProxies.parse("127.0.0.1,::1")
config :tarakan, :trusted_proxies, trusted_proxies
# Bind address. Defaults to dual-stack IPv6 (`::`), which also accepts IPv4.
# Set PHX_IP=127.0.0.1 to bind loopback-only behind a same-host reverse proxy.
# Any valid IPv4/IPv6 literal is accepted; a malformed value fails fast rather
# than silently binding all interfaces.
phx_ip = System.get_env("PHX_IP", "::")
listen_ip =
case :inet.parse_address(String.to_charlist(phx_ip)) do
{:ok, ip} ->
ip
{:error, _reason} ->
raise """
environment variable PHX_IP is invalid: #{inspect(phx_ip)}
Expected an IPv4 or IPv6 address, e.g. "::", "0.0.0.0", or "127.0.0.1".
"""
end
config :tarakan, TarakanWeb.Endpoint,
url: [host: host, port: 443, scheme: "https"],
http: [
# See the documentation on https://bandit.hexdocs.pm/Bandit.html#t:options/0
ip: listen_ip
],
secret_key_base: secret_key_base
elektrine_email_api_key =
System.get_env("ELEKTRINE_EMAIL_API_KEY") ||
raise "environment variable ELEKTRINE_EMAIL_API_KEY is missing"
config :tarakan, Tarakan.Mailer,
adapter: Tarakan.Mailer.ElektrineAdapter,
api_key: elektrine_email_api_key,
base_url: System.get_env("ELEKTRINE_EMAIL_API_URL", "https://elektrine.com")
# Bounty marketplace (fiat escrow). Optional: credit-funded bounties work
# without Stripe keys; fiat funding stays unavailable until they are set.
if stripe_secret_key = System.get_env("STRIPE_SECRET_KEY") do
config :tarakan, :stripe_secret_key, stripe_secret_key
end
if stripe_webhook_secret = System.get_env("STRIPE_WEBHOOK_SECRET") do
config :tarakan, :stripe_webhook_secret, stripe_webhook_secret
end
# Plan price ids for subscription checkout (config.exs placeholders are
# never valid Stripe objects).
if stripe_price_enterprise = System.get_env("STRIPE_PRICE_ENTERPRISE") do
config :tarakan, :stripe_price_enterprise, stripe_price_enterprise
end
if take_rate = System.get_env("MARKET_TAKE_RATE") do
config :tarakan, :market_take_rate, String.to_float(take_rate)
end
# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
# to your endpoint configuration:
#
# config :tarakan, TarakanWeb.Endpoint,
# https: [
# ...,
# port: 443,
# cipher_suite: :strong,
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
# ]
#
# The `cipher_suite` is set to `:strong` to support only the
# latest and more secure SSL ciphers. This means old browsers
# and clients may not be supported. You can set it to
# `:compatible` for wider support.
#
# `:keyfile` and `:certfile` expect an absolute path to the key
# and cert in disk or a relative path inside priv, for example
# "priv/ssl/server.key". For all supported SSL configuration
# options, see https://plug.hexdocs.pm/Plug.SSL.html#configure/1
#
# SSL is forced in production via the `:trusted_ssl` config in
# config/prod.exs: the endpoint plugs TarakanWeb.Plugs.ForwardedProto
# (trusted-proxy-gated X-Forwarded-Proto rewrite) followed by Plug.SSL
# (HSTS + http->https redirect). See `Plug.SSL` for the available options.
end

118
config/test.exs Normal file
View file

@ -0,0 +1,118 @@
import Config
config :tarakan, secure_cookies: false
# Only in tests, remove the complexity from the password hashing algorithm
config :argon2_elixir, t_cost: 1, m_cost: 8
# Configure your database
#
# The MIX_TEST_PARTITION environment variable can be used
# to provide built-in test partitioning in CI environment.
# Run `mix help test` for more information.
config :tarakan, Tarakan.Repo,
username: "postgres",
password: "postgres",
hostname: "localhost",
database: "tarakan_test#{System.get_env("MIX_TEST_PARTITION")}",
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: System.schedulers_online() * 2
config :tarakan, Oban, testing: :manual
# Tests use the GitHub stub; enable REST object fallback with mirrors off.
config :tarakan, Tarakan.RepositoryMirror, enabled: false, rest_fallback: true
config :tarakan, Tarakan.HostedRepositories,
root: "tmp/test_hosted#{System.get_env("MIX_TEST_PARTITION")}",
max_push_bytes: 262_144_000,
quota_bytes: 1_073_741_824
config :tarakan, TarakanWeb.GitHTTP,
anonymous_rate_limit: {100_000, 60},
account_rate_limit: {100_000, 60}
# Push bookkeeping runs inline so tests observe it deterministically.
config :tarakan, TarakanWeb.GitHTTP.Service, synchronous_post_receive: true
# Login-link delivery runs inline so tests observe tokens and emails.
config :tarakan, Tarakan.Accounts, synchronous_login_delivery: true
config :tarakan,
github_client: Tarakan.GitHubStub,
github_bulk_client: Tarakan.GitHubBulkStub,
github_oauth_client: Tarakan.GitHub.OAuthStub,
gitlab_oauth_client: Tarakan.GitLab.OAuthStub,
request_completion_mode: :document_or_legacy_prose,
stripe_api: Tarakan.Billing.StripeStub,
stripe_webhook_secret: "whsec_test_secret",
stripe_price_enterprise: "price_enterprise_test",
market_take_rate: 0.10
# Infestation tests: refresh rollups inline so list/get see data without Oban drain.
config :tarakan, :infestations,
read_from_rollup: true,
refresh_async: true,
sync_refresh: true
# LiveView tests assert immediate registry stat updates.
config :tarakan, :registry_stats_ttl_seconds, 0
config :tarakan, :github,
client_id: "test-client-id",
client_secret: "test-client-secret",
api_token: nil
config :tarakan, Tarakan.RepositoryCode,
global_upstream_limit: 100_000,
repository_upstream_limit: 100_000,
upstream_window_seconds: 60
# The analytics cache is process-global while the database is per-test, so any
# TTL would leak one case's aggregates into another. Zero bypasses it.
config :tarakan, Tarakan.AnalyticsCache, ttl_ms: 0
config :tarakan, :gitlab,
base_url: "https://gitlab.com",
client_id: "test-gitlab-client-id",
client_secret: "test-gitlab-client-secret"
# We don't run a server during test. If one is required,
# you can enable the server option below.
config :tarakan, TarakanWeb.Endpoint,
http: [ip: {127, 0, 0, 1}, port: 4002],
secret_key_base: "vTG1EmduEPjiggdJIzKiBkK0Moh6gUUV8LlYu4qiKU/dsX4APCeA0kQPUH78NFDz",
server: false
# In test we don't send emails
config :tarakan, Tarakan.Mailer, adapter: Swoosh.Adapters.Test
# Keep the limiter in the request path without coupling unrelated async tests
# to the same loopback-IP bucket. The limiter itself has focused low-limit tests.
config :tarakan, TarakanWeb.Plugs.ApiRateLimit,
request_limit: 100_000,
mutation_limit: 100_000
config :tarakan, TarakanWeb.BrowserRateLimit,
login_ip: {100_000, 60},
login_pair: {100_000, 300},
magic_ip: {100_000, 3_600},
magic_email: {100_000, 3_600},
registration_ip: {100_000, 3_600}
# Disable swoosh api client as it is only required for production adapters
config :swoosh, :api_client, false
# Print only warnings and errors during test
config :logger, level: :warning
# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime
# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
enable_expensive_runtime_checks: true
# Sort query params output of verified routes for robust url comparisons
config :phoenix,
sort_verified_routes_query_params: true