feat(webapp): dashboard parity for mollifier-buffered runs#3757
Conversation
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
b8ead31 to
109fbd7
Compare
dd31d60 to
ba09531
Compare
109fbd7 to
c7a66bd
Compare
ba09531 to
1de95f4
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3157546 to
432f81a
Compare
c7a66bd to
094d006
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
432f81a to
8c19830
Compare
094d006 to
9914976
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8c19830 to
fd7e01d
Compare
9914976 to
2ee45a8
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fd7e01d to
83880f8
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
83880f8 to
1a8fbc6
Compare
f4b6064 to
0547ba9
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1a8fbc6 to
558703b
Compare
0547ba9 to
0708ce5
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
558703b to
372ca71
Compare
79a0885 to
c2898d3
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
c2898d3 to
0cdfe2c
Compare
2ea3d92 to
46c08fb
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0cdfe2c to
bdc87f5
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bdc87f5 to
04fab12
Compare
0396ab9 to
65ca573
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
04fab12 to
17e5432
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
17e5432 to
e50c7b9
Compare
65ca573 to
15f5580
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
15f5580 to
f6d15b1
Compare
e50c7b9 to
cbc70ed
Compare
…ity envId from realtime counter Three CodeRabbit findings from #3709, re-raised on #3757: - resources.taskruns.$runParam.debug.ts: buffered fallback returned the run's queue / concurrencyKey / queueTimestamp from the snapshot without verifying org membership. Any authenticated user who knew a friendlyId could read those fields across orgs. Now joins through orgMember the same way the PG path does and 404s on miss. - resources.runs.$runParam.logs.download.ts: same shape — the buffered placeholder leaked runId existence to non-members on direct URL access. Same orgMember check now gates the buffered branch. - mollifierTelemetry.server.ts: recordRealtimeBufferedSubscription was attaching envId (a UUID) as an OTEL counter dimension, violating the project's "no high-cardinality IDs in metric attributes" guideline. Dropped the parameter; the call site's logger.info still emits envId. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f6d15b1 to
fcd196d
Compare
cbc70ed to
da1a1dd
Compare
Address review findings on PR #3757: - replay: guard `synthetic.traceId` / `spanId` before adapting a buffered snapshot into the TaskRun shape ReplayTaskRunService expects. Without the guard, an older snapshot missing those fields produces `00-undefined-undefined-01` as the W3C traceparent, which OTel silently drops — severing the replayed run's trace linkage. Extract the adapter into `buildSyntheticReplayTaskRun` so the guard is unit tested. - run-detail: reflect the buffered snapshot's CANCELED state into the NavBar status + Cancel-button gate. Previously `tryMollifiedRunFallback` hardcoded `status: PENDING` / `isFinished: false` regardless of `buffered.status` / `cancelledAt`, so cancelling a buffered run left the NavBar showing Pending with a Cancel button until the drainer materialised the row. Extract the mapping into `buildSyntheticRunHeader` and unit test PENDING vs CANCELED. - admin runs redirect (@.runs.$runParam): preselect the root span on the buffered redirect via `v3RunSpanPath`, matching the sibling redirect routes. Without this the trace tree opened with nothing selected for buffered runs reached via the admin impersonate path. - RunStreamPresenter: switch from `deserialiseSnapshot` (redis-worker) to the webapp wrapper `deserialiseMollifierSnapshot` so both read-side modules share one deserialisation path, per the contract comment in `syntheticRedirectInfo.server.ts`. - cancel route: collapse the `mutateSnapshot` "not_found" branch into the same retry message as "busy". Both indicate the drainer raced the mutation between `getEntry` and `mutateSnapshot`; the run is in PG by then and a retry hits the regular cancel path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address review findings on PR #3757: - replay: guard `synthetic.traceId` / `spanId` before adapting a buffered snapshot into the TaskRun shape ReplayTaskRunService expects. Without the guard, an older snapshot missing those fields produces `00-undefined-undefined-01` as the W3C traceparent, which OTel silently drops — severing the replayed run's trace linkage. Extract the adapter into `buildSyntheticReplayTaskRun` so the guard is unit tested. - run-detail: reflect the buffered snapshot's CANCELED state into the NavBar status + Cancel-button gate. Previously `tryMollifiedRunFallback` hardcoded `status: PENDING` / `isFinished: false` regardless of `buffered.status` / `cancelledAt`, so cancelling a buffered run left the NavBar showing Pending with a Cancel button until the drainer materialised the row. Extract the mapping into `buildSyntheticRunHeader` and unit test PENDING vs CANCELED. - admin runs redirect (@.runs.$runParam): preselect the root span on the buffered redirect via `v3RunSpanPath`, matching the sibling redirect routes. Without this the trace tree opened with nothing selected for buffered runs reached via the admin impersonate path. - RunStreamPresenter: switch from `deserialiseSnapshot` (redis-worker) to the webapp wrapper `deserialiseMollifierSnapshot` so both read-side modules share one deserialisation path, per the contract comment in `syntheticRedirectInfo.server.ts`. - cancel route: collapse the `mutateSnapshot` "not_found" branch into the same retry message as "busy". Both indicate the drainer raced the mutation between `getEntry` and `mutateSnapshot`; the run is in PG by then and a retry hits the regular cancel path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
214bd92 to
c2e1c6e
Compare
50dcb33 to
7494c3d
Compare
c2e1c6e to
0f7365d
Compare
Address review findings on PR #3757: - replay: guard `synthetic.traceId` / `spanId` before adapting a buffered snapshot into the TaskRun shape ReplayTaskRunService expects. Without the guard, an older snapshot missing those fields produces `00-undefined-undefined-01` as the W3C traceparent, which OTel silently drops — severing the replayed run's trace linkage. Extract the adapter into `buildSyntheticReplayTaskRun` so the guard is unit tested. - run-detail: reflect the buffered snapshot's CANCELED state into the NavBar status + Cancel-button gate. Previously `tryMollifiedRunFallback` hardcoded `status: PENDING` / `isFinished: false` regardless of `buffered.status` / `cancelledAt`, so cancelling a buffered run left the NavBar showing Pending with a Cancel button until the drainer materialised the row. Extract the mapping into `buildSyntheticRunHeader` and unit test PENDING vs CANCELED. - admin runs redirect (@.runs.$runParam): preselect the root span on the buffered redirect via `v3RunSpanPath`, matching the sibling redirect routes. Without this the trace tree opened with nothing selected for buffered runs reached via the admin impersonate path. - RunStreamPresenter: switch from `deserialiseSnapshot` (redis-worker) to the webapp wrapper `deserialiseMollifierSnapshot` so both read-side modules share one deserialisation path, per the contract comment in `syntheticRedirectInfo.server.ts`. - cancel route: collapse the `mutateSnapshot` "not_found" branch into the same retry message as "busy". Both indicate the drainer raced the mutation between `getEntry` and `mutateSnapshot`; the run is in PG by then and a retry hits the regular cancel path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- CancelRunDialog: restore the `onCancelSubmitted` callback the PR description promised but never actually shipped. The run-detail route was passing this prop to a component that didn't accept it, breaking the webapp typecheck. Wire the callback to the form's onSubmit so the parent can close the Radix Dialog without wrapping the submit button in `DialogClose` — that wrapper races submit (close fires first, unmounts the form, the cancel POST never lands). - NoLogsView: restore the original "We delete old logs" retention copy on the no-completedAt branch. The earlier change overwrote it with a "Waiting to start" panel intended for buffered runs, but buffered runs always carry a synthetic trace (buildSyntheticTraceForBufferedRun) and never reach NoLogsView — so the new copy was unreachable for the case it was added for, while clobbering the actual case the branch fires for (in-flight PG runs with no logs). - syntheticReplayTaskRun: document why `as unknown as TaskRun` is load-bearing. SyntheticRun and Prisma TaskRun are not structurally assignable (optional vs required fields, narrower status enum, absent PG columns), so a direct cast won't compile; routing through `unknown` is the explicit "we know this is a subset, the audited fields ReplayTaskRunService reads are enumerated on SyntheticRun" signal. - replay loader: scope the buffered `orgProject` lookup by `organizationId: entry.orgId` as well as the env id. The prior `orgMember.findFirst` check confirms the user belongs to `entry.orgId`; pinning organizationId on the project query mirrors the PG path's `project.organization.members.some.userId` scoping and means a malformed entry whose envId resolves to a different org can't leak that project through this loader. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| }, | ||
| }); | ||
|
|
||
| // Mollifier read-fallback: if the original isn't in PG yet, | ||
| // synthesise a TaskRun from the buffered snapshot. The B4-extended | ||
| // SyntheticRun carries every field ReplayTaskRunService reads. We | ||
| // also need projectSlug + orgSlug + envSlug for the redirect path, | ||
| // so look those up via the snapshot's runtimeEnvironmentId. | ||
| let taskRun: SyntheticReplayTaskRun | null = pgRun ?? null; | ||
| if (!taskRun) { | ||
| const buffer = getMollifierBuffer(); | ||
| const entry = buffer ? await buffer.getEntry(runParam) : null; | ||
| if (entry) { | ||
| const synthetic = await findRunByIdWithMollifierFallback({ | ||
| runId: runParam, | ||
| environmentId: entry.envId, | ||
| organizationId: entry.orgId, | ||
| }); | ||
| if (synthetic) { | ||
| const envRow = await prisma.runtimeEnvironment.findFirst({ | ||
| where: { id: entry.envId }, | ||
| select: { | ||
| slug: true, | ||
| project: { select: { slug: true, organization: { select: { slug: true } } } }, | ||
| }, | ||
| }); | ||
| if (envRow) { | ||
| taskRun = buildSyntheticReplayTaskRun({ synthetic, envRow }); | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🚩 Replay action handler lacks user authentication (pre-existing)
The action export in resources.taskruns.$runParam.replay.ts:249 does not call requireUser or requireUserId, meaning any request with a valid runParam can replay a run. The original PG query at line 260 also has no user/org membership filter. The new buffered path (lines 284-306) inherits this pattern — it looks up the buffer entry and environment without any user check. While this is consistent with the pre-existing code, it extends the unauthenticated surface to buffered runs. Compare with the cancel route (resources.taskruns.$runParam.cancel.ts:20) which correctly calls requireUserId and checks org membership on both PG and buffer paths.
(Refers to lines 249-306)
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Dashboard surfaces handle buffered runs by falling back to the mollifier snapshot:
_app.../runs.\$runParam,resources.../spans.\$spanParam,resources.../streams.\$streamKey).@.runs.\$runParam,runs.\$runParam,projects.v3.\$projectRef.runs.\$runParam).resources.taskruns/...andresources.../idempotencyKey.reset.realtime.v1.runs.\$runId,resources.../realtime.v1.*).CancelRunDialoggains anonCancelSubmittedcallback so submit isn't raced by the RadixDialogClosewrapper.Stacked on the mutations PR.
Test plan