Skip to content

feat(sunset): one-click export sign-in, and drop Sign in from the site nav - #1802

Merged
CREDO23 merged 5 commits into
MODSetter:devfrom
CREDO23:sunset-export-signin
Sep 17, 2026
Merged

CREDO23 merged 5 commits into
MODSetter:devfrom
CREDO23:sunset-export-signin

Conversation

@CREDO23

@CREDO23 CREDO23 commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Two changes from testing SUNSET_MODE locally, and they depend on each other.

Signing in to export is one click

Clicking Sign in to export on /sunset went to /login, which on a Google-only deployment renders a page containing a logo, a heading and one button. Three clicks and two page loads for the single action the 30-day export window exists for.

/sunset now goes straight to /auth/google/authorize-redirect when the runtime auth type is GOOGLE, and still routes to /login for LOCAL, where the password form is real content. Both call sites use it — the first click and the 401 retry inside the export — so an expired session behaves the same way. trackLoginAttempt("google") came along with the redirect, so the analytics event is unchanged.

The return leg already worked and is untouched: Google's callback lands on /dashboard, and the sunset redirect bounces it to /sunset, where the button reads "Export account".

The new sunset/layout.tsx is required rather than incidental. RuntimeConfigProvider is opt-in per route — /login, /register, /desktop/login and /dashboard each declare it — and without it useIsGoogleAuth() hits the provider's guard and /sunset 500s. Same three lines as /login's layout. It makes the page dynamically rendered, which is fine: it is noindex and reads a per-request cookie regardless.

Sign in leaves the nav and footer

It was the bar's only filled button, so on /downloads the loudest control on the page asked visitors to log in — directly above the line "One installer, no account, no cloud". HomePillars says "there is no sign-up, no email, no workspace to be invited to", and the page description says "no account". The button contradicted all of it, and after T+30 the accounts are deleted and it points at nothing.

The one audience that still needs a login is hosted users exporting during the wind-down, and they reach /sunset from the launch email, the legacy desktop client, or the /dashboard redirect — then use that page's own button, which the first change just made a single click. The nav entry was a third path to somewhere they were already being sent.

SIGN_IN_URL and the now-unused HomeButton import go with it.

Checks

Biome and tsc --noEmit clean. Verified on a local stack with SUNSET_MODE=1: /sunset returns 200 and reaches Google without the intermediate page; /downloads returns 200 with no "Sign in" anywhere on it.

/login has nothing to choose between when AUTH_TYPE is GOOGLE -- it renders a page whose only content is a single Google button. Export is the one action the 30-day tail exists for, so /sunset now goes straight to the provider and leaves that page to LOCAL deployments, where the password form is real content.

The page needs its own layout because RuntimeConfigProvider is opt-in per route, the way /login, /register and /dashboard already do it.
@vercel

vercel Bot commented Sep 17, 2026

Copy link
Copy Markdown

@CREDO23 is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f457b90b-b81e-41ca-af17-9217f18a8f06

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

It was the bar's only filled button, so on /downloads the loudest control on the page asked visitors to log in, directly above the line "One installer, no account, no cloud". There is no account to sign in to.

The one audience that still needs it is hosted users exporting during the wind-down, and /sunset carries its own sign-in button for them. They reach that page from the launch email, the legacy desktop app, or the /dashboard redirect, so the nav entry was a third path to somewhere they were already being sent.
@CREDO23 CREDO23 changed the title feat(sunset): sign in for export in one click on Google deployments feat(sunset): one-click export sign-in, and drop Sign in from the site nav Sep 17, 2026
The page hands out a free app, so the form is an offer rather than a gate: the OS grid and the releases link stay exactly where they were, and the note says outright that the installers below need no address.

It reuses /license's TrialForm rather than growing a second one. The only thing that differs between the two pages is the line under the field, so that becomes a prop and /license keeps its own wording as the default. The note is also width-capped and given more room above it, since at full container width it ran as one long line.

The hero's OS auto-detect button goes: with the form above it and the platform grid below, it was the third way to start the same download.

Individual's trial button on /pricing now names the length, matching the FAQ and meta description on that page.
The site has to link the release by tag: /releases/latest is pinned to the legacy 0.0.x app for good, so it will never point at 2.x.

The tag lives under surfsense_web/ rather than being read from surfsense_local/VERSION because the web image builds with context: ./surfsense_web, so nothing outside that directory exists at build time. bump-version.sh writes it alongside the three manifests it already updates, which also rebuilds the web image: that path is a trigger in docker-build.yml.
/releases/latest is pinned to the legacy v0.0.40 for good, so that the old desktop updater never sees 2.x. The website resolved the same pointer, which meant /downloads handed every visitor the discontinued hosted client -- and publishing 2.0.0 with the latest box unchecked means it would never have corrected itself.

The lookup is now /releases/tags/<tag>, with the tag coming from app-release.ts. It also moves to the server with an hour of revalidation: the browser call was unauthenticated against a 60/hour per-IP limit, so one office behind a shared address emptied the grid for everyone on it, and the installer links only appeared after hydration on a page that is an SEO target.

app-release.ts absorbs the asset labels and the releases URL because desktop-download-utils.ts has hooks at module scope, so a server component importing it fails to compile. The client hook stays for the dashboard sidebar, now resolving the same tag.

No assets means the platform section is hidden and the releases link carries the page, rather than placeholder rows that never resolve. That is what /downloads shows today, since v2.0.0 is not cut yet.
@CREDO23
CREDO23 merged commit f1c92b6 into MODSetter:dev Sep 17, 2026
4 of 8 checks passed
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