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,219 @@
defmodule TarakanWeb.AccountSessionControllerTest do
use TarakanWeb.ConnCase, async: true
import Tarakan.AccountsFixtures
alias Tarakan.Accounts
setup do
%{unconfirmed_account: unconfirmed_account_fixture(), account: account_fixture()}
end
describe "POST /accounts/log-in - handle/email and password" do
test "logs the account in", %{conn: conn, account: account} do
account = set_password(account)
conn =
post(conn, ~p"/accounts/log-in", %{
"account" => %{"identifier" => account.handle, "password" => valid_account_password()}
})
assert get_session(conn, :account_token)
assert redirected_to(conn) == ~p"/"
# Now do a logged in request and assert on the menu
conn = get(conn, ~p"/")
response = html_response(conn, 200)
assert response =~ "@#{account.handle}"
assert response =~ ~p"/accounts/settings"
assert response =~ ~p"/accounts/log-out"
end
test "logs the account in with remember me", %{conn: conn, account: account} do
account = set_password(account)
conn =
post(conn, ~p"/accounts/log-in", %{
"account" => %{
"identifier" => account.email,
"password" => valid_account_password(),
"remember_me" => "true"
}
})
assert conn.resp_cookies["_tarakan_web_account_remember_me"]
assert redirected_to(conn) == ~p"/"
end
test "logs the account in with return to", %{conn: conn, account: account} do
account = set_password(account)
conn =
conn
|> init_test_session(account_return_to: "/foo/bar")
|> post(~p"/accounts/log-in", %{
"account" => %{
"identifier" => account.handle,
"password" => valid_account_password()
}
})
assert redirected_to(conn) == "/foo/bar"
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "Welcome back!"
end
test "redirects to login page with invalid credentials", %{conn: conn, account: account} do
conn =
post(conn, ~p"/accounts/log-in?mode=password", %{
"account" => %{"identifier" => account.handle, "password" => "invalid_password"}
})
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"Invalid handle, email, or password"
assert redirected_to(conn) == ~p"/accounts/log-in"
end
end
describe "POST /accounts/log-in - magic link" do
test "logs the account in", %{conn: conn, account: account} do
{token, _hashed_token} = generate_account_magic_link_token(account)
conn =
post(conn, ~p"/accounts/log-in", %{
"account" => %{"token" => token}
})
assert get_session(conn, :account_token)
assert redirected_to(conn) == ~p"/"
# Now do a logged in request and assert on the menu
conn = get(conn, ~p"/")
response = html_response(conn, 200)
assert response =~ "@#{account.handle}"
assert response =~ ~p"/accounts/settings"
assert response =~ ~p"/accounts/log-out"
end
test "confirms unconfirmed account", %{conn: conn, unconfirmed_account: account} do
{token, _hashed_token} = generate_account_magic_link_token(account)
refute account.confirmed_at
conn =
post(conn, ~p"/accounts/log-in", %{
"account" => %{"token" => token},
"_action" => "confirmed"
})
assert get_session(conn, :account_token)
assert redirected_to(conn) == ~p"/"
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "Account confirmed successfully."
assert Accounts.get_account!(account.id).confirmed_at
# Now do a logged in request and assert on the menu
conn = get(conn, ~p"/")
response = html_response(conn, 200)
assert response =~ "@#{account.handle}"
assert response =~ ~p"/accounts/settings"
assert response =~ ~p"/accounts/log-out"
end
test "redirects to login page when magic link is invalid", %{conn: conn} do
conn =
post(conn, ~p"/accounts/log-in", %{
"account" => %{"token" => "invalid"}
})
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"The link is invalid or it has expired."
assert redirected_to(conn) == ~p"/accounts/log-in"
end
test "redirects to login page for a crafted non-base64 magic link", %{conn: conn} do
conn =
post(conn, ~p"/accounts/log-in", %{
"account" => %{"token" => "not base64!"}
})
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"The link is invalid or it has expired."
assert redirected_to(conn) == ~p"/accounts/log-in"
end
end
describe "POST /accounts/update-password" do
test "updates the password for a confirmed account in sudo mode", %{
conn: conn,
account: account
} do
conn =
conn
|> log_in_account(account)
|> post(~p"/accounts/update-password", %{
"account" => %{
"password" => valid_account_password(),
"password_confirmation" => valid_account_password()
}
})
assert redirected_to(conn) == ~p"/accounts/settings"
assert Accounts.get_account_by_email_and_password(account.email, valid_account_password())
end
test "redirects to re-authentication when the sudo window expired", %{
conn: conn,
account: account
} do
stale_at = DateTime.add(DateTime.utc_now(:second), -3, :hour)
conn =
conn
|> log_in_account(account, token_authenticated_at: stale_at)
|> post(~p"/accounts/update-password", %{
"account" => %{
"password" => valid_account_password(),
"password_confirmation" => valid_account_password()
}
})
assert redirected_to(conn) == ~p"/accounts/log-in?return_to=%2Faccounts%2Fsettings"
refute Accounts.get_account_by_email_and_password(account.email, valid_account_password())
end
test "refuses to establish a password before the email is confirmed", %{
conn: conn,
unconfirmed_account: account
} do
conn =
conn
|> log_in_account(account)
|> post(~p"/accounts/update-password", %{
"account" => %{
"password" => valid_account_password(),
"password_confirmation" => valid_account_password()
}
})
assert redirected_to(conn) == ~p"/accounts/settings"
refute Accounts.get_account!(account.id).hashed_password
end
end
describe "DELETE /accounts/log-out" do
test "logs the account out", %{conn: conn, account: account} do
conn = conn |> log_in_account(account) |> delete(~p"/accounts/log-out")
assert redirected_to(conn) == ~p"/"
refute get_session(conn, :account_token)
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "Logged out successfully"
end
test "succeeds even if the account is not logged in", %{conn: conn} do
conn = delete(conn, ~p"/accounts/log-out")
assert redirected_to(conn) == ~p"/"
refute get_session(conn, :account_token)
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "Logged out successfully"
end
end
end

View file

@ -0,0 +1,148 @@
defmodule TarakanWeb.API.ClientAuthControllerTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.Accounts.ApiCredentials
test "browser approval exchanges a device code for one scoped credential", %{conn: conn} do
start_response =
conn
|> post(~p"/api/client-auth/start", %{client_name: "Tarakan CLI on laptop"})
|> json_response(201)
assert start_response["device_code"] =~ "trkd_"
assert start_response["user_code"] =~ ~r/^[A-Z2-7]{4}-[A-Z2-7]{4}$/
assert start_response["verification_uri_complete"] =~
"/client/authorize/#{start_response["user_code"]}"
pending =
build_conn()
|> post(~p"/api/client-auth/exchange", %{device_code: start_response["device_code"]})
|> json_response(400)
assert pending == %{"error" => "authorization_pending"}
account = account_fixture()
{:ok, view, _html} =
build_conn()
|> log_in_account(account)
|> live(~p"/client/authorize/#{start_response["user_code"]}")
assert has_element?(view, "#client-authorization-code")
assert has_element?(view, "#client-authorization-approve-button")
view
|> element("#client-authorization-approve-button")
|> render_click()
assert has_element?(view, "#client-authorization-approved")
exchange_response =
build_conn()
|> post(~p"/api/client-auth/exchange", %{device_code: start_response["device_code"]})
|> json_response(200)
assert exchange_response["token"] =~ "trkn_"
assert exchange_response["token_type"] == "Bearer"
assert "tasks:read" in exchange_response["scopes"]
assert "tasks:claim" in exchange_response["scopes"]
assert "contributions:write" in exchange_response["scopes"]
assert "reviews:submit" in exchange_response["scopes"]
refute "reviews:verify" in exchange_response["scopes"]
refute "reviews:read" in exchange_response["scopes"]
assert {:ok, ^account, credential} = ApiCredentials.authenticate(exchange_response["token"])
assert credential.name == "Tarakan CLI on laptop"
# Device-minted credentials are short-lived (agent blast-radius control).
expires_in_days = DateTime.diff(credential.expires_at, DateTime.utc_now(), :day)
assert expires_in_days in 6..7
consumed =
build_conn()
|> post(~p"/api/client-auth/exchange", %{device_code: start_response["device_code"]})
|> json_response(400)
assert consumed == %{"error" => "invalid_device_code"}
revoke_conn =
build_conn()
|> put_req_header("authorization", "Bearer #{exchange_response["token"]}")
|> delete(~p"/api/client-auth/session")
assert response(revoke_conn, 204) == ""
assert :error = ApiCredentials.authenticate(exchange_response["token"])
end
test "the browser can deny a login without issuing a credential", %{conn: conn} do
start_response =
conn
|> post(~p"/api/client-auth/start", %{})
|> json_response(201)
{:ok, view, _html} =
build_conn()
|> log_in_account(account_fixture())
|> live(~p"/client/authorize/#{start_response["user_code"]}")
view
|> element("#client-authorization-deny-button")
|> render_click()
assert has_element?(view, "#client-authorization-denied")
denied =
build_conn()
|> post(~p"/api/client-auth/exchange", %{device_code: start_response["device_code"]})
|> json_response(403)
assert denied == %{"error" => "access_denied"}
end
test "authorization page requires a signed-in web account", %{conn: conn} do
start_response =
conn
|> post(~p"/api/client-auth/start", %{})
|> json_response(201)
assert {:error, {:redirect, %{to: path}}} =
live(build_conn(), ~p"/client/authorize/#{start_response["user_code"]}")
assert path == ~p"/accounts/log-in"
end
test "a signed-in session can approve without recent reauth", %{conn: conn} do
start_response =
conn
|> post(~p"/api/client-auth/start", %{})
|> json_response(201)
return_to = ~p"/client/authorize/#{start_response["user_code"]}"
stale_at = DateTime.add(DateTime.utc_now(:second), -9 * 60, :minute)
{:ok, view, _html} =
build_conn()
|> log_in_account(account_fixture(), token_authenticated_at: stale_at)
|> live(return_to)
assert has_element?(view, "#client-authorization-approve-button")
view
|> element("#client-authorization-approve-button")
|> render_click()
assert has_element?(view, "#client-authorization-approved")
end
test "invalid device codes fail without revealing authorization state", %{conn: conn} do
response =
conn
|> post(~p"/api/client-auth/exchange", %{device_code: "not-a-device-code"})
|> json_response(400)
assert response == %{"error" => "invalid_device_code"}
end
end

View file

@ -0,0 +1,142 @@
defmodule TarakanWeb.API.FindingControllerTest do
use TarakanWeb.ConnCase
setup do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
%{repository: repository, submitter: submitter}
end
test "returns a serialized public finding", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan =
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_with_disclosure_fixture()})
|> publish_scan("public")
[finding] = scan.findings
conn = get(conn, ~p"/api/findings/#{finding.public_id}")
assert %{"finding" => data} = json_response(conn, 200)
assert data["public_id"] == finding.public_id
assert data["title"] == finding.title
assert data["severity"] == "high"
assert data["status"] == "verified"
assert data["description"] =~ "String-built SQL"
assert data["reproduction_steps"] =~ "Run the payload"
assert data["affected_versions"] == ">= 1.0, < 2.0"
assert data["cwe_id"] == "CWE-89"
assert data["cve_id"] == "CVE-2026-12345"
assert data["file_path"] == "lib/example/module_1.ex"
assert data["line_start"] == 10
assert data["line_end"] == 15
assert data["first_seen_commit_sha"] == scan.commit_sha
assert data["last_seen_commit_sha"] == scan.commit_sha
assert data["verified_at"]
assert is_map(data["counters"])
assert data["repository"] == %{"host" => "github.com", "owner" => "openai", "name" => "codex"}
assert data["record_url"] == TarakanWeb.Endpoint.url() <> "/findings/#{finding.public_id}"
assert data["inserted_at"]
end
test "404s for a restricted finding", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
{:ok, _restricted} =
Tarakan.Scans.update_visibility(
Tarakan.Accounts.Scope.for_account(moderator_account_fixture()),
scan,
"restricted",
%{
"moderation_reason" => "takedown_review",
"moderation_notes" => "Restricted in this test to keep it off the public API."
}
)
[finding] = scan.findings
conn = get(conn, ~p"/api/findings/#{finding.public_id}")
assert json_response(conn, 404)["error"] =~ "not found"
end
test "404s for a summary-only finding", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan =
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_fixture(1)})
|> publish_scan("public_summary")
[finding] = scan.findings
conn = get(conn, ~p"/api/findings/#{finding.public_id}")
assert json_response(conn, 404)["error"] =~ "not found"
end
test "404s for an unknown public id", %{conn: conn} do
conn = get(conn, ~p"/api/findings/#{Ecto.UUID.generate()}")
assert json_response(conn, 404)["error"] =~ "not found"
end
defp findings_json_with_disclosure_fixture do
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => "lib/example/module_1.ex",
"line_start" => 10,
"line_end" => 15,
"severity" => "high",
"title" => "Unsanitized input reaches interpolated query (1)",
"description" => "String-built SQL executed with request parameters.",
"reproduction" => "1. Check out the pinned commit\n2. Run the payload",
"affected_versions" => ">= 1.0, < 2.0",
"cwe" => "CWE-89",
"cve" => "CVE-2026-12345"
}
]
})
end
defp publish_scan(scan, visibility) do
scan = confirmation_fixture(scan, reviewer_account_fixture())
scan = confirmation_fixture(scan, reviewer_account_fixture())
scope = Tarakan.Accounts.Scope.for_account(moderator_account_fixture())
if visibility == "public" do
scan.repository
|> Tarakan.Repositories.Repository.participation_changeset(%{
participation_mode: "maintainer_verified"
})
|> Tarakan.Repo.update!()
end
{:ok, scan} =
Tarakan.Scans.accept_scan(scope, scan, %{
"moderation_reason" => "evidence_reviewed",
"moderation_notes" =>
"Two independent reviewers supplied reproducible evidence for the pinned commit."
})
{:ok, scan} =
Tarakan.Scans.update_visibility(scope, scan, visibility, %{
"moderation_reason" => "disclosure_reviewed",
"moderation_notes" =>
"Disclosure was separately reviewed for scope, secrets, and personal data.",
"sensitive_data_reviewed" => "true"
})
scan
end
end

View file

@ -0,0 +1,153 @@
defmodule TarakanWeb.API.FindingSignalsApiTest do
@moduledoc """
The three worker submission endpoints that had no HTTP surface until now:
calibrated severity, code embeddings, and cluster detectors.
"""
use TarakanWeb.ConnCase, async: true
import Ecto.Query, only: [from: 2]
alias Tarakan.Accounts.ApiCredentials
alias Tarakan.Repo
alias Tarakan.Scans.CanonicalFinding
setup %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
findings =
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => "lib/vulnerable.ex",
"severity" => "critical",
"title" => "Command injection #{System.unique_integer([:positive])}",
"description" => "User input reaches System.cmd without escaping."
}
]
})
scan_fixture(repository, submitter, %{"findings_json" => findings})
finding = Repo.one!(from f in CanonicalFinding, where: f.repository_id == ^repository.id)
reviewer = reviewer_account_fixture()
{:ok, token, _cred} =
ApiCredentials.create(reviewer, %{
name: "signals",
scopes: ["reviews:read", "reviews:verify"]
})
%{
conn: put_req_header(conn, "authorization", "Bearer #{token}"),
anon: build_conn(),
repository: repository,
finding: finding
}
end
defp signal_path(repository, finding, suffix) do
"/api/github.com/#{repository.owner}/#{repository.name}/findings/#{finding.public_id}/#{suffix}"
end
describe "POST .../severity" do
test "stores a rescore beside the submitter's claim", ctx do
conn =
post(ctx.conn, signal_path(ctx.repository, ctx.finding, "severity"), %{
"severity" => "low",
"rubric" => "rubric-v1"
})
assert %{"calibrated_severity" => "low"} = json_response(conn, 200)
assert Repo.get!(CanonicalFinding, ctx.finding.id).severity == "critical"
end
test "rejects a severity outside the scale", ctx do
conn =
post(ctx.conn, signal_path(ctx.repository, ctx.finding, "severity"), %{
"severity" => "catastrophic",
"rubric" => "rubric-v1"
})
assert %{"errors" => %{"calibrated_severity" => _}} = json_response(conn, 422)
end
end
describe "POST .../embedding" do
test "stores the vector and assigns a cluster", ctx do
conn =
post(ctx.conn, signal_path(ctx.repository, ctx.finding, "embedding"), %{
"embedding" => [0.1, 0.9, 0.2],
"embedding_model" => "test-embed-v1"
})
assert %{"code_pattern_key" => key} = json_response(conn, 200)
assert key =~ ~r/^code:/
end
test "rejects an all-zero vector, which would match everything", ctx do
conn =
post(ctx.conn, signal_path(ctx.repository, ctx.finding, "embedding"), %{
"embedding" => [0.0, 0.0, 0.0],
"embedding_model" => "test-embed-v1"
})
assert %{"errors" => %{"embedding" => _}} = json_response(conn, 422)
end
end
describe "POST /api/patterns/:key/rule" do
@rule """
rules:
- id: tarakan-cmd-injection
message: user input reaches System.cmd
severity: ERROR
languages: [elixir]
patterns:
- pattern: System.cmd($C, $A)
"""
test "accepts a validated detector and marks it servable", ctx do
conn =
post(ctx.conn, "/api/patterns/code:abc/rule", %{
"rule_yaml" => @rule,
"language" => "elixir",
"checked_count" => 3,
"matched_count" => 2,
"matched_finding_ids" => [Ecto.UUID.generate(), Ecto.UUID.generate()]
})
assert %{"servable" => true, "matched_count" => 2} = json_response(conn, 201)
end
test "a detector that matched nothing is stored but not servable", ctx do
conn =
post(ctx.conn, "/api/patterns/code:abc/rule", %{
"rule_yaml" => @rule,
"checked_count" => 3,
"matched_count" => 0,
"matched_finding_ids" => []
})
assert %{"servable" => false, "validated_at" => nil} = json_response(conn, 201)
end
test "rejects a match count with no receipts", ctx do
conn =
post(ctx.conn, "/api/patterns/code:abc/rule", %{
"rule_yaml" => @rule,
"checked_count" => 3,
"matched_count" => 2,
"matched_finding_ids" => []
})
assert %{"errors" => %{"matched_finding_ids" => _}} = json_response(conn, 422)
end
test "anonymous submissions are refused", ctx do
conn = post(ctx.anon, "/api/patterns/code:abc/rule", %{"rule_yaml" => @rule})
assert json_response(conn, 401)
end
end
end

View file

@ -0,0 +1,137 @@
defmodule TarakanWeb.API.InfestationControllerTest do
use TarakanWeb.ConnCase, async: true
import Ecto.Query, only: [from: 2]
alias Tarakan.FindingMemory
setup do
submitter = github_account_fixture()
other = github_account_fixture()
repo_a = listed_github_repository_fixture(submitter)
{:ok, repo_b} = Tarakan.Repositories.register_github_repository("acme/widget", other)
repo_b = listed_repository_fixture(repo_b)
title = "API infestation sample #{System.unique_integer([:positive])}"
findings = fn path ->
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => path,
"line_start" => 1,
"line_end" => 2,
"severity" => "high",
"title" => title,
"description" => "Shared issue class for the patterns API test."
}
]
})
end
scan_fixture(repo_a, submitter, %{"findings_json" => findings.("lib/a.ex")})
scan_fixture(repo_b, other, %{"findings_json" => findings.("src/b.rs")})
%{pattern_key: FindingMemory.pattern_key(title), title: title}
end
test "lists patterns", %{conn: conn, pattern_key: pattern_key} do
conn = get(conn, ~p"/api/infestations")
assert %{"patterns" => patterns} = json_response(conn, 200)
assert pattern = Enum.find(patterns, &(&1["pattern_key"] == pattern_key))
assert pattern["repo_count"] >= 2
assert pattern["instance_count"] >= 2
assert pattern["record_url"] =~ "/infestations/#{pattern_key}"
end
test "whitelists query params", %{conn: conn, pattern_key: pattern_key} do
conn = get(conn, ~p"/api/infestations?days=13&min_repos=0&limit=5000")
assert %{"patterns" => _} = json_response(conn, 200)
conn = get(conn, ~p"/api/infestations?days=7&min_repos=2&limit=10")
assert %{"patterns" => patterns} = json_response(conn, 200)
assert Enum.any?(patterns, &(&1["pattern_key"] == pattern_key))
end
test "shows a pattern with its first page of instances", %{
conn: conn,
pattern_key: pattern_key,
title: title
} do
conn = get(conn, ~p"/api/infestations/#{pattern_key}")
assert %{"pattern" => pattern, "instances" => instances} = json_response(conn, 200)
assert pattern["pattern_key"] == pattern_key
assert pattern["title"] =~ title
assert length(instances) >= 2
assert Enum.any?(instances, &(&1["repository"]["owner"] == "openai"))
assert Enum.any?(instances, &(&1["repository"]["owner"] == "acme"))
end
test "404s for an unknown pattern", %{conn: conn} do
conn = get(conn, ~p"/api/infestations/no-such-pattern")
assert json_response(conn, 404)["error"] =~ "not found"
end
describe "vaccine packs" do
alias Tarakan.Accounts.Scope
alias Tarakan.FindingSignals
alias Tarakan.Repo
alias Tarakan.Scans.CanonicalFinding
# The endpoint must refuse to invent a detector. It used to always return
# one, and the one it returned matched nothing.
test "404s while nobody has written a validated detector", %{
conn: conn,
pattern_key: pattern_key
} do
conn = get(conn, ~p"/api/infestations/#{pattern_key}/vaccine.yaml")
assert %{"error" => error} = json_response(conn, 404)
assert error =~ "no validated detector"
end
test "serves the validated rule once one exists", %{conn: conn, pattern_key: pattern_key} do
# Put this infestation's findings into one code cluster.
cluster = "code:vaccinetest"
Repo.all(from f in CanonicalFinding, where: f.pattern_key == ^pattern_key)
|> Enum.each(fn finding ->
finding
|> CanonicalFinding.embedding_changeset(%{code_pattern_key: cluster})
|> Repo.update!()
end)
scope = Scope.for_account(reviewer_account_fixture())
{:ok, _rule} =
FindingSignals.put_rule(scope, cluster, %{
engine: "semgrep",
language: "elixir",
rule_yaml: """
rules:
- id: tarakan-real-detector
message: Shared issue class
severity: ERROR
languages: [elixir]
patterns:
- pattern: System.cmd($C, $A)
""",
checked_count: 2,
matched_count: 2,
matched_finding_ids: [Ecto.UUID.generate(), Ecto.UUID.generate()]
})
conn = get(conn, ~p"/api/infestations/#{pattern_key}/vaccine.yaml")
assert body = response(conn, 200)
assert get_resp_header(conn, "content-type") |> hd() =~ "application/x-yaml"
assert body =~ "tarakan-real-detector"
assert body =~ "matched 2 of 2 known instances"
refute body =~ "tarakan-vaccine-placeholder"
end
end
end

View file

@ -0,0 +1,66 @@
defmodule TarakanWeb.API.LeaderboardControllerTest do
use TarakanWeb.ConnCase
setup do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_fixture(1)})
|> publish_scan("public")
%{submitter: submitter}
end
test "returns ranked rows", %{conn: conn, submitter: submitter} do
conn = get(conn, ~p"/api/leaderboard")
assert %{"leaderboard" => rows} = json_response(conn, 200)
assert row = Enum.find(rows, &(&1["handle"] == submitter.handle))
assert row["rank"] == 1
assert row["reputation"]["total"] > 0
assert is_map(row["stats"])
assert row["slashed_stakes"] == 0
assert row["profile_url"] == TarakanWeb.Endpoint.url() <> "/" <> submitter.handle
end
test "whitelists sort, severity, and window params", %{conn: conn} do
conn = get(conn, ~p"/api/leaderboard?sort=reviews&severity=high&window=7")
assert %{"leaderboard" => _} = json_response(conn, 200)
conn = get(conn, ~p"/api/leaderboard?sort=bogus&severity=bogus&window=bogus")
assert %{"leaderboard" => _} = json_response(conn, 200)
end
defp publish_scan(scan, visibility) do
scan = confirmation_fixture(scan, reviewer_account_fixture())
scan = confirmation_fixture(scan, reviewer_account_fixture())
scope = Tarakan.Accounts.Scope.for_account(moderator_account_fixture())
if visibility == "public" do
scan.repository
|> Tarakan.Repositories.Repository.participation_changeset(%{
participation_mode: "maintainer_verified"
})
|> Tarakan.Repo.update!()
end
{:ok, scan} =
Tarakan.Scans.accept_scan(scope, scan, %{
"moderation_reason" => "evidence_reviewed",
"moderation_notes" =>
"Two independent reviewers supplied reproducible evidence for the pinned commit."
})
{:ok, scan} =
Tarakan.Scans.update_visibility(scope, scan, visibility, %{
"moderation_reason" => "disclosure_reviewed",
"moderation_notes" =>
"Disclosure was separately reviewed for scope, secrets, and personal data.",
"sensitive_data_reviewed" => "true"
})
scan
end
end

View file

@ -0,0 +1,88 @@
defmodule TarakanWeb.API.RepositoryControllerTest do
use TarakanWeb.ConnCase, async: true
alias Tarakan.Accounts.ApiCredentials
alias Tarakan.Repositories
setup %{conn: conn} do
account = github_account_fixture()
token = api_token(account)
%{conn: conn, account: account, token: token}
end
defp authed(conn, token), do: put_req_header(conn, "authorization", "Bearer #{token}")
defp api_token(account) do
{:ok, token, _credential} =
ApiCredentials.create(account, %{
name: "registry importer",
scopes: ["findings:submit"]
})
token
end
test "rejects registration without a token", %{conn: conn} do
conn = post(conn, ~p"/api/repositories", %{"url" => "openai/codex"})
assert json_response(conn, 401)["error"] =~ "API token"
end
test "registers a public repository by owner/name", %{conn: conn, token: token} do
conn = conn |> authed(token) |> post(~p"/api/repositories", %{"url" => "openai/codex"})
assert %{"repository" => repo} = json_response(conn, 200)
assert repo["owner"] == "openai"
assert repo["name"] == "codex"
assert repo["host"] == "github.com"
assert repo["record_url"] =~ "/github.com/openai/codex"
end
test "is idempotent on re-register", %{conn: conn, token: token, account: account} do
{:ok, first} = Repositories.register_github_repository("openai/codex", account)
conn = conn |> authed(token) |> post(~p"/api/repositories", %{"url" => "openai/codex"})
assert %{"repository" => repo} = json_response(conn, 200)
assert repo["owner"] == first.owner
assert repo["name"] == first.name
end
test "requires a url", %{conn: conn, token: token} do
conn = conn |> authed(token) |> post(~p"/api/repositories", %{})
assert json_response(conn, 422)["errors"]["url"] == ["is required"]
end
test "lists reviewable repositories", %{conn: conn, token: token, account: account} do
{:ok, _repo} = Repositories.register_github_repository("openai/codex", account)
conn = conn |> authed(token) |> get(~p"/api/repositories?status=unscanned")
assert %{"repositories" => repos} = json_response(conn, 200)
assert Enum.any?(repos, &(&1["owner"] == "openai" and &1["name"] == "codex"))
end
test "admin credentials are not registration rate limited", %{conn: conn} do
admin =
github_account_fixture()
|> then(fn account ->
account
|> Tarakan.Accounts.Account.authorization_changeset(%{
state: "active",
platform_role: "admin",
trust_tier: "reviewer"
})
|> Tarakan.Repo.update!()
end)
token = api_token(admin)
# Well above the normal mutation (20) and repository_fetch (10) windows.
for _ <- 1..35 do
conn =
conn
|> recycle()
|> authed(token)
|> post(~p"/api/repositories", %{"url" => "openai/codex"})
assert json_response(conn, 200)["repository"]["name"] == "codex"
end
end
end

View file

@ -0,0 +1,548 @@
defmodule TarakanWeb.API.ScanControllerTest do
use TarakanWeb.ConnCase, async: true
alias Tarakan.Accounts.ApiCredentials
alias Tarakan.Accounts.Scope
alias Tarakan.Repositories
alias Tarakan.Repositories.Repository
alias Tarakan.Repo
alias Tarakan.Scans
setup %{conn: conn} do
account = github_account_fixture()
repository = github_repository_fixture(account)
token = api_token(account)
%{conn: conn, account: account, repository: repository, token: token}
end
defp authed(conn, token), do: put_req_header(conn, "authorization", "Bearer #{token}")
defp api_token(account) do
{:ok, token, _credential} =
ApiCredentials.create(account, %{
name: "Scan submitter",
scopes: ["findings:submit"]
})
token
end
defp scan_body(overrides \\ %{}) do
Map.merge(
%{
"commit_sha" => random_commit_sha(),
"model" => "claude-sonnet-5",
"prompt_version" => "tarakan-baseline/v1",
"run_id" => "api-run-#{System.unique_integer([:positive, :monotonic])}",
"document" => %{"tarakan_scan_format" => 1, "findings" => []}
},
overrides
)
end
test "rejects requests without a token", %{conn: conn} do
conn = post(conn, ~p"/api/github.com/openai/codex/reports", scan_body())
assert json_response(conn, 401)["error"] =~ "API token"
end
test "rejects requests with an invalid or revoked token", %{conn: conn, account: account} do
conn1 =
conn |> authed("garbage") |> post(~p"/api/github.com/openai/codex/reports", scan_body())
assert json_response(conn1, 401)
old_token = api_token(account)
[credential | _rest] = ApiCredentials.list(account)
{:ok, _credential} = ApiCredentials.revoke(account, credential.id)
conn2 =
conn |> authed(old_token) |> post(~p"/api/github.com/openai/codex/reports", scan_body())
assert json_response(conn2, 401)
end
test "404s for a repository not in the registry", %{conn: conn, token: token} do
conn = conn |> authed(token) |> post(~p"/api/github.com/unknown/repo/reports", scan_body())
assert json_response(conn, 404)["error"] =~ "not registered"
end
test "does not disclose a quarantined repository to an unrelated credential", %{
conn: conn,
repository: repository
} do
_contained =
repository
|> Repository.listing_changeset(%{listing_status: "quarantined"})
|> Repo.update!()
outsider_token = api_token(account_fixture())
conn =
conn
|> authed(outsider_token)
|> post(~p"/api/github.com/openai/codex/reports", scan_body())
assert json_response(conn, 404)["error"] =~ "not registered"
end
test "records a clean scan", %{conn: conn, token: token} do
conn = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", scan_body())
response = json_response(conn, 201)
assert response["findings_count"] == 0
assert response["verified"] == false
assert response["review_status"] == "quarantined"
assert response["visibility"] == "public"
assert response["provenance_attestation"] == "self_reported"
assert response["repository"] == "openai/codex"
assert response["record_url"] =~ "/github.com/openai/codex"
repository = Repositories.get_github_repository("openai", "codex")
assert repository.status == "reviewed"
assert repository.scan_count == 1
end
test "records a scan with findings", %{conn: conn, token: token} do
document = Jason.decode!(findings_json_fixture(2))
body = scan_body(%{"document" => document, "notes" => "run #7 of the nightly sweep"})
conn = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
response = json_response(conn, 201)
assert response["findings_count"] == 2
assert response["kind"] == "report"
assert response["disclosed"] == true
assert is_list(response["findings"])
assert length(response["findings"]) == 2
assert hd(response["findings"])["url"] =~ "/findings/"
repository = Repositories.get_github_repository("openai", "codex")
assert repository.status == "findings"
assert repository.open_findings_count == 2
end
test "mass report path works without a job claim", %{conn: conn, token: token} do
document = Jason.decode!(findings_json_fixture(1))
body = scan_body(%{"document" => document, "provenance" => "agent"})
conn =
conn
|> authed(token)
|> post(~p"/api/github.com/openai/codex/reports", body)
response = json_response(conn, 201)
assert response["kind"] == "report"
assert response["visibility"] == "public"
assert response["findings_count"] == 1
assert hd(response["findings"])["public_id"]
end
test "cannot self-accept or self-publish through submission attributes", %{
conn: conn,
token: token
} do
body =
scan_body(%{
"review_status" => "accepted",
"visibility" => "public",
"verified_at" => DateTime.utc_now()
})
conn = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
response = json_response(conn, 201)
assert response["review_status"] == "quarantined"
assert response["visibility"] == "public"
assert response["verified"] == false
end
test "records a human-authored review without model metadata", %{conn: conn, token: token} do
body = %{
"commit_sha" => random_commit_sha(),
"provenance" => "human",
"review_kind" => "business_logic",
"notes" => "Manually traced organization ownership transfer.",
"document" => Jason.decode!(findings_json_fixture(1))
}
conn = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
response = json_response(conn, 201)
assert response["provenance"] == "human"
assert response["review_kind"] == "business_logic"
assert response["model"] == nil
assert response["prompt_version"] == nil
assert response["findings_count"] == 1
end
test "requires the scan document", %{conn: conn, token: token} do
body = Map.delete(scan_body(), "document")
conn1 = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
assert %{"document" => [message]} = json_response(conn1, 422)["errors"]
assert message =~ "required"
conn2 =
conn
|> authed(token)
|> post(~p"/api/github.com/openai/codex/reports", scan_body(%{"document" => "[]"}))
assert json_response(conn2, 422)["errors"]["document"]
end
test "rejects an invalid document with the parser's message", %{conn: conn, token: token} do
body = scan_body(%{"document" => %{"tarakan_scan_format" => 2, "findings" => []}})
conn = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
assert %{"findings_json" => [message]} = json_response(conn, 422)["errors"]
assert message == "tarakan_scan_format must be 1"
end
test "rejects envelope validation errors", %{conn: conn, token: token} do
body = scan_body(%{"commit_sha" => "abc123", "model" => nil})
conn = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
errors = json_response(conn, 422)["errors"]
assert errors["commit_sha"] == ["must be a full 40-character commit SHA"]
assert errors["model"] == ["can't be blank"]
end
test "rejects a commit GitHub does not know", %{conn: conn, token: token} do
body = scan_body(%{"commit_sha" => "dead" <> String.duplicate("0", 36)})
conn = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
assert json_response(conn, 422)["errors"]["commit_sha"] == [
"commit not found in this repository on GitHub"
]
end
test "blocks retrying the same run id", %{conn: conn, token: token} do
body = scan_body()
conn1 = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
assert json_response(conn1, 201)
conn2 = conn |> authed(token) |> post(~p"/api/github.com/openai/codex/reports", body)
assert json_response(conn2, 422)["errors"]["run_id"] == [
"this agent run was already submitted"
]
end
describe "GET /reports and verdict" do
setup %{repository: repository, account: submitter} do
scan =
scan_fixture(repository, submitter, %{
"findings_json" => findings_json_fixture(1)
})
reviewer = reviewer_tier_account_fixture()
%{scan: scan, reviewer: reviewer, reviewer_token: reviews_token(reviewer)}
end
test "reviewer-tier reviews:read token sees restricted findings", %{
conn: conn,
reviewer_token: token,
scan: scan
} do
scan = restrict_scan(scan)
body =
conn
|> authed(token)
|> get(~p"/api/github.com/openai/codex/reports")
|> json_response(200)
entry = Enum.find(body["reports"], &(&1["id"] == scan.id))
assert entry["details_visible"]
assert length(entry["findings"]) == 1
assert hd(entry["findings"])["severity"]
end
test "returns compact canonical memory for reconciliation", %{
conn: conn,
token: token,
scan: scan
} do
body =
conn
|> authed(token)
|> get(~p"/api/github.com/openai/codex/memory?commit_sha=#{scan.commit_sha}")
|> json_response(200)
assert body["target_commit_sha"] == scan.commit_sha
assert [finding] = body["findings"]
assert finding["same_commit"]
assert finding["status"] == "open"
assert finding["detections_count"] == 1
assert finding["public_id"]
# Nothing disputed yet, but the corpus ships on every response so clients
# can rely on the key existing.
assert body["suppressions"]["repository"] == []
assert body["suppressions"]["patterns"] == []
assert body["suppressions"]["note"] =~ "non-bugs"
end
test "memory carries disputed findings as suppressions", %{
conn: conn,
token: token,
scan: scan
} do
[occurrence] = scan.findings
Tarakan.Repo.get!(Tarakan.Scans.CanonicalFinding, occurrence.canonical_finding_id)
|> Ecto.Changeset.change(status: "disputed", disputes_count: 2)
|> Tarakan.Repo.update!()
body =
conn
|> authed(token)
|> get(~p"/api/github.com/openai/codex/memory?commit_sha=#{scan.commit_sha}")
|> json_response(200)
assert [suppression] = body["suppressions"]["repository"]
assert suppression["scope"] == "repository"
assert suppression["fingerprint"]
assert suppression["file_path"]
end
test "records a check on one canonical finding", %{
conn: conn,
scan: scan
} do
token = reviews_token(moderator_account_fixture())
memory =
conn
|> authed(token)
|> get(~p"/api/github.com/openai/codex/memory?commit_sha=#{scan.commit_sha}")
|> json_response(200)
[finding] = memory["findings"]
body =
conn
|> recycle()
|> authed(token)
|> post(~p"/api/github.com/openai/codex/findings/#{finding["public_id"]}/check", %{
"commit_sha" => scan.commit_sha,
"verdict" => "confirmed",
"provenance" => "human",
"notes" => "Independently reproduced this individual finding at the pinned commit."
})
|> json_response(201)
assert body["status"] == "open"
assert body["confirmations_count"] == 1
end
test "a plain findings:submit token cannot see restricted findings", %{
conn: conn,
token: token,
scan: scan
} do
scan = restrict_scan(scan)
body =
conn
|> authed(token)
|> get(~p"/api/github.com/openai/codex/reports")
|> json_response(200)
# After a moderator takedown, the submitter's own restricted scan is not
# exposed to a non-reviewer token.
refute Enum.any?(body["reports"], &(&1["id"] == scan.id and &1["findings"] != []))
end
test "records a verdict with a proof-of-concept", %{
conn: conn,
reviewer_token: token,
scan: scan
} do
body =
conn
|> authed(token)
|> post(~p"/api/github.com/openai/codex/reports/#{scan.id}/check", %{
"verdict" => "confirmed",
"provenance" => "agent",
"notes" => "Reproduced the reported issue against the pinned commit source.",
"evidence" => "import test; test('repro', t => t.throws(() => vulnerable()))"
})
|> json_response(201)
assert length(body["confirmations"]) == 1
assert hd(body["confirmations"])["verdict"] == "confirmed"
end
test "the submitter cannot verify their own review", %{
conn: conn,
account: submitter,
scan: scan
} do
token = reviews_token(reviewer_tier(submitter))
conn =
conn
|> authed(token)
|> post(~p"/api/github.com/openai/codex/reports/#{scan.id}/check", %{
"verdict" => "confirmed",
"notes" => "Trying to verify my own submission, which must be refused."
})
assert json_response(conn, 409)["error"] =~ "submitter"
end
test "a read-only reviewer credential cannot record a verdict", %{conn: conn, scan: scan} do
# Reviewer-tier account (can see the scan) but the credential lacks
# reviews:verify, so recording a verdict is forbidden.
{:ok, read_only, _cred} =
ApiCredentials.create(reviewer_tier_account_fixture(), %{
name: "Read-only reviewer",
scopes: ["reviews:read"]
})
conn =
conn
|> authed(read_only)
|> post(~p"/api/github.com/openai/codex/reports/#{scan.id}/check", %{
"verdict" => "confirmed",
"notes" => "Has read access but no verify scope, so this must be denied."
})
assert json_response(conn, 403)["error"] =~ "not authorized"
end
test "a token that cannot see the review gets 404, not a leak", %{
conn: conn,
token: token,
scan: scan
} do
scan = restrict_scan(scan)
# A plain findings:submit token lacks read scope, so the restricted scan
# is invisible - the endpoint must 404 rather than reveal it exists.
conn =
conn
|> authed(token)
|> post(~p"/api/github.com/openai/codex/reports/#{scan.id}/check", %{
"verdict" => "confirmed",
"notes" => "This token cannot see the scan, so it must not verify it."
})
assert json_response(conn, 404)["error"] =~ "not found"
end
test "an unrelated credential cannot distinguish a quarantined repository", %{
conn: conn,
repository: repository,
scan: scan
} do
_contained =
repository
|> Repository.listing_changeset(%{listing_status: "quarantined"})
|> Repo.update!()
outsider_token = reviews_token(account_fixture())
conn1 =
conn
|> authed(outsider_token)
|> get(~p"/api/github.com/openai/codex/reports")
assert json_response(conn1, 404)["error"] =~ "not registered"
conn2 =
conn
|> recycle()
|> authed(outsider_token)
|> post(~p"/api/github.com/openai/codex/reports/#{scan.id}/check", %{
"verdict" => "confirmed",
"notes" => "Quarantined repositories must look exactly like unregistered ones."
})
assert json_response(conn2, 404)["error"] =~ "not registered"
end
test "the submitter keeps access to their quarantined repository", %{
conn: conn,
repository: repository,
account: submitter,
scan: scan
} do
_contained =
repository
|> Repository.listing_changeset(%{listing_status: "quarantined"})
|> Repo.update!()
{:ok, read_token, _credential} =
ApiCredentials.create(submitter, %{name: "Reader", scopes: ["reviews:read"]})
body =
conn
|> authed(read_token)
|> get(~p"/api/github.com/openai/codex/reports")
|> json_response(200)
assert Enum.any?(body["reports"], &(&1["id"] == scan.id))
end
test "an unrelated credential cannot list a pending repository's reviews", %{
conn: conn,
repository: repository
} do
_pending =
repository
|> Repository.listing_changeset(%{listing_status: "pending"})
|> Repo.update!()
outsider_token = reviews_token(account_fixture())
conn =
conn
|> authed(outsider_token)
|> get(~p"/api/github.com/openai/codex/reports")
assert json_response(conn, 404)["error"] =~ "not registered"
end
end
defp restrict_scan(scan) do
moderator_scope = Scope.for_account(moderator_account_fixture())
{:ok, scan} =
Scans.update_visibility(moderator_scope, scan, "restricted", %{
"moderation_reason" => "evidence_reviewed",
"moderation_notes" => "Moderator takedown recorded for this visibility boundary test."
})
scan
end
defp reviewer_tier_account_fixture do
account_fixture() |> reviewer_tier()
end
defp reviewer_tier(account) do
account
|> Tarakan.Accounts.Account.authorization_changeset(%{
state: "active",
platform_role: "member",
trust_tier: "reviewer"
})
|> Repo.update!()
end
defp reviews_token(account) do
{:ok, token, _credential} =
ApiCredentials.create(account, %{
name: "Verifier",
scopes: ["reviews:read", "reviews:verify"]
})
token
end
end

View file

@ -0,0 +1,601 @@
defmodule TarakanWeb.API.WorkControllerTest do
use TarakanWeb.ConnCase, async: true
alias Tarakan.Accounts
alias Tarakan.Accounts.ApiCredentials
alias Tarakan.Repositories.Repository
alias Tarakan.Repo
alias Tarakan.Work
setup %{conn: conn} do
creator = github_account_fixture()
repository = listed_github_repository_fixture(creator)
worker = account_fixture()
worker_token = client_token(worker)
creator_token = client_token(creator)
%{
conn: conn,
creator: creator,
creator_token: creator_token,
repository: repository,
worker: worker,
worker_token: worker_token
}
end
defp authed(conn, token), do: put_req_header(conn, "authorization", "Bearer #{token}")
defp client_token(account) do
{:ok, token, _credential} =
ApiCredentials.create(account, %{
name: "work controller test",
scopes: ["tasks:read", "tasks:claim", "contributions:write"]
})
token
end
test "all work queue endpoints require an API token", %{conn: conn} do
conn = get(conn, ~p"/api/github.com/openai/codex/jobs")
assert json_response(conn, 401)["error"] =~ "API token"
end
test "lists the global open jobs queue", %{
conn: conn,
creator: creator,
repository: repository,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn = conn |> authed(token) |> get(~p"/api/jobs")
assert %{"jobs" => jobs} = json_response(conn, 200)
assert Enum.any?(jobs, &(&1["id"] == task.id))
match = Enum.find(jobs, &(&1["id"] == task.id))
assert match["status"] == "open"
assert match["repository"]["owner"] == repository.owner
assert match["repository"]["name"] == repository.name
assert match["repository"]["primary_language"] == repository.primary_language
assert match["repository"]["stars_count"] == repository.stars_count
end
test "global jobs queue filters by language and min stars", %{
conn: conn,
creator: creator,
repository: repository,
worker_token: token
} do
task = review_task_fixture(repository, creator)
# Fixture repo is Rust with 42000 stars (GitHub stub).
conn =
conn
|> authed(token)
|> get(~p"/api/jobs", %{"language" => "Rust", "min_stars" => "1000"})
assert %{"jobs" => jobs} = json_response(conn, 200)
assert Enum.any?(jobs, &(&1["id"] == task.id))
conn =
build_conn()
|> authed(token)
|> get(~p"/api/jobs", %{"language" => "Elixir"})
assert %{"jobs" => jobs} = json_response(conn, 200)
refute Enum.any?(jobs, &(&1["id"] == task.id))
conn =
build_conn()
|> authed(token)
|> get(~p"/api/jobs", %{"min_stars" => "999999"})
assert %{"jobs" => jobs} = json_response(conn, 200)
refute Enum.any?(jobs, &(&1["id"] == task.id))
end
# A worker declares what it can run so it never claims a kind it does not
# implement and then holds the lease until it expires.
test "global jobs queue filters by the kinds a worker can run", %{
conn: conn,
creator: creator,
repository: repository,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn =
conn
|> authed(token)
|> get(~p"/api/jobs", %{"kinds" => "#{task.kind},refute_finding"})
assert %{"jobs" => jobs} = json_response(conn, 200)
assert Enum.any?(jobs, &(&1["id"] == task.id))
conn =
build_conn()
|> authed(token)
|> get(~p"/api/jobs", %{"kinds" => "reproduce_finding"})
assert %{"jobs" => jobs} = json_response(conn, 200)
refute Enum.any?(jobs, &(&1["id"] == task.id))
end
# An old client and a new server must still be able to talk, so a name the
# server does not know is dropped rather than erroring or filtering to empty.
test "unknown kind names are ignored rather than rejected", %{
conn: conn,
creator: creator,
repository: repository,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn =
conn
|> authed(token)
|> get(~p"/api/jobs", %{"kinds" => "not_a_real_kind"})
assert %{"jobs" => jobs} = json_response(conn, 200)
assert Enum.any?(jobs, &(&1["id"] == task.id))
end
test "global jobs queue includes the caller's active claims", %{
conn: conn,
creator: creator,
repository: repository,
worker: worker,
worker_token: token
} do
task =
review_task_fixture(repository, creator, %{"kind" => "code_review", "capability" => "agent"})
{:ok, claimed} = Work.claim_task(task, worker)
assert claimed.status == "claimed"
conn = conn |> authed(token) |> get(~p"/api/jobs")
assert %{"jobs" => jobs} = json_response(conn, 200)
match = Enum.find(jobs, &(&1["id"] == claimed.id))
assert match
assert match["status"] == "claimed"
assert match["lease"]["active"] == true
end
test "lists a repository's tasks with client-ready relationships", %{
conn: conn,
creator: creator,
repository: repository,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn = conn |> authed(token) |> get(~p"/api/github.com/openai/codex/jobs")
assert %{"jobs" => [response]} = json_response(conn, 200)
assert response["id"] == task.id
assert response["kind"] == "threat_model"
assert response["capability"] == "human"
assert response["status"] == "open"
assert response["visibility"] == "public"
assert response["commit_sha"] == task.commit_sha
assert response["commit_committed_at"] == "2026-07-01T12:00:00.000000Z"
assert response["repository"]["canonical_url"] == "https://github.com/openai/codex"
assert response["repository"]["host"] == "github.com"
assert response["repository"]["id"] == repository.id
assert response["repository"]["name"] == "codex"
assert response["repository"]["owner"] == "openai"
assert response["repository"]["participation_mode"] == repository.participation_mode
assert response["repository"]["record_url"] =~ "/github.com/openai/codex"
assert response["creator"]["id"] == creator.id
assert response["creator"]["handle"] == creator.handle
assert response["creator"] |> Map.keys() |> Enum.sort() == ["handle", "id"]
assert response["claimant"] == nil
assert response["lease"] == nil
assert response["contribution"] == nil
assert response["job_url"] =~ "/jobs/#{task.id}"
end
test "returns an empty list and 404s an unregistered repository", %{
conn: conn,
worker_token: token
} do
conn1 = conn |> authed(token) |> get(~p"/api/github.com/openai/codex/jobs")
assert json_response(conn1, 200) == %{"jobs" => []}
conn2 =
conn
|> recycle()
|> authed(token)
|> get(~p"/api/github.com/unknown/repository/jobs")
assert json_response(conn2, 404)["error"] =~ "not registered"
end
test "does not disclose a quarantined repository to an unrelated credential", %{
conn: conn,
repository: repository,
worker_token: token
} do
_contained =
repository
|> Repository.listing_changeset(%{listing_status: "quarantined"})
|> Repo.update!()
conn = conn |> authed(token) |> get(~p"/api/github.com/openai/codex/jobs")
assert json_response(conn, 404)["error"] =~ "not registered"
end
test "shows a task and returns 404 for missing or malformed ids", %{
conn: conn,
creator: creator,
repository: repository,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn1 = conn |> authed(token) |> get(~p"/api/jobs/#{task.id}")
assert json_response(conn1, 200)["id"] == task.id
conn2 = conn |> recycle() |> authed(token) |> get("/api/jobs/not-an-id")
assert json_response(conn2, 404)["error"] == "job not found"
conn3 = conn |> recycle() |> authed(token) |> get("/api/jobs/999999999")
assert json_response(conn3, 404)["error"] == "job not found"
end
test "claims a task and exposes the active lease", %{
conn: conn,
creator: creator,
repository: repository,
worker: worker,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn = conn |> authed(token) |> post(~p"/api/jobs/#{task.id}/claim")
response = json_response(conn, 200)
assert response["status"] == "claimed"
assert response["claimant"]["id"] == worker.id
assert response["lease"]["active"] == true
assert response["lease"]["claimed_at"]
assert response["lease"]["expires_at"]
original_expiry = response["lease"]["expires_at"]
conn =
conn
|> recycle()
|> authed(token)
|> post(~p"/api/jobs/#{task.id}/claim")
repeated = json_response(conn, 200)
assert repeated["claimant"]["id"] == worker.id
assert repeated["lease"]["expires_at"] == original_expiry
end
test "creators may claim their own jobs; active claims conflict for others", %{
conn: conn,
creator: creator,
creator_token: creator_token,
repository: repository,
worker_token: worker_token
} do
task = review_task_fixture(repository, creator)
# Solo/hosted workflow: job creators may claim and perform their own Jobs.
conn1 = conn |> authed(creator_token) |> post(~p"/api/jobs/#{task.id}/claim")
assert json_response(conn1, 200)["claimant"]["id"] == creator.id
conn_release =
conn |> recycle() |> authed(creator_token) |> delete(~p"/api/jobs/#{task.id}/claim")
assert json_response(conn_release, 200)["status"] == "open"
conn2 = conn |> recycle() |> authed(worker_token) |> post(~p"/api/jobs/#{task.id}/claim")
assert json_response(conn2, 200)
outsider = account_fixture()
outsider_token = client_token(outsider)
conn3 = conn |> recycle() |> authed(outsider_token) |> post(~p"/api/jobs/#{task.id}/claim")
assert json_response(conn3, 409)["error"] =~ "active claim"
end
test "only the claimant can release a task", %{
conn: conn,
creator: creator,
repository: repository,
worker: worker,
worker_token: worker_token
} do
task = review_task_fixture(repository, creator)
{:ok, task} = Work.claim_task(task, worker)
outsider_token = client_token(account_fixture())
conn1 = conn |> authed(outsider_token) |> delete(~p"/api/jobs/#{task.id}/claim")
assert json_response(conn1, 403)["error"] =~ "current claimant"
conn2 =
conn
|> recycle()
|> authed(worker_token)
|> delete(~p"/api/jobs/#{task.id}/claim")
response = json_response(conn2, 200)
assert response["status"] == "open"
assert response["claimant"] == nil
assert response["lease"] == nil
end
test "claimant can renew an active lease", %{
conn: conn,
creator: creator,
repository: repository,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn = conn |> authed(token) |> post(~p"/api/jobs/#{task.id}/claim")
first = json_response(conn, 200)
conn =
conn
|> recycle()
|> authed(token)
|> post(~p"/api/jobs/#{task.id}/claim/renew")
renewed = json_response(conn, 200)
assert renewed["lease"]["active"]
assert renewed["lease"]["expires_at"] >= first["lease"]["expires_at"]
end
test "completion path submits a claimed task for independent review", %{
conn: conn,
creator: creator,
repository: repository,
worker: worker,
worker_token: token
} do
task = review_task_fixture(repository, creator)
{:ok, task} = Work.claim_task(task, worker)
body = %{
"provenance" => "hybrid",
"summary" => "The authorization boundary is enforced.",
"evidence" => "Reviewed both entry points and ran the focused regression test."
}
conn = conn |> authed(token) |> post(~p"/api/jobs/#{task.id}/complete", body)
response = json_response(conn, 200)
assert response["status"] == "submitted"
assert response["visibility"] == "public"
assert response["submitted_at"]
assert response["completed_at"] == nil
assert response["lease"]["active"] == false
assert response["contribution"] == %{
"contributor" => %{
"handle" => worker.handle,
"id" => worker.id
},
"evidence" => body["evidence"],
"id" => response["contribution"]["id"],
"version" => 1,
"provenance" => "hybrid",
"submitted_at" => response["contribution"]["submitted_at"],
"summary" => body["summary"]
}
conn2 =
conn
|> recycle()
|> authed(token)
|> delete(~p"/api/jobs/#{task.id}/claim")
assert json_response(conn2, 403)["error"] =~ "current claimant"
end
test "completion requires the active claimant and valid evidence metadata", %{
conn: conn,
creator: creator,
repository: repository,
worker: worker,
worker_token: token
} do
task = review_task_fixture(repository, creator)
conn1 =
conn
|> authed(token)
|> post(~p"/api/jobs/#{task.id}/complete", %{
"provenance" => "human",
"summary" => "Completed",
"evidence" => "Attempted submission without first holding the task's active claim."
})
assert json_response(conn1, 403)["error"] =~ "current claimant"
{:ok, _task} = Work.claim_task(task, worker)
conn2 =
conn
|> recycle()
|> authed(token)
|> post(~p"/api/jobs/#{task.id}/complete", %{
"provenance" => "unverifiable",
"summary" => ""
})
errors = json_response(conn2, 422)["errors"]
assert errors["provenance"] == ["is invalid"]
assert errors["summary"] == ["can't be blank"]
end
test "completion provenance must satisfy the requested capability", %{
conn: conn,
creator: creator,
repository: repository,
worker: worker,
worker_token: token
} do
task = review_task_fixture(repository, creator, %{"capability" => "hybrid"})
{:ok, _task} = Work.claim_task(task, worker)
conn =
conn
|> authed(token)
|> post(~p"/api/jobs/#{task.id}/complete", %{
"provenance" => "human",
"summary" => "Manual review completed.",
"evidence" => "Manually traced the requested paths and recorded reproducible notes."
})
assert json_response(conn, 422)["errors"]["provenance"] == [
"does not satisfy this task's required capability"
]
end
test "proposals are publicly listed and publishing is not exposed to client credentials", %{
conn: conn,
creator: creator,
repository: repository,
creator_token: creator_token,
worker_token: worker_token
} do
proposal = proposed_review_task_fixture(repository, creator)
conn1 =
conn
|> authed(worker_token)
|> get(~p"/api/github.com/openai/codex/jobs")
assert [listed] = json_response(conn1, 200)["jobs"]
assert listed["id"] == proposal.id
assert listed["status"] == "proposed"
assert listed["visibility"] == "public"
conn2 =
conn
|> recycle()
|> authed(creator_token)
|> get(~p"/api/jobs/#{proposal.id}")
assert json_response(conn2, 200)["status"] == "proposed"
moderator = moderator_account_fixture()
moderator_token = Accounts.create_account_api_token(moderator)
conn3 =
conn
|> recycle()
|> authed(moderator_token)
|> post("/api/jobs/#{proposal.id}/publish", %{
"reason" => "The task scope is safe, bounded, and useful to contributors."
})
assert response(conn3, 404) == "Not Found"
assert {:ok, open} =
Work.publish_task(proposal, moderator, %{
"reason" => "The task scope is safe, bounded, and useful to contributors."
})
assert open.status == "open"
end
test "acceptance is not exposed to client credentials", %{
conn: conn,
creator: creator,
repository: repository,
worker: worker,
worker_token: worker_token
} do
task = review_task_fixture(repository, creator)
{:ok, task} = Work.claim_task(task, worker)
{:ok, submitted} =
Work.submit_task(task, worker, %{
"provenance" => "human",
"summary" => "The requested boundary was independently traced.",
"evidence" => "Ran the negative authorization suite against both repository entry points."
})
conn1 =
conn
|> authed(worker_token)
|> post("/api/jobs/#{submitted.id}/accept", %{
"reason" => "I should not be allowed to approve my own contribution.",
"evidence" => "This evidence comes from the original contributor and is not independent."
})
assert response(conn1, 404) == "Not Found"
reviewer = moderator_account_fixture()
reviewer_token = Accounts.create_account_api_token(reviewer)
assert Work.get_visible_task(submitted.id, Tarakan.Accounts.Scope.for_account(reviewer))
conn2 =
conn
|> recycle()
|> authed(reviewer_token)
|> post("/api/jobs/#{submitted.id}/accept", %{
"reason" => "The result was independently reproduced at the pinned commit.",
"evidence" => "Checked out the pinned SHA and ran the documented negative-path tests."
})
assert response(conn2, 404) == "Not Found"
assert {:ok, accepted} =
Work.accept_task(submitted, reviewer, %{
"reason" => "The result was independently reproduced at the pinned commit.",
"evidence" =>
"Checked out the pinned SHA and ran the documented negative-path tests."
})
assert accepted.status == "accepted"
assert accepted.visibility == "public"
outsider = account_fixture()
outsider_token = Accounts.create_account_api_token(outsider)
conn3 =
conn
|> recycle()
|> authed(outsider_token)
|> get(~p"/api/jobs/#{accepted.id}")
response = json_response(conn3, 200)
assert response["status"] == "accepted"
assert response["visibility"] == "public"
assert response["contribution"]["summary"] =~ "boundary"
assert response["contribution"]["evidence"] =~ "negative authorization suite"
assert {:ok, redacted} =
Work.disclose_task(accepted, reviewer, "public_summary", %{
"reason" =>
"The redacted result is safe and useful without publishing raw evidence."
})
conn4 =
conn
|> recycle()
|> authed(outsider_token)
|> get(~p"/api/jobs/#{redacted.id}")
response = json_response(conn4, 200)
assert response["visibility"] == "public_summary"
assert response["contribution"]["summary"] =~ "boundary"
assert response["contribution"]["evidence"] == nil
assert response["decisions"] == []
assert response["disclosed_at"]
assert response["sensitive_data_reviewed"] == false
end
end

View file

@ -0,0 +1,71 @@
defmodule TarakanWeb.BadgeControllerTest do
use TarakanWeb.ConnCase, async: true
alias Tarakan.Repo
alias Tarakan.Scans.CanonicalFinding
defp fixed_finding_fixture(repository, days_to_fix) do
now = DateTime.utc_now()
%CanonicalFinding{}
|> Ecto.Changeset.change(%{
repository_id: repository.id,
fingerprint: "fp-#{System.unique_integer([:positive])}",
file_path: "lib/app.ex",
line_start: 1,
severity: "high",
title: "Finding",
description: "Body.",
status: "fixed",
first_seen_commit_sha: random_commit_sha(),
last_seen_commit_sha: random_commit_sha(),
fixed_commit_sha: random_commit_sha(),
verified_at: DateTime.add(now, -days_to_fix * 86_400, :second),
fixed_at: now,
inserted_at: now,
updated_at: now
})
|> Repo.insert!()
end
test "serves an SVG carrying the median fix time", %{conn: conn} do
repository = listed_github_repository_fixture()
fixed_finding_fixture(repository, 3)
conn = get(conn, ~p"/badges/github.com/#{repository.owner}/#{repository.name}")
assert response_content_type(conn, :svg) =~ "image/svg+xml"
body = response(conn, 200)
assert body =~ "<svg"
assert body =~ "security"
assert body =~ "3d median fix"
assert get_resp_header(conn, "cache-control") == ["public, max-age=900"]
end
test "resolves a hosted repository from its bare slug", %{conn: conn} do
repository = listed_hosted_repository_fixture()
conn = get(conn, ~p"/badges/#{repository.owner}/#{repository.name}")
assert response(conn, 200) =~ "no findings"
end
test "does not leak whether an unlisted repository exists", %{conn: conn} do
repository =
github_repository_fixture()
|> Tarakan.Repositories.Repository.listing_changeset(%{listing_status: "quarantined"})
|> Repo.update!()
quarantined =
get(conn, ~p"/badges/github.com/#{repository.owner}/#{repository.name}")
|> response(200)
missing =
get(conn, ~p"/badges/github.com/nobody/nothing")
|> response(200)
assert quarantined =~ "not listed"
assert quarantined == missing
end
end

View file

@ -0,0 +1,14 @@
defmodule TarakanWeb.ErrorHTMLTest do
use TarakanWeb.ConnCase, async: true
# Bring render_to_string/4 for testing custom views
import Phoenix.Template, only: [render_to_string: 4]
test "renders 404.html" do
assert render_to_string(TarakanWeb.ErrorHTML, "404", "html", []) == "Not Found"
end
test "renders 500.html" do
assert render_to_string(TarakanWeb.ErrorHTML, "500", "html", []) == "Internal Server Error"
end
end

View file

@ -0,0 +1,12 @@
defmodule TarakanWeb.ErrorJSONTest do
use TarakanWeb.ConnCase, async: true
test "renders 404" do
assert TarakanWeb.ErrorJSON.render("404.json", %{}) == %{errors: %{detail: "Not Found"}}
end
test "renders 500" do
assert TarakanWeb.ErrorJSON.render("500.json", %{}) ==
%{errors: %{detail: "Internal Server Error"}}
end
end

View file

@ -0,0 +1,143 @@
defmodule TarakanWeb.FeedControllerTest do
use TarakanWeb.ConnCase
alias Tarakan.FindingMemory
test "the findings feed is a well-formed Atom document with absolute entry links", %{
conn: conn
} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan =
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_fixture(1)})
|> publish_scan("public")
[finding] = scan.findings
base = TarakanWeb.Endpoint.url()
conn = get(conn, ~p"/feeds/findings.xml")
assert response_content_type(conn, :xml) =~ "application/atom+xml"
assert get_resp_header(conn, "cache-control") == ["public, max-age=300"]
body = response(conn, 200)
assert_well_formed(body)
assert body =~ ~s(<feed xmlns="http://www.w3.org/2005/Atom">)
assert body =~ ~s(<link rel="self" href="#{base}/feeds/findings.xml"/>)
assert body =~ "<id>#{base}/findings/#{finding.public_id}</id>"
assert body =~ ~s(<link href="#{base}/findings/#{finding.public_id}"/>)
assert body =~ finding.title
end
test "the findings feed excludes open and restricted findings", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
open_scan =
scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
restricted =
scan_fixture(repository, account_fixture(), %{"findings_json" => findings_json_fixture(1)})
{:ok, _restricted} =
Tarakan.Scans.update_visibility(
Tarakan.Accounts.Scope.for_account(moderator_account_fixture()),
restricted,
"restricted",
%{
"moderation_reason" => "takedown_review",
"moderation_notes" => "Restricted in this test to keep it out of the feed."
}
)
body = conn |> get(~p"/feeds/findings.xml") |> response(200)
for scan <- [open_scan, restricted], finding <- scan.findings do
refute body =~ to_string(finding.public_id)
end
end
test "the infestations feed is a well-formed Atom document with absolute entry links", %{
conn: conn
} do
submitter = github_account_fixture()
other = github_account_fixture()
repo_a = listed_github_repository_fixture(submitter)
{:ok, repo_b} = Tarakan.Repositories.register_github_repository("acme/widget", other)
repo_b = listed_repository_fixture(repo_b)
title = "Feed infestation sample #{System.unique_integer([:positive])}"
findings = fn path ->
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => path,
"severity" => "high",
"title" => title,
"description" => "Shared issue class for the patterns feed test."
}
]
})
end
scan_fixture(repo_a, submitter, %{"findings_json" => findings.("lib/a.ex")})
scan_fixture(repo_b, other, %{"findings_json" => findings.("src/b.rs")})
pattern_key = FindingMemory.pattern_key(title)
base = TarakanWeb.Endpoint.url()
conn = get(conn, ~p"/feeds/infestations.xml")
assert response_content_type(conn, :xml) =~ "application/atom+xml"
body = response(conn, 200)
assert_well_formed(body)
assert body =~ ~s(<link rel="self" href="#{base}/feeds/infestations.xml"/>)
assert body =~ "<id>#{base}/infestations/#{pattern_key}</id>"
assert body =~ title
end
defp assert_well_formed(xml) do
{document, rest} = :xmerl_scan.string(String.to_charlist(xml))
assert rest == []
assert {:xmlElement, :feed, :feed, _, _, _, _, _, _, _, _, _} = document
end
defp publish_scan(scan, visibility) do
scan = confirmation_fixture(scan, reviewer_account_fixture())
scan = confirmation_fixture(scan, reviewer_account_fixture())
scope = Tarakan.Accounts.Scope.for_account(moderator_account_fixture())
if visibility == "public" do
scan.repository
|> Tarakan.Repositories.Repository.participation_changeset(%{
participation_mode: "maintainer_verified"
})
|> Tarakan.Repo.update!()
end
{:ok, scan} =
Tarakan.Scans.accept_scan(scope, scan, %{
"moderation_reason" => "evidence_reviewed",
"moderation_notes" =>
"Two independent reviewers supplied reproducible evidence for the pinned commit."
})
{:ok, scan} =
Tarakan.Scans.update_visibility(scope, scan, visibility, %{
"moderation_reason" => "disclosure_reviewed",
"moderation_notes" =>
"Disclosure was separately reviewed for scope, secrets, and personal data.",
"sensitive_data_reviewed" => "true"
})
scan
end
end

View file

@ -0,0 +1,121 @@
defmodule TarakanWeb.GitHubAuthControllerTest do
use TarakanWeb.ConnCase
alias Tarakan.Accounts
test "starts GitHub authorization with state and PKCE", %{conn: conn} do
conn = get(conn, ~p"/auth/github?return_to=/")
location = redirected_to(conn, 302)
query = location |> URI.parse() |> Map.fetch!(:query) |> URI.decode_query()
assert String.starts_with?(location, "https://github.com/login/oauth/authorize?")
assert query["client_id"] == "test-client-id"
assert query["code_challenge_method"] == "S256"
assert query["code_challenge"]
assert query["state"] == get_session(conn, :github_oauth_state)
assert get_session(conn, :github_oauth_verifier)
end
test "creates a session after GitHub authorizes the user", %{conn: conn} do
authorization_conn = get(conn, ~p"/auth/github?return_to=/")
state = get_session(authorization_conn, :github_oauth_state)
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/github/callback?code=valid-code&state=#{state}")
assert redirected_to(callback_conn) == "/"
token = get_session(callback_conn, :account_token)
assert {account, _inserted_at} = Accounts.get_account_by_session_token(token)
assert account.handle == "tarakantester"
assert is_nil(account.display_name)
assert is_nil(account.email)
refute get_session(callback_conn, :github_oauth_state)
refute get_session(callback_conn, :github_oauth_verifier)
assert Tarakan.Repo.get_by!(Tarakan.Accounts.Identity,
account_id: account.id,
provider: "github"
)
end
test "rejects a callback with an invalid state", %{conn: conn} do
authorization_conn = get(conn, ~p"/auth/github")
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/github/callback?code=valid-code&state=wrong-state")
assert redirected_to(callback_conn) == "/"
refute get_session(callback_conn, :account_token)
end
test "links GitHub to the signed-in Tarakan account", %{conn: conn} do
account = account_fixture()
authorization_conn =
conn
|> log_in_account(account)
|> get(~p"/auth/github?return_to=/accounts/settings")
state = get_session(authorization_conn, :github_oauth_state)
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/github/callback?code=valid-code&state=#{state}")
assert redirected_to(callback_conn) == "/accounts/settings"
token = get_session(callback_conn, :account_token)
assert {linked_account, _inserted_at} = Accounts.get_account_by_session_token(token)
assert linked_account.id == account.id
assert Tarakan.Repo.get_by!(Tarakan.Accounts.Identity,
account_id: account.id,
provider: "github"
)
end
test "refuses to link an identity from a stale signed-in session", %{conn: conn} do
account = account_fixture()
stale_at = DateTime.add(DateTime.utc_now(:second), -9 * 60, :minute)
authorization_conn =
conn
|> log_in_account(account, token_authenticated_at: stale_at)
|> get(~p"/auth/github?return_to=/accounts/settings")
state = get_session(authorization_conn, :github_oauth_state)
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/github/callback?code=valid-code&state=#{state}")
assert redirected_to(callback_conn) == "/accounts/settings"
refute Tarakan.Repo.get_by(Tarakan.Accounts.Identity,
account_id: account.id,
provider: "github"
)
end
test "does not retain a malicious return path in the OAuth session" do
for return_to <- ["//attacker.example", "/\\attacker.example", "/%255cattacker.example"] do
query = URI.encode_query(%{"return_to" => return_to})
authorization_conn = get(build_conn(), "/auth/github?#{query}")
assert get_session(authorization_conn, :github_oauth_return_to) == "/"
end
end
test "signs the current user out", %{conn: conn} do
conn = conn |> log_in_account(account_fixture()) |> delete(~p"/accounts/log-out")
assert redirected_to(conn) == "/"
refute get_session(conn, :account_token)
end
end

View file

@ -0,0 +1,115 @@
defmodule TarakanWeb.GitLabAuthControllerTest do
use TarakanWeb.ConnCase
alias Tarakan.Accounts
test "starts GitLab authorization with state, PKCE, and read_user", %{conn: conn} do
conn = get(conn, ~p"/auth/gitlab?return_to=/")
location = redirected_to(conn, 302)
query = location |> URI.parse() |> Map.fetch!(:query) |> URI.decode_query()
assert String.starts_with?(location, "https://gitlab.com/oauth/authorize?")
assert query["client_id"] == "test-gitlab-client-id"
assert query["response_type"] == "code"
assert query["scope"] == "read_user"
assert query["code_challenge_method"] == "S256"
assert query["code_challenge"]
assert query["state"] == get_session(conn, :gitlab_oauth_state)
assert get_session(conn, :gitlab_oauth_verifier)
end
test "creates an account and session without native registration", %{conn: conn} do
authorization_conn = get(conn, ~p"/auth/gitlab?return_to=/")
state = get_session(authorization_conn, :gitlab_oauth_state)
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/gitlab/callback?code=valid-gitlab-code&state=#{state}")
assert redirected_to(callback_conn) == "/"
token = get_session(callback_conn, :account_token)
assert {account, _inserted_at} = Accounts.get_account_by_session_token(token)
assert account.handle == "gitlabsignal"
assert is_nil(account.display_name)
assert is_nil(account.email)
refute get_session(callback_conn, :gitlab_oauth_state)
refute get_session(callback_conn, :gitlab_oauth_verifier)
assert Tarakan.Repo.get_by!(Tarakan.Accounts.Identity,
account_id: account.id,
provider: "gitlab",
provider_uid: "24680"
)
end
test "rejects a callback with an invalid state", %{conn: conn} do
authorization_conn = get(conn, ~p"/auth/gitlab")
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/gitlab/callback?code=valid-gitlab-code&state=wrong-state")
assert redirected_to(callback_conn) == "/"
refute get_session(callback_conn, :account_token)
end
test "links GitLab to the signed-in Tarakan account", %{conn: conn} do
account = account_fixture()
authorization_conn =
conn
|> log_in_account(account)
|> get(~p"/auth/gitlab?return_to=/accounts/settings")
state = get_session(authorization_conn, :gitlab_oauth_state)
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/gitlab/callback?code=valid-gitlab-code&state=#{state}")
assert redirected_to(callback_conn) == "/accounts/settings"
token = get_session(callback_conn, :account_token)
assert {linked_account, _inserted_at} = Accounts.get_account_by_session_token(token)
assert linked_account.id == account.id
assert Tarakan.Repo.get_by!(Tarakan.Accounts.Identity,
account_id: account.id,
provider: "gitlab"
)
end
test "refuses to link an identity from a stale signed-in session", %{conn: conn} do
account = account_fixture()
stale_at = DateTime.add(DateTime.utc_now(:second), -9 * 60, :minute)
authorization_conn =
conn
|> log_in_account(account, token_authenticated_at: stale_at)
|> get(~p"/auth/gitlab?return_to=/accounts/settings")
state = get_session(authorization_conn, :gitlab_oauth_state)
callback_conn =
authorization_conn
|> recycle()
|> get(~p"/auth/gitlab/callback?code=valid-gitlab-code&state=#{state}")
assert redirected_to(callback_conn) == "/accounts/settings"
refute Tarakan.Repo.get_by(Tarakan.Accounts.Identity,
account_id: account.id,
provider: "gitlab"
)
end
test "does not retain an encoded authority return path in the OAuth session" do
query = URI.encode_query(%{"return_to" => "/%252f%252fattacker.example"})
authorization_conn = get(build_conn(), "/auth/gitlab?#{query}")
assert get_session(authorization_conn, :gitlab_oauth_return_to) == "/"
end
end

View file

@ -0,0 +1,15 @@
defmodule TarakanWeb.InfestationRedirectControllerTest do
use TarakanWeb.ConnCase, async: true
test "GET /patterns permanently redirects to /infestations", %{conn: conn} do
conn = get(conn, ~p"/patterns")
assert redirected_to(conn, 301) == ~p"/infestations"
end
test "GET /patterns/:pattern_key permanently redirects to /infestations/:pattern_key", %{
conn: conn
} do
conn = get(conn, ~p"/patterns/some-pattern-key")
assert redirected_to(conn, 301) == ~p"/infestations/some-pattern-key"
end
end

View file

@ -0,0 +1,138 @@
defmodule TarakanWeb.SEOControllerTest do
use TarakanWeb.ConnCase
test "robots.txt allows crawling and points at the sitemap", %{conn: conn} do
response = conn |> get(~p"/robots.txt") |> text_response(200)
assert response =~ "User-agent: *"
assert response =~ "Allow: /"
assert response =~ "Disallow: /*/code/"
assert response =~ "Sitemap: " <> TarakanWeb.Endpoint.url() <> "/sitemap.xml"
end
test "security.txt follows RFC 9116 with a fresh expiry", %{conn: conn} do
conn = get(conn, "/.well-known/security.txt")
assert response_content_type(conn, :text) =~ "text/plain"
response = response(conn, 200)
base = TarakanWeb.Endpoint.url()
assert response =~ "Contact: mailto:security@example.com"
assert response =~ "Preferred-Languages: en"
assert response =~ "Canonical: #{base}/.well-known/security.txt"
assert response =~ "Policy: #{base}/policies/disclosure"
assert [_, expires] = Regex.run(~r/^Expires: (.+)$/m, response)
assert {:ok, expires_at, _} = DateTime.from_iso8601(expires)
assert DateTime.diff(expires_at, DateTime.utc_now(), :day) in 360..366
end
test "the sitemap lists hubs, listed repositories, public findings, and open jobs", %{
conn: conn
} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan =
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_fixture(2)})
|> publish_scan("public")
response = conn |> get(~p"/sitemap.xml") |> response(200)
base = TarakanWeb.Endpoint.url()
assert response =~ ~s(<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">)
assert response =~ "<loc>#{base}/</loc>"
assert response =~ "<loc>#{base}/explore</loc>"
assert response =~ "<loc>#{base}/leaderboard</loc>"
assert response =~ "<loc>#{base}/jobs</loc>"
assert response =~ "<loc>#{base}/agents</loc>"
assert response =~ "<loc>#{base}/github.com/openai/codex/security</loc>"
for finding <- scan.findings do
assert response =~ "<loc>#{base}/findings/#{finding.public_id}</loc>"
end
end
test "the sitemap indexes fresh findings but not restricted or summary ones", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
fresh = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
restricted =
scan_fixture(repository, account_fixture(), %{"findings_json" => findings_json_fixture(1)})
{:ok, _restricted} =
Tarakan.Scans.update_visibility(
Tarakan.Accounts.Scope.for_account(moderator_account_fixture()),
restricted,
"restricted",
%{
"moderation_reason" => "takedown_review",
"moderation_notes" =>
"Deliberately restricted in this test to keep it out of search discovery."
}
)
summary =
scan_fixture(repository, account_fixture(), %{"findings_json" => findings_json_fixture(1)})
publish_scan(summary, "public_summary")
response = conn |> get(~p"/sitemap.xml") |> response(200)
for finding <- fresh.findings do
assert response =~ "/findings/#{finding.public_id}"
end
for scan <- [restricted, summary], finding <- scan.findings do
refute response =~ to_string(finding.public_id)
end
end
test "quarantined repositories stay out of the sitemap", %{conn: conn} do
repository = github_repository_fixture()
repository
|> Tarakan.Repositories.Repository.listing_changeset(%{listing_status: "quarantined"})
|> Tarakan.Repo.update!()
response = conn |> get(~p"/sitemap.xml") |> response(200)
refute response =~ "openai/codex"
end
defp publish_scan(scan, visibility) do
scan = confirmation_fixture(scan, reviewer_account_fixture())
scan = confirmation_fixture(scan, reviewer_account_fixture())
scope = Tarakan.Accounts.Scope.for_account(moderator_account_fixture())
if visibility == "public" do
scan.repository
|> Tarakan.Repositories.Repository.participation_changeset(%{
participation_mode: "maintainer_verified"
})
|> Tarakan.Repo.update!()
end
{:ok, scan} =
Tarakan.Scans.accept_scan(scope, scan, %{
"moderation_reason" => "evidence_reviewed",
"moderation_notes" =>
"Two independent reviewers supplied reproducible evidence for the pinned commit."
})
{:ok, scan} =
Tarakan.Scans.update_visibility(scope, scan, visibility, %{
"moderation_reason" => "disclosure_reviewed",
"moderation_notes" =>
"Disclosure was separately reviewed for scope, secrets, and personal data.",
"sensitive_data_reviewed" => "true"
})
scan
end
end

View file

@ -0,0 +1,281 @@
defmodule TarakanWeb.Webhooks.StripeControllerTest do
use TarakanWeb.ConnCase, async: true
alias Tarakan.Accounts.Scope
alias Tarakan.Market.Bounty
alias Tarakan.Repo
@secret "whsec_test_secret"
defp fiat_bounty do
repository = listed_github_repository_fixture()
sponsor = active_account_fixture() |> fund_credits(1_000)
{bounty, _checkout_url} = fiat_bounty_fixture(Scope.for_account(sponsor), repository)
bounty
end
defp signed_post(conn, payload, opts \\ []) do
timestamp = Keyword.get(opts, :timestamp, System.system_time(:second))
secret = Keyword.get(opts, :secret, @secret)
signature =
:crypto.mac(:hmac, :sha256, secret, "#{timestamp}.#{payload}")
|> Base.encode16(case: :lower)
conn
|> put_req_header("content-type", "application/json")
|> put_req_header("stripe-signature", "t=#{timestamp},v1=#{signature}")
|> post(~p"/webhooks/stripe", payload)
end
defp checkout_completed_payload(session_id) do
Jason.encode!(%{
"id" => "evt_1",
"type" => "checkout.session.completed",
"data" => %{"object" => %{"id" => session_id, "payment_intent" => "pi_1"}}
})
end
test "a validly signed checkout.session.completed funds the bounty", %{conn: conn} do
bounty = fiat_bounty()
conn = signed_post(conn, checkout_completed_payload(bounty.stripe_checkout_session_id))
assert json_response(conn, 200) == %{"received" => true}
assert Repo.get!(Bounty, bounty.id).status == "open"
end
defp checkout_payload(session_id, type, extra) do
Jason.encode!(%{
"id" => "evt_1",
"type" => type,
"data" => %{"object" => Map.merge(%{"id" => session_id}, extra)}
})
end
test "a completed but unpaid session does not fund the bounty", %{conn: conn} do
bounty = fiat_bounty()
# Delayed-notification methods complete the session before the money
# arrives. Funding here would let work be claimed against nothing.
conn =
signed_post(
conn,
checkout_payload(
bounty.stripe_checkout_session_id,
"checkout.session.completed",
%{"payment_status" => "unpaid"}
)
)
assert json_response(conn, 200) == %{"received" => true}
assert Repo.get!(Bounty, bounty.id).status == "pending_funding"
end
test "the later async payment confirmation funds it", %{conn: conn} do
bounty = fiat_bounty()
conn =
signed_post(
conn,
checkout_payload(
bounty.stripe_checkout_session_id,
"checkout.session.completed",
%{"payment_status" => "unpaid"}
)
)
assert json_response(conn, 200) == %{"received" => true}
assert Repo.get!(Bounty, bounty.id).status == "pending_funding"
conn =
conn
|> recycle()
|> signed_post(
checkout_payload(
bounty.stripe_checkout_session_id,
"checkout.session.async_payment_succeeded",
%{}
)
)
assert json_response(conn, 200) == %{"received" => true}
assert Repo.get!(Bounty, bounty.id).status == "open"
end
test "a failed async payment leaves the bounty unfunded", %{conn: conn} do
bounty = fiat_bounty()
conn =
signed_post(
conn,
checkout_payload(
bounty.stripe_checkout_session_id,
"checkout.session.async_payment_failed",
%{}
)
)
assert json_response(conn, 200) == %{"received" => true}
assert Repo.get!(Bounty, bounty.id).status == "pending_funding"
end
test "an invalid signature is rejected", %{conn: conn} do
bounty = fiat_bounty()
conn =
signed_post(conn, checkout_completed_payload(bounty.stripe_checkout_session_id),
secret: "whsec_wrong"
)
assert json_response(conn, 400) == %{"error" => "invalid_signature"}
assert Repo.get!(Bounty, bounty.id).status == "pending_funding"
end
test "a stale timestamp is rejected", %{conn: conn} do
bounty = fiat_bounty()
conn =
signed_post(conn, checkout_completed_payload(bounty.stripe_checkout_session_id),
timestamp: System.system_time(:second) - 600
)
assert json_response(conn, 400) == %{"error" => "timestamp_outside_tolerance"}
assert Repo.get!(Bounty, bounty.id).status == "pending_funding"
end
test "a missing signature header is rejected", %{conn: conn} do
conn =
conn
|> put_req_header("content-type", "application/json")
|> post(~p"/webhooks/stripe", checkout_completed_payload("cs_test_whatever"))
assert json_response(conn, 400) == %{"error" => "missing_signature"}
end
test "a tampered body is rejected", %{conn: conn} do
timestamp = System.system_time(:second)
signature =
:crypto.mac(
:hmac,
:sha256,
@secret,
"#{timestamp}.{\"type\":\"checkout.session.completed\"}"
)
|> Base.encode16(case: :lower)
conn =
conn
|> put_req_header("content-type", "application/json")
|> put_req_header("stripe-signature", "t=#{timestamp},v1=#{signature}")
|> post(~p"/webhooks/stripe", checkout_completed_payload("cs_test_tampered"))
assert json_response(conn, 400) == %{"error" => "invalid_signature"}
end
test "unknown events are acknowledged and ignored", %{conn: conn} do
payload = Jason.encode!(%{"id" => "evt_2", "type" => "payment_intent.created", "data" => %{}})
conn = signed_post(conn, payload)
assert json_response(conn, 200) == %{"received" => true}
end
test "funding an unknown session still returns 200", %{conn: conn} do
conn = signed_post(conn, checkout_completed_payload("cs_test_unknown"))
assert json_response(conn, 200) == %{"received" => true}
end
describe "subscription events" do
defp subscription_event_payload(type, object) do
Jason.encode!(%{"id" => "evt_sub", "type" => type, "data" => %{"object" => object}})
end
defp checkout_subscription_payload(account) do
subscription_event_payload("checkout.session.completed", %{
"id" => "cs_test_sub",
"mode" => "subscription",
"client_reference_id" => Integer.to_string(account.id),
"customer" => "cus_webhook_1",
"subscription" => "sub_webhook_1",
"metadata" => %{"plan" => "team"}
})
end
test "a signed subscription checkout activates the account's subscription", %{conn: conn} do
account = account_fixture()
conn = signed_post(conn, checkout_subscription_payload(account))
assert json_response(conn, 200) == %{"received" => true}
subscription = Tarakan.Billing.subscription(account)
assert subscription.status == "active"
assert subscription.plan == "team"
assert subscription.stripe_subscription_id == "sub_webhook_1"
end
test "customer.subscription.updated syncs the subscription", %{conn: conn} do
account = account_fixture()
conn = signed_post(conn, checkout_subscription_payload(account))
assert json_response(conn, 200) == %{"received" => true}
payload =
subscription_event_payload("customer.subscription.updated", %{
"id" => "sub_webhook_1",
"status" => "active",
"current_period_end" => 1_900_000_000,
"items" => %{"data" => [%{"price" => %{"id" => "price_enterprise_test"}}]}
})
conn = signed_post(build_conn(), payload)
assert json_response(conn, 200) == %{"received" => true}
subscription = Tarakan.Billing.subscription(account)
assert subscription.plan == "enterprise"
assert DateTime.to_unix(subscription.current_period_end) == 1_900_000_000
end
test "invoice.payment_failed and customer.subscription.deleted move the status", %{
conn: conn
} do
account = account_fixture()
conn = signed_post(conn, checkout_subscription_payload(account))
assert json_response(conn, 200) == %{"received" => true}
failed =
subscription_event_payload("invoice.payment_failed", %{
"subscription" => "sub_webhook_1"
})
conn = signed_post(build_conn(), failed)
assert json_response(conn, 200) == %{"received" => true}
assert Tarakan.Billing.subscription(account).status == "past_due"
deleted =
subscription_event_payload("customer.subscription.deleted", %{
"id" => "sub_webhook_1"
})
conn = signed_post(build_conn(), deleted)
assert json_response(conn, 200) == %{"received" => true}
assert Tarakan.Billing.subscription(account).status == "canceled"
end
test "subscription events require a valid signature", %{conn: conn} do
account = account_fixture()
conn =
signed_post(conn, checkout_subscription_payload(account), secret: "whsec_wrong")
assert json_response(conn, 400) == %{"error" => "invalid_signature"}
assert Tarakan.Billing.subscription(account) == nil
end
end
end