@capxul/mcp 4.2.0-rc.1 → 4.2.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.mjs CHANGED
@@ -852,6 +852,7 @@ const COUNTRY_CODE_RE = /^[A-Z]{2}$/;
852
852
  const ACCOUNT_ID_RE = /^account_[0-9A-Za-z]+$/;
853
853
  const PARTY_ID_RE$1 = /^party_[0-9A-Za-z]+$/;
854
854
  const APP_ID_RE = /^app_[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
855
+ const TX_HASH_RE = /^0x[0-9a-f]{64}$/i;
855
856
  const WEI_RE = /^[0-9]+$/;
856
857
  Math.floor(Number.MAX_SAFE_INTEGER / 1e3);
857
858
  function toAddress(raw) {
@@ -903,6 +904,10 @@ function toPublishableKey(raw) {
903
904
  if (typeof raw !== "string" || !PUBLISHABLE_KEY_PATTERN.test(raw)) throw Errors.invalidInput("publishableKey", invalidValueReason("must match cap_pk_(test|live) plus 32 Crockford base32 chars", raw));
904
905
  return raw;
905
906
  }
907
+ function toTxHash(raw) {
908
+ if (typeof raw !== "string" || !TX_HASH_RE.test(raw)) throw Errors.invalidInput("txHash", invalidValueReason("must be 0x + 64 hex chars", raw));
909
+ return raw.toLowerCase();
910
+ }
906
911
  function toEpochMs(raw) {
907
912
  assertSafeNonNegativeInteger(raw, "epochMs");
908
913
  return raw;
@@ -982,19 +987,108 @@ function invalidValueReason(prefix, raw) {
982
987
  //#region ../../packages/config/src/tokens.ts
983
988
  /** `TestUSDC` ("USDX") — Base Sepolia, 6 decimals, open `mint`. (Canon §1.) */
984
989
  const USDX_ADDRESS_BASE_SEPOLIA = "0xf09fcbb6df9f8f918e58f9c8ab15a76ade862b77";
990
+ const USDX_DEPLOYMENT_START_BLOCK = 39860173;
991
+ /**
992
+ * The ERC-20 `symbol()` the deployed `TestUSDC` contract returns
993
+ * (`packages/contracts/src/TestUSDC.sol:10`). It travels with the address and
994
+ * the decimals so a holdings row can never carry one token's address with
995
+ * another token's display symbol. This is the display symbol, not the
996
+ * currency: see `USDX_CURRENCY` below.
997
+ */
998
+ const USDX_SYMBOL = "USDX";
999
+ const SYNTHETIC_TEST_ASSET_SOURCE = "synthetic-test-liquidity";
985
1000
  const USDX_ASSET = {
986
1001
  assetId: assetIdFor(84532, USDX_ADDRESS_BASE_SEPOLIA),
987
1002
  chainId: toChainId(84532),
988
- symbol: "USDX",
1003
+ symbol: USDX_SYMBOL,
989
1004
  peg: toCurrencyCode("USD"),
990
1005
  tokenAddress: USDX_ADDRESS_BASE_SEPOLIA,
991
- deploymentStartBlock: 39860173,
992
- decimals: 6
1006
+ deploymentStartBlock: USDX_DEPLOYMENT_START_BLOCK,
1007
+ decimals: 6,
1008
+ source: "settlement"
993
1009
  };
994
- [{
1010
+ /**
1011
+ * The settlement tier: rows the exact-transfer path and the Movement scanner
1012
+ * admit, each carrying the legacy `currency` projection those readers expect.
1013
+ * Adding an owned test asset here would put candidate liquidity on the
1014
+ * money-write path, so M03's rows go to the candidate tier below instead.
1015
+ */
1016
+ const CONFIGURED_MONEY_ASSETS = [{
995
1017
  ...USDX_ASSET,
996
1018
  currency: USDX_ASSET.peg
997
- }].map((asset) => asset.tokenAddress.toLowerCase());
1019
+ }];
1020
+ /**
1021
+ * The candidate tier: five owned test assets, every field read back from Base
1022
+ * Sepolia after the deployment that created it (chain 84532, blocks
1023
+ * 46,465,978–46,465,982). Real contracts, authored liquidity, no settlement
1024
+ * admission — so rollback is removing consumers, never relabelling a
1025
+ * deployed address or deleting its history.
1026
+ *
1027
+ * `symbol` is the display string the owned contract returns. A
1028
+ * provider-supported USDC would be a different contract at a different
1029
+ * address returning the same symbol, which is why the resolvers below key on
1030
+ * `assetId`, or on chain plus address, and never on a symbol.
1031
+ */
1032
+ const SYNTHETIC_TEST_ASSETS = [
1033
+ {
1034
+ assetId: assetIdFor(84532, "0xb3d8566fb90f7df939f4bc08a09b19047117f549"),
1035
+ chainId: toChainId(84532),
1036
+ tokenAddress: "0xb3d8566fb90f7df939f4bc08a09b19047117f549",
1037
+ symbol: "USDC",
1038
+ decimals: 6,
1039
+ peg: toCurrencyCode("USD"),
1040
+ deploymentStartBlock: 46465978,
1041
+ deploymentTransaction: "0xa7fb8bb9d1fd1cc5fe2fc42fa4cdccace7742efae8ea99f091a283e5709343de",
1042
+ source: SYNTHETIC_TEST_ASSET_SOURCE
1043
+ },
1044
+ {
1045
+ assetId: assetIdFor(84532, "0x7ddcfb6aaffb9908c4c2db308b784c269eec8a01"),
1046
+ chainId: toChainId(84532),
1047
+ tokenAddress: "0x7ddcfb6aaffb9908c4c2db308b784c269eec8a01",
1048
+ symbol: "USDT",
1049
+ decimals: 6,
1050
+ peg: toCurrencyCode("USD"),
1051
+ deploymentStartBlock: 46465979,
1052
+ deploymentTransaction: "0xa17ad76fe8b24cdf1fbcff245c3eb022444710cf9fa7b5ee59818be654f4ae10",
1053
+ source: SYNTHETIC_TEST_ASSET_SOURCE
1054
+ },
1055
+ {
1056
+ assetId: assetIdFor(84532, "0x1d93d525f73453fe18eebf044e8a3954bfe3721e"),
1057
+ chainId: toChainId(84532),
1058
+ tokenAddress: "0x1d93d525f73453fe18eebf044e8a3954bfe3721e",
1059
+ symbol: "WETH",
1060
+ decimals: 18,
1061
+ peg: null,
1062
+ deploymentStartBlock: 46465980,
1063
+ deploymentTransaction: "0xcb9b2d024686fac93ec1243ccf02d3567fd531da46176115660cba2ba644b09d",
1064
+ source: SYNTHETIC_TEST_ASSET_SOURCE
1065
+ },
1066
+ {
1067
+ assetId: assetIdFor(84532, "0x8fe52c70aa9f7b6d74d8bb26eca33d87413cb624"),
1068
+ chainId: toChainId(84532),
1069
+ tokenAddress: "0x8fe52c70aa9f7b6d74d8bb26eca33d87413cb624",
1070
+ symbol: "WBTC",
1071
+ decimals: 8,
1072
+ peg: null,
1073
+ deploymentStartBlock: 46465981,
1074
+ deploymentTransaction: "0x728ba7b430ffd141f83d0ed5ce429d050049d7b097c936fd11e9c572d1243854",
1075
+ source: SYNTHETIC_TEST_ASSET_SOURCE
1076
+ },
1077
+ {
1078
+ assetId: assetIdFor(84532, "0x5865fe9787ac214feb5facaebaec06969ac0a9a3"),
1079
+ chainId: toChainId(84532),
1080
+ tokenAddress: "0x5865fe9787ac214feb5facaebaec06969ac0a9a3",
1081
+ symbol: "cNGN",
1082
+ decimals: 6,
1083
+ peg: toCurrencyCode("NGN"),
1084
+ deploymentStartBlock: 46465982,
1085
+ deploymentTransaction: "0xcedf254bcef57fc64189261a5ab1161bc4fde370e470933f627c4d8ddb5a2e26",
1086
+ source: SYNTHETIC_TEST_ASSET_SOURCE
1087
+ }
1088
+ ];
1089
+ toChainId(84532);
1090
+ [...CONFIGURED_MONEY_ASSETS, ...SYNTHETIC_TEST_ASSETS];
1091
+ CONFIGURED_MONEY_ASSETS.map((asset) => asset.tokenAddress.toLowerCase());
998
1092
  //#endregion
999
1093
  //#region ../../node_modules/.pnpm/abitype@1.2.3_typescript@7.0.2_zod@4.4.3/node_modules/abitype/dist/esm/regex.js
1000
1094
  function execTyped(regex, string) {
@@ -3738,6 +3832,12 @@ const USDX_BASE_SEPOLIA_TOKEN = {
3738
3832
  USDX_BASE_SEPOLIA_TOKEN.chainId;
3739
3833
  USDX_BASE_SEPOLIA_TOKEN.chainId;
3740
3834
  10n ** BigInt(6);
3835
+ /**
3836
+ * The bootstrap manage role. It administers people and roles, cannot spend,
3837
+ * and is not a signer of the Organization Safe; "Owner" implied the latter,
3838
+ * so the label is Admin (ruled 2026-09-06).
3839
+ */
3840
+ const ADMIN_ROLE_LABEL = "Admin";
3741
3841
  function normalizeOrgRoleLabel(label) {
3742
3842
  const normalized = label.trim().replace(/\s+/g, " ");
3743
3843
  if (normalized.length === 0) throw Errors.invalidInput("role.label", "must be a non-empty role label");
@@ -6788,6 +6888,8 @@ const CAPXUL_OPERATIONS = {
6788
6888
  emitAnnotationSaved: "activity.emitAnnotationSaved",
6789
6889
  get: "activity.get",
6790
6890
  list: "activity.list",
6891
+ /** The SDK's live Activity read over the indexer's SSE stream. */
6892
+ subscribe: "activity.subscribe",
6791
6893
  summary: "activity.summary"
6792
6894
  },
6793
6895
  addressBook: {
@@ -7271,6 +7373,17 @@ const AuthFailedProps = Schema.Struct({
7271
7373
  auth_type: OptionalString,
7272
7374
  reason: OptionalString
7273
7375
  });
7376
+ const IdentityRefusedProps = Schema.Struct({
7377
+ ...TelemetryEnvelopeProps,
7378
+ /** The refused identity event tag, for example CreateOrganization. */
7379
+ event: OptionalString,
7380
+ /** The machine's refusal code: WRONG_STATE, SUPERSEDED or STALE_EPOCH. */
7381
+ refusal_code: OptionalString,
7382
+ /** The machine slot the request targeted, for example identity:org. */
7383
+ slot: OptionalString,
7384
+ /** The machine state at refusal, for example authenticated:claiming. */
7385
+ state: OptionalString
7386
+ });
7274
7387
  const AuthSignedOutProps = Schema.Struct(TelemetryEnvelopeProps);
7275
7388
  const ProvisioningSafeCreatedProps = Schema.Struct({
7276
7389
  ...TelemetryEnvelopeProps,
@@ -7658,10 +7771,24 @@ const DepositSettledProps = Schema.Struct({
7658
7771
  });
7659
7772
  const PermissionMirrorVerificationProps = Schema.Struct({
7660
7773
  ...TelemetryEnvelopeProps,
7774
+ /** The RECEIPT verification outcome. What the mirror then did is separate. */
7661
7775
  outcome: Schema.String,
7662
7776
  reason: Schema.String,
7663
7777
  chain_id: Schema.Number,
7664
- retry_count: Schema.Number
7778
+ retry_count: Schema.Number,
7779
+ /**
7780
+ * #1960 R02, consumed by R03. A verified receipt is not an applied Permission:
7781
+ * these two optional fields let the producer say what the applying mutation
7782
+ * actually returned, and which command it was, without either fact rewriting
7783
+ * the receipt outcome above. Absent when application has not happened yet.
7784
+ */
7785
+ application_result: Schema.optional(Schema.Literals([
7786
+ "applied",
7787
+ "replayed",
7788
+ "conflicting_replay",
7789
+ "revision_mismatch"
7790
+ ])),
7791
+ command_id: OptionalString
7665
7792
  });
7666
7793
  const MovementScanWindowProps = Schema.Struct({
7667
7794
  ...TelemetryEnvelopeProps,
@@ -7707,6 +7834,10 @@ Schema.Struct({
7707
7834
  name: Schema.Literal("auth_failed"),
7708
7835
  props: AuthFailedProps
7709
7836
  });
7837
+ Schema.Struct({
7838
+ name: Schema.Literal("identity_refused"),
7839
+ props: IdentityRefusedProps
7840
+ });
7710
7841
  Schema.Struct({
7711
7842
  name: Schema.Literal("auth_signed_out"),
7712
7843
  props: AuthSignedOutProps
@@ -7887,6 +8018,10 @@ Schema.Struct({
7887
8018
  name: Schema.Literal("movement_scan_incident"),
7888
8019
  props: MovementScanIncidentProps
7889
8020
  });
8021
+ /** The one spelling of "whose scope did this happen in" across every surface. */
8022
+ const ScopeKindSchema = Schema.Literals(["account", "organization"]);
8023
+ const AccountKindSchema = Schema.Literals(["personalSafe", "orgTreasury"]);
8024
+ const OptionalReasonCode = Schema.optional(Schema.Literals(CAPXUL_ERROR_CODES));
7890
8025
  const ActivityReferenceProps = {
7891
8026
  reference_kind: Schema.Literals(["payment", "movement"]),
7892
8027
  reference_id: Schema.String
@@ -7917,8 +8052,8 @@ const ActivityFilterProps = {
7917
8052
  };
7918
8053
  const ActivityActionProps = {
7919
8054
  ...TelemetryEnvelopeProps,
7920
- scope_kind: Schema.Literals(["account", "organization"]),
7921
- reason_code: Schema.optional(Schema.Literals(CAPXUL_ERROR_CODES))
8055
+ scope_kind: ScopeKindSchema,
8056
+ reason_code: OptionalReasonCode
7922
8057
  };
7923
8058
  Schema.Struct({
7924
8059
  name: Schema.Literal("contact_relationship_changed"),
@@ -7930,7 +8065,7 @@ Schema.Struct({
7930
8065
  "hidden",
7931
8066
  "restored"
7932
8067
  ]),
7933
- scope_kind: Schema.Literals(["account", "organization"]),
8068
+ scope_kind: ScopeKindSchema,
7934
8069
  scope_id: Schema.String,
7935
8070
  owner_party_id: Schema.String,
7936
8071
  party_id: Schema.String,
@@ -7946,9 +8081,9 @@ Schema.Struct({
7946
8081
  });
7947
8082
  const ContactActionProps = {
7948
8083
  ...TelemetryEnvelopeProps,
7949
- scope_kind: Schema.Literals(["account", "organization"]),
8084
+ scope_kind: ScopeKindSchema,
7950
8085
  party_id: OptionalString,
7951
- reason_code: Schema.optional(Schema.Literals(CAPXUL_ERROR_CODES))
8086
+ reason_code: OptionalReasonCode
7952
8087
  };
7953
8088
  Schema.Struct({
7954
8089
  name: Schema.Literal("ui_contact_action_completed"),
@@ -7975,7 +8110,7 @@ Schema.Struct({
7975
8110
  props: Schema.Struct({
7976
8111
  ...TelemetryEnvelopeProps,
7977
8112
  ...ActivityReferenceProps,
7978
- scope_kind: Schema.Literals(["account", "organization"]),
8113
+ scope_kind: ScopeKindSchema,
7979
8114
  scope_id: Schema.String,
7980
8115
  occurred_at: Schema.Number
7981
8116
  })
@@ -8030,6 +8165,193 @@ Schema.Struct({
8030
8165
  })
8031
8166
  ])
8032
8167
  });
8168
+ /**
8169
+ * Reliability closeout (#1960 R02) — the shape every explicit UI observation
8170
+ * below shares. `scope_kind` says whose surface the person was looking at,
8171
+ * `organization_id` is the verified Organization the producer resolved (absent
8172
+ * on a personal action), and `reason_code` is a catalog error code, never copy.
8173
+ */
8174
+ const UiStepProps = {
8175
+ ...TelemetryEnvelopeProps,
8176
+ scope_kind: ScopeKindSchema,
8177
+ organization_id: OptionalOrgId,
8178
+ reason_code: OptionalReasonCode
8179
+ };
8180
+ const AccessRecoveryCompletedProps = Schema.Union([Schema.Struct({
8181
+ ...TelemetryEnvelopeProps,
8182
+ recovery: Schema.Literal("session_restoration"),
8183
+ outcome: Schema.Literals([
8184
+ "restored",
8185
+ "absent",
8186
+ "failed"
8187
+ ]),
8188
+ reason_code: OptionalReasonCode,
8189
+ organization_id: OptionalOrgId
8190
+ }), Schema.Struct({
8191
+ ...TelemetryEnvelopeProps,
8192
+ recovery: Schema.Literal("signer_readiness"),
8193
+ outcome: Schema.Literals(["ready", "unavailable"]),
8194
+ reason_code: OptionalReasonCode,
8195
+ organization_id: OptionalOrgId
8196
+ })]);
8197
+ Schema.Struct({
8198
+ name: Schema.Literal("access_recovery_completed"),
8199
+ props: AccessRecoveryCompletedProps
8200
+ });
8201
+ Schema.Struct({
8202
+ name: Schema.Literal("ui_access_step_completed"),
8203
+ props: Schema.Struct({
8204
+ ...UiStepProps,
8205
+ step: Schema.Literals([
8206
+ "dashboard_granted",
8207
+ "redirect_completed",
8208
+ "gate_error_displayed",
8209
+ "retry_selected",
8210
+ "capability_refusal_displayed",
8211
+ "signer_refusal_displayed"
8212
+ ]),
8213
+ capability: Schema.optional(Schema.Literals(["spend", "managePeople"])),
8214
+ probe: Schema.optional(Schema.Literals([
8215
+ "session",
8216
+ "membership",
8217
+ "lifecycle"
8218
+ ])),
8219
+ reason: Schema.optional(Schema.Literals([
8220
+ "loading",
8221
+ "no-permission",
8222
+ "org-unavailable"
8223
+ ]))
8224
+ })
8225
+ });
8226
+ Schema.Struct({
8227
+ name: Schema.Literal("org_invite_progressed"),
8228
+ props: Schema.Struct({
8229
+ ...TelemetryEnvelopeProps,
8230
+ organization_id: OrgIdTelemetrySchema,
8231
+ progress: Schema.Literals([
8232
+ "account_ready",
8233
+ "permission_applied",
8234
+ "membership_activated",
8235
+ "revoked"
8236
+ ]),
8237
+ /** The invited Party. The initiating actor stays on the envelope's identity. */
8238
+ member_party_id: Schema.String,
8239
+ occurred_at: Schema.Number
8240
+ })
8241
+ });
8242
+ Schema.Struct({
8243
+ name: Schema.Literal("invoice_issued"),
8244
+ props: Schema.Struct({
8245
+ ...TelemetryEnvelopeProps,
8246
+ request_id: Schema.String,
8247
+ issuer_scope_kind: ScopeKindSchema,
8248
+ issuer_scope_id: Schema.String,
8249
+ payer_party_id: OptionalString,
8250
+ occurred_at: Schema.Number
8251
+ })
8252
+ });
8253
+ Schema.Struct({
8254
+ name: Schema.Literal("invoice_request_transitioned"),
8255
+ props: Schema.Struct({
8256
+ ...TelemetryEnvelopeProps,
8257
+ request_id: Schema.String,
8258
+ transition: Schema.Literals([
8259
+ "approval_prepared",
8260
+ "declined",
8261
+ "cancelled"
8262
+ ]),
8263
+ actor_scope_kind: ScopeKindSchema,
8264
+ actor_scope_id: Schema.String,
8265
+ occurred_at: Schema.Number
8266
+ })
8267
+ });
8268
+ Schema.Struct({
8269
+ name: Schema.Literal("ui_invoice_step_completed"),
8270
+ props: Schema.Struct({
8271
+ ...UiStepProps,
8272
+ step: Schema.Literals([
8273
+ "opened",
8274
+ "previewed",
8275
+ "dismissed",
8276
+ "submitted",
8277
+ "result_displayed",
8278
+ "refusal_displayed",
8279
+ "retry_selected"
8280
+ ]),
8281
+ request_id: OptionalString
8282
+ })
8283
+ });
8284
+ Schema.Struct({
8285
+ name: Schema.Literal("ui_treasury_step_completed"),
8286
+ props: Schema.Struct({
8287
+ ...UiStepProps,
8288
+ step: Schema.Literals([
8289
+ "balance_displayed",
8290
+ "read_refusal_displayed",
8291
+ "retry_selected",
8292
+ "recovery_completed"
8293
+ ]),
8294
+ account_kind: Schema.optional(AccountKindSchema)
8295
+ })
8296
+ });
8297
+ Schema.Struct({
8298
+ name: Schema.Literal("ui_receive_step_completed"),
8299
+ props: Schema.Struct({
8300
+ ...UiStepProps,
8301
+ step: Schema.Literals([
8302
+ "instructions_displayed",
8303
+ "address_copied",
8304
+ "copy_failed",
8305
+ "refusal_displayed",
8306
+ "retry_selected"
8307
+ ]),
8308
+ account_kind: Schema.optional(AccountKindSchema)
8309
+ })
8310
+ });
8311
+ Schema.Struct({
8312
+ name: Schema.Literal("payroll_group_changed"),
8313
+ props: Schema.Struct({
8314
+ ...TelemetryEnvelopeProps,
8315
+ organization_id: OrgIdTelemetrySchema,
8316
+ change: Schema.Literals([
8317
+ "created",
8318
+ "updated",
8319
+ "deleted"
8320
+ ]),
8321
+ group_id: Schema.String,
8322
+ member_count: Schema.Number,
8323
+ occurred_at: Schema.Number
8324
+ })
8325
+ });
8326
+ Schema.Struct({
8327
+ name: Schema.Literal("payroll_run_transitioned"),
8328
+ props: Schema.Struct({
8329
+ ...TelemetryEnvelopeProps,
8330
+ organization_id: OrgIdTelemetrySchema,
8331
+ transition: Schema.Literals([
8332
+ "prepared",
8333
+ "authorized",
8334
+ "settled"
8335
+ ]),
8336
+ run_id: Schema.String,
8337
+ payment_count: Schema.optional(Schema.Number),
8338
+ occurred_at: Schema.Number
8339
+ })
8340
+ });
8341
+ Schema.Struct({
8342
+ name: Schema.Literal("ui_payroll_action_completed"),
8343
+ props: Schema.Struct({
8344
+ ...UiStepProps,
8345
+ action: Schema.Literals([
8346
+ "opened",
8347
+ "refusal_displayed",
8348
+ "recovery_completed",
8349
+ "cancelled",
8350
+ "submitted_displayed"
8351
+ ]),
8352
+ run_id: OptionalString
8353
+ })
8354
+ });
8033
8355
  function redactTelemetryProps(name, props, options = {}) {
8034
8356
  if (props === void 0) return void 0;
8035
8357
  const clone = cloneProps$1(props);
@@ -8325,6 +8647,10 @@ const BootstrapEnvelope = Schema.Struct({
8325
8647
  siteBaseUrl: Schema.String,
8326
8648
  openfortPublishableKey: Schema.String,
8327
8649
  shieldPublishableKey: Schema.String,
8650
+ /** Which Openfort third-party auth provider the signer presents; absent means better-auth. */
8651
+ openfortAuthProvider: Schema.optional(Schema.Literals(["better-auth", "oidc"])),
8652
+ /** Origin of the Ponder indexer the SDK reads directly; absent means no indexer reads. */
8653
+ indexerUrl: Schema.optional(Schema.String),
8328
8654
  engineeringTelemetry: Schema.optional(EngineeringTelemetryBootstrapPolicy)
8329
8655
  })
8330
8656
  });
@@ -8399,6 +8725,7 @@ const CAPXUL_FUNCTIONS = {
8399
8725
  prepareOrganizationPaymentExecution: "moneyExecution/paymentCommandActions:prepareOrganizationPaymentExecution",
8400
8726
  submitPaymentCommandExecution: "moneyExecution/paymentCommandActions:submitPaymentCommandExecution"
8401
8727
  },
8728
+ "moneyExecution/providerSendWitness": { read: "moneyExecution/providerSendWitness:read" },
8402
8729
  media: {
8403
8730
  generateUploadUrl: "media:generateUploadUrl",
8404
8731
  setOrgLogo: "media:setOrgLogo",
@@ -8458,6 +8785,11 @@ const CAPXUL_FUNCTIONS = {
8458
8785
  loadByAuthUserId: "smartAccount/queries:loadByAuthUserId",
8459
8786
  loadBySmartAccountAddress: "smartAccount/queries:loadBySmartAccountAddress"
8460
8787
  },
8788
+ e2eControls: {
8789
+ holdUserOperationReceipt: "e2eControls:holdUserOperationReceipt",
8790
+ isUserOperationReceiptHeld: "e2eControls:isUserOperationReceiptHeld",
8791
+ releaseUserOperationReceipt: "e2eControls:releaseUserOperationReceipt"
8792
+ },
8461
8793
  system: { health: "system:health" }
8462
8794
  };
8463
8795
  //#endregion
@@ -12046,7 +12378,7 @@ const moneyExecutionContract = {
12046
12378
  };
12047
12379
  //#endregion
12048
12380
  //#region ../../packages/sdk/package.json
12049
- var version$1 = "4.2.0-rc.1";
12381
+ var version$1 = "4.2.0-rc.10";
12050
12382
  //#endregion
12051
12383
  //#region ../../packages/sdk/src/telemetry/exception-projection.ts
12052
12384
  /** Fixed fallback for failures that have no safe message. */
@@ -12143,6 +12475,17 @@ function observeFailedResult(result, adapter, operation, origin) {
12143
12475
  return result;
12144
12476
  }
12145
12477
  /**
12478
+ * @internal Reports a failure that can never become a method result.
12479
+ *
12480
+ * A reactive stream is torn down after its call already returned, so nothing
12481
+ * downstream observes it. `captureException` is the right kind: the caller did
12482
+ * not ask for the end, so it is not an expected product outcome.
12483
+ */
12484
+ function observeStreamFailure(adapter, operation, cause) {
12485
+ if (adapter === void 0) return;
12486
+ report(adapter, "exception", operation, cause, resolveAdapterSnapshot(adapter));
12487
+ }
12488
+ /**
12146
12489
  * One failure, one event. The identity machine reports a failed transition
12147
12490
  * first; when the same `CapxulError` then surfaces as a public method result
12148
12491
  * (directly or down its `cause` chain), the boundary drops that second report.
@@ -12219,6 +12562,34 @@ function ignoreDeliveryFailure(delivery) {
12219
12562
  Promise.resolve(delivery).catch(() => void 0);
12220
12563
  } catch {}
12221
12564
  }
12565
+ /**
12566
+ * Fold a caller-captured attempt identity into the host's resolved context.
12567
+ *
12568
+ * The host's `resolveContext` runs at the moment an SDK method is entered, so a
12569
+ * host that mints a correlation per resolve gives every operation of one user
12570
+ * attempt a different identity — and a user or Organization switch between the
12571
+ * click and the reply relabels an action that already started. When the caller
12572
+ * captured `correlation_id`/`journey_id` BEFORE the action started, that is the
12573
+ * attempt, and it replaces what the resolver returned for this one call. The
12574
+ * result is what the SDK span/Log, the failure envelope and the backend carrier
12575
+ * all read, so the three agree by construction rather than by convention.
12576
+ *
12577
+ * A caller that captured nothing gets the resolver's context unchanged, so
12578
+ * automatic reads keep their own invocation context.
12579
+ */
12580
+ function withCapturedAttemptContext(context, controls) {
12581
+ const correlationId = controls?.correlation_id;
12582
+ const journeyId = controls?.journey_id;
12583
+ if (correlationId === void 0 && journeyId === void 0) return context;
12584
+ const captured = sanitizeObservationContext({
12585
+ ...correlationId === void 0 ? {} : { correlationId },
12586
+ ...journeyId === void 0 ? {} : { journeyId }
12587
+ });
12588
+ return captured === void 0 ? context : {
12589
+ ...context,
12590
+ ...captured
12591
+ };
12592
+ }
12222
12593
  const MAX_EVIDENCE_TEXT = 4e3;
12223
12594
  const MAX_CAUSE_DEPTH = 8;
12224
12595
  function evidenceText(value) {
@@ -14445,7 +14816,8 @@ var BetterAuthBrowserAdapter = class {
14445
14816
  try {
14446
14817
  const res = await this.fetchImpl(this.url("/api/auth/get-session"), withSignal$1({
14447
14818
  method: "GET",
14448
- credentials: "include"
14819
+ credentials: "include",
14820
+ cache: "no-store"
14449
14821
  }, options?.signal));
14450
14822
  if (options?.signal?.aborted) return {
14451
14823
  ok: false,
@@ -14517,7 +14889,8 @@ var BetterAuthBrowserAdapter = class {
14517
14889
  try {
14518
14890
  const res = await this.fetchImpl(this.url("/api/auth/convex/token"), withSignal$1({
14519
14891
  method: "GET",
14520
- credentials: "include"
14892
+ credentials: "include",
14893
+ cache: "no-store"
14521
14894
  }, options?.signal));
14522
14895
  if (options?.signal?.aborted) return {
14523
14896
  ok: false,
@@ -15030,7 +15403,7 @@ function isTransientBootstrapFailure(error) {
15030
15403
  const status = error.details?.httpStatus;
15031
15404
  return typeof status === "number" && isTransientHttpStatus(status);
15032
15405
  }
15033
- async function safeText(res) {
15406
+ async function safeText$1(res) {
15034
15407
  try {
15035
15408
  return await res.text();
15036
15409
  } catch {
@@ -15103,6 +15476,8 @@ var HttpBootstrapAdapter = class {
15103
15476
  siteBaseUrl: normalizeRuntimeUrl("siteBaseUrl", decodedState.siteBaseUrl),
15104
15477
  openfortPublishableKey: decodedState.openfortPublishableKey,
15105
15478
  shieldPublishableKey: decodedState.shieldPublishableKey,
15479
+ ...decodedState.openfortAuthProvider === void 0 ? {} : { openfortAuthProvider: decodedState.openfortAuthProvider },
15480
+ ...decodedState.indexerUrl === void 0 ? {} : { indexerUrl: decodedState.indexerUrl },
15106
15481
  ...decodedEngineeringTelemetry !== void 0 && Result.isSuccess(decodedEngineeringTelemetry) ? { engineeringTelemetry: decodedEngineeringTelemetry.success } : {}
15107
15482
  };
15108
15483
  },
@@ -15111,7 +15486,7 @@ var HttpBootstrapAdapter = class {
15111
15486
  return bootstrapErrorFromCapxul("malformedBody", Errors.providerError("convex", "bootstrap", cause instanceof Error ? cause : new Error(String(cause))));
15112
15487
  }
15113
15488
  });
15114
- return Effect.promise(() => safeText(res)).pipe(Effect.flatMap((body) => {
15489
+ return Effect.promise(() => safeText$1(res)).pipe(Effect.flatMap((body) => {
15115
15490
  if (res.status === 401 || body.startsWith("NOT_AUTHENTICATED")) return Effect.fail(bootstrapErrorFromCapxul("notAuthenticated", Errors.notAuthenticated()));
15116
15491
  if (res.status === 400 || body.startsWith("INVALID_INPUT")) return Effect.fail(bootstrapErrorFromCapxul("invalidInput", Errors.invalidInput("publishableKey", "rejected by bootstrap")));
15117
15492
  const responseBody = body.slice(0, 300);
@@ -18294,6 +18669,12 @@ function makeConnectionId() {
18294
18669
  }
18295
18670
  //#endregion
18296
18671
  //#region ../../packages/sdk/src/adapters/convex-call/ConvexCallAdapter.ts
18672
+ /**
18673
+ * A socket that has not emitted `close` within this window is not going to.
18674
+ * ponytail: one fixed bound; `closeTimeoutMs` is the knob if a slow runtime
18675
+ * ever needs a different one.
18676
+ */
18677
+ const DEFAULT_CLOSE_TIMEOUT_MS = 5e3;
18297
18678
  /** Exact floor-first allowlist; every additional handler must migrate its validator first. */
18298
18679
  const OBSERVED_CONVEX_ACTIONS = /* @__PURE__ */ new Set([
18299
18680
  "payroll/actions:authorizeRun",
@@ -18362,7 +18743,9 @@ var ConvexCallAdapter = class {
18362
18743
  #applicationId;
18363
18744
  #observation;
18364
18745
  #connectionMonitor;
18746
+ #closeTimeoutMs;
18365
18747
  constructor(deps) {
18748
+ this.#closeTimeoutMs = deps.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS;
18366
18749
  this.#connectionMonitor = new ConvexConnectionMonitor();
18367
18750
  const webSocketConstructor = this.#connectionMonitor.observedWebSocketConstructor();
18368
18751
  this.#client = deps.client ?? new ConvexClient(deps.convexUrl, webSocketConstructor === void 0 ? {} : { webSocketConstructor });
@@ -18461,11 +18844,33 @@ var ConvexCallAdapter = class {
18461
18844
  callback({ status: "loading" });
18462
18845
  })));
18463
18846
  }
18847
+ /**
18848
+ * Teardown always completes. `ConvexClient.close()` resolves only when the
18849
+ * socket emits `close`, and `WebSocketManager.close()` in the `connecting`
18850
+ * state arms `ws.onopen = () => ws.close()` without ever closing the socket
18851
+ * itself — so a handshake that stalls right after a server-initiated close
18852
+ * (code 1012, which is what a Convex deploy sends) leaves that promise
18853
+ * pending for as long as the page lives. Convex marks the client closed and
18854
+ * terminates the socket manager synchronously before returning it, so
18855
+ * abandoning it drops nothing. A rejection is dropped for the same reason —
18856
+ * the layer release turns it into a defect that fails the whole scope close,
18857
+ * and teardown has no caller who can act on it.
18858
+ */
18464
18859
  async close() {
18465
18860
  this.#connectionMonitor.close();
18466
- await this.#client.close();
18861
+ await settledWithin(this.#client.close(), this.#closeTimeoutMs);
18467
18862
  }
18468
18863
  };
18864
+ function settledWithin(promise, timeoutMs) {
18865
+ return new Promise((resolve) => {
18866
+ const timer = setTimeout(resolve, timeoutMs);
18867
+ const finish = () => {
18868
+ clearTimeout(timer);
18869
+ resolve();
18870
+ };
18871
+ promise.then(finish, finish);
18872
+ });
18873
+ }
18469
18874
  function ConvexCallLayer(deps) {
18470
18875
  return Layer.effect(ConvexCallPortTag, Effect.acquireRelease(Effect.sync(() => new ConvexCallAdapter(deps)), (adapter) => Effect.promise(() => adapter.close()).pipe(Effect.orDie)));
18471
18876
  }
@@ -19418,6 +19823,32 @@ var ConsoleDiagnosticAdapter = class {
19418
19823
  }
19419
19824
  };
19420
19825
  //#endregion
19826
+ //#region ../../packages/sdk/src/adapters/diagnostic/EffectLogDiagnosticAdapter.ts
19827
+ /**
19828
+ * Diagnostic breadcrumbs as SDK log records. The signer's readiness cycle
19829
+ * traces (`openfort.*`) used to reach only the browser console; through this
19830
+ * adapter they run in the client's own Effect context, so the engineering
19831
+ * telemetry layer ships them to PostHog Logs beside `identity.transition`.
19832
+ * Logging never throws back into the cycle that emitted it.
19833
+ */
19834
+ var EffectLogDiagnosticAdapter = class {
19835
+ #runPromise;
19836
+ #console;
19837
+ constructor(context, consoleFallback) {
19838
+ this.#runPromise = Effect.runPromiseWith(context);
19839
+ this.#console = consoleFallback;
19840
+ }
19841
+ trace(scope, detail) {
19842
+ this.#console?.trace(scope, detail);
19843
+ try {
19844
+ this.#runPromise(Effect.logInfo(scope).pipe(Effect.annotateLogs({
19845
+ ...detail,
19846
+ diagnostic_scope: scope
19847
+ }), Effect.catchCause(() => Effect.void))).catch(() => void 0);
19848
+ } catch {}
19849
+ }
19850
+ };
19851
+ //#endregion
19421
19852
  //#region ../../node_modules/.pnpm/axios@1.17.0/node_modules/axios/lib/helpers/bind.js
19422
19853
  /**
19423
19854
  * Create a bound version of a function with a specified `this` context
@@ -42496,15 +42927,35 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42496
42927
  });
42497
42928
  throw failOpenfort("configure", "no-secure-context", /* @__PURE__ */ new Error("Web Crypto unavailable: browser is not a secure context"));
42498
42929
  }
42499
- function betterAuthSessionUrl() {
42500
- return `${authBaseUrl}/get-session`;
42930
+ const authProvider = bootstrap.openfortAuthProvider ?? "better-auth";
42931
+ function accessTokenUrl() {
42932
+ return authProvider === "oidc" ? `${authBaseUrl}/convex/token` : `${authBaseUrl}/get-session`;
42501
42933
  }
42502
42934
  function encryptionSessionUrl() {
42503
42935
  return `${authBaseUrl}/encryption-session`;
42504
42936
  }
42937
+ let cycleStartedAt = null;
42938
+ let stepStartedAt = 0;
42939
+ let tokenCalls = 0;
42940
+ const sinceCycleStart = () => cycleStartedAt === null ? void 0 : Date.now() - cycleStartedAt;
42941
+ const step = (name, extra = {}) => {
42942
+ const now = Date.now();
42943
+ diagnostic?.trace("openfort.step", {
42944
+ step: name,
42945
+ duration_ms: now - stepStartedAt,
42946
+ elapsed_ms: sinceCycleStart(),
42947
+ ...extra
42948
+ });
42949
+ stepStartedAt = now;
42950
+ };
42505
42951
  async function fetchBetterAuthAccessToken() {
42952
+ tokenCalls += 1;
42953
+ const tokenStartedAt = Date.now();
42506
42954
  try {
42507
- const response = await fetch(betterAuthSessionUrl(), { credentials: "include" });
42955
+ const response = await fetch(accessTokenUrl(), {
42956
+ credentials: "include",
42957
+ cache: "no-store"
42958
+ });
42508
42959
  if (!response.ok) {
42509
42960
  diagnostic?.trace("openfort.token", {
42510
42961
  ok: false,
@@ -42514,7 +42965,8 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42514
42965
  });
42515
42966
  return null;
42516
42967
  }
42517
- const token = (await response.json()).session?.token?.trim();
42968
+ const body = await response.json();
42969
+ const token = (authProvider === "oidc" ? body.token : body.session?.token)?.trim();
42518
42970
  if (token === void 0 || token.length === 0) {
42519
42971
  diagnostic?.trace("openfort.token", {
42520
42972
  ok: false,
@@ -42525,7 +42977,11 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42525
42977
  }
42526
42978
  diagnostic?.trace("openfort.token", {
42527
42979
  ok: true,
42528
- tokenPresent: true
42980
+ tokenPresent: true,
42981
+ provider: authProvider,
42982
+ call: tokenCalls,
42983
+ duration_ms: Date.now() - tokenStartedAt,
42984
+ elapsed_ms: sinceCycleStart()
42529
42985
  });
42530
42986
  return token;
42531
42987
  } catch (cause) {
@@ -42541,7 +42997,7 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42541
42997
  baseConfiguration: { publishableKey: bootstrap.openfortPublishableKey },
42542
42998
  shieldConfiguration: { shieldPublishableKey: bootstrap.shieldPublishableKey },
42543
42999
  thirdPartyAuth: {
42544
- provider: o$13.BETTER_AUTH,
43000
+ provider: authProvider === "oidc" ? o$13.OIDC : o$13.BETTER_AUTH,
42545
43001
  getAccessToken: fetchBetterAuthAccessToken
42546
43002
  }
42547
43003
  });
@@ -42581,10 +43037,16 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42581
43037
  let walletReadyPromise = null;
42582
43038
  function startWalletReady() {
42583
43039
  return (async () => {
43040
+ const startedAt = Date.now();
43041
+ cycleStartedAt = startedAt;
43042
+ stepStartedAt = startedAt;
43043
+ tokenCalls = 0;
42584
43044
  if (isInsecureBrowserContext()) failNoSecureContext();
42585
43045
  await openfort.waitForInitialization();
43046
+ step("initialize");
42586
43047
  const accessToken = await fetchBetterAuthAccessToken();
42587
43048
  if (accessToken === null) throw openfortProviderError("token", /* @__PURE__ */ new Error("Better Auth access token unavailable for Openfort"));
43049
+ step("token");
42588
43050
  let encryptionResponse;
42589
43051
  try {
42590
43052
  encryptionResponse = await fetch(encryptionSessionUrl(), {
@@ -42627,10 +43089,12 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42627
43089
  ok: true,
42628
43090
  httpStatus: encryptionResponse.status
42629
43091
  });
43092
+ step("encryptionSession", { httpStatus: encryptionResponse.status });
42630
43093
  let embeddedState;
42631
43094
  try {
42632
43095
  embeddedState = await openfort.embeddedWallet.getEmbeddedState();
42633
43096
  diagnostic?.trace("openfort.embeddedState", { state: embeddedState });
43097
+ step("embeddedState", { state: embeddedState });
42634
43098
  } catch (cause) {
42635
43099
  diagnostic?.trace("openfort.embeddedState", {
42636
43100
  ok: false,
@@ -42644,6 +43108,7 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42644
43108
  try {
42645
43109
  await configureEmbeddedWallet(encryptionBody.sessionId);
42646
43110
  diagnostic?.trace("openfort.configure", { ok: true });
43111
+ step("configure");
42647
43112
  } catch (cause) {
42648
43113
  const error = openfortProviderError("configure", cause);
42649
43114
  diagnostic?.trace("openfort.configure", {
@@ -42656,6 +43121,7 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42656
43121
  try {
42657
43122
  await openfort.embeddedWallet.get();
42658
43123
  diagnostic?.trace("openfort.get", { ok: true });
43124
+ step("get");
42659
43125
  } catch (cause) {
42660
43126
  if (!isStaleUserSignal(cause)) {
42661
43127
  diagnostic?.trace("openfort.get", {
@@ -42669,7 +43135,13 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42669
43135
  failure_mode: "stale-openfort-cache"
42670
43136
  });
42671
43137
  await healStaleOpenfortCache(encryptionBody.sessionId);
43138
+ step("healStaleCache");
42672
43139
  }
43140
+ step("walletReady", {
43141
+ ok: true,
43142
+ total_ms: Date.now() - startedAt,
43143
+ token_calls: tokenCalls
43144
+ });
42673
43145
  })();
42674
43146
  }
42675
43147
  async function ensureOpenfortWalletReady() {
@@ -42752,9 +43224,13 @@ function createOpenfortBrowserSignerFromBootstrap(bootstrap, options = {}) {
42752
43224
  statusStore,
42753
43225
  ensureWalletReady: ensureOpenfortWalletReady,
42754
43226
  getAddress: async () => {
43227
+ const addressStartedAt = Date.now();
42755
43228
  try {
42756
43229
  const address = await signer.getAddress();
42757
- diagnostic?.trace("openfort.address", { ok: true });
43230
+ diagnostic?.trace("openfort.address", {
43231
+ ok: true,
43232
+ duration_ms: Date.now() - addressStartedAt
43233
+ });
42758
43234
  return address;
42759
43235
  } catch (cause) {
42760
43236
  diagnostic?.trace("openfort.address", {
@@ -43856,14 +44332,66 @@ function organizationWrongState(currentState, validStates) {
43856
44332
  function requestCancelled(options) {
43857
44333
  return options?.signal?.aborted === true;
43858
44334
  }
44335
+ function accountInFlight(state) {
44336
+ return state.phase === "authenticated" && (state.account.at === "deriving" || state.account.at === "claiming");
44337
+ }
44338
+ function settledAccount(deps, options) {
44339
+ return new Promise((resolve) => {
44340
+ let done = false;
44341
+ let unsubscribe = null;
44342
+ const onAbort = () => finish({
44343
+ ok: false,
44344
+ error: Errors.cancelled({ operation: CAPXUL_OPERATIONS.onboarding.completeOrganization })
44345
+ });
44346
+ const finish = (result) => {
44347
+ if (done) return;
44348
+ done = true;
44349
+ unsubscribe?.();
44350
+ options?.signal?.removeEventListener("abort", onAbort);
44351
+ resolve(result);
44352
+ };
44353
+ if (options?.signal?.aborted) {
44354
+ onAbort();
44355
+ return;
44356
+ }
44357
+ options?.signal?.addEventListener("abort", onAbort, { once: true });
44358
+ const stop = deps.subscribeIdentity((state) => {
44359
+ if (!accountInFlight(state)) finish({
44360
+ ok: true,
44361
+ value: state
44362
+ });
44363
+ });
44364
+ if (done) {
44365
+ stop();
44366
+ return;
44367
+ }
44368
+ unsubscribe = stop;
44369
+ const current = deps.snapshotIdentity();
44370
+ if (!accountInFlight(current)) finish({
44371
+ ok: true,
44372
+ value: current
44373
+ });
44374
+ });
44375
+ }
43859
44376
  async function reachClaimedAccount(deps, options) {
43860
44377
  let state = deps.snapshotIdentity();
44378
+ if (accountInFlight(state)) {
44379
+ const settled = await settledAccount(deps, options);
44380
+ if (!settled.ok) return settled;
44381
+ state = settled.value;
44382
+ }
43861
44383
  if (state.phase !== "authenticated" || state.account.at === "unknown") {
43862
44384
  const ensured = await deps.sendIdentity({ _tag: "EnsureAccount" }, options);
43863
44385
  if (!ensured.ok) return ensured;
43864
44386
  state = ensured.value;
43865
44387
  }
43866
44388
  if (state.phase !== "authenticated") return organizationWrongState(state.phase, ["authenticated:claimed"]);
44389
+ if (accountInFlight(state)) {
44390
+ const settled = await settledAccount(deps, options);
44391
+ if (!settled.ok) return settled;
44392
+ state = settled.value;
44393
+ if (state.phase !== "authenticated") return organizationWrongState(state.phase, ["authenticated:claimed"]);
44394
+ }
43867
44395
  if (state.account.at !== "claimed") {
43868
44396
  const event = state.account.at === "failed" ? { _tag: "RetryAccount" } : state.account.at === "counterfactual" ? { _tag: "ClaimAccount" } : { _tag: "EnsureAccount" };
43869
44397
  const claimed = await deps.sendIdentity(event, options);
@@ -44215,6 +44743,25 @@ const permissionContract = { read: makeFunctionReference(CAPXUL_FUNCTIONS["permi
44215
44743
  function isAborted(signal) {
44216
44744
  return signal?.aborted === true;
44217
44745
  }
44746
+ /**
44747
+ * One owning operation per public Permission method. The compound command
44748
+ * (prepare, equality checks, sign, submit) keeps owning its own cancellation;
44749
+ * the observed runner around it is what gives the attempt its
44750
+ * `capxul_sdk_operation` record, its span and its failure capture, so a signer
44751
+ * refusal or an unexpected provider error joins to the operation like every
44752
+ * other public surface.
44753
+ */
44754
+ function observed(deps, operation, options, run) {
44755
+ const controls = deps.invocationControls?.(options) ?? options;
44756
+ return runCapxulEffect(Effect.gen(function* () {
44757
+ if (controls?.signal?.aborted === true) return yield* Effect.fail(Errors.cancelled({ operation }));
44758
+ const result = yield* Effect.tryPromise({
44759
+ try: () => run(controls?.signal),
44760
+ catch: (cause) => cause instanceof CapxulError ? cause : Errors.unknown(cause)
44761
+ });
44762
+ return yield* result.ok ? Effect.succeed(result.value) : Effect.fail(result.error);
44763
+ }), observationOnlyControls(controls), operation, deps.runPromise);
44764
+ }
44218
44765
  async function execute(deps, orgId, command, signal) {
44219
44766
  if (isAborted(signal)) return {
44220
44767
  ok: false,
@@ -44274,36 +44821,37 @@ async function execute(deps, orgId, command, signal) {
44274
44821
  }
44275
44822
  function makePermissionMethods(deps, orgId) {
44276
44823
  const reads = deps.permissionFunctions ?? permissionContract;
44824
+ const ops = CAPXUL_OPERATIONS.org.permissions;
44277
44825
  return {
44278
- create: (input, options) => execute(deps, orgId, {
44826
+ create: (input, options) => observed(deps, ops.create, options, (signal) => execute(deps, orgId, {
44279
44827
  operation: "create",
44280
44828
  ...input
44281
- }, options?.signal),
44282
- change: (input, options) => execute(deps, orgId, {
44829
+ }, signal)),
44830
+ change: (input, options) => observed(deps, ops.change, options, (signal) => execute(deps, orgId, {
44283
44831
  operation: "change",
44284
44832
  ...input
44285
- }, options?.signal),
44286
- assign: (input, options) => execute(deps, orgId, {
44833
+ }, signal)),
44834
+ assign: (input, options) => observed(deps, ops.assign, options, (signal) => execute(deps, orgId, {
44287
44835
  operation: "assign",
44288
44836
  ...input
44289
- }, options?.signal),
44290
- revoke: (input, options) => execute(deps, orgId, {
44837
+ }, signal)),
44838
+ revoke: (input, options) => observed(deps, ops.revoke, options, (signal) => execute(deps, orgId, {
44291
44839
  operation: "revoke",
44292
44840
  ...input
44293
- }, options?.signal),
44294
- replace: (input, options) => execute(deps, orgId, {
44841
+ }, signal)),
44842
+ replace: (input, options) => observed(deps, ops.replace, options, (signal) => execute(deps, orgId, {
44295
44843
  operation: "replace",
44296
44844
  ...input
44297
- }, options?.signal),
44298
- list: (options) => runIfActive(options?.signal, CAPXUL_OPERATIONS.permissions.list, () => deps.convexCall.query(reads.read, { orgId })),
44299
- get: async (permissionId, options) => {
44300
- const listed = await runIfActive(options?.signal, CAPXUL_OPERATIONS.permissions.get, () => deps.convexCall.query(reads.read, { orgId }));
44845
+ }, signal)),
44846
+ list: (options) => observed(deps, ops.list, options, (signal) => runIfActive(signal, CAPXUL_OPERATIONS.permissions.list, () => deps.convexCall.query(reads.read, { orgId }))),
44847
+ get: (permissionId, options) => observed(deps, ops.get, options, async (signal) => {
44848
+ const listed = await runIfActive(signal, CAPXUL_OPERATIONS.permissions.get, () => deps.convexCall.query(reads.read, { orgId }));
44301
44849
  if (!listed.ok) return listed;
44302
44850
  return {
44303
44851
  ok: true,
44304
44852
  value: listed.value.permissions.find((row) => row.permissionId === permissionId) ?? null
44305
44853
  };
44306
- }
44854
+ })
44307
44855
  };
44308
44856
  }
44309
44857
  //#endregion
@@ -44865,7 +45413,7 @@ function hermeticOrgView(input) {
44865
45413
  name: input.name,
44866
45414
  handle: input.handle,
44867
45415
  safeAddress: toAddress(placeholder),
44868
- role: "Owner",
45416
+ role: ADMIN_ROLE_LABEL,
44869
45417
  treasury: zeroTreasury(orgId),
44870
45418
  bio: null,
44871
45419
  size: null,
@@ -45111,6 +45659,13 @@ function isRetryableOrganizationSetupFailure(error) {
45111
45659
  * constructed for each `org(orgId)` call. It has no shared mutable active-Org
45112
45660
  * state. The closed-over `orgId` is its only entity reference.
45113
45661
  */
45662
+ /** The observed-runner pair a method bundle needs to own its operation records. */
45663
+ function observedRunnerDeps(deps) {
45664
+ return {
45665
+ ...deps.runPromise === void 0 ? {} : { runPromise: deps.runPromise },
45666
+ ...deps.invocationControls === void 0 ? {} : { invocationControls: deps.invocationControls }
45667
+ };
45668
+ }
45114
45669
  function makeOrgMethods(deps) {
45115
45670
  const orgDeps = {
45116
45671
  ...deps.orgPort === void 0 ? {} : { orgPort: deps.orgPort },
@@ -45278,6 +45833,7 @@ function makeOrgMethods(deps) {
45278
45833
  },
45279
45834
  permissions: convexCall === void 0 ? makeNotImplementedPermissionMethods() : makePermissionMethods({
45280
45835
  convexCall,
45836
+ ...observedRunnerDeps(deps),
45281
45837
  ...deps.actor === void 0 ? {} : { actor: deps.actor },
45282
45838
  ...deps.chainId === void 0 ? {} : { chainId: Number(deps.chainId) },
45283
45839
  ...deps.signer === void 0 ? {} : { signer: deps.signer }
@@ -45578,11 +46134,28 @@ const authFailure = (record, reason, mode) => ({
45578
46134
  ...linkage(record)
45579
46135
  }
45580
46136
  });
46137
+ const REFUSAL_EVENTS = /* @__PURE__ */ new Set([
46138
+ "ClaimAccount",
46139
+ "RetryAccount",
46140
+ "CreateOrganization",
46141
+ "AttachOrganization",
46142
+ "RetryOrganization"
46143
+ ]);
45581
46144
  function mapIdentityProductObservation(record, state) {
45582
46145
  if (record.machine !== "identity" || !IDENTITY_EVENT_TAG_SET.has(record.event)) return NONE;
45583
46146
  if (record.outcome === "cancelled") return NONE;
45584
46147
  if (record.slot === "identity:auth" && record.outcome === "refused") return authFailure(record, record.refusal_code, void 0);
45585
46148
  if (record.slot === "identity:auth" && record.outcome === "failed") return authFailure(record, record.error_code, record.failure?.mode);
46149
+ if (record.outcome === "refused" && REFUSAL_EVENTS.has(record.event)) return {
46150
+ name: "identity_refused",
46151
+ props: {
46152
+ event: record.event,
46153
+ refusal_code: record.refusal_code,
46154
+ slot: record.slot,
46155
+ state: record.state,
46156
+ ...linkage(record)
46157
+ }
46158
+ };
45586
46159
  if (record.outcome !== "applied") return NONE;
45587
46160
  switch (APPLIED_ACTION_BY_EVENT[record.event]) {
45588
46161
  case "none": return NONE;
@@ -45741,10 +46314,13 @@ function assembleCapxulClient(input) {
45741
46314
  ...input.invokeTimeoutMs === void 0 ? {} : { invokeTimeoutMs: input.invokeTimeoutMs },
45742
46315
  afterVerifyOtp: async () => {
45743
46316
  const browserSigner = input.signer;
45744
- if (browserSigner !== void 0 && "resetSession" in browserSigner && typeof browserSigner.resetSession === "function") try {
45745
- browserSigner.resetSession();
45746
- } catch (cause) {
45747
- throw signerFailure(browserSigner.source, "resetSession", cause);
46317
+ if (browserSigner !== void 0 && "resetSession" in browserSigner && typeof browserSigner.resetSession === "function") {
46318
+ try {
46319
+ browserSigner.resetSession();
46320
+ } catch (cause) {
46321
+ throw signerFailure(browserSigner.source, "resetSession", cause);
46322
+ }
46323
+ if (browserSigner.statusStore?.status() === "unknown" && typeof browserSigner.ensureWalletReady === "function") browserSigner.ensureWalletReady().catch(() => {});
45748
46324
  }
45749
46325
  await detectPendingOrgInvitations?.();
45750
46326
  kickProvisioning?.();
@@ -45771,6 +46347,7 @@ function assembleCapxulClient(input) {
45771
46347
  ensureAccount: account._internal.ensureReady,
45772
46348
  getLifecycle: account.getLifecycle,
45773
46349
  snapshotIdentity: actor.snapshot,
46350
+ subscribeIdentity: actor.subscribe,
45774
46351
  sendIdentity: (event, options) => runCapxulEffect(askIdentity(actor, event, options), options, CAPXUL_OPERATIONS._internal.identity.send, effectRunner.runPromise)
45775
46352
  });
45776
46353
  const system = makeSystemMethods({ convexCall: input.ports.convexCall });
@@ -45904,6 +46481,7 @@ function assembleCapxulClient(input) {
45904
46481
  identity: identityRuntime,
45905
46482
  bootstrap: input.bootstrap,
45906
46483
  accounts: { fund: accounts.fund },
46484
+ ...input.ports.indexerRead === void 0 ? {} : { indexer: input.ports.indexerRead },
45907
46485
  organizationSetup: { getProofReceipt: (orgId) => runPortEffect(input.ports.convexCall.query(organizationSetupProofReceiptQuery, { orgId })) },
45908
46486
  telemetry: input.ports.telemetry,
45909
46487
  captureExternalAddressAcknowledged: (address, organizationId) => {
@@ -45962,8 +46540,10 @@ function withHostObservationControls(snapshot, input, actorId) {
45962
46540
  const previous = readInvocationObservation(input);
45963
46541
  if (previous !== void 0) return attachInvocationObservation({ ...input }, previous);
45964
46542
  const captured = snapshot?.() ?? { active: true };
46543
+ const context = captured.active ? withCapturedAttemptContext(captured.context, input) : captured.context;
45965
46544
  return attachInvocationObservation({ ...input }, {
45966
46545
  ...captured,
46546
+ ...context === void 0 ? {} : { context },
45967
46547
  ...actorId === void 0 ? {} : { actorId }
45968
46548
  });
45969
46549
  }
@@ -45983,6 +46563,382 @@ function snapshotHostObservability(observability) {
45983
46563
  };
45984
46564
  }
45985
46565
  //#endregion
46566
+ //#region ../../packages/sdk/src/ports/indexer-read.ts
46567
+ /** The indexer's own page bound. Exceeding it is a caller defect, not a refusal. */
46568
+ const INDEXER_MAX_LIMIT = 1e3;
46569
+ const LOWER_CASE_ADDRESS = /^0x[0-9a-f]{40}$/;
46570
+ /**
46571
+ * Refuse a page the indexer would refuse, before any implementation spends a
46572
+ * round trip on it. Every implementation calls this, so a consumer test written
46573
+ * against the hermetic adapter cannot pass on input production rejects. Throws
46574
+ * a `CapxulError`; callers convert it to an `IndexerReadError`.
46575
+ */
46576
+ function assertIndexerPage(input) {
46577
+ const safe = String(input.safe).toLowerCase();
46578
+ if (!LOWER_CASE_ADDRESS.test(safe)) throw Errors.invalidInput("safe", "must be a lower-case EVM address");
46579
+ if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 1e3) throw Errors.invalidInput("limit", `must be an integer from 1 to ${INDEXER_MAX_LIMIT}`);
46580
+ const offset = input.offset ?? 0;
46581
+ if (!Number.isSafeInteger(offset) || offset < 0) throw Errors.invalidInput("offset", "must be a non-negative integer");
46582
+ return safe;
46583
+ }
46584
+ var IndexerReadError = class extends Data.TaggedError("IndexerReadError") {};
46585
+ function indexerReadErrorFromCapxul(operation, error, cause = error) {
46586
+ return new IndexerReadError({
46587
+ operation,
46588
+ publicCode: error.code,
46589
+ publicError: error,
46590
+ cause,
46591
+ ...error.details === void 0 ? {} : { details: error.details }
46592
+ });
46593
+ }
46594
+ Context.Service()("@capxul/sdk/ports/IndexerReadPort");
46595
+ //#endregion
46596
+ //#region ../../packages/sdk/src/adapters/ponder/decode.ts
46597
+ /**
46598
+ * Decode the indexer's rows at the trust boundary.
46599
+ *
46600
+ * Ponder returns the raw PostgreSQL result: `integer` arrives as a number,
46601
+ * `numeric(78)` and `text` arrive as strings. Amounts, block numbers and
46602
+ * timestamps are `numeric(78)`, so they become `bigint` here and never pass
46603
+ * through `Number`. Every decoder throws a `CapxulError`; the adapter turns
46604
+ * that into a typed `IndexerReadError`.
46605
+ */
46606
+ const HEX = /^0x[0-9a-fA-F]+$/;
46607
+ function field(row, key) {
46608
+ if (!(key in row)) throw Errors.invalidInput(key, "missing from the indexer row");
46609
+ return row[key];
46610
+ }
46611
+ function text(row, key) {
46612
+ const value = field(row, key);
46613
+ if (typeof value !== "string") throw Errors.invalidInput(key, "must be a string");
46614
+ return value;
46615
+ }
46616
+ function hex(row, key) {
46617
+ const value = text(row, key);
46618
+ if (!HEX.test(value)) throw Errors.invalidInput(key, "must be a hex string");
46619
+ return value.toLowerCase();
46620
+ }
46621
+ function integer(row, key) {
46622
+ const value = field(row, key);
46623
+ const parsed = typeof value === "string" ? Number(value) : value;
46624
+ if (typeof parsed !== "number" || !Number.isSafeInteger(parsed)) throw Errors.invalidInput(key, "must be an integer");
46625
+ return parsed;
46626
+ }
46627
+ /** `numeric(78)` crosses the wire as a decimal string; keep every digit. */
46628
+ function big(row, key) {
46629
+ const value = field(row, key);
46630
+ if (typeof value === "bigint") return value;
46631
+ const raw = typeof value === "number" ? String(value) : value;
46632
+ if (typeof raw !== "string" || !/^-?[0-9]+$/.test(raw)) throw Errors.invalidInput(key, "must be an exact integer amount");
46633
+ return BigInt(raw);
46634
+ }
46635
+ function asRow(value) {
46636
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw Errors.invalidInput("row", "must be an object");
46637
+ return value;
46638
+ }
46639
+ function identity(row) {
46640
+ return {
46641
+ id: text(row, "id"),
46642
+ chainId: toChainId(integer(row, "chain_id")),
46643
+ txHash: toTxHash(hex(row, "tx_hash")),
46644
+ transactionLogOrdinal: integer(row, "transaction_log_ordinal"),
46645
+ blockNumber: big(row, "block_number"),
46646
+ blockHash: hex(row, "block_hash"),
46647
+ timestamp: big(row, "timestamp")
46648
+ };
46649
+ }
46650
+ function decodeTransfer(value) {
46651
+ const row = asRow(value);
46652
+ return {
46653
+ ...identity(row),
46654
+ assetId: toAssetId(text(row, "asset_id")),
46655
+ token: toAddress(hex(row, "token")),
46656
+ from: toAddress(hex(row, "from")),
46657
+ to: toAddress(hex(row, "to")),
46658
+ amount: big(row, "amount")
46659
+ };
46660
+ }
46661
+ function decodePayment(value) {
46662
+ const row = asRow(value);
46663
+ return {
46664
+ ...identity(row),
46665
+ contract: toAddress(hex(row, "contract")),
46666
+ settlementId: hex(row, "settlement_id"),
46667
+ sender: toAddress(hex(row, "sender")),
46668
+ recipient: toAddress(hex(row, "recipient")),
46669
+ assetId: toAssetId(text(row, "asset_id")),
46670
+ token: toAddress(hex(row, "token")),
46671
+ amount: big(row, "amount"),
46672
+ kind: integer(row, "kind"),
46673
+ documentHash: hex(row, "document_hash")
46674
+ };
46675
+ }
46676
+ /** The `balance` view exposes the signed sum under the underlying column name `to`. */
46677
+ function decodeBalance(value) {
46678
+ const row = asRow(value);
46679
+ return {
46680
+ chainId: toChainId(integer(row, "chain_id")),
46681
+ assetId: toAssetId(text(row, "asset_id")),
46682
+ address: toAddress(hex(row, "to")),
46683
+ amount: big(row, "amount")
46684
+ };
46685
+ }
46686
+ const DECODERS = {
46687
+ transfer: decodeTransfer,
46688
+ payment: decodePayment,
46689
+ balance: decodeBalance
46690
+ };
46691
+ /** Decode one `/sql/db` or `/sql/live` payload. Ponder returns `{ rows: [...] }`. */
46692
+ function decodeRows(table, body) {
46693
+ const rows = asRow(body).rows;
46694
+ if (!Array.isArray(rows)) throw Errors.invalidInput("rows", "must be an array");
46695
+ const decode = DECODERS[table];
46696
+ return rows.map(decode);
46697
+ }
46698
+ /** Decode Ponder's native `/status`: `{ [chainName]: { id, block: { number, timestamp } } }`. */
46699
+ function decodeStatus(body) {
46700
+ const chains = asRow(body);
46701
+ return Object.entries(chains).map(([chain, value]) => {
46702
+ const entry = asRow(value);
46703
+ const block = asRow(field(entry, "block"));
46704
+ return {
46705
+ chain,
46706
+ chainId: toChainId(integer(entry, "id")),
46707
+ blockNumber: big(block, "number"),
46708
+ blockTimestamp: big(block, "timestamp")
46709
+ };
46710
+ });
46711
+ }
46712
+ //#endregion
46713
+ //#region ../../packages/sdk/src/adapters/ponder/statements.ts
46714
+ /**
46715
+ * The exact statements the indexer accepts.
46716
+ *
46717
+ * `apps/indexer/src/queries.ts` compiles its allowlist with `@ponder/client`
46718
+ * and compares `sql`, `params` and `typings` byte for byte against the caller's
46719
+ * statement. Anything else gets 403. The SDK therefore reproduces the compiled
46720
+ * text here rather than pulling Ponder and Drizzle into a published browser
46721
+ * bundle to regenerate three fixed statements.
46722
+ *
46723
+ * `statements.test.ts` pins the text. When the indexer schema or a query in
46724
+ * that allowlist changes, this file changes with it or every read fails 403.
46725
+ */
46726
+ const HEADS = {
46727
+ transfer: "select \"id\", \"chain_id\", \"tx_hash\", \"transaction_log_ordinal\", \"block_number\", \"block_hash\", \"timestamp\", \"asset_id\", \"token\", \"from\", \"to\", \"amount\" from \"transfer\" where (\"transfer\".\"from\" = $1 or \"transfer\".\"to\" = $2) order by \"transfer\".\"block_number\" desc, \"transfer\".\"id\" desc",
46728
+ payment: "select \"id\", \"chain_id\", \"tx_hash\", \"transaction_log_ordinal\", \"block_number\", \"block_hash\", \"timestamp\", \"contract\", \"settlement_id\", \"sender\", \"recipient\", \"asset_id\", \"token\", \"amount\", \"kind\", \"document_hash\" from \"payment\" where (\"payment\".\"sender\" = $1 or \"payment\".\"recipient\" = $2) order by \"payment\".\"block_number\" desc, \"payment\".\"id\" desc",
46729
+ balance: "select \"chain_id\", \"asset_id\", \"to\", \"amount\" from \"balance\" where \"balance\".\"to\" = $1"
46730
+ };
46731
+ /** How many times the statement binds the Safe address. */
46732
+ const ACTOR_PARAMS = {
46733
+ transfer: 2,
46734
+ payment: 2,
46735
+ balance: 1
46736
+ };
46737
+ /**
46738
+ * Build the compiled query for one table and page. Throws a `CapxulError` for
46739
+ * a page or address the indexer would refuse, so the caller never spends a
46740
+ * round trip to learn it built the request wrong.
46741
+ */
46742
+ function ponderQuery(table, input) {
46743
+ const safe = assertIndexerPage(input);
46744
+ const offset = input.offset ?? 0;
46745
+ const actors = ACTOR_PARAMS[table];
46746
+ const params = [];
46747
+ for (let i = 0; i < actors; i++) params.push(safe);
46748
+ params.push(input.limit);
46749
+ let sql = `${HEADS[table]} limit $${actors + 1}`;
46750
+ if (offset > 0) {
46751
+ params.push(offset);
46752
+ sql = `${sql} offset $${actors + 2}`;
46753
+ }
46754
+ return {
46755
+ sql,
46756
+ params,
46757
+ typings: params.map(() => "none")
46758
+ };
46759
+ }
46760
+ /**
46761
+ * The `?sql=` value. `@ponder/client` sends `superjson.stringify(query)`; for a
46762
+ * payload of strings and numbers superjson emits no `meta`, so the wire form is
46763
+ * exactly this envelope.
46764
+ */
46765
+ function ponderQueryParam(query) {
46766
+ return JSON.stringify({ json: query });
46767
+ }
46768
+ //#endregion
46769
+ //#region ../../packages/sdk/src/adapters/ponder/sse.ts
46770
+ /**
46771
+ * The smallest SSE reader that can carry an `Authorization` header.
46772
+ *
46773
+ * `@ponder/client` opens its live query with `EventSource`, which accepts no
46774
+ * headers, so it cannot reach the guarded indexer at all. The indexer's CORS
46775
+ * policy allows exactly one request header (`Authorization`), so this reader
46776
+ * sends nothing else. Ponder writes one `data:` line per frame.
46777
+ */
46778
+ async function readEventStream(body, onData, stopped) {
46779
+ const reader = body.getReader();
46780
+ const decoder = new TextDecoder();
46781
+ let buffer = "";
46782
+ try {
46783
+ for (;;) {
46784
+ const { done, value } = await reader.read();
46785
+ if (done || stopped()) return;
46786
+ buffer += decoder.decode(value, { stream: true });
46787
+ let split = buffer.indexOf("\n\n");
46788
+ while (split !== -1) {
46789
+ const frame = buffer.slice(0, split);
46790
+ buffer = buffer.slice(split + 2);
46791
+ const data = frameData(frame);
46792
+ if (data !== void 0) onData(data);
46793
+ if (stopped()) return;
46794
+ split = buffer.indexOf("\n\n");
46795
+ }
46796
+ }
46797
+ } finally {
46798
+ await reader.cancel().catch(() => void 0);
46799
+ }
46800
+ }
46801
+ function frameData(frame) {
46802
+ const lines = [];
46803
+ for (const line of frame.split("\n")) {
46804
+ if (!line.startsWith("data:")) continue;
46805
+ lines.push(line.slice(line.startsWith("data: ") ? 6 : 5));
46806
+ }
46807
+ return lines.length === 0 ? void 0 : lines.join("\n");
46808
+ }
46809
+ //#endregion
46810
+ //#region ../../packages/sdk/src/adapters/ponder/PonderIndexerAdapter.ts
46811
+ var PonderIndexerAdapter = class {
46812
+ #baseUrl;
46813
+ #token;
46814
+ #fetch;
46815
+ #observation;
46816
+ constructor(deps) {
46817
+ this.#baseUrl = deps.baseUrl.replace(/\/$/, "");
46818
+ this.#token = deps.token;
46819
+ this.#observation = deps.observation;
46820
+ this.#fetch = deps.fetch ?? ((input, init) => globalThis.fetch(input, init));
46821
+ }
46822
+ read(table, input) {
46823
+ const operation = `indexer.read.${table}`;
46824
+ return Effect.tryPromise({
46825
+ try: async () => {
46826
+ return decodeRows(table, await (await this.#request("db", table, input, operation)).json());
46827
+ },
46828
+ catch: (cause) => toIndexerReadError(operation, cause)
46829
+ });
46830
+ }
46831
+ subscribe(table, input, callback) {
46832
+ const operation = CAPXUL_OPERATIONS.activity.subscribe;
46833
+ return Effect.sync(() => {
46834
+ let stopped = false;
46835
+ const unsubscribe = () => {
46836
+ stopped = true;
46837
+ };
46838
+ callback({ status: "loading" });
46839
+ this.#stream(table, input, operation, callback, () => stopped).catch(() => void 0);
46840
+ return unsubscribe;
46841
+ });
46842
+ }
46843
+ status = Effect.tryPromise({
46844
+ try: async () => {
46845
+ const response = await this.#fetch(`${this.#baseUrl}/status`, { method: "GET" });
46846
+ if (!response.ok) throw httpError("indexer.status", response.status, await safeText(response));
46847
+ return decodeStatus(await response.json());
46848
+ },
46849
+ catch: (cause) => toIndexerReadError("indexer.status", cause)
46850
+ });
46851
+ /** One authenticated `/sql/:method` call. Throws a `CapxulError` on refusal. */
46852
+ async #request(method, table, input, operation) {
46853
+ const query = ponderQuery(table, input);
46854
+ const token = await this.#token({ forceRefreshToken: false });
46855
+ if (token === null || token === "") throw Errors.notAuthenticated();
46856
+ const url = `${this.#baseUrl}/sql/${method}?sql=${encodeURIComponent(ponderQueryParam(query))}`;
46857
+ const headers = { authorization: `Bearer ${token}` };
46858
+ if (method === "live") headers.accept = "text/event-stream";
46859
+ let response;
46860
+ try {
46861
+ response = await this.#fetch(url, {
46862
+ method: "GET",
46863
+ headers
46864
+ });
46865
+ } catch (cause) {
46866
+ throw Errors.networkError(operation, cause, {
46867
+ provider: "indexer",
46868
+ failure_mode: "upstream-down"
46869
+ });
46870
+ }
46871
+ if (!response.ok) throw httpError(operation, response.status, await safeText(response));
46872
+ return response;
46873
+ }
46874
+ /**
46875
+ * Follow the live stream until the caller unsubscribes or the indexer closes
46876
+ * it. The indexer closes the stream on token expiry or revoked authority
46877
+ * with no frame, so any end the caller did not ask for is a teardown: it
46878
+ * reaches `captureException` under `activity.subscribe` and the caller sees
46879
+ * one `error` snapshot.
46880
+ */
46881
+ async #stream(table, input, operation, callback, stopped) {
46882
+ let failure;
46883
+ try {
46884
+ const response = await this.#request("live", table, input, operation);
46885
+ if (response.body === null) throw Errors.providerError("indexer", operation, "empty stream");
46886
+ await readEventStream(response.body, (data) => {
46887
+ try {
46888
+ callback({
46889
+ status: "ok",
46890
+ value: decodeRows(table, JSON.parse(data))
46891
+ });
46892
+ } catch (cause) {
46893
+ failure = toPublicError$1(operation, cause);
46894
+ }
46895
+ }, () => stopped() || failure !== void 0);
46896
+ } catch (cause) {
46897
+ failure = toPublicError$1(operation, cause);
46898
+ }
46899
+ if (stopped()) return;
46900
+ const error = failure ?? Errors.capabilityUnavailable("indexer", operation);
46901
+ observeStreamFailure(this.#observation, CAPXUL_OPERATIONS.activity.subscribe, error);
46902
+ callback({
46903
+ status: "error",
46904
+ error
46905
+ });
46906
+ }
46907
+ };
46908
+ /**
46909
+ * Map an indexer refusal into the shared error vocabulary.
46910
+ *
46911
+ * 401 is the expected outcome of an expired or revoked session. 403 is not:
46912
+ * the indexer accepts only its own compiled statements for a Safe in the
46913
+ * claim, so a refusal means this SDK and that deployment disagree, or the
46914
+ * session gained a Safe and still holds the older token. Both must be loud.
46915
+ */
46916
+ function httpError(operation, status, body) {
46917
+ if (status === 401) return Errors.notAuthenticated();
46918
+ if (status === 429) return Errors.rateLimited({ resource: "indexer" });
46919
+ if (status === 503) return Errors.capabilityUnavailable("indexer", operation);
46920
+ return Errors.providerError("indexer", operation, body, {
46921
+ httpStatus: status,
46922
+ ...status >= 500 ? { failure_mode: "upstream-down" } : {},
46923
+ details: { reason: status === 403 ? "scope-refused" : "http-status" }
46924
+ });
46925
+ }
46926
+ function toPublicError$1(operation, cause) {
46927
+ if (cause instanceof CapxulError) return cause;
46928
+ return Errors.providerError("indexer", operation, cause);
46929
+ }
46930
+ function toIndexerReadError(operation, cause) {
46931
+ if (cause instanceof IndexerReadError) return cause;
46932
+ return indexerReadErrorFromCapxul(operation, toPublicError$1(operation, cause), cause);
46933
+ }
46934
+ async function safeText(response) {
46935
+ try {
46936
+ return await response.text();
46937
+ } catch {
46938
+ return "";
46939
+ }
46940
+ }
46941
+ //#endregion
45986
46942
  //#region ../../packages/sdk/src/adapters/_shared/clock.ts
45987
46943
  async function readClockNow(clock) {
45988
46944
  try {
@@ -46439,7 +47395,16 @@ async function createProductionAdapters(input) {
46439
47395
  }));
46440
47396
  const applicationLayer = Layer.merge(portsLayer, optionalEngineeringTelemetryLayer(bootstrapResult.value.engineeringTelemetry, resolvedInput.value.runtime));
46441
47397
  const context = await Effect.runPromise(Layer.buildWithScope(applicationLayer, scope));
46442
- const ports = await Effect.runPromise(collectProductionFlowPorts.pipe(Effect.provide(context)));
47398
+ const collected = await Effect.runPromise(collectProductionFlowPorts.pipe(Effect.provide(context)));
47399
+ const indexerUrl = input.indexerUrl ?? bootstrapResult.value.indexerUrl;
47400
+ const indexerRead = productionIndexerReadPort(indexerUrl === void 0 ? input : {
47401
+ ...input,
47402
+ indexerUrl
47403
+ }, collected, observation);
47404
+ const ports = indexerRead === void 0 ? collected : {
47405
+ ...collected,
47406
+ indexerRead
47407
+ };
46443
47408
  const stopConnectionObservation = observeProductionConvexConnection(ports.convexCall, context);
46444
47409
  const close = idempotentClose(async () => {
46445
47410
  try {
@@ -46566,7 +47531,7 @@ async function createCapxulClientWithSignerControls(input, controls) {
46566
47531
  ...adapters.value.bootstrap,
46567
47532
  authBaseUrl: resolvedAuthBaseUrl
46568
47533
  }, {
46569
- diagnostic: new ConsoleDiagnosticAdapter(),
47534
+ diagnostic: new EffectLogDiagnosticAdapter(adapters.value.context, new ConsoleDiagnosticAdapter()),
46570
47535
  signUserOpHash: controls.signEmbeddedUserOpHash
46571
47536
  });
46572
47537
  signer = withSignerControl(signer, controls.signUserOpHash);
@@ -46771,6 +47736,28 @@ function idempotentClose(close) {
46771
47736
  await close();
46772
47737
  };
46773
47738
  }
47739
+ /**
47740
+ * Build the Ponder read port for this client, or `undefined` when no indexer
47741
+ * origin was supplied. The token provider is the same
47742
+ * `AuthClientPort.getConvexJwt` closure `ConvexCallPort` uses, so the indexer
47743
+ * and Convex see one session with one scope.
47744
+ */
47745
+ function productionIndexerReadPort(input, ports, observation) {
47746
+ if (input.indexerUrl === void 0 || input.indexerUrl === "") return void 0;
47747
+ return new PonderIndexerAdapter({
47748
+ baseUrl: normalizeHttpUrl("indexerUrl", input.indexerUrl),
47749
+ token: async ({ forceRefreshToken }) => {
47750
+ const token = await Effect.runPromise(Effect.result(ports.authClient.getConvexJwt({
47751
+ forceRefresh: forceRefreshToken,
47752
+ ...input.signal === void 0 ? {} : { signal: input.signal }
47753
+ })));
47754
+ if (Result.isFailure(token)) return null;
47755
+ return String(token.success.token);
47756
+ },
47757
+ ...input.fetch === void 0 ? {} : { fetch: input.fetch },
47758
+ ...observation === void 0 ? {} : { observation }
47759
+ });
47760
+ }
46774
47761
  //#endregion
46775
47762
  //#region src/tools/account.ts
46776
47763
  const READ = "account:read";
@@ -47382,7 +48369,7 @@ function stdioIdentity(env = process.env, options = {}) {
47382
48369
  }
47383
48370
  //#endregion
47384
48371
  //#region package.json
47385
- var version = "4.2.0-rc.1";
48372
+ var version = "4.2.0-rc.10";
47386
48373
  //#endregion
47387
48374
  //#region src/deps.ts
47388
48375
  const NO_IDENTITY = async () => void 0;