Repository navigation
Report a password-protected PDF as unreadable with cause protected - #96
Merged
Merged
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The response-code documentation currently gives contradictory permanence rules for unknown unreadable causes.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Adds a structured protected cause for password-protected PDFs instead of requiring stderr parsing.
Changes:
- Propagates causes from unreadable-input exception subclasses.
- Maps MuPDF password failures to
protected. - Adds integration coverage and documentation.
[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or rungh pr ready --undo.
Click "Ready for review" or rungh pr readyto reengage.
| File | Description |
|---|---|
hotcell-server/lib/hot_cell/worker.rb |
Propagates unreadable causes. |
hotcell-server/lib/hot_cell/server/errors.rb |
Adds the cause extension point. |
hotcell-core/lib/hot_cell/codes.rb |
Defines PROTECTED. |
activestorage-hotcell-server/lib/active_storage/hot_cell/server/tool_operation.rb |
Maps stderr patterns to specialized failures. |
activestorage-hotcell-server/lib/active_storage/hot_cell/server/previewers/pdf/mutool.rb |
Detects password authentication failures. |
activestorage-hotcell-server/test/previewers_test.rb |
Tests protected and ordinary unreadable PDFs. |
docs/operation-api.md |
Documents operation-defined causes. |
docs/codes.md |
Documents the protected cause. |
docs/active-storage.md |
Documents MuPDF behavior. |
CHANGELOG.md |
Records both gem changes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
flavorjones
force-pushed
the
card-5285-protected-pdf-cause
branch
from
October 7, 2026 21:11
8a8d0b1 to
916db97
Compare
Applications rendering a lock placeholder for protected PDFs matched mutool's stderr phrase in the failure message, which nothing specified. A ProtectedDocument refusal now carries cause: protected onto the wire: an UnreadableInput subclass may declare the failure's cause, run! maps stderr patterns onto the subclass to raise, and the worker reports the declared cause.
`PROTECTED` sat among the `killed` causes in `codes.rb`, under their shared comment, and no doc mentioned that `unreadable` can carry a cause. Move the constant beside `KILLED` with its own comment, document the cause in `docs/codes.md`, `docs/operation-api.md` and `docs/active-storage.md`, and add a changelog entry.
The Poppler previewer answered a password-protected PDF as `unreadable` with no cause, unlike the `mutool` previewer. Map `pdftoppm`'s `Incorrect password` stderr to `ProtectedDocument`.
flavorjones
force-pushed
the
card-5285-protected-pdf-cause
branch
from
October 7, 2026 21:13
916db97 to
6931732
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Motivation
An application that shows a lock placeholder for a password-protected PDF has to recognize one. The cell answers
unreadablewith no cause, so HEY matchesmutool's stderr phrasecannot authenticate passwordinside the exception message (encryption_aware_pdf_previewer.rb:27). Nothing in Hot Cell specifies that phrase, so a change tomutool's wording, or to how the message is rendered, silently breaks the placeholder.Details
HotCell::UnreadableInputcan defineself.cause, and the worker sends that cause with theunreadablefailure.unreadablestays permanent whatever its cause.HotCell::Codes::PROTECTED("protected") is the first such cause.ToolOperation#run!takescauses:, a map from stderr pattern to the exception class to raise. Both PDF previewers map their password error to a newProtectedDocument:mutooloncannot authenticate password, and Poppler'spdftoppmonIncorrect password. A password-protected PDF answersunreadablewith causeprotected. Every other failure of either tool answers as before.docs/codes.md,docs/operation-api.md,docs/active-storage.mdand the changelog describe the cause.docs/codes.mdno longer says that every unknown cause is transient: only an unknown cause ofkilledis.The cause is in the exception message, after the code (
unreadable: protected: …). #104 exposes the failure on the exception, so an application readserror.hot_cell_failure.causeinstead of parsing the message.