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,125 @@
defmodule TarakanWeb.AccountLive.ConfirmationTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
import Tarakan.AccountsFixtures
alias Tarakan.Accounts
setup do
%{unconfirmed_account: unconfirmed_account_fixture(), confirmed_account: account_fixture()}
end
describe "Magic-link login" do
test "renders login page for a legacy unconfirmed account", %{
conn: conn,
unconfirmed_account: account
} do
token =
extract_account_token(fn url ->
Accounts.deliver_login_instructions(account, url)
end)
{:ok, _lv, html} = live(conn, ~p"/accounts/log-in/#{token}")
refute html =~ "Confirm"
assert html =~ "Log in"
end
test "renders login page for confirmed account", %{conn: conn, confirmed_account: account} do
token =
extract_account_token(fn url ->
Accounts.deliver_login_instructions(account, url)
end)
{:ok, _lv, html} = live(conn, ~p"/accounts/log-in/#{token}")
assert html =~ "Stay logged in on this device"
end
test "renders login page for already logged in account", %{
conn: conn,
confirmed_account: account
} do
conn = log_in_account(conn, account)
token =
extract_account_token(fn url ->
Accounts.deliver_login_instructions(account, url)
end)
{:ok, _lv, html} = live(conn, ~p"/accounts/log-in/#{token}")
assert html =~ "Log in"
end
test "logs in a legacy unconfirmed account with the given token once", %{
conn: conn,
unconfirmed_account: account
} do
token =
extract_account_token(fn url ->
Accounts.deliver_login_instructions(account, url)
end)
{:ok, lv, _html} = live(conn, ~p"/accounts/log-in/#{token}")
form = form(lv, "#login_form", %{"account" => %{"token" => token}})
render_submit(form)
conn = follow_trigger_action(form, conn)
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "Welcome back!"
assert Accounts.get_account!(account.id).confirmed_at
# we are logged in now
assert get_session(conn, :account_token)
assert redirected_to(conn) == ~p"/"
# log out, new conn
conn = build_conn()
{:ok, _lv, html} =
live(conn, ~p"/accounts/log-in/#{token}")
|> follow_redirect(conn, ~p"/accounts/log-in")
assert html =~ "Magic link is invalid or it has expired"
end
test "logs confirmed account in without changing confirmed_at", %{
conn: conn,
confirmed_account: account
} do
token =
extract_account_token(fn url ->
Accounts.deliver_login_instructions(account, url)
end)
{:ok, lv, _html} = live(conn, ~p"/accounts/log-in/#{token}")
form = form(lv, "#login_form", %{"account" => %{"token" => token}})
render_submit(form)
conn = follow_trigger_action(form, conn)
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
"Welcome back!"
assert Accounts.get_account!(account.id).confirmed_at == account.confirmed_at
# log out, new conn
conn = build_conn()
{:ok, _lv, html} =
live(conn, ~p"/accounts/log-in/#{token}")
|> follow_redirect(conn, ~p"/accounts/log-in")
assert html =~ "Magic link is invalid or it has expired"
end
test "raises error for invalid token", %{conn: conn} do
{:ok, _lv, html} =
live(conn, ~p"/accounts/log-in/invalid-token")
|> follow_redirect(conn, ~p"/accounts/log-in")
assert html =~ "Magic link is invalid or it has expired"
end
end
end

View file

@ -0,0 +1,134 @@
defmodule TarakanWeb.AccountLive.LoginTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
import Tarakan.AccountsFixtures
describe "login page" do
test "renders login page", %{conn: conn} do
{:ok, _lv, html} = live(conn, ~p"/accounts/log-in")
assert html =~ "Log in"
assert html =~ "Continue with GitHub"
assert html =~ "Continue with GitLab"
assert html =~ "Email me a login link"
end
test "preserves a protected route stored in the session", %{conn: conn} do
return_to = "/client/authorize/ABCD-EFGH"
{:ok, view, _html} =
conn
|> init_test_session(%{account_return_to: return_to})
|> live(~p"/accounts/log-in")
assert has_element?(
view,
"#login_form_password input[name='account[return_to]'][value='#{return_to}']"
)
assert has_element?(
view,
"#github-login-button[href='/auth/github?return_to=%2Fclient%2Fauthorize%2FABCD-EFGH']"
)
end
end
describe "account login - magic link" do
test "sends magic link email when account exists", %{conn: conn} do
account = account_fixture()
{:ok, lv, _html} = live(conn, ~p"/accounts/log-in")
{:ok, _lv, html} =
form(lv, "#login_form_magic", account: %{email: account.email})
|> render_submit()
|> follow_redirect(conn, ~p"/accounts/log-in")
assert html =~ "If your email is in our system"
assert Tarakan.Repo.get_by!(Tarakan.Accounts.AccountToken, account_id: account.id).context ==
"login"
end
test "does not disclose if account is registered", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/log-in")
{:ok, _lv, html} =
form(lv, "#login_form_magic", account: %{email: "idonotexist@example.com"})
|> render_submit()
|> follow_redirect(conn, ~p"/accounts/log-in")
assert html =~ "If your email is in our system"
end
end
describe "account login - password" do
test "redirects if account logs in with valid credentials", %{conn: conn} do
account = account_fixture() |> set_password()
{:ok, lv, _html} = live(conn, ~p"/accounts/log-in")
form =
form(lv, "#login_form_password",
account: %{
identifier: account.handle,
password: valid_account_password(),
remember_me: true
}
)
conn = submit_form(form, conn)
assert redirected_to(conn) == ~p"/"
end
test "redirects to login page with a flash error if credentials are invalid", %{
conn: conn
} do
{:ok, lv, _html} = live(conn, ~p"/accounts/log-in")
form =
form(lv, "#login_form_password",
account: %{identifier: "test@email.com", password: "123456"}
)
render_submit(form)
conn = follow_trigger_action(form, conn)
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"Invalid handle, email, or password"
assert redirected_to(conn) == ~p"/accounts/log-in"
end
end
describe "login navigation" do
test "github is the primary path for new users", %{conn: conn} do
{:ok, _lv, html} = live(conn, ~p"/accounts/log-in")
assert html =~ "One click. No password required."
assert html =~ ~s(id="github-login-button")
assert html =~ "Continue with GitHub"
end
end
describe "re-authentication (sudo mode)" do
setup %{conn: conn} do
account = account_fixture()
%{account: account, conn: log_in_account(conn, account)}
end
test "shows login page with email filled in", %{conn: conn, account: account} do
{:ok, _lv, html} = live(conn, ~p"/accounts/log-in")
assert html =~ "Confirm it"
assert html =~ "connect another host"
assert html =~ "Email me a login link"
assert html =~
~s(<input type="email" name="account[email]" id="login_form_magic_email" value="#{account.email}")
end
end
end

View file

@ -0,0 +1,109 @@
defmodule TarakanWeb.AccountLive.RegistrationTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
import Tarakan.AccountsFixtures
describe "Registration page" do
test "renders registration page", %{conn: conn} do
{:ok, _lv, html} = live(conn, ~p"/accounts/register")
assert html =~ "Join Tarakan"
assert html =~ "Log in"
end
test "redirects if already logged in", %{conn: conn} do
result =
conn
|> log_in_account(account_fixture())
|> live(~p"/accounts/register")
|> follow_redirect(conn, ~p"/")
assert {:ok, _conn} = result
end
test "renders errors for invalid data", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/register")
result =
lv
|> element("#registration_form")
|> render_change(account: %{"handle" => "valid-handle", "email" => "with spaces"})
assert result =~ "Join Tarakan"
assert result =~ "must have the @ sign and no spaces"
end
end
describe "register account" do
test "creates an unconfirmed account and logs in immediately", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/register")
email = unique_account_email()
form = form(lv, "#registration_form", account: valid_account_attributes(email: email))
render_submit(form)
login_form = form(lv, "#registration_login_form")
conn = follow_trigger_action(login_form, conn)
assert get_session(conn, :account_token)
assert redirected_to(conn) == ~p"/"
# The instant session does not confirm the email: only the emailed login
# link proves mailbox control.
assert %{confirmed_at: nil} = Tarakan.Accounts.get_account_by_email(email)
end
test "does not reveal that an email is already registered", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/register")
account = account_fixture(%{email: "test@email.com"})
{:ok, _lv, html} =
lv
|> form("#registration_form",
account: %{"handle" => unique_account_handle(), "email" => account.email}
)
|> render_submit()
|> follow_redirect(conn, ~p"/accounts/log-in")
assert html =~ "If an account matches those details, a sign-in link will arrive shortly."
refute html =~ "has already been taken"
refute html =~ account.email
end
test "does not reveal that a handle is already registered", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/register")
account = account_fixture()
email = unique_account_email()
{:ok, _lv, html} =
lv
|> form("#registration_form",
account: %{"handle" => account.handle, "email" => email}
)
|> render_submit()
|> follow_redirect(conn, ~p"/accounts/log-in")
assert html =~ "If an account matches those details, a sign-in link will arrive shortly."
refute html =~ "has already been taken"
refute Tarakan.Accounts.get_account_by_email(email)
end
end
describe "registration navigation" do
test "redirects to login page when the Log in button is clicked", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/register")
{:ok, _login_live, login_html} =
lv
|> element("main a", "Log in")
|> render_click()
|> follow_redirect(conn, ~p"/accounts/log-in")
assert login_html =~ "Log in"
end
end
end

View file

@ -0,0 +1,434 @@
defmodule TarakanWeb.AccountLive.SettingsTest do
use TarakanWeb.ConnCase, async: true
alias Tarakan.Accounts
import Phoenix.LiveViewTest
import Tarakan.AccountsFixtures
describe "Settings page" do
test "opens on the account panel", %{conn: conn} do
{:ok, view, html} =
conn
|> log_in_account(account_fixture())
|> live(~p"/accounts/settings")
assert html =~ "Save email"
assert html =~ "Save password"
assert html =~ "Connected code hosts"
assert html =~ "GitHub"
assert html =~ "GitLab"
assert has_element?(view, "#settings-tab-account[aria-current=page]")
refute has_element?(view, "#api-reference")
refute has_element?(view, "#ssh-key-form")
end
test "moves between panels from the rail", %{conn: conn} do
{:ok, view, _html} =
conn
|> log_in_account(account_fixture())
|> live(~p"/accounts/settings")
html =
view
|> element("#settings-tab-credentials")
|> render_click()
assert html =~ "Client credentials"
assert_patch(view, ~p"/accounts/settings/credentials")
assert has_element?(view, "#settings-tab-credentials[aria-current=page]")
refute has_element?(view, "#email_form")
view |> element("#settings-tab-ssh") |> render_click()
assert_patch(view, ~p"/accounts/settings/ssh-keys")
assert has_element?(view, "#ssh-key-form")
view |> element("#settings-tab-agents") |> render_click()
assert_patch(view, ~p"/accounts/settings/agents")
assert has_element?(view, "#settings-model-scoreboard", "None yet")
end
test "an unknown panel slug falls back to the account panel", %{conn: conn} do
{:ok, view, _html} =
conn
|> log_in_account(account_fixture())
|> live(~p"/accounts/settings/nonsense")
assert has_element?(view, "#email_form")
assert has_element?(view, "#settings-tab-account[aria-current=page]")
end
test "renders the API reference on the credentials panel", %{conn: conn} do
{:ok, view, html} =
conn
|> log_in_account(account_fixture())
|> live(~p"/accounts/settings/credentials")
assert has_element?(view, "#api-reference", "API reference")
assert has_element?(view, "#api-reference-base-url", "/api")
assert html =~ "/client-auth/exchange"
assert html =~ "/repositories"
assert html =~ "/jobs/:id/claim/renew"
assert html =~ "/:host/:owner/:name/reports"
end
test "marks an attached code-host identity as connected", %{conn: conn} do
{:ok, view, _html} =
conn
|> log_in_account(github_account_fixture())
|> live(~p"/accounts/settings")
assert has_element?(view, "#settings-github-identity", "Connected")
assert has_element?(view, "#settings-gitlab-identity", "Connect")
end
test "redirects if account is not logged in", %{conn: conn} do
assert {:error, redirect} = live(conn, ~p"/accounts/settings")
assert {:redirect, %{to: path, flash: flash}} = redirect
assert path == ~p"/accounts/log-in"
assert %{"error" => "You must log in to access this page."} = flash
end
test "generates and independently revokes a client credential", %{conn: conn} do
account = account_fixture()
{:ok, view, html} =
conn
|> log_in_account(account)
|> live(~p"/accounts/settings/credentials")
assert html =~ "Client credentials"
refute has_element?(view, "#api-token-value")
view
|> form("#api-credential-form", %{
"credential" => %{
"name" => "Task reader",
"scopes" => ["tasks:read"]
}
})
|> render_submit()
token =
view
|> element("#api-token-value")
|> render()
|> String.replace(~r/<[^>]+>/, "")
|> String.trim()
assert {:ok, fetched} = Accounts.fetch_account_by_api_token(token)
assert fetched.id == account.id
[credential] = Tarakan.Accounts.ApiCredentials.list(account)
assert credential.name == "Task reader"
assert credential.scopes == ["tasks:read"]
assert has_element?(view, "#api-credential-#{credential.id}")
view
|> element("#revoke-api-credential-#{credential.id}")
|> render_click()
assert :error = Accounts.fetch_account_by_api_token(token)
refute has_element?(view, "#revoke-api-credential-#{credential.id}")
end
test "can bind a least-privilege credential to one repository", %{conn: conn} do
account = github_account_fixture()
repository = github_repository_fixture(account)
{:ok, view, _html} =
conn
|> log_in_account(account)
|> live(~p"/accounts/settings/credentials")
view
|> form("#api-credential-form", %{
"credential" => %{
"name" => "Codex reader",
"repository" => "openai/codex",
"scopes" => ["tasks:read"]
}
})
|> render_submit()
token =
view
|> element("#api-token-value")
|> render()
|> String.replace(~r/<[^>]+>/, "")
|> String.trim()
assert {:ok, ^account, credential} =
Tarakan.Accounts.ApiCredentials.authenticate(token)
assert credential.repository_id == repository.id
assert credential.scopes == ["tasks:read"]
end
test "redirects if account is not in sudo mode", %{conn: conn} do
stale_at = DateTime.add(DateTime.utc_now(:second), -9 * 60, :minute)
{:ok, conn} =
conn
|> log_in_account(account_fixture(), token_authenticated_at: stale_at)
|> live(~p"/accounts/settings")
|> follow_redirect(conn, ~p"/accounts/log-in?return_to=%2Faccounts%2Fsettings")
assert conn.resp_body =~ "sign-in older than 2 hours for sensitive settings"
end
test "prompts unconfirmed accounts to confirm email instead of credential forms", %{
conn: conn
} do
conn = log_in_account(conn, unconfirmed_account_fixture())
{:ok, view, html} = live(conn, ~p"/accounts/settings")
assert has_element?(view, "#email-confirmation-required")
assert has_element?(view, "#settings-tab-account", "unconfirmed")
assert html =~ "Confirm your email to unlock credentials"
refute has_element?(view, "#password_form")
{:ok, view, _html} = live(conn, ~p"/accounts/settings/credentials")
refute has_element?(view, "#api-credential-form")
{:ok, view, _html} = live(conn, ~p"/accounts/settings/ssh-keys")
refute has_element?(view, "#ssh-key-form")
end
end
describe "SSH keys" do
@describetag :tmp_dir
defp generate_public_key(tmp_dir) do
path = Path.join(tmp_dir, "key-#{System.unique_integer([:positive])}")
{_output, 0} = System.cmd("ssh-keygen", ["-t", "ed25519", "-f", path, "-N", "", "-q"])
File.read!(path <> ".pub")
end
test "adds and removes a key", %{conn: conn, tmp_dir: tmp_dir} do
account = account_fixture()
{:ok, view, html} =
conn
|> log_in_account(account)
|> live(~p"/accounts/settings/ssh-keys")
assert html =~ "SSH keys"
view
|> form("#ssh-key-form",
ssh_key: %{name: "laptop", public_key: generate_public_key(tmp_dir)}
)
|> render_submit()
assert has_element?(view, "#ssh-key-list", "laptop")
assert has_element?(view, "#ssh-key-list", "SHA256:")
[key] = Tarakan.Accounts.SshKeys.list_for_account(account)
view
|> element("#delete-ssh-key-#{key.id}")
|> render_click()
refute has_element?(view, "#ssh-key-list")
assert Tarakan.Accounts.SshKeys.list_for_account(account) == []
end
test "rejects an invalid key inline", %{conn: conn} do
{:ok, view, _html} =
conn
|> log_in_account(account_fixture())
|> live(~p"/accounts/settings/ssh-keys")
html =
view
|> form("#ssh-key-form", ssh_key: %{name: "junk", public_key: "not a key"})
|> render_submit()
assert html =~ "is not a supported OpenSSH public key"
end
end
describe "update email form" do
setup %{conn: conn} do
account = account_fixture()
%{conn: log_in_account(conn, account), account: account}
end
test "updates the account email", %{conn: conn, account: account} do
new_email = unique_account_email()
{:ok, lv, _html} = live(conn, ~p"/accounts/settings")
result =
lv
|> form("#email_form", %{
"account" => %{"email" => new_email}
})
|> render_submit()
assert result =~ "A link to confirm your email"
assert Accounts.get_account_by_email(account.email)
end
test "renders errors with invalid data (phx-change)", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/settings")
result =
lv
|> element("#email_form")
|> render_change(%{
"action" => "update_email",
"account" => %{"email" => "with spaces"}
})
assert result =~ "Save email"
assert result =~ "must have the @ sign and no spaces"
end
test "renders errors with invalid data (phx-submit)", %{conn: conn, account: account} do
{:ok, lv, _html} = live(conn, ~p"/accounts/settings")
result =
lv
|> form("#email_form", %{
"account" => %{"email" => account.email}
})
|> render_submit()
assert result =~ "Save email"
assert result =~ "did not change"
end
end
describe "update password form" do
setup %{conn: conn} do
account = account_fixture()
%{conn: log_in_account(conn, account), account: account}
end
test "updates the account password", %{conn: conn, account: account} do
new_password = valid_account_password()
{:ok, lv, _html} = live(conn, ~p"/accounts/settings")
form =
form(lv, "#password_form", %{
"account" => %{
"password" => new_password,
"password_confirmation" => new_password
}
})
render_submit(form)
new_password_conn = follow_trigger_action(form, conn)
assert redirected_to(new_password_conn) == ~p"/accounts/settings"
assert get_session(new_password_conn, :account_token) != get_session(conn, :account_token)
assert Phoenix.Flash.get(new_password_conn.assigns.flash, :info) =~
"Password updated successfully"
assert Accounts.get_account_by_email_and_password(account.email, new_password)
end
test "renders errors with invalid data (phx-change)", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/settings")
result =
lv
|> element("#password_form")
|> render_change(%{
"account" => %{
"password" => "too short",
"password_confirmation" => "does not match"
}
})
assert result =~ "Save password"
assert result =~ "should be at least 15 character(s)"
assert result =~ "does not match password"
end
test "renders errors with invalid data (phx-submit)", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/accounts/settings")
result =
lv
|> form("#password_form", %{
"account" => %{
"password" => "too short",
"password_confirmation" => "does not match"
}
})
|> render_submit()
assert result =~ "Save password"
assert result =~ "should be at least 15 character(s)"
assert result =~ "does not match password"
end
end
describe "confirm email" do
setup %{conn: conn} do
account = account_fixture()
email = unique_account_email()
token =
extract_account_token(fn url ->
Accounts.deliver_account_update_email_instructions(
%{account | email: email},
account.email,
url
)
end)
%{conn: log_in_account(conn, account), token: token, email: email, account: account}
end
test "updates the account email once", %{
conn: conn,
account: account,
token: token,
email: email
} do
{:error, redirect} = live(conn, ~p"/accounts/settings/confirm-email/#{token}")
assert {:live_redirect, %{to: path, flash: flash}} = redirect
assert path == ~p"/accounts/settings"
assert %{"info" => message} = flash
assert message == "Email changed successfully."
refute Accounts.get_account_by_email(account.email)
assert Accounts.get_account_by_email(email)
# use confirm token again
{:error, redirect} = live(conn, ~p"/accounts/settings/confirm-email/#{token}")
assert {:live_redirect, %{to: path, flash: flash}} = redirect
assert path == ~p"/accounts/settings"
assert %{"error" => message} = flash
assert message == "Email change link is invalid or it has expired."
end
test "does not update email with invalid token", %{conn: conn, account: account} do
{:error, redirect} = live(conn, ~p"/accounts/settings/confirm-email/oops")
assert {:live_redirect, %{to: path, flash: flash}} = redirect
assert path == ~p"/accounts/settings"
assert %{"error" => message} = flash
assert message == "Email change link is invalid or it has expired."
assert Accounts.get_account_by_email(account.email)
end
test "redirects if account is not logged in", %{token: token} do
conn = build_conn()
{:error, redirect} = live(conn, ~p"/accounts/settings/confirm-email/#{token}")
assert {:redirect, %{to: path, flash: flash}} = redirect
assert path == ~p"/accounts/log-in"
assert %{"error" => message} = flash
assert message == "You must log in to access this page."
end
end
end

View file

@ -0,0 +1,134 @@
defmodule TarakanWeb.AdminLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.Accounts
alias Tarakan.Accounts.Account
alias Tarakan.Repo
setup %{conn: conn} do
admin =
account_fixture()
|> Account.authorization_changeset(%{
state: "active",
platform_role: "admin",
trust_tier: "reviewer"
})
|> Repo.update!()
%{admin: admin, conn: log_in_account(conn, admin)}
end
test "admin sees account summary, search, and management links", %{conn: conn} do
target = account_fixture(%{handle: "managed-account"})
{:ok, view, _html} = live(conn, ~p"/admin")
assert has_element?(view, "#admin-dashboard")
assert has_element?(view, "#admin-summary-admins")
assert has_element?(view, "#admin-account-filter")
assert has_element?(view, "#admin-account-#{target.id}-manage")
view
|> form("#admin-account-filter", filters: %{query: "managed-account"})
|> render_change()
assert has_element?(view, "#admin-account-#{target.id}-manage")
end
test "admin updates account standing, role, and trust tier", %{conn: conn} do
target = account_fixture()
{:ok, view, _html} = live(conn, ~p"/admin/accounts/#{target.id}")
assert has_element?(view, "#admin-account")
assert has_element?(view, "#admin-authorization-form")
view
|> form("#admin-authorization-form",
authorization: %{
state: "active",
platform_role: "moderator",
trust_tier: "reviewer"
}
)
|> render_submit()
updated = Accounts.get_account!(target.id)
assert updated.state == "active"
assert updated.platform_role == "moderator"
assert updated.trust_tier == "reviewer"
assert has_element?(view, "#admin-authorization-form")
end
test "ordinary members cannot open platform administration", %{conn: _admin_conn} do
member =
account_fixture() |> Account.authorization_changeset(%{state: "active"}) |> Repo.update!()
conn = log_in_account(build_conn(), member)
assert {:error, {:redirect, %{to: path, flash: flash}}} = live(conn, ~p"/admin")
assert path == ~p"/"
assert flash["error"] == "Administrator access is required."
end
test "last administrator cannot remove their own authority", %{conn: conn, admin: admin} do
{:ok, view, _html} = live(conn, ~p"/admin/accounts/#{admin.id}")
view
|> form("#admin-authorization-form",
authorization: %{
state: "active",
platform_role: "member",
trust_tier: "reviewer"
}
)
|> render_submit()
assert Accounts.get_account!(admin.id).platform_role == "admin"
assert has_element?(view, "#admin-authorization-form")
end
test "filtering requires a still-valid sudo session", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin")
expire_sudo_mode(view)
assert {:error, {:live_redirect, %{to: "/accounts/log-in?return_to=%2Fadmin"}}} =
view
|> form("#admin-account-filter", filters: %{query: "anything"})
|> render_change()
end
test "saving requires a still-valid sudo session", %{conn: conn} do
target = account_fixture()
{:ok, view, _html} = live(conn, ~p"/admin/accounts/#{target.id}")
expire_sudo_mode(view)
assert {:error,
{:live_redirect, %{to: "/accounts/log-in?return_to=%2Fadmin%2Faccounts%2F" <> _}}} =
view
|> form("#admin-authorization-form",
authorization: %{
state: "active",
platform_role: "moderator",
trust_tier: "reviewer"
}
)
|> render_submit()
assert Accounts.get_account!(target.id).platform_role == target.platform_role
end
# Simulates the two-hour sudo window expiring while the LiveView stays open.
defp expire_sudo_mode(view) do
stale = DateTime.add(DateTime.utc_now(), -3, :hour)
:sys.replace_state(view.pid, fn state ->
account = %{state.socket.assigns.current_scope.account | authenticated_at: stale}
put_in(state.socket.assigns.current_scope.account, account)
end)
end
end

View file

@ -0,0 +1,34 @@
defmodule TarakanWeb.AgentsLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
test "install, publish Reports, pick up Jobs", %{conn: conn} do
{:ok, view, html} = live(conn, ~p"/agents")
assert has_element?(view, "#agents-commands")
assert has_element?(view, "#agents-dump-commands")
assert has_element?(view, "#agents-pickup-commands")
assert has_element?(view, "#agents-report-api")
assert html =~ "/install.sh | bash"
assert html =~ "tarakan login"
assert html =~ "tarakan worker --agent kimi"
assert html =~ "tarakan --agent kimi --pickup"
assert html =~ "POST "
assert html =~ "/reports"
assert html =~ "Report"
assert html =~ "Check"
assert html =~ "Job"
refute html =~ "tarakan login --url"
end
test "install.sh covers worker and pickup", %{conn: conn} do
conn = get(conn, "/install.sh")
assert conn.status == 200
body = response(conn, 200)
assert body =~ "tarakan login"
assert body =~ "tarakan worker --agent kimi"
assert body =~ "tarakan --agent kimi --pickup"
end
end

View file

@ -0,0 +1,79 @@
defmodule TarakanWeb.AlertLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.Billing
alias Tarakan.Repo
test "redirects anonymous visitors to login", %{conn: conn} do
assert {:error, {:redirect, %{to: "/accounts/log-in"}}} = live(conn, ~p"/alerts")
end
test "creates, edits, toggles, and deletes a watchlist", %{conn: conn} do
account = account_fixture()
{:ok, view, _html} = conn |> log_in_account(account) |> live(~p"/alerts")
assert has_element?(view, "#watchlists")
assert has_element?(view, "#watchlist-form")
# Create
view
|> form("#watchlist-form", watchlist: %{name: "Deps", entries: "openai/codex\nacme/widget"})
|> render_submit()
[watchlist] = Billing.list_watchlists(account)
assert watchlist.name == "Deps"
assert watchlist.entries == ["openai/codex", "acme/widget"]
assert has_element?(view, "#watchlist-#{watchlist.id}")
assert has_element?(view, "#watchlist-#{watchlist.id}", "openai/codex")
# Toggle notify off
view |> element("#watchlist-notify-#{watchlist.id}") |> render_click()
refute Repo.get!(Billing.Watchlist, watchlist.id).notify
# Edit
view |> element("#watchlist-edit-#{watchlist.id}") |> render_click()
view
|> form("#watchlist-form", watchlist: %{name: "Deps v2", entries: "openai/codex"})
|> render_submit()
updated = Repo.get!(Billing.Watchlist, watchlist.id)
assert updated.name == "Deps v2"
assert updated.entries == ["openai/codex"]
assert has_element?(view, "#watchlist-#{watchlist.id}", "Deps v2")
# Delete
view |> element("#watchlist-delete-#{watchlist.id}") |> render_click()
refute has_element?(view, "#watchlist-#{watchlist.id}")
assert Billing.list_watchlists(account) == []
end
test "invalid entries show an error and do not persist", %{conn: conn} do
account = account_fixture()
{:ok, view, _html} = conn |> log_in_account(account) |> live(~p"/alerts")
html =
view
|> form("#watchlist-form", watchlist: %{name: "Bad", entries: "not a ref"})
|> render_submit()
assert html =~ "owner/name"
assert Billing.list_watchlists(account) == []
end
test "watchlists are owner-scoped", %{conn: conn} do
owner = account_fixture()
{:ok, _} =
Billing.create_watchlist(Tarakan.Accounts.Scope.for_account(owner), %{
"name" => "Private",
"entries" => ["openai/codex"]
})
{:ok, view, _html} = conn |> log_in_account(account_fixture()) |> live(~p"/alerts")
refute has_element?(view, "#watchlists", "Private")
end
end

View file

@ -0,0 +1,88 @@
defmodule TarakanWeb.BillingLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.Billing.Subscription
alias Tarakan.Repo
defp subscription_fixture(account, overrides) do
attrs =
Map.merge(
%{
account_id: account.id,
plan: "enterprise",
status: "active",
stripe_customer_id: "cus_lv",
stripe_subscription_id: "sub_lv_#{account.id}",
current_period_end: DateTime.utc_now()
},
overrides
)
%Subscription{}
|> Subscription.changeset(attrs)
|> Repo.insert!()
end
test "redirects anonymous visitors to login", %{conn: conn} do
assert {:error, {:redirect, %{to: "/accounts/log-in"}}} = live(conn, ~p"/accounts/billing")
end
test "shows the unsubscribed state with the managed-disclosure button", %{conn: conn} do
{:ok, view, _html} = conn |> log_in_account(account_fixture()) |> live(~p"/accounts/billing")
assert has_element?(view, "#billing-current")
assert has_element?(view, "#billing-plan", "None")
assert has_element?(view, "#billing-subscribe-enterprise")
refute has_element?(view, "#billing-manage-button")
end
test "shows the active plan, status, period end, and manage button", %{conn: conn} do
account = account_fixture()
subscription_fixture(account, %{})
{:ok, view, _html} = conn |> log_in_account(account) |> live(~p"/accounts/billing")
assert has_element?(view, "#billing-plan", "Managed disclosure")
assert has_element?(view, "#billing-status", "Active")
assert has_element?(view, "#billing-manage-button")
refute has_element?(view, "#billing-subscribe-enterprise")
end
test "renders past_due and canceled states", %{conn: conn} do
past_due = account_fixture()
subscription_fixture(past_due, %{status: "past_due"})
{:ok, view, _html} = conn |> log_in_account(past_due) |> live(~p"/accounts/billing")
assert has_element?(view, "#billing-status", "Past due")
canceled = account_fixture()
subscription_fixture(canceled, %{status: "canceled"})
{:ok, view, _html} = conn |> log_in_account(canceled) |> live(~p"/accounts/billing")
assert has_element?(view, "#billing-status", "Canceled")
assert has_element?(view, "#billing-subscribe-enterprise")
end
test "subscribe redirects to Stripe checkout", %{conn: conn} do
{:ok, view, _html} = conn |> log_in_account(account_fixture()) |> live(~p"/accounts/billing")
assert {:error, {:redirect, %{to: checkout_url}}} =
view |> element("#billing-subscribe-enterprise") |> render_click()
assert checkout_url =~ "https://checkout.stripe.com/"
end
test "manage redirects to the Stripe billing portal", %{conn: conn} do
account = account_fixture()
subscription_fixture(account, %{})
{:ok, view, _html} = conn |> log_in_account(account) |> live(~p"/accounts/billing")
assert {:error, {:redirect, %{to: portal_url}}} =
view |> element("#billing-manage-button") |> render_click()
assert portal_url =~ "https://billing.stripe.com/"
end
end

View file

@ -0,0 +1,155 @@
defmodule TarakanWeb.BountyLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.Accounts.Scope
alias Tarakan.Market
alias Tarakan.Market.Bounty
alias Tarakan.Repo
defp open_bounty do
repository = listed_github_repository_fixture()
sponsor = active_account_fixture() |> fund_credits(1_000)
bounty = credits_bounty_fixture(Scope.for_account(sponsor), repository)
{bounty, sponsor, repository}
end
describe "index" do
test "renders open bounties for anonymous visitors", %{conn: conn} do
{bounty, sponsor, _repository} = open_bounty()
{:ok, view, html} = live(conn, ~p"/bounties")
assert html =~ "Contracts"
assert has_element?(view, "#bounties")
assert has_element?(view, "#bounty-#{bounty.public_id}")
assert html =~ bounty.title
assert html =~ "500 credits"
assert html =~ "@#{sponsor.handle}"
assert has_element?(view, "#bounty-filters")
end
test "shows the empty state when nothing is open", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/bounties")
assert has_element?(view, "#bounties-empty")
end
end
describe "new" do
test "redirects anonymous visitors to login", %{conn: conn} do
assert {:error, {:redirect, %{to: "/accounts/log-in"}}} = live(conn, ~p"/bounties/new")
end
test "creates a credits bounty and lands on the poster", %{conn: conn} do
repository = listed_github_repository_fixture()
sponsor = active_account_fixture() |> fund_credits(1_000)
conn = log_in_account(conn, sponsor)
{:ok, view, _html} = live(conn, ~p"/bounties/new")
assert has_element?(view, "#bounty-form")
assert has_element?(view, "#bounty-credit-balance")
# The target is picked from search, not typed.
view
|> form("#bounty-form", %{"bounty" => %{"repo_query" => repository.name}})
|> render_change()
assert view
|> element("#bounty-repo-results button", "#{repository.owner}/#{repository.name}")
|> render_click()
assert has_element?(
view,
"#bounty-selected-repository",
"#{repository.host}/#{repository.owner}/#{repository.name}"
)
{:ok, _show_view, html} =
view
|> form("#bounty-form", %{
"bounty" => %{
"target_type" => "repository",
"title" => "Harden the webhook verifier",
"description" => "Audit the signature verification path and ship a fix with tests.",
"funding" => "credits",
"amount" => "300"
}
})
|> render_submit()
|> follow_redirect(conn)
assert html =~ "Harden the webhook verifier"
assert html =~ "300 credits"
bounty = Repo.one!(Bounty)
assert bounty.status == "open"
assert bounty.credit_amount == 300
assert Tarakan.Credits.balance(sponsor) == 700
end
end
describe "show" do
test "anonymous visitors see the poster and a login prompt, not a claim button", %{
conn: conn
} do
{bounty, _sponsor, _repository} = open_bounty()
{:ok, view, html} = live(conn, ~p"/bounties/#{bounty.public_id}")
assert html =~ bounty.title
assert has_element?(view, "#bounty-status")
refute has_element?(view, "#bounty-claim-button")
assert has_element?(view, "#bounty-login-to-claim")
end
test "the sponsor sees cancel controls but no claim button", %{conn: conn} do
{bounty, sponsor, _repository} = open_bounty()
conn = log_in_account(conn, sponsor)
{:ok, view, _html} = live(conn, ~p"/bounties/#{bounty.public_id}")
refute has_element?(view, "#bounty-claim-button")
assert has_element?(view, "#bounty-cancel-button")
end
test "an eligible hunter sees and uses the claim button", %{conn: conn} do
{bounty, _sponsor, _repository} = open_bounty()
hunter = active_account_fixture()
conn = log_in_account(conn, hunter)
{:ok, view, _html} = live(conn, ~p"/bounties/#{bounty.public_id}")
assert has_element?(view, "#bounty-claim-button")
html = view |> element("#bounty-claim-button") |> render_click()
assert html =~ "claimed"
assert has_element?(view, "#bounty-claims")
bounty = Repo.get!(Bounty, bounty.id)
assert bounty.status == "claimed"
claim = Repo.one!(Tarakan.Market.BountyClaim)
assert claim.account_id == hunter.id
assert claim.review_task_id
end
end
describe "wanted banners" do
test "the repository security page shows the banner for its open bounty", %{conn: conn} do
{bounty, _sponsor, repository} = open_bounty()
{:ok, view, _html} =
live(conn, TarakanWeb.RepositoryPaths.repository_security_path(repository))
assert has_element?(view, "#wanted-banner")
bounty = Market.get_bounty!(bounty.public_id)
assert bounty.status == "open"
end
end
end

View file

@ -0,0 +1,79 @@
defmodule TarakanWeb.ClientAuthorizationLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.Accounts.ClientAuthorizations
setup :register_and_log_in_account
test "approve/deny with no loaded authorization flashes instead of crashing", %{conn: conn} do
# An unknown/expired user code leaves @authorization nil and hides the
# buttons - but a queued or crafted event must not reach the context with
# nil and raise a FunctionClauseError.
{:ok, view, html} = live(conn, ~p"/client/authorize/UNKNOWNXY")
assert html =~ "invalid or expired"
assert render_click(view, "approve") =~ "expired or was already used"
assert render_click(view, "deny") =~ "expired or was already used"
end
describe "consent screen" do
test "attributes the client-supplied name instead of asserting it", %{conn: conn} do
{:ok, _device_code, user_code, _authorization} =
ClientAuthorizations.start(%{"client_name" => "Totally Official Thing"})
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{user_code}")
# The name is presented as the request's own claim, next to a warning,
# rather than as a statement this page vouches for.
assert html =~ "Calls itself"
assert html =~ "Totally Official Thing"
assert html =~ "Nobody at Tarakan will"
end
test "a name carrying control or bidi characters is cleaned before display", %{conn: conn} do
hostile = "Tarakan" <> "\u202e" <> "lortnoC" <> "\u200b" <> " Client"
{:ok, _device_code, user_code, authorization} =
ClientAuthorizations.start(%{"client_name" => hostile})
refute authorization.client_name =~ "\u202e"
refute authorization.client_name =~ "\u200b"
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{user_code}")
refute html =~ "\u202e"
end
test "a name of only unusable characters falls back to the default", %{conn: _conn} do
{:ok, _device_code, _user_code, authorization} =
ClientAuthorizations.start(%{"client_name" => "\u200b\u202e"})
assert authorization.client_name == "Tarakan Client"
end
test "a name with markup-shaped characters is refused outright" do
assert {:error, changeset} =
ClientAuthorizations.start(%{"client_name" => "Tarakan <script> Client"})
assert Keyword.has_key?(changeset.errors, :client_name)
end
end
describe "user code lookups" do
test "wrong guesses are budgeted per account", %{conn: conn} do
# Well past the per-account allowance; the page must stay uninformative
# rather than answering "exists / does not exist" indefinitely.
for index <- 1..35 do
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{"AAAA000" <> to_string(index)}")
assert html =~ "invalid or expired"
end
# A real code now reads the same as a wrong one: throttled and missing
# are deliberately indistinguishable.
{:ok, _device_code, user_code, _authorization} = ClientAuthorizations.start()
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{user_code}")
assert html =~ "invalid or expired"
end
end
end

View file

@ -0,0 +1,80 @@
defmodule TarakanWeb.CommunityLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
test "the homepage shows the shoutbox and gates posting", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/")
assert has_element?(view, "#registry-shoutbox")
refute has_element?(view, "#registry-presence")
assert has_element?(view, "#shoutbox-empty")
refute has_element?(view, "#shoutbox-form")
assert has_element?(view, ~s(#registry-shoutbox a[href="/accounts/log-in"]))
end
test "a signed-in contributor posts a live escaped shout", %{conn: conn} do
account = account_fixture()
{:ok, view, _html} = live(log_in_account(conn, account), ~p"/")
{:ok, observer, _html} = live(Phoenix.ConnTest.build_conn(), ~p"/")
assert has_element?(view, "#shoutbox-form")
assert has_element?(view, ~s(#shoutbox-form input[type="text"]))
html =
view
|> form("#shoutbox-form", shout: %{body: "Reviewing <script>alert(1)</script> auth."})
|> render_submit()
assert has_element?(
view,
"#shoutbox-messages article",
"Reviewing <script>alert(1)</script> auth."
)
assert has_element?(view, "#shoutbox-body-1[phx-mounted]")
assert has_element?(
observer,
"#shoutbox-messages article",
"Reviewing <script>alert(1)</script> auth."
)
assert html =~ "&lt;script&gt;"
refute html =~ "<script>alert(1)</script>"
end
test "moderators can remove a shout from the homepage", %{conn: conn} do
author = account_fixture()
{:ok, shout} =
Tarakan.Community.create_shout(Tarakan.Accounts.Scope.for_account(author), %{
"body" => "Off-topic shout"
})
moderator = moderator_account_fixture()
{:ok, view, _html} = live(log_in_account(conn, moderator), ~p"/")
view
|> element("#shout-#{shout.id} button", "Remove")
|> render_click()
assert has_element?(view, "#shout-#{shout.id}", "Removed by moderation")
refute has_element?(view, "#shout-#{shout.id} button", "Remove")
end
test "the compact composer rejects blank messages without an inline error", %{conn: conn} do
{:ok, view, _html} = live(log_in_account(conn, account_fixture()), ~p"/")
assert has_element?(view, "#shoutbox-form input[required]")
html =
view
|> form("#shoutbox-form", shout: %{body: " "})
|> render_submit()
assert html =~ "Write a message before sending."
refute has_element?(view, "#shoutbox-body-0-error")
refute html =~ "be blank"
end
end

View file

@ -0,0 +1,160 @@
defmodule TarakanWeb.ExploreLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
alias Tarakan.Activity
test "renders the wire: registrations and unverified public reviews", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
{:ok, view, _html} = live(conn, ~p"/explore")
assert has_element?(view, "#activity-wire")
assert has_element?(view, "#wire-reg-#{repository.id}", "openai/codex")
assert has_element?(view, "#wire-scan-#{scan.id}", "@#{submitter.handle}")
assert has_element?(view, "#wire-scan-#{scan.id}", "1 finding")
end
test "filters the wire by kind", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter)
{:ok, view, _html} = live(conn, ~p"/explore")
view |> element("#explore-filter button", "Registrations") |> render_click()
assert has_element?(view, "#wire-reg-#{repository.id}")
refute has_element?(view, "#wire-scan-#{scan.id}")
view |> element("#explore-filter button", "Reports") |> render_click()
assert has_element?(view, "#wire-scan-#{scan.id}")
refute has_element?(view, "#wire-reg-#{repository.id}")
end
test "new activity lands on the wire without a reload", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/explore")
assert has_element?(view, "#activity-wire-empty")
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
Activity.broadcast_registration(repository)
assert has_element?(view, "#wire-reg-#{repository.id}", "openai/codex")
end
test "verdicts on the wire show who ruled and how", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
reviewer = reviewer_account_fixture()
confirmation_fixture(scan, reviewer)
{:ok, view, _html} = live(conn, ~p"/explore")
assert render(view) =~ "@#{reviewer.handle}"
assert render(view) =~ "confirmed a finding on"
end
test "handles link to contributor profiles", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter)
{:ok, view, _html} = live(conn, ~p"/explore")
assert view
|> element("#wire-scan-#{scan.id} a[href='/#{submitter.handle}']")
|> render() =~ "@#{submitter.handle}"
end
test "comments join the wire live and on reload", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
{:ok, view, _html} = live(conn, ~p"/explore")
commenter = account_fixture()
scope = Tarakan.Accounts.Scope.for_account(commenter)
{:ok, comment} =
Tarakan.Discussion.create_comment(scope, %{finding | scan: scan}, %{
"body" => "Reproduced on a clean checkout."
})
assert has_element?(view, "#wire-comment-#{comment.id}", "@#{commenter.handle}")
assert has_element?(view, "#wire-comment-#{comment.id}", "commented on")
{:ok, reloaded, _html} = live(conn, ~p"/explore")
assert has_element?(reloaded, "#wire-comment-#{comment.id}")
reloaded |> element("#explore-filter button", "Comments") |> render_click()
assert has_element?(reloaded, "#wire-comment-#{comment.id}")
refute has_element?(reloaded, "#wire-scan-#{scan.id}")
end
test "search narrows the wire by handle or repository", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter)
{:ok, view, _html} = live(conn, ~p"/explore")
view
|> form("#explore-search-form", %{"q" => submitter.handle})
|> render_change()
assert has_element?(view, "#wire-scan-#{scan.id}")
refute has_element?(view, "#wire-reg-#{repository.id}")
view
|> form("#explore-search-form", %{"q" => "no-such-thing"})
|> render_change()
assert has_element?(view, "#activity-wire-empty")
end
test "shows watcher presence", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/explore")
assert has_element?(view, "#explore-watchers")
assert view |> element("#explore-watchers") |> render() =~ "watching"
end
test "hot findings rail ranks upvoted findings and refreshes on votes", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
canonical = finding.canonical_finding
# Hot rail excludes pure single-run unconfirmed noise; second detection qualifies.
_second =
scan_fixture(repository, account_fixture(), %{
"findings_json" => findings_json_fixture(1),
"commit_sha" => scan.commit_sha
})
canonical = Tarakan.Repo.get!(Tarakan.Scans.CanonicalFinding, canonical.id)
{:ok, view, _html} = live(conn, ~p"/explore")
assert has_element?(view, "#hot-findings", "No findings upvoted this week.")
voter = Tarakan.Accounts.Scope.for_account(account_fixture())
{:ok, _summary} = Tarakan.Reputation.cast_vote(voter, "canonical_finding", canonical.id, 1)
assert has_element?(view, "#hot-finding-#{canonical.id}", "+1")
assert view
|> element("#hot-finding-#{canonical.id}")
|> render() =~ ~s(href="/findings/)
end
end

View file

@ -0,0 +1,112 @@
defmodule TarakanWeb.FindingDiscussionTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
alias Tarakan.Accounts.Scope
alias Tarakan.Discussion
setup do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
%{finding: %{finding | scan: scan}, repository: repository}
end
test "anonymous visitors see the discussion but are prompted to sign in", %{
conn: conn,
finding: finding
} do
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-discussion")
assert has_element?(view, "#finding-comment-login")
assert has_element?(view, "#finding-no-comments")
refute has_element?(view, "#finding-comment-form")
end
test "a signed-in account posts a comment", %{conn: conn, finding: finding} do
conn = log_in_account(conn, account_fixture())
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
view
|> form("#finding-comment-form", %{"body" => "Reproduced against the pinned commit."})
|> render_submit()
assert has_element?(view, "#finding-comment-count", "1 comment")
assert render(view) =~ "Reproduced against the pinned commit."
refute has_element?(view, "#finding-no-comments")
end
test "a reply nests under its parent", %{conn: conn, finding: finding} do
author = account_fixture()
{:ok, parent} =
Discussion.create_comment(Scope.for_account(author), finding, %{"body" => "Parent comment."})
conn = log_in_account(conn, account_fixture())
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
view |> element("#comment-#{parent.id} button", "Reply") |> render_click()
view
|> form("#reply-form-#{parent.id}", %{"body" => "A threaded reply."})
|> render_submit()
assert has_element?(view, "#comment-#{parent.id} #comment-#{last_comment_id()}")
assert has_element?(view, "#finding-comment-count", "2 comments")
end
test "a moderator can remove a comment and it shows as a placeholder", %{
conn: conn,
finding: finding
} do
author = account_fixture()
{:ok, comment} =
Discussion.create_comment(Scope.for_account(author), finding, %{"body" => "Spammy comment."})
conn = log_in_account(conn, moderator_account_fixture())
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#comment-#{comment.id} button", "Remove")
view
|> element("#comment-#{comment.id} button", "Remove")
|> render_click()
assert has_element?(view, "#comment-#{comment.id}", "Removed by moderation")
end
test "restricted findings expose no discussion to anonymous visitors", %{
conn: conn,
repository: repository
} do
submitter = github_account_fixture(%{handle: "restricted-author"})
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
{:ok, _restricted} =
Tarakan.Scans.update_visibility(
Scope.for_account(moderator_account_fixture()),
scan,
"restricted",
%{
"moderation_reason" => "takedown_review",
"moderation_notes" =>
"Restricted in this test to confirm discussion follows finding disclosure."
}
)
assert_error_sent 404, fn -> get(conn, ~p"/findings/#{finding.public_id}") end
end
defp last_comment_id do
import Ecto.Query
Tarakan.Repo.one(
from c in Tarakan.Discussion.Comment, order_by: [desc: c.id], limit: 1, select: c.id
)
end
end

View file

@ -0,0 +1,420 @@
defmodule TarakanWeb.FindingLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
setup do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
%{repository: repository, submitter: submitter}
end
test "renders a publicly disclosed finding", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan =
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_fixture(1)})
|> publish_scan("public")
[finding] = scan.findings
{:ok, view, html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-title", finding.title)
assert has_element?(view, "#finding-severity", "high")
assert has_element?(view, "#finding-description", "String-built SQL")
assert has_element?(view, "#finding-canonical-memory", "detected in 1 run")
assert has_element?(view, "#finding-source-link[href='/findings/#{finding.public_id}/code']")
assert has_element?(view, "#finding-verified-badge")
assert has_element?(view, "#finding-disclosure-badge")
assert has_element?(view, "#finding-copy-link")
assert has_element?(view, "#finding-cite", "/findings/#{finding.public_id}")
assert has_element?(view, "#finding-verdict-counts", "2 confirmed · 0 disputed")
assert html =~ scan.commit_sha
assert html =~ "Public"
assert has_element?(view, "#finding-record-link[href='/github.com/openai/codex/security']")
end
test "shows the raw model report exactly as submitted", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
assert scan.raw_document == findings_json_fixture(1)
{:ok, view, html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-raw-report")
assert html =~ "tarakan_scan_format"
end
test "a qualified contributor records a verdict from the finding page", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
reviewer =
account_fixture()
|> Tarakan.Accounts.Account.authorization_changeset(%{
state: "active",
platform_role: "member",
trust_tier: "reviewer"
})
|> Tarakan.Repo.update!()
conn = log_in_account(conn, reviewer)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-verdict-counts", "0 confirmed · 0 disputed")
view
|> form("#finding-verdict-form", %{
"notes" => "Reproduced against the pinned commit with the documented payload."
})
|> render_submit(%{"verdict" => "confirmed"})
assert has_element?(view, "#finding-verdict-counts", "1 confirmed · 0 disputed")
assert has_element?(view, "#finding-checks", "@#{reviewer.handle}")
assert has_element?(
view,
"#finding-checks",
"Reproduced against the pinned commit with the documented payload."
)
assert has_element?(view, "#finding-checks", "counts toward quorum")
refute has_element?(view, "#finding-verdict-form")
{:ok, public_view, _html} =
live(Phoenix.ConnTest.build_conn(), ~p"/findings/#{finding.public_id}")
assert has_element?(public_view, "#finding-checks", "@#{reviewer.handle}")
assert has_element?(public_view, "#finding-checks", "documented payload")
end
test "the submitter cannot verify their own finding", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
conn = log_in_account(conn, submitter)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
refute has_element?(view, "#finding-verdict-form")
end
test "the dead render carries the meta description and canonical URL", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan =
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_fixture(1)})
|> publish_scan("public")
[finding] = scan.findings
html = conn |> get(~p"/findings/#{finding.public_id}") |> html_response(200)
assert html =~ ~s(rel="canonical")
assert html =~ "/findings/#{finding.public_id}"
assert html =~ "High in openai/codex"
assert get_resp_header(get(conn, ~p"/findings/#{finding.public_id}"), "x-robots-tag") == []
end
test "fresh submissions resolve for anonymous visitors immediately", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-title", finding.title)
refute has_element?(view, "#finding-verified-badge")
end
test "restricted findings do not resolve for anonymous visitors", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
{:ok, _restricted} =
Tarakan.Scans.update_visibility(
Tarakan.Accounts.Scope.for_account(moderator_account_fixture()),
scan,
"restricted",
%{
"moderation_reason" => "takedown_review",
"moderation_notes" =>
"Deliberately restricted in this test to exercise the takedown boundary."
}
)
assert_error_sent 404, fn -> get(conn, ~p"/findings/#{finding.public_id}") end
end
test "public-summary findings do not resolve for anonymous visitors", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
publish_scan(scan, "public_summary")
assert_error_sent 404, fn -> get(conn, ~p"/findings/#{finding.public_id}") end
end
test "the submitter can still open their own restricted finding", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
{:ok, _restricted} =
Tarakan.Scans.update_visibility(
Tarakan.Accounts.Scope.for_account(moderator_account_fixture()),
scan,
"restricted",
%{
"moderation_reason" => "takedown_review",
"moderation_notes" =>
"Deliberately restricted in this test to exercise submitter access."
}
)
conn = log_in_account(conn, submitter)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-title", finding.title)
end
test "the lifecycle timeline lists first-seen and check events", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
reviewer = reviewer_account_fixture()
conn = log_in_account(conn, reviewer)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-timeline-first-seen", "First seen")
refute has_element?(view, "li[id^='finding-timeline-check-']")
refute has_element?(view, "#finding-timeline-verified")
refute has_element?(view, "#finding-timeline-vendor-notified")
view
|> form("#finding-verdict-form", %{
"notes" => "Reproduced against the pinned commit with the documented payload."
})
|> render_submit(%{"verdict" => "confirmed"})
assert has_element?(view, "#finding-timeline li[id^='finding-timeline-check-']")
assert has_element?(view, "#finding-timeline", "@#{reviewer.handle}")
assert has_element?(view, "#finding-timeline", "confirmed")
end
test "the lifecycle timeline shows verified and vendor events when set", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan =
repository
|> scan_fixture(submitter, %{"findings_json" => findings_json_fixture(1)})
|> publish_scan("public")
[finding] = scan.findings
conn = log_in_account(conn, reviewer_account_fixture())
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(view, "#finding-timeline-first-seen")
assert has_element?(view, "#finding-timeline li[id^='finding-timeline-check-']")
assert has_element?(view, "#finding-timeline-verified", "Verified")
refute has_element?(view, "#finding-timeline-vendor-notified")
view
|> form("#finding-vendor-form", %{
"vendor_notification" => %{"notified_on" => "2026-01-15"}
})
|> render_submit()
assert has_element?(view, "#finding-timeline-vendor-notified", "Vendor notified")
canonical =
Tarakan.Repo.get_by!(Tarakan.Scans.CanonicalFinding, repository_id: repository.id)
assert canonical.vendor_notified_at == ~U[2026-01-15 00:00:00.000000Z]
view
|> form("#finding-vendor-form", %{"vendor_notification" => %{"notified_on" => ""}})
|> render_submit()
refute has_element?(view, "#finding-timeline-vendor-notified")
assert Tarakan.Repo.get!(Tarakan.Scans.CanonicalFinding, canonical.id).vendor_notified_at ==
nil
end
test "CWE and CVE badges link out and disclosure metadata renders", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan =
scan_fixture(repository, submitter, %{
"findings_json" => findings_json_with_disclosure_fixture()
})
[finding] = scan.findings
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
assert has_element?(
view,
"#finding-cwe-badge[href='https://cwe.mitre.org/data/definitions/89.html']",
"CWE-89"
)
assert has_element?(
view,
"#finding-cve-badge[href='https://nvd.nist.gov/vuln/detail/CVE-2026-12345']",
"CVE-2026-12345"
)
assert has_element?(view, "#finding-reproduction", "Run the payload")
assert has_element?(view, "#finding-affected-versions", ">= 1.0, < 2.0")
end
test "CWE and CVE badges and disclosure metadata are absent when unset", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
refute has_element?(view, "#finding-cwe-badge")
refute has_element?(view, "#finding-cve-badge")
refute has_element?(view, "#finding-reproduction")
refute has_element?(view, "#finding-affected-versions")
end
test "the vendor notification form is hidden from ordinary members", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
{:ok, anonymous_view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
refute has_element?(anonymous_view, "#finding-vendor-form")
conn = log_in_account(conn, submitter)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
refute has_element?(view, "#finding-vendor-form")
end
test "an unauthorized vendor notification event is rejected", %{
conn: conn,
repository: repository,
submitter: submitter
} do
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
conn = log_in_account(conn, submitter)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
render_hook(view, "record_vendor_notification", %{
"vendor_notification" => %{"notified_on" => "2026-01-15"}
})
assert has_element?(view, "#flash-group", "not authorized")
canonical =
Tarakan.Repo.get_by!(Tarakan.Scans.CanonicalFinding, repository_id: repository.id)
assert canonical.vendor_notified_at == nil
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,110 @@
defmodule TarakanWeb.FindingVoteTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
alias Tarakan.Accounts.Scope
alias Tarakan.Discussion
setup do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
[finding] = scan.findings
%{finding: %{finding | scan: scan}, submitter: submitter}
end
test "a signed-in visitor upvotes a finding and the score updates", %{
conn: conn,
finding: finding
} do
conn = log_in_account(conn, account_fixture())
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
canonical_id = finding.canonical_finding.id
view
|> element(~s(#vote-canonical_finding-#{canonical_id} button[phx-value-vote="1"]))
|> render_click()
assert has_element?(view, "#vote-canonical_finding-#{canonical_id}", "1")
end
test "the submitter cannot vote on their own finding", %{
conn: conn,
finding: finding,
submitter: submitter
} do
conn = log_in_account(conn, submitter)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
canonical_id = finding.canonical_finding.id
html =
view
|> element(~s(#vote-canonical_finding-#{canonical_id} button[phx-value-vote="1"]))
|> render_click()
assert html =~ "cannot vote on your own"
assert has_element?(view, "#vote-canonical_finding-#{canonical_id}", "0")
end
test "anonymous vote clicks are gated to login", %{conn: conn, finding: finding} do
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
# Anonymous controls are disabled, so the buttons carry the disabled attr.
assert has_element?(
view,
~s(#vote-canonical_finding-#{finding.canonical_finding.id} button[disabled])
)
end
test "a comment can be voted on", %{conn: conn, finding: finding} do
{:ok, comment} =
Discussion.create_comment(Scope.for_account(account_fixture()), finding, %{
"body" => "This looks exploitable."
})
conn = log_in_account(conn, account_fixture())
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
view
|> element(~s(#vote-comment-#{comment.id} button[phx-value-vote="1"]))
|> render_click()
assert has_element?(view, "#vote-comment-#{comment.id}", "1")
end
test "malformed vote parameters are rejected without crashing", %{
conn: conn,
finding: finding
} do
conn = log_in_account(conn, account_fixture())
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}")
html =
render_click(view, "vote", %{
"type" => "canonical_finding",
"id" => "1 OR 1=1",
"vote" => "1"
})
assert html =~ "could not be recorded"
html =
render_click(view, "vote", %{
"type" => "canonical_finding",
"id" => "#{finding.canonical_finding.id}",
"vote" => "1; DROP"
})
assert html =~ "could not be recorded"
assert has_element?(view, "#vote-canonical_finding-#{finding.canonical_finding.id}", "0")
end
test "only the canonical finding on the security page carries a vote control", %{
finding: finding
} do
conn = Phoenix.ConnTest.build_conn()
{:ok, view, _html} = live(conn, ~p"/github.com/openai/codex/security")
assert has_element?(view, "#vote-canonical_finding-#{finding.canonical_finding.id}")
refute has_element?(view, "#vote-finding-#{finding.id}")
end
end

View file

@ -0,0 +1,180 @@
defmodule TarakanWeb.InfestationLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.FindingMemory
test "index and show render multi-repo patterns", %{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 = "Live infestation #{System.unique_integer([:positive])}"
findings = fn path ->
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => path,
"severity" => "critical",
"title" => title,
"description" => "Infestation liveview fixture."
}
]
})
end
scan_fixture(repo_a, submitter, %{"findings_json" => findings.("a.ex")})
scan_fixture(repo_b, other, %{"findings_json" => findings.("b.ex")})
# repo_a is hit twice by the same pattern at different paths, so the
# per-repo rollup and the per-finding ledger must disagree on row count.
scan_fixture(repo_a, submitter, %{"findings_json" => findings.("a2.ex")})
pattern = FindingMemory.pattern_key(title)
{:ok, index, html} = live(conn, ~p"/infestations")
assert html =~ "Infestations"
assert has_element?(index, "#infestations-constellation")
assert has_element?(index, "#infestation-#{pattern}")
{:ok, show, show_html} = live(conn, ~p"/infestations/#{pattern}")
assert show_html =~ title
assert has_element?(show, "#infestation-repo-count", "2")
assert has_element?(show, "#infestation-graph")
assert has_element?(show, "#infestation-instances")
# The repo table is a rollup: one row per repository, carrying the counts
# that distinguish it from the instance ledger below.
graph_rows = show |> element("#infestation-graph tbody") |> render()
assert graph_rows =~ "#{repo_a.owner}/#{repo_a.name}"
assert graph_rows =~ "#{repo_b.owner}/#{repo_b.name}"
row_a = show |> element("#infestation-graph-node-#{repo_a.id}") |> render() |> squish()
assert row_a =~ ">2</td>", "repo_a is hit twice and must report 2, not a blank cell"
row_b = show |> element("#infestation-graph-node-#{repo_b.id}") |> render() |> squish()
assert row_b =~ ">1</td>", "repo_b is hit once and must report 1"
# 2 repository rows, 3 instance rows: the two views are different grains.
ledger = show |> element("#infestation-ledger") |> render()
assert length(Regex.scan(~r/<li[^>]+id="ledger_instances-/, ledger)) == 3
end
describe "fix propagation" do
setup %{conn: conn} do
submitter = github_account_fixture()
other = github_account_fixture()
source = listed_github_repository_fixture(submitter)
{:ok, target} = Tarakan.Repositories.register_github_repository("acme/widget", other)
target = listed_repository_fixture(target)
title = "Propagatable finding #{System.unique_integer([:positive])}"
findings =
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => "lib/handler.ex",
"severity" => "critical",
"title" => title,
"description" => "Shared across both repositories."
}
]
})
source_scan = scan_fixture(source, submitter, %{"findings_json" => findings})
scan_fixture(target, other, %{"findings_json" => findings})
# Settle the source instance as fixed so a template can be captured.
[occurrence] = source_scan.findings
source_finding =
Tarakan.Repo.get!(Tarakan.Scans.CanonicalFinding, occurrence.canonical_finding_id)
|> Ecto.Changeset.change(%{
status: "fixed",
fixed_at: DateTime.utc_now(),
fixed_commit_sha: source_scan.commit_sha
})
|> Tarakan.Repo.update!()
%Tarakan.Scans.FindingCheck{}
|> Tarakan.Scans.FindingCheck.changeset(%{
commit_sha: source_scan.commit_sha,
verdict: "fixed",
provenance: "human",
notes: "Escaped the interpolated value and added a regression test."
})
|> Ecto.Changeset.put_change(:canonical_finding_id, source_finding.id)
|> Ecto.Changeset.put_change(:account_id, submitter.id)
|> Tarakan.Repo.insert!()
moderator = moderator_account_fixture()
{:ok, template} =
Tarakan.Fixes.capture_fix(
Tarakan.Accounts.Scope.for_account(moderator),
source_finding
)
%{
conn: log_in_account(conn, moderator),
pattern: FindingMemory.pattern_key(title),
source: source,
target: target,
template: template
}
end
test "shows the captured fix and carries it to the remaining repository", %{
conn: conn,
pattern: pattern,
source: source,
target: target,
template: template
} do
{:ok, view, html} = live(conn, ~p"/infestations/#{pattern}")
assert html =~ "Fixed on"
assert html =~ "#{source.owner}/#{source.name}"
assert html =~ "Escaped the interpolated value"
assert has_element?(view, "#infestation-propagate-fix", "Propagate to 1")
html = view |> element("#infestation-propagate-fix") |> render_click()
assert html =~ "Opened 1 fix job"
assert html =~ "carried to 1 repo"
# A real, public job now exists on the other repository, carrying the fix.
# Scan submission auto-opens a verification job too, so reach the fix job
# through the propagation rather than by repository alone.
assert [propagation] = Tarakan.Fixes.list_propagations(template)
assert propagation.repository_id == target.id
task = propagation.review_task
assert task.status == "open"
assert task.visibility == "public"
assert task.description =~ "Escaped the interpolated value"
end
test "anonymous visitors see the fix but cannot propagate it", %{pattern: pattern} do
{:ok, view, html} = live(build_conn(), ~p"/infestations/#{pattern}")
assert html =~ "Fixed on"
refute has_element?(view, "#infestation-propagate-fix")
end
end
# Collapse the whitespace HEEx leaves around interpolated cell values so
# assertions can match on the value itself.
defp squish(html) do
html
|> String.replace(~r/>\s+/, ">")
|> String.replace(~r/\s+</, "<")
end
end

View file

@ -0,0 +1,59 @@
defmodule TarakanWeb.JobsLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
import Tarakan.WorkFixtures
test "renders the public jobs queue for anonymous visitors", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/jobs")
assert html =~ "Jobs"
assert html =~ "tarakan login"
assert html =~ "tarakan --agent kimi --pickup"
assert html =~ "tarakan worker --agent kimi"
end
test "lists open public jobs", %{conn: conn} do
submitter = account_fixture()
repository = listed_github_repository_fixture(submitter)
task =
review_task_fixture(repository, submitter, %{
"title" => "Review auth middleware",
"visibility" => "public"
})
{:ok, view, html} = live(conn, ~p"/jobs")
assert has_element?(view, "#job-#{task.id}")
assert html =~ "Review auth middleware"
end
test "check jobs surface before ordinary open jobs", %{conn: conn} do
submitter = account_fixture()
repository = listed_github_repository_fixture(submitter)
ordinary =
review_task_fixture(repository, submitter, %{
"title" => "Ordinary code review job",
"kind" => "code_review",
"visibility" => "public"
})
# Publishing a Report with findings auto-opens a verify_findings Job.
_scan =
scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
check =
Tarakan.Work.list_open_public_tasks(20)
|> Enum.find(&(&1.kind == "verify_findings" and &1.repository_id == repository.id))
assert check
{:ok, _view, html} = live(conn, ~p"/jobs")
check_pos = :binary.match(html, "job-#{check.id}") |> elem(0)
ordinary_pos = :binary.match(html, "job-#{ordinary.id}") |> elem(0)
assert check_pos < ordinary_pos
end
end

View file

@ -0,0 +1,111 @@
defmodule TarakanWeb.LeaderboardLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
defp verified_contributor do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
confirmation_fixture(scan, reviewer_account_fixture())
confirmation_fixture(scan, reviewer_account_fixture())
{submitter, repository}
end
test "renders ranked contributors linking to their profiles", %{conn: conn} do
{submitter, _repository} = verified_contributor()
{:ok, view, _html} = live(conn, ~p"/leaderboard")
assert has_element?(view, "#leaderboard-rank-1")
assert has_element?(view, ~s(#leaderboard a[href="/#{submitter.handle}"]))
# The distinct verified canonical finding (+30) puts the submitter on top;
# the report occurrence itself is not a second reputation event.
assert has_element?(view, "#leaderboard-rank-1", submitter.handle)
assert has_element?(view, "#leaderboard-rank-1", "30")
end
test "the leaderboard can be re-sorted", %{conn: conn} do
verified_contributor()
{:ok, view, _html} = live(conn, ~p"/leaderboard")
html = view |> element("#leaderboard-sort button[phx-value-by='findings']") |> render_click()
assert_patch(view, ~p"/leaderboard?sort=findings")
assert html =~ ~s(aria-pressed="true")
end
test "filter controls render and patching filters the entries", %{conn: conn} do
{submitter, _repository} = verified_contributor()
{:ok, view, _html} = live(conn, ~p"/leaderboard")
assert has_element?(view, "#leaderboard-severity")
assert has_element?(view, "#leaderboard-window")
assert has_element?(view, "#leaderboard-rank-1")
# The fixture's findings are "high"; filtering to critical empties the board.
view |> element("#leaderboard-severity-form") |> render_change(%{"severity" => "critical"})
assert_patch(view, ~p"/leaderboard?severity=critical")
assert has_element?(view, "#leaderboard-empty")
refute has_element?(view, "#leaderboard-rank-1")
# Clearing the severity brings the contributor back; the window tabs patch too.
view |> element("#leaderboard-severity-form") |> render_change(%{"severity" => ""})
assert has_element?(view, "#leaderboard-rank-1", submitter.handle)
view |> element("#leaderboard-window button[phx-value-window='7']") |> render_click()
assert_patch(view, ~p"/leaderboard?window=7")
assert has_element?(view, "#leaderboard-rank-1", submitter.handle)
end
test "rows surface slashed stakes", %{conn: conn} do
{submitter, repository} = verified_contributor()
# A second report (a distinct finding) is refuted by a dispute quorum.
refuted =
scan_fixture(repository, submitter, %{
"findings_json" =>
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => "lib/example/other.ex",
"severity" => "high",
"title" => "Refuted finding #{System.unique_integer([:positive])}",
"description" => "Slashed stake fixture."
}
]
})
})
confirmation_fixture(refuted, reviewer_account_fixture(), "disputed")
confirmation_fixture(refuted, reviewer_account_fixture(), "disputed")
{:ok, view, _html} = live(conn, ~p"/leaderboard")
assert has_element?(view, "#leaderboard-rank-1", "1 slashed")
end
test "an empty record shows the empty state", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/leaderboard")
assert has_element?(view, "#leaderboard-empty")
end
test "rows show earned badge chips after the handle", %{conn: conn} do
{submitter, _repository} = verified_contributor()
{:ok, view, _html} = live(conn, ~p"/leaderboard")
assert has_element?(view, "#leaderboard-rank-1-badge-first_blood", "First blood")
refute has_element?(view, "#leaderboard-rank-1-badge-century")
# The reviewer accounts checked the report but earned no badges, so their
# rows (if ranked) carry no chips.
html = render(view)
assert html =~ submitter.handle
end
test "the header links to the leaderboard", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/")
assert has_element?(view, ~s(a[href="/leaderboard"]))
end
end

View file

@ -0,0 +1,72 @@
defmodule TarakanWeb.ModelAnalyticsLiveTest do
use TarakanWeb.ConnCase, async: true
import Phoenix.LiveViewTest
alias Tarakan.Repo
alias Tarakan.Scans.CanonicalFinding
defp confirm_findings(scan) do
for occurrence <- scan.findings do
CanonicalFinding
|> Repo.get!(occurrence.canonical_finding_id)
|> Ecto.Changeset.change(status: "verified")
|> Repo.update!()
end
end
test "says so plainly when nothing has been reported", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/models")
assert html =~ "No model has reported enough findings yet"
end
# The scoreboard hides models below five reported findings, so both models
# need a real body of work before they show up at all.
defp unrelated_findings_json(count) do
findings =
for index <- 1..count do
%{
"file" => "lib/unrelated/module_#{index}.ex",
"line_start" => index * 7,
"line_end" => index * 7 + 2,
"severity" => "low",
"title" => "Unrelated observation (#{index})",
"description" => "Something else entirely."
}
end
Jason.encode!(%{"tarakan_scan_format" => 1, "findings" => findings})
end
test "scores models and lists the selected model's blind spots", %{conn: conn} do
account = github_account_fixture()
repository = github_repository_fixture(account)
found =
scan_fixture(repository, account, %{
"model" => "sharp-model",
"findings_json" => findings_json_fixture(5)
})
confirm_findings(found)
scan_fixture(repository, account, %{
"model" => "blunt-model",
"findings_json" => unrelated_findings_json(5)
})
{:ok, view, html} = live(conn, ~p"/models")
assert html =~ "sharp-model"
assert html =~ "blunt-model"
html =
view
|> element("#model-row-blunt-model")
|> render_click()
assert html =~ "Blind spots"
assert html =~ "Unsanitized input reaches interpolated query"
end
end

View file

@ -0,0 +1,207 @@
defmodule TarakanWeb.ModerationLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
alias Tarakan.Accounts
alias Tarakan.Accounts.Scope
alias Tarakan.Moderation
test "reporting requires an authenticated account", %{conn: conn} do
assert {:error, {:redirect, %{to: "/accounts/log-in"}}} =
live(conn, ~p"/moderation/report")
end
test "a participant submits a restricted report and can inspect its case", %{conn: conn} do
reporter = account_fixture()
subject = account_fixture()
conn = log_in_account(conn, reporter)
{:ok, view, _html} =
live(conn, ~p"/moderation/report?subject_type=account&subject_id=#{subject.id}")
assert has_element?(view, "#moderation-report-form")
assert has_element?(view, "#header-report-content")
refute has_element?(view, "#header-moderation-queue")
view
|> form("#moderation-report-form",
report: %{
subject_type: "account",
subject_id: subject.id,
reason: "harassment",
description: "This account is posting targeted harassment in public review evidence."
}
)
|> render_submit()
{path, flash} = assert_redirect(view)
assert path =~ ~r{^/moderation/cases/\d+$}
assert flash["info"]
{:ok, case_view, _html} = live(conn, path)
assert has_element?(case_view, "#moderation-case")
assert has_element?(case_view, "#moderation-case-status", "Open")
refute has_element?(case_view, "#moderation-case-actions")
refute has_element?(case_view, "#moderation-case-assignment")
end
test "an ordinary account cannot open the moderator queue", %{conn: conn} do
conn = log_in_account(conn, account_fixture())
assert {:error, {:redirect, %{to: "/"}}} = live(conn, ~p"/moderation/queue")
end
test "a moderator assigns and resolves a queued report", %{conn: conn} do
case_record = report_account!(account_fixture(), account_fixture())
moderator = moderator_account_fixture()
conn = log_in_account(conn, moderator)
{:ok, queue_view, _html} = live(conn, ~p"/moderation/queue")
assert has_element?(queue_view, "#header-moderation-queue")
assert has_element?(queue_view, "#moderation-case-count", "1 open")
assert has_element?(queue_view, "#assign-moderation-case-#{case_record.id}")
queue_view
|> element("#assign-moderation-case-#{case_record.id}")
|> render_click()
assert has_element?(queue_view, "#cases-#{case_record.id}", "In review")
{:ok, case_view, _html} = live(conn, ~p"/moderation/cases/#{case_record.id}")
assert has_element?(case_view, "#moderation-case-decision-form")
case_view
|> form("#moderation-case-decision-form",
resolution: %{
reason: "The evidence was independently reviewed and confirms a policy violation."
}
)
|> render_submit(%{"disposition" => "resolved"})
assert has_element?(case_view, "#moderation-case-status", "Resolved")
assert has_element?(case_view, "#moderation-case-resolution")
refute has_element?(case_view, "#moderation-case-decision-form")
end
test "the subject can appeal without receiving participant identity data", %{conn: conn} do
reporter = account_fixture()
subject = account_fixture()
resolver = moderator_account_fixture()
case_record =
reporter
|> report_account!(subject)
|> resolve_case!(resolver, "resolved")
conn = log_in_account(conn, subject)
{:ok, view, _html} = live(conn, ~p"/moderation/cases/#{case_record.id}")
assert has_element?(view, "#moderation-appeal-form")
refute has_element?(view, "#moderation-case-actions")
view
|> form("#moderation-appeal-form",
appeal: %{
reason: "The decision cites evidence from a different account and should be reconsidered."
}
)
|> render_submit()
assert has_element?(view, "#moderation-case-appeals")
assert has_element?(view, "#moderation-case-appeals", "Open")
refute has_element?(view, "#moderation-appeal-form")
refute has_element?(view, "#moderation-case-actions")
end
test "an independent moderator decides an appeal", %{conn: conn} do
reporter = account_fixture()
subject = account_fixture()
resolver = moderator_account_fixture()
appeal_moderator = moderator_account_fixture()
case_record =
reporter
|> report_account!(subject)
|> resolve_case!(resolver, "resolved")
{:ok, appeal} =
Moderation.appeal(Accounts.scope_for_account(subject), case_record, %{
"reason" =>
"The original decision relied on unrelated evidence and needs independent review."
})
conn = log_in_account(conn, appeal_moderator)
{:ok, view, _html} = live(conn, ~p"/moderation/cases/#{case_record.id}")
assert has_element?(view, "#moderation-appeal-decision-form-#{appeal.id}")
view
|> form("#moderation-appeal-decision-form-#{appeal.id}",
appeal_decision: %{
appeal_id: appeal.id,
reason: "Independent review confirms the original evidence was unrelated."
}
)
|> render_submit(%{"decision" => "upheld"})
assert has_element?(view, "#moderation-case-status", "Overturned")
assert has_element?(view, "#moderation-appeal-#{appeal.id}", "Upheld")
refute has_element?(view, "#moderation-appeal-decision-form-#{appeal.id}")
end
test "an expired sudo session redirects resolution to re-authentication", %{conn: conn} do
case_record = report_account!(account_fixture(), account_fixture())
moderator = moderator_account_fixture()
{:ok, assigned} = Moderation.assign(Scope.for_account(moderator), case_record)
# Outside the two-hour sudo window.
stale_at = DateTime.add(DateTime.utc_now(), -3, :hour)
conn = log_in_account(conn, moderator, token_authenticated_at: stale_at)
{:ok, case_view, _html} = live(conn, ~p"/moderation/cases/#{assigned.id}")
assert has_element?(case_view, "#moderation-case-decision-form")
assert {:error,
{:live_redirect, %{to: "/accounts/log-in?return_to=%2Fmoderation%2Fcases%2F" <> _}}} =
case_view
|> form("#moderation-case-decision-form",
resolution: %{
reason: "The evidence was independently reviewed and confirms a violation."
}
)
|> render_submit(%{"disposition" => "resolved"})
{:ok, unresolved} = Moderation.get_case(Scope.for_account(moderator), assigned.id)
assert unresolved.status == "in_review"
end
defp report_account!(reporter, subject) do
{:ok, case_record} =
Moderation.report(Scope.for_account(reporter), %{
"subject_type" => "account",
"subject_id" => subject.id,
"reason" => "fabricated_evidence",
"description" => "The submitted evidence appears fabricated and needs independent review."
})
case_record
end
defp resolve_case!(case_record, moderator, disposition) do
{:ok, assigned} = Moderation.assign(Scope.for_account(moderator), case_record)
{:ok, decided} =
Moderation.resolve(
Scope.for_account(moderator),
assigned,
disposition,
"The evidence was independently reviewed and supports this moderation decision."
)
decided
end
end

View file

@ -0,0 +1,98 @@
defmodule TarakanWeb.PageLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
test "the disclosure policy page renders its sections", %{conn: conn} do
html = conn |> get(~p"/policies/disclosure") |> html_response(200)
assert html =~ "Disclosure policy"
assert html =~ "Public by default"
assert html =~ "Visibility levels"
assert html =~ "public_summary"
assert html =~ "restricted"
assert html =~ "Verification quorum"
assert html =~ "Vendor notification"
assert html =~ "security.txt"
end
test "the content policy page renders its sections", %{conn: conn} do
html = conn |> get(~p"/policies/content") |> html_response(200)
assert html =~ "Content policy"
assert html =~ "Allowed content"
assert html =~ "Prohibited content"
assert html =~ "Secrets and credentials"
assert html =~ "Takedowns and appeals"
end
test "the pricing page renders the free record, bounties, and managed disclosure",
%{conn: conn} do
html = conn |> get(~p"/pricing") |> html_response(200)
assert html =~ ~s(id="pricing-free")
assert html =~ ~s(id="pricing-contracts")
assert html =~ ~s(id="pricing-managed")
assert html =~ "Tarakan keeps 10%"
assert html =~ "mailto:"
# No paid tiers, and the user-facing word is "contract", never "bounty".
refute html =~ ~s(id="pricing-team")
refute html =~ "Vaccine packs"
refute html =~ "bounty"
refute html =~ "Bounties"
end
test "the pricing checkout POST redirects anonymous visitors to login", %{conn: conn} do
conn = post(conn, ~p"/billing/checkout", %{"plan" => "team"})
assert redirected_to(conn) =~ "/accounts/log-in"
end
test "the managed disclosure page renders its sections", %{conn: conn} do
html = conn |> get(~p"/services/disclosure") |> html_response(200)
assert html =~ "Managed disclosure"
assert html =~ "What it is"
assert html =~ "Handling, not suppression"
assert html =~ "Intake"
assert html =~ ~s(id="managed-disclosure-contact")
assert html =~ "mailto:"
end
test "the pricing checkout POST redirects to Stripe for members", %{conn: conn} do
conn =
conn
|> log_in_account(account_fixture())
|> post(~p"/billing/checkout", %{"plan" => "enterprise"})
assert redirected_to(conn) =~ "https://checkout.stripe.com/"
end
# These were plain controller pages, the only routes in the shell without a
# LiveSocket. That made navigating to them a full reload and left them out of
# anything driven by live navigation.
test "the static pages are LiveViews", %{conn: conn} do
for path <- ["/pricing", "/policies/disclosure", "/policies/content", "/services/disclosure"] do
assert {:ok, _view, _html} = live(conn, path)
end
end
test "pricing marks its own nav entry active", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/pricing")
assert html =~ ~r/href="\/pricing"[^>]*aria-current="page"/
end
test "nav links live-navigate between a LiveView and a policy page", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/leaderboard")
assert {:ok, _pricing, html} =
view
|> element(~s(nav[aria-label="Primary"] a[href="/pricing"]))
|> render_click()
|> follow_redirect(conn, ~p"/pricing")
assert html =~ "Pricing"
end
end

View file

@ -0,0 +1,101 @@
defmodule TarakanWeb.ProfileLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
test "renders a contributor profile with public contribution counts", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(2)})
confirmation_fixture(scan, reviewer_account_fixture())
{:ok, view, _html} = live(conn, ~p"/#{submitter.handle}")
assert has_element?(view, "#profile-handle", submitter.handle)
assert has_element?(view, "#profile-review-count", "1")
assert has_element?(view, "#profile-finding-count", "2")
assert has_element?(view, "#profile-repo-count", "1")
assert has_element?(view, "#profile-reviews", "reviewed")
assert has_element?(view, "#profile-repositories", repository.name)
assert has_element?(view, "#profile-findings")
end
test "a moderator profile shows the role badge", %{conn: conn} do
moderator = moderator_account_fixture()
{:ok, view, _html} = live(conn, ~p"/#{moderator.handle}")
assert has_element?(view, "#profile-role", "Moderator")
end
test "an unknown handle returns not found", %{conn: conn} do
assert_error_sent 404, fn -> get(conn, ~p"/#{"ghost-nobody"}") end
end
test "a submitter handle on the security page links to the profile", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
{:ok, view, _html} = live(conn, ~p"/github.com/openai/codex/security")
assert has_element?(view, ~s(a[href="/#{submitter.handle}"]))
end
test "finding rows link to the finding page", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan = scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
finding = hd(scan.findings || Tarakan.Repo.preload(scan, :findings).findings)
{:ok, view, _html} = live(conn, ~p"/#{submitter.handle}")
assert has_element?(
view,
~s(#profile-finding-#{finding.public_id} a[href="/findings/#{finding.public_id}"])
)
end
test "renders the credits tile and the recent ledger", %{conn: conn} do
account = account_fixture()
{:ok, _entry} =
Tarakan.Credits.credit(account, :mint_finding_verified, {"canonical_finding", 1})
{:ok, _entry} = Tarakan.Credits.debit(account, :spend_priority_boost, nil, 20)
{:ok, view, _html} = live(conn, ~p"/#{account.handle}")
assert has_element?(view, "#profile-credit-balance", "30")
assert has_element?(view, "#profile-credits", "mint finding verified")
assert has_element?(view, "#profile-credits", "+50")
assert has_element?(view, "#profile-credits", "-20")
assert has_element?(view, "#profile-credits", "balance 30")
end
test "renders an empty credits ledger", %{conn: conn} do
account = account_fixture()
{:ok, view, _html} = live(conn, ~p"/#{account.handle}")
assert has_element?(view, "#profile-credit-balance", "0")
assert has_element?(view, "#profile-no-credits")
end
test "the badge strip renders earned badges only", %{conn: conn} do
submitter = github_account_fixture()
repository = listed_github_repository_fixture(submitter)
scan_fixture(repository, submitter, %{"findings_json" => findings_json_fixture(1)})
{:ok, view, _html} = live(conn, ~p"/#{submitter.handle}")
assert has_element?(view, "#profile-badges")
assert has_element?(view, "#profile-badge-first_blood", "First blood")
refute has_element?(view, "#profile-badge-century")
refute has_element?(view, "#profile-badge-sharpshooter")
end
test "a profile without earned badges renders no badge strip", %{conn: conn} do
account = account_fixture()
{:ok, view, _html} = live(conn, ~p"/#{account.handle}")
refute has_element?(view, "#profile-badges")
end
end

View file

@ -0,0 +1,411 @@
defmodule TarakanWeb.RepositoryCodeLiveTest do
use TarakanWeb.ConnCase, async: false
import Phoenix.LiveViewTest
alias Tarakan.Accounts.Scope
alias Tarakan.RepositoryCode.Cache
alias Tarakan.Scans
@default_commit_sha String.duplicate("7", 40)
# develop branch tip in the GitHub stub (must remain a real branch tip).
@develop_commit_sha String.duplicate("8", 40)
# A fetchable commit that is not the tip of any published branch (and not a
# special-cased stub SHA such as all-c truncated trees).
@historical_commit_sha String.duplicate("b", 40)
setup do
Cache.clear()
repository = listed_github_repository_fixture()
%{repository: repository}
end
test "repository roots open the code browser by default", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/github.com/openai/codex")
render_async(view, 1_000)
assert has_element?(view, "#repository-navigation")
assert has_element?(view, "#repository-code-tab[aria-current='page']", "Code")
assert has_element?(
view,
"#repository-overview-tab[href='/github.com/openai/codex/security']"
)
assert has_element?(view, "#code-tree")
end
test "the legacy code entry route still opens the default tree", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/github.com/openai/codex/code")
render_async(view, 1_000)
assert has_element?(view, "#code-tree")
assert has_element?(view, "#code-commit-sha", String.slice(@default_commit_sha, 0, 7))
end
test "browses directories at the freshly resolved default commit", %{conn: conn} do
{:ok, view, _html} =
live(conn, ~p"/github.com/openai/codex/code/#{@default_commit_sha}")
render_async(view, 1_000)
assert has_element?(view, "#code-tree")
assert has_element?(view, "#code-tree-entries [id^='code-entry-']", "lib")
assert has_element?(
view,
"#code-tree-entries a[href='/github.com/openai/codex/code/#{@default_commit_sha}/README.md']"
)
end
test "round-trips encoded spaces, percent signs, fragments, and Unicode filenames", %{
conn: conn
} do
root = "/github.com/openai/codex/code/#{@default_commit_sha}"
{:ok, tree_view, _html} = live(conn, root)
render_async(tree_view, 1_000)
assert has_element?(
tree_view,
"a[href='#{root}/space%20%23%20100%25.txt']",
"space # 100%.txt"
)
assert has_element?(tree_view, "a[href='#{root}/%CE%BB.ex']", "λ.ex")
{:ok, encoded_view, _html} = live(conn, root <> "/space%20%23%20100%25.txt")
render_async(encoded_view, 1_000)
assert has_element?(encoded_view, "#code-file", "space # 100%.txt")
assert has_element?(encoded_view, "#L1 code", "# Codex")
{:ok, unicode_view, _html} = live(conn, root <> "/%CE%BB.ex")
render_async(unicode_view, 1_000)
assert has_element?(unicode_view, "#code-file", "λ.ex")
assert has_element?(unicode_view, "#L1 code", "defmodule Codex")
end
test "folder and file rows show findings for the pinned commit", %{
conn: conn,
repository: repository
} do
scan = finding_scan_fixture(repository, account_fixture(), @default_commit_sha)
_scan = publish_full_scan(repository, scan)
{:ok, root_view, _html} = live(conn, ~p"/github.com/openai/codex")
render_async(root_view, 1_000)
assert has_element?(root_view, "#code-entry-bGli-findings", "1 finding")
assert has_element?(root_view, "#code-reference", "1 finding")
{:ok, lib_view, _html} =
live(conn, ~p"/github.com/openai/codex/code/#{@default_commit_sha}/lib")
render_async(lib_view, 1_000)
assert has_element?(lib_view, "#code-entry-bGliL2NvZGV4LmV4-findings", "1 finding")
end
test "public summaries do not leak file paths through code-row badges", %{
conn: conn,
repository: repository
} do
scan = finding_scan_fixture(repository, account_fixture(), @default_commit_sha)
scan = confirmation_fixture(scan, reviewer_account_fixture())
scan = confirmation_fixture(scan, reviewer_account_fixture())
moderator_scope = Scope.for_account(moderator_account_fixture())
{:ok, accepted} = Scans.accept_scan(moderator_scope, scan, moderation_attributes())
{:ok, _summary} =
Scans.update_visibility(
moderator_scope,
accepted,
"public_summary",
moderation_attributes()
)
{:ok, view, _html} = live(conn, ~p"/github.com/openai/codex")
render_async(view, 1_000)
html = render(view)
refute has_element?(view, "[id$='-findings']")
refute html =~ "lib/codex.ex"
end
test "renders escaped plain-text lines with stable anchors and selection", %{conn: conn} do
{:ok, view, _html} =
live(
conn,
~p"/github.com/openai/codex/code/#{@default_commit_sha}/README.md?lines=1"
)
render_async(view, 1_000)
assert has_element?(view, "#code-file")
assert has_element?(view, "#L1.bg-panel")
assert has_element?(view, "#L1 code", "# Codex")
assert has_element?(
view,
"#L1 a[href='/github.com/openai/codex/code/#{@default_commit_sha}/README.md?lines=1#L1']"
)
end
test "rejects an out-of-range single-line selection", %{conn: conn} do
{:ok, view, _html} =
live(
conn,
~p"/github.com/openai/codex/code/#{@default_commit_sha}/README.md?lines=1000001"
)
render_async(view, 1_000)
assert has_element?(view, "#invalid-line-selection")
refute has_element?(view, "#code-lines .bg-panel")
end
test "renders hostile source as escaped text rather than executable markup", %{conn: conn} do
{:ok, view, _html} =
live(
conn,
~p"/github.com/openai/codex/code/#{@default_commit_sha}/unsafe.html"
)
render_async(view, 1_000)
html = render(view)
assert has_element?(view, "#L1 code", "</code><script id=\"source-xss\">alert(1)</script>")
refute has_element?(view, "script#source-xss")
assert html =~ "&lt;/code&gt;&lt;script id=&quot;source-xss&quot;&gt;"
end
test "rejects guessed historical SHAs on the generic browser", %{conn: conn} do
paths = [
~p"/github.com/openai/codex/code/#{@historical_commit_sha}",
~p"/github.com/openai/codex/code/#{@historical_commit_sha}/README.md"
]
for path <- paths do
{:ok, view, _html} = live(conn, path)
render_async(view, 1_000)
assert has_element?(view, "#code-browser-error")
assert has_element?(view, "#code-browser-error", "Source not found")
refute has_element?(view, "#code-tree")
refute has_element?(view, "#code-file")
end
end
test "branch switch opens another published branch tip", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/github.com/openai/codex/code/#{@default_commit_sha}")
render_async(view, 1_000)
assert has_element?(view, "#code-branch-select")
assert has_element?(view, "#code-tree")
view
|> form("#code-branch-form", %{branch: "develop"})
|> render_change()
path = ~p"/github.com/openai/codex/code/#{@develop_commit_sha}"
assert_redirect(view, path)
{:ok, switched, _html} = live(conn, path)
render_async(switched, 1_000)
assert has_element?(switched, "#code-tree")
assert has_element?(switched, "#code-commit-sha", String.slice(@develop_commit_sha, 0, 7))
assert has_element?(switched, ~s(#code-branch-select option[value="develop"][selected]))
end
test "deep link to a non-default branch tip works", %{conn: conn} do
{:ok, view, _html} =
live(conn, ~p"/github.com/openai/codex/code/#{@develop_commit_sha}/README.md")
render_async(view, 1_000)
assert has_element?(view, "#code-file")
assert has_element?(view, "#code-commit-sha", String.slice(@develop_commit_sha, 0, 7))
assert has_element?(view, ~s(#code-branch-select option[value="develop"][selected]))
end
test "rejects encoded traversal and backslash paths at the route boundary", %{conn: conn} do
unsafe_paths = [
"/github.com/openai/codex/code/#{@default_commit_sha}/lib/%2E%2E/README.md",
"/github.com/openai/codex/code/#{@default_commit_sha}/lib/%5C..%5Csecret"
]
for path <- unsafe_paths do
{:ok, view, _html} = live(conn, path)
assert has_element?(view, "#code-browser-error", "Invalid path")
refute has_element?(view, "#code-file")
end
end
test "an authorized opaque finding route opens historical source without leaking path in links",
%{
conn: conn,
repository: repository
} do
submitter = account_fixture()
scan = finding_scan_fixture(repository, submitter, @historical_commit_sha)
finding = hd(scan.findings)
{:ok, view, _html} =
live(log_in_account(conn, submitter), ~p"/findings/#{finding.public_id}/code")
render_async(view, 1_000)
assert has_element?(view, "#finding-code-context")
assert has_element?(view, "#code-file")
assert has_element?(view, "#L2.bg-panel")
refute has_element?(view, "#source-breadcrumbs a")
assert has_element?(view, "#L2 a[href='/findings/#{finding.public_id}/code#L2']")
end
test "the opaque route does not reveal a moderator-restricted finding to anonymous visitors",
%{
conn: conn,
repository: repository
} do
scan = finding_scan_fixture(repository, account_fixture(), @historical_commit_sha)
finding = hd(scan.findings)
moderator_scope = Scope.for_account(moderator_account_fixture())
{:ok, _restricted} =
Scans.update_visibility(moderator_scope, scan, "restricted", moderation_attributes())
assert_raise Ecto.NoResultsError, fn ->
live(conn, ~p"/findings/#{finding.public_id}/code")
end
end
test "marks a reported line range that does not exist at the pinned commit", %{
conn: conn,
repository: repository
} do
submitter = account_fixture()
scan = finding_scan_fixture(repository, submitter, @historical_commit_sha, 99)
finding = hd(scan.findings)
{:ok, view, _html} =
live(log_in_account(conn, submitter), ~p"/findings/#{finding.public_id}/code")
render_async(view, 1_000)
assert has_element?(view, "#finding-line-outside-file")
refute has_element?(view, "#code-lines .bg-panel")
end
test "finding source routes reject enumerable integer identifiers", %{conn: conn} do
assert_raise Ecto.NoResultsError, fn ->
live(conn, "/findings/1/code")
end
end
test "a connected finding view is evicted when a moderator restricts the scan", %{
conn: conn,
repository: repository
} do
scan = finding_scan_fixture(repository, account_fixture(), @historical_commit_sha)
scan = publish_full_scan(repository, scan)
finding = hd(scan.findings)
{:ok, view, _html} = live(conn, ~p"/findings/#{finding.public_id}/code")
render_async(view, 1_000)
assert has_element?(view, "#code-file")
moderator_scope = Scope.for_account(moderator_account_fixture())
assert {:ok, _restricted} =
Scans.update_visibility(moderator_scope, scan, "restricted", moderation_attributes())
assert_redirect(view, ~p"/github.com/openai/codex")
end
test "the default code page is uncached but remains indexable", %{conn: conn} do
conn = get(conn, ~p"/github.com/openai/codex")
assert html_response(conn, 200)
assert get_resp_header(conn, "cache-control") == ["no-store"]
assert get_resp_header(conn, "x-robots-tag") == []
end
test "commit-pinned code routes prohibit caches and search indexing", %{conn: conn} do
conn = get(conn, ~p"/github.com/openai/codex/code/#{@default_commit_sha}")
assert html_response(conn, 200)
assert get_resp_header(conn, "cache-control") == ["no-store"]
assert get_resp_header(conn, "x-robots-tag") == ["noindex, nofollow"]
end
test "opaque finding routes prohibit caches and search indexing", %{
conn: conn,
repository: repository
} do
scan = finding_scan_fixture(repository, account_fixture(), @historical_commit_sha)
finding = repository |> publish_full_scan(scan) |> Map.fetch!(:findings) |> hd()
conn = get(conn, ~p"/findings/#{finding.public_id}/code")
assert html_response(conn, 200)
assert get_resp_header(conn, "cache-control") == ["no-store"]
assert get_resp_header(conn, "x-robots-tag") == ["noindex, nofollow"]
end
defp finding_scan_fixture(repository, submitter, commit_sha, line_start \\ 2) do
document =
Jason.encode!(%{
"tarakan_scan_format" => 1,
"findings" => [
%{
"file" => "lib/codex.ex",
"line_start" => line_start,
"line_end" => line_start,
"severity" => "high",
"title" => "Authorization is not checked",
"description" => "A request reaches a privileged operation without a policy check."
}
]
})
scan_fixture(repository, submitter, %{
"commit_sha" => commit_sha,
"findings_json" => document
})
end
defp publish_full_scan(repository, scan) do
repository
|> Tarakan.Repositories.Repository.participation_changeset(%{
participation_mode: "maintainer_verified"
})
|> Tarakan.Repo.update!()
scan = confirmation_fixture(scan, reviewer_account_fixture())
scan = confirmation_fixture(scan, reviewer_account_fixture())
moderator_scope = Scope.for_account(moderator_account_fixture())
{:ok, accepted} = Scans.accept_scan(moderator_scope, scan, moderation_attributes())
{:ok, disclosed} =
Scans.update_visibility(
moderator_scope,
accepted,
"public",
moderation_attributes(%{"sensitive_data_reviewed" => "true"})
)
disclosed
end
defp moderation_attributes(overrides \\ %{}) do
Enum.into(overrides, %{
"moderation_reason" => "evidence_reviewed",
"moderation_notes" =>
"Independent evidence and disclosure boundaries were reviewed for this exact commit."
})
end
end

View file

@ -0,0 +1,273 @@
defmodule TarakanWeb.RepositoryCommitsLiveTest do
use TarakanWeb.ConnCase, async: false
import Phoenix.LiveViewTest
alias Tarakan.Accounts
alias Tarakan.HostedRepositories
alias Tarakan.HostedRepositories.Storage
@moduletag :tmp_dir
setup %{tmp_dir: tmp_dir} do
on_exit(fn ->
File.rm_rf(Application.fetch_env!(:tarakan, Tarakan.HostedRepositories)[:root])
end)
Tarakan.RepositoryCode.Cache.clear()
account = account_fixture()
scope = Accounts.scope_for_account(account)
{:ok, repository} = HostedRepositories.create(scope, %{"name" => "history"})
%{repository: repository, tmp_dir: tmp_dir}
end
defp push_commit(repository, tmp_dir, dir_name, message) do
work = Path.join(tmp_dir, dir_name)
{_output, 0} =
System.cmd("git", ["clone", "--quiet", Storage.dir(repository), work],
stderr_to_stdout: true
)
File.write!(Path.join(work, "README.md"), "# #{message}\n")
env = [
{"GIT_AUTHOR_NAME", "t"},
{"GIT_AUTHOR_EMAIL", "t@example.com"},
{"GIT_COMMITTER_NAME", "t"},
{"GIT_COMMITTER_EMAIL", "t@example.com"}
]
{_output, 0} = System.cmd("git", ["-C", work, "add", "."], env: env)
{_output, 0} = System.cmd("git", ["-C", work, "commit", "--quiet", "-m", message], env: env)
{_output, 0} =
System.cmd("git", ["-C", work, "push", "--quiet", "origin", "HEAD"],
env: env,
stderr_to_stdout: true
)
{sha, 0} = System.cmd("git", ["-C", work, "rev-parse", "HEAD"])
String.trim(sha)
end
defp push_merge_commit(repository, tmp_dir, dir_name, branch, message) do
work = Path.join(tmp_dir, dir_name)
{_output, 0} =
System.cmd("git", ["clone", "--quiet", Storage.dir(repository), work],
stderr_to_stdout: true
)
env = [
{"GIT_AUTHOR_NAME", "t"},
{"GIT_AUTHOR_EMAIL", "t@example.com"},
{"GIT_COMMITTER_NAME", "t"},
{"GIT_COMMITTER_EMAIL", "t@example.com"}
]
{main, 0} = System.cmd("git", ["-C", work, "rev-parse", "--abbrev-ref", "HEAD"])
main = String.trim(main)
{_output, 0} = System.cmd("git", ["-C", work, "checkout", "--quiet", "-b", branch], env: env)
File.write!(Path.join(work, "side.txt"), "side\n")
{_output, 0} = System.cmd("git", ["-C", work, "add", "."], env: env)
{_output, 0} =
System.cmd("git", ["-C", work, "commit", "--quiet", "-m", "side change"], env: env)
{_output, 0} = System.cmd("git", ["-C", work, "checkout", "--quiet", main], env: env)
File.write!(Path.join(work, "main.txt"), "main\n")
{_output, 0} = System.cmd("git", ["-C", work, "add", "."], env: env)
{_output, 0} =
System.cmd("git", ["-C", work, "commit", "--quiet", "-m", "main change"], env: env)
{_output, 0} =
System.cmd("git", ["-C", work, "merge", "--quiet", "--no-ff", "-m", message, branch],
env: env,
stderr_to_stdout: true
)
{_output, 0} =
System.cmd("git", ["-C", work, "push", "--quiet", "origin", "HEAD"],
env: env,
stderr_to_stdout: true
)
{sha, 0} = System.cmd("git", ["-C", work, "rev-parse", "HEAD"])
String.trim(sha)
end
defp push_branch_commit(repository, tmp_dir, dir_name, branch, message) do
work = Path.join(tmp_dir, dir_name)
{_output, 0} =
System.cmd("git", ["clone", "--quiet", Storage.dir(repository), work],
stderr_to_stdout: true
)
File.write!(Path.join(work, "FEATURE.md"), "# #{message}\n")
env = [
{"GIT_AUTHOR_NAME", "t"},
{"GIT_AUTHOR_EMAIL", "t@example.com"},
{"GIT_COMMITTER_NAME", "t"},
{"GIT_COMMITTER_EMAIL", "t@example.com"}
]
{_output, 0} = System.cmd("git", ["-C", work, "checkout", "--quiet", "-b", branch], env: env)
{_output, 0} = System.cmd("git", ["-C", work, "add", "."], env: env)
{_output, 0} = System.cmd("git", ["-C", work, "commit", "--quiet", "-m", message], env: env)
{_output, 0} =
System.cmd("git", ["-C", work, "push", "--quiet", "origin", branch],
env: env,
stderr_to_stdout: true
)
{sha, 0} = System.cmd("git", ["-C", work, "rev-parse", "HEAD"])
String.trim(sha)
end
test "lists the default branch history and links each commit to its detail page", %{
conn: conn,
repository: repository,
tmp_dir: tmp_dir
} do
first_sha = push_commit(repository, tmp_dir, "work-first", "initial")
tip = push_commit(repository, tmp_dir, "work-second", "second")
{:ok, view, _html} = live(conn, "/#{repository.owner}/#{repository.name}/commits")
render_async(view, 1_000)
assert has_element?(view, "#repository-commits-tab[aria-current='page']")
# The active tab is still a link: from a commit detail page it points at the
# commit list, which is the obvious way back and used to be unclickable.
assert has_element?(view, "a#repository-commits-tab[aria-current='page'][href]")
assert has_element?(view, "#commits-list a", "second")
assert has_element?(view, "#commits-list a", "initial")
assert has_element?(
view,
"#commits-list a[href='/#{repository.owner}/#{repository.name}/commits/#{tip}']"
)
assert has_element?(
view,
"#commits-list a[href='/#{repository.owner}/#{repository.name}/commits/#{first_sha}']"
)
refute has_element?(view, "#commits-load-more")
end
test "the commit detail page shows the full message, patch, and code link", %{
conn: conn,
repository: repository,
tmp_dir: tmp_dir
} do
_first_sha = push_commit(repository, tmp_dir, "work-first", "initial")
tip = push_commit(repository, tmp_dir, "work-second", "second")
{:ok, view, _html} =
live(conn, "/#{repository.owner}/#{repository.name}/commits/#{tip}")
render_async(view, 1_000)
assert has_element?(view, "#commit-subject", "second")
assert has_element?(view, "#commit-detail-sha", String.slice(tip, 0, 7))
assert has_element?(view, "#commit-patch", "+# second")
assert has_element?(
view,
"#commit-browse-code[href='/#{repository.owner}/#{repository.name}/code/#{tip}']"
)
# The code link opens the browser pinned at this exact commit.
{:ok, code_view, _html} = live(conn, "/#{repository.owner}/#{repository.name}/code/#{tip}")
render_async(code_view, 1_000)
assert has_element?(code_view, "#code-tree")
end
test "merge commits render with an empty patch state", %{
conn: conn,
repository: repository,
tmp_dir: tmp_dir
} do
_main_sha = push_commit(repository, tmp_dir, "work-first", "initial")
merge_sha = push_merge_commit(repository, tmp_dir, "work-merge", "side", "merge side")
{:ok, view, _html} =
live(conn, "/#{repository.owner}/#{repository.name}/commits/#{merge_sha}")
render_async(view, 1_000)
assert has_element?(view, "#commit-subject", "merge side")
assert has_element?(view, "#commit-patch-empty", "No textual changes")
refute has_element?(view, "#commits-error")
end
test "the commit detail page rejects unreachable commits", %{
conn: conn,
repository: repository,
tmp_dir: tmp_dir
} do
_sha = push_commit(repository, tmp_dir, "work-first", "initial")
unknown = String.duplicate("d", 40)
{:ok, view, _html} =
live(conn, "/#{repository.owner}/#{repository.name}/commits/#{unknown}")
render_async(view, 1_000)
assert has_element?(view, "#commits-error", "Commit not found")
refute has_element?(view, "#commit-detail")
end
test "the branch picker switches the listed history", %{
conn: conn,
repository: repository,
tmp_dir: tmp_dir
} do
_main_sha = push_commit(repository, tmp_dir, "work-first", "initial")
feature_sha =
push_branch_commit(repository, tmp_dir, "work-feature", "feature", "feature work")
{:ok, view, _html} = live(conn, "/#{repository.owner}/#{repository.name}/commits")
render_async(view, 1_000)
assert has_element?(view, "#commits-branch-select")
refute has_element?(view, "#commits-list a", "feature work")
view
|> form("#commits-branch-form", %{branch: "feature"})
|> render_change()
render_async(view, 1_000)
assert has_element?(view, "#commits-list a", "feature work")
assert has_element?(
view,
"#commits-list a[href='/#{repository.owner}/#{repository.name}/commits/#{feature_sha}']"
)
end
test "an empty repository shows an empty state", %{conn: conn, repository: repository} do
{:ok, view, _html} = live(conn, "/#{repository.owner}/#{repository.name}/commits")
render_async(view, 1_000)
assert has_element?(view, "#commits-error", "No commits yet")
refute has_element?(view, "#commits-list")
end
test "unknown repositories 404", %{conn: conn} do
assert_raise Ecto.NoResultsError, fn ->
live(conn, "/nobody/here/commits")
end
end
end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,111 @@
defmodule TarakanWeb.RepositoryNewLiveTest do
use TarakanWeb.ConnCase, async: false
import Phoenix.LiveViewTest
alias Tarakan.HostedRepositories
alias Tarakan.Repositories
setup :register_and_log_in_account
setup do
on_exit(fn ->
File.rm_rf(Application.fetch_env!(:tarakan, Tarakan.HostedRepositories)[:root])
end)
:ok
end
test "requires authentication" do
conn = Phoenix.ConnTest.build_conn()
assert {:error, {:redirect, %{to: path}}} = live(conn, ~p"/repositories/new")
assert path =~ "/accounts/log-in"
end
test "creates a hosted repository and navigates to it", %{conn: conn, account: account} do
{:ok, view, _html} = live(conn, ~p"/repositories/new")
assert has_element?(view, "#new-repository-form")
view
|> form("#new-repository-form", repository: %{name: "from-the-ui"})
|> render_submit()
assert_redirect(view, "/#{account.handle}/from-the-ui")
assert HostedRepositories.resolve(account.handle, "from-the-ui")
# the bare GitHub-style path must dispatch through the hosted scope
{:ok, repo_view, _html} = live(conn, "/#{account.handle}/from-the-ui")
assert has_element?(repo_view, "#repository-name")
end
test "shows validation errors inline", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/repositories/new")
html =
view
|> form("#new-repository-form", repository: %{name: "bad name"})
|> render_submit()
assert html =~ "may only contain"
end
describe "remote registration" do
setup %{conn: conn} do
%{conn: log_in_account(conn, github_account_fixture())}
end
test "registers a repository and opens its public record", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/repositories/new")
view
|> form("#register-remote-form", repository: %{url: "github.com/OpenAI/Codex"})
|> render_submit()
assert_redirect(view, ~p"/github.com/openai/codex")
assert Repositories.get_github_repository("openai", "codex")
{:ok, record_view, _html} = live(conn, ~p"/github.com/openai/codex/security")
assert has_element?(record_view, "#repository-name")
assert has_element?(record_view, "#repository-source-link")
assert has_element?(record_view, "#github-metadata")
assert has_element?(record_view, "#repository-submitter")
assert has_element?(record_view, "#scans-empty")
end
test "shows a useful error for an invalid repository", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/repositories/new")
view
|> form("#register-remote-form",
repository: %{url: "https://example.com/not/github"}
)
|> render_submit()
assert has_element?(view, "#repository_url-error")
end
test "rejects a valid-looking repository that GitHub cannot find", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/repositories/new")
view
|> form("#register-remote-form", repository: %{url: "missing/repository"})
|> render_submit()
assert has_element?(view, "#repository_url-error")
refute Repositories.get_github_repository("missing", "repository")
end
test "shows the same safe error for a private repository", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/repositories/new")
view
|> form("#register-remote-form", repository: %{url: "private/repository"})
|> render_submit()
assert has_element?(view, "#repository_url-error")
refute Repositories.get_github_repository("private", "repository")
end
end
end

View file

@ -0,0 +1,367 @@
defmodule TarakanWeb.ReviewTaskLiveTest do
use TarakanWeb.ConnCase
import Phoenix.LiveViewTest
setup %{conn: conn} do
creator = github_account_fixture()
repository = listed_github_repository_fixture(creator)
task = review_task_fixture(repository, creator)
%{conn: conn, creator: creator, repository: repository, task: task}
end
test "the public can inspect a task but cannot claim anonymously", %{conn: conn, task: task} do
{:ok, view, _html} = live(conn, ~p"/jobs/#{task.id}")
assert has_element?(view, "#review-task-title")
assert has_element?(view, "#review-task-status", "Open")
refute has_element?(view, "#claim-review-task-button")
html = render_hook(view, "claim", %{})
assert html =~ "not authorized"
html = render_hook(view, "review", %{"action" => "invented", "decision" => %{}})
assert html =~ "review action is invalid"
assert {:error, {:live_redirect, %{to: "/accounts/log-in?return_to=%2Fjobs%2F" <> _}}} =
render_hook(view, "publish", %{"decision" => %{}})
end
test "the task creator may claim and perform their own job", %{
conn: conn,
creator: creator,
task: task
} do
conn = log_in_account(conn, creator)
{:ok, view, _html} = live(conn, ~p"/jobs/#{task.id}")
assert has_element?(view, "#claim-review-task-button")
refute has_element?(view, "#review-task-own-notice")
view |> element("#claim-review-task-button") |> render_click()
assert has_element?(view, "#review-task-status", "Claimed")
assert has_element?(view, "#review-task-completion-form")
refute has_element?(view, "#review-task-agent-path")
end
test "agent-required jobs show the CLI path instead of free-text completion", %{
conn: conn,
creator: creator,
repository: repository
} do
task =
review_task_fixture(repository, creator, %{
"kind" => "code_review",
"capability" => "agent",
"title" => "Agent code review of auth boundaries"
})
worker = account_fixture()
conn = log_in_account(conn, worker)
{:ok, view, _html} = live(conn, ~p"/jobs/#{task.id}")
assert has_element?(view, "#review-task-title")
assert has_element?(view, "#review-task", "Agent required")
view |> element("#claim-review-task-button") |> render_click()
assert has_element?(view, "#review-task-status", "Claimed")
assert has_element?(view, "#review-task-agent-path")
refute has_element?(view, "#review-task-completion-form")
assert render(view) =~ "tarakan report"
assert render(view) =~ "--job #{task.id}"
end
test "agent check jobs show only the check command and their target findings", %{
conn: conn,
creator: creator,
repository: repository
} do
report =
scan_fixture(repository, account_fixture(), %{"findings_json" => findings_json_fixture()})
task =
review_task_fixture(repository, creator, %{
"kind" => "verify_findings",
"capability" => "agent",
"target_review_id" => report.id,
"title" => "Independently check the report"
})
worker = reviewer_account_fixture()
{:ok, view, _html} =
conn
|> log_in_account(worker)
|> live(~p"/jobs/#{task.id}")
assert has_element?(view, "#review-task-target-report", "Target report ##{report.id}")
assert has_element?(view, "#review-task-target-report", "Unsanitized input")
view |> element("#claim-review-task-button") |> render_click()
assert has_element?(view, "#review-task-agent-path")
assert render(view) =~ "tarakan worker --agent grok --once --jobs-only"
refute render(view) =~ "tarakan report"
end
test "a hybrid claimant can verify a report from the web", %{
conn: conn,
creator: creator,
repository: repository
} do
report =
scan_fixture(repository, account_fixture(), %{"findings_json" => findings_json_fixture()})
task =
review_task_fixture(repository, creator, %{
"kind" => "verify_findings",
"capability" => "hybrid",
"target_review_id" => report.id,
"title" => "Reproduce the reported data flow"
})
worker = reviewer_account_fixture()
{:ok, view, _html} =
conn
|> log_in_account(worker)
|> live(~p"/jobs/#{task.id}")
view |> element("#claim-review-task-button") |> render_click()
assert has_element?(view, "#review-task-verification-form")
refute has_element?(view, "#review-task-completion-form")
view
|> form("#review-task-verification-form",
verification: %{
provenance: "hybrid",
verdict: "confirmed",
notes: "Reproduced every reported path against the exact pinned commit.",
evidence: "Ran the negative-path request and observed the authorization bypass."
}
)
|> render_submit()
assert has_element?(view, "#review-task-status", "Submitted")
assert has_element?(view, "#review-task-target-confirmations", "authorization bypass")
assert Tarakan.Work.get_task!(task.id).linked_review_id == report.id
end
test "agent fix jobs show the autonomous patch workflow", %{
conn: conn,
creator: creator,
repository: repository
} do
task =
review_task_fixture(repository, creator, %{
"kind" => "write_fix",
"capability" => "agent",
"title" => "Patch the authorization bypass"
})
worker = account_fixture()
{:ok, view, _html} =
conn
|> log_in_account(worker)
|> live(~p"/jobs/#{task.id}")
view |> element("#claim-review-task-button") |> render_click()
assert has_element?(view, "#review-task-agent-path", "reviewable unified diff")
assert render(view) =~ "tarakan worker --agent grok --once --jobs-only"
refute render(view) =~ "tarakan report"
end
test "a proposed fix is rendered as a patch artifact", %{
conn: conn,
creator: creator,
repository: repository
} do
task =
review_task_fixture(repository, creator, %{
"kind" => "write_fix",
"capability" => "human",
"title" => "Patch the authorization bypass"
})
worker = account_fixture()
{:ok, view, _html} =
conn
|> log_in_account(worker)
|> live(~p"/jobs/#{task.id}")
view |> element("#claim-review-task-button") |> render_click()
assert has_element?(
view,
"#review-task-completion-form",
"Proposed unified diff and test plan"
)
view
|> form("#review-task-completion-form",
contribution: %{
provenance: "human",
summary: "Require ownership before the state transition.",
evidence:
"diff --git a/lib/action.ex b/lib/action.ex\n--- a/lib/action.ex\n+++ b/lib/action.ex\n@@ -1 +1,2 @@\n run()\n+authorize()\n\nTest: mix test"
}
)
|> render_submit()
assert has_element?(view, "#review-task-fix-badge", "Patch proposal")
assert has_element?(view, "#review-task-contribution", "Proposed fix")
assert has_element?(view, "#review-task-contribution", "diff --git")
refute has_element?(view, "#review-task-historical-badge")
end
test "another contributor claims and submits the task for review", %{conn: conn, task: task} do
worker = account_fixture()
conn = log_in_account(conn, worker)
{:ok, view, _html} = live(conn, ~p"/jobs/#{task.id}")
view |> element("#claim-review-task-button") |> render_click()
assert has_element?(view, "#review-task-status", "Claimed")
assert has_element?(view, "#review-task-completion-form")
refute has_element?(view, "#review-task-agent-path")
view
|> form("#review-task-completion-form",
contribution: %{
provenance: "human",
summary: "The boundary is enforced consistently.",
evidence: "Reproduced the negative path with the repository test suite."
}
)
|> render_submit()
assert has_element?(view, "#review-task-status", "Submitted")
assert has_element?(view, "#review-task-review-pending")
assert has_element?(view, "#review-task-contribution", "Human")
assert has_element?(view, "#review-task-contribution", "boundary is enforced")
refute has_element?(view, "#review-task-completion-form")
end
test "a qualified independent reviewer accepts submitted evidence", %{
conn: conn,
task: task
} do
worker = account_fixture()
{:ok, task} = Tarakan.Work.claim_task(task, worker)
{:ok, task} =
Tarakan.Work.submit_task(task, worker, %{
"provenance" => "human",
"summary" => "The boundary is enforced consistently.",
"evidence" => "Reproduced the negative path with the repository test suite."
})
reviewer = moderator_account_fixture()
conn = log_in_account(conn, reviewer)
{:ok, view, _html} = live(conn, ~p"/jobs/#{task.id}")
assert has_element?(view, "#review-task-decision-form")
view
|> form("#review-task-decision-form",
decision: %{
reason: "The submitted behavior was reproduced independently.",
evidence: "Checked out the pinned SHA and ran the documented negative-path tests."
}
)
|> render_submit(%{"action" => "accept"})
assert has_element?(view, "#review-task-status", "Accepted")
assert has_element?(view, "#review-task-visibility", "Full evidence public")
assert has_element?(view, "#review-task-contribution")
assert has_element?(view, "#review-task-disclosure-form")
refute has_element?(view, "#review-task-decision-form")
assert Tarakan.Work.get_visible_task(task.id)
{:ok, accepted_view, accepted_html} =
live(Phoenix.ConnTest.build_conn(), ~p"/jobs/#{task.id}")
assert has_element?(accepted_view, "#review-task-status", "Accepted")
assert accepted_html =~ "Reproduced the negative path"
html =
view
|> form("#review-task-disclosure-form", disclosure: %{reason: "short"})
|> render_submit(%{"visibility" => "public_summary"})
assert html =~ "should be at least 10 character"
assert Tarakan.Work.get_task!(task.id).visibility == "public"
view
|> form("#review-task-disclosure-form",
disclosure: %{
reason: "The redacted result is safe and useful to publish without raw evidence."
}
)
|> render_submit(%{"visibility" => "public_summary"})
assert has_element?(view, "#review-task-visibility", "Public summary")
{:ok, public_view, public_html} =
live(Phoenix.ConnTest.build_conn(), ~p"/jobs/#{task.id}")
assert has_element?(public_view, "#review-task-status", "Accepted")
assert public_html =~ "boundary is enforced"
refute public_html =~ "Reproduced the negative path"
refute public_html =~ "documented negative-path tests"
end
test "disclosure requires recent authentication", %{conn: conn, task: task} do
worker = account_fixture()
{:ok, task} = Tarakan.Work.claim_task(task, worker)
{:ok, task} =
Tarakan.Work.submit_task(task, worker, %{
"provenance" => "human",
"summary" => "The boundary is enforced consistently.",
"evidence" => "Reproduced the negative path with the repository test suite."
})
reviewer = moderator_account_fixture()
{:ok, task} =
Tarakan.Work.accept_task(task, reviewer, %{
"reason" => "The submitted behavior was reproduced independently.",
"evidence" => "Checked out the pinned SHA and ran the documented negative-path tests."
})
# Outside the two-hour sudo window.
stale_at = DateTime.add(DateTime.utc_now(), -3, :hour)
conn = log_in_account(conn, reviewer, token_authenticated_at: stale_at)
{:ok, view, _html} = live(conn, ~p"/jobs/#{task.id}")
assert {:error, {:live_redirect, %{to: "/accounts/log-in?return_to=%2Fjobs%2F" <> _}}} =
view
|> form("#review-task-disclosure-form",
disclosure: %{
reason: "The redacted result is safe and useful to publish without raw evidence."
}
)
|> render_submit(%{"visibility" => "public_summary"})
assert Tarakan.Work.get_task!(task.id).visibility == "public"
end
test "a claimant can release work back to the queue", %{conn: conn, task: task} do
worker = account_fixture()
conn = log_in_account(conn, worker)
{:ok, view, _html} = live(conn, ~p"/jobs/#{task.id}")
view |> element("#claim-review-task-button") |> render_click()
view |> element("#release-review-task-button") |> render_click()
assert has_element?(view, "#review-task-status", "Open")
assert has_element?(view, "#claim-review-task-button")
end
end