Skip to content

Commit 54b7e9d

Browse files
alexpricedevclaude
andauthored
Rewrite terms of service for GDPR and CCPA compliance (#54)
* test: update terms test assertions for comprehensive rewrite Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: rewrite terms of service for GDPR and CCPA compliance Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7e3213b commit 54b7e9d

2 files changed

Lines changed: 199 additions & 27 deletions

File tree

src/server/controllers/app/terms.test.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,47 @@ import { createBunRequest } from "../../test-utils/bun-request";
2222
import { terms } from "./terms";
2323

2424
describe("Terms Controller", () => {
25-
test("renders terms page", async () => {
25+
test("renders terms page with all required sections", async () => {
2626
const request = createBunRequest("http://localhost:3000/terms");
2727
const response = await terms.index(request);
2828

2929
expect(response.status).toBe(200);
3030
const html = await response.text();
3131
expect(html).toContain("TERMS OF SERVICE");
3232
expect(html).toContain("Acceptance of Terms");
33+
expect(html).toContain("Description of Service");
34+
expect(html).toContain("Your Account");
35+
expect(html).toContain("GitHub Integration");
3336
expect(html).toContain("Email Communications");
37+
expect(html).toContain("Data and Privacy");
38+
expect(html).toContain("Acceptable Use");
39+
expect(html).toContain("Intellectual Property");
40+
expect(html).toContain("Third-Party Services");
41+
expect(html).toContain("Service Availability");
42+
expect(html).toContain("Disclaimer of Warranties");
43+
expect(html).toContain("Limitation of Liability");
44+
expect(html).toContain("Indemnification");
45+
expect(html).toContain("Termination");
46+
expect(html).toContain("Governing Law");
47+
expect(html).toContain("Severability");
48+
expect(html).toContain("Changes to Terms");
49+
expect(html).toContain("Contact");
50+
});
51+
52+
test("references privacy policy", async () => {
53+
const request = createBunRequest("http://localhost:3000/terms");
54+
const response = await terms.index(request);
55+
const html = await response.text();
56+
57+
expect(html).toContain("/privacy");
58+
});
59+
60+
test("names third-party services", async () => {
61+
const request = createBunRequest("http://localhost:3000/terms");
62+
const response = await terms.index(request);
63+
const html = await response.text();
64+
65+
expect(html).toContain("GitHub");
66+
expect(html).toContain("Resend");
3467
});
3568
});

src/server/templates/terms.tsx

Lines changed: 165 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,68 +23,207 @@ export const Terms = ({ user, csrfToken }: TermsProps) => (
2323
<h2>1. Acceptance of Terms</h2>
2424
<p>
2525
By accessing or using re:starred ("the Service"), you agree to be
26-
bound by these Terms of Service. If you do not agree, do not use the
27-
Service.
26+
bound by these Terms of Service and our{" "}
27+
<a href="/privacy">Privacy Policy</a>. Together, they govern your use
28+
of the Service. If you do not agree, do not use the Service.
2829
</p>
30+
<p>You must be at least 16 years old to use the Service.</p>
2931

3032
<h2>2. Description of Service</h2>
3133
<p>
3234
re:starred is a free service that sends you a weekly email digest of
3335
forgotten GitHub starred repositories. The Service requires you to
34-
authenticate with your GitHub account and grant read access to your
35-
starred repositories.
36+
authenticate via GitHub OAuth and grant read-only access to your
37+
starred repositories. We analyse your stars to surface repos you may
38+
have forgotten about.
3639
</p>
3740

3841
<h2>3. Your Account</h2>
3942
<p>
40-
You are responsible for maintaining the security of your GitHub
41-
account. You must provide accurate information when signing up. You
42-
may delete your account at any time from your account settings page.
43+
Your account is created via GitHub OAuth. You are responsible for
44+
maintaining the security of your GitHub account and any activity that
45+
occurs through your re:starred account.
46+
</p>
47+
<p>
48+
You must provide accurate information when signing up. You may delete
49+
your account at any time from your account settings page. Account
50+
deletion is immediate and permanent — all your data is removed as
51+
described in our <a href="/privacy">Privacy Policy</a>.
52+
</p>
53+
54+
<h2>4. GitHub Integration</h2>
55+
<p>
56+
We request read-only access to your starred repositories via GitHub
57+
OAuth. Your GitHub access token is encrypted at rest using
58+
AES-256-GCM. We never modify your GitHub data — we only read your
59+
starred repositories to build your digest.
60+
</p>
61+
<p>
62+
GitHub's own Terms of Service apply to your GitHub account. Our access
63+
to your data is subject to the permissions you grant during
64+
authentication.
4365
</p>
4466

45-
<h2>4. Email Communications</h2>
67+
<h2>5. Email Communications</h2>
68+
<p>
69+
You explicitly opt in to receive digest emails during onboarding. Your
70+
weekly digest is sent on the day and time you choose.
71+
</p>
4672
<p>
47-
By consenting during onboarding, you agree to receive a weekly email
48-
digest. You can unsubscribe at any time via the unsubscribe link in
49-
any email or from your account settings. We will stop sending emails
50-
within 24 hours of your unsubscribe request.
73+
You can unsubscribe at any time via the unsubscribe link in any digest
74+
email or from your account settings. We will stop sending digest
75+
emails within 24 hours of your unsubscribe request.
76+
</p>
77+
<p>
78+
Service notifications (e.g. changes to these terms or our privacy
79+
policy) may be sent regardless of your digest preference.
5180
</p>
5281

53-
<h2>5. Acceptable Use</h2>
82+
<h2>6. Data and Privacy</h2>
5483
<p>
55-
You agree not to misuse the Service, including but not limited to:
56-
attempting to access other users' data, circumventing rate limits, or
57-
using the Service for any unlawful purpose.
84+
Full details about how we collect, use, and protect your data are in
85+
our <a href="/privacy">Privacy Policy</a>. In summary:
5886
</p>
87+
<ul>
88+
<li>
89+
We collect account data (from GitHub OAuth), your starred
90+
repositories, and consent records
91+
</li>
92+
<li>We do not sell your data</li>
93+
<li>
94+
Your rights under GDPR and CCPA are detailed in our{" "}
95+
<a href="/privacy">Privacy Policy</a>
96+
</li>
97+
</ul>
98+
99+
<h2>7. Acceptable Use</h2>
100+
<p>You agree not to:</p>
101+
<ul>
102+
<li>Access or attempt to access other users' data</li>
103+
<li>Circumvent rate limits or other technical restrictions</li>
104+
<li>Scrape, crawl, or automate access to the Service</li>
105+
<li>Impersonate another person or entity</li>
106+
<li>Use the Service for any unlawful purpose</li>
107+
<li>Attempt to reverse-engineer any part of the Service</li>
108+
<li>Interfere with the operation or availability of the Service</li>
109+
</ul>
59110

60-
<h2>6. Intellectual Property</h2>
111+
<h2>8. Intellectual Property</h2>
61112
<p>
62113
The Service and its original content, features, and functionality are
63114
owned by re:starred. Your GitHub data remains yours.
64115
</p>
116+
<p>
117+
You grant us only the limited licence needed to provide the Service —
118+
specifically, fetching and analysing your starred repositories to
119+
build your weekly digest.
120+
</p>
121+
122+
<h2>9. Third-Party Services</h2>
123+
<p>The Service relies on two third parties:</p>
124+
<ul>
125+
<li>
126+
<strong>GitHub</strong> (github.com) — authentication and star data.
127+
Their Terms of Service apply to your use of GitHub.
128+
</li>
129+
<li>
130+
<strong>Resend</strong> (resend.com) — email delivery. Their Terms
131+
of Service apply to their processing of your email address.
132+
</li>
133+
</ul>
134+
<p>
135+
We are not responsible for the availability of third-party services or
136+
changes to their terms.
137+
</p>
65138

66-
<h2>7. Disclaimer of Warranties</h2>
139+
<h2>10. Service Availability and Modifications</h2>
140+
<p>
141+
The Service is provided on a reasonable-efforts basis. We do not
142+
guarantee any specific uptime or availability.
143+
</p>
144+
<p>
145+
We may modify, suspend, or discontinue the Service at any time. Where
146+
possible, planned changes will be communicated via email in advance.
147+
</p>
148+
149+
<h2>11. Disclaimer of Warranties</h2>
150+
<p>
151+
The Service is provided "as is" and "as available" without warranties
152+
of any kind, whether express or implied. We do not guarantee the
153+
accuracy, reliability, or completeness of any content delivered
154+
through the Service.
155+
</p>
67156
<p>
68-
The Service is provided "as is" without warranties of any kind. We do
69-
not guarantee uninterrupted or error-free operation.
157+
We are not responsible for changes to the GitHub API that may affect
158+
the Service's functionality.
70159
</p>
71160

72-
<h2>8. Limitation of Liability</h2>
161+
<h2>12. Limitation of Liability</h2>
73162
<p>
74163
To the fullest extent permitted by law, re:starred shall not be liable
75164
for any indirect, incidental, special, or consequential damages
76165
arising from your use of the Service.
77166
</p>
167+
<p>
168+
Our total liability is capped at the amount you have paid to use the
169+
Service, which is zero — the Service is free.
170+
</p>
171+
<p>
172+
Nothing in these terms excludes liability for fraud or for death or
173+
personal injury caused by negligence.
174+
</p>
175+
176+
<h2>13. Indemnification</h2>
177+
<p>
178+
You agree to indemnify and hold re:starred harmless against any
179+
claims, damages, or expenses arising from your misuse of the Service
180+
or violation of these terms.
181+
</p>
78182

79-
<h2>9. Changes to Terms</h2>
183+
<h2>14. Termination</h2>
184+
<p>
185+
You can terminate your use of the Service at any time by deleting your
186+
account from your account settings. We may terminate or suspend your
187+
account if you violate these terms.
188+
</p>
189+
<p>
190+
On termination, all your data is deleted in accordance with our{" "}
191+
<a href="/privacy">Privacy Policy</a>.
192+
</p>
193+
<p>
194+
Sections that by their nature should survive termination will survive,
195+
including Limitation of Liability, Indemnification, and Governing Law.
196+
</p>
197+
198+
<h2>15. Governing Law and Disputes</h2>
199+
<p>
200+
These terms are governed by the laws of England and Wales. If a
201+
dispute arises, we encourage you to contact us first to seek informal
202+
resolution. If the dispute cannot be resolved informally, the courts
203+
of England and Wales shall have exclusive jurisdiction.
204+
</p>
205+
206+
<h2>16. Severability</h2>
207+
<p>
208+
If any provision of these terms is found to be invalid or
209+
unenforceable, the remaining provisions will continue in full force
210+
and effect.
211+
</p>
212+
213+
<h2>17. Changes to Terms</h2>
214+
<p>
215+
We may update these terms from time to time. For material changes, we
216+
will notify you by email. Continued use of the Service after
217+
notification constitutes acceptance of the updated terms.
218+
</p>
80219
<p>
81-
We may update these Terms from time to time. Continued use of the
82-
Service after changes constitutes acceptance of the new Terms.
220+
If you disagree with the changes, you should stop using the Service
221+
and delete your account.
83222
</p>
84223

85-
<h2>10. Contact</h2>
224+
<h2>18. Contact</h2>
86225
<p>
87-
Questions about these Terms? Open an issue on our{" "}
226+
Questions about these terms? Open an issue on our{" "}
88227
<a
89228
href="https://github.com/alexpricedev/restarred/issues"
90229
target="_blank"

0 commit comments

Comments
 (0)