mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-27 19:25:15 +02:00
Merge remote-tracking branch 'upstream/dev' into feat/opentelemetry
This commit is contained in:
commit
98e3950dc8
20 changed files with 569 additions and 122 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.0.24
|
||||
0.0.25
|
||||
|
|
|
|||
|
|
@ -1,11 +1,42 @@
|
|||
<citations>
|
||||
Apply chunk citations only when the runtime injects `<document>` /
|
||||
`<chunk id='…'>` blocks.
|
||||
Citations reach the answer through two channels. Use whichever applies — and
|
||||
never invent ids you didn't see. Citation ids are resolved by exact-match
|
||||
lookup; a wrong id silently breaks the link, so when in doubt, omit.
|
||||
|
||||
### Channel A — chunk blocks injected this turn
|
||||
When `search_surfsense_docs` or `web_search` returns `<document>` /
|
||||
`<chunk id='…'>` blocks in this turn:
|
||||
|
||||
1. For each factual statement taken from those chunks, add
|
||||
`[citation:chunk_id]` using the exact id from `<chunk id='…'>`.
|
||||
2. Multiple chunks → `[citation:id1], [citation:id2]` (comma-separated).
|
||||
3. Never invent or normalise ids; if unsure, omit.
|
||||
4. Plain brackets only — no markdown links, no footnote numbering.
|
||||
5. If no chunk-tagged documents appear this turn, do not fabricate citations.
|
||||
`[citation:chunk_id]` using the **exact** id from a visible
|
||||
`<chunk id='…'>` tag. Copy digit-for-digit (or the URL verbatim);
|
||||
do not retype from memory.
|
||||
2. `<document_id>` is the parent doc id, **not** a citation source —
|
||||
only ids inside `<chunk id='…'>` count.
|
||||
3. Multiple chunks → `[citation:id1], [citation:id2]` (comma-separated,
|
||||
each id copied individually).
|
||||
4. Never invent, normalise, or guess at adjacent ids; if unsure, omit.
|
||||
5. Plain brackets only — no markdown links, no footnote numbering.
|
||||
|
||||
### Channel B — citations relayed by a `task` specialist
|
||||
A `task(...)` tool message may contain `[citation:<chunk_id>]` markers
|
||||
the specialist already attached to its prose. The specialist saw the
|
||||
underlying `<chunk id='…'>` blocks; you didn't. So:
|
||||
|
||||
1. **Preserve those markers verbatim** in your final answer — do not
|
||||
reformat, renumber, drop, or wrap them in markdown links. When you
|
||||
paraphrase a specialist sentence, copy the marker character-for-
|
||||
character; do not regenerate the id from memory (LLMs reliably
|
||||
corrupt nearby digits).
|
||||
2. Keep each marker attached to the sentence the specialist attached
|
||||
it to.
|
||||
3. Do **not** add new `[citation:…]` markers of your own to a
|
||||
specialist's prose; if a fact has no marker, the specialist
|
||||
couldn't tie it to a chunk and neither can you.
|
||||
4. When a specialist returns JSON, the citation markers live inside
|
||||
the prose-bearing fields (e.g. a summary or excerpt). Pull them
|
||||
along with the surrounding sentence when you quote.
|
||||
|
||||
If neither channel surfaces citation markers this turn, do not fabricate
|
||||
them.
|
||||
</citations>
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@ Read-only specialist for the user's workspace (documents and folders). Use to fi
|
|||
|
||||
Pass your full question as one string. The specialist runs in isolation: it cannot see this thread, so include any path hints, filters, or constraints it needs.
|
||||
|
||||
The specialist returns plain prose with absolute paths.
|
||||
The specialist returns plain prose with absolute paths and `[citation:<chunk_id>]` markers when claims came from KB-indexed chunks. Preserve those markers verbatim if you forward the answer.
|
||||
|
|
|
|||
|
|
@ -35,6 +35,43 @@ Map outcomes to your `status`:
|
|||
|
||||
You construct the structured `evidence` fields from your own knowledge of what you called and what you observed — the tools do not return them. Never report values you did not actually see.
|
||||
|
||||
## Chunk citations in your prose
|
||||
|
||||
When `read_file` returns a KB-indexed document under `/documents/`, the response includes `<chunk id='…'>` blocks. Whenever a fact in your `action_summary` or `evidence.content_excerpt` came from a specific chunk, append `[citation:<chunk_id>]` to the sentence stating that fact, using the **exact** id from the `<chunk id='…'>` tag. The caller relays these markers to the end user verbatim, and the UI resolves each id by exact match against the database, so a wrong id silently breaks the citation.
|
||||
|
||||
### Where chunk ids live in `read_file` output
|
||||
|
||||
A KB document's XML has three numeric attributes — only **one** is a citation source:
|
||||
|
||||
```
|
||||
<document>
|
||||
<document_metadata>
|
||||
<document_id>42</document_id> ← NOT a citation. Parent doc id; ignore for citations.
|
||||
...
|
||||
</document_metadata>
|
||||
<chunk_index>
|
||||
<entry chunk_id="128" lines="14-22"/> ← Index hint; the same id also appears below.
|
||||
<entry chunk_id="129" lines="23-30" matched="true"/>
|
||||
</chunk_index>
|
||||
<document_content>
|
||||
<chunk id='128'><![CDATA[…]]></chunk> ← This is the citation source.
|
||||
<chunk id='129'><![CDATA[…]]></chunk>
|
||||
</document_content>
|
||||
</document>
|
||||
```
|
||||
|
||||
### Rules
|
||||
|
||||
- Use the **exact** id from a `<chunk id='…'>` tag whose content you actually quoted or paraphrased. Copy digit-for-digit; do **not** retype from memory.
|
||||
- Before emitting `[citation:N]`, confirm the literal substring `<chunk id='N'>` (or its index twin `chunk_id="N"`) appears in the tool result you are summarising this turn. If you can't see it, omit the citation.
|
||||
- Never cite `<document_id>` — that's the parent doc, not a chunk.
|
||||
- Never invent, normalise, shorten, or guess at adjacent ids. If unsure between two candidates, omit rather than pick.
|
||||
- Prefer **fewer accurate citations** over many speculative ones.
|
||||
- Multiple chunks supporting the same point → comma-separated and copied individually: `[citation:128], [citation:129]`.
|
||||
- Plain square brackets only — no markdown links, no parentheses, no footnote numbers.
|
||||
- Tool results without `<chunk id='…'>` (write/edit/move confirmations, `ls` / `glob` / `grep` listings, error strings) carry no chunk id and need none.
|
||||
- Populate `evidence.chunk_ids` with **only** ids you actually emitted in `[citation:…]` markers — same set, same digits.
|
||||
|
||||
## Examples
|
||||
|
||||
**Example 1 — happy path write (path discovered from existing convention):**
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ Map outcomes to your `status`:
|
|||
|
||||
You construct the structured `evidence` fields from your own knowledge of what you called and what you observed — the tools do not return them. `chunk_ids` apply only to `<priority_documents>` hits; for local-file operations leave them `null`. Never report values you did not actually see.
|
||||
|
||||
## Chunk citations in your prose
|
||||
|
||||
In desktop mode your filesystem tools read local files only, and local-file tool results do **not** carry `<chunk id='…'>` tags. Do not emit `[citation:…]` markers in `action_summary` or `evidence.content_excerpt`, and leave `evidence.chunk_ids` `null` — the absolute path is the only reference for local-file work.
|
||||
|
||||
## Examples
|
||||
|
||||
**Example 1 — happy path write (path discovered from existing convention):**
|
||||
|
|
|
|||
|
|
@ -27,3 +27,42 @@ Reply in plain prose:
|
|||
- Cite every claim with an absolute path under `/documents/`.
|
||||
- If the workspace does not contain the requested information, say so explicitly. Do not fabricate paths or content.
|
||||
- If the question is genuinely ambiguous after a thorough lookup, list the candidates with their paths and stop.
|
||||
|
||||
## Chunk citations
|
||||
|
||||
When the evidence for a claim came from a `read_file` response that included `<chunk id='…'>` blocks (i.e. a KB-indexed document under `/documents/`), append `[citation:<chunk_id>]` to the sentence stating that claim. The caller passes these markers through to the end user verbatim, and the UI resolves each id by exact match against the database, so a wrong id silently breaks the citation.
|
||||
|
||||
### Where chunk ids live in `read_file` output
|
||||
|
||||
A KB document's XML has three numeric attributes — only **one** is a citation source:
|
||||
|
||||
```
|
||||
<document>
|
||||
<document_metadata>
|
||||
<document_id>42</document_id> ← NOT a citation. Parent doc id; ignore for citations.
|
||||
...
|
||||
</document_metadata>
|
||||
<chunk_index>
|
||||
<entry chunk_id="128" lines="14-22"/> ← Index hint; the same id also appears below.
|
||||
<entry chunk_id="129" lines="23-30" matched="true"/>
|
||||
</chunk_index>
|
||||
<document_content>
|
||||
<chunk id='128'><![CDATA[…]]></chunk> ← This is the citation source.
|
||||
<chunk id='129'><![CDATA[…]]></chunk>
|
||||
</document_content>
|
||||
</document>
|
||||
```
|
||||
|
||||
### Rules
|
||||
|
||||
- Use the **exact** id from a `<chunk id='…'>` tag whose content you actually quoted or paraphrased. Copy digit-for-digit; do **not** retype from memory.
|
||||
- Before emitting `[citation:N]`, confirm the literal substring `<chunk id='N'>` (or its index twin `chunk_id="N"`) appears in the tool result you are summarising this turn. If you can't see it, omit the citation.
|
||||
- Never cite `<document_id>` — that's the parent doc, not a chunk.
|
||||
- Never invent, normalise, shorten, or guess at adjacent ids. If unsure between two candidates, omit rather than pick.
|
||||
- Prefer **fewer accurate citations** over many speculative ones. One correct `[citation:128]` is more useful than a string of wrong ids.
|
||||
- Multiple chunks supporting the same point → comma-separated and copied individually: `[citation:128], [citation:129]`.
|
||||
- Plain square brackets only — no markdown links, no parentheses, no footnote numbers.
|
||||
- If a claim came from a tool result that did **not** carry a chunk id (`ls`, `glob`, `grep` listings, error strings, or files without `<chunk id='…'>`), skip the citation.
|
||||
- The absolute path under `/documents/` is always required; chunk citations are additive, they do not replace the path reference.
|
||||
|
||||
Example: `The Q2 roadmap lists three milestones (/documents/planning/q2-roadmap.md) [citation:128], [citation:129].`
|
||||
|
|
|
|||
|
|
@ -28,3 +28,7 @@ Reply in plain prose:
|
|||
- Cite every claim with an absolute path.
|
||||
- If the workspace does not contain the requested information, say so explicitly. Do not fabricate paths or content.
|
||||
- If the question is genuinely ambiguous after a thorough lookup, list the candidates with their paths and stop.
|
||||
|
||||
## Chunk citations
|
||||
|
||||
In desktop mode your filesystem tools read local files only, and local-file `read_file` responses do **not** carry `<chunk id='…'>` tags. Cite each claim with the absolute local path; do not emit `[citation:…]` markers — your caller has nothing to resolve them against.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "surf-new-backend"
|
||||
version = "0.0.24"
|
||||
version = "0.0.25"
|
||||
description = "SurfSense Backend"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
|
|
|
|||
2
surfsense_backend/uv.lock
generated
2
surfsense_backend/uv.lock
generated
|
|
@ -8121,7 +8121,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "surf-new-backend"
|
||||
version = "0.0.24"
|
||||
version = "0.0.25"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "alembic" },
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "surfsense_browser_extension",
|
||||
"displayName": "Surfsense Browser Extension",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.25",
|
||||
"description": "Extension to collect Browsing History for SurfSense.",
|
||||
"author": "https://github.com/MODSetter",
|
||||
"engines": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "surfsense-desktop",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.25",
|
||||
"description": "SurfSense Desktop App",
|
||||
"main": "dist/main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -19,3 +19,12 @@ NEXT_PUBLIC_POSTHOG_KEY=
|
|||
# Cloudflare Turnstile CAPTCHA for anonymous chat abuse prevention
|
||||
# Get your site key from https://dash.cloudflare.com/ -> Turnstile
|
||||
NEXT_PUBLIC_TURNSTILE_SITE_KEY=
|
||||
|
||||
# Google AdSense (optional, only enables ads on the /free hub page).
|
||||
# Publisher ID from your AdSense dashboard, e.g. ca-pub-XXXXXXXXXXXXXXXX.
|
||||
# Leave empty to disable ad rendering entirely.
|
||||
NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID=
|
||||
# Ad unit slot IDs from AdSense dashboard -> Ads -> By ad unit.
|
||||
# Leave empty to hide individual slots while keeping the script loaded.
|
||||
NEXT_PUBLIC_GOOGLE_ADSENSE_SLOT_FREE_HUB_IN_CONTENT=
|
||||
NEXT_PUBLIC_GOOGLE_ADSENSE_SLOT_FREE_HUB_BEFORE_FAQ=
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
import { SquareArrowOutUpRight } from "lucide-react";
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { AdUnit } from "@/components/ads/ad-unit";
|
||||
import { ADSENSE_SLOTS } from "@/components/ads/adsense-config";
|
||||
import { AdSenseScript } from "@/components/ads/adsense-script";
|
||||
import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
||||
import { FAQJsonLd, JsonLd } from "@/components/seo/json-ld";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
|
|
@ -157,6 +160,7 @@ export default async function FreeHubPage() {
|
|||
|
||||
return (
|
||||
<div className="min-h-screen pt-20">
|
||||
<AdSenseScript />
|
||||
<JsonLd
|
||||
data={{
|
||||
"@context": "https://schema.org",
|
||||
|
|
@ -216,6 +220,14 @@ export default async function FreeHubPage() {
|
|||
|
||||
<Separator className="my-12 max-w-4xl mx-auto" />
|
||||
|
||||
{/* In-content ad: above the model table */}
|
||||
<aside
|
||||
aria-label="Advertisement"
|
||||
className="max-w-4xl mx-auto mb-8 min-h-[100px]"
|
||||
>
|
||||
<AdUnit slot={ADSENSE_SLOTS.freeHubInContent} />
|
||||
</aside>
|
||||
|
||||
{/* Model Table */}
|
||||
{seoModels.length > 0 ? (
|
||||
<section
|
||||
|
|
@ -340,6 +352,14 @@ export default async function FreeHubPage() {
|
|||
|
||||
<Separator className="my-12 max-w-4xl mx-auto" />
|
||||
|
||||
{/* In-content ad: after CTA, before FAQ */}
|
||||
<aside
|
||||
aria-label="Advertisement"
|
||||
className="max-w-3xl mx-auto my-8 min-h-[100px]"
|
||||
>
|
||||
<AdUnit slot={ADSENSE_SLOTS.freeHubBeforeFaq} />
|
||||
</aside>
|
||||
|
||||
{/* FAQ */}
|
||||
<section className="max-w-3xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-center mb-8">Frequently Asked Questions</h2>
|
||||
|
|
|
|||
|
|
@ -1,190 +1,369 @@
|
|||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Privacy Policy | SurfSense",
|
||||
description: "Privacy Policy for SurfSense application",
|
||||
description:
|
||||
"Privacy Policy for SurfSense. Learn how we collect, use, and protect your data, and how third-party services such as Google AdSense use cookies on our site.",
|
||||
alternates: {
|
||||
canonical: "https://www.surfsense.com/privacy",
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Update this date whenever you make a material change to the policy. Keeping
|
||||
* it as a static constant (rather than `new Date()`) avoids hydration
|
||||
* mismatches and makes the policy look professionally maintained to reviewers
|
||||
* (including AdSense reviewers).
|
||||
*/
|
||||
const LAST_UPDATED = "May 21, 2026";
|
||||
|
||||
export default function PrivacyPolicy() {
|
||||
return (
|
||||
<div className="container max-w-4xl mx-auto py-12 px-4">
|
||||
<h1 className="text-4xl font-bold mb-8">Privacy Policy</h1>
|
||||
|
||||
<div className="prose dark:prose-invert max-w-none">
|
||||
<p className="text-lg mb-6">Last updated: {new Date().toLocaleDateString()}</p>
|
||||
<p className="text-lg mb-6">Last updated: {LAST_UPDATED}</p>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">1. Introduction</h2>
|
||||
<p>
|
||||
Welcome to SurfSense. We respect your privacy and are committed to protecting your
|
||||
personal data. This privacy policy will inform you about how we look after your personal
|
||||
data when you visit our website and tell you about your privacy rights and how the law
|
||||
protects you.
|
||||
Welcome to SurfSense ("SurfSense", "we", "us", or "our"). We operate the website at{" "}
|
||||
<a href="https://www.surfsense.com">www.surfsense.com</a> and the SurfSense application
|
||||
(collectively, the "Service"). We respect your privacy and are committed to protecting
|
||||
your personal data. This Privacy Policy explains what data we collect, how we use it,
|
||||
who we share it with, and the rights you have over your data.
|
||||
</p>
|
||||
<p className="mt-4">
|
||||
By using our services, you acknowledge that you have read and understood this Privacy
|
||||
Policy. We reserve the right to modify this policy at any time, and such modifications
|
||||
shall be effective immediately upon posting the modified policy on this website.
|
||||
By accessing or using the Service, you acknowledge that you have read and understood
|
||||
this Privacy Policy. If you do not agree with our policies and practices, do not use
|
||||
the Service. We may modify this policy from time to time; material changes will be
|
||||
reflected by updating the "Last updated" date above.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">2. Data We Collect</h2>
|
||||
<p>
|
||||
We may collect, use, store and transfer different kinds of personal data about you which
|
||||
we have grouped together as follows:
|
||||
</p>
|
||||
<p>We collect the following categories of personal data:</p>
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">
|
||||
<li>
|
||||
<strong>Identity Data</strong> includes first name, last name, username or similar
|
||||
identifier.
|
||||
<strong>Identity Data</strong> includes first name, last name, username, or similar
|
||||
identifier you provide when registering for an account.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Contact Data</strong> includes email address and telephone numbers.
|
||||
<strong>Contact Data</strong> includes email address and any contact information you
|
||||
provide when reaching out to support or completing the contact form.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Technical Data</strong> includes internet protocol (IP) address, your login
|
||||
data, browser type and version, time zone setting and location, browser plug-in types
|
||||
and versions, operating system and platform, and other technology on the devices you
|
||||
use to access this website.
|
||||
<strong>Account and Authentication Data</strong> includes hashed passwords (for local
|
||||
authentication) and OAuth tokens issued by identity providers such as Google when you
|
||||
sign in with a third-party account.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Usage Data</strong> includes information about how you use our website and
|
||||
services.
|
||||
<strong>Chat and Knowledge Base Data</strong> includes the messages, prompts,
|
||||
documents, and notes you submit through the Service when signed in. Anonymous chat
|
||||
sessions on our free pages are not stored in any user-linked database.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Surf Data</strong> includes information about surf sessions, preferences, and
|
||||
equipment settings.
|
||||
<strong>Document and Integration Data</strong> includes content from files you upload
|
||||
and data fetched from third-party services you connect (such as Slack, Google Drive,
|
||||
Notion, Confluence, GitHub, and others) under the scopes you authorize.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Marketing and Communications Data</strong> includes your preferences in
|
||||
receiving marketing from us and your communication preferences.
|
||||
<strong>Billing Data</strong> includes information necessary to process payments
|
||||
(such as transaction identifiers and credit balances). Card details are handled by
|
||||
our payment processor and are not stored on our servers.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Aggregated Data</strong> which may be derived from your personal data but is
|
||||
not considered personal data as it does not directly or indirectly reveal your
|
||||
identity.
|
||||
<strong>Technical Data</strong> includes internet protocol (IP) address, browser type
|
||||
and version, time zone, operating system, device identifiers, and other technology
|
||||
identifiers from the devices you use to access the Service.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Usage Data</strong> includes information about how you interact with the
|
||||
Service, such as pages visited, features used, referring URLs, and timestamps.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Advertising Data</strong> includes cookie identifiers, ad interaction data,
|
||||
and pseudonymous identifiers set by Google AdSense and its partners on pages that
|
||||
serve ads. See Section 5 for details.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Marketing and Communications Data</strong> includes your preferences for
|
||||
receiving marketing communications from us.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Aggregated Data</strong> derived from any of the above and stripped of
|
||||
identifiers. Aggregated data is not considered personal data under most laws.
|
||||
</li>
|
||||
</ul>
|
||||
<p className="mt-4">
|
||||
We may also collect, use and share Aggregated Data such as statistical or demographic
|
||||
data for any purpose. Aggregated Data may be derived from your personal data but is not
|
||||
considered personal data in law as this data does not directly or indirectly reveal your
|
||||
identity.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">3. How We Use Your Data</h2>
|
||||
<p>We use your personal data only where we have a lawful basis to do so, including:</p>
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">
|
||||
<li>
|
||||
To create and manage your account, authenticate you, and provide the Service you have
|
||||
requested.
|
||||
</li>
|
||||
<li>
|
||||
To process payments, manage your credit balance, and prevent fraud and abuse of the
|
||||
Service.
|
||||
</li>
|
||||
<li>
|
||||
To answer your queries by sending prompts and content you submit to large language
|
||||
model providers (see Section 8) and return the responses to you.
|
||||
</li>
|
||||
<li>
|
||||
To synchronize data from third-party services you have explicitly connected (such as
|
||||
Slack, Google Drive, or Notion) so that the Service can search and reference that
|
||||
content on your behalf.
|
||||
</li>
|
||||
<li>
|
||||
To monitor, analyze, and improve the Service, diagnose issues, and detect security
|
||||
incidents.
|
||||
</li>
|
||||
<li>
|
||||
To communicate with you about product updates, security notices, support requests,
|
||||
and (with your consent where required) marketing.
|
||||
</li>
|
||||
<li>
|
||||
To serve and measure advertising on pages where ads are shown (currently, our free
|
||||
public pages). See Section 5 for details.
|
||||
</li>
|
||||
<li>To comply with legal obligations and enforce our Terms of Service.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">4. Cookies and Tracking Technologies</h2>
|
||||
<p>
|
||||
We will only use your personal data when the law allows us to. Most commonly, we will
|
||||
use your personal data in the following circumstances:
|
||||
We and our partners use cookies, local storage, and similar technologies to operate the
|
||||
Service, remember your preferences, measure usage, and serve advertising. The
|
||||
categories include:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">
|
||||
<li>
|
||||
Where we need to perform the contract we are about to enter into or have entered into
|
||||
with you.
|
||||
<strong>Strictly necessary</strong> cookies and storage required for authentication,
|
||||
session management, security (including CAPTCHA), and core functionality.
|
||||
</li>
|
||||
<li>
|
||||
Where it is necessary for our legitimate interests (or those of a third party) and
|
||||
your interests and fundamental rights do not override those interests.
|
||||
</li>
|
||||
<li>Where we need to comply with a legal obligation.</li>
|
||||
<li>
|
||||
To provide and maintain our services, including to monitor the usage of our service.
|
||||
<strong>Preference</strong> cookies and storage that remember choices such as theme,
|
||||
language, and onboarding state.
|
||||
</li>
|
||||
<li>
|
||||
To improve our services, products, marketing, and customer relationships and
|
||||
experiences.
|
||||
<strong>Analytics</strong> cookies that help us understand how the Service is used so
|
||||
we can improve it. We use PostHog for product analytics.
|
||||
</li>
|
||||
<li>To communicate with you about updates, security alerts, and support messages.</li>
|
||||
<li>To provide customer support and respond to your requests or inquiries.</li>
|
||||
<li>
|
||||
For business transfers, such as in connection with a merger, sale of company assets,
|
||||
financing, or acquisition.
|
||||
<strong>Advertising</strong> cookies set by Google AdSense and its partners on pages
|
||||
that serve ads. These cookies are used to deliver relevant ads, measure ad
|
||||
performance, and limit how often an ad is shown to the same user. See Section 5.
|
||||
</li>
|
||||
</ul>
|
||||
<p className="mt-4">
|
||||
We may use your information for marketing purposes, such as sending you information
|
||||
about our products, services, promotions, and events. You can opt-out of receiving these
|
||||
communications at any time.
|
||||
You can control cookies through your browser settings. Blocking strictly necessary
|
||||
cookies will prevent the Service from functioning correctly. Where required by law, we
|
||||
request your consent before setting non-essential cookies.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">4. Data Security</h2>
|
||||
<h2 className="text-2xl font-semibold mb-4">5. Advertising and Google AdSense</h2>
|
||||
<p>
|
||||
We have put in place appropriate security measures to prevent your personal data from
|
||||
being accidentally lost, used or accessed in an unauthorized way, altered or disclosed.
|
||||
In addition, we limit access to your personal data to those employees, agents,
|
||||
contractors and other third parties who have a business need to know.
|
||||
</p>
|
||||
<p className="mt-4">
|
||||
While we implement safeguards designed to protect your information, no security system
|
||||
is impenetrable and due to the inherent nature of the Internet, we cannot guarantee that
|
||||
information, during transmission through the Internet or while stored on our systems, is
|
||||
absolutely safe from intrusion by others.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">5. Data Retention</h2>
|
||||
<p>
|
||||
We will only retain your personal data for as long as necessary to fulfill the purposes
|
||||
we collected it for, including for the purposes of satisfying any legal, accounting, or
|
||||
reporting requirements. To determine the appropriate retention period for personal data,
|
||||
we consider the amount, nature, and sensitivity of the personal data, the potential risk
|
||||
of harm from unauthorized use or disclosure of your personal data, the purposes for
|
||||
which we process your personal data and whether we can achieve those purposes through
|
||||
other means, and the applicable legal requirements.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">6. Your Legal Rights</h2>
|
||||
<p>
|
||||
Under certain circumstances, you have rights under data protection laws in relation to
|
||||
your personal data, including:
|
||||
Our free public pages (currently <Link href="/free">www.surfsense.com/free</Link>) are
|
||||
supported by advertising served through Google AdSense, a service provided by Google
|
||||
LLC.
|
||||
</p>
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">
|
||||
<li>The right to request access to your personal data.</li>
|
||||
<li>The right to request correction of your personal data.</li>
|
||||
<li>The right to request erasure of your personal data.</li>
|
||||
<li>The right to object to processing of your personal data.</li>
|
||||
<li>The right to request restriction of processing your personal data.</li>
|
||||
<li>The right to request transfer of your personal data.</li>
|
||||
<li>The right to withdraw consent.</li>
|
||||
<li>
|
||||
Google, as a third-party vendor, uses cookies (including the DoubleClick DART
|
||||
cookie) to serve ads to you based on your visits to our Service and other websites
|
||||
on the Internet.
|
||||
</li>
|
||||
<li>
|
||||
Google's use of advertising cookies enables it and its partners to serve ads to you
|
||||
based on your visit to our Service and/or other sites on the Internet.
|
||||
</li>
|
||||
<li>
|
||||
You may opt out of personalized advertising by visiting{" "}
|
||||
<a href="https://www.google.com/settings/ads">Google Ads Settings</a>. You may also
|
||||
opt out of some third-party vendors' use of cookies for personalized advertising at{" "}
|
||||
<a href="https://www.aboutads.info/choices/">www.aboutads.info/choices</a> (US) or{" "}
|
||||
<a href="https://www.youronlinechoices.com/">youronlinechoices.com</a> (EU).
|
||||
</li>
|
||||
<li>
|
||||
For users in the European Economic Area, the United Kingdom, and Switzerland, we
|
||||
use a Google-certified Consent Management Platform to obtain your consent for
|
||||
personalized advertising before such cookies are set. You may change or withdraw
|
||||
your consent at any time through the consent banner.
|
||||
</li>
|
||||
<li>
|
||||
We do not knowingly serve personalized advertising to children. See Section 11.
|
||||
</li>
|
||||
</ul>
|
||||
<p className="mt-4">
|
||||
Please note that these rights are not absolute, and we may be entitled to refuse
|
||||
requests where exceptions apply. If you wish to exercise any of the rights set out
|
||||
above, please contact us. We may need to request specific information from you to help
|
||||
us confirm your identity and ensure your right to access your personal data.
|
||||
For more information about how Google uses data when you use our Service, see{" "}
|
||||
<a href="https://policies.google.com/technologies/partner-sites">
|
||||
How Google uses information from sites or apps that use our services
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">7. Third-Party Services</h2>
|
||||
<h2 className="text-2xl font-semibold mb-4">6. Data Security</h2>
|
||||
<p>
|
||||
Our service may contain links to other websites that are not operated by us. If you
|
||||
click on a third-party link, you will be directed to that third party's site. We
|
||||
strongly advise you to review the Privacy Policy of every site you visit. We have no
|
||||
control over and assume no responsibility for the content, privacy policies, or
|
||||
practices of any third-party sites or services.
|
||||
We implement technical and organizational measures designed to protect your personal
|
||||
data against accidental loss, unauthorized access, alteration, and disclosure. Access
|
||||
to personal data is limited to personnel who need it to operate the Service.
|
||||
</p>
|
||||
<p className="mt-4">
|
||||
No system can be guaranteed to be fully secure. We cannot guarantee that personal data
|
||||
transmitted to or stored by the Service will be free from unauthorized access. You are
|
||||
responsible for keeping your account credentials confidential.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">8. Contact Us</h2>
|
||||
<h2 className="text-2xl font-semibold mb-4">7. Data Retention</h2>
|
||||
<p>
|
||||
If you have any questions about this privacy policy or our privacy practices, please
|
||||
contact us at:
|
||||
We retain personal data only for as long as necessary to provide the Service and to
|
||||
comply with our legal, accounting, and reporting obligations. Account data is retained
|
||||
for the life of your account; you can request deletion at any time. Aggregated data
|
||||
that no longer identifies you may be retained indefinitely for analytics and product
|
||||
improvement purposes. Anonymous chat sessions on our free pages are not retained in
|
||||
any user-linked database.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">8. Third-Party Services</h2>
|
||||
<p>
|
||||
We rely on the following categories of third-party processors and providers to operate
|
||||
the Service. Each is bound by its own privacy policy, which we encourage you to
|
||||
review:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">
|
||||
<li>
|
||||
<strong>Authentication</strong>: Google (OAuth sign-in).
|
||||
</li>
|
||||
<li>
|
||||
<strong>Hosting and infrastructure</strong>: Vercel, Cloudflare (CAPTCHA via
|
||||
Cloudflare Turnstile, DNS, and edge protection).
|
||||
</li>
|
||||
<li>
|
||||
<strong>Analytics</strong>: PostHog (product analytics).
|
||||
</li>
|
||||
<li>
|
||||
<strong>Advertising</strong>: Google AdSense (see Section 5).
|
||||
</li>
|
||||
<li>
|
||||
<strong>Large language model providers</strong>: OpenAI, Anthropic, Google, and
|
||||
other LLM providers process the prompts and content you submit to the Service in
|
||||
order to generate responses.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Integration providers</strong>: When you explicitly connect a third-party
|
||||
service (such as Slack, Google Drive, Notion, Confluence, GitHub, Jira, Linear, or
|
||||
similar), data is exchanged with that service under the scopes you authorize.
|
||||
</li>
|
||||
</ul>
|
||||
<p className="mt-4">
|
||||
We do not sell personal data to third parties. We share data with the providers above
|
||||
only to the extent needed to operate the Service.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">
|
||||
9. Your Legal Rights (Including GDPR)
|
||||
</h2>
|
||||
<p>
|
||||
Subject to applicable law, you have the following rights in relation to your personal
|
||||
data:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">
|
||||
<li>The right to access the personal data we hold about you.</li>
|
||||
<li>The right to request correction of inaccurate or incomplete data.</li>
|
||||
<li>The right to request erasure of your personal data ("right to be forgotten").</li>
|
||||
<li>The right to object to or restrict certain processing of your data.</li>
|
||||
<li>The right to data portability (to receive your data in a portable format).</li>
|
||||
<li>
|
||||
The right to withdraw consent at any time where we rely on consent to process your
|
||||
data (such as for advertising cookies in the EEA, UK, and Switzerland).
|
||||
</li>
|
||||
<li>
|
||||
The right to lodge a complaint with your local supervisory authority if you believe
|
||||
our processing of your data infringes applicable law.
|
||||
</li>
|
||||
</ul>
|
||||
<p className="mt-4">
|
||||
To exercise any of these rights, please contact us using the details in Section 13. We
|
||||
may need to verify your identity before responding to your request.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">10. California Residents (CCPA / CPRA)</h2>
|
||||
<p>
|
||||
If you are a California resident, you have additional rights under the California
|
||||
Consumer Privacy Act (as amended by the CPRA), including:
|
||||
</p>
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">
|
||||
<li>
|
||||
The right to know what categories of personal information we have collected about
|
||||
you and how it is used and shared.
|
||||
</li>
|
||||
<li>The right to delete personal information we have collected from you.</li>
|
||||
<li>The right to correct inaccurate personal information.</li>
|
||||
<li>
|
||||
The right to opt out of the "sale" or "sharing" of personal information for
|
||||
cross-context behavioral advertising. We do not sell personal data; however,
|
||||
advertising cookies set by Google AdSense may be considered "sharing" under
|
||||
California law. To opt out, you can use the consent controls described in Section 5
|
||||
or enable a Global Privacy Control (GPC) signal in your browser, which we honor.
|
||||
</li>
|
||||
<li>The right not to be discriminated against for exercising your privacy rights.</li>
|
||||
</ul>
|
||||
<p className="mt-4">
|
||||
To exercise your CCPA rights, please contact us using the details in Section 13.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">11. Children's Privacy</h2>
|
||||
<p>
|
||||
The Service is not directed to children under 13 (or under 16 in the EEA, UK, and
|
||||
Switzerland). We do not knowingly collect personal data from children. If you believe
|
||||
a child has provided us with personal data, please contact us and we will take steps
|
||||
to delete it. We do not knowingly serve personalized advertising to children.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">12. Changes to This Policy</h2>
|
||||
<p>
|
||||
We may update this Privacy Policy from time to time to reflect changes in our
|
||||
practices, technology, legal requirements, or for other operational reasons. When we
|
||||
make material changes, we will update the "Last updated" date at the top of this page
|
||||
and, where appropriate, provide additional notice (such as an in-product notification
|
||||
or email). Your continued use of the Service after the updated policy becomes
|
||||
effective constitutes your acceptance of the revised policy.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">13. Contact Us</h2>
|
||||
<p>
|
||||
If you have questions about this Privacy Policy or our privacy practices, or if you
|
||||
want to exercise any of your rights, please contact us at:
|
||||
</p>
|
||||
<p className="mt-2">
|
||||
<strong>Email:</strong> rohan@surfsense.com
|
||||
<strong>Email:</strong>{" "}
|
||||
<a href="mailto:rohan@surfsense.com">rohan@surfsense.com</a>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
|||
78
surfsense_web/components/ads/ad-unit.tsx
Normal file
78
surfsense_web/components/ads/ad-unit.tsx
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
"use client";
|
||||
|
||||
import type { CSSProperties } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const ADSENSE_CLIENT_ID = process.env.NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID;
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
adsbygoogle?: Record<string, unknown>[];
|
||||
}
|
||||
}
|
||||
|
||||
interface AdUnitProps {
|
||||
/** AdSense ad slot ID from your AdSense dashboard. */
|
||||
slot: string;
|
||||
/** AdSense ad format. Defaults to "auto" for responsive display ads. */
|
||||
format?: "auto" | "fluid" | "rectangle" | "vertical" | "horizontal";
|
||||
/** Optional layout (e.g. "in-article"). */
|
||||
layout?: string;
|
||||
/** Optional layout key (required for in-feed ads). */
|
||||
layoutKey?: string;
|
||||
/** Full-width responsive on mobile. Defaults to true. */
|
||||
responsive?: boolean;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a Google AdSense ad unit. Requires <AdSenseScript /> to be mounted
|
||||
* on the same page. Renders nothing if NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID
|
||||
* is unset or if `slot` is empty (so missing-slot env vars stay invisible).
|
||||
*/
|
||||
export function AdUnit({
|
||||
slot,
|
||||
format = "auto",
|
||||
layout,
|
||||
layoutKey,
|
||||
responsive = true,
|
||||
className,
|
||||
style,
|
||||
}: AdUnitProps) {
|
||||
const insRef = useRef<HTMLModElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!ADSENSE_CLIENT_ID || !slot) return;
|
||||
const el = insRef.current;
|
||||
if (!el) return;
|
||||
// Guard against duplicate pushes (React StrictMode dev double-invoke,
|
||||
// client-side navigation back to this page, or HMR remounts). AdSense
|
||||
// sets data-adsbygoogle-status="done" once it has filled a slot.
|
||||
if (el.getAttribute("data-adsbygoogle-status")) return;
|
||||
try {
|
||||
(window.adsbygoogle = window.adsbygoogle || []).push({});
|
||||
} catch {
|
||||
// AdSense throws if pushed before the script has loaded or on
|
||||
// duplicate pushes. The script processes pending pushes when it
|
||||
// finishes loading, so we can safely swallow this.
|
||||
}
|
||||
}, [slot]);
|
||||
|
||||
if (!ADSENSE_CLIENT_ID || !slot) return null;
|
||||
|
||||
return (
|
||||
<ins
|
||||
ref={insRef}
|
||||
className={cn("adsbygoogle block", className)}
|
||||
style={{ display: "block", ...style }}
|
||||
data-ad-client={ADSENSE_CLIENT_ID}
|
||||
data-ad-slot={slot}
|
||||
data-ad-format={format}
|
||||
data-ad-layout={layout}
|
||||
data-ad-layout-key={layoutKey}
|
||||
data-full-width-responsive={responsive ? "true" : "false"}
|
||||
/>
|
||||
);
|
||||
}
|
||||
13
surfsense_web/components/ads/adsense-config.ts
Normal file
13
surfsense_web/components/ads/adsense-config.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Centralized AdSense ad slot IDs.
|
||||
*
|
||||
* After creating ad units in your AdSense dashboard (Ads → By ad unit), paste
|
||||
* the numeric slot IDs into the corresponding env vars below. Empty slot IDs
|
||||
* render nothing (see <AdUnit />), so partial rollout is safe.
|
||||
*/
|
||||
export const ADSENSE_SLOTS = {
|
||||
/** /free hub: between the model table and "Why SurfSense" section. */
|
||||
freeHubInContent: process.env.NEXT_PUBLIC_GOOGLE_ADSENSE_SLOT_FREE_HUB_IN_CONTENT ?? "",
|
||||
/** /free hub: between the CTA and the FAQ section. */
|
||||
freeHubBeforeFaq: process.env.NEXT_PUBLIC_GOOGLE_ADSENSE_SLOT_FREE_HUB_BEFORE_FAQ ?? "",
|
||||
} as const;
|
||||
27
surfsense_web/components/ads/adsense-script.tsx
Normal file
27
surfsense_web/components/ads/adsense-script.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"use client";
|
||||
|
||||
import Script from "next/script";
|
||||
|
||||
const ADSENSE_CLIENT_ID = process.env.NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID;
|
||||
|
||||
/**
|
||||
* Loads the Google AdSense library (adsbygoogle.js). Mount this once on any
|
||||
* route that renders <AdUnit /> instances. Scoped per-route (not in the root
|
||||
* layout) so the third-party script is not shipped on unrelated pages.
|
||||
*
|
||||
* Renders nothing if NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID is unset, so dev and
|
||||
* preview deployments without the env var stay ad-free.
|
||||
*/
|
||||
export function AdSenseScript() {
|
||||
if (!ADSENSE_CLIENT_ID) return null;
|
||||
|
||||
return (
|
||||
<Script
|
||||
id="adsbygoogle-init"
|
||||
async
|
||||
strategy="afterInteractive"
|
||||
src={`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${ADSENSE_CLIENT_ID}`}
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -19,6 +19,11 @@
|
|||
"enabled": false,
|
||||
"status": "maintenance",
|
||||
"statusMessage": "Rework in progress."
|
||||
},
|
||||
"COMPOSIO_GOOGLE_DRIVE_CONNECTOR": {
|
||||
"enabled": false,
|
||||
"status": "maintenance",
|
||||
"statusMessage": "Temporarily unavailable due to an upstream Composio bug (ComposioHQ/composio#3471) that returns malformed presigned URLs for Drive file downloads. Use the native Google Drive connector in the meantime."
|
||||
}
|
||||
},
|
||||
"globalSettings": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "surfsense_web",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.25",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.26.0",
|
||||
"description": "SurfSense Frontend",
|
||||
|
|
|
|||
1
surfsense_web/public/ads.txt
Normal file
1
surfsense_web/public/ads.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
google.com, pub-4479898201883964, DIRECT, f08c47fec0942fa0
|
||||
Loading…
Add table
Add a link
Reference in a new issue