Changelog
Every AgentGate release and what changed in it.
Changelog
AgentGate follows semantic versioning from 1.0.0. The SDK wire protocol and public APIs are versioned separately (/v1/..., /sdk/v1/...).
Unreleased
- AgentGate is a hosted service: the self-hosted-binary offer and open-source positioning are gone from the site, docs, pricing and terms; the operations guide is an internal document; the pricing page has one plan (hosted pilot).
- Hosted instance operations: its own auto-renewing Let's Encrypt certificate (was the manually renewed wildcard), nightly backups encrypted to the operator's age public key with a passed restore drill, and an external uptime probe with alerting (
scripts/ops/, docs/operations.md).
Changed
- Production rule set
prod-1.1.0-count(deploy/rules.count-mode.json): the instrument checks enforce. A submission that solved the proof of work but never ran the page's instrument program gets the visible check (instrument_missing) and a wrong answer is challenged (instrument_invalid, overriding its block default until Firefox and Safari are measured). Underprod-1.0.0-countboth were counted, so such a script still got tokens in enforce mode.instrument_slow,sdk_late_init,agent_class,env_automation,env_cdp_low_pointer,env_cdp_stealth,env_agent_domandtls_non_browserstay in count mode until measured on real people (docs/backlog.mdE1). probe_public.py:fabricated_telemetryexpects428in both modes. The probe runs against a local instance withBASE_URL(plusADMIN_BASE_URLandADMIN_KEY), writingevaluations/local-probe-*.json.TestShippedCountModeRulesLoadAndBlockpins the count-mode override set and checks, through the server, that a scripted submit without the instrument program is challenged.
Added
- Legal pages, published as drafts for the owner's review:
/docs/terms(early access terms of service) and/docs/acceptable-use, in a new Legal docs section together with the privacy notice (/privacystill redirects). The footer's Legal column, the signup form's consent line and the pricing FAQ ("Is there an SLA?") link to them.
2.0.0 — one React app
Every page is now one React/TypeScript app (web/, embedded in the binary): the marketing site, the docs, the account pages, the customer console and the operator dashboard. The server renders no pages any more except the human handoff page.
Changed
/,/pricing,/roadmap,/changelog,/demo,/hack,/docs/*,/signup,/login,/reset[/<token>],/invite/<token>,/app/*and/dashboard/*serve the app'sindex.htmlwith the page's title, description, canonical URL and a no-JavaScript fallback filled in by the server. Unknown paths get the app's not-found page with status 404.- The app reads JSON from
/api/site/*,/api/docs/*and/api/demo/form; its code is under/assets/. A reverse proxy must pass/assets/,/api/and/fonts/(seenginx-agentgate.conf). /appand/dashboardanswer the app directly instead of redirecting to/app/and/dashboard/; old hash links (/app/#/sites/x) still work. The agent prompt links to/app/sites/<key>and/dashboard/sites/<key>.- The handoff page is styled by its own
/handoff.css. make release-checkruns the web app's end-to-end journeys in real Chrome (web/scripts/e2e.mjs --serve).
Removed
- The
WEB_UIsetting and the server-rendered pages:site/*.html,page.html,hack.html,/site.css,/site.js,/docs.css,/docs.jsand/account.js. - The separate operator dashboard app (
dashboard/,make dashboard,/dashboard/assets/*and/app/assets/*).
Unchanged: the /v1 APIs, /docs/<slug>.md, /docs/search.json, the OpenAPI files, /llms.txt, /llms-full.txt, /agent.md, /gate.js, /sdk/v1/*, /.well-known/security.txt, /privacy and the old /docs/quickstart* redirects.
Added
- Testing keys for automated tests and CI (
docs/testing.md): site keyssite_test_always_pass,site_test_always_fail,site_test_force_interactiveand secretsags_test_always_pass,ags_test_always_fail,ags_test_token_spent. Any origin, no detection, nothing stored; test tokens (agr_test_…) are rejected by real secrets and the gateway, and test secrets reject real tokens.
Fixed
/v1/gateway/checkspends a browser receipt only when it admits the request, in one transaction with the allow event. A block or challenge after a valid receipt, or a failed event write (503 in enforce mode), no longer consumes it, so an honest retry succeeds.
1.0.0 — 2026-09-25 — market readiness
The product release: browser SDK and siteverify (Turnstile side), gateway and WAF-style rule language for agents (AWS WAF side), operator dashboard, model lifecycle and operations. Per-item status and known limits are in docs/market-readiness-design.md §8. Unmeasured detectors ship in count mode.
Added
- Durable state: SQLite store (pure Go, WAL, migrations), sites with origins, actions, routes and monitor/enforce mode, hashed backend credentials with rotation, persistent signing keys with rotation (
agentgate keys), a sharedEvaluatedecision interface, decision events with daily aggregates and retention, restart-safe replay protection, and a route registry. - WAF rule language: IP sets, country, ASN, cloud, Tor, header/query/path/ method/JA4/verified-agent statements with and/or/not and scope-down; rate-based rules keyed on IP, /24, ASN, session, agent, header or label; versioned managed rule groups (
agentgate-core,-agents,-bot-control,-anonymity) with overrides; immunity time; custom responses. - Threat intelligence: IP→ASN/country (iptoasn, public domain), cloud and datacenter ranges, Tor exits, verified crawler IP ranges and reverse DNS, decaying IP reputation.
- Agent-native features (A1–A4; README "Agent-native features",
docs/quickstart-agents.md): - Per-agent site policy: allowed actions, per-site quotas, prices, a crawler price and handling of unverified agent claims. Enforced through labels and default rules. Priced actions answer402with Cloudflare pay-per-crawl headers (crawler-price,crawler-exact-price,crawler-max-price,crawler-charged,crawler-error). This is signalling only. - Human handoff. A challenged agent session gets a five-minute, single-use URL and an inline SVG QR code. The person completes the check on their own device, and the agent pollsGET /v1/handoff/{id}for the pass. Adds migration 0030 and the dependencygithub.com/skip2/go-qrcode(MIT). - Declared agent tools at/.well-known/agentgate-tools.jsonand/v1/agent-tools/{siteKey}. The tool shape is MCP's, and it maps onto WebMCP'sregisterTool. - Signed decision receipts: anAgentGate-Receiptcompact JWS (EdDSA/Ed25519). It verifies with the JWKS at/.well-known/agentgate-keys.jsonand throughPOST /v1/receipts/verify. - Operator login (D2):
POST /v1/admin/loginexchangesADMIN_KEYfor an HttpOnly SameSite=Strict session cookie (hashed inadmin_sessions), CSRF token on mutations, login rate limits;X-Admin-Keystill works. - Admin API (D1) with an OpenAPI 3.1 contract (
docs/openapi-admin.yaml): sites, mode switch, credentials (reveal once, rotate, revoke), per-site rule sets and per-rule count/enforce overrides with validation, metrics, request sources, decisions with cursors and filters, decision detail, operator labels and label export. Site scope on every lookup; config changes audited with actor and diff. Migrations 0040–0042. - Operator dashboard (D3) at
/dashboard/: React/TypeScript, embedded build, Overview, Sites, Visitors, Decisions, Rules and Labelling views, light and dark.make dashboardrebuilds it. - Private Access Tokens (RFC 9577/9578 type 2, blind RSA): challenge header, token verification, issuer directories (Cloudflare and Fastly demo issuers verified),
agentgate:device:attestedlabels; all RFC 9474/9577/9578 test vectors pass. The skip-the-check rule ships ascount. - Gateway (G1–G4):
GET /v1/gateway/check, authenticated by a site backend credential, with trustedX-Original-*metadata, nginx-style path normalisation, receipts, clearances and Web Bot Auth (content-digest only where the route requires it) feeding the rule engine; 204/401/403/503 with stableX-AgentGate-Reasoncodes and monitor-modewouldDecision. Machine routes use rate policy, identity and rules only. nginxauth_requestconfig (docs/nginx/agentgate.conf) tested against a real nginx; Gonet/httpand Express middleware with body digest checks and asiteverifyhelper;docs/quickstart-gateway.md. Receipts and clearances go through areceiptVerifierinterface that fails closed until the SDK workstream's implementation is plugged in.
- Model lifecycle (M1–M4): per-site opt-in capture of model feature vectors (numbers only) with per-site retention;
decision_labels(shared contract with the dashboard) andPOST /v1/admin/labels;agentgate features export(JSONL,agentgate.features.v1); the probe matrix labels and exports its decisions;train_agent.py/train.py --realretrain on labelled rows with real/synthetic weighting, per-cohort held-out metrics and versionedmodels/*.vN.jsonfiles with metadata; candidate models scored in shadow (agentgate:shadow:*,shadow_*scores,<kind>_candidateversions),GET /v1/admin/models/{kind}/compare, promotion and rollback recorded inconfig_changesand persisted inmodel_registry. Migrations 0050, 0051.
Changed
train_agent.pyno longer overwritesagent_model.jsonor the parity fixture by default;train.pywritesmodels/model.vN.jsoninstead ofcandidate-model.json.- Every decision event, including refusals before evaluation, records the active model versions.
- Operations (O1–O5): private Prometheus
/metricsonMETRICS_ADDR(off by default, loopback only; bounded labels: route templates, site IDs, rule names);/healthzliveness with the version and/readyzreadiness (store, migrations, key store; optional checks degrade) with bounded timeouts;agentgate version,help,healthcheck,backup --out(onlineVACUUM INTO+keys.json, 0600, digests) andrestore --in; Dockerfile (distroless nonroot, read-only root),docker-compose.ymlwith optional Jaeger,Makefile(build, test, fuzz-short, vuln, release with ldflags version and SHA256SUMS);cmd/loadtestandprobes/pow_bench.mjswith measured limits indocs/operations.md; release checklist indocs/release.md. OTEL_TRACES_EXPORTER=nonedisables span export (the container default).
Changed
agentgate.service: hardened (empty capability set, syscall filter,ProtectKernel*,RestrictAddressFamilies,UMask=0077),Restart=alwayswith a start limit;LISTEN_ADDRdefault in the unit.install-first.shwaits for/readyz, enables the metrics listener and checkskeys.json;upgrade-binary.shtakes an online backup first and rolls back the binary, then the state, if the new build is not ready./healthzanswers JSON ({"status":"ok","version":…}) instead ofok.
Security
nginx-agentgate.conf(repository copy) also blocks/v1/admin/and/dashboard/publicly; the deployed server config is not changed yet.- Fuzz targets for structured fields, signature inputs, markdown, proof JSON and test signatures; fixed a NUL-byte placeholder leak and an off-site protocol-relative link in the markdown renderer.
- grpc upgraded to v1.83.2 (GO-2026-6443);
govulncheckclean. - Threat model and privacy notice.
0.3.0 — 2026-09-24 — detection floor and WAF-style rules
- Rules engine over labels: allow, block, challenge, drop, count; rule sets from
rules.jsonorPOST /admin/rules; every decision audited with labels. - Web Bot Auth per draft-ietf-webbotauth-httpsig-protocol-00: key directories, registries, per-agent quotas and replay namespaces, verdict labels; bot catalog.
- JA4 TLS fingerprint, header-shape and HTTP/2 fingerprints (direct TLS mode).
- Browser environment detectors, per-request instrumentation challenge, behaviour traces and a human/bot/agent model; signed test identity.
- Accessible "verify another way" alternative; probe matrix.
- Redesigned site; public testing policy moved to
/hack. - Deployed with unmeasured detectors in count mode.
0.2.0 — 2026-09-24 — invisible challenge
- Browser proof of work and interaction signals; press-and-hold check only when risky; soft per-IP limits; decision logging with scores and signals.
- Review fixes: signed agent requests bound to their body; shared addresses get the check before the content model; policy read under lock; form recovers from a failed check request; registry collisions rejected.
0.1.0 — 2026-09-24 — proof of concept
- Agent-aware form gateway with evaluation lab, idempotent submissions, rate limits, content model, public challenge, audit log and OTEL traces.