tarakan/priv/repo/migrations/20260711001947_add_scan_review_controls.exs
Maxfield Luke af6077b9c3
All checks were successful
CI and deploy / Test (push) Successful in 4m52s
CI and deploy / Deploy production (push) Successful in 23s
Initial commit on Forgejo
Fresh repository history for elektrine/tarakan hosted at
https://git.elektrine.com/elektrine/tarakan.
2026-07-29 04:43:40 -04:00

80 lines
3.1 KiB
Elixir

defmodule Tarakan.Repo.Migrations.AddScanReviewControls do
use Ecto.Migration
def up do
alter table(:scans) do
add :review_status, :string, null: false, default: "quarantined"
add :visibility, :string, null: false, default: "restricted"
add :moderation_reason, :string
add :moderation_notes, :text
add :reviewed_at, :utc_datetime_usec
add :reviewed_by_id, references(:accounts, on_delete: :restrict)
end
create index(:scans, [:repository_id, :review_status, :visibility, "inserted_at DESC"],
name: :scans_public_record_index
)
create index(:scans, [:reviewed_by_id])
create constraint(:scans, :scans_review_status_must_be_valid,
check: "review_status IN ('quarantined', 'accepted', 'rejected', 'contested')"
)
create constraint(:scans, :scans_visibility_must_be_valid,
check: "visibility IN ('restricted', 'public_summary', 'public')"
)
create constraint(:scans, :scans_publication_requires_acceptance,
check: "visibility = 'restricted' OR review_status = 'accepted'"
)
create constraint(:scans, :scans_acceptance_requires_verification,
check: "review_status != 'accepted' OR verified_at IS NOT NULL"
)
create constraint(:scans, :scans_acceptance_requires_quorum,
check: "review_status != 'accepted' OR confirmations_count - disputes_count >= 2"
)
create constraint(:scans, :scans_moderation_requires_attribution,
check:
"review_status = 'quarantined' OR (reviewed_by_id IS NOT NULL AND reviewed_at IS NOT NULL AND length(btrim(moderation_reason)) >= 3 AND length(btrim(moderation_notes)) >= 20)"
)
execute "UPDATE repositories SET status = 'unscanned' WHERE status = 'clear'"
drop constraint(:repositories, :repositories_status_must_be_valid)
create constraint(:repositories, :repositories_status_must_be_valid,
check: "status IN ('unscanned', 'scanning', 'findings', 'reviewed', 'stale')"
)
end
def down do
execute "UPDATE repositories SET status = 'unscanned' WHERE status = 'reviewed'"
drop constraint(:repositories, :repositories_status_must_be_valid)
create constraint(:repositories, :repositories_status_must_be_valid,
check: "status IN ('unscanned', 'scanning', 'findings', 'clear', 'stale')"
)
drop constraint(:scans, :scans_moderation_requires_attribution)
drop constraint(:scans, :scans_acceptance_requires_quorum)
drop constraint(:scans, :scans_acceptance_requires_verification)
drop constraint(:scans, :scans_publication_requires_acceptance)
drop constraint(:scans, :scans_visibility_must_be_valid)
drop constraint(:scans, :scans_review_status_must_be_valid)
drop index(:scans, [:reviewed_by_id])
drop index(:scans, name: :scans_public_record_index)
alter table(:scans) do
remove :reviewed_by_id
remove :reviewed_at
remove :moderation_notes
remove :moderation_reason
remove :visibility
remove :review_status
end
end
end