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

64 lines
2.4 KiB
Markdown

# 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.