Skip to content

Instantly share code, notes, and snippets.

@nickmerwin
Created May 15, 2026 05:37
Show Gist options
  • Select an option

  • Save nickmerwin/095efc20bd4fdd4eeb8d19a66d89f4cb to your computer and use it in GitHub Desktop.

Select an option

Save nickmerwin/095efc20bd4fdd4eeb8d19a66d89f4cb to your computer and use it in GitHub Desktop.
PR #359 — Bulk Job Undo + Reports — QA plan (review app staging-pr-359)

PR #359 — Bulk Job Undo + Reports QA Plan

Review app: https://staging-pr-359.mediagraph.io/login Basic auth: staging / 2d34745ed4ef2761 App login: use any staging org admin account.

PR: https://github.com/mediagraph-io/mediagraph/pull/359


What changed (scope)

  1. Generalized bulk-job undo. undo_bulk_job! now reverts Asset metadata, taggings, custom-meta values, collection/lightbox membership, and votes by walking PaperTrail versions tagged with bulk_job_id — not just storage-folder moves.
  2. Stamping. Every PaperTrail version a bulk job produces is now tagged with its bulk_job_id (via Asset.with_bulk_job at the job boundary + a thread-local fallback for child records). New partial index versions(bulk_job_id) WHERE NOT NULL.
  3. Vote + Asset tracking. Vote is now PaperTrail-tracked. Asset's tracked-field list expanded (rating, has_people, nsfw_detected, submitted, model_release_status, captured_at, etc.).
  4. Safety. New :undo ability (admins + global_content can undo any org bulk job; users can undo their own). 30-day undo horizon. Per-field "skip if changed since" — undo never clobbers a field the user edited after the bulk job ran.
  5. Reports → Bulk Jobs UX. Summary column with details modal, asset-count modal, undo progress modal, "undone by X" stamp, and filters (date range / user / asset GUID).

QA scenarios

A. Basic meta undo (happy path)

  1. Explore → select 3–5 assets → Bulk Edit → set Description (overwrite) to QA TEST DESC. Run it; wait for 100%.
  2. Confirm the assets show QA TEST DESC.
  3. On the bulk-job completion notification, click Undo. A nested progress bar appears.
  4. ✅ Expected: descriptions revert to their original values; undo job reaches 100%.

B. Tag add + remove undo

  1. Bulk-add two keywords (qa-kw-1, qa-kw-2) to a few assets. Undo.
    • ✅ Both keywords removed; pre-existing tags untouched.
  2. Bulk-remove an existing keyword from assets. Undo.
    • ✅ The removed keyword is recreated on those assets.

C. Creator tag / custom meta / vote

  1. Bulk-set a Creator tag → Undo → ✅ original creator restored (or cleared if there was none).
  2. Bulk-set a custom meta field value → Undo → ✅ value removed.
  3. Bulk vote (thumbs up/down) on assets → Undo → ✅ vote reset.

D. Collection / Lightbox membership

  1. Bulk add assets to a Collection → Undo → ✅ assets removed from that Collection.
  2. Repeat for a Lightbox.

E. Trash / restore

  1. Bulk delete (trash) a couple of disposable test assets → Undo → ✅ assets restored (un-trashed).

F. "Skip if changed since" (the important safety case)

  1. Bulk-set Description = BULK A on an asset. Wait for completion.
  2. Manually edit that asset's description to MANUAL EDIT (single-asset edit, not bulk).
  3. Undo the bulk job.
  4. ✅ Expected: description stays MANUAL EDIT (NOT reverted to the pre-bulk value). The undo job's warnings list shows a Skipped description (modified after the original bulk job) entry.

G. 30-day horizon

  • A bulk job older than 30 days: the Undo button is disabled in Reports → Bulk Jobs with an explanatory tooltip. (If you can age a record via console, the undo job records an undo_too_old warning and finishes without reverting.)

H. Authorization

  1. As a general (non-admin, non-content) user, attempt to undo a bulk job created by someone else (via the API or another user's job in Reports).
    • ✅ Expected: 403 / "You do not have permission to undo this bulk job."
  2. As that same general user, undo your own bulk job → ✅ allowed.
  3. As admin or global_content, Reports → Bulk Jobs lists all org bulk jobs and Undo works on any.

I. Reports → Bulk Jobs page

URL: /<org-slug>/manage/reports/bulk-jobs

  • Summary column: shows a one-line summary of what each job did. Click the ℹ︎ info icon → modal lists every operation, the user, status (colored tag), and undone-by info.
  • Assets count: click the number → modal with a paginated thumb/filename/GUID table of that job's assets.
  • Undo column:
    • For an undoable processed job → Undo button; clicking opens a progress modal (same BulkJobProgress component as a normal in-flight job).
    • After undo → shows undone by <name> <time-ago>.
    • Job > 30 days old → button disabled with tooltip.
  • Filters bar: date range picker, user select (type to search), asset-GUID search, Clear button. Each narrows the table; combining them ANDs.
  • Undo job rows: an undo job's summary reads Undo of bulk job #<N>: <original summary>; the details modal lists each reverted op prefixed with .

J. Regression sanity

  • Run a normal bulk edit end-to-end (no undo) → still works, progress bar + warnings behave as before.
  • Meta Imports table (Reports) → asset-count modal still works (it now shares the same JobAssetsTable component).

Known limitations (expected, not bugs)

  • Only changes made after this code shipped are undoable. A bulk job run before the bulk_job_id stamping existed has no tagged versions; undoing it surfaces a No reversible changes were recorded for this bulk job warning and finishes cleanly (does not error).
  • Non-PaperTrail operations (AI/auto-tag, alt-text generation, face search, rotate, optimization requests, Frame.io sync) are not reverted — they're skipped, not errored.
  • Undo runs as its own bulk job; large jobs revert in the same batched, progress-reported fashion as the original.

Infra note (not user-facing)

The review-app SSL 525 and the ES collection_paths fielddata 400 were environment bugs, already fixed:

  • Cloudflare zone SSL was full; staging origin is HTTP-only kamal-proxy. Added a scoped Configuration Rule: staging*.mediagraph.io → SSL Flexible (prod is DNS-only, unaffected).
  • bin/deploy-review now clones the source index settings+mappings before _reindex (fix committed to master separately, 74769d13).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment