feat(sunset): wind down the hosted service behind SUNSET_MODE - #1777
AnishSarkar22 wants to merge 199 commits into
Conversation
…thread management
|
@AnishSarkar22 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. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
refactor(local): move the update prompt from a banner to a title bar button
Electron 41+ ships no postinstall; the binary is fetched lazily on the first
require('electron'). electron-vite reads path.txt directly and throws
"Electron uninstall" on a fresh clone, or whenever a peer change renames
the .pnpm folder. Run install-electron (idempotent) as our own postinstall.
feat(local): polish local app UI: artifact filtering, settings, and sidebar
feat(local): cancel running jobs, and show how many sources chat uses
…dev catalogue instead of guessing from the name
…ility fix(local): resolve remote model capabilities from a vendored models.dev catalogue
This migration updates the document status to include a 'cancelled' state, allowing for better management of background document jobs. The downgrade function ensures that cancelled statuses are reverted to 'failed' when necessary.
…d-list to chats-dialog
…me, drop seconds unit
…mposer focus styling
…itioning, add optional tooltip toggle to relative-time
Records the values a deployment that sells licenses must set: the Stripe price the webhook matches a Payment Link against, Resend's SMTP strings, and the Keygen CE connection.
The pricing card now has a primary Buy action driven by NEXT_PUBLIC_STRIPE_LICENSE_INDIVIDUAL_URL, with a secondary trial button beside it.
…y matching known vs unknown capability
…then curated sections
…estructure refactor(dashboard): restructure sidebar and chats navigation, polish studio, onboarding, and model settings UI
… NotebookLM alternative"
…nstead of primary
…oreground for hero dither
The v1.0.x tags belong to the old project versioning, so the relaunch starts at 2.0.0. The release workflow now refuses a tag that disagrees with surfsense_local/VERSION, since extraMetadata.version patches the Electron package but not pyproject.toml.
…isclosure, matching /sunset's compact layout
…estructure feat(marketing): polish onboarding, /sunset, and /license pages to match site design system
…rials for 30 days A trial is handed to an email address, not to an installation, so the email now opens with an install link built from NEXT_FRONTEND_URL. Deployments without a portal keep the original steps rather than printing a dead link. Trial length moves to 30 days so the week before the first plugin ships does not eat half of it. The number is read from LICENSE_TRIAL_DAYS everywhere, including the subject line and the pricing copy, which previously hardcoded 14.
# Conflicts: # surfsense_web/app/(home)/license/page.tsx
Wire the licence purchase flow to Stripe, and set the app to 2.0.0
# Conflicts: # surfsense_local/frontend/src/components/ui/icons.tsx # surfsense_local/frontend/src/features/updates/update-settings.test.tsx # surfsense_local/frontend/src/features/updates/update-settings.tsx # surfsense_web/lib/auth-utils.ts
Description
SUNSET_MODE, one flag read per request on both sides, turning the hosted service export-only at T-0. Unset means off, so self-hosted installs are unaffected.SunsetWriteBlockMiddlewarerefuses writes with410. Reads are never blocked, so export keeps working./auth/except/auth/register, plus/api/v1/license/*and the Stripe webhook — people still need to sign in to export./healthnow reportssunsetand accepts1/true/yes/on. Contract 4 documentsSUNSET_MODE=1, which the old comparison read as false.proxy.tsredirects app routes to/sunsetwhile the portal stays reachable. NotNEXT_PUBLIC_*, so sunsetting is a restart, not a rebuild.lib/public-routes.tsso middleware avoidsauth-utils' browser-only helpers;isPublicRouteis re-exported, no call sites change.purge_hosted_accounts.pyfor T+30 — loops over the existingerase_accountso blobs go with the rows. Dry-run by default, refuses without the flag, typed confirmation, resumable..env.examplefiles and both compose files.--noticecolour token.Known gap for review: nothing purges artifact blobs when a workspace is deleted, so the purge empties
documents/but notartifacts/— deleting the storage container is required. Same gap affects single-account deletion today, independent of this PR.Motivation and Context
FIX #
Screenshots
API Changes
Change Type
Testing Performed
Checklist
High-level PR Summary
This PR implements the hosted service wind-down infrastructure (Workstream B from the pivot plan). It introduces a
SUNSET_MODEflag that transitions the hosted service into an export-only state at T-0, blocking writes while keeping authentication and data export functional. The implementation includes backend middleware to refuse writes with 410 responses, frontend redirects to a/sunsetpage for app routes, comprehensive runbooks for T-0 sunset and T+30 data purge operations, and a purge script that loops over the existingerase_accountfunction. Additionally, it refactors the desktop app's update notification from a banner to a title bar button styled with a new--noticecolor. The system is designed to be a no-op for self-hosted installations whereSUNSET_MODEremains unset.⏱️ Estimated Review Time: 30-90 minutes
💡 Review Order Suggestion
plans/community-local/00d-pivot-plan.mdplans/community-local/sunset-runbook.mdplans/community-local/purge-runbook.mdsurfsense_backend/app/sunset.pysurfsense_backend/app/app.pysurfsense_backend/scripts/purge_hosted_accounts.pysurfsense_backend/tests/unit/test_sunset_flag.pysurfsense_backend/tests/unit/test_sunset_write_block.pysurfsense_web/lib/sunset.tssurfsense_web/lib/public-routes.tssurfsense_web/proxy.tssurfsense_web/tests/unit/sunset-redirect.test.tssurfsense_backend/.env.examplesurfsense_web/.env.exampledocker/.env.exampledocker/docker-compose.dev.ymldocker/docker-compose.ymlsurfsense_local/frontend/src/features/updates/update-settings.tsxsurfsense_local/frontend/src/features/updates/update-settings.test.tsxsurfsense_local/frontend/src/features/dashboard/dashboard-page.tsxsurfsense_local/frontend/src/app/app-bootstrap.tsxsurfsense_local/frontend/src/components/ui/icons.tsxsurfsense_local/frontend/src/index.csssurfsense_local/frontend/src/test-utils.tsx.cursor/skills/color-system/PALETTE.css