zubbl-sdk 1.1.42 → 1.1.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  export type ZubblConfig = {
2
2
  apiKey: string;
3
+ signingSecret: string;
3
4
  tenantId: string;
4
5
  appId: string;
5
6
  baseUrl?: string;
@@ -3,6 +3,7 @@ export declare const isNode: boolean;
3
3
  export declare const isWorker: boolean;
4
4
  export interface ZubblConfig {
5
5
  apiKey: string | null;
6
+ signingSecret: string | null;
6
7
  tenantId: string | null;
7
8
  appId: string | null;
8
9
  baseUrl: string;
@@ -30,6 +30,7 @@ function assertBrowserSafety(cfg) {
30
30
  function createConfigStore(initial) {
31
31
  let current = {
32
32
  apiKey: null,
33
+ signingSecret: null,
33
34
  tenantId: null,
34
35
  appId: null,
35
36
  baseUrl: "https://api.zubbl.com/api",
@@ -57,6 +58,14 @@ function createConfigStore(initial) {
57
58
  if (current.apiKey) {
58
59
  headers.Authorization = `Bearer ${current.apiKey}`;
59
60
  }
61
+ // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch
62
+ if (current.signingSecret) {
63
+ headers["X-Zubbl-Signing-Secret"] = current.signingSecret;
64
+ }
65
+ else if (current.apiKey) {
66
+ // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints
67
+ throw new Error("[Zubbl SDK] Missing signingSecret (required for signed requests)");
68
+ }
60
69
  return headers;
61
70
  }
62
71
  return { init, get, buildHeaders };
@@ -463,9 +472,12 @@ async function httpRequest(url, options = {}) {
463
472
  const apiKey = (headers["Authorization"] || headers["authorization"] || "")
464
473
  .replace(/^Bearer\s+/i, "")
465
474
  .trim();
466
- const signingSecret = (process.env.SDK_SIGNING_SECRET || apiKey || "").trim();
475
+ const signingSecret = headers["X-Zubbl-Signing-Secret"]?.trim() || "";
476
+ if (!apiKey) {
477
+ throw new Error("Missing API key (Authorization: Bearer ...) — cannot send requests");
478
+ }
467
479
  if (!signingSecret) {
468
- throw new Error("Missing API key (Authorization: Bearer ...) — cannot sign requests");
480
+ throw new Error("Missing signing secret — cannot sign requests");
469
481
  }
470
482
  // We must sign the exact bytes we send.
471
483
  // If body is an object, stringify it BEFORE signing AND BEFORE sending.
@@ -496,6 +508,8 @@ async function httpRequest(url, options = {}) {
496
508
  finalOptions.headers = (finalOptions.headers || {});
497
509
  finalOptions.headers["X-Zubbl-Nonce"] = nonce;
498
510
  finalOptions.headers["X-Zubbl-Signature"] = signature;
511
+ // 🔒 Never send the signing secret over the wire (internal-only)
512
+ delete finalOptions.headers["X-Zubbl-Signing-Secret"];
499
513
  // Record adaptive context sample (keep your existing behaviour)
500
514
  recordContextSample("/http", "GET", 200, 123);
501
515
  const response = await fetch(url, finalOptions);
@@ -531,10 +545,24 @@ async function identifyUserFeature(store, { email, name }) {
531
545
  throw new Error("email is required");
532
546
  const config = store.get();
533
547
  const storage = createStorage();
534
- // Check cache
535
- const cached = storage.get(USER_CACHE_KEY);
536
- if (cached?.id) {
537
- return { external_user_id: cached.id, cached: true };
548
+ // Determine override identity (prefer config.identity which SIM sets)
549
+ const cfgIdentity = config?.identity;
550
+ const storeIdentity = store?.identity;
551
+ const overrideEnabled = (cfgIdentity && cfgIdentity.override === true) ||
552
+ (storeIdentity && storeIdentity.override === true);
553
+ const overrideId = overrideEnabled
554
+ ? (cfgIdentity?.id ||
555
+ storeIdentity?.id ||
556
+ store?.externalUserId ||
557
+ store?.userId ||
558
+ undefined)
559
+ : undefined;
560
+ // Check cache (skip cache when override is enabled, we must honour overrideId)
561
+ if (!overrideId) {
562
+ const cached = storage.get(USER_CACHE_KEY);
563
+ if (cached?.id) {
564
+ return { external_user_id: cached.id, cached: true };
565
+ }
538
566
  }
539
567
  const adaptiveHeaders = getAdaptiveHeaders();
540
568
  const geoHeaders = await getGeoHeaders();
@@ -544,20 +572,14 @@ async function identifyUserFeature(store, { email, name }) {
544
572
  ...adaptiveHeaders,
545
573
  ...geoHeaders,
546
574
  });
547
- // ✅ If SIM / consumer provides a stable external user ID, reuse it
548
- const overrideId = store?.identity?.id ||
549
- store?.externalUserId ||
550
- store?.userId ||
551
- undefined;
575
+ // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint
552
576
  const identifyUrl = overrideId
553
577
  ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`
554
578
  : `${config.baseUrl}/sdk/identify`;
555
579
  const resp = await httpRequest(identifyUrl, {
556
580
  method: "POST",
557
581
  headers,
558
- body: JSON.stringify(overrideId
559
- ? { email, name } // backend will reuse path param ID
560
- : { email, name }),
582
+ body: JSON.stringify({ email, name }),
561
583
  });
562
584
  const data = await resp.json().catch(() => ({}));
563
585
  const { external_user_id } = data;
@@ -1 +1 @@
1
- {"version":3,"file":"zubbl-sdk.cjs.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n return headers;\n}\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\nconst apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\nconst signingSecret = (process.env.SDK_SIGNING_SECRET || apiKey || \"\").trim();\n\nif (!signingSecret) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot sign requests\");\n}\n\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(`[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`);\n}\n\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n","// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // Check cache\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM / consumer provides a stable external user ID, reuse it\n const overrideId =\n (store as any)?.identity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined;\n\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify(\n overrideId\n ? { email, name } // backend will reuse path param ID\n : { email, name }\n ),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n return { decision: \"allow\", status: resp.status, data: json };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":"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"}
1
+ {"version":3,"file":"zubbl-sdk.cjs.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n signingSecret: string | null; // ✅ used for HMAC signing (never sent over the wire)\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n signingSecret: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch\n if (current.signingSecret) {\n headers[\"X-Zubbl-Signing-Secret\"] = current.signingSecret;\n } else if (current.apiKey) {\n // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints\n throw new Error(\"[Zubbl SDK] Missing signingSecret (required for signed requests)\");\n }\n\n return headers;\n }\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\n const apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\n const signingSecret =\n ((headers as any)[\"X-Zubbl-Signing-Secret\"] as string | undefined)?.trim() || \"\";\n\n if (!apiKey) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot send requests\");\n }\n\n if (!signingSecret) {\n throw new Error(\"Missing signing secret — cannot sign requests\");\n }\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // 🔒 Never send the signing secret over the wire (internal-only)\n delete (finalOptions.headers as any)[\"X-Zubbl-Signing-Secret\"];\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(\n `[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`\n );\n }\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n","\n\n// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // ✅ Determine override identity (prefer config.identity which SIM sets)\n const cfgIdentity = (config as any)?.identity;\n const storeIdentity = (store as any)?.identity;\n\n const overrideEnabled =\n (cfgIdentity && cfgIdentity.override === true) ||\n (storeIdentity && storeIdentity.override === true);\n\n const overrideId = overrideEnabled\n ? (cfgIdentity?.id ||\n storeIdentity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined)\n : undefined;\n\n // Check cache (skip cache when override is enabled, we must honour overrideId)\n if (!overrideId) {\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ email, name }),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n signingSecret: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n return { decision: \"allow\", status: resp.status, data: json };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":"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"}
@@ -28,6 +28,7 @@ function assertBrowserSafety(cfg) {
28
28
  function createConfigStore(initial) {
29
29
  let current = {
30
30
  apiKey: null,
31
+ signingSecret: null,
31
32
  tenantId: null,
32
33
  appId: null,
33
34
  baseUrl: "https://api.zubbl.com/api",
@@ -55,6 +56,14 @@ function createConfigStore(initial) {
55
56
  if (current.apiKey) {
56
57
  headers.Authorization = `Bearer ${current.apiKey}`;
57
58
  }
59
+ // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch
60
+ if (current.signingSecret) {
61
+ headers["X-Zubbl-Signing-Secret"] = current.signingSecret;
62
+ }
63
+ else if (current.apiKey) {
64
+ // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints
65
+ throw new Error("[Zubbl SDK] Missing signingSecret (required for signed requests)");
66
+ }
58
67
  return headers;
59
68
  }
60
69
  return { init, get, buildHeaders };
@@ -461,9 +470,12 @@ async function httpRequest(url, options = {}) {
461
470
  const apiKey = (headers["Authorization"] || headers["authorization"] || "")
462
471
  .replace(/^Bearer\s+/i, "")
463
472
  .trim();
464
- const signingSecret = (process.env.SDK_SIGNING_SECRET || apiKey || "").trim();
473
+ const signingSecret = headers["X-Zubbl-Signing-Secret"]?.trim() || "";
474
+ if (!apiKey) {
475
+ throw new Error("Missing API key (Authorization: Bearer ...) — cannot send requests");
476
+ }
465
477
  if (!signingSecret) {
466
- throw new Error("Missing API key (Authorization: Bearer ...) — cannot sign requests");
478
+ throw new Error("Missing signing secret — cannot sign requests");
467
479
  }
468
480
  // We must sign the exact bytes we send.
469
481
  // If body is an object, stringify it BEFORE signing AND BEFORE sending.
@@ -494,6 +506,8 @@ async function httpRequest(url, options = {}) {
494
506
  finalOptions.headers = (finalOptions.headers || {});
495
507
  finalOptions.headers["X-Zubbl-Nonce"] = nonce;
496
508
  finalOptions.headers["X-Zubbl-Signature"] = signature;
509
+ // 🔒 Never send the signing secret over the wire (internal-only)
510
+ delete finalOptions.headers["X-Zubbl-Signing-Secret"];
497
511
  // Record adaptive context sample (keep your existing behaviour)
498
512
  recordContextSample("/http", "GET", 200, 123);
499
513
  const response = await fetch(url, finalOptions);
@@ -529,10 +543,24 @@ async function identifyUserFeature(store, { email, name }) {
529
543
  throw new Error("email is required");
530
544
  const config = store.get();
531
545
  const storage = createStorage();
532
- // Check cache
533
- const cached = storage.get(USER_CACHE_KEY);
534
- if (cached?.id) {
535
- return { external_user_id: cached.id, cached: true };
546
+ // Determine override identity (prefer config.identity which SIM sets)
547
+ const cfgIdentity = config?.identity;
548
+ const storeIdentity = store?.identity;
549
+ const overrideEnabled = (cfgIdentity && cfgIdentity.override === true) ||
550
+ (storeIdentity && storeIdentity.override === true);
551
+ const overrideId = overrideEnabled
552
+ ? (cfgIdentity?.id ||
553
+ storeIdentity?.id ||
554
+ store?.externalUserId ||
555
+ store?.userId ||
556
+ undefined)
557
+ : undefined;
558
+ // Check cache (skip cache when override is enabled, we must honour overrideId)
559
+ if (!overrideId) {
560
+ const cached = storage.get(USER_CACHE_KEY);
561
+ if (cached?.id) {
562
+ return { external_user_id: cached.id, cached: true };
563
+ }
536
564
  }
537
565
  const adaptiveHeaders = getAdaptiveHeaders();
538
566
  const geoHeaders = await getGeoHeaders();
@@ -542,20 +570,14 @@ async function identifyUserFeature(store, { email, name }) {
542
570
  ...adaptiveHeaders,
543
571
  ...geoHeaders,
544
572
  });
545
- // ✅ If SIM / consumer provides a stable external user ID, reuse it
546
- const overrideId = store?.identity?.id ||
547
- store?.externalUserId ||
548
- store?.userId ||
549
- undefined;
573
+ // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint
550
574
  const identifyUrl = overrideId
551
575
  ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`
552
576
  : `${config.baseUrl}/sdk/identify`;
553
577
  const resp = await httpRequest(identifyUrl, {
554
578
  method: "POST",
555
579
  headers,
556
- body: JSON.stringify(overrideId
557
- ? { email, name } // backend will reuse path param ID
558
- : { email, name }),
580
+ body: JSON.stringify({ email, name }),
559
581
  });
560
582
  const data = await resp.json().catch(() => ({}));
561
583
  const { external_user_id } = data;
@@ -1 +1 @@
1
- {"version":3,"file":"zubbl-sdk.esm.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n return headers;\n}\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\nconst apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\nconst signingSecret = (process.env.SDK_SIGNING_SECRET || apiKey || \"\").trim();\n\nif (!signingSecret) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot sign requests\");\n}\n\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(`[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`);\n}\n\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n","// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // Check cache\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM / consumer provides a stable external user ID, reuse it\n const overrideId =\n (store as any)?.identity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined;\n\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify(\n overrideId\n ? { email, name } // backend will reuse path param ID\n : { email, name }\n ),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n return { decision: \"allow\", status: resp.status, data: json };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":"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"}
1
+ {"version":3,"file":"zubbl-sdk.esm.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n signingSecret: string | null; // ✅ used for HMAC signing (never sent over the wire)\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n signingSecret: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch\n if (current.signingSecret) {\n headers[\"X-Zubbl-Signing-Secret\"] = current.signingSecret;\n } else if (current.apiKey) {\n // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints\n throw new Error(\"[Zubbl SDK] Missing signingSecret (required for signed requests)\");\n }\n\n return headers;\n }\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\n const apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\n const signingSecret =\n ((headers as any)[\"X-Zubbl-Signing-Secret\"] as string | undefined)?.trim() || \"\";\n\n if (!apiKey) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot send requests\");\n }\n\n if (!signingSecret) {\n throw new Error(\"Missing signing secret — cannot sign requests\");\n }\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // 🔒 Never send the signing secret over the wire (internal-only)\n delete (finalOptions.headers as any)[\"X-Zubbl-Signing-Secret\"];\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(\n `[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`\n );\n }\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n","\n\n// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // ✅ Determine override identity (prefer config.identity which SIM sets)\n const cfgIdentity = (config as any)?.identity;\n const storeIdentity = (store as any)?.identity;\n\n const overrideEnabled =\n (cfgIdentity && cfgIdentity.override === true) ||\n (storeIdentity && storeIdentity.override === true);\n\n const overrideId = overrideEnabled\n ? (cfgIdentity?.id ||\n storeIdentity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined)\n : undefined;\n\n // Check cache (skip cache when override is enabled, we must honour overrideId)\n if (!overrideId) {\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ email, name }),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n signingSecret: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n return { decision: \"allow\", status: resp.status, data: json };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zubbl-sdk",
3
- "version": "1.1.42",
3
+ "version": "1.1.44",
4
4
  "type": "module",
5
5
  "description": "Zubbl SDK for secure policy enforcement (browser, Node, universal)",
6
6
  "main": "dist/zubbl-sdk.cjs.js",