Repository navigation
feat: measure Schaffa usage and catch errors with self-hosted Umami and GlitchTip - #14
Conversation
Powered by human calories and mass GPU cycles.
Powered by human calories and mass GPU cycles.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Powered by human calories and mass GPU cycles.
Powered by human calories and mass GPU cycles.
|
Note 🤖 Claude Opus 5.5 responding on behalf of beastyrabbit @codex review The new head fixes the CI audit failure with a scoped |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6c1c6cd14f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Powered by human calories and mass GPU cycles.
Powered by human calories and mass GPU cycles.
|
Note 🤖 Claude Opus 5.5 responding on behalf of beastyrabbit @codex review New head 8375037 adds one privacy-text change: the API documentation at |
|
Note 🤖 Claude Opus 5.5 responding on behalf of beastyrabbit @codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8375037c40
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Powered by human calories and mass GPU cycles.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 28f559040b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Powered by human calories and mass GPU cycles.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f44b411ce3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Powered by human calories and mass GPU cycles.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 306824a856
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Powered by human calories and mass GPU cycles.
Powered by human calories and mass GPU cycles.
|
Note 🤖 Claude Opus 5.5 responding on behalf of beastyrabbit @codex review New head 2212667 removes the duplicated browser scrubber, which pushed SonarQube new-code duplication to 3.6%. Server and browser now share one implementation ( |
|
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |

0 New Issues
0 Fixed Issues
0 Accepted Issues
No data about coverage (0.00% Estimated after merge)
Note
🤖 Claude Opus 5.5 responding on behalf of beastyrabbit
Until now Schaffa had no idea how its landing page, account flow, or published content was used, and server or browser errors only showed up if someone happened to read the container logs. This PR connects Schaffa to the homelab's self-hosted Umami (analytics) and GlitchTip (error tracking). Analytics only run after a visitor opts in through a new bilingual cookie banner.
What changes for visitors
/skills, account and sign-in, and the Impressum and privacy pages. It is self-hostedvanilla-cookieconsentv3 with no CDN, and follows<html lang>. The two categories are necessary and analytics, and "Analyse akzeptieren" / "Nur notwendige" carry equal weight. A Cookie-Einstellungen / Cookie settings link in the shared legal footer reopens it at any time. Before a choice nothing is stored. After a choice onlycc_cookieholds the decision, for six months. Withdrawing consent reloads the page with a GET, so a token form is never resubmitted.data-performance), outbound links, and custom events (sign-in start, CTA clicks, quickstart and skill-install copies, token copies). It also records session replay and heatmaps with strict masking: every input, the account workspace and token reveals are blocked. Replay never loads on/account*, on pages that show a secret, or on URLs with a query or hash. Search params, hashes, titles and referrers are stripped before sending. There is noidentify./admin) gets GlitchTip only: no banner, no Umami.cc_cookiewhile keeping "without sign-in and without a banner choice nothing is stored" true.Published content: counted on the server, never instrumented
Pages, files, guides and presentations under
/p,/fand/gbelong to the people who upload them. Schaffa promises byte-identical HTML under strict, partly sandboxed CSPs. Injecting a tracker or banner there would break that promise and track readers of third-party content. So nothing is injected, and replay and heatmaps never run on it.Views are counted server-side instead. After a successful
GET, Schaffa sends a fire-and-forget Umami eventcontent-viewwith the public path and kind. It forwards no visitor IP, User-Agent, referrer or title, and stores nothing on the device, so no consent is needed (Art. 6(1)(f)). Obvious bots are skipped. Guide.json/.mdexports and the interactive-page warning screen are not counted. The transport has a 1.5 s timeout, at most 8 requests in flight, no retries, and it drains response bodies, so a slow Umami can never delay serving. The same transport records API outcomes without personal data: content published, deleted or rejected by a scan, uploads rejected by quota, lockdown or rate limit, signup/login success or failure, and tokens created or revoked.GlitchTip
@sentry/nodeis preloaded throughnode --import, with the Fastify integration. Only unexpected 5xx errors are reported; deliberate operational states such asstorage_quotaorinteractive_disabledare not.console.erroris captured too.@sentry/browserbundle is lazy-loaded on idle. A tiny early queue catches errors and unhandled rejections that happen before it loads. User-facing error paths report unexpected exceptions.dataCollectiondisables every personal-data category. Headers, cookies, bodies, query strings,sfa_/sus_tokens, Bearer values, JWTs and e-mail addresses are removed before sending. No replay and no browser storage, so it runs as technically necessary.environmentandrelease=schaffa@<package version>. Traces are sampled at 10 %, with propagation same-origin only.POST /admin/api/telemetry-test, which throws "Schaffa GlitchTip test error — safe to ignore"..js.mapfiles from the image, so maps are never shipped or served.v*tag, a newsourcemapsjob runs afterpublish. It rebuildsdistdeterministically, checks that the debug IDs match the exact GHCR image it just pushed, and uploads tohttps://glitchtip.heerlab.comwith the Infisical-syncedGLITCHTIP_AUTH_TOKENsecret.Everything is off unless
UMAMI_URL/UMAMI_WEBSITE_IDand/orGLITCHTIP_DSNare set. That keeps local dev, tests and preview builds out, and self-hosted instances stay telemetry-free by default. PostHog was never used in the app, so there is nothing to remove.Environments and configuration
Schaffa has one deployment (production), so it gets one Umami website (
Schaffa) and one GlitchTip project (beasty-rabbit/schaffa). The public client config goes into the kub-homelab HelmRelease in a separate PR. The upload token lives only in Infisical and the synced repository secret.Verification
pnpm checkpasses: typecheck, Biome, 174 tests and gitleaks, with 6 platform-only skips.pnpm buildpasses.docker buildpasses. The image contains no*.js.mapand keeps the debug IDs. The container starts and/healthzreturns 200. A local rebuild produced the same debug IDs as the image.cc_cookieafter one;/p/HTML stays byte-identical with an unchanged CSP.TODOs and open points
/api/websites/<id>/recorder) is now public. Replay and heatmaps get verified live after the release.Somewhere a GPU is overheating so I don't have to think.