From dfb62c691b1cf7c371d4db663eef651e31c38e0b Mon Sep 17 00:00:00 2001 From: Ronak Date: Thu, 17 Sep 2026 23:02:16 +0530 Subject: [PATCH 1/4] docs: fix repository setup commands --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b86695..a08d08d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,8 @@ you through it. ## Setup ```bash -git clone https://github.com//.git -cd /web +git clone https://github.com/ScalerOpenSourceLabsOrg/scaleropensourcelabs.com.git +cd scaleropensourcelabs.com/web npm install npm run dev # http://localhost:3000 # port 3000 is often taken; use `npm run dev -- -p 3001` From c55b30cc82feb5ca6afa8f7b3a3611d35537f08d Mon Sep 17 00:00:00 2001 From: Ronak Date: Tue, 22 Sep 2026 14:27:08 +0530 Subject: [PATCH 2/4] test: handle unconfigured join gate in smoke test --- web/scripts/smoke.mjs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/web/scripts/smoke.mjs b/web/scripts/smoke.mjs index 7c3b4df..93e9cb4 100644 --- a/web/scripts/smoke.mjs +++ b/web/scripts/smoke.mjs @@ -205,11 +205,28 @@ await pg.waitForTimeout(700); // deleted. The page held an anonymous application form for a spell; membership is an // @sst.scaler.com address, which is the one thing that form could not check, so the door // and the test are the same act now. +const joinState = await pg.evaluate(() => { + const text = document.querySelector("main")?.innerText ?? ""; + return { + configured: /continue with google|sign in with your college account/i.test(text), + unconfigured: /sign-in is not set up here/i.test(text), + hasFormFields: + document.querySelectorAll("main input, main select, main textarea").length > 0, + statesDomain: /sst\\.scaler\\.com/i.test(text), + }; +}); + +// CI intentionally runs without Firebase configuration. In that environment /join must +// show the honest "not configured" state instead of a fake sign-in control. In a configured +// deployment it must show the real college-account sign-in gate. Both states must remain +// form-free. ok( - "join offers sign-in, not a form", - (await pg.evaluate(() => - /continue with google/i.test(document.querySelector("main")?.innerText ?? ""), - )), + "join shows a valid gate state", + joinState.configured || joinState.unconfigured, +); +ok( + "and no application fields survive on the page", + !joinState.hasFormFields, ); // THE ASSERTION THAT WOULD CATCH A REGRESSION HERE. A form reappearing on this page is // the specific thing this change removed, so its absence is checked rather than assumed — From c73cbdb6354ba9d872f076182cafe496fb3e5b7e Mon Sep 17 00:00:00 2001 From: Ronak Date: Tue, 22 Sep 2026 14:27:43 +0530 Subject: [PATCH 3/4] fix: explain join domain when auth is unconfigured --- web/components/JoinGate.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/components/JoinGate.tsx b/web/components/JoinGate.tsx index c8ef92e..1a52410 100644 --- a/web/components/JoinGate.tsx +++ b/web/components/JoinGate.tsx @@ -241,8 +241,10 @@ function Gate() {

Sign-in is not set up here.

This deployment has no Firebase configuration, so registration is switched off. - If you are running the site locally, see web/.env.example. If you - are seeing this on the live site, that is a bug — please tell us. + When sign-in is available, only students with an @{DOMAIN} + address can register. If you are running the site locally, see{" "} + web/.env.example. If you are seeing this on the live site, that is a + bug — please tell us.

Email the organisers From 69b5b3d309828f47763f4466fbc76db0dd937f22 Mon Sep 17 00:00:00 2001 From: Ronak Date: Tue, 22 Sep 2026 14:27:51 +0530 Subject: [PATCH 4/4] test: keep join smoke checks valid in CI --- web/scripts/smoke.mjs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/web/scripts/smoke.mjs b/web/scripts/smoke.mjs index 93e9cb4..0e671e5 100644 --- a/web/scripts/smoke.mjs +++ b/web/scripts/smoke.mjs @@ -212,7 +212,7 @@ const joinState = await pg.evaluate(() => { unconfigured: /sign-in is not set up here/i.test(text), hasFormFields: document.querySelectorAll("main input, main select, main textarea").length > 0, - statesDomain: /sst\\.scaler\\.com/i.test(text), + statesDomain: /sst\.scaler\.com/i.test(text), }; }); @@ -228,28 +228,15 @@ ok( "and no application fields survive on the page", !joinState.hasFormFields, ); -// THE ASSERTION THAT WOULD CATCH A REGRESSION HERE. A form reappearing on this page is -// the specific thing this change removed, so its absence is checked rather than assumed — -// zero inputs of any kind in the main column. -ok( - "and no application fields survive on the page", - (await pg.evaluate( - () => document.querySelectorAll("main input, main select, main textarea").length, - )) === 0, -); ok( "join keeps ?path in the URL", new URL(pg.url()).searchParams.get("path") === "program-track", ); -// THE DOMAIN RULE IS ON THE PAGE, not just in the rules. It is the whole membership test -// and the one sentence a reader cannot afford to skim past, so a copy pass that removed it -// would leave people signing in with a personal Gmail and being refused with no warning. -ok( - "and states the one address that can register", - (await pg.evaluate(() => - /sst\.scaler\.com/i.test(document.querySelector("main")?.innerText ?? ""), - )), -); +// The domain rule is important in both states: a configured gate explains the membership +// requirement, while the unconfigured state explains what will be required once auth is +// available. +ok("and states the one address that can register", joinState.statesDomain); + // The form must NOT be reachable without signing in. This is a UI assertion, not a // security one — the boundary is firestore.rules — but a form rendering to a signed-out // visitor would mean the gate had broken open.