Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions HANDOFF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Handoff from workstream B (privacy suite)

Changes I wanted to make in files another workstream owns. Not made.

## `docs/terms.md` — workstream A

1. **Incorporate the DPA by reference.** `docs/dpa.md` is written to apply automatically
("accept-by-reference from the terms"), but nothing in the terms currently says so, which
means it does not actually apply. Add to §5 (*Your content, and who owns it*) or §1:

> Where the files you sync contain personal data belonging to other people, you are the
> controller of that data and we are your processor. The [Data Processing
> Agreement](/docs/dpa.html) sets out the terms on which we process it and forms part of
> these terms. You do not need to sign or request it.

2. **Point at the new privacy pages.** §6 and the closing links reference
`docs/privacy.md` only. Add `/docs/privacy-policy.html`, `/docs/cookies.html` and
`/docs/subprocessors.html`.

3. **Age.** `docs/privacy-policy.md` §11 states minimum age 16 and cites terms §3. Keep the
two in step if §3 changes.

## `docs/privacy.md` — a claim I could not verify

Under *How long it is kept*: "Older changes are deleted by a scheduled job."

**There is no such job in this repository.** I grepped the source tree for a cron entry, a
Vercel cron config, a scheduled function and a `DELETE FROM file_versions`, and queried
`cron.job` on the production Supabase database — the `pg_cron` schema does not exist there.
What the code does enforce is the *serving* side: `listChanges` refuses a cursor pointing at
history older than what survives, and reports `retentionDays: 7`
(`apps/service/src/store.ts:458`).

I did not edit `privacy.md` beyond the cross-links my brief allows. I documented the gap
honestly in `docs/privacy-policy.md` §8 and flagged it with a `<!-- LAWYER -->` comment.
Someone should either land the sweep as a scheduled job with a test, or soften the sentence
in `privacy.md`.

## `apps/docs-site/scripts/generate-docs.mjs` — `stripHtmlComments`, shared with workstream C

Workstream C's edits arrived in this worktree mid-run (Crosscode was syncing the two
checkouts). I removed C's page registrations from my branch so it builds standalone, but I
**kept** C's `stripHtmlComments()` helper — without it the `<!-- LAWYER: ... -->` notes in
my four pages render as escaped visible text on the published site, because the renderer
runs with `html: false`. If C's branch merges first, this is the same function twice and
the merge is a no-op. If mine merges first, C's is redundant. Either way, keep exactly one.

## `docs/support.md` — whoever owns it

It still contains the literal placeholder `[SUPPORT EMAIL]` in three table rows. The real
address is `support@getcrosscode.dev`.

## `apps/docs-site/src/analytics.js` — workstream E

`docs/cookies.md` is written for the post-removal state of `crosscode_distinct_id`, as my
brief instructs. If that removal does not land, the cookies page is wrong. Its "Before this
takes effect" checklist says so.

Same file: `docs/observability.md` notes the module is not included on
`apps/docs-site/auth/signup.html`, so `sign_up_completed` never fires. Not mine to fix, but
it affects what the analytics section of the privacy policy describes.
4 changes: 4 additions & 0 deletions apps/docs-site/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ dist
/docs/support.html
/docs/terms.html
/docs/refund-policy.html
/docs/privacy-policy.html
/docs/cookies.html
/docs/subprocessors.html
/docs/dpa.html
/public/docs/
/public/llms.txt
/public/llms-full.txt
4 changes: 4 additions & 0 deletions apps/docs-site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,10 @@ <h2>Docs</h2>
<h2>Trust</h2>
<a href="/docs/safety.html">Safety model</a>
<a href="/docs/privacy.html">Privacy</a>
<a href="/docs/privacy-policy.html">Privacy Policy</a>
<a href="/docs/cookies.html">Cookies</a>
<a href="/docs/subprocessors.html">Subprocessors</a>
<a href="/docs/dpa.html">Data Processing Agreement</a>
<a href="/docs/limitations.html">Limitations</a>
<a href="/docs/terms.html">Terms</a>
<a href="/docs/support.html">Support</a>
Expand Down
57 changes: 54 additions & 3 deletions apps/docs-site/scripts/generate-docs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ const NAV_GROUPS = [
label: "Support & legal",
links: [
{ href: "/docs/support.html", label: "Support", key: "support" },
{ href: "/docs/terms.html", label: "Terms of Service", key: "terms" }
{ href: "/docs/terms.html", label: "Terms of Service", key: "terms" },
{ href: "/docs/privacy-policy.html", label: "Privacy Policy", key: "privacy-policy" },
{ href: "/docs/cookies.html", label: "Cookies", key: "cookies" },
{ href: "/docs/subprocessors.html", label: "Subprocessors", key: "subprocessors" },
{ href: "/docs/dpa.html", label: "Data Processing Agreement", key: "dpa" }
]
}
];
Expand Down Expand Up @@ -159,6 +163,38 @@ const GENERATED_PAGES = [
title: "Terms of Service",
mdFile: "terms.md",
htmlOut: "terms.html",
nextHref: "/docs/privacy-policy.html",
nextLabel: "Privacy Policy"
},
{
key: "privacy-policy",
title: "Privacy Policy",
mdFile: "privacy-policy.md",
htmlOut: "privacy-policy.html",
nextHref: "/docs/cookies.html",
nextLabel: "Cookies and local storage"
},
{
key: "cookies",
title: "Cookies and local storage",
mdFile: "cookies.md",
htmlOut: "cookies.html",
nextHref: "/docs/subprocessors.html",
nextLabel: "Subprocessors"
},
{
key: "subprocessors",
title: "Subprocessors",
mdFile: "subprocessors.md",
htmlOut: "subprocessors.html",
nextHref: "/docs/dpa.html",
nextLabel: "Data Processing Agreement"
},
{
key: "dpa",
title: "Data Processing Agreement",
mdFile: "dpa.md",
htmlOut: "dpa.html",
nextHref: "/docs/index.html",
nextLabel: "Docs overview"
}
Expand Down Expand Up @@ -241,19 +277,34 @@ ${bodyHtml}
<footer class="site-footer">
<p>Crosscode: local-first Git coordination.</p>
<p><a href="/">Home</a> &middot; <a href="${GITHUB_REPO}" rel="noopener">View on GitHub</a></p>
<p>
<a href="/docs/privacy.html">Privacy</a> &middot;
<a href="/docs/privacy-policy.html">Privacy Policy</a> &middot;
<a href="/docs/cookies.html">Cookies</a> &middot;
<a href="/docs/subprocessors.html">Subprocessors</a> &middot;
<a href="/docs/dpa.html">DPA</a>
</p>
</footer>
</body>
</html>
`;
}

// Legal docs carry `<!-- LAWYER: ... -->` notes flagging choices that need review. The
// renderer runs with html:false, so a comment left in would be escaped and printed on the
// page as visible text. Strip them from everything published; the repo's docs/*.md keeps
// them, which is where they are meant to be read.
function stripHtmlComments(markdown) {
return markdown.replace(/^[ \t]*<!--[\s\S]*?-->[ \t]*\r?\n?/gm, "");
}

function generateDocPages() {
mkdirSync(siteDocsDir, { recursive: true });
mkdirSync(publicDocsDir, { recursive: true });

for (const p of GENERATED_PAGES) {
const mdPath = path.join(rootDocsDir, p.mdFile);
const mdContent = readFileSync(mdPath, "utf8");
const mdContent = stripHtmlComments(readFileSync(mdPath, "utf8"));
const bodyHtml = md.render(mdContent);
const mdOutName = p.mdOutName ?? p.mdFile;
const mdHref = `/docs/${mdOutName}`;
Expand Down Expand Up @@ -360,7 +411,7 @@ function generateLlmsFullTxt() {
];

for (const s of sections) {
const content = readFileSync(path.join(rootDocsDir, s.file), "utf8");
const content = stripHtmlComments(readFileSync(path.join(rootDocsDir, s.file), "utf8"));
parts.push("---", "", `<!-- source: docs/${s.file} -->`, "", content.trimEnd(), "");
}

Expand Down
4 changes: 4 additions & 0 deletions apps/docs-site/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export default defineConfig({
limitations: resolve(root, "docs/limitations.html"),
support: resolve(root, "docs/support.html"),
terms: resolve(root, "docs/terms.html"),
privacyPolicy: resolve(root, "docs/privacy-policy.html"),
cookies: resolve(root, "docs/cookies.html"),
subprocessors: resolve(root, "docs/subprocessors.html"),
dpa: resolve(root, "docs/dpa.html"),
signin: resolve(root, "auth/signin.html"),
signup: resolve(root, "auth/signup.html"),
passwordReset: resolve(root, "auth/reset.html"),
Expand Down
Loading
Loading