Context
"Integrate and your reports build themselves." For Stacks apps this means a first-party package that hooks the framework's own event surface - models with the observe trait emit product:created / order:created / user:created style events, and commerce/CMS/auth modules dispatch domain events - and forwards them to ReportsHQ as the standard taxonomy from docs/events.md (#6).
Scope
- New package (suggested:
@reportshq/stacks, repostacksjs/reportshq-stacksor apackages/workspace inside this repo - decide and document). Zero third-party deps; Bun-first. - Config:
REPORTSHQ_KEY+ optionalREPORTSHQ_ENDPOINTenv, aconfig/services.ts-style block, per-domain toggles (commerce: true, users: true, cms: false), sampling rate. - Transport: in-process buffer with size + interval flush, batched
POST /ingest, bounded retry with backoff, drop-oldest under pressure, never blocks the request path, flush on shutdown. - Mappers from Stacks events to taxonomy events:
commerce.order.created {total, currency, items},commerce.order.refunded,user.registered,user.login,cms.post.published, ... - exactly the reserved names indocs/events.md; extend that doc first when a mapper needs a new name. - Wiring: one-line install documented (register listeners via
app/Events.tsor a package-provided boot hook - whichever the framework supports cleanly; if a clean package-boot hook is missing in Stacks, add one upstream rather than documenting a workaround). - Tests against a fake ingest server: batching, retry, sampling, mapper payload shapes.
- Publish with
bun run release:patchonce green; dogfood it inside reportshq itself (ReportsHQ reporting on ReportsHQ).
Acceptance
- A fresh Stacks app with the package installed and
REPORTSHQ_KEYset emitsuser.registeredandcommerce.order.createdevents visible via the read API (#6) with no further code.
Depends on #6. Feeds #14. Part of #1 (M5 Integrations and auto-reports). Ground rules: see #1.