From b2cf7c11c2d651ca3122b13940d11fe1b37e1845 Mon Sep 17 00:00:00 2001 From: Bitcoin Error Log <18273620+BitcoinErrorLog@users.noreply.github.com> Date: Tue, 22 Sep 2026 08:04:14 +0100 Subject: [PATCH 1/7] Remove Shop production warning banners and auth capability dumps Drop unsolicited maturity and real-money amber callouts from checkout, orders, and seller payment settings. Staging keeps the test-rails notice. Awaiting payment keeps a single muted hold sentence. Sign-in and grant QR dialogs no longer dump capability paths. --- .../next/remove-maturity-warnings.changed.md | 1 + .../MarketplaceGetPaidSettings.tsx | 2 +- .../MarketplaceMessagingEnableDialog.tsx | 11 +-------- .../MarketplacePaymentStatusCard.test.tsx | 20 ++++++++++------ .../MarketplacePaymentStatusCard.tsx | 6 ++--- .../MarketplaceReauthDialog.test.tsx | 10 ++++---- .../Marketplace/MarketplaceReauthDialog.tsx | 24 ++----------------- .../MarketplaceSessionConnectDialog.test.tsx | 3 +++ .../MarketplaceSessionConnectDialog.tsx | 24 +------------------ .../organisms/SignIn/SignIn.test.tsx | 5 ++-- src/components/organisms/SignIn/SignIn.tsx | 9 ------- .../Marketplace/MarketplaceCart.test.tsx | 16 +++++++------ .../templates/Marketplace/MarketplaceCart.tsx | 15 +++++------- .../Marketplace/MarketplaceListing.test.tsx | 3 ++- .../MarketplacePaymentSettings.test.tsx | 10 ++++---- .../MarketplacePaymentSettings.tsx | 7 +----- src/libs/commerce/checkout-hold.test.ts | 3 ++- src/libs/commerce/checkout-hold.ts | 4 ++-- .../marketplace/MarketplaceCart.vrt.test.tsx | 9 ++++--- .../MarketplacePaymentStatus.vrt.test.tsx | 9 +++---- 20 files changed, 70 insertions(+), 121 deletions(-) create mode 100644 changelog.d/next/remove-maturity-warnings.changed.md diff --git a/changelog.d/next/remove-maturity-warnings.changed.md b/changelog.d/next/remove-maturity-warnings.changed.md new file mode 100644 index 0000000000..e8618a1743 --- /dev/null +++ b/changelog.d/next/remove-maturity-warnings.changed.md @@ -0,0 +1 @@ +Removed unsolicited production maturity and real-money warning banners from Shop checkout, orders, payment settings, and auth QR dialogs. Staging still shows the test-rails notice; checkout keeps a muted seller-direct helper; awaiting payment keeps the hold sentence. diff --git a/src/components/organisms/Marketplace/MarketplaceGetPaidSettings.tsx b/src/components/organisms/Marketplace/MarketplaceGetPaidSettings.tsx index 3098343015..d2440364fb 100644 --- a/src/components/organisms/Marketplace/MarketplaceGetPaidSettings.tsx +++ b/src/components/organisms/Marketplace/MarketplaceGetPaidSettings.tsx @@ -518,7 +518,7 @@ export function MarketplaceGetPaidSettings({ locksConnect }: MarketplaceGetPaidS - Pubky Ring displays the exact creator capability grant. No identity secret enters Pubky App. + No identity secret enters this app. Bitkit sends a watch-only BIP84 account claim directly to Paykit Server. Spending keys remain in the diff --git a/src/components/organisms/Marketplace/MarketplaceMessagingEnableDialog.tsx b/src/components/organisms/Marketplace/MarketplaceMessagingEnableDialog.tsx index 45bc17c913..9c8d961a09 100644 --- a/src/components/organisms/Marketplace/MarketplaceMessagingEnableDialog.tsx +++ b/src/components/organisms/Marketplace/MarketplaceMessagingEnableDialog.tsx @@ -6,7 +6,6 @@ import { Button } from '@/atoms/Button/Button'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/atoms/Dialog/Dialog'; import { Typography } from '@/atoms/Typography/Typography'; import { useMarketplaceMessagingEnable } from '@/hooks/useMarketplaceMessagingEnable/useMarketplaceMessagingEnable'; -import { PAYKIT_MESSAGING_CAPABILITY } from '@/libs/commerce/messaging-contracts'; import { Logger } from '@/libs/logger/logger'; import { QrCodeSlot } from '@/molecules/QrCodeSlot/QrCodeSlot'; import { toast } from '@/molecules/Toaster/use-toast'; @@ -65,15 +64,7 @@ export function MarketplaceMessagingEnablePanel({ return (
- Messaging normally needs no extra approval: a sign-in made with the current grant already covers messaging and - connects automatically — if that were your case, you would never see this step. You are seeing it because this - sign-in predates the combined grant (its session has no messaging scope) or the homeserver no longer accepts its - session. Approving once with your signer (Pubky Ring) grants this app a homeserver session scoped to{' '} - {PAYKIT_MESSAGING_CAPABILITY} — the Paykit - tree where encrypted-message data lives, plus the app's own storage scope (the homeserver keeps one session - per browser, so this approval also carries your normal posting and publishing access). Your identity key never - enters this browser; message encryption uses a separate key generated and kept on this device. After this - one-time approval, messaging resumes automatically on this device until the session expires or you sign out. + {reconnect ? 'Reconnect encrypted messaging for this device.' : 'Approve encrypted messaging for this device.'} {enable.status === 'error' ? ( diff --git a/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.test.tsx b/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.test.tsx index c1daba11eb..e065e86560 100644 --- a/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.test.tsx +++ b/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.test.tsx @@ -133,7 +133,7 @@ describe('MarketplacePaymentStatusCard', () => { }); it.each(['transaction-service', 'locks-paykit', 'unavailable'] as const)( - 'shows the non-dismissible real-money notice in %s mode', + 'does not show a production money warning in %s mode', (adapterMode) => { render( { />, ); - const notice = screen.getByRole('note'); - expect(notice).toHaveTextContent('Real money. Payments are final and go directly to the seller.'); - expect(notice.querySelector('button')).not.toBeInTheDocument(); + expect(screen.queryByRole('note')).not.toBeInTheDocument(); + expect(screen.queryByText('Real money. Payments are final and go directly to the seller.')).not.toBeInTheDocument(); }, ); - it('shows the staging notice instead of the real-money notice on a staging deploy', () => { + it('shows the staging notice on a staging deploy', () => { runtime.deployEnv = 'staging'; render( { expect(screen.queryByText(/Real money/)).not.toBeInTheDocument(); }); - it('fails closed to the real-money notice for an unknown deploy environment', () => { + it('does not show a production money warning when the deploy environment is unknown', () => { runtime.deployEnv = undefined; render( { />, ); - expect(screen.getByRole('note')).toHaveTextContent('Real money. Payments are final and go directly to the seller.'); + expect(screen.queryByRole('note')).not.toBeInTheDocument(); + expect(screen.queryByText(/Real money/)).not.toBeInTheDocument(); }); it('shows the sandbox badge without any payment notice, even on a staging deploy', () => { @@ -281,6 +281,8 @@ describe('MarketplacePaymentStatusCard', () => { expect( screen.getByText('Bitcoin is temporarily unavailable. Other payment methods are unaffected.'), ).toBeInTheDocument(); + expect(screen.getByText('The item is held for you once a payment starts.')).toBeInTheDocument(); + expect(screen.queryByText(/never holds funds/i)).not.toBeInTheDocument(); expect(screen.getByRole('button', { name: /Card \(Stripe\)/ })).toBeInTheDocument(); }); @@ -347,6 +349,10 @@ describe('MarketplacePaymentStatusCard', () => { ); expect(screen.getByText(holderUnboundCopy(holdExpiresAt))).toBeInTheDocument(); + expect(screen.queryByText('Real money. Payments are final and go directly to the seller.')).not.toBeInTheDocument(); + expect(screen.queryByText(/Choose how to pay/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/pays the seller directly/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/never holds funds/i)).not.toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: 'Back' })); await waitFor(() => expect(CommerceController.executeMarketplaceCommand).toHaveBeenCalledWith( diff --git a/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.tsx b/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.tsx index 09b688b483..d30fe7c2f2 100644 --- a/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.tsx +++ b/src/components/organisms/Marketplace/MarketplacePaymentStatusCard.tsx @@ -210,15 +210,13 @@ export function MarketplacePaymentStatusCard({ {order.fiatVerification === 'seller-attested' && Seller-attested} {isSandbox && Sandbox · simulated payment · no real funds}
- {!isSandbox && isBuyer && isAwaiting && ( + {!isSandbox && isBuyer && isAwaiting && isStaging && ( - {isStaging - ? 'Staging environment — test rails, no real funds move' - : 'Real money. Payments are final and go directly to the seller.'} + Staging environment — test rails, no real funds move )} {visibleStatus === 'confirmed' && order.fiatVerification === 'gateway-notified' && ( diff --git a/src/components/organisms/Marketplace/MarketplaceReauthDialog.test.tsx b/src/components/organisms/Marketplace/MarketplaceReauthDialog.test.tsx index c667001542..6d9b5fedbf 100644 --- a/src/components/organisms/Marketplace/MarketplaceReauthDialog.test.tsx +++ b/src/components/organisms/Marketplace/MarketplaceReauthDialog.test.tsx @@ -21,13 +21,15 @@ vi.mock('@/hooks/useStepUpReauth/useStepUpReauth', () => ({ })); describe('MarketplaceReauthDialog', () => { - it('renders the exact requested capability string beside the QR so the user can compare it with the signer', async () => { + it('asks for a sign-in in product language and does not print capability paths', async () => { render(); await userEvent.setup().click(screen.getByRole('button', { name: 'Sign in again' })); - // Verbatim from the single CAPABILITIES constant — never a paraphrase. - expect(screen.getByText(CAPABILITIES)).toBeInTheDocument(); - expect(screen.getByText(/Pubky Ring will show this exact permission list/)).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: 'Sign in again' })).toBeInTheDocument(); + expect(screen.getByText('Sign in again for this device.')).toBeInTheDocument(); + expect(screen.queryByText(CAPABILITIES)).not.toBeInTheDocument(); + expect(screen.queryByText(/compare it before approving/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/permission list/i)).not.toBeInTheDocument(); }); }); diff --git a/src/components/organisms/Marketplace/MarketplaceReauthDialog.tsx b/src/components/organisms/Marketplace/MarketplaceReauthDialog.tsx index 1bb20aabf3..7148605e8e 100644 --- a/src/components/organisms/Marketplace/MarketplaceReauthDialog.tsx +++ b/src/components/organisms/Marketplace/MarketplaceReauthDialog.tsx @@ -5,7 +5,6 @@ import { Copy, KeyRound, Loader2, RefreshCw, Smartphone } from 'lucide-react'; import { Button } from '@/atoms/Button/Button'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/atoms/Dialog/Dialog'; import { Typography } from '@/atoms/Typography/Typography'; -import { CAPABILITIES } from '@/config/app'; import { useStepUpReauth } from '@/hooks/useStepUpReauth/useStepUpReauth'; import { Logger } from '@/libs/logger/logger'; import { QrCodeSlot } from '@/molecules/QrCodeSlot/QrCodeSlot'; @@ -74,31 +73,12 @@ export function MarketplaceReauthDialog({ - Sign in again with full permissions + Sign in again - Approving with your signer (Pubky Ring) signs you in again with the app's full permission list — public - app data, encrypted messaging, and private storage. Your account and data stay exactly as they are; only the - session's permissions widen, so watchlist sync, portable receipts, and messaging all work. + Sign in again for this device. - - Ring will show the full permission list — that is correct. This approval replaces your current session for the - same identity; it does not create a new account. - - - {/* The exact requested capability string, verbatim from the single - `CAPABILITIES` constant the flow is generated with — Ring displays - the same list at approval time, so the user can compare the two - (docs/ecommerce/step-up-approval.md, QR/phish-swap row). */} -
- - {CAPABILITIES} - - - Pubky Ring will show this exact permission list — compare it before approving. - -
{reauth.status === 'error' ? (
diff --git a/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.test.tsx b/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.test.tsx index b3186c6b32..2261e0f89f 100644 --- a/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.test.tsx +++ b/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.test.tsx @@ -73,5 +73,8 @@ describe('MarketplaceSessionConnectDialog', () => { expect(screen.getByLabelText('Copy authorization link')).toBeInTheDocument(); expect(screen.getByRole('button', { name: /open in pubky ring/i })).toBeInTheDocument(); expect(screen.getByRole('button', { name: /copy link/i })).toBeInTheDocument(); + expect(screen.getByText('Sign in to Pubky Shop.')).toBeInTheDocument(); + expect(screen.queryByText(/permission list/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/compare it before approving/i)).not.toBeInTheDocument(); }); }); diff --git a/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.tsx b/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.tsx index 27133a4aa2..fa68ab069b 100644 --- a/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.tsx +++ b/src/components/organisms/Marketplace/MarketplaceSessionConnectDialog.tsx @@ -5,7 +5,6 @@ import { Copy, KeyRound, Loader2, RefreshCw, Smartphone } from 'lucide-react'; import { Button } from '@/atoms/Button/Button'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/atoms/Dialog/Dialog'; import { Typography } from '@/atoms/Typography/Typography'; -import { CAPABILITIES } from '@/config/app'; import { useMarketplaceSessionConnect } from '@/hooks/useMarketplaceSessionConnect/useMarketplaceSessionConnect'; import { Logger } from '@/libs/logger/logger'; import { getMarketplaceGrantFlowEnabled } from '@/libs/runtime-config/runtime-config'; @@ -89,29 +88,8 @@ export function MarketplaceSessionConnectDialog({ - {grantFlowEnabled - ? 'Approve with Bitkit or Pubky Ring to reconnect the marketplace session for the identity already signed in to Shop. Nothing is charged until you pay.' - : requestsFullGrant - ? 'Approving with Pubky Ring signs you in to Shop with the full permission list and lets this marketplace place orders, bids, and offers as you. Nothing is charged until you pay.' - : 'Approving with Pubky Ring lets this marketplace place orders, bids, and offers as you. Nothing is charged until you pay. The approval stays on this device across tabs and restarts until it expires or you sign out.'} + {requestsFullGrant && !grantFlowEnabled ? 'Sign in to Pubky Shop.' : 'Approve purchases for this device.'} - - {grantFlowEnabled - ? 'Your signer will show an empty permission list. This approval proves identity to the marketplace service and does not change homeserver access.' - : requestsFullGrant - ? 'Ring will show the full permission list — that is correct. This is the first Shop-scoped approval; it was not covered by signing in on pubky.app.' - : 'Ring will show an empty permission list — that is correct. This approval only proves your identity to the marketplace service; it grants no read or write access to anything on your homeserver.'} - - {requestsFullGrant && !grantFlowEnabled && ( -
- - {CAPABILITIES} - - - Pubky Ring will show this exact permission list — compare it before approving. - -
- )} {['error', 'mismatch', 'expired', 'cancelled'].includes(session.status) ? (
diff --git a/src/components/organisms/SignIn/SignIn.test.tsx b/src/components/organisms/SignIn/SignIn.test.tsx index 6a799d7ae6..3c612e20a3 100644 --- a/src/components/organisms/SignIn/SignIn.test.tsx +++ b/src/components/organisms/SignIn/SignIn.test.tsx @@ -384,12 +384,13 @@ describe('SignInContent', () => { expect(button).toBeDisabled(); }); - it('renders the exact CAPABILITIES string beside the QR', async () => { + it('does not print requested capability paths beside the QR', async () => { const { CAPABILITIES } = await import('@/config/app'); await act(async () => { render(); }); - expect(screen.getByText(CAPABILITIES)).toBeInTheDocument(); + expect(screen.queryByText(CAPABILITIES)).not.toBeInTheDocument(); + expect(screen.queryByText(/compare it before approving/i)).not.toBeInTheDocument(); }); it('renders content cards with column layout', async () => { diff --git a/src/components/organisms/SignIn/SignIn.tsx b/src/components/organisms/SignIn/SignIn.tsx index a1390313e3..7da61d08a8 100644 --- a/src/components/organisms/SignIn/SignIn.tsx +++ b/src/components/organisms/SignIn/SignIn.tsx @@ -10,7 +10,6 @@ import { Link } from '@/atoms/Link/Link'; import { PageHeader } from '@/atoms/PageHeader/PageHeader'; import { PageSubtitle } from '@/atoms/PageSubtitle/PageSubtitle'; import { Typography } from '@/atoms/Typography/Typography'; -import { CAPABILITIES } from '@/config/app'; import { useMobileAuth } from '@/hooks/useMobileAuth/useMobileAuth'; import { Logger } from '@/libs/logger/logger'; import { cn } from '@/libs/utils/utils'; @@ -178,14 +177,6 @@ export const SignInContent = () => { activeQrHasHoverEffect /> -
- - {CAPABILITIES} - - - Pubky Ring will show this exact permission list — compare it before approving. - -
diff --git a/src/components/templates/Marketplace/MarketplaceCart.test.tsx b/src/components/templates/Marketplace/MarketplaceCart.test.tsx index c13ffc9a9b..2e2a9654e9 100644 --- a/src/components/templates/Marketplace/MarketplaceCart.test.tsx +++ b/src/components/templates/Marketplace/MarketplaceCart.test.tsx @@ -253,30 +253,31 @@ describe('MarketplaceCart', () => { }); it.each(['transaction-service', 'locks-paykit', 'unavailable'] as const)( - 'shows the fail-closed real-money notice in %s mode and the interim address copy', + 'shows muted seller-direct helper in %s production checkout, not an amber money warning', (adapterMode) => { seededCart(); view.adapterMode = adapterMode; view.hasMarketplaceSession = true; + view.deployEnv = 'production'; render(); - expect(screen.getAllByRole('note')).toHaveLength(1); - expect(screen.getByRole('note')).toHaveTextContent( - 'Real money. Payments are final and go directly to the seller.', - ); + expect(screen.queryByRole('note')).not.toBeInTheDocument(); + expect(screen.queryByText('Real money. Payments are final and go directly to the seller.')).not.toBeInTheDocument(); + expect(screen.getByText('Paid directly to the seller.')).toBeInTheDocument(); expect(screen.getByText(MARKETPLACE_DELIVERY_ADDRESS_DISCLOSURE)).toBeInTheDocument(); }, ); - it('fails closed to the real-money notice for an unknown deploy environment', () => { + it('does not show a production money warning when the deploy environment is unknown', () => { seededCart(); view.adapterMode = 'sandbox'; view.deployEnv = undefined; render(); - expect(screen.getByRole('note')).toHaveTextContent('Real money. Payments are final and go directly to the seller.'); + expect(screen.queryByRole('note')).not.toBeInTheDocument(); + expect(screen.queryByText(/Real money/)).not.toBeInTheDocument(); expect(screen.queryByText(/Staging environment/)).not.toBeInTheDocument(); }); @@ -289,6 +290,7 @@ describe('MarketplaceCart', () => { expect(screen.getByRole('note')).toHaveTextContent('Staging environment — test rails, no real funds move'); expect(screen.queryByText('Real money. Payments are final and go directly to the seller.')).not.toBeInTheDocument(); + expect(screen.queryByText('Paid directly to the seller.')).not.toBeInTheDocument(); }); it.each([false, true])('renders truthful address copy exactly once with saved addresses=%s', (hasSavedAddress) => { diff --git a/src/components/templates/Marketplace/MarketplaceCart.tsx b/src/components/templates/Marketplace/MarketplaceCart.tsx index 086c7c8254..9fa88a920e 100644 --- a/src/components/templates/Marketplace/MarketplaceCart.tsx +++ b/src/components/templates/Marketplace/MarketplaceCart.tsx @@ -506,7 +506,7 @@ export function MarketplaceCart() { This places {checkout.orderCount} orders — one per seller and delivery method. )} - {isStaging ? ( + {isStaging && ( Staging environment — test rails, no real funds move - ) : ( - - Real money. Payments are final and go directly to the seller. - )} + {!isStaging && !isSandbox && ( + + Paid directly to the seller. + + )} {!canPlaceOrder && ( {approvalNeeded diff --git a/src/components/templates/Marketplace/MarketplaceListing.test.tsx b/src/components/templates/Marketplace/MarketplaceListing.test.tsx index bb8b80d960..e329b7bf72 100644 --- a/src/components/templates/Marketplace/MarketplaceListing.test.tsx +++ b/src/components/templates/Marketplace/MarketplaceListing.test.tsx @@ -396,7 +396,8 @@ describe('MarketplaceListing', () => { expect(screen.getByRole('button', { name: 'Approve in Pubky Ring' })).toBeInTheDocument(); await user.click(screen.getByRole('button', { name: 'Approve in Pubky Ring' })); - expect(screen.getByText(/Ring will show an empty permission list/i)).toBeInTheDocument(); + expect(screen.getByText('Approve purchases for this device.')).toBeInTheDocument(); + expect(screen.queryByText(/permission list/i)).not.toBeInTheDocument(); expect(screen.queryByText(CAPABILITIES)).not.toBeInTheDocument(); }); }); diff --git a/src/components/templates/Marketplace/MarketplacePaymentSettings.test.tsx b/src/components/templates/Marketplace/MarketplacePaymentSettings.test.tsx index cf848ae559..6c6ec6178a 100644 --- a/src/components/templates/Marketplace/MarketplacePaymentSettings.test.tsx +++ b/src/components/templates/Marketplace/MarketplacePaymentSettings.test.tsx @@ -109,13 +109,15 @@ function setPaykitIframeSource(iframe: HTMLIFrameElement): WindowProxy { } describe('MarketplacePaymentSettings', () => { - it('leads with the seller-direct promise', async () => { + it('leads with how-you-get-paid setup copy, not a funds warning', async () => { await renderSettings(); expect(screen.getByRole('heading', { name: 'How you get paid' })).toBeInTheDocument(); - expect( - screen.getByText('Every method pays the seller directly — this marketplace never holds funds.'), - ).toBeInTheDocument(); + expect(screen.getByText('Set up the methods buyers can use at checkout.')).toBeInTheDocument(); + expect(screen.queryByText(/pays the seller directly/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/never holds funds/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/pre-production/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/this prototype/i)).not.toBeInTheDocument(); }); it('renders the three method cards in buyer-familiar order', async () => { diff --git a/src/components/templates/Marketplace/MarketplacePaymentSettings.tsx b/src/components/templates/Marketplace/MarketplacePaymentSettings.tsx index a82a62236a..98acb55acb 100644 --- a/src/components/templates/Marketplace/MarketplacePaymentSettings.tsx +++ b/src/components/templates/Marketplace/MarketplacePaymentSettings.tsx @@ -50,7 +50,7 @@ export function MarketplacePaymentSettings() { How you get paid - Every method pays the seller directly — this marketplace never holds funds. + Set up the methods buyers can use at checkout.
@@ -141,11 +141,6 @@ export function MarketplacePaymentSettings() {
- -
- Locks and Paykit Server are pre-production. Do not use this prototype to protect valuable content or real - funds without an independent security and operational review. -
); diff --git a/src/libs/commerce/checkout-hold.test.ts b/src/libs/commerce/checkout-hold.test.ts index 67e0777acf..4189f97fe1 100644 --- a/src/libs/commerce/checkout-hold.test.ts +++ b/src/libs/commerce/checkout-hold.test.ts @@ -20,11 +20,12 @@ describe('checkout-hold copy', () => { it('renders unbound and bound holder copy with the deadline', () => { expect(holderUnboundCopy('2026-08-20T21:15:00.000Z')).toBe( - 'This item is held for you until Aug 20, 2026, 9:15 PM UTC. Choose how to pay. Every method pays the seller directly.', + 'The item is held for you until Aug 20, 2026, 9:15 PM UTC.', ); expect(holderBoundCopy('2026-08-20T21:15:00.000Z')).toBe( 'Pay by Aug 20, 2026, 9:15 PM UTC. If the window ends, the item restocks.', ); + expect(holderUnboundCopy(null)).toBe('The item is held for you once a payment starts.'); }); it('detects late completion from paid plus leftover elapsed reason', () => { diff --git a/src/libs/commerce/checkout-hold.ts b/src/libs/commerce/checkout-hold.ts index 5a6614b19b..83853204a1 100644 --- a/src/libs/commerce/checkout-hold.ts +++ b/src/libs/commerce/checkout-hold.ts @@ -36,8 +36,8 @@ export function formatHoldDeadline(holdExpiresAt: string | null | undefined): st export function holderUnboundCopy(holdExpiresAt: string | null | undefined): string { const deadline = formatHoldDeadline(holdExpiresAt); return deadline - ? `This item is held for you until ${deadline}. Choose how to pay. Every method pays the seller directly.` - : 'This item is held for you. Choose how to pay. Every method pays the seller directly.'; + ? `The item is held for you until ${deadline}.` + : 'The item is held for you once a payment starts.'; } export function holderBoundCopy(holdExpiresAt: string | null | undefined): string { diff --git a/src/test/vrt/marketplace/MarketplaceCart.vrt.test.tsx b/src/test/vrt/marketplace/MarketplaceCart.vrt.test.tsx index dde34c8ca2..257e81c9f4 100644 --- a/src/test/vrt/marketplace/MarketplaceCart.vrt.test.tsx +++ b/src/test/vrt/marketplace/MarketplaceCart.vrt.test.tsx @@ -166,10 +166,10 @@ vi.mock('@/config/commerce', async (importOriginal) => { return { ...actual, getCommerceAdapterMode: () => view.adapterMode }; }); -// The checkout money notice is gated on the deploy environment, not the +// The checkout staging amber is gated on the deploy environment, not the // adapter mode. Each scene names its environment explicitly: staging (test // rails, no real funds) is the default; the locks-paykit scene runs on -// production, where real payment rails are live. +// production, where the muted helper is "Paid directly to the seller." vi.mock('@/libs/runtime-config/runtime-config', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, getDeployEnv: () => view.deployEnv }; @@ -464,9 +464,8 @@ describe('Marketplace cart — visual regression', () => { }); // locks-paykit mode: real payment rails are live, so the guarantee copy must - // NOT claim "no real funds move" — it states where the funds actually go. - // The scene is framed as the production deploy, so the money notice is the - // real-money one. + // NOT claim "no real funds move". The scene is framed as production, so there + // is no staging amber; checkout shows the muted seller-direct helper only. it('renders the locks-paykit checkout labels at desktop viewport', async () => { const { singleSeller } = await fixtures; view.items = singleSeller; diff --git a/src/test/vrt/marketplace/MarketplacePaymentStatus.vrt.test.tsx b/src/test/vrt/marketplace/MarketplacePaymentStatus.vrt.test.tsx index 9a31678039..64b248fc14 100644 --- a/src/test/vrt/marketplace/MarketplacePaymentStatus.vrt.test.tsx +++ b/src/test/vrt/marketplace/MarketplacePaymentStatus.vrt.test.tsx @@ -58,10 +58,11 @@ vi.mock('@/hooks/useMarketplaceLocksPayment/useMarketplaceLocksPayment', () => ( }), })); -// The money notice is gated on the deploy environment. Each scene names its -// environment: locks-paykit scenes run on production (real rails — the -// real-money notice is truthful there); transaction-service scenes run on -// staging (test rails — no real funds move). Sandbox scenes render no notice. +// Staging amber is gated on the deploy environment. Each scene names its +// environment: locks-paykit scenes run on production (no amber money +// notice; awaiting payment shows muted hold copy); transaction-service +// scenes run on staging (test rails — no real funds move). Sandbox scenes +// render no notice. vi.mock('@/libs/runtime-config/runtime-config', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, getDeployEnv: () => view.deployEnv }; From 9c3c97d7117efee172f4f26b8c9a4407be2c25c9 Mon Sep 17 00:00:00 2001 From: Bitcoin Error Log <18273620+BitcoinErrorLog@users.noreply.github.com> Date: Tue, 22 Sep 2026 08:09:09 +0100 Subject: [PATCH 2/7] Update SignIn snapshot and listing grant copy tests The QR no longer dumps capability paths. Auction bid step-up now asserts the plain Shop sentence instead of the old permission-list copy. --- .../organisms/SignIn/SignIn.test.tsx.snap | 16 ---------------- .../Marketplace/MarketplaceListing.test.tsx | 8 ++++---- .../MarketplaceSessionConnect.vrt.test.tsx | 5 +++-- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/components/organisms/SignIn/SignIn.test.tsx.snap b/src/components/organisms/SignIn/SignIn.test.tsx.snap index 096b1e267b..2b96408bc7 100644 --- a/src/components/organisms/SignIn/SignIn.test.tsx.snap +++ b/src/components/organisms/SignIn/SignIn.test.tsx.snap @@ -73,22 +73,6 @@ exports[`SignInContent - Snapshots > matches snapshot for the QR sign-in layout width="48" /> -
- - /pub/pubky.app/:rw,/pub/paykit/:rw,/priv/pubky.app/:rw - -

- Pubky Ring will show this exact permission list — compare it before approving. -

-