Skip to content

Keep existing payments working when new sales are off - #2020

Open
stefan-burke wants to merge 42 commits into
mainfrom
payment-aggregate/01-safety-behavior
Open

Keep existing payments working when new sales are off#2020
stefan-burke wants to merge 42 commits into
mainfrom
payment-aggregate/01-safety-behavior

Conversation

@stefan-burke

@stefan-burke stefan-burke commented Aug 1, 2026

Copy link
Copy Markdown
Member

What changed

Turning off new sales now stops new checkouts without cutting off payment work that already exists.

  • Refunds, payment callbacks, checkout completion, cancellation pages, and dashboard links use the provider for existing payments.
  • The site remembers the last active provider when new sales are turned off.
  • Older sites recover automatically when only one provider has saved credentials.
  • When several providers could own old payments, the operator must choose one before enabling sales or changing a domain.
  • Saving provider credentials keeps a newer provider choice and does not turn sales back on.
  • Provider credential saves and domain changes share the settings task lock, so overlapping requests cannot bypass recovery checks.

Operator impact

An operator can pause new online sales and still refund or finish payments already in progress. If an older site has an unclear provider, the settings page asks for an explicit choice while keeping new sales off.

Known limitation

Each payment still stores only its provider reference, not the provider name. If a site took payments through more than one provider, older payments may still need per-payment provider tracking. That follow-up is recorded in TODO.md and docs/payment-aggregate-acceptance.md.

The requested splits for the oversized settings modules are also recorded in TODO.md. They were not included here because this PR has a strict source-change limit.

Verification

  • Source churn against current main: 606 additions + 134 deletions = 740 lines.
  • Full deno task precommit passed on 0c4b76eac before merging current main.
  • The merged Stripe cleanup suite passed: 12 tests.
  • Every review thread has been answered and resolved.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 15 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 15bbe988-2481-435f-9602-c3eb5f7d477f

📥 Commits

Reviewing files that changed from the base of the PR and between bdefe2d and 17e3ea5.

📒 Files selected for processing (16)
  • TODO.md
  • src/features/admin/settings-domains.ts
  • src/features/admin/settings-general.ts
  • src/features/admin/settings-helpers.ts
  • src/locales/en/settings.json
  • src/shared/db/settings.ts
  • test/features/admin/settings-domains/custom-save.test.ts
  • test/features/admin/settings-general/payment-provider.test.ts
  • test/features/admin/settings-helpers/provider-credentials.test.ts
  • test/features/admin/settings-page/last-active-provider.test.ts
  • test/features/admin/settings-stripe.test.ts
  • test/shared/db/settings/public-api.test.ts
  • test/shared/stripe/endpoints/connection.test.ts
  • test/specs/steps/payment-provider-choice.ts
  • test/test-utils/csrf-and-forms.test.ts
  • test/test-utils/csrf.ts
📝 Walkthrough

Walkthrough

This change separates provider resolution for new sales from existing payments. It stores the last active provider, supports recovery while sales remain disabled, updates refunds and webhooks, adds recovery UI and domain guards, and documents payment-aggregate acceptance constraints.

Changes

Payment provider state and existing-payment flows

Layer / File(s) Summary
Remembered provider persistence
src/shared/db/settings.ts, src/shared/payments.ts, src/shared/db/settings/raw-writes.ts, src/shared/db/client.ts
Provider activation and deactivation now persist active and remembered providers atomically. Existing-payment operations resolve the remembered or unambiguous configured provider.
Payment and webhook integration
src/features/api/payment-processing/*, src/features/api/webhooks.ts, src/shared/payment-dashboard.ts
Refunds, classification, cancellation, webhooks, and dashboard links use existing-payment provider resolution. Refund failure details use a shared helper.
Admin recovery flow
src/features/admin/*, src/ui/templates/admin/settings/*, src/locales/en/settings.json
The admin can select a provider for existing payments without enabling new sales. Domain changes remain blocked while recovery choices exist.
Validation and acceptance coverage
test/**/*, specs/payments/payment-provider-choice.feature, docs/payment-aggregate-acceptance.md, TODO.md
Tests cover provider persistence, recovery, refunds, webhooks, settings UI, domain guards, and documented payment-aggregate constraints.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: existing payments remain serviceable when new sales are disabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch payment-aggregate/01-safety-behavior
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch payment-aggregate/01-safety-behavior

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/api/payment-processing/refunds.ts`:
- Around line 40-50: Define and export a shared ExistingPaymentProviderResult
type from `#shared/payments.ts`, then update getPaymentProviderOrLog in
src/features/api/payment-processing/refunds.ts#L40-L50 to use it instead of the
inline Awaited<ReturnType<...>> expression. Also update authenticateWebhook in
src/features/api/webhooks.ts#L321-L329 to use
NonNullable<ExistingPaymentProviderResult>, preserving its existing non-nullable
return contract.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: beec80eb-fa11-41a1-a2b5-fac7fdeca1e3

📥 Commits

Reviewing files that changed from the base of the PR and between 09e47fd and 2e4f452.

📒 Files selected for processing (18)
  • TODO.md
  • docs/payment-aggregate-acceptance.md
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • src/features/admin/require-provider.ts
  • src/features/api/payment-processing/classify.ts
  • src/features/api/payment-processing/refunds.ts
  • src/features/api/webhooks.ts
  • src/features/settings-bundles.ts
  • src/shared/db/settings.ts
  • src/shared/payments.ts
  • src/shared/settings/keys.ts
  • src/shared/settings/registry.ts
  • test/integration/server/payments/sales-off-safety.test.ts
  • test/integration/server/webhooks/refund-skip-conditions.test.ts
  • test/shared/db/settings/public-api.test.ts
  • test/shared/payments.test.ts
  • test/shared/settings/keys.test.ts
  • test/shared/settings/registry.test.ts

Comment thread src/features/api/payment-processing/refunds.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e4f452de1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/db/settings.ts Outdated
Comment thread src/shared/payments.ts Outdated
Switching new sales off (saving the payment provider as "none") used to strand
every payment already captured: refunds, replayed callbacks, redirect
completion, the cancel page, and operator refunds all resolved the provider
through the new-sales gate, so they broke the moment a buyer could no longer
start a checkout -- even though the provider's credentials stay stored.

Separate the two questions. New sales keep using getActivePaymentProvider /
isPaymentsEnabled. Refunds, provider reconciliation, replayed callbacks, and
completion of already-started payment work use a new resolver,
getPaymentProviderForExistingPayments, which falls back to the last provider the
operator activated when new sales are off. That provider is remembered in a new
last_active_payment_provider setting, captured when a provider is switched on
and again when new sales are switched off (a second "none" save keeps it).

The seven accepted safety rules the payment aggregate must satisfy --
including the owner-review, queued owner email, and aggregate-activation
behaviour not yet on main -- are recorded as acceptance constraints in
docs/payment-aggregate-acceptance.md, not built ahead of their time.

Regression tests cover each path: a captured payment refunded while sales are
off, an in-flight payment completing and issuing the ticket, a handled failure
replaying on a redelivered callback, and an operator refunding an existing paid
booking -- all written to fail before the fix and pass after.
@stefan-burke
stefan-burke force-pushed the payment-aggregate/01-safety-behavior branch from 2e4f452 to dc137e9 Compare August 1, 2026 00:49

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc137e955d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/payments.ts Outdated
CodeRabbit (CHANGES_REQUESTED): export a named ExistingPaymentProvider type
from #shared/payments.ts and use it in place of the duplicated
Awaited<ReturnType<typeof getPaymentProviderForExistingPayments>> expression
in getPaymentProviderOrLog and authenticateWebhook.

Codex P2: persist PAYMENT_PROVIDER and LAST_ACTIVE_PAYMENT_PROVIDER in one
writeRawBatch transaction (mirroring the existing Stripe activation path), so a
failure between the two writes cannot leave new sales enabled against a stale
remembered provider. The snapshot mirrors the committed values only after the
batch succeeds. A second 'none' save keeps the remembered provider.

Codex P1 (per-charge provider) and P1 (pre-existing none sites): recorded as
known gaps in docs/payment-aggregate-acceptance.md and TODO.md rather than
implemented here — per-charge provider tracking is the reference a charge lives
in and is future aggregate work; a site already on 'none' with no recorded
last-active provider is not regressed by this PR and recovers via a one-click
provider re-select.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc4a6dc84b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/db/settings.ts Outdated
Comment thread src/shared/db/settings.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
TODO.md (2)

34-35: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the Markdown reference to PR #1995.

Line 35 starts with #1995.. This triggers MD018 and renders as a malformed heading. Keep the reference in the sentence, such as shipped on PR #1995..

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TODO.md` around lines 34 - 35, Update the Finding 1 sentence in TODO.md so
the PR reference remains inline, ensuring it uses “PR `#1995`” rather than
starting the line with “#1995.” and triggering MD018.

Source: Linters/SAST tools


25-32: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace local scan references with durable references.

The TODO records an absolute /home/user/... path and local worktree names. These values are not available to other contributors and will become stale. Use stable ticket, PR, or repository-relative references.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TODO.md` around lines 25 - 32, Update the TODO entry describing Findings 2
and 4 to remove the absolute local scan path and local worktree names, replacing
them with durable ticket, pull-request, or repository-relative references while
preserving the findings’ descriptions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/shared/db/settings.ts`:
- Around line 464-480: Update setPaymentProviderNone so keepLastActive is
derived from the current database state or the provider transition is
serialized, preventing a concurrent activation from persisting a stale
LAST_ACTIVE_PAYMENT_PROVIDER alongside payment_provider = "none". Preserve the
behavior of retaining the last active provider on repeated disable operations,
and add a regression test covering the disable/activation interleaving.

In `@test/integration/server/payments/sales-off-safety.test.ts`:
- Around line 93-125: Replace the manual try/finally disposal at
test/integration/server/payments/sales-off-safety.test.ts lines 93-125 and lines
195-207 with using declarations for the stub results: use using mockVerify for
the verifyWebhookSignature stub and using mockRefund for the refund stub, then
keep each test body directly after its declaration and remove the corresponding
restore calls and try/finally wrappers.

In `@TODO.md`:
- Around line 492-494: The existing-payment guarantee is too broad because
fallback does not track the provider that captured each charge. In TODO.md lines
492-494 and docs/payment-aggregate-acceptance.md lines 21-25, replace the
unconditional claim with wording that guarantees recovery only for payments
captured by the remembered provider, while explicitly retaining the per-charge
provider identity gap.
- Around line 513-516: Update the payment persistence and dispatch flow so each
payment charge retains its capture-time provider using the existing
payment_charges.provider and reference_index fields, rather than storing
provider identity only on processed_payments. Backfill legacy charges only when
capture-time evidence identifies one unambiguous provider; mark unresolved
charges non-dispatchable and expose them for operator review, then dispatch
existing-payment work from each charge’s provider instead of a global fallback.

---

Outside diff comments:
In `@TODO.md`:
- Around line 34-35: Update the Finding 1 sentence in TODO.md so the PR
reference remains inline, ensuring it uses “PR `#1995`” rather than starting the
line with “#1995.” and triggering MD018.
- Around line 25-32: Update the TODO entry describing Findings 2 and 4 to remove
the absolute local scan path and local worktree names, replacing them with
durable ticket, pull-request, or repository-relative references while preserving
the findings’ descriptions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ee66fda4-586e-4c45-8d73-c697b958b976

📥 Commits

Reviewing files that changed from the base of the PR and between 2e4f452 and bc4a6dc.

📒 Files selected for processing (18)
  • TODO.md
  • docs/payment-aggregate-acceptance.md
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • src/features/admin/require-provider.ts
  • src/features/api/payment-processing/classify.ts
  • src/features/api/payment-processing/refunds.ts
  • src/features/api/webhooks.ts
  • src/features/settings-bundles.ts
  • src/shared/db/settings.ts
  • src/shared/payments.ts
  • src/shared/settings/keys.ts
  • src/shared/settings/registry.ts
  • test/integration/server/payments/sales-off-safety.test.ts
  • test/integration/server/webhooks/refund-skip-conditions.test.ts
  • test/shared/db/settings/public-api.test.ts
  • test/shared/payments.test.ts
  • test/shared/settings/keys.test.ts
  • test/shared/settings/registry.test.ts

Comment thread src/shared/db/settings.ts
Comment thread test/integration/server/payments/sales-off-safety.test.ts Outdated
Comment thread TODO.md Outdated
Comment thread TODO.md Outdated
The shared type refactor shifted the payments.ts ?? equivalent from line
379 to 387; record the same equivalent in settings.ts:471 (data.payment_provider
?? "" — a provider type or null, never falsy-but-non-null).
CodeRabbit: tighten 'never stranded' to 'payments captured by that provider
stay refundable and completable' in the acceptance doc and TODO, since the
fallback only resolves the remembered provider (not per-charge).

CodeRabbit: replace manual try/finally stub disposal with using declarations
in sales-off-safety.test.ts (the established pattern in
test/integration/server/webhooks/).
Comment thread src/shared/db/settings.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3fbb3d6d9a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/db/settings.ts Outdated
Comment thread src/shared/payments.ts Outdated
Codex: throw on a corrupt non-empty last_active_payment_provider value
(offensive programming — a stored garbage string is surfaced at read time
rather than silently treated as null). Covered by a regression test.

Codex: paymentDashboardUrl and the domain-change webhook warning both read
settings.paymentProvider (the new-sales gate) and returned null when sales
were off, hiding dashboard links and the domain-change warning for existing
payments. Both now fall back to settings.lastActivePaymentProvider.

Remove the broken CODEX_SECURITY_PYTHON export from flake.nix — the
codexSecurityPython variable was never defined (landed on main in commit
09e47fd), breaking nix develop and every nix-wrapped check runner.
Pre-existing none sites: the resolver now falls back to the sole provider
with stored credentials when exactly one is configured (unambiguous
evidence). When zero or multiple providers have credentials, it returns null
(genuine ambiguity — operator must re-select, no guessing).

Concurrency race: setPaymentProviderNone now reads the current provider from
the database via a SQL subquery inside the batch statement (not from the
request-start snapshot), so a concurrent activation landing before the
batch is correctly reflected. Uses a single INSERT OR REPLACE ... SELECT
that evaluates subqueries against pre-statement state, making read and write
atomic without withTransaction's cache invalidation (which resets the
session private key).

Regression tests: single-credential recovery, multi-credential no-guess,
sumup sole-credential, concurrency race (stale snapshot vs DB state).
Raw-cache mirroring assertions kill the syncStoredSetting removal mutant.
Mirror-located tests added for require-provider, refunds, webhooks,
settings-page, custom-domain, subdomain.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/shared/db/settings/raw-writes.ts (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Export syncWrittenBatch and reuse it in setPaymentProviderNone to fix the doc comment and remove duplicated cache-sync logic. The comment on syncWrittenBatch claims it is "Shared by every batch write path," but setPaymentProviderNone bypasses it, manually calling syncStoredSetting twice with the same key/value-mirroring logic that syncWrittenBatch already implements in one syncCache call.

  • src/shared/db/settings/raw-writes.ts#L95-105: export syncWrittenBatch, or correct the comment to state it is shared only by writeRawBatch-based paths.
  • src/shared/db/settings.ts#L507-512: once known values are available (after the write completes), call syncWrittenBatch([[CONFIG_KEYS.PAYMENT_PROVIDER, "none"], [CONFIG_KEYS.LAST_ACTIVE_PAYMENT_PROVIDER, lastActive]]) instead of two separate syncStoredSetting calls.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/db/settings/raw-writes.ts` at line 1, The syncWrittenBatch
helper’s documented shared usage is incomplete and setPaymentProviderNone
duplicates its cache synchronization. Export syncWrittenBatch from
raw-writes.ts, then update setPaymentProviderNone to call it after the write
completes with both payment-provider key/value pairs, replacing the two
syncStoredSetting calls.
test/shared/db/settings/public-api.test.ts (1)

133-141: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reload after the second none save.

This test only checks the current snapshot. A second setPaymentProviderNone() call could clear the stored remembered provider while this assertion still passes.

Invalidate the cache, reload CONFIG_KEYS.LAST_ACTIVE_PAYMENT_PROVIDER, and assert that the value remains "stripe".

Proposed test extension
       await settings.update.setPaymentProviderNone();
       await settings.update.setPaymentProviderNone();
       expect(settings.paymentProvider).toBeNull();
       expect(settings.lastActivePaymentProvider).toBe("stripe");
+
+      settings.invalidateCache();
+      await settings.loadKeys([CONFIG_KEYS.LAST_ACTIVE_PAYMENT_PROVIDER]);
+      expect(settings.lastActivePaymentProvider).toBe("stripe");

As per coding guidelines, “Every bug fix must include a regression test that reproduces the exact defect and fails before the fix.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/shared/db/settings/public-api.test.ts` around lines 133 - 141, The test
“a second none save keeps the remembered provider” only verifies the in-memory
snapshot; invalidate the settings cache after the second
setPaymentProviderNone() call, reload CONFIG_KEYS.LAST_ACTIVE_PAYMENT_PROVIDER,
and assert the persisted value remains "stripe" alongside the existing
assertions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/mutation/equivalent-mutants/shared-m-z.txt`:
- Around line 29-33: Remove the three ?? → || entries for custom-domain.tsx and
subdomain.tsx from the equivalent-mutant list, since empty-string
paymentProvider values make them behaviorally different. Correct the
accompanying falsy-value statement so it does not claim that "none" is falsy; do
not narrow the state type or alter advancedDefaultState unless choosing that
alternative instead.

In `@src/shared/db/settings.ts`:
- Around line 473-516: Update setPaymentProviderNone to use
executeBatchWithResults, add RETURNING key, value to the INSERT statement, and
extract the returned last_active_payment_provider row instead of calling
requireOne. Protect the subsequent syncStoredSetting calls from a concurrent
activation so this operation cannot overwrite newer cached provider state with
the stale "none" state; use the existing cache synchronization mechanism.

In `@src/shared/payment-dashboard.ts`:
- Around line 33-36: Add a regression test for paymentDashboardUrl that sets
payment_provider to null and last_active_payment_provider to "stripe", then
asserts paymentDashboardUrl("pi_123") returns the expected Stripe dashboard URL.
Place it alongside the existing dashboard tests and preserve the current
direct-provider cases.

---

Outside diff comments:
In `@src/shared/db/settings/raw-writes.ts`:
- Line 1: The syncWrittenBatch helper’s documented shared usage is incomplete
and setPaymentProviderNone duplicates its cache synchronization. Export
syncWrittenBatch from raw-writes.ts, then update setPaymentProviderNone to call
it after the write completes with both payment-provider key/value pairs,
replacing the two syncStoredSetting calls.

In `@test/shared/db/settings/public-api.test.ts`:
- Around line 133-141: The test “a second none save keeps the remembered
provider” only verifies the in-memory snapshot; invalidate the settings cache
after the second setPaymentProviderNone() call, reload
CONFIG_KEYS.LAST_ACTIVE_PAYMENT_PROVIDER, and assert the persisted value remains
"stripe" alongside the existing assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bd6eada2-ebfb-4da1-a0da-abcec4751031

📥 Commits

Reviewing files that changed from the base of the PR and between bc4a6dc and 5345a26.

📒 Files selected for processing (26)
  • TODO.md
  • docs/payment-aggregate-acceptance.md
  • flake.nix
  • scripts/mutation/equivalent-mutants/shared-db.txt
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • src/features/admin/settings-page.ts
  • src/shared/db/settings.ts
  • src/shared/db/settings/raw-writes.ts
  • src/shared/payment-dashboard.ts
  • src/shared/payments.ts
  • src/ui/templates/admin/settings-advanced.tsx
  • src/ui/templates/admin/settings.tsx
  • src/ui/templates/admin/settings/custom-domain.tsx
  • src/ui/templates/admin/settings/subdomain.tsx
  • test/features/admin/require-provider.test.ts
  • test/features/admin/settings-page/last-active-provider.test.ts
  • test/features/api/payment-processing/refunds.test.ts
  • test/features/api/webhooks.test.ts
  • test/integration/server/payments/sales-off-safety.test.ts
  • test/integration/server/webhooks/refund-skip-conditions.test.ts
  • test/shared/db/settings/public-api.test.ts
  • test/shared/payments.test.ts
  • test/ui/templates/admin/settings-advanced/state.ts
  • test/ui/templates/admin/settings-state.ts
  • test/ui/templates/admin/settings/custom-domain.test.ts
  • test/ui/templates/admin/settings/subdomain.test.ts
💤 Files with no reviewable changes (1)
  • flake.nix

Comment thread scripts/mutation/equivalent-mutants/shared-m-z.txt Outdated
Comment thread src/shared/db/settings.ts
Comment thread src/shared/payment-dashboard.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5345a26401

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/db/settings.ts Outdated
Comment thread src/ui/templates/admin/settings/custom-domain.tsx Outdated
Comment thread src/shared/payments.ts Outdated
Comment thread src/shared/payments.ts Outdated
Comment thread scripts/mutation/equivalent-mutants/shared-m-z.txt Outdated
Comment thread src/shared/payments.ts Outdated
Comment thread TODO.md Outdated
Comment thread src/shared/payment-dashboard.ts Outdated
Finding (1): Replace the lagging-replica readOne after the INSERT...SELECT
with RETURNING value — the computed last_active is read from the write's own
batch result, never from a replica.

Finding (2): Unify paymentDashboardUrl and settings-page.ts on the shared
existingPaymentProviderType() from payments.ts — one provider-resolution
mechanism, no duplicate credential scans. Templates restored to main
(untouched); the advanced settings-page state supplies the resolved provider
via s.paymentProvider, so DomainPaymentWebhookWarning sees it without
template changes.

Finding (3): Remove the invalid shared-db equivalent entry for none->empty.
Finding (4): Remove the invalid UI ??->|| equivalent entries (string|null).
Finding (6): Document INSERT...SELECT (not withTransaction) in TODO.md.

Template files (.tsx) reverted to main to reduce mutation scope. Two
settings-state test fixtures reverted to match.
…tActive

Replace rawWritesApi + manual branch checks + results[0]! with a single
valibot tupleWithRest schema that validates the full batch result shape:
exactly one result set with exactly one {value: string} row, plus any
remaining result sets. v.parse(results)[0].rows[0].value is fully
type-safe — no local invalid-shape branches, no non-null assertions, no
test-only exports.

Restore distinct lastActivePaymentProvider in template state (not
overloaded into paymentProvider which controls the sales radio).
Templates use s.paymentProvider ?? s.lastActivePaymentProvider so the
domain-change warning shows when sales are off while the radio stays
'none'. Template test fixtures and types updated to match.

Remove all jscpd:ignore markers outside import blocks; extract shared
test helpers (log-spy, webhook-verify-helpers, withRefundRedirect).

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17a9483505

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/payments.ts Outdated
Comment thread src/shared/db/settings/raw-writes.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/shared/db/settings.ts (1)

250-260: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep provider selection in one atomic path. lastActivePaymentProvider correctly maps "" to null and throws for unsupported values. Square and SumUp use the shared setter, but Stripe activate() writes PAYMENT_PROVIDER before the shared setter writes LAST_ACTIVE_PAYMENT_PROVIDER. Include both keys in one atomic activation path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/db/settings.ts` around lines 250 - 260, The Stripe activation flow
must update PAYMENT_PROVIDER and LAST_ACTIVE_PAYMENT_PROVIDER atomically. Modify
Stripe’s activate() path to use the shared setter or atomic mechanism that
writes both settings together, removing the separate PAYMENT_PROVIDER write
while preserving lastActivePaymentProvider’s empty-value and validation
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/features/api/webhooks.test.ts`:
- Around line 33-36: Update the “rejects a success callback with only bad token
params” test to store the response text and assert it contains the specific
invalid-payment-callback message used by the sibling test, replacing the
non-empty-length assertion.

In `@test/shared/db/settings/raw-writes.test.ts`:
- Around line 66-79: Add a negative test alongside the existing
“executeSettingsBatchReturningValue” test that exercises a RETURNING result with
zero or multiple rows and asserts the validation rejects it. Cover the newly
added batchReturningValue parse-rejection branch directly while preserving the
existing successful single-row test.
- Around line 33-37: Update the “throws on an empty batch” test callback to be
async and await the rejects assertion for writeRawBatch([]), ensuring the test
waits for and correctly reports the expected rejection.

In `@test/test-utils/log-spy.ts`:
- Around line 17-18: Remove the useDebugLogSpy re-export from this helper module
and update all callers to import it directly from its defining ./debug-log.ts
module; do not move or duplicate the implementation, and do not retain a
compatibility import path.
- Around line 20-22: Extract the duplicated call-matching logic from errorLogged
and debugLogged into one private logLogged helper that accepts the spy and
needle, preserves the explicit boolean return type, and has both exported
functions delegate to it without changing behavior.

In `@test/test-utils/webhook-verify-helpers.ts`:
- Around line 9-23: The webhook test helper does not expose the HTTP status, so
the deleted-listing refund test cannot verify its promised 404 response. In
test/test-utils/webhook-verify-helpers.ts lines 9-23, update withWebhookVerify’s
assertions callback to receive res.status and pass it through; in
test/features/api/payment-processing/refunds.test.ts lines 164-182, update the
deleted-listing refund test callback to assert that status is 404 while
preserving the existing JSON assertion.

In `@test/ui/templates/admin/settings/custom-domain.test.ts`:
- Around line 19-20: Strengthen warning assertions in
test/ui/templates/admin/settings/custom-domain.test.ts:19-20 and
test/ui/templates/admin/settings/subdomain.test.ts:19-20 by asserting the
complete provider warning structure, including its linked provider settings
target. At test/ui/templates/admin/settings/custom-domain.test.ts:32 and
test/ui/templates/admin/settings/subdomain.test.ts:32, assert that both the
complete warning element and provider link are absent, using structural or exact
observable assertions rather than independent presence-only checks.

---

Outside diff comments:
In `@src/shared/db/settings.ts`:
- Around line 250-260: The Stripe activation flow must update PAYMENT_PROVIDER
and LAST_ACTIVE_PAYMENT_PROVIDER atomically. Modify Stripe’s activate() path to
use the shared setter or atomic mechanism that writes both settings together,
removing the separate PAYMENT_PROVIDER write while preserving
lastActivePaymentProvider’s empty-value and validation behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5616ebe7-d126-4c16-86d4-71ab49e89259

📥 Commits

Reviewing files that changed from the base of the PR and between 5345a26 and 17a9483.

📒 Files selected for processing (16)
  • TODO.md
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • src/features/admin/settings-page.ts
  • src/shared/db/client.ts
  • src/shared/db/settings.ts
  • src/shared/db/settings/raw-writes.ts
  • src/shared/payment-dashboard.ts
  • src/shared/payments.ts
  • src/ui/templates/admin/settings.tsx
  • test/features/api/payment-processing/refunds.test.ts
  • test/features/api/webhooks.test.ts
  • test/shared/db/settings/raw-writes.test.ts
  • test/test-utils/log-spy.ts
  • test/test-utils/webhook-verify-helpers.ts
  • test/ui/templates/admin/settings/custom-domain.test.ts
  • test/ui/templates/admin/settings/subdomain.test.ts

Comment thread test/features/api/webhooks.test.ts Outdated
Comment thread test/shared/db/settings/raw-writes.test.ts Outdated
Comment thread test/shared/db/settings/raw-writes.test.ts
Comment thread test/test-utils/log-spy.ts Outdated
Comment thread test/test-utils/log-spy.ts Outdated
Comment thread test/test-utils/webhook-verify-helpers.ts
Comment thread test/ui/templates/admin/settings/custom-domain.test.ts
Add comprehensive render-snapshot tests for custom-domain.tsx and
subdomain.tsx that assert every form field, action, label, CSS class,
and i18n-rendered text — killing ~46 string-literal and operator mutants.

Add a check-form test for subdomain.tsx covering the no-subdomain render
path (type=text, muted, Check button, suffix).

Remove stale equivalent-mutant entries: settings-page.ts:128:46 (line no
longer has ??) and settings-bundles.ts:247:40 (superseded by 248:40 in
shared-m-z.txt).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/ui/templates/admin/settings/custom-domain.test.ts`:
- Around line 47-63: Strengthen the assertions at
test/ui/templates/admin/settings/custom-domain.test.ts:47-63 by matching the
custom_domain input value tickets.example.com and verifying it is associated
with the custom-domain form. In
test/ui/templates/admin/settings/subdomain.test.ts:47-63, assert the hidden
subdomain control contains my-sub and belongs to the registration form. In
test/ui/templates/admin/settings/subdomain.test.ts:76-79, bind the
availability-check input and its control to the check form, replacing
independent presence-only assertions with form-scoped observable checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: df80243a-a347-49a9-8b09-5debd683ebcf

📥 Commits

Reviewing files that changed from the base of the PR and between 17a9483 and 9c67112.

📒 Files selected for processing (4)
  • scripts/mutation/equivalent-mutants/shared-a-l.txt
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • test/ui/templates/admin/settings/custom-domain.test.ts
  • test/ui/templates/admin/settings/subdomain.test.ts
💤 Files with no reviewable changes (2)
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • scripts/mutation/equivalent-mutants/shared-a-l.txt

Comment thread test/ui/templates/admin/settings/custom-domain.test.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c67112c19

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/mutation/equivalent-mutants/shared-m-z.txt Outdated
refunds.ts (16/16 killed): direct unit tests for tryRefund,
validationFailure, refuseMismatch, refundSpec, refundedNoteText —
table-driven for REFUND_REASONS.

webhooks.ts (22/47 killed): Square orderId redirect, 409 concurrent
reservation, refunded-with-failed-refund, augmented log assertions.

custom-domain.tsx (8/8 killed): CSS-class, whitespace, and ??→||
assertions via regex-based render checks.

subdomain.tsx (15/15 killed): i18n keys, CSS classes, ??→||, &&→||,
!→∅, false→true, value→ via register+check form assertions.

raw-writes.ts (4/6 killed): recordSettingsLoaded and loaded.add
removal via audit-wrapped assertions.

Remaining 29 survivors: webhooks.ts complex processSessionAndRedirect
paths (multi-token URLs, thank-you), raw-writes loaded.add (not read
by getCachedRaw), client.ts false→true (transient-error retry).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/features/api/payment-processing/refunds.test.ts`:
- Around line 314-322: Strengthen the non-404 case in the validationFailure test
by asserting an observable refund attempt outcome, not only refunded: false.
Reuse the existing errorLogged/errorSpy pattern for the unconfigured provider,
or configure a stub via stubStripeRefund and assert its specific result, so the
test distinguishes an attempted refund from skipping the non-404 branch.

In `@test/shared/db/settings/raw-writes.test.ts`:
- Around line 56-67: The test currently verifies only cache state and does not
confirm persisted deletion. Split the deletion behavior from the
audit-registration case, then in the focused `writeOrDelete` test invalidate the
cache, reload `CONFIG_KEYS.SQUARE_LOCATION_ID`, and assert
`settings.square.locationId` is empty while retaining the existing write/delete
setup.

In `@test/ui/templates/admin/settings/custom-domain.test.ts`:
- Around line 33-35: Remove the validation-action assertion from the
warning-suppression test and place it in the existing form-rendering test, or
create a dedicated test for it. Keep the current test focused exclusively on
verifying warning suppression, while preserving the validation action
expectation separately.
- Line 36: Replace the syntax-focused comments at
test/ui/templates/admin/settings/custom-domain.test.ts lines 36-36 and
test/ui/templates/admin/settings/subdomain.test.ts lines 33-34 with brief
behavior-focused statements that an empty configured provider suppresses the
warning; replace the comment at
test/ui/templates/admin/settings/subdomain.test.ts lines 44-45 with a brief
statement that the preview rendering path suppresses the warning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 092d3bcf-ecdc-4709-9bf3-3fa7955060a5

📥 Commits

Reviewing files that changed from the base of the PR and between 9c67112 and b6dbcd7.

📒 Files selected for processing (5)
  • test/features/api/payment-processing/refunds.test.ts
  • test/features/api/webhooks.test.ts
  • test/shared/db/settings/raw-writes.test.ts
  • test/ui/templates/admin/settings/custom-domain.test.ts
  • test/ui/templates/admin/settings/subdomain.test.ts

Comment thread test/features/api/payment-processing/refunds.test.ts
Comment thread test/shared/db/settings/raw-writes.test.ts Outdated
Comment thread test/ui/templates/admin/settings/custom-domain.test.ts Outdated
Comment thread test/ui/templates/admin/settings/custom-domain.test.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6dbcd7b09

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/payment-dashboard.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aab800bcda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/payments.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/admin/settings-general.ts`:
- Around line 76-87: Declare an explicit shared handler return type for the
exported handlePaymentProviderRecoveryPost constant, applying it to the
settingsHandler result while preserving its existing extract, save, log, and
validate behavior.

In `@src/shared/existing-payment-provider.ts`:
- Line 32: Update the exported existingPaymentProviderApi.getStored function to
explicitly declare a PaymentProviderSetting | null return type, while preserving
its existing settings.paymentProviderSetting return behavior.
- Around line 55-62: Update the provider-selection flow around current,
remembered, and configured providers to load configured first and accept current
or remembered only when configured contains that provider; otherwise continue to
the single-provider or recovery-choice fallback. Add a regression test covering
a remembered provider with missing credentials, asserting it is not selected and
the appropriate null or recovery result is returned.

In `@test/features/api/webhooks/success-details.test.ts`:
- Around line 205-208: Review the setup around the raw update in the relevant
test and reuse an existing test-utils/db-helpers function for assigning an
attendee’s package_group_id if one exists. Replace the direct getDb().execute
call with that helper while preserving the same group.id and attendee.id values;
retain the raw SQL only if no suitable helper exists.

In `@test/ui/templates/admin/settings/custom-domain.test.ts`:
- Around line 43-56: Require each expected form or input match before inspecting
attributes: in test/ui/templates/admin/settings/custom-domain.test.ts lines
43-56, assert the custom-domain form match is not null and return early if
needed, then require its custom_domain input similarly; apply the same pattern
to the recovery form in
test/features/admin/settings-page/last-active-provider.test.ts lines 43-53, the
registration form and hidden subdomain input in
test/ui/templates/admin/settings/subdomain.test.ts lines 60-67, and the
availability-check form and text input in
test/ui/templates/admin/settings/subdomain.test.ts lines 91-99. Replace optional
`?.[0]` access for these required elements with strong assertions and early
returns for type narrowing.

In `@test/ui/templates/admin/settings/payment.test.ts`:
- Around line 119-125: Add direct tests alongside the existing Stripe
availability test for SquareForm and SumUpForm, using matching
existingPaymentProvider values with paymentProvider set to null. Assert the
rendered HTML contains id="settings-square" and id="settings-sumup" to cover
both existing-provider visibility branches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bb9cd672-da9a-4e30-bcd4-6ddb74c5d5ca

📥 Commits

Reviewing files that changed from the base of the PR and between d6c57df and c988434.

📒 Files selected for processing (38)
  • TODO.md
  • docs/payment-aggregate-acceptance.md
  • scripts/mutation/equivalent-mutants/features.txt
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • src/features/admin/settings-general.ts
  • src/features/admin/settings-page.ts
  • src/features/admin/settings.ts
  • src/locales/en/settings.json
  • src/shared/db/settings.ts
  • src/shared/db/settings/raw-writes.ts
  • src/shared/existing-payment-provider.ts
  • src/shared/payment-dashboard.ts
  • src/shared/payments.ts
  • src/ui/templates/admin/settings-advanced.tsx
  • src/ui/templates/admin/settings.tsx
  • src/ui/templates/admin/settings/custom-domain.tsx
  • src/ui/templates/admin/settings/payment.tsx
  • src/ui/templates/admin/settings/subdomain.tsx
  • src/ui/templates/components/radio-option.tsx
  • test/features/admin/settings-general/payment-provider.test.ts
  • test/features/admin/settings-page/last-active-provider.test.ts
  • test/features/api/payment-processing/refunds.test.ts
  • test/features/api/webhooks/callbacks.test.ts
  • test/features/api/webhooks/helpers.ts
  • test/features/api/webhooks/provider.test.ts
  • test/features/api/webhooks/success-details.test.ts
  • test/integration/server/webhooks/refund-skip-conditions.test.ts
  • test/shared/db/settings/raw-writes.test.ts
  • test/shared/payment-dashboard.test.ts
  • test/shared/payments.test.ts
  • test/test-utils/debug-log.ts
  • test/test-utils/webhook-verify-helpers.ts
  • test/ui/templates/admin/settings-advanced/page.test.ts
  • test/ui/templates/admin/settings-advanced/state.ts
  • test/ui/templates/admin/settings-state.ts
  • test/ui/templates/admin/settings/custom-domain.test.ts
  • test/ui/templates/admin/settings/payment.test.ts
  • test/ui/templates/admin/settings/subdomain.test.ts

Comment thread src/features/admin/settings-general.ts Outdated
Comment thread src/shared/existing-payment-provider.ts Outdated
Comment thread src/shared/existing-payment-provider.ts Outdated
Comment thread test/features/api/webhooks/success-details.test.ts
Comment thread test/ui/templates/admin/settings/custom-domain.test.ts Outdated
Comment thread test/ui/templates/admin/settings/payment.test.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 704933bc1e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/admin/settings-page.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd669d095d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/db/settings.ts
Comment thread src/features/admin/require-provider.ts Outdated
Comment thread src/features/settings-bundles.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/shared/db/settings.ts (1)

487-497: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Alias the settings reads.

Line 491 and Line 495 read settings without AS aliases. Use distinct descriptive singular aliases for the current-provider and remembered-provider reads, then qualify value.

As per coding guidelines, “Alias SQL tables with descriptive full singular words using AS.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/db/settings.ts` around lines 487 - 497, Update the SQL in the
settings migration to alias both settings subqueries with distinct descriptive
singular aliases using AS: one for the current payment provider and one for the
remembered provider. Qualify each referenced value column with its corresponding
alias while preserving the existing provider validation and fallback behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/admin/settings-general.ts`:
- Around line 77-87: Update settingsHandler’s validation contract to return the
parsed PaymentProviderSchema value, and modify handlePaymentProviderRecoveryPost
so its validate callback returns that validated PaymentProviderType. Pass the
validated value directly to settings.update.recoverPaymentProvider, removing the
existing `as PaymentProviderType` cast while preserving the invalid-input error
path.

In `@src/locales/en/settings.json`:
- Line 24: Update the success.existing_payment_provider_set locale string to end
with a period, preserving the existing message text and placeholder.

In `@src/ui/templates/admin/settings/payment-provider.tsx`:
- Line 80: Preserve the submitted recovery provider when recovery validation
fails: extend SettingsPageState on the failure path with the submitted provider,
and update the recovery-provider radio rendering to derive checked from that
state instead of hardcoding false. Add a direct regression test covering the
failed recovery POST and confirming the submitted provider remains selected.

In `@test/features/admin/settings-general/payment-provider.test.ts`:
- Around line 143-155: Update the stale recovery scenario in the “rejects a
stale recovery post after sales were enabled” test to expect an error explicitly
stating that recovery is unavailable after sales are enabled, rather than the
missing-credentials message. Preserve the rejected POST behavior and the
existing paymentProvider and lastActivePaymentProvider assertions.

---

Outside diff comments:
In `@src/shared/db/settings.ts`:
- Around line 487-497: Update the SQL in the settings migration to alias both
settings subqueries with distinct descriptive singular aliases using AS: one for
the current payment provider and one for the remembered provider. Qualify each
referenced value column with its corresponding alias while preserving the
existing provider validation and fallback behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2e376587-42fe-4c22-aca6-a35335ec5c61

📥 Commits

Reviewing files that changed from the base of the PR and between 92fc06c and 7daf37c.

📒 Files selected for processing (38)
  • scripts/screenshots/app-server.ts
  • src/features/admin/require-provider.ts
  • src/features/admin/settings-domains.ts
  • src/features/admin/settings-general.ts
  • src/features/admin/settings-helpers.ts
  • src/features/admin/settings-page.ts
  • src/features/admin/settings-stripe.ts
  • src/features/settings-bundles.ts
  • src/locales/en/settings.json
  • src/shared/db/settings.ts
  • src/shared/existing-payment-provider.ts
  • src/ui/templates/admin/settings-advanced.tsx
  • src/ui/templates/admin/settings.tsx
  • src/ui/templates/admin/settings/custom-domain.tsx
  • src/ui/templates/admin/settings/domain-payment-warning.tsx
  • src/ui/templates/admin/settings/payment-provider.tsx
  • src/ui/templates/admin/settings/payment.tsx
  • src/ui/templates/admin/settings/subdomain.tsx
  • src/ui/templates/components/actions.tsx
  • test/features/admin/require-provider.test.ts
  • test/features/admin/settings-general/payment-provider.test.ts
  • test/features/admin/settings-page/last-active-provider.test.ts
  • test/features/admin/settings-stripe.test.ts
  • test/integration/server/settings/domains.test.ts
  • test/integration/server/webhooks/refund-skip-conditions.test.ts
  • test/shared/db/settings/public-api.test.ts
  • test/shared/db/settings/stripe-credentials.test.ts
  • test/shared/existing-payment-provider.test.ts
  • test/shared/payment-dashboard.test.ts
  • test/shared/payments.test.ts
  • test/shared/stripe/endpoints.test.ts
  • test/test-utils/refund-routes.ts
  • test/test-utils/settings.ts
  • test/ui/templates/admin/settings-advanced/state.ts
  • test/ui/templates/admin/settings/custom-domain.test.ts
  • test/ui/templates/admin/settings/domain-payment-warning.test.tsx
  • test/ui/templates/admin/settings/payment.test.ts
  • test/ui/templates/admin/settings/subdomain.test.ts
💤 Files with no reviewable changes (1)
  • src/ui/templates/admin/settings/payment.tsx

Comment thread src/features/admin/settings-general.ts Outdated
Comment thread src/locales/en/settings.json Outdated
Comment thread src/ui/templates/admin/settings/payment-provider.tsx Outdated
Comment thread test/features/admin/settings-general/payment-provider.test.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a8f275d162

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/admin/settings-helpers.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6df7bd427a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/admin/settings-helpers.ts Outdated
Comment thread src/features/admin/settings-helpers.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@specs/payments/payment-provider-choice.feature`:
- Around line 45-57: The scenario is asserting registration availability while
only checking the host subdomain. Update the scenario step for “mylisting” to
use the registration action with save: "1" after each provider-recovery state,
or change the assertions to validate availability instead; preserve the
recovery-dependent behavior being tested.

In `@test/features/admin/settings-domains/custom-validate.test.ts`:
- Around line 158-174: Update the catch block in the “clears the task when
validation throws” test to assert that the captured error is the expected
network failure, rather than swallowing it; keep the finally block restoring
bunnyCdnApi.validateCustomDomain and preserve the settings.currentTask
assertion.

In `@test/features/admin/settings-domains/support.ts`:
- Line 10: Remove the setAmbiguousPaymentProvider alias: in
test/features/admin/settings-domains/support.ts:10-10, re-export
requirePaymentProviderRecovery directly; in
test/features/admin/settings-domains/custom-save.test.ts:7-7, import and call
requirePaymentProviderRecovery at line 38; and in
test/features/admin/settings-domains/host-subdomain.test.ts:10-10, import and
call requirePaymentProviderRecovery at line 179.
- Around line 82-86: Update the exported subdomainCheck function with an
explicit return type, using an existing named interface or shared type from the
file when available; otherwise define a concise named type for its available,
fullDomain, and ok fields, while preserving the current return values.

In `@test/specs/steps/payment-provider-choice.ts`:
- Around line 161-177: Update the step definition “the organiser must choose the
provider for existing payments” so each required radio input is validated by
independently extracting or checking its full input tag, then asserting name,
required, and value separately. Remove the order-dependent combined regexes
while preserving the existing Stripe and Square value checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4d18e108-7357-454f-9737-bacf2a083a85

📥 Commits

Reviewing files that changed from the base of the PR and between 7daf37c and 55d10e2.

📒 Files selected for processing (19)
  • scripts/mutation/equivalent-mutants/features.txt
  • scripts/mutation/equivalent-mutants/shared-m-z.txt
  • specs/payments/payment-provider-choice.feature
  • test/features/admin/settings-domains/custom-page.test.ts
  • test/features/admin/settings-domains/custom-save.test.ts
  • test/features/admin/settings-domains/custom-validate.test.ts
  • test/features/admin/settings-domains/host-subdomain.test.ts
  • test/features/admin/settings-domains/support.ts
  • test/features/admin/settings-helpers/provider-credentials.test.ts
  • test/features/admin/settings-helpers/secret.test.ts
  • test/features/admin/settings-stripe.test.ts
  • test/integration/server/settings/domains.test.ts
  • test/scripts/mutation/isolation/copy-back.test.ts
  • test/specs/steps/payment-provider-choice.ts
  • test/test-utils/settings.ts
  • test/ui/templates/admin/settings/domain-payment-warning.test.tsx
  • test/ui/templates/admin/settings/payment-provider.test.tsx
  • test/ui/templates/admin/settings/payment.test.ts
  • test/ui/templates/components/actions.test.ts
💤 Files with no reviewable changes (2)
  • test/integration/server/settings/domains.test.ts
  • test/ui/templates/admin/settings/payment.test.ts

Comment thread specs/payments/payment-provider-choice.feature
Comment thread test/features/admin/settings-domains/custom-validate.test.ts
Comment thread test/features/admin/settings-domains/support.ts Outdated
Comment thread test/features/admin/settings-domains/support.ts Outdated
Comment thread test/specs/steps/payment-provider-choice.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff728d158d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/db/settings.ts Outdated
Comment thread test/features/admin/settings-stripe.test.ts Outdated
Comment thread scripts/mutation/equivalent-mutants/features.txt Outdated
Comment thread src/shared/db/settings.ts Outdated
Comment thread src/features/admin/settings-general.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/admin/settings-helpers.ts (1)

332-332: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the activateFromMissing semantics.

hasSecret now drives two behaviors: the "required" guard and the activateFromMissing flag passed to saveSecret. The comment on hasSecret (Line 332) and saveSecret (Lines 351-357) does not explain that activateFromMissing signals "no credentials existed before this save" and is used to decide whether to auto-activate the provider. This is not obvious from the parameter name alone, and misuse affects whether a payment provider goes live unexpectedly.

📝 Proposed comment clarification
-  /** Whether a secret is already stored (drives the "required" guard). */
+  /** Whether a secret is already stored. Drives the "required" guard and
+   * `activateFromMissing` (true when no secret existed before this save;
+   * callers use it to auto-activate the provider only on first setup). */
   hasSecret: () => boolean;

Also applies to: 351-357

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/admin/settings-helpers.ts` at line 332, Document the `hasSecret`
contract and the `saveSecret` parameter so they explicitly state that a false
prior credential state produces `activateFromMissing`, meaning no credentials
existed before the save and the provider may be auto-activated. Clarify how this
value relates to the required guard and prevent ambiguity about provider
activation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/features/admin/settings-helpers.ts`:
- Line 332: Document the `hasSecret` contract and the `saveSecret` parameter so
they explicitly state that a false prior credential state produces
`activateFromMissing`, meaning no credentials existed before the save and the
provider may be auto-activated. Clarify how this value relates to the required
guard and prevent ambiguity about provider activation behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 89043aca-853d-4c23-a5d0-16beb1f4e623

📥 Commits

Reviewing files that changed from the base of the PR and between 55d10e2 and ff728d1.

📒 Files selected for processing (21)
  • scripts/screenshots/app-server.ts
  • src/features/admin/settings-general.ts
  • src/features/admin/settings-helpers.ts
  • src/features/admin/settings-stripe.ts
  • src/locales/en/settings.json
  • src/shared/db/settings.ts
  • src/ui/templates/admin/settings.tsx
  • src/ui/templates/admin/settings/payment-provider.tsx
  • src/ui/templates/admin/settings/payment.tsx
  • test/features/admin/settings-domains/custom-save.test.ts
  • test/features/admin/settings-domains/custom-validate.test.ts
  • test/features/admin/settings-domains/host-subdomain.test.ts
  • test/features/admin/settings-domains/support.ts
  • test/features/admin/settings-general/payment-provider.test.ts
  • test/features/admin/settings-helpers/provider-credentials.test.ts
  • test/shared/db/settings/public-api.test.ts
  • test/shared/db/settings/stripe-credentials.test.ts
  • test/shared/stripe/endpoints.test.ts
  • test/specs/steps/payment-provider-choice.ts
  • test/test-utils/settings.ts
  • test/ui/templates/admin/settings/payment-provider.test.tsx

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 862bdd0f15

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/db/settings.ts Outdated
Comment thread src/shared/db/settings.ts
Comment thread src/shared/db/settings.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/features/admin/settings-general/payment-provider.test.ts (1)

109-127: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Assert the recovery activity log.

The successful recovery test does not verify the new activity-log behavior. A mutation that removes or changes handlePaymentProviderRecoveryPost.log can pass this test.

Read getAllActivityLog() after the POST. Assert that it contains Existing payment provider set to Stripe.

As per coding guidelines, “Maintain 100% coverage and mutation kill rate for changed source” and tests must use strong observable assertions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/features/admin/settings-general/payment-provider.test.ts` around lines
109 - 127, Update the successful recovery test around the POST to read
getAllActivityLog() and assert it contains “Existing payment provider set to
Stripe.”, while preserving the existing response, settings, and redirect
assertions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/test-utils/csrf.ts`:
- Around line 27-29: Remove the local inputTagWithValue definitions from
payment.test.ts and csrf-and-forms.test.ts, import the shared inputTagWithValue
helper from test/test-utils/csrf.ts, and update their usages to use that import.
- Around line 27-29: Update inputTagWithValue to regex-escape the value before
constructing the pattern, and require an attribute boundary before the value
attribute so similarly named attributes cannot match. Add an exact regression
test covering a metacharacter value such as a.b, while preserving complete
coverage of the changed utility.

---

Outside diff comments:
In `@test/features/admin/settings-general/payment-provider.test.ts`:
- Around line 109-127: Update the successful recovery test around the POST to
read getAllActivityLog() and assert it contains “Existing payment provider set
to Stripe.”, while preserving the existing response, settings, and redirect
assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5ae117fd-b81a-4b64-b206-f0c60f412280

📥 Commits

Reviewing files that changed from the base of the PR and between ff728d1 and bdefe2d.

📒 Files selected for processing (12)
  • scripts/mutation/equivalent-mutants/features.txt
  • specs/payments/payment-provider-choice.feature
  • src/features/admin/settings-general.ts
  • src/shared/db/settings.ts
  • test/features/admin/settings-general/payment-provider.test.ts
  • test/features/admin/settings-stripe/provider-state.test.ts
  • test/shared/db/settings/public-api.test.ts
  • test/specs/steps/payment-provider-choice.ts
  • test/test-utils/csrf-and-forms.test.ts
  • test/test-utils/csrf.ts
  • test/ui/templates/admin/settings/payment-provider.test.tsx
  • test/ui/templates/admin/settings/payment.test.ts

Comment thread test/test-utils/csrf.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bdefe2d718

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/features/admin/settings-helpers.ts Outdated
Comment thread src/features/admin/settings-domains.ts Outdated
…safety-behavior

# Conflicts:
#	flake.nix
#	test/shared/stripe/endpoints/cleanup.test.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff70865d8d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

import {
getActivePaymentProvider,
type ExistingPaymentProvider,
getPaymentProviderForExistingPayments,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Split the expanded webhook module below 400 lines

This refactor grows webhooks.ts from 458 to 462 lines, moving an already oversized module farther beyond the repository's approximately 400-line target. Extract the payment callback or webhook authentication/processing paths into focused modules so this central route file does not continue accumulating separate payment flows.

AGENTS.md reference: AGENTS.md:L82-L82

Useful? React with 👍 / 👎.

Comment thread src/shared/db/client.ts
/** Same as {@link executeBatchWithoutCacheInvalidation} but returns each
* statement's {@link ResultSet}, so an INSERT ... RETURNING can read the
* written value back from the write round-trip itself. */
export const executeBatchReturningResults = async (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Split the expanded database client below 400 lines

Adding this batch-returning API grows client.ts from 929 to 936 lines, more than twice the repository's approximately 400-line target. Move the batch execution helpers into a focused database-client module rather than extending this already overloaded client assembly.

AGENTS.md reference: AGENTS.md:L82-L82

Useful? React with 👍 / 👎.


export const StripeForm = (s: SettingsPageState): JSX.Element | null =>
s.paymentProvider === "stripe" ? (
showsStripe(s) ? (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reconfigure Stripe when re-saving the remembered key

When sales are off with Stripe remembered, this newly exposes the Stripe form and the domain warning tells the operator to re-save the key after changing the domain. The rendered secret field contains the mask sentinel, however, so defineProviderCredentialsRoute returns the unchanged response at settings-helpers.ts:395-398 before saveSecret calls setupWebhookEndpoint; following the warning therefore leaves Stripe sending callbacks to the old domain. Re-run webhook setup with the stored key for this re-save action, or require the operator to enter the key again.

Useful? React with 👍 / 👎.

@stefan-burke stefan-burke changed the title Keep existing payments refundable when new sales are off Keep existing payments working when new sales are off Aug 4, 2026
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