Skip to content

fix(dx): make analytics setup safe to repeat - #11

Merged
WillieCubed merged 2 commits into
mainfrom
fix/idempotent-csp-write
Sep 24, 2026
Merged

WillieCubed merged 2 commits into
mainfrom
fix/idempotent-csp-write

Conversation

@WillieCubed

Copy link
Copy Markdown
Contributor

TL;DR

Running lvbt-analytics csp --write again no longer rewrites a headers file that already has everything it needs, and it says whether it changed anything. A new how-to sets up the analytics production from nothing, with exact values, and can be followed again without changing anything that is already done.

Overview of Changes

Why

The owner asked that every LVBT bootstrap and setup step be idempotent, and that setup guidance give exact values for someone starting from a brand-new account. The CSP helper was the only setup-style command in this repository, and it wrote the file on every run, changing its timestamp and producing noisy diffs. Nothing documented how to set up the collector and the weekly report the first time; only the rotation runbooks existed.

What changed

The CSP helper now compares the merged header with the file's current contents and writes only when they differ, and prints whether it changed the file. A new test runs it twice and checks that the second run leaves the file's content and timestamp alone.

The new how-to, "Set up the analytics production", covers the GitHub production environment; the account ID in both places the workflows read it (the environment for the Deploy workflow, the repository for the weekly report); a deploy token and a report token, both created as account API tokens in the LVBT account ("Las Vegans for Better Transit") so they outlive the person who made them, with exactly the permissions each workflow uses; the collector's events.lasvegasfortransit.org custom domain, which a deploy creates; LVBT_EVENTS_SECRET, generated and stored in one command so it is never shown; and the LVBT_ANALYTICS_LIVE switch for the weekly report. Every section starts by checking whether it is already done. Each token is pasted into a waiting gh secret set prompt, so nothing sits on the clipboard while something else is copied. The guide says in one sentence that a platform.json will replace most of it once the repository moves to repository tooling 0.4.2 or later.

Testing

pnpm check passes. The report token's "Account Analytics: Read" permission comes from Cloudflare's Analytics Engine SQL API documentation, and the custom-domain note (an existing CNAME blocks it) from its Workers custom domains documentation.

Follow-ups

  • Move this repository to repository tooling 0.4.2 or later and declare its production in a platform.json, so pnpm bootstrap --production checks and sets these up.

🤖 Generated with Claude Code

WillieCubed and others added 2 commits September 23, 2026 18:33
`lvbt-analytics csp --write <file>` rewrote the headers file on
every run, even when the Content-Security-Policy header already
had everything the merge would add. That touched the file's mtime
and produced spurious diffs for a command meant to be safe to
re-run. Compare the merged header against the current contents
first and only write when they differ; either way the command now
prints whether it changed the file.

Add a vitest test that runs it twice: the first run updates the
header and reports the change, the second leaves the file's
content and mtime untouched and reports no change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A new how-to walks a first-time maintainer through everything the
repository needs in production: the GitHub environment, the account
ID in both places the workflows read it, an account-owned deploy
token and a read-only report token with exact permissions, the
collector's custom domain, its LVBT_EVENTS_SECRET made without ever
showing it, and the LVBT_ANALYTICS_LIVE switch for the weekly report.
Every step checks first, so following it again changes nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@WillieCubed
WillieCubed merged commit cfc38ad into main Sep 24, 2026
1 check passed
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