From 3de0ccd3d7012fb48bf2cb7d5dafe9fc885f59ae Mon Sep 17 00:00:00 2001 From: Gabriel Garcia Date: Mon, 28 Sep 2026 15:23:56 +0200 Subject: [PATCH 1/4] fix(example): skip browser auth callback on proxied demos The Onboarding, Contract Amendment, Contract Document and Invoice Schedule demos send every request through the example app's own proxy, which mints the gateway token server-side and sets Authorization itself. They still used the default refresh-token auth callback, which calls /api/fetch-refresh-token - an endpoint that returns 403 in production so the deployed demo never hands an access token to the browser. The failed callback left no cached token, so the SDK retried it before every request, flooding the deployed app's network log with 403s. Use authType='none', as the GP onboarding demos already do, and drop the now-unreached token stub from the invoice-schedule e2e spec. Co-Authored-By: Claude Opus 5.5 --- example/e2e/invoice-schedule.spec.ts | 6 ------ example/src/ContractAmendment.tsx | 2 +- example/src/ContractDocument.tsx | 2 +- example/src/InvoiceSchedule.tsx | 2 +- example/src/flows/Onboarding/Onboarding.tsx | 1 + 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/example/e2e/invoice-schedule.spec.ts b/example/e2e/invoice-schedule.spec.ts index 751f5a4f2..ac8f67ef2 100644 --- a/example/e2e/invoice-schedule.spec.ts +++ b/example/e2e/invoice-schedule.spec.ts @@ -37,12 +37,6 @@ const currenciesResponse = { * reverse registration order, so the specific stubs below take precedence over it. */ async function stubInvoiceScheduleApi(page: Page) { - await page.route('**/api/fetch-refresh-token', (route) => - route.fulfill({ - json: { access_token: 'e2e-access-token', expires_in: 3600 }, - }), - ); - await page.route( /\/v1\/contractors\/employments\/[^/]+\/contractor-currencies/, (route) => route.fulfill({ json: currenciesResponse }), diff --git a/example/src/ContractAmendment.tsx b/example/src/ContractAmendment.tsx index d0bf0dd6a..412060cf3 100644 --- a/example/src/ContractAmendment.tsx +++ b/example/src/ContractAmendment.tsx @@ -113,7 +113,7 @@ function AmendmentFlow({ export function ContractAmendment() { const EMPLOYMENT_ID = import.meta.env.VITE_CONTRACT_AMENDMENT_EMPLOYMENT_ID; // set another employment ID here as it will probably fail for you return ( - +
+ ); diff --git a/example/src/InvoiceSchedule.tsx b/example/src/InvoiceSchedule.tsx index 9baea1a08..e76f86d41 100644 --- a/example/src/InvoiceSchedule.tsx +++ b/example/src/InvoiceSchedule.tsx @@ -85,7 +85,7 @@ export function InvoiceSchedule() { const [employmentId, setEmploymentId] = useState(null); return ( - +
{employmentId ? ( diff --git a/example/src/flows/Onboarding/Onboarding.tsx b/example/src/flows/Onboarding/Onboarding.tsx index 730361474..8c00f3a90 100644 --- a/example/src/flows/Onboarding/Onboarding.tsx +++ b/example/src/flows/Onboarding/Onboarding.tsx @@ -401,6 +401,7 @@ const OnboardingWithProps = ({ }: OnboardingFormData) => ( Date: Mon, 28 Sep 2026 15:27:01 +0200 Subject: [PATCH 2/4] refactor(example): default to no browser auth when proxy is passed Every proxy the example app uses is its own Express server, which mints the gateway token itself, so passing proxy already implies the browser never needs a token. Make that the RemoteFlows wrapper's default instead of adding authType='none' to each proxied demo. An explicit authType still wins, so Termination and JsonSchemaPlayground keep company-manager. Co-Authored-By: Claude Opus 5.5 --- example/src/ContractAmendment.tsx | 2 +- example/src/ContractDocument.tsx | 2 +- example/src/InvoiceSchedule.tsx | 2 +- example/src/RemoteFlows.tsx | 10 ++++++---- example/src/flows/Onboarding/Onboarding.tsx | 1 - 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/example/src/ContractAmendment.tsx b/example/src/ContractAmendment.tsx index 412060cf3..d0bf0dd6a 100644 --- a/example/src/ContractAmendment.tsx +++ b/example/src/ContractAmendment.tsx @@ -113,7 +113,7 @@ function AmendmentFlow({ export function ContractAmendment() { const EMPLOYMENT_ID = import.meta.env.VITE_CONTRACT_AMENDMENT_EMPLOYMENT_ID; // set another employment ID here as it will probably fail for you return ( - +
+ ); diff --git a/example/src/InvoiceSchedule.tsx b/example/src/InvoiceSchedule.tsx index e76f86d41..9baea1a08 100644 --- a/example/src/InvoiceSchedule.tsx +++ b/example/src/InvoiceSchedule.tsx @@ -85,7 +85,7 @@ export function InvoiceSchedule() { const [employmentId, setEmploymentId] = useState(null); return ( - +
{employmentId ? ( diff --git a/example/src/RemoteFlows.tsx b/example/src/RemoteFlows.tsx index 83820f7ff..10445a725 100644 --- a/example/src/RemoteFlows.tsx +++ b/example/src/RemoteFlows.tsx @@ -47,8 +47,9 @@ type RemoteFlowsProps = Omit & { auth?: RemoteFlowsSDKProps['auth']; isClientToken?: boolean; /** - * `'none'` skips the FE-side auth callback entirely — use it when the proxy - * mints tokens server-side and the FE never needs to hold one. + * `'none'` skips the FE-side auth callback entirely. It's the default when + * `proxy` is passed, since the example proxy mints tokens server-side and + * the FE never needs to hold one. */ authType?: 'refresh-token' | 'company-manager' | 'client' | 'none'; }; @@ -59,8 +60,9 @@ export const RemoteFlows = ({ authType, ...props }: RemoteFlowsProps) => { + const hasProxy = !!props.proxy; const auth = useMemo(() => { - if (authType === 'none') { + if (authType === 'none' || (!authType && !isClientToken && hasProxy)) { return undefined; } if (authType === 'company-manager') { @@ -71,7 +73,7 @@ export const RemoteFlows = ({ } return fetchCompanyToken; - }, [authType, isClientToken]); + }, [authType, isClientToken, hasProxy]); return ( ( Date: Mon, 28 Sep 2026 15:31:00 +0200 Subject: [PATCH 3/4] refactor(example): drop company-manager auth from proxied demos Termination and JsonSchemaPlayground pass proxy, and the example proxy overwrites the Authorization header with a token it mints server-side, so the company-manager token the browser fetched was never used. On the deployed app /api/fetch-company-manager returns 403, so it only added failing requests. Let them fall back to the proxy default like the other proxied demos. Co-Authored-By: Claude Opus 5.5 --- example/src/Termination.tsx | 2 +- .../src/flows/JsonSchemaPlayground/JsonSchemaPlayground.tsx | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/example/src/Termination.tsx b/example/src/Termination.tsx index d84791769..15951ab0d 100644 --- a/example/src/Termination.tsx +++ b/example/src/Termination.tsx @@ -192,7 +192,7 @@ export const TerminationWithProps = ({ }) => { const proxyURL = window.location.origin; return ( - + { }, []); return ( - + Date: Mon, 28 Sep 2026 15:37:24 +0200 Subject: [PATCH 4/4] refactor(example): drop company-manager auth from remaining proxied demos JsonSchemaComparison, ContractorOnboarding and CreateCompany also pass proxy with authType='company-manager'. Same as Termination and JsonSchemaPlayground: the proxy overwrites Authorization with its own token, so the browser-fetched one was never used and only produced 403s on the deployed app. Co-Authored-By: Claude Opus 5.5 --- example/src/ContractorOnboarding.tsx | 5 +---- example/src/CreateCompany.tsx | 5 +---- example/src/JsonSchemaComparisonDemo.tsx | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/example/src/ContractorOnboarding.tsx b/example/src/ContractorOnboarding.tsx index 2443a4083..f3248f826 100644 --- a/example/src/ContractorOnboarding.tsx +++ b/example/src/ContractorOnboarding.tsx @@ -745,10 +745,7 @@ export const ContractorOnboardingWithProps = ({ }: ContractorOnboardingFormData) => { return (
- +
{ return (
- +
diff --git a/example/src/JsonSchemaComparisonDemo.tsx b/example/src/JsonSchemaComparisonDemo.tsx index 79e472354..149394158 100644 --- a/example/src/JsonSchemaComparisonDemo.tsx +++ b/example/src/JsonSchemaComparisonDemo.tsx @@ -3,10 +3,7 @@ import { RemoteFlows } from './RemoteFlows'; export const JsonSchemaComparisonDemo = () => { return ( - + );