@capxul/sdk 2.3.2 → 2.5.0

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, I as CapxulError, L as EXPECTED_OPERATION_OUTCOMES, M as toRoleKey, R as Errors, S as toCurrencyCode, b as toChainId, c as BYTES32_RE, d as WEI_RE, f as ZERO_BYTES32, h as toAddress, 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 isCapxulError } from "./InMemoryAuthCacheAdapter-qMpBOGb3.mjs";
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-D5Cv0yz0.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, Effect, Exit, Fiber, Layer, Queue, Ref, Result, Schema, SchemaGetter, Scope } from "effect";
4
4
  import { makeFunctionReference } from "convex/server";
@@ -1291,1078 +1291,249 @@ new Map([
1291
1291
  ["setAllowance(bytes32,uint128,uint128,uint128,uint64,uint64)", "SetAllowance(bytes32,uint128,uint128,uint128,uint64,uint64)"]
1292
1292
  ].map(([functionSignature, eventSignature]) => [toFunctionSelector(functionSignature), toEventSelector(eventSignature)]));
1293
1293
  //#endregion
1294
- //#region src/surface/_shared/provisioning-telemetry.ts
1295
- async function emitProvisioningTelemetry(telemetry, smartAccount) {
1296
- if (telemetry === void 0) return;
1297
- await Effect.runPromise(telemetry.emit({
1298
- name: "provisioning_safe_created",
1299
- props: { safe_address: smartAccount.smartAccountAddress }
1300
- }).pipe(Effect.catch((cause) => Effect.sync(() => reportProvisioningTelemetryFailure("error", smartAccount, cause))), Effect.catchDefect((cause) => Effect.sync(() => reportProvisioningTelemetryFailure("defect", smartAccount, cause)))));
1301
- }
1302
- function reportProvisioningTelemetryFailure(kind, smartAccount, cause) {
1303
- if (!isProvisioningTelemetryDebugEnabled()) return;
1304
- globalThis.console?.warn?.("[capxul] provisioning telemetry dropped", {
1305
- kind,
1306
- safeAddress: smartAccount.smartAccountAddress,
1307
- cause
1308
- });
1309
- }
1310
- function isProvisioningTelemetryDebugEnabled() {
1311
- return globalThis.process?.env?.CAPXUL_DEBUG_TELEMETRY === "1";
1312
- }
1313
- //#endregion
1314
- //#region src/telemetry/get-failure-mode.ts
1294
+ //#region ../wire/src/brands.ts
1295
+ const lowercasedString = Schema.String.pipe(Schema.decodeTo(Schema.String, {
1296
+ decode: SchemaGetter.transform((value) => value.toLowerCase()),
1297
+ encode: SchemaGetter.transform((value) => value)
1298
+ }));
1299
+ const addressSchema = (name) => lowercasedString.pipe(Schema.refine((value) => EVM_ADDRESS_RE$1.test(value), { message: `${name} must be a 0x-prefixed EVM address` }));
1300
+ const bytes32BrandSchema = (name) => lowercasedString.pipe(Schema.refine((value) => BYTES32_RE.test(value), { message: `${name} must be a 0x-prefixed bytes32 value` }));
1301
+ /** Lowercase, 0x-prefixed bytes32 evidence without a public brand. */
1302
+ const Bytes32Schema = bytes32BrandSchema("value");
1303
+ const AddressSchema$1 = addressSchema("address");
1304
+ const SafeAddressSchema = addressSchema("safe address");
1305
+ const ModuleAddressSchema = addressSchema("module address");
1306
+ const TxHashSchema$1 = bytes32BrandSchema("transaction hash");
1307
+ const RoleKeySchema = bytes32BrandSchema("role key");
1308
+ const AllowanceKeySchema = bytes32BrandSchema("allowance key");
1309
+ const BlockNumberSchema$1 = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" }));
1310
+ const LogIndexSchema = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" }));
1311
+ const WeiAmountSchema$1 = Schema.String.pipe(Schema.refine((value) => WEI_RE.test(value), { message: "must be a non-negative integer string" }));
1312
+ const SettlementIdSchema = bytes32BrandSchema("settlementId").pipe(Schema.refine((value) => value !== ZERO_BYTES32, { message: "settlementId must not be zero" }));
1315
1313
  /**
1316
- * The five canonical {@link FailureMode} members, for runtime membership checks.
1317
- * Single source of truth tests assert against this exact set so the taxonomy
1318
- * and its guard can never drift apart.
1314
+ * `AppId` schema. Mirrors `toAppId` from `@capxul/types`:
1315
+ * `app_` + Crockford-base32 ULID (26 chars, first char in `[0-7]`).
1319
1316
  */
1320
- const FAILURE_MODES = new Set([
1321
- "auth-origin-mismatch",
1322
- "stale-openfort-cache",
1323
- "app-env-allowlist",
1324
- "no-secure-context",
1325
- "unknown"
1326
- ]);
1327
- function isFailureMode(value) {
1328
- return typeof value === "string" && FAILURE_MODES.has(value);
1329
- }
1317
+ const AppIdSchema$1 = Schema.String.pipe(Schema.refine((s) => APP_ID_RE.test(s), { message: "must be app_ plus a ULID" }));
1330
1318
  /**
1331
- * Extract the structured {@link FailureMode} from a CapxulError.
1332
- *
1333
- * Reads `details.failure_mode` and returns it only when it is one of the five
1334
- * canonical members; any other value (a legacy free string, a typo, a
1335
- * non-string) yields `undefined` so downstream telemetry never reports an
1336
- * unrecognised cause.
1319
+ * `ChainId` schema. Mirrors `toChainId`: positive safe integer.
1337
1320
  */
1338
- function getFailureMode(error) {
1339
- if (!isCapxulError(error)) return void 0;
1340
- const details = error.details;
1341
- if (details === void 0) return void 0;
1342
- return isFailureMode(details.failure_mode) ? details.failure_mode : void 0;
1343
- }
1321
+ const ChainIdSchema$1 = Schema.Number.pipe(Schema.refine((n) => Number.isSafeInteger(n) && n > 0, { message: "must be a positive safe integer" }));
1344
1322
  /**
1345
- * Resolve the canonical {@link FailureMode} for a `$exception`, guaranteeing a
1346
- * taxonomy member is always returned — never `undefined`, never a free string.
1347
- *
1348
- * Resolution order:
1349
- * 1. the structured mode on the error's `details.failure_mode` (already guarded);
1350
- * 2. a caller-supplied `contextFailureMode`, but ONLY when it passes the same
1351
- * runtime membership check — the static `FailureMode` type is erased at
1352
- * runtime, so an operation string (e.g. `"signer-get-address"`) injected via
1353
- * a JS caller or `as` cast is rejected here rather than leaking to telemetry;
1354
- * 3. `"unknown"` otherwise, so an unclassifiable error is still tagged with a
1355
- * canonical value instead of being emitted with no `failure_mode` at all.
1323
+ * `CurrencyCode` schema. Mirrors `toCurrencyCode`: currently supported
1324
+ * consumer-facing ISO-ish currency code set.
1356
1325
  */
1357
- function resolveFailureMode(error, contextFailureMode) {
1358
- return getFailureMode(error) ?? (isFailureMode(contextFailureMode) ? contextFailureMode : "unknown");
1359
- }
1360
- //#endregion
1361
- //#region src/signer.ts
1362
- const EVM_ADDRESS_HEX = /^0x[0-9a-fA-F]{40}$/;
1363
- const ECDSA_SIGNATURE_HEX = /^0x[0-9a-fA-F]{130}$/;
1364
- const SAFE_OP_DIGEST_HEX = /^0x[0-9a-fA-F]{64}$/;
1326
+ const CurrencyCodeSchema$1 = Schema.String.pipe(Schema.refine((s) => SUPPORTED_CURRENCY_CODES.includes(s), { message: "must be a supported currency code" }));
1327
+ const DOCUMENT_HASH_HEX_RE = /^[0-9a-fA-F]{64}$/;
1365
1328
  /**
1366
- * The readiness store a signer reports when it runs no readiness cycle. It
1367
- * fails CLOSED: a node key signer or an injected wallet never claims `ready`,
1368
- * so a gate that reads this never opens on a guess.
1329
+ * `DocumentHash` schema. Mirrors `toDocumentHash`: bare or 0x-prefixed bytes32,
1330
+ * normalized to lowercase 0x-prefixed form.
1369
1331
  */
1370
- const UNOBSERVABLE_SIGNER_STATUS = {
1371
- status: () => "unknown",
1372
- subscribe: () => () => void 0
1373
- };
1332
+ const DocumentHashSchema = Schema.String.pipe(Schema.decodeTo(Schema.String, {
1333
+ decode: SchemaGetter.transform((s) => {
1334
+ const stripped = s.startsWith("0x") || s.startsWith("0X") ? s.slice(2) : s;
1335
+ return DOCUMENT_HASH_HEX_RE.test(stripped) ? `0x${stripped.toLowerCase()}` : s;
1336
+ }),
1337
+ encode: SchemaGetter.transform((s) => s)
1338
+ }), Schema.refine((s) => BYTES32_RE.test(s), { message: "must be 32 bytes of hex" }));
1339
+ /** L2 orchestrated money evidence requires a nonzero Document hash. */
1340
+ const NonzeroDocumentHashSchema = DocumentHashSchema.pipe(Schema.refine((value) => value !== ZERO_BYTES32, { message: "documentHash must not be zero" }));
1374
1341
  /**
1375
- * Walk an error and its `cause` links once each. A self-referential chain
1376
- * terminates. Both signer predicates read the chain, so they read it here.
1342
+ * `SessionToken` schema. Mirrors `toSessionToken`: non-empty string.
1343
+ * Issuance source distinguishes SDK-handshake tokens from auth-session
1344
+ * tokens; the brand itself is opaque.
1377
1345
  */
1378
- function* causeChain(cause) {
1379
- const seen = /* @__PURE__ */ new Set();
1380
- let current = cause;
1381
- while (typeof current === "object" && current !== null && !seen.has(current)) {
1382
- seen.add(current);
1383
- yield current;
1384
- current = current.cause;
1385
- }
1386
- }
1387
- /** Fold a signer throw into the public error contract. */
1388
- function signerFailure(source, operation, cause) {
1389
- let failureMode;
1390
- for (const link of causeChain(cause)) {
1391
- if (link instanceof CapxulError && link.code === "SIGNER_REJECTED") return link;
1392
- failureMode = getFailureMode(link) ?? failureMode;
1393
- const error = link;
1394
- if (error.code === 4001 || error.error === "passkey_user_cancelled") return Errors.signerRejected({
1395
- source,
1396
- cause
1397
- });
1398
- }
1399
- return Errors.providerError("signer", operation, cause, failureMode === void 0 ? void 0 : { failure_mode: failureMode });
1400
- }
1346
+ const SessionTokenSchema = Schema.String.pipe(Schema.refine((s) => s.length > 0, { message: "must be a non-empty string" }));
1401
1347
  /**
1402
- * Browser `CapxulSigner` backed by an injected EIP-1193 wallet (MetaMask, etc.).
1403
- * Signs the SafeOp digest via `eth_sign`, then verifies the returned signature
1404
- * recovers the selected account against that raw digest. Wallets that prefix
1405
- * `eth_sign` payloads are rejected before the backend submits an invalid SafeOp.
1406
- * The node key signer lives in `@capxul/sdk/node` (`localPrivateKeySigner`).
1348
+ * `EpochMs` schema. Mirrors `toEpochMs`: non-negative safe integer.
1407
1349
  */
1408
- function injectedWalletSigner(provider) {
1409
- const resolveAddress = async () => {
1410
- const accounts = await provider.request({ method: "eth_requestAccounts" });
1411
- const first = Array.isArray(accounts) ? accounts[0] : void 0;
1412
- if (typeof first !== "string") throw new Error("injectedWalletSigner: wallet returned no accounts");
1413
- if (!EVM_ADDRESS_HEX.test(first)) throw new Error("injectedWalletSigner: wallet returned invalid address format");
1414
- return toAddress(first);
1415
- };
1416
- return {
1417
- source: "injected-eip1193",
1418
- getAddress: resolveAddress,
1419
- async signUserOpHash(hash) {
1420
- if (!SAFE_OP_DIGEST_HEX.test(hash)) throw new Error("injectedWalletSigner: SafeOp digest must be a 0x-prefixed 32-byte hex");
1421
- const address = await resolveAddress();
1422
- let signature;
1423
- try {
1424
- signature = await provider.request({
1425
- method: "eth_sign",
1426
- params: [address, hash]
1427
- });
1428
- } catch (cause) {
1429
- const detail = cause instanceof Error ? cause.message : String(cause);
1430
- throw new Error(`injectedWalletSigner: eth_sign failed; enable raw-hash signing for deployment (${detail})`, { cause });
1431
- }
1432
- if (typeof signature !== "string") throw new Error("injectedWalletSigner: wallet returned a non-string signature");
1433
- if (!ECDSA_SIGNATURE_HEX.test(signature)) throw new Error("injectedWalletSigner: wallet returned invalid signature format");
1434
- if ((await recoverRawDigestSigner({
1435
- hash,
1436
- signature
1437
- })).toLowerCase() !== address.toLowerCase()) throw new Error("injectedWalletSigner: wallet signature did not recover the selected account for the raw SafeOp digest; use a raw-hash-capable wallet or @capxul/sdk/node localPrivateKeySigner for deployed flows");
1438
- return signature;
1439
- }
1440
- };
1441
- }
1442
- async function recoverRawDigestSigner(input) {
1350
+ const EpochMsSchema$1 = Schema.Number.pipe(Schema.refine((n) => Number.isSafeInteger(n) && n >= 0, { message: "must be a non-negative safe integer" }));
1351
+ /**
1352
+ * `DurationMs` schema. Mirrors `toDurationMs`: non-negative safe integer.
1353
+ */
1354
+ const DurationMsSchema$1 = Schema.Number.pipe(Schema.refine((n) => Number.isSafeInteger(n) && n >= 0, { message: "must be a non-negative safe integer" }));
1355
+ //#endregion
1356
+ //#region ../wire/src/bootstrap.ts
1357
+ const PUBLIC_POSTHOG_PROJECT_TOKEN = /^phc_[A-Za-z0-9_-]{1,191}$/u;
1358
+ const PostHogIngestOrigin = Schema.String.pipe(Schema.refine((value) => {
1443
1359
  try {
1444
- return toAddress(await recoverAddress(input));
1445
- } catch (cause) {
1446
- const detail = cause instanceof Error ? cause.message : String(cause);
1447
- throw new Error(`injectedWalletSigner: could not verify raw SafeOp digest signature (${detail})`, { cause });
1360
+ const url = new URL(value);
1361
+ return url.protocol === "https:" && url.username.length === 0 && url.password.length === 0 && url.pathname === "/" && url.search.length === 0 && url.hash.length === 0 && (url.hostname === "posthog.com" || url.hostname.endsWith(".posthog.com"));
1362
+ } catch {
1363
+ return false;
1448
1364
  }
1449
- }
1365
+ }, { message: "must be a credential-free PostHog HTTPS ingest origin" }));
1366
+ const EngineeringTelemetryBootstrapPolicy = Schema.Struct({
1367
+ host: PostHogIngestOrigin,
1368
+ projectToken: Schema.String.pipe(Schema.refine((value) => PUBLIC_POSTHOG_PROJECT_TOKEN.test(value), { message: "must be a public PostHog project token" })),
1369
+ capxulEnv: Schema.Union([
1370
+ Schema.Literal("development"),
1371
+ Schema.Literal("staging"),
1372
+ Schema.Literal("production"),
1373
+ Schema.Literal("local")
1374
+ ])
1375
+ });
1376
+ /**
1377
+ * `BootstrapEnvelope` v1.
1378
+ *
1379
+ * - `protocol`: discriminator that lets future protocols coexist on the
1380
+ * same endpoint without a wire-shape conflict.
1381
+ * - `version`: numeric version inside the protocol. Unknown versions MUST
1382
+ * fail decode with an INVALID_INPUT-class `CapxulError` at the SDK seam.
1383
+ * - `state`: the resolved bootstrap payload. Field shape matches the
1384
+ * `BootstrapResolution` port; the SDK consumer can pass `state`
1385
+ * directly (after `normalizeRuntimeUrl` on the two URL fields) into
1386
+ * the port without re-branding.
1387
+ */
1388
+ const BootstrapEnvelope = Schema.Struct({
1389
+ protocol: Schema.Literal("capxul.bootstrap"),
1390
+ version: Schema.Literal(1),
1391
+ state: Schema.Struct({
1392
+ applicationId: AppIdSchema$1,
1393
+ chainId: ChainIdSchema$1,
1394
+ sessionToken: SessionTokenSchema,
1395
+ issuedAt: EpochMsSchema$1,
1396
+ expiresIn: DurationMsSchema$1,
1397
+ authBaseUrl: Schema.String,
1398
+ convexUrl: Schema.String,
1399
+ siteBaseUrl: Schema.String,
1400
+ openfortPublishableKey: Schema.String,
1401
+ shieldPublishableKey: Schema.String,
1402
+ engineeringTelemetry: Schema.optional(EngineeringTelemetryBootstrapPolicy)
1403
+ })
1404
+ });
1450
1405
  //#endregion
1451
- //#region src/internal/invocation-observation.ts
1452
- const INVOCATION_OBSERVATION = Symbol("capxul.invocation-observation");
1453
- const FAILURE_INVOCATION_SNAPSHOT = Symbol("capxul.failure-invocation-snapshot");
1454
- /** @internal Attach one immutable, non-wire invocation snapshot to an SDK-owned object. */
1455
- function attachInvocationObservation(target, source) {
1456
- const snapshot = Object.freeze(source.context === void 0 ? { active: source.active } : {
1457
- active: source.active,
1458
- context: Object.freeze({ ...source.context })
1459
- });
1460
- Object.defineProperty(target, INVOCATION_OBSERVATION, {
1461
- configurable: false,
1462
- enumerable: false,
1463
- value: snapshot,
1464
- writable: false
1465
- });
1466
- return target;
1467
- }
1468
- /** @internal Read the snapshot without exposing its symbol or adding a wire field. */
1469
- function readInvocationObservation(source) {
1470
- if (typeof source !== "object" || source === null) return void 0;
1471
- return source[INVOCATION_OBSERVATION];
1472
- }
1473
- /** @internal Carry a snapshot across an SDK adapter projection without resolving again. */
1474
- function copyInvocationObservation(source, target) {
1475
- const snapshot = readInvocationObservation(source);
1476
- return snapshot === void 0 ? target : attachInvocationObservation(target, snapshot);
1477
- }
1478
- /** @internal Carry the public call-start delivery decision with its failure envelope. */
1479
- function markFailureInvocationSnapshot(failure, snapshot) {
1480
- Object.defineProperty(failure, FAILURE_INVOCATION_SNAPSHOT, {
1481
- configurable: false,
1482
- enumerable: false,
1483
- value: Object.freeze(snapshot),
1484
- writable: false
1485
- });
1486
- return failure;
1487
- }
1488
- /** @internal Read the call-start delivery decision; undefined means a direct adapter call. */
1489
- function readFailureInvocationSnapshot(failure) {
1490
- if (typeof failure !== "object" || failure === null) return void 0;
1491
- const snapshot = failure[FAILURE_INVOCATION_SNAPSHOT];
1492
- return typeof snapshot === "object" && snapshot !== null && "active" in snapshot ? snapshot : void 0;
1493
- }
1494
- //#endregion
1495
- //#region src/domain/machine/telemetry.ts
1496
- const definedEntries = (values) => Object.fromEntries(Object.entries(values).filter((entry) => entry[1] !== void 0));
1497
- const SAFE_ENGINEERING_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
1498
- const safeEngineeringIdentifier = (value) => value !== void 0 && SAFE_ENGINEERING_ID.test(value) ? value : void 0;
1499
- const portFailureOutcome = (code) => code === "CANCELLED" ? "cancelled" : "failed";
1500
- function formatTraceparent(span) {
1501
- const traceId = span.traceId.toLowerCase();
1502
- const spanId = span.spanId.toLowerCase();
1503
- if (!/^[0-9a-f]{32}$/u.test(traceId) || !/^[0-9a-f]{16}$/u.test(spanId)) return void 0;
1504
- if (/^0+$/u.test(traceId) || /^0+$/u.test(spanId)) return void 0;
1505
- return `00-${traceId}-${spanId}-${span.sampled ? "01" : "00"}`;
1506
- }
1507
- /** Canonical, bounded fields for the one wide engineering log owned by P3. */
1508
- const transitionLogFields = (record) => {
1509
- const { correlation_id, journey_id, ...canonical } = record;
1510
- const safeCorrelation = safeEngineeringIdentifier(correlation_id);
1511
- const safeJourney = safeEngineeringIdentifier(journey_id);
1512
- return definedEntries({
1513
- ...canonical,
1514
- ...safeCorrelation === void 0 ? {} : { correlation_id: safeCorrelation },
1515
- ...safeJourney === void 0 ? {} : { journey_id: safeJourney }
1516
- });
1517
- };
1518
- /** The shell span owns transition/refusal classification and no other seam's fields. */
1519
- const transitionSpanFields = (record) => {
1520
- if (record.outcome === "applied") return {
1521
- machine: record.machine,
1522
- from: record.from,
1523
- event: record.event,
1524
- to: record.to
1525
- };
1526
- return {
1527
- machine: record.machine,
1528
- state: record.state,
1529
- event: record.event,
1530
- ...record.outcome === "refused" ? { refused: record.refusal_code } : {}
1531
- };
1532
- };
1406
+ //#region ../wire/src/functions.ts
1533
1407
  /**
1534
- * Emit engineering telemetry as an isolated side effect. Exporter/logger defects
1535
- * can never change the actor's transition, reply, or P3 observer cardinality.
1408
+ * Backend function paths, keyed by Convex module path then export name.
1409
+ *
1410
+ * Invariant (gate-enforced): `CAPXUL_FUNCTIONS[m][e] === \`${m}:${e}\``.
1536
1411
  */
1537
- const logIdentityTransition = (record) => (record.outcome === "applied" ? Effect.logInfo("identity.transition") : record.outcome === "failed" ? Effect.logError("identity.transition") : Effect.logWarning("identity.transition")).pipe(Effect.annotateLogs(transitionLogFields(record)), Effect.andThen(record.outcome === "applied" ? Effect.void : Effect.fail({ code: record.outcome === "refused" ? record.refusal_code : record.error_code })), Effect.withSpan("identity.transition"), Effect.annotateSpans(transitionSpanFields(record)), Effect.catchCause(() => Effect.void));
1538
- //#endregion
1539
- //#region src/domain/machine/shell.ts
1540
- const INVOCATION_PARENT_SPAN = Symbol("@capxul/sdk/identity-invocation-parent-span");
1541
- function carryInvocationParentSpan(controls, parent) {
1542
- return {
1543
- ...controls,
1544
- [INVOCATION_PARENT_SPAN]: parent
1545
- };
1546
- }
1547
- function withInvocationParentSpan(effect, controls) {
1548
- const parent = controls?.[INVOCATION_PARENT_SPAN];
1549
- return parent === void 0 ? effect : effect.pipe(Effect.withParentSpan(parent));
1550
- }
1551
- var ActorFailure = class extends Error {
1552
- reason;
1553
- machine;
1554
- state;
1555
- event;
1556
- details;
1557
- _tag = "ActorFailure";
1558
- constructor(reason, machine, state, event, details) {
1559
- super(`${machine}:${state}:${event} ${reason}`);
1560
- this.reason = reason;
1561
- this.machine = machine;
1562
- this.state = state;
1563
- this.event = event;
1564
- this.details = details;
1565
- this.name = "ActorFailure";
1566
- }
1567
- };
1568
- const duration = (startedAt) => Math.max(0, Date.now() - startedAt);
1569
- const failReply = (reply, failure) => reply === null ? Effect.void : Effect.asVoid(Deferred.fail(reply, failure));
1570
- const withCarriage = (controls) => ({
1571
- ...controls.correlation_id === void 0 ? {} : { correlation_id: controls.correlation_id },
1572
- ...controls.journey_id === void 0 ? {} : { journey_id: controls.journey_id }
1573
- });
1574
- const timeoutFailure = {
1575
- code: "PROVIDER_ERROR",
1576
- message: "Identity work timed out"
1577
- };
1578
- const cancelledFailure = {
1579
- code: "CANCELLED",
1580
- message: "Identity work cancelled"
1581
- };
1582
- const abort = (signal) => signal.aborted ? Effect.fail(cancelledFailure) : Effect.callback((resume) => {
1583
- const onAbort = () => resume(Effect.fail(cancelledFailure));
1584
- signal.addEventListener("abort", onAbort, { once: true });
1585
- return Effect.sync(() => signal.removeEventListener("abort", onAbort));
1586
- });
1587
- const control = (effect, controls) => {
1588
- let controlled = effect;
1589
- const deadlineDelay = controls.deadlineMs === void 0 ? void 0 : Math.max(0, controls.deadlineMs - Date.now());
1590
- const timeoutMs = controls.timeoutMs === void 0 ? deadlineDelay : deadlineDelay === void 0 ? controls.timeoutMs : Math.min(controls.timeoutMs, deadlineDelay);
1591
- if (timeoutMs !== void 0) controlled = controlled.pipe(Effect.timeoutOrElse({
1592
- duration: `${timeoutMs} millis`,
1593
- orElse: () => Effect.fail(timeoutFailure)
1594
- }));
1595
- if (controls.signal !== void 0) controlled = Effect.raceFirst(controlled, abort(controls.signal));
1596
- return controlled;
1597
- };
1598
- const boot = (spec, options = {}) => Effect.gen(function* () {
1599
- const mailbox = yield* Queue.unbounded();
1600
- const cell = yield* Ref.make(spec.initial);
1601
- const slotEpochs = /* @__PURE__ */ new Map();
1602
- const slots = /* @__PURE__ */ new Map();
1603
- const stateObservers = /* @__PURE__ */ new Set();
1604
- const transitionObservers = /* @__PURE__ */ new Set();
1605
- let bootTransitionObserver = options.onTransition;
1606
- let stopped = false;
1607
- const defect = (cause) => {
1608
- try {
1609
- options.onDefect?.(cause);
1610
- } catch {}
1611
- };
1612
- const emit = (record) => Effect.sync(() => {
1613
- if (bootTransitionObserver !== void 0) try {
1614
- bootTransitionObserver(record);
1615
- } catch (cause) {
1616
- bootTransitionObserver = void 0;
1617
- defect(cause);
1618
- }
1619
- for (const observer of transitionObservers) try {
1620
- observer(record);
1621
- } catch (cause) {
1622
- transitionObservers.delete(observer);
1623
- defect(cause);
1624
- }
1625
- }).pipe(Effect.andThen(logIdentityTransition(record)));
1626
- const notify = (state) => {
1627
- for (const observer of stateObservers) try {
1628
- observer(state);
1629
- } catch (cause) {
1630
- stateObservers.delete(observer);
1631
- defect(cause);
1632
- }
1633
- };
1634
- const makeFailure = (state, event, reason, details) => new ActorFailure(reason, spec.machine, spec.label(state), event._tag, details);
1635
- const nonApplied = (state, event, reason, outcome, env) => {
1636
- const slot = env.origin?.slot ?? spec.slot(event);
1637
- return copyInvocationObservation(env.invocation, {
1638
- machine: spec.machine,
1639
- state: spec.label(state),
1640
- event: event._tag,
1641
- slot,
1642
- epoch: env.origin?.epoch ?? slotEpochs.get(slot) ?? 0,
1643
- outcome,
1644
- duration_ms: duration(env.startedAt),
1645
- ...withCarriage(env.invocation),
1646
- ...outcome === "refused" ? { refusal_code: reason } : { error_code: reason }
1647
- });
1648
- };
1649
- const applied = (from, to, event, slot, epoch, env) => copyInvocationObservation(env.invocation, {
1650
- machine: spec.machine,
1651
- from: spec.label(from),
1652
- event: event._tag,
1653
- to: spec.label(to),
1654
- slot,
1655
- epoch,
1656
- outcome: "applied",
1657
- duration_ms: duration(env.startedAt),
1658
- ...withCarriage(env.invocation)
1659
- });
1660
- const finish = (cursor, state) => {
1661
- const held = slots.get(cursor.slot);
1662
- if (held === void 0 || held.cursor !== cursor) return Effect.void;
1663
- slots.delete(cursor.slot);
1664
- return Effect.asVoid(Deferred.succeed(held.reply, state));
1665
- };
1666
- const recoverFailure = (state, cursor, failure) => {
1667
- const event = spec.recoverFailure?.(state, cursor.event, failure);
1668
- if (event === void 0) return Effect.succeed(state);
1669
- const outcome = spec.transition(state, event);
1670
- if ("refused" in outcome) return Effect.succeed(state);
1671
- return Ref.set(cell, outcome.next).pipe(Effect.tap(() => {
1672
- return emit(applied(state, outcome.next, event, cursor.slot, cursor.epoch, {
1673
- invocation: cursor.invocation,
1674
- startedAt: cursor.startedAt
1675
- })).pipe(Effect.andThen(Effect.sync(() => {
1676
- notify(outcome.next);
1677
- })));
1678
- }), Effect.as(outcome.next));
1679
- };
1680
- const step = (env) => Effect.gen(function* () {
1681
- const state = yield* Ref.get(cell);
1682
- if (env.origin !== null && (slotEpochs.get(env.origin.slot) ?? 0) !== env.origin.epoch) {
1683
- const held = slots.get(env.origin.slot);
1684
- if (held === void 0 || held.cursor !== env.origin) return;
1685
- slots.delete(env.origin.slot);
1686
- const event = { _tag: env.origin.event };
1687
- yield* emit(nonApplied(state, event, "STALE_EPOCH", "refused", env));
1688
- yield* failReply(held.reply, makeFailure(state, event, "STALE_EPOCH"));
1689
- return;
1690
- }
1691
- if (env.origin !== null && env.event._tag === "~lane/exit") {
1692
- const exit = env.event;
1693
- const held = slots.get(env.origin.slot);
1694
- if (held === void 0 || held.cursor !== env.origin) return;
1695
- if (exit.defect !== void 0) {
1696
- slots.delete(env.origin.slot);
1697
- defect(exit.defect);
1698
- const event = { _tag: env.origin.event };
1699
- const failedState = yield* recoverFailure(state, env.origin, {
1700
- code: "WORK_DIED",
1701
- message: "Identity work died"
1702
- });
1703
- yield* emit(nonApplied(failedState, event, "WORK_DIED", "failed", env));
1704
- yield* failReply(held.reply, makeFailure(failedState, event, "WORK_DIED"));
1705
- return;
1706
- }
1707
- if (exit.failure !== void 0) {
1708
- slots.delete(env.origin.slot);
1709
- const outcome = exit.failure.code === "CANCELLED" ? "cancelled" : "failed";
1710
- const event = { _tag: env.origin.event };
1711
- const failedState = exit.failure === timeoutFailure || exit.failure === cancelledFailure ? yield* recoverFailure(state, env.origin, exit.failure) : state;
1712
- yield* emit(nonApplied(failedState, event, exit.failure.code, outcome, env));
1713
- const details = exit.failure === timeoutFailure ? { reason: "timeout" } : void 0;
1714
- yield* failReply(held.reply, makeFailure(failedState, event, exit.failure.code, details));
1715
- return;
1716
- }
1717
- yield* finish(env.origin, state);
1718
- return;
1719
- }
1720
- const outcome = spec.transition(state, env.event);
1721
- if ("refused" in outcome) {
1722
- yield* emit(nonApplied(state, env.event, outcome.refused, "refused", env));
1723
- yield* failReply(env.reply, makeFailure(state, env.event, outcome.refused));
1724
- return;
1725
- }
1726
- const next = outcome.next;
1727
- yield* Ref.set(cell, next);
1728
- const emitApplied = (slot, epoch) => emit(applied(state, next, env.event, slot, epoch, env));
1729
- if (env.origin !== null) {
1730
- yield* emitApplied(env.origin.slot, env.origin.epoch);
1731
- notify(next);
1732
- return;
1733
- }
1734
- for (const slot of spec.invalidates?.(env.event) ?? []) {
1735
- if (!slots.has(slot)) continue;
1736
- slotEpochs.set(slot, (slotEpochs.get(slot) ?? 0) + 1);
1737
- }
1738
- const work = env.reply === null ? void 0 : spec.work?.({
1739
- state: next,
1740
- event: env.event
1741
- });
1742
- if (work === void 0 || env.reply === null) {
1743
- const slot = spec.slot(env.event);
1744
- yield* emitApplied(slot, slotEpochs.get(slot) ?? 0);
1745
- notify(next);
1746
- if (env.reply !== null) yield* Deferred.succeed(env.reply, next).pipe(Effect.asVoid);
1747
- return;
1748
- }
1749
- const previous = slots.get(work.slot);
1750
- if (previous !== void 0) {
1751
- slots.delete(work.slot);
1752
- yield* Fiber.interrupt(previous.fiber);
1753
- const previousEvent = { _tag: previous.cursor.event };
1754
- const reason = previous.cursor.epoch === (slotEpochs.get(work.slot) ?? 0) ? "SUPERSEDED" : "STALE_EPOCH";
1755
- yield* emit(nonApplied(next, previousEvent, reason, "refused", {
1756
- origin: previous.cursor,
1757
- invocation: previous.cursor.invocation,
1758
- startedAt: previous.cursor.startedAt
1759
- }));
1760
- yield* failReply(previous.reply, makeFailure(next, previousEvent, reason));
1761
- }
1762
- const epoch = (slotEpochs.get(work.slot) ?? 0) + 1;
1763
- slotEpochs.set(work.slot, epoch);
1764
- const cursor = {
1765
- slot: work.slot,
1766
- epoch,
1767
- event: env.event._tag,
1768
- startedAt: env.startedAt,
1769
- invocation: env.invocation
1770
- };
1771
- yield* emitApplied(work.slot, epoch);
1772
- notify(next);
1773
- const send = (event) => Queue.offer(mailbox, {
1774
- event,
1775
- reply: null,
1776
- origin: cursor,
1777
- invocation: env.invocation,
1778
- startedAt: env.startedAt
1779
- }).pipe(Effect.asVoid);
1780
- const complete = (event) => Queue.offer(mailbox, {
1781
- event,
1782
- reply: null,
1783
- origin: cursor,
1784
- invocation: env.invocation,
1785
- startedAt: env.startedAt
1786
- }).pipe(Effect.asVoid);
1787
- const guarded = Effect.gen(function* () {
1788
- yield* Effect.annotateCurrentSpan({
1789
- slot: work.slot,
1790
- epoch,
1791
- port: work.port
1792
- });
1793
- return yield* control(work.run(send, env.invocation), env.invocation);
1794
- }).pipe(Effect.withSpan(`identity.work.${work.slot}`)).pipe(Effect.matchEffect({
1795
- onFailure: (failure) => complete({
1796
- _tag: "~lane/exit",
1797
- failure
1798
- }),
1799
- onSuccess: () => complete({ _tag: "~lane/exit" })
1800
- }), Effect.catchDefect((cause) => complete({
1801
- _tag: "~lane/exit",
1802
- defect: cause
1803
- })));
1804
- const fiber = yield* Effect.forkChild(guarded, { startImmediately: true });
1805
- slots.set(work.slot, {
1806
- fiber,
1807
- reply: env.reply,
1808
- cursor
1809
- });
1810
- });
1811
- const loop = yield* Effect.forkScoped(Effect.forever(Queue.take(mailbox).pipe(Effect.flatMap((env) => withInvocationParentSpan(step(env), env.invocation)))));
1812
- yield* Effect.addFinalizer(() => Effect.gen(function* () {
1813
- stopped = true;
1814
- yield* Fiber.interrupt(loop);
1815
- const state = yield* Ref.get(cell);
1816
- const outstanding = [...slots.values()];
1817
- slots.clear();
1818
- for (const held of outstanding) {
1819
- yield* Fiber.interrupt(held.fiber);
1820
- const env = {
1821
- origin: held.cursor,
1822
- invocation: held.cursor.invocation,
1823
- startedAt: held.cursor.startedAt
1824
- };
1825
- const event = { _tag: held.cursor.event };
1826
- yield* emit(nonApplied(state, event, "ACTOR_STOPPED", "refused", env));
1827
- yield* failReply(held.reply, makeFailure(state, event, "ACTOR_STOPPED"));
1828
- }
1829
- stateObservers.clear();
1830
- transitionObservers.clear();
1831
- yield* Queue.shutdown(mailbox);
1832
- }));
1833
- const offer = (event, reply, invocation) => {
1834
- const state = Ref.getUnsafe(cell);
1835
- if (stopped) return withInvocationParentSpan(emit(nonApplied(state, event, "ACTOR_STOPPED", "refused", {
1836
- origin: null,
1837
- invocation,
1838
- startedAt: Date.now()
1839
- })).pipe(Effect.andThen(Effect.fail(makeFailure(state, event, "ACTOR_STOPPED")))), invocation);
1840
- const startedAt = Date.now();
1841
- return Queue.offer(mailbox, {
1842
- event,
1843
- reply,
1844
- origin: null,
1845
- invocation,
1846
- startedAt
1847
- }).pipe(Effect.asVoid);
1848
- };
1849
- return {
1850
- ask: (event, invocation = {}) => Effect.gen(function* () {
1851
- const reply = yield* Deferred.make();
1852
- yield* offer(event, reply, invocation);
1853
- return yield* Deferred.await(reply);
1854
- }),
1855
- tell: (event, invocation = {}) => offer(event, null, invocation),
1856
- snapshot: () => Ref.getUnsafe(cell),
1857
- subscribe: (observer) => {
1858
- stateObservers.add(observer);
1859
- return () => {
1860
- stateObservers.delete(observer);
1861
- };
1862
- },
1863
- subscribeTransitions: (observer) => {
1864
- transitionObservers.add(observer);
1865
- return () => {
1866
- transitionObservers.delete(observer);
1867
- };
1868
- }
1869
- };
1870
- });
1871
- //#endregion
1872
- //#region src/surface/to-capxul-result.ts
1873
- /** The one place an Effect becomes a Promise on the public surface. */
1874
- async function runProgram(program, runPromise = Effect.runPromise) {
1875
- const result = await runPromise(program.pipe(Effect.catchDefect((defect) => Effect.fail(Errors.unknown(defect))), Effect.result));
1876
- if (Result.isFailure(result)) return {
1877
- ok: false,
1878
- error: result.failure
1879
- };
1880
- return {
1881
- ok: true,
1882
- value: result.success
1883
- };
1884
- }
1885
- async function toCapxulResult(program, layer) {
1886
- return runProgram(program.pipe(Effect.provide(layer)));
1887
- }
1888
- /**
1889
- * Signal-aware bridge for the Convex-backed method bundles. The adapters fail
1890
- * with `{ publicError }` rather than a bare `CapxulError`, so the wrapper is
1891
- * unwrapped here — once — instead of at every call site.
1892
- */
1893
- async function runIfActive(signal, operation, effect, runPromise = Effect.runPromise) {
1894
- if (signal?.aborted === true) return {
1895
- ok: false,
1896
- error: Errors.cancelled({ operation })
1897
- };
1898
- const program = effect().pipe(Effect.mapError((error) => error.publicError));
1899
- return runProgram(signal === void 0 ? program : Effect.raceFirst(program, Effect.callback((resume) => {
1900
- if (signal.aborted) {
1901
- resume(Effect.fail(Errors.cancelled({ operation })));
1902
- return Effect.void;
1903
- }
1904
- const onAbort = () => resume(Effect.fail(Errors.cancelled({ operation })));
1905
- signal.addEventListener("abort", onAbort, { once: true });
1906
- return Effect.sync(() => signal.removeEventListener("abort", onAbort));
1907
- })), runPromise);
1908
- }
1909
- //#endregion
1910
- //#region src/surface/_shared/effect-actor-bridge.ts
1911
- const facadeOutcome = (value) => {
1912
- if (typeof value !== "object" || value === null || !("ok" in value) || value.ok !== false) return "succeeded";
1913
- const reason = value.reason;
1914
- if (reason === "CANCELLED") return "cancelled";
1915
- return typeof reason === "string" && EXPECTED_OPERATION_OUTCOMES.has(reason) ? "refused" : "failed";
1916
- };
1917
- const rejectedFacadeOutcome = (cause) => {
1918
- if (cause instanceof CapxulError) return cause.code === "CANCELLED" ? "cancelled" : "failed";
1919
- if (typeof cause !== "object" || cause === null) return "failed";
1920
- const candidate = cause;
1921
- return candidate.code === "CANCELLED" || candidate.reason === "CANCELLED" || candidate.error?.code === "CANCELLED" || candidate.publicError?.code === "CANCELLED" ? "cancelled" : "failed";
1922
- };
1923
- const RESOLVED_FACADE_SPAN_FAILURE = Symbol("resolved facade span failure");
1924
- /** The single facade-span bridge consumed by the renderer-neutral React facade. */
1925
- async function runIdentityFacade(verb, controls, run, runPromise = Effect.runPromise) {
1926
- const correlationId = safeEngineeringIdentifier(controls?.correlation_id);
1927
- let resolvedFailure;
1928
- return runPromise(Effect.gen(function* () {
1929
- const parent = yield* Effect.currentSpan;
1930
- return yield* Effect.tryPromise({
1931
- try: () => run(carryInvocationParentSpan(controls, parent)),
1932
- catch: (cause) => cause
1933
- });
1934
- }).pipe(Effect.tapError((cause) => Effect.annotateCurrentSpan({ outcome: rejectedFacadeOutcome(cause) })), Effect.flatMap((value) => {
1935
- const outcome = facadeOutcome(value);
1936
- return Effect.annotateCurrentSpan({ outcome }).pipe(Effect.andThen(outcome === "failed" || outcome === "cancelled" ? Effect.sync(() => {
1937
- resolvedFailure = value;
1938
- }).pipe(Effect.andThen(Effect.fail(RESOLVED_FACADE_SPAN_FAILURE))) : Effect.succeed(value)));
1939
- }), Effect.withSpan(`identity.${verb}`), Effect.annotateSpans({
1940
- verb,
1941
- ...correlationId === void 0 ? {} : { correlation_id: correlationId }
1942
- }), Effect.catch((cause) => cause === RESOLVED_FACADE_SPAN_FAILURE ? Effect.succeed(resolvedFailure) : Effect.fail(cause))));
1943
- }
1944
- /**
1945
- * Bridge an Effect whose typed failure carries `{ publicError: CapxulError }`
1946
- * into the `Promise<CapxulResult<T>>` shape the consumer-facing method bundles
1947
- * return. Applies to every port that surfaces a `publicError` (smart-account,
1948
- * identity, auth-cache, account provision/deploy).
1949
- */
1950
- async function runPortEffect(effect, controls, operation = "port", runPromise = Effect.runPromise) {
1951
- const deadlineDelay = controls?.deadlineMs === void 0 ? void 0 : Math.max(0, controls.deadlineMs - Date.now());
1952
- const timeoutMs = controls?.timeoutMs === void 0 ? deadlineDelay : deadlineDelay === void 0 ? controls.timeoutMs : Math.min(controls.timeoutMs, deadlineDelay);
1953
- const observed = (timeoutMs === void 0 ? effect : effect.pipe(Effect.timeoutOrElse({
1954
- duration: `${timeoutMs} millis`,
1955
- orElse: () => Effect.fail({ publicError: Errors.providerTimeout("sdk", operation, timeoutMs) })
1956
- }))).pipe(Effect.tap(() => Effect.annotateCurrentSpan({ outcome: "succeeded" })), Effect.tapError((failure) => {
1957
- const mode = failure.publicError.details?.failure_mode;
1958
- return Effect.annotateCurrentSpan({
1959
- outcome: portFailureOutcome(failure.publicError.code),
1960
- failure_code: failure.publicError.code,
1961
- ...typeof mode === "string" ? { mode } : {}
1962
- });
1963
- }), Effect.tapDefect(() => Effect.annotateCurrentSpan({
1964
- outcome: "failed",
1965
- failure_code: "UNKNOWN"
1966
- })), Effect.withSpan(`identity.port.${operation}`));
1967
- return runIfActive(controls?.signal, operation, () => withInvocationParentSpan(observed, controls), runPromise);
1968
- }
1969
- /** Map machine-internal failure state onto the public SDK error vocabulary. */
1970
- function publicIdentityFailure(failure) {
1971
- if (failure.error !== void 0) return failure.error;
1972
- return new CapxulError(failure.code === "WORK_DIED" ? "UNKNOWN" : failure.code, failure.message, {
1973
- ...failure.mode === void 0 ? {} : { details: { failure_mode: failure.mode } },
1974
- layer: "identity"
1975
- });
1976
- }
1977
- /** The session carried by the actor's current snapshot, or `null`. */
1978
- function sessionFromActor(actor) {
1979
- return actor.authSession();
1980
- }
1981
- //#endregion
1982
- //#region src/surface/account-deps.ts
1983
- /** The single Context tag the account atom + `account.getStatus` resolve. */
1984
- var AccountDepsTag = class extends Context.Service()("@capxul/sdk/AccountDeps") {};
1985
- /** Wrap a bundle as the `Layer<AccountDepsTag>` the React provider consumes. */
1986
- function accountDepsLayer(deps) {
1987
- return Layer.succeed(AccountDepsTag, deps);
1988
- }
1989
- /**
1990
- * `account.getStatus` as a single Effect requiring ONLY `AccountDepsTag`.
1991
- * Faithful transcription of the current public method body (`account.ts`):
1992
- * resolve the session (actor first, then the resume-path `authCache`), then
1993
- * walk the readiness ladder. The `SmartAccountPort` failure narrows to its
1994
- * `publicError`; a consumer `AccountProvider.getAddress` rejection becomes a
1995
- * `providerError` (defending the public `CapxulResult` contract).
1996
- */
1997
- const accountStatusProgram = Effect.gen(function* () {
1998
- const deps = yield* AccountDepsTag;
1999
- const session = yield* Effect.promise(() => currentSession(deps.actor, deps.authCache));
2000
- if (session === null) return { status: "notAuthenticated" };
2001
- const current = yield* deps.smartAccountPort.loadByAuthUserId(session.authUserId).pipe(Effect.mapError((failure) => failure.publicError));
2002
- if (current !== null) return statusFromAccount(current, deps.requirement);
2003
- if (deps.requirement === "none") return {
2004
- status: "accountReady",
2005
- requirement: deps.requirement,
2006
- account: null,
2007
- deployment: { status: "counterfactual" }
2008
- };
2009
- const signer = deps.signer;
2010
- if (signer === void 0) return {
2011
- status: "accountRequired",
2012
- requirement: deps.requirement,
2013
- chainId: deps.chainId
2014
- };
2015
- const signerAddress = yield* Effect.tryPromise({
2016
- try: () => signer.getAddress(),
2017
- catch: (cause) => signerFailure(signer.source, "getAddress", cause)
2018
- });
2019
- return {
2020
- status: "accountProviderReady",
2021
- requirement: deps.requirement,
2022
- chainId: deps.chainId,
2023
- source: signer.source,
2024
- signerAddress
2025
- };
2026
- });
2027
- /**
2028
- * Resume-path session resolution. Consults the actor first; if the actor has
2029
- * no session (e.g. page refresh before any sign-in event), reads
2030
- * `authCache.getSession`. `AuthCacheError` is non-fatal at this read point —
2031
- * treat as "no session" and let the consumer's `auth.signIn` path resolve.
2032
- */
2033
- async function currentSession(actor, authCache) {
2034
- const fromActor = sessionFromActor(actor);
2035
- if (fromActor !== null) return fromActor;
2036
- if (authCache === void 0) return null;
2037
- const cached = await Effect.runPromise(Effect.result(authCache.getSession));
2038
- if (Result.isSuccess(cached)) {
2039
- if (cached.success !== null && typeof actor.restoreAuthSession === "function") {
2040
- const restored = await Effect.runPromise(Effect.result(actor.restoreAuthSession(cached.success)));
2041
- if (Result.isFailure(restored)) return null;
2042
- }
2043
- return cached.success;
2044
- }
2045
- return null;
2046
- }
2047
- /** Map a backend `SmartAccount` row onto the readiness `AccountStatus`. */
2048
- function statusFromAccount(account, requirement) {
2049
- if (requirement === "deployed") {
2050
- if (account.deployedAt === null) return {
2051
- status: "accountPrepared",
2052
- requirement,
2053
- account,
2054
- deployment: { status: "counterfactual" }
2055
- };
2056
- return {
2057
- status: "accountReady",
2058
- requirement,
2059
- account,
2060
- deployment: {
2061
- status: "deployed",
2062
- deployedAt: account.deployedAt
2063
- }
2064
- };
2065
- }
2066
- return {
2067
- status: "accountReady",
2068
- requirement,
2069
- account,
2070
- deployment: account.deployedAt === null ? { status: "counterfactual" } : {
2071
- status: "deployed",
2072
- deployedAt: account.deployedAt
2073
- }
2074
- };
2075
- }
2076
- //#endregion
2077
- //#region src/surface/account-lifecycle.ts
2078
- function isActiveProvisioningPhase(phase) {
2079
- return phase.status === "wallet" || phase.status === "identity" || phase.status === "provision" || phase.status === "deploy";
2080
- }
2081
- function isRequirementMet(status, requirement) {
2082
- if (requirement === "none") return status.status !== "notAuthenticated";
2083
- if (status.status !== "accountReady") return false;
2084
- return requirement !== "deployed" || status.deployment.status === "deployed";
2085
- }
2086
- function mapProvisioningFailureStep(step) {
2087
- switch (step) {
2088
- case "wallet": return "connecting";
2089
- case "identity": return "registering";
2090
- case "provision":
2091
- case "deploy": return "activating";
2092
- }
2093
- }
2094
- function mapProvisioningPhaseToSetupStep(phase) {
2095
- switch (phase.status) {
2096
- case "idle":
2097
- case "wallet": return "connecting";
2098
- case "identity": return "registering";
2099
- case "provision":
2100
- case "deploy": return "activating";
2101
- case "ready":
2102
- case "failed": return "connecting";
2103
- }
2104
- }
2105
- function isSettingUpLifecycle(lifecycle) {
2106
- return lifecycle.status === "settingUp";
2107
- }
2108
- function readyLifecycle(status, accountId) {
2109
- return {
2110
- status: "ready",
2111
- accountId,
2112
- canTransact: status.status === "accountReady" && status.deployment.status === "deployed"
2113
- };
2114
- }
2115
- function mapAccountLifecycle(input) {
2116
- const { status, phase, requirement, accountId } = input;
2117
- if (status.status === "notAuthenticated") return { status: "loading" };
2118
- if (phase.status === "failed") return {
2119
- status: "failed",
2120
- at: mapProvisioningFailureStep(phase.at),
2121
- error: phase.error
2122
- };
2123
- if (isRequirementMet(status, requirement) || phase.status === "ready") {
2124
- if (accountId === void 0) return { status: "loading" };
2125
- return readyLifecycle(status, accountId);
2126
- }
2127
- if (isActiveProvisioningPhase(phase) || phase.status === "idle") return {
2128
- status: "settingUp",
2129
- step: mapProvisioningPhaseToSetupStep(phase)
2130
- };
2131
- return { status: "loading" };
2132
- }
2133
- //#endregion
2134
- //#region ../wire/src/brands.ts
2135
- const lowercasedString = Schema.String.pipe(Schema.decodeTo(Schema.String, {
2136
- decode: SchemaGetter.transform((value) => value.toLowerCase()),
2137
- encode: SchemaGetter.transform((value) => value)
2138
- }));
2139
- const addressSchema = (name) => lowercasedString.pipe(Schema.refine((value) => EVM_ADDRESS_RE$1.test(value), { message: `${name} must be a 0x-prefixed EVM address` }));
2140
- const bytes32BrandSchema = (name) => lowercasedString.pipe(Schema.refine((value) => BYTES32_RE.test(value), { message: `${name} must be a 0x-prefixed bytes32 value` }));
2141
- /** Lowercase, 0x-prefixed bytes32 evidence without a public brand. */
2142
- const Bytes32Schema = bytes32BrandSchema("value");
2143
- const AddressSchema$1 = addressSchema("address");
2144
- const SafeAddressSchema = addressSchema("safe address");
2145
- const ModuleAddressSchema = addressSchema("module address");
2146
- const TxHashSchema$1 = bytes32BrandSchema("transaction hash");
2147
- const RoleKeySchema = bytes32BrandSchema("role key");
2148
- const AllowanceKeySchema = bytes32BrandSchema("allowance key");
2149
- const BlockNumberSchema$1 = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" }));
2150
- const LogIndexSchema = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" }));
2151
- const WeiAmountSchema$1 = Schema.String.pipe(Schema.refine((value) => WEI_RE.test(value), { message: "must be a non-negative integer string" }));
2152
- const SettlementIdSchema = bytes32BrandSchema("settlementId").pipe(Schema.refine((value) => value !== ZERO_BYTES32, { message: "settlementId must not be zero" }));
2153
- /**
2154
- * `AppId` schema. Mirrors `toAppId` from `@capxul/types`:
2155
- * `app_` + Crockford-base32 ULID (26 chars, first char in `[0-7]`).
2156
- */
2157
- const AppIdSchema$1 = Schema.String.pipe(Schema.refine((s) => APP_ID_RE.test(s), { message: "must be app_ plus a ULID" }));
2158
- /**
2159
- * `ChainId` schema. Mirrors `toChainId`: positive safe integer.
2160
- */
2161
- const ChainIdSchema$1 = Schema.Number.pipe(Schema.refine((n) => Number.isSafeInteger(n) && n > 0, { message: "must be a positive safe integer" }));
2162
- /**
2163
- * `CurrencyCode` schema. Mirrors `toCurrencyCode`: currently supported
2164
- * consumer-facing ISO-ish currency code set.
2165
- */
2166
- const CurrencyCodeSchema$1 = Schema.String.pipe(Schema.refine((s) => SUPPORTED_CURRENCY_CODES.includes(s), { message: "must be a supported currency code" }));
2167
- const DOCUMENT_HASH_HEX_RE = /^[0-9a-fA-F]{64}$/;
2168
- /**
2169
- * `DocumentHash` schema. Mirrors `toDocumentHash`: bare or 0x-prefixed bytes32,
2170
- * normalized to lowercase 0x-prefixed form.
2171
- */
2172
- const DocumentHashSchema = Schema.String.pipe(Schema.decodeTo(Schema.String, {
2173
- decode: SchemaGetter.transform((s) => {
2174
- const stripped = s.startsWith("0x") || s.startsWith("0X") ? s.slice(2) : s;
2175
- return DOCUMENT_HASH_HEX_RE.test(stripped) ? `0x${stripped.toLowerCase()}` : s;
2176
- }),
2177
- encode: SchemaGetter.transform((s) => s)
2178
- }), Schema.refine((s) => BYTES32_RE.test(s), { message: "must be 32 bytes of hex" }));
2179
- /** L2 orchestrated money evidence requires a nonzero Document hash. */
2180
- const NonzeroDocumentHashSchema = DocumentHashSchema.pipe(Schema.refine((value) => value !== ZERO_BYTES32, { message: "documentHash must not be zero" }));
2181
- /**
2182
- * `SessionToken` schema. Mirrors `toSessionToken`: non-empty string.
2183
- * Issuance source distinguishes SDK-handshake tokens from auth-session
2184
- * tokens; the brand itself is opaque.
2185
- */
2186
- const SessionTokenSchema = Schema.String.pipe(Schema.refine((s) => s.length > 0, { message: "must be a non-empty string" }));
2187
- /**
2188
- * `EpochMs` schema. Mirrors `toEpochMs`: non-negative safe integer.
2189
- */
2190
- const EpochMsSchema$1 = Schema.Number.pipe(Schema.refine((n) => Number.isSafeInteger(n) && n >= 0, { message: "must be a non-negative safe integer" }));
2191
- /**
2192
- * `DurationMs` schema. Mirrors `toDurationMs`: non-negative safe integer.
2193
- */
2194
- const DurationMsSchema$1 = Schema.Number.pipe(Schema.refine((n) => Number.isSafeInteger(n) && n >= 0, { message: "must be a non-negative safe integer" }));
2195
- //#endregion
2196
- //#region ../wire/src/bootstrap.ts
2197
- const PUBLIC_POSTHOG_PROJECT_TOKEN = /^phc_[A-Za-z0-9_-]{1,191}$/u;
2198
- const PostHogIngestOrigin = Schema.String.pipe(Schema.refine((value) => {
2199
- try {
2200
- const url = new URL(value);
2201
- return url.protocol === "https:" && url.username.length === 0 && url.password.length === 0 && url.pathname === "/" && url.search.length === 0 && url.hash.length === 0 && (url.hostname === "posthog.com" || url.hostname.endsWith(".posthog.com"));
2202
- } catch {
2203
- return false;
2204
- }
2205
- }, { message: "must be a credential-free PostHog HTTPS ingest origin" }));
2206
- const EngineeringTelemetryBootstrapPolicy = Schema.Struct({
2207
- host: PostHogIngestOrigin,
2208
- projectToken: Schema.String.pipe(Schema.refine((value) => PUBLIC_POSTHOG_PROJECT_TOKEN.test(value), { message: "must be a public PostHog project token" })),
2209
- capxulEnv: Schema.Union([
2210
- Schema.Literal("development"),
2211
- Schema.Literal("staging"),
2212
- Schema.Literal("production")
2213
- ])
2214
- });
2215
- /**
2216
- * `BootstrapEnvelope` v1.
2217
- *
2218
- * - `protocol`: discriminator that lets future protocols coexist on the
2219
- * same endpoint without a wire-shape conflict.
2220
- * - `version`: numeric version inside the protocol. Unknown versions MUST
2221
- * fail decode with an INVALID_INPUT-class `CapxulError` at the SDK seam.
2222
- * - `state`: the resolved bootstrap payload. Field shape matches the
2223
- * `BootstrapResolution` port; the SDK consumer can pass `state`
2224
- * directly (after `normalizeRuntimeUrl` on the two URL fields) into
2225
- * the port without re-branding.
2226
- */
2227
- const BootstrapEnvelope = Schema.Struct({
2228
- protocol: Schema.Literal("capxul.bootstrap"),
2229
- version: Schema.Literal(1),
2230
- state: Schema.Struct({
2231
- applicationId: AppIdSchema$1,
2232
- chainId: ChainIdSchema$1,
2233
- sessionToken: SessionTokenSchema,
2234
- issuedAt: EpochMsSchema$1,
2235
- expiresIn: DurationMsSchema$1,
2236
- authBaseUrl: Schema.String,
2237
- convexUrl: Schema.String,
2238
- siteBaseUrl: Schema.String,
2239
- openfortPublishableKey: Schema.String,
2240
- shieldPublishableKey: Schema.String,
2241
- engineeringTelemetry: Schema.optional(EngineeringTelemetryBootstrapPolicy)
2242
- })
2243
- });
2244
- //#endregion
2245
- //#region ../wire/src/functions.ts
2246
- /**
2247
- * Backend function paths, keyed by Convex module path then export name.
2248
- *
2249
- * Invariant (gate-enforced): `CAPXUL_FUNCTIONS[m][e] === \`${m}:${e}\``.
2250
- */
2251
- const CAPXUL_FUNCTIONS = {
2252
- "account/actions": {
2253
- faucetMint: "account/actions:faucetMint",
2254
- readBalance: "account/actions:readBalance"
2255
- },
2256
- "financialOps/addressBook": {
2257
- add: "financialOps/addressBook:add",
2258
- get: "financialOps/addressBook:get",
2259
- hide: "financialOps/addressBook:hide",
2260
- label: "financialOps/addressBook:label",
2261
- list: "financialOps/addressBook:list",
2262
- unhide: "financialOps/addressBook:unhide"
2263
- },
2264
- "financialOps/destinations": {
2265
- add: "financialOps/destinations:add",
2266
- list: "financialOps/destinations:list",
2267
- remove: "financialOps/destinations:remove"
2268
- },
2269
- "financialOps/mutations": { createPayee: "financialOps/mutations:createPayee" },
2270
- "financialOps/queries": {
2271
- depositInstructions: "financialOps/queries:depositInstructions",
2272
- getPayee: "financialOps/queries:getPayee",
2273
- getPayment: "financialOps/queries:getPayment",
2274
- listPayments: "financialOps/queries:listPayments",
2275
- me: "financialOps/queries:me",
2276
- renderStoredDocument: "financialOps/queries:renderStoredDocument",
2277
- resolveHandle: "financialOps/queries:resolveHandle",
2278
- resolvePayee: "financialOps/queries:resolvePayee",
2279
- verifyPaymentDocument: "financialOps/queries:verifyPaymentDocument"
2280
- },
2281
- "financialOps/requestsInbox": {
2282
- approve: "financialOps/requestsInbox:approve",
2283
- cancel: "financialOps/requestsInbox:cancel",
2284
- decline: "financialOps/requestsInbox:decline",
2285
- get: "financialOps/requestsInbox:get",
2286
- inboxList: "financialOps/requestsInbox:inboxList",
2287
- issue: "financialOps/requestsInbox:issue",
2288
- list: "financialOps/requestsInbox:list"
2289
- },
2290
- "identity/mutations": {
2291
- completeOnboarding: "identity/mutations:completeOnboarding",
2292
- create: "identity/mutations:create",
2293
- update: "identity/mutations:update"
2294
- },
2295
- "identity/queries": {
2296
- loadByAuthUserId: "identity/queries:loadByAuthUserId",
2297
- usernameAvailable: "identity/queries:usernameAvailable"
2298
- },
2299
- "holdings/actions": { current: "holdings/actions:current" },
2300
- "movement/activity": {
2301
- annotate: "movement/activity:annotate",
2302
- get: "movement/activity:get",
2303
- list: "movement/activity:list"
2304
- },
2305
- "moneyExecution/actions": {
2306
- preparePermissionExecution: "moneyExecution/actions:preparePermissionExecution",
2307
- preparePaymentExecution: "moneyExecution/actions:preparePaymentExecution",
2308
- submitPermissionExecution: "moneyExecution/actions:submitPermissionExecution",
2309
- submitPaymentExecution: "moneyExecution/actions:submitPaymentExecution"
2310
- },
2311
- "moneyExecution/paymentCommandActions": {
2312
- preparePaymentLifecycleExecution: "moneyExecution/paymentCommandActions:preparePaymentLifecycleExecution",
2313
- prepareOrganizationPaymentExecution: "moneyExecution/paymentCommandActions:prepareOrganizationPaymentExecution",
2314
- submitPaymentCommandExecution: "moneyExecution/paymentCommandActions:submitPaymentCommandExecution"
2315
- },
2316
- media: {
2317
- generateUploadUrl: "media:generateUploadUrl",
2318
- setOrgLogo: "media:setOrgLogo",
2319
- setProfileImage: "media:setProfileImage"
2320
- },
2321
- "org/actions": {
2322
- confirmBootstrap: "org/actions:confirmBootstrap",
2323
- detectAndAcceptPendingInvitations: "org/actions:detectAndAcceptPendingInvitations",
2324
- inviteMember: "org/actions:inviteMember",
2325
- prepareBootstrap: "org/actions:prepareBootstrap",
2326
- prepareFounderAccount: "org/actions:prepareFounderAccount",
2327
- readTreasury: "org/actions:readTreasury",
2328
- resumeBootstrapSubmission: "org/actions:resumeBootstrapSubmission",
2329
- submitBootstrap: "org/actions:submitBootstrap"
2330
- },
2331
- "permission/actions": { verify: "permission/actions:verify" },
2332
- "permission/mutations": { command: "permission/mutations:command" },
2333
- "permission/queries": {
2334
- authorize: "permission/queries:authorize",
2335
- read: "permission/queries:read"
2336
- },
2337
- "org/lifecycle": {
2338
- getProofReceipt: "org/lifecycle:getProofReceipt",
2339
- load: "org/lifecycle:load",
2340
- recordFailure: "org/lifecycle:recordFailure",
2341
- retry: "org/lifecycle:retry",
2342
- startOrResume: "org/lifecycle:startOrResume"
2343
- },
2344
- "org/mutations": {
2345
- createOrg: "org/mutations:createOrg",
2346
- resendInviteToken: "org/mutations:resendInviteToken"
2347
- },
2348
- "org/queries": {
2349
- listAll: "org/queries:listAll",
2350
- listMembersByOrgId: "org/queries:listMembersByOrgId",
2351
- listMine: "org/queries:listMine",
2352
- listRolesByOrgId: "org/queries:listRolesByOrgId",
2353
- loadByOrgId: "org/queries:loadByOrgId",
2354
- me: "org/queries:me"
2355
- },
2356
- "smartAccount/actions": {
2357
- claim: "smartAccount/actions:claim",
2358
- confirmDeployment: "smartAccount/actions:confirmDeployment"
2359
- },
2360
- "smartAccount/mutations": { provision: "smartAccount/mutations:provision" },
2361
- "smartAccount/queries": {
2362
- loadByAuthUserId: "smartAccount/queries:loadByAuthUserId",
2363
- loadBySmartAccountAddress: "smartAccount/queries:loadBySmartAccountAddress"
2364
- },
2365
- system: { health: "system:health" }
1412
+ const CAPXUL_FUNCTIONS = {
1413
+ "account/actions": {
1414
+ faucetMint: "account/actions:faucetMint",
1415
+ readBalance: "account/actions:readBalance"
1416
+ },
1417
+ "financialOps/addressBook": {
1418
+ add: "financialOps/addressBook:add",
1419
+ get: "financialOps/addressBook:get",
1420
+ hide: "financialOps/addressBook:hide",
1421
+ label: "financialOps/addressBook:label",
1422
+ list: "financialOps/addressBook:list",
1423
+ unhide: "financialOps/addressBook:unhide"
1424
+ },
1425
+ "financialOps/destinations": {
1426
+ add: "financialOps/destinations:add",
1427
+ list: "financialOps/destinations:list",
1428
+ remove: "financialOps/destinations:remove"
1429
+ },
1430
+ "financialOps/mutations": { createPayee: "financialOps/mutations:createPayee" },
1431
+ "financialOps/queries": {
1432
+ depositInstructions: "financialOps/queries:depositInstructions",
1433
+ getPayee: "financialOps/queries:getPayee",
1434
+ getPayment: "financialOps/queries:getPayment",
1435
+ listPayments: "financialOps/queries:listPayments",
1436
+ me: "financialOps/queries:me",
1437
+ renderStoredDocument: "financialOps/queries:renderStoredDocument",
1438
+ resolveHandle: "financialOps/queries:resolveHandle",
1439
+ resolvePayee: "financialOps/queries:resolvePayee",
1440
+ verifyPaymentDocument: "financialOps/queries:verifyPaymentDocument"
1441
+ },
1442
+ "financialOps/requestsInbox": {
1443
+ approve: "financialOps/requestsInbox:approve",
1444
+ cancel: "financialOps/requestsInbox:cancel",
1445
+ decline: "financialOps/requestsInbox:decline",
1446
+ get: "financialOps/requestsInbox:get",
1447
+ inboxList: "financialOps/requestsInbox:inboxList",
1448
+ issue: "financialOps/requestsInbox:issue",
1449
+ list: "financialOps/requestsInbox:list"
1450
+ },
1451
+ "identity/mutations": {
1452
+ completeOnboarding: "identity/mutations:completeOnboarding",
1453
+ create: "identity/mutations:create",
1454
+ update: "identity/mutations:update"
1455
+ },
1456
+ "identity/queries": {
1457
+ loadByAuthUserId: "identity/queries:loadByAuthUserId",
1458
+ usernameAvailable: "identity/queries:usernameAvailable"
1459
+ },
1460
+ "holdings/actions": { current: "holdings/actions:current" },
1461
+ "movement/activity": {
1462
+ annotate: "movement/activity:annotate",
1463
+ get: "movement/activity:get",
1464
+ list: "movement/activity:list",
1465
+ summary: "movement/activity:summary"
1466
+ },
1467
+ "moneyExecution/actions": {
1468
+ preparePermissionExecution: "moneyExecution/actions:preparePermissionExecution",
1469
+ preparePaymentExecution: "moneyExecution/actions:preparePaymentExecution",
1470
+ submitPermissionExecution: "moneyExecution/actions:submitPermissionExecution",
1471
+ submitPaymentExecution: "moneyExecution/actions:submitPaymentExecution"
1472
+ },
1473
+ "moneyExecution/paymentCommandActions": {
1474
+ preparePaymentLifecycleExecution: "moneyExecution/paymentCommandActions:preparePaymentLifecycleExecution",
1475
+ prepareOrganizationPaymentExecution: "moneyExecution/paymentCommandActions:prepareOrganizationPaymentExecution",
1476
+ submitPaymentCommandExecution: "moneyExecution/paymentCommandActions:submitPaymentCommandExecution"
1477
+ },
1478
+ media: {
1479
+ generateUploadUrl: "media:generateUploadUrl",
1480
+ setOrgLogo: "media:setOrgLogo",
1481
+ setProfileImage: "media:setProfileImage"
1482
+ },
1483
+ "org/actions": {
1484
+ confirmBootstrap: "org/actions:confirmBootstrap",
1485
+ detectAndAcceptPendingInvitations: "org/actions:detectAndAcceptPendingInvitations",
1486
+ inviteMember: "org/actions:inviteMember",
1487
+ prepareBootstrap: "org/actions:prepareBootstrap",
1488
+ prepareFounderAccount: "org/actions:prepareFounderAccount",
1489
+ readTreasury: "org/actions:readTreasury",
1490
+ resumeBootstrapSubmission: "org/actions:resumeBootstrapSubmission",
1491
+ submitBootstrap: "org/actions:submitBootstrap"
1492
+ },
1493
+ "payroll/actions": { authorizeRun: "payroll/actions:authorizeRun" },
1494
+ "payroll/mutations": {
1495
+ removeGroup: "payroll/mutations:removeGroup",
1496
+ saveGroup: "payroll/mutations:saveGroup"
1497
+ },
1498
+ "payroll/queries": {
1499
+ groups: "payroll/queries:groups",
1500
+ runs: "payroll/queries:runs"
1501
+ },
1502
+ "permission/actions": { verify: "permission/actions:verify" },
1503
+ "permission/mutations": { command: "permission/mutations:command" },
1504
+ "permission/queries": {
1505
+ authorize: "permission/queries:authorize",
1506
+ read: "permission/queries:read"
1507
+ },
1508
+ "org/lifecycle": {
1509
+ getProofReceipt: "org/lifecycle:getProofReceipt",
1510
+ load: "org/lifecycle:load",
1511
+ recordFailure: "org/lifecycle:recordFailure",
1512
+ retry: "org/lifecycle:retry",
1513
+ startOrResume: "org/lifecycle:startOrResume"
1514
+ },
1515
+ "org/mutations": {
1516
+ createOrg: "org/mutations:createOrg",
1517
+ resendInviteToken: "org/mutations:resendInviteToken"
1518
+ },
1519
+ "org/queries": {
1520
+ listAll: "org/queries:listAll",
1521
+ listMembersByOrgId: "org/queries:listMembersByOrgId",
1522
+ listMine: "org/queries:listMine",
1523
+ listRolesByOrgId: "org/queries:listRolesByOrgId",
1524
+ loadByOrgId: "org/queries:loadByOrgId",
1525
+ me: "org/queries:me"
1526
+ },
1527
+ "smartAccount/actions": {
1528
+ claim: "smartAccount/actions:claim",
1529
+ confirmDeployment: "smartAccount/actions:confirmDeployment"
1530
+ },
1531
+ "smartAccount/mutations": { provision: "smartAccount/mutations:provision" },
1532
+ "smartAccount/queries": {
1533
+ loadByAuthUserId: "smartAccount/queries:loadByAuthUserId",
1534
+ loadBySmartAccountAddress: "smartAccount/queries:loadBySmartAccountAddress"
1535
+ },
1536
+ system: { health: "system:health" }
2366
1537
  };
2367
1538
  //#endregion
2368
1539
  //#region ../wire/src/status.ts
@@ -3521,7 +2692,7 @@ Schema.Struct({
3521
2692
  items: Schema.Array(OrganizationPaymentExecutionItemSchema),
3522
2693
  lineage: Schema.optional(PaymentCommandLineageSchema)
3523
2694
  });
3524
- Schema.Struct({
2695
+ const PreparedPaymentCommandExecutionSchema = Schema.Struct({
3525
2696
  executionId: MoneyExecutionIdSchema,
3526
2697
  commandId: PaymentCommandIdSchema,
3527
2698
  paymentIds: Schema.Array(PaymentIdSchema),
@@ -3594,155 +2765,1058 @@ Schema.Struct({
3594
2765
  signerAddress: AddressSchema$1,
3595
2766
  command: PermissionCommandSchema
3596
2767
  });
3597
- Schema.Struct({
3598
- executionId: MoneyExecutionIdSchema,
3599
- commandId: PaymentCommandIdSchema,
3600
- operation: PermissionOperationSchema,
3601
- orgId: nonEmpty("orgId"),
3602
- command: PermissionCommandSchema,
3603
- expectedRevision: nonNegativeInteger("expectedRevision"),
3604
- chainId: BaseSepoliaChainIdSchema,
3605
- signerAddress: AddressSchema$1,
3606
- userOpSenderSafe: SafeAddressSchema,
3607
- digest: Bytes32Schema,
3608
- value: PermissionResourceSchema
2768
+ Schema.Struct({
2769
+ executionId: MoneyExecutionIdSchema,
2770
+ commandId: PaymentCommandIdSchema,
2771
+ operation: PermissionOperationSchema,
2772
+ orgId: nonEmpty("orgId"),
2773
+ command: PermissionCommandSchema,
2774
+ expectedRevision: nonNegativeInteger("expectedRevision"),
2775
+ chainId: BaseSepoliaChainIdSchema,
2776
+ signerAddress: AddressSchema$1,
2777
+ userOpSenderSafe: SafeAddressSchema,
2778
+ digest: Bytes32Schema,
2779
+ value: PermissionResourceSchema
2780
+ });
2781
+ Schema.Struct({
2782
+ status: Schema.Literal("submitted"),
2783
+ executionId: MoneyExecutionIdSchema,
2784
+ commandId: PaymentCommandIdSchema,
2785
+ userOpHash: Bytes32Schema,
2786
+ value: PermissionResourceSchema
2787
+ });
2788
+ const PayrollRunStatusSchema = Schema.Literals([
2789
+ "draft",
2790
+ "authorized",
2791
+ "settled"
2792
+ ]);
2793
+ const PayrollRunIdSchema = Schema.String.pipe(Schema.refine((value) => /^payroll_run_[0-9a-f]{64}$/u.test(value), { message: "payrollRunId must be a payroll_run_ digest identifier" }));
2794
+ const SignedMinorUnitSchema = Schema.String.pipe(Schema.refine((value) => /^-?(0|[1-9][0-9]*)$/u.test(value), { message: "must be an integer minor-unit string" }));
2795
+ const MinorUnitSchema = Schema.String.pipe(Schema.refine((value) => /^(0|[1-9][0-9]*)$/u.test(value), { message: "must be a non-negative integer minor-unit string" }));
2796
+ const PayrollRunItemInputSchema = Schema.Struct({
2797
+ to: PaymentRef,
2798
+ partyId: nonEmpty("partyId"),
2799
+ gross: MinorUnitSchema,
2800
+ net: MinorUnitSchema,
2801
+ adjustments: Schema.Array(Schema.Struct({
2802
+ label: Schema.String,
2803
+ amount: SignedMinorUnitSchema
2804
+ }))
2805
+ });
2806
+ Schema.Struct({
2807
+ orgId: nonEmpty("orgId"),
2808
+ permissionId: PermissionIdSchema,
2809
+ requestKey: nonEmpty("requestKey"),
2810
+ signerAddress: AddressSchema$1,
2811
+ period: Schema.Struct({
2812
+ start: nonNegativeInteger("period.start"),
2813
+ end: nonNegativeInteger("period.end")
2814
+ }),
2815
+ items: Schema.Array(PayrollRunItemInputSchema)
2816
+ });
2817
+ const PayrollRunSchema = Schema.Struct({
2818
+ id: PayrollRunIdSchema,
2819
+ status: PayrollRunStatusSchema,
2820
+ periodStart: nonNegativeInteger("periodStart"),
2821
+ periodEnd: nonNegativeInteger("periodEnd"),
2822
+ total: FinancialOpsMoney,
2823
+ recipientCount: nonNegativeInteger("recipientCount")
2824
+ });
2825
+ Schema.Struct({
2826
+ runs: Schema.Array(PayrollRunSchema),
2827
+ settledThisMonth: FinancialOpsMoney
2828
+ });
2829
+ Schema.Struct({
2830
+ run: PayrollRunSchema,
2831
+ execution: PreparedPaymentCommandExecutionSchema
2832
+ });
2833
+ const PayrollGroupIdSchema = Schema.String.pipe(Schema.refine((value) => /^payroll_group_[0-9A-Z]{26}$/u.test(value), { message: "payrollGroupId must be a payroll_group_ ULID identifier" }));
2834
+ const PayrollGroupMemberSchema = Schema.Struct({
2835
+ partyId: PartyIdSchema,
2836
+ amount: Schema.String,
2837
+ currency: CurrencyCodeSchema$1
2838
+ });
2839
+ Schema.Struct({
2840
+ id: PayrollGroupIdSchema,
2841
+ name: nonEmpty("name"),
2842
+ tone: Schema.String,
2843
+ members: Schema.Array(PayrollGroupMemberSchema)
2844
+ });
2845
+ Schema.Struct({
2846
+ id: Schema.optional(PayrollGroupIdSchema),
2847
+ name: Schema.String,
2848
+ tone: Schema.String,
2849
+ members: Schema.Array(PayrollGroupMemberSchema)
2850
+ });
2851
+ `
2852
+ .capxul-doc{--ink:#1d1d1f;--muted:#6e6e73;--line:#e7e7ea;--accent:#0a7d4b;--bg:#fff;
2853
+ font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;
2854
+ color:var(--ink);background:var(--bg);max-width:44rem;margin:0 auto;padding:2.75rem 3rem;
2855
+ border:1px solid var(--line);border-radius:16px;box-shadow:0 1px 2px rgba(0,0,0,.04),0 12px 32px rgba(0,0,0,.06);
2856
+ line-height:1.5;font-size:15px;overflow-wrap:anywhere;word-break:break-word}
2857
+ .capxul-doc *{box-sizing:border-box;min-width:0}
2858
+ .capxul-doc .doc-header{display:flex;flex-direction:column;gap:1.25rem;padding-bottom:1.5rem;border-bottom:1px solid var(--line);margin-bottom:1.75rem}
2859
+ .capxul-doc .doc-brand{display:flex;align-items:center;gap:.5rem;color:var(--accent);font-weight:600}
2860
+ .capxul-doc .doc-brand-mark{font-size:1.1rem}
2861
+ .capxul-doc .doc-brand-name{letter-spacing:.02em}
2862
+ .capxul-doc .doc-headline{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;flex-wrap:wrap}
2863
+ .capxul-doc .doc-title{font-size:1.9rem;font-weight:700;letter-spacing:-.02em;margin:0}
2864
+ .capxul-doc .doc-badge{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;
2865
+ color:var(--accent);background:rgba(10,125,75,.1);padding:.3rem .6rem;border-radius:999px;max-width:100%;text-align:right}
2866
+ .capxul-doc .doc-parties{display:grid;grid-template-columns:1fr 1fr;gap:1.25rem;margin-bottom:1.75rem}
2867
+ .capxul-doc .doc-party{display:flex;flex-direction:column;gap:.15rem}
2868
+ .capxul-doc .doc-party-label{font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
2869
+ .capxul-doc .doc-party-name{font-weight:600}
2870
+ .capxul-doc .doc-meta{display:flex;flex-direction:column;gap:.4rem;margin-bottom:1.75rem}
2871
+ .capxul-doc .doc-meta-row{display:flex;justify-content:space-between;gap:1rem;font-size:.92rem}
2872
+ .capxul-doc .doc-meta-label{color:var(--muted);flex-shrink:0}
2873
+ .capxul-doc .doc-meta-value{font-weight:500;text-align:right}
2874
+ .capxul-doc time{color:var(--ink);font-variant-numeric:tabular-nums}
2875
+ .capxul-doc .doc-line-items{width:100%;border-collapse:collapse;margin:.5rem 0 1.5rem;font-size:.92rem}
2876
+ .capxul-doc .doc-line-items th{text-align:left;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;
2877
+ color:var(--muted);font-weight:600;padding:.5rem .25rem;border-bottom:1px solid var(--line)}
2878
+ .capxul-doc .doc-line-items td{padding:.7rem .25rem;border-bottom:1px solid var(--line)}
2879
+ .capxul-doc .doc-li-qty,.capxul-doc .doc-li-unit,.capxul-doc .doc-li-total{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
2880
+ .capxul-doc .doc-li-desc{width:100%}
2881
+ .capxul-doc .doc-totals{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem}
2882
+ .capxul-doc .doc-total-line{display:flex;justify-content:space-between;align-items:baseline;gap:1rem}
2883
+ .capxul-doc .doc-total-label{color:var(--muted)}
2884
+ .capxul-doc .doc-total-deduction .doc-amount-value{color:var(--muted)}
2885
+ .capxul-doc .doc-total-grand{border-top:2px solid var(--ink);margin-top:.5rem;padding-top:.75rem;font-size:1.15rem}
2886
+ .capxul-doc .doc-total-grand .doc-amount-value{font-weight:700}
2887
+ .capxul-doc .doc-amount-value{font-variant-numeric:tabular-nums;font-weight:600}
2888
+ .capxul-doc .doc-hero{text-align:center;padding:1.5rem 0 2rem}
2889
+ .capxul-doc .doc-hero-label{font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
2890
+ .capxul-doc .doc-hero-amount{font-size:2.6rem;font-weight:700;letter-spacing:-.02em;margin-top:.35rem}
2891
+ .capxul-doc .doc-note{color:var(--ink);background:#f7f7f8;border-radius:10px;padding:.9rem 1.1rem;margin:0}
2892
+ .capxul-doc .doc-dest-address{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9rem}
2893
+ .capxul-doc .doc-footer{margin-top:1.75rem;padding-top:1.25rem;border-top:1px solid var(--line);color:var(--muted);font-size:.9rem}
2894
+ .capxul-doc code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.82rem;color:var(--muted);word-break:break-all}
2895
+ @media (max-width:540px){.capxul-doc{padding:1.75rem 1.25rem}.capxul-doc .doc-parties{grid-template-columns:1fr}}
2896
+ `.trim();
2897
+ //#endregion
2898
+ //#region ../wire/src/secret-material.ts
2899
+ const SENSITIVE_MATERIAL_PATTERNS = [
2900
+ /0x[a-fA-F0-9]{40,}/u,
2901
+ /(?:^|[^a-fA-F0-9])[a-fA-F0-9]{64}(?:$|[^a-fA-F0-9])/u,
2902
+ /eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/u,
2903
+ /(?:(?:sk|pk|rk)_(?:live|test)|(?:phc|phx|ghp|gho|ghu|ghs|ghr|whsec)_|github_pat_|xox[baprs]-|AKIA[0-9A-Z]{16}|AIza)[A-Za-z0-9_-]*/iu
2904
+ ];
2905
+ /**
2906
+ * Reject: does the value carry any known secret material? Best effort — callers
2907
+ * drop the whole value on a match; a false negative is a leak, a false positive
2908
+ * merely omits an observation field.
2909
+ */
2910
+ function containsSensitiveMaterial(value) {
2911
+ return SENSITIVE_MATERIAL_PATTERNS.some((pattern) => pattern.test(value));
2912
+ }
2913
+ //#endregion
2914
+ //#region ../wire/src/observation-context.ts
2915
+ /** Single bounded HTTP carrier used before a Convex action envelope exists. */
2916
+ const OBSERVATION_CONTEXT_HEADER = "x-capxul-observation-context";
2917
+ const FIELD_RULES = {
2918
+ application: {
2919
+ maxLength: 64,
2920
+ pattern: /^[A-Za-z0-9][A-Za-z0-9._-]*$/u
2921
+ },
2922
+ applicationId: {
2923
+ maxLength: 30,
2924
+ pattern: APP_ID_RE
2925
+ },
2926
+ release: {
2927
+ maxLength: 128,
2928
+ pattern: /^[A-Za-z0-9][A-Za-z0-9._+@:/-]*$/u
2929
+ },
2930
+ sessionId: {
2931
+ maxLength: 128,
2932
+ pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
2933
+ },
2934
+ organizationId: {
2935
+ maxLength: 128,
2936
+ pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
2937
+ },
2938
+ journeyId: {
2939
+ maxLength: 128,
2940
+ pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
2941
+ },
2942
+ correlationId: {
2943
+ maxLength: 128,
2944
+ pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
2945
+ },
2946
+ anonymousId: {
2947
+ maxLength: 128,
2948
+ pattern: /^anon_[A-Za-z0-9-]+$/u
2949
+ },
2950
+ traceparent: {
2951
+ maxLength: 55,
2952
+ pattern: /^00-[0-9a-f]{32}-[0-9a-f]{16}-0[01]$/u
2953
+ }
2954
+ };
2955
+ /**
2956
+ * Copy only the canonical allowlist and silently omit malformed/sensitive
2957
+ * values. Observation metadata is best effort and may never reject a domain
2958
+ * operation.
2959
+ */
2960
+ function sanitizeObservationContext(input) {
2961
+ if (typeof input !== "object" || input === null || Array.isArray(input)) return void 0;
2962
+ const source = input;
2963
+ const sanitized = {};
2964
+ for (const field of Object.keys(FIELD_RULES)) {
2965
+ const value = source[field];
2966
+ if (!isSafeField(field, value)) continue;
2967
+ sanitized[field] = value;
2968
+ }
2969
+ return Object.keys(sanitized).length === 0 ? void 0 : sanitized;
2970
+ }
2971
+ /** Encode only the sanitized allowlist; absence stays absence. */
2972
+ function encodeObservationContextHeader(input) {
2973
+ const sanitized = sanitizeObservationContext(input);
2974
+ return sanitized === void 0 ? void 0 : JSON.stringify(sanitized);
2975
+ }
2976
+ function isSafeField(field, value) {
2977
+ if (typeof value !== "string") return false;
2978
+ const rule = FIELD_RULES[field];
2979
+ return value.length > 0 && value.length <= rule.maxLength && value === value.trim() && !value.includes("://") && !containsSensitiveMaterial(value) && rule.pattern.test(value);
2980
+ }
2981
+ //#endregion
2982
+ //#region src/surface/_shared/provisioning-telemetry.ts
2983
+ async function emitProvisioningTelemetry(telemetry, smartAccount) {
2984
+ if (telemetry === void 0) return;
2985
+ await Effect.runPromise(telemetry.emit({
2986
+ name: "provisioning_safe_created",
2987
+ props: { safe_address: smartAccount.smartAccountAddress }
2988
+ }).pipe(Effect.catch((cause) => Effect.sync(() => reportProvisioningTelemetryFailure("error", smartAccount, cause))), Effect.catchDefect((cause) => Effect.sync(() => reportProvisioningTelemetryFailure("defect", smartAccount, cause)))));
2989
+ }
2990
+ function reportProvisioningTelemetryFailure(kind, smartAccount, cause) {
2991
+ if (!isProvisioningTelemetryDebugEnabled()) return;
2992
+ globalThis.console?.warn?.("[capxul] provisioning telemetry dropped", {
2993
+ kind,
2994
+ safeAddress: smartAccount.smartAccountAddress,
2995
+ cause
2996
+ });
2997
+ }
2998
+ function isProvisioningTelemetryDebugEnabled() {
2999
+ return globalThis.process?.env?.CAPXUL_DEBUG_TELEMETRY === "1";
3000
+ }
3001
+ //#endregion
3002
+ //#region src/telemetry/get-failure-mode.ts
3003
+ /**
3004
+ * The five canonical {@link FailureMode} members, for runtime membership checks.
3005
+ * Single source of truth — tests assert against this exact set so the taxonomy
3006
+ * and its guard can never drift apart.
3007
+ */
3008
+ const FAILURE_MODES = new Set([
3009
+ "auth-origin-mismatch",
3010
+ "stale-openfort-cache",
3011
+ "app-env-allowlist",
3012
+ "no-secure-context",
3013
+ "unknown"
3014
+ ]);
3015
+ function isFailureMode(value) {
3016
+ return typeof value === "string" && FAILURE_MODES.has(value);
3017
+ }
3018
+ /**
3019
+ * Extract the structured {@link FailureMode} from a CapxulError.
3020
+ *
3021
+ * Reads `details.failure_mode` and returns it only when it is one of the five
3022
+ * canonical members; any other value (a legacy free string, a typo, a
3023
+ * non-string) yields `undefined` so downstream telemetry never reports an
3024
+ * unrecognised cause.
3025
+ */
3026
+ function getFailureMode(error) {
3027
+ if (!isCapxulError(error)) return void 0;
3028
+ const details = error.details;
3029
+ if (details === void 0) return void 0;
3030
+ return isFailureMode(details.failure_mode) ? details.failure_mode : void 0;
3031
+ }
3032
+ /**
3033
+ * Resolve the canonical {@link FailureMode} for a `$exception`, guaranteeing a
3034
+ * taxonomy member is always returned — never `undefined`, never a free string.
3035
+ *
3036
+ * Resolution order:
3037
+ * 1. the structured mode on the error's `details.failure_mode` (already guarded);
3038
+ * 2. a caller-supplied `contextFailureMode`, but ONLY when it passes the same
3039
+ * runtime membership check — the static `FailureMode` type is erased at
3040
+ * runtime, so an operation string (e.g. `"signer-get-address"`) injected via
3041
+ * a JS caller or `as` cast is rejected here rather than leaking to telemetry;
3042
+ * 3. `"unknown"` otherwise, so an unclassifiable error is still tagged with a
3043
+ * canonical value instead of being emitted with no `failure_mode` at all.
3044
+ */
3045
+ function resolveFailureMode(error, contextFailureMode) {
3046
+ return getFailureMode(error) ?? (isFailureMode(contextFailureMode) ? contextFailureMode : "unknown");
3047
+ }
3048
+ //#endregion
3049
+ //#region src/signer.ts
3050
+ const EVM_ADDRESS_HEX = /^0x[0-9a-fA-F]{40}$/;
3051
+ const ECDSA_SIGNATURE_HEX = /^0x[0-9a-fA-F]{130}$/;
3052
+ const SAFE_OP_DIGEST_HEX = /^0x[0-9a-fA-F]{64}$/;
3053
+ /**
3054
+ * The readiness store a signer reports when it runs no readiness cycle. It
3055
+ * fails CLOSED: a node key signer or an injected wallet never claims `ready`,
3056
+ * so a gate that reads this never opens on a guess.
3057
+ */
3058
+ const UNOBSERVABLE_SIGNER_STATUS = {
3059
+ status: () => "unknown",
3060
+ subscribe: () => () => void 0
3061
+ };
3062
+ /**
3063
+ * Walk an error and its `cause` links once each. A self-referential chain
3064
+ * terminates. Both signer predicates read the chain, so they read it here.
3065
+ */
3066
+ function* causeChain(cause) {
3067
+ const seen = /* @__PURE__ */ new Set();
3068
+ let current = cause;
3069
+ while (typeof current === "object" && current !== null && !seen.has(current)) {
3070
+ seen.add(current);
3071
+ yield current;
3072
+ current = current.cause;
3073
+ }
3074
+ }
3075
+ /** Fold a signer throw into the public error contract. */
3076
+ function signerFailure(source, operation, cause) {
3077
+ let failureMode;
3078
+ for (const link of causeChain(cause)) {
3079
+ if (link instanceof CapxulError && link.code === "SIGNER_REJECTED") return link;
3080
+ failureMode = getFailureMode(link) ?? failureMode;
3081
+ const error = link;
3082
+ if (error.code === 4001 || error.error === "passkey_user_cancelled") return Errors.signerRejected({
3083
+ source,
3084
+ cause
3085
+ });
3086
+ }
3087
+ return Errors.providerError("signer", operation, cause, failureMode === void 0 ? void 0 : { failure_mode: failureMode });
3088
+ }
3089
+ /**
3090
+ * Browser `CapxulSigner` backed by an injected EIP-1193 wallet (MetaMask, etc.).
3091
+ * Signs the SafeOp digest via `eth_sign`, then verifies the returned signature
3092
+ * recovers the selected account against that raw digest. Wallets that prefix
3093
+ * `eth_sign` payloads are rejected before the backend submits an invalid SafeOp.
3094
+ * The node key signer lives in `@capxul/sdk/node` (`localPrivateKeySigner`).
3095
+ */
3096
+ function injectedWalletSigner(provider) {
3097
+ const resolveAddress = async () => {
3098
+ const accounts = await provider.request({ method: "eth_requestAccounts" });
3099
+ const first = Array.isArray(accounts) ? accounts[0] : void 0;
3100
+ if (typeof first !== "string") throw new Error("injectedWalletSigner: wallet returned no accounts");
3101
+ if (!EVM_ADDRESS_HEX.test(first)) throw new Error("injectedWalletSigner: wallet returned invalid address format");
3102
+ return toAddress(first);
3103
+ };
3104
+ return {
3105
+ source: "injected-eip1193",
3106
+ getAddress: resolveAddress,
3107
+ async signUserOpHash(hash) {
3108
+ if (!SAFE_OP_DIGEST_HEX.test(hash)) throw new Error("injectedWalletSigner: SafeOp digest must be a 0x-prefixed 32-byte hex");
3109
+ const address = await resolveAddress();
3110
+ let signature;
3111
+ try {
3112
+ signature = await provider.request({
3113
+ method: "eth_sign",
3114
+ params: [address, hash]
3115
+ });
3116
+ } catch (cause) {
3117
+ const detail = cause instanceof Error ? cause.message : String(cause);
3118
+ throw new Error(`injectedWalletSigner: eth_sign failed; enable raw-hash signing for deployment (${detail})`, { cause });
3119
+ }
3120
+ if (typeof signature !== "string") throw new Error("injectedWalletSigner: wallet returned a non-string signature");
3121
+ if (!ECDSA_SIGNATURE_HEX.test(signature)) throw new Error("injectedWalletSigner: wallet returned invalid signature format");
3122
+ if ((await recoverRawDigestSigner({
3123
+ hash,
3124
+ signature
3125
+ })).toLowerCase() !== address.toLowerCase()) throw new Error("injectedWalletSigner: wallet signature did not recover the selected account for the raw SafeOp digest; use a raw-hash-capable wallet or @capxul/sdk/node localPrivateKeySigner for deployed flows");
3126
+ return signature;
3127
+ }
3128
+ };
3129
+ }
3130
+ async function recoverRawDigestSigner(input) {
3131
+ try {
3132
+ return toAddress(await recoverAddress(input));
3133
+ } catch (cause) {
3134
+ const detail = cause instanceof Error ? cause.message : String(cause);
3135
+ throw new Error(`injectedWalletSigner: could not verify raw SafeOp digest signature (${detail})`, { cause });
3136
+ }
3137
+ }
3138
+ //#endregion
3139
+ //#region src/internal/invocation-observation.ts
3140
+ const INVOCATION_OBSERVATION = Symbol("capxul.invocation-observation");
3141
+ const FAILURE_INVOCATION_SNAPSHOT = Symbol("capxul.failure-invocation-snapshot");
3142
+ /** @internal Attach one immutable, non-wire invocation snapshot to an SDK-owned object. */
3143
+ function attachInvocationObservation(target, source) {
3144
+ const snapshot = Object.freeze(source.context === void 0 ? { active: source.active } : {
3145
+ active: source.active,
3146
+ context: Object.freeze({ ...source.context })
3147
+ });
3148
+ Object.defineProperty(target, INVOCATION_OBSERVATION, {
3149
+ configurable: false,
3150
+ enumerable: false,
3151
+ value: snapshot,
3152
+ writable: false
3153
+ });
3154
+ return target;
3155
+ }
3156
+ /** @internal Read the snapshot without exposing its symbol or adding a wire field. */
3157
+ function readInvocationObservation(source) {
3158
+ if (typeof source !== "object" || source === null) return void 0;
3159
+ return source[INVOCATION_OBSERVATION];
3160
+ }
3161
+ /** @internal Carry a snapshot across an SDK adapter projection without resolving again. */
3162
+ function copyInvocationObservation(source, target) {
3163
+ const snapshot = readInvocationObservation(source);
3164
+ return snapshot === void 0 ? target : attachInvocationObservation(target, snapshot);
3165
+ }
3166
+ /** @internal Carry the public call-start delivery decision with its failure envelope. */
3167
+ function markFailureInvocationSnapshot(failure, snapshot) {
3168
+ Object.defineProperty(failure, FAILURE_INVOCATION_SNAPSHOT, {
3169
+ configurable: false,
3170
+ enumerable: false,
3171
+ value: Object.freeze(snapshot),
3172
+ writable: false
3173
+ });
3174
+ return failure;
3175
+ }
3176
+ /** @internal Read the call-start delivery decision; undefined means a direct adapter call. */
3177
+ function readFailureInvocationSnapshot(failure) {
3178
+ if (typeof failure !== "object" || failure === null) return void 0;
3179
+ const snapshot = failure[FAILURE_INVOCATION_SNAPSHOT];
3180
+ return typeof snapshot === "object" && snapshot !== null && "active" in snapshot ? snapshot : void 0;
3181
+ }
3182
+ //#endregion
3183
+ //#region src/domain/machine/telemetry.ts
3184
+ const definedEntries = (values) => Object.fromEntries(Object.entries(values).filter((entry) => entry[1] !== void 0));
3185
+ const SAFE_ENGINEERING_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
3186
+ const safeEngineeringIdentifier = (value) => value !== void 0 && SAFE_ENGINEERING_ID.test(value) ? value : void 0;
3187
+ const portFailureOutcome = (code) => code === "CANCELLED" ? "cancelled" : "failed";
3188
+ function formatTraceparent(span) {
3189
+ const traceId = span.traceId.toLowerCase();
3190
+ const spanId = span.spanId.toLowerCase();
3191
+ if (!/^[0-9a-f]{32}$/u.test(traceId) || !/^[0-9a-f]{16}$/u.test(spanId)) return void 0;
3192
+ if (/^0+$/u.test(traceId) || /^0+$/u.test(spanId)) return void 0;
3193
+ return `00-${traceId}-${spanId}-${span.sampled ? "01" : "00"}`;
3194
+ }
3195
+ /** Canonical, bounded fields for the one wide engineering log owned by P3. */
3196
+ const transitionLogFields = (record) => {
3197
+ const { correlation_id, journey_id, ...canonical } = record;
3198
+ const safeCorrelation = safeEngineeringIdentifier(correlation_id);
3199
+ const safeJourney = safeEngineeringIdentifier(journey_id);
3200
+ return definedEntries({
3201
+ ...canonical,
3202
+ ...safeCorrelation === void 0 ? {} : { correlation_id: safeCorrelation },
3203
+ ...safeJourney === void 0 ? {} : { journey_id: safeJourney }
3204
+ });
3205
+ };
3206
+ /** The shell span owns transition/refusal classification and no other seam's fields. */
3207
+ const transitionSpanFields = (record) => {
3208
+ if (record.outcome === "applied") return {
3209
+ machine: record.machine,
3210
+ from: record.from,
3211
+ event: record.event,
3212
+ to: record.to
3213
+ };
3214
+ return {
3215
+ machine: record.machine,
3216
+ state: record.state,
3217
+ event: record.event,
3218
+ ...record.outcome === "refused" ? { refused: record.refusal_code } : {}
3219
+ };
3220
+ };
3221
+ /**
3222
+ * Emit engineering telemetry as an isolated side effect. Exporter/logger defects
3223
+ * can never change the actor's transition, reply, or P3 observer cardinality.
3224
+ */
3225
+ const logIdentityTransition = (record) => (record.outcome === "applied" ? Effect.logInfo("identity.transition") : record.outcome === "failed" ? Effect.logError("identity.transition") : Effect.logWarning("identity.transition")).pipe(Effect.annotateLogs(transitionLogFields(record)), Effect.andThen(record.outcome === "applied" ? Effect.void : Effect.fail({ code: record.outcome === "refused" ? record.refusal_code : record.error_code })), Effect.withSpan("identity.transition"), Effect.annotateSpans(transitionSpanFields(record)), Effect.catchCause(() => Effect.void));
3226
+ //#endregion
3227
+ //#region src/domain/machine/shell.ts
3228
+ const INVOCATION_PARENT_SPAN = Symbol("@capxul/sdk/identity-invocation-parent-span");
3229
+ function carryInvocationParentSpan(controls, parent) {
3230
+ return {
3231
+ ...controls,
3232
+ [INVOCATION_PARENT_SPAN]: parent
3233
+ };
3234
+ }
3235
+ function withInvocationParentSpan(effect, controls) {
3236
+ const parent = controls?.[INVOCATION_PARENT_SPAN];
3237
+ return parent === void 0 ? effect : effect.pipe(Effect.withParentSpan(parent));
3238
+ }
3239
+ var ActorFailure = class extends Error {
3240
+ reason;
3241
+ machine;
3242
+ state;
3243
+ event;
3244
+ details;
3245
+ _tag = "ActorFailure";
3246
+ constructor(reason, machine, state, event, details) {
3247
+ super(`${machine}:${state}:${event} ${reason}`);
3248
+ this.reason = reason;
3249
+ this.machine = machine;
3250
+ this.state = state;
3251
+ this.event = event;
3252
+ this.details = details;
3253
+ this.name = "ActorFailure";
3254
+ }
3255
+ };
3256
+ const duration = (startedAt) => Math.max(0, Date.now() - startedAt);
3257
+ const failReply = (reply, failure) => reply === null ? Effect.void : Effect.asVoid(Deferred.fail(reply, failure));
3258
+ const withCarriage = (controls) => ({
3259
+ ...controls.correlation_id === void 0 ? {} : { correlation_id: controls.correlation_id },
3260
+ ...controls.journey_id === void 0 ? {} : { journey_id: controls.journey_id }
3261
+ });
3262
+ const timeoutFailure = {
3263
+ code: "PROVIDER_ERROR",
3264
+ message: "Identity work timed out"
3265
+ };
3266
+ const cancelledFailure = {
3267
+ code: "CANCELLED",
3268
+ message: "Identity work cancelled"
3269
+ };
3270
+ const abort = (signal) => signal.aborted ? Effect.fail(cancelledFailure) : Effect.callback((resume) => {
3271
+ const onAbort = () => resume(Effect.fail(cancelledFailure));
3272
+ signal.addEventListener("abort", onAbort, { once: true });
3273
+ return Effect.sync(() => signal.removeEventListener("abort", onAbort));
3609
3274
  });
3610
- Schema.Struct({
3611
- status: Schema.Literal("submitted"),
3612
- executionId: MoneyExecutionIdSchema,
3613
- commandId: PaymentCommandIdSchema,
3614
- userOpHash: Bytes32Schema,
3615
- value: PermissionResourceSchema
3275
+ const control = (effect, controls) => {
3276
+ let controlled = effect;
3277
+ const deadlineDelay = controls.deadlineMs === void 0 ? void 0 : Math.max(0, controls.deadlineMs - Date.now());
3278
+ const timeoutMs = controls.timeoutMs === void 0 ? deadlineDelay : deadlineDelay === void 0 ? controls.timeoutMs : Math.min(controls.timeoutMs, deadlineDelay);
3279
+ if (timeoutMs !== void 0) controlled = controlled.pipe(Effect.timeoutOrElse({
3280
+ duration: `${timeoutMs} millis`,
3281
+ orElse: () => Effect.fail(timeoutFailure)
3282
+ }));
3283
+ if (controls.signal !== void 0) controlled = Effect.raceFirst(controlled, abort(controls.signal));
3284
+ return controlled;
3285
+ };
3286
+ const boot = (spec, options = {}) => Effect.gen(function* () {
3287
+ const mailbox = yield* Queue.unbounded();
3288
+ const cell = yield* Ref.make(spec.initial);
3289
+ const slotEpochs = /* @__PURE__ */ new Map();
3290
+ const slots = /* @__PURE__ */ new Map();
3291
+ const stateObservers = /* @__PURE__ */ new Set();
3292
+ const transitionObservers = /* @__PURE__ */ new Set();
3293
+ let bootTransitionObserver = options.onTransition;
3294
+ let stopped = false;
3295
+ const defect = (cause) => {
3296
+ try {
3297
+ options.onDefect?.(cause);
3298
+ } catch {}
3299
+ };
3300
+ const emit = (record) => Effect.sync(() => {
3301
+ if (bootTransitionObserver !== void 0) try {
3302
+ bootTransitionObserver(record);
3303
+ } catch (cause) {
3304
+ bootTransitionObserver = void 0;
3305
+ defect(cause);
3306
+ }
3307
+ for (const observer of transitionObservers) try {
3308
+ observer(record);
3309
+ } catch (cause) {
3310
+ transitionObservers.delete(observer);
3311
+ defect(cause);
3312
+ }
3313
+ }).pipe(Effect.andThen(logIdentityTransition(record)));
3314
+ const notify = (state) => {
3315
+ for (const observer of stateObservers) try {
3316
+ observer(state);
3317
+ } catch (cause) {
3318
+ stateObservers.delete(observer);
3319
+ defect(cause);
3320
+ }
3321
+ };
3322
+ const makeFailure = (state, event, reason, details) => new ActorFailure(reason, spec.machine, spec.label(state), event._tag, details);
3323
+ const nonApplied = (state, event, reason, outcome, env) => {
3324
+ const slot = env.origin?.slot ?? spec.slot(event);
3325
+ return copyInvocationObservation(env.invocation, {
3326
+ machine: spec.machine,
3327
+ state: spec.label(state),
3328
+ event: event._tag,
3329
+ slot,
3330
+ epoch: env.origin?.epoch ?? slotEpochs.get(slot) ?? 0,
3331
+ outcome,
3332
+ duration_ms: duration(env.startedAt),
3333
+ ...withCarriage(env.invocation),
3334
+ ...outcome === "refused" ? { refusal_code: reason } : { error_code: reason }
3335
+ });
3336
+ };
3337
+ const applied = (from, to, event, slot, epoch, env) => copyInvocationObservation(env.invocation, {
3338
+ machine: spec.machine,
3339
+ from: spec.label(from),
3340
+ event: event._tag,
3341
+ to: spec.label(to),
3342
+ slot,
3343
+ epoch,
3344
+ outcome: "applied",
3345
+ duration_ms: duration(env.startedAt),
3346
+ ...withCarriage(env.invocation)
3347
+ });
3348
+ const finish = (cursor, state) => {
3349
+ const held = slots.get(cursor.slot);
3350
+ if (held === void 0 || held.cursor !== cursor) return Effect.void;
3351
+ slots.delete(cursor.slot);
3352
+ return Effect.asVoid(Deferred.succeed(held.reply, state));
3353
+ };
3354
+ const recoverFailure = (state, cursor, failure) => {
3355
+ const event = spec.recoverFailure?.(state, cursor.event, failure);
3356
+ if (event === void 0) return Effect.succeed(state);
3357
+ const outcome = spec.transition(state, event);
3358
+ if ("refused" in outcome) return Effect.succeed(state);
3359
+ return Ref.set(cell, outcome.next).pipe(Effect.tap(() => {
3360
+ return emit(applied(state, outcome.next, event, cursor.slot, cursor.epoch, {
3361
+ invocation: cursor.invocation,
3362
+ startedAt: cursor.startedAt
3363
+ })).pipe(Effect.andThen(Effect.sync(() => {
3364
+ notify(outcome.next);
3365
+ })));
3366
+ }), Effect.as(outcome.next));
3367
+ };
3368
+ const step = (env) => Effect.gen(function* () {
3369
+ const state = yield* Ref.get(cell);
3370
+ if (env.origin !== null && (slotEpochs.get(env.origin.slot) ?? 0) !== env.origin.epoch) {
3371
+ const held = slots.get(env.origin.slot);
3372
+ if (held === void 0 || held.cursor !== env.origin) return;
3373
+ slots.delete(env.origin.slot);
3374
+ const event = { _tag: env.origin.event };
3375
+ yield* emit(nonApplied(state, event, "STALE_EPOCH", "refused", env));
3376
+ yield* failReply(held.reply, makeFailure(state, event, "STALE_EPOCH"));
3377
+ return;
3378
+ }
3379
+ if (env.origin !== null && env.event._tag === "~lane/exit") {
3380
+ const exit = env.event;
3381
+ const held = slots.get(env.origin.slot);
3382
+ if (held === void 0 || held.cursor !== env.origin) return;
3383
+ if (exit.defect !== void 0) {
3384
+ slots.delete(env.origin.slot);
3385
+ defect(exit.defect);
3386
+ const event = { _tag: env.origin.event };
3387
+ const failedState = yield* recoverFailure(state, env.origin, {
3388
+ code: "WORK_DIED",
3389
+ message: "Identity work died"
3390
+ });
3391
+ yield* emit(nonApplied(failedState, event, "WORK_DIED", "failed", env));
3392
+ yield* failReply(held.reply, makeFailure(failedState, event, "WORK_DIED"));
3393
+ return;
3394
+ }
3395
+ if (exit.failure !== void 0) {
3396
+ slots.delete(env.origin.slot);
3397
+ const outcome = exit.failure.code === "CANCELLED" ? "cancelled" : "failed";
3398
+ const event = { _tag: env.origin.event };
3399
+ const failedState = exit.failure === timeoutFailure || exit.failure === cancelledFailure ? yield* recoverFailure(state, env.origin, exit.failure) : state;
3400
+ yield* emit(nonApplied(failedState, event, exit.failure.code, outcome, env));
3401
+ const details = exit.failure === timeoutFailure ? { reason: "timeout" } : void 0;
3402
+ yield* failReply(held.reply, makeFailure(failedState, event, exit.failure.code, details));
3403
+ return;
3404
+ }
3405
+ yield* finish(env.origin, state);
3406
+ return;
3407
+ }
3408
+ const outcome = spec.transition(state, env.event);
3409
+ if ("refused" in outcome) {
3410
+ yield* emit(nonApplied(state, env.event, outcome.refused, "refused", env));
3411
+ yield* failReply(env.reply, makeFailure(state, env.event, outcome.refused));
3412
+ return;
3413
+ }
3414
+ const next = outcome.next;
3415
+ yield* Ref.set(cell, next);
3416
+ const emitApplied = (slot, epoch) => emit(applied(state, next, env.event, slot, epoch, env));
3417
+ if (env.origin !== null) {
3418
+ yield* emitApplied(env.origin.slot, env.origin.epoch);
3419
+ notify(next);
3420
+ return;
3421
+ }
3422
+ for (const slot of spec.invalidates?.(env.event) ?? []) {
3423
+ if (!slots.has(slot)) continue;
3424
+ slotEpochs.set(slot, (slotEpochs.get(slot) ?? 0) + 1);
3425
+ }
3426
+ const work = env.reply === null ? void 0 : spec.work?.({
3427
+ state: next,
3428
+ event: env.event
3429
+ });
3430
+ if (work === void 0 || env.reply === null) {
3431
+ const slot = spec.slot(env.event);
3432
+ yield* emitApplied(slot, slotEpochs.get(slot) ?? 0);
3433
+ notify(next);
3434
+ if (env.reply !== null) yield* Deferred.succeed(env.reply, next).pipe(Effect.asVoid);
3435
+ return;
3436
+ }
3437
+ const previous = slots.get(work.slot);
3438
+ if (previous !== void 0) {
3439
+ slots.delete(work.slot);
3440
+ yield* Fiber.interrupt(previous.fiber);
3441
+ const previousEvent = { _tag: previous.cursor.event };
3442
+ const reason = previous.cursor.epoch === (slotEpochs.get(work.slot) ?? 0) ? "SUPERSEDED" : "STALE_EPOCH";
3443
+ yield* emit(nonApplied(next, previousEvent, reason, "refused", {
3444
+ origin: previous.cursor,
3445
+ invocation: previous.cursor.invocation,
3446
+ startedAt: previous.cursor.startedAt
3447
+ }));
3448
+ yield* failReply(previous.reply, makeFailure(next, previousEvent, reason));
3449
+ }
3450
+ const epoch = (slotEpochs.get(work.slot) ?? 0) + 1;
3451
+ slotEpochs.set(work.slot, epoch);
3452
+ const cursor = {
3453
+ slot: work.slot,
3454
+ epoch,
3455
+ event: env.event._tag,
3456
+ startedAt: env.startedAt,
3457
+ invocation: env.invocation
3458
+ };
3459
+ yield* emitApplied(work.slot, epoch);
3460
+ notify(next);
3461
+ const send = (event) => Queue.offer(mailbox, {
3462
+ event,
3463
+ reply: null,
3464
+ origin: cursor,
3465
+ invocation: env.invocation,
3466
+ startedAt: env.startedAt
3467
+ }).pipe(Effect.asVoid);
3468
+ const complete = (event) => Queue.offer(mailbox, {
3469
+ event,
3470
+ reply: null,
3471
+ origin: cursor,
3472
+ invocation: env.invocation,
3473
+ startedAt: env.startedAt
3474
+ }).pipe(Effect.asVoid);
3475
+ const guarded = Effect.gen(function* () {
3476
+ yield* Effect.annotateCurrentSpan({
3477
+ slot: work.slot,
3478
+ epoch,
3479
+ port: work.port
3480
+ });
3481
+ return yield* control(work.run(send, env.invocation), env.invocation);
3482
+ }).pipe(Effect.withSpan(`identity.work.${work.slot}`)).pipe(Effect.matchEffect({
3483
+ onFailure: (failure) => complete({
3484
+ _tag: "~lane/exit",
3485
+ failure
3486
+ }),
3487
+ onSuccess: () => complete({ _tag: "~lane/exit" })
3488
+ }), Effect.catchDefect((cause) => complete({
3489
+ _tag: "~lane/exit",
3490
+ defect: cause
3491
+ })));
3492
+ const fiber = yield* Effect.forkChild(guarded, { startImmediately: true });
3493
+ slots.set(work.slot, {
3494
+ fiber,
3495
+ reply: env.reply,
3496
+ cursor
3497
+ });
3498
+ });
3499
+ const loop = yield* Effect.forkScoped(Effect.forever(Queue.take(mailbox).pipe(Effect.flatMap((env) => withInvocationParentSpan(step(env), env.invocation)))));
3500
+ yield* Effect.addFinalizer(() => Effect.gen(function* () {
3501
+ stopped = true;
3502
+ yield* Fiber.interrupt(loop);
3503
+ const state = yield* Ref.get(cell);
3504
+ const outstanding = [...slots.values()];
3505
+ slots.clear();
3506
+ for (const held of outstanding) {
3507
+ yield* Fiber.interrupt(held.fiber);
3508
+ const env = {
3509
+ origin: held.cursor,
3510
+ invocation: held.cursor.invocation,
3511
+ startedAt: held.cursor.startedAt
3512
+ };
3513
+ const event = { _tag: held.cursor.event };
3514
+ yield* emit(nonApplied(state, event, "ACTOR_STOPPED", "refused", env));
3515
+ yield* failReply(held.reply, makeFailure(state, event, "ACTOR_STOPPED"));
3516
+ }
3517
+ stateObservers.clear();
3518
+ transitionObservers.clear();
3519
+ yield* Queue.shutdown(mailbox);
3520
+ }));
3521
+ const offer = (event, reply, invocation) => {
3522
+ const state = Ref.getUnsafe(cell);
3523
+ if (stopped) return withInvocationParentSpan(emit(nonApplied(state, event, "ACTOR_STOPPED", "refused", {
3524
+ origin: null,
3525
+ invocation,
3526
+ startedAt: Date.now()
3527
+ })).pipe(Effect.andThen(Effect.fail(makeFailure(state, event, "ACTOR_STOPPED")))), invocation);
3528
+ const startedAt = Date.now();
3529
+ return Queue.offer(mailbox, {
3530
+ event,
3531
+ reply,
3532
+ origin: null,
3533
+ invocation,
3534
+ startedAt
3535
+ }).pipe(Effect.asVoid);
3536
+ };
3537
+ return {
3538
+ ask: (event, invocation = {}) => Effect.gen(function* () {
3539
+ const reply = yield* Deferred.make();
3540
+ yield* offer(event, reply, invocation);
3541
+ return yield* Deferred.await(reply);
3542
+ }),
3543
+ tell: (event, invocation = {}) => offer(event, null, invocation),
3544
+ snapshot: () => Ref.getUnsafe(cell),
3545
+ subscribe: (observer) => {
3546
+ stateObservers.add(observer);
3547
+ return () => {
3548
+ stateObservers.delete(observer);
3549
+ };
3550
+ },
3551
+ subscribeTransitions: (observer) => {
3552
+ transitionObservers.add(observer);
3553
+ return () => {
3554
+ transitionObservers.delete(observer);
3555
+ };
3556
+ }
3557
+ };
3616
3558
  });
3617
- `
3618
- .capxul-doc{--ink:#1d1d1f;--muted:#6e6e73;--line:#e7e7ea;--accent:#0a7d4b;--bg:#fff;
3619
- font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;
3620
- color:var(--ink);background:var(--bg);max-width:44rem;margin:0 auto;padding:2.75rem 3rem;
3621
- border:1px solid var(--line);border-radius:16px;box-shadow:0 1px 2px rgba(0,0,0,.04),0 12px 32px rgba(0,0,0,.06);
3622
- line-height:1.5;font-size:15px;overflow-wrap:anywhere;word-break:break-word}
3623
- .capxul-doc *{box-sizing:border-box;min-width:0}
3624
- .capxul-doc .doc-header{display:flex;flex-direction:column;gap:1.25rem;padding-bottom:1.5rem;border-bottom:1px solid var(--line);margin-bottom:1.75rem}
3625
- .capxul-doc .doc-brand{display:flex;align-items:center;gap:.5rem;color:var(--accent);font-weight:600}
3626
- .capxul-doc .doc-brand-mark{font-size:1.1rem}
3627
- .capxul-doc .doc-brand-name{letter-spacing:.02em}
3628
- .capxul-doc .doc-headline{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;flex-wrap:wrap}
3629
- .capxul-doc .doc-title{font-size:1.9rem;font-weight:700;letter-spacing:-.02em;margin:0}
3630
- .capxul-doc .doc-badge{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;
3631
- color:var(--accent);background:rgba(10,125,75,.1);padding:.3rem .6rem;border-radius:999px;max-width:100%;text-align:right}
3632
- .capxul-doc .doc-parties{display:grid;grid-template-columns:1fr 1fr;gap:1.25rem;margin-bottom:1.75rem}
3633
- .capxul-doc .doc-party{display:flex;flex-direction:column;gap:.15rem}
3634
- .capxul-doc .doc-party-label{font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
3635
- .capxul-doc .doc-party-name{font-weight:600}
3636
- .capxul-doc .doc-meta{display:flex;flex-direction:column;gap:.4rem;margin-bottom:1.75rem}
3637
- .capxul-doc .doc-meta-row{display:flex;justify-content:space-between;gap:1rem;font-size:.92rem}
3638
- .capxul-doc .doc-meta-label{color:var(--muted);flex-shrink:0}
3639
- .capxul-doc .doc-meta-value{font-weight:500;text-align:right}
3640
- .capxul-doc time{color:var(--ink);font-variant-numeric:tabular-nums}
3641
- .capxul-doc .doc-line-items{width:100%;border-collapse:collapse;margin:.5rem 0 1.5rem;font-size:.92rem}
3642
- .capxul-doc .doc-line-items th{text-align:left;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;
3643
- color:var(--muted);font-weight:600;padding:.5rem .25rem;border-bottom:1px solid var(--line)}
3644
- .capxul-doc .doc-line-items td{padding:.7rem .25rem;border-bottom:1px solid var(--line)}
3645
- .capxul-doc .doc-li-qty,.capxul-doc .doc-li-unit,.capxul-doc .doc-li-total{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
3646
- .capxul-doc .doc-li-desc{width:100%}
3647
- .capxul-doc .doc-totals{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem}
3648
- .capxul-doc .doc-total-line{display:flex;justify-content:space-between;align-items:baseline;gap:1rem}
3649
- .capxul-doc .doc-total-label{color:var(--muted)}
3650
- .capxul-doc .doc-total-deduction .doc-amount-value{color:var(--muted)}
3651
- .capxul-doc .doc-total-grand{border-top:2px solid var(--ink);margin-top:.5rem;padding-top:.75rem;font-size:1.15rem}
3652
- .capxul-doc .doc-total-grand .doc-amount-value{font-weight:700}
3653
- .capxul-doc .doc-amount-value{font-variant-numeric:tabular-nums;font-weight:600}
3654
- .capxul-doc .doc-hero{text-align:center;padding:1.5rem 0 2rem}
3655
- .capxul-doc .doc-hero-label{font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
3656
- .capxul-doc .doc-hero-amount{font-size:2.6rem;font-weight:700;letter-spacing:-.02em;margin-top:.35rem}
3657
- .capxul-doc .doc-note{color:var(--ink);background:#f7f7f8;border-radius:10px;padding:.9rem 1.1rem;margin:0}
3658
- .capxul-doc .doc-dest-address{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9rem}
3659
- .capxul-doc .doc-footer{margin-top:1.75rem;padding-top:1.25rem;border-top:1px solid var(--line);color:var(--muted);font-size:.9rem}
3660
- .capxul-doc code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.82rem;color:var(--muted);word-break:break-all}
3661
- @media (max-width:540px){.capxul-doc{padding:1.75rem 1.25rem}.capxul-doc .doc-parties{grid-template-columns:1fr}}
3662
- `.trim();
3663
3559
  //#endregion
3664
- //#region ../wire/src/secret-material.ts
3665
- const SENSITIVE_MATERIAL_PATTERNS = [
3666
- /0x[a-fA-F0-9]{40,}/u,
3667
- /(?:^|[^a-fA-F0-9])[a-fA-F0-9]{64}(?:$|[^a-fA-F0-9])/u,
3668
- /eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/u,
3669
- /(?:(?:sk|pk|rk)_(?:live|test)|(?:phc|phx|ghp|gho|ghu|ghs|ghr|whsec)_|github_pat_|xox[baprs]-|AKIA[0-9A-Z]{16}|AIza)[A-Za-z0-9_-]*/iu
3670
- ];
3560
+ //#region src/surface/to-capxul-result.ts
3561
+ /** The one place an Effect becomes a Promise on the public surface. */
3562
+ async function runProgram(program, runPromise = Effect.runPromise) {
3563
+ const result = await runPromise(program.pipe(Effect.catchDefect((defect) => Effect.fail(Errors.unknown(defect))), Effect.result));
3564
+ if (Result.isFailure(result)) return {
3565
+ ok: false,
3566
+ error: result.failure
3567
+ };
3568
+ return {
3569
+ ok: true,
3570
+ value: result.success
3571
+ };
3572
+ }
3573
+ async function toCapxulResult(program, layer) {
3574
+ return runProgram(program.pipe(Effect.provide(layer)));
3575
+ }
3671
3576
  /**
3672
- * Reject: does the value carry any known secret material? Best effort — callers
3673
- * drop the whole value on a match; a false negative is a leak, a false positive
3674
- * merely omits an observation field.
3577
+ * Signal-aware bridge for the Convex-backed method bundles. The adapters fail
3578
+ * with `{ publicError }` rather than a bare `CapxulError`, so the wrapper is
3579
+ * unwrapped here once — instead of at every call site.
3675
3580
  */
3676
- function containsSensitiveMaterial(value) {
3677
- return SENSITIVE_MATERIAL_PATTERNS.some((pattern) => pattern.test(value));
3581
+ async function runIfActive(signal, operation, effect, runPromise = Effect.runPromise) {
3582
+ if (signal?.aborted === true) return {
3583
+ ok: false,
3584
+ error: Errors.cancelled({ operation })
3585
+ };
3586
+ const program = effect().pipe(Effect.mapError((error) => error.publicError));
3587
+ return runProgram(signal === void 0 ? program : Effect.raceFirst(program, Effect.callback((resume) => {
3588
+ if (signal.aborted) {
3589
+ resume(Effect.fail(Errors.cancelled({ operation })));
3590
+ return Effect.void;
3591
+ }
3592
+ const onAbort = () => resume(Effect.fail(Errors.cancelled({ operation })));
3593
+ signal.addEventListener("abort", onAbort, { once: true });
3594
+ return Effect.sync(() => signal.removeEventListener("abort", onAbort));
3595
+ })), runPromise);
3596
+ }
3597
+ //#endregion
3598
+ //#region src/surface/_shared/effect-actor-bridge.ts
3599
+ const facadeOutcome = (value) => {
3600
+ if (typeof value !== "object" || value === null || !("ok" in value) || value.ok !== false) return "succeeded";
3601
+ const reason = value.reason;
3602
+ if (reason === "CANCELLED") return "cancelled";
3603
+ return typeof reason === "string" && EXPECTED_OPERATION_OUTCOMES.has(reason) ? "refused" : "failed";
3604
+ };
3605
+ const rejectedFacadeOutcome = (cause) => {
3606
+ if (cause instanceof CapxulError) return cause.code === "CANCELLED" ? "cancelled" : "failed";
3607
+ if (typeof cause !== "object" || cause === null) return "failed";
3608
+ const candidate = cause;
3609
+ return candidate.code === "CANCELLED" || candidate.reason === "CANCELLED" || candidate.error?.code === "CANCELLED" || candidate.publicError?.code === "CANCELLED" ? "cancelled" : "failed";
3610
+ };
3611
+ const RESOLVED_FACADE_SPAN_FAILURE = Symbol("resolved facade span failure");
3612
+ /** The single facade-span bridge consumed by the renderer-neutral React facade. */
3613
+ async function runIdentityFacade(verb, controls, run, runPromise = Effect.runPromise) {
3614
+ const correlationId = safeEngineeringIdentifier(controls?.correlation_id);
3615
+ let resolvedFailure;
3616
+ return runPromise(Effect.gen(function* () {
3617
+ const parent = yield* Effect.currentSpan;
3618
+ return yield* Effect.tryPromise({
3619
+ try: () => run(carryInvocationParentSpan(controls, parent)),
3620
+ catch: (cause) => cause
3621
+ });
3622
+ }).pipe(Effect.tapError((cause) => Effect.annotateCurrentSpan({ outcome: rejectedFacadeOutcome(cause) })), Effect.flatMap((value) => {
3623
+ const outcome = facadeOutcome(value);
3624
+ return Effect.annotateCurrentSpan({ outcome }).pipe(Effect.andThen(outcome === "failed" || outcome === "cancelled" ? Effect.sync(() => {
3625
+ resolvedFailure = value;
3626
+ }).pipe(Effect.andThen(Effect.fail(RESOLVED_FACADE_SPAN_FAILURE))) : Effect.succeed(value)));
3627
+ }), Effect.withSpan(`identity.${verb}`), Effect.annotateSpans({
3628
+ verb,
3629
+ ...correlationId === void 0 ? {} : { correlation_id: correlationId }
3630
+ }), Effect.catch((cause) => cause === RESOLVED_FACADE_SPAN_FAILURE ? Effect.succeed(resolvedFailure) : Effect.fail(cause))));
3631
+ }
3632
+ /**
3633
+ * Bridge an Effect whose typed failure carries `{ publicError: CapxulError }`
3634
+ * into the `Promise<CapxulResult<T>>` shape the consumer-facing method bundles
3635
+ * return. Applies to every port that surfaces a `publicError` (smart-account,
3636
+ * identity, auth-cache, account provision/deploy).
3637
+ */
3638
+ async function runPortEffect(effect, controls, operation = "port", runPromise = Effect.runPromise) {
3639
+ const deadlineDelay = controls?.deadlineMs === void 0 ? void 0 : Math.max(0, controls.deadlineMs - Date.now());
3640
+ const timeoutMs = controls?.timeoutMs === void 0 ? deadlineDelay : deadlineDelay === void 0 ? controls.timeoutMs : Math.min(controls.timeoutMs, deadlineDelay);
3641
+ const observed = (timeoutMs === void 0 ? effect : effect.pipe(Effect.timeoutOrElse({
3642
+ duration: `${timeoutMs} millis`,
3643
+ orElse: () => Effect.fail({ publicError: Errors.providerTimeout("sdk", operation, timeoutMs) })
3644
+ }))).pipe(Effect.tap(() => Effect.annotateCurrentSpan({ outcome: "succeeded" })), Effect.tapError((failure) => {
3645
+ const mode = failure.publicError.details?.failure_mode;
3646
+ return Effect.annotateCurrentSpan({
3647
+ outcome: portFailureOutcome(failure.publicError.code),
3648
+ failure_code: failure.publicError.code,
3649
+ ...typeof mode === "string" ? { mode } : {}
3650
+ });
3651
+ }), Effect.tapDefect(() => Effect.annotateCurrentSpan({
3652
+ outcome: "failed",
3653
+ failure_code: "UNKNOWN"
3654
+ })), Effect.withSpan(`identity.port.${operation}`));
3655
+ return runIfActive(controls?.signal, operation, () => withInvocationParentSpan(observed, controls), runPromise);
3656
+ }
3657
+ /** Map machine-internal failure state onto the public SDK error vocabulary. */
3658
+ function publicIdentityFailure(failure) {
3659
+ if (failure.error !== void 0) return failure.error;
3660
+ return new CapxulError(failure.code === "WORK_DIED" ? "UNKNOWN" : failure.code, failure.message, {
3661
+ ...failure.mode === void 0 ? {} : { details: { failure_mode: failure.mode } },
3662
+ layer: "identity"
3663
+ });
3664
+ }
3665
+ /** The session carried by the actor's current snapshot, or `null`. */
3666
+ function sessionFromActor(actor) {
3667
+ return actor.authSession();
3668
+ }
3669
+ //#endregion
3670
+ //#region src/surface/account-deps.ts
3671
+ /** The single Context tag the account atom + `account.getStatus` resolve. */
3672
+ var AccountDepsTag = class extends Context.Service()("@capxul/sdk/AccountDeps") {};
3673
+ /** Wrap a bundle as the `Layer<AccountDepsTag>` the React provider consumes. */
3674
+ function accountDepsLayer(deps) {
3675
+ return Layer.succeed(AccountDepsTag, deps);
3676
+ }
3677
+ /**
3678
+ * `account.getStatus` as a single Effect requiring ONLY `AccountDepsTag`.
3679
+ * Faithful transcription of the current public method body (`account.ts`):
3680
+ * resolve the session (actor first, then the resume-path `authCache`), then
3681
+ * walk the readiness ladder. The `SmartAccountPort` failure narrows to its
3682
+ * `publicError`; a consumer `AccountProvider.getAddress` rejection becomes a
3683
+ * `providerError` (defending the public `CapxulResult` contract).
3684
+ */
3685
+ const accountStatusProgram = Effect.gen(function* () {
3686
+ const deps = yield* AccountDepsTag;
3687
+ const session = yield* Effect.promise(() => currentSession(deps.actor, deps.authCache));
3688
+ if (session === null) return { status: "notAuthenticated" };
3689
+ const current = yield* deps.smartAccountPort.loadByAuthUserId(session.authUserId).pipe(Effect.mapError((failure) => failure.publicError));
3690
+ if (current !== null) return statusFromAccount(current, deps.requirement);
3691
+ if (deps.requirement === "none") return {
3692
+ status: "accountReady",
3693
+ requirement: deps.requirement,
3694
+ account: null,
3695
+ deployment: { status: "counterfactual" }
3696
+ };
3697
+ const signer = deps.signer;
3698
+ if (signer === void 0) return {
3699
+ status: "accountRequired",
3700
+ requirement: deps.requirement,
3701
+ chainId: deps.chainId
3702
+ };
3703
+ const signerAddress = yield* Effect.tryPromise({
3704
+ try: () => signer.getAddress(),
3705
+ catch: (cause) => signerFailure(signer.source, "getAddress", cause)
3706
+ });
3707
+ return {
3708
+ status: "accountProviderReady",
3709
+ requirement: deps.requirement,
3710
+ chainId: deps.chainId,
3711
+ source: signer.source,
3712
+ signerAddress
3713
+ };
3714
+ });
3715
+ /**
3716
+ * Resume-path session resolution. Consults the actor first; if the actor has
3717
+ * no session (e.g. page refresh before any sign-in event), reads
3718
+ * `authCache.getSession`. `AuthCacheError` is non-fatal at this read point —
3719
+ * treat as "no session" and let the consumer's `auth.signIn` path resolve.
3720
+ */
3721
+ async function currentSession(actor, authCache) {
3722
+ const fromActor = sessionFromActor(actor);
3723
+ if (fromActor !== null) return fromActor;
3724
+ if (authCache === void 0) return null;
3725
+ const cached = await Effect.runPromise(Effect.result(authCache.getSession));
3726
+ if (Result.isSuccess(cached)) {
3727
+ if (cached.success !== null && typeof actor.restoreAuthSession === "function") {
3728
+ const restored = await Effect.runPromise(Effect.result(actor.restoreAuthSession(cached.success)));
3729
+ if (Result.isFailure(restored)) return null;
3730
+ }
3731
+ return cached.success;
3732
+ }
3733
+ return null;
3734
+ }
3735
+ /** Map a backend `SmartAccount` row onto the readiness `AccountStatus`. */
3736
+ function statusFromAccount(account, requirement) {
3737
+ if (requirement === "deployed") {
3738
+ if (account.deployedAt === null) return {
3739
+ status: "accountPrepared",
3740
+ requirement,
3741
+ account,
3742
+ deployment: { status: "counterfactual" }
3743
+ };
3744
+ return {
3745
+ status: "accountReady",
3746
+ requirement,
3747
+ account,
3748
+ deployment: {
3749
+ status: "deployed",
3750
+ deployedAt: account.deployedAt
3751
+ }
3752
+ };
3753
+ }
3754
+ return {
3755
+ status: "accountReady",
3756
+ requirement,
3757
+ account,
3758
+ deployment: account.deployedAt === null ? { status: "counterfactual" } : {
3759
+ status: "deployed",
3760
+ deployedAt: account.deployedAt
3761
+ }
3762
+ };
3678
3763
  }
3679
3764
  //#endregion
3680
- //#region ../wire/src/observation-context.ts
3681
- /** Single bounded HTTP carrier used before a Convex action envelope exists. */
3682
- const OBSERVATION_CONTEXT_HEADER = "x-capxul-observation-context";
3683
- const FIELD_RULES = {
3684
- application: {
3685
- maxLength: 64,
3686
- pattern: /^[A-Za-z0-9][A-Za-z0-9._-]*$/u
3687
- },
3688
- applicationId: {
3689
- maxLength: 30,
3690
- pattern: APP_ID_RE
3691
- },
3692
- release: {
3693
- maxLength: 128,
3694
- pattern: /^[A-Za-z0-9][A-Za-z0-9._+@:/-]*$/u
3695
- },
3696
- sessionId: {
3697
- maxLength: 128,
3698
- pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
3699
- },
3700
- organizationId: {
3701
- maxLength: 128,
3702
- pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
3703
- },
3704
- journeyId: {
3705
- maxLength: 128,
3706
- pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
3707
- },
3708
- correlationId: {
3709
- maxLength: 128,
3710
- pattern: /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u
3711
- },
3712
- anonymousId: {
3713
- maxLength: 128,
3714
- pattern: /^anon_[A-Za-z0-9-]+$/u
3715
- },
3716
- traceparent: {
3717
- maxLength: 55,
3718
- pattern: /^00-[0-9a-f]{32}-[0-9a-f]{16}-0[01]$/u
3765
+ //#region src/surface/account-lifecycle.ts
3766
+ function isActiveProvisioningPhase(phase) {
3767
+ return phase.status === "wallet" || phase.status === "identity" || phase.status === "provision" || phase.status === "deploy";
3768
+ }
3769
+ function isRequirementMet(status, requirement) {
3770
+ if (requirement === "none") return status.status !== "notAuthenticated";
3771
+ if (status.status !== "accountReady") return false;
3772
+ return requirement !== "deployed" || status.deployment.status === "deployed";
3773
+ }
3774
+ function mapProvisioningFailureStep(step) {
3775
+ switch (step) {
3776
+ case "wallet": return "connecting";
3777
+ case "identity": return "registering";
3778
+ case "provision":
3779
+ case "deploy": return "activating";
3719
3780
  }
3720
- };
3721
- /**
3722
- * Copy only the canonical allowlist and silently omit malformed/sensitive
3723
- * values. Observation metadata is best effort and may never reject a domain
3724
- * operation.
3725
- */
3726
- function sanitizeObservationContext(input) {
3727
- if (typeof input !== "object" || input === null || Array.isArray(input)) return void 0;
3728
- const source = input;
3729
- const sanitized = {};
3730
- for (const field of Object.keys(FIELD_RULES)) {
3731
- const value = source[field];
3732
- if (!isSafeField(field, value)) continue;
3733
- sanitized[field] = value;
3781
+ }
3782
+ function mapProvisioningPhaseToSetupStep(phase) {
3783
+ switch (phase.status) {
3784
+ case "idle":
3785
+ case "wallet": return "connecting";
3786
+ case "identity": return "registering";
3787
+ case "provision":
3788
+ case "deploy": return "activating";
3789
+ case "ready":
3790
+ case "failed": return "connecting";
3734
3791
  }
3735
- return Object.keys(sanitized).length === 0 ? void 0 : sanitized;
3736
3792
  }
3737
- /** Encode only the sanitized allowlist; absence stays absence. */
3738
- function encodeObservationContextHeader(input) {
3739
- const sanitized = sanitizeObservationContext(input);
3740
- return sanitized === void 0 ? void 0 : JSON.stringify(sanitized);
3793
+ function isSettingUpLifecycle(lifecycle) {
3794
+ return lifecycle.status === "settingUp";
3741
3795
  }
3742
- function isSafeField(field, value) {
3743
- if (typeof value !== "string") return false;
3744
- const rule = FIELD_RULES[field];
3745
- return value.length > 0 && value.length <= rule.maxLength && value === value.trim() && !value.includes("://") && !containsSensitiveMaterial(value) && rule.pattern.test(value);
3796
+ function readyLifecycle(status, accountId) {
3797
+ return {
3798
+ status: "ready",
3799
+ accountId,
3800
+ canTransact: status.status === "accountReady" && status.deployment.status === "deployed"
3801
+ };
3802
+ }
3803
+ function mapAccountLifecycle(input) {
3804
+ const { status, phase, requirement, accountId } = input;
3805
+ if (status.status === "notAuthenticated") return { status: "loading" };
3806
+ if (phase.status === "failed") return {
3807
+ status: "failed",
3808
+ at: mapProvisioningFailureStep(phase.at),
3809
+ error: phase.error
3810
+ };
3811
+ if (isRequirementMet(status, requirement) || phase.status === "ready") {
3812
+ if (accountId === void 0) return { status: "loading" };
3813
+ return readyLifecycle(status, accountId);
3814
+ }
3815
+ if (isActiveProvisioningPhase(phase) || phase.status === "idle") return {
3816
+ status: "settingUp",
3817
+ step: mapProvisioningPhaseToSetupStep(phase)
3818
+ };
3819
+ return { status: "loading" };
3746
3820
  }
3747
3821
  //#endregion
3748
3822
  //#region src/contract/actor-scope.ts
@@ -3979,7 +4053,7 @@ function mapActorRequest(request, payer) {
3979
4053
  ...resolvedPayer === void 0 ? {} : { payer: resolvedPayer },
3980
4054
  amount: request.amount,
3981
4055
  reference: request.reference,
3982
- status: mapActorRequestStatus(request.status),
4056
+ status: request.status,
3983
4057
  expiresAt: request.expiresAt ?? null
3984
4058
  };
3985
4059
  }
@@ -4037,28 +4111,17 @@ function mapApprovedInboxPayment(command, input) {
4037
4111
  };
4038
4112
  }
4039
4113
  }
4040
- function mapActorRequestStatus(status) {
4114
+ function mapInboxStatus(status) {
4041
4115
  switch (status) {
4042
4116
  case "draft":
4043
4117
  case "sent":
4044
- case "viewed":
4118
+ case "viewed": return "open";
4119
+ case "pending_settlement": return "approved";
4045
4120
  case "paid":
4046
- case "pending_settlement":
4047
- case "declined":
4048
- case "cancelled":
4049
- case "expired": return status;
4050
- default: return "sent";
4051
- }
4052
- }
4053
- function mapInboxStatus(status) {
4054
- switch (status) {
4055
- case "approved":
4056
4121
  case "declined":
4057
- case "paid":
4058
4122
  case "cancelled":
4059
4123
  case "expired": return status;
4060
- case "pending_settlement": return "approved";
4061
- default: return "open";
4124
+ default: throw Errors.invalidInput("status", "unknown request status");
4062
4125
  }
4063
4126
  }
4064
4127
  function normalizeRefForBackend$1(ref, field) {
@@ -4377,6 +4440,7 @@ const financialOpsContract = {
4377
4440
  listPayments: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].listPayments),
4378
4441
  getPayment: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].getPayment),
4379
4442
  activityList: makeFunctionReference(CAPXUL_FUNCTIONS["movement/activity"].list),
4443
+ activitySummary: makeFunctionReference(CAPXUL_FUNCTIONS["movement/activity"].summary),
4380
4444
  activityGet: makeFunctionReference(CAPXUL_FUNCTIONS["movement/activity"].get),
4381
4445
  activityAnnotate: makeFunctionReference(CAPXUL_FUNCTIONS["movement/activity"].annotate),
4382
4446
  verifyPaymentDocument: makeFunctionReference(CAPXUL_FUNCTIONS["financialOps/queries"].verifyPaymentDocument),
@@ -4550,7 +4614,10 @@ function canonicalJson(value) {
4550
4614
  async function fingerprintPaymentIntent(intent) {
4551
4615
  return keccak256(toBytes(canonicalJson(intent)));
4552
4616
  }
4553
- async function executePrepared(deps, prepare, expectedRequest, signal) {
4617
+ function matchesIntent(expected) {
4618
+ return async (request) => await fingerprintPaymentIntent(request) === await fingerprintPaymentIntent(expected);
4619
+ }
4620
+ async function executePrepared(deps, prepare, isExpectedRequest, signal) {
4554
4621
  if (isAborted$1(signal)) return {
4555
4622
  ok: false,
4556
4623
  error: Errors.cancelled({ operation: "payments" })
@@ -4571,7 +4638,7 @@ async function executePrepared(deps, prepare, expectedRequest, signal) {
4571
4638
  }
4572
4639
  const prepared = await prepare(signerAddress);
4573
4640
  if (!prepared.ok) return prepared;
4574
- if (await fingerprintPaymentIntent(prepared.value.request) !== await fingerprintPaymentIntent(expectedRequest)) return {
4641
+ if (!await isExpectedRequest(prepared.value.request)) return {
4575
4642
  ok: false,
4576
4643
  error: Errors.invalidInput("payment", "prepared command mismatch")
4577
4644
  };
@@ -4606,13 +4673,13 @@ function executePaymentLifecycle(deps, intent, signal) {
4606
4673
  return executePrepared(deps, (signerAddress) => runIfActive(signal, "payments.prepareLifecycleExecution", () => deps.convexCall.action(deps.functions.preparePaymentLifecycleExecution, { input: {
4607
4674
  signerAddress,
4608
4675
  intent
4609
- } })), intent, signal);
4676
+ } })), matchesIntent(intent), signal);
4610
4677
  }
4611
4678
  function executeOrganizationPayment(deps, input, signal) {
4612
4679
  return executePrepared(deps, (signerAddress) => runIfActive(signal, "organizationPayments.prepareExecution", () => deps.convexCall.action(deps.functions.prepareOrganizationPaymentExecution, { input: {
4613
4680
  ...input,
4614
4681
  signerAddress
4615
- } })), input, signal);
4682
+ } })), matchesIntent(input), signal);
4616
4683
  }
4617
4684
  //#endregion
4618
4685
  //#region src/surface/money.ts
@@ -4628,6 +4695,40 @@ function actorReferenceToBackend(actor) {
4628
4695
  case "org": return actor;
4629
4696
  }
4630
4697
  }
4698
+ /**
4699
+ * The activity backend gives its actor a different name than the other
4700
+ * financialOps functions: `{kind: "organization", orgId}`, and not
4701
+ * `{kind: "org", orgId}`. Thus it does not use `actorReferenceToBackend`.
4702
+ *
4703
+ * The `personal` case sends NO actor. This is correct, and it does not lose
4704
+ * data. `requireActivityActor` uses the signed-in Account when the actor is
4705
+ * absent, and `canReadActor` refuses all other account identifiers
4706
+ * (`packages/backend/convex/movement/activityAuth.ts`). Thus "personal" and
4707
+ * "absent" both name the one Account that an SDK caller can read. The SDK does
4708
+ * not hold an account identifier to send.
4709
+ *
4710
+ * The `switch` is exhaustive. A new `ActorReference` variant is a compile error
4711
+ * here. The conditional expression that this function replaced removed each
4712
+ * value that was not an organization.
4713
+ */
4714
+ function activityActorField(actor) {
4715
+ if (actor === void 0) return {};
4716
+ switch (actor.kind) {
4717
+ case "personal": return {};
4718
+ case "organization": return { actor: {
4719
+ kind: "organization",
4720
+ orgId: actor.organizationId
4721
+ } };
4722
+ }
4723
+ }
4724
+ /** An absent actor and a `personal` actor both name the signed-in Account. */
4725
+ function actorScopeKey(actor) {
4726
+ return actor === void 0 || actor.kind === "personal" ? "personal" : `org:${actor.organizationId}`;
4727
+ }
4728
+ /** Two actor references name the same scope. */
4729
+ function sameActor(left, right) {
4730
+ return actorScopeKey(left) === actorScopeKey(right);
4731
+ }
4631
4732
  const memoryPaymentRequestKeys = /* @__PURE__ */ new Map();
4632
4733
  const paymentAttemptReleases = /* @__PURE__ */ new Set();
4633
4734
  let paymentAttemptPagehideInstalled = false;
@@ -5058,31 +5159,48 @@ function makeFinancialOpsMethods(deps) {
5058
5159
  },
5059
5160
  activity: {
5060
5161
  list: (params, options) => runIfActive(options?.signal, "activity.list", () => deps.convexCall.query(fns.activityList, { input: {
5061
- ...params?.actor?.kind === "organization" ? { actor: {
5062
- kind: "organization",
5063
- orgId: params.actor.organizationId
5064
- } } : {},
5162
+ ...activityActorField(params?.actor),
5065
5163
  ...params?.cursor === void 0 ? {} : { cursor: params.cursor },
5066
- ...params?.limit === void 0 ? {} : { limit: params.limit }
5164
+ ...params?.limit === void 0 ? {} : { limit: params.limit },
5165
+ ...params?.range === void 0 ? {} : { range: params.range },
5166
+ ...params?.filter === void 0 ? {} : { filter: params.filter }
5067
5167
  } })),
5068
- get: (reference, options) => runIfActive(options?.signal, "activity.get", () => deps.convexCall.query(fns.activityGet, { input: {
5069
- kind: reference.kind,
5070
- id: reference.id,
5071
- ...reference.kind === "payment" && reference.actor?.kind === "organization" ? { actor: {
5072
- kind: "organization",
5073
- orgId: reference.actor.organizationId
5074
- } } : {}
5168
+ summary: (params, options) => runIfActive(options?.signal, "activity.summary", () => deps.convexCall.query(fns.activitySummary, { input: {
5169
+ ...activityActorField(params?.actor),
5170
+ ...params?.window === void 0 ? {} : { window: params.window }
5075
5171
  } })),
5076
- annotate: (input, options) => runIfActive(options?.signal, "activity.annotate", () => deps.convexCall.mutation(fns.activityAnnotate, { input: {
5077
- ...input.actor?.kind === "organization" ? { actor: {
5078
- kind: "organization",
5079
- orgId: input.actor.organizationId
5080
- } } : {},
5081
- movementId: input.movementId,
5082
- ...input.counterpartyLabel === void 0 ? {} : { counterpartyLabel: input.counterpartyLabel },
5083
- ...input.accountingCategory === void 0 ? {} : { accountingCategory: input.accountingCategory },
5084
- ...input.memo === void 0 ? {} : { memo: input.memo }
5085
- } }))
5172
+ get: (reference, options) => {
5173
+ const actor = actorReferenceToBackend(options?.actor);
5174
+ return runIfActive(options?.signal, "activity.get", () => deps.convexCall.query(fns.activityGet, {
5175
+ input: {
5176
+ kind: reference.kind,
5177
+ id: reference.id,
5178
+ ...reference.kind === "payment" ? activityActorField(reference.actor) : {}
5179
+ },
5180
+ ...actor === void 0 ? {} : { actor }
5181
+ }));
5182
+ },
5183
+ annotate: (input, options) => {
5184
+ if (input.actor !== void 0 && input.reference.kind === "payment" && input.reference.actor !== void 0 && !sameActor(input.actor, input.reference.actor)) return Promise.resolve({
5185
+ ok: false,
5186
+ error: Errors.invalidInput("reference.actor", "must match the annotation actor")
5187
+ });
5188
+ const referenceActor = input.reference.kind === "payment" ? activityActorField(input.reference.actor).actor : void 0;
5189
+ return runIfActive(options?.signal, "activity.annotate", () => deps.convexCall.mutation(fns.activityAnnotate, { input: {
5190
+ ...activityActorField(input.actor),
5191
+ reference: input.reference.kind === "payment" && referenceActor !== void 0 ? {
5192
+ kind: "payment",
5193
+ id: input.reference.id,
5194
+ actor: referenceActor
5195
+ } : {
5196
+ kind: input.reference.kind,
5197
+ id: input.reference.id
5198
+ },
5199
+ ...input.counterpartyLabel === void 0 ? {} : { counterpartyLabel: input.counterpartyLabel },
5200
+ ...input.accountingCategory === void 0 ? {} : { accountingCategory: input.accountingCategory },
5201
+ ...input.memo === void 0 ? {} : { memo: input.memo }
5202
+ } }));
5203
+ }
5086
5204
  },
5087
5205
  offramp: {
5088
5206
  quote: (input, options) => {
@@ -5410,7 +5528,7 @@ function mapOk(result, f) {
5410
5528
  }
5411
5529
  //#endregion
5412
5530
  //#region package.json
5413
- var version = "2.3.2";
5531
+ var version = "2.5.0";
5414
5532
  //#endregion
5415
5533
  //#region src/ports/auth-client.ts
5416
5534
  var AuthClientError = class extends Data.TaggedError("AuthClientError") {};
@@ -5584,7 +5702,8 @@ const TelemetryEnvelopeProps = {
5584
5702
  "development",
5585
5703
  "staging",
5586
5704
  "production",
5587
- "unknown"
5705
+ "unknown",
5706
+ "local"
5588
5707
  ]),
5589
5708
  producer: Schema.Literals([
5590
5709
  "server",
@@ -7476,7 +7595,7 @@ function makePermissionMethods(deps, orgId) {
7476
7595
  }
7477
7596
  //#endregion
7478
7597
  //#region src/surface/organization-payments.ts
7479
- function executionDependencies(input) {
7598
+ function executionDependencies$1(input) {
7480
7599
  return input.actor === void 0 || input.chainId === void 0 || input.signer === void 0 ? null : {
7481
7600
  actor: input.actor,
7482
7601
  chainId: input.chainId,
@@ -7493,7 +7612,7 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
7493
7612
  ok: false,
7494
7613
  error: Errors.cancelled({ operation })
7495
7614
  };
7496
- const execution = executionDependencies(deps);
7615
+ const execution = executionDependencies$1(deps);
7497
7616
  if (execution === null) return {
7498
7617
  ok: false,
7499
7618
  error: Errors.notImplemented("organizationPayments", "executionComposition")
@@ -7588,6 +7707,197 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
7588
7707
  };
7589
7708
  }
7590
7709
  //#endregion
7710
+ //#region src/contract/payroll.ts
7711
+ const payrollContract = {
7712
+ authorizeRun: makeFunctionReference(CAPXUL_FUNCTIONS["payroll/actions"].authorizeRun),
7713
+ runs: makeFunctionReference(CAPXUL_FUNCTIONS["payroll/queries"].runs),
7714
+ groups: makeFunctionReference(CAPXUL_FUNCTIONS["payroll/queries"].groups),
7715
+ saveGroup: makeFunctionReference(CAPXUL_FUNCTIONS["payroll/mutations"].saveGroup),
7716
+ removeGroup: makeFunctionReference(CAPXUL_FUNCTIONS["payroll/mutations"].removeGroup)
7717
+ };
7718
+ //#endregion
7719
+ //#region src/surface/payroll.ts
7720
+ const AUTHORIZE_RUN = "payroll.authorizeRun";
7721
+ function toPayrollRun(wire) {
7722
+ return {
7723
+ id: toPayrollRunId(wire.id),
7724
+ status: wire.status,
7725
+ periodStart: wire.periodStart,
7726
+ periodEnd: wire.periodEnd,
7727
+ total: wire.total,
7728
+ recipientCount: wire.recipientCount
7729
+ };
7730
+ }
7731
+ function toPayrollRuns(wire) {
7732
+ return {
7733
+ runs: wire.runs.map(toPayrollRun),
7734
+ settledThisMonth: wire.settledThisMonth
7735
+ };
7736
+ }
7737
+ function toPayrollGroup(wire) {
7738
+ return {
7739
+ id: toPayrollGroupId(wire.id),
7740
+ name: wire.name,
7741
+ tone: wire.tone,
7742
+ members: wire.members.map((member) => ({
7743
+ partyId: member.partyId,
7744
+ amount: member.amount,
7745
+ currency: member.currency
7746
+ }))
7747
+ };
7748
+ }
7749
+ const MINOR_UNIT_INTEGER = /^-?\d+$/u;
7750
+ /**
7751
+ * One prepared `Money` counted in the minor units `net` is written in, or
7752
+ * `null` when the value is not a decimal number. `amount.value` is a DECIMAL
7753
+ * string (`"200"` at 6 decimals is 200000000 minor units), so comparing it to
7754
+ * `net` directly would compare two different units and pass nothing.
7755
+ */
7756
+ function minorUnits(amount) {
7757
+ const [whole = "", fraction = ""] = amount.value.split(".");
7758
+ if (!/^\d+$/u.test(whole) || !/^\d*$/u.test(fraction) || fraction.length > amount.decimals) return null;
7759
+ return BigInt(whole + fraction.padEnd(amount.decimals, "0"));
7760
+ }
7761
+ /**
7762
+ * One prepared item must pay the person this caller named, the amount this
7763
+ * caller set, under a payslip that attests to the same figures.
7764
+ *
7765
+ * `issuedAt` and `employerRef` are server facts the caller cannot contradict,
7766
+ * so they are not compared. Everything the caller DID supply is: the recipient
7767
+ * `Ref`, the transfer amount against `net`, and the payslip's employee, gross
7768
+ * and net. Adjustments are not in the signed command at all — the backend
7769
+ * enforces `gross + Σ adjustments === net` (ADR-0022 R8), and gross and net
7770
+ * being right is what the signer can prove here.
7771
+ */
7772
+ function isRunItem(prepared, item) {
7773
+ if (prepared === void 0) return false;
7774
+ const payslip = prepared.document;
7775
+ return canonicalJson(prepared.to) === canonicalJson(item.to) && prepared.paymentType === "payroll" && MINOR_UNIT_INTEGER.test(item.net) && minorUnits(prepared.amount) === BigInt(item.net) && payslip?.primaryType === "Payslip" && payslip.message.employeeRef === item.partyId && payslip.message.gross === item.gross && payslip.message.net === item.net;
7776
+ }
7777
+ /**
7778
+ * The batch the backend derived from a payroll intent must be the batch this
7779
+ * caller asked for, checked before the digest is signed.
7780
+ *
7781
+ * The payslip envelope on each item is server-built and carries the run row's
7782
+ * own `issuedAt`, so the batch cannot be fingerprinted against a local copy
7783
+ * (`matchesIntent` is unavailable here). What CAN be verified is every field
7784
+ * the caller supplied — the org, the Budget, the request key, and per item the
7785
+ * recipient, the amount and the payslip figures — plus the lineage binding the
7786
+ * batch to the run just written. A prepared command that pays a different
7787
+ * person, a different amount, from a different Budget, or under a different
7788
+ * run never reaches the signer.
7789
+ */
7790
+ function isRunBatch(input) {
7791
+ return (request) => {
7792
+ const batch = request;
7793
+ return Promise.resolve(batch.orgId === input.orgId && batch.permissionId === input.permissionId && batch.requestKey === input.requestKey && batch.lineage?.kind === "payroll" && batch.lineage.runId === input.runId && batch.items?.length === input.items.length && input.items.every((item, index) => isRunItem(batch.items?.[index], item)));
7794
+ };
7795
+ }
7796
+ function executionDependencies(deps) {
7797
+ return deps.actor === void 0 || deps.chainId === void 0 || deps.signer === void 0 ? null : {
7798
+ actor: deps.actor,
7799
+ chainId: deps.chainId,
7800
+ convexCall: deps.convexCall,
7801
+ functions: moneyExecutionContract,
7802
+ signer: deps.signer
7803
+ };
7804
+ }
7805
+ function makePayrollMethods(deps, orgId) {
7806
+ const requestKeyScope = deps.requestKeyScope ?? `client-${crypto.randomUUID()}`;
7807
+ async function authorize(input, signal) {
7808
+ const execution = executionDependencies(deps);
7809
+ if (execution === null) return {
7810
+ ok: false,
7811
+ error: Errors.notImplemented("payroll", "executionComposition")
7812
+ };
7813
+ const requestKey = await paymentRequestKeyLifecycle(`${requestKeyScope}:${AUTHORIZE_RUN}`, {
7814
+ orgId,
7815
+ input
7816
+ }, input.requestKey);
7817
+ let authorized;
7818
+ const submitted = await executePrepared(execution, async (signerAddress) => {
7819
+ const prepared = await runIfActive(signal, AUTHORIZE_RUN, () => deps.convexCall.action(payrollContract.authorizeRun, { input: {
7820
+ orgId,
7821
+ permissionId: input.permissionId,
7822
+ requestKey: requestKey.key,
7823
+ signerAddress,
7824
+ period: input.period,
7825
+ items: input.items
7826
+ } }));
7827
+ if (!prepared.ok) return prepared;
7828
+ authorized = prepared.value.run;
7829
+ return {
7830
+ ok: true,
7831
+ value: prepared.value.execution
7832
+ };
7833
+ }, (request) => authorized === void 0 || authorized.periodStart !== input.period.start || authorized.periodEnd !== input.period.end ? Promise.resolve(false) : isRunBatch({
7834
+ orgId,
7835
+ permissionId: input.permissionId,
7836
+ requestKey: requestKey.key,
7837
+ runId: authorized.id,
7838
+ items: input.items
7839
+ })(request), signal);
7840
+ try {
7841
+ await requestKey.finish(submitted.ok);
7842
+ } catch {}
7843
+ if (!submitted.ok) return submitted;
7844
+ return authorized === void 0 ? {
7845
+ ok: false,
7846
+ error: Errors.unknown()
7847
+ } : {
7848
+ ok: true,
7849
+ value: toPayrollRun(authorized)
7850
+ };
7851
+ }
7852
+ return {
7853
+ runs: (options) => runIfActive(options?.signal, "payroll.runs", () => Effect.map(deps.convexCall.query(payrollContract.runs, { orgId }), toPayrollRuns)),
7854
+ authorizeRun: async (input, options) => {
7855
+ if (options?.signal?.aborted === true) return {
7856
+ ok: false,
7857
+ error: Errors.cancelled({ operation: AUTHORIZE_RUN })
7858
+ };
7859
+ try {
7860
+ return await authorize(input, options?.signal);
7861
+ } catch (cause) {
7862
+ return {
7863
+ ok: false,
7864
+ error: cause instanceof CapxulError ? cause : Errors.unknown(cause)
7865
+ };
7866
+ }
7867
+ },
7868
+ groups: {
7869
+ list: (options) => runIfActive(options?.signal, "payroll.groups.list", () => Effect.map(deps.convexCall.query(payrollContract.groups, { orgId }), (groups) => groups.map(toPayrollGroup))),
7870
+ save: (input, options) => runIfActive(options?.signal, "payroll.groups.save", () => Effect.map(deps.convexCall.mutation(payrollContract.saveGroup, {
7871
+ orgId,
7872
+ ...input.id === void 0 ? {} : { id: String(input.id) },
7873
+ name: input.name,
7874
+ tone: input.tone,
7875
+ members: input.members
7876
+ }), toPayrollGroup)),
7877
+ remove: (id, options) => runIfActive(options?.signal, "payroll.groups.remove", () => Effect.map(deps.convexCall.mutation(payrollContract.removeGroup, {
7878
+ orgId,
7879
+ id
7880
+ }), () => void 0))
7881
+ }
7882
+ };
7883
+ }
7884
+ const payrollUnavailable = () => Promise.resolve({
7885
+ ok: false,
7886
+ error: Errors.notImplemented("payroll", "executionComposition")
7887
+ });
7888
+ /** The bundle an unconfigured client exposes — every verb refuses, none throws. */
7889
+ function makeUnavailablePayrollMethods() {
7890
+ return {
7891
+ runs: payrollUnavailable,
7892
+ authorizeRun: payrollUnavailable,
7893
+ groups: {
7894
+ list: payrollUnavailable,
7895
+ save: payrollUnavailable,
7896
+ remove: payrollUnavailable
7897
+ }
7898
+ };
7899
+ }
7900
+ //#endregion
7591
7901
  //#region src/surface/_shared/org-telemetry.ts
7592
7902
  /** Extract the domain from an email for telemetry (never the local part / PII). */
7593
7903
  function emailDomain$1(email) {
@@ -8125,6 +8435,13 @@ function makeOrgMethods(deps) {
8125
8435
  ...deps.actor === void 0 ? {} : { actor: deps.actor },
8126
8436
  ...deps.chainId === void 0 ? {} : { chainId: Number(deps.chainId) },
8127
8437
  ...deps.signer === void 0 ? {} : { signer: deps.signer }
8438
+ }, String(orgId)),
8439
+ payroll: convexCall === void 0 ? makeUnavailablePayrollMethods() : makePayrollMethods({
8440
+ convexCall,
8441
+ ...deps.requestKeyScope === void 0 ? {} : { requestKeyScope: deps.requestKeyScope },
8442
+ ...deps.actor === void 0 ? {} : { actor: deps.actor },
8443
+ ...deps.chainId === void 0 ? {} : { chainId: Number(deps.chainId) },
8444
+ ...deps.signer === void 0 ? {} : { signer: deps.signer }
8128
8445
  }, String(orgId))
8129
8446
  };
8130
8447
  }
@@ -8163,13 +8480,74 @@ const organizationPaymentExecutionUnavailable = () => Promise.resolve({
8163
8480
  //#region src/contract/holdings.ts
8164
8481
  const holdingsContract = { current: makeFunctionReference(CAPXUL_FUNCTIONS["holdings/actions"].current) };
8165
8482
  //#endregion
8483
+ //#region src/domain/money/primary-holding.ts
8484
+ const CURRENCY_BY_TOKEN_SYMBOL = new Map([["USDX", toCurrencyCode("USD")]]);
8485
+ /**
8486
+ * The designated display asset: the payable row holding the most money, or
8487
+ * `null` when no row is payable.
8488
+ *
8489
+ * A `HoldingRow` (`packages/wire/src/money.ts`) is a RAW CHAIN ROW, and three
8490
+ * of its shapes cannot become a `Holding`. Each is SKIPPED rather than
8491
+ * reported, because a row nobody can render is not a failure of the read:
8492
+ *
8493
+ * - no `decimals` — the raw balance cannot be lifted into major units;
8494
+ * - no `symbol` — the asset cannot be named;
8495
+ * - a symbol that stands for no supported `CurrencyCode` — the balance
8496
+ * cannot be stated as `Money` without inventing a currency for it.
8497
+ *
8498
+ * This replaces the app's hand pick in `formatCurrentHoldingsBalance`
8499
+ * (`dashboard-formatters.ts`): a `.find()` over a hardcoded `["USDX","USDC"]`
8500
+ * list falling back to `rows[0]`. Ties keep the earlier row, so the same
8501
+ * snapshot always yields the same answer.
8502
+ */
8503
+ function primaryHolding(rows) {
8504
+ let primary = null;
8505
+ for (const row of rows) {
8506
+ const holding = toHolding(row);
8507
+ if (holding === null) continue;
8508
+ if (primary === null || compareDecimal(holding.available.value, primary.available.value) > 0) primary = holding;
8509
+ }
8510
+ return primary;
8511
+ }
8512
+ function toHolding(row) {
8513
+ if (row.symbol === void 0 || row.decimals === void 0) return null;
8514
+ const currency = currencyForTokenSymbol(row.symbol);
8515
+ if (currency === null) return null;
8516
+ return {
8517
+ id: row.assetKind === "native" ? "native" : row.tokenAddress.toLowerCase(),
8518
+ symbol: row.symbol,
8519
+ available: fromWei(row.rawBalance, row.decimals, currency)
8520
+ };
8521
+ }
8522
+ function currencyForTokenSymbol(symbol) {
8523
+ return CURRENCY_BY_TOKEN_SYMBOL.get(symbol.toUpperCase()) ?? null;
8524
+ }
8525
+ /**
8526
+ * Order two non-negative major-unit decimal strings without converting either
8527
+ * to a JavaScript number. Rows carry different `decimals`, so the raw integers
8528
+ * are not comparable: 1999999999 at 9 decimals is LESS than 2000000 at 6.
8529
+ */
8530
+ function compareDecimal(first, second) {
8531
+ const [firstWhole = "0", firstFraction = ""] = first.split(".");
8532
+ const [secondWhole = "0", secondFraction = ""] = second.split(".");
8533
+ const width = Math.max(firstFraction.length, secondFraction.length);
8534
+ const firstScaled = BigInt(firstWhole + firstFraction.padEnd(width, "0"));
8535
+ const secondScaled = BigInt(secondWhole + secondFraction.padEnd(width, "0"));
8536
+ if (firstScaled === secondScaled) return 0;
8537
+ return firstScaled < secondScaled ? -1 : 1;
8538
+ }
8539
+ //#endregion
8166
8540
  //#region src/surface/holdings.ts
8167
8541
  function makeHoldingsMethods(deps) {
8168
8542
  const functions = deps.functions ?? holdingsContract;
8169
- return { current: (input, options) => runIfActive(options?.signal, "holdings.current", () => deps.convexCall.action(functions.current, input?.actor?.kind === "organization" ? { actor: {
8543
+ const read = (operation, actor, signal, pick) => runIfActive(signal, operation, () => deps.convexCall.action(functions.current, actor?.kind === "organization" ? { actor: {
8170
8544
  kind: "organization",
8171
- orgId: input.actor.organizationId
8172
- } } : {})) };
8545
+ orgId: actor.organizationId
8546
+ } } : {}).pipe(Effect.map(pick)));
8547
+ return {
8548
+ current: (input, options) => read("holdings.current", input?.actor, options?.signal, (snapshot) => snapshot),
8549
+ primary: (input, options) => read("holdings.primary", input?.actor, options?.signal, (snapshot) => primaryHolding(snapshot.rows))
8550
+ };
8173
8551
  }
8174
8552
  //#endregion
8175
8553
  //#region src/surface/factory.ts
@@ -8998,4 +9376,4 @@ function withHostObservation(actor, snapshot) {
8998
9376
  };
8999
9377
  }
9000
9378
  //#endregion
9001
- export { fingerprintPaymentIntent as A, formatTraceparent as B, ClockPortTag as C, AuthClientError as D, authClientPortFromPromiseAdapter as E, sanitizeObservationContext as F, signerFailure as G, readInvocationObservation as H, CAPXUL_FUNCTIONS as I, BASE_SEPOLIA_CHAIN_ID as J, CAPXUL_PAYMENTS_V2_ADDRESS as K, BootstrapEnvelope as L, fromWei as M, OBSERVATION_CONTEXT_HEADER as N, AuthClientPortTag as O, encodeObservationContextHeader as P, isRestoring as Q, EngineeringTelemetryBootstrapPolicy as R, ClockError as S, bootstrapErrorFromCapxul as T, causeChain as U, copyInvocationObservation as V, injectedWalletSigner as W, destination as X, deriveCapxulSafeAddress as Y, isClaimed as Z, wireChainId as _, observeFailedResult as a, ConvexCallPortTag as b, captureExceptionSync as c, TelemetryPortTag as d, redactTelemetryEvent as f, accountReadErrorFromCapxul as g, AccountReadPortTag as h, observationContextProps as i, toWei as j, version as k, detectAuthCacheAdapter as l, smartAccountErrorFromCapxul as m, postHogProductTelemetry as n, postHogFailureObservation as o, SmartAccountPortTag as p, normalizeBindingEmail as q, CAPXUL_SDK_EXPECTED_OUTCOME_EVENT as r, captureException as s, assembleCapxulClient as t, PostHogTelemetryLayer as u, IdentityPortTag as v, BootstrapPortTag as w, convexCallErrorFromCapxul as x, identityErrorFromCapxul as y, isSettingUpLifecycle as z };
9379
+ export { isClaimed as $, fingerprintPaymentIntent as A, OBSERVATION_CONTEXT_HEADER as B, ClockPortTag as C, AuthClientError as D, authClientPortFromPromiseAdapter as E, copyInvocationObservation as F, CAPXUL_FUNCTIONS as G, sanitizeObservationContext as H, readInvocationObservation as I, CAPXUL_PAYMENTS_V2_ADDRESS as J, BootstrapEnvelope as K, causeChain as L, fromWei as M, isSettingUpLifecycle as N, AuthClientPortTag as O, formatTraceparent as P, destination as Q, injectedWalletSigner as R, ClockError as S, bootstrapErrorFromCapxul as T, PAYMENT_DIRECTIONS as U, encodeObservationContextHeader as V, PAYMENT_STATUSES as W, BASE_SEPOLIA_CHAIN_ID as X, normalizeBindingEmail as Y, deriveCapxulSafeAddress as Z, wireChainId as _, observeFailedResult as a, ConvexCallPortTag as b, captureExceptionSync as c, TelemetryPortTag as d, isRestoring as et, redactTelemetryEvent as f, accountReadErrorFromCapxul as g, AccountReadPortTag as h, observationContextProps as i, toWei as j, version as k, detectAuthCacheAdapter as l, smartAccountErrorFromCapxul as m, postHogProductTelemetry as n, postHogFailureObservation as o, SmartAccountPortTag as p, EngineeringTelemetryBootstrapPolicy as q, CAPXUL_SDK_EXPECTED_OUTCOME_EVENT as r, captureException as s, assembleCapxulClient as t, PostHogTelemetryLayer as u, IdentityPortTag as v, BootstrapPortTag as w, convexCallErrorFromCapxul as x, identityErrorFromCapxul as y, signerFailure as z };