From a51c9a975d0e6e64a2c9558f9669dd8fe6dcc790 Mon Sep 17 00:00:00 2001 From: Georgios Jason Efstathiou Date: Fri, 19 Jun 2026 15:42:03 +0200 Subject: [PATCH] feat(wave): add CAPTCHA to repo application form Renders the Cloudflare Turnstile widget on the last step of the repo application form and sends the token via the x-turnstile-token header, mirroring the issue application page. Required for the backend captcha check added in drips-network/wave#662. --- src/lib/utils/wave/wavePrograms.ts | 2 + .../[waveProgramId]/form/+page.svelte | 46 +++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/lib/utils/wave/wavePrograms.ts b/src/lib/utils/wave/wavePrograms.ts index 4b6f16719..56e3acf89 100644 --- a/src/lib/utils/wave/wavePrograms.ts +++ b/src/lib/utils/wave/wavePrograms.ts @@ -68,6 +68,7 @@ export async function batchApplyRepos( waveProgramId: string, orgRepoIds: string[], formData: BatchApplyFormData, + turnstileToken?: string, ) { return parseRes( batchApplyResponseSchema, @@ -77,6 +78,7 @@ export async function batchApplyRepos( orgRepoIds, formData, }), + headers: turnstileToken ? { 'x-turnstile-token': turnstileToken } : {}, }), ); } diff --git a/src/routes/(pages)/wave/(flows)/maintainer-onboarding/apply-to-wave-program/[waveProgramId]/form/+page.svelte b/src/routes/(pages)/wave/(flows)/maintainer-onboarding/apply-to-wave-program/[waveProgramId]/form/+page.svelte index 5a0454df1..fc22f758c 100644 --- a/src/routes/(pages)/wave/(flows)/maintainer-onboarding/apply-to-wave-program/[waveProgramId]/form/+page.svelte +++ b/src/routes/(pages)/wave/(flows)/maintainer-onboarding/apply-to-wave-program/[waveProgramId]/form/+page.svelte @@ -14,6 +14,7 @@ import Plus from '$lib/components/icons/Plus.svelte'; import Trash from '$lib/components/icons/Trash.svelte'; import { batchApplyRepos } from '$lib/utils/wave/wavePrograms'; + import Turnstile from '$lib/components/turnstile/turnstile.svelte'; import doWithErrorModal from '$lib/utils/do-with-error-modal'; import FlowStepWrapper from '../../../../shared/flow-step-wrapper.svelte'; import type { PreviousParticipation } from '$lib/utils/wave/types/waveProgram'; @@ -152,12 +153,15 @@ return null; }); + let turnstileToken = $state(undefined); + let formValid = $derived( plannedIssuesValid && repoRelationshipValid && upstreamRelationshipValid && forkJustificationValid && - !limitViolation, + !limitViolation && + !!turnstileToken, ); let previousParticipationItems: Items = { @@ -206,13 +210,21 @@ try { await doWithErrorModal(async () => { - await batchApplyRepos(undefined, data.waveProgram.id, repoIds, { - previousParticipation: previousParticipation as PreviousParticipation[], - plannedIssuesDescription, - ...(multipleReposSelected ? { repoRelationshipDescription } : {}), - ...(anySelectedRepoIsFork ? { upstreamRelationshipDescription, forkJustification } : {}), - supportingLinks: supportingLinks.length > 0 ? supportingLinks : undefined, - }); + await batchApplyRepos( + undefined, + data.waveProgram.id, + repoIds, + { + previousParticipation: previousParticipation as PreviousParticipation[], + plannedIssuesDescription, + ...(multipleReposSelected ? { repoRelationshipDescription } : {}), + ...(anySelectedRepoIsFork + ? { upstreamRelationshipDescription, forkJustification } + : {}), + supportingLinks: supportingLinks.length > 0 ? supportingLinks : undefined, + }, + turnstileToken, + ); }); submittedSuccessfully = true; @@ -458,6 +470,19 @@ There's no wrong answer. We need this context to review forks accurately.`} Inaccurate information may result in your application being rejected and could lead to disqualification from the Drips Wave Program. + + + {#if data.isKycVerified} +
+ (turnstileToken = t)} /> +
+ {/if} +
{/if} {#snippet leftActions()} @@ -536,4 +561,9 @@ There's no wrong answer. We need this context to review forks accurately.`} gap: 0.5rem; align-items: flex-start; } + + .turnstile-wrapper { + display: flex; + justify-content: flex-start; + }