Skip to content

JITSU-123: blocking-modal presentation for billing banners#1419

Open
absorbb wants to merge 11 commits into
newjitsufrom
feat/billing-modal-surfaces
Open

JITSU-123: blocking-modal presentation for billing banners#1419
absorbb wants to merge 11 commits into
newjitsufrom
feat/billing-modal-surfaces

Conversation

@absorbb

@absorbb absorbb commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

JITSU-123 console slice (items 1, 2-partial, 4, 5 + design decisions). Banner payloads gain kind: "banner" | "modal" and extra:

  • BannerModal: parametrized modal presentation — 600px, top accent bar, card-language header (icon tile + title + badge), indented body, full-width action with centered subtitle. Mask not closable; Jitsu admins can dismiss regardless of closeable (session-only). Never renders on billing-fix pages.
  • BillingBlockingDialog deleted: pastDue is a server-driven modal (jitsucom/jitsu-cloud-billing#27); the console-computed quota-exceeded modal is retired.
  • API-level read-only: verifyAccessWithRole rejects editEntities/deleteEntities for workspaces carrying the readonly feature flag; reads open, manageUsers stays role-gated (inviting the card-holding teammate stays possible), Jitsu admins/service accounts bypass.
  • Billing page: non-modal banners nest compact (no extra/action/dismiss) under Events Usage instead of the top strip.
  • Partial throttle: appended as a line to the first server banner's body; standalone banner only when nothing to attach to.

JITSU-123

🤖 Generated with Claude Code

…-123)

Banner payloads gain kind: "banner" | "modal". Modals render the same
parametrized payload (severity theme, icon, title, badge, body, action)
in an antd Modal with a non-closable mask; Jitsu admins can dismiss
regardless of closeable (session-only). Modals never render on the
pages needed to fix billing (settings/domains/billing — the old
doNotBlockIfUsageExceeded set).

Replaces BillingBlockingDialog entirely: the past-due case is now a
server-driven modal from billing/settings (jitsu-cloud-billing#27),
and the console-computed quota-exceeded modal is retired — it locked
the UI at >100% while delivery runs to 105%, conflicting with JITSU-88
semantics (and its mask swallowed clicks on the banners underneath).
Removes the doNotBlockIfUsageExceeded plumbing from the layout and its
four pages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 23, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing modal migration and related page-layout updates in this PR. I focused on behavior/security regressions introduced by replacing BillingBlockingDialog with server-driven modal banners and removing per-page blocking props. I left two inline comments with concrete questions about potential blocking-edge cases.

Comment thread webapps/console/components/Billing/BillingBanners.tsx Outdated
Comment thread webapps/console/components/Billing/BillingBanners.tsx Outdated
… billing-page banners, throttle line, modal design

- verifyAccessWithRole rejects editEntities/deleteEntities mutations
  (403) for workspaces carrying the `readonly` feature flag (billing
  enforcement, e.g. unpaid invoices). Reads stay open; manageUsers
  stays role-gated only, so inviting the teammate who holds the credit
  card remains possible; Jitsu admins and service accounts bypass.
- Banner contract gains `extra` (widget zone, carries the quota
  progress bar); the billing page nests all non-modal banners under
  Events Usage via BannerCard's new `compact` mode (no extra, no
  action, no dismiss) instead of showing them in the top strip.
- Partial throttle alongside server banners no longer replaces them —
  its one fact is appended as a line to the first banner's body; a
  standalone throttle banner appears only when there is nothing to
  attach to.
- BannerModal redesigned to the approved mock: 600px, top accent bar,
  card-language header (icon tile + title + badge), indented body and
  full-width action with centered subtitle — replacing the legacy
  1000px/text-4xl proportions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing modal migration, billing-page banner rendering, and API readonly enforcement changes. I left a few inline comments for correctness edge cases that look worth addressing.

Comment thread webapps/console/components/Billing/BillingManager.tsx
Comment thread webapps/console/components/Billing/BillingBanners.tsx
Comment thread webapps/console/lib/api.ts
jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 23, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing-banner/modal refactor, readonly permission guard, and related settings-page wiring. I left one inline comment for a user-visible throttle regression in the new banner-priority flow.

Comment thread webapps/console/components/Billing/BillingBanners.tsx Outdated
The active-throttle and projection banners — and the priority rules
between them and server banners — now come fully composed from the
billing server (composeWorkspaceBanners). BillingBanners drops
useEventsUsage and all client banner construction; it only renders,
filters by onBillingPage, and dismisses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 23, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing banner/modal refactor and readonly-access enforcement across the touched console files. I left two inline notes for potential correctness regressions: modal dismissibility via keyboard and compact billing-page banners bypassing dismissal behavior.

Comment thread webapps/console/components/Billing/BillingBanners.tsx
Comment thread webapps/console/components/Billing/BillingManager.tsx
…ted banners

The throttling-warning, usage-exceeded-upgrade and projection alerts in
BillingManager duplicated the server banners now nested under Events
Usage — remove them (and the orphaned copy.tsx). The past-due alert
stays (it carries the direct Stripe payment link, which compact nested
banners deliberately omit) and past-due surfaces are excluded from the
nesting to avoid the same duplication. Overage-fee alerts stay — paid
plans get no banners.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing banner/modal refactor and readonly API enforcement across the changed console files.

I found one additional correctness concern to double-check: readonly enforcement currently appears scoped to verifyAccessWithRole(..., editEntities|deleteEntities), while some mutating endpoints still gate writes with verifyAccess only.

Comment thread webapps/console/lib/api.ts
jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 23, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing modal/banner migration and the new readonly permission checks. I found a few correctness gaps and left them inline (blocking-modal dismissibility and readonly enforcement coverage/admin bypass behavior).

Comment thread webapps/console/components/Billing/BillingBanners.tsx
Comment thread webapps/console/lib/api.ts
Comment thread webapps/console/lib/api.ts
…admin bypass, section-route permission, fullscreen modals, nested filter

- BannerModal always renders an action (falls back to "Go to billing")
  so a non-closeable modal can never strand a non-admin without a CTA,
  and gates keyboard (Esc) dismissal with the same condition as the ✕.
- Jitsu admins bypass the readonly guard even when they hold an
  explicit workspaceAccess row.
- POST /api/workspace/[id]/[section] (workspaceOptions writes) moves
  from verifyAccess to verifyAccessWithRole("editEntities") so it
  honors roles and the readonly flag.
- Fullscreen pages mount BillingBanners in modalsOnly mode — blocking
  modals are no longer skipped there (parity with the old dialog).
- The Events Usage nesting shows only banners the server moved off the
  top strip (onBillingPage === false), preventing double display of any
  future default-visible banner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…past-due exclusion

Applies the filter that a failed command chain silently dropped from an
earlier commit: nest only banners the server moved off the top strip
(onBillingPage === false), never modals, never past-due surfaces (the
dedicated unpaid-invoices alert carries the payment link).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing modal/banner refactor plus readonly API enforcement in this PR. The modal fallback CTA, Esc gating, fullscreen modal mount, and workspace-options POST role/readonly check all look correct. I left one inline follow-up question about a potential billing-page banner duplication edge case.

Comment thread webapps/console/components/Billing/BillingManager.tsx Outdated
jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 23, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing banner/modal refactor, settings-page layout changes, and the new readonly enforcement in verifyAccessWithRole plus the updated workspace section writer. Overall the direction looks good. I found one remaining readonly-enforcement gap (noted inline): there is still a mutating route gated only by verifyAccess, so readonly workspaces can still mutate backend state through that path.

Comment thread webapps/console/lib/api.ts
POST /api/[workspaceId]/profile-builder/state mutates
ProfileBuilderState2.fullRebuildInfo but used plain verifyAccess —
switch to verifyAccessWithRole("editEntities") so it honors roles and
the billing readonly flag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff from f1f843f to 654ca9c, focusing on billing banner/modal behavior, readonly enforcement, and the updated write-route access checks.

I verified the moved blocking-modal flow in , fullscreen mounting in , and the readonly gate plus the two route migrations to role-based checks.

No new actionable bugs, security issues, or correctness regressions stood out in this change set.

jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 23, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff from f1f843f to 654ca9c, focusing on billing banner/modal behavior, readonly enforcement, and the updated write-route access checks.

I verified the moved blocking-modal flow in BillingBanners, fullscreen mounting in WorkspacePageLayout, and the verifyAccessWithRole readonly gate plus the two route migrations to role-based checks.

No new actionable bugs, security issues, or correctness regressions stood out in this change set.

/settings/domains was in the modal-exempt list only as a carry-over of
the legacy doNotBlockIfUsageExceeded set — nothing there is needed to
fix billing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 23, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the changes in f1f843fc22ee72ddbe62da19c6bf57e4ecd663d4..9441b3763382b3f1d4ea086c299d7dbc3625ef61, focusing on billing banner/modal rendering and readonly-access enforcement updates in the touched API routes.

I did not find new actionable bugs, security issues, or correctness regressions in this revision.

Comment thread webapps/console/pages/[workspaceId]/settings/billing/details.tsx
Comment thread webapps/console/components/Billing/BillingBanners.tsx Outdated
…ODAL_EXEMPT_PAGES

Per review: billing-modal exemption is now declared by the page itself
via a WorkspacePageLayout property instead of a hardcoded path list in
BillingBanners — settings, billing and billing/details set it, so
"which pages stay reachable with unpaid invoices" is visible right in
the page files. Applies to fullscreen mounts too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jul 24, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing-banner/modal rollout, layout wiring, and readonly API enforcement in this PR range. Overall direction looks good; I left two non-blocking inline questions around potential user-visible regressions/contract brittleness.

Comment thread webapps/console/pages/[workspaceId]/settings/domains.tsx
Comment thread webapps/console/components/Billing/BillingManager.tsx Outdated
…oarse-flag alert

The nested list excluded past-due ids in favor of the legacy "unpaid
invoices" alert — but that alert fires on the old coarse
subscriptionStatus.pastDue, so the new state-driven warning showed
nowhere on the billing page. The legacy alert is removed (the plan
section keeps its Stripe-portal links) and the nesting now includes
every banner moved off the top strip; modal payloads (past-due
escalated) render as compact cards here since the page suppresses
blocking modals but must still inform.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the billing banner/modal refactor, WorkspacePageLayout wiring, and readonly API enforcement changes in this PR. I found one potential regression to double-check: the Domains settings page appears to have lost its billing-modal exemption, which can make that page inaccessible for past-due workspaces.

Comment thread webapps/console/pages/[workspaceId]/settings/domains.tsx
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.

2 participants