maniator / maniator/verticopolis

[Feature]: [P3] Desktop analytics is structurally dark, so an itch.io demo and Steam both ship unmeasured

Open
#781 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
5
Forks
1
PR merge metrics
No merged PRs in 30d

Description

Raised while scoping a possible itch.io demo. Verified against main, not inferred.

The shape

The plan for itch.io is to distribute the SAME Electron app we ship to Steam, not to embed the web build. That makes both channels one story: desktop analytics. A packaged build loads from app://host (a privileged custom scheme registered in the shell's main.ts), so it is a static bundle with no server behind it.

Three things stand between that build and a reported event:

  1. The wrapper gate, deliberate and first. telemetryHostAllowed (src/telemetry.ts:57) returns false for every wrapped mode before it reads a hostname, so nothing is emitted whatever origin the shell serves from. This is by design: enabling desktop analytics is meant to be a reviewed change in this repo, never a wrapper-side hostname choice. Any fix has to open this gate deliberately, not route around it.
  2. The transport assumes a same-origin server. The client posts to the relative path /api/ingest (src/analyticsRelay.ts:29), a function in the same Vercel deployment. A packaged app has no such route: the path resolves through the app protocol handler and 404s. Desktop needs an absolute ingest URL, which turns a same-origin beacon into a cross-origin request.
  3. The server would refuse the origin as written. originAllowed (src/analyticsIngest.ts:177) allows only verticopolis.com, *.verticopolis.com, and (non-production only) *.vercel.app; an app://host origin is none of those. Note the nuance: the function returns true when the Origin header is ABSENT, so what Electron actually sends decides the result today. The file already describes itself as a functional gate rather than a security boundary; a cross-origin desktop client makes that distinction load-bearing and it should be stated deliberately.

What must be settled together

  • The platform dimension cannot describe the channel. resolvePlatformLabel (src/analyticsEnrichment.ts:33-41) returns only web, twa, or ios, and maps ANY isNativeWrapper port to ios. Steam, itch, and a future channel would be indistinguishable, which defeats the point of measuring a demo. This is exactly the vocabulary work #710 is gated on, so #710 should be resolved by this ruling rather than separately.
  • Trust and abuse. An absolute ingest URL is postable by anyone. Decide the model (a per-build token, a separate desktop ingest path, accepting the noise) rather than widening an allowlist and hoping.
  • Consent. A channel we cannot name is a channel whose privacy copy we have not written. The desktop consent surface rides with this.
  • The two gates move in lockstep. Both files say so: the client emits from telemetryHostAllowed, the server accepts at originAllowed, and drift silently drops events (client dark, or a 403 on a same-origin beacon).

Not in scope

Embedding the web build as an itch HTML5 page. That would add a separate problem (itch serves those from html-classic.itch.zone and *.ssl.hwcdn.net, suffixes shared by every game on itch, so trusting them would let any itch game post into our ingest, the same shared-suffix hazard the code already reasons about for *.vercel.app). Recorded here so the option is a decision rather than a surprise, but the ruling is about the Electron build.

P3 while no demo is scheduled. This escalates the moment a demo date is set: shipping a demo with zero measurement is a product decision, not a technical gap, and it would be discovered too late.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read telemetryHostAllowed in src/telemetry.ts, the relative transport in src/analyticsRelay.ts, originAllowed in src/analyticsIngest.ts, and resolvePlatformLabel in src/analyticsEnrichment.ts. First resolve the desktop channel, trust, consent, and client/server gate decisions, including how #710 fits. Done means the repository has an agreed implementation scope for measurable Electron builds without silently weakening ingestion controls.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, typescript
Domain
analytics, api, backend-api-design, desktop, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.