@capxul/sdk 2.8.0 → 2.8.2

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,4 +1,4 @@
1
- import { A as toPartyId, B as Errors, G as failureFingerprint, H as CHAIN_UPSTREAMS, K as isFailureMode, M as toPayrollRunId, P as toRoleKey, R as CapxulError, S as toCurrencyCode, U as FAILURE_MODES$1, V as isCapxulError, W as chainCauseProperties, b as toChainId, c as BYTES32_RE, d as WEI_RE, f as ZERO_BYTES32, h as toAddress, j as toPayrollGroupId, k as toOrgId, l as EVM_ADDRESS_RE$1, m as toAccountId, n as BrowserAuthCacheAdapter, q as revertSummaryText, s as APP_ID_RE, t as InMemoryAuthCacheAdapter, u as SUPPORTED_CURRENCY_CODES, v as toAuthUserId, w as toEmail, x as toCountryCode, y as toBudgetId, z as EXPECTED_OPERATION_OUTCOMES } from "./InMemoryAuthCacheAdapter-FptQ2p7C.mjs";
1
+ import { A as toPartyId, B as Errors, G as decodeChainCause, H as CHAIN_UPSTREAMS, J as revertSummaryText, K as failureFingerprint, L as CAPXUL_ERROR_CODES, M as toPayrollRunId, P as toRoleKey, R as CapxulError, S as toCurrencyCode, U as FAILURE_MODES$1, V as isCapxulError, W as chainCauseProperties, b as toChainId, c as BYTES32_RE, d as WEI_RE, f as ZERO_BYTES32, h as toAddress, j as toPayrollGroupId, k as toOrgId, l as EVM_ADDRESS_RE$1, m as toAccountId, n as BrowserAuthCacheAdapter, q as isFailureMode, s as APP_ID_RE, t as InMemoryAuthCacheAdapter, u as SUPPORTED_CURRENCY_CODES, v as toAuthUserId, w as toEmail, x as toCountryCode, y as toBudgetId, z as EXPECTED_OPERATION_OUTCOMES } from "./InMemoryAuthCacheAdapter-BrEN-men.mjs";
2
2
  import { concat, encodeAbiParameters, encodeFunctionData, encodePacked, formatUnits, getContractAddress, keccak256, padHex, parseUnits, recoverAddress, stringToHex, toBytes, toEventSelector, toFunctionSelector, toFunctionSignature } from "viem";
3
3
  import { Context, Data, Deferred, Duration, Effect, Exit, Fiber, Layer, Queue, Ref, Result, Schema, SchemaGetter, Scope } from "effect";
4
4
  import { makeFunctionReference } from "convex/server";
@@ -14,6 +14,7 @@ const DEFINITIVE_PROVIDER_MODES = /* @__PURE__ */ new Set([
14
14
  "auth-origin-mismatch",
15
15
  "app-env-allowlist",
16
16
  "no-secure-context",
17
+ "signer-not-ready",
17
18
  "revert",
18
19
  "insufficient-balance",
19
20
  "insufficient-allowance",
@@ -3044,6 +3045,50 @@ function isSafeField(field, value) {
3044
3045
  return value.length > 0 && value.length <= rule.maxLength && value === value.trim() && !value.includes("://") && !containsSensitiveMaterial(value) && rule.pattern.test(value);
3045
3046
  }
3046
3047
  //#endregion
3048
+ //#region src/internal/invocation-observation.ts
3049
+ const INVOCATION_OBSERVATION = Symbol("capxul.invocation-observation");
3050
+ const FAILURE_INVOCATION_SNAPSHOT = Symbol("capxul.failure-invocation-snapshot");
3051
+ /** @internal Attach one immutable, non-wire invocation snapshot to an SDK-owned object. */
3052
+ function attachInvocationObservation(target, source) {
3053
+ const snapshot = Object.freeze(source.context === void 0 ? { active: source.active } : {
3054
+ active: source.active,
3055
+ context: Object.freeze({ ...source.context })
3056
+ });
3057
+ Object.defineProperty(target, INVOCATION_OBSERVATION, {
3058
+ configurable: false,
3059
+ enumerable: false,
3060
+ value: snapshot,
3061
+ writable: false
3062
+ });
3063
+ return target;
3064
+ }
3065
+ /** @internal Read the snapshot without exposing its symbol or adding a wire field. */
3066
+ function readInvocationObservation(source) {
3067
+ if (typeof source !== "object" || source === null) return void 0;
3068
+ return source[INVOCATION_OBSERVATION];
3069
+ }
3070
+ /** @internal Carry a snapshot across an SDK adapter projection without resolving again. */
3071
+ function copyInvocationObservation(source, target) {
3072
+ const snapshot = readInvocationObservation(source);
3073
+ return snapshot === void 0 ? target : attachInvocationObservation(target, snapshot);
3074
+ }
3075
+ /** @internal Carry the public call-start delivery decision with its failure envelope. */
3076
+ function markFailureInvocationSnapshot(failure, snapshot) {
3077
+ Object.defineProperty(failure, FAILURE_INVOCATION_SNAPSHOT, {
3078
+ configurable: false,
3079
+ enumerable: false,
3080
+ value: Object.freeze(snapshot),
3081
+ writable: false
3082
+ });
3083
+ return failure;
3084
+ }
3085
+ /** @internal Read the call-start delivery decision; undefined means a direct adapter call. */
3086
+ function readFailureInvocationSnapshot(failure) {
3087
+ if (typeof failure !== "object" || failure === null) return void 0;
3088
+ const snapshot = failure[FAILURE_INVOCATION_SNAPSHOT];
3089
+ return typeof snapshot === "object" && snapshot !== null && "active" in snapshot ? snapshot : void 0;
3090
+ }
3091
+ //#endregion
3047
3092
  //#region src/surface/_shared/provisioning-telemetry.ts
3048
3093
  async function emitProvisioningTelemetry(telemetry, smartAccount) {
3049
3094
  if (telemetry === void 0) return;
@@ -3121,9 +3166,29 @@ function* causeChain(cause) {
3121
3166
  current = current.cause;
3122
3167
  }
3123
3168
  }
3169
+ const SIGNER_NOT_READY_CODES = /* @__PURE__ */ new Set(["MISSING_SIGNER", "NOT_CONFIGURED"]);
3170
+ function isOpenfortSignerNotReadyCode(value) {
3171
+ return typeof value === "string" && SIGNER_NOT_READY_CODES.has(value);
3172
+ }
3173
+ /** Return the exact Openfort code that requires an embedded-signer rebuild. */
3174
+ function openfortSignerNotReadyCode(cause) {
3175
+ for (const link of causeChain(cause)) {
3176
+ const error = link;
3177
+ for (const value of [
3178
+ error.error,
3179
+ error.code,
3180
+ error.details?.provider_error_code
3181
+ ]) if (isOpenfortSignerNotReadyCode(value)) return value;
3182
+ }
3183
+ }
3184
+ /** Openfort's typed signal that its embedded signer state must be rebuilt. */
3185
+ function isSignerNotReadySignal(cause) {
3186
+ return openfortSignerNotReadyCode(cause) !== void 0;
3187
+ }
3124
3188
  /** Fold a signer throw into the public error contract. */
3125
3189
  function signerFailure(source, operation, cause) {
3126
3190
  let failureMode;
3191
+ const providerErrorCode = source === "openfort-embedded" ? openfortSignerNotReadyCode(cause) : void 0;
3127
3192
  for (const link of causeChain(cause)) {
3128
3193
  if (link instanceof CapxulError && link.code === "SIGNER_REJECTED") return link;
3129
3194
  failureMode = getFailureMode(link) ?? failureMode;
@@ -3132,8 +3197,15 @@ function signerFailure(source, operation, cause) {
3132
3197
  source,
3133
3198
  cause
3134
3199
  });
3200
+ if (providerErrorCode !== void 0) failureMode = "signer-not-ready";
3135
3201
  }
3136
- return Errors.providerError("signer", operation, cause, failureMode === void 0 ? void 0 : { failure_mode: failureMode });
3202
+ return Errors.providerError("signer", operation, cause, failureMode === void 0 && providerErrorCode === void 0 ? void 0 : {
3203
+ ...failureMode === void 0 ? {} : { failure_mode: failureMode },
3204
+ ...providerErrorCode === void 0 ? {} : { details: {
3205
+ provider_error_source: "openfort",
3206
+ provider_error_code: providerErrorCode
3207
+ } }
3208
+ });
3137
3209
  }
3138
3210
  /**
3139
3211
  * Browser `CapxulSigner` backed by an injected EIP-1193 wallet (MetaMask, etc.).
@@ -3185,50 +3257,6 @@ async function recoverRawDigestSigner(input) {
3185
3257
  }
3186
3258
  }
3187
3259
  //#endregion
3188
- //#region src/internal/invocation-observation.ts
3189
- const INVOCATION_OBSERVATION = Symbol("capxul.invocation-observation");
3190
- const FAILURE_INVOCATION_SNAPSHOT = Symbol("capxul.failure-invocation-snapshot");
3191
- /** @internal Attach one immutable, non-wire invocation snapshot to an SDK-owned object. */
3192
- function attachInvocationObservation(target, source) {
3193
- const snapshot = Object.freeze(source.context === void 0 ? { active: source.active } : {
3194
- active: source.active,
3195
- context: Object.freeze({ ...source.context })
3196
- });
3197
- Object.defineProperty(target, INVOCATION_OBSERVATION, {
3198
- configurable: false,
3199
- enumerable: false,
3200
- value: snapshot,
3201
- writable: false
3202
- });
3203
- return target;
3204
- }
3205
- /** @internal Read the snapshot without exposing its symbol or adding a wire field. */
3206
- function readInvocationObservation(source) {
3207
- if (typeof source !== "object" || source === null) return void 0;
3208
- return source[INVOCATION_OBSERVATION];
3209
- }
3210
- /** @internal Carry a snapshot across an SDK adapter projection without resolving again. */
3211
- function copyInvocationObservation(source, target) {
3212
- const snapshot = readInvocationObservation(source);
3213
- return snapshot === void 0 ? target : attachInvocationObservation(target, snapshot);
3214
- }
3215
- /** @internal Carry the public call-start delivery decision with its failure envelope. */
3216
- function markFailureInvocationSnapshot(failure, snapshot) {
3217
- Object.defineProperty(failure, FAILURE_INVOCATION_SNAPSHOT, {
3218
- configurable: false,
3219
- enumerable: false,
3220
- value: Object.freeze(snapshot),
3221
- writable: false
3222
- });
3223
- return failure;
3224
- }
3225
- /** @internal Read the call-start delivery decision; undefined means a direct adapter call. */
3226
- function readFailureInvocationSnapshot(failure) {
3227
- if (typeof failure !== "object" || failure === null) return void 0;
3228
- const snapshot = failure[FAILURE_INVOCATION_SNAPSHOT];
3229
- return typeof snapshot === "object" && snapshot !== null && "active" in snapshot ? snapshot : void 0;
3230
- }
3231
- //#endregion
3232
3260
  //#region src/domain/machine/telemetry.ts
3233
3261
  const definedEntries = (values) => Object.fromEntries(Object.entries(values).filter((entry) => entry[1] !== void 0));
3234
3262
  const SAFE_ENGINEERING_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
@@ -3690,21 +3718,27 @@ async function runIdentityFacade(verb, controls, run, runPromise = Effect.runPro
3690
3718
  async function runPortEffect(effect, controls, operation = "port", runPromise = Effect.runPromise) {
3691
3719
  const deadlineDelay = controls?.deadlineMs === void 0 ? void 0 : Math.max(0, controls.deadlineMs - Date.now());
3692
3720
  const timeoutMs = controls?.timeoutMs === void 0 ? deadlineDelay : deadlineDelay === void 0 ? controls.timeoutMs : Math.min(controls.timeoutMs, deadlineDelay);
3693
- const observed = (timeoutMs === void 0 ? effect : effect.pipe(Effect.timeoutOrElse({
3721
+ return runCapxulEffect((timeoutMs === void 0 ? effect : effect.pipe(Effect.timeoutOrElse({
3694
3722
  duration: `${timeoutMs} millis`,
3695
3723
  orElse: () => Effect.fail({ publicError: Errors.providerTimeout("sdk", operation, timeoutMs) })
3696
- }))).pipe(Effect.tap(() => Effect.annotateCurrentSpan({ outcome: "succeeded" })), Effect.tapError((failure) => {
3697
- const mode = failure.publicError.details?.failure_mode;
3724
+ }))).pipe(Effect.mapError((failure) => failure.publicError)), controls, operation, runPromise);
3725
+ }
3726
+ /** Observe a public Effect that already uses the canonical CapxulError channel. */
3727
+ async function runCapxulEffect(effect, controls, operation = "port", runPromise = Effect.runPromise) {
3728
+ const invocation = readInvocationObservation(controls);
3729
+ const correlationId = safeEngineeringIdentifier(controls?.correlation_id ?? invocation?.context?.correlationId);
3730
+ const observed = effect.pipe(Effect.tap(() => Effect.annotateCurrentSpan({ outcome: "succeeded" })), Effect.tapError((error) => {
3731
+ const mode = error.mode ?? error.details?.failure_mode;
3698
3732
  return Effect.annotateCurrentSpan({
3699
- outcome: portFailureOutcome(failure.publicError.code),
3700
- failure_code: failure.publicError.code,
3733
+ outcome: portFailureOutcome(error.code),
3734
+ failure_code: error.code,
3701
3735
  ...typeof mode === "string" ? { mode } : {}
3702
3736
  });
3703
3737
  }), Effect.tapDefect(() => Effect.annotateCurrentSpan({
3704
3738
  outcome: "failed",
3705
3739
  failure_code: "UNKNOWN"
3706
- })), Effect.withSpan(`identity.port.${operation}`));
3707
- return runIfActive(controls?.signal, operation, () => withInvocationParentSpan(observed, controls), runPromise);
3740
+ })), Effect.withSpan(`identity.port.${operation}`), Effect.annotateSpans(correlationId === void 0 ? {} : { correlation_id: correlationId }));
3741
+ return runIfActive(controls?.signal, operation, () => withInvocationParentSpan(observed, controls).pipe(Effect.mapError((publicError) => ({ publicError }))), runPromise);
3708
3742
  }
3709
3743
  /** Map machine-internal failure state onto the public SDK error vocabulary. */
3710
3744
  function publicIdentityFailure(failure) {
@@ -4419,7 +4453,7 @@ function makeAccountMethods(deps) {
4419
4453
  value: provisioningPhase(deps.actor.snapshot())
4420
4454
  };
4421
4455
  };
4422
- const resolveLifecycle = async () => {
4456
+ const resolveLifecycle = async (controls) => {
4423
4457
  const phase = provisioningPhase(deps.actor.snapshot());
4424
4458
  const status = await getStatus();
4425
4459
  if (!status.ok) return accountFailureResult(status.error);
@@ -4427,7 +4461,7 @@ function makeAccountMethods(deps) {
4427
4461
  if (status.value.status !== "notAuthenticated" && (phase.status === "ready" || isRequirementMet(status.value, requirement))) {
4428
4462
  const accountReadPort = deps.accountReadPort;
4429
4463
  if (accountReadPort === void 0) return accountFailureResult(Errors.invalidInput("account", "accountReadPort is required to resolve ready lifecycle"));
4430
- const account = await runPortEffect(accountReadPort.readBalance({ chainId: toChainId(deps.chainId) }));
4464
+ const account = await runPortEffect(accountReadPort.readBalance(copyInvocationObservation(controls, { chainId: toChainId(deps.chainId) })), controls, "accounts.read", deps.runPromise);
4431
4465
  if (!account.ok) return accountFailureResult(account.error);
4432
4466
  accountId = String(account.value.id);
4433
4467
  }
@@ -4441,8 +4475,9 @@ function makeAccountMethods(deps) {
4441
4475
  })
4442
4476
  };
4443
4477
  };
4444
- const getLifecycle = () => resolveLifecycle();
4478
+ const getLifecycle = () => resolveLifecycle(deps.invocationControls?.());
4445
4479
  const retrySetup = async () => {
4480
+ const controls = deps.invocationControls?.();
4446
4481
  const resetSession = deps.signer?.resetSession;
4447
4482
  if (typeof resetSession === "function") try {
4448
4483
  resetSession.call(deps.signer);
@@ -4451,7 +4486,7 @@ function makeAccountMethods(deps) {
4451
4486
  }
4452
4487
  const retried = await drive({ _tag: "RetryAccount" });
4453
4488
  if (!retried.ok) return accountFailureResult(retried.error);
4454
- return resolveLifecycle();
4489
+ return resolveLifecycle(controls);
4455
4490
  };
4456
4491
  return {
4457
4492
  methods: {
@@ -4511,146 +4546,45 @@ const moneyExecutionContract = {
4511
4546
  };
4512
4547
  //#endregion
4513
4548
  //#region package.json
4514
- var version = "2.8.0";
4549
+ var version = "2.8.2";
4515
4550
  //#endregion
4516
- //#region src/telemetry/stack-frame-parser.ts
4517
- /**
4518
- * Regex for V8/Chrome stack trace frame lines.
4519
- * Matches:
4520
- * `at functionName (url:line:col)`
4521
- * `at url:line:col`
4522
- * `at async functionName (url:line:col)`
4523
- * `at new ClassName (url:line:col)`
4524
- */
4525
- const V8_FRAME_RE = /^\s*at\s+(?:(.+?)\s+\()?(?:(.+?)(?::(\d+):(\d+))?|(.+?))\)?\s*$/;
4526
- function isNonUrlName(name) {
4527
- return name === "<anonymous>" || name.startsWith("eval") || name.startsWith("new ") || name.startsWith("async ");
4528
- }
4529
- /**
4530
- * Parse a V8/Chrome-style stack trace string into PostHog `ExceptionFrame` objects.
4531
- * Returns an empty array when `error.stack` is absent or empty.
4532
- *
4533
- * Handles:
4534
- * - Standard `at functionName (url:line:col)`
4535
- * - Bare `at url:line:col` (no function name)
4536
- * - `at async functionName (url:line:col)`
4537
- * - `at new ClassName (url:line:col)`
4538
- * - Native frames: `at Array.forEach (<anonymous>)`
4539
- */
4540
- function parseV8StackFrames(error) {
4541
- const stack = error.stack;
4542
- if (stack === void 0 || stack === null || stack === "") return [];
4543
- const lines = stack.split("\n");
4544
- const frames = [];
4545
- for (const line of lines) {
4546
- const trimmed = line.trim();
4547
- if (!trimmed.startsWith("at ")) continue;
4548
- const match = V8_FRAME_RE.exec(trimmed);
4549
- if (match === null) continue;
4550
- if (match[1] !== void 0) frames.push({
4551
- function: match[1],
4552
- filename: match[2],
4553
- lineno: match[3] !== void 0 ? Number(match[3]) : null,
4554
- colno: match[4] !== void 0 ? Number(match[4]) : null
4555
- });
4556
- else if (match[2] !== void 0 && !isNonUrlName(match[2])) frames.push({
4557
- function: "<anonymous>",
4558
- filename: match[2],
4559
- lineno: match[3] !== void 0 ? Number(match[3]) : null,
4560
- colno: match[4] !== void 0 ? Number(match[4]) : null
4561
- });
4562
- else frames.push({
4563
- function: match[1] ?? match[2] ?? match[5] ?? "<anonymous>",
4564
- filename: match[2] ?? match[5] ?? "<anonymous>",
4565
- lineno: match[3] !== void 0 ? Number(match[3]) : null,
4566
- colno: match[4] !== void 0 ? Number(match[4]) : null
4567
- });
4568
- }
4569
- return frames;
4551
+ //#region src/telemetry/exception-projection.ts
4552
+ /** Fixed fallback for failures that have no safe message. */
4553
+ const EXCEPTION_MESSAGE = "Capxul SDK operation failed";
4554
+ const SDK_VERSION = version;
4555
+ /** The one PostHog Error Tracking projection for every SDK exception emitter. */
4556
+ function projectSdkException(input) {
4557
+ const operation = normalizeExceptionOperation(input.operation);
4558
+ const errorKind = normalizeExceptionErrorKind(input.errorKind);
4559
+ const mode = isFailureMode(input.failureMode) ? input.failureMode : void 0;
4560
+ const message = input.message ?? "Capxul SDK operation failed";
4561
+ const where = input.chainUpstream === void 0 ? "" : ` on ${input.chainUpstream}${input.chainMethod === void 0 ? "" : ` during ${input.chainMethod}`}`;
4562
+ return {
4563
+ ...input.properties,
4564
+ sdk_version: input.sdkVersion,
4565
+ operation,
4566
+ error_kind: errorKind,
4567
+ handled: true,
4568
+ $exception_type: errorKind,
4569
+ $exception_message: message,
4570
+ $exception_level: "error",
4571
+ $exception_fingerprint: failureFingerprint(errorKind, mode, operation),
4572
+ $issue_name: `${errorKind}${mode === void 0 ? "" : `: ${mode}`}${where} (${operation})`,
4573
+ $issue_description: input.issueDescription ?? message,
4574
+ $exception_list: input.exceptionList
4575
+ };
4570
4576
  }
4571
- /** Fixed, leak-safe frame used when the error carries no parseable stack. */
4572
- const SDK_BOUNDARY_FILENAME = "capxul-sdk-observation://boundary";
4573
- /**
4574
- * Build PostHog's `$exception_list` (always a single entry). Error Tracking
4575
- * groups on `type`, so it is ALWAYS present (the CapxulError code) — the
4576
- * previous `[{ frames }]` shape omitted it and PostHog dropped the event as
4577
- * "missing field `type`". When the error has no parseable stack, a synthetic
4578
- * boundary frame stands in so the event still ingests as a real Issue (#1031).
4579
- */
4580
- function buildExceptionList(input) {
4581
- const frames = input.frames.length > 0 ? input.frames : [{
4582
- filename: SDK_BOUNDARY_FILENAME,
4583
- function: input.operation ?? "unknown",
4584
- lineno: 1,
4585
- colno: 1
4586
- }];
4587
- return [{
4588
- type: input.type,
4589
- value: input.value,
4590
- mechanism: {
4591
- handled: true,
4592
- type: "capxul_sdk_boundary"
4593
- },
4594
- stacktrace: { frames }
4595
- }];
4577
+ function normalizeExceptionOperation(value) {
4578
+ return typeof value === "string" && /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,255}$/u.test(value) ? value : "unknown";
4596
4579
  }
4597
- //#endregion
4598
- //#region src/telemetry/capture-exception.ts
4599
- /** Fixed, leak-safe message — the raw error message may carry PII and never ships. */
4600
- const EXCEPTION_MESSAGE = "Capxul SDK operation failed";
4601
- /**
4602
- * Capture an error as a `$exception` event through the telemetry port,
4603
- * formatted for PostHog Error Tracking.
4604
- *
4605
- * Parses stack traces into `$exception_list` format, extracts structured
4606
- * metadata from CapxulError objects, and supplements with context props.
4607
- * Fire-and-forget: telemetry defects are silently swallowed.
4608
- * Returns `Effect<void, never>` for use in Effect pipelines; the underlying
4609
- * adapter work is synchronous, so callers outside Effect contexts can
4610
- * use `Effect.runSync`.
4611
- */
4612
- function captureException(telemetry, error, context) {
4613
- return Effect.catchDefect(Effect.sync(() => {
4614
- const frames = error instanceof Error ? parseV8StackFrames(error) : [];
4615
- const capxulError = isCapxulError(error) ? error : null;
4616
- const errorCode = capxulError?.code ?? context?.capxul_error_code ?? "UNKNOWN";
4617
- const props = {
4618
- capxul_error_code: errorCode,
4619
- $exception_type: errorCode,
4620
- $exception_message: EXCEPTION_MESSAGE,
4621
- $exception_list: buildExceptionList({
4622
- type: errorCode,
4623
- value: EXCEPTION_MESSAGE,
4624
- ...context?.operation === void 0 ? {} : { operation: context.operation },
4625
- frames
4626
- }),
4627
- layer: capxulError?.layer ?? context?.layer,
4628
- operation: context?.operation,
4629
- provider: context?.provider,
4630
- failure_mode: resolveFailureMode(error, context?.failure_mode)
4631
- };
4632
- if (capxulError?.details !== void 0) props.details = JSON.stringify(capxulError.details);
4633
- for (const key of Object.keys(props)) if (props[key] === void 0) delete props[key];
4634
- return telemetry.emit({
4635
- name: "$exception",
4636
- props
4637
- });
4638
- }).pipe(Effect.flatten), () => Effect.void);
4580
+ function normalizeExceptionErrorKind(value) {
4581
+ return safeExceptionLabel(value) ?? "UNKNOWN";
4639
4582
  }
4640
- /**
4641
- * Synchronous fire-and-forget capture. Runs the Effect inline with
4642
- * `Effect.runSync` so callers outside an Effect context can report errors
4643
- * without awaiting. Core SDK public methods use the assembled observation
4644
- * boundary instead.
4645
- */
4646
- function captureExceptionSync(telemetry, error, context) {
4647
- try {
4648
- Effect.runSync(captureException(telemetry, error, context));
4649
- } catch {}
4583
+ function safeExceptionLabel(value) {
4584
+ return typeof value === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/u.test(value) ? value : void 0;
4650
4585
  }
4651
4586
  //#endregion
4652
4587
  //#region src/observation.ts
4653
- const SDK_VERSION = version;
4654
4588
  /** Stable PostHog event used for typed failures that are expected product outcomes. */
4655
4589
  const CAPXUL_SDK_EXPECTED_OUTCOME_EVENT = "capxul_sdk_expected_outcome";
4656
4590
  /**
@@ -4676,13 +4610,13 @@ function postHogFailureObservation(policy, fixedSnapshot) {
4676
4610
  }));
4677
4611
  return;
4678
4612
  }
4679
- policy.deliver(() => policy.client.capture("$exception", postHogExceptionProperties(safeFailure, properties)));
4613
+ policy.deliver(() => policy.client.capture("$exception", projectFailureException(safeFailure, properties)));
4680
4614
  };
4681
4615
  const captureException = (failure) => {
4682
4616
  const prepared = prepare(failure);
4683
4617
  if (prepared === void 0 || policy.client === null || policy.client === void 0) return;
4684
4618
  const [safeFailure, properties] = prepared;
4685
- policy.deliver(() => policy.client.capture("$exception", postHogExceptionProperties(safeFailure, properties)));
4619
+ policy.deliver(() => policy.client.capture("$exception", projectFailureException(safeFailure, properties)));
4686
4620
  };
4687
4621
  return {
4688
4622
  resolveContext: () => {
@@ -4893,19 +4827,20 @@ function postHogProperties(failure, context) {
4893
4827
  ...observationContextProps(merged)
4894
4828
  };
4895
4829
  }
4896
- function postHogExceptionProperties(failure, properties) {
4830
+ function projectFailureException(failure, properties) {
4897
4831
  const filename = `capxul-sdk-observation://boundary/${failure.operation}`;
4898
4832
  const message = failure.message ?? "Capxul SDK operation failed";
4899
- const mode = failure.detail?.failure_mode;
4900
- return {
4901
- ...properties,
4902
- $exception_type: failure.errorKind,
4903
- $exception_message: message,
4904
- $exception_level: "error",
4905
- $exception_fingerprint: failureFingerprint(failure.errorKind, isFailureMode(mode) ? mode : void 0, failure.operation),
4906
- $issue_name: issueName(failure, isFailureMode(mode) ? mode : void 0),
4907
- $issue_description: issueDescription(failure, message),
4908
- $exception_list: [{
4833
+ return projectSdkException({
4834
+ properties,
4835
+ sdkVersion: failure.sdkVersion,
4836
+ operation: failure.operation,
4837
+ errorKind: failure.errorKind,
4838
+ failureMode: failure.detail?.failure_mode,
4839
+ message,
4840
+ issueDescription: issueDescription(failure, message),
4841
+ ...failure.detail?.chain_upstream === void 0 ? {} : { chainUpstream: failure.detail.chain_upstream },
4842
+ ...failure.detail?.chain_method === void 0 ? {} : { chainMethod: failure.detail.chain_method },
4843
+ exceptionList: [{
4909
4844
  type: failure.errorKind,
4910
4845
  value: message,
4911
4846
  mechanism: {
@@ -4926,7 +4861,7 @@ function postHogExceptionProperties(failure, properties) {
4926
4861
  },
4927
4862
  ...failure.stack === void 0 ? {} : { stack: failure.stack }
4928
4863
  }]
4929
- };
4864
+ });
4930
4865
  }
4931
4866
  /**
4932
4867
  * The decoded revert leads the description: the provider's own message masks
@@ -4944,13 +4879,6 @@ function issueDescription(failure, message) {
4944
4879
  });
4945
4880
  return providerMessage === void 0 ? revert : `${revert}; ${providerMessage}`;
4946
4881
  }
4947
- function issueName(failure, mode) {
4948
- const upstream = failure.detail?.chain_upstream;
4949
- const method = failure.detail?.chain_method;
4950
- const cause = mode === void 0 ? "" : `: ${mode}`;
4951
- const where = typeof upstream !== "string" ? "" : ` on ${upstream}${typeof method === "string" ? ` during ${method}` : ""}`;
4952
- return `${failure.errorKind}${cause}${where} (${failure.operation})`;
4953
- }
4954
4882
  const MAX_EVIDENCE_TEXT = 4e3;
4955
4883
  const MAX_CAUSE_DEPTH = 8;
4956
4884
  function evidenceText(value) {
@@ -5054,18 +4982,45 @@ function sanitizeFailureObservation(failure) {
5054
4982
  * Shared by the failure boundary and the `bootstrap_failed` product event.
5055
4983
  */
5056
4984
  function failureDetail(cause) {
5057
- if (!isCapxulError(cause)) return void 0;
5058
- const details = cause.details;
4985
+ const error = observationError(cause);
4986
+ if (error === void 0) return void 0;
4987
+ const details = error.details;
5059
4988
  const source = typeof details === "object" && details !== null ? details : {};
5060
4989
  return sanitizeFailureDetail({
5061
4990
  provider: source.provider,
5062
4991
  provider_operation: source.operation,
5063
- failure_mode: cause.mode ?? source.failure_mode,
4992
+ provider_error_source: source.provider_error_source,
4993
+ provider_error_code: source.provider_error_code,
4994
+ target_host: source.target_host,
4995
+ failure_mode: error.mode ?? source.failure_mode,
5064
4996
  reason: source.reason,
5065
4997
  http_status: source.httpStatus,
5066
- ...cause.chain === void 0 ? {} : chainCauseProperties(cause.chain)
4998
+ connection_id: source.connection_id,
4999
+ connection_count: source.connection_count,
5000
+ connection_retries: source.connection_retries,
5001
+ close_code: source.close_code,
5002
+ close_was_clean: source.close_was_clean,
5003
+ close_reason_present: source.close_reason_present,
5004
+ document_visibility: source.document_visibility,
5005
+ navigator_online: source.navigator_online,
5006
+ last_browser_event: source.last_browser_event,
5007
+ ms_since_browser_event: source.ms_since_browser_event,
5008
+ ...error.chain === void 0 ? {} : chainCauseProperties(error.chain)
5067
5009
  });
5068
5010
  }
5011
+ const CAPXUL_ERROR_CODE_SET = new Set(CAPXUL_ERROR_CODES);
5012
+ function observationError(cause) {
5013
+ if (isCapxulError(cause)) return cause;
5014
+ if (typeof cause !== "object" || cause === null) return void 0;
5015
+ const candidate = cause;
5016
+ if (typeof candidate.code !== "string" || !CAPXUL_ERROR_CODE_SET.has(candidate.code) || typeof candidate.message !== "string") return;
5017
+ const chain = decodeChainCause(candidate.chain);
5018
+ return {
5019
+ ...candidate.details === void 0 ? {} : { details: candidate.details },
5020
+ ...candidate.mode === void 0 ? {} : { mode: candidate.mode },
5021
+ ...chain === null ? {} : { chain }
5022
+ };
5023
+ }
5069
5024
  /** The chain-cause half of {@link sanitizeFailureDetail}: same bounds, same masking. */
5070
5025
  function sanitizeChainDetail(source, detail) {
5071
5026
  for (const key of [
@@ -5077,6 +5032,7 @@ function sanitizeChainDetail(source, detail) {
5077
5032
  const value = source[key];
5078
5033
  if (typeof value === "string" && ENUMERATED_DETAIL_RE.test(value)) detail[key] = value;
5079
5034
  }
5035
+ sanitizeProviderErrorDetail(source, detail);
5080
5036
  const status = source.http_status;
5081
5037
  if (typeof status === "number" && Number.isInteger(status) && status >= 100 && status <= 599) detail.http_status = status;
5082
5038
  for (const key of [
@@ -5105,15 +5061,51 @@ function sanitizeChainDetail(source, detail) {
5105
5061
  const providerMessage = evidenceText(source.chain_provider_message);
5106
5062
  if (providerMessage !== void 0) detail.chain_provider_message = providerMessage;
5107
5063
  }
5064
+ function sanitizeProviderErrorDetail(source, detail) {
5065
+ if (source.provider_error_source !== "openfort") return;
5066
+ detail.provider_error_source = "openfort";
5067
+ if (isOpenfortSignerNotReadyCode(source.provider_error_code)) detail.provider_error_code = source.provider_error_code;
5068
+ }
5069
+ function sanitizeConnectionDetail(source, detail) {
5070
+ const targetHost = source.target_host;
5071
+ if (typeof targetHost === "string" && TARGET_HOST_RE.test(targetHost)) detail.target_host = targetHost;
5072
+ for (const key of [
5073
+ "connection_id",
5074
+ "document_visibility",
5075
+ "last_browser_event"
5076
+ ]) {
5077
+ const value = source[key];
5078
+ if (typeof value === "string" && ENUMERATED_DETAIL_RE.test(value)) detail[key] = value;
5079
+ }
5080
+ for (const key of [
5081
+ "connection_count",
5082
+ "connection_retries",
5083
+ "close_code",
5084
+ "ms_since_browser_event"
5085
+ ]) {
5086
+ const value = source[key];
5087
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && (key !== "close_code" || value <= 4999)) detail[key] = value;
5088
+ }
5089
+ for (const key of [
5090
+ "close_was_clean",
5091
+ "close_reason_present",
5092
+ "navigator_online"
5093
+ ]) {
5094
+ const value = source[key];
5095
+ if (typeof value === "boolean") detail[key] = value;
5096
+ }
5097
+ }
5108
5098
  function sanitizeFailureDetail(input) {
5109
5099
  if (typeof input !== "object" || input === null) return void 0;
5110
5100
  const source = input;
5111
5101
  const detail = {};
5102
+ sanitizeConnectionDetail(source, detail);
5112
5103
  sanitizeChainDetail(source, detail);
5113
5104
  return Object.keys(detail).length === 0 ? void 0 : detail;
5114
5105
  }
5115
5106
  /** Enumerated codes only (`convex`, `no-secure-context`, `bootstrap-encode`); free text fails. */
5116
5107
  const ENUMERATED_DETAIL_RE = /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/u;
5108
+ const TARGET_HOST_RE = /^[A-Za-z0-9.[\]:-]{1,253}$/u;
5117
5109
  /** A four-byte revert selector, or the bare `0x` of an empty revert. */
5118
5110
  const REVERT_SELECTOR_RE = /^0x(?:[0-9a-fA-F]{8})?$/u;
5119
5111
  function normalizeSdkVersion(value) {
@@ -6277,13 +6269,14 @@ var ClockPortTag = class extends Context.Service()("@capxul/sdk/ports/ClockPort"
6277
6269
  //#endregion
6278
6270
  //#region src/ports/convex-call.ts
6279
6271
  var ConvexCallError = class extends Data.TaggedError("ConvexCallError") {};
6280
- function convexCallErrorFromCapxul(operation, error) {
6272
+ function convexCallErrorFromCapxul(operation, error, transport) {
6281
6273
  return new ConvexCallError({
6282
6274
  operation,
6283
6275
  publicCode: error.code,
6284
6276
  publicError: error,
6285
6277
  cause: error,
6286
- ...error.details === void 0 ? {} : { details: error.details }
6278
+ ...error.details === void 0 ? {} : { details: error.details },
6279
+ ...transport === void 0 ? {} : { transport }
6287
6280
  });
6288
6281
  }
6289
6282
  var ConvexCallPortTag = class extends Context.Service()("@capxul/sdk/ports/ConvexCallPort") {};
@@ -6324,31 +6317,56 @@ function wireChainId(chainId) {
6324
6317
  return chainId;
6325
6318
  }
6326
6319
  //#endregion
6327
- //#region src/ports/account-read.ts
6328
- var AccountReadError = class extends Data.TaggedError("AccountReadError") {};
6329
- function accountReadErrorFromCapxul(operation, error, cause = error) {
6330
- return new AccountReadError({
6331
- operation,
6332
- publicCode: error.code,
6333
- publicError: error,
6334
- cause,
6335
- ...error.details === void 0 ? {} : { details: error.details }
6336
- });
6320
+ //#region src/telemetry/invocation.ts
6321
+ const PRODUCT_INVOCATION = Symbol("capxul.product-telemetry-invocation");
6322
+ function bindProductTelemetryInvocation(telemetry, source) {
6323
+ return telemetry[PRODUCT_INVOCATION]?.(source) ?? telemetry;
6337
6324
  }
6338
- var AccountReadPortTag = class extends Context.Service()("@capxul/sdk/ports/AccountReadPort") {};
6339
6325
  //#endregion
6340
- //#region src/ports/smart-account.ts
6341
- var SmartAccountError = class extends Data.TaggedError("SmartAccountError") {};
6342
- function smartAccountErrorFromCapxul(operation, error, cause = error) {
6343
- return new SmartAccountError({
6344
- operation,
6345
- publicCode: error.code,
6346
- publicError: error,
6347
- cause,
6348
- ...error.details === void 0 ? {} : { details: error.details }
6326
+ //#region src/adapters/convex-call/retry-idempotent-read.ts
6327
+ const MAX_RETRIES = 2;
6328
+ function isConnectionLoss(error) {
6329
+ return error.publicCode === "NETWORK_ERROR" && error.publicError.mode === "upstream-down" && error.publicError.details?.reason === "connection-lost-in-flight";
6330
+ }
6331
+ function retryIdempotentRead(effect, operation, telemetry, invocationSource) {
6332
+ return Effect.suspend(() => {
6333
+ let attempt = 0;
6334
+ const invocationTelemetry = telemetry === void 0 ? void 0 : bindProductTelemetryInvocation(telemetry, invocationSource);
6335
+ return effect.pipe(Effect.tapError((error) => {
6336
+ if (!isConnectionLoss(error) || attempt >= MAX_RETRIES) return Effect.void;
6337
+ attempt += 1;
6338
+ const eventFields = {
6339
+ operation,
6340
+ failure_mode: "upstream-down",
6341
+ reason: "connection-lost-in-flight",
6342
+ attempt,
6343
+ delay_ms: 0,
6344
+ ...error.transport === void 0 ? {} : {
6345
+ connection_id: error.transport.connection_id,
6346
+ connection_count: error.transport.connection_count
6347
+ }
6348
+ };
6349
+ const transport = error.transport;
6350
+ const connection = transport === void 0 ? void 0 : omitTransportKind(transport);
6351
+ const log = Effect.logInfo("capxul.operation.retried").pipe(Effect.annotateLogs(connection === void 0 ? eventFields : {
6352
+ ...eventFields,
6353
+ ...connection
6354
+ }), Effect.catchCause(() => Effect.void));
6355
+ if (invocationTelemetry === void 0) return log;
6356
+ return log.pipe(Effect.andThen(invocationTelemetry.emit({
6357
+ name: "operation_retried",
6358
+ props: eventFields
6359
+ })), Effect.catchCause(() => Effect.void));
6360
+ }), Effect.retry({
6361
+ times: MAX_RETRIES,
6362
+ while: isConnectionLoss
6363
+ }));
6349
6364
  });
6350
6365
  }
6351
- var SmartAccountPortTag = class extends Context.Service()("@capxul/sdk/ports/SmartAccountPort") {};
6366
+ function omitTransportKind(transport) {
6367
+ const { kind: _kind, ...connection } = transport;
6368
+ return connection;
6369
+ }
6352
6370
  //#endregion
6353
6371
  //#region ../observability/src/index.ts
6354
6372
  const PII = Schema.String.pipe(Schema.brand("PII"));
@@ -6500,7 +6518,10 @@ const BootstrapFailedProps = Schema.Struct({
6500
6518
  applicationId: OptionalAppId,
6501
6519
  durationMs: OptionalDurationMs,
6502
6520
  origin: OptionalString,
6503
- reason: OptionalString
6521
+ provider: OptionalString,
6522
+ provider_operation: OptionalString,
6523
+ reason: OptionalString,
6524
+ target_host: OptionalString
6504
6525
  });
6505
6526
  const AccountBalanceReadProps = Schema.Struct({
6506
6527
  ...TelemetryEnvelopeProps,
@@ -6565,6 +6586,9 @@ const OperationRetriedProps = Schema.Struct({
6565
6586
  ...TelemetryEnvelopeProps,
6566
6587
  operation: Schema.String,
6567
6588
  failure_mode: FailureModeSchema,
6589
+ reason: Schema.optional(Schema.Literal("connection-lost-in-flight")),
6590
+ connection_id: OptionalString,
6591
+ connection_count: Schema.optional(Schema.Number),
6568
6592
  attempt: Schema.Number,
6569
6593
  delay_ms: DurationMsSchema
6570
6594
  });
@@ -6741,7 +6765,9 @@ const PaymentVerificationRetryProps = Schema.Struct({
6741
6765
  command_id: Schema.String,
6742
6766
  attempt: Schema.Number,
6743
6767
  reason_code: Schema.String,
6744
- chain_id: Schema.Number
6768
+ chain_id: Schema.Number,
6769
+ delay_ms: DurationMsSchema,
6770
+ outcome: Schema.Literals(["scheduled", "unresolved"])
6745
6771
  });
6746
6772
  const DepositInitiatedProps = Schema.Struct({ ...TelemetryEnvelopeProps });
6747
6773
  const DepositSettledProps = Schema.Struct({
@@ -6982,7 +7008,7 @@ function redactTelemetryEvent(event, options = {}) {
6982
7008
  }
6983
7009
  function redactTelemetryProps(name, props, options = {}) {
6984
7010
  if (props === void 0) return void 0;
6985
- const clone = cloneProps$1(props);
7011
+ const clone = cloneProps(props);
6986
7012
  if (options.rawMode === true) return clone;
6987
7013
  for (const key of PII_PROP_KEYS_BY_EVENT[name] ?? []) redactProperty(clone, key);
6988
7014
  return clone;
@@ -6997,17 +7023,17 @@ function redactProperty(props, key) {
6997
7023
  const value = props[key];
6998
7024
  if (typeof value === "string") props[key] = sha256Hex(value).slice(0, 12);
6999
7025
  }
7000
- function cloneProps$1(props) {
7026
+ function cloneProps(props) {
7001
7027
  const cloned = {};
7002
- for (const [key, value] of Object.entries(props)) cloned[key] = cloneTelemetryValue$1(value);
7028
+ for (const [key, value] of Object.entries(props)) cloned[key] = cloneTelemetryValue(value);
7003
7029
  return cloned;
7004
7030
  }
7005
- function cloneTelemetryValue$1(value) {
7006
- if (Array.isArray(value)) return value.map(cloneTelemetryValue$1);
7031
+ function cloneTelemetryValue(value) {
7032
+ if (Array.isArray(value)) return value.map(cloneTelemetryValue);
7007
7033
  if (value === null || typeof value !== "object") return value;
7008
7034
  if (Object.getPrototypeOf(value) !== Object.prototype) return value;
7009
7035
  const cloned = {};
7010
- for (const [key, nested] of Object.entries(value)) cloned[key] = cloneTelemetryValue$1(nested);
7036
+ for (const [key, nested] of Object.entries(value)) cloned[key] = cloneTelemetryValue(nested);
7011
7037
  return cloned;
7012
7038
  }
7013
7039
  const SHA256_INITIAL_HASH = [
@@ -7165,89 +7191,31 @@ function rotr(value, bits) {
7165
7191
  //#region src/ports/telemetry.ts
7166
7192
  var TelemetryPortTag = class extends Context.Service()("@capxul/sdk/ports/TelemetryPort") {};
7167
7193
  //#endregion
7168
- //#region src/adapters/telemetry/PostHogTelemetryAdapter.ts
7169
- var PostHogTelemetryAdapter = class {
7170
- #capture;
7171
- #identify;
7172
- #group;
7173
- #reset;
7174
- constructor(deps) {
7175
- this.#capture = deps.capture;
7176
- this.#identify = deps.identify ?? (() => void 0);
7177
- this.#group = deps.group ?? (() => void 0);
7178
- this.#reset = deps.reset ?? (() => void 0);
7179
- }
7180
- emit(event) {
7181
- return this.#run(() => this.#capture(event.name, redactTelemetryProps(event.name, cloneProps(event.props)), event), "emit", event.name);
7182
- }
7183
- identify(input) {
7184
- return this.#run(() => this.#identify(cloneIdentifyInput(input)), "identify");
7185
- }
7186
- group(input) {
7187
- return this.#run(() => this.#group(cloneGroupInput(input)), "group");
7188
- }
7189
- reset() {
7190
- return this.#run(() => this.#reset(), "reset");
7191
- }
7192
- #run(operation, operationName, eventName) {
7193
- const diagnose = Effect.logWarning("product.telemetry.transport.dropped").pipe(Effect.annotateLogs({
7194
- operation: operationName,
7195
- ...eventName === void 0 ? {} : { product_event: eventName }
7196
- }), Effect.catchCause(() => Effect.void));
7197
- return Effect.suspend(() => {
7198
- let pending;
7199
- try {
7200
- pending = operation();
7201
- } catch {
7202
- return diagnose;
7203
- }
7204
- if (pending === void 0) return Effect.void;
7205
- const transport = Effect.tryPromise({
7206
- try: () => pending,
7207
- catch: () => void 0
7208
- }).pipe(Effect.catch(() => diagnose));
7209
- return Effect.forkDetach(transport, { startImmediately: true }).pipe(Effect.asVoid);
7210
- });
7211
- }
7212
- };
7213
- function PostHogTelemetryLayer(deps) {
7214
- return Layer.succeed(TelemetryPortTag, new PostHogTelemetryAdapter(deps));
7215
- }
7216
- function cloneIdentifyInput(input) {
7217
- const traits = input.traits === void 0 ? void 0 : cloneProps(input.traits);
7218
- const properties = input.properties === void 0 ? void 0 : cloneProps(input.properties);
7219
- return {
7220
- distinctId: input.distinctId,
7221
- ...input.anonDistinctId === void 0 ? {} : { anonDistinctId: input.anonDistinctId },
7222
- ...traits === void 0 ? {} : { traits },
7223
- ...properties === void 0 ? {} : { properties }
7224
- };
7225
- }
7226
- function cloneGroupInput(input) {
7227
- const properties = input.properties === void 0 ? void 0 : cloneProps(input.properties);
7228
- return properties === void 0 ? {
7229
- groupType: input.groupType,
7230
- groupKey: input.groupKey
7231
- } : {
7232
- groupType: input.groupType,
7233
- groupKey: input.groupKey,
7234
- properties
7235
- };
7236
- }
7237
- function cloneProps(props) {
7238
- if (props === void 0) return void 0;
7239
- const cloned = {};
7240
- for (const [key, value] of Object.entries(props)) cloned[key] = cloneTelemetryValue(value);
7241
- return cloned;
7194
+ //#region src/ports/account-read.ts
7195
+ var AccountReadError = class extends Data.TaggedError("AccountReadError") {};
7196
+ function accountReadErrorFromCapxul(operation, error, cause = error) {
7197
+ return new AccountReadError({
7198
+ operation,
7199
+ publicCode: error.code,
7200
+ publicError: error,
7201
+ cause,
7202
+ ...error.details === void 0 ? {} : { details: error.details }
7203
+ });
7242
7204
  }
7243
- function cloneTelemetryValue(value) {
7244
- if (Array.isArray(value)) return value.map(cloneTelemetryValue);
7245
- if (value === null || typeof value !== "object") return value;
7246
- if (Object.getPrototypeOf(value) !== Object.prototype) return value;
7247
- const cloned = {};
7248
- for (const [key, nested] of Object.entries(value)) cloned[key] = cloneTelemetryValue(nested);
7249
- return cloned;
7205
+ var AccountReadPortTag = class extends Context.Service()("@capxul/sdk/ports/AccountReadPort") {};
7206
+ //#endregion
7207
+ //#region src/ports/smart-account.ts
7208
+ var SmartAccountError = class extends Data.TaggedError("SmartAccountError") {};
7209
+ function smartAccountErrorFromCapxul(operation, error, cause = error) {
7210
+ return new SmartAccountError({
7211
+ operation,
7212
+ publicCode: error.code,
7213
+ publicError: error,
7214
+ cause,
7215
+ ...error.details === void 0 ? {} : { details: error.details }
7216
+ });
7250
7217
  }
7218
+ var SmartAccountPortTag = class extends Context.Service()("@capxul/sdk/ports/SmartAccountPort") {};
7251
7219
  //#endregion
7252
7220
  //#region src/flows/identity.ts
7253
7221
  const IDENTITY_SLOT = {
@@ -8167,7 +8135,7 @@ function accountsDepsLayer(deps) {
8167
8135
  }
8168
8136
  const readAccountProgram = Effect.gen(function* () {
8169
8137
  const deps = yield* AccountsDepsTag;
8170
- return yield* deps.accountReadPort.readBalance({ chainId: deps.chainId }).pipe(Effect.tapError((error) => Effect.promise(() => emitAccountBalanceFailed(deps.telemetry, error.publicError))), Effect.mapError((error) => error.publicError));
8138
+ return yield* deps.accountReadPort.readBalance(copyInvocationObservation(deps.invocationSource, { chainId: deps.chainId })).pipe(Effect.tapError((error) => Effect.promise(() => emitAccountBalanceFailed(deps.telemetry, error.publicError))), Effect.mapError((error) => error.publicError));
8171
8139
  });
8172
8140
  function fundFromFaucetProgram(amount) {
8173
8141
  return Effect.gen(function* () {
@@ -8197,7 +8165,11 @@ function makeAccountsMethods(deps) {
8197
8165
  ok: false,
8198
8166
  error: Errors.cancelled({ operation: "accounts.read" })
8199
8167
  };
8200
- return toCapxulResult(readAccountProgram, accountsDepsLayer(deps));
8168
+ const controls = deps.invocationControls?.(options) ?? options;
8169
+ return runCapxulEffect(readAccountProgram.pipe(Effect.provide(accountsDepsLayer({
8170
+ ...deps,
8171
+ ...controls === void 0 ? {} : { invocationSource: controls }
8172
+ }))), controls, "accounts.read", deps.runPromise);
8201
8173
  },
8202
8174
  async fund(amount, options) {
8203
8175
  if (options?.signal?.aborted) return {
@@ -8962,7 +8934,7 @@ function emitCreationFunnelTail(telemetry, org, chainId) {
8962
8934
  function readTreasuryProgram(orgId) {
8963
8935
  return Effect.gen(function* () {
8964
8936
  const deps = yield* OrgDepsTag;
8965
- if (deps.orgPort !== void 0) return yield* deps.orgPort.readTreasury({ orgId }).pipe(Effect.mapError((error) => error.publicError));
8937
+ if (deps.orgPort !== void 0) return yield* deps.orgPort.readTreasury(copyInvocationObservation(deps.invocationSource, { orgId })).pipe(Effect.mapError((error) => error.publicError));
8966
8938
  return zeroTreasury(orgId);
8967
8939
  });
8968
8940
  }
@@ -9046,7 +9018,7 @@ function detectAndAcceptPendingInvitationsProgram() {
9046
9018
  function listOrgsProgram() {
9047
9019
  return Effect.gen(function* () {
9048
9020
  const deps = yield* OrgDepsTag;
9049
- if (deps.orgPort !== void 0) return yield* deps.orgPort.listOrgs({}).pipe(Effect.mapError((error) => error.publicError));
9021
+ if (deps.orgPort !== void 0) return yield* deps.orgPort.listOrgs(copyInvocationObservation(deps.invocationSource, {})).pipe(Effect.mapError((error) => error.publicError));
9050
9022
  return [];
9051
9023
  });
9052
9024
  }
@@ -9134,11 +9106,28 @@ function isRetryableOrganizationSetupFailure(error) {
9134
9106
  * state. The closed-over `orgId` is its only entity reference.
9135
9107
  */
9136
9108
  function makeOrgMethods(deps) {
9137
- const layer = orgDepsLayer({
9109
+ const orgDeps = {
9138
9110
  ...deps.orgPort === void 0 ? {} : { orgPort: deps.orgPort },
9139
9111
  ...deps.chainId === void 0 ? {} : { chainId: deps.chainId },
9140
9112
  ...deps.telemetry === void 0 ? {} : { telemetry: deps.telemetry }
9141
- });
9113
+ };
9114
+ const layer = orgDepsLayer(orgDeps);
9115
+ const treasury = (orgId, controls) => {
9116
+ return runCapxulEffect(readTreasuryProgram(orgId).pipe(Effect.provide(orgDepsLayer({
9117
+ ...orgDeps,
9118
+ ...controls === void 0 ? {} : { invocationSource: controls }
9119
+ }))), controls, "org.treasury", deps.runPromise);
9120
+ };
9121
+ const listOrganizations = (controls) => {
9122
+ if (controls?.signal?.aborted) return Promise.resolve({
9123
+ ok: false,
9124
+ error: Errors.cancelled({ operation: "org.orgs" })
9125
+ });
9126
+ return runCapxulEffect(listOrgsProgram().pipe(Effect.provide(orgDepsLayer({
9127
+ ...orgDeps,
9128
+ ...controls === void 0 ? {} : { invocationSource: controls }
9129
+ }))), controls, "org.orgs", deps.runPromise);
9130
+ };
9142
9131
  return {
9143
9132
  createOrg(input, options) {
9144
9133
  if (options?.signal?.aborted) return Promise.resolve({
@@ -9147,13 +9136,7 @@ function makeOrgMethods(deps) {
9147
9136
  });
9148
9137
  return toCapxulResult(createOrgProgram(input), layer);
9149
9138
  },
9150
- orgs: Object.assign((options) => {
9151
- if (options?.signal?.aborted) return Promise.resolve({
9152
- ok: false,
9153
- error: Errors.cancelled({ operation: "org.orgs" })
9154
- });
9155
- return toCapxulResult(listOrgsProgram(), layer);
9156
- }, { detectAndAcceptPendingInvitations(options) {
9139
+ orgs: Object.assign((options) => listOrganizations(deps.invocationControls?.(options) ?? options), { detectAndAcceptPendingInvitations(options) {
9157
9140
  if (options?.signal?.aborted) return Promise.resolve({
9158
9141
  ok: false,
9159
9142
  error: Errors.cancelled({ operation: "orgs.detectAndAcceptPendingInvitations" })
@@ -9225,19 +9208,20 @@ function makeOrgMethods(deps) {
9225
9208
  ok: false,
9226
9209
  error: Errors.cancelled({ operation: "org.treasury" })
9227
9210
  });
9228
- return toCapxulResult(readTreasuryProgram(orgId), layer);
9211
+ return treasury(orgId, deps.invocationControls?.(options) ?? options);
9229
9212
  },
9230
9213
  account: { async get(options) {
9231
9214
  if (options?.signal?.aborted) return {
9232
9215
  ok: false,
9233
9216
  error: Errors.cancelled({ operation: "org.account.get" })
9234
9217
  };
9235
- const treasury = await toCapxulResult(readTreasuryProgram(orgId), layer);
9236
- if (!treasury.ok) return {
9218
+ const controls = deps.invocationControls?.(options) ?? options;
9219
+ const treasuryResult = await treasury(orgId, controls);
9220
+ if (!treasuryResult.ok) return {
9237
9221
  ok: false,
9238
- error: treasury.error
9222
+ error: treasuryResult.error
9239
9223
  };
9240
- const orgList = await toCapxulResult(listOrgsProgram(), layer);
9224
+ const orgList = await listOrganizations(controls);
9241
9225
  if (!orgList.ok) return {
9242
9226
  ok: false,
9243
9227
  error: orgList.error
@@ -9246,10 +9230,10 @@ function makeOrgMethods(deps) {
9246
9230
  return {
9247
9231
  ok: true,
9248
9232
  value: {
9249
- id: treasury.value.id,
9233
+ id: treasuryResult.value.id,
9250
9234
  address: org?.safeAddress ?? null,
9251
- balance: treasury.value.balance,
9252
- available: treasury.value.available
9235
+ balance: treasuryResult.value.balance,
9236
+ available: treasuryResult.value.available
9253
9237
  }
9254
9238
  };
9255
9239
  } },
@@ -9401,13 +9385,16 @@ function compareDecimal(first, second) {
9401
9385
  //#region src/surface/holdings.ts
9402
9386
  function makeHoldingsMethods(deps) {
9403
9387
  const functions = deps.functions ?? holdingsContract;
9404
- const read = (operation, actor, signal, pick) => runIfActive(signal, operation, () => deps.convexCall.action(functions.current, actor?.kind === "organization" ? { actor: {
9405
- kind: "organization",
9406
- orgId: actor.organizationId
9407
- } } : {}).pipe(Effect.map(pick)));
9388
+ const read = (operation, actor, options, pick) => {
9389
+ const controls = deps.invocationControls?.(options) ?? options;
9390
+ return runCapxulEffect(retryIdempotentRead(deps.convexCall.action(functions.current, copyInvocationObservation(controls, actor?.kind === "organization" ? { actor: {
9391
+ kind: "organization",
9392
+ orgId: actor.organizationId
9393
+ } } : {})), operation, deps.telemetry, controls).pipe(Effect.map(pick), Effect.mapError((error) => error.publicError)), controls, operation, deps.runPromise);
9394
+ };
9408
9395
  return {
9409
- current: (input, options) => read("holdings.current", input?.actor, options?.signal, (snapshot) => snapshot),
9410
- primary: (input, options) => read("holdings.primary", input?.actor, options?.signal, (snapshot) => primaryHolding(snapshot.rows))
9396
+ current: (input, options) => read("holdings.current", input?.actor, options, (snapshot) => snapshot),
9397
+ primary: (input, options) => read("holdings.primary", input?.actor, options, (snapshot) => primaryHolding(snapshot.rows))
9411
9398
  };
9412
9399
  }
9413
9400
  //#endregion
@@ -9418,78 +9405,6 @@ function detectAuthCacheAdapter() {
9418
9405
  return new InMemoryAuthCacheAdapter();
9419
9406
  }
9420
9407
  //#endregion
9421
- //#region src/telemetry/from-posthog.ts
9422
- const PRODUCT_INVOCATION = Symbol("capxul.product-telemetry-invocation");
9423
- /** @internal Bind paired emit/identify/reset work to one call-start snapshot. */
9424
- function bindProductTelemetryInvocation(telemetry, source) {
9425
- return telemetry[PRODUCT_INVOCATION]?.(source) ?? telemetry;
9426
- }
9427
- /**
9428
- * Drop props that must never cross to a host-owned external sink. Today that is
9429
- * the `$exception` `details` blob: `captureException` serializes
9430
- * `CapxulError.details` (e.g. `{ asset, available, required }`, `{ name }`,
9431
- * `{ accountId }` — errors.ts) into it, and the shared redactor has no
9432
- * `$exception` rule, so it is stripped here at the boundary (infra#1037). The
9433
- * safe fields (error code, operation, failure_mode, the fixed leak-safe message,
9434
- * stack frames) are preserved.
9435
- */
9436
- function stripHostUnsafeProps(props) {
9437
- if (props === void 0) return void 0;
9438
- const { details: _details, ...safe } = props;
9439
- return safe;
9440
- }
9441
- /**
9442
- * The subset of a posthog-js client the seam calls. `identify` / `group` /
9443
- * `reset` are optional — a host that only wants event capture can omit them.
9444
- */
9445
- /**
9446
- * Adapt the host's already-initialized posthog-like client into a
9447
- * `TelemetryPort` for the `telemetry` prop / input. This port SUPPLANTS the
9448
- * SDK's no-op default telemetry sink (`production.ts` binds it via
9449
- * `Layer.succeed`, not `compose` — there is no client-side success relay to
9450
- * compose with); it is additive to Capxul's backend first-party record and
9451
- * never owns the client.
9452
- */
9453
- function postHogProductTelemetry(policy, fixedSnapshot) {
9454
- const telemetry = new PostHogTelemetryAdapter({
9455
- capture: (name, props, source) => {
9456
- const snapshot = readInvocationObservation(source) ?? fixedSnapshot ?? policy.snapshot();
9457
- if (!snapshot.active || policy.client === null || policy.client === void 0) return;
9458
- const event = stampTelemetryEnvelope({
9459
- name,
9460
- props
9461
- }, {
9462
- capxul_env: policy.capxulEnv,
9463
- producer: "sdk"
9464
- });
9465
- policy.deliver(() => policy.client.capture(name, {
9466
- ...stripHostUnsafeProps(event.props),
9467
- ...observationContextProps(snapshot.context)
9468
- }));
9469
- },
9470
- identify: (input) => {
9471
- if (!(fixedSnapshot ?? policy.snapshot()).active || policy.client?.identify === void 0) return;
9472
- policy.deliver(() => policy.client.identify(input.distinctId, {
9473
- ...input.traits,
9474
- ...input.properties
9475
- }));
9476
- },
9477
- group: (input) => {
9478
- if (!(fixedSnapshot ?? policy.snapshot()).active || policy.client?.group === void 0) return;
9479
- policy.deliver(() => policy.client.group(input.groupType, input.groupKey, input.properties === void 0 ? void 0 : { ...input.properties }));
9480
- },
9481
- reset: () => {
9482
- if (!(fixedSnapshot ?? policy.snapshot()).active || policy.client?.reset === void 0) return;
9483
- policy.deliver(() => policy.client.reset());
9484
- }
9485
- });
9486
- Object.defineProperty(telemetry, PRODUCT_INVOCATION, {
9487
- enumerable: false,
9488
- value: (source) => postHogProductTelemetry(policy, readInvocationObservation(source) ?? fixedSnapshot ?? policy.snapshot())
9489
- });
9490
- return telemetry;
9491
- }
9492
- //#endregion
9493
9408
  //#region src/telemetry/identity-product.ts
9494
9409
  const NONE = null;
9495
9410
  const IDENTITY_EVENT_TAG_SET = new Set(IDENTITY_EVENT_TAGS);
@@ -9686,6 +9601,8 @@ function assembleCapxulClient(input) {
9686
9601
  accountReadPort: input.ports.accountRead,
9687
9602
  profileMethods: financialOps.me,
9688
9603
  convexCall: input.ports.convexCall,
9604
+ runPromise: effectRunner.runPromise,
9605
+ invocationControls: (controls) => withHostObservationControls(observation.hostObservationSnapshot, controls),
9689
9606
  ...input.signer === void 0 ? {} : { signer: input.signer }
9690
9607
  });
9691
9608
  kickProvisioning = accountBundle.kickProvisioning;
@@ -9723,16 +9640,25 @@ function assembleCapxulClient(input) {
9723
9640
  });
9724
9641
  const system = makeSystemMethods({ convexCall: input.ports.convexCall });
9725
9642
  const media = makeMediaMethods({ convexCall: input.ports.convexCall });
9726
- const holdings = makeHoldingsMethods({ convexCall: input.ports.convexCall });
9643
+ const holdings = makeHoldingsMethods({
9644
+ convexCall: input.ports.convexCall,
9645
+ telemetry: input.ports.telemetry,
9646
+ runPromise: effectRunner.runPromise,
9647
+ invocationControls: (controls) => withHostObservationControls(observation.hostObservationSnapshot, controls)
9648
+ });
9727
9649
  const accounts = makeAccountsMethods({
9728
9650
  accountReadPort: input.ports.accountRead,
9729
9651
  chainId: input.bootstrap.chainId,
9730
- telemetry: input.ports.telemetry
9652
+ telemetry: input.ports.telemetry,
9653
+ runPromise: effectRunner.runPromise,
9654
+ invocationControls: (controls) => withHostObservationControls(observation.hostObservationSnapshot, controls)
9731
9655
  });
9732
9656
  const orgMethods = makeOrgMethods({
9733
9657
  actor,
9734
9658
  chainId: input.bootstrap.chainId,
9735
9659
  telemetry: input.ports.telemetry,
9660
+ runPromise: effectRunner.runPromise,
9661
+ invocationControls: (controls) => withHostObservationControls(observation.hostObservationSnapshot, controls),
9736
9662
  requestKeyScope: `${input.bootstrap.convexUrl}:${String(input.bootstrap.chainId)}`,
9737
9663
  ...selectedOrgPort === void 0 ? {} : { orgPort: selectedOrgPort },
9738
9664
  convexCall: input.ports.convexCall,
@@ -9869,11 +9795,7 @@ function transitionError(record) {
9869
9795
  }
9870
9796
  function withHostObservation(actor, snapshot) {
9871
9797
  if (snapshot === void 0) return actor;
9872
- const controls = (input) => {
9873
- const captured = snapshot();
9874
- const copied = { ...input };
9875
- return captured === void 0 ? copied : attachInvocationObservation(copied, captured);
9876
- };
9798
+ const controls = (input) => withHostObservationControls(snapshot, input);
9877
9799
  return {
9878
9800
  ...actor,
9879
9801
  ask: (event, input) => actor.ask(event, controls(input)),
@@ -9881,5 +9803,10 @@ function withHostObservation(actor, snapshot) {
9881
9803
  restoreAuthSession: (session, input) => actor.restoreAuthSession(session, controls(input))
9882
9804
  };
9883
9805
  }
9806
+ function withHostObservationControls(snapshot, input) {
9807
+ const copied = { ...input };
9808
+ const captured = snapshot?.();
9809
+ return captured === void 0 ? copied : attachInvocationObservation(copied, captured);
9810
+ }
9884
9811
  //#endregion
9885
- export { deriveCapxulSafeAddress as $, postHogFailureObservation as A, injectedWalletSigner as B, fingerprintPaymentIntent as C, failureEvidenceProps as D, failureDetail as E, isSettingUpLifecycle as F, PAYMENT_DIRECTIONS as G, OBSERVATION_CONTEXT_HEADER as H, formatTraceparent as I, BootstrapEnvelope as J, PAYMENT_STATUSES as K, copyInvocationObservation as L, captureExceptionSync as M, version as N, observationContextProps as O, fromWei as P, BASE_SEPOLIA_CHAIN_ID as Q, readInvocationObservation as R, AuthClientPortTag as S, CAPXUL_SDK_EXPECTED_OUTCOME_EVENT as T, encodeObservationContextHeader as U, signerFailure as V, sanitizeObservationContext as W, CAPXUL_PAYMENTS_V2_ADDRESS as X, EngineeringTelemetryBootstrapPolicy as Y, normalizeBindingEmail as Z, ClockPortTag as _, TelemetryPortTag as a, authClientPortFromPromiseAdapter as b, smartAccountErrorFromCapxul as c, wireChainId as d, destination as et, IdentityPortTag as f, ClockError as g, convexCallErrorFromCapxul as h, PostHogTelemetryLayer as i, captureException as j, observeFailedResult as k, AccountReadPortTag as l, ConvexCallPortTag as m, postHogProductTelemetry as n, isRestoring as nt, redactTelemetryEvent as o, identityErrorFromCapxul as p, CAPXUL_FUNCTIONS as q, detectAuthCacheAdapter as r, SmartAccountPortTag as s, assembleCapxulClient as t, isClaimed as tt, accountReadErrorFromCapxul as u, BootstrapPortTag as v, toWei as w, AuthClientError as x, bootstrapErrorFromCapxul as y, causeChain as z };
9812
+ export { sanitizeObservationContext as $, observationContextProps as A, fromWei as B, AuthClientError as C, CAPXUL_SDK_EXPECTED_OUTCOME_EVENT as D, toWei as E, normalizeExceptionErrorKind as F, isSignerNotReadySignal as G, formatTraceparent as H, normalizeExceptionOperation as I, resolveFailureMode as J, openfortSignerNotReadyCode as K, projectSdkException as L, postHogFailureObservation as M, EXCEPTION_MESSAGE as N, failureDetail as O, SDK_VERSION as P, encodeObservationContextHeader as Q, safeExceptionLabel as R, authClientPortFromPromiseAdapter as S, fingerprintPaymentIntent as T, causeChain as U, isSettingUpLifecycle as V, injectedWalletSigner as W, readInvocationObservation as X, copyInvocationObservation as Y, OBSERVATION_CONTEXT_HEADER as Z, convexCallErrorFromCapxul as _, AccountReadPortTag as a, CAPXUL_PAYMENTS_V2_ADDRESS as at, BootstrapPortTag as b, redactTelemetryEvent as c, deriveCapxulSafeAddress as ct, retryIdempotentRead as d, isRestoring as dt, PAYMENT_DIRECTIONS as et, PRODUCT_INVOCATION as f, ConvexCallPortTag as g, identityErrorFromCapxul as h, smartAccountErrorFromCapxul as i, EngineeringTelemetryBootstrapPolicy as it, observeFailedResult as j, failureEvidenceProps as k, redactTelemetryProps as l, destination as lt, IdentityPortTag as m, detectAuthCacheAdapter as n, CAPXUL_FUNCTIONS as nt, accountReadErrorFromCapxul as o, normalizeBindingEmail as ot, wireChainId as p, signerFailure as q, SmartAccountPortTag as r, BootstrapEnvelope as rt, TelemetryPortTag as s, BASE_SEPOLIA_CHAIN_ID as st, assembleCapxulClient as t, PAYMENT_STATUSES as tt, stampTelemetryEnvelope as u, isClaimed as ut, ClockError as v, AuthClientPortTag as w, bootstrapErrorFromCapxul as x, ClockPortTag as y, version as z };