mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
## Summary Adds a compact Privacy Policy update notice for signed-in Studio users on organization landing pages. - Shows on `/org`, `/organizations`, and `/org/:slug` - Opens the approved policy explanation in a dialog - Links to the Privacy Policy and `privacy@supabase.com` - Persists acknowledgement in a dated local storage key - Stays off project and organization settings routes so it cannot cover product controls ## Why The Privacy Policy changes the data controller from Supabase, Inc. to Supabase Pte. Ltd. User rights and protections are unchanged. This restores the established authenticated Studio notification pattern: - [#35923](https://github.com/supabase/supabase/pull/35923): May 2025 Privacy Policy notice - [#43681](https://github.com/supabase/supabase/pull/43681) and [#43889](https://github.com/supabase/supabase/pull/43889): March 2026 Privacy Policy notice and design pass - [#45632](https://github.com/supabase/supabase/pull/45632): May 2026 Terms of Service notice - [#48524](https://github.com/supabase/supabase/pull/48524): current reusable Studio banner stack ## Release order The policy content and Studio notice deploy independently. Keep this PR in draft until [#50392](https://github.com/supabase/supabase/pull/50392) is approved, merged, and live. The notice appears immediately when this Studio change deploys. ## To test 1. Open Studio on `/organizations` or an organization project-list page. 2. Confirm the compact Privacy Policy notice appears. 3. Open **Learn more** and confirm the dialog copy and both links. 4. Select **Understood** or close the notice. 5. Reload and confirm the notice remains dismissed. 6. Remove `privacy-policy-update-2026-09-16-dismissed` from local storage and confirm the notice returns. 7. Open a project route and confirm the notice is absent. ## Verification - Prettier passes on changed files. - ESLint passes on changed Studio files. - Focused Vitest suites pass: 25 tests. - Studio Unit Tests & Build Check passes. - TypeScript & Lint, UI Tests, Studio Docker Build, dead-code, ratchet, and validation workflows pass. - All four self-hosted Studio E2E shards pass for both router implementations. - All deploy previews pass. - The Studio preview rendered the compact notice on the organization landing page without console errors. The dialog and dismissal flow still need an authenticated browser pass after the session redirected to sign-in. A direct local Studio TypeScript check reaches one existing unrelated error in `packages/ui-patterns/src/McpUrlBuilder/components/InstructionBlocks.tsx`; no changed file reports an error and the required TypeScript CI workflow passes. ## Measurement Success means signed-in users can find the updated policy from the organization landing experience without interrupting project work. The dated dismissal key confirms acknowledgement locally. CI protects the non-blocking route scope, and Privacy can monitor questions sent to `privacy@supabase.com` after release. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Pamela Chia <pamelachiamayyee@gmail.com>
96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
import { LOCAL_STORAGE_KEYS } from 'common'
|
|
import {
|
|
Badge,
|
|
Button,
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogSection,
|
|
DialogSectionSeparator,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from 'ui'
|
|
|
|
import { InlineLink } from '../../InlineLink'
|
|
import { BannerCard } from '../BannerCard'
|
|
import { BANNER_ID, useBannerStack } from '../BannerStackProvider'
|
|
import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
|
|
|
|
export const BannerPrivacyPolicyUpdate = () => {
|
|
const { dismissBanner } = useBannerStack()
|
|
const [, setPrivacyPolicyUpdateAcknowledged] = useLocalStorageQuery(
|
|
LOCAL_STORAGE_KEYS.PRIVACY_POLICY_UPDATE,
|
|
false
|
|
)
|
|
|
|
const acknowledgeUpdate = () => {
|
|
setPrivacyPolicyUpdateAcknowledged(true)
|
|
dismissBanner(BANNER_ID.PRIVACY_POLICY_UPDATE)
|
|
}
|
|
|
|
return (
|
|
<BannerCard onDismiss={acknowledgeUpdate}>
|
|
<div className="flex flex-col gap-y-2">
|
|
<Badge variant="default" className="w-min -ml-0.5 uppercase inline-flex items-center mb-2">
|
|
Notice
|
|
</Badge>
|
|
|
|
<div className="flex flex-col gap-y-1 mb-2">
|
|
<p className="text-sm font-medium">We've updated our Privacy Policy</p>
|
|
<p className="text-xs text-foreground-lighter text-balance">
|
|
The data controller is now Supabase Pte. Ltd. Your rights and protections are unchanged.
|
|
</p>
|
|
</div>
|
|
<PrivacyPolicyUpdateDialog onAcknowledge={acknowledgeUpdate} />
|
|
</div>
|
|
</BannerCard>
|
|
)
|
|
}
|
|
|
|
const PrivacyPolicyUpdateDialog = ({ onAcknowledge }: { onAcknowledge: () => void }) => {
|
|
return (
|
|
<Dialog>
|
|
<DialogTrigger asChild>
|
|
<Button className="w-min">Learn more</Button>
|
|
</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Privacy Policy update</DialogTitle>
|
|
<DialogDescription>
|
|
We've updated our Privacy Policy to align with our Data Processing Addendum.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<DialogSectionSeparator />
|
|
|
|
<DialogSection className="text-sm flex flex-col gap-y-2">
|
|
<p>
|
|
The data controller is now listed as Supabase Pte. Ltd. (previously Supabase, Inc.).
|
|
</p>
|
|
<p>
|
|
This is an organizational change for clarity. Your rights, our obligations, and your
|
|
data protections remain unchanged.
|
|
</p>
|
|
<p>
|
|
Read the updated{' '}
|
|
<InlineLink href="https://supabase.com/privacy">Privacy Policy</InlineLink> or{' '}
|
|
<InlineLink href="mailto:privacy@supabase.com">contact us</InlineLink> with any
|
|
questions.
|
|
</p>
|
|
</DialogSection>
|
|
|
|
<DialogFooter>
|
|
<DialogClose asChild>
|
|
<Button className="opacity-100" onClick={onAcknowledge}>
|
|
Understood
|
|
</Button>
|
|
</DialogClose>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|