[pull] main from Stirling-Tools:main - #333
Merged
Merged
Conversation
…#7762) Review Flow PR 5b — the second half of #7479 (left open for reference), stacked on #7761. That PR ranks a row's actions and gives the server a resolve transition; this one adds the buttons that fix things: **Retry** and **Decrypt and retry**, for editor failures and policy failures alike. Merging both reproduces #7479's diff byte-for-byte — this branch's tree is identical to #7479's head. ## What's added **The retry stash** (`notificationRetry.ts`). When a tool run fails, `useToolOperation` stashes what a retry needs — endpoint, parameters, file ids — in its own IndexedDB database, keyed on the failing document. Capped at 25 records, oldest evicted first. Password-shaped fields are stripped at any depth on the way in, and the walk is depth-bounded so a pathological or cyclic object fails closed rather than storing a subtree it never examined. `hasLocalFile` moves in here from `localFilePresence`, which this replaces. **`Retry` on an editor failure** opens the failed tool with the document selected, so the user sees the settings before it runs again. **`Decrypt and retry` on an editor failure** opens the same unlock modal the app uses for a locked upload. On submit it re-runs the stashed operation with the password added, adopts the result into the workbench, and reports the row resolved. **`Retry` and `Decrypt and retry` on a policy failure.** The unlock goes through `POST /api/v1/security/remove-password`, the result is adopted, and the stored policy re-runs on it server-side. `RetryTarget` is a discriminated union: the tool arm comes from the stash, the policy arm is derived from the notification itself (`policyId` plus the document reference), so no stash is needed for a policy failure. **Run registration.** A policy re-run is recorded with the run store, so it polls to terminal, imports its output honouring the policy's `outputMode`, and continues the rest of the upload chain rather than running one policy in isolation. The chain-eligibility ordering moves into `uploadChain.ts`, shared between the auto-run and the retry. **An upload's chain holds back until its unlock prompt is answered** (`pendingUnlocks.ts`), so skipping the prompt is what creates the failure, and answering it never races the policy run. ## Behaviour - The unlocked document **versions the encrypted original in place**, not a second copy beside it. Consumed rather than deleted, so the swap cannot close the incident as a file removal. - Exactly one policy run starts per click. Adoption is marked `derivedFromTool` so the upload auto-run does not also fire on it, which would bill the customer twice. - Failures stop the sequence where they occur. A wrong password reports in the unlock modal and nothing else runs. A failed adoption neither re-runs nor resolves. A refused re-run leaves the document adopted and does not resolve. - **A re-run whose output cannot be delivered leaves the row open.** If the local policy cache cannot place the policy, the run still fires but nothing polls it, so the row stays open and says so rather than closing on a result that never arrives. - The password reaches the network from one place and is never stored, logged, or put in an error message. - A failure this browser did not report has no stash entry, so its Retry is simply not offered on other devices. ## Not included Unattended failures (folder, S3, webhook) still cannot be retried: no browser holds the document. Those actions stay disabled with a reason. Re-running from the source needs a ledger requeue transition that does not exist yet. `ToolType.custom` tools (Convert, OCR) have no single endpoint to re-submit to, so they get no Retry. ## How to test Needs a proprietary or SaaS build with login enabled, and a stored policy that will fail on a locked document. `task dev:all`, then sign in. 1. **Create the failure.** Add a password-protected PDF to the editor and choose **Skip for now**. The upload's policy run fails on it. 2. **Open the bell** once the badge appears. The row's primary button is now **Decrypt and retry** — on #7761 alone it was View file, because the slot ranking arrived there but the handler arrives here. 3. **Press it.** The unlock modal opens. Enter the wrong password first: the modal shows the server's message and stays open. 4. **Enter the correct password.** The unlocked document replaces the encrypted original in the workbench (versioned, not deleted), the policy re-runs on it, and the row leaves the list. 5. **Check the run is tracked.** The activity feed shows the re-run progressing to completion and its output arriving in the workbench, rather than a run that never reports. 6. **Confirm only one run per click.** In DevTools there is exactly one `POST /api/v1/policies/{id}/run` for the retry. Two would mean the adopted document also triggered the upload policy. 7. **Confirm nothing leaks the password.** Search the request log and IndexedDB (`stirling-pdf-retry`) for what you typed. It should appear only in the one unlock request body. 8. **Editor retry.** Fail a plain tool run (rotate a corrupted file), open the bell, press **Retry**: the failed tool opens with that document selected. 9. **Confirm the stash strips secrets.** After a remove-password failure, inspect IndexedDB `stirling-pdf-retry`: the stashed parameters contain no password-shaped field. ## Migration None.
## What this changes - **Big folders don't lag.** The file list only draws the rows you can actually see, so a folder with thousands of files feels the same as one with ten. Selecting a file redraws that file, not the whole folder. - **The 500-file limit is gone.** A mounted disk folder used to list only its 500 newest files and quietly hide the rest. You now see everything in it. - **Back and the breadcrumbs work.** Walking into folders now leaves proper history, so Back steps up one folder. Before, every folder overwrote the same history entry, so Back dumped you out of the library entirely. - **Deep links to a folder work.** Opening a link to a folder that hadn't finished loading used to bounce you to the top of the library. It now waits for the folder to appear. - **"New folder" is one button.** The version on an empty folder was a different button, with a different name, that guessed where to put the folder and greyed itself out when it couldn't. It's now the same menu as the one in the top right. - **"Local" in the left bar is just a filter.** Clicking it filters the list by source. It used to switch you into a separate view with its own rules for what counted as a file, its own empty screen, and its own exceptions everywhere folders were involved. - **Folders obey the source filter.** Picking Cloud or Local now filters folders too, not just files, so mounted folders stop appearing under every setting. - **Opening a file that's already open** takes you to it, instead of trying to add it a second time. - **Opening a cloud file keeps it in its folder** instead of dropping it at the top of the library.
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )