Skip to content

Commit 909791c

Browse files
authored
Merge pull request #9 from pkgdiff-dev/gsd/quick-261019-privacy-analytics
Replace Google Analytics with Cloudflare Web Analytics and complete the privacy policy
2 parents ab6ddad + 431800a commit 909791c

13 files changed

Lines changed: 216 additions & 162 deletions

File tree

‎src/frontend/nginx-security-headers.conf‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ add_header X-Frame-Options "DENY" always;
55
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
66
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()" always;
77
# Script 'unsafe-inline' is needed by the inline theme script and Angular's inline loaders.
8-
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://static.cloudflareinsights.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' https://cloudflareinsights.com https://www.googletagmanager.com https://www.google-analytics.com https://*.google-analytics.com https://*.analytics.google.com; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;
8+
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' https://cloudflareinsights.com; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;

‎src/frontend/src/app/app.ts‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, Component, afterNextRender, effect, inject, un
22
import { RouterOutlet } from '@angular/router';
33
import { ToastComponent } from './shared/components/toast/toast';
44
import { ConfirmModalComponent } from './shared/components/confirm-modal/confirm-modal.component';
5-
import { AnalyticsService } from './core/services/analytics.service';
65
import { RouteLoaderComponent } from './shared/components/route-loader/route-loader';
76
import { PackageService } from './core/services/package.service';
87
import { SignalrService } from './core/services/signalr.service';
@@ -22,8 +21,6 @@ export class App {
2221
private liveUpdates = inject(LiveUpdatesService);
2322

2423
constructor() {
25-
inject(AnalyticsService).init();
26-
2724
afterNextRender(() => {
2825
this.loadLiveUpdates();
2926
this.signalr.startConnection().catch(() => undefined);

‎src/frontend/src/app/core/services/analytics.service.ts‎

Lines changed: 0 additions & 56 deletions
This file was deleted.

‎src/frontend/src/app/features/cookies/cookies.html‎

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ <h1 class="text-3xl font-bold tracking-tight text-[#111418] dark:text-white mb-2
1111
<section>
1212
<h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">1. Overview</h2>
1313
<p>
14-
{{ appName }} uses browser local storage to enhance your user experience. We do not use
15-
third-party cookies or tracking technologies. This policy explains what we store locally
16-
in your browser and why.
14+
{{ appName }} sets no cookies and uses no tracking technologies. It keeps a few preferences in
15+
your browser's local storage so the site remembers them. This policy lists exactly what is
16+
stored and why.
1717
</p>
1818
</section>
1919

2020
<section>
2121
<h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">2. What We Store</h2>
2222
<p class="mb-4">
23-
All data is stored locally in your browser using localStorage. Nothing is sent to
24-
external servers except when explicitly requested by your actions (e.g., package searches).
23+
These entries live only in your browser (localStorage, or sessionStorage where noted). They are
24+
never sent to our servers or to anyone else.
2525
</p>
2626

2727
<div class="overflow-x-auto border border-gray-200 dark:border-gray-700 rounded-lg">
@@ -47,6 +47,12 @@ <h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">2. What We
4747
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Essential</td>
4848
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Token lifetime</td>
4949
</tr>
50+
<tr>
51+
<td class="py-3 px-4 font-mono text-xs">lastSelectedRegistry</td>
52+
<td class="py-3 px-4">The registry you last selected on the home page</td>
53+
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Functional</td>
54+
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Persistent</td>
55+
</tr>
5056
<tr>
5157
<td class="py-3 px-4 font-mono text-xs">recentRegistries</td>
5258
<td class="py-3 px-4">Recent registry selections for quick access</td>
@@ -55,25 +61,37 @@ <h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">2. What We
5561
</tr>
5662
<tr>
5763
<td class="py-3 px-4 font-mono text-xs">pkgdiff-cookie-consent</td>
58-
<td class="py-3 px-4">Your cookie consent choice</td>
64+
<td class="py-3 px-4">Remembers that you dismissed the privacy notice</td>
5965
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Essential</td>
6066
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Persistent</td>
6167
</tr>
68+
<tr>
69+
<td class="py-3 px-4 font-mono text-xs">pkgdiff-linkedin-oauth-state</td>
70+
<td class="py-3 px-4">Protects the LinkedIn sign-in flow (admin only, sessionStorage)</td>
71+
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Essential</td>
72+
<td class="py-3 px-4 text-gray-500 dark:text-gray-400">Until the flow completes</td>
73+
</tr>
6274
</tbody>
6375
</table>
6476
</div>
6577

6678
<p class="mt-4 text-xs text-gray-500 dark:text-gray-500">
67-
All items marked as "Functional" or "Essential" are necessary for the Service to operate
68-
correctly. We do not use analytics, advertising, or tracking cookies.
79+
"Essential" entries are needed for the Service to work; "Functional" entries only remember your
80+
choices. None of them identify or track you, so they need no consent.
6981
</p>
7082
</section>
7183

7284
<section>
73-
<h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">3. Third-Party Cookies</h2>
85+
<h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">3. Analytics and Third Parties</h2>
86+
<p class="mb-3">
87+
We count visits with Cloudflare Web Analytics, which sets no cookies, stores nothing in your
88+
browser and does not track you across sites or visits.
89+
</p>
7490
<p>
75-
{{ appName }} does not integrate with any third-party services that set cookies or track
76-
users. All functionality is self-contained within our application.
91+
No third-party service sets cookies on {{ appName }}. Your browser does contact Google Fonts and
92+
GitHub to load fonts and images; see the
93+
<a href="/privacy" title="Privacy Policy" class="text-primary hover:underline">Privacy Policy</a>
94+
for what they receive.
7795
</p>
7896
</section>
7997

@@ -88,17 +106,16 @@ <h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">4. Managin
88106
<li><strong>Safari:</strong> Preferences → Privacy → Manage Website Data → pkgdiff.dev → Remove</li>
89107
</ul>
90108
<p class="mt-3">
91-
Clearing local storage will reset your theme preference and consent choice. Essential
92-
functional data (like auth tokens) will also be removed, logging you out if applicable.
109+
Clearing it resets your theme and registry choices and shows the privacy notice again.
110+
Administrators are also signed out.
93111
</p>
94112
</section>
95113

96114
<section>
97115
<h2 class="text-lg font-semibold text-[#111418] dark:text-white mb-3">5. Changes to This Policy</h2>
98116
<p>
99117
We may update this Cookie Policy from time to time. Changes will be posted on this page
100-
with an updated "Last updated" date. Continued use of {{ appName }} after changes
101-
constitutes acceptance of the updated policy.
118+
with an updated "Last updated" date.
102119
</p>
103120
</section>
104121

‎src/frontend/src/app/features/cookies/cookies.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export class CookiesComponent implements OnInit {
1212
private seo = inject(SeoService);
1313
appName = APP_CONFIG.name;
1414
contactEmail = APP_CONFIG.contact.email;
15-
lastUpdated = 'February 9, 2026';
15+
lastUpdated = 'October 19, 2026';
1616

1717
ngOnInit() {
1818
this.seo.updateMeta({

0 commit comments

Comments
 (0)