docs: lead with self-hosting as the model, add a security policy - #24
Conversation
The README framed the absence of a registry install as a deficiency — "not published to npm yet ... until you publish, install them locally". That reads as an unfinished project, which is the wrong impression to give anyone arriving from a post or article, and it isn't what's true. Fork-and-self-host is the intended model. It's also the whole argument against the hosted alternatives: attribution data is the last thing you want behind someone else's API, and Firebase Dynamic Links shutting down is exactly the risk that shipping this as a hosted dependency would recreate. Framing the strongest position as a missing feature undersold it. Rewrote the section to argue that directly, and cite Sparkle running the PHP backend in production on their own infrastructure and database — which is also why docs/decisions.md records bugs found on real devices rather than in tests. Kept the workspace / file: / tarball mechanics underneath as layout options rather than workarounds, and reframed the closing note around publishing *your fork* privately, which is the realistic case. Also fix the opening line: it said "three installable packages". There are four, and they aren't installed from a registry. Add SECURITY.md. This handles HMAC-signed claim tokens, device fingerprints, and conversion data, so having no disclosure route was a real gap. Points at GitHub private advisories, states the actual rate-limit defaults and retention behaviour, and documents the probabilistic matching tier and X-Forwarded-For trust as known design limits so they get argued rather than filed as bugs. Spells out that a fork is its own security maintainer — nothing reaches forks automatically, which is the direct consequence of the distribution model above.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The previous commit made "fork and self-host" the README's headline position, but left it as an assertion with no reasoning behind it — out of character for a repo where every other significant call has a written record, and weak exactly where it needs to be strong, since an article arguing "fork it, don't depend on it" sends readers straight to this file. Writes down why the distribution model matches the argument the project exists for: hosted attribution is a dependency risk (FDL is shutting down, the commercial options can reprice at will), attribution data is a bad thing to hold that risk over, and publishing this as a package people depend on would rebuild the same structure one layer down. States the costs rather than glossing them — slower adoption than an npm install, forks receiving no automatic security updates, expected divergence making upstream fixes not apply cleanly, and the asymmetry that publishing later is easy while unpublishing is not. Also notes that the packages' local 1.0.0 is a placeholder, not a stability claim, so it doesn't get read as one later. Status is Done, not Decided: this file defines Decided as "design settled, not yet built", and there is nothing left to build here. README links to it, so the claim and its trade-offs travel together.
|
Added decision #31 (docs/decisions.md), closing the first follow-up listed above. The previous commit made fork-and-self-host the README's headline position but left it as an assertion with nothing behind it — out of character for this repo, and weak precisely where it needs to be strong, since an article arguing "fork it, don't depend on it" sends readers straight to this file. #31 records why the distribution model matches the argument the project exists for, and states the costs plainly rather than glossing them: slower adoption than Status is Done, not Decided — this file defines Decided as "design settled, not yet built", and there's nothing left to build. The README now links to it, so the claim and its trade-offs travel together. |
Two launch-readiness items, ahead of posting about the project.
1. The README undersold the distribution model
It framed the absence of a registry install as a deficiency:
That reads as unfinished — the wrong impression for someone arriving from an article, and not what's actually true. Fork-and-self-host is the intended model.
It's also the entire argument against the hosted alternatives. Attribution data — every click, every device fingerprint, every conversion — is the last thing you want sitting behind someone else's API. Firebase Dynamic Links shutting down is precisely the risk that shipping this as a hosted dependency would recreate. The README was presenting its strongest position as a missing feature.
Rewrote it to argue that directly, with Sparkle as evidence: the PHP backend running in production on their own infrastructure, against their own database and reward logic — which is also why
docs/decisions.mdrecords bugs found on real devices rather than in tests.The workspace /
file:/ tarball instructions are unchanged, just reframed as layout options rather than workarounds. The closing note now covers publishing your fork privately under your own scope, which is the realistic case for a team that wants ordinary dependencies.Also: the opening line said "three installable packages". There are four, and they aren't installed from a registry.
2.
SECURITY.mdThe project handles HMAC-signed claim tokens, device fingerprints, and conversion data, so having no disclosure route was a genuine gap — and a visible one to anyone evaluating it on HN.
Written from the code rather than a template:
X-Forwarded-Fortrust as known design limits, so they get argued on the reasoning rather than filed as bugsCLICK_TOKEN_SECREThandling, including that rotation invalidates outstanding tokensexamples/and the mock backend, which are deliberately insecure and documented as suchThe part a template would have missed: a fork is its own security maintainer. Nothing reaches forks automatically and there's no central service to revoke anything — the direct consequence of the distribution model in part 1.
Follow-ups, not in this PR
docs/decisions.mdentry records the self-host decision. It's now a positioning claim in the README with no reasoning behind it, which is out of character for this repo.