@capxul/sdk 2.5.2 → 2.5.4

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,6 +1,6 @@
1
1
  import { A as toPartyId, B as Errors, M as toPayrollRunId, P as toRoleKey, R as CapxulError, S as toCurrencyCode, V as isCapxulError, 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, 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-uOcqpqu8.mjs";
2
2
  import { concat, encodeAbiParameters, encodeFunctionData, encodePacked, formatUnits, getContractAddress, keccak256, padHex, parseUnits, recoverAddress, stringToHex, toBytes, toEventSelector, toFunctionSelector, toFunctionSignature } from "viem";
3
- import { Context, Data, Deferred, Effect, Exit, Fiber, Layer, Queue, Ref, Result, Schema, SchemaGetter, Scope } from "effect";
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";
5
5
  //#region src/domain/identity/model.ts
6
6
  const WRONG = { refused: "WRONG_STATE" };
@@ -4549,73 +4549,8 @@ function isMoneyTelemetryDebugEnabled() {
4549
4549
  return globalThis.process?.env?.CAPXUL_DEBUG_TELEMETRY === "1";
4550
4550
  }
4551
4551
  //#endregion
4552
- //#region src/surface/payment-execution.ts
4553
- function mismatch(field, message) {
4554
- return {
4555
- ok: false,
4556
- error: Errors.invalidInput(field, message)
4557
- };
4558
- }
4559
- function cancelled(operation) {
4560
- return {
4561
- ok: false,
4562
- error: Errors.cancelled({ operation })
4563
- };
4564
- }
4565
- function isAborted$2(signal) {
4566
- return signal?.aborted === true;
4567
- }
4568
- async function signerCall(source, operation, run) {
4569
- try {
4570
- return {
4571
- ok: true,
4572
- value: await run()
4573
- };
4574
- } catch (cause) {
4575
- return {
4576
- ok: false,
4577
- error: signerFailure(source, operation, cause)
4578
- };
4579
- }
4580
- }
4581
- async function executePersonalPayment(deps, payment, signal, requestKey) {
4582
- if (isAborted$2(signal)) return cancelled("payments.pay");
4583
- if (deps.signer === void 0) return mismatch("signer", "payments.pay requires a configured CapxulSigner");
4584
- const session = deps.actor.authSession();
4585
- if (session === null) return {
4586
- ok: false,
4587
- error: Errors.notAuthenticated()
4588
- };
4589
- const signerAddress = await signerCall(deps.signer.source, "getAddress", () => deps.signer.getAddress());
4590
- if (!signerAddress.ok) return signerAddress;
4591
- const expectedSafe = deriveCapxulSafeAddress({ email: session.email });
4592
- const resolvedRequestKey = requestKey ?? `pay_${crypto.randomUUID()}`;
4593
- const prepared = await runIfActive(signal, "payments.prepareExecution", () => deps.convexCall.action(deps.functions.preparePaymentExecution, { input: {
4594
- requestKey: resolvedRequestKey,
4595
- signerAddress: signerAddress.value,
4596
- payment
4597
- } }));
4598
- if (!prepared.ok) return prepared;
4599
- if (prepared.value.requestKey !== resolvedRequestKey || JSON.stringify(prepared.value.payment) !== JSON.stringify(payment)) return mismatch("payment", "prepared Payment execution uses another request");
4600
- if (prepared.value.chainId !== deps.chainId) return mismatch("chainId", "prepared Payment execution uses another chain");
4601
- if (prepared.value.signerAddress.toLowerCase() !== signerAddress.value.toLowerCase()) return mismatch("signerAddress", "prepared Payment execution uses another signer");
4602
- if (prepared.value.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase()) return mismatch("userOpSenderSafe", "prepared Payment execution uses another Account Safe");
4603
- if (prepared.value.emitPaymentInitiated) await emitPaymentInitiated(deps.telemetry, {
4604
- kind: prepared.value.purposeKind,
4605
- paymentId: prepared.value.paymentId
4606
- });
4607
- if (isAborted$2(signal)) return cancelled("payments.pay");
4608
- const signature = await signerCall(deps.signer.source, "signUserOpHash", () => deps.signer.signUserOpHash(prepared.value.digest));
4609
- if (!signature.ok) return signature;
4610
- if (isAborted$2(signal)) return cancelled("payments.pay");
4611
- return runIfActive(void 0, "payments.submitExecution", () => deps.convexCall.action(deps.functions.submitPaymentExecution, { input: {
4612
- executionId: prepared.value.executionId,
4613
- signature: signature.value
4614
- } }));
4615
- }
4616
- //#endregion
4617
4552
  //#region src/surface/payment-command-execution.ts
4618
- function isAborted$1(signal) {
4553
+ function isAborted$2(signal) {
4619
4554
  return signal?.aborted === true;
4620
4555
  }
4621
4556
  function canonicalJson(value) {
@@ -4631,7 +4566,7 @@ function matchesIntent(expected) {
4631
4566
  return async (request) => await fingerprintPaymentIntent(request) === await fingerprintPaymentIntent(expected);
4632
4567
  }
4633
4568
  async function executePrepared(deps, prepare, isExpectedRequest, signal) {
4634
- if (isAborted$1(signal)) return {
4569
+ if (isAborted$2(signal)) return {
4635
4570
  ok: false,
4636
4571
  error: Errors.cancelled({ operation: "payments" })
4637
4572
  };
@@ -4660,7 +4595,7 @@ async function executePrepared(deps, prepare, isExpectedRequest, signal) {
4660
4595
  ok: false,
4661
4596
  error: Errors.invalidInput("payment", "prepared authority mismatch")
4662
4597
  };
4663
- if (isAborted$1(signal)) return {
4598
+ if (isAborted$2(signal)) return {
4664
4599
  ok: false,
4665
4600
  error: Errors.cancelled({ operation: "payments" })
4666
4601
  };
@@ -4673,7 +4608,7 @@ async function executePrepared(deps, prepare, isExpectedRequest, signal) {
4673
4608
  error: signerFailure(deps.signer.source, "signUserOpHash", cause)
4674
4609
  };
4675
4610
  }
4676
- if (isAborted$1(signal)) return {
4611
+ if (isAborted$2(signal)) return {
4677
4612
  ok: false,
4678
4613
  error: Errors.cancelled({ operation: "payments" })
4679
4614
  };
@@ -4695,6 +4630,71 @@ function executeOrganizationPayment(deps, input, signal) {
4695
4630
  } })), matchesIntent(input), signal);
4696
4631
  }
4697
4632
  //#endregion
4633
+ //#region src/surface/payment-execution.ts
4634
+ function mismatch(field, message) {
4635
+ return {
4636
+ ok: false,
4637
+ error: Errors.invalidInput(field, message)
4638
+ };
4639
+ }
4640
+ function cancelled(operation) {
4641
+ return {
4642
+ ok: false,
4643
+ error: Errors.cancelled({ operation })
4644
+ };
4645
+ }
4646
+ function isAborted$1(signal) {
4647
+ return signal?.aborted === true;
4648
+ }
4649
+ async function signerCall(source, operation, run) {
4650
+ try {
4651
+ return {
4652
+ ok: true,
4653
+ value: await run()
4654
+ };
4655
+ } catch (cause) {
4656
+ return {
4657
+ ok: false,
4658
+ error: signerFailure(source, operation, cause)
4659
+ };
4660
+ }
4661
+ }
4662
+ async function executePersonalPayment(deps, payment, signal, requestKey) {
4663
+ if (isAborted$1(signal)) return cancelled("payments.pay");
4664
+ if (deps.signer === void 0) return mismatch("signer", "payments.pay requires a configured CapxulSigner");
4665
+ const session = deps.actor.authSession();
4666
+ if (session === null) return {
4667
+ ok: false,
4668
+ error: Errors.notAuthenticated()
4669
+ };
4670
+ const signerAddress = await signerCall(deps.signer.source, "getAddress", () => deps.signer.getAddress());
4671
+ if (!signerAddress.ok) return signerAddress;
4672
+ const expectedSafe = deriveCapxulSafeAddress({ email: session.email });
4673
+ const resolvedRequestKey = requestKey ?? `pay_${crypto.randomUUID()}`;
4674
+ const prepared = await runIfActive(signal, "payments.prepareExecution", () => deps.convexCall.action(deps.functions.preparePaymentExecution, { input: {
4675
+ requestKey: resolvedRequestKey,
4676
+ signerAddress: signerAddress.value,
4677
+ payment
4678
+ } }));
4679
+ if (!prepared.ok) return prepared;
4680
+ if (prepared.value.requestKey !== resolvedRequestKey || canonicalJson(prepared.value.payment) !== canonicalJson(payment)) return mismatch("payment", "prepared Payment execution uses another request");
4681
+ if (prepared.value.chainId !== deps.chainId) return mismatch("chainId", "prepared Payment execution uses another chain");
4682
+ if (prepared.value.signerAddress.toLowerCase() !== signerAddress.value.toLowerCase()) return mismatch("signerAddress", "prepared Payment execution uses another signer");
4683
+ if (prepared.value.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase()) return mismatch("userOpSenderSafe", "prepared Payment execution uses another Account Safe");
4684
+ if (prepared.value.emitPaymentInitiated) await emitPaymentInitiated(deps.telemetry, {
4685
+ kind: prepared.value.purposeKind,
4686
+ paymentId: prepared.value.paymentId
4687
+ });
4688
+ if (isAborted$1(signal)) return cancelled("payments.pay");
4689
+ const signature = await signerCall(deps.signer.source, "signUserOpHash", () => deps.signer.signUserOpHash(prepared.value.digest));
4690
+ if (!signature.ok) return signature;
4691
+ if (isAborted$1(signal)) return cancelled("payments.pay");
4692
+ return runIfActive(void 0, "payments.submitExecution", () => deps.convexCall.action(deps.functions.submitPaymentExecution, { input: {
4693
+ executionId: prepared.value.executionId,
4694
+ signature: signature.value
4695
+ } }));
4696
+ }
4697
+ //#endregion
4698
4698
  //#region src/surface/money.ts
4699
4699
  function actorReferenceToBackend(actor) {
4700
4700
  if (actor === void 0) return void 0;
@@ -5541,7 +5541,7 @@ function mapOk(result, f) {
5541
5541
  }
5542
5542
  //#endregion
5543
5543
  //#region package.json
5544
- var version = "2.5.2";
5544
+ var version = "2.5.4";
5545
5545
  //#endregion
5546
5546
  //#region src/ports/auth-client.ts
5547
5547
  var AuthClientError = class extends Data.TaggedError("AuthClientError") {};
@@ -5828,6 +5828,28 @@ const FaucetFailedProps = Schema.Struct({
5828
5828
  ...TelemetryEnvelopeProps,
5829
5829
  reason: OptionalString
5830
5830
  });
5831
+ const AaGatewayUpstreamFallbackProps = Schema.Struct({
5832
+ ...TelemetryEnvelopeProps,
5833
+ method: Schema.String,
5834
+ from_upstream: Schema.Literals([
5835
+ "alchemy",
5836
+ "infura",
5837
+ "public"
5838
+ ]),
5839
+ to_upstream: Schema.optional(Schema.Literals([
5840
+ "alchemy",
5841
+ "infura",
5842
+ "public"
5843
+ ])),
5844
+ failure: Schema.Literals([
5845
+ "http-429",
5846
+ "http-5xx",
5847
+ "rpc-rate-limit",
5848
+ "timeout",
5849
+ "network"
5850
+ ]),
5851
+ status: Schema.optional(Schema.Number)
5852
+ });
5831
5853
  const ORG_ID_TELEMETRY_RE = /^org_[0-9A-Za-z]+$/;
5832
5854
  const OrgIdTelemetrySchema = Schema.String.pipe(Schema.refine((value) => ORG_ID_TELEMETRY_RE.test(value), { message: "must be org_ plus an alphanumeric id" }));
5833
5855
  const OptionalOrgId = Schema.optional(OrgIdTelemetrySchema);
@@ -5878,6 +5900,8 @@ const OrganizationCreationFailedProps = Schema.Struct({
5878
5900
  stage: OnboardingStageSchema,
5879
5901
  error_code: Schema.String,
5880
5902
  retryable: Schema.Boolean,
5903
+ /** #1655: the SDK's backoff before this attempt. Absent on the first attempt. */
5904
+ backoff_ms: Schema.optional(DurationMsSchema),
5881
5905
  failure_reason: Schema.optional(Schema.Literals([
5882
5906
  "deterministic_address_mismatch",
5883
5907
  "receipt_provider_unavailable",
@@ -6128,6 +6152,10 @@ Schema.Struct({
6128
6152
  name: Schema.Literal("faucet_failed"),
6129
6153
  props: FaucetFailedProps
6130
6154
  });
6155
+ Schema.Struct({
6156
+ name: Schema.Literal("aa_gateway_upstream_fallback"),
6157
+ props: AaGatewayUpstreamFallbackProps
6158
+ });
6131
6159
  Schema.Struct({
6132
6160
  name: Schema.Literal("org_create_started"),
6133
6161
  props: OrgCreateStartedProps
@@ -6518,6 +6546,29 @@ const IDENTITY_SLOT_BY_EVENT = {
6518
6546
  OrgFailed: IDENTITY_SLOT.org
6519
6547
  };
6520
6548
  const identitySlot = (event) => IDENTITY_SLOT_BY_EVENT[event._tag];
6549
+ /** 2 s, 4 s, 8 s, 16 s, 32 s, 60 s, 60 s: about three minutes, then the user decides. */
6550
+ const DEFAULT_CONFIRMATION_BACKOFF = {
6551
+ initialDelayMs: 2e3,
6552
+ maxDelayMs: 6e4,
6553
+ maxRetries: 7
6554
+ };
6555
+ /**
6556
+ * A public partial override must not bring the tight loop back: a zero,
6557
+ * negative, or non-finite delay, or a non-integer or infinite retry count,
6558
+ * falls back to the default for that field. `maxDelayMs` is never below
6559
+ * `initialDelayMs`.
6560
+ */
6561
+ const positiveMs = (value, fallback) => value !== void 0 && Number.isFinite(value) && value > 0 ? value : fallback;
6562
+ function normalizeConfirmationBackoff(override) {
6563
+ const initialDelayMs = positiveMs(override?.initialDelayMs, DEFAULT_CONFIRMATION_BACKOFF.initialDelayMs);
6564
+ const maxDelayMs = Math.max(initialDelayMs, positiveMs(override?.maxDelayMs, DEFAULT_CONFIRMATION_BACKOFF.maxDelayMs));
6565
+ const retries = override?.maxRetries;
6566
+ return {
6567
+ initialDelayMs,
6568
+ maxDelayMs,
6569
+ maxRetries: retries !== void 0 && Number.isSafeInteger(retries) && retries >= 0 ? retries : DEFAULT_CONFIRMATION_BACKOFF.maxRetries
6570
+ };
6571
+ }
6521
6572
  const failureOf = (error) => {
6522
6573
  if (error instanceof CapxulError) {
6523
6574
  const mode = error.details?.failure_mode;
@@ -6626,7 +6677,7 @@ const orgEngineeringContext = (controls, parent) => {
6626
6677
  ...traceparent === void 0 ? {} : { traceparent }
6627
6678
  };
6628
6679
  };
6629
- const runOrgStep = (setup, orgId, step, controls) => {
6680
+ const runOrgStep = (setup, orgId, step, controls, retryDelayMs) => {
6630
6681
  const [name, invoke] = step === "preparingFounderAccount" ? ["organization-setup.prepare-founder-account", (parent) => setup.prepareFounderAccount({
6631
6682
  orgId,
6632
6683
  observationContext: orgEngineeringContext(controls, parent)
@@ -6638,11 +6689,12 @@ const runOrgStep = (setup, orgId, step, controls) => {
6638
6689
  observationContext: orgEngineeringContext(controls, parent)
6639
6690
  })] : ["organization-setup.confirm-submitted-bootstrap", (parent) => setup.confirmSubmittedBootstrap({
6640
6691
  orgId,
6641
- observationContext: orgEngineeringContext(controls, parent)
6692
+ observationContext: orgEngineeringContext(controls, parent),
6693
+ ...retryDelayMs === void 0 ? {} : { retryDelayMs }
6642
6694
  })];
6643
6695
  return resultEffect(name, invoke);
6644
6696
  };
6645
- const orgLane = (setup, start, send, controls) => Effect.gen(function* () {
6697
+ const orgLane = (setup, start, send, controls, backoff) => Effect.gen(function* () {
6646
6698
  let orgId;
6647
6699
  let lifecycle;
6648
6700
  if (start.kind === "create") {
@@ -6705,9 +6757,12 @@ const orgLane = (setup, start, send, controls) => Effect.gen(function* () {
6705
6757
  orgId,
6706
6758
  step
6707
6759
  });
6760
+ let retries = 0;
6761
+ let retryDelayMs;
6708
6762
  while (step !== "ready") {
6709
6763
  const current = step;
6710
- const advanced = yield* Effect.result(runOrgStep(setup, orgId, current, controls));
6764
+ const advanced = yield* Effect.result(runOrgStep(setup, orgId, current, controls, retryDelayMs));
6765
+ retryDelayMs = void 0;
6711
6766
  if (Result.isFailure(advanced)) {
6712
6767
  yield* send({
6713
6768
  _tag: "OrgFailed",
@@ -6719,6 +6774,38 @@ const orgLane = (setup, start, send, controls) => Effect.gen(function* () {
6719
6774
  }
6720
6775
  lifecycle = advanced.success;
6721
6776
  if (lifecycle.status === "failed") {
6777
+ if (lifecycle.at === "confirmingBootstrap" && lifecycle.retryable && retries < backoff.maxRetries) {
6778
+ const delayMs = Math.min(backoff.initialDelayMs * 2 ** retries, backoff.maxDelayMs);
6779
+ retries += 1;
6780
+ yield* Effect.sleep(Duration.millis(delayMs));
6781
+ const reset = yield* Effect.result(resultEffect("organization-setup.retry", (parent) => setup.retry({
6782
+ orgId,
6783
+ observationContext: orgEngineeringContext(controls, parent)
6784
+ })));
6785
+ if (Result.isFailure(reset)) {
6786
+ yield* send({
6787
+ _tag: "OrgFailed",
6788
+ orgId,
6789
+ step: current,
6790
+ failure: reset.failure
6791
+ });
6792
+ return yield* Effect.fail(reset.failure);
6793
+ }
6794
+ lifecycle = reset.success;
6795
+ if (lifecycle.status !== "failed") {
6796
+ retryDelayMs = delayMs;
6797
+ step = orgStep(lifecycle);
6798
+ yield* step === "ready" ? send({
6799
+ _tag: "OrgReady",
6800
+ orgId
6801
+ }) : send({
6802
+ _tag: "OrgAt",
6803
+ orgId,
6804
+ step
6805
+ });
6806
+ continue;
6807
+ }
6808
+ }
6722
6809
  const failure = failureOf(lifecycle.error);
6723
6810
  yield* send({
6724
6811
  _tag: "OrgFailed",
@@ -6797,6 +6884,7 @@ const identitySpec = (input, sessionStore = { current: null }) => {
6797
6884
  hasSigner: input.signer !== void 0,
6798
6885
  ...input.otpTtlMs === void 0 ? {} : { otpTtlMs: input.otpTtlMs }
6799
6886
  };
6887
+ const backoff = normalizeConfirmationBackoff(input.confirmationBackoff);
6800
6888
  return {
6801
6889
  machine: "identity",
6802
6890
  initial: RESTORING,
@@ -6902,7 +6990,7 @@ const identitySpec = (input, sessionStore = { current: null }) => {
6902
6990
  run: (send, controls) => orgLane(input.organizationSetup, {
6903
6991
  kind: "create",
6904
6992
  draft: event.draft
6905
- }, send, controls)
6993
+ }, send, controls, backoff)
6906
6994
  };
6907
6995
  case "AttachOrganization": return input.organizationSetup === void 0 || org?.at !== "loading" ? void 0 : {
6908
6996
  slot: IDENTITY_SLOT.org,
@@ -6910,7 +6998,7 @@ const identitySpec = (input, sessionStore = { current: null }) => {
6910
6998
  run: (send, controls) => orgLane(input.organizationSetup, {
6911
6999
  kind: "attach",
6912
7000
  orgId: org.orgId
6913
- }, send, controls)
7001
+ }, send, controls, backoff)
6914
7002
  };
6915
7003
  case "RetryOrganization": return input.organizationSetup === void 0 || org?.at !== "settingUp" ? void 0 : {
6916
7004
  slot: IDENTITY_SLOT.org,
@@ -6918,7 +7006,7 @@ const identitySpec = (input, sessionStore = { current: null }) => {
6918
7006
  run: (send, controls) => orgLane(input.organizationSetup, {
6919
7007
  kind: "retry",
6920
7008
  orgId: org.orgId
6921
- }, send, controls)
7009
+ }, send, controls, backoff)
6922
7010
  };
6923
7011
  default: return;
6924
7012
  }
@@ -9313,6 +9401,43 @@ function executeIdentityProductObservation(telemetry, record, state) {
9313
9401
  }
9314
9402
  //#endregion
9315
9403
  //#region src/surface/create-capxul-client.ts
9404
+ /**
9405
+ * Start the signer readiness cycle when the identity becomes claimed (#1667).
9406
+ *
9407
+ * The cycle used to run only from the embedded-wallet port's `getAddress` and
9408
+ * `signRawDigest`. Nothing calls those after a sign-in or a session restore,
9409
+ * and `resetSession`, which every OTP verify performs, sets the status back to
9410
+ * `unknown`. Thus `client.signer.status()` never left `unknown` on a fresh
9411
+ * session, and each `.Actions` gate that requires `ready` stayed closed. A
9412
+ * claimed identity is the first point where the browser signer has a session to
9413
+ * recover. A signed-out client starts no cycle and reports `unknown`.
9414
+ *
9415
+ * The assembly does not await the call, on purpose: readiness must converge
9416
+ * without a signature. The cycle reports its own failure. It writes
9417
+ * `unavailable` to the same store the gate reads, and adds a DiagnosticPort
9418
+ * breadcrumb, and the next `getAddress` retries it, as before. The rejection is
9419
+ * thus observed and not discarded. A throw here would only cause an unhandled
9420
+ * rejection, and the actor shell removes an observer that throws.
9421
+ *
9422
+ * The `unknown` test holds this to ONE cycle per session. The call sets the
9423
+ * status to `recovering` synchronously, so the later claimed transitions of the
9424
+ * same session, such as the org lane, start no second cycle, and a
9425
+ * `resetSession` that sets the status back to `unknown` permits one more.
9426
+ *
9427
+ * ponytail: one cycle per claim. A cycle that fails stays `unavailable` until
9428
+ * a `getAddress` or a new claim, so a gate that refuses to sign while
9429
+ * `unavailable` needs a reload. Give the action part an explicit retry if that
9430
+ * becomes the common failure.
9431
+ */
9432
+ function startSignerReadinessOnClaim(actor, signer) {
9433
+ if (signer?.statusStore === void 0 || signer.ensureWalletReady === void 0) return () => {};
9434
+ const browserSigner = signer;
9435
+ return actor.subscribe((state) => {
9436
+ if (state.phase !== "authenticated" || state.account.at !== "claimed") return;
9437
+ if (browserSigner.statusStore?.status() !== "unknown") return;
9438
+ browserSigner.ensureWalletReady?.().catch(() => {});
9439
+ });
9440
+ }
9316
9441
  function assembleCapxulClient(input) {
9317
9442
  const observation = input;
9318
9443
  const authCache = input.authCache ?? detectAuthCacheAdapter();
@@ -9340,11 +9465,13 @@ function assembleCapxulClient(input) {
9340
9465
  error: transitionError(record)
9341
9466
  }, failureObservation, `identity.${record.event}`, "machine");
9342
9467
  });
9468
+ const unsubscribeSignerReadiness = startSignerReadinessOnClaim(actor, input.signer);
9343
9469
  let stopPromise = null;
9344
9470
  const stopActor = () => {
9345
9471
  if (stopPromise === null) {
9346
9472
  unsubscribeProductTelemetry();
9347
9473
  unsubscribeFailureObservation();
9474
+ unsubscribeSignerReadiness();
9348
9475
  stopPromise = effectRunner.runPromise(Scope.close(scope, Exit.void));
9349
9476
  }
9350
9477
  return stopPromise;
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as OrgId, C as Address, N as CountryCode, O as AuthSession, S as AccountId, U as PayrollGroupId, V as PartyId, W as PayrollRunId, Y as RoleKey, a as SignerStatusStore, at as CapxulErrorDetails, c as AccountProviderSource, ct as FailureMode, d as eip1193AccountProvider, et as toAddress, f as localPrivateKeyAccountProvider, g as SmartAccount, h as Session, i as SignerStatus, it as CapxulErrorCode, j as BudgetId, k as AuthUserId, l as AccountRequirement, lt as isCapxulError, m as Profile, n as CapxulSigner, nt as CAPXUL_ERROR_CODES, o as injectedWalletSigner, ot as Errors, p as CapxulResult, r as Eip1193RequestProvider, rt as CapxulError, s as AccountProvider, t as CapxulDigestSigner, tt as toCountryCode, u as Eip1193Provider, x as Account, z as Money } from "./signer-BSEG9xgN.mjs";
2
- import { $ as PermissionChangeInput, $n as Readiness, $t as MovementActivityEvidence, A as OrgView, An as IdentityMethods, At as ActivityKind, B as PayrollGroupMember, Bn as PAYMENT_DIRECTIONS, Bt as DepositInstructions, C as DetectPendingOrgInvitationsResult, Cn as ResolvedTarget, Ct as InboxItem, D as OrgMethods, Dn as AccountLifecycle, Dt as ActivityDetail, E as MemberView, En as fingerprintPaymentIntent, Et as ActivityAnnotationInput, F as RoleSpendCap, Fn as ActorRef, Ft as ActivityReference, G as PayrollRunItemInput, Gt as DestinationPayload, H as PayrollMethods, Hn as PaymentStatus$1, Ht as DestinationAddInput, I as RoleView, In as CurrentHoldings, It as ActivitySummary, J as OrganizationPaymentBatchInput, Jn as CAPXUL_PAYMENTS_V2_ADDRESS, Jt as DestinationsMethods, K as PayrollRunStatus, Kt as DestinationRail, L as AuthorizeRunInput, Ln as Permission, Lt as ActivitySummaryParams, M as OrganizationAuditLogItem, Mn as AuthMethods, Mt as ActivityMethods, N as ResendInviteTokenInput, Nn as OrgLifecycle, Nt as ActivityPage, O as OrgScopedMethods, On as AccountSetupStep, Ot as ActivityFilter, P as RoleDefinition, Pn as OrgSetupStep, Pt as ActivityRange, Q as PermissionAssignInput, Qn as OrgLane, Qt as MeProfile, R as PayrollGroup, Rn as SubmittedPermissionExecution, Rt as ActivitySummaryTotal, S as CreateOrgInput, Sn as Ref, St as InboxApproveInput, T as MemberStatus, Tn as TargetsMethods, Tt as ActivityAnnotation, U as PayrollOptions, Un as RequestStatus, Ut as DestinationKind, V as PayrollGroupsMethods, Vn as PAYMENT_STATUSES, Vt as Destination, W as PayrollRun, Wt as DestinationListInput, X as OrganizationPaymentItemInput, Xn as IdentityEvent, Xt as HandlesMethods, Y as OrganizationPaymentInput, Yn as Destination$1, Yt as FinancialOpsMethods, Z as OrganizationPaymentsMethods, Zn as IdentityState, Zt as MeMethods, _ as SystemMethods, _n as PaymentType, _t as ActorRequestsMethods, a as SdkFailureObservation, an as PayeesMethods, ar as InvocationControls, at as PermissionReadResult, b as CurrentUserContext, bn as RecipientResolution, bt as AddressBookLabelInput, c as PostHogObservabilityOptions, cn as PaymentDirection, ct as OrgMeMethod, d as CreateCapxulClientInput, dn as PaymentDocumentRender, dt as AccountMethods, en as OfframpMethods, er as StateLabel, et as PermissionCreateInput, f as IdentityProfileDetails, fn as PaymentDocumentVerification, ft as ActorProfile, g as Holding, gn as PaymentTiming, gt as ActorRequestIssueInput, h as HoldingsMethods, hn as PaymentStatus, ht as ActorRequest, i as ObservationDelivery, in as Payee, ir as IdentityTransition, it as PermissionRevokeInput, j as OrganizationAccount, jn as SmartAccountMethods, jt as ActivityListParams, k as OrgTemplate, kn as isSettingUpLifecycle, kt as ActivityItem, l as postHogObservability, ln as PaymentDocumentKind, lt as OrgMeOptions, m as IdentityRuntimeSendResult, mn as PaymentMoney, mt as ActorRelationshipMethods, n as ObservationAdapter, nn as OfframpQuoteInput, nr as isClaimed, nt as PermissionOptions, o as HostObservability, on as Payment, ot as Budget, p as IdentityRuntime, pn as PaymentDocumentsMethods, pt as ActorProfileMethods, q as PayrollRuns, qn as TelemetryPort, qt as DestinationRemoveInput, r as ObservationContext, rn as OfframpStatus, rr as isRestoring, rt as PermissionReplaceInput, s as PostHogObservabilityClient, sn as PaymentActivityEvidence, st as OrgMe, t as CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, tn as OfframpQuote, tr as destination, tt as PermissionMethods, u as CapxulClient, un as PaymentDocumentRef, ut as AccountsMethods, v as SystemHealth, vn as PaymentsMethods, vt as AddressBookAddInput, w as InviteMemberInput, wn as TargetReference, wt as InboxMethods, x as CurrentUserMethods, xn as RecipientResolutionKind, xt as AddressBookMethods, y as MediaMethods, yn as PaymentsPayInput, yt as AddressBookEntry, z as PayrollGroupInput, zn as InboxStatus, zt as ActorReference } from "./observation-BQ2VKWH5.mjs";
1
+ import { B as OrgId, C as Address, N as CountryCode, O as AuthSession, S as AccountId, U as PayrollGroupId, V as PartyId, W as PayrollRunId, Y as RoleKey, a as SignerStatusStore, at as CapxulErrorDetails, c as AccountProviderSource, ct as FailureMode, d as eip1193AccountProvider, et as toAddress, f as localPrivateKeyAccountProvider, g as SmartAccount, h as Session, i as SignerStatus, it as CapxulErrorCode, j as BudgetId, k as AuthUserId, l as AccountRequirement, lt as isCapxulError, m as Profile, n as CapxulSigner, nt as CAPXUL_ERROR_CODES, o as injectedWalletSigner, ot as Errors, p as CapxulResult, r as Eip1193RequestProvider, rt as CapxulError, s as AccountProvider, t as CapxulDigestSigner, tt as toCountryCode, u as Eip1193Provider, x as Account, z as Money } from "./signer-DIZRkFHh.mjs";
2
+ import { $ as PermissionChangeInput, $n as Readiness, $t as MovementActivityEvidence, A as OrgView, An as IdentityMethods, At as ActivityKind, B as PayrollGroupMember, Bn as PAYMENT_DIRECTIONS, Bt as DepositInstructions, C as DetectPendingOrgInvitationsResult, Cn as ResolvedTarget, Ct as InboxItem, D as OrgMethods, Dn as AccountLifecycle, Dt as ActivityDetail, E as MemberView, En as fingerprintPaymentIntent, Et as ActivityAnnotationInput, F as RoleSpendCap, Fn as ActorRef, Ft as ActivityReference, G as PayrollRunItemInput, Gt as DestinationPayload, H as PayrollMethods, Hn as PaymentStatus$1, Ht as DestinationAddInput, I as RoleView, In as CurrentHoldings, It as ActivitySummary, J as OrganizationPaymentBatchInput, Jn as CAPXUL_PAYMENTS_V2_ADDRESS, Jt as DestinationsMethods, K as PayrollRunStatus, Kt as DestinationRail, L as AuthorizeRunInput, Ln as Permission, Lt as ActivitySummaryParams, M as OrganizationAuditLogItem, Mn as AuthMethods, Mt as ActivityMethods, N as ResendInviteTokenInput, Nn as OrgLifecycle, Nt as ActivityPage, O as OrgScopedMethods, On as AccountSetupStep, Ot as ActivityFilter, P as RoleDefinition, Pn as OrgSetupStep, Pt as ActivityRange, Q as PermissionAssignInput, Qn as OrgLane, Qt as MeProfile, R as PayrollGroup, Rn as SubmittedPermissionExecution, Rt as ActivitySummaryTotal, S as CreateOrgInput, Sn as Ref, St as InboxApproveInput, T as MemberStatus, Tn as TargetsMethods, Tt as ActivityAnnotation, U as PayrollOptions, Un as RequestStatus, Ut as DestinationKind, V as PayrollGroupsMethods, Vn as PAYMENT_STATUSES, Vt as Destination, W as PayrollRun, Wt as DestinationListInput, X as OrganizationPaymentItemInput, Xn as IdentityEvent, Xt as HandlesMethods, Y as OrganizationPaymentInput, Yn as Destination$1, Yt as FinancialOpsMethods, Z as OrganizationPaymentsMethods, Zn as IdentityState, Zt as MeMethods, _ as SystemMethods, _n as PaymentType, _t as ActorRequestsMethods, a as SdkFailureObservation, an as PayeesMethods, ar as InvocationControls, at as PermissionReadResult, b as CurrentUserContext, bn as RecipientResolution, bt as AddressBookLabelInput, c as PostHogObservabilityOptions, cn as PaymentDirection, ct as OrgMeMethod, d as CreateCapxulClientInput, dn as PaymentDocumentRender, dt as AccountMethods, en as OfframpMethods, er as StateLabel, et as PermissionCreateInput, f as IdentityProfileDetails, fn as PaymentDocumentVerification, ft as ActorProfile, g as Holding, gn as PaymentTiming, gt as ActorRequestIssueInput, h as HoldingsMethods, hn as PaymentStatus, ht as ActorRequest, i as ObservationDelivery, in as Payee, ir as IdentityTransition, it as PermissionRevokeInput, j as OrganizationAccount, jn as SmartAccountMethods, jt as ActivityListParams, k as OrgTemplate, kn as isSettingUpLifecycle, kt as ActivityItem, l as postHogObservability, ln as PaymentDocumentKind, lt as OrgMeOptions, m as IdentityRuntimeSendResult, mn as PaymentMoney, mt as ActorRelationshipMethods, n as ObservationAdapter, nn as OfframpQuoteInput, nr as isClaimed, nt as PermissionOptions, o as HostObservability, on as Payment, ot as Budget, p as IdentityRuntime, pn as PaymentDocumentsMethods, pt as ActorProfileMethods, q as PayrollRuns, qn as TelemetryPort, qt as DestinationRemoveInput, r as ObservationContext, rn as OfframpStatus, rr as isRestoring, rt as PermissionReplaceInput, s as PostHogObservabilityClient, sn as PaymentActivityEvidence, st as OrgMe, t as CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, tn as OfframpQuote, tr as destination, tt as PermissionMethods, u as CapxulClient, un as PaymentDocumentRef, ut as AccountsMethods, v as SystemHealth, vn as PaymentsMethods, vt as AddressBookAddInput, w as InviteMemberInput, wn as TargetReference, wt as InboxMethods, x as CurrentUserMethods, xn as RecipientResolutionKind, xt as AddressBookMethods, y as MediaMethods, yn as PaymentsPayInput, yt as AddressBookEntry, z as PayrollGroupInput, zn as InboxStatus, zt as ActorReference } from "./observation-CXl5XZDX.mjs";
3
3
  import { Hex } from "viem";
4
4
  import { Context, Effect, Layer } from "effect";
5
5
  import { FunctionReference } from "convex/server";
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as AuthClientPortTag, B as injectedWalletSigner, C as convexCallErrorFromCapxul, D as bootstrapErrorFromCapxul, E as BootstrapPortTag, F as isSettingUpLifecycle, G as PAYMENT_DIRECTIONS, H as OBSERVATION_CONTEXT_HEADER, I as formatTraceparent, J as BootstrapEnvelope, K as PAYMENT_STATUSES, L as copyInvocationObservation, M as fingerprintPaymentIntent, N as toWei, O as authClientPortFromPromiseAdapter, P as fromWei, Q as BASE_SEPOLIA_CHAIN_ID, R as readInvocationObservation, S as ConvexCallPortTag, T as ClockPortTag, U as encodeObservationContextHeader, V as signerFailure, W as sanitizeObservationContext, X as CAPXUL_PAYMENTS_V2_ADDRESS, Y as EngineeringTelemetryBootstrapPolicy, Z as normalizeBindingEmail, _ as AccountReadPortTag, a as failureEvidenceProps, b as IdentityPortTag, c as postHogFailureObservation, d as detectAuthCacheAdapter, et as destination, f as PostHogTelemetryLayer, g as smartAccountErrorFromCapxul, h as SmartAccountPortTag, i as failureDetail, j as version, k as AuthClientError, l as captureException, n as postHogProductTelemetry, nt as isRestoring, o as observationContextProps, p as TelemetryPortTag, q as CAPXUL_FUNCTIONS, r as CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, s as observeFailedResult, t as assembleCapxulClient, tt as isClaimed, u as captureExceptionSync, v as accountReadErrorFromCapxul, w as ClockError, x as identityErrorFromCapxul, y as wireChainId, z as causeChain } from "./create-capxul-client-BDksczn-.mjs";
1
+ import { A as AuthClientPortTag, B as injectedWalletSigner, C as convexCallErrorFromCapxul, D as bootstrapErrorFromCapxul, E as BootstrapPortTag, F as isSettingUpLifecycle, G as PAYMENT_DIRECTIONS, H as OBSERVATION_CONTEXT_HEADER, I as formatTraceparent, J as BootstrapEnvelope, K as PAYMENT_STATUSES, L as copyInvocationObservation, M as fingerprintPaymentIntent, N as toWei, O as authClientPortFromPromiseAdapter, P as fromWei, Q as BASE_SEPOLIA_CHAIN_ID, R as readInvocationObservation, S as ConvexCallPortTag, T as ClockPortTag, U as encodeObservationContextHeader, V as signerFailure, W as sanitizeObservationContext, X as CAPXUL_PAYMENTS_V2_ADDRESS, Y as EngineeringTelemetryBootstrapPolicy, Z as normalizeBindingEmail, _ as AccountReadPortTag, a as failureEvidenceProps, b as IdentityPortTag, c as postHogFailureObservation, d as detectAuthCacheAdapter, et as destination, f as PostHogTelemetryLayer, g as smartAccountErrorFromCapxul, h as SmartAccountPortTag, i as failureDetail, j as version, k as AuthClientError, l as captureException, n as postHogProductTelemetry, nt as isRestoring, o as observationContextProps, p as TelemetryPortTag, q as CAPXUL_FUNCTIONS, r as CAPXUL_SDK_EXPECTED_OUTCOME_EVENT, s as observeFailedResult, t as assembleCapxulClient, tt as isClaimed, u as captureExceptionSync, v as accountReadErrorFromCapxul, w as ClockError, x as identityErrorFromCapxul, y as wireChainId, z as causeChain } from "./create-capxul-client-BGhQ0sKC.mjs";
2
2
  import { B as Errors, C as toDurationMs, D as toJwtToken, E as toEpochSeconds, F as toSessionToken, I as decodeConvexError, L as CAPXUL_ERROR_CODES, N as toPublishableKey, O as toKycTier, P as toRoleKey, R as CapxulError, S as toCurrencyCode, T as toEpochMs, V as isCapxulError, b as toChainId, g as toAllowedOrigin, h as toAddress, k as toOrgId, m as toAccountId, o as AuthCachePortTag, p as currencySymbolFor, v as toAuthUserId, w as toEmail, x as toCountryCode } from "./InMemoryAuthCacheAdapter-uOcqpqu8.mjs";
3
3
  import { keccak256, recoverAddress, stringToHex } from "viem";
4
4
  import { Cause, Context, Data, Duration, Effect, Exit, Layer, Result, Schedule, SchemaIssue, SchemaParser, Scope, Tracer } from "effect";
@@ -2061,7 +2061,8 @@ var ConvexOrganizationSetupAdapter = class {
2061
2061
  confirmSubmittedBootstrap(input) {
2062
2062
  return this.#lifecycleAction("confirmBootstrap", input, () => this.#convex.action(this.#fns.confirmBootstrap, copyInvocationObservation(input, {
2063
2063
  orgId: input.orgId,
2064
- ...input.observationContext === void 0 ? {} : { observationContext: input.observationContext }
2064
+ ...input.observationContext === void 0 ? {} : { observationContext: input.observationContext },
2065
+ ...input.retryDelayMs === void 0 ? {} : { retryDelayMs: input.retryDelayMs }
2065
2066
  })));
2066
2067
  }
2067
2068
  async recordFailure(input) {
@@ -2566,6 +2567,7 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
2566
2567
  return {
2567
2568
  ...signer,
2568
2569
  statusStore,
2570
+ ensureWalletReady: ensureOpenfortWalletReady,
2569
2571
  getAddress: async () => {
2570
2572
  try {
2571
2573
  const address = await signer.getAddress();
@@ -1,4 +1,4 @@
1
- import { O as AuthSession, _ as AuthCacheError, b as CachedJwt, n as CapxulSigner, v as AuthCachePort, y as AuthCachePortTag } from "../signer-BSEG9xgN.mjs";
1
+ import { O as AuthSession, _ as AuthCacheError, b as CachedJwt, n as CapxulSigner, v as AuthCachePort, y as AuthCachePortTag } from "../signer-DIZRkFHh.mjs";
2
2
  import { Hex } from "viem";
3
3
  import { Effect, FileSystem, Layer, Path } from "effect";
4
4
 
@@ -1,4 +1,4 @@
1
- import { $ as WeiAmount, A as BlockNumber, B as OrgId, C as Address$1, D as AppId, E as AnonymousDistinctId, F as DocumentHash, G as PermissionAssignmentId, H as PaymentCommandId, I as DurationMs, J as PublishableKey, K as PermissionId, L as Email, M as ChainId, N as CountryCode, O as AuthSession, P as CurrencyCode, Q as TxHash, R as EpochMs, T as AllowedOrigin, U as PayrollGroupId, V as PartyId, W as PayrollRunId, X as SessionToken, Y as RoleKey, Z as SmartAccount, a as SignerStatusStore, at as CapxulErrorDetails, b as CachedJwt, c as AccountProviderSource, ct as FailureMode, g as SmartAccount$1, h as Session$1, it as CapxulErrorCode, j as BudgetId, k as AuthUserId, l as AccountRequirement, m as Profile$1, n as CapxulSigner, p as CapxulResult, q as Profile, rt as CapxulError, st as Failure, v as AuthCachePort, w as AllowanceKey, x as Account$1, z as Money } from "./signer-BSEG9xgN.mjs";
1
+ import { $ as WeiAmount, A as BlockNumber, B as OrgId, C as Address$1, D as AppId, E as AnonymousDistinctId, F as DocumentHash, G as PermissionAssignmentId, H as PaymentCommandId, I as DurationMs, J as PublishableKey, K as PermissionId, L as Email, M as ChainId, N as CountryCode, O as AuthSession, P as CurrencyCode, Q as TxHash, R as EpochMs, T as AllowedOrigin, U as PayrollGroupId, V as PartyId, W as PayrollRunId, X as SessionToken, Y as RoleKey, Z as SmartAccount, a as SignerStatusStore, at as CapxulErrorDetails, b as CachedJwt, c as AccountProviderSource, ct as FailureMode, g as SmartAccount$1, h as Session$1, it as CapxulErrorCode, j as BudgetId, k as AuthUserId, l as AccountRequirement, m as Profile$1, n as CapxulSigner, p as CapxulResult, q as Profile, rt as CapxulError, st as Failure, v as AuthCachePort, w as AllowanceKey, x as Account$1, z as Money } from "./signer-DIZRkFHh.mjs";
2
2
  import { Address, Hex } from "viem";
3
3
  import { Context, Effect, Layer, Schema, Scope, Tracer } from "effect";
4
4
  import { FunctionReference } from "convex/server";
@@ -340,7 +340,7 @@ interface TelemetryPort {
340
340
  }
341
341
  //#endregion
342
342
  //#region ../observability/src/index.d.ts
343
- declare const TELEMETRY_EVENT_NAMES: readonly ["auth_otp_requested", "auth_otp_delivered", "auth_otp_expired", "auth_verified", "auth_failed", "auth_signed_out", "onboarding_intent_selected", "onboarding_profile_submitted", "onboarding_organization_submitted", "onboarding_dashboard_reached", "provisioning_safe_created", "provisioning_safe_confirmed", "bootstrap_resolved", "bootstrap_failed", "member_activation_started", "member_activation_ready", "member_activation_failed", "organization_creation_started", "organization_creation_ready", "organization_creation_failed", "account_balance_read", "account_balance_failed", "faucet_requested", "faucet_confirmed", "faucet_failed", "org_create_started", "org_safe_created", "org_safe_confirmed", "org_roles_seeded", "org_created", "org_create_failed", "org_invite_sent", "org_invite_accepted", "org_invite_expired", "payment_initiated", "payment_settled", "payment_failed", "deposit_initiated", "deposit_settled", "permission_mirror_verification", "movement_scan_window", "movement_scan_checkpoint", "movement_scan_incident"];
343
+ declare const TELEMETRY_EVENT_NAMES: readonly ["auth_otp_requested", "auth_otp_delivered", "auth_otp_expired", "auth_verified", "auth_failed", "auth_signed_out", "onboarding_intent_selected", "onboarding_profile_submitted", "onboarding_organization_submitted", "onboarding_dashboard_reached", "provisioning_safe_created", "provisioning_safe_confirmed", "bootstrap_resolved", "bootstrap_failed", "member_activation_started", "member_activation_ready", "member_activation_failed", "organization_creation_started", "organization_creation_ready", "organization_creation_failed", "aa_gateway_upstream_fallback", "account_balance_read", "account_balance_failed", "faucet_requested", "faucet_confirmed", "faucet_failed", "org_create_started", "org_safe_created", "org_safe_confirmed", "org_roles_seeded", "org_created", "org_create_failed", "org_invite_sent", "org_invite_accepted", "org_invite_expired", "payment_initiated", "payment_settled", "payment_failed", "deposit_initiated", "deposit_settled", "permission_mirror_verification", "movement_scan_window", "movement_scan_checkpoint", "movement_scan_incident"];
344
344
  type TelemetryEventName = (typeof TELEMETRY_EVENT_NAMES)[number];
345
345
  type TelemetryProps = Record<string, unknown>;
346
346
  type TelemetryEvent = {
@@ -974,6 +974,12 @@ type OrganizationSetupStepInput = {
974
974
  readonly orgId: OrgId;
975
975
  readonly signal?: AbortSignal; /** @internal Safe trace/correlation carriage owned by the identity flow. */
976
976
  readonly observationContext?: WireObservationContext;
977
+ /**
978
+ * @internal #1655: milliseconds the identity flow waited before this
979
+ * confirmation attempt. Absent on the first attempt. The backend copies it
980
+ * onto `organization_creation_failed` as `backoff_ms`.
981
+ */
982
+ readonly retryDelayMs?: number;
977
983
  };
978
984
  type RecordOrganizationSetupFailureInput = {
979
985
  readonly orgId: OrgId;
@@ -21,7 +21,7 @@ type CapxulErrorCode = (typeof CAPXUL_ERROR_CODES)[number];
21
21
  * into `unknown`; the signer's secure-context probe now names it.
22
22
  * - `unknown`: catch-all when no cause could be determined.
23
23
  */
24
- type FailureMode = "auth-origin-mismatch" | "stale-openfort-cache" | "app-env-allowlist" | "no-secure-context" | "unknown";
24
+ type FailureMode = "auth-origin-mismatch" | "stale-openfort-cache" | "app-env-allowlist" | "no-secure-context" /** #1684: an upstream RPC provider throttled the call (HTTP 429 or JSON-RPC -32005). Retryable. */ | "rate-limited" | "unknown";
25
25
  /**
26
26
  * The one failure representation carried by domain state, actor work, and
27
27
  * public error projection. Keeping it beside the canonical error catalog
@@ -378,6 +378,14 @@ interface CapxulSigner extends CapxulDigestSigner {
378
378
  * `client.signer`, and substitutes `UNOBSERVABLE_SIGNER_STATUS` when absent.
379
379
  */
380
380
  readonly statusStore?: SignerStatusStore;
381
+ /**
382
+ * Start this signer's readiness cycle, or join the one already running,
383
+ * without signing anything. `assembleCapxulClient` calls it when the
384
+ * identity is claimed, so the status converges on `ready` or `unavailable`
385
+ * on its own (#1667). A signer that runs no cycle omits this, and keeps
386
+ * reporting `unknown`.
387
+ */
388
+ readonly ensureWalletReady?: () => Promise<void>;
381
389
  }
382
390
  /**
383
391
  * Observable signer readiness (ACCESS #1520 · C12). `unknown` means the
@@ -1,4 +1,4 @@
1
- import { Gn as TelemetryGroupInput, Kn as TelemetryIdentifyInput, Wn as TelemetryEvent, ir as IdentityTransition, n as ObservationAdapter, u as CapxulClient } from "../observation-BQ2VKWH5.mjs";
1
+ import { Gn as TelemetryGroupInput, Kn as TelemetryIdentifyInput, Wn as TelemetryEvent, ir as IdentityTransition, n as ObservationAdapter, u as CapxulClient } from "../observation-CXl5XZDX.mjs";
2
2
  import { Effect, Layer } from "effect";
3
3
 
4
4
  //#region src/testing/telemetry/RecordingTelemetryAdapter.d.ts
@@ -1,4 +1,4 @@
1
- import { $ as deriveCapxulSafeAddress, C as convexCallErrorFromCapxul, D as bootstrapErrorFromCapxul, N as toWei, O as authClientPortFromPromiseAdapter, P as fromWei, g as smartAccountErrorFromCapxul, m as redactTelemetryEvent, t as assembleCapxulClient, v as accountReadErrorFromCapxul, x as identityErrorFromCapxul, y as wireChainId } from "../create-capxul-client-BDksczn-.mjs";
1
+ import { $ as deriveCapxulSafeAddress, C as convexCallErrorFromCapxul, D as bootstrapErrorFromCapxul, N as toWei, O as authClientPortFromPromiseAdapter, P as fromWei, g as smartAccountErrorFromCapxul, m as redactTelemetryEvent, t as assembleCapxulClient, v as accountReadErrorFromCapxul, x as identityErrorFromCapxul, y as wireChainId } from "../create-capxul-client-BGhQ0sKC.mjs";
2
2
  import { B as Errors, C as toDurationMs, D as toJwtToken, E as toEpochSeconds, F as toSessionToken, N as toPublishableKey, O as toKycTier, R as CapxulError, T as toEpochMs, _ as toAppId, b as toChainId, g as toAllowedOrigin, h as toAddress, m as toAccountId, t as InMemoryAuthCacheAdapter, v as toAuthUserId, w as toEmail, x as toCountryCode } from "../InMemoryAuthCacheAdapter-uOcqpqu8.mjs";
3
3
  import { keccak256 } from "viem";
4
4
  import { Effect, Result, Semaphore } from "effect";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capxul/sdk",
3
- "version": "2.5.2",
3
+ "version": "2.5.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Xelmar-tech/infrastructure.git",
@@ -48,10 +48,10 @@
48
48
  "vitest": "npm:@voidzero-dev/vite-plus-test@0.1.23",
49
49
  "@capxul/config": "0.2.1",
50
50
  "@capxul/errors": "0.0.2",
51
- "@capxul/typescript-config": "0.0.0",
52
- "@capxul/observability": "2.5.2",
51
+ "@capxul/types": "0.2.1",
52
+ "@capxul/observability": "2.5.4",
53
53
  "@capxul/wire": "0.5.1",
54
- "@capxul/types": "0.2.1"
54
+ "@capxul/typescript-config": "0.0.0"
55
55
  },
56
56
  "_permissionlessPinReason": "permissionless.toSafeSmartAccount is pinned to 0.3.4 for live Safe deployment E2E. Counterfactual address fixtures captured 2026-05-17 in packages/backend/convex/_shared/__tests__/counterfactual.test.ts and packages/config/tests/safe.test.ts must be re-verified before upgrading.",
57
57
  "scripts": {