@kismet-tech/edge-events
v0.1.0
Published
Kismet edge events: the one server-side content-event builder, bot vocabulary, kid_sid adopt/mint/reconcile and booking-intent tees shared by the Cloudflare injection worker, kismet.travel middleware and Kismet-built sites
Maintainers
Readme
@kismet-tech/edge-events
The one edge-events surface for Kismet. Every server-side emitter of content_events
builds its payload here, reads the same bot vocabulary, and shares the same identity
carrier rules:
| Consumer | How |
|---|---|
| Cloudflare injection worker (Juniper, Red Cottage, Upstay, observe-mode zones) | api/hotels-api-ts/assets/vrm-injection-worker.js is BUILT from src/ + api/hotels-api-ts/worker/vrm-injection-worker.entry.js (npm run worker:build in api/hotels-api-ts) |
| kismet.travel middleware.ts (tracking_mode='kismet') | import { buildContentEvent, detectBot, ... } from '@kismet-tech/edge-events' |
| Kismet-built sites (sand-sea-site and the SDK starter) | same import; extractKidSid / mintLocalKidSid / postResolveAnchor replace per-site copies |
| @kismet-tech/sdk | should depend on this package and derive AI_BOTS from BOT_NAMES instead of a hand-kept list |
Ingest (POST /v1/content-events, content-event.service.ts) stays the classification
and persistence authority. Nothing here classifies; detectBot is the edge parity hint.
What is in it
buildContentEvent(input)/postContentEvent(ctx, env, event)/fireContentEvent(ctx, env, input): the payload builder (trackingModeserverdefault,kismetfor kismet.travel; resourceClasscontent_vr/content_vrm; actionType precedencefetch > cta_click > property_view > view; stay fields;verifiedBot;responseStatus/responseTimeMs) and the transport (TRACKING_ENDPOINT, defaulthttps://kismet.travel/api/track;X-Kismet-Tracking-KeyfromCOLLECTION_KEY;X-API-KeyfromAPI_KEY; 2s cap;ctx.waitUntil).normalizeServingDomain(host): apex, nowww., no port.detectBot(ua),BOT_PATTERN_ROWS,BOT_NAMES,BOT_CATEGORIES: generated fromapi/hotels-api-ts/src/data/bot-patterns.jsonbyscripts/generate-bot-patterns.mjs. Never hand-edited; CI fails when stale.normalizePath,pathSuffix,OBSERVE_SKIP_EXTENSIONS,OBSERVE_AGENT_SUFFIXES,OBSERVE_SKIP_PATH_PREFIXES,OBSERVE_SKIP_PATHS,observeShouldTrack: the observe tier's rules (parity with the Fixtures PHP beacon skips, AW-186).KID_SID_RE,extractKidSid(url, request)(adopt-only,?kid_sidthen_kid_sidcookie, strict grammar),mintLocalKidSid()(kid_+ 8, IDENTITY-CANON Inv. 9),setKidSidCookie,extractClickIds,buildResolveAnchorBody,postResolveAnchor,parseResolveAnchorResponse,reconcileColdKidSid(the resolve-anchor reconcile withproposedKidSid).parseStayDate,parseGuestCount,parsePromoCode,resolveBookingIntent,teePriceCheck,teeEngineConfirmation: the booking-engine intent tee, quote capture and confirmation bridge.
Web-platform APIs only (fetch, URL, crypto.getRandomValues, AbortSignal.timeout):
runs on Cloudflare Workers, Next.js Edge middleware and Node 20+.
Env the module reads
| Key | Meaning | Default |
|---|---|---|
| TRACKING_ENDPOINT | where content events POST | https://kismet.travel/api/track |
| COLLECTION_KEY | ctk_ tracking key, sent as X-Kismet-Tracking-Key | none |
| API_KEY | service key, sent as X-API-Key (ingest-direct emitters) | none |
| KISMET_API_ORIGIN | origin for resolve-anchor / quote-capture / booking-bridge | https://api.ksmt.app |
| RESOLVE_ANCHOR_ENDPOINT | full override for the identity authority URL | KISMET_API_ORIGIN + /v1/identity/resolve-anchor |
Bot vocabulary
node scripts/generate-bot-patterns.mjs # regenerate src/bot-patterns.generated.js
node scripts/generate-bot-patterns.mjs --check # CIThe generated file mirrors the JSON exactly (order matters: specific patterns before
general ones). api/hotels-api-ts/src/tests/edge-events-bot-vocabulary.test.ts asserts
the rows equal the JSON and that the worker asset's inlined detectBot agrees with
ingest's detectBot on every named bot.
Building the worker from this module
cd api/hotels-api-ts
npm run worker:build # writes assets/vrm-injection-worker.js
npm run worker:check # CI: fails if the committed asset is stale
npm run worker:test # parity corpus + vocabulary + the vrm-worker test setscripts/build-vrm-injection-worker.mjs inlines src/*.js verbatim (comments
included) above the worker entry, so the deployed script stays readable. The parity
corpus (src/tests/edge-events-parity/) drives the built asset through human / GPTBot
/ ClaudeBot / .md fetch / ?kid_sid= echo / cta / stay-param / observe-mode cases
and byte-compares every outbound body and served response with the golden recorded
from the pre-module asset.
Develop
npm ci
npm run typecheck # tsc --checkJs over src/
npm test # node --test
npm run build # dist/esm (+ .d.ts) and dist/cjsSource is plain ESM JavaScript with JSDoc types so the worker build can inline it
byte-for-byte; consumers get types from the emitted .d.ts.
Publish
Manual, like @kismet-tech/sdk: bump version, then from this directory
npm publish --access public(prepublishOnly runs typecheck, tests and the build.) publishConfig targets the
public npm registry so Kismet-built sites and the SDK can install it without a
GitHub Packages token. kismet.travel routes the whole @kismet-tech scope to GitHub
Packages, so mirror the same version there when kismet.travel needs it:
npm publish --registry=https://npm.pkg.github.com