Skip to content

chore(analytics): keep anonymous usage aggregates, drop the visitor trail - #240

Merged
harlan-zw merged 9 commits into
mainfrom
chore/remove-telemetry
Sep 22, 2026
Merged

harlan-zw merged 9 commits into
mainfrom
chore/remove-telemetry

Conversation

@harlan-zw

@harlan-zw harlan-zw commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

❓ Type of change

  • 🧹 Chore

📚 Description

Privacy is a skilld.dev tenet, and several paths sent visitor behaviour to third parties or stored it per reader. This PR keeps the data the site needs to grow and drops the part that names a person.

Kept, as anonymous aggregates.

  • Command copies and CLI runs go to Cloudflare Analytics Engine. A data point holds surface, grammar (run or install), kind, Skill, and two-letter country. It holds no IP address, no cookie, and no account id. The CLI may still send a userId; the endpoint drops it, so the sampling index is the Skill and an account cannot be followed across runs. Blob order is fixed in shared/analytics.ts, because reordering would rewrite every saved query.
  • The copy body is strict. A field the endpoint never asked for is a 400, not a value that reaches the data point by accident.
  • Cloudflare Web Analytics (RUM) stays. Its same-origin beacon proxy forwards only a content type, so no visitor IP or cookie leaves the Worker, and page and referrer URLs in the beacon body lose their query strings.
  • Sentry stays, hardened. Browser envelopes go through a same-origin Worker route (/api/monitoring) that forwards only to the configured DSN, so sentry.io never sees a visitor IP. The browser SDK sends errors only: no tracing, no session tracking, no replay. Client and server strip query strings, cookies, headers, bodies, and user.ip_address, and drop console and UI click breadcrumbs.
  • Traces stay on at 1% for request timing. Invocation logs are off: they record a full request URL and client metadata for every request, which the wide events already cover without the visitor detail.

Dropped.

  • install_events in D1. It kept one timestamped row per visitor action. The count it fed now comes from Analytics Engine.
  • weekly_click_events. Every row named a reader. feat(identity): count email clicks as daily aggregates #243 brings the digest click number back as a daily counter with no reader id.
  • The Iconify API fallback, so a visitor's browser never calls api.iconify.design.
  • The Algolia npm-search client, which called Algolia from the browser on a surface the site no longer ships.
flowchart LR
  V["Visitor copies a command"] -->|"POST /api/events/install"| W["Worker"]
  C["skilld CLI run"] -->|"POST /api/events/cli"| W
  W -->|"surface, mode, kind, slug, country"| AE["Analytics Engine<br/>skilld_web_v1 / skilld_cli_v1"]
  W -.->|"userId dropped"| X["✗"]
  AE -->|"SQL API"| K["Daily check-in Pulse<br/>run and install copies"]
  V -->|"beacon"| P["Same-origin RUM proxy<br/>query strings stripped"] --> CWA["Cloudflare Web Analytics"]
  B["Browser error"] --> M["/api/monitoring<br/>PII scrubbed"] --> S["Sentry"]
Loading

📝 Migration

  • 0119_drop_click_and_install_events.sql drops weekly_click_events and install_events. It cannot be recovered.
  • The skilld_web_v1 Analytics Engine dataset is created on first write. No dashboard step.
  • In the Sentry skilld project, enable "Prevent Storing of IP Addresses" and server-side data scrubbing.

Notes:

  • sendDefaultPii is deprecated in @sentry/nuxt 10.73 and ignored when dataCollection is set. dataCollection.userInfo: false already makes the browser client send infer_ip: never, so the deprecated flag is not set.
  • The admin weekly report no longer shows copy counts, because Analytics Engine is not readable from D1. The daily check-in reads them over the SQL API instead.
  • newly_broken_repos_impacted no longer counts an install event as impact, because the table is gone. A star, subscription, collection, or Skill still counts.

@harlan-zw harlan-zw mentioned this pull request Sep 16, 2026
2 tasks done
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. labels Sep 16, 2026
@harlan-github-agent

harlan-github-agent Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

🤖 MERGED

Harlan Agent Kit posted this automated review. It is not Harlan's personal review or approval. AI open source policy. Last updated: 2026-09-22 08:14 UTC.

GitHub merged this pull request.

  • Copy totals silently undercount once more than 50 slug groups exist in a day. Next: Add a second untruncated totals query (GROUP BY mode, no LIMIT) for total/run/install, and keep the LIMIT 50 query only for the ranked top list.
  • The 96-byte index cap is enforced in characters, not bytes, so astral-character slugs still get the whole data point rejected. Next: Cut the encoded bytes to 96 (TextEncoder, subarray, TextDecoder) instead of slicing the string by characters.

Opened pull request #274: #274.

@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. labels Sep 16, 2026
@harlan-zw harlan-zw changed the title chore: remove telemetry for visitor privacy chore: remove analytics and harden Sentry for privacy Sep 16, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. harlan-agent-blocked The automated Review found a material defect in this head commit. and removed harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-blocked The automated Review found a material defect in this head commit. labels Sep 16, 2026
@harlan-zw
harlan-zw added this pull request to stack #245 September 16, 2026 15:09
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. labels Sep 16, 2026
harlan-zw added a commit that referenced this pull request Sep 16, 2026
The page described the site after #240 and #241 only. #242, #243, #244,
and #246 change CLI token labels, email click counts, like visibility,
repository indexing, and image loading, and D1 recovery keeps deleted rows
for up to 30 days.
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. labels Sep 16, 2026
@harlan-zw harlan-zw changed the title chore: remove analytics and harden Sentry for privacy chore: remove event tracking and harden Sentry for privacy Sep 16, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. labels Sep 16, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-pending The automated Review is waiting on a gate for this head commit. harlan-agent-ready The automated Review passed every gate on this head commit. and removed harlan-agent-ready The automated Review passed every gate on this head commit. harlan-agent-pending The automated Review is waiting on a gate for this head commit. labels Sep 22, 2026
@harlan-zw
harlan-zw force-pushed the chore/remove-telemetry branch from 439bc7b to d5c5665 Compare September 22, 2026 02:23
@harlan-zw harlan-zw changed the title chore: remove event tracking and harden Sentry for privacy chore(analytics): keep anonymous usage aggregates, drop the visitor trail Sep 22, 2026
harlan-zw added a commit that referenced this pull request Sep 22, 2026
Loop 2 is judged on digest click-throughs, and #240 removed the only measure along with the per-reader click history. Links now carry the campaign, issue, placement, and path, and a daily counter stores nothing that names a reader.
harlan-zw added a commit that referenced this pull request Sep 22, 2026
skilld.dev had no page that says what it stores, why, and for how long.
The page describes the site after #240 and #241 and explains how to
delete an account.
harlan-zw added a commit that referenced this pull request Sep 22, 2026
The page described the site after #240 and #241 only. #242, #243, #244,
and #246 change CLI token labels, email click counts, like visibility,
repository indexing, and image loading, and D1 recovery keeps deleted rows
for up to 30 days.
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. and removed harlan-agent-ready The automated Review passed every gate on this head commit. labels Sep 22, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-blocked The automated Review found a material defect in this head commit. harlan-agent-running An Agent holds a Task on this issue or pull request right now. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-blocked The automated Review found a material defect in this head commit. labels Sep 22, 2026
harlan-zw and others added 9 commits September 22, 2026 17:02
Privacy is a core skilld.dev tenet. Sentry, the Cloudflare Web Analytics
beacon, CLI and install copy events, and weekly email click tracking all
sent or stored visitor behaviour that the site does not need. Wide events
in Workers Logs remain the operational record.
Install copy events stopped being written, so the table and the daily summary counts that read it only reported zeros.
The owner wants Sentry kept and hardened for privacy instead of removed. This restores it as on main; the next commit hardens it.
Sentry stays, but it must not learn who a visitor is. Browser envelopes
now go through a same-origin Worker route, so sentry.io never sees a
visitor IP. Browser tracing and session tracking are off. Every event,
transaction, and breadcrumb loses query strings, cookies, bodies, and the
user IP before it leaves the client or the Worker.
The owner wants RUM kept. The beacon proxy already forwards only a content
type, so no visitor IP or cookie leaves the Worker. Page and referrer URLs
in the beacon body now lose their query strings before forwarding.
skilld.dev is early, so it needs to know which Skills people run and where
they find them. Removing copy and CLI events took that away with the personal
data. Both come back as anonymous aggregates.

Copies and CLI runs now write to Cloudflare Analytics Engine, which holds
surface, grammar, kind, Skill, and country for 90 days and nothing that names
a person. The `install_events` D1 table stays dropped: it kept one timestamped
row per visitor action. The CLI may still send a `userId`, and the endpoint
drops it, so the sampling index is the Skill and never the account.

The copy body is strict, so a field the endpoint never asked for is a 400.
The daily check-in reads copies over the Analytics Engine SQL API, split as
run and install. Traces go back on at 1% for request timing; invocation logs
stay off, because they record a full URL and client metadata per request.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant