- TypeScript 60%
- Go 30.3%
- JavaScript 9.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .github/workflows | ||
| testdata | ||
| worker | ||
| .gitignore | ||
| .golangci.yml | ||
| go.mod | ||
| go.sum | ||
| licence.go | ||
| licence_test.go | ||
| README.md | ||
licence
Licences for the paid apps (keybars Pro, later shepherd Pro), sold through Polar.
worker/: the Cloudflare Worker atlicence.jwarykowski.dev. An app sends the customer's Polar key once per machine toPOST /v1/<product>/activate; the Worker activates it with Polar, checks the key is for that product, and returns a token signed with the product's Ed25519 key.POST /v1/<product>/deactivatefrees the machine.- The Go package: apps verify tokens offline, and activate and deactivate.
var Pro = licence.Product{ID: "keybars-pro", Keys: []string{publicKey}}
path, _ := Pro.Path()
l, _, err := Pro.Load(path)
pro := err == nil && l.Covers(buildDate)
A licence covers releases built until updatesUntil (a year after
purchase), on the computer it was activated on: the token carries an HMAC
of the machine ID (/etc/machine-id, macOS's IOPlatformUUID, Windows'
MachineGuid), and Load returns ErrOtherMachine for a copied licence
file. Activating again there takes one of the key's machines. LICENCE_SERVER points the client at another server.
Adding a product
- In Polar, make the product with a licence-key benefit.
- Add it to
worker/src/products.tsand its benefit ID toBENEFITSinworker/wrangler.jsonc. npm run keygen <product>writes the private key to~/.config/licence-signing/and prints the public key for the app.npx wrangler secret put SIGNING_KEY_<PRODUCT> --env="" < <that file>, thennpm run deploy.
Sandbox
npm run deploy:sandbox runs the Worker against Polar's sandbox on
workers.dev, with its own Polar IDs (env.sandbox in wrangler.jsonc) and
its own signing keys (npm run keygen <product> sandbox). Sandbox
purchases are free, so release builds must never trust a sandbox key.
To replace a signing key, ship the new public key in the app's Keys
before uploading the new secret.
Development
go test ./...
golangci-lint run ./... # .golangci.yml; golangci-lint fmt ./... formats
cd worker && npm ci && npm run check && npm test
npm run lint && npm run fmt:check # oxlint and oxfmt; npm run fmt formats
npm run fixture # regenerate testdata/ after changing the token format