Files
supabase/apps/studio/components/interfaces/App/AppBannerWrapper.tsx
Pamela Chia 4ae0c08967 feat: tos v3 update banner + publish subprocessor list (#48524)
Terms of Service v3 (effective August 1, 2026, #48482) incorporates the
Data Processing Addendum by reference, and Legal asked for an in-app
notice announcing the change. The subprocessor list page that the new
Terms, DPA, and notice all point at was merged as an intentionally
hidden draft (#48100) and never un-hidden.

**Changed:**

- **Dashboard ToS-update banner**: re-enables `BannerTOSUpdate` with the
v3 copy provided by Legal (DPA incorporation, subprocessor list
location, fees provisions). New expiry (August 29) and a new
localStorage key, since anyone who dismissed the May v2 banner would
otherwise never see this one.
- **Subprocessor list page published**: removes `noindex,nofollow` and
links the page from the Legal Hub index, so the page customers are told
to subscribe on is actually discoverable.
- **Studio e2e fixture updated**: the global Playwright fixture
suppressed the banner via the old localStorage key; with the gate live
again it would have rendered the banner into every e2e run. It now sets
the new key.

## To test

Verified on the Vercel previews :

- [x] Studio: banner renders on dashboard load with the Notice badge and
new copy; Learn more dialog shows the three changes with correct hrefs
(DPA page, subprocessor list, /terms); Understood dismisses and persists
across reload via `terms-of-service-update-2026-08-01`
- [x] www: `/legal` lists Subprocessor List under Customer Legal
Resources; `/legal/customer-resources/subprocessor-list` serves `robots`
meta `index,follow` and renders the download button + subscribe form;
zero console errors on all tested pages

## Linear

- fixes GROWTH-1067


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added a publicly accessible Subprocessor List to the legal resources.
* Updated the Terms of Service notice to reflect the August 1, 2026
update, including data processing, subprocessors, fraud prevention, and
consumer provisions.

* **Documentation**
* Made the Subprocessor List discoverable through standard search
indexing and the legal resources page.
* Extended the Terms of Service banner availability through August 29,
2026.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 15:49:08 +08:00

52 lines
1.7 KiB
TypeScript

import { LOCAL_STORAGE_KEYS, useFlag } from 'common'
import { PropsWithChildren, useEffect } from 'react'
import { OrganizationResourceBanner } from '../Organization/HeaderBanner'
import { ClockSkewBanner } from '@/components/layouts/AppLayout/ClockSkewBanner'
import { NoticeBanner } from '@/components/layouts/AppLayout/NoticeBanner'
import { StatusPageBanner } from '@/components/layouts/AppLayout/StatusPageBanner'
import { BannerTOSUpdate } from '@/components/ui/BannerStack/Banners/BannerTOSUpdate'
import { useBannerStack } from '@/components/ui/BannerStack/BannerStackProvider'
import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
const TOSUpdateExpiry = new Date('2026-08-29T00:00:00Z')
export const AppBannerWrapper = ({ children }: PropsWithChildren<{}>) => {
const showNoticeBanner = useFlag('showNoticeBanner')
const clockSkewBanner = useFlag('clockSkewBanner')
const { addBanner, dismissBanner } = useBannerStack()
const [TOSUpdateAcknowledged, , { isSuccess }] = useLocalStorageQuery(
LOCAL_STORAGE_KEYS.TERMS_OF_SERVICE_UPDATE,
false
)
useEffect(() => {
if (Date.now() >= TOSUpdateExpiry.getTime()) return
if (isSuccess && !TOSUpdateAcknowledged) {
addBanner({
id: 'tos-update-banner',
isDismissed: false,
content: <BannerTOSUpdate />,
priority: 2,
})
} else {
dismissBanner('tos-update-banner')
}
}, [TOSUpdateAcknowledged, isSuccess, addBanner, dismissBanner])
return (
<div className="flex flex-col">
<div className="shrink-0">
<StatusPageBanner />
{showNoticeBanner && <NoticeBanner />}
<OrganizationResourceBanner />
{clockSkewBanner && <ClockSkewBanner />}
</div>
{children}
</div>
)
}