@capxul/mcp 4.1.3 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/main.mjs +442 -72
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -104,9 +104,12 @@ vp run --filter @capxul/mcp build
|
|
|
104
104
|
|
|
105
105
|
The tests are hermetic: a real HTTP server, a fake token exchange, and a fake
|
|
106
106
|
SDK client. They do not prove a live OAuth flow against a deployed backend, a
|
|
107
|
-
chain path, or settlement.
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
chain path, or settlement.
|
|
108
|
+
[#922](https://github.com/Xelmar-tech/infrastructure/issues/922) records the
|
|
109
|
+
historical packed-install gap. The current
|
|
110
|
+
`scripts/__tests__/pack-install-smoke.test.mjs` installs MCP and Sandbox
|
|
111
|
+
tarballs in a clean project and invokes their bins with `--help`. Run it
|
|
112
|
+
against the current artifacts before claiming installed-bin proof.
|
|
110
113
|
|
|
111
114
|
A live staging run in #1812 proves browser login, `account:write` consent,
|
|
112
115
|
Person onboarding, a ready Account, OAuth scope step-up, and the Account tools. A
|
package/dist/main.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { createHash } from "node:crypto";
|
|
|
8
8
|
import { createServer } from "node:http";
|
|
9
9
|
import { localhostHostValidation, localhostOriginValidation, toNodeHandler } from "@modelcontextprotocol/node";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
-
import { Cause, Clock, Context, Data, Deferred, Duration, Effect, Exit, Fiber, Layer, Queue, Ref, Result, Schedule, Schema, SchemaGetter, SchemaIssue, SchemaParser, Scope, Tracer } from "effect";
|
|
11
|
+
import { Cause, Clock, Context, Data, Deferred, Duration, Effect, Exit, Fiber, FiberSet, Layer, Queue, Ref, Result, Schedule, Schema, SchemaGetter, SchemaIssue, SchemaParser, Scope, Stream, Tracer } from "effect";
|
|
12
12
|
import { FetchHttpClient, Headers, HttpClient } from "effect/unstable/http";
|
|
13
13
|
import { OtlpExporter, OtlpLogger, OtlpSerialization, OtlpTracer } from "effect/unstable/observability";
|
|
14
14
|
import { resolve } from "path";
|
|
@@ -24,39 +24,275 @@ import zlib from "zlib";
|
|
|
24
24
|
import { McpServer, createMcpHandler } from "@modelcontextprotocol/server";
|
|
25
25
|
import { instrument } from "@posthog/mcp";
|
|
26
26
|
//#region ../../packages/errors/src/secret-material.ts
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
const CREDENTIAL_FIELDS = /* @__PURE__ */ new Set([
|
|
28
|
+
"password",
|
|
29
|
+
"passwd",
|
|
30
|
+
"pwd",
|
|
31
|
+
"pass",
|
|
32
|
+
"passphrase",
|
|
33
|
+
"currentpassword",
|
|
34
|
+
"newpassword",
|
|
35
|
+
"confirmpassword",
|
|
36
|
+
"passwordconfirmation",
|
|
37
|
+
"passwordhash",
|
|
38
|
+
"hashedpassword",
|
|
39
|
+
"pin",
|
|
40
|
+
"privatekey",
|
|
41
|
+
"walletprivatekey",
|
|
42
|
+
"secretkey",
|
|
43
|
+
"signingkey",
|
|
44
|
+
"signingsecret",
|
|
45
|
+
"seed",
|
|
46
|
+
"seedphrase",
|
|
47
|
+
"mnemonic",
|
|
48
|
+
"recoveryphrase",
|
|
49
|
+
"recovery",
|
|
50
|
+
"recoverycode",
|
|
51
|
+
"recoverycodes",
|
|
52
|
+
"keyshare",
|
|
53
|
+
"signingmaterial",
|
|
54
|
+
"recoverymaterial",
|
|
55
|
+
"privatekeybytes",
|
|
56
|
+
"signingprivatekey",
|
|
57
|
+
"encryptionkey",
|
|
58
|
+
"decryptionkey",
|
|
59
|
+
"authtoken",
|
|
60
|
+
"apitoken",
|
|
61
|
+
"bearertoken",
|
|
62
|
+
"oauthtoken",
|
|
63
|
+
"csrftoken",
|
|
64
|
+
"clientassertion",
|
|
65
|
+
"token",
|
|
66
|
+
"accesstoken",
|
|
67
|
+
"refreshtoken",
|
|
68
|
+
"idtoken",
|
|
69
|
+
"sessiontoken",
|
|
70
|
+
"session",
|
|
71
|
+
"sessionkey",
|
|
72
|
+
"sessionsecret",
|
|
73
|
+
"authsessionid",
|
|
74
|
+
"sessioncredential",
|
|
75
|
+
"sessioncredentials",
|
|
76
|
+
"sessioncookie",
|
|
77
|
+
"auth",
|
|
78
|
+
"authentication",
|
|
79
|
+
"authorization",
|
|
80
|
+
"proxyauthorization",
|
|
81
|
+
"cookie",
|
|
82
|
+
"cookies",
|
|
83
|
+
"setcookie",
|
|
84
|
+
"apikey",
|
|
85
|
+
"xapikey",
|
|
86
|
+
"xauthtoken",
|
|
87
|
+
"clientsecret",
|
|
88
|
+
"secret",
|
|
89
|
+
"secrets",
|
|
90
|
+
"credential",
|
|
91
|
+
"credentials",
|
|
92
|
+
"signature",
|
|
93
|
+
"otp",
|
|
94
|
+
"otpcode",
|
|
95
|
+
"totpsecret",
|
|
96
|
+
"onetimecode",
|
|
97
|
+
"onetimepassword",
|
|
98
|
+
"verificationcode",
|
|
99
|
+
"authcode",
|
|
100
|
+
"authorizationcode",
|
|
101
|
+
"oauthcode",
|
|
102
|
+
"codeverifier"
|
|
103
|
+
]);
|
|
104
|
+
/** Match credential fields by meaning, without hiding token addresses or replay IDs. */
|
|
105
|
+
function isCredentialField(name, context) {
|
|
106
|
+
const normalized = name.toLowerCase().replace(/[^a-z0-9]/gu, "");
|
|
107
|
+
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);
|
|
108
|
+
}
|
|
109
|
+
function decodeUrlComponent(text) {
|
|
110
|
+
try {
|
|
111
|
+
return decodeURIComponent(text);
|
|
112
|
+
} catch {
|
|
113
|
+
return text;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** Preserve URL diagnostics while removing credentials from their declared components. */
|
|
117
|
+
function redactUrlSecrets(value, source) {
|
|
118
|
+
try {
|
|
119
|
+
const absolute = /^[a-z][a-z0-9+.-]*:/iu.test(value);
|
|
120
|
+
const protocolRelative = value.startsWith("//");
|
|
121
|
+
const url = new URL(value, "https://redaction.invalid");
|
|
122
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") return maskText(value);
|
|
123
|
+
let changed = url.username.length > 0 || url.password.length > 0;
|
|
124
|
+
const maskParams = (params) => new URLSearchParams(Array.from(params, ([name, entry]) => {
|
|
125
|
+
const safeName = maskText(name);
|
|
126
|
+
const safeEntry = isCredentialField(name) || /^(?:code|draft|__posthog)$/iu.test(name) ? "[REDACTED]" : maskText(entry);
|
|
127
|
+
changed ||= safeName !== name || safeEntry !== entry;
|
|
128
|
+
return [safeName, safeEntry];
|
|
129
|
+
})).toString();
|
|
130
|
+
const provider = source !== void 0 || /(?:^|\.)(?:alchemy\.com|alchemyapi\.io|infura\.io)$/iu.test(url.hostname);
|
|
131
|
+
const segments = (absolute || protocolRelative ? url.pathname : value.split(/[?#]/u)[0] ?? "").split("/");
|
|
132
|
+
const path = segments.map((segment, index) => {
|
|
133
|
+
const decoded = decodeUrlComponent(segment);
|
|
134
|
+
const masked = provider && /^v[23]$/u.test(decodeUrlComponent(segments[index - 1] ?? "")) && decoded.length > 0 ? "[REDACTED]" : maskText(decoded);
|
|
135
|
+
changed ||= masked !== decoded;
|
|
136
|
+
return masked === decoded ? segment : encodeURIComponent(masked);
|
|
137
|
+
}).join("/");
|
|
138
|
+
const query = maskParams(url.searchParams);
|
|
139
|
+
const fragment = url.hash.slice(1);
|
|
140
|
+
const decodedFragment = decodeUrlComponent(fragment);
|
|
141
|
+
const maskedFragment = maskText(decodedFragment);
|
|
142
|
+
changed ||= maskedFragment !== decodedFragment;
|
|
143
|
+
const fragmentQuery = fragment.indexOf("?");
|
|
144
|
+
const fragmentPath = fragment.slice(0, fragmentQuery);
|
|
145
|
+
const maskedFragmentPath = maskText(decodeUrlComponent(fragmentPath));
|
|
146
|
+
changed ||= maskedFragmentPath !== decodeUrlComponent(fragmentPath);
|
|
147
|
+
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);
|
|
148
|
+
const origin = absolute ? url.origin : protocolRelative ? `//${url.host}` : "";
|
|
149
|
+
if (!changed) return value;
|
|
150
|
+
return `${origin}${path}${query ? `?${query}` : ""}${hash ? `#${hash}` : ""}`;
|
|
151
|
+
} catch {
|
|
152
|
+
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));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const JSON_FIELD = /("(?:[^"\\]|\\.)*")(\s*:\s*)("(?:[^"\\]|\\.)*"|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/gu;
|
|
156
|
+
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;
|
|
157
|
+
const EMBEDDED_URL = /(https?:\/\/[^\s"<>]*)/giu;
|
|
158
|
+
function isSecretLabel(name) {
|
|
159
|
+
return isCredentialField(name) || /^request[ _-]?body$/iu.test(name);
|
|
160
|
+
}
|
|
161
|
+
const JSON_ENCODING_MAX = 8;
|
|
162
|
+
const JSON_NESTING_MAX = 64;
|
|
163
|
+
const JSON_KEY = /("(?:[^"\\]|\\.)*")\s*:/gu;
|
|
164
|
+
const JSON_CONTAINER_START = /(?:\{\s*["}]|\[\s*[[\]{}"0-9tfn-])/uy;
|
|
165
|
+
function hasSecretJsonKey(value) {
|
|
166
|
+
for (const match of value.matchAll(JSON_KEY)) try {
|
|
167
|
+
if (match[1] !== void 0 && isSecretLabel(JSON.parse(match[1]))) return true;
|
|
168
|
+
} catch {}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
/** Project a complete fragment once. Never retry all of its nested substrings. */
|
|
172
|
+
function projectJsonFragment(value, encodingDepth, overDepth) {
|
|
173
|
+
if (overDepth || encodingDepth >= JSON_ENCODING_MAX) return "[REDACTED]";
|
|
174
|
+
let parsed;
|
|
175
|
+
try {
|
|
176
|
+
parsed = JSON.parse(value);
|
|
177
|
+
} catch {
|
|
178
|
+
return hasSecretJsonKey(value) ? "[REDACTED]" : value;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
let changed = false;
|
|
182
|
+
const masked = JSON.stringify(parsed, (name, nested) => {
|
|
183
|
+
if (isSecretLabel(name)) {
|
|
184
|
+
changed ||= nested !== "[REDACTED]";
|
|
185
|
+
return "[REDACTED]";
|
|
186
|
+
}
|
|
187
|
+
if (typeof nested === "string") {
|
|
188
|
+
const projected = maskJsonFragments(nested, encodingDepth + 1);
|
|
189
|
+
changed ||= projected !== nested;
|
|
190
|
+
return projected;
|
|
191
|
+
}
|
|
192
|
+
return nested;
|
|
193
|
+
});
|
|
194
|
+
return changed ? masked : value;
|
|
195
|
+
} catch {
|
|
196
|
+
return "[REDACTED]";
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** Scan balanced object/array fragments once, respecting JSON quotes and escapes. */
|
|
200
|
+
function maskJsonFragments(value, encodingDepth = 0) {
|
|
201
|
+
if (value.trimStart().startsWith("\"")) try {
|
|
202
|
+
const decoded = JSON.parse(value);
|
|
203
|
+
if (typeof decoded === "string") {
|
|
204
|
+
if (encodingDepth >= JSON_ENCODING_MAX) return "\"[REDACTED]\"";
|
|
205
|
+
const masked = maskJsonFragments(decoded, encodingDepth + 1);
|
|
206
|
+
return masked === decoded ? value : JSON.stringify(masked);
|
|
207
|
+
}
|
|
208
|
+
} catch {}
|
|
209
|
+
let output = "";
|
|
210
|
+
let cursor = 0;
|
|
211
|
+
let start = -1;
|
|
212
|
+
let depth = 0;
|
|
213
|
+
let overDepth = false;
|
|
214
|
+
let quoted = false;
|
|
215
|
+
let escaped = false;
|
|
216
|
+
for (let index = 0; index < value.length; index++) {
|
|
217
|
+
const character = value[index];
|
|
218
|
+
if (start < 0) {
|
|
219
|
+
JSON_CONTAINER_START.lastIndex = index;
|
|
220
|
+
if (!JSON_CONTAINER_START.test(value)) continue;
|
|
221
|
+
start = index;
|
|
222
|
+
depth = 1;
|
|
223
|
+
overDepth = false;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (quoted) {
|
|
227
|
+
if (escaped) escaped = false;
|
|
228
|
+
else if (character === "\\") escaped = true;
|
|
229
|
+
else if (character === "\"") quoted = false;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (character === "\"") quoted = true;
|
|
233
|
+
else if (character === "{" || character === "[") {
|
|
234
|
+
depth++;
|
|
235
|
+
overDepth ||= depth > JSON_NESTING_MAX;
|
|
236
|
+
} else if (character === "}" || character === "]") {
|
|
237
|
+
depth--;
|
|
238
|
+
if (depth !== 0) continue;
|
|
239
|
+
output += value.slice(cursor, start) + projectJsonFragment(value.slice(start, index + 1), encodingDepth, overDepth);
|
|
240
|
+
cursor = index + 1;
|
|
241
|
+
start = -1;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (start >= 0) {
|
|
245
|
+
const fragment = value.slice(start);
|
|
246
|
+
output += value.slice(cursor, start) + (overDepth || hasSecretJsonKey(fragment) ? "[REDACTED]" : fragment);
|
|
247
|
+
cursor = value.length;
|
|
248
|
+
}
|
|
249
|
+
return output + value.slice(cursor);
|
|
250
|
+
}
|
|
251
|
+
function maskLabelledText(value) {
|
|
252
|
+
const jsonMasked = maskJsonFragments(value).replace(JSON_FIELD, (whole, quotedName, separator) => {
|
|
253
|
+
try {
|
|
254
|
+
return isSecretLabel(JSON.parse(quotedName)) ? `${quotedName}${separator}"[REDACTED]"` : whole;
|
|
255
|
+
} catch {
|
|
256
|
+
return whole;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
let output = "";
|
|
260
|
+
let cursor = 0;
|
|
261
|
+
for (const match of jsonMasked.matchAll(PROSE_FIELD)) {
|
|
262
|
+
const [, whole, label, entry] = match;
|
|
263
|
+
if (whole === void 0 || label === void 0 || entry === void 0 || match.index < cursor || /^Bearer[ \t]+/iu.test(entry)) continue;
|
|
264
|
+
const words = label.split(/[ \t]+/u);
|
|
265
|
+
for (let index = 0; index < words.length; index++) {
|
|
266
|
+
const name = words.slice(index).join(" ");
|
|
267
|
+
if (isSecretLabel(name)) {
|
|
268
|
+
const prefix = words.slice(0, index).join(" ");
|
|
269
|
+
output += jsonMasked.slice(cursor, match.index) + `${prefix ? `${prefix} ` : ""}${name}=[REDACTED]`;
|
|
270
|
+
cursor = match.index + whole.length;
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return output + jsonMasked.slice(cursor);
|
|
276
|
+
}
|
|
277
|
+
const TOKEN_MASKS = [
|
|
278
|
+
[/\bBearer\s+(?!(?:realm|error|error_description|scope|authorization_uri|resource|claims)\s*=)[^\s,;"']+/giu, "Bearer [REDACTED]"],
|
|
37
279
|
[/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/gu, "[REDACTED]"],
|
|
38
280
|
[/(^|[^a-fA-F0-9])(?<!0[xX])[a-fA-F0-9]{64}(?=$|[^a-fA-F0-9])/gu, "$1[REDACTED]"],
|
|
39
|
-
[/(?:(?: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]"]
|
|
40
|
-
[/(https?:\/\/[^\s"']+?\/v[0-9]\/)[A-Za-z0-9_-]{16,}/giu, "$1[REDACTED]"],
|
|
41
|
-
[/\b(api[ _-]?key|access[ _-]?token|token|secret|password|passphrase|private[ _-]?key|authorization|cookie|signature|request[ _-]?body|credential|otp|one[ _-]?time[ _-]?(?:password|code)|verification[ _-]?code)\b\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,;&]+)/giu, "$1=[REDACTED]"]
|
|
281
|
+
[/(?:(?: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]"]
|
|
42
282
|
];
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
283
|
+
/** URL components and malformed URLs use this non-recursive masking layer. */
|
|
284
|
+
function maskText(value) {
|
|
285
|
+
let text = maskLabelledText(value);
|
|
286
|
+
for (const [pattern, replacement] of TOKEN_MASKS) text = text.replace(pattern, replacement);
|
|
287
|
+
return text;
|
|
288
|
+
}
|
|
289
|
+
/** Reject only when the same semantic sanitizer removes credential material. */
|
|
48
290
|
function containsSensitiveMaterial(value) {
|
|
49
|
-
return
|
|
291
|
+
return redactSecrets(value) !== value;
|
|
50
292
|
}
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
* lines, provider messages, PostHog rows) but must not carry live credentials.
|
|
55
|
-
*/
|
|
56
|
-
function redactSecrets(value) {
|
|
57
|
-
let text = value;
|
|
58
|
-
for (const [pattern, replacement] of MASKS) text = text.replace(pattern, replacement);
|
|
59
|
-
return text;
|
|
293
|
+
/** Mask credential fields and embedded URLs while preserving surrounding evidence. */
|
|
294
|
+
function redactSecrets(value, source) {
|
|
295
|
+
return maskLabelledText(value).split(EMBEDDED_URL).map((part, index) => index % 2 === 1 ? redactUrlSecrets(part, source).replaceAll("%5BREDACTED%5D", "[REDACTED]") : maskText(part)).join("");
|
|
60
296
|
}
|
|
61
297
|
//#endregion
|
|
62
298
|
//#region ../../packages/errors/src/chain-cause.ts
|
|
@@ -5177,6 +5413,7 @@ const ActivityFilterProps = {
|
|
|
5177
5413
|
filter_status: Schema.optional(Schema.Array(Schema.Literals([
|
|
5178
5414
|
"pending",
|
|
5179
5415
|
"settling",
|
|
5416
|
+
"unresolved",
|
|
5180
5417
|
"pending_claim",
|
|
5181
5418
|
"scheduled",
|
|
5182
5419
|
"streaming",
|
|
@@ -10353,6 +10590,7 @@ function verifiedOperationFields(attributes) {
|
|
|
10353
10590
|
/** Observe a public Effect that already uses the canonical CapxulError channel. */
|
|
10354
10591
|
async function runCapxulEffect(effect, controls, operation = CAPXUL_OPERATIONS.runtime.port, runPromise = Effect.runPromise) {
|
|
10355
10592
|
const invocation = readInvocationObservation(controls);
|
|
10593
|
+
let owningSpan;
|
|
10356
10594
|
const correlationId = safeEngineeringIdentifier(invocation?.context?.correlationId ?? controls?.correlation_id);
|
|
10357
10595
|
const context = invocation?.active === false ? void 0 : sanitizeObservationContext(invocation?.context);
|
|
10358
10596
|
const fields = {
|
|
@@ -10379,6 +10617,10 @@ async function runCapxulEffect(effect, controls, operation = CAPXUL_OPERATIONS.r
|
|
|
10379
10617
|
const failure = error instanceof CapxulError ? error : void 0;
|
|
10380
10618
|
const outcome = Exit.isSuccess(exit) ? "succeeded" : failure?.code === "CANCELLED" ? "cancelled" : failure !== void 0 && EXPECTED_OPERATION_OUTCOMES.has(failure.code) ? "refused" : "failed";
|
|
10381
10619
|
const span = yield* Effect.currentSpan.pipe(Effect.orDie);
|
|
10620
|
+
if (Exit.isFailure(exit) && invocation?.active === true) owningSpan = Object.freeze({
|
|
10621
|
+
traceId: span.traceId,
|
|
10622
|
+
spanId: span.spanId
|
|
10623
|
+
});
|
|
10382
10624
|
const completion = {
|
|
10383
10625
|
...fields,
|
|
10384
10626
|
...verifiedOperationFields(span.attributes),
|
|
@@ -10392,7 +10634,10 @@ async function runCapxulEffect(effect, controls, operation = CAPXUL_OPERATIONS.r
|
|
|
10392
10634
|
yield* (outcome === "failed" ? Effect.logError("capxul_sdk_operation") : Effect.logInfo("capxul_sdk_operation")).pipe(Effect.annotateLogs(completion), Effect.catchCause(() => Effect.void));
|
|
10393
10635
|
return yield* Exit.isSuccess(exit) ? Effect.succeed(exit.value) : Effect.failCause(exit.cause);
|
|
10394
10636
|
}).pipe(Effect.withSpan(operation)), controls));
|
|
10395
|
-
return !result.ok && invocation !== void 0 ? markFailureInvocationSnapshot(result,
|
|
10637
|
+
return !result.ok && invocation !== void 0 ? markFailureInvocationSnapshot(result, {
|
|
10638
|
+
...invocation,
|
|
10639
|
+
...owningSpan === void 0 ? {} : { owningSpan }
|
|
10640
|
+
}) : result;
|
|
10396
10641
|
}
|
|
10397
10642
|
/** Map machine-internal failure state onto the public SDK error vocabulary. */
|
|
10398
10643
|
function publicIdentityFailure(failure) {
|
|
@@ -11559,7 +11804,7 @@ const moneyExecutionContract = {
|
|
|
11559
11804
|
};
|
|
11560
11805
|
//#endregion
|
|
11561
11806
|
//#region ../../packages/sdk/package.json
|
|
11562
|
-
var version$1 = "4.
|
|
11807
|
+
var version$1 = "4.2.0";
|
|
11563
11808
|
//#endregion
|
|
11564
11809
|
//#region ../../packages/sdk/src/telemetry/exception-projection.ts
|
|
11565
11810
|
/** Fixed fallback for failures that have no safe message. */
|
|
@@ -11698,7 +11943,8 @@ function report(adapter, kind, operation, cause, invocation, origin, authoritati
|
|
|
11698
11943
|
}, {
|
|
11699
11944
|
active: invocation.active,
|
|
11700
11945
|
...invocation.actorId === void 0 ? {} : { actorId: invocation.actorId },
|
|
11701
|
-
...context === void 0 ? {} : { context }
|
|
11946
|
+
...context === void 0 ? {} : { context },
|
|
11947
|
+
...invocation.owningSpan === void 0 ? {} : { owningSpan: invocation.owningSpan }
|
|
11702
11948
|
});
|
|
11703
11949
|
try {
|
|
11704
11950
|
ignoreDeliveryFailure(kind === "operation" ? adapter.captureOperationFailure(failure) : adapter.captureException(failure));
|
|
@@ -11737,8 +11983,6 @@ function evidenceText(value) {
|
|
|
11737
11983
|
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
11738
11984
|
return redactSecrets(value).slice(0, MAX_EVIDENCE_TEXT);
|
|
11739
11985
|
}
|
|
11740
|
-
/** A field whose NAME says credential is masked whatever its value looks like. */
|
|
11741
|
-
const CREDENTIAL_FIELD_NAME = /(?:otp|pass(?:word|wd|phrase)?|token|secret|credential|api[_-]?key|private[_-]?key|authorization|cookie|session)/iu;
|
|
11742
11986
|
/** Copy a details object into a JSON-safe shape with every string masked. */
|
|
11743
11987
|
function evidenceValue(value, depth = 0) {
|
|
11744
11988
|
if (typeof value === "string") return evidenceText(value);
|
|
@@ -11749,7 +11993,7 @@ function evidenceValue(value, depth = 0) {
|
|
|
11749
11993
|
if (Array.isArray(value)) return value.slice(0, 50).map((item) => evidenceValue(item, depth + 1));
|
|
11750
11994
|
const copy = {};
|
|
11751
11995
|
for (const [key, nested] of Object.entries(value)) {
|
|
11752
|
-
if (
|
|
11996
|
+
if (isCredentialField(key)) {
|
|
11753
11997
|
copy[key] = "[REDACTED]";
|
|
11754
11998
|
continue;
|
|
11755
11999
|
}
|
|
@@ -13516,21 +13760,8 @@ const ENGINEERING_CAPXUL_ENVS = [
|
|
|
13516
13760
|
"production",
|
|
13517
13761
|
"local"
|
|
13518
13762
|
];
|
|
13519
|
-
const
|
|
13520
|
-
|
|
13521
|
-
"content-type",
|
|
13522
|
-
"traceparent",
|
|
13523
|
-
"tracestate",
|
|
13524
|
-
"x-request-id"
|
|
13525
|
-
];
|
|
13526
|
-
const ENGINEERING_REDACTED_HEADER_NAMES = Object.freeze([
|
|
13527
|
-
"authorization",
|
|
13528
|
-
"cookie",
|
|
13529
|
-
"set-cookie",
|
|
13530
|
-
"x-api-key",
|
|
13531
|
-
/auth|email|key|otp|secret|session|token|wallet/i
|
|
13532
|
-
]);
|
|
13533
|
-
const traceHeaderFilter = (name) => SAFE_TRACED_HEADER_NAMES.includes(name.toLowerCase());
|
|
13763
|
+
const traceHeaderFilter = (_name) => true;
|
|
13764
|
+
const credentialHeaderPattern = Object.assign(/./u, { test: (name) => isCredentialField(name, "header") });
|
|
13534
13765
|
const postHogOtlpEndpoints = (host) => {
|
|
13535
13766
|
const base = host.replace(/\/+$/, "");
|
|
13536
13767
|
return {
|
|
@@ -13562,23 +13793,79 @@ const validateEngineeringTelemetryConfig = (config) => {
|
|
|
13562
13793
|
headers: Object.freeze({ authorization: headerEntries[0][1] })
|
|
13563
13794
|
};
|
|
13564
13795
|
};
|
|
13565
|
-
|
|
13566
|
-
|
|
13567
|
-
|
|
13568
|
-
|
|
13569
|
-
|
|
13796
|
+
const failureText = (failure, key, limit, source) => {
|
|
13797
|
+
if (failure === null || typeof failure !== "object") return void 0;
|
|
13798
|
+
try {
|
|
13799
|
+
let owner = failure;
|
|
13800
|
+
let descriptor;
|
|
13801
|
+
for (let depth = 0; owner !== null && depth < 4; depth += 1) {
|
|
13802
|
+
descriptor = Object.getOwnPropertyDescriptor(owner, key);
|
|
13803
|
+
if (descriptor !== void 0 || key !== "name") break;
|
|
13804
|
+
owner = Object.getPrototypeOf(owner);
|
|
13805
|
+
}
|
|
13806
|
+
const value = descriptor?.value;
|
|
13807
|
+
return typeof value === "string" || key === "code" && typeof value === "number" ? redactSecrets(String(value), source).slice(0, limit) : void 0;
|
|
13808
|
+
} catch {
|
|
13809
|
+
return;
|
|
13810
|
+
}
|
|
13811
|
+
};
|
|
13812
|
+
const exportFailure = (failure, source) => {
|
|
13813
|
+
const message = failureText(failure, "message", 2048, source) ?? (typeof failure === "string" ? redactSecrets(failure, source).slice(0, 2048) : "Engineering operation failed");
|
|
13814
|
+
const code = failureText(failure, "code", 128);
|
|
13815
|
+
const error = new Error((code === void 0 ? message : `${message} [code=${code}]`).slice(0, 2048));
|
|
13816
|
+
error.name = failureText(failure, "_tag", 128) ?? failureText(failure, "name", 128) ?? "Error";
|
|
13817
|
+
error.stack = failureText(failure, "stack", 8192, source) ?? `${error.name}: ${error.message}`;
|
|
13818
|
+
return error;
|
|
13819
|
+
};
|
|
13820
|
+
const exportFailureExit = (cause, source) => Exit.failCause(Cause.fromReasons(cause.reasons.filter((reason) => !Cause.isInterruptReason(reason)).slice(0, 8).map((reason) => Cause.isFailReason(reason) ? Cause.makeFailReason(exportFailure(reason.error, source)) : Cause.makeDieReason(exportFailure(reason.defect, source)))));
|
|
13821
|
+
const BROWSER_KEEPALIVE_BYTES = 65536;
|
|
13822
|
+
let unfinishedBrowserExportBytes = 0;
|
|
13823
|
+
const hasBrowserDocument = () => typeof window !== "undefined" && typeof document !== "undefined";
|
|
13824
|
+
const browserExportClient = (client) => HttpClient.transform(client, (response, request) => Effect.acquireUseRelease(Effect.sync(() => {
|
|
13825
|
+
const bytes = "contentLength" in request.body ? request.body.contentLength : void 0;
|
|
13826
|
+
if (request.body._tag === "Stream" || request.body._tag === "FormData" || bytes === void 0 || !Number.isSafeInteger(bytes) || bytes < 0 || unfinishedBrowserExportBytes + bytes > BROWSER_KEEPALIVE_BYTES) return;
|
|
13827
|
+
unfinishedBrowserExportBytes += bytes;
|
|
13828
|
+
return bytes;
|
|
13829
|
+
}), (bytes) => response.pipe(Effect.provideService(FetchHttpClient.RequestInit, { keepalive: bytes !== void 0 }), Effect.tap((result) => bytes === void 0 ? Effect.void : Stream.runDrain(result.stream).pipe(Effect.catch((error) => error.reason._tag === "EmptyBodyError" ? Effect.void : Effect.fail(error))))), (bytes) => Effect.sync(() => {
|
|
13830
|
+
if (bytes !== void 0) unfinishedBrowserExportBytes -= bytes;
|
|
13831
|
+
})));
|
|
13832
|
+
const spanUpstream = (span) => {
|
|
13833
|
+
let current = span;
|
|
13834
|
+
while (current?._tag === "Span") {
|
|
13835
|
+
const upstream = current.attributes.get("chain.upstream");
|
|
13836
|
+
if (upstream === "alchemy" || upstream === "infura") return upstream;
|
|
13837
|
+
current = current.parent._tag === "Some" ? current.parent.value : void 0;
|
|
13570
13838
|
}
|
|
13571
13839
|
};
|
|
13572
|
-
const REDACTED_SPAN_FAILURE = Exit.fail(new RedactedEngineeringSpanFailure());
|
|
13573
13840
|
/** Preserve domain exits while preventing the OTLP serializer from seeing raw causes. */
|
|
13574
13841
|
const makeLeakSafeEngineeringTracer = (delegate) => Tracer.make({
|
|
13575
13842
|
span(options) {
|
|
13576
13843
|
const span = delegate.span(options);
|
|
13577
13844
|
const wrapped = Object.create(span);
|
|
13845
|
+
Object.defineProperty(wrapped, "attribute", { value: (name, value) => {
|
|
13846
|
+
const source = spanUpstream(span);
|
|
13847
|
+
const header = /^http\.(?:request|response)\.header\.(.+)$/u.exec(name)?.[1];
|
|
13848
|
+
if (header !== void 0 && isCredentialField(header, "header")) span.attribute(name, "[REDACTED]");
|
|
13849
|
+
else if (typeof value === "string" && name === "url.query") span.attribute(name, redactUrlSecrets(`?${value}`).slice(1, 2049));
|
|
13850
|
+
else if (typeof value === "string" && name === "url.path") {
|
|
13851
|
+
const fullUrl = span.attributes.get("url.full");
|
|
13852
|
+
const path = typeof fullUrl === "string" ? /^https?:\/\/[^/]+([^?#]*)/u.exec(fullUrl)?.[1] ?? value : value;
|
|
13853
|
+
span.attribute(name, redactUrlSecrets(path, source).slice(0, 2048));
|
|
13854
|
+
} else if (typeof value === "string" && (name === "url.full" || header === "location" || header === "referer" || header === "referrer")) span.attribute(name, redactUrlSecrets(value, source).slice(0, 2048));
|
|
13855
|
+
else if (header !== void 0 && typeof value === "string") span.attribute(name, redactSecrets(value, source).slice(0, 2048));
|
|
13856
|
+
else span.attribute(name, value);
|
|
13857
|
+
} });
|
|
13578
13858
|
Object.defineProperty(wrapped, "end", {
|
|
13579
13859
|
configurable: false,
|
|
13580
13860
|
enumerable: false,
|
|
13581
|
-
value: (endTime, exit) =>
|
|
13861
|
+
value: (endTime, exit) => {
|
|
13862
|
+
if (Exit.isFailure(exit) && !Cause.hasInterruptsOnly(exit.cause)) {
|
|
13863
|
+
const first = exit.cause.reasons.find((reason) => !Cause.isInterruptReason(reason));
|
|
13864
|
+
const code = failureText(first === void 0 ? void 0 : Cause.isFailReason(first) ? first.error : first.defect, "code", 128);
|
|
13865
|
+
if (code !== void 0) span.attribute("error.code", code);
|
|
13866
|
+
span.end(endTime, exportFailureExit(exit.cause, spanUpstream(span)));
|
|
13867
|
+
} else span.end(endTime, exit);
|
|
13868
|
+
},
|
|
13582
13869
|
writable: false
|
|
13583
13870
|
});
|
|
13584
13871
|
return wrapped;
|
|
@@ -13609,8 +13896,29 @@ const makeEngineeringTelemetryLayer = (config) => {
|
|
|
13609
13896
|
resource,
|
|
13610
13897
|
mergeWithExisting: true
|
|
13611
13898
|
});
|
|
13612
|
-
const headerPolicy = Layer.merge(Layer.succeed(HttpClient.TracerHeaderFilter, traceHeaderFilter), Layer.succeed(Headers.CurrentRedactedNames,
|
|
13613
|
-
|
|
13899
|
+
const headerPolicy = Layer.merge(Layer.succeed(HttpClient.TracerHeaderFilter, traceHeaderFilter), Layer.succeed(Headers.CurrentRedactedNames, [credentialHeaderPattern]));
|
|
13900
|
+
const browserLifecycle = Layer.effectDiscard(Effect.gen(function* () {
|
|
13901
|
+
if (validated.producer !== "browser" || !hasBrowserDocument()) return;
|
|
13902
|
+
const browserWindow = window;
|
|
13903
|
+
const browserDocument = document;
|
|
13904
|
+
const flusher = yield* OtlpExporter.Flusher;
|
|
13905
|
+
const run = yield* FiberSet.makeRuntime();
|
|
13906
|
+
const flush = () => {
|
|
13907
|
+
run(flusher.flush);
|
|
13908
|
+
};
|
|
13909
|
+
const visibilityChanged = () => {
|
|
13910
|
+
if (browserDocument.visibilityState === "hidden") flush();
|
|
13911
|
+
};
|
|
13912
|
+
yield* Effect.acquireRelease(Effect.sync(() => {
|
|
13913
|
+
browserDocument.addEventListener("visibilitychange", visibilityChanged);
|
|
13914
|
+
browserWindow.addEventListener("pagehide", flush);
|
|
13915
|
+
}), () => Effect.sync(() => {
|
|
13916
|
+
browserDocument.removeEventListener("visibilitychange", visibilityChanged);
|
|
13917
|
+
browserWindow.removeEventListener("pagehide", flush);
|
|
13918
|
+
}));
|
|
13919
|
+
}));
|
|
13920
|
+
const transport = Layer.effect(HttpClient.HttpClient, Effect.map(HttpClient.HttpClient, (client) => validated.producer === "browser" && hasBrowserDocument() ? browserExportClient(client) : client)).pipe(Layer.provide(FetchHttpClient.layer));
|
|
13921
|
+
return browserLifecycle.pipe(Layer.provideMerge(Layer.mergeAll(tracing, logging, headerPolicy)), Layer.provide(OtlpSerialization.layerJson), Layer.provide(transport));
|
|
13614
13922
|
};
|
|
13615
13923
|
//#endregion
|
|
13616
13924
|
//#region ../../packages/sdk/src/ports/auth-client.ts
|
|
@@ -17939,6 +18247,12 @@ function isTransportError(err) {
|
|
|
17939
18247
|
}
|
|
17940
18248
|
//#endregion
|
|
17941
18249
|
//#region ../../packages/sdk/src/ports/identity.ts
|
|
18250
|
+
/** The chain families a payout address may name (#1955). */
|
|
18251
|
+
const PAYOUT_CHAINS = [
|
|
18252
|
+
"evm",
|
|
18253
|
+
"solana",
|
|
18254
|
+
"starknet"
|
|
18255
|
+
];
|
|
17942
18256
|
var IdentityError = class extends Data.TaggedError("IdentityError") {};
|
|
17943
18257
|
function identityErrorFromCapxul(operation, error, cause = error) {
|
|
17944
18258
|
return new IdentityError({
|
|
@@ -19955,7 +20269,7 @@ AxiosError$1.ERR_FORM_DATA_DEPTH_EXCEEDED = "ERR_FORM_DATA_DEPTH_EXCEEDED";
|
|
|
19955
20269
|
//#endregion
|
|
19956
20270
|
//#region ../../node_modules/.pnpm/delayed-stream@1.0.0/node_modules/delayed-stream/lib/delayed_stream.js
|
|
19957
20271
|
var require_delayed_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
19958
|
-
var Stream$
|
|
20272
|
+
var Stream$3 = __require("stream").Stream;
|
|
19959
20273
|
var util$4 = __require("util");
|
|
19960
20274
|
module.exports = DelayedStream;
|
|
19961
20275
|
function DelayedStream() {
|
|
@@ -19967,7 +20281,7 @@ var require_delayed_stream = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
19967
20281
|
this._released = false;
|
|
19968
20282
|
this._bufferedEvents = [];
|
|
19969
20283
|
}
|
|
19970
|
-
util$4.inherits(DelayedStream, Stream$
|
|
20284
|
+
util$4.inherits(DelayedStream, Stream$3);
|
|
19971
20285
|
DelayedStream.create = function(source, options) {
|
|
19972
20286
|
var delayedStream = new this();
|
|
19973
20287
|
options = options || {};
|
|
@@ -20007,7 +20321,7 @@ var require_delayed_stream = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
20007
20321
|
this._bufferedEvents = [];
|
|
20008
20322
|
};
|
|
20009
20323
|
DelayedStream.prototype.pipe = function() {
|
|
20010
|
-
var r = Stream$
|
|
20324
|
+
var r = Stream$3.prototype.pipe.apply(this, arguments);
|
|
20011
20325
|
this.resume();
|
|
20012
20326
|
return r;
|
|
20013
20327
|
};
|
|
@@ -20034,7 +20348,7 @@ var require_delayed_stream = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
20034
20348
|
//#region ../../node_modules/.pnpm/combined-stream@1.0.8/node_modules/combined-stream/lib/combined_stream.js
|
|
20035
20349
|
var require_combined_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
20036
20350
|
var util$3 = __require("util");
|
|
20037
|
-
var Stream$
|
|
20351
|
+
var Stream$2 = __require("stream").Stream;
|
|
20038
20352
|
var DelayedStream = require_delayed_stream();
|
|
20039
20353
|
module.exports = CombinedStream;
|
|
20040
20354
|
function CombinedStream() {
|
|
@@ -20049,7 +20363,7 @@ var require_combined_stream = /* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
20049
20363
|
this._insideLoop = false;
|
|
20050
20364
|
this._pendingNext = false;
|
|
20051
20365
|
}
|
|
20052
|
-
util$3.inherits(CombinedStream, Stream$
|
|
20366
|
+
util$3.inherits(CombinedStream, Stream$2);
|
|
20053
20367
|
CombinedStream.create = function(options) {
|
|
20054
20368
|
var combinedStream = new this();
|
|
20055
20369
|
options = options || {};
|
|
@@ -20076,7 +20390,7 @@ var require_combined_stream = /* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
20076
20390
|
return this;
|
|
20077
20391
|
};
|
|
20078
20392
|
CombinedStream.prototype.pipe = function(dest, options) {
|
|
20079
|
-
Stream$
|
|
20393
|
+
Stream$2.prototype.pipe.call(this, dest, options);
|
|
20080
20394
|
this.resume();
|
|
20081
20395
|
return dest;
|
|
20082
20396
|
};
|
|
@@ -28324,7 +28638,7 @@ var FormData_default = (/* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin((
|
|
|
28324
28638
|
var https$2 = __require("https");
|
|
28325
28639
|
var parseUrl$1 = __require("url").parse;
|
|
28326
28640
|
var fs = __require("fs");
|
|
28327
|
-
var Stream = __require("stream").Stream;
|
|
28641
|
+
var Stream$1 = __require("stream").Stream;
|
|
28328
28642
|
var crypto$2 = __require("crypto");
|
|
28329
28643
|
var mime = require_mime_types();
|
|
28330
28644
|
var asynckit = require_asynckit();
|
|
@@ -28374,7 +28688,7 @@ var FormData_default = (/* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin((
|
|
|
28374
28688
|
else if (typeof value === "string") valueLength = Buffer.byteLength(value);
|
|
28375
28689
|
this._valueLength += valueLength;
|
|
28376
28690
|
this._overheadLength += Buffer.byteLength(header) + FormData.LINE_BREAK.length;
|
|
28377
|
-
if (!value || !value.path && !(value.readable && hasOwn(value, "httpVersion")) && !(value instanceof Stream)) return;
|
|
28691
|
+
if (!value || !value.path && !(value.readable && hasOwn(value, "httpVersion")) && !(value instanceof Stream$1)) return;
|
|
28378
28692
|
if (!options.knownLength) this._valuesToMeasure.push(value);
|
|
28379
28693
|
};
|
|
28380
28694
|
FormData.prototype._lengthRetriever = function(value, callback) {
|
|
@@ -43057,8 +43371,52 @@ const loadIdentityProgram = Effect.gen(function* () {
|
|
|
43057
43371
|
if (authUserId === void 0) return null;
|
|
43058
43372
|
return yield* deps.identityPort.loadByAuthUserId(authUserId).pipe(Effect.catchDefect((cause) => Effect.fail(identityErrorFromCapxul("loadByAuthUserId", cause instanceof CapxulError ? cause : Errors.unknown(cause), cause))), Effect.mapError((failure) => failure.publicError));
|
|
43059
43373
|
});
|
|
43060
|
-
|
|
43061
|
-
|
|
43374
|
+
/**
|
|
43375
|
+
* THE ONE boundary grammar for those optional fields. Both `completeProfile`
|
|
43376
|
+
* entry points — the method bundle here and the identity runtime in
|
|
43377
|
+
* `create-capxul-client.ts` — run it, so a malformed value is refused the same
|
|
43378
|
+
* way at each and never reaches the port.
|
|
43379
|
+
*/
|
|
43380
|
+
function checkProfileCarriage(profile) {
|
|
43381
|
+
const carriage = {};
|
|
43382
|
+
if (profile.imageStorageId !== void 0) {
|
|
43383
|
+
if (typeof profile.imageStorageId !== "string" || profile.imageStorageId.trim().length === 0) return {
|
|
43384
|
+
ok: false,
|
|
43385
|
+
field: "imageStorageId",
|
|
43386
|
+
message: "must be a non-empty storage id"
|
|
43387
|
+
};
|
|
43388
|
+
carriage.imageStorageId = profile.imageStorageId.trim();
|
|
43389
|
+
}
|
|
43390
|
+
if (profile.payoutAddresses !== void 0) {
|
|
43391
|
+
if (!Array.isArray(profile.payoutAddresses)) return {
|
|
43392
|
+
ok: false,
|
|
43393
|
+
field: "payoutAddresses",
|
|
43394
|
+
message: "must be an array"
|
|
43395
|
+
};
|
|
43396
|
+
if (profile.payoutAddresses.length > 10) return {
|
|
43397
|
+
ok: false,
|
|
43398
|
+
field: "payoutAddresses",
|
|
43399
|
+
message: `must carry at most 10 addresses`
|
|
43400
|
+
};
|
|
43401
|
+
const entries = [];
|
|
43402
|
+
for (const entry of profile.payoutAddresses) {
|
|
43403
|
+
if (typeof entry !== "object" || entry === null || !PAYOUT_CHAINS.some((chain) => chain === entry.chain) || typeof entry.address !== "string" || entry.address.trim().length === 0) return {
|
|
43404
|
+
ok: false,
|
|
43405
|
+
field: "payoutAddresses",
|
|
43406
|
+
message: `each entry needs a chain of ${PAYOUT_CHAINS.join(", ")} and an address`
|
|
43407
|
+
};
|
|
43408
|
+
entries.push({
|
|
43409
|
+
chain: entry.chain,
|
|
43410
|
+
address: entry.address.trim()
|
|
43411
|
+
});
|
|
43412
|
+
}
|
|
43413
|
+
carriage.payoutAddresses = entries;
|
|
43414
|
+
}
|
|
43415
|
+
return {
|
|
43416
|
+
ok: true,
|
|
43417
|
+
carriage
|
|
43418
|
+
};
|
|
43419
|
+
}
|
|
43062
43420
|
function makeIdentityMethods(deps) {
|
|
43063
43421
|
const convexCall = deps.convexCall;
|
|
43064
43422
|
return {
|
|
@@ -43097,6 +43455,11 @@ function makeIdentityMethods(deps) {
|
|
|
43097
43455
|
error: Errors.invalidInput("country", "unsupported country")
|
|
43098
43456
|
};
|
|
43099
43457
|
}
|
|
43458
|
+
const carried = checkProfileCarriage(profile);
|
|
43459
|
+
if (!carried.ok) return {
|
|
43460
|
+
ok: false,
|
|
43461
|
+
error: Errors.invalidInput(carried.field, carried.message)
|
|
43462
|
+
};
|
|
43100
43463
|
const session = deps.actor?.authSession();
|
|
43101
43464
|
if (session === void 0 || session === null) return {
|
|
43102
43465
|
ok: false,
|
|
@@ -43107,7 +43470,8 @@ function makeIdentityMethods(deps) {
|
|
|
43107
43470
|
email: session.email,
|
|
43108
43471
|
displayName,
|
|
43109
43472
|
country,
|
|
43110
|
-
handle
|
|
43473
|
+
handle,
|
|
43474
|
+
...carried.carriage
|
|
43111
43475
|
}), options, CAPXUL_OPERATIONS.identity.completeProfile);
|
|
43112
43476
|
},
|
|
43113
43477
|
async handleAvailable(handle, options) {
|
|
@@ -45201,6 +45565,11 @@ function assembleCapxulClient(input) {
|
|
|
45201
45565
|
ok: false,
|
|
45202
45566
|
reason: "INVALID_INPUT"
|
|
45203
45567
|
};
|
|
45568
|
+
const carried = checkProfileCarriage(profile);
|
|
45569
|
+
if (!carried.ok) return {
|
|
45570
|
+
ok: false,
|
|
45571
|
+
reason: "INVALID_INPUT"
|
|
45572
|
+
};
|
|
45204
45573
|
const session = actor.authSession();
|
|
45205
45574
|
if (session === null) return {
|
|
45206
45575
|
ok: false,
|
|
@@ -45211,7 +45580,8 @@ function assembleCapxulClient(input) {
|
|
|
45211
45580
|
email: session.email,
|
|
45212
45581
|
displayName,
|
|
45213
45582
|
country,
|
|
45214
|
-
handle
|
|
45583
|
+
handle,
|
|
45584
|
+
...carried.carriage
|
|
45215
45585
|
}), controls, CAPXUL_OPERATIONS.identity.completeProfile, effectRunner.runPromise);
|
|
45216
45586
|
return result.ok ? { ok: true } : {
|
|
45217
45587
|
ok: false,
|
|
@@ -46705,7 +47075,7 @@ function stdioIdentity(env = process.env, options = {}) {
|
|
|
46705
47075
|
}
|
|
46706
47076
|
//#endregion
|
|
46707
47077
|
//#region package.json
|
|
46708
|
-
var version = "4.
|
|
47078
|
+
var version = "4.2.0";
|
|
46709
47079
|
//#endregion
|
|
46710
47080
|
//#region src/deps.ts
|
|
46711
47081
|
const NO_IDENTITY = async () => void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capxul/mcp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Capxul MCP server for auth, Account readiness, identity, Organizations, relationships, requests, destinations, and testnet funding over Streamable HTTP.",
|
|
6
6
|
"keywords": [
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
|
|
52
52
|
"vite-plus": "0.3.0",
|
|
53
53
|
"@capxul/config": "0.3.0",
|
|
54
|
-
"@capxul/sdk": "4.
|
|
54
|
+
"@capxul/sdk": "4.2.0",
|
|
55
55
|
"@capxul/typescript-config": "0.0.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|