Surface recorded failures in a notification bell (Review Flow PR 4) - #7478
Surface recorded failures in a notification bell (Review Flow PR 4)#7478EthanHealy01 wants to merge 3 commits into
Conversation
062a1b9 to
dff3d86
Compare
| "notifications.noDocumentLinked", | ||
| "This failure is not linked to a specific document, so it cannot be opened or retried here.", | ||
| ); | ||
| return isResolvableHere(notification) |
There was a problem hiding this comment.
noteFor returns "not on this device" when isResolvableHere(notification) is true, which inverts the condition and can show the opposite reason to users.
| return isResolvableHere(notification) | |
| return !isResolvableHere(notification) |
Details
✨ AI Reasoning
The function builds explanatory notes for why actions are unavailable. After ruling out non-owned rows, local-file-present rows, and missing file ids, it decides whether to show a "not on this device" message. That message is currently returned when the predicate indicates resolvability in the current environment, which contradicts the meaning of the text being shown. This creates a path where users receive the opposite explanation from the actual condition.
Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info
f495edc to
29d124e
Compare
A bell in the editor and the processor lists the failures the reader is allowed to see, each with the actions they can actually take: open the document, view the run in the processor, dismiss. Resolution (retry, decrypt-and-retry) is a separate PR; the server declares those actions here and a build with no client handler for them skips them. Actions carry an audience (owner / team reviewer / anyone) and the server derives the reader's ownership of each row, so an admin reviewing someone else's failure is not offered a document their browser does not hold. Order is the kind's declaration order, first leading. An attended policy run now carries the client's own document reference, which is what lets a repeat fold onto one incident, lets deleting the file clear its failure, and lets the owner open the document from the row. The bell also re-reads as soon as a failure this user caused is recorded, rather than leaving them to wait out a poll interval for news of their own upload. Other people's failures still arrive on the poll.
29d124e to
ae906e7
Compare
… feature/failure-notifications # Conflicts: # frontend/editor/public/locales/en-US/translation.toml # frontend/editor/src/core/components/layout/Workbench.tsx # frontend/editor/src/portal/components/AppShell.tsx
… document Deleting a document from the editor closed only the incidents the editor had reported itself. A policy run the same upload triggered was recorded by the processor, so its failures stayed in the queue about a document that no longer exists anywhere, and the only way to clear them was to dismiss each one by hand. The guard was keyed on origin, which is not the question. The question is which of the two id spaces the row's fileId is in: an editor report and an attended policy run both carry the id the client minted for its own document, so the client that holds it can say it is gone; a source-fed run carries a one-way hash of a path or key that was never on any device, so no client can name it. That is the absence of a source, not the origin, and it is the same rule the frontend already uses to decide whether a row is resolvable locally. Losing the origin clause does not widen anything: the actor and team clauses still hold. It matters most where the actor clause cannot help, which is a login-disabled deployment where both sides are null and every unattended row would otherwise match; that case is now pinned by its own test. Both tests run against the real database, because the scoping lives entirely in the JPQL and the in-memory fake implements the same rules by hand -- it would agree with a wrong query.
🚀 V2 Auto-Deployment Complete!🔗 Direct Test URL (non-SSL) http://54.175.155.236:7478 🧩 Admin portal included - try it at http://54.175.155.236:7478/portal. This deployment will be automatically cleaned up when the PR is closed. 🔄 Auto-deployed for approved V2 contributors. |
Review Flow PR 4 of 5. Stacked on #7477. Recorded failures appear in a notification bell, showing each reader the failures they are allowed to see and the actions they can actually take.
Scope is deliberately viewing and triage only. Resolving a failure — retry, decrypt-and-retry — is #7479.
What's added
A notification bell in the editor and the processor shell. Polls
GET /api/v1/notificationsevery 30 seconds, shows an unread badge, and lists open failures newest first. Each row shows the failure's title, its message with Copy error and Show full message chips, an occurrence count, and its available actions.A notification API (
stirling.software.proprietary.notification), derived from failures on read rather than stored in its own table:GET /api/v1/notificationsPOST /api/v1/notifications/{id}/actions/{actionId}POST /api/v1/notifications/{id}/resolvedEvery id is prefixed (
failure:<uuid>); none of these routes accepts a raw failure id.Per-reader actions. A
FailureKinddeclares each action with an audience (OWNER,TEAM_REVIEWER,ANYONE_WHO_SEES). The server resolves that against the reader and derivesOwnership(MINE/THEIRS/UNOWNED) from the row's actor, so an admin reviewing someone else's failure is not offered a document their browser does not hold. Adding a failure kind requires no frontend change.Server-run and client-run actions are distinguished.
FailureActionIdcarries anExecutionfacet; the registry requires a bean only for server actions, and dispatching a client action returns 400.Actions available on this PR: View file (opens the document in the editor), View in processor (dev builds only), Dismiss. The server also declares Retry and Decrypt and retry on the password-protected kind; this build wires no handler for them, so the bell skips them rather than rendering a dead button. #7479 adds the handlers.
Attended policy runs record their document.
POST /api/v1/policies/{id}/runaccepts an optional opaquefileId, recorded when the run carries exactly one primary document. This is what lets a repeat fold onto one incident instead of opening a new one per upload, lets deleting the file clear its failure, and lets the owner open the document from the row.A
RESOLVEDstatus transition, system-set when a client-side retry succeeds.Behaviour changes
FAILED. Other people's failures still arrive on the poll, which is what it is for./processor/documentsstays behindimport.meta.env.DEV, and View in processor is gated to match so it cannot navigate to a section that is not mounted. Both lift when failures get their own review screen.ACKNOWLEDGEis no longer offered by any kind. The id, bean and status remain so existing rows stay readable.Known limits
file_run_events.How to test
Needs a proprietary or SaaS build with login enabled.
task dev:all, then sign in.POST /api/v1/notifications/failure%3A<uuid>/actions/DISMISS— note the prefixed id.GET /api/v1/notificationsper 30s per tab, not three.Migration
None. No new column and no new value in any CHECK-constrained enum;
CheckConstrainedEnumsTestfails if that changes.