Skip to content

Allow reviewed exceptions to related-hold blocks - #1545

Open
jazairi wants to merge 2 commits into
mainfrom
etd-704
Open

jazairi wants to merge 2 commits into
mainfrom
etd-704

Conversation

@jazairi

@jazairi jazairi commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Why these changes are being introduced:

An author may legitimately have multiple distinct
theses with holds. We need an affordance for
processors to override the publication block in
such cases.

Relevant ticket(s):

How this addresses that need:

  • Adds a field to the the processing form that allows processors to override the publication
    block for related theses.
  • Manages exceptions to publication blocks in a model that's backed by PaperTrail.
  • Refreshes publication readiness when holds are saved, reassigned, or deleted.
  • Rechecks holds before queuing publication and when publication jobs run.

Side effects of this change:

Existing stale readiness statuses are not
automatically fixed. However, this is a highly
unlikely edge case.

Developer

Accessibility
  • ANDI or WAVE has been run in accordance to our guide.
  • This PR contains no changes to the view layer.
  • New issues flagged by ANDI or WAVE have been resolved.
  • New issues flagged by ANDI or WAVE have been ticketed (link in the Pull Request details above).
  • No new accessibility issues have been flagged.
New ENV
  • All new ENV is documented in README.
  • All new ENV has been added to Heroku Pipeline, Staging and Prod.
  • ENV has not changed.
Approval beyond code review
  • UXWS/stakeholder approval has been confirmed.
  • UXWS/stakeholder review will be completed retroactively.
  • UXWS/stakeholder review is not needed.
Additional context needed to review

It's easiest to test using the preseeded data in the staging db. I've loaded a copy of that db into the review app.

Code Reviewer

Code
  • I have confirmed that the code works as intended.
  • Any CodeClimate issues have been fixed or confirmed as
    added technical debt.
Documentation
  • The commit message is clear and follows our guidelines
    (not just this pull request message).
  • The documentation has been updated or is unnecessary.
  • New dependencies are appropriate or there were no changes.
Testing
  • There are appropriate tests covering any new functionality.
  • No additional test coverage is required.

Why these changes are being introduced:

An author may legitimately have multiple distinct
theses with holds. We need an affordance for
processors to override the publication block in
such cases.

Relevant ticket(s):

- [ETD-704](https://mitlibraries.atlassian.net/browse/ETD-704)
- [ETD-689](https://mitlibraries.atlassian.net/browse/ETD-689)

How this addresses that need:

- Adds a field to the the processing form that
allows processors to override the publication
block for related theses.
- Manages exceptions to publication blocks in a
model that's backed by PaperTrail.
- Refreshes publication readiness when holds are
saved, reassigned, or deleted.
- Rechecks holds before queuing publication and
when publication jobs run.

Side effects of this change:

Existing stale readiness statuses are not
automatically fixed. However, this is a highly
unlikely edge case.
@mitlib
mitlib temporarily deployed to thesis-submit-pr-1545 November 9, 2026 23:08 Inactive
@coveralls

coveralls commented Nov 9, 2026 •

Copy link
Copy Markdown

Coverage Status

coverage: 98.382% (+0.08%) from 98.298% — etd-704 into main

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The change introduces synchronous N+1 queries across publication batches and can reject unchanged unchecked exceptions after hold removal, discarding metadata edits.

2 open issues
What changed in this PR

This PR lets processors waive publication blocks caused by holds on distinct related theses, while preserving direct holds and other readiness requirements.

Changes:

  • Adds directional, audited exceptions and controls to grant or revoke them in the processing form.
  • Refreshes readiness when holds change and rechecks holds before queuing and executing publication.
  • Adds regression tests for authorization, audit history, rollback, and publication safeguards.
File Description
test/​models/​related_hold_exception_test.rb Tests exception validation, persistence, rollback, and cleanup.
test/​models/​hold_test.rb Tests readiness updates after hold changes.
test/​jobs/​dspace_publication_job_test.rb Tests publication safeguards against current holds.
test/​controllers/​thesis_controller_test.rb Tests review permissions, processing updates, and publication filtering.
db/​schema.rb Records the exception table and constraints.
db/​migrate/​20261105120000_create_related_hold_exceptions.rb Creates directional exceptions with database integrity checks.
app/​views/​thesis/​process_thesis.html.erb Adds related-thesis details and exception checkboxes.
app/​models/​thesis.rb Applies exceptions to readiness and saves reviews transactionally.
app/​models/​related_hold_exception.rb Validates and audits exception grants and revocations.
app/​models/​hold.rb Refreshes affected theses after hold saves and deletions.
app/​jobs/​dspace_publication_job.rb Rechecks holds before publication proceeds.
app/​controllers/​thesis_controller.rb Handles review submissions and queues eligible publication candidates.

Review effort: Balanced

Comment thread app/controllers/thesis_controller.rb Resolved
Comment thread app/models/related_hold_exception.rb Resolved
Why these changes are being introduced:

A copilot review noted that  stale unchecked hold
reviews could reject valid metadata edits.
Additionally, publication candidate selection
led n+1 queries.

Relevant ticket(s):

- [ETD-704](https://mitlibraries.atlassian.net/browse/ETD-704)

How this addresses that need:

- Absent unchecked related-thesis exceptions are
now treated as no-ops.
- Publication candidates are now selected through
one SQL query.

Side effects of this change:

We don't typically insert SQL queries in scopes,
but it seemed like the least-bad option in this
case.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The attachment-race retry can reuse a stale association from the rolled-back attempt, skip recreating the exception, and lose the processor’s decision; reload the association before building the lookup.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Reload persisted exceptions before retrying attachment association

app/​models/​related_hold_exception.rb:48

On the attachment-race retry, this association can still contain the exception created during the first attempt even though that attempt's transaction rolled back. Reusing the same thesis object then treats the rolled-back exception as existing, so line 52 skips recreating it and the successful retry loses the processor's decision. Reload the association before building this lookup so each attempt uses persisted exceptions.

1 resolved since last review

Review effort: Balanced

@jazairi

jazairi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

🔵 Needs a closer look

The attachment-race retry can reuse a stale association from the rolled-back attempt, skip recreating the exception, and lose the processor’s decision; reload the association before building the lookup.

1 open issue

1 previously missed issue
In code that hasn't changed since last review

Medium severity Reload persisted exceptions before retrying attachment association
app/​models/​related_hold_exception.rb:48

On the attachment-race retry, this association can still contain the exception created during the first attempt even though that attempt's transaction rolled back. Reusing the same thesis object then treats the rolled-back exception as existing, so line 52 skips recreating it and the successful retry loses the processor's decision. Reload the association before building this lookup so each attempt uses persisted exceptions.

1 resolved since last review

Review effort: Balanced

This is incorrect. The stale association exists, but the processor’s decision isn’t lost. Saving the thesis automatically saves the retained exception, including its PaperTrail audit.

This branch was successfully deployed

1 active deployment
thesis-submit-pr-1545 — 26256543 Deployed Nov 13, 2026 by jazairi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants