@capxul/observability 4.20.0-beta.2 → 4.20.0-beta.21

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.
@@ -0,0 +1,3463 @@
1
+ import { Effect, Schema, SchemaGetter } from "effect";
2
+ //#region ../errors/src/secret-material.ts
3
+ const CREDENTIAL_FIELDS = /* @__PURE__ */ new Set([
4
+ "password",
5
+ "passwd",
6
+ "pwd",
7
+ "pass",
8
+ "passphrase",
9
+ "currentpassword",
10
+ "newpassword",
11
+ "confirmpassword",
12
+ "passwordconfirmation",
13
+ "passwordhash",
14
+ "hashedpassword",
15
+ "pin",
16
+ "privatekey",
17
+ "walletprivatekey",
18
+ "secretkey",
19
+ "signingkey",
20
+ "signingsecret",
21
+ "seed",
22
+ "seedphrase",
23
+ "mnemonic",
24
+ "recoveryphrase",
25
+ "recovery",
26
+ "recoverycode",
27
+ "recoverycodes",
28
+ "keyshare",
29
+ "signingmaterial",
30
+ "recoverymaterial",
31
+ "privatekeybytes",
32
+ "signingprivatekey",
33
+ "encryptionkey",
34
+ "decryptionkey",
35
+ "authtoken",
36
+ "apitoken",
37
+ "bearertoken",
38
+ "oauthtoken",
39
+ "csrftoken",
40
+ "clientassertion",
41
+ "token",
42
+ "accesstoken",
43
+ "refreshtoken",
44
+ "idtoken",
45
+ "sessiontoken",
46
+ "session",
47
+ "sessionkey",
48
+ "sessionsecret",
49
+ "authsessionid",
50
+ "sessioncredential",
51
+ "sessioncredentials",
52
+ "sessioncookie",
53
+ "auth",
54
+ "authentication",
55
+ "authorization",
56
+ "proxyauthorization",
57
+ "cookie",
58
+ "cookies",
59
+ "setcookie",
60
+ "apikey",
61
+ "xapikey",
62
+ "xauthtoken",
63
+ "clientsecret",
64
+ "secret",
65
+ "secrets",
66
+ "credential",
67
+ "credentials",
68
+ "signature",
69
+ "otp",
70
+ "otpcode",
71
+ "totpsecret",
72
+ "onetimecode",
73
+ "onetimepassword",
74
+ "verificationcode",
75
+ "authcode",
76
+ "authorizationcode",
77
+ "oauthcode",
78
+ "codeverifier",
79
+ "devicecode",
80
+ "usercode",
81
+ "continuitytoken",
82
+ "refreshattemptid",
83
+ "revocationtoken"
84
+ ]);
85
+ /** Match credential fields by meaning, without hiding token addresses or replay IDs. */
86
+ function isCredentialField(name, context) {
87
+ const normalized = name.toLowerCase().replace(/[^a-z0-9]/gu, "");
88
+ return CREDENTIAL_FIELDS.has(normalized) || /(?:password(?:hash)?|passwd|passphrase|privatekey|signingkey|apikey|clientsecret|accesstoken|refreshtoken|sessiontoken)$/u.test(normalized) || context === "authentication" && (normalized === "code" || normalized === "sessionid") || context === "header" && /(?:token|secret|apikey|privatekey|signingkey|password|authorization|cookie|session)$/u.test(normalized);
89
+ }
90
+ function decodeUrlComponent(text) {
91
+ try {
92
+ return decodeURIComponent(text);
93
+ } catch {
94
+ return text;
95
+ }
96
+ }
97
+ /** Preserve URL diagnostics while removing credentials from their declared components. */
98
+ function redactUrlSecrets(value, source) {
99
+ try {
100
+ const absolute = /^[a-z][a-z0-9+.-]*:/iu.test(value);
101
+ const protocolRelative = value.startsWith("//");
102
+ const url = new URL(value, "https://redaction.invalid");
103
+ if (url.protocol !== "https:" && url.protocol !== "http:") return maskText(value);
104
+ let changed = url.username.length > 0 || url.password.length > 0;
105
+ const maskParams = (params) => new URLSearchParams(Array.from(params, ([name, entry]) => {
106
+ const safeName = maskText(name);
107
+ const safeEntry = isCredentialField(name) || /^(?:code|draft|__posthog)$/iu.test(name) ? "[REDACTED]" : maskText(entry);
108
+ changed ||= safeName !== name || safeEntry !== entry;
109
+ return [safeName, safeEntry];
110
+ })).toString();
111
+ const provider = source === "alchemy" || source === "infura" || /(?:^|\.)(?:alchemy\.com|alchemyapi\.io|infura\.io)$/iu.test(url.hostname);
112
+ const rawPath = absolute || protocolRelative ? url.pathname : value.split(/[?#]/u)[0] ?? "";
113
+ const segments = rawPath.split("/");
114
+ let path = segments.map((segment, index) => {
115
+ const decoded = decodeUrlComponent(segment);
116
+ const masked = provider && /^v[23]$/u.test(decodeUrlComponent(segments[index - 1] ?? "")) && decoded.length > 0 ? "[REDACTED]" : maskText(decoded);
117
+ changed ||= masked !== decoded;
118
+ return masked === decoded ? segment : encodeURIComponent(masked);
119
+ }).join("/");
120
+ if (source === "gateway" && rawPath.length > 0) {
121
+ path = `${rawPath.startsWith("/") ? "/" : ""}${encodeURIComponent("[REDACTED]")}`;
122
+ changed = true;
123
+ }
124
+ const query = maskParams(url.searchParams);
125
+ const fragment = url.hash.slice(1);
126
+ const decodedFragment = decodeUrlComponent(fragment);
127
+ const maskedFragment = maskText(decodedFragment);
128
+ changed ||= maskedFragment !== decodedFragment;
129
+ const fragmentQuery = fragment.indexOf("?");
130
+ const fragmentPath = fragment.slice(0, fragmentQuery);
131
+ const maskedFragmentPath = maskText(decodeUrlComponent(fragmentPath));
132
+ changed ||= maskedFragmentPath !== decodeUrlComponent(fragmentPath);
133
+ const hash = fragmentQuery >= 0 ? `${maskedFragmentPath === decodeUrlComponent(fragmentPath) ? fragmentPath : encodeURIComponent(maskedFragmentPath)}?${maskParams(new URLSearchParams(fragment.slice(fragmentQuery + 1)))}` : fragment.includes("=") ? maskParams(new URLSearchParams(fragment)) : maskedFragment === decodedFragment ? fragment : encodeURIComponent(maskedFragment);
134
+ const origin = absolute ? url.origin : protocolRelative ? `//${url.host}` : "";
135
+ if (!changed) return value;
136
+ return `${origin}${path}${query ? `?${query}` : ""}${hash ? `#${hash}` : ""}`;
137
+ } catch {
138
+ if (source === "gateway") return "[REDACTED]";
139
+ return maskText(value.replace(/(https?:\/\/)[^/\s@]+@/giu, "$1[REDACTED]@").replace(/([?&#])([^=&#]+)=([^&#]*)/gu, (whole, separator, name) => isCredentialField(decodeUrlComponent(name)) || /^(?:code|draft|__posthog)$/iu.test(decodeUrlComponent(name)) ? `${separator}${name}=[REDACTED]` : whole));
140
+ }
141
+ }
142
+ const JSON_FIELD = /("(?:[^"\\]|\\.)*")(\s*:\s*)("(?:[^"\\]|\\.)*"|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/gu;
143
+ const PROSE_FIELD = /(?=(\b([A-Za-z][A-Za-z0-9_-]*(?:[ \t]+[A-Za-z][A-Za-z0-9_-]*){0,3})\s*[:=]\s*((?:Bearer|Basic)[ \t]+[^\s,;"']+|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^\s,;&"']+)))/gu;
144
+ const EMBEDDED_URL = /(https?:\/\/[^\s"<>]*)/giu;
145
+ function isSecretLabel(name) {
146
+ return isCredentialField(name) || /^request[ _-]?body$/iu.test(name);
147
+ }
148
+ const JSON_ENCODING_MAX = 8;
149
+ const JSON_NESTING_MAX = 64;
150
+ const JSON_KEY = /("(?:[^"\\]|\\.)*")\s*:/gu;
151
+ const JSON_CONTAINER_START = /(?:\{\s*["}]|\[\s*[[\]{}"0-9tfn-])/uy;
152
+ function hasSecretJsonKey(value) {
153
+ for (const match of value.matchAll(JSON_KEY)) try {
154
+ if (match[1] !== void 0 && isSecretLabel(JSON.parse(match[1]))) return true;
155
+ } catch {}
156
+ return false;
157
+ }
158
+ /** Project a complete fragment once. Never retry all of its nested substrings. */
159
+ function projectJsonFragment(value, encodingDepth, overDepth) {
160
+ if (overDepth || encodingDepth >= JSON_ENCODING_MAX) return "[REDACTED]";
161
+ let parsed;
162
+ try {
163
+ parsed = JSON.parse(value);
164
+ } catch {
165
+ return hasSecretJsonKey(value) ? "[REDACTED]" : value;
166
+ }
167
+ try {
168
+ let changed = false;
169
+ const masked = JSON.stringify(parsed, (name, nested) => {
170
+ if (isSecretLabel(name)) {
171
+ changed ||= nested !== "[REDACTED]";
172
+ return "[REDACTED]";
173
+ }
174
+ if (typeof nested === "string") {
175
+ const projected = maskJsonFragments(nested, encodingDepth + 1);
176
+ changed ||= projected !== nested;
177
+ return projected;
178
+ }
179
+ return nested;
180
+ });
181
+ return changed ? masked : value;
182
+ } catch {
183
+ return "[REDACTED]";
184
+ }
185
+ }
186
+ /** Scan balanced object/array fragments once, respecting JSON quotes and escapes. */
187
+ function maskJsonFragments(value, encodingDepth = 0) {
188
+ if (value.trimStart().startsWith("\"")) try {
189
+ const decoded = JSON.parse(value);
190
+ if (typeof decoded === "string") {
191
+ if (encodingDepth >= JSON_ENCODING_MAX) return "\"[REDACTED]\"";
192
+ const masked = maskJsonFragments(decoded, encodingDepth + 1);
193
+ return masked === decoded ? value : JSON.stringify(masked);
194
+ }
195
+ } catch {}
196
+ let output = "";
197
+ let cursor = 0;
198
+ let start = -1;
199
+ let depth = 0;
200
+ let overDepth = false;
201
+ let quoted = false;
202
+ let escaped = false;
203
+ for (let index = 0; index < value.length; index++) {
204
+ const character = value[index];
205
+ if (start < 0) {
206
+ JSON_CONTAINER_START.lastIndex = index;
207
+ if (!JSON_CONTAINER_START.test(value)) continue;
208
+ start = index;
209
+ depth = 1;
210
+ overDepth = false;
211
+ continue;
212
+ }
213
+ if (quoted) {
214
+ if (escaped) escaped = false;
215
+ else if (character === "\\") escaped = true;
216
+ else if (character === "\"") quoted = false;
217
+ continue;
218
+ }
219
+ if (character === "\"") quoted = true;
220
+ else if (character === "{" || character === "[") {
221
+ depth++;
222
+ overDepth ||= depth > JSON_NESTING_MAX;
223
+ } else if (character === "}" || character === "]") {
224
+ depth--;
225
+ if (depth !== 0) continue;
226
+ output += value.slice(cursor, start) + projectJsonFragment(value.slice(start, index + 1), encodingDepth, overDepth);
227
+ cursor = index + 1;
228
+ start = -1;
229
+ }
230
+ }
231
+ if (start >= 0) {
232
+ const fragment = value.slice(start);
233
+ output += value.slice(cursor, start) + (overDepth || hasSecretJsonKey(fragment) ? "[REDACTED]" : fragment);
234
+ cursor = value.length;
235
+ }
236
+ return output + value.slice(cursor);
237
+ }
238
+ function maskLabelledText(value) {
239
+ const jsonMasked = maskJsonFragments(value).replace(JSON_FIELD, (whole, quotedName, separator) => {
240
+ try {
241
+ return isSecretLabel(JSON.parse(quotedName)) ? `${quotedName}${separator}"[REDACTED]"` : whole;
242
+ } catch {
243
+ return whole;
244
+ }
245
+ });
246
+ let output = "";
247
+ let cursor = 0;
248
+ for (const match of jsonMasked.matchAll(PROSE_FIELD)) {
249
+ const [, whole, label, entry] = match;
250
+ if (whole === void 0 || label === void 0 || entry === void 0 || match.index < cursor || /^Bearer[ \t]+/iu.test(entry)) continue;
251
+ const words = label.split(/[ \t]+/u);
252
+ for (let index = 0; index < words.length; index++) {
253
+ const name = words.slice(index).join(" ");
254
+ if (isSecretLabel(name)) {
255
+ const prefix = words.slice(0, index).join(" ");
256
+ output += jsonMasked.slice(cursor, match.index) + `${prefix ? `${prefix} ` : ""}${name}=[REDACTED]`;
257
+ cursor = match.index + whole.length;
258
+ break;
259
+ }
260
+ }
261
+ }
262
+ return output + jsonMasked.slice(cursor);
263
+ }
264
+ const TOKEN_MASKS = [
265
+ [/\bBearer\s+(?!(?:realm|error|error_description|scope|authorization_uri|resource|claims)\s*=)[^\s,;"']+/giu, "Bearer [REDACTED]"],
266
+ [/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/gu, "[REDACTED]"],
267
+ [/(^|[^a-fA-F0-9])(?<!0[xX])[a-fA-F0-9]{64}(?=$|[^a-fA-F0-9])/gu, "$1[REDACTED]"],
268
+ [/(?:(?: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_-]*/giu, "[REDACTED]"]
269
+ ];
270
+ /** URL components and malformed URLs use this non-recursive masking layer. */
271
+ function maskText(value) {
272
+ let text = maskLabelledText(value);
273
+ for (const [pattern, replacement] of TOKEN_MASKS) text = text.replace(pattern, replacement);
274
+ return text;
275
+ }
276
+ /** Mask credential fields and embedded URLs while preserving surrounding evidence. */
277
+ function redactSecrets(value, source) {
278
+ return maskLabelledText(value).split(EMBEDDED_URL).map((part, index) => index % 2 === 1 ? redactUrlSecrets(part, source).replaceAll("%5BREDACTED%5D", "[REDACTED]") : maskText(part)).join("");
279
+ }
280
+ //#endregion
281
+ //#region ../errors/src/chain-cause.ts
282
+ /**
283
+ * Why an operation failed — the one flat vocabulary. The first four are the
284
+ * auth/provider diagnoses that predate this file. The rest name the chain
285
+ * path. `FailureMode` is derived from this list so a runtime membership check
286
+ * (the SDK's `$exception` projection, the observability schema) and the type
287
+ * can never drift apart.
288
+ */
289
+ const FAILURE_MODES = [
290
+ "auth-origin-mismatch",
291
+ "stale-openfort-cache",
292
+ "app-env-allowlist",
293
+ "no-secure-context",
294
+ "signer-not-ready",
295
+ "rate-limited",
296
+ "timeout",
297
+ "upstream-down",
298
+ "revert",
299
+ "insufficient-balance",
300
+ "insufficient-allowance",
301
+ "rejected",
302
+ "unauthorized",
303
+ "forbidden",
304
+ "bad-request",
305
+ "method-unsupported",
306
+ "unknown"
307
+ ];
308
+ /** Who answered. `alto` is the bundler; `gateway` is the AA gateway's own logic. */
309
+ const CHAIN_UPSTREAMS = [
310
+ "alchemy",
311
+ "infura",
312
+ "public",
313
+ "alto",
314
+ "gateway"
315
+ ];
316
+ //#endregion
317
+ //#region ../errors/src/errors.ts
318
+ const CAPXUL_ERROR_CODES = [
319
+ "NOT_AUTHENTICATED",
320
+ "EMAIL_DELIVERY_FAILED",
321
+ "PROFILE_NOT_FOUND",
322
+ "SMART_ACCOUNT_MISSING",
323
+ "PLAYER_NOT_FOUND",
324
+ "ACCOUNT_NOT_FOUND",
325
+ "ACCOUNT_CLAIMED_BY_OTHER_SIGNER",
326
+ "PROVIDER_ERROR",
327
+ "CAPABILITY_UNAVAILABLE",
328
+ "INVALID_INPUT",
329
+ "ENV_MISSING",
330
+ "NOT_IMPLEMENTED",
331
+ "VERIFICATION_REQUIRED",
332
+ "INSUFFICIENT_BALANCE",
333
+ "INVALID_RECIPIENT",
334
+ "ROLE_PERMISSION_DENIED",
335
+ "TRANSACTION_FAILED",
336
+ "RATE_LIMITED",
337
+ "NETWORK_ERROR",
338
+ "UNKNOWN",
339
+ "OTP_EXPIRED",
340
+ "SIGNER_REJECTED",
341
+ "CANCELLED",
342
+ "WRONG_STATE",
343
+ "STALE_EPOCH",
344
+ "SUPERSEDED",
345
+ "WORK_DIED",
346
+ "ACTOR_STOPPED"
347
+ ];
348
+ new Set(CAPXUL_ERROR_CODES);
349
+ //#endregion
350
+ //#region ../types/src/organization-setup.ts
351
+ /** Backend-owned Organization setup states shared by wire and telemetry. */
352
+ const ORGANIZATION_SETUP_STATUSES = [
353
+ "awaitingAuthorization",
354
+ "processing",
355
+ "needsAttention",
356
+ "ready",
357
+ "rechecking",
358
+ "failed"
359
+ ];
360
+ /** Closed reasons for a stored Organization setup issue. */
361
+ const ORGANIZATION_SETUP_REASONS = [
362
+ "submission_unknown",
363
+ "receipt_unresolved",
364
+ "provider_unavailable",
365
+ "receipt_reverted",
366
+ "deterministic_address_mismatch",
367
+ "receipt_mismatch",
368
+ "block_identity_changed",
369
+ "authority_event_mismatch",
370
+ "allowance_timestamp_mismatch",
371
+ "receipt_identity_unavailable",
372
+ "receipt_identity_mismatch",
373
+ "contract_code_unavailable",
374
+ "contract_state_mismatch",
375
+ "permission_projection_mismatch",
376
+ "bootstrap_reorg",
377
+ "dependent_authority_unresolved",
378
+ "historical_evidence_missing",
379
+ "worker_failed"
380
+ ];
381
+ //#endregion
382
+ //#region ../types/src/index.ts
383
+ const EVM_ADDRESS_RE = /^0x[0-9a-f]{40}$/i;
384
+ const BYTES32_RE = /^0x[0-9a-f]{64}$/i;
385
+ `${"0".repeat(64)}`;
386
+ const SUPPORTED_CURRENCIES = [
387
+ {
388
+ code: "USD",
389
+ symbol: "$",
390
+ name: "US Dollar"
391
+ },
392
+ {
393
+ code: "NGN",
394
+ symbol: "NGN",
395
+ name: "Nigerian Naira"
396
+ },
397
+ {
398
+ code: "GHS",
399
+ symbol: "GHS",
400
+ name: "Ghanaian Cedi"
401
+ },
402
+ {
403
+ code: "KES",
404
+ symbol: "KSh",
405
+ name: "Kenyan Shilling"
406
+ },
407
+ {
408
+ code: "UGX",
409
+ symbol: "USh",
410
+ name: "Ugandan Shilling"
411
+ }
412
+ ];
413
+ SUPPORTED_CURRENCIES.map((currency) => currency.code);
414
+ Object.fromEntries(SUPPORTED_CURRENCIES.map((currency) => [currency.code, currency.symbol]));
415
+ const APP_ID_RE = /^app_[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
416
+ Math.floor(Number.MAX_SAFE_INTEGER / 1e3);
417
+ //#endregion
418
+ //#region src/operations.ts
419
+ const CAPXUL_OPERATIONS = {
420
+ account: {
421
+ addressBook: {
422
+ add: "account.addressBook.add",
423
+ get: "account.addressBook.get",
424
+ hide: "account.addressBook.hide",
425
+ label: "account.addressBook.label",
426
+ list: "account.addressBook.list",
427
+ unhide: "account.addressBook.unhide"
428
+ },
429
+ balance: "account.balance",
430
+ faucetMint: "account.faucetMint",
431
+ getLifecycle: "account.getLifecycle",
432
+ readBalance: "account.readBalance",
433
+ retrySetup: "account.retrySetup",
434
+ status: "account.status",
435
+ profile: {
436
+ depositInstructions: "account.profile.depositInstructions",
437
+ get: "account.profile.get"
438
+ },
439
+ inbox: {
440
+ approve: "account.inbox.approve",
441
+ decline: "account.inbox.decline",
442
+ list: "account.inbox.list"
443
+ },
444
+ requests: {
445
+ cancel: "account.requests.cancel",
446
+ get: "account.requests.get",
447
+ issue: "account.requests.issue",
448
+ list: "account.requests.list"
449
+ }
450
+ },
451
+ accounts: {
452
+ fund: "accounts.fund",
453
+ read: "accounts.read"
454
+ },
455
+ activity: {
456
+ annotate: "activity.annotate",
457
+ emitAnnotationSaved: "activity.emitAnnotationSaved",
458
+ get: "activity.get",
459
+ list: "activity.list",
460
+ /** The SDK's live Activity read over the indexer's SSE stream. */
461
+ subscribe: "activity.subscribe",
462
+ summary: "activity.summary"
463
+ },
464
+ addressBook: {
465
+ add: "addressBook.add",
466
+ emitRelationshipChanged: "addressBook.emitRelationshipChanged",
467
+ get: "addressBook.get",
468
+ hide: "addressBook.hide",
469
+ label: "addressBook.label",
470
+ list: "addressBook.list",
471
+ unhide: "addressBook.unhide"
472
+ },
473
+ applications: { create: "applications.create" },
474
+ auth: {
475
+ canSendOtp: "auth.canSendOtp",
476
+ getSession: "auth.getSession",
477
+ signIn: "auth.signIn",
478
+ signOut: "auth.signOut",
479
+ sendVerificationOtp: "auth.sendVerificationOTP",
480
+ verifyOtp: "auth.verifyOtp"
481
+ },
482
+ client: {
483
+ createOrg: "createOrg",
484
+ orgs: "orgs"
485
+ },
486
+ /** AUTH A3 (#2073): the SDK facade over the native continuation endpoints. */
487
+ clientRequests: {
488
+ decide: "clientRequests.decide",
489
+ read: "clientRequests.read"
490
+ },
491
+ /** AUTH A2 (#2072): the native client authorization issuer and its browser
492
+ * continuation. One name per durable transition the endpoints can fail on. */
493
+ clientAuthorization: {
494
+ acceptRequest: "clientAuthorization.acceptRequest",
495
+ cancelRequest: "clientAuthorization.cancelRequest",
496
+ consumeRequest: "clientAuthorization.consumeRequest",
497
+ denyRequest: "clientAuthorization.denyRequest",
498
+ invalidateContext: "clientAuthorization.invalidateContext",
499
+ markConsented: "clientAuthorization.markConsented",
500
+ readMetadata: "clientAuthorization.readMetadata",
501
+ revokeGrant: "clientAuthorization.revokeGrant",
502
+ rotateGrant: "clientAuthorization.rotateGrant",
503
+ startRequest: "clientAuthorization.startRequest",
504
+ sweepExpired: "clientAuthorization.sweepExpired"
505
+ },
506
+ credentials: {
507
+ bootstrapClient: "credentials.bootstrapClient",
508
+ mintQuickstartKey: "credentials.mintQuickstartKey"
509
+ },
510
+ currentUser: { get: "currentUser.get" },
511
+ devIdentity: { seedFinancialOpsOrg: "devIdentity.seedFinancialOpsOrg" },
512
+ dev: { browserSeed: "dev.browserSeed" },
513
+ destinations: {
514
+ add: "destinations.add",
515
+ list: "destinations.list",
516
+ remove: "destinations.remove"
517
+ },
518
+ faucetSafe: { deploy: "FaucetSafe.deploy" },
519
+ financialOps: {
520
+ addDestination: "financialOps.addDestination",
521
+ approveRequest: "financialOps.approveRequest",
522
+ cancelRequest: "financialOps.cancelRequest",
523
+ createPayee: "financialOps.createPayee",
524
+ declineRequest: "financialOps.declineRequest",
525
+ emitInvoiceIssued: "financialOps.emitInvoiceIssued",
526
+ emitInvoiceRequestTransitioned: "financialOps.emitInvoiceRequestTransitioned",
527
+ emitPaymentWriterTelemetry: "financialOps.emitPaymentWriterTelemetry",
528
+ issueRequest: "financialOps.issueRequest",
529
+ migrateEvidenceIdentity: "financialOps.migrateEvidenceIdentity",
530
+ planEvidenceIdentity: "financialOps.planEvidenceIdentity",
531
+ recoverSettlementVerification: "financialOps.recoverSettlementVerification",
532
+ removeDestination: "financialOps.removeDestination",
533
+ verifySettlement: "financialOps.verifySettlement"
534
+ },
535
+ holdings: { current: "holdings.current" },
536
+ indexer: { reconcile: "indexer.reconcile" },
537
+ identity: {
538
+ accountAt: "identity.AccountAt",
539
+ accountClaimed: "identity.AccountClaimed",
540
+ accountClaiming: "identity.AccountClaiming",
541
+ accountDerived: "identity.AccountDerived",
542
+ accountFailed: "identity.AccountFailed",
543
+ attachOrganization: "identity.AttachOrganization",
544
+ claimAccount: "identity.ClaimAccount",
545
+ completeOnboarding: "identity.completeOnboarding",
546
+ completeProfile: "identity.completeProfile",
547
+ create: "identity.create",
548
+ createOrganization: "identity.CreateOrganization",
549
+ ensureAccount: "identity.EnsureAccount",
550
+ leaveOrganization: "identity.LeaveOrganization",
551
+ loadByAuthUserId: "identity.loadByAuthUserId",
552
+ loadCurrent: "identity.loadCurrent",
553
+ orgAt: "identity.OrgAt",
554
+ orgFailed: "identity.OrgFailed",
555
+ orgReady: "identity.OrgReady",
556
+ otpFailed: "identity.OtpFailed",
557
+ otpSent: "identity.OtpSent",
558
+ readSession: "identity.ReadSession",
559
+ requestOtp: "identity.RequestOtp",
560
+ reset: "identity.Reset",
561
+ restoreSession: "identity.RestoreSession",
562
+ resumeOtpEntry: "identity.ResumeOtpEntry",
563
+ retryAccount: "identity.RetryAccount",
564
+ retryOrganization: "identity.RetryOrganization",
565
+ sessionAbsent: "identity.SessionAbsent",
566
+ sessionRead: "identity.SessionRead",
567
+ sessionReadFailed: "identity.SessionReadFailed",
568
+ sessionRestored: "identity.SessionRestored",
569
+ signedOut: "identity.SignedOut",
570
+ signOut: "identity.SignOut",
571
+ signOutFailed: "identity.SignOutFailed",
572
+ update: "identity.update",
573
+ handleAvailable: "identity.handleAvailable",
574
+ verified: "identity.Verified",
575
+ verifyFailed: "identity.VerifyFailed",
576
+ verifyOtp: "identity.VerifyOtp"
577
+ },
578
+ media: {
579
+ generateUploadUrl: "media.generateUploadUrl",
580
+ setOrgLogo: "media.setOrgLogo",
581
+ setProfileImage: "media.setProfileImage",
582
+ uploadImage: "media.uploadImage"
583
+ },
584
+ me: {
585
+ depositInstructions: "me.depositInstructions",
586
+ get: "me.get"
587
+ },
588
+ moneyExecution: {
589
+ abandonPaymentExecution: "moneyExecution.abandonPaymentExecution",
590
+ prepareOrganizationPaymentExecution: "moneyExecution.prepareOrganizationPaymentExecution",
591
+ prepareRequestPaymentExecution: "moneyExecution.prepareRequestPaymentExecution",
592
+ preparePaymentExecution: "moneyExecution.preparePaymentExecution",
593
+ preparePaymentLifecycleExecution: "moneyExecution.preparePaymentLifecycleExecution",
594
+ prepareInvitationConfiguration: "moneyExecution.prepareInvitationConfiguration",
595
+ preparePermissionExecution: "moneyExecution.preparePermissionExecution",
596
+ recoverSubmissionClaims: "moneyExecution.recoverSubmissionClaims",
597
+ submit: "moneyExecution.submit",
598
+ prepareInvoiceCheckoutExecution: "moneyExecution.prepareInvoiceCheckoutExecution",
599
+ prepareOfferCheckoutExecution: "moneyExecution.prepareOfferCheckoutExecution",
600
+ submitPaymentCommandExecution: "moneyExecution.submitPaymentCommandExecution",
601
+ submitInvitationConfigurationExecution: "moneyExecution.submitInvitationConfigurationExecution",
602
+ submitPaymentExecution: "moneyExecution.submitPaymentExecution",
603
+ submitPermissionExecution: "moneyExecution.submitPermissionExecution"
604
+ },
605
+ movement: {
606
+ emitDepositSettled: "movement.emitDepositSettled",
607
+ scan: "movement.scan"
608
+ },
609
+ inbox: {
610
+ paymentTerms: "inbox.paymentTerms",
611
+ approve: "inbox.approve",
612
+ fulfill: "inbox.fulfill",
613
+ decline: "inbox.decline",
614
+ list: "inbox.list"
615
+ },
616
+ offramp: {
617
+ quote: "offramp.quote",
618
+ status: "offramp.status"
619
+ },
620
+ offers: {
621
+ create: "offers.create",
622
+ get: "offers.get",
623
+ list: "offers.list",
624
+ revise: "offers.revise",
625
+ deactivate: "offers.deactivate"
626
+ },
627
+ checkouts: {
628
+ request: "checkouts.request",
629
+ prepareRequest: "checkouts.prepareRequest",
630
+ requestState: "checkouts.requestState",
631
+ reconcileRequest: "checkouts.reconcileRequest",
632
+ prepareRequestRegistered: "checkouts.prepareRequestRegistered",
633
+ invoice: "checkouts.invoice",
634
+ prepareInvoice: "checkouts.prepareInvoice",
635
+ invoiceState: "checkouts.invoiceState",
636
+ reconcileInvoice: "checkouts.reconcileInvoice",
637
+ payInvoiceRegistered: "checkouts.payInvoiceRegistered",
638
+ prepareRegistered: "checkouts.prepareRegistered",
639
+ state: "checkouts.state",
640
+ reconcile: "checkouts.reconcile",
641
+ offer: "checkouts.offer",
642
+ create: "checkouts.create",
643
+ get: "checkouts.get",
644
+ prepare: "checkouts.prepare"
645
+ },
646
+ onboarding: {
647
+ completeOrganization: "onboarding.completeOrganization",
648
+ completePerson: "onboarding.completePerson"
649
+ },
650
+ org: {
651
+ account: { get: "org.account.get" },
652
+ auditLog: "org.auditLog",
653
+ confirmBootstrap: "org.confirmBootstrap",
654
+ createOrg: "org.createOrg",
655
+ create: "org.create",
656
+ /**
657
+ * §11: the consent mutation reports `org_invite_accepted` through its own
658
+ * scheduled emitter. It is named for the emit, not the acceptance, because
659
+ * the interactive acceptance itself owns `org.invitations.accept`.
660
+ */
661
+ emitInviteAccepted: "org.emitInviteAccepted",
662
+ emitInviteProgressed: "org.emitInviteProgressed",
663
+ expireInvitations: "org.expireInvitations",
664
+ getLifecycle: "org.getLifecycle",
665
+ getProofReceipt: "org.getProofReceipt",
666
+ invite: "org.invite",
667
+ /** D8 invitation lifecycle: preview, own list, read, and the four transitions. */
668
+ invitations: {
669
+ /** The exact grantee's consent commit (§8): one accepted digest, once. */
670
+ accept: "org.invitations.accept",
671
+ /**
672
+ * The authoring write. It is named `authorize`, not `invite`, because the
673
+ * backend already uses `org.invitations.invite` as a refusal label and
674
+ * `lint:telemetry-spine` refuses a label that collides with an operation.
675
+ */
676
+ authorize: "org.invitations.authorize",
677
+ cancel: "org.invitations.cancel",
678
+ decline: "org.invitations.decline",
679
+ get: "org.invitations.get",
680
+ subscribe: "org.invitations.subscribe",
681
+ list: "org.invitations.list",
682
+ /**
683
+ * The Admin-scoped Organization list. It is named `listScoped`, not
684
+ * `list`, because the own-offer list already owns `org.invitations.list`.
685
+ */
686
+ listScoped: "org.invitations.listScoped",
687
+ /**
688
+ * The authoring write's inner hops: the SDK drives the backend's existing
689
+ * prepare/submit pair, and these names label the two Convex calls. The
690
+ * owning `capxul_sdk_operation` record stays `org.invitations.authorize`.
691
+ */
692
+ prepareConfiguration: "org.invitations.prepareConfiguration",
693
+ preview: "org.invitations.preview",
694
+ resend: "org.invitations.resend",
695
+ retry: "org.invitations.retry",
696
+ submitConfiguration: "org.invitations.submitConfiguration"
697
+ },
698
+ list: "org.list",
699
+ load: "org.load",
700
+ me: "org.me",
701
+ members: "org.members",
702
+ orgs: "org.orgs",
703
+ payment: "org.payment",
704
+ permissions: {
705
+ assign: "org.permissions.assign",
706
+ change: "org.permissions.change",
707
+ create: "org.permissions.create",
708
+ get: "org.permissions.get",
709
+ getCommand: "org.permissions.getCommand",
710
+ subscribeCommand: "org.permissions.subscribeCommand",
711
+ list: "org.permissions.list",
712
+ replace: "org.permissions.replace",
713
+ previewReplacement: "org.permissions.previewReplacement",
714
+ revoke: "org.permissions.revoke"
715
+ },
716
+ payments: {
717
+ get: "org.payments.get",
718
+ list: "org.payments.list",
719
+ pay: "org.payments.pay",
720
+ payBatch: "org.payments.payBatch",
721
+ previewRetry: "org.payments.previewRetry",
722
+ subscribe: "org.payments.subscribe"
723
+ },
724
+ payroll: {
725
+ authorizeRun: "org.payroll.authorizeRun",
726
+ getRun: "org.payroll.getRun",
727
+ subscribeRun: "org.payroll.subscribeRun",
728
+ groups: {
729
+ list: "org.payroll.groups.list",
730
+ remove: "org.payroll.groups.remove",
731
+ save: "org.payroll.groups.save"
732
+ },
733
+ runs: "org.payroll.runs",
734
+ terms: "org.payroll.terms"
735
+ },
736
+ addressBook: {
737
+ add: "org.addressBook.add",
738
+ get: "org.addressBook.get",
739
+ hide: "org.addressBook.hide",
740
+ label: "org.addressBook.label",
741
+ list: "org.addressBook.list",
742
+ unhide: "org.addressBook.unhide"
743
+ },
744
+ inbox: {
745
+ approve: "org.inbox.approve",
746
+ decline: "org.inbox.decline",
747
+ list: "org.inbox.list"
748
+ },
749
+ lifecycle: { startOrResume: "org.lifecycle.startOrResume" },
750
+ prepareBootstrap: "org.prepareBootstrap",
751
+ prepareFounderAccount: "org.prepareFounderAccount",
752
+ profile: {
753
+ depositInstructions: "org.profile.depositInstructions",
754
+ get: "org.profile.get"
755
+ },
756
+ readTreasury: "org.readTreasury",
757
+ requests: {
758
+ cancel: "org.requests.cancel",
759
+ get: "org.requests.get",
760
+ issue: "org.requests.issue",
761
+ list: "org.requests.list"
762
+ },
763
+ recordFailure: "org.recordFailure",
764
+ recordProgress: "org.recordProgress",
765
+ resumeBootstrapSubmission: "org.resumeBootstrapSubmission",
766
+ retry: "org.retry",
767
+ retrySetup: "org.retrySetup",
768
+ roles: "org.roles",
769
+ startOrResume: "org.startOrResume",
770
+ submitBootstrap: "org.submitBootstrap",
771
+ treasury: "org.treasury"
772
+ },
773
+ organization: { setup: "organization.setup" },
774
+ organizationPayments: {
775
+ pay: "organizationPayments.pay",
776
+ payBatch: "organizationPayments.payBatch",
777
+ prepareExecution: "organizationPayments.prepareExecution",
778
+ retry: "organizationPayments.retry"
779
+ },
780
+ organizationSetup: { getProofReceipt: "organizationSetup.getProofReceipt" },
781
+ payments: {
782
+ cancel: "payments.cancel",
783
+ claim: "payments.claim",
784
+ createCommitment: "payments.createCommitment",
785
+ get: "payments.get",
786
+ ledger: "payments",
787
+ list: "payments.list",
788
+ pay: "payments.pay",
789
+ prepareExecution: "payments.prepareExecution",
790
+ prepareLifecycleExecution: "payments.prepareLifecycleExecution",
791
+ redirect: "payments.redirect",
792
+ retry: "payments.retry",
793
+ submitCommandExecution: "payments.submitCommandExecution",
794
+ submitExecution: "payments.submitExecution",
795
+ subscribe: "payments.subscribe"
796
+ },
797
+ paymentDocuments: {
798
+ get: "paymentDocuments.get",
799
+ render: "paymentDocuments.render",
800
+ verify: "paymentDocuments.verify"
801
+ },
802
+ recipient: { resolve: "recipient.resolve" },
803
+ payroll: {
804
+ authorizeRun: "payroll.authorizeRun",
805
+ getRun: "payroll.getRun",
806
+ subscribeRun: "payroll.subscribeRun",
807
+ emitGroupChanged: "payroll.emitGroupChanged",
808
+ emitRunTransitioned: "payroll.emitRunTransitioned",
809
+ groups: {
810
+ access: "payroll.groups",
811
+ list: "payroll.groups.list",
812
+ remove: "payroll.groups.remove",
813
+ save: "payroll.groups.save"
814
+ },
815
+ removeGroup: "payroll.removeGroup",
816
+ runs: "payroll.runs",
817
+ saveGroup: "payroll.saveGroup",
818
+ terms: "payroll.terms"
819
+ },
820
+ permission: {
821
+ getCommand: "permission.getCommand",
822
+ previewReplacement: "permission.previewReplacement",
823
+ verifyInvitationConfiguration: "permission.verifyInvitationConfiguration",
824
+ command: "permission.command",
825
+ retryVerification: "permission.retryVerification",
826
+ verify: "permission.verify",
827
+ verifySubmitted: "permission.verifySubmitted"
828
+ },
829
+ permissions: {
830
+ assign: "permissions.assign",
831
+ change: "permissions.change",
832
+ create: "permissions.create",
833
+ get: "permissions.get",
834
+ getCommand: "permissions.getCommand",
835
+ subscribeCommand: "permissions.subscribeCommand",
836
+ list: "permissions.list",
837
+ prepareExecution: "permissions.prepareExecution",
838
+ previewReplacement: "permissions.previewReplacement",
839
+ replace: "permissions.replace",
840
+ revoke: "permissions.revoke",
841
+ submitExecution: "permissions.submitExecution"
842
+ },
843
+ publishableKeys: {
844
+ mint: "publishableKeys.mint",
845
+ revoke: "publishableKeys.revoke",
846
+ rotate: "publishableKeys.rotate"
847
+ },
848
+ requests: {
849
+ cancel: "requests.cancel",
850
+ get: "requests.get",
851
+ issue: "requests.issue",
852
+ list: "requests.list"
853
+ },
854
+ runtime: {
855
+ assign: "assign",
856
+ canSendOtp: "canSendOtp",
857
+ cancelCommitment: "cancel_commitment",
858
+ change: "change",
859
+ claimCommitment: "claim_commitment",
860
+ create: "create",
861
+ createCapxulClient: "createCapxulClient",
862
+ createCapxulClientWithOrgDeploymentSeams: "createCapxulClientWithOrgDeploymentSeams",
863
+ createCommitment: "create_commitment",
864
+ getConvexJwt: "getConvexJwt",
865
+ getSession: "getSession",
866
+ initialize: "initialize",
867
+ mutation: "mutation",
868
+ now: "now",
869
+ port: "port",
870
+ query: "query",
871
+ redirectCommitment: "redirect_commitment",
872
+ replace: "replace",
873
+ resolve: "resolve",
874
+ revoke: "revoke",
875
+ send: "send",
876
+ sendOtp: "sendOtp",
877
+ signIn: "signIn",
878
+ signOut: "signOut",
879
+ sleep: "sleep",
880
+ verifyOtp: "verifyOtp",
881
+ wallet: "wallet"
882
+ },
883
+ smartAccount: {
884
+ claim: "smartAccount.claim",
885
+ confirmDeployment: "smartAccount.confirmDeployment",
886
+ loadByAuthUserId: "smartAccount.loadByAuthUserId",
887
+ loadCurrent: "smartAccount.loadCurrent",
888
+ provision: "smartAccount.provision"
889
+ },
890
+ system: {
891
+ health: "system.health",
892
+ ping: "system.ping",
893
+ runtimeChain: "system.runtimeChain"
894
+ },
895
+ testUsdc: { mint: "TestUSDC.mint" },
896
+ _internal: {
897
+ accounts: { fund: "_internal.accounts.fund" },
898
+ close: "_internal.close",
899
+ identity: {
900
+ completeProfile: "_internal.identity.completeProfile",
901
+ runFacade: "_internal.identity.runFacade",
902
+ send: "_internal.identity.send"
903
+ },
904
+ organizationSetup: { getProofReceipt: "_internal.organizationSetup.getProofReceipt" }
905
+ },
906
+ tenancy: {
907
+ revokeBackendTenancyConsent: "tenancy.revokeBackendTenancyConsent",
908
+ seedBackendTenancy: "tenancy.seedBackendTenancy"
909
+ }
910
+ };
911
+ function collectOperations(tree) {
912
+ return Object.values(tree).flatMap((value) => typeof value === "string" ? [value] : collectOperations(value));
913
+ }
914
+ const operations = new Set(collectOperations(CAPXUL_OPERATIONS));
915
+ function isCapxulOperation(value) {
916
+ return typeof value === "string" && operations.has(value);
917
+ }
918
+ function normalizeCapxulOperation(value) {
919
+ return isCapxulOperation(value) ? value : "unknown";
920
+ }
921
+ //#endregion
922
+ //#region src/index.ts
923
+ const TELEMETRY_EVENT_NAMES = [
924
+ "auth_otp_requested",
925
+ "auth_otp_delivered",
926
+ "auth_otp_expired",
927
+ "auth_verified",
928
+ "auth_failed",
929
+ "identity_refused",
930
+ "auth_signed_out",
931
+ "native_authorization_started",
932
+ "native_authorization_reviewed",
933
+ "native_authorization_accepted",
934
+ "native_authorization_denied",
935
+ "native_authorization_connected",
936
+ "native_authorization_failed",
937
+ "onboarding_intent_selected",
938
+ "onboarding_profile_submitted",
939
+ "onboarding_organization_submitted",
940
+ "onboarding_dashboard_reached",
941
+ "provisioning_safe_created",
942
+ "provisioning_safe_confirmed",
943
+ "bootstrap_resolved",
944
+ "bootstrap_failed",
945
+ "member_activation_started",
946
+ "member_activation_ready",
947
+ "member_activation_failed",
948
+ "organization_creation_started",
949
+ "organization_creation_ready",
950
+ "organization_creation_failed",
951
+ "chain_upstream_fallback",
952
+ "bundler_error",
953
+ "receipt_pending",
954
+ "operation_retried",
955
+ "account_balance_read",
956
+ "account_balance_failed",
957
+ "faucet_requested",
958
+ "faucet_confirmed",
959
+ "faucet_failed",
960
+ "org_create_started",
961
+ "org_safe_created",
962
+ "org_safe_confirmed",
963
+ "org_roles_seeded",
964
+ "org_created",
965
+ "org_create_failed",
966
+ "org_invite_sent",
967
+ "org_invite_accepted",
968
+ "org_invite_expired",
969
+ "payment_initiated",
970
+ "payment_settled",
971
+ "payment_failed",
972
+ "payment_verification_retry",
973
+ "payment_lifecycle_transition",
974
+ "quick_pay_external_address_acknowledged",
975
+ "deposit_initiated",
976
+ "deposit_settled",
977
+ "permission_mirror_verification",
978
+ "movement_scan_window",
979
+ "movement_scan_checkpoint",
980
+ "movement_scan_incident",
981
+ "indexer_drift_corrected",
982
+ "activity_annotation_saved",
983
+ "ui_activity_action_completed",
984
+ "contact_relationship_changed",
985
+ "ui_contact_action_completed",
986
+ "access_recovery_completed",
987
+ "ui_access_step_completed",
988
+ "org_invite_progressed",
989
+ "invoice_issued",
990
+ "invoice_request_transitioned",
991
+ "ui_invoice_step_completed",
992
+ "ui_treasury_step_completed",
993
+ "ui_receive_step_completed",
994
+ "payroll_group_changed",
995
+ "payroll_run_transitioned",
996
+ "ui_payroll_action_completed",
997
+ "cli_diagnostic_completed",
998
+ "cli_first_used",
999
+ "cli_command_started",
1000
+ "cli_command_completed"
1001
+ ];
1002
+ const TELEMETRY_JOURNEYS = {
1003
+ returning_user_login: {
1004
+ type: "funnel",
1005
+ steps: [
1006
+ "auth_otp_requested",
1007
+ "auth_otp_delivered",
1008
+ "auth_verified"
1009
+ ],
1010
+ drops_on: ["auth_otp_expired", "auth_failed"]
1011
+ },
1012
+ new_user_first_signin: {
1013
+ type: "funnel",
1014
+ steps: [
1015
+ "auth_otp_requested",
1016
+ "auth_otp_delivered",
1017
+ "auth_verified",
1018
+ "provisioning_safe_created",
1019
+ "provisioning_safe_confirmed"
1020
+ ],
1021
+ drops_on: ["auth_otp_expired", "auth_failed"]
1022
+ },
1023
+ sign_out_session_close: {
1024
+ type: "point_event",
1025
+ point_event: "auth_signed_out"
1026
+ },
1027
+ member_activation: {
1028
+ type: "funnel",
1029
+ steps: ["member_activation_started", "member_activation_ready"],
1030
+ drops_on: ["member_activation_failed"]
1031
+ },
1032
+ organization_creation_lifecycle: {
1033
+ type: "funnel",
1034
+ steps: ["organization_creation_started", "organization_creation_ready"],
1035
+ drops_on: ["organization_creation_failed"]
1036
+ },
1037
+ new_member_personal_dashboard: {
1038
+ type: "funnel",
1039
+ steps: [
1040
+ "auth_verified",
1041
+ "onboarding_intent_selected",
1042
+ "onboarding_profile_submitted",
1043
+ "member_activation_ready",
1044
+ "onboarding_dashboard_reached"
1045
+ ],
1046
+ step_filters: {
1047
+ onboarding_intent_selected: [{
1048
+ key: "intent",
1049
+ value: ["personal"],
1050
+ operator: "exact",
1051
+ type: "event"
1052
+ }, {
1053
+ key: "entry_point",
1054
+ value: ["signup"],
1055
+ operator: "exact",
1056
+ type: "event"
1057
+ }],
1058
+ onboarding_profile_submitted: [{
1059
+ key: "intent",
1060
+ value: ["personal"],
1061
+ operator: "exact",
1062
+ type: "event"
1063
+ }],
1064
+ onboarding_dashboard_reached: [{
1065
+ key: "intent",
1066
+ value: ["personal"],
1067
+ operator: "exact",
1068
+ type: "event"
1069
+ }]
1070
+ }
1071
+ },
1072
+ new_member_organization_dashboard: {
1073
+ type: "funnel",
1074
+ steps: [
1075
+ "auth_verified",
1076
+ "onboarding_intent_selected",
1077
+ "onboarding_profile_submitted",
1078
+ "onboarding_organization_submitted",
1079
+ "member_activation_started",
1080
+ "member_activation_ready",
1081
+ "organization_creation_started",
1082
+ "organization_creation_ready",
1083
+ "onboarding_dashboard_reached"
1084
+ ],
1085
+ step_filters: {
1086
+ onboarding_intent_selected: [{
1087
+ key: "intent",
1088
+ value: ["organization"],
1089
+ operator: "exact",
1090
+ type: "event"
1091
+ }, {
1092
+ key: "entry_point",
1093
+ value: ["signup"],
1094
+ operator: "exact",
1095
+ type: "event"
1096
+ }],
1097
+ onboarding_profile_submitted: [{
1098
+ key: "intent",
1099
+ value: ["organization"],
1100
+ operator: "exact",
1101
+ type: "event"
1102
+ }],
1103
+ onboarding_dashboard_reached: [{
1104
+ key: "intent",
1105
+ value: ["organization"],
1106
+ operator: "exact",
1107
+ type: "event"
1108
+ }]
1109
+ }
1110
+ },
1111
+ existing_member_organization_dashboard: {
1112
+ type: "funnel",
1113
+ steps: [
1114
+ "onboarding_intent_selected",
1115
+ "onboarding_organization_submitted",
1116
+ "organization_creation_started",
1117
+ "organization_creation_ready",
1118
+ "onboarding_dashboard_reached"
1119
+ ],
1120
+ step_filters: {
1121
+ onboarding_intent_selected: [{
1122
+ key: "intent",
1123
+ value: ["organization"],
1124
+ operator: "exact",
1125
+ type: "event"
1126
+ }, {
1127
+ key: "entry_point",
1128
+ value: ["dashboard"],
1129
+ operator: "exact",
1130
+ type: "event"
1131
+ }],
1132
+ onboarding_dashboard_reached: [{
1133
+ key: "intent",
1134
+ value: ["organization"],
1135
+ operator: "exact",
1136
+ type: "event"
1137
+ }]
1138
+ }
1139
+ },
1140
+ money_on_screen: {
1141
+ type: "point_event",
1142
+ point_event: "account_balance_read"
1143
+ },
1144
+ fund_account: {
1145
+ type: "funnel",
1146
+ steps: ["faucet_requested", "faucet_confirmed"],
1147
+ drops_on: ["faucet_failed"]
1148
+ },
1149
+ org_creation: {
1150
+ type: "funnel",
1151
+ steps: [
1152
+ "org_create_started",
1153
+ "org_safe_created",
1154
+ "org_safe_confirmed",
1155
+ "org_roles_seeded",
1156
+ "org_created"
1157
+ ],
1158
+ drops_on: ["org_create_failed"]
1159
+ },
1160
+ org_member_onboarding: {
1161
+ type: "funnel",
1162
+ steps: ["org_invite_sent", "org_invite_accepted"],
1163
+ drops_on: ["org_invite_expired"]
1164
+ },
1165
+ direct_payment: {
1166
+ type: "funnel",
1167
+ steps: ["payment_initiated", "payment_settled"],
1168
+ drops_on: ["payment_failed"]
1169
+ },
1170
+ deposit: {
1171
+ type: "funnel",
1172
+ steps: ["deposit_initiated", "deposit_settled"]
1173
+ }
1174
+ };
1175
+ const PII = Schema.String.pipe(Schema.brand("PII"));
1176
+ const OptionalString = Schema.optional(Schema.String);
1177
+ const AddressSchema = Schema.String.pipe(Schema.decodeTo(Schema.String, {
1178
+ decode: SchemaGetter.transform((value) => value.toLowerCase()),
1179
+ encode: SchemaGetter.transform((value) => value)
1180
+ }), Schema.refine((value) => EVM_ADDRESS_RE.test(value), { message: "must be 0x + 40 hex chars" }));
1181
+ const AppIdSchema = Schema.String.pipe(Schema.refine((value) => APP_ID_RE.test(value), { message: "must be app_ plus a ULID" }));
1182
+ const BlockNumberSchema = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" }));
1183
+ const ChainIdSchema = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value > 0, { message: "must be a positive safe integer" }));
1184
+ const DurationMsSchema = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" }));
1185
+ const EpochMsSchema = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value >= 0, { message: "must be a non-negative safe integer" }));
1186
+ const PublishableKeyIdSchema = Schema.String.pipe(Schema.refine((value) => value.length > 0, { message: "must be a non-empty string" }));
1187
+ const TxHashSchema = Schema.String.pipe(Schema.refine((value) => BYTES32_RE.test(value), { message: "must be 0x + 64 hex chars" }));
1188
+ const ACCOUNT_ID_TELEMETRY_RE = /^account_[0-9A-Za-z]+$/;
1189
+ const WEI_AMOUNT_TELEMETRY_RE = /^[0-9]+$/;
1190
+ const AccountIdSchema = Schema.String.pipe(Schema.refine((value) => ACCOUNT_ID_TELEMETRY_RE.test(value), { message: "must be account_ plus an alphanumeric id" }));
1191
+ const WeiAmountSchema = Schema.String.pipe(Schema.refine((value) => WEI_AMOUNT_TELEMETRY_RE.test(value), { message: "must be a non-negative integer string" }));
1192
+ const CurrencyCodeSchema = Schema.String.pipe(Schema.refine((value) => value.length > 0, { message: "must be a non-empty currency code" }));
1193
+ const BalanceBucketSchema = Schema.Literals(["zero", "nonzero"]);
1194
+ const OptionalAccountId = Schema.optional(AccountIdSchema);
1195
+ const OptionalWeiAmount = Schema.optional(WeiAmountSchema);
1196
+ const OptionalCurrencyCode = Schema.optional(CurrencyCodeSchema);
1197
+ const OptionalBalanceBucket = Schema.optional(BalanceBucketSchema);
1198
+ /** Which Safe a money record is about. Declared here so the money-domain
1199
+ * props below can name it as well as the UI-step props further down. */
1200
+ const AccountKindSchema = Schema.Literals(["personalSafe", "orgTreasury"]);
1201
+ const OptionalAccountKind = Schema.optional(AccountKindSchema);
1202
+ const OptionalAddress = Schema.optional(AddressSchema);
1203
+ const OptionalAppId = Schema.optional(AppIdSchema);
1204
+ const OptionalBlockNumber = Schema.optional(BlockNumberSchema);
1205
+ const OptionalChainId = Schema.optional(ChainIdSchema);
1206
+ const OptionalDurationMs = Schema.optional(DurationMsSchema);
1207
+ const OptionalEpochMs = Schema.optional(EpochMsSchema);
1208
+ const OptionalPublishableKeyId = Schema.optional(PublishableKeyIdSchema);
1209
+ const OptionalTxHash = Schema.optional(TxHashSchema);
1210
+ /**
1211
+ * Environment discriminator (ADR-0020 A1 amendment, 2026-08-07). PostHog
1212
+ * project 368736 is the SINGLE sink for every environment, so `capxul_env` —
1213
+ * not project isolation — is what keeps a production surface from reading dev
1214
+ * traffic. It is REQUIRED on every catalog event and every synced artifact
1215
+ * filters on it.
1216
+ *
1217
+ * `unknown` is a defect marker, not an environment: it means a producer
1218
+ * reached the transport without declaring where it runs. It is in the union so
1219
+ * the property is never ABSENT (an absent property is invisible to a filter,
1220
+ * a present `unknown` is loud), and sync v2 never synthesizes an artifact for
1221
+ * it.
1222
+ */
1223
+ const CAPXUL_ENVS = [
1224
+ "development",
1225
+ "staging",
1226
+ "production",
1227
+ "unknown",
1228
+ "local"
1229
+ ];
1230
+ /**
1231
+ * Environments a synced product surface may be built for. `unknown` and
1232
+ * `local` cannot. This list is deliberately narrower than `CAPXUL_ENVS`.
1233
+ */
1234
+ const SYNCABLE_CAPXUL_ENVS = [
1235
+ "development",
1236
+ "staging",
1237
+ "production"
1238
+ ];
1239
+ /**
1240
+ * Which half of the system emitted the event. REQUIRED alongside `capxul_env`
1241
+ * so a name that two halves can produce (settlement, auth) stays attributable.
1242
+ */
1243
+ const TELEMETRY_PRODUCERS = [
1244
+ "server",
1245
+ "browser",
1246
+ "sdk",
1247
+ "mcp",
1248
+ "e2e"
1249
+ ];
1250
+ /**
1251
+ * The canonical envelope (ADR-0020 A4): snake_case ONLY. `capxul_env` and
1252
+ * `producer` are REQUIRED — a boundary that forgets to stamp them fails schema
1253
+ * decode instead of silently shipping an unattributable event. Call sites do
1254
+ * not pass them: `stampTelemetryEnvelope` injects them at the emit boundary,
1255
+ * which is the only place that knows where the process runs.
1256
+ */
1257
+ const TelemetryEnvelopeProps = {
1258
+ capxul_env: Schema.Literals(CAPXUL_ENVS),
1259
+ producer: Schema.Literals(TELEMETRY_PRODUCERS),
1260
+ journey_id: OptionalString,
1261
+ correlation_id: OptionalString,
1262
+ sdk_version: OptionalString
1263
+ };
1264
+ /**
1265
+ * The cause of a failure, flat (ADR-0023 R7–R8). `failure_mode` is the one
1266
+ * word from `@capxul/errors`; the `chain_*` keys are the `ChainCause` when the
1267
+ * failure came from the chain path. Spread into every failure event and posted
1268
+ * on `$exception`, so one PostHog filter finds a cause wherever it was seen.
1269
+ */
1270
+ const FailureModeSchema = Schema.Literals(FAILURE_MODES);
1271
+ const ChainUpstreamSchema = Schema.Literals(CHAIN_UPSTREAMS);
1272
+ /**
1273
+ * The refusing upstream's response headers (#1818): exactly the names in
1274
+ * `RESPONSE_HEADER_ALLOWLIST`, each optional, so the catalog itself refuses a
1275
+ * `set-cookie` or `authorization` that a producer let through.
1276
+ */
1277
+ const ResponseHeadersSchema = Schema.Struct({
1278
+ "retry-after": OptionalString,
1279
+ "www-authenticate": OptionalString,
1280
+ "content-type": OptionalString,
1281
+ "x-request-id": OptionalString,
1282
+ "cf-ray": OptionalString,
1283
+ "x-ratelimit-remaining": OptionalString,
1284
+ "x-ratelimit-reset": OptionalString,
1285
+ server: OptionalString
1286
+ });
1287
+ /** One upstream tried, flat (#1818): the `chain_attempts` entry on every producer's row. */
1288
+ const ChainAttemptSchema = Schema.Struct({
1289
+ upstream: ChainUpstreamSchema,
1290
+ failure_mode: FailureModeSchema,
1291
+ http_status: Schema.optional(Schema.Number),
1292
+ rpc_code: Schema.optional(Schema.Number),
1293
+ duration_ms: Schema.Number
1294
+ });
1295
+ const ChainCauseTelemetryProps = {
1296
+ failure_mode: Schema.optional(FailureModeSchema),
1297
+ chain_upstream: Schema.optional(ChainUpstreamSchema),
1298
+ chain_method: OptionalString,
1299
+ chain_retryable: Schema.optional(Schema.Boolean),
1300
+ chain_http_status: Schema.optional(Schema.Number),
1301
+ chain_rpc_code: Schema.optional(Schema.Number),
1302
+ chain_revert_name: OptionalString,
1303
+ chain_revert_selector: OptionalString,
1304
+ chain_revert_args: Schema.optional(Schema.Record(Schema.String, Schema.String)),
1305
+ chain_provider_message: OptionalString,
1306
+ chain_attempts: Schema.optional(Schema.Array(ChainAttemptSchema)),
1307
+ chain_response_headers: Schema.optional(ResponseHeadersSchema)
1308
+ };
1309
+ /**
1310
+ * Stamp the required envelope onto an event at its emit boundary. Call-site
1311
+ * props win on conflict: a relay that already knows the true producer (the
1312
+ * browser-failure relay stamps `browser` while running on the server) must not
1313
+ * be overwritten by the transport's own default.
1314
+ */
1315
+ function stampTelemetryEnvelope(event, defaults) {
1316
+ return {
1317
+ name: event.name,
1318
+ props: {
1319
+ ...defaults,
1320
+ ...event.props
1321
+ }
1322
+ };
1323
+ }
1324
+ const AuthOtpRequestedProps = Schema.Struct({
1325
+ ...TelemetryEnvelopeProps,
1326
+ email: Schema.optional(PII),
1327
+ email_domain: OptionalString
1328
+ });
1329
+ const AuthOtpDeliveredProps = Schema.Struct({
1330
+ ...TelemetryEnvelopeProps,
1331
+ durationMs: OptionalDurationMs,
1332
+ email: Schema.optional(PII),
1333
+ email_domain: OptionalString,
1334
+ resendMessageId: OptionalString
1335
+ });
1336
+ const AuthOtpExpiredProps = Schema.Struct({
1337
+ ...TelemetryEnvelopeProps,
1338
+ email: Schema.optional(PII),
1339
+ email_domain: OptionalString
1340
+ });
1341
+ const AuthVerifiedProps = Schema.Struct({
1342
+ ...TelemetryEnvelopeProps,
1343
+ auth_type: OptionalString
1344
+ });
1345
+ const AuthFailedProps = Schema.Struct({
1346
+ ...TelemetryEnvelopeProps,
1347
+ ...ChainCauseTelemetryProps,
1348
+ email: Schema.optional(PII),
1349
+ auth_type: OptionalString,
1350
+ reason: OptionalString
1351
+ });
1352
+ const IdentityRefusedProps = Schema.Struct({
1353
+ ...TelemetryEnvelopeProps,
1354
+ /** The refused identity event tag, for example CreateOrganization. */
1355
+ event: OptionalString,
1356
+ /** The machine's refusal code: WRONG_STATE, SUPERSEDED or STALE_EPOCH. */
1357
+ refusal_code: OptionalString,
1358
+ /** The machine slot the request targeted, for example identity:org. */
1359
+ slot: OptionalString,
1360
+ /** The machine state at refusal, for example authenticated:claiming. */
1361
+ state: OptionalString
1362
+ });
1363
+ const AuthSignedOutProps = Schema.Struct(TelemetryEnvelopeProps);
1364
+ const NativeAuthorizationMode = Schema.Literals(["login", "signup"]);
1365
+ const NativeAuthorizationStartedProps = Schema.Struct({
1366
+ ...TelemetryEnvelopeProps,
1367
+ mode: NativeAuthorizationMode
1368
+ });
1369
+ const NativeAuthorizationReviewedProps = Schema.Struct({
1370
+ ...TelemetryEnvelopeProps,
1371
+ mode: NativeAuthorizationMode
1372
+ });
1373
+ const NativeAuthorizationAcceptedProps = Schema.Struct({
1374
+ ...TelemetryEnvelopeProps,
1375
+ mode: NativeAuthorizationMode,
1376
+ /** Whether consent also had to finish account setup first. */
1377
+ setup_state: Schema.optional(Schema.Literals([
1378
+ "not_required",
1379
+ "new",
1380
+ "resumable"
1381
+ ]))
1382
+ });
1383
+ const NativeAuthorizationDeniedProps = Schema.Struct({
1384
+ ...TelemetryEnvelopeProps,
1385
+ mode: NativeAuthorizationMode
1386
+ });
1387
+ const NativeAuthorizationConnectedProps = Schema.Struct({
1388
+ ...TelemetryEnvelopeProps,
1389
+ mode: NativeAuthorizationMode
1390
+ });
1391
+ const NativeAuthorizationFailedProps = Schema.Struct({
1392
+ ...TelemetryEnvelopeProps,
1393
+ mode: Schema.optional(NativeAuthorizationMode),
1394
+ /** The refusal word the store returned, for example `identity_mismatch` or
1395
+ * `request_expired`. These are the closed `CLIENT_AUTHORIZATION_REFUSALS` from
1396
+ * `@capxul/wire` plus the store-internal `fresh_session_required` (ruling R3),
1397
+ * which the continuation maps to `identity_mismatch` on the wire but reports
1398
+ * truthfully here. Kept as `OptionalString` rather than an imported literal
1399
+ * set: this package must not depend on the transport contract. */
1400
+ reason: OptionalString
1401
+ });
1402
+ const ProvisioningSafeCreatedProps = Schema.Struct({
1403
+ ...TelemetryEnvelopeProps,
1404
+ safe_address: OptionalAddress
1405
+ });
1406
+ const ProvisioningSafeConfirmedProps = Schema.Struct({
1407
+ ...TelemetryEnvelopeProps,
1408
+ chainId: OptionalChainId,
1409
+ deployedAt: OptionalEpochMs,
1410
+ deployedAtBlock: OptionalBlockNumber,
1411
+ deployTxHash: OptionalTxHash,
1412
+ durationMs: OptionalDurationMs,
1413
+ safe_address: OptionalAddress,
1414
+ userOpHash: OptionalTxHash
1415
+ });
1416
+ const BootstrapResolvedProps = Schema.Struct({
1417
+ ...TelemetryEnvelopeProps,
1418
+ applicationId: OptionalAppId,
1419
+ durationMs: OptionalDurationMs,
1420
+ env: OptionalString,
1421
+ keyId: OptionalPublishableKeyId,
1422
+ origin: OptionalString
1423
+ });
1424
+ const BootstrapFailedProps = Schema.Struct({
1425
+ ...TelemetryEnvelopeProps,
1426
+ ...ChainCauseTelemetryProps,
1427
+ applicationId: OptionalAppId,
1428
+ durationMs: OptionalDurationMs,
1429
+ origin: OptionalString,
1430
+ provider: OptionalString,
1431
+ provider_operation: OptionalString,
1432
+ reason: OptionalString,
1433
+ target_host: OptionalString
1434
+ });
1435
+ /**
1436
+ * R08 (#1966): which Safe was read, on which chain, of which token. `currency`
1437
+ * is the DISPLAY code the surface shows ("USD"); it never says which ERC-20 the
1438
+ * `balanceOf` actually hit, so a reader could not tell a treasury read from a
1439
+ * personal one, nor one token from another with the same fiat peg. The producer
1440
+ * takes each of these from the authority that already decided it — the verified
1441
+ * Organization row's chain, the configured token address — never from a label.
1442
+ * The verified `organization_id` and its group arrive from the backend
1443
+ * attribution, so they are not repeated here.
1444
+ *
1445
+ * D1 (2026-09-10): `asset_id` carries the canonical branded identity the read
1446
+ * resolved, `eip155:<chainId>/erc20:<lowercase-address>`, from the registry
1447
+ * row. `token_address`/`chain_id` are its parts; `currency` is the peg and a
1448
+ * display code. The producer emits the branded id so the live read can be
1449
+ * grouped by ASSET, never by symbol or peg.
1450
+ */
1451
+ const AccountBalanceReadProps = Schema.Struct({
1452
+ ...TelemetryEnvelopeProps,
1453
+ account_id: OptionalAccountId,
1454
+ account_kind: OptionalAccountKind,
1455
+ chain_id: OptionalChainId,
1456
+ token_address: OptionalAddress,
1457
+ asset_id: OptionalString,
1458
+ currency: OptionalCurrencyCode,
1459
+ balance_bucket: OptionalBalanceBucket,
1460
+ durationMs: OptionalDurationMs
1461
+ });
1462
+ const AccountBalanceFailedProps = Schema.Struct({
1463
+ ...TelemetryEnvelopeProps,
1464
+ ...ChainCauseTelemetryProps,
1465
+ reason: OptionalString
1466
+ });
1467
+ const FaucetRequestedProps = Schema.Struct({
1468
+ ...TelemetryEnvelopeProps,
1469
+ amount: OptionalWeiAmount,
1470
+ chainId: OptionalChainId,
1471
+ asset_id: OptionalString
1472
+ });
1473
+ const FaucetConfirmedProps = Schema.Struct({
1474
+ ...TelemetryEnvelopeProps,
1475
+ amount: OptionalWeiAmount,
1476
+ chainId: OptionalChainId,
1477
+ txHash: OptionalTxHash,
1478
+ asset_id: OptionalString,
1479
+ token_address: OptionalAddress,
1480
+ durationMs: OptionalDurationMs
1481
+ });
1482
+ const FaucetFailedProps = Schema.Struct({
1483
+ ...TelemetryEnvelopeProps,
1484
+ ...ChainCauseTelemetryProps,
1485
+ reason: OptionalString,
1486
+ amount: OptionalWeiAmount,
1487
+ chainId: OptionalChainId,
1488
+ asset_id: OptionalString,
1489
+ token_address: OptionalAddress
1490
+ });
1491
+ const ChainServiceSchema = Schema.Literals(["aa-gateway", "backend"]);
1492
+ const ChainUpstreamFallbackProps = Schema.Struct({
1493
+ ...TelemetryEnvelopeProps,
1494
+ service: ChainServiceSchema,
1495
+ method: Schema.String,
1496
+ from_upstream: ChainUpstreamSchema,
1497
+ to_upstream: Schema.optional(ChainUpstreamSchema),
1498
+ failure_mode: FailureModeSchema,
1499
+ exhausted: Schema.Boolean,
1500
+ http_status: Schema.optional(Schema.Number),
1501
+ rpc_code: Schema.optional(Schema.Number),
1502
+ response_headers: Schema.optional(ResponseHeadersSchema)
1503
+ });
1504
+ const BundlerErrorProps = Schema.Struct({
1505
+ ...TelemetryEnvelopeProps,
1506
+ method: Schema.String,
1507
+ failure_mode: FailureModeSchema,
1508
+ chain_upstream: ChainUpstreamSchema,
1509
+ chain_retryable: Schema.Boolean,
1510
+ http_status: Schema.optional(Schema.Number),
1511
+ rpc_code: Schema.optional(Schema.Number),
1512
+ chain_revert_name: OptionalString,
1513
+ chain_provider_message: OptionalString
1514
+ });
1515
+ const ReceiptPendingProps = Schema.Struct({
1516
+ ...TelemetryEnvelopeProps,
1517
+ service: ChainServiceSchema,
1518
+ method: Schema.String,
1519
+ chain_upstream: ChainUpstreamSchema,
1520
+ reason: Schema.Literals(["zero_block_hash", "no_receipt"])
1521
+ });
1522
+ const OperationRetriedProps = Schema.Struct({
1523
+ ...TelemetryEnvelopeProps,
1524
+ operation: Schema.String,
1525
+ failure_mode: FailureModeSchema,
1526
+ reason: Schema.optional(Schema.Literal("connection-lost-in-flight")),
1527
+ connection_id: OptionalString,
1528
+ connection_count: Schema.optional(Schema.Number),
1529
+ attempt: Schema.Number,
1530
+ delay_ms: DurationMsSchema
1531
+ });
1532
+ const ORG_ID_TELEMETRY_RE = /^org_[0-9A-Za-z]+$/;
1533
+ const OrgIdTelemetrySchema = Schema.String.pipe(Schema.refine((value) => ORG_ID_TELEMETRY_RE.test(value), { message: "must be org_ plus an alphanumeric id" }));
1534
+ const OptionalOrgId = Schema.optional(OrgIdTelemetrySchema);
1535
+ const AttemptNumberSchema = Schema.Number.pipe(Schema.refine((value) => Number.isSafeInteger(value) && value > 0, { message: "must be a positive safe integer" }));
1536
+ const OnboardingStageSchema = Schema.Literals([
1537
+ "profile",
1538
+ "accountProvisioning",
1539
+ "accountClaim",
1540
+ "preparingFounderAccount",
1541
+ "awaitingFounderAuthorization",
1542
+ "submittingBootstrap",
1543
+ "confirmingBootstrap"
1544
+ ]);
1545
+ const MemberActivationStartedProps = Schema.Struct({
1546
+ ...TelemetryEnvelopeProps,
1547
+ $insert_id: Schema.String
1548
+ });
1549
+ const MemberActivationReadyProps = Schema.Struct({
1550
+ ...TelemetryEnvelopeProps,
1551
+ $insert_id: Schema.String,
1552
+ duration_ms: DurationMsSchema
1553
+ });
1554
+ const MemberActivationFailedProps = Schema.Struct({
1555
+ ...TelemetryEnvelopeProps,
1556
+ ...ChainCauseTelemetryProps,
1557
+ $insert_id: Schema.String,
1558
+ stage: OnboardingStageSchema,
1559
+ error_code: Schema.String,
1560
+ retryable: Schema.Boolean
1561
+ });
1562
+ const OrganizationCreationStartedProps = Schema.Struct({
1563
+ ...TelemetryEnvelopeProps,
1564
+ $insert_id: Schema.String,
1565
+ organization_id: OrgIdTelemetrySchema,
1566
+ attempt_number: AttemptNumberSchema,
1567
+ release: Schema.optional(Schema.String.check(Schema.isPattern(/^[0-9a-f]{40}$/u)))
1568
+ });
1569
+ const OrganizationCreationReadyProps = Schema.Struct({
1570
+ ...TelemetryEnvelopeProps,
1571
+ $insert_id: Schema.String,
1572
+ organization_id: OrgIdTelemetrySchema,
1573
+ attempt_number: AttemptNumberSchema,
1574
+ duration_ms: DurationMsSchema,
1575
+ release: Schema.optional(Schema.String.check(Schema.isPattern(/^[0-9a-f]{40}$/u)))
1576
+ });
1577
+ const OrganizationCreationFailedProps = Schema.Struct({
1578
+ ...TelemetryEnvelopeProps,
1579
+ ...ChainCauseTelemetryProps,
1580
+ $insert_id: Schema.String,
1581
+ organization_id: OrgIdTelemetrySchema,
1582
+ attempt_number: AttemptNumberSchema,
1583
+ stage: OnboardingStageSchema,
1584
+ error_code: Schema.String,
1585
+ retryable: Schema.Boolean,
1586
+ release: Schema.optional(Schema.String.check(Schema.isPattern(/^[0-9a-f]{40}$/u))),
1587
+ /** #1655: the SDK's backoff before this attempt. Absent on the first attempt. */
1588
+ backoff_ms: Schema.optional(DurationMsSchema),
1589
+ failure_reason: Schema.optional(Schema.Literals([
1590
+ "receipt_provider_unavailable",
1591
+ "block_provider_unavailable",
1592
+ ...ORGANIZATION_SETUP_REASONS
1593
+ ]))
1594
+ });
1595
+ const OnboardingIntentSchema = Schema.Literals(["personal", "organization"]);
1596
+ const OnboardingIntentSelectedProps = Schema.Struct({
1597
+ ...TelemetryEnvelopeProps,
1598
+ journey_id: Schema.String,
1599
+ intent: OnboardingIntentSchema,
1600
+ entry_point: Schema.String
1601
+ });
1602
+ const OnboardingProfileSubmittedProps = Schema.Struct({
1603
+ ...TelemetryEnvelopeProps,
1604
+ journey_id: Schema.String,
1605
+ intent: OnboardingIntentSchema
1606
+ });
1607
+ const OnboardingOrganizationSubmittedProps = Schema.Struct({
1608
+ ...TelemetryEnvelopeProps,
1609
+ journey_id: Schema.String
1610
+ });
1611
+ const OnboardingDashboardReachedProps = Schema.Struct({
1612
+ ...TelemetryEnvelopeProps,
1613
+ journey_id: Schema.String,
1614
+ intent: OnboardingIntentSchema,
1615
+ organization_id: Schema.optional(OrgIdTelemetrySchema)
1616
+ });
1617
+ const OrgCreateStartedProps = Schema.Struct({
1618
+ ...TelemetryEnvelopeProps,
1619
+ org_id: OptionalOrgId,
1620
+ email_domain: OptionalString,
1621
+ template: OptionalString
1622
+ });
1623
+ const OrgSafeCreatedProps = Schema.Struct({
1624
+ ...TelemetryEnvelopeProps,
1625
+ org_id: OptionalOrgId,
1626
+ chainId: OptionalChainId,
1627
+ safe_address: OptionalAddress
1628
+ });
1629
+ const OrgSafeConfirmedProps = Schema.Struct({
1630
+ ...TelemetryEnvelopeProps,
1631
+ org_id: OptionalOrgId,
1632
+ chainId: OptionalChainId,
1633
+ safe_address: OptionalAddress,
1634
+ durationMs: OptionalDurationMs
1635
+ });
1636
+ const OrgRolesSeededProps = Schema.Struct({
1637
+ ...TelemetryEnvelopeProps,
1638
+ org_id: OptionalOrgId,
1639
+ chainId: OptionalChainId,
1640
+ role: OptionalString,
1641
+ txHash: OptionalTxHash
1642
+ });
1643
+ const OrgCreatedProps = Schema.Struct({
1644
+ ...TelemetryEnvelopeProps,
1645
+ org_id: OptionalOrgId,
1646
+ chainId: OptionalChainId,
1647
+ safe_address: OptionalAddress,
1648
+ durationMs: OptionalDurationMs
1649
+ });
1650
+ const OrgCreateFailedProps = Schema.Struct({
1651
+ ...TelemetryEnvelopeProps,
1652
+ ...ChainCauseTelemetryProps,
1653
+ org_id: OptionalOrgId,
1654
+ reason: OptionalString
1655
+ });
1656
+ const OrgInviteSentProps = Schema.Struct({
1657
+ ...TelemetryEnvelopeProps,
1658
+ org_id: OptionalOrgId,
1659
+ invitation_id: OptionalString,
1660
+ generation: OptionalString,
1661
+ command_id: OptionalString,
1662
+ subject_party_id: OptionalString,
1663
+ persisted_at: OptionalEpochMs,
1664
+ email_domain: OptionalString,
1665
+ role: OptionalString,
1666
+ status: OptionalString
1667
+ });
1668
+ const OrgInviteAcceptedProps = Schema.Struct({
1669
+ ...TelemetryEnvelopeProps,
1670
+ org_id: OptionalOrgId,
1671
+ invitation_id: OptionalString,
1672
+ accepted_at: OptionalEpochMs,
1673
+ generation: OptionalString,
1674
+ command_id: OptionalString,
1675
+ subject_party_id: OptionalString,
1676
+ role: OptionalString,
1677
+ status: OptionalString
1678
+ });
1679
+ const OrgInviteExpiredProps = Schema.Struct({
1680
+ ...TelemetryEnvelopeProps,
1681
+ org_id: OptionalOrgId,
1682
+ email_domain: OptionalString,
1683
+ invitation_id: OptionalString,
1684
+ reason: OptionalString,
1685
+ role: OptionalString,
1686
+ status: OptionalString
1687
+ });
1688
+ const RecipientLocatorKindSchema = Schema.Literals([
1689
+ "handle",
1690
+ "email",
1691
+ "address",
1692
+ "party"
1693
+ ]);
1694
+ const RecipientResolutionStatusSchema = Schema.Literals([
1695
+ "known_party",
1696
+ "new_email",
1697
+ "external_address"
1698
+ ]);
1699
+ const RecipientPartyKindSchema = Schema.Literals([
1700
+ "person",
1701
+ "organization",
1702
+ "unresolved"
1703
+ ]);
1704
+ const RecipientTelemetryProps = {
1705
+ recipient_locator_kind: Schema.optional(RecipientLocatorKindSchema),
1706
+ recipient_resolution_status: Schema.optional(RecipientResolutionStatusSchema),
1707
+ recipient_party_id: OptionalString,
1708
+ recipient_party_kind: Schema.optional(RecipientPartyKindSchema),
1709
+ recipient_is_capxul_account: Schema.optional(Schema.Boolean),
1710
+ recipient_handle: OptionalString,
1711
+ recipient_address: OptionalAddress,
1712
+ external_address_acknowledged: Schema.optional(Schema.Boolean)
1713
+ };
1714
+ const PaymentInitiatedProps = Schema.Struct({
1715
+ command_id: OptionalString,
1716
+ execution_id: OptionalString,
1717
+ payment_lifecycle_id: OptionalString,
1718
+ ...TelemetryEnvelopeProps,
1719
+ ...RecipientTelemetryProps,
1720
+ kind: Schema.String,
1721
+ payment_id: Schema.String
1722
+ });
1723
+ const PaymentLifecycleProps = {
1724
+ payment_state: OptionalString,
1725
+ execution_state: OptionalString,
1726
+ occurred_at: Schema.optional(Schema.Number),
1727
+ causal_sequence: Schema.optional(Schema.Number),
1728
+ sponsorship_valid_until: Schema.optional(Schema.Number),
1729
+ terminal_event_id: OptionalString
1730
+ };
1731
+ const PaymentSettledL2Props = Schema.Struct({
1732
+ ...PaymentLifecycleProps,
1733
+ ...TelemetryEnvelopeProps,
1734
+ ...RecipientTelemetryProps,
1735
+ kind: Schema.String,
1736
+ chain_id: Schema.Number,
1737
+ settlement_id: Schema.String,
1738
+ payment_id: OptionalString,
1739
+ payment_ids: OptionalString,
1740
+ command_id: OptionalString,
1741
+ payment_lifecycle_id: OptionalString,
1742
+ execution_id: OptionalString,
1743
+ user_op_hash: OptionalString,
1744
+ transaction_hash: OptionalString
1745
+ });
1746
+ const PaymentFailedL2Props = Schema.Struct({
1747
+ ...PaymentLifecycleProps,
1748
+ ...TelemetryEnvelopeProps,
1749
+ ...ChainCauseTelemetryProps,
1750
+ ...RecipientTelemetryProps,
1751
+ kind: Schema.String,
1752
+ payment_id: Schema.String,
1753
+ payment_ids: OptionalString,
1754
+ reason_code: Schema.String,
1755
+ command_id: OptionalString,
1756
+ payment_lifecycle_id: OptionalString,
1757
+ execution_id: OptionalString,
1758
+ user_op_hash: OptionalString
1759
+ });
1760
+ const PaymentVerificationRetryProps = Schema.Struct({
1761
+ ...PaymentLifecycleProps,
1762
+ ...TelemetryEnvelopeProps,
1763
+ ...RecipientTelemetryProps,
1764
+ command_id: Schema.String,
1765
+ payment_lifecycle_id: Schema.String,
1766
+ attempt: Schema.Number,
1767
+ reason_code: Schema.String,
1768
+ chain_id: Schema.Number,
1769
+ delay_ms: DurationMsSchema,
1770
+ outcome: Schema.Literals(["scheduled", "unresolved"]),
1771
+ payment_id: OptionalString,
1772
+ payment_ids: OptionalString,
1773
+ execution_id: OptionalString,
1774
+ user_op_hash: OptionalString
1775
+ });
1776
+ const PaymentLifecycleTransitionProps = Schema.Struct({
1777
+ ...TelemetryEnvelopeProps,
1778
+ ...RecipientTelemetryProps,
1779
+ payment_id: Schema.String,
1780
+ payment_lifecycle_id: Schema.String,
1781
+ command_id: Schema.String,
1782
+ payment_state: Schema.String,
1783
+ occurred_at: Schema.Number,
1784
+ causal_sequence: Schema.Number,
1785
+ execution_id: OptionalString,
1786
+ execution_state: OptionalString,
1787
+ user_op_hash: OptionalString,
1788
+ sponsorship_valid_until: Schema.optional(Schema.Number),
1789
+ reason_code: OptionalString
1790
+ });
1791
+ const QuickPayExternalAddressAcknowledgedProps = Schema.Struct({
1792
+ ...TelemetryEnvelopeProps,
1793
+ recipient_locator_kind: Schema.Literal("address"),
1794
+ recipient_resolution_status: Schema.Literal("external_address"),
1795
+ recipient_address: AddressSchema,
1796
+ external_address_acknowledged: Schema.Literal(true),
1797
+ organization_id: OptionalOrgId
1798
+ });
1799
+ const DepositInitiatedProps = Schema.Struct({
1800
+ ...TelemetryEnvelopeProps,
1801
+ scope_kind: Schema.optional(Schema.Literals(["account", "organization"])),
1802
+ account_kind: Schema.optional(Schema.Literals(["personalSafe", "orgTreasury"])),
1803
+ chain_id: Schema.optional(Schema.Number),
1804
+ network: Schema.optional(Schema.Literal("base-sepolia")),
1805
+ organization_id: OptionalOrgId,
1806
+ $groups: Schema.optional(Schema.Struct({ organization: OptionalOrgId })),
1807
+ actor_id: OptionalString,
1808
+ actor_kind: Schema.optional(Schema.Literal("authenticated")),
1809
+ distinct_id: OptionalString,
1810
+ trace_id: OptionalString,
1811
+ span_id: OptionalString
1812
+ });
1813
+ const DepositSettledProps = Schema.Struct({
1814
+ ...TelemetryEnvelopeProps,
1815
+ chain_id: Schema.Number,
1816
+ tx_hash: Schema.String,
1817
+ log_index: Schema.Number
1818
+ });
1819
+ const PermissionMirrorVerificationProps = Schema.Struct({
1820
+ ...TelemetryEnvelopeProps,
1821
+ /** The RECEIPT verification outcome. What the mirror then did is separate. */
1822
+ outcome: Schema.String,
1823
+ reason: Schema.String,
1824
+ chain_id: Schema.Number,
1825
+ retry_count: Schema.Number,
1826
+ /**
1827
+ * #1960 R02, consumed by R03. A verified receipt is not an applied Permission:
1828
+ * these two optional fields let the producer say what the applying mutation
1829
+ * actually returned, and which command it was, without either fact rewriting
1830
+ * the receipt outcome above. Absent when application has not happened yet.
1831
+ */
1832
+ application_result: Schema.optional(Schema.Literals([
1833
+ "applied",
1834
+ "replayed",
1835
+ "conflicting_replay",
1836
+ "revision_mismatch",
1837
+ "cleanup_required",
1838
+ "not_applied",
1839
+ "application_failure",
1840
+ "mismatch",
1841
+ "refused"
1842
+ ])),
1843
+ command_kind: Schema.optional(Schema.Literals(["invitation_configuration", "invitation_eoa"])),
1844
+ command_id: OptionalString,
1845
+ invitation_id: OptionalString,
1846
+ generation: OptionalString,
1847
+ purpose: Schema.optional(Schema.Literals([
1848
+ "configure",
1849
+ "grant",
1850
+ "disable",
1851
+ "compensate"
1852
+ ])),
1853
+ $insert_id: OptionalString,
1854
+ /**
1855
+ * #1961 R03. The authorized stored row names the Permission it changed; the
1856
+ * verified receipt names the chain facts that prove it. Every field is
1857
+ * optional because a pending or provider-failed verification has neither an
1858
+ * application result nor a receipt to report.
1859
+ */
1860
+ permission_id: OptionalString,
1861
+ permission_assignment_id: OptionalString,
1862
+ permission_operation: Schema.optional(Schema.Literals([
1863
+ "create",
1864
+ "change",
1865
+ "assign",
1866
+ "revoke",
1867
+ "replace"
1868
+ ])),
1869
+ revision: Schema.optional(Schema.Number),
1870
+ user_op_hash: OptionalString,
1871
+ transaction_hash: OptionalString,
1872
+ block_number: Schema.optional(Schema.Number),
1873
+ log_index: Schema.optional(Schema.Number)
1874
+ });
1875
+ const MovementScanWindowProps = Schema.Struct({
1876
+ ...TelemetryEnvelopeProps,
1877
+ chain_id: Schema.Number,
1878
+ token_address: Schema.String,
1879
+ from_block: Schema.Number,
1880
+ to_block: Schema.Number,
1881
+ log_count: Schema.Number,
1882
+ request_count: Schema.Number,
1883
+ outcome: Schema.String
1884
+ });
1885
+ const MovementScanCheckpointProps = Schema.Struct({
1886
+ ...TelemetryEnvelopeProps,
1887
+ chain_id: Schema.Number,
1888
+ token_address: Schema.String,
1889
+ next_block: Schema.Number,
1890
+ anchor_block_number: Schema.Number
1891
+ });
1892
+ const MovementScanIncidentProps = Schema.Struct({
1893
+ ...TelemetryEnvelopeProps,
1894
+ chain_id: Schema.Number,
1895
+ token_address: Schema.String,
1896
+ incident_kind: Schema.String,
1897
+ anchor_block_number: Schema.Number
1898
+ });
1899
+ /**
1900
+ * One durable row the reconciliation job corrected against Ponder (SPEC D9).
1901
+ *
1902
+ * Both block fields are optional and for the same reason: a correction INTO
1903
+ * drift (a Payment settled in Convex whose Ponder fact a reorg removed) has no
1904
+ * current block, and a correction that confirms a later fact has one.
1905
+ *
1906
+ * `projection_kind` is closed. A later ticket that reconciles a deploy, a
1907
+ * bootstrap or a grant outcome adds its kind here in the same change; an
1908
+ * unknown kind must not decode.
1909
+ */
1910
+ const IndexerDriftCorrectedProps = Schema.Struct({
1911
+ ...TelemetryEnvelopeProps,
1912
+ projection_kind: Schema.Literals([
1913
+ "member_authority",
1914
+ "payment_settlement",
1915
+ "permission_assignment"
1916
+ ]),
1917
+ previous_state: Schema.String,
1918
+ current_state: Schema.String,
1919
+ previous_block: Schema.optional(Schema.Number),
1920
+ current_block: Schema.optional(Schema.Number),
1921
+ logical_event_id: Schema.optional(Schema.String),
1922
+ scope_kind: Schema.optional(Schema.Literals(["account", "organization"])),
1923
+ account_id: OptionalAccountId,
1924
+ reference_id: OptionalString
1925
+ });
1926
+ const AuthOtpRequestedTelemetryEventSchema = Schema.Struct({
1927
+ name: Schema.Literal("auth_otp_requested"),
1928
+ props: AuthOtpRequestedProps
1929
+ });
1930
+ const AuthOtpDeliveredTelemetryEventSchema = Schema.Struct({
1931
+ name: Schema.Literal("auth_otp_delivered"),
1932
+ props: AuthOtpDeliveredProps
1933
+ });
1934
+ const AuthOtpExpiredTelemetryEventSchema = Schema.Struct({
1935
+ name: Schema.Literal("auth_otp_expired"),
1936
+ props: AuthOtpExpiredProps
1937
+ });
1938
+ const AuthVerifiedTelemetryEventSchema = Schema.Struct({
1939
+ name: Schema.Literal("auth_verified"),
1940
+ props: AuthVerifiedProps
1941
+ });
1942
+ const AuthFailedTelemetryEventSchema = Schema.Struct({
1943
+ name: Schema.Literal("auth_failed"),
1944
+ props: AuthFailedProps
1945
+ });
1946
+ const IdentityRefusedTelemetryEventSchema = Schema.Struct({
1947
+ name: Schema.Literal("identity_refused"),
1948
+ props: IdentityRefusedProps
1949
+ });
1950
+ const AuthSignedOutTelemetryEventSchema = Schema.Struct({
1951
+ name: Schema.Literal("auth_signed_out"),
1952
+ props: AuthSignedOutProps
1953
+ });
1954
+ const NativeAuthorizationStartedTelemetryEventSchema = Schema.Struct({
1955
+ name: Schema.Literal("native_authorization_started"),
1956
+ props: NativeAuthorizationStartedProps
1957
+ });
1958
+ const NativeAuthorizationReviewedTelemetryEventSchema = Schema.Struct({
1959
+ name: Schema.Literal("native_authorization_reviewed"),
1960
+ props: NativeAuthorizationReviewedProps
1961
+ });
1962
+ const NativeAuthorizationAcceptedTelemetryEventSchema = Schema.Struct({
1963
+ name: Schema.Literal("native_authorization_accepted"),
1964
+ props: NativeAuthorizationAcceptedProps
1965
+ });
1966
+ const NativeAuthorizationDeniedTelemetryEventSchema = Schema.Struct({
1967
+ name: Schema.Literal("native_authorization_denied"),
1968
+ props: NativeAuthorizationDeniedProps
1969
+ });
1970
+ const NativeAuthorizationConnectedTelemetryEventSchema = Schema.Struct({
1971
+ name: Schema.Literal("native_authorization_connected"),
1972
+ props: NativeAuthorizationConnectedProps
1973
+ });
1974
+ const NativeAuthorizationFailedTelemetryEventSchema = Schema.Struct({
1975
+ name: Schema.Literal("native_authorization_failed"),
1976
+ props: NativeAuthorizationFailedProps
1977
+ });
1978
+ const OnboardingIntentSelectedTelemetryEventSchema = Schema.Struct({
1979
+ name: Schema.Literal("onboarding_intent_selected"),
1980
+ props: OnboardingIntentSelectedProps
1981
+ });
1982
+ const OnboardingProfileSubmittedTelemetryEventSchema = Schema.Struct({
1983
+ name: Schema.Literal("onboarding_profile_submitted"),
1984
+ props: OnboardingProfileSubmittedProps
1985
+ });
1986
+ const OnboardingOrganizationSubmittedTelemetryEventSchema = Schema.Struct({
1987
+ name: Schema.Literal("onboarding_organization_submitted"),
1988
+ props: OnboardingOrganizationSubmittedProps
1989
+ });
1990
+ const OnboardingDashboardReachedTelemetryEventSchema = Schema.Struct({
1991
+ name: Schema.Literal("onboarding_dashboard_reached"),
1992
+ props: OnboardingDashboardReachedProps
1993
+ });
1994
+ const ProvisioningSafeCreatedTelemetryEventSchema = Schema.Struct({
1995
+ name: Schema.Literal("provisioning_safe_created"),
1996
+ props: ProvisioningSafeCreatedProps
1997
+ });
1998
+ const ProvisioningSafeConfirmedTelemetryEventSchema = Schema.Struct({
1999
+ name: Schema.Literal("provisioning_safe_confirmed"),
2000
+ props: ProvisioningSafeConfirmedProps
2001
+ });
2002
+ const BootstrapResolvedTelemetryEventSchema = Schema.Struct({
2003
+ name: Schema.Literal("bootstrap_resolved"),
2004
+ props: BootstrapResolvedProps
2005
+ });
2006
+ const BootstrapFailedTelemetryEventSchema = Schema.Struct({
2007
+ name: Schema.Literal("bootstrap_failed"),
2008
+ props: BootstrapFailedProps
2009
+ });
2010
+ const MemberActivationStartedTelemetryEventSchema = Schema.Struct({
2011
+ name: Schema.Literal("member_activation_started"),
2012
+ props: MemberActivationStartedProps
2013
+ });
2014
+ const MemberActivationReadyTelemetryEventSchema = Schema.Struct({
2015
+ name: Schema.Literal("member_activation_ready"),
2016
+ props: MemberActivationReadyProps
2017
+ });
2018
+ const MemberActivationFailedTelemetryEventSchema = Schema.Struct({
2019
+ name: Schema.Literal("member_activation_failed"),
2020
+ props: MemberActivationFailedProps
2021
+ });
2022
+ const OrganizationCreationStartedTelemetryEventSchema = Schema.Struct({
2023
+ name: Schema.Literal("organization_creation_started"),
2024
+ props: OrganizationCreationStartedProps
2025
+ });
2026
+ const OrganizationCreationReadyTelemetryEventSchema = Schema.Struct({
2027
+ name: Schema.Literal("organization_creation_ready"),
2028
+ props: OrganizationCreationReadyProps
2029
+ });
2030
+ const OrganizationCreationFailedTelemetryEventSchema = Schema.Struct({
2031
+ name: Schema.Literal("organization_creation_failed"),
2032
+ props: OrganizationCreationFailedProps
2033
+ });
2034
+ const AccountBalanceReadTelemetryEventSchema = Schema.Struct({
2035
+ name: Schema.Literal("account_balance_read"),
2036
+ props: AccountBalanceReadProps
2037
+ });
2038
+ const AccountBalanceFailedTelemetryEventSchema = Schema.Struct({
2039
+ name: Schema.Literal("account_balance_failed"),
2040
+ props: AccountBalanceFailedProps
2041
+ });
2042
+ const FaucetRequestedTelemetryEventSchema = Schema.Struct({
2043
+ name: Schema.Literal("faucet_requested"),
2044
+ props: FaucetRequestedProps
2045
+ });
2046
+ const FaucetConfirmedTelemetryEventSchema = Schema.Struct({
2047
+ name: Schema.Literal("faucet_confirmed"),
2048
+ props: FaucetConfirmedProps
2049
+ });
2050
+ const FaucetFailedTelemetryEventSchema = Schema.Struct({
2051
+ name: Schema.Literal("faucet_failed"),
2052
+ props: FaucetFailedProps
2053
+ });
2054
+ const ChainUpstreamFallbackTelemetryEventSchema = Schema.Struct({
2055
+ name: Schema.Literal("chain_upstream_fallback"),
2056
+ props: ChainUpstreamFallbackProps
2057
+ });
2058
+ const BundlerErrorTelemetryEventSchema = Schema.Struct({
2059
+ name: Schema.Literal("bundler_error"),
2060
+ props: BundlerErrorProps
2061
+ });
2062
+ const ReceiptPendingTelemetryEventSchema = Schema.Struct({
2063
+ name: Schema.Literal("receipt_pending"),
2064
+ props: ReceiptPendingProps
2065
+ });
2066
+ const OperationRetriedTelemetryEventSchema = Schema.Struct({
2067
+ name: Schema.Literal("operation_retried"),
2068
+ props: OperationRetriedProps
2069
+ });
2070
+ const OrgCreateStartedTelemetryEventSchema = Schema.Struct({
2071
+ name: Schema.Literal("org_create_started"),
2072
+ props: OrgCreateStartedProps
2073
+ });
2074
+ const OrgSafeCreatedTelemetryEventSchema = Schema.Struct({
2075
+ name: Schema.Literal("org_safe_created"),
2076
+ props: OrgSafeCreatedProps
2077
+ });
2078
+ const OrgSafeConfirmedTelemetryEventSchema = Schema.Struct({
2079
+ name: Schema.Literal("org_safe_confirmed"),
2080
+ props: OrgSafeConfirmedProps
2081
+ });
2082
+ const OrgRolesSeededTelemetryEventSchema = Schema.Struct({
2083
+ name: Schema.Literal("org_roles_seeded"),
2084
+ props: OrgRolesSeededProps
2085
+ });
2086
+ const OrgCreatedTelemetryEventSchema = Schema.Struct({
2087
+ name: Schema.Literal("org_created"),
2088
+ props: OrgCreatedProps
2089
+ });
2090
+ const OrgCreateFailedTelemetryEventSchema = Schema.Struct({
2091
+ name: Schema.Literal("org_create_failed"),
2092
+ props: OrgCreateFailedProps
2093
+ });
2094
+ const OrgInviteSentTelemetryEventSchema = Schema.Struct({
2095
+ name: Schema.Literal("org_invite_sent"),
2096
+ props: OrgInviteSentProps
2097
+ });
2098
+ const OrgInviteAcceptedTelemetryEventSchema = Schema.Struct({
2099
+ name: Schema.Literal("org_invite_accepted"),
2100
+ props: OrgInviteAcceptedProps
2101
+ });
2102
+ const OrgInviteExpiredTelemetryEventSchema = Schema.Struct({
2103
+ name: Schema.Literal("org_invite_expired"),
2104
+ props: OrgInviteExpiredProps
2105
+ });
2106
+ const PaymentInitiatedTelemetryEventSchema = Schema.Struct({
2107
+ name: Schema.Literal("payment_initiated"),
2108
+ props: PaymentInitiatedProps
2109
+ });
2110
+ const PaymentSettledTelemetryEventSchema = Schema.Struct({
2111
+ name: Schema.Literal("payment_settled"),
2112
+ props: PaymentSettledL2Props
2113
+ });
2114
+ const PaymentFailedTelemetryEventSchema = Schema.Struct({
2115
+ name: Schema.Literal("payment_failed"),
2116
+ props: PaymentFailedL2Props
2117
+ });
2118
+ const PaymentVerificationRetryTelemetryEventSchema = Schema.Struct({
2119
+ name: Schema.Literal("payment_verification_retry"),
2120
+ props: PaymentVerificationRetryProps
2121
+ });
2122
+ const PaymentLifecycleTransitionTelemetryEventSchema = Schema.Struct({
2123
+ name: Schema.Literal("payment_lifecycle_transition"),
2124
+ props: PaymentLifecycleTransitionProps
2125
+ });
2126
+ const QuickPayExternalAddressAcknowledgedTelemetryEventSchema = Schema.Struct({
2127
+ name: Schema.Literal("quick_pay_external_address_acknowledged"),
2128
+ props: QuickPayExternalAddressAcknowledgedProps
2129
+ });
2130
+ const DepositInitiatedTelemetryEventSchema = Schema.Struct({
2131
+ name: Schema.Literal("deposit_initiated"),
2132
+ props: DepositInitiatedProps
2133
+ });
2134
+ const DepositSettledTelemetryEventSchema = Schema.Struct({
2135
+ name: Schema.Literal("deposit_settled"),
2136
+ props: DepositSettledProps
2137
+ });
2138
+ const PermissionMirrorVerificationTelemetryEventSchema = Schema.Struct({
2139
+ name: Schema.Literal("permission_mirror_verification"),
2140
+ props: PermissionMirrorVerificationProps
2141
+ });
2142
+ const MovementScanWindowTelemetryEventSchema = Schema.Struct({
2143
+ name: Schema.Literal("movement_scan_window"),
2144
+ props: MovementScanWindowProps
2145
+ });
2146
+ const MovementScanCheckpointTelemetryEventSchema = Schema.Struct({
2147
+ name: Schema.Literal("movement_scan_checkpoint"),
2148
+ props: MovementScanCheckpointProps
2149
+ });
2150
+ const MovementScanIncidentTelemetryEventSchema = Schema.Struct({
2151
+ name: Schema.Literal("movement_scan_incident"),
2152
+ props: MovementScanIncidentProps
2153
+ });
2154
+ const IndexerDriftCorrectedTelemetryEventSchema = Schema.Struct({
2155
+ name: Schema.Literal("indexer_drift_corrected"),
2156
+ props: IndexerDriftCorrectedProps
2157
+ });
2158
+ /** The one spelling of "whose scope did this happen in" across every surface. */
2159
+ const ScopeKindSchema = Schema.Literals(["account", "organization"]);
2160
+ const OptionalReasonCode = Schema.optional(Schema.Literals(CAPXUL_ERROR_CODES));
2161
+ const ActivityReferenceProps = {
2162
+ reference_kind: Schema.Literals(["payment", "movement"]),
2163
+ reference_id: Schema.String
2164
+ };
2165
+ const ActivityFilterProps = {
2166
+ filter_kind: Schema.optional(Schema.Literals([
2167
+ "all",
2168
+ "payment",
2169
+ "movement"
2170
+ ])),
2171
+ filter_direction: Schema.optional(Schema.Literals([
2172
+ "all",
2173
+ "in",
2174
+ "out",
2175
+ "self"
2176
+ ])),
2177
+ filter_status: Schema.optional(Schema.Array(Schema.Literals([
2178
+ "pending",
2179
+ "settling",
2180
+ "unresolved",
2181
+ "pending_claim",
2182
+ "scheduled",
2183
+ "streaming",
2184
+ "settled",
2185
+ "cancelled",
2186
+ "failed"
2187
+ ])))
2188
+ };
2189
+ const ActivityActionProps = {
2190
+ ...TelemetryEnvelopeProps,
2191
+ scope_kind: ScopeKindSchema,
2192
+ reason_code: OptionalReasonCode
2193
+ };
2194
+ const ContactRelationshipChangedTelemetryEventSchema = Schema.Struct({
2195
+ name: Schema.Literal("contact_relationship_changed"),
2196
+ props: Schema.Struct({
2197
+ ...TelemetryEnvelopeProps,
2198
+ change: Schema.Literals([
2199
+ "added",
2200
+ "renamed",
2201
+ "hidden",
2202
+ "restored"
2203
+ ]),
2204
+ scope_kind: ScopeKindSchema,
2205
+ scope_id: Schema.String,
2206
+ owner_party_id: Schema.String,
2207
+ party_id: Schema.String,
2208
+ hidden: Schema.Boolean,
2209
+ occurred_at: Schema.Number,
2210
+ operation: Schema.Literals([
2211
+ CAPXUL_OPERATIONS.addressBook.add,
2212
+ CAPXUL_OPERATIONS.addressBook.label,
2213
+ CAPXUL_OPERATIONS.addressBook.hide,
2214
+ CAPXUL_OPERATIONS.addressBook.unhide
2215
+ ])
2216
+ })
2217
+ });
2218
+ const ContactActionProps = {
2219
+ ...TelemetryEnvelopeProps,
2220
+ scope_kind: ScopeKindSchema,
2221
+ party_id: OptionalString,
2222
+ reason_code: OptionalReasonCode
2223
+ };
2224
+ /** One completed online CLI diagnostic. No command input or provider text. */
2225
+ const CLI_COMMAND_NAMES = [
2226
+ "status",
2227
+ "request",
2228
+ "request.list",
2229
+ "request.get",
2230
+ "request.cancel",
2231
+ "offer",
2232
+ "offer.create",
2233
+ "offer.list",
2234
+ "offer.get",
2235
+ "offer.revise",
2236
+ "offer.deactivate",
2237
+ "org.offer",
2238
+ "org.offer.create",
2239
+ "org.offer.list",
2240
+ "org.offer.get",
2241
+ "org.offer.revise",
2242
+ "org.offer.deactivate",
2243
+ "request.issue",
2244
+ "inbox",
2245
+ CAPXUL_OPERATIONS.inbox.list,
2246
+ "inbox.get",
2247
+ "inbox.pay",
2248
+ CAPXUL_OPERATIONS.inbox.decline,
2249
+ "org.request",
2250
+ "org.request.list",
2251
+ "org.request.get",
2252
+ "org.request.cancel",
2253
+ "org.request.issue",
2254
+ "org.inbox",
2255
+ CAPXUL_OPERATIONS.org.inbox.list,
2256
+ "org.inbox.get",
2257
+ "org.inbox.pay",
2258
+ CAPXUL_OPERATIONS.org.inbox.decline,
2259
+ "capxul",
2260
+ "doctor",
2261
+ "telemetry",
2262
+ "telemetry.status",
2263
+ "telemetry.enable",
2264
+ "telemetry.disable",
2265
+ "auth",
2266
+ "auth.login",
2267
+ "auth.signup",
2268
+ "auth.send",
2269
+ "auth.verify",
2270
+ "auth.profile",
2271
+ "auth.status",
2272
+ "auth.logout",
2273
+ "account",
2274
+ CAPXUL_OPERATIONS.account.status,
2275
+ CAPXUL_OPERATIONS.account.balance,
2276
+ "account.deposit",
2277
+ "account.retry",
2278
+ "document",
2279
+ "document.get",
2280
+ "document.verify",
2281
+ "document.render",
2282
+ "document.export",
2283
+ "payment",
2284
+ "payment.list",
2285
+ "payment.get",
2286
+ "payment.wait",
2287
+ "payment.send",
2288
+ "payment.retry",
2289
+ "activity",
2290
+ CAPXUL_OPERATIONS.activity.list,
2291
+ CAPXUL_OPERATIONS.activity.get,
2292
+ CAPXUL_OPERATIONS.activity.summary,
2293
+ CAPXUL_OPERATIONS.activity.annotate,
2294
+ "contact",
2295
+ "contact.list",
2296
+ "contact.get",
2297
+ "contact.add",
2298
+ "contact.label",
2299
+ "contact.hide",
2300
+ "contact.unhide",
2301
+ "org",
2302
+ CAPXUL_OPERATIONS.org.list,
2303
+ "org.use",
2304
+ "org.status",
2305
+ CAPXUL_OPERATIONS.org.me,
2306
+ "org.balance",
2307
+ "org.deposit",
2308
+ "org.permission",
2309
+ "org.permission.list",
2310
+ "org.permission.get",
2311
+ "org.permission.create",
2312
+ "org.permission.change",
2313
+ "org.permission.assign",
2314
+ "org.permission.revoke",
2315
+ "org.permission.replace",
2316
+ "org.permission.command",
2317
+ "org.permission.command.get",
2318
+ "org.permission.command.wait",
2319
+ CAPXUL_OPERATIONS.org.payment,
2320
+ "org.payment.list",
2321
+ "org.payment.get",
2322
+ "org.payment.wait",
2323
+ "org.payment.retry",
2324
+ "org.payment.send",
2325
+ "org.payroll",
2326
+ "org.payroll.groups",
2327
+ CAPXUL_OPERATIONS.org.payroll.groups.list,
2328
+ CAPXUL_OPERATIONS.org.payroll.groups.save,
2329
+ CAPXUL_OPERATIONS.org.payroll.groups.remove,
2330
+ CAPXUL_OPERATIONS.org.payroll.terms,
2331
+ "org.payroll.list",
2332
+ "org.payroll.run",
2333
+ "org.payroll.get",
2334
+ "org.payroll.wait",
2335
+ CAPXUL_OPERATIONS.org.members,
2336
+ "org.member",
2337
+ "org.member.get",
2338
+ "org.member.invite",
2339
+ "org.contact",
2340
+ "org.contact.list",
2341
+ "org.contact.get",
2342
+ "org.contact.add",
2343
+ "org.contact.label",
2344
+ "org.contact.hide",
2345
+ "org.contact.unhide",
2346
+ CAPXUL_OPERATIONS.org.invite,
2347
+ "org.invite.list",
2348
+ "org.invite.get",
2349
+ "org.invite.wait",
2350
+ "org.invite.review",
2351
+ "org.invite.accept",
2352
+ "org.invite.decline",
2353
+ "org.invite.cancel",
2354
+ "org.invite.resend",
2355
+ "org.invite.retry",
2356
+ "org.wait",
2357
+ CAPXUL_OPERATIONS.org.create,
2358
+ CAPXUL_OPERATIONS.org.retry,
2359
+ "unknown"
2360
+ ];
2361
+ const CLI_CAPABILITIES = [
2362
+ "cli",
2363
+ "diagnostics",
2364
+ "collection",
2365
+ "authentication",
2366
+ "account",
2367
+ "organization",
2368
+ "contacts",
2369
+ "documents",
2370
+ "payments",
2371
+ "activity"
2372
+ ];
2373
+ const CLI_INVOCATION_KINDS = [
2374
+ "command",
2375
+ "help",
2376
+ "version",
2377
+ "completion",
2378
+ "parse_refusal",
2379
+ "collection_control"
2380
+ ];
2381
+ const CliRelease = Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/u));
2382
+ const CliInvocationProps = {
2383
+ ...TelemetryEnvelopeProps,
2384
+ schema_version: Schema.Literal(1),
2385
+ command: Schema.Literals(CLI_COMMAND_NAMES),
2386
+ capability: Schema.Literals(CLI_CAPABILITIES),
2387
+ invocation_kind: Schema.Literals(CLI_INVOCATION_KINDS),
2388
+ invocation_id: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u)),
2389
+ cli_identity_kind: Schema.optional(Schema.Literals(["anonymous", "identified"])),
2390
+ anonymous_id: Schema.optional(Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u))),
2391
+ auth_user_id: Schema.optional(Schema.String.check(Schema.isPattern(/^[^\s]{1,256}$/u))),
2392
+ occurred_at: Schema.Number,
2393
+ cli_version: CliRelease,
2394
+ sdk_version: CliRelease,
2395
+ release: CliRelease,
2396
+ platform: Schema.Literals([
2397
+ "darwin",
2398
+ "linux",
2399
+ "unknown"
2400
+ ]),
2401
+ architecture: Schema.Literals([
2402
+ "arm64",
2403
+ "x64",
2404
+ "unknown"
2405
+ ]),
2406
+ ci: Schema.Boolean,
2407
+ tty: Schema.Boolean,
2408
+ output_mode: Schema.Literals(["human", "json"])
2409
+ };
2410
+ const CliFirstUsedTelemetryEventSchema = Schema.Struct({
2411
+ name: Schema.Literal("cli_first_used"),
2412
+ props: Schema.Struct(CliInvocationProps)
2413
+ });
2414
+ const CliCommandStartedTelemetryEventSchema = Schema.Struct({
2415
+ name: Schema.Literal("cli_command_started"),
2416
+ props: Schema.Struct({
2417
+ ...CliInvocationProps,
2418
+ invocation_kind: Schema.Literals([
2419
+ "command",
2420
+ "help",
2421
+ "version"
2422
+ ])
2423
+ })
2424
+ });
2425
+ const CliCommandCompletedTelemetryEventSchema = Schema.Struct({
2426
+ name: Schema.Literal("cli_command_completed"),
2427
+ props: Schema.Struct({
2428
+ ...CliInvocationProps,
2429
+ outcome: Schema.Literals([
2430
+ "succeeded",
2431
+ "refused",
2432
+ "failed",
2433
+ "cancelled"
2434
+ ]),
2435
+ duration_ms: Schema.Number,
2436
+ organization_id: Schema.optional(OrgIdTelemetrySchema),
2437
+ setup_status: Schema.optional(Schema.Literals(ORGANIZATION_SETUP_STATUSES)),
2438
+ setup_reason: Schema.optional(Schema.Literals(ORGANIZATION_SETUP_REASONS)),
2439
+ $groups: Schema.optional(Schema.Struct({ organization: OrgIdTelemetrySchema })),
2440
+ error_code: Schema.optional(Schema.Literals([
2441
+ ...CAPXUL_ERROR_CODES,
2442
+ "CLI_USAGE",
2443
+ "CLI_CONFIG",
2444
+ "CLI_STORAGE",
2445
+ "CLI_DEFECT",
2446
+ "CLI_DEADLINE"
2447
+ ]))
2448
+ })
2449
+ });
2450
+ const CliDiagnosticCompletedTelemetryEventSchema = Schema.Struct({
2451
+ name: Schema.Literal("cli_diagnostic_completed"),
2452
+ props: Schema.Struct({
2453
+ ...TelemetryEnvelopeProps,
2454
+ outcome: Schema.Literals([
2455
+ "succeeded",
2456
+ "refused",
2457
+ "failed",
2458
+ "cancelled"
2459
+ ]),
2460
+ invocation_id: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u)),
2461
+ cli_version: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/u))
2462
+ })
2463
+ });
2464
+ const UiContactActionCompletedTelemetryEventSchema = Schema.Struct({
2465
+ name: Schema.Literal("ui_contact_action_completed"),
2466
+ props: Schema.Union([
2467
+ Schema.Struct({
2468
+ ...ContactActionProps,
2469
+ action: Schema.Literal("add"),
2470
+ outcome: Schema.Literals(["opened", "cancelled"])
2471
+ }),
2472
+ Schema.Struct({
2473
+ ...ContactActionProps,
2474
+ action: Schema.Literal("refusal"),
2475
+ outcome: Schema.Literal("displayed")
2476
+ }),
2477
+ Schema.Struct({
2478
+ ...ContactActionProps,
2479
+ action: Schema.Literal("retry"),
2480
+ outcome: Schema.Literal("requested")
2481
+ })
2482
+ ])
2483
+ });
2484
+ const ActivityAnnotationSavedTelemetryEventSchema = Schema.Struct({
2485
+ name: Schema.Literal("activity_annotation_saved"),
2486
+ props: Schema.Struct({
2487
+ ...TelemetryEnvelopeProps,
2488
+ ...ActivityReferenceProps,
2489
+ scope_kind: ScopeKindSchema,
2490
+ scope_id: Schema.String,
2491
+ occurred_at: Schema.Number
2492
+ })
2493
+ });
2494
+ const UiActivityActionCompletedTelemetryEventSchema = Schema.Struct({
2495
+ name: Schema.Literal("ui_activity_action_completed"),
2496
+ props: Schema.Union([
2497
+ Schema.Struct({
2498
+ ...ActivityActionProps,
2499
+ action: Schema.Literal("read"),
2500
+ outcome: Schema.Literals(["partial_displayed", "recovered"]),
2501
+ surface: Schema.Literals([
2502
+ "transactions",
2503
+ "recent",
2504
+ "summary"
2505
+ ])
2506
+ }),
2507
+ Schema.Struct({
2508
+ ...ActivityActionProps,
2509
+ ...ActivityFilterProps,
2510
+ action: Schema.Literal("filter"),
2511
+ outcome: Schema.Literal("committed")
2512
+ }),
2513
+ Schema.Struct({
2514
+ ...ActivityActionProps,
2515
+ action: Schema.Literal("refusal"),
2516
+ outcome: Schema.Literal("displayed")
2517
+ }),
2518
+ Schema.Struct({
2519
+ ...ActivityActionProps,
2520
+ action: Schema.Literal("retry"),
2521
+ outcome: Schema.Literal("requested")
2522
+ }),
2523
+ Schema.Struct({
2524
+ ...ActivityActionProps,
2525
+ ...ActivityReferenceProps,
2526
+ action: Schema.Literal("detail"),
2527
+ outcome: Schema.Literals(["opened", "failed"])
2528
+ }),
2529
+ Schema.Struct({
2530
+ ...ActivityActionProps,
2531
+ ...ActivityReferenceProps,
2532
+ action: Schema.Literal("receipt"),
2533
+ outcome: Schema.Literals([
2534
+ "document_rendered",
2535
+ "explorer_opened",
2536
+ "popup_blocked",
2537
+ "failed"
2538
+ ])
2539
+ }),
2540
+ Schema.Struct({
2541
+ ...ActivityActionProps,
2542
+ ...ActivityFilterProps,
2543
+ action: Schema.Literal("export"),
2544
+ outcome: Schema.Literals([
2545
+ "completed",
2546
+ "partial",
2547
+ "failed"
2548
+ ]),
2549
+ row_count: Schema.optional(Schema.Number),
2550
+ truncated: Schema.optional(Schema.Boolean)
2551
+ })
2552
+ ])
2553
+ });
2554
+ /**
2555
+ * Reliability closeout (#1960 R02) — the shape every explicit UI observation
2556
+ * below shares. `scope_kind` says whose surface the person was looking at,
2557
+ * `organization_id` is the verified Organization the producer resolved (absent
2558
+ * on a personal action), and `reason_code` is a catalog error code, never copy.
2559
+ */
2560
+ const UiStepProps = {
2561
+ ...TelemetryEnvelopeProps,
2562
+ scope_kind: ScopeKindSchema,
2563
+ organization_id: OptionalOrgId,
2564
+ reason_code: OptionalReasonCode
2565
+ };
2566
+ const AccessRecoveryCompletedProps = Schema.Union([Schema.Struct({
2567
+ ...TelemetryEnvelopeProps,
2568
+ recovery: Schema.Literal("session_restoration"),
2569
+ outcome: Schema.Literals([
2570
+ "restored",
2571
+ "absent",
2572
+ "failed"
2573
+ ]),
2574
+ reason_code: OptionalReasonCode,
2575
+ organization_id: OptionalOrgId
2576
+ }), Schema.Struct({
2577
+ ...TelemetryEnvelopeProps,
2578
+ recovery: Schema.Literal("signer_readiness"),
2579
+ outcome: Schema.Literals(["ready", "unavailable"]),
2580
+ reason_code: OptionalReasonCode,
2581
+ organization_id: OptionalOrgId
2582
+ })]);
2583
+ const AccessRecoveryCompletedTelemetryEventSchema = Schema.Struct({
2584
+ name: Schema.Literal("access_recovery_completed"),
2585
+ props: AccessRecoveryCompletedProps
2586
+ });
2587
+ /**
2588
+ * R05 (#1963) wired three of these steps at the app's dashboard Access
2589
+ * boundary: `dashboard_granted` on the commit of the granted content,
2590
+ * `gate_error_displayed` on the mounted error surface, and `retry_selected` on
2591
+ * the actual selection. `redirect_completed` stays RESERVED and unproduced —
2592
+ * asking for a navigation is not arriving, and the destination page's own
2593
+ * normalized pageview already carries the arrival on the same journey, so a
2594
+ * second event would add no fact. `capability_refusal_displayed` and
2595
+ * `signer_refusal_displayed` belong to the screens that draw those refusals
2596
+ * (Recipients, Invoice, Payroll, Quick Pay); Access publishes the contract and
2597
+ * the `CanReason` those owners report, and produces neither itself.
2598
+ */
2599
+ const UiAccessStepCompletedTelemetryEventSchema = Schema.Struct({
2600
+ name: Schema.Literal("ui_access_step_completed"),
2601
+ props: Schema.Struct({
2602
+ ...UiStepProps,
2603
+ step: Schema.Literals([
2604
+ "dashboard_granted",
2605
+ "redirect_completed",
2606
+ "gate_error_displayed",
2607
+ "retry_selected",
2608
+ "capability_refusal_displayed",
2609
+ "signer_refusal_displayed"
2610
+ ]),
2611
+ capability: Schema.optional(Schema.Literals(["spend", "managePeople"])),
2612
+ probe: Schema.optional(Schema.Literals([
2613
+ "session",
2614
+ "membership",
2615
+ "lifecycle"
2616
+ ])),
2617
+ reason: Schema.optional(Schema.Literals([
2618
+ "loading",
2619
+ "no-permission",
2620
+ "org-unavailable"
2621
+ ]))
2622
+ })
2623
+ });
2624
+ /**
2625
+ * R06 (#1964) wired three of the four progress words to the durable writer that
2626
+ * commits each one. `account_ready` comes from `org/memberLifecycle.ts`, for
2627
+ * every membership row a claimed personal Account actually advanced.
2628
+ * `permission_applied` and `membership_activated` come from
2629
+ * `permission/mirror.ts`: the first only when the mirror wrote a NEW Permission
2630
+ * state, the second only when that call flipped a `pending_grant` row to
2631
+ * `active`. A replay of an applied command writes neither, so it reports
2632
+ * neither. `revoked` stays RESERVED and unproduced — no writer revokes a
2633
+ * membership yet, and #1459 owns that ceremony.
2634
+ */
2635
+ const OrgInviteProgressedTelemetryEventSchema = Schema.Struct({
2636
+ name: Schema.Literal("org_invite_progressed"),
2637
+ props: Schema.Struct({
2638
+ ...TelemetryEnvelopeProps,
2639
+ organization_id: OrgIdTelemetrySchema,
2640
+ progress: Schema.Literals([
2641
+ "configuration_authorized",
2642
+ "account_ready",
2643
+ "permission_applied",
2644
+ "membership_activated",
2645
+ "revoked"
2646
+ ]),
2647
+ /** The invited Party. The initiating actor stays on the envelope's identity. */
2648
+ member_party_id: Schema.String,
2649
+ invitation_id: Schema.optional(Schema.String),
2650
+ generation: Schema.optional(Schema.String),
2651
+ command_id: Schema.optional(Schema.String),
2652
+ occurred_at: Schema.Number
2653
+ })
2654
+ });
2655
+ const InvoiceIssuedTelemetryEventSchema = Schema.Struct({
2656
+ name: Schema.Literal("invoice_issued"),
2657
+ props: Schema.Struct({
2658
+ ...TelemetryEnvelopeProps,
2659
+ request_id: Schema.String,
2660
+ issuer_scope_kind: ScopeKindSchema,
2661
+ issuer_scope_id: Schema.String,
2662
+ payer_party_id: OptionalString,
2663
+ occurred_at: Schema.Number
2664
+ })
2665
+ });
2666
+ const InvoiceRequestTransitionedTelemetryEventSchema = Schema.Struct({
2667
+ name: Schema.Literal("invoice_request_transitioned"),
2668
+ props: Schema.Struct({
2669
+ ...TelemetryEnvelopeProps,
2670
+ request_id: Schema.String,
2671
+ transition: Schema.Literals([
2672
+ "approval_prepared",
2673
+ "declined",
2674
+ "cancelled"
2675
+ ]),
2676
+ actor_scope_kind: ScopeKindSchema,
2677
+ actor_scope_id: Schema.String,
2678
+ occurred_at: Schema.Number
2679
+ })
2680
+ });
2681
+ const UiInvoiceStepCompletedTelemetryEventSchema = Schema.Struct({
2682
+ name: Schema.Literal("ui_invoice_step_completed"),
2683
+ props: Schema.Struct({
2684
+ ...UiStepProps,
2685
+ step: Schema.Literals([
2686
+ "opened",
2687
+ "previewed",
2688
+ "dismissed",
2689
+ "submitted",
2690
+ "result_displayed",
2691
+ "refusal_displayed",
2692
+ "retry_selected"
2693
+ ]),
2694
+ request_id: OptionalString
2695
+ })
2696
+ });
2697
+ const UiTreasuryStepCompletedTelemetryEventSchema = Schema.Struct({
2698
+ name: Schema.Literal("ui_treasury_step_completed"),
2699
+ props: Schema.Struct({
2700
+ ...UiStepProps,
2701
+ step: Schema.Literals([
2702
+ "balance_displayed",
2703
+ "read_refusal_displayed",
2704
+ "retry_selected",
2705
+ "recovery_completed"
2706
+ ]),
2707
+ account_kind: Schema.optional(AccountKindSchema)
2708
+ })
2709
+ });
2710
+ const UiReceiveStepCompletedTelemetryEventSchema = Schema.Struct({
2711
+ name: Schema.Literal("ui_receive_step_completed"),
2712
+ props: Schema.Struct({
2713
+ ...UiStepProps,
2714
+ step: Schema.Literals([
2715
+ "instructions_displayed",
2716
+ "address_copied",
2717
+ "copy_failed",
2718
+ "refusal_displayed",
2719
+ "retry_selected"
2720
+ ]),
2721
+ account_kind: Schema.optional(AccountKindSchema)
2722
+ })
2723
+ });
2724
+ const PayrollGroupChangedTelemetryEventSchema = Schema.Struct({
2725
+ name: Schema.Literal("payroll_group_changed"),
2726
+ props: Schema.Struct({
2727
+ ...TelemetryEnvelopeProps,
2728
+ organization_id: OrgIdTelemetrySchema,
2729
+ change: Schema.Literals([
2730
+ "created",
2731
+ "updated",
2732
+ "deleted"
2733
+ ]),
2734
+ group_id: Schema.String,
2735
+ member_count: Schema.Number,
2736
+ occurred_at: Schema.Number
2737
+ })
2738
+ });
2739
+ const PayrollRunTransitionedTelemetryEventSchema = Schema.Struct({
2740
+ name: Schema.Literal("payroll_run_transitioned"),
2741
+ props: Schema.Struct({
2742
+ ...TelemetryEnvelopeProps,
2743
+ organization_id: OrgIdTelemetrySchema,
2744
+ transition: Schema.Literals([
2745
+ "prepared",
2746
+ "authorized",
2747
+ "settled"
2748
+ ]),
2749
+ run_id: Schema.String,
2750
+ /**
2751
+ * The `paymentCommands` row at `payrollRuns.batchRef` — the durable owner of
2752
+ * this run's Payment membership. `payment_count` counts THAT command's
2753
+ * `paymentIds`, so an unrelated Payment quoting the run id changes neither.
2754
+ */
2755
+ command_id: OptionalString,
2756
+ payment_count: Schema.optional(Schema.Number),
2757
+ occurred_at: Schema.Number
2758
+ })
2759
+ });
2760
+ const UiPayrollActionCompletedTelemetryEventSchema = Schema.Struct({
2761
+ name: Schema.Literal("ui_payroll_action_completed"),
2762
+ props: Schema.Struct({
2763
+ ...UiStepProps,
2764
+ action: Schema.Literals([
2765
+ "opened",
2766
+ "refusal_displayed",
2767
+ "recovery_completed",
2768
+ "cancelled",
2769
+ "submitted_displayed"
2770
+ ]),
2771
+ run_id: OptionalString
2772
+ })
2773
+ });
2774
+ const TELEMETRY_EVENT_SCHEMAS = {
2775
+ contact_relationship_changed: ContactRelationshipChangedTelemetryEventSchema,
2776
+ access_recovery_completed: AccessRecoveryCompletedTelemetryEventSchema,
2777
+ ui_access_step_completed: UiAccessStepCompletedTelemetryEventSchema,
2778
+ org_invite_progressed: OrgInviteProgressedTelemetryEventSchema,
2779
+ invoice_issued: InvoiceIssuedTelemetryEventSchema,
2780
+ invoice_request_transitioned: InvoiceRequestTransitionedTelemetryEventSchema,
2781
+ ui_invoice_step_completed: UiInvoiceStepCompletedTelemetryEventSchema,
2782
+ ui_treasury_step_completed: UiTreasuryStepCompletedTelemetryEventSchema,
2783
+ ui_receive_step_completed: UiReceiveStepCompletedTelemetryEventSchema,
2784
+ payroll_group_changed: PayrollGroupChangedTelemetryEventSchema,
2785
+ payroll_run_transitioned: PayrollRunTransitionedTelemetryEventSchema,
2786
+ ui_payroll_action_completed: UiPayrollActionCompletedTelemetryEventSchema,
2787
+ ui_contact_action_completed: UiContactActionCompletedTelemetryEventSchema,
2788
+ cli_diagnostic_completed: CliDiagnosticCompletedTelemetryEventSchema,
2789
+ cli_first_used: CliFirstUsedTelemetryEventSchema,
2790
+ cli_command_started: CliCommandStartedTelemetryEventSchema,
2791
+ cli_command_completed: CliCommandCompletedTelemetryEventSchema,
2792
+ activity_annotation_saved: ActivityAnnotationSavedTelemetryEventSchema,
2793
+ ui_activity_action_completed: UiActivityActionCompletedTelemetryEventSchema,
2794
+ auth_otp_requested: AuthOtpRequestedTelemetryEventSchema,
2795
+ auth_otp_delivered: AuthOtpDeliveredTelemetryEventSchema,
2796
+ auth_otp_expired: AuthOtpExpiredTelemetryEventSchema,
2797
+ auth_verified: AuthVerifiedTelemetryEventSchema,
2798
+ auth_failed: AuthFailedTelemetryEventSchema,
2799
+ identity_refused: IdentityRefusedTelemetryEventSchema,
2800
+ auth_signed_out: AuthSignedOutTelemetryEventSchema,
2801
+ native_authorization_started: NativeAuthorizationStartedTelemetryEventSchema,
2802
+ native_authorization_reviewed: NativeAuthorizationReviewedTelemetryEventSchema,
2803
+ native_authorization_accepted: NativeAuthorizationAcceptedTelemetryEventSchema,
2804
+ native_authorization_denied: NativeAuthorizationDeniedTelemetryEventSchema,
2805
+ native_authorization_connected: NativeAuthorizationConnectedTelemetryEventSchema,
2806
+ native_authorization_failed: NativeAuthorizationFailedTelemetryEventSchema,
2807
+ onboarding_intent_selected: OnboardingIntentSelectedTelemetryEventSchema,
2808
+ onboarding_profile_submitted: OnboardingProfileSubmittedTelemetryEventSchema,
2809
+ onboarding_organization_submitted: OnboardingOrganizationSubmittedTelemetryEventSchema,
2810
+ onboarding_dashboard_reached: OnboardingDashboardReachedTelemetryEventSchema,
2811
+ provisioning_safe_created: ProvisioningSafeCreatedTelemetryEventSchema,
2812
+ provisioning_safe_confirmed: ProvisioningSafeConfirmedTelemetryEventSchema,
2813
+ bootstrap_resolved: BootstrapResolvedTelemetryEventSchema,
2814
+ bootstrap_failed: BootstrapFailedTelemetryEventSchema,
2815
+ member_activation_started: MemberActivationStartedTelemetryEventSchema,
2816
+ member_activation_ready: MemberActivationReadyTelemetryEventSchema,
2817
+ member_activation_failed: MemberActivationFailedTelemetryEventSchema,
2818
+ organization_creation_started: OrganizationCreationStartedTelemetryEventSchema,
2819
+ organization_creation_ready: OrganizationCreationReadyTelemetryEventSchema,
2820
+ organization_creation_failed: OrganizationCreationFailedTelemetryEventSchema,
2821
+ account_balance_read: AccountBalanceReadTelemetryEventSchema,
2822
+ account_balance_failed: AccountBalanceFailedTelemetryEventSchema,
2823
+ faucet_requested: FaucetRequestedTelemetryEventSchema,
2824
+ faucet_confirmed: FaucetConfirmedTelemetryEventSchema,
2825
+ faucet_failed: FaucetFailedTelemetryEventSchema,
2826
+ chain_upstream_fallback: ChainUpstreamFallbackTelemetryEventSchema,
2827
+ bundler_error: BundlerErrorTelemetryEventSchema,
2828
+ receipt_pending: ReceiptPendingTelemetryEventSchema,
2829
+ operation_retried: OperationRetriedTelemetryEventSchema,
2830
+ org_create_started: OrgCreateStartedTelemetryEventSchema,
2831
+ org_safe_created: OrgSafeCreatedTelemetryEventSchema,
2832
+ org_safe_confirmed: OrgSafeConfirmedTelemetryEventSchema,
2833
+ org_roles_seeded: OrgRolesSeededTelemetryEventSchema,
2834
+ org_created: OrgCreatedTelemetryEventSchema,
2835
+ org_create_failed: OrgCreateFailedTelemetryEventSchema,
2836
+ org_invite_sent: OrgInviteSentTelemetryEventSchema,
2837
+ org_invite_accepted: OrgInviteAcceptedTelemetryEventSchema,
2838
+ org_invite_expired: OrgInviteExpiredTelemetryEventSchema,
2839
+ payment_initiated: PaymentInitiatedTelemetryEventSchema,
2840
+ payment_settled: PaymentSettledTelemetryEventSchema,
2841
+ payment_failed: PaymentFailedTelemetryEventSchema,
2842
+ payment_verification_retry: PaymentVerificationRetryTelemetryEventSchema,
2843
+ payment_lifecycle_transition: PaymentLifecycleTransitionTelemetryEventSchema,
2844
+ quick_pay_external_address_acknowledged: QuickPayExternalAddressAcknowledgedTelemetryEventSchema,
2845
+ deposit_initiated: DepositInitiatedTelemetryEventSchema,
2846
+ deposit_settled: DepositSettledTelemetryEventSchema,
2847
+ permission_mirror_verification: PermissionMirrorVerificationTelemetryEventSchema,
2848
+ movement_scan_window: MovementScanWindowTelemetryEventSchema,
2849
+ movement_scan_checkpoint: MovementScanCheckpointTelemetryEventSchema,
2850
+ movement_scan_incident: MovementScanIncidentTelemetryEventSchema,
2851
+ indexer_drift_corrected: IndexerDriftCorrectedTelemetryEventSchema
2852
+ };
2853
+ const FINANCIAL_OPS_TARGET_TELEMETRY_PRODUCERS = [];
2854
+ /**
2855
+ * Contract-first events whose producer is owned by a later domain node.
2856
+ *
2857
+ * A domain node removes its entry when it adds the producer. The telemetry
2858
+ * gate rejects an entry that has a producer.
2859
+ */
2860
+ const CONTRACT_FIRST_TELEMETRY_EVENTS = [];
2861
+ /**
2862
+ * Catalog events whose product mapper remains gated on the #1150 frontend
2863
+ * adoption. L1 S1 removes their retired SDK-flow producers without inventing
2864
+ * replacements inside the identity actor. The telemetry-spine gate enforces
2865
+ * planned-XOR-wired: a name must leave this list in the same change that adds
2866
+ * its real product-boundary producer.
2867
+ */
2868
+ const PRODUCT_MAPPER_GATED_TELEMETRY_EVENTS = ["auth_otp_expired"];
2869
+ /** Catalogued browser observations whose producers remain owned by app adoption. */
2870
+ const BROWSER_GATED_TELEMETRY_EVENTS = [
2871
+ "onboarding_intent_selected",
2872
+ "onboarding_profile_submitted",
2873
+ "onboarding_organization_submitted",
2874
+ "onboarding_dashboard_reached",
2875
+ "ui_activity_action_completed",
2876
+ "ui_contact_action_completed",
2877
+ "ui_access_step_completed",
2878
+ "ui_invoice_step_completed",
2879
+ "ui_treasury_step_completed",
2880
+ "ui_receive_step_completed",
2881
+ "ui_payroll_action_completed"
2882
+ ];
2883
+ let trackHandler = () => {};
2884
+ function setTrackHandler(handler) {
2885
+ const previous = trackHandler;
2886
+ trackHandler = handler;
2887
+ return previous;
2888
+ }
2889
+ function getTrackHandler() {
2890
+ return trackHandler;
2891
+ }
2892
+ function track(name, props) {
2893
+ trackHandler(name, props);
2894
+ }
2895
+ function redactTelemetryEvent(event, options = {}) {
2896
+ const props = redactTelemetryProps(event.name, event.props, options);
2897
+ return props === void 0 ? { name: event.name } : {
2898
+ name: event.name,
2899
+ props
2900
+ };
2901
+ }
2902
+ function redactTelemetryProps(name, props, options = {}) {
2903
+ if (props === void 0) return void 0;
2904
+ const clone = cloneProps(props);
2905
+ if (options.rawMode === true) return clone;
2906
+ for (const key of PII_PROP_KEYS_BY_EVENT[name] ?? []) redactProperty(clone, key);
2907
+ return clone;
2908
+ }
2909
+ /**
2910
+ * Remove query strings and fragments from every PostHog URL/referrer/path
2911
+ * property before transport. Browser applications may carry emails, draft ids,
2912
+ * or other capabilities in the URL; those values must never leave the origin.
2913
+ *
2914
+ * The callback replaces the event's data with a sanitized copy. Nested values
2915
+ * can refer to live clients or configuration; observation must never mutate them.
2916
+ */
2917
+ function sanitizePostHogBrowserEvent(event, urlPolicy = "path-only") {
2918
+ if (event === null) return event;
2919
+ const transportToken = event.properties.token;
2920
+ const seen = /* @__PURE__ */ new WeakMap();
2921
+ event.properties = sanitizePostHogBrowserValue(event.properties, seen, urlPolicy);
2922
+ if (transportToken !== void 0) event.properties.token = transportToken;
2923
+ if (event.$set !== void 0) event.$set = sanitizePostHogBrowserValue(event.$set, seen, urlPolicy);
2924
+ if (event.$set_once !== void 0) event.$set_once = sanitizePostHogBrowserValue(event.$set_once, seen, urlPolicy);
2925
+ return event;
2926
+ }
2927
+ /**
2928
+ * Drop local events before transport. Sanitize and stamp every other browser
2929
+ * event with `capxul_env` and `producer: "browser"`.
2930
+ */
2931
+ function createCapxulBeforeSend(capxulEnv, urlPolicy = "path-only") {
2932
+ return (event) => {
2933
+ if (capxulEnv === "local") return null;
2934
+ const sanitized = sanitizePostHogBrowserEvent(event, urlPolicy);
2935
+ if (sanitized === null) return sanitized;
2936
+ sanitized.properties.capxul_env = capxulEnv;
2937
+ sanitized.properties.producer ??= "browser";
2938
+ return sanitized;
2939
+ };
2940
+ }
2941
+ function utilityAppAnalytics(input) {
2942
+ return {
2943
+ api_host: input.host,
2944
+ defaults: "2026-01-30",
2945
+ autocapture: false,
2946
+ capture_pageview: false,
2947
+ capture_pageleave: true,
2948
+ disable_session_recording: true,
2949
+ disable_persistence: true,
2950
+ capture_heatmaps: false,
2951
+ capture_exceptions: false,
2952
+ capture_performance: false,
2953
+ disable_surveys: true,
2954
+ disable_web_experiments: true,
2955
+ disable_product_tours: true,
2956
+ disable_conversations: true,
2957
+ disable_external_dependency_loading: true,
2958
+ person_profiles: "identified_only",
2959
+ advanced_disable_flags: true,
2960
+ save_campaign_params: false,
2961
+ save_referrer: false,
2962
+ before_send: createCapxulBeforeSend(input.capxulEnv)
2963
+ };
2964
+ }
2965
+ /** In unstructured bodies, preserve text around explicitly named credentials. */
2966
+ const NETWORK_FIELD = /((?:"?)([A-Za-z_][A-Za-z0-9_.-]*)(?:"?)\s*[:=]\s*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^\s,;&}]+)/gu;
2967
+ function maskNetworkText(text, context) {
2968
+ return redactSecrets(text).replace(NETWORK_FIELD, (whole, prefix, name, value) => {
2969
+ if (!isCredentialField(name, context)) return whole;
2970
+ const quote = value.startsWith("\"") ? "\"" : value.startsWith("'") ? "'" : "";
2971
+ return `${prefix}${quote}[REDACTED]${quote}`;
2972
+ });
2973
+ }
2974
+ function maskNetworkHeaders(headers) {
2975
+ if (headers === void 0) return void 0;
2976
+ const masked = {};
2977
+ for (const [name, value] of Object.entries(headers)) masked[name] = isCredentialField(name, "header") ? "[REDACTED]" : /^(?:location|content-location|referer)$/iu.test(name) ? redactUrlSecrets(value) : maskNetworkText(value);
2978
+ return masked;
2979
+ }
2980
+ function maskJsonValue(value, depth = 0, context) {
2981
+ if (typeof value === "function" || typeof value === "symbol") return "[UNREADABLE]";
2982
+ if (typeof value === "string") return maskNetworkText(value, context);
2983
+ if (typeof value !== "object" || value === null) return value;
2984
+ if (depth >= 16) return "[REDACTED]";
2985
+ if (Array.isArray(value)) return value.map((item) => maskJsonValue(item, depth + 1, context));
2986
+ const masked = Object.create(null);
2987
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
2988
+ if (!descriptor.enumerable) continue;
2989
+ masked[key] = isCredentialField(key, context) ? "[REDACTED]" : !("value" in descriptor) ? "[UNREADABLE]" : typeof descriptor.value === "string" && isPostHogUrlProperty(key) ? redactUrlSecrets(descriptor.value) : maskJsonValue(descriptor.value, depth + 1, context);
2990
+ }
2991
+ return masked;
2992
+ }
2993
+ function maskNetworkBody(body, context) {
2994
+ try {
2995
+ if (typeof body !== "string") return maskJsonValue(body, 0, context);
2996
+ let parsed;
2997
+ try {
2998
+ parsed = JSON.parse(body);
2999
+ } catch {
3000
+ if (/^[^=&\s]+=[\s\S]*$/u.test(body)) return new URLSearchParams(Array.from(new URLSearchParams(body), ([name, value]) => [name, isCredentialField(name, context) ? "[REDACTED]" : maskNetworkText(value)])).toString();
3001
+ return maskNetworkText(body, context);
3002
+ }
3003
+ return JSON.stringify(maskJsonValue(parsed, 0, context));
3004
+ } catch {
3005
+ return "[UNREADABLE]";
3006
+ }
3007
+ }
3008
+ /** Keep request evidence while masking credential values at the browser boundary. */
3009
+ function maskCapturedNetworkRequest(request) {
3010
+ const requestUrl = request.name ?? request.url ?? "";
3011
+ let context;
3012
+ try {
3013
+ const path = new URL(requestUrl, "https://capxul.invalid").pathname;
3014
+ if (/\/(?:auth|oauth|sign-in|signin|login|verify-otp|verify-email)(?:\/|$)/iu.test(path)) context = "authentication";
3015
+ } catch {}
3016
+ return {
3017
+ ...request,
3018
+ ...request.name === void 0 ? {} : { name: redactUrlSecrets(request.name) },
3019
+ ...request.url === void 0 ? {} : { url: redactUrlSecrets(request.url) },
3020
+ requestHeaders: maskNetworkHeaders(request.requestHeaders),
3021
+ responseHeaders: maskNetworkHeaders(request.responseHeaders),
3022
+ requestBody: maskNetworkBody(request.requestBody, context),
3023
+ responseBody: maskNetworkBody(request.responseBody)
3024
+ };
3025
+ }
3026
+ function productAppAnalytics(input) {
3027
+ return {
3028
+ api_host: input.host,
3029
+ defaults: "2026-01-30",
3030
+ autocapture: false,
3031
+ capture_pageview: false,
3032
+ capture_pageleave: true,
3033
+ disable_session_recording: false,
3034
+ disable_persistence: false,
3035
+ capture_heatmaps: false,
3036
+ capture_exceptions: true,
3037
+ capture_performance: {
3038
+ network_timing: true,
3039
+ web_vitals: false
3040
+ },
3041
+ disable_surveys: true,
3042
+ disable_web_experiments: true,
3043
+ disable_product_tours: true,
3044
+ disable_conversations: true,
3045
+ disable_external_dependency_loading: false,
3046
+ person_profiles: "identified_only",
3047
+ advanced_disable_flags: false,
3048
+ save_campaign_params: false,
3049
+ save_referrer: false,
3050
+ session_recording: {
3051
+ maskAllInputs: true,
3052
+ maskInputFn: (text, element) => {
3053
+ const autocomplete = element?.getAttribute("autocomplete")?.toLowerCase().split(/\s+/u) ?? [];
3054
+ return element?.getAttribute("type")?.toLowerCase() === "password" || autocomplete.some((value) => [
3055
+ "one-time-code",
3056
+ "current-password",
3057
+ "new-password"
3058
+ ].includes(value)) || isCredentialField(element?.getAttribute("name") ?? "") || isCredentialField(element?.getAttribute("id") ?? "") ? "*".repeat(text.length) : maskNetworkText(text);
3059
+ },
3060
+ captureCanvas: { recordCanvas: false },
3061
+ recordHeaders: true,
3062
+ recordBody: true,
3063
+ maskCapturedNetworkRequestFn: maskCapturedNetworkRequest
3064
+ },
3065
+ before_send: createCapxulBeforeSend(input.capxulEnv, "diagnostic")
3066
+ };
3067
+ }
3068
+ /**
3069
+ * Apply a named privacy profile before an application-owned PostHog client
3070
+ * initializes. Hosts still own the vendor client and lifecycle; this helper
3071
+ * centralizes the security-relevant options and the missing-key opt-out (no
3072
+ * key ⇒ no client ⇒ no network call).
3073
+ */
3074
+ function initializeCapxulBrowserAnalytics(profile, input, initialize) {
3075
+ const key = input.key?.trim();
3076
+ if (key === void 0 || key.length === 0) return void 0;
3077
+ try {
3078
+ const options = profile(input);
3079
+ const client = initialize(key, options);
3080
+ warnWhenReplayHasNoRecorder(options, client);
3081
+ return client;
3082
+ } catch {
3083
+ return;
3084
+ }
3085
+ }
3086
+ let replayRecorderWarned = false;
3087
+ /**
3088
+ * #1709: `posthog-js/dist/module.slim` never registers the session recording
3089
+ * manager, so a profile that enables replay records nothing with it. The
3090
+ * client exposes the manager as `sessionRecording` once `init` ran on the
3091
+ * standard build. Warn once per page so the missing build is visible.
3092
+ */
3093
+ function warnWhenReplayHasNoRecorder(options, client) {
3094
+ if (replayRecorderWarned) return;
3095
+ const replayEnabled = typeof options === "object" && options !== null && options.disable_session_recording === false;
3096
+ const recorderMissing = typeof client === "object" && client !== null && client.sessionRecording === void 0;
3097
+ if (!replayEnabled || !recorderMissing) return;
3098
+ replayRecorderWarned = true;
3099
+ console.warn("@capxul/observability: session replay is enabled but the PostHog client has no session recording manager. Import the standard `posthog-js` build; `posthog-js/dist/module.slim` records nothing.");
3100
+ }
3101
+ /** The utility profile, pre-bound — the shape ADR-0016's consumers already use. */
3102
+ function initializePostHogBrowserAnalytics(input, initialize) {
3103
+ return initializeCapxulBrowserAnalytics(utilityAppAnalytics, input, initialize);
3104
+ }
3105
+ /**
3106
+ * Build an explicit SPA pageview sink for toolbar-free PostHog clients. The
3107
+ * pathname-only input avoids query capabilities, repeated pathnames are
3108
+ * deduplicated, and vendor failures remain best-effort.
3109
+ */
3110
+ function createPostHogBrowserPageviewTracker(client) {
3111
+ let previousPathname;
3112
+ return (pathname) => {
3113
+ if (client === null || client === void 0) return;
3114
+ const safePathname = stripUrlQueryAndFragment(pathname);
3115
+ if (safePathname === previousPathname) return;
3116
+ try {
3117
+ Promise.resolve(client.capture("$pageview", { $pathname: safePathname })).catch(() => {});
3118
+ previousPathname = safePathname;
3119
+ } catch {}
3120
+ };
3121
+ }
3122
+ function sanitizePostHogBrowserValue(value, seen, urlPolicy) {
3123
+ if (typeof value !== "object" || value === null || value instanceof Date) return value;
3124
+ if (seen.has(value)) return seen.get(value);
3125
+ if (Array.isArray(value)) {
3126
+ const copy = [];
3127
+ seen.set(value, copy);
3128
+ for (let index = 0; index < value.length; index++) {
3129
+ const item = value[index];
3130
+ copy[index] = typeof item === "string" ? maskNetworkText(item) : sanitizePostHogBrowserValue(item, seen, urlPolicy);
3131
+ }
3132
+ return copy;
3133
+ }
3134
+ const properties = Object.create(null);
3135
+ seen.set(value, properties);
3136
+ for (const [key, nestedValue] of Object.entries(value)) {
3137
+ if (isPostHogQueryDerivedProperty(key)) continue;
3138
+ if (isCredentialField(key)) {
3139
+ properties[key] = "[REDACTED]";
3140
+ continue;
3141
+ }
3142
+ if (typeof nestedValue === "string") {
3143
+ properties[key] = isPostHogUrlProperty(key) ? urlPolicy === "path-only" ? stripUrlQueryAndFragment(nestedValue) : redactUrlSecrets(nestedValue) : maskNetworkText(nestedValue);
3144
+ continue;
3145
+ }
3146
+ properties[key] = sanitizePostHogBrowserValue(nestedValue, seen, urlPolicy);
3147
+ }
3148
+ return properties;
3149
+ }
3150
+ const POSTHOG_QUERY_DERIVED_PROPERTY_NAMES = [
3151
+ "utm_source",
3152
+ "utm_medium",
3153
+ "utm_campaign",
3154
+ "utm_content",
3155
+ "utm_term",
3156
+ "gad_source",
3157
+ "mc_cid",
3158
+ "gclid",
3159
+ "gclsrc",
3160
+ "dclid",
3161
+ "gbraid",
3162
+ "wbraid",
3163
+ "fbclid",
3164
+ "msclkid",
3165
+ "twclid",
3166
+ "li_fat_id",
3167
+ "igshid",
3168
+ "ttclid",
3169
+ "rdt_cid",
3170
+ "epik",
3171
+ "qclid",
3172
+ "sccid",
3173
+ "irclid",
3174
+ "_kx",
3175
+ "ph_keyword"
3176
+ ];
3177
+ function isPostHogQueryDerivedProperty(key) {
3178
+ const normalized = key.toLowerCase();
3179
+ return POSTHOG_QUERY_DERIVED_PROPERTY_NAMES.some((propertyName) => normalized === propertyName || normalized.endsWith(`_${propertyName}`) || normalized.endsWith(`$${propertyName}`));
3180
+ }
3181
+ function isPostHogUrlProperty(key) {
3182
+ const normalized = key.toLowerCase();
3183
+ return normalized.includes("url") || normalized.includes("referrer") || normalized.includes("path") || normalized.includes("filename");
3184
+ }
3185
+ function stripUrlQueryAndFragment(value) {
3186
+ const queryIndex = value.indexOf("?");
3187
+ const fragmentIndex = value.indexOf("#");
3188
+ if (queryIndex === -1 && fragmentIndex === -1) return value;
3189
+ if (queryIndex === -1) return value.slice(0, fragmentIndex);
3190
+ if (fragmentIndex === -1) return value.slice(0, queryIndex);
3191
+ return value.slice(0, Math.min(queryIndex, fragmentIndex));
3192
+ }
3193
+ var RecordingTelemetryAdapter = class {
3194
+ #events = [];
3195
+ #rawMode;
3196
+ constructor(options = {}) {
3197
+ this.#rawMode = options.rawMode === true;
3198
+ }
3199
+ get events() {
3200
+ return this.#events.map((event) => cloneEvent(event));
3201
+ }
3202
+ emit(event) {
3203
+ return Effect.sync(() => {
3204
+ this.#events.push(redactTelemetryEvent(event, { rawMode: this.#rawMode }));
3205
+ });
3206
+ }
3207
+ identify(_input) {
3208
+ return Effect.void;
3209
+ }
3210
+ group(_input) {
3211
+ return Effect.void;
3212
+ }
3213
+ reset() {
3214
+ return Effect.void;
3215
+ }
3216
+ reportHandledError(_error, _context) {
3217
+ return Effect.void;
3218
+ }
3219
+ clear() {
3220
+ this.#events.length = 0;
3221
+ }
3222
+ };
3223
+ var PostHogTelemetryAdapter = class {
3224
+ #capture;
3225
+ constructor(deps) {
3226
+ this.#capture = deps.capture;
3227
+ }
3228
+ emit(event) {
3229
+ return Effect.sync(() => {
3230
+ try {
3231
+ Promise.resolve(this.#capture(event.name, redactTelemetryProps(event.name, event.props))).catch(() => {});
3232
+ } catch {}
3233
+ });
3234
+ }
3235
+ identify(_input) {
3236
+ return Effect.void;
3237
+ }
3238
+ group(_input) {
3239
+ return Effect.void;
3240
+ }
3241
+ reset() {
3242
+ return Effect.void;
3243
+ }
3244
+ reportHandledError(_error, _context) {
3245
+ return Effect.void;
3246
+ }
3247
+ };
3248
+ var InMemoryTelemetryBusAdapter = class {
3249
+ #subscribers = /* @__PURE__ */ new Set();
3250
+ #rawMode;
3251
+ constructor(options = {}) {
3252
+ this.#rawMode = options.rawMode === true;
3253
+ }
3254
+ subscribe(handler) {
3255
+ this.#subscribers.add(handler);
3256
+ return () => {
3257
+ this.#subscribers.delete(handler);
3258
+ };
3259
+ }
3260
+ emit(event) {
3261
+ return Effect.sync(() => {
3262
+ const delivered = redactTelemetryEvent(event, { rawMode: this.#rawMode });
3263
+ for (const handler of this.#subscribers) try {
3264
+ handler(cloneEvent(delivered));
3265
+ } catch {}
3266
+ });
3267
+ }
3268
+ identify(_input) {
3269
+ return Effect.void;
3270
+ }
3271
+ group(_input) {
3272
+ return Effect.void;
3273
+ }
3274
+ reset() {
3275
+ return Effect.void;
3276
+ }
3277
+ reportHandledError(_error, _context) {
3278
+ return Effect.void;
3279
+ }
3280
+ };
3281
+ const PII_PROP_KEYS_BY_EVENT = {
3282
+ auth_otp_requested: ["email"],
3283
+ auth_otp_delivered: ["email"],
3284
+ auth_otp_expired: ["email"],
3285
+ auth_failed: ["email"]
3286
+ };
3287
+ function redactProperty(props, key) {
3288
+ const value = props[key];
3289
+ if (typeof value === "string") props[key] = sha256Hex(value).slice(0, 12);
3290
+ }
3291
+ function cloneEvent(event) {
3292
+ if (event.props === void 0) return { name: event.name };
3293
+ return {
3294
+ name: event.name,
3295
+ props: cloneProps(event.props)
3296
+ };
3297
+ }
3298
+ function cloneProps(props) {
3299
+ const cloned = {};
3300
+ for (const [key, value] of Object.entries(props)) cloned[key] = cloneTelemetryValue(value);
3301
+ return cloned;
3302
+ }
3303
+ function cloneTelemetryValue(value) {
3304
+ if (Array.isArray(value)) return value.map(cloneTelemetryValue);
3305
+ if (value === null || typeof value !== "object") return value;
3306
+ if (Object.getPrototypeOf(value) !== Object.prototype) return value;
3307
+ const cloned = {};
3308
+ for (const [key, nested] of Object.entries(value)) cloned[key] = cloneTelemetryValue(nested);
3309
+ return cloned;
3310
+ }
3311
+ const SHA256_INITIAL_HASH = [
3312
+ 1779033703,
3313
+ 3144134277,
3314
+ 1013904242,
3315
+ 2773480762,
3316
+ 1359893119,
3317
+ 2600822924,
3318
+ 528734635,
3319
+ 1541459225
3320
+ ];
3321
+ const SHA256_K = [
3322
+ 1116352408,
3323
+ 1899447441,
3324
+ 3049323471,
3325
+ 3921009573,
3326
+ 961987163,
3327
+ 1508970993,
3328
+ 2453635748,
3329
+ 2870763221,
3330
+ 3624381080,
3331
+ 310598401,
3332
+ 607225278,
3333
+ 1426881987,
3334
+ 1925078388,
3335
+ 2162078206,
3336
+ 2614888103,
3337
+ 3248222580,
3338
+ 3835390401,
3339
+ 4022224774,
3340
+ 264347078,
3341
+ 604807628,
3342
+ 770255983,
3343
+ 1249150122,
3344
+ 1555081692,
3345
+ 1996064986,
3346
+ 2554220882,
3347
+ 2821834349,
3348
+ 2952996808,
3349
+ 3210313671,
3350
+ 3336571891,
3351
+ 3584528711,
3352
+ 113926993,
3353
+ 338241895,
3354
+ 666307205,
3355
+ 773529912,
3356
+ 1294757372,
3357
+ 1396182291,
3358
+ 1695183700,
3359
+ 1986661051,
3360
+ 2177026350,
3361
+ 2456956037,
3362
+ 2730485921,
3363
+ 2820302411,
3364
+ 3259730800,
3365
+ 3345764771,
3366
+ 3516065817,
3367
+ 3600352804,
3368
+ 4094571909,
3369
+ 275423344,
3370
+ 430227734,
3371
+ 506948616,
3372
+ 659060556,
3373
+ 883997877,
3374
+ 958139571,
3375
+ 1322822218,
3376
+ 1537002063,
3377
+ 1747873779,
3378
+ 1955562222,
3379
+ 2024104815,
3380
+ 2227730452,
3381
+ 2361852424,
3382
+ 2428436474,
3383
+ 2756734187,
3384
+ 3204031479,
3385
+ 3329325298
3386
+ ];
3387
+ function sha256Hex(input) {
3388
+ const padded = padSha256Message(new TextEncoder().encode(input));
3389
+ const view = new DataView(padded.buffer, padded.byteOffset, padded.byteLength);
3390
+ const words = /* @__PURE__ */ new Uint32Array(64);
3391
+ let h0 = SHA256_INITIAL_HASH[0];
3392
+ let h1 = SHA256_INITIAL_HASH[1];
3393
+ let h2 = SHA256_INITIAL_HASH[2];
3394
+ let h3 = SHA256_INITIAL_HASH[3];
3395
+ let h4 = SHA256_INITIAL_HASH[4];
3396
+ let h5 = SHA256_INITIAL_HASH[5];
3397
+ let h6 = SHA256_INITIAL_HASH[6];
3398
+ let h7 = SHA256_INITIAL_HASH[7];
3399
+ for (let offset = 0; offset < padded.byteLength; offset += 64) {
3400
+ for (let i = 0; i < 16; i++) words[i] = view.getUint32(offset + i * 4);
3401
+ for (let i = 16; i < 64; i++) {
3402
+ const s0 = rotr(words[i - 15], 7) ^ rotr(words[i - 15], 18) ^ words[i - 15] >>> 3;
3403
+ const s1 = rotr(words[i - 2], 17) ^ rotr(words[i - 2], 19) ^ words[i - 2] >>> 10;
3404
+ words[i] = words[i - 16] + s0 + words[i - 7] + s1 >>> 0;
3405
+ }
3406
+ let a = h0;
3407
+ let b = h1;
3408
+ let c = h2;
3409
+ let d = h3;
3410
+ let e = h4;
3411
+ let f = h5;
3412
+ let g = h6;
3413
+ let h = h7;
3414
+ for (let i = 0; i < 64; i++) {
3415
+ const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
3416
+ const ch = e & f ^ ~e & g;
3417
+ const temp1 = h + s1 + ch + SHA256_K[i] + words[i] >>> 0;
3418
+ const temp2 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) + (a & b ^ a & c ^ b & c) >>> 0;
3419
+ h = g;
3420
+ g = f;
3421
+ f = e;
3422
+ e = d + temp1 >>> 0;
3423
+ d = c;
3424
+ c = b;
3425
+ b = a;
3426
+ a = temp1 + temp2 >>> 0;
3427
+ }
3428
+ h0 = h0 + a >>> 0;
3429
+ h1 = h1 + b >>> 0;
3430
+ h2 = h2 + c >>> 0;
3431
+ h3 = h3 + d >>> 0;
3432
+ h4 = h4 + e >>> 0;
3433
+ h5 = h5 + f >>> 0;
3434
+ h6 = h6 + g >>> 0;
3435
+ h7 = h7 + h >>> 0;
3436
+ }
3437
+ return [
3438
+ h0,
3439
+ h1,
3440
+ h2,
3441
+ h3,
3442
+ h4,
3443
+ h5,
3444
+ h6,
3445
+ h7
3446
+ ].map((word) => word.toString(16).padStart(8, "0")).join("");
3447
+ }
3448
+ function padSha256Message(bytes) {
3449
+ const bitLength = bytes.byteLength * 8;
3450
+ const zeroPadLength = (64 - (bytes.byteLength + 1 + 8) % 64) % 64;
3451
+ const output = new Uint8Array(bytes.byteLength + 1 + zeroPadLength + 8);
3452
+ output.set(bytes);
3453
+ output[bytes.byteLength] = 128;
3454
+ const view = new DataView(output.buffer);
3455
+ view.setUint32(output.byteLength - 8, Math.floor(bitLength / 4294967296));
3456
+ view.setUint32(output.byteLength - 4, bitLength >>> 0);
3457
+ return output;
3458
+ }
3459
+ function rotr(value, bits) {
3460
+ return value >>> bits | value << 32 - bits;
3461
+ }
3462
+ //#endregion
3463
+ export { OnboardingIntentSelectedTelemetryEventSchema as $, redactTelemetryProps as $t, FINANCIAL_OPS_TARGET_TELEMETRY_PRODUCERS as A, ReceiptPendingTelemetryEventSchema as At, MemberActivationFailedTelemetryEventSchema as B, UiContactActionCompletedTelemetryEventSchema as Bt, CliCommandCompletedTelemetryEventSchema as C, PayrollGroupChangedTelemetryEventSchema as Ct, ContactRelationshipChangedTelemetryEventSchema as D, ProvisioningSafeConfirmedTelemetryEventSchema as Dt, CliFirstUsedTelemetryEventSchema as E, PostHogTelemetryAdapter as Et, IdentityRefusedTelemetryEventSchema as F, TELEMETRY_EVENT_SCHEMAS as Ft, MovementScanWindowTelemetryEventSchema as G, createCapxulBeforeSend as Gt, MemberActivationStartedTelemetryEventSchema as H, UiPayrollActionCompletedTelemetryEventSchema as Ht, InMemoryTelemetryBusAdapter as I, TELEMETRY_JOURNEYS as It, NativeAuthorizationDeniedTelemetryEventSchema as J, initializeCapxulBrowserAnalytics as Jt, NativeAuthorizationAcceptedTelemetryEventSchema as K, createPostHogBrowserPageviewTracker as Kt, IndexerDriftCorrectedTelemetryEventSchema as L, TELEMETRY_PRODUCERS as Lt, FaucetConfirmedTelemetryEventSchema as M, ResponseHeadersSchema as Mt, FaucetFailedTelemetryEventSchema as N, SYNCABLE_CAPXUL_ENVS as Nt, DepositInitiatedTelemetryEventSchema as O, ProvisioningSafeCreatedTelemetryEventSchema as Ot, FaucetRequestedTelemetryEventSchema as P, TELEMETRY_EVENT_NAMES as Pt, OnboardingDashboardReachedTelemetryEventSchema as Q, redactTelemetryEvent as Qt, InvoiceIssuedTelemetryEventSchema as R, UiAccessStepCompletedTelemetryEventSchema as Rt, ChainUpstreamSchema as S, PaymentVerificationRetryTelemetryEventSchema as St, CliDiagnosticCompletedTelemetryEventSchema as T, PermissionMirrorVerificationTelemetryEventSchema as Tt, MovementScanCheckpointTelemetryEventSchema as U, UiReceiveStepCompletedTelemetryEventSchema as Ut, MemberActivationReadyTelemetryEventSchema as V, UiInvoiceStepCompletedTelemetryEventSchema as Vt, MovementScanIncidentTelemetryEventSchema as W, UiTreasuryStepCompletedTelemetryEventSchema as Wt, NativeAuthorizationReviewedTelemetryEventSchema as X, maskCapturedNetworkRequest as Xt, NativeAuthorizationFailedTelemetryEventSchema as Y, initializePostHogBrowserAnalytics as Yt, NativeAuthorizationStartedTelemetryEventSchema as Z, productAppAnalytics as Zt, CLI_COMMAND_NAMES as _, PRODUCT_MAPPER_GATED_TELEMETRY_EVENTS as _t, AuthFailedTelemetryEventSchema as a, CAPXUL_OPERATIONS as an, OrgCreatedTelemetryEventSchema as at, ChainAttemptSchema as b, PaymentLifecycleTransitionTelemetryEventSchema as bt, AuthOtpRequestedTelemetryEventSchema as c, ORGANIZATION_SETUP_REASONS as cn, OrgInviteProgressedTelemetryEventSchema as ct, BROWSER_GATED_TELEMETRY_EVENTS as d, FAILURE_MODES as dn, OrgSafeConfirmedTelemetryEventSchema as dt, sanitizePostHogBrowserEvent as en, OnboardingOrganizationSubmittedTelemetryEventSchema as et, BootstrapFailedTelemetryEventSchema as f, isCredentialField as fn, OrgSafeCreatedTelemetryEventSchema as ft, CLI_CAPABILITIES as g, PII as gt, CAPXUL_ENVS as h, OrganizationCreationStartedTelemetryEventSchema as ht, ActivityAnnotationSavedTelemetryEventSchema as i, utilityAppAnalytics as in, OrgCreateStartedTelemetryEventSchema as it, FailureModeSchema as j, RecordingTelemetryAdapter as jt, DepositSettledTelemetryEventSchema as k, QuickPayExternalAddressAcknowledgedTelemetryEventSchema as kt, AuthSignedOutTelemetryEventSchema as l, ORGANIZATION_SETUP_STATUSES as ln, OrgInviteSentTelemetryEventSchema as lt, BundlerErrorTelemetryEventSchema as m, redactUrlSecrets as mn, OrganizationCreationReadyTelemetryEventSchema as mt, AccountBalanceFailedTelemetryEventSchema as n, stampTelemetryEnvelope as nn, OperationRetriedTelemetryEventSchema as nt, AuthOtpDeliveredTelemetryEventSchema as o, isCapxulOperation as on, OrgInviteAcceptedTelemetryEventSchema as ot, BootstrapResolvedTelemetryEventSchema as p, redactSecrets as pn, OrganizationCreationFailedTelemetryEventSchema as pt, NativeAuthorizationConnectedTelemetryEventSchema as q, getTrackHandler as qt, AccountBalanceReadTelemetryEventSchema as r, track as rn, OrgCreateFailedTelemetryEventSchema as rt, AuthOtpExpiredTelemetryEventSchema as s, normalizeCapxulOperation as sn, OrgInviteExpiredTelemetryEventSchema as st, AccessRecoveryCompletedTelemetryEventSchema as t, setTrackHandler as tn, OnboardingProfileSubmittedTelemetryEventSchema as tt, AuthVerifiedTelemetryEventSchema as u, CAPXUL_ERROR_CODES as un, OrgRolesSeededTelemetryEventSchema as ut, CLI_INVOCATION_KINDS as v, PaymentFailedTelemetryEventSchema as vt, CliCommandStartedTelemetryEventSchema as w, PayrollRunTransitionedTelemetryEventSchema as wt, ChainUpstreamFallbackTelemetryEventSchema as x, PaymentSettledTelemetryEventSchema as xt, CONTRACT_FIRST_TELEMETRY_EVENTS as y, PaymentInitiatedTelemetryEventSchema as yt, InvoiceRequestTransitionedTelemetryEventSchema as z, UiActivityActionCompletedTelemetryEventSchema as zt };