prop/docs/plans/2026-04-11-contact-edit-approval-design.md
Graham McIntire a66d3094ca Add contact edit approval system with admin review queue
Registered users can suggest edits to any contact's core fields
(callsigns, grids, band, mode, timestamp). Edits enter an admin
approval queue with field-by-field diff view. On approve, changes
are applied and enrichment re-enqueued if grids/band changed.
Users receive email notification on approve or reject.

Also updates dependabot.yml for mix ecosystem.
2026-04-11 16:15:49 -05:00

2.4 KiB

Contact Edit Approval System — Design

Goal

Allow registered users to suggest corrections to any contact's core fields. Edits enter an admin approval queue with field-by-field diff view. Users receive email notification when their edit is approved or rejected.

Data Model

New contact_edits table:

Field Type Purpose
id binary_id PK
contact_id references contacts Target contact
user_id references users Submitter
proposed_changes :map (JSONB) Only changed fields, e.g. %{"grid1" => "EM13kk"}
status Ecto.Enum (:pending, :approved, :rejected) Review state
admin_note :string Optional admin explanation
reviewed_by_id references users Admin who acted
reviewed_at :utc_datetime When reviewed
timestamps inserted_at = submission time

Schema: ContactEdit in lib/microwaveprop/radio/contact_edit.ex.

Editable Fields

station1, station2, grid1, grid2, band, mode, qso_timestamp.

Not editable: pos1/pos2, distance_km, enrichment statuses (computed fields).

User Flow

  • Contact detail page (/contacts/:id): logged-in users see "Suggest Edit" button.
  • Clicking opens inline form pre-filled with current values.
  • On submit: backend diffs against current contact, stores only changed fields.
  • Validation: same rules as submission_changeset (callsign format, grid format, valid band/mode).
  • Reject if nothing changed.
  • Flash confirmation on success. Badge shows "pending edit" if user has one.

Admin Flow

  • /admin/contact-edits: pending edits, newest first.
  • Columns: contact link, submitter callsign, submitted at, fields changed.
  • Review view: field-by-field diff table (current vs proposed), only changed fields.
  • Optional note textarea, Approve/Reject buttons.
  • Approve: update contact fields, re-enqueue enrichment if grid1/grid2/band changed.
  • Reject: no contact changes.
  • Nav badge shows pending count.

Multiple Edits

Independent queue — multiple edits per contact allowed. Admin reviews each separately.

Email Notifications

Plain text via Swoosh (existing mailer). Sent on approve or reject. Includes:

  • Contact identifier (station1 <-> station2, band, date)
  • What was proposed
  • Decision (approved/rejected)
  • Admin note if provided

Re-enrichment

On approve, if any of grid1/grid2/band changed: recalculate pos1/pos2 from grids, clear distance_km (will be recomputed), re-enqueue weather/HRRR/terrain/IEMRE jobs.