@capxul/sdk 1.2.2 → 1.2.3

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.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { A as OBSERVATION_CONTEXT_HEADER, B as normalizeBindingEmail, C as convexCallErrorFromCapxul, D as bootstrapErrorFromCapxul, E as BootstrapPortTag, F as isSettingUpLifecycle, I as formatTraceparent, L as EXCEPTION_MESSAGE, M as sanitizeObservationContext, N as CAPXUL_FUNCTIONS, O as authClientPortFromPromiseAdapter, P as BootstrapEnvelope, R as captureException, S as ConvexCallPortTag, T as ClockPortTag, U as destination, V as BASE_SEPOLIA_CHAIN_ID, _ as identityErrorFromCapxul, a as redactTelemetryProps, b as markFailureInvocationSnapshot, c as smartAccountErrorFromCapxul, d as fromWei, f as AccountReadPortTag, g as IdentityPortTag, h as wireChainId, j as encodeObservationContextHeader, k as AuthClientPortTag, l as SubAccountPortTag, m as toWei, n as detectAuthCacheAdapter, o as stampTelemetryEnvelope, p as accountReadErrorFromCapxul, r as TelemetryPortTag, s as SmartAccountPortTag, t as assembleCapxulClient, u as subAccountErrorFromCapxul, v as copyInvocationObservation, w as ClockError, x as readInvocationObservation, y as hasFailureInvocationSnapshot, z as captureExceptionSync } from "./create-capxul-client-DVzm78RU.mjs";
2
- import { A as decodeConvexError, C as toJwtToken, D as toRoleKey, E as toPublishableKey, M as EXPECTED_OPERATION_OUTCOMES, N as Errors, O as toSessionToken, P as isCapxulError, S as toEpochSeconds, T as toOrgId, _ as toCountryCode, b as toEmail, d as toAccountId, f as toAddress, g as toChainId, h as toAuthUserId, j as CapxulError, k as toSubAccountId, o as AuthCachePortTag, p as toAllowedOrigin, v as toCurrencyCode, w as toKycTier, x as toEpochMs, y as toDurationMs } from "./InMemoryAuthCacheAdapter-Dr1sEd9y.mjs";
1
+ import { A as version, B as readInvocationObservation, C as convexCallErrorFromCapxul, D as bootstrapErrorFromCapxul, E as BootstrapPortTag, F as BootstrapEnvelope, H as captureExceptionSync, I as EngineeringTelemetryBootstrapPolicy, K as destination, L as isSettingUpLifecycle, M as encodeObservationContextHeader, N as sanitizeObservationContext, O as authClientPortFromPromiseAdapter, P as CAPXUL_FUNCTIONS, R as formatTraceparent, S as ConvexCallPortTag, T as ClockPortTag, U as normalizeBindingEmail, V as captureException, W as BASE_SEPOLIA_CHAIN_ID, _ as accountReadErrorFromCapxul, a as observeFailedResult, b as IdentityPortTag, c as PostHogTelemetryLayer, d as SmartAccountPortTag, f as smartAccountErrorFromCapxul, g as AccountReadPortTag, h as fromWei, i as observationContextProps, j as OBSERVATION_CONTEXT_HEADER, k as AuthClientPortTag, l as TelemetryPortTag, m as subAccountErrorFromCapxul, n as postHogProductTelemetry, o as postHogFailureObservation, p as SubAccountPortTag, r as CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, s as detectAuthCacheAdapter, t as assembleCapxulClient, v as toWei, w as ClockError, x as identityErrorFromCapxul, y as wireChainId, z as copyInvocationObservation } from "./create-capxul-client-BTnlLLag.mjs";
2
+ import { A as decodeConvexError, C as toJwtToken, D as toRoleKey, E as toPublishableKey, N as Errors, O as toSessionToken, P as isCapxulError, S as toEpochSeconds, T as toOrgId, _ as toCountryCode, b as toEmail, d as toAccountId, f as toAddress, g as toChainId, h as toAuthUserId, j as CapxulError, k as toSubAccountId, o as AuthCachePortTag, p as toAllowedOrigin, v as toCurrencyCode, w as toKycTier, x as toEpochMs, y as toDurationMs } from "./InMemoryAuthCacheAdapter-Dr1sEd9y.mjs";
3
3
  import { keccak256, recoverAddress, stringToHex } from "viem";
4
4
  import { Cause, Context, Data, Effect, Exit, Layer, Result, SchemaIssue, SchemaParser, Scope, Tracer } from "effect";
5
5
  import { getFunctionName, makeFunctionReference } from "convex/server";
@@ -304,9 +304,6 @@ async function recoverRawDigestSigner(input) {
304
304
  }
305
305
  }
306
306
  //#endregion
307
- //#region package.json
308
- var version = "1.2.2";
309
- //#endregion
310
307
  //#region ../observability/src/engineering.ts
311
308
  const SAFE_TRACED_HEADER_NAMES = [
312
309
  "content-length",
@@ -346,7 +343,7 @@ const validateEngineeringTelemetryConfig = (config) => {
346
343
  } catch {
347
344
  throw new TypeError("engineering telemetry host must be an absolute HTTPS URL");
348
345
  }
349
- if (url.protocol !== "https:" || url.username.length > 0 || url.password.length > 0 || url.pathname !== "/" || url.search.length > 0 || url.hash.length > 0) throw new TypeError("engineering telemetry host must be a credential-free HTTPS origin");
346
+ if (url.protocol !== "https:" || url.username.length > 0 || url.password.length > 0 || url.pathname !== "/" || url.search.length > 0 || url.hash.length > 0 || !(url.hostname === "posthog.com" || url.hostname.endsWith(".posthog.com"))) throw new TypeError("engineering telemetry host must be a credential-free HTTPS origin");
350
347
  if (!ENGINEERING_CAPXUL_ENVS.has(config.capxulEnv)) throw new TypeError("engineering telemetry capxulEnv is not canonical");
351
348
  if (!ENGINEERING_PRODUCERS.has(config.producer)) throw new TypeError("engineering telemetry producer is not canonical");
352
349
  if (!SAFE_RESOURCE_VALUE.test(config.sdkVersion)) throw new TypeError("engineering telemetry sdkVersion must be a bounded safe value");
@@ -420,10 +417,12 @@ function resolveAuthClientUrl(authBaseUrl, path) {
420
417
  //#endregion
421
418
  //#region src/internal/observation-http.ts
422
419
  /** Resolve one bounded pre-auth snapshot for an outbound SDK HTTP request. */
423
- function observationRequestHeaders(adapter) {
420
+ function observationRequestHeaders(adapter, source) {
424
421
  if (adapter === void 0) return {};
425
422
  try {
426
- const encoded = encodeObservationContextHeader(adapter.resolveContext?.());
423
+ const invocation = readInvocationObservation(source);
424
+ if (invocation !== void 0 && !invocation.active) return {};
425
+ const encoded = encodeObservationContextHeader(invocation === void 0 ? adapter.resolveContext?.() : invocation.context);
427
426
  return encoded === void 0 ? {} : { [OBSERVATION_CONTEXT_HEADER]: encoded };
428
427
  } catch {
429
428
  return {};
@@ -519,7 +518,7 @@ var BetterAuthBrowserAdapter = class {
519
518
  method: "POST",
520
519
  headers: {
521
520
  "Content-Type": "application/json",
522
- ...observationRequestHeaders(this.observation)
521
+ ...observationRequestHeaders(this.observation, input)
523
522
  },
524
523
  body: JSON.stringify({
525
524
  email: input.email,
@@ -937,7 +936,7 @@ var BetterAuthNodeAdapter = class {
937
936
  headers: {
938
937
  "content-type": "application/json",
939
938
  ...this.origin ? { origin: this.origin } : {},
940
- ...observationRequestHeaders(this.observation)
939
+ ...observationRequestHeaders(this.observation, input)
941
940
  },
942
941
  body: JSON.stringify({
943
942
  email: input.email,
@@ -1192,20 +1191,28 @@ var HttpBootstrapAdapter = class {
1192
1191
  if (res.ok) return Effect.tryPromise({
1193
1192
  try: async () => {
1194
1193
  const body = await res.json();
1195
- const decoded = SchemaParser.decodeUnknownResult(BootstrapEnvelope)(body);
1194
+ const state = typeof body === "object" && body !== null && "state" in body && typeof body.state === "object" && body.state !== null ? body.state : void 0;
1195
+ const rawEngineeringTelemetry = state?.engineeringTelemetry;
1196
+ const baseBody = state === void 0 || rawEngineeringTelemetry === void 0 ? body : {
1197
+ ...body,
1198
+ state: Object.fromEntries(Object.entries(state).filter(([key]) => key !== "engineeringTelemetry"))
1199
+ };
1200
+ const decoded = SchemaParser.decodeUnknownResult(BootstrapEnvelope)(baseBody);
1196
1201
  if (Result.isFailure(decoded)) throw Errors.invalidInput("bootstrapEnvelope", SchemaIssue.makeFormatterDefault()(decoded.failure));
1197
- const { state } = decoded.success;
1202
+ const { state: decodedState } = decoded.success;
1203
+ const decodedEngineeringTelemetry = rawEngineeringTelemetry === void 0 ? void 0 : SchemaParser.decodeUnknownResult(EngineeringTelemetryBootstrapPolicy)(rawEngineeringTelemetry, { onExcessProperty: "error" });
1198
1204
  return {
1199
- applicationId: state.applicationId,
1200
- chainId: state.chainId,
1201
- sessionToken: state.sessionToken,
1202
- issuedAt: state.issuedAt,
1203
- expiresIn: state.expiresIn,
1204
- authBaseUrl: normalizeRuntimeUrl("authBaseUrl", state.authBaseUrl),
1205
- convexUrl: normalizeRuntimeUrl("convexUrl", state.convexUrl),
1206
- siteBaseUrl: normalizeRuntimeUrl("siteBaseUrl", state.siteBaseUrl),
1207
- openfortPublishableKey: state.openfortPublishableKey,
1208
- shieldPublishableKey: state.shieldPublishableKey
1205
+ applicationId: decodedState.applicationId,
1206
+ chainId: decodedState.chainId,
1207
+ sessionToken: decodedState.sessionToken,
1208
+ issuedAt: decodedState.issuedAt,
1209
+ expiresIn: decodedState.expiresIn,
1210
+ authBaseUrl: normalizeRuntimeUrl("authBaseUrl", decodedState.authBaseUrl),
1211
+ convexUrl: normalizeRuntimeUrl("convexUrl", decodedState.convexUrl),
1212
+ siteBaseUrl: normalizeRuntimeUrl("siteBaseUrl", decodedState.siteBaseUrl),
1213
+ openfortPublishableKey: decodedState.openfortPublishableKey,
1214
+ shieldPublishableKey: decodedState.shieldPublishableKey,
1215
+ ...decodedEngineeringTelemetry !== void 0 && Result.isSuccess(decodedEngineeringTelemetry) ? { engineeringTelemetry: decodedEngineeringTelemetry.success } : {}
1209
1216
  };
1210
1217
  },
1211
1218
  catch: (cause) => {
@@ -1631,7 +1638,6 @@ var ConvexSmartAccountAdapter = class {
1631
1638
  return this.#convex.action(this.#fns.confirmDeployment, {
1632
1639
  chainId: wireChainId(input.chainId),
1633
1640
  safeAddress: input.safeAddress,
1634
- ...input.telemetryRunId === void 0 ? {} : { telemetryRunId: input.telemetryRunId },
1635
1641
  evidence
1636
1642
  }).pipe(Effect.mapError((error) => smartAccountErrorFromCapxul("confirmDeployment", error.publicError, error)), Effect.flatMap((row) => Effect.try({
1637
1643
  try: () => brandProvisionedSmartAccount(input.authUserId, row),
@@ -1641,8 +1647,7 @@ var ConvexSmartAccountAdapter = class {
1641
1647
  claim(input) {
1642
1648
  return this.#convex.action(this.#fns.claim, copyInvocationObservation(input, {
1643
1649
  chainId: wireChainId(input.chainId),
1644
- signerAddress: input.signerAddress,
1645
- ...input.telemetryRunId === void 0 ? {} : { telemetryRunId: input.telemetryRunId }
1650
+ signerAddress: input.signerAddress
1646
1651
  })).pipe(Effect.mapError((error) => smartAccountErrorFromCapxul("claim", error.publicError, error)), Effect.flatMap((row) => Effect.try({
1647
1652
  try: () => brandProvisionedSmartAccount(input.authUserId, row),
1648
1653
  catch: (cause) => smartAccountErrorFromUnknown("claim", cause)
@@ -2154,90 +2159,6 @@ function fail(error) {
2154
2159
  };
2155
2160
  }
2156
2161
  //#endregion
2157
- //#region src/adapters/telemetry/PostHogTelemetryAdapter.ts
2158
- var PostHogTelemetryAdapter = class {
2159
- #capture;
2160
- #identify;
2161
- #group;
2162
- #reset;
2163
- constructor(deps) {
2164
- this.#capture = deps.capture;
2165
- this.#identify = deps.identify ?? (() => void 0);
2166
- this.#group = deps.group ?? (() => void 0);
2167
- this.#reset = deps.reset ?? (() => void 0);
2168
- }
2169
- emit(event) {
2170
- return this.#run(() => this.#capture(event.name, redactTelemetryProps(event.name, cloneProps(event.props))), "emit", event.name);
2171
- }
2172
- identify(input) {
2173
- return this.#run(() => this.#identify(cloneIdentifyInput(input)), "identify");
2174
- }
2175
- group(input) {
2176
- return this.#run(() => this.#group(cloneGroupInput(input)), "group");
2177
- }
2178
- reset() {
2179
- return this.#run(() => this.#reset(), "reset");
2180
- }
2181
- #run(operation, operationName, eventName) {
2182
- const diagnose = Effect.logWarning("product.telemetry.transport.dropped").pipe(Effect.annotateLogs({
2183
- operation: operationName,
2184
- ...eventName === void 0 ? {} : { product_event: eventName }
2185
- }), Effect.catchCause(() => Effect.void));
2186
- return Effect.suspend(() => {
2187
- let pending;
2188
- try {
2189
- pending = operation();
2190
- } catch {
2191
- return diagnose;
2192
- }
2193
- if (pending === void 0) return Effect.void;
2194
- const transport = Effect.tryPromise({
2195
- try: () => pending,
2196
- catch: () => void 0
2197
- }).pipe(Effect.catch(() => diagnose));
2198
- return Effect.forkDetach(transport, { startImmediately: true }).pipe(Effect.asVoid);
2199
- });
2200
- }
2201
- };
2202
- function PostHogTelemetryLayer(deps) {
2203
- return Layer.succeed(TelemetryPortTag, new PostHogTelemetryAdapter(deps));
2204
- }
2205
- function cloneIdentifyInput(input) {
2206
- const traits = input.traits === void 0 ? void 0 : cloneProps(input.traits);
2207
- const properties = input.properties === void 0 ? void 0 : cloneProps(input.properties);
2208
- return {
2209
- distinctId: input.distinctId,
2210
- ...input.anonDistinctId === void 0 ? {} : { anonDistinctId: input.anonDistinctId },
2211
- ...traits === void 0 ? {} : { traits },
2212
- ...properties === void 0 ? {} : { properties }
2213
- };
2214
- }
2215
- function cloneGroupInput(input) {
2216
- const properties = input.properties === void 0 ? void 0 : cloneProps(input.properties);
2217
- return properties === void 0 ? {
2218
- groupType: input.groupType,
2219
- groupKey: input.groupKey
2220
- } : {
2221
- groupType: input.groupType,
2222
- groupKey: input.groupKey,
2223
- properties
2224
- };
2225
- }
2226
- function cloneProps(props) {
2227
- if (props === void 0) return void 0;
2228
- const cloned = {};
2229
- for (const [key, value] of Object.entries(props)) cloned[key] = cloneTelemetryValue(value);
2230
- return cloned;
2231
- }
2232
- function cloneTelemetryValue(value) {
2233
- if (Array.isArray(value)) return value.map(cloneTelemetryValue);
2234
- if (value === null || typeof value !== "object") return value;
2235
- if (Object.getPrototypeOf(value) !== Object.prototype) return value;
2236
- const cloned = {};
2237
- for (const [key, nested] of Object.entries(value)) cloned[key] = cloneTelemetryValue(nested);
2238
- return cloned;
2239
- }
2240
- //#endregion
2241
2162
  //#region src/adapters/diagnostic/ConsoleDiagnosticAdapter.ts
2242
2163
  const DEFAULT_ACCOUNT_SETUP_LOG_PREFIX = "[capxul:account-setup]";
2243
2164
  var ConsoleDiagnosticAdapter = class {
@@ -2497,220 +2418,73 @@ function normalizeBetterAuthBaseUrl(raw) {
2497
2418
  return trimmed.endsWith("/api/auth") ? trimmed : `${trimmed}/api/auth`;
2498
2419
  }
2499
2420
  //#endregion
2500
- //#region src/observation.ts
2501
- const SDK_VERSION$1 = version;
2502
- /** Stable PostHog event used for typed failures that are expected product outcomes. */
2503
- const CAPXUL_SDK_EXPECTED_OUTCOME_EVENT = "capxul_sdk_expected_outcome";
2504
- /**
2505
- * Adapt the host's already-initialized PostHog-like client. This function does
2506
- * not import, initialize, configure, or own PostHog.
2507
- */
2508
- function fromPostHog(client, options = {}) {
2509
- const prepare = (failure) => {
2510
- if (!isEnabled(options.enabled)) return;
2511
- if (client === null || client === void 0) return;
2512
- const safeFailure = sanitizeFailureObservation(failure);
2513
- return [safeFailure, postHogProperties(safeFailure, hasFailureInvocationSnapshot(failure) ? void 0 : resolveContext(options.context))];
2514
- };
2515
- const captureOperationFailure = (failure) => {
2516
- const prepared = prepare(failure);
2517
- if (prepared === void 0 || client === null || client === void 0) return;
2518
- const [safeFailure, properties] = prepared;
2519
- if (classifyOperationOutcome(safeFailure.errorKind) === "expected") {
2520
- if (typeof client.capture !== "function") return;
2521
- deliver(() => client.capture(CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, {
2522
- ...properties,
2523
- outcome_class: "expected"
2524
- }));
2525
- return;
2421
+ //#region src/host-observability.ts
2422
+ const HOST_INVOCATION = Symbol("capxul.host-observability-invocation");
2423
+ /** Build the SDK's one host module around an already-initialized PostHog client. */
2424
+ function postHogObservability(client, options = {}) {
2425
+ const inactive = Object.freeze({
2426
+ active: false,
2427
+ contextProps: Object.freeze({})
2428
+ });
2429
+ const snapshot = () => {
2430
+ if (client === null || client === void 0) return inactive;
2431
+ try {
2432
+ if (!(typeof options.enabled === "function" ? options.enabled() : options.enabled ?? true)) return inactive;
2433
+ const sanitized = sanitizeObservationContext(typeof options.context === "function" ? options.context() : options.context);
2434
+ const context = sanitized === void 0 ? void 0 : Object.freeze({ ...sanitized });
2435
+ return Object.freeze({
2436
+ active: true,
2437
+ ...context === void 0 ? {} : { context },
2438
+ contextProps: Object.freeze(observationContextProps(context))
2439
+ });
2440
+ } catch {
2441
+ return inactive;
2526
2442
  }
2527
- deliver(() => client.capture("$exception", postHogExceptionProperties(safeFailure, properties)));
2528
- };
2529
- const captureException = (failure) => {
2530
- const prepared = prepare(failure);
2531
- if (prepared === void 0 || client === null || client === void 0) return;
2532
- const [safeFailure, properties] = prepared;
2533
- deliver(() => client.capture("$exception", postHogExceptionProperties(safeFailure, properties)));
2534
2443
  };
2535
- return {
2536
- resolveContext: () => {
2537
- if (!isEnabled(options.enabled) || client === null || client === void 0) return void 0;
2538
- return resolveRawContext(options.context) ?? {};
2539
- },
2540
- captureOperationFailure,
2541
- captureException
2444
+ const policy = {
2445
+ client,
2446
+ capxulEnv: options.capxulEnv ?? "unknown",
2447
+ snapshot,
2448
+ deliver: (capture) => {
2449
+ try {
2450
+ const delivery = capture();
2451
+ if (isPromiseLike(delivery)) Promise.resolve(delivery).catch(() => void 0);
2452
+ } catch {}
2453
+ }
2542
2454
  };
2543
- }
2544
- function classifyOperationOutcome(kind) {
2545
- return EXPECTED_OPERATION_OUTCOMES.has(kind) ? "expected" : "unexpected";
2546
- }
2547
- function deliver(capture) {
2548
- try {
2549
- ignoreDeliveryFailure(capture());
2550
- } catch {}
2551
- }
2552
- /** @internal Reports a factory-level typed failure without changing its identity. */
2553
- function observeFailedResult(result, adapter, operation) {
2554
- if (adapter !== void 0 && isFailedResult(result)) report(adapter, "operation", operation, result.error, resolveAdapterContext(adapter));
2555
- return result;
2556
- }
2557
- function report(adapter, kind, operation, cause, invocationContext) {
2558
- const operationName = normalizeOperation(operation);
2559
- const kindName = normalizeErrorKind(errorKind(cause));
2560
- const context = sanitizeObservationContext({
2561
- ...invocationContext,
2562
- ...isCapxulError(cause) && cause.correlationId !== void 0 ? { correlationId: cause.correlationId } : {}
2563
- });
2564
- const failure = markFailureInvocationSnapshot({
2565
- exception: syntheticException(operationName, kindName),
2566
- sdkVersion: SDK_VERSION$1,
2567
- operation: operationName,
2568
- errorKind: kindName,
2569
- ...context === void 0 ? {} : { context }
2570
- });
2571
- try {
2572
- ignoreDeliveryFailure(kind === "operation" ? adapter.captureOperationFailure(failure) : adapter.captureException(failure));
2573
- } catch {}
2574
- }
2575
- function resolveAdapterContext(adapter) {
2576
- try {
2577
- return adapter.resolveContext?.();
2578
- } catch {
2579
- return;
2580
- }
2581
- }
2582
- function ignoreDeliveryFailure(delivery) {
2583
- if (!isPromiseLike(delivery)) return;
2584
- try {
2585
- Promise.resolve(delivery).catch(() => void 0);
2586
- } catch {}
2587
- }
2588
- /**
2589
- * Map an ALREADY-sanitized observation context to the snake_case PostHog
2590
- * property keys. Shared by the failure boundary here and the host
2591
- * success-telemetry seam (`telemetry/from-posthog.ts`) so both attach identical
2592
- * correlation fields from one definition.
2593
- */
2594
- function observationContextProps(context) {
2595
- const props = {};
2596
- if (context?.application !== void 0) props.application = context.application;
2597
- if (context?.release !== void 0) props.release = context.release;
2598
- if (context?.sessionId !== void 0) props.session_id = context.sessionId;
2599
- if (context?.organizationId !== void 0) props.organization_id = context.organizationId;
2600
- if (context?.journeyId !== void 0) props.journey_id = context.journeyId;
2601
- if (context?.correlationId !== void 0) props.correlation_id = context.correlationId;
2602
- if (context?.anonymousId !== void 0) props.anonymous_id = context.anonymousId;
2603
- return props;
2604
- }
2605
- function postHogProperties(failure, context) {
2606
- const merged = sanitizeObservationContext({
2607
- ...context,
2608
- ...failure.context
2609
- });
2610
- return {
2611
- sdk_version: failure.sdkVersion,
2612
- operation: failure.operation,
2613
- error_kind: failure.errorKind,
2614
- handled: true,
2615
- ...observationContextProps(merged)
2455
+ const module = {
2456
+ failures: postHogFailureObservation(policy),
2457
+ product: postHogProductTelemetry(policy)
2616
2458
  };
2617
- }
2618
- function postHogExceptionProperties(failure, properties) {
2619
- const filename = `capxul-sdk-observation://boundary/${failure.operation}`;
2620
- return {
2621
- ...properties,
2622
- $exception_type: failure.errorKind,
2623
- $exception_message: EXCEPTION_MESSAGE,
2624
- $exception_level: "error",
2625
- $exception_list: [{
2626
- type: failure.errorKind,
2627
- value: EXCEPTION_MESSAGE,
2628
- mechanism: {
2629
- type: "capxul_sdk_boundary",
2630
- handled: true,
2631
- synthetic: true
2459
+ Object.defineProperty(module, HOST_INVOCATION, {
2460
+ enumerable: false,
2461
+ value: {
2462
+ bind: () => {
2463
+ const invocation = snapshot();
2464
+ return {
2465
+ failures: postHogFailureObservation(policy, invocation),
2466
+ product: postHogProductTelemetry(policy, invocation)
2467
+ };
2632
2468
  },
2633
- stacktrace: {
2634
- type: "raw",
2635
- frames: [{
2636
- platform: "javascript",
2637
- filename,
2638
- function: `CapxulSdkBoundary.${failure.operation}`,
2639
- lineno: 1,
2640
- colno: 1,
2641
- in_app: true
2642
- }]
2643
- }
2644
- }]
2645
- };
2646
- }
2647
- function resolveContext(context) {
2648
- return sanitizeObservationContext(resolveRawContext(context));
2649
- }
2650
- /** Resolve the host context closure without sanitizing — the call-start snapshot. */
2651
- function resolveRawContext(context) {
2652
- try {
2653
- return typeof context === "function" ? context() : context;
2654
- } catch {
2655
- return;
2656
- }
2657
- }
2658
- function isEnabled(enabled) {
2659
- try {
2660
- return typeof enabled === "function" ? enabled() : enabled ?? true;
2661
- } catch {
2662
- return false;
2663
- }
2664
- }
2665
- function errorKind(cause) {
2666
- try {
2667
- if (isCapxulError(cause)) return normalizeErrorKind(cause.code);
2668
- if (cause instanceof Error) return normalizeErrorKind(cause.name);
2669
- return "UnknownFailure";
2670
- } catch {
2671
- return "Error";
2672
- }
2673
- }
2674
- function sanitizeFailureObservation(failure) {
2675
- const operation = normalizeOperation(failure.operation);
2676
- const kind = normalizeErrorKind(failure.errorKind);
2677
- const context = sanitizeObservationContext(failure.context);
2678
- return {
2679
- exception: syntheticException(operation, kind),
2680
- sdkVersion: normalizeSdkVersion(failure.sdkVersion),
2681
- operation,
2682
- errorKind: kind,
2683
- ...context === void 0 ? {} : { context }
2469
+ snapshot
2470
+ }
2471
+ });
2472
+ return module;
2473
+ }
2474
+ /** @internal Bind both projections to one call-start decision/context snapshot. */
2475
+ function bindHostObservabilityInvocation(observability) {
2476
+ return observability?.[HOST_INVOCATION]?.bind() ?? observability;
2477
+ }
2478
+ /** @internal Read one call-start snapshot for actor/transition carriage. */
2479
+ function snapshotHostObservability(observability) {
2480
+ const snapshot = observability?.[HOST_INVOCATION]?.snapshot();
2481
+ return snapshot === void 0 ? void 0 : {
2482
+ active: snapshot.active,
2483
+ ...snapshot.context === void 0 ? {} : { context: snapshot.context }
2684
2484
  };
2685
2485
  }
2686
- function normalizeSdkVersion(value) {
2687
- return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9.+_-]{0,127}$/u.test(value) ? value : "unknown";
2688
- }
2689
- function normalizeOperation(value) {
2690
- return typeof value === "string" && /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,255}$/u.test(value) ? value : "unknown";
2691
- }
2692
- function normalizeErrorKind(value) {
2693
- return typeof value === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/u.test(value) ? value : "Error";
2694
- }
2695
- function syntheticException(operation, kind) {
2696
- const error = new Error(EXCEPTION_MESSAGE);
2697
- error.name = kind;
2698
- error.stack = `${kind}: ${error.message}\n at CapxulSdkBoundary.${operation} (capxul-sdk-observation://boundary/${operation}:1:1)`;
2699
- return error;
2700
- }
2701
2486
  function isPromiseLike(value) {
2702
- return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
2703
- }
2704
- function isPlainObject(value) {
2705
- if (typeof value !== "object" || value === null) return false;
2706
- const prototype = Object.getPrototypeOf(value);
2707
- return prototype === Object.prototype || prototype === null;
2708
- }
2709
- function isCapxulResult(value) {
2710
- return isPlainObject(value) && typeof value.ok === "boolean";
2711
- }
2712
- function isFailedResult(value) {
2713
- return isCapxulResult(value) && value.ok === false && "error" in value;
2487
+ return (typeof value === "object" && value !== null || typeof value === "function") && "then" in value;
2714
2488
  }
2715
2489
  const SDK_VERSION = version;
2716
2490
  /**
@@ -2863,7 +2637,19 @@ function productionConvexCallLayer(input, refreshConvexAuthRef) {
2863
2637
  function isRefreshableConvexCallPort(convexCall) {
2864
2638
  return "refreshAuth" in convexCall && typeof convexCall.refreshAuth === "function";
2865
2639
  }
2640
+ function resolveProductionObservability(input) {
2641
+ const observation = input.observability?.failures ?? input.observation;
2642
+ const telemetry = input.observability?.product ?? input.telemetry;
2643
+ const invocationObservability = input.invocationObservability;
2644
+ return {
2645
+ observation,
2646
+ telemetry,
2647
+ invocationObservation: invocationObservability?.failures ?? observation,
2648
+ invocationTelemetry: invocationObservability?.product ?? telemetry
2649
+ };
2650
+ }
2866
2651
  async function createProductionAdapters(input) {
2652
+ const { observation, telemetry, invocationObservation, invocationTelemetry } = resolveProductionObservability(input);
2867
2653
  const resolvedInput = resolveInput(input);
2868
2654
  if (!resolvedInput.ok) return resolvedInput;
2869
2655
  const scope = await Effect.runPromise(Scope.make());
@@ -2871,7 +2657,7 @@ async function createProductionAdapters(input) {
2871
2657
  const bootstrapLayer = HttpBootstrapLayer({
2872
2658
  bootstrapBaseUrl: resolvedInput.value.bootstrapBaseUrl,
2873
2659
  ...input.fetch === void 0 ? {} : { fetch: input.fetch },
2874
- ...input.observation === void 0 ? {} : { observation: input.observation }
2660
+ ...invocationObservation === void 0 ? {} : { observation: invocationObservation }
2875
2661
  });
2876
2662
  try {
2877
2663
  const bootstrapContext = await Effect.runPromise(Layer.buildWithScope(bootstrapLayer, scope));
@@ -2881,7 +2667,7 @@ async function createProductionAdapters(input) {
2881
2667
  ...resolvedInput.value.origin === void 0 ? {} : { origin: resolvedInput.value.origin }
2882
2668
  }));
2883
2669
  if (!bootstrapResult.ok) {
2884
- await emitBootstrapTelemetry(input.telemetry, {
2670
+ await emitBootstrapTelemetry(invocationTelemetry, {
2885
2671
  name: "bootstrap_failed",
2886
2672
  props: {
2887
2673
  ...bootstrapTelemetryEnvelope(input, resolvedInput.value),
@@ -2898,7 +2684,7 @@ async function createProductionAdapters(input) {
2898
2684
  }
2899
2685
  const runtimeUrlsResult = resolveRuntimeUrls(bootstrapResult.value, resolvedInput.value.runtime, input.authBaseUrl);
2900
2686
  if (!runtimeUrlsResult.ok) {
2901
- await emitBootstrapTelemetry(input.telemetry, {
2687
+ await emitBootstrapTelemetry(invocationTelemetry, {
2902
2688
  name: "bootstrap_failed",
2903
2689
  props: {
2904
2690
  ...bootstrapTelemetryEnvelope(input, resolvedInput.value),
@@ -2910,7 +2696,7 @@ async function createProductionAdapters(input) {
2910
2696
  return runtimeUrlsResult;
2911
2697
  }
2912
2698
  const runtimeUrls = runtimeUrlsResult;
2913
- await emitBootstrapTelemetry(input.telemetry, {
2699
+ await emitBootstrapTelemetry(invocationTelemetry, {
2914
2700
  name: "bootstrap_resolved",
2915
2701
  props: {
2916
2702
  ...bootstrapTelemetryEnvelope(input, resolvedInput.value),
@@ -2935,19 +2721,15 @@ async function createProductionAdapters(input) {
2935
2721
  runtimeUrls: runtimeUrls.value,
2936
2722
  chainId: bootstrapResult.value.chainId,
2937
2723
  applicationId: bootstrapResult.value.applicationId,
2938
- ...input.observation === void 0 ? {} : { observation: input.observation },
2724
+ ...observation === void 0 ? {} : { observation },
2939
2725
  ...input.authCache === void 0 ? {} : { authCache: input.authCache },
2940
- ...input.telemetry === void 0 ? {} : { telemetry: input.telemetry },
2726
+ ...telemetry === void 0 ? {} : { telemetry },
2941
2727
  ...injectedClient === void 0 ? {} : { convexClient: injectedClient },
2942
2728
  ...input.fetch === void 0 ? {} : { fetch: input.fetch },
2943
2729
  ...input.signal === void 0 ? {} : { signal: input.signal },
2944
2730
  ...input.resetSignerSession === void 0 ? {} : { resetSignerSession: input.resetSignerSession }
2945
2731
  }));
2946
- const applicationLayer = input.engineeringTelemetry === void 0 ? portsLayer : Layer.merge(portsLayer, makeEngineeringTelemetryLayer({
2947
- ...input.engineeringTelemetry,
2948
- producer: resolvedInput.value.runtime === "browser" ? "browser" : "server",
2949
- sdkVersion: SDK_VERSION
2950
- }));
2732
+ const applicationLayer = Layer.merge(portsLayer, optionalEngineeringTelemetryLayer(bootstrapResult.value.engineeringTelemetry, resolvedInput.value.runtime));
2951
2733
  const context = await Effect.runPromise(Layer.buildWithScope(applicationLayer, scope));
2952
2734
  return {
2953
2735
  ok: true,
@@ -2966,6 +2748,20 @@ async function createProductionAdapters(input) {
2966
2748
  };
2967
2749
  }
2968
2750
  }
2751
+ function optionalEngineeringTelemetryLayer(policy, runtime) {
2752
+ if (policy === void 0) return Layer.empty;
2753
+ try {
2754
+ return makeEngineeringTelemetryLayer({
2755
+ host: policy.host,
2756
+ headers: { authorization: `Bearer ${policy.projectToken}` },
2757
+ capxulEnv: policy.capxulEnv,
2758
+ producer: runtime === "browser" ? "browser" : "server",
2759
+ sdkVersion: SDK_VERSION
2760
+ });
2761
+ } catch {
2762
+ return Layer.empty;
2763
+ }
2764
+ }
2969
2765
  function refreshConvexAuthOnSession(authClient, refresh) {
2970
2766
  return {
2971
2767
  ...authClient,
@@ -2995,14 +2791,17 @@ function resetSignerSessionOnSignOut(authClient, resetRef) {
2995
2791
  };
2996
2792
  }
2997
2793
  async function createCapxulClient$1(input) {
2794
+ const invocationObservability = bindHostObservabilityInvocation(input.observability);
2795
+ const observation = invocationObservability?.failures ?? input.observation;
2998
2796
  const validation = validateCreateCapxulClientInput(input);
2999
- if (!validation.ok) return observeFailedResult(validation, input.observation, "createCapxulClient");
2797
+ if (!validation.ok) return observeFailedResult(validation, observation, "createCapxulClient");
3000
2798
  const resetSignerSession = { current: null };
3001
2799
  const adapters = await createProductionAdapters({
3002
2800
  ...input,
3003
- resetSignerSession
2801
+ resetSignerSession,
2802
+ ...invocationObservability === void 0 ? {} : { invocationObservability }
3004
2803
  });
3005
- if (!adapters.ok) return observeFailedResult(adapters, input.observation, "createCapxulClient");
2804
+ if (!adapters.ok) return observeFailedResult(adapters, observation, "createCapxulClient");
3006
2805
  try {
3007
2806
  const runtime = input.runtime ?? detectRuntime();
3008
2807
  const resolvedAuthBaseUrl = resolveBrowserAuthBaseUrl({
@@ -3039,6 +2838,7 @@ async function createCapxulClient$1(input) {
3039
2838
  ...input.signal === void 0 ? {} : { signal: input.signal },
3040
2839
  ...input.otpTtlMs === void 0 ? {} : { otpTtlMs: input.otpTtlMs },
3041
2840
  invokeTimeoutMs: input.invokeTimeoutMs ?? 3e4,
2841
+ ...input.observability === void 0 ? {} : { hostObservationSnapshot: () => snapshotHostObservability(input.observability) },
3042
2842
  effectRunner: {
3043
2843
  runSync: Effect.runSyncWith(adapters.value.context),
3044
2844
  runPromise: Effect.runPromiseWith(adapters.value.context)
@@ -3067,7 +2867,7 @@ async function createCapxulClient$1(input) {
3067
2867
  return observeFailedResult({
3068
2868
  ok: false,
3069
2869
  error: toPublicError(cause, "createCapxulClient")
3070
- }, input.observation, "createCapxulClient");
2870
+ }, observation, "createCapxulClient");
3071
2871
  }
3072
2872
  }
3073
2873
  function validateCreateCapxulClientInput(input) {
@@ -3216,80 +3016,6 @@ async function createCapxulClient(input) {
3216
3016
  return createCapxulClient$1(input);
3217
3017
  }
3218
3018
  //#endregion
3219
- //#region src/telemetry/from-posthog.ts
3220
- /**
3221
- * Drop props that must never cross to a host-owned external sink. Today that is
3222
- * the `$exception` `details` blob: `captureException` serializes
3223
- * `CapxulError.details` (e.g. `{ asset, available, required }`, `{ name }`,
3224
- * `{ accountId }` — errors.ts) into it, and the shared redactor has no
3225
- * `$exception` rule, so it is stripped here at the boundary (infra#1037). The
3226
- * safe fields (error code, operation, failure_mode, the fixed leak-safe message,
3227
- * stack frames) are preserved.
3228
- */
3229
- function stripHostUnsafeProps(props) {
3230
- if (props === void 0) return void 0;
3231
- const { details: _details, ...safe } = props;
3232
- return safe;
3233
- }
3234
- /**
3235
- * Adapt the host's already-initialized posthog-like client into a
3236
- * `TelemetryPort` for the `telemetry` prop / input. This port SUPPLANTS the
3237
- * SDK's no-op default telemetry sink (`production.ts` binds it via
3238
- * `Layer.succeed`, not `compose` — there is no client-side success relay to
3239
- * compose with); it is additive to Capxul's backend first-party record and
3240
- * never owns the client.
3241
- */
3242
- function telemetryFromPostHog(client, options = {}) {
3243
- const active = () => {
3244
- if (client === null || client === void 0) return false;
3245
- try {
3246
- return typeof options.enabled === "function" ? options.enabled() : options.enabled ?? true;
3247
- } catch {
3248
- return false;
3249
- }
3250
- };
3251
- const contextProps = () => {
3252
- let raw;
3253
- try {
3254
- raw = typeof options.context === "function" ? options.context() : options.context;
3255
- } catch {
3256
- return {};
3257
- }
3258
- return observationContextProps(sanitizeObservationContext(raw));
3259
- };
3260
- return new PostHogTelemetryAdapter({
3261
- capture: (name, props) => {
3262
- if (!active() || client === null || client === void 0) return;
3263
- const event = stampTelemetryEnvelope({
3264
- name,
3265
- props
3266
- }, {
3267
- capxul_env: options.capxulEnv ?? "unknown",
3268
- producer: "sdk"
3269
- });
3270
- client.capture(name, {
3271
- ...stripHostUnsafeProps(event.props),
3272
- ...contextProps()
3273
- });
3274
- },
3275
- identify: (input) => {
3276
- if (!active() || client?.identify === void 0) return;
3277
- client.identify(input.distinctId, {
3278
- ...input.traits,
3279
- ...input.properties
3280
- });
3281
- },
3282
- group: (input) => {
3283
- if (!active() || client?.group === void 0) return;
3284
- client.group(input.groupType, input.groupKey, input.properties === void 0 ? void 0 : { ...input.properties });
3285
- },
3286
- reset: () => {
3287
- if (!active() || client?.reset === void 0) return;
3288
- client.reset();
3289
- }
3290
- });
3291
- }
3292
- //#endregion
3293
- export { CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, CapxulError, captureException, captureExceptionSync, createCapxulClient, deriveDevPrivateKey, devPrivateKeySigner, eip1193AccountProvider, embeddedSigner, fromPostHog, injectedWalletSigner, isCapxulError, isSettingUpLifecycle, localPrivateKeyAccountProvider, openfortEmbeddedSigner, openfortEmbeddedSignerFromWallet, openfortEmbeddedWalletPort, destination as resolveIdentityDestination, telemetryFromPostHog, toCountryCode, toAddress as toEvmAddress };
3019
+ export { CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, CapxulError, captureException, captureExceptionSync, createCapxulClient, deriveDevPrivateKey, devPrivateKeySigner, eip1193AccountProvider, embeddedSigner, injectedWalletSigner, isCapxulError, isSettingUpLifecycle, localPrivateKeyAccountProvider, openfortEmbeddedSigner, openfortEmbeddedSignerFromWallet, openfortEmbeddedWalletPort, postHogObservability, destination as resolveIdentityDestination, toCountryCode, toAddress as toEvmAddress };
3294
3020
 
3295
3021
  //# sourceMappingURL=index.mjs.map