1.4 KiB · text History b868907
defmodule GitGud.Repo.Migrations.CreatePackageSigningKeys do
  use Ecto.Migration

  @moduledoc """
  Per-repository, per-format signing keys for the package registries.

  Hex requires every registry resource to be signed, and apt requires a
  signed `Release`. Both want a keypair whose public half a client
  pins once (`mix hex.repo add --public-key`, `/etc/apt/keyrings`) and
  whose private half never leaves the server — so the private key is
  encrypted at rest with the same AES-256-GCM master key
  `GitGud.Secrets` uses, and carries the same `key_id` so a rotation
  re-wrap reaches it too.

  Per repository rather than per forge: the public key is the thing a
  consumer pins, and one shared key would mean rotating it breaks every
  repository at once.
  """

  def change do
    create table(:package_signing_keys) do
      add :repository_id, references(:repositories, on_delete: :delete_all), null: false
      add :format, :string, null: false, size: 20
      # Public half, PEM, served verbatim to clients.
      add :public_key, :text, null: false
      # Private half, AES-256-GCM under the GitGud.Secrets master key.
      add :private_key_ciphertext, :binary, null: false
      add :private_key_iv, :binary, null: false
      add :private_key_tag, :binary, null: false
      add :key_id, :string, null: false

      timestamps(type: :utc_datetime)
    end

    create unique_index(:package_signing_keys, [:repository_id, :format])
  end
end