Changelog
Notable changes to the NessGate resolver and its specification, newest first. Specification stability guarantees live in the specification.
2026
Dual-era MCP, library federation, inbound inspection, hardening (1.18.0 → 1.22.0)
- @nessgate/inspect 0.2.0 / 0.2.1, /inspect page — Web Bot Auth verification accepts RSA-PSS-SHA512 signatures alongside Ed25519 (RFC 7638 RSA thumbprints, key-type-to-algorithm matching; validated against the protocol draft's Appendix E.1 vector). Lower-level modules are importable from their own subpaths (
/webbotauth,/agents,/netattr,/agentcard). New /inspect page documenting the local, server-side workflow with worked examples of each evidence level, plus runnable Fastify and Next.js examples in the repository. The resolver is unchanged at 1.22.2. (2026-10-04) - 1.22.2 / @nessgate/inspect 0.1.5 — documentation and wording precision: storage statements now consistently distinguish persistent storage (none for discovered domain or resource data), temporary edge caching, short-lived rate-limit counters, and the anonymous operational events described in the Privacy Policy; assorted repository documentation tidying. No behavior changes. (2026-10-04)
- @nessgate/inspect 0.1.3 / 0.1.4 — normative Signature-Agent label rule (profile
section 5.2.1): the member keyed to the signature label must be the covered member; the published
Appendix E.2.1 vector's label/member mismatch is documented as a vector defect — rejected as
published, while the label-corrected form verifies the same cryptographic bytes. Multiple
web-bot-auth signatures are validated independently (section 5.2.2), one result per signature.
Legacy bare-string
Signature-Agentvalues must be https origins resolved at the well-known directory path — a non-root path, query, or fragment is rejected rather than fetched (0.1.4). (2026-10-04) - 1.22.0 / @nessgate/inspect 0.1.2 — Web Bot Auth verification now implements the IETF
WG protocol draft (draft-ietf-webbotauth-httpsig-protocol-00) and was validated against its Appendix E.2 test vectors (see the 0.1.3/0.1.4 entry above for the
later-documented E.2.1 vector defect):
Signature-Agentparsed as a Structured Fields dictionary withtypesemantics (directoryorigins at the well-known path,jwks_uri; unsupported types ignored, never inferred), the covered;key=member drives key discovery,keyidmust be the JWK thumbprint,created/expires/tag/@authority-or-@target-urienforced before any verified verdict, redirects never followed during discovery, multiple signatures handled without misattribution. MCP initialize-era support extends to revision 2025-11-25. Package release triggers separated (a release can no longer publish the other package as a side effect); an IP-level lab measurement retired in favor of the privacy policy's stronger wording. (2026-10-03) - 1.21.0 — MCP-Registry federation returns one record per server name: the registry's own
isLatestmarker wins; without it, the deterministic fallback is the greatest version under numeric-aware comparison — an older version can never win by appearing first. Readiness checks of nessgate.com's own endpoints are answered through the in-process router (the platform refuses a worker fetch into its own zone), so the service no longer misreports itself unreachable. A deterministic offline gate (npm run gate) now backs CI and both package publish workflows; the live smoke suite stays post-deploy only. (2026-10-03) - 1.20.0 — Dual-era MCP client: protocol revision 2026-07-28 (stateless;
initializeremoved;server/discoverrequired) is recognized in readiness and introspection alongside the initialize-based revisions, and the hosted/mcpanswers theserver/discoverprobe with the versions it actually implements. A2A v1 cards:supportedInterfaces[].protocolBindingwith per-interfaceprotocolVersion(0.3.x and legacy shapes keep working). A declared document larger than the bounded readiness read reportsincomplete(verified: "oversized"), neverbroken. (2026-10-03) - 1.19.0 — The library gains opt-in MCP-Registry federation (
registry: true, failures disclosed asfederatedUnavailable) and bounded declared-pointer delegation (delegate: true, accounting indelegation). (2026-10-03) - @nessgate/inspect 0.1.0 / 0.1.1 — experimental inbound-request inspection package: evidence tiers (claimed / cryptographically-verified via RFC 9421 Web Bot Auth, including the current Signature-Agent dictionary form / network-verified via each operator's documented method / directory-attributed / unknown), provenance on every fact, no decisions or scores, plus an Express middleware. 0.1.1 hardens every outbound fetch: per-hop redirect validation, DNS checks rejecting private and reserved space, response-size and JWKS key caps. (2026-10-03)
- 1.18.0–1.18.1 —
readyrequires protocol-level evidence (an endpoint answering HTTP 200 is not an MCP server; documentation-section paths are never endpoints); registry-federation failures disclosed asfederatedUnavailable; platform request-budget exhaustion disclosed asskipped:capacity. (2026-09-30)
Connection readiness, connection plans, three MCP tools, and an open self-test (1.13.0 → 1.17.1)
- Connection readiness (opt-in):
GET /explore/{domain}?readiness=1attaches areadinessblock to each connectable resource, assessed read-only from the service's own published metadata — OpenAPIservers+securitySchemes, A2A agent cards, and the MCP OAuth metadata chain (RFC 9728 → RFC 8414). Outcomes are enums, never scores:ready,credentials-required,incomplete(withmissing[]naming the exact under-published field), and — from 1.16.0 —broken, claimed only on positive evidence (the declared location answered 404/410/5xx or an unparseable document; denials and network failures never read as broken). Default/exploreoutput is unchanged. (1.13.0, 2026-09-27; broken outcome 1.16.0, 2026-09-29) - Connection plan:
POST /connect/{domain}matches the caller's declared client capabilities against what the domain publishes (deterministic intersection) and returns one outcome with a concrete plan — protocol, endpoint, transport, version, and the auth metadata the service published. Capabilities are input only (nothing stored); responses are uncached; credentials stay with the caller. An emptyclientis answered with a broad default and labeledclientAssumed:truerather than a falseno-compatible-method(1.15.1). (1.14.0, 2026-09-27) - MCP server grew to three read-only tools:
discover_domain,connect_domain,check_readiness— same handlers and rate limits as the REST endpoints. (1.17.0, 2026-09-29) - Open self-test:
npx @nessgate/resolver yourdomain.com(binnessgate-ready) runs the readiness assessment client-side — repeated observations, unanimity required, exit 0 only when a connectable path is consistently usable; otherwise it names the exact missing field. Nothing is reported anywhere. An OpenAPI document that declares top-levelsecurity: []now reads as explicitly open. (1.17.0, 2026-09-29) - Anonymous usage outcomes: the existing single-site categorical metric gained
connect:<outcome>andreadiness:<aggregate>labels — one label per call, no domains, IPs, client payloads, or identifiers. Library versions 1.13.0–1.17.1 on npm; worker, OpenAPI description, and MCP serverInfo versions kept in step. (2026-09-27 → 2026-09-29)
Anti-bot honesty in the verify pass: identify walls, never assume, never evade
- The reachability states grew to distinguish what a denial actually means:
blocked(anti-bot protection reliably identified via a small conservative signal list — challenge headers and high-precision markers; NessGate reports walls, and never attempts CAPTCHA bypasses, proxy rotation, or any evasion),rate-limited(429 — alive;Retry-Aftercaptured as evidence, never acted on), andunknown(a denial whose cause cannot be established). Two honesty corrections to yesterday's initial verify release: a bare 403 no longer reads asauth-required— auth systems and bot-walls both use 403, so without protocol evidence (401/407 orWWW-Authenticate) it isunknown; and 429 no longer reads asunreachable. Every verified record now carries anevidenceobject ({status, signal name, retryAfterSeconds}) so the classification is auditable — response content is never stored. Library 1.12.0; additive except the disclosed 403/429 relabeling inside the day-old opt-in verify pass.
Opt-in reachability verification (?verify=1)
- Finding an address does not mean an agent can use it.
?verify=1(and the library'sresolve(domain, {verify: true})) adds per-recordreachability—ok/auth-required/not-found/unreachable— withcheckedAt, distinguishing outages from auth walls from dead declarations. Evidence-derived where possible: already-fetched surfaces areokwith no extra request, MCP records reuse introspection, and only declared pointers get one safe probe each (HEAD, then a bounded GET — never a POST, never an execution), capped at 8.okasserts only that the endpoint answered a safe request; absentreachabilitymeans not checked. Off by default; additive; library 1.11.0.
Seven fixes from an adversarial component evaluation
- An isolated evaluation (deterministic adversarial scenario suite + unseen live domains +
free-tool comparisons) demonstrated seven concrete weaknesses; each fix ships with its
demonstrating scenario as a regression test. Discovery: YAML OpenAPI specs
(
/openapi.yaml/.yml) are now detected via the document's own top-level marker (pointer records, verbatim title — no capability enumeration without a YAML parser, stated plainly); thellms-full.txtcompanion location is probed; one catalog declared through several channels (well-known +rel="ard"+ robots Agentmap) now yields one record, not three (both hosted and library). Library robustness: a globaldeadlineMsbudget (default 20 s — the hosted worker always had one; the library did not), with empty cut-short results labeledincomplete; a nonexistent probed host (DNS NXDOMAIN) now counts as an answer rather than a refusal; a transient apex DNS failure is retried once before it can read as nonexistence. New library capability:resolve(domain, {org: true})— bounded related-host discovery (docs./developers./…), the in-process counterpart of/explore?org=1, reportingorgChecked. Library 1.10.0; all changes additive.
Unified outcome label: found / none-found / blocked / incomplete
- Every
/discoverand/exploreresponse (and the library'sresolve()) now carries a singleoutcomelabel, derived from a classification of every failed probe: a clean 404/410, a nonexistent host, or a redirect pointing away is an answer (absence confirmed at that location); an auth wall, rate limit, timeout, or network failure is a refusal (absence unknown). Nothing found + refusals at least as common as answers →blocked, never a silent empty./exploreaddsincompletewhen budgets cut the walk short, andblockedProbesdiscloses refusal counts even undernone-found. The homepage checker now says explicitly when a domain would not let hosted checks look. Additive; existing fields unchanged.
Related-host check: probe slots go to plausible publishing hosts
/explore/{domain}?org=1probes a bounded set of same-domain hosts. Host selection is now prioritized: homepage-linked hosts with developer/documentation-facing labels (docs.,developers.,api.,platform.,community., …) first, then the conventional shortlist, then remaining homepage-linked hosts — so CDN/telemetry/navigation subdomains that happen to appear first in the homepage HTML no longer consume the probe budget. Probes now also include/.well-known/ai-catalog.json(the ARD-canonical name). Prioritization only orders the bounded probe list; a host is still reported only when it serves a validated machine-readable document. The homepage check UI now lists exactly which hosts were checked when nothing is found, and distinguishes rate limiting from a timeout.- When the queried domain's own homepage redirects to a different registrable domain
(
aws.com → aws.amazon.com), the org response now reports it ashomepageRedirect— an honest observation of the publisher's own configuration, never merged into resources — and the homepage UI offers a one-click "Check {target} →" follow-through. Shell domains stop reading as bare, unexplained empties. - Probe set widened:
cloud.joined the conventional shortlist (cloud.google.com servesllms.txtwhile docs./developers.google.com do not) and the host cap rose from 4 to 6, still inside the request budget. Org responses also gainorgBlocked: hosts whose probes were all refused or blackholed (network failure, 401/403/405/429, 5xx) — a clean 404 still counts as "answered, publishes nothing". The UI reports blocked hosts as absence unknown (the embeddable library from your own machine may succeed) instead of implying "nothing found".
Opt-in read-only MCP introspection (?mcp=1)
- When a domain declares an MCP endpoint,
/discover/{domain}?mcp=1(and the library'sresolve(domain, {mcp: true})) can ask that server what it declares, using the protocol's own read-only handshake:initializeandtools/list— nothing else, ever. No tool execution, no credentials (auth walls are labeledauth-required, never retried), POSTs never follow redirects, HTTPS endpoints on the queried registrable domain only, max 3 per resolution, 256 KB response cap. Declared tools (name/description/inputSchema) land verbatim in the existingcapabilitiesenvelope;introspectionrecords the negotiated protocol version andserverInfo; responses are labeledintrospected:["mcp"]. Off by default — the default response never introspects. Additive; library 1.8.0.
Declared capabilities on resources (verbatim) + honest redirect attribution in the library
/discoverresources (and the library'sresolve()) can now carry acapabilitiesarray copied 1:1 from the publisher's own declarations: OpenAPI operations (method, path, operationId, summary) with declaredsecurityschemes, and A2A / GB‑Z agent-card skills. Nothing is inferred, renamed, or reclassified — a source that declares nothing simply has nocapabilitiesfield. Lists cap at 40 with a labeledcapabilitiesTruncatedflag. For OpenAPI documents larger than the 64 KB detection prefix, one additional bounded read (1 MB) enumerates operations; larger specs stay detected-but-not-enumerated.- The embeddable library (
@nessgate/resolver1.7.0) now records the final post-redirect URL assourceUrland labels a fetched document whose final URL crossed to a different registrable domainverified-external-locationinstead ofverified-publisher-location— accurate attribution for wholesale rebrands (e.g.neon.tech → neon.com). The hosted resolver remains domain-locked and never follows cross-domain redirects. Additive; existing fields are unchanged.
Charter amended — anonymous operational measurement of discovery fulfilment
- Charter Promise 6 and the Privacy Policy now permit NessGate to record anonymous, categorical events about its own operation: for each discovery call, one outcome label — resources returned, none returned, invalid input, or error — with a timestamp and nothing else. There are no domains, request contents, IP addresses, or identities, and no client-IP classification. Cloudflare Analytics Engine stores these events, aggregates them when queried, may sample them, and retains them for about three months. The sole purpose is to measure whether NessGate actually returns results to agents; it never captures who calls or what they look up, and never influences how any resource is classified. Domain data, user data, cookies, and visitor tracking remain prohibited.
v1.6.0 — Benchmark-driven general rules
- Canonical-host fallback (same registrable domain only). When the exact host
publishes nothing and its homepage redirects to
www./a subdomain of itself,/discover(and the library) probes that canonical host forllms.txtandard.json. Cross-registrable-domain redirects are never followed here. - Stricter text-probe validation. HTML is now detected behind leading
<!-- -->comments, closing a false positive where an HTML login shell could pass asllms.txt; genuine text files with comment headers still pass. publisher-redirect-candidate. In Related Discovery, an apex homepage redirecting to a different registrable domain yields a provenance-carrying candidate entry (verified resources required) — never treated as the same authoritative host.- Heavy-route CPU cut: documents are parsed once and shape-checked as objects, instead of re-parsed per candidate type.
v1.5.0 — Related Discovery
GET /explore/{domain}?related=1(opt-in). A clearly separate cross-registrable-domain layer, returned inrelated[]and never mixed with exact-host results.publisher-declared-related: the queried domain itself serves a purpose-built declaration naming the site (a legacy Related Website Set file, checked for reciprocity, or a Digital Asset Links web statement) — hyperlinks never qualify.registry-verified-related: a domain-verifying registry names the specific host, always attributed.infrastructure-correlated-candidate: caller-supplied candidates with a cited technical signal. Technical signals (nameserver containment) are recorded insignals[]as corroboration only — they never mean "official" or "same organization", alone or combined. Bounded (≤5 related hosts), deterministic, non-crawling; evidence rules indocs/related-discovery-rules.md.
v1.4.0 — Organization Discovery
GET /explore/{domain}?org=1(opt-in). Many organizations publish their machine-readable resources on a related subdomain (developers.openai.com) rather than the apex. Organization Discovery probes a bounded set of plausible same-registrable-domain hosts — subdomains the homepage itself links to, plus a small conventional shortlist (at most 4 hosts × 2 paths) — and reports only resources that actually verify, labelled evidencesame-domain-hostwith the probe provenance. The registrable domain is shared; the organizational relationship is not independently verified. Hosts probed appear inorgChecked. No brute-force scanning; off by default;/discoverand default/exploreunchanged.
v1.3.3 — Documentation
- Corrected the npm package README: current mechanism list, accurate export names, browser guidance (use the hosted endpoint for arbitrary domains), and the optional GB/Z 185.5 gateway option. No behavior change.
v1.3.2 — Evidence-based exploration; version alignment
GET /explore/{domain}(additive). Everything/discoverreturns, plus bounded delegated discovery: NessGate follows the explicit machine-readable pointers a domain declares (anllms.txtindex's links, ARD and api-catalog entries) up to depth 2 — cross-host only where the publisher named the target — and federates the official MCP Registry for the domain's verified reverse-DNS namespace. Every record carries anevidenceclass (publisher-hosted/publisher-declared/namespace-verified/candidate) and aprovenancechain. Strictly bounded (depth ≤2, ≤8 hosts, ≤24 requests, global byte cap, SSRF checks on every hop); stateless; no crawling, no guessed subdomains, no ownership claim./discoveris unchanged.- Opt-in candidate verification.
POST /explore/{domain}with{"candidates":[…]}verifies caller-suggested URLs (from the caller's own AI or search) and labels eachevidence:"candidate"— existence and type confirmed, relationship to the domain unverified. NessGate itself runs no AI. - Honest empty results. An empty answer now reads "no supported resources found on this exact host", noting that related product hosts or external registries may publish more.
- Version labels aligned across the library, MCP server, registry listing, and this API description. No behavior change.
v1.3.1 — Accuracy fixes
- AID, not DNS-AID. The DNS adapter reads the AID draft's TXT record
(
v=aid1at_agent); it is not the IETF DNS-AID draft (SVCB at_agents), which is a separate, unimplemented mechanism. The adapter id changed fromdns-aidtoaid. - ARD scope narrowed. NessGate implements ARD's normative domain resolution
(well-known catalog +
rel="ard", both MUST in v0.91) plus the robotsAgentmap:surface; in-page JSON-LD and the not-yet-specified DNS mechanism are not read.
v1.3.0 — GB/Z 185.4 agent descriptions
- GB/Z 185.4 (China, 智能体互联). ACS agent descriptions are recognized by
content and normalized (source
gbz-185-4), preservingaic, provider, security schemes, certificate, and skills. No GB/Z-specific path is guessed. The embeddable library adds an optional, Node-only GB/Z 185.5 gateway query against a caller-configured endpoint with caller-supplied authentication.
v1.2.0 — Universal resolver: adapter architecture
- Fourteen adapters over four channels (well-known paths, the ARD
rel="ard"link, the robotsAgentmap:directive, and a DNS TXT lookup): adds ANP agent descriptions, UCP merchant profiles, the AID TXT record, and the two additional ARD surfaces to the original set. Listed in the official MCP Registry ascom.nessgate/nessgate.
v1.1.0 — Initial public release
- The neutral resolver.
GET /discover/{domain}reads whatever a domain publishes across the supported machine-discovery locations (ARD /ai-catalog.json, A2A agent card,llms.txt, RFC 9727 api-catalog, ai-info.json, OpenAPI, Open Resource Discovery, host-meta) and returns one normalized answer, with a link back to each source so an agent can read the domain directly. NessGate reads these; it does not define or replace them. - Embeddable library. A dependency-free resolver at
/resolver.mjsand on npm as@nessgate/resolver, running in browsers, Node, Deno, Workers, and agent runtimes with no runtime dependency on nessgate.com. The same lookup is available as thediscover_domainMCP tool at/mcp. - Open and neutral. Open specification, Apache-2.0 reference implementation, governed by the Charter: free forever, neutral, no accounts, no ranking, no lock-in, stores nothing.