defmodule Tarakan.Repo.Migrations.AddFindingTargetedTaskKinds do use Ecto.Migration @old ~w(code_review threat_model privacy_review business_logic verify_findings write_fix) @new @old ++ ~w(diff_review refute_finding reproduce_finding calibrate_severity) def up do alter table(:review_tasks) do # refute_finding / reproduce_finding / calibrate_severity all act on one # canonical finding rather than a tree, so they need a finding to point at. add :target_canonical_finding_id, references(:canonical_findings, on_delete: :delete_all) end create index(:review_tasks, [:target_canonical_finding_id]) drop constraint(:review_tasks, :review_tasks_kind_must_be_valid) create constraint(:review_tasks, :review_tasks_kind_must_be_valid, check: kind_check(@new)) alter table(:canonical_finding_checks) do # An adversarial check was asked to break the finding, not to agree with it. # Reusing the existing verdicts keeps the vocabulary small: "confirmed" on # an adversarial check means the attack failed and the finding held. add :adversarial, :boolean, null: false, default: false end create index(:canonical_finding_checks, [:canonical_finding_id, :adversarial]) end def down do drop index(:canonical_finding_checks, [:canonical_finding_id, :adversarial]) alter table(:canonical_finding_checks) do remove :adversarial end drop constraint(:review_tasks, :review_tasks_kind_must_be_valid) create constraint(:review_tasks, :review_tasks_kind_must_be_valid, check: kind_check(@old)) drop index(:review_tasks, [:target_canonical_finding_id]) alter table(:review_tasks) do remove :target_canonical_finding_id end end defp kind_check(kinds) do list = Enum.map_join(kinds, ", ", &"'#{&1}'") "kind IN (#{list})" end end