maniator / maniator/verticopolis
[Feature]: [P3] Desktop analytics is structurally dark, so an itch.io demo and Steam both ship unmeasured
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:
- 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. - 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. - The server would refuse the origin as written.
originAllowed(src/analyticsIngest.ts:177) allows onlyverticopolis.com,*.verticopolis.com, and (non-production only)*.vercel.app; anapp://hostorigin 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 onlyweb,twa, orios, and maps ANYisNativeWrapperport toios. 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 atoriginAllowed, 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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