#46: user-safe catalog refresh — batch backup/restore wrappers#83
Conversation
…e_user_markings drop_ascc_state deletes user-submitted covers/images/contributions along with a state's catalog tree, and bundles no longer contain covers. These wrappers make the drop/re-import refresh non-destructive: - backup_user_markings: enumerates markings carrying user content (covers, contributions, is_reviewed, edit history, --uploader images) and exports each via backup_marking; fail-fast, manifest lists non-exportable rows (no code / unlinked covers) instead of silently skipping them. - restore_user_markings: restores every backup, continues past failures, writes restore_report.json whose failures list is the editor review queue; exits nonzero if anything failed. - docs/devel/USER_SAFE_REFRESH.md: the wrapped refresh sequence + caveats. Note: common suite is 134/135 on this branch; the one failure (test_top_search_ignores_catalog_text) pre-exists on staging tip 0998d6a and is unrelated (search semantics). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Code review overview
Syntax ErrorsNo issues found. Code SmellsFile: Why it matters: The method iterates over every cover-contribution row in Python to call Suggested fix: Consider whether File: Why it matters: Scoping markings by Suggested fix: Consider filtering via File: Why it matters: The command picks up any Suggested fix: Either use filenames that follow a predictable pattern (e.g. only files whose names match the File: Why it matters: The schema strings are version-pinned ( Suggested fix: Add a schema-version assertion when reading the manifest on the restore side, or at minimum log the schema string so operators can spot a mismatch. BugsFile: Why it matters: Only Suggested fix: Use a whitelist replacement (e.g. File: Why it matters: The test asserts Suggested fix: Assert on sets ( File: Why it matters: When failures occur, Suggested fix: Wrap the report write in a try/except and print restored/failed counts to stdout as a fallback. Security VulnerabilitiesFile: Why it matters: Suggested fix: Optionally resolve and validate that |
* #47: link existing covers and markings from the detail pages Editors can now relate records that already exist, instead of only attaching brand-new covers to the one marking being viewed: - RecordDetail: "Link Existing Cover" dialog (ID or C-42 code) POSTs the existing cover-markings endpoint and refreshes the associated list. - CoverDetail: "Link Existing Marking" dialog, same endpoint, refreshes associated markings + the review link. - Both buttons are gated to editor/admin (isStaff) to match the endpoint's IsEditorOrAdminWrite permission. - ID parsing extracted to lib/recordLinking with unit tests. Ported by hand from the pre-refactor reese/cover-workflow-improvements branch (7ae724a); image-move parts of that branch land separately (#48). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * #48: move images between markings and covers, both directions v1 had no cover table, so every uploaded cover photo is stapled to a marking. Editors can now reassign an image's polymorphic subject: Backend: - ImageSerializer update-path validate(): target subject must exist (subject_id is a bare integer column, nothing else checks) and image_view must match the new subject_type — 400s instead of the DB check constraint's 500. - ImageViewSet.perform_update: on subject change, the moved image lands at the end of the target's display order (never displacing its default) and the source subject promotes a new display_order=0 (mirrors perform_destroy). Frontend: - RecordDetail: "Move to cover" action on marking-subject thumbnails; dialog targets covers already linked to the marking, with a cover image-view select (Ian/Wayne's Charlestown cross-contamination case). - CoverDetail: reverse "Move to marking" via a new optional onMoveImage action on EntryAssociatedThumbnailsCard; targets linked markings with FULL/DETAIL views. - services/markings.moveImageSubject(): PATCH /images/{id}/ with field error surfacing. Tests: +5 backend (both directions, display-order bookkeeping, 400 on missing target, 400 on view mismatch, 403 for contributors). Suite 135/136 (1 pre-existing staging failure, see PR #83). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Michael Connolly <connollymp3000@gmail.com>
What
Thin orchestration around the existing per-marking backup/restore so a
drop_ascc_state→import_apmc_bundlerefresh no longer destroys user-submitted content:backup_user_markings <dir>— enumerates every marking carrying user-origin content (has covers, contributions,is_reviewed=True, edit history, or--uploader <username>images) and exports each viabackup_marking. Fail-fast: any export error aborts before a drop can run against a partial backup set. Writesmanifest.jsonreporting what could NOT be exported (markings without acode, covers linked to no marking) instead of silently skipping.restore_user_markings <dir> [--dry-run]— restores every backup, continues past failures (eachrestore_markingis transactional on its own), writesrestore_report.json; thefailureslist is the editor review queue. Exits nonzero if anything failed.docs/devel/USER_SAFE_REFRESH.md— the wrapped sequence + caveats (code-less markings, media binaries, editor-edits-win-over-munger semantics).Why
drop_ascc_statecascades throughCoverMarkingand deletes user covers/images/contributions, and post-policy bundles contain no covers — so a refresh of woco.dev (needed so Ian stops reviewing stale edition-5 data, per his 6/28–29 emails) would wipe his and Wayne's submissions. This is also the prerequisite for any future prod re-run.Tests
common.tests.test_user_markings_batch(4 tests): enumeration selects only user-content markings; no-code markings land in the manifest; full round-tripbackup → drop_ascc_state VA → restorebrings back covers/links/markings; a corrupt file doesn't stop the batch and is reported.commonsuite: 134/135 — the one failure (test_top_search_ignores_catalog_text) pre-exists on staging tip0998d6awith this branch's files removed (verified via stash) and is unrelated (top-search vscatalog_txtsemantics). @grubermeister flagging it for you since it's in the search area you've been changing.ruff clean,
manage.py checkclean, no schema changes.Not in this PR
The actual woco.dev refresh run (needs coordination on who runs it + re-run bundles), and the post-refresh re-measurement of Ian's reports (Abingdon 7/7/9, FL Almirante/Almirante/Alaqua manuscripts).
🤖 Generated with Claude Code