Skip to content
On this pageSDKMCP server

Reference / Changelog

Changelog

What changed in each release of the two packages, newest first. Read every line marked Breaking before you upgrade: it can need a change in your code or change what your agent does. Each version is a link you can share.

SDK

@vulsight/guard on npm. Set it up with the SDK page.

Upgrade to the current release with one command. Then read the Breaking lines of every release you skipped.

Terminal
npm install @vulsight/guard@0.7.0

0.7.0

Added

  • An agent set to observe on the guard gets one console.warn naming the decision enforce mode would have given, with its reasons.
  • DecisionRecord carries the agent's dashboard name as optional agentName on listed decisions.

Changed

  • reportSettlement finds a payment's decision through x402's onPaymentResponse hook, which guard() now registers. It no longer reads the signed PAYMENT-SIGNATURE header.
  • Breaking Pass reportSettlement the response wrapFetchWithPayment returned, and call guard() before you register any onPaymentResponse hook of your own.
  • Breaking For a paid request sent without wrapFetchWithPayment, pass its response to processPaymentResult on new x402HTTPClient(client) before reportSettlement.
  • An x402 client with no onPaymentResponse gets a warning and cannot report a settlement.
  • Breaking guard() also registers a payment policy, so Hookable requires registerPolicy. An x402Client from @x402/core 2.24 or later has it. A structural wrapper must expose it.
  • Breaking A second guard() on the same x402 client throws. Give each session its own x402 client.
  • Breaking observe mode lets a payment through only when the guard did not answer in time. That means it was unreachable, sent a 408 or a 5xx other than 503 payment_screening_unavailable, or ran past its time budget.
  • A rate limit, and a page sent for checking that the guard refused, now abort the payment in both modes.
  • A page whose read failed or was still arriving after 5 s now aborts the payment in both modes.
  • A 402 or decision the SDK cannot read, and a held payment whose review poll failed, now abort in both modes.
  • Breaking guard() throws when session is not 1 to 200 characters with no NUL character.
  • Breaking guard() and new GuardClient() throw when apiKey is missing or blank. 0.6.0 built and failed on each call.
  • Breaking X402Proposal and X402Payment refuse an unknown field, so a caller of vulsight.api.decide must drop fields the API does not take.
  • Breaking X402Proposal and X402Payment refuse a scheme that is not lowercase letters, digits, and hyphens. Send exact as the 402 writes it.
  • X402Proposal and X402Payment accept x402Version (2 only), assetTransferMethod, paymentFlow, and the 402's extra.
  • Breaking TypeScript change RuleId includes payment_method_supported; handle it in exhaustive maps and switches.
  • When a seller offers several options, the x402 client pays with one the guard supports instead of aborting on an unsupported first one.
  • When a seller offers no supported option, the payment hook refuses before signing, in both modes, and lists up to five of the options offered.
  • The payment hook refuses before signing, in both modes, a 402 that is not x402 version 2.
  • On Solana, the payment hook refuses before signing a transfer method other than the default.
  • The payment carries the 402's declared assetTransferMethod and paymentFlow to the guard.
  • X402_SUPPORT and paymentSupport(payment) from @vulsight/guard/types are the supported payments and their check. The API, the advisory MCP tool, and the proxy use the same.
  • A refusal of an unsupported payment names the payment's own network.
  • reportSettlement reads the older X-PAYMENT-RESPONSE header too, and reports each receipt once. A repeat returns the recorded settlement.
  • reportSettlement keeps up to 1000 receipts. It refuses a receipt two payments name, a response from the unsigned vulsight.fetch, and a payment the guard did not decide.
  • On a second 402, or a receipt whose success is false, reportSettlement names the seller's reason only for known x402 refusal codes. Anything else is an unknown outcome.
  • A reportSettlement error for a short-funded wallet says to wait until the signed payment expires: on EVM when the 402 offer's time limit passes, on Solana when its recent blockhash is no longer valid.
  • reportSettlement reports a used or expired authorization, a failed simulation, and settlement_pending as possibly settled.
  • A possibly settled error says to check the wallet's transfers to the payee on chain before paying again, and that an allowed or approved amount still counts toward the daily cap for the UTC day the guard checked it.
  • In observe mode, a payment's amount counts toward the cap only if enforce mode would have allowed it, or held it and the review timeout has not passed.
  • reportSettlement errors that name the paid URL drop its query.
  • A payment waits only for pages from its own site, and for text sent for checking under a label that names no site. Another site's unchecked page blocks only payments to that site.
  • The review wait tries again after a poll the guard did not answer or rate limited. A refused or unreadable poll aborts at once and names the held decision to check before a retry.
  • A held payment prints one console.warn when the wait starts. It names the decision, the Review page at <baseUrl>/review, and how long the SDK waits.
  • A payment still held when the wait ends says to deny the open review on the Review page first, then run the payment again. The open review counts toward today's cap until it expires.
  • An expired review says to run the payment again and approve it before it expires, or to raise the Review timeout and waitForReviewSeconds with it.
  • A refused or failed last review poll links the decision at <baseUrl>/decisions/<id>.
  • Breaking The held payment sentences changed, so code that matched the old "Ask your user to review it in the VulSight Guard dashboard." sentence must update.
  • file() given undefined or null sends nothing for checking and answers pass.
  • file() given any other value that is not a string sends nothing, answers unavailable, and logs a warning.
  • A text sent for checking that the guard refused or still rate limits aborts the next payment it concerns, in both modes.
  • Breaking Every guard call refuses a base URL that redirects and names the address to set.
  • Every guard call sends an x-vulsight-client header with the SDK version, and a 408 counts as an outage.
  • An error for an answer that is not the guard's names the host and status, and an answer this SDK cannot read says to update it.
  • README and Policy docs: the daily cap is one USDC budget per key across every network and lane.
  • README: how long the proxy holds an EVM payment for review, and what its review_pending and resign_required answers mean.
  • README: where to answer a held payment's review, and to give the HTTP client a read timeout of at least 60 seconds.
  • README: the proxy's Solana receipt statuses, and the 16 MiB daily ceiling on text sent for checking.
  • README: the vs_test_ prefix as only a key format, and the MCP tool as advisory, not enforced.
  • README: the sample reads its keys from the environment, pays the demo seller, and says how to run it.

Fixed

  • When a seller answers the signed retry with a redirect, the wrapped fetch returns it unfollowed with a warning that the payment may have been made, where it used to throw. A browser hides redirects, so there it throws that warning.
  • A page the guard passed is sent for checking again when it is read a minute or more later. That replaces a pass the guard no longer honors.
  • A cited excerpt is cut between characters, so a page with an emoji at its 2000th unit no longer fails the decision.
  • A payment still held when the wait ends mentions Approve and always allow this payee only when a first payment is the only reason for the hold.

Security

  • Breaking TxHash refuses the all-zero hash and SolanaSignature the all-zero signature, the unsigned placeholders.
  • The payment hook refuses, before signing, terms that are not one of the 402's offers.
  • The hook that runs after signing blocks, in every mode, a payment whose x402 version, offer, or resource URL changed after the check, or whose 402 was replaced so no decision matches it.
  • reportSettlement refuses, as the proxy does, a receipt whose transaction is the payment's own EIP-3009 nonce, the buyer's own Solana signature, or an unsigned placeholder. The error never repeats the value.
  • On Base, reportSettlement records the signing wallet as the payer of a receipt that names none, and refuses one naming another payer, as the proxy does. A paid 402 can be reported too.
  • vulsight.fetch throws on a URL under the guard's own /p/ proxy path, and on a read redirected onto one, so a proxied payment is not decided twice and its proxy token stays out of decision records.

0.6.0

What changed

Added

  • The wrapped fetch sends every 402 for checking, the unpaid one and one answering a signed retry, with the text the proxy sends for it: the description in its terms, then its body.
  • The next payment waits for a 402's check, and cites the 402 when it was the last read from that origin.
  • file(text, origin) sends the text under the origin of an http(s) URL given as origin, so text read from a seller's page is linked to that seller.

Changed

  • A text is posted once per origin rather than once per hash, so identical text two sellers serve is linked to each of them.
  • README: what is checked in a body, and which text sent for checking holds payments.

Fixed

  • A binary body (a NUL byte in its first 8 KiB) up to 4 MiB sends the readable text inside it for checking, where it sent 64 KiB of replacement characters.
  • A binary body over 4 MiB is still sent at the cap and stays unchecked, since the rest was never read.
  • A payment no longer cites a page with no text, such as an empty body or an image with no readable text, which the guard read as a page it never received and held for review.

0.5.0

What changed

Added

  • Breaking TypeScript change Policy includes required blocklistEnabled; add false to constructed values, or use Policy.parse(input) to apply the default.
  • Breaking TypeScript change RuleId includes wallet_blocklist; handle it in exhaustive maps and switches.

Changed

  • Allow more time for pending reads, sending context for checking, one retry, and the payment decision, matching the longer content check budget.
  • README: explain that completed content blocks deny payments and review results hold them when content enforcement is enabled.

Fixed

  • Keep each payment attempt's quote identity separate so reused quotes cannot mix decision identifiers.
  • Keep the content check's answer, a person's review clearance, and whether the check is enforced in context and decision responses.

Security

  • README: treat the proxy token as a secret, keep its URL out of history, logs, and screenshots, and rotate the key if it leaks.

0.4.1

What changed

Added

  • observed402PayTo and payer carry descriptions.

Changed

  • A page read that failed aborts the payment with the page's origin and what cut the read short.
  • reportSettlement names the header, the field, and the next step when a seller's receipt cannot be recorded, in place of a raw decoder or zod error.
  • reportSettlement refuses a receipt whose network is not the payment's before it posts.
  • A decision's sentences open with the rule that denied or held the payment and end with the notes.

Fixed

  • The review poll rounds the time left up to a whole second, so waitForReviewSeconds 1 polls once where 0.4.0 could abort without a poll.
  • A NUL byte in a page is sent as the replacement character, and a leading byte order mark is kept.
  • A page the guard refused blocks one payment rather than every later one.
  • The origin sent with a text is clipped to 200 characters.

0.4.0

What changed

Added

  • The payment hook sends an Idempotency-Key per payment attempt, so a retried call is decided once.
  • Solana Devnet and Solana Mainnet USDC beside Base Sepolia and Base, with base58 address checks.
  • holdOverAtomic on Policy and the amount_hold_over reason.
  • decisions.list pages with a before cursor.

Changed

  • A policy list holds at most 200 payees.

Security

  • Every request field carries its own sentence, and a resource URL with credentials is refused.

0.3.0

What changed

Added

  • The seller URL cap is the exported RESOURCE_URL_MAX, 2000 characters.

Changed

  • Abort reasons name the cause. A 200 that is not the guard's JSON names the host, and a 402 with no resource aborts instead of throwing.
  • A review still open at the wait budget keeps its rule sentences.

Security

  • A NUL byte in any field is refused at the boundary.

0.2.2

What changed

Changed

  • Inputs are bounded and every 422 is worded.
  • README: a text at the 64 KiB cap counts as unavailable, never a pass.

Fixed

  • Every page sent for checking is kept until the guard has taken it.

0.2.1

What changed

Changed

  • Longer payment verification deadlines.

0.2.0

What changed

Added

  • allowedResources on Policy: a payment for a resource outside the declared task is held.
  • Every tool result can be sent for checking, with a Claude Code hook.
  • BASE_MAINNET beside BASE_SEPOLIA; a payment on any other network is blocked before the guard is asked.

Changed

  • The default review wait is 120 seconds, the default policy's review timeout.
  • The excerpt sent for checking is the API's full 2000 characters, and a flagged page read again renews the hold.

Fixed

  • A rejected API key aborts with the key sentence instead of blaming the page.

0.1.2

What changed

Changed

  • "Seller" for the party the agent pays, in the sentences and the README.

0.1.1

What changed

Changed

  • @x402/core unpinned.
  • Error sentences name the host, the code, and the next step.

Fixed

  • The page sent for checking is clipped to 64 KiB of UTF-8, and the payment hook stays inside its 5 s budget.
  • Settlement reports are verified, deduplicated, and awaited.

0.1.0

What changed

Added

  • First publish: guard() with the x402 payment hook, the API client, and the shared types.

MCP server

@vulsight/guard-mcp on npm. Set it up with its setup page.

advisory

The MCP tool is advisory. The agent chooses whether to ask. For a check it cannot skip, use the proxy URL or the SDK hook.

0.4.0

Added

  • A file_context text or hook result that could not be sent for checking because the guard was out (a 408, a 429, a 5xx, or no answer) is kept.
  • The next check_payment a kept text concerns sends it first, and fails closed while the guard is still out.
  • The Claude Code hook keeps unsent results, at most 200 a session, in a file under the system temp directory that only the server's operating system user can read, so a restarted server still sends them.
  • A reused idempotency_key answers with a sentence that names the causes and asks for a new key.
  • list_recent_decisions names each agent and takes a before cursor.

Changed

  • check_payment forwards an x402 payment's x402Version, the requirement's extra, assetTransferMethod, and paymentFlow.
  • check_payment refuses locally what the guard cannot judge: any scheme but exact, an upfront or escrow flow, and a transfer method other than EIP-3009 on Base or the default on Solana.
  • Breaking check_payment refuses a payment with a field it does not take, where 0.3.0 dropped it. Pass only the listed fields, not the whole 402 accepts entry.
  • Breaking check_payment refuses a scheme that is not lowercase letters, digits, and hyphens. Pass it as the 402 writes it.
  • The printed skill (--skill, --skill codex) says the tool is advisory, not enforced.
  • The printed skill adds a step that lists the payment methods the guard supports.
  • The printed skill says when to skip the tool for a payment sent through the proxy URL.
  • The printed skill says which terms and receipts to report.
  • The printed skill says the vs_test_ prefix is only a key format, not test money.
  • The printed skill asks for the proxy URL shown with the user's API key when it needs one. It does not pay until it has it.
  • The printed skill tells the user to install the server with --scope user.
  • The printed skill says a 409 resign_required after a content wait means nothing was sent, and to request the URL through the proxy again and sign the fresh 402.
  • A flagged page sent for checking under its URL origin holds that seller in every lane, the proxy included.
  • check_payment sends kept texts for checking one at a time, within its own time budget, and stops on a cancel between them.
  • A check_payment that runs out of time fails closed, and the next one sends the rest.
  • A refused kept text is reported as one kept from earlier, not one sent with this payment.
  • A page's kept text tells the agent to send it again with file_context before a payment through the proxy URL.
  • check_payment's held and expired answers name the Review page at <baseUrl>/review.
  • A held answer says to repeat check_payment with the same payment, context, seller_402, and idempotency_key when nothing new was read. Otherwise, or with no key, have the review denied, send any new content with file_context, and check again.
  • An expired answer says to check again with a new idempotency_key and approve it before it expires, or to raise the Review timeout and wait_seconds.
  • A hold whose answer could not be read links <baseUrl>/decisions/<id>.
  • report_settlement and the printed skill say a receipt whose success is false may still have settled. file_context says so too.
  • report_settlement and the printed skill say the seller can use the signed payment until it expires: the 402 offer's time limit on EVM, the recent blockhash on Solana.
  • report_settlement and the printed skill say to check the wallet's transfers to the payee on chain before paying again.
  • report_settlement and the printed skill say an allowed or approved amount still counts toward the daily cap for the UTC day the guard checked it.
  • In observe mode, a payment's amount counts toward the cap only if enforce mode would have allowed it, or held it and the review timeout has not passed.
  • get_policy prints limits and thresholds in USDC instead of the asset's smallest unit.
  • get_policy says an allowed payee skips the wallet blocklist and the guard's issuer freeze check, while the token contract still refuses a transfer to a frozen account.
  • A failed, rate-limited, or unreadable review poll is tried again until wait_seconds runs out, and a wait whose every poll failed says the answer could not be read.
  • Breaking Guard calls refuse a missing key and a base URL that redirects; set the key and the final base URL.
  • Guard calls send x-vulsight-client and treat a 408 as an outage.
  • The daily cap is one budget per key across networks, and get_policy says so.
  • README: install with --scope user, the guard's tools do not pay (the agent brings its own x402 payment tool and wallet), and how to get a lost proxy URL.
  • Breaking Node 20.3 or later.

Fixed

  • A cancelled check_payment stops before it decides, and a response the guard refuses is told to the report_settlement call that sent it, not sent again in another client's check.
  • The Claude Code hook reports a missing key or a failed send for checking to the agent, and a bare unknown command prints usage and exits 1.
  • An excerpt cut inside a character is sent whole, and text with nothing to read counts as a pass.

Security

  • report_settlement refuses an all-zero txHash or Solana signature, the unsigned placeholders, before it asks the guard, as the proxy does.

0.3.0

What changed

Added

  • check_payment takes seller_402, the seller's 402 answer, and sends it for checking before deciding, like context; the decision cites context when both are given.
  • report_settlement takes response, the body of the paid answer. It sends the body for checking under the paid seller's origin, and the next check_payment waits for it.
  • If report_settlement cannot send response for checking, the settlement stays recorded, and the next check_payment sends it first, failing closed while the guard is out.
  • A paid response the guard refuses fails one check and is then dropped, as in the SDK.

Changed

  • file_context and the skill ask for a web page's origin as a URL in origin, so a flagged page holds only payments to that seller. Any other label, such as a bare host or a tool's name, still holds every payment in the session.
  • file_context and the skill say to send for checking a paid answer that has no receipt to report.
  • The hook sends a tool result fetched from an http(s) url for checking under that url's origin, and anything else under the tool's name.

Fixed

  • An empty response records the settlement and sends nothing for checking.

Security

  • A retry that reuses idempotency_key with a changed seller_402 is decided again instead of replaying the earlier answer.

0.2.8

What changed

Fixed

  • Return 404 for malformed request paths without stopping the server.

Security

  • Reject browser requests from foreign origins on the local HTTP endpoint.

0.2.7

What changed

Added

  • check_payment asks for observed402PayTo, the payee the seller's own 402 named, so a redirected payee is denied, and its schema carries the field descriptions.

Changed

  • The dashboard step follows every pending review, with or without a wait.
  • The denying sentence comes before the notes in every answer.
  • README: a NUL is sent as the replacement character, a leading byte order mark is kept, and the stored excerpt carries the flagged passages.

Fixed

  • The hook command sends a tool result as reportContext clips it, and a review poll with under a second left still polls for one.
  • A NUL in a check_payment context posts as the replacement character.

0.2.6

What changed

Added

  • check_payment takes an idempotency_key, so a retried call is decided once.
  • Solana Devnet and Solana Mainnet USDC beside Base Sepolia and Base.
  • The policy read names the hold threshold.

Fixed

  • The review poll's remaining wait is clamped at zero, ending the negative timeout warning.

0.2.5

What changed

Added

  • --help on the CLI, and abort reasons that name the cause.

Fixed

  • A session's texts are sent for checking in one chain, and a payment waits for it to drain. So a page sent with the payment reaches the guard before it decides.

0.2.4

What changed

Fixed

  • A text at the 64 KiB cap counts as unavailable, never a pass.

0.2.3

What changed

Changed

  • README claims corrected before the release.

0.2.2

What changed

Changed

  • Longer payment verification deadlines.
  • README: any MCP client can take the server.

0.2.1

What changed

Changed

  • The default review wait is 120 seconds like the SDK, and the documented Codex config carries the tool timeout.

0.2.0

What changed

Added

  • A payment for a resource outside the declared task is held.
  • file_context sends every tool result for checking, and a Claude Code hook does it for that client.
  • Base beside Base Sepolia as a policy network.

Changed

  • The excerpt sent for checking is the API's full 2000 characters.

0.1.3

What changed

Changed

  • "Seller" for the party the agent pays.

0.1.2

What changed

Changed

  • Version bump beside sdk 0.1.1, which unpinned @x402/core.

0.1.1

What changed

Added

  • --skill prints the bundled Claude Code skill, --skill codex the Codex snippet.

0.1.0

What changed

Added

  • First publish: the MCP server with check_payment and get_policy, and the bundled skill.