xytara 3.1.11 → 3.1.12

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/RELEASE_NOTES.md CHANGED
@@ -1,11 +1,5 @@
1
- `xytara` 3.1.11 hardens the open provider network's money ledger and the hosted executor, and tightens repository hygiene. No API is removed; the public provider directory now lists active providers only.
1
+ `xytara` 3.1.12 makes the public adapter-depth surface report open-network providers truthfully.
2
2
 
3
- Highlights:
4
-
5
- - **Settled-amount reconciliation** — a provider's revenue share accrues on min(quote, the amount actually settled on-chain) for x402 calls; an unrecognised settlement asset accrues nothing and is flagged. Every ledger row records its settlement basis (quoted vs. settled).
6
- - **Registration-scoped ledgers** — ledger rows and payouts belong to one registration of a `provider_id`. A removed and re-registered id never sees, inherits, or is credited by a previous owner's rows, and removal cancels that registration's pending payouts.
7
- - **In-flight payout guard** — a payout being sent by the external signer cannot be cancelled mid-dispatch (so no freed reservation can ever be re-sent); a payout cancelled before a late tx report is reinstated for reconciliation instead of being lost.
8
- - **One execution budget per call** — cold-start ride-out retries and failover candidates share a single wall-clock budget inside the x402 authorization window, and per-target timeouts are capped at 30s, so a routed call can always still settle.
9
- - **Provider endpoint policy** — on hosted deploys, provider endpoints must be public `https` (loopback, private, link-local and metadata hosts are refused and re-checked by DNS at dispatch); redirects are never followed. Providers receive only a sanitized payment context — never the buyer's signed authorization.
10
- - The MCP executor's bearer check is timing-safe and fails closed on a hosted deploy; adapter execution truth counts only enabled targets; rate-limit identity compares are timing-safe.
11
- - Repository hygiene: a complete `.gitignore`, the publish workflow waits for the live deploy before registry publication, and `.env.example` documents every runtime knob.
3
+ - `/v1/adapter-depth` and `/v1/adapter-depth/summary` now count ACTIVE open-network providers that declared an adapter task as provider-live paths, alongside operator env targets. Each is labelled `routing: open_provider_registry`, and the pack lists its `depth_sources`. A pending provider never counts, and a provider is shown as shadowed (not counted) when an operator env target pins the whole lane, because env targets are routed first.
4
+ - Previously the surface only looked at env targets, so it reported `provider_wiring_required` even while paid MCP calls were being served by the live registry provider. It now reports `initial_provider_live_path` for the task that provider serves.
5
+ - Internal callers without runtime state keep the env-only view, so no other surface changes.
@@ -3,6 +3,7 @@
3
3
  const packageJson = require("../package.json");
4
4
  const { catalog } = require("../fixtures/catalog");
5
5
  const { loadExecutionTargetRegistry } = require("./external_execution_runtime");
6
+ const { listProviders } = require("./provider_registry");
6
7
 
7
8
  function normalizeString(value, fallback = "") {
8
9
  const raw = typeof value === "string" ? value.trim() : "";
@@ -59,10 +60,60 @@ function summarizeTarget(target) {
59
60
  };
60
61
  }
61
62
 
62
- function summarizeAdapterTaskDepth(task) {
63
- const targets = listTargetsForTask(task.task_ref).map(summarizeTarget);
63
+ // ACTIVE open-network providers that declared this task_ref. Env targets resolve before the
64
+ // registry at call time, so a provider is shadowed (not routed) when an enabled env target pins
65
+ // the WHOLE lane (task_ref with no tool/integration selector); it is then listed but not counted.
66
+ function listRegistryProvidersForTask(state, taskRef, envTargets) {
67
+ if (!state) return [];
68
+ const normalizedTaskRef = normalizeString(taskRef);
69
+ const wholeLanePinned = envTargets.some((target) =>
70
+ target.enabled !== false
71
+ && normalizeString(target.task_ref) === normalizedTaskRef
72
+ && !normalizeString(target.tool_name)
73
+ && !normalizeString(target.integration_id)
74
+ );
75
+ return listProviders(state, { status: "active" })
76
+ .filter((provider) => Array.isArray(provider.task_refs) && provider.task_refs.includes(normalizedTaskRef))
77
+ .map((provider) => {
78
+ const health = (provider.health && provider.health.status) || "healthy";
79
+ return {
80
+ target_id: `registry:${provider.provider_id}`,
81
+ provider: provider.provider_id,
82
+ routing: "open_provider_registry",
83
+ task_ref: normalizedTaskRef,
84
+ tool_name: null,
85
+ tool_names: Array.isArray(provider.tool_names) ? provider.tool_names.slice() : [],
86
+ integration_id: null,
87
+ enabled: !wholeLanePinned,
88
+ shadowed_by_env_target: wholeLanePinned,
89
+ health_status: health,
90
+ timeout_ms: provider.timeout_ms,
91
+ endpoint_configured: Boolean(normalizeString(provider.endpoint_url)),
92
+ auth_configured: Boolean(normalizeString(provider.auth_token)),
93
+ operational_coverage: {
94
+ execute_endpoint: Boolean(normalizeString(provider.endpoint_url)),
95
+ bearer_auth: Boolean(normalizeString(provider.auth_token)),
96
+ bounded_timeout: Number(provider.timeout_ms || 0) >= 500,
97
+ // The provider-network execution contract fixes the deliverable shape
98
+ // (result.output / output_payload), and activation is operator-vetted against it.
99
+ proof_fact_compatible: true,
100
+ deterministic_retry_surface: true,
101
+ tool_level_binding: Array.isArray(provider.tool_names) && provider.tool_names.length > 0,
102
+ operator_health_surface: "runtime_tracked_provider_health",
103
+ operator_tool_catalog_surface: null
104
+ }
105
+ };
106
+ });
107
+ }
108
+
109
+ function summarizeAdapterTaskDepth(task, state) {
110
+ const envTargets = listTargetsForTask(task.task_ref).map(summarizeTarget);
111
+ const registryTargets = listRegistryProvidersForTask(state, task.task_ref, loadExecutionTargetRegistry());
112
+ const targets = envTargets.concat(registryTargets);
64
113
  const enabledTargets = targets.filter((target) => target.enabled);
65
- const toolNames = Array.from(new Set(enabledTargets.map((target) => target.tool_name).filter(Boolean))).sort();
114
+ const toolNames = Array.from(new Set(enabledTargets
115
+ .flatMap((target) => [target.tool_name].concat(target.tool_names || []))
116
+ .filter(Boolean))).sort();
66
117
  const allTargetsCovered = enabledTargets.length > 0 && enabledTargets.every((target) =>
67
118
  target.operational_coverage.execute_endpoint
68
119
  && target.operational_coverage.bounded_timeout
@@ -80,6 +131,8 @@ function summarizeAdapterTaskDepth(task) {
80
131
  provider_live: enabledTargets.length > 0,
81
132
  configured_target_count: targets.length,
82
133
  enabled_target_count: enabledTargets.length,
134
+ env_target_count: envTargets.length,
135
+ registry_provider_count: registryTargets.filter((target) => target.enabled).length,
83
136
  configured_tool_count: toolNames.length,
84
137
  configured_tools: toolNames,
85
138
  execution_targets: targets,
@@ -89,11 +142,17 @@ function summarizeAdapterTaskDepth(task) {
89
142
  };
90
143
  }
91
144
 
92
- function buildAdapterDepthPack() {
93
- const adapterTasks = listAdapterTasks().map(summarizeAdapterTaskDepth);
145
+ // `state` (optional): the live runtime state. When given, ACTIVE open-network providers count as
146
+ // provider-live paths alongside operator env targets (each labelled routing:open_provider_registry).
147
+ // Without it the pack is env-target-only, exactly as before.
148
+ function buildAdapterDepthPack(state) {
149
+ const adapterTasks = listAdapterTasks().map((task) => summarizeAdapterTaskDepth(task, state));
94
150
  const providerLiveTasks = adapterTasks.filter((task) => task.provider_live);
95
151
  const deepenedTasks = adapterTasks.filter((task) => task.provider_depth_state === "provider_live_path_deepened");
96
152
  const configuredTargets = loadExecutionTargetRegistry().filter((target) => target && target.enabled !== false);
153
+ const registryProviderIds = new Set(adapterTasks.flatMap((task) =>
154
+ task.execution_targets.filter((target) => target.routing === "open_provider_registry" && target.enabled).map((target) => target.provider)
155
+ ));
97
156
  return {
98
157
  ok: true,
99
158
  product: packageJson.name,
@@ -110,8 +169,10 @@ function buildAdapterDepthPack() {
110
169
  deepened_provider_live_task_count: deepenedTasks.length,
111
170
  configured_execution_target_count: configuredTargets.length,
112
171
  configured_provider_count: new Set(configuredTargets.map((target) => normalizeString(target.provider))).size,
113
- configured_tool_count: new Set(configuredTargets.map((target) => normalizeString(target.tool_name)).filter(Boolean)).size
172
+ configured_tool_count: new Set(configuredTargets.map((target) => normalizeString(target.tool_name)).filter(Boolean)).size,
173
+ registry_provider_count: registryProviderIds.size
114
174
  },
175
+ depth_sources: state ? ["operator_env_targets", "open_provider_registry"] : ["operator_env_targets"],
115
176
  adapter_tasks: adapterTasks,
116
177
  production_depth_requirements: [
117
178
  "at_least_one_enabled_execution_target_for_provider_backed_task",
@@ -136,8 +197,8 @@ function buildAdapterDepthPack() {
136
197
  };
137
198
  }
138
199
 
139
- function summarizeAdapterDepthPack() {
140
- const pack = buildAdapterDepthPack();
200
+ function summarizeAdapterDepthPack(state) {
201
+ const pack = buildAdapterDepthPack(state);
141
202
  return {
142
203
  ok: true,
143
204
  product: pack.product,
@@ -145,6 +206,7 @@ function summarizeAdapterDepthPack() {
145
206
  summary_version: "xytara-adapter-depth-summary-v1",
146
207
  adapter_depth_state: pack.adapter_depth_state,
147
208
  counts: pack.counts,
209
+ depth_sources: pack.depth_sources,
148
210
  public_claim_boundary: pack.public_claim_boundary,
149
211
  linked_surfaces: pack.linked_surfaces
150
212
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xytara",
3
- "version": "3.1.11",
3
+ "version": "3.1.12",
4
4
  "description": "x402 pay-per-call agent-commerce runtime: gasless USDC on Base, an open settling provider network with a ledger-reconciled revenue split and automated on-chain payouts (key-less runtime, delegated signer), and bounded cryptographic delegated spend. Proven live on Base mainnet.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -769,7 +769,38 @@ async function hardeningChecks() {
769
769
  } finally {
770
770
  global.fetch = orig;
771
771
  }
772
- console.log(" hardening: epoch-isolation | in-flight guard | timeout cap | settlement basis | endpoint policy | budget");
772
+ // 19. ADAPTER DEPTH counts active open-network providers (labelled registry-routed) when given
773
+ // state; without state it stays env-target-only; a whole-lane env pin shadows the registry.
774
+ const { buildAdapterDepthPack, summarizeAdapterDepthPack } = require("../lib/adapter_depth_contract");
775
+ const prevTargets = process.env.XYTARA_EXECUTION_TARGETS_JSON;
776
+ delete process.env.XYTARA_EXECUTION_TARGETS_JSON;
777
+ try {
778
+ const ad = {};
779
+ assert.strictEqual(summarizeAdapterDepthPack(ad).adapter_depth_state, "provider_wiring_required", "no env targets + no providers -> wiring required");
780
+ reg.registerProvider(ad, { provider_id: "ad_mcp", endpoint_url: "https://ad.example/execute", task_refs: ["adapter.mcp.invoke"], tool_names: ["keccak256"], revenue_share_bps: 7000, auth_token: "t" });
781
+ assert.strictEqual(summarizeAdapterDepthPack(ad).adapter_depth_state, "provider_wiring_required", "a PENDING provider is not a live path");
782
+ reg.setProviderStatus(ad, "ad_mcp", "active");
783
+ let pack = buildAdapterDepthPack(ad);
784
+ assert.strictEqual(pack.adapter_depth_state, "initial_provider_live_path", "one active registry provider -> initial live path");
785
+ const invoke = pack.adapter_tasks.find((t) => t.task_ref === "adapter.mcp.invoke");
786
+ assert.strictEqual(invoke.registry_provider_count, 1, "registry provider counted on its declared task");
787
+ assert.strictEqual(invoke.execution_targets[0].routing, "open_provider_registry", "labelled registry-routed");
788
+ assert.strictEqual(invoke.execution_targets[0].auth_token, undefined, "no auth_token leaks into the depth pack");
789
+ assert.deepStrictEqual(pack.public_claim_boundary.live_task_refs, ["adapter.mcp.invoke"], "claim limited to the declared task");
790
+ assert.strictEqual(buildAdapterDepthPack().adapter_depth_state, "provider_wiring_required", "no state -> env-only (unchanged for internal callers)");
791
+ reg.registerProvider(ad, { provider_id: "ad_mcp2", endpoint_url: "https://ad2.example/execute", task_refs: ["adapter.mcp.invoke"], revenue_share_bps: 7000 });
792
+ reg.setProviderStatus(ad, "ad_mcp2", "active");
793
+ assert.strictEqual(summarizeAdapterDepthPack(ad).adapter_depth_state, "provider_live_path_deepened", "two covered live paths -> deepened");
794
+ process.env.XYTARA_EXECUTION_TARGETS_JSON = JSON.stringify([{ target_id: "pin", task_ref: "adapter.mcp.invoke", endpoint_url: "https://pin.example/execute", provider: "pin_provider", enabled: true }]);
795
+ pack = buildAdapterDepthPack(ad);
796
+ const pinned = pack.adapter_tasks.find((t) => t.task_ref === "adapter.mcp.invoke");
797
+ assert.ok(pinned.execution_targets.filter((t) => t.routing === "open_provider_registry").every((t) => t.shadowed_by_env_target && !t.enabled), "whole-lane env pin shadows registry providers");
798
+ assert.strictEqual(pinned.registry_provider_count, 0, "shadowed providers are not counted");
799
+ } finally {
800
+ if (prevTargets === undefined) delete process.env.XYTARA_EXECUTION_TARGETS_JSON; else process.env.XYTARA_EXECUTION_TARGETS_JSON = prevTargets;
801
+ }
802
+
803
+ console.log(" hardening: epoch-isolation | in-flight guard | timeout cap | settlement basis | endpoint policy | budget | adapter-depth registry");
773
804
  }
774
805
 
775
806
  async function main() {
package/server.js CHANGED
@@ -4945,12 +4945,12 @@ async function routeRequest(req, res) {
4945
4945
  }
4946
4946
 
4947
4947
  if (req.method === "GET" && url.pathname === "/v1/adapter-depth") {
4948
- sendJson(res, 200, buildAdapterDepthPack());
4948
+ sendJson(res, 200, buildAdapterDepthPack(state));
4949
4949
  return;
4950
4950
  }
4951
4951
 
4952
4952
  if (req.method === "GET" && url.pathname === "/v1/adapter-depth/summary") {
4953
- sendJson(res, 200, summarizeAdapterDepthPack());
4953
+ sendJson(res, 200, summarizeAdapterDepthPack(state));
4954
4954
  return;
4955
4955
  }
4956
4956