@truealter/sdk 0.5.0 → 0.5.3

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.
@@ -215,17 +215,27 @@ var AlterInvalidResponse = class extends AlterError {
215
215
  }
216
216
  };
217
217
 
218
- // src/x402.ts
218
+ // src/meta.ts
219
+ var SDK_NAME = "@truealter/sdk";
220
+ var SDK_VERSION = "0.5.3" ;
219
221
  var X402Client = class {
220
222
  signer;
221
223
  maxPerQuery;
222
224
  networks;
223
225
  assets;
226
+ // undefined = allowlist check disabled (backward-compatible default).
227
+ // Non-null = active allowlist; reject any recipient not in the set.
228
+ recipientAllowlist;
224
229
  constructor(opts = {}) {
225
230
  this.signer = opts.signer;
226
231
  this.maxPerQuery = opts.maxPerQuery !== void 0 ? Number(opts.maxPerQuery) : void 0;
227
232
  this.networks = new Set(opts.networks ?? ["base", "base-sepolia"]);
228
233
  this.assets = new Set(opts.assets ?? ["USDC"]);
234
+ if (opts.recipientAllowlist !== void 0) {
235
+ this.recipientAllowlist = opts.recipientAllowlist.length === 0 ? void 0 : new Set(opts.recipientAllowlist.map((a) => a.toLowerCase()));
236
+ } else {
237
+ this.recipientAllowlist = void 0;
238
+ }
229
239
  }
230
240
  /**
231
241
  * Validate the envelope against this client's policy and, if a signer
@@ -251,6 +261,15 @@ var X402Client = class {
251
261
  );
252
262
  }
253
263
  }
264
+ if (this.recipientAllowlist !== void 0) {
265
+ const recipientNorm = (envelope.recipient ?? "").toLowerCase();
266
+ if (!recipientNorm || !this.recipientAllowlist.has(recipientNorm)) {
267
+ throw new AlterError(
268
+ "PAYMENT_REQUIRED",
269
+ `recipient "${envelope.recipient}" is not on the known-recipient allowlist`
270
+ );
271
+ }
272
+ }
254
273
  if (!this.signer) {
255
274
  throw new AlterPaymentRequired(envelope.resource ?? "unknown", envelope);
256
275
  }
@@ -309,6 +328,9 @@ var MCPClient = class {
309
328
  x402;
310
329
  signing;
311
330
  extraHeaders;
331
+ preflightHook;
332
+ preflightPromise = null;
333
+ preflightDone = false;
312
334
  requestCounter = 0;
313
335
  initialised = false;
314
336
  constructor(opts = {}) {
@@ -317,17 +339,43 @@ var MCPClient = class {
317
339
  this.fetchImpl = opts.fetch ?? fetch;
318
340
  this.timeoutMs = opts.timeoutMs ?? 3e4;
319
341
  this.maxRetries = opts.maxRetries ?? 2;
320
- this.clientInfo = opts.clientInfo ?? { name: "@truealter/sdk", version: "0.2.0" };
342
+ this.clientInfo = opts.clientInfo ?? { name: SDK_NAME, version: SDK_VERSION };
321
343
  this.x402 = opts.x402;
322
344
  this.signing = opts.signing;
323
345
  this.extraHeaders = opts.extraHeaders;
346
+ this.preflightHook = opts.preflightHook;
347
+ }
348
+ /**
349
+ * Run the lazy preflight hook (D-MIN-VERSION-FLOOR-1) exactly once.
350
+ * Idempotent and serialised: concurrent callers share the same
351
+ * promise. Throws from the hook propagate to every concurrent caller.
352
+ */
353
+ async runPreflight() {
354
+ if (this.preflightDone) return;
355
+ if (!this.preflightHook) {
356
+ this.preflightDone = true;
357
+ return;
358
+ }
359
+ if (!this.preflightPromise) {
360
+ this.preflightPromise = this.preflightHook().then(
361
+ () => {
362
+ this.preflightDone = true;
363
+ },
364
+ (err) => {
365
+ this.preflightPromise = null;
366
+ throw err;
367
+ }
368
+ );
369
+ }
370
+ await this.preflightPromise;
324
371
  }
325
372
  /**
326
373
  * Send the MCP `initialize` handshake and capture the resulting session
327
- * id. Idempotent safe to call multiple times.
374
+ * id. Idempotent: safe to call multiple times.
328
375
  */
329
376
  async initialize() {
330
377
  if (this.initialised) return null;
378
+ await this.runPreflight();
331
379
  const result = await this.rpc("initialize", {
332
380
  protocolVersion: MCP_PROTOCOL_VERSION,
333
381
  capabilities: {},
@@ -487,7 +535,10 @@ var MCPClient = class {
487
535
  ...this.extraHeaders ?? {},
488
536
  "Content-Type": "application/json",
489
537
  Accept: "application/json",
490
- "User-Agent": `${this.clientInfo.name}/${this.clientInfo.version}`
538
+ "User-Agent": `${this.clientInfo.name}/${this.clientInfo.version}`,
539
+ "X-Alter-Client-Id": "alter-identity",
540
+ "X-Alter-Client-Version": SDK_VERSION,
541
+ "X-Alter-Client-Channel": "npm"
491
542
  };
492
543
  if (this.apiKey) headers["X-ALTER-API-Key"] = this.apiKey;
493
544
  if (this.sessionId) headers["Mcp-Session-Id"] = this.sessionId;
@@ -574,7 +625,7 @@ function buildExtraHeaders() {
574
625
  }
575
626
  var EXTRA_HEADERS = buildExtraHeaders();
576
627
  console.warn(
577
- "This bridge is a dev/demo surface. Authenticated MCP tools require Q5c signing; for production, import `@truealter/sdk` directly. Bridge signing lands in Wave-2."
628
+ "This bridge is a dev/demo surface. Authenticated MCP tools require ES256 per-invocation signing; for production, import `@truealter/sdk` directly. Bridge signing is planned for a future release."
578
629
  );
579
630
  var client = new MCPClient({
580
631
  endpoint: ENDPOINT,