# 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"
