Releases: soapbucket/sbproxy
v1.1.0
Changelog
All notable changes to SBproxy v1.x. Versions before v1.0 shipped as the
Go implementation and now live in the archived
soapbucket/sbproxy-go
repository.
[Unreleased]
Work that has merged to main since the v1.1.0 tag and is queued for
the next version cut. No promises about backward compatibility for any
of the new YAML fields below until the version that ships them.
[1.1.0] - 2026-06-06
First minor release on the Rust v1.x line. This release carries
breaking changes to the MCP tool-access policy (now closed-by-default
and principal-aware); read the Breaking section and
docs/migration-mcp-rbac.md before upgrading. It also ships 66 native
AI providers behind one OpenAI-compatible API.
Breaking
-
MCP default-deny:
ToolAccessPolicyflipped from
open-by-default to closed-by-default. An unknown caller (no
matching ACL rule) is denied every tool. An emptyallowed: []
list under an ACL rule means "deny all", not "allow all".
Operators who want the legacy behaviour adddefault_allow: true
on the origin's MCP action. The legacykey_permissions: { key: [tools] }
shape is gone; rewrite to the principal-awaretool_access[]
selector list. Seedocs/migration-mcp-rbac.md. -
MCP principal-aware ACL:
ToolAccessPolicynow
carriestool_access[]rules withprincipals[]selectors
(virtual_key,sub,team,project,user,role,
tenant_id) plus anallowed[]tool list. The legacy
key_permissions: HashMap<String, Vec<String>>map is removed
along withToolAccessPolicy::is_tool_allowed(key, tool); the new
surface ispolicy.check(&principal, tool) -> ToolAccessDecision
andpolicy.filter_tools(&principal, &tools).tools/listnow
filters by RBAC against the inbound principal (the legacy schema
leaked tool names throughtools/listeven when the gate would
deny the matchingtools/call). A newtool_quotas[]table
enforces per-tool sliding-window quotas keyed on
(tenant_id, principal_id, tool_name). See
docs/migration-mcp-rbac.md.
Added
-
66 native AI providers behind one OpenAI-compatible API. The
embeddedai_providers.ymlregistry ships 66 providers (up from 43),
adding Hugging Face Inference, GitHub Models, Vercel AI Gateway,
Nebius, Baseten, Lambda, FriendliAI, Scaleway, Nscale, DigitalOcean
Gradient, OVHcloud, Inference.net, kluster.ai, OpenPipe, Writer,
Upstage, Aleph Alpha, MiniMax, Volcengine Ark (Doubao), Tencent
Hunyuan, Baidu Qianfan (ERNIE), StepFun, and Mixedbread. The catalog
is plain YAML and operator-extensible at runtime via
proxy.ai_providers_file; themodelfield passes through to the
upstream, so any model a provider serves is reachable without
per-model config. The "200+ models" reach is native (bring your own
keys); OpenRouter is one provider among the 66, not a dependency. See
docs/providers.md#extending-the-provider-catalog. -
Session ledger from live MCP traffic. A new top-level
session_ledger:block makes SBproxy emit the canonical
session-ledger-v1run record (shared with mcptest) from its
tools/callpath: oneheaderper session, then onetool_call
record per call carryingsession_id, a zero-basedhop_index, the
bare tool name and server, redactedparams/result, an error
flag, and the round-tripduration_ms.sink: logging(default)
emits each record as asession_ledgertracing line;sink: file
with apath:appends NDJSON. Off unlessenabled: true; when off
the tool-call path pays only a single atomic load. Payloads are
redacted with the same secret-stripping the access log uses. See
docs/mcp.mdandexamples/mcp-federation/sb.yml. -
Structured-log schema v2 (
SCHEMA_VERSION = "2"). Three changes
land together so downstream tooling can read them in one swing:
optionalsession_idanduser_idtop-level fields parallel the
RequestEventenvelope (cross-surface JOIN no longer relies on
request_idalone); the field-key redaction marker is normalised
to[REDACTED:<NAME>]everywhere (was<redacted:name>in v1) so
the schema-v1 layer matches the existing PII-rule replacement
shape; the schema bump is additive on the field set (a v1 reader
parsing a v2 line keeps working because every new field is
skip_serializing_if = Option::is_none). Marker normalisation is
a string change; downstream tooling that greps for the old
<redacted:...>form must update. -
Phase-timing breakdown on the access log + new
sbproxy_phase_duration_secondsPrometheus histogram. The
access log carriedlatency_msend to end and that was it; an
operator looking at a slow request could not tell from the log
whether the time went to the auth provider, the upstream, or a
response transform. Three new optional fields land on every
AccessLogEntry:auth_ms(request_start → auth provider
returned),upstream_ttfb_ms(request_start → first upstream
response byte),response_filter_ms(first upstream byte → end
ofresponse_filter). All three areOption<f64>and
serde-skipwhen None, so origins that short-circuit (cache
hit, auth deny) keep compact lines. The same observations also
feed a newsbproxy_phase_duration_seconds{phase, origin}
histogram with buckets identical to
sbproxy_request_duration_secondsfor cross-cut dashboards. See
docs/access-log.mdanddocs/metrics-stability.md. -
Nine standard HTTP fields on the access log:
host,query,
protocol,scheme,user_agent,referer,upstream_status,
response_content_type,response_content_encoding. The log
was missing the canonical fields most HTTP access-log consumers
expect (Apache, NGINX, Envoy, the cookie-cutter ELK pipeline).
hostis the client-supplied Host header (distinct from
origin, the matched virtual-host pattern);upstream_status
is the upstream's response code when the proxy rewrote the
status the client sees. All nine areOption,serde-skipwhen
not applicable. Promoted from the generic header allowlist
because nearly every analytics consumer wants them. See
docs/access-log.md. -
Opt-in OpenTelemetry metrics mirror alongside the canonical
Prometheus surface. Newtelemetry.export_metrics: true
(withtelemetry.metrics_interval_secscadence, default 30s)
installs an OTelMeterProviderthat ships observations to the
same OTLP collector the trace pipeline targets. The first two
mirrored instruments aresbproxy.phase.durationand
sbproxy.request.duration; record-paths fall back to OTel's
global no-op meter when the export is off, so operators pay
nothing for the mirror unless they opt in. The Prometheus
surface remains canonical; this is for operators who already
aggregate via Mimir / Datadog / Honeycomb and want to skip the
Prometheus scrape. -
OIDC Relying-Party stack shipped end to end.
/oidc/callback(auth-code + PKCE + sealed session cookie)
plus the helpers + config wiring for
/.well-known/openid-configurationdiscovery, refresh-token
rotation, RP-initiated logout at/oidc/logout, userinfo →
X-Auth-*trust headers, an optional server-side session store
(in-memory + KV-backed redb/file/Redis) for targeted revocation.
Seedocs/configuration.md§ OIDC auth. -
OpenAI Apps SDK / MCP Apps (SEP-1865) compatibility.
Gateway-side_meta.mcpAppspassthrough for tool definitions,
params.audit.causeplumbing ontools/call, and a typed
validator set (apps.template_declared,apps.iframe_sandbox,
apps.csp_present,apps.cache_metadata) usable by sbproxy,
the enterprise extension, and any CI gate over the
sbproxy-pluginsurface. -
Web Bot Auth full conformance, publish + sign sides.
SBproxy now publishes its own JWKS-shaped
directory at/.well-known/http-message-signatures-directory
and a Signature Agent Card at
/.well-known/web-bot-auth/agent-card(opt in via
web_bot_auth_publishper origin). New
sbproxy-middleware::signatures::MessageSignatureSigner
primitive signs outbound requests per RFC 9421, round-trips
through the existing verifier. Seedocs/web-bot-auth.mdand
examples/web-bot-auth-publish/. -
Three previously-undocumented OSS policies now have docs +
runnable examples:object_authz(BOLA + BFLA with
enumeration detection),content_digest(RFC 9530 request-body
verification),agent_budget(per-agent semantic rate limit).
Seedocs/object-authz.md,docs/content-digest.md,
docs/agent-budget.md. -
Discoverable FAQ.
docs/faq.mdcovers install, common
401 causes, OIDC minimal config, log levels, OSS-vs-enterprise
scope, and pointers into the rest ofdocs/. Wired into
docs/README.mdunder "Getting started". -
Explicit SIGINT/SIGTERM handling with a structured shutdown
event and a 30s default drain budget. Pingora's
Server::run_foreveralready trapped SIGTERM and SIGINT, but
the proxy emitted no operator-facing log line on receipt, so a
pod eviction ordocker stoplooked the same as a crash in the
log stream. This change subscribes to Pingora's execution-phase
broadcast and emitsshutdown_signal_received,
shutdown_grace_period, andshutdown_completetracing events
with the resolved grace budget. The Kubernetes operator
(sbproxy-k8s-operator) now installs the same SIGINT/SIGTERM
handlers viatokio::signal::ctrl_cand
tokio::signal::unix::signal(SignalKind::terminate()); before
this change the operator relied on the orchestrator SIGKILL at
terminationGracePeriodSeconds. The drain budget is the new
SBPROXY_SHUTDOWN_GRACE_MSenv var (or--shutdown-grace-ms
CLI flag) which defaults to 30000ms, matching Kubernetes'
defaultterminationGracePeriodSeconds. The legacy
SB_GRACE_TIME/--grace-time(seconds) still works and
takes precedence when expli...
v1.0.1
Changelog
All notable changes to SBproxy v1.x. Versions before v1.0 shipped as the
Go implementation and now live in the archived
soapbucket/sbproxy-go
repository.
[1.0.1] - 2026-05-04
Patch release. No runtime behavior changes.
Fixed
- Container image publish: the
release.ymlworkflow's docker
prepare step extracted the flat-layout tarballs into/tmp/
directly, which tripped a sticky-bitCannot utimeerror on the
archive's./entry and causedghcr.io/soapbucket/sbproxy:1.0.0
to never publish. Each platform tarball now extracts to a per-arch
staging dir before the binary moves into the docker context.
[1.0.0] - 2026-05-03
First Rust release of SBproxy on this repository.
What changed
- Implementation: SBproxy is now written in Rust on Cloudflare's
Pingora. The Go implementation that previously occupied this repo
(v0.1.0throughv0.1.2) has moved to
soapbucket/sbproxy-go,
preserved as thev0.1.2-go-finalbranch and tag, and is now in
maintenance-only mode. - Data plane: routing, AI gateway, MCP gateway, guardrails, security
policies, and scripting (CEL, Lua, JavaScript, WebAssembly) all ship
open source in this release. Seedocs/architecture.md
for the request pipeline shape. - Enterprise tier: see
docs/enterprise.mdfor
what enterprise adds on top of the OSS data plane and how to request
access.
Upgrading from v0.1.x (Go)
The internal config schema (schema-v1) is supported by both the Go
v0.1.x line and this Rust v1.x line, so existing sb.yml files
should compile unchanged. See MIGRATION.md for the
full upgrade path.
v1.0.0
Changelog
All notable changes to SBproxy v1.x. Versions before v1.0 shipped as the
Go implementation and now live in the archived
soapbucket/sbproxy-go
repository.
[1.0.0] - 2026-05-03
First Rust release of SBproxy on this repository.
What changed
- Implementation: SBproxy is now written in Rust on Cloudflare's
Pingora. The Go implementation that previously occupied this repo
(v0.1.0throughv0.1.2) has moved to
soapbucket/sbproxy-go,
preserved as thev0.1.2-go-finalbranch and tag, and is now in
maintenance-only mode. - Data plane: routing, AI gateway, MCP gateway, guardrails, security
policies, and scripting (CEL, Lua, JavaScript, WebAssembly) all ship
open source in this release. Seedocs/architecture.md
for the request pipeline shape. - Enterprise tier: see
docs/enterprise.mdfor
what enterprise adds on top of the OSS data plane and how to request
access.
Upgrading from v0.1.x (Go)
The internal config schema (schema-v1) is supported by both the Go
v0.1.x line and this Rust v1.x line, so existing sb.yml files
should compile unchanged. See MIGRATION.md for the
full upgrade path.
v0.1.2-go-final
Changelog
- d7e2c42 Bump dorny/paths-filter from 3 to 4
- db783e0 Bump github/codeql-action from 3 to 4
- e95ac44 Bump google.golang.org/api from 0.275.0 to 0.276.0
- b78e049 Merge branch 'main' into docs/readme-and-site-update
- 4697a27 Merge pull request #18 from soapbucket/rickcrawford-patch-1
- aed73ad Merge pull request #19 from soapbucket/docs/readme-and-site-update
- f17aa3b Merge pull request #21 from soapbucket/docs/readme-redesign
- 4bb5600 Merge pull request #22 from soapbucket/chore/add-notice-file
- 6266e36 Merge pull request #23 from soapbucket/dependabot/github_actions/github/codeql-action-4
- e21ec2c Merge pull request #24 from soapbucket/dependabot/github_actions/dorny/paths-filter-4
- 591b183 Merge pull request #25 from soapbucket/dependabot/go_modules/google.golang.org/api-0.276.0
- a222ebb Merge pull request #26 from soapbucket/chore/add-notice-file
- bb0c103 Merge pull request #27 from soapbucket/adding-new-features
- 66a0ff3 Merge pull request #28 from soapbucket/adding-new-features
- 4402d9e Merge pull request #29 from soapbucket/rickcrawford-patch-1
- c1a1ddf Merge pull request #30 from soapbucket/dependabot/go_modules/github.com/pires/go-proxyproto-0.12.0
- 8ec7700 Merge pull request #31 from soapbucket/dependabot/go_modules/modernc.org/sqlite-1.49.1
- dec9446 Merge pull request #32 from soapbucket/fix-ai-pool-circuit-concurrent-load
- 189096c Merge pull request #33 from soapbucket/adding-new-features
- 711a9cc Merge pull request #34 from soapbucket/chore/archive-notice-and-deps
- be2c630 Merge pull request #35 from soapbucket/chore/move-archive-notice-to-archive-repo
- 33f7303 Merge pull request #36 from soapbucket/fix/e2e-case18-wait
- d037fbf README cleanup
- bb4cebc Remove GitHub Discussions link from README
- 7c6e324 Rewrite README with feature-first, technology-agnostic messaging
- c296a85 chore(deps): bump github.com/pires/go-proxyproto from 0.11.0 to 0.12.0
- 9a9e61f chore(deps): bump modernc.org/sqlite from 1.48.2 to 1.49.1
- 454b282 chore(readme): move archive notice to soapbucket/sbproxy-go
- 539769e chore: add Go-archive notice + bump gomarkdown for CVE
- 3657f2a chore: add NOTICE file for Apache 2.0 third-party attribution
- 3444b15 chore: update e2e configs to use new security headers array and session key
- b9396c0 feat(go): implement all 111 IMPLEMENTATION-GO.md features (P0-P9)
- bb3c467 fix(ai): tune upstream pool and circuit breaker for concurrent load
- f323ee8 fix(e2e): scope wait to flood curls in case 18 + bound them with --max-time
- 4440bc5 fix(lint): simplify postServer declaration in SSE client test
- d1aeae0 fix(security): mitigate reflected XSS on /metrics endpoint
- 1d94b19 fix: resolve data race in mirror test and stripe pattern in secret warner
- e3d730d perf(transport): match upstream pool tuning to Pingora baseline
- eee11fa refactor: security_headers array format and session field rename
v0.1.2
Changelog
- fcff782 Change cloud hosting link to sbproxy.dev
- f5352ee Fix CI running on docs-only PRs
- 49c22e7 Fix CI skip for docs-only PRs (use step-level conditions) (#16)
- 393813e Fix Go version badge to match go.mod (1.25)
- d88aa8d Merge branch 'main' into feature-added-providers
- 3fe4610 Merge branch 'main' into fix-comparison-doc
- e3d1c77 Merge pull request #10 from soapbucket/fix-install-script
- d7ca471 Merge pull request #11 from soapbucket/feature-added-providers
- 59392fe Merge pull request #12 from soapbucket/feature-added-providers
- 4738c27 Merge pull request #13 from soapbucket/rickcrawford-patch-1
- c7833e9 Merge pull request #14 from soapbucket/fix/ci-skip-docs-only
- 79246a1 Merge pull request #15 from soapbucket/rickcrawford-patch-1
- 2c86051 Merge pull request #17 from soapbucket/fix-version
- 7f4d033 Merge pull request #8 from soapbucket/fix/readme-go-version-badge
- ebe88f4 Merge pull request #9 from soapbucket/fix-comparison-doc
- 73956cd Update README
- b391409 added providers
- af88581 fixed flaky test
- dac4c14 fixed race condition in test
- 0a5e9a9 fixed version
- d710844 moved codeql to build task
- ad57f12 set to pr only
- 679dd23 uddated ci to skip md file changes
- 5a31939 updated comparison
- b725592 updated docs
- 88467bc use user's bin dir