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

View file

@ -0,0 +1,310 @@
defmodule TarakanWeb.RepositoryLive.Index do
use TarakanWeb, :live_view
alias Tarakan.Activity
alias Tarakan.AnalyticsCache
alias Tarakan.Community
alias Tarakan.FindingMemory
alias Tarakan.Fixes
alias Tarakan.Infestations
alias Tarakan.ModelAnalytics
alias Tarakan.Repositories
alias Tarakan.Scans
alias Tarakan.SecurityPosture
alias Tarakan.Work
alias TarakanWeb.Presence
@presence_topic "registry:observers"
@impl true
def mount(_params, _session, socket) do
if connected?(socket) do
Repositories.subscribe()
Activity.subscribe()
Community.subscribe()
Phoenix.PubSub.subscribe(Tarakan.PubSub, @presence_topic)
{:ok, _ref} = Presence.track(self(), @presence_topic, socket.id, %{})
end
{:ok,
socket
|> assign(:page_title, "Public security record")
|> assign(
:meta_description,
"Local agents. Public Reports. Pick up Jobs or publish findings at a pinned commit."
)
|> assign(:canonical_path, ~p"/")
|> assign(:stats, Repositories.registry_stats())
|> assign(:contributor_count, Scans.public_contributor_count())
|> assign(:open_tasks, Work.list_open_public_tasks())
|> assign(:scan_queue, scan_queue())
|> assign(:infestations_window, 7)
|> assign(:infestations, home_infestations(7))
|> assign(:infestations_refreshed_at, System.monotonic_time(:millisecond))
|> assign(:observer_count, observer_count())
|> assign(:shouts, chronological_shouts(socket.assigns.current_scope))
|> assign(:shout_form, to_form(Community.change_shout(), as: :shout))
|> assign(:shout_form_version, 0)
|> assign(:can_moderate_shouts, Community.can_moderate?(socket.assigns.current_scope))
|> assign(:search_query, "")
|> assign(:search_results, [])
|> assign_record_effects()}
end
# Three aggregates over the whole record, identical for every visitor, on the
# busiest page there is. They go through the shared cache so a traffic spike
# cannot replay them per request.
defp assign_record_effects(socket) do
socket
|> assign_effect_lists()
|> assign_responsive_scale()
|> assign(
:pattern_graph,
AnalyticsCache.fetch({:home_pattern_graph, 12}, &encoded_pattern_graph/0,
on_unavailable: nil
)
)
end
# The slowest ranked median, used to scale the responsiveness bars.
defp assign_responsive_scale(socket) do
assign(
socket,
:responsive_max_days,
socket.assigns.responsive
|> Enum.map(& &1.median_days_to_fix)
|> Enum.reject(&is_nil/1)
|> Enum.max(fn -> 0 end)
)
end
# nil rather than an empty graph: a record with nothing entangled yet should
# render no field at all, not an empty one.
defp encoded_pattern_graph do
graph = Infestations.pattern_graph(patterns: 12)
if length(graph.nodes) >= 2, do: Jason.encode!(graph)
end
defp assign_effect_lists(socket) do
socket
|> assign(
:carried_fixes,
AnalyticsCache.fetch(
{:home_carried_fixes, 4},
fn ->
Fixes.list_recent_carried_fixes(limit: 4)
end,
on_unavailable: []
)
)
|> assign(
:regressions,
AnalyticsCache.fetch(
{:home_regressions, 4},
fn ->
FindingMemory.list_recent_regressions(limit: 4)
end,
on_unavailable: []
)
)
|> assign(
:responsive,
AnalyticsCache.fetch(
{:home_responsive, 5},
fn ->
SecurityPosture.leaderboard(limit: 5)
end,
on_unavailable: []
)
)
|> assign(
:model_precision,
AnalyticsCache.fetch(
{:home_model_precision, 5},
fn ->
# Ranked by precision rather than volume: the interesting question is
# which agent is right, not which one talks most.
ModelAnalytics.cached_model_scoreboard(limit: 25)
|> Enum.filter(& &1.precision)
|> Enum.sort_by(& &1.precision, :desc)
|> Enum.take(5)
end,
on_unavailable: []
)
)
end
# Bar width relative to the slowest ranked repository. A floor of 6% keeps the
# fastest row from rendering as an invisible sliver, and a zero maximum (every
# repo fixed same-day) fills the bar rather than dividing by zero.
defp home_bar_pct(_value, max) when max in [nil, 0, 0.0], do: 100
defp home_bar_pct(nil, _max), do: 0
defp home_bar_pct(value, max) do
value |> Kernel./(max) |> Kernel.*(100) |> Float.round(1) |> max(6.0) |> min(100.0)
end
@queue_limit 8
# list_shouts/2 serves "the most recent N", newest first. The shoutbox reads
# like a chat log - oldest visible message at the top, newest at the bottom.
defp chronological_shouts(scope) do
scope |> Community.list_shouts() |> Enum.reverse()
end
defp scan_queue do
Repositories.list_reviewable_repositories(
status: "unscanned",
limit: @queue_limit,
listing: :listed
)
end
@infestation_windows [7, 30, 90]
# Homepage floor is 3 repos: 2-repo matches are often unrelated findings that
# share a generic normalized title, so they would just add noise at scale.
# `list_infestations/1` ranks by the window's repo count (the pattern rollup
# keeps per-window counters), so the selected window drives the ranking.
@home_infestation_min_repos 3
defp home_infestations(days) when days in @infestation_windows do
Infestations.list_infestations(min_repos: @home_infestation_min_repos, days: days, limit: 12)
end
@infestations_debounce_ms 15_000
defp refresh_collective(socket) do
socket
|> assign(:contributor_count, Scans.public_contributor_count())
|> assign(:open_tasks, Work.list_open_public_tasks())
|> assign(:scan_queue, scan_queue())
|> maybe_refresh_infestations()
end
defp maybe_refresh_infestations(socket) do
now = System.monotonic_time(:millisecond)
last = Map.get(socket.assigns, :infestations_refreshed_at, 0)
if now - last >= @infestations_debounce_ms do
socket
|> assign(:infestations, home_infestations(socket.assigns.infestations_window))
|> assign(:infestations_refreshed_at, now)
else
socket
end
end
@impl true
def handle_info({:activity, entry}, socket) do
_entry = entry
{:noreply, refresh_collective(socket)}
end
def handle_info({:repository_registered, _repository}, socket) do
{:noreply,
socket
|> assign(:stats, Repositories.registry_stats())
|> assign(:scan_queue, scan_queue())}
end
def handle_info({:repository_record_updated, repository}, socket) do
_repository = repository
{:noreply,
socket
|> assign(:stats, Repositories.registry_stats())
|> refresh_collective()}
end
def handle_info(%Phoenix.Socket.Broadcast{event: "presence_diff"}, socket) do
{:noreply, assign(socket, :observer_count, observer_count())}
end
def handle_info({event, _shout}, socket) when event in [:shout_posted, :shout_removed] do
{:noreply, assign(socket, :shouts, chronological_shouts(socket.assigns.current_scope))}
end
@impl true
def handle_event("infestations_window", %{"days" => days}, socket)
when days in ["7", "30", "90"] do
days = String.to_integer(days)
{:noreply,
socket
|> assign(:infestations_window, days)
|> assign(:infestations, home_infestations(days))
|> assign(:infestations_refreshed_at, System.monotonic_time(:millisecond))}
end
def handle_event("search", params, socket) do
query = params |> Map.get("q", "") |> String.trim()
{:noreply,
socket
|> assign(:search_query, query)
|> assign(:search_results, Repositories.search_repositories(query))}
end
def handle_event(
"post_shout",
%{"shout" => attrs},
%{assigns: %{current_scope: %{account: account}}} = socket
)
when not is_nil(account) do
case Community.create_shout(socket.assigns.current_scope, attrs) do
{:ok, _shout} ->
{:noreply,
socket
|> assign(:shout_form, to_form(Community.change_shout(), as: :shout))
|> update(:shout_form_version, &(&1 + 1))
|> assign(:shouts, chronological_shouts(socket.assigns.current_scope))}
{:error, :rate_limited} ->
{:noreply, put_flash(socket, :error, "Slow down - a few shouts per minute is plenty.")}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply,
socket
|> assign(:shout_form, to_form(changeset, as: :shout))
|> put_flash(:error, "Write a message before sending.")}
{:error, _reason} ->
{:noreply, put_flash(socket, :error, "That shout could not be posted.")}
end
end
def handle_event("post_shout", _params, socket) do
{:noreply, redirect(socket, to: ~p"/accounts/log-in")}
end
def handle_event(
"remove_shout",
%{"id" => id},
%{assigns: %{current_scope: %{account: account}}} = socket
)
when not is_nil(account) do
with {:ok, shout} <- Community.get_shout(id),
{:ok, _removed} <-
Community.remove_shout(socket.assigns.current_scope, shout, %{
"removed_reason" => "community_moderation"
}) do
{:noreply, assign(socket, :shouts, chronological_shouts(socket.assigns.current_scope))}
else
_error -> {:noreply, put_flash(socket, :error, "That shout could not be removed.")}
end
end
def handle_event("remove_shout", _params, socket) do
{:noreply, put_flash(socket, :error, "That shout could not be removed.")}
end
defp observer_count do
@presence_topic |> Presence.list() |> map_size()
end
defp shout_time(%DateTime{} = datetime), do: Calendar.strftime(datetime, "%b %-d · %H:%M")
end