Skip to content

walkerOS v4.5.0

Latest

Choose a tag to compare

@github-actions github-actions released this 24 Aug 17:42
· 11 commits to main since this release

Changes

Add package READMEs and npm keywords. The MCP packages now ship install
instructions for Claude Code, Cursor, and VS Code plus MCP registry metadata
(mcpName).

The AWS Lambda and GCP Cloud Functions sources now forward every field of the
incoming request body to the collector, not just event, data, context,
user, globals, and consent. Fields such as source (release and trace
provenance) ride through and accumulate across crossings, matching the Express
and Fetch sources; as with those sources, a client can also supply id,
timestamp, consent, user, and source, which the collector treats as
values rather than overriding. Both sources now accept name as the event-name
field, the walkerOS standard; {"event": "..."} keeps working as a legacy alias
and is removed at the next major.

settings.context now accepts any Mapping.Value, not just the enum literals,
and resolves it per request against { event, ingest }, so one instance serves
every transport: [{ "key": "ingest.transport" }, { "value": "beacon" }] reads
the sender's annotation and pins beacon without it. The widening introduces no
silent-degradation path: a result outside the vocabulary falls back to auto
and reports context_undetermined, and a bare string that is neither a literal
nor a dot path is rejected by the schema.

Bot detection now scores all sixteen request signals instead of the user agent
alone, and emits one botScore with a botCategory, botProduct and reason
codes. This replaces the old output: agentScore is removed, score values
changed, and settings.output takes string | false. New settings: context
and suspiciousAt.

A path entry in config.bundle.packages now counts as the package pin, so
bundling and setup use the local package instead of failing when steps still
declare conflicting inline versions of it.

walkeros setup now resolves a component's package the same way
walkeros bundle does: the flow's pinned version is downloaded from the
registry (sharing the bundle cache) and imported from there. Setup works via npx
without a local install; path: packages are supported for local development.

The Express source's async option now resolves per HTTP method: a boolean
still applies to the whole source, and a record like { "GET": true } or
{ "POST": false } overrides one method while the other keeps its default. The
default changed: GET is now synchronous, so a step such as the file transformer
or a cache can serve real content instead of the tracking GIF, while POST keeps
the fast respond-first acknowledgement. To restore respond-first GET set
async: true or async: { "GET": true }; configs that set async: false only
to fix asset serving can drop it.

The GTM destination no longer pushes the gtm.js start event into the dataLayer
unless it loads the container itself. Set loadScript: true to have walkerOS
install GTM, start event included. Without it, walkerOS only pushes your mapped
events, so an existing container's triggers are left alone.

Revenue now reaches Klaviyo. A mapping rule's settings.value was written into
the event's properties, where Klaviyo stores it as a segmentable custom
property and ignores it for revenue reporting, while valueCurrency was set on
the event attributes with no sibling value to denominate. Both now sit together
on the attributes, which is where klaviyo-api serializes value and
value_currency from. Properties are unaffected -- map a value through the
rule's data mapping if you also want it as a custom property.

Events now carry Klaviyo's unique_id dedup key, defaulting to the walkerOS
event id. Klaviyo previously fell back to the event time truncated to the
second, which dropped distinct events for one profile and metric inside the same
second. Map settings.uniqueId on the destination or on a mapping rule to
deduplicate on a business identifier instead.

config.batch now works on the server API destination. It previously had no
pushBatch, which is the collector's gate for batching, so the setting was
accepted and silently ignored and every event was still sent as its own request.
A flush is now one request whose body is a JSON array of the batched events, one
element per event, mapped per event and passed through transform per element,
matching the web variant. transform is also declared in the settings schema
now, so it shows up in the package hints instead of being an undocumented
option.

Server sources answer rejected client input with 4xx JSON instead of unhandled
errors or 500s: unparseable bodies return 400 at the HTTP boundary, and invalid
events return 400 with the reason wherever the response is still open
(synchronous handling; in the express default respond-first mode the 200 ack has
already been sent, so the rejection surfaces as a warn and a counter instead)
(push resolves {ok: false, invalid: true, error}). Genuine pipeline failures
return 500 instead of success: true. Invalid input now counts on
collector.status.sources.<id>.rejected instead of inflating status.failed.
The express source no longer sends X-Powered-By and now sets
X-Content-Type-Options: nosniff on every response.

Server sources now share one request scope and one event envelope, so
config.ingest paths and POST body forms behave identically on Express, Fetch,
Lambda and Cloud Functions. Batches and bare arrays are accepted everywhere, and
a destination before-chain fan-out no longer drops all but the first event.
Breaking: AWS requestContext.* moves under raw.*, Express drops protocol
and hostname, and Fetch { fn } header mappings become
{ key: 'headers.*' }. See the migration guide.

Published Packages