@clue-ai/nodejs-sdk
v0.1.1
Published
Clue Node.js / Express backend SDK — sends ObservationSourceEvent batches to the Clue ingest API. OTel-core architecture (provider/instrumentation/context/exporter).
Readme
@clue-ai/nodejs-sdk
Clue Node.js / Express backend SDK. Phase 4 internal OTel architecture:
events flow through a NodeTracerProvider + BatchSpanProcessor +
ObservationSourceEventExporter to
/api/v1/ingest/observation-source-event-batches.
Minimal integration
import { ClueInit, ClueTrack } from "@clue-ai/nodejs-sdk";
await ClueInit({
enabled: true,
endpoint: process.env.CLUE_INGEST_ENDPOINT!,
projectKey: process.env.CLUE_PROJECT_KEY!,
apiKey: process.env.CLUE_API_KEY!,
environment: "production",
serviceName: "my-api",
serviceKey: "my-api",
producerId: "my-api",
});
ClueTrack("order_placed", { product_name: "shirt", amount: 100 });Privacy and PII handling
1. Hard-deny: PII / secrets are stripped before transport
The SDK strips a built-in set of property keys before the value is
set as an OTel span attribute (i.e. before it leaves the customer
process). Caller-supplied deniedKeys are added on top of the
hardcoded ALWAYS_DENIED_KEYS — they cannot remove a default-denied
key.
Hard-deny categories (case- and separator-insensitive — userEmail,
user-email, USER_EMAIL, email_address all match):
- Auth credentials:
authorization,cookie,set-cookie,password,passwd,secret,token,access_token,refresh_token,session,session_token,api_key,apikey,private_key - PII categories (Phase 4 P0):
email,phone,credit_card,ssn
This list is a strict superset of the server-side ingest hard-deny
(@clue/shared INGEST_HARD_DENY_KEYS), enforced by a CI parity test
in test/sanitize.test.ts.
Nested objects in ClueTrack properties are recursively sanitized —
ClueTrack("x", { user: { email: "[email protected]", name: "Alice" } }) emits
the name field but never transmits email.
2. Default-masked: configure server allowlist for analysis projection
Properties that pass the hard-deny gate are still masked by default
on the server side. To make a property appear in Clue's analysis UI,
the property key must be listed in the project environment's
observationAnalysisPropertyAllowlist. Without this, the property
lands in raw_only_keys (visible in raw archive only) and not in
analysisProperties.projected.
Configure the allowlist via the Clue admin UI or the
ProjectEnvironment update API after taking a privacy review of which
property names you want to project for analytics.
3. Identity-event email pass-through is intentional
ClueIdentify(userId, { email: "..." }) populates a structured
user_profile.email field on the canonical identity event. This is a
deliberate, opt-in identity contract — the SDK does NOT strip the
email trait on identity-event paths because the canonical identity
event would be meaningless without it. The server-side worker still
applies the hard-deny gate after Phase 4 ingest if the field path
matches.
Build / test
pnpm install
pnpm build
pnpm test # unit + parity tests
pnpm test:cov # with coverageLive-verify (opt-in, requires apps/api + apps/worker running):
CLUE_LIVE_VERIFY=1 \
CLUE_LIVE_PROJECT_KEY=pk_dev_xxx \
CLUE_LIVE_API_KEY=cluesk_dev_xxx \
pnpm exec vitest run test/canonical-endpoint-live.test.ts