Skip to content

Retry and decrypt-and-retry for recorded failures (Review Flow PR 5) - #7479

Draft
EthanHealy01 wants to merge 1 commit into
feature/failure-notificationsfrom
feature/policy-decrypt-retry
Draft

Retry and decrypt-and-retry for recorded failures (Review Flow PR 5)#7479
EthanHealy01 wants to merge 1 commit into
feature/failure-notificationsfrom
feature/policy-decrypt-retry

Conversation

@EthanHealy01

@EthanHealy01 EthanHealy01 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Flow PR 5. Stacked on #7478. All resolution of a recorded failure lives here: Retry and Decrypt and retry, for editor failures and policy failures alike. #7478 surfaces failures and offers viewing and dismissal; this PR adds the buttons that fix them.

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.

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. The row reveals a password field. 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.

A policy-shaped retry target. 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 action slot model. FailureActionSlot ranks each offer as the row's RESOLUTION, SECONDARY or OVERFLOW, and promoteActions turns those into the row's primary and secondary buttons plus the reason for anything withheld. It arrives with this PR because ranking is only a question worth asking once a kind has a resolution to rank — the bell alone offers viewing and dismissal, in declaration order.

Behaviour

  • The unlocked document is added, not consumed: the encrypted original stays in the workbench.
  • 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 inline 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 Surface recorded failures in a notification bell (Review Flow PR 4) #7478 alone it was View file, because the slot ranking and the handler both arrive here.
  3. Press it. A password field appears in the row. Enter the wrong password first: the row reports the server's message inline and stays open.
  4. Enter the correct password. The unlocked document appears in the workbench alongside the still-encrypted original, 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.

@stirlingbot stirlingbot Bot added the has conflicts Pull request has merge conflicts with the base branch label Aug 12, 2026
@EthanHealy01
EthanHealy01 force-pushed the feature/failure-notifications branch 2 times, most recently from dff3d86 to 9c2fa39 Compare August 13, 2026 01:35
@EthanHealy01
EthanHealy01 force-pushed the feature/policy-decrypt-retry branch from 801bd5b to dd5ddaa Compare August 13, 2026 01:46
@stirlingbot stirlingbot Bot removed the has conflicts Pull request has merge conflicts with the base branch label Aug 13, 2026
@EthanHealy01
EthanHealy01 force-pushed the feature/policy-decrypt-retry branch from dd5ddaa to 41772a5 Compare August 13, 2026 15:27
@EthanHealy01 EthanHealy01 changed the title Decrypt a held document and re-run the policy that failed (Review Flow PR 5) Retry and decrypt-and-retry for recorded failures (Review Flow PR 5) Aug 13, 2026
@EthanHealy01
EthanHealy01 force-pushed the feature/failure-notifications branch 2 times, most recently from 29d124e to ae906e7 Compare August 13, 2026 21:29
…rying

All resolution of a recorded failure lives here, on top of the bell that
surfaces it:

- The retry stash: what a failed tool run would need to run again (endpoint,
  parameters, file ids), kept client-side with password-shaped fields stripped
  at any depth and a depth-bounded walk that fails closed.
- Editor retry and decrypt-and-retry: re-open the failed tool, or unlock a
  password-protected document and re-run it in place.
- Server policy retry: an attended policy failure is re-run with the password
  the user supplies, exactly once per click.

The action slot model arrives with them. Slots rank an action as the row's
resolution, its runner-up, or overflow, which is only a question worth asking
once a kind has a resolution to rank: the bell alone offers viewing and
dismissal, in declaration order. promoteActions turns those slots into the
row's primary and secondary buttons and reports what it withheld.

A build without this PR still shows every failure; the server declares RETRY
and DECRYPT_AND_RETRY there and a client with no handler for them skips them.
@EthanHealy01
EthanHealy01 force-pushed the feature/policy-decrypt-retry branch from 41772a5 to 5fb095b Compare August 13, 2026 21:31
@stirlingbot

stirlingbot Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

🚀 V2 Auto-Deployment Complete!

🔗 Direct Test URL (non-SSL) http://54.175.155.236:7479

🧩 Admin portal included - try it at http://54.175.155.236:7479/portal.

This deployment will be automatically cleaned up when the PR is closed.

🔄 Auto-deployed for approved V2 contributors.

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.

1 participant