@aurascope-analytics/forwarder-edge-worker
v0.1.2
Published
AuraScope Analytics edge-worker forwarder — a Cloudflare Worker handler that observes cache-served requests and ships them with waitUntil
Readme
Edge-worker forwarder
This Cloudflare Worker is the server-plane witness for requests handled at the
content delivery network edge, including cache-served requests that never reach an
application hook or origin access log. It emits the frozen structured request-event
shape with per-line v: 1, a random per-isolate iid, and a monotonic per-isolate
n. It never computes or sends event_id; ingest owns that identifier.
The handler awaits only the tenant’s real origin/next response. It returns that
Response unchanged and schedules capture plus shipping with
ctx.waitUntil(...), so AuraScope network work does not extend the response hot
path. A minimal Cloudflare integration is the default export in src/index.ts:
export default createWorkerHandler();Fail-open: two mechanisms, two jobs (ADR 0037)
A Worker that throws serves the tenant’s visitor a Cloudflare error page, so the handler arms both of the runtime’s protections and neither substitutes for the other:
ctx.passThroughOnException()is the first statement of the handler, before the metrics increment, before capture, before the origin fetch. It covers unhandled exceptions in our code: the runtime re-issues the request to the origin as though this Worker were not installed. Ordering is the decision — a throw can only degrade that way if the flag was already set.WaitUntilContextdeclares the method optional so non-Worker callers (the end-to-end driver, unit tests) stay constructible; that is a testing affordance, pinned as such by a contract test on the exported entrypoint and by a type check inscripts/check-edge-worker-install.sh.- Every origin fetch sits inside its own
try/catch, because Cloudflare states plainly that (1) does not cover errors from the originfetch(). The catch counts the failure on its ownoriginFailedcounter, logs it, and returns a minimal, status-only502— no body, no vendor identifier. It never re-throws: request bodies are streamed rather than buffered, so a re-throw after the body is consumed would leave the fallback re-issuing the request without it, turning a visitor’s checkout into an unrelated4xx.
An origin that answers is never touched — any status it returns, including its
own 5xx, is passed through unchanged. Only a throw reaches the catch, and no
event is captured for a request that has no origin status.
Daily-request-limit fall-through on a free Cloudflare plan is a route
setting (request_limit_fail_open), not a runtime call, and is owned by the
deploy-on-behalf path — arming pass-through does not satisfy it.
Bind INGEST_URL, AURASCOPE_SITE_KEY, and the secret
AURASCOPE_FORWARDER_SK at deployment. AURASCOPE_PROBE_MARKER is an optional
synthetic-traffic self-declaration (ADR 0020), sent as the
x-aurascope-probe-marker batch envelope header — a versioned addition to the
frozen v1 contract; shipped events (including the user agent) are never mutated
by it. The raw
CF-Connecting-IP value (falling back to X-Forwarded-For) and the full path plus
query are shipped; ingest resolves trusted hops and applies its allowlist.
The edge worker is an unreplayable sender: there is no durable disk and no local
retry queue. A 200 is a normal acknowledgement. A 202 {"buffered":true} is
also success because ingest has accepted ownership into its bounded ADR-0004
buffer. Any other response or network error loses the event and increments the
per-isolate lost counter; 401 is also logged. The in-memory observed,
shipped, buffered, lost, and originFailed counters are unit-test
observability only—durable production metrics must be exported to the Cloudflare
platform, and every one of them dies with its isolate, so none of them is a
fleet-wide figure. originFailed is deliberately separate from lost: lost
means an event we captured never reached ingest, and folding “the tenant’s
origin was unreachable” into it would make the shipment-loss number unreadable
for exactly the tenants having the worst day. No drop header is sent.
This package publishes to the public npm registry as
@aurascope-analytics/forwarder-edge-worker (ADR 0032), so a tenant adds it to their
Workers project as an ordinary dependency:
npm install @aurascope-analytics/forwarder-edge-workerIt ships src/ — TypeScript, deliberately: Wrangler compiles TypeScript itself, so a
pre-compiled dist/ would add a build step that buys a tenant nothing and costs them
readable sources at the edge. The exports map points at src/index.ts for both the
runtime entry and the types. Operator detail:
docs/distribution.md.
Install dependencies with bun install, type-check with bun run build, and run
the core under Bun with bun test. scripts/check-edge-worker-install.sh covers what
those cannot: it packs the package, installs the tarball into a throwaway project, and
type-checks the public guide's exact import lines under moduleResolution: bundler with
@cloudflare/workers-types — the packaging and resolution half of the tenant's path.
Wrangler itself is the deployment runtime and is still not installed or exercised in
this repository's continuous-integration lane; that remains an explicit deployment-test
gap. A deployment may also co-serve the /px proxy role, but that routing is
deliberately not built here.
