Two things ship here
The Swift package follows semantic versioning, and the wire schema is versioned separately. The hosted dashboard ships in phases.
Swift package
Cloudflare backend only — key liveness, first-seen installs and per-project retention. No wire change: the SDK, the batch format and the /v1 bodies are untouched, so an existing emitter and reader keep working. The number skips 0.2.0 because the backend package was never bumped for that tag.
- Migration 0004:
keys.last_used_at, coalesced to at most one write per key per minute, so a key can be checked for traffic before it is revoked - Migration 0005:
installs— first sighting per install, exempt from the raw purge, with a backfill marker so backfilled days are not read as exact - Migration 0006:
projects.retention_days— raw retention per project, default 90, bounds 90–400 - Fixed: the
events_dedupedtally no longer counts the installs write, which had made returning users read as replayed events - The read endpoints now perform the coalesced key touch, deferred with waitUntil — still safe and idempotent, no longer literally write-free
A hardening pass with no breaking API changes: every 0.1.0 call site compiles unchanged. One normative wording change in wire schema v1 — a backend SHOULD now treat (projectId, installId, seq) as a per-event idempotency key — and one required Worker migration.
- Low Data Mode: the default transport sets
allowsConstrainedNetworkAccess = false, so batches stay queued until the mode lifts - Request timeouts: 20s per request and 60s per resource, replacing the URLSession defaults of 60s and 7 days
- An additive
queue.headsidecar next toqueue.jsonl; 0.1.0 queue files load unchanged - Per-event idempotency in the Worker (migration
0003_event_idempotency.sql): replays are absorbed, the request still answers 202 StatsClient.record(_:props:)— a nonisolated, non-async sibling oftrack()that is safe in a button action or a view body
First tagged release: wire schema v1, the Stats core emitter, the StatsCloudflare adapter, and the Cloudflare Worker + D1 backend.
- Actor-based client: track, identify, consent, flush, reset, lifecycle
- JSON-lines durable queue;
track()returns once on disk - Dispatcher: batching by bytes then count, jittered backoff, 24-hour delivery ceiling
- Consent as three independent groups, persisted
- Bundled privacy manifest with tracking set to false, asserted by a test