Repository navigation
Releases: latere-ai/pons
Release list
v0.4.3
v0.4.2
Added
- With
OTEL_EXPORTER_OTLP_ENDPOINTset, the server also exports the Go
runtime's metrics: memory, goroutines, GOGC, GOMAXPROCS and scheduling
latency, asgo.memory.*,go.goroutine.count,go.config.gogc,
go.processor.limitandgo.schedule.duration, through
latere.ai/x/pkgv0.106.0.
v0.4.1
Fixed
- A connector's answer cut by a time bound is a timeout, and one its caller
left is a cancel, however the cancelled read ends. A transport may report
a cancelled read as the end of the body: a body read past its request's
bound then came back whole and short, and a streamed answer ended by
PONS_STREAM_IDLE_TIMEOUT, or left by its caller, was recorded asok
where it is nowtimeoutorcanceled.
v0.3.0
-
Added: a list of connectors takes
owner, as a list of connections
does, and sends it in itsconnector.listquestion, so your
authorizer can let a service list one person's servers, for instance
to remove a closed account's, with a filter naming that person alone.
A list that names no owner asks as before. -
Added: one reason of a deny of
connection.usereaches the caller.
When your authorizer denies a use withkept_apart_from_google, for
a session that already used a connection you keep apart from this one,
Pons answers409 connection_not_connectedwith that reason in
details.reason, at the MCP and the forwarding address, so the
session can tell the person to start a new conversation. Every other
deny of a use is still404 connection_not_found. Send this reason
only for a connection the session holds. -
Added: MCP servers added by their address for others. The owner of an
added connector is the one your authorizer's allow of
connector.createnames, a string Pons gives no meaning: use one for
a person, one for an organization and one for the whole installation.
A list of connectors shows the added connectors of every owner the
allow's filter names, and a connect to another owner's connector asks
connector.readof it first, so an organization's members connect
the servers its administrators added when you let them read those
connectors. Under the owner policy an added connector stays its
owner's alone. -
Added: for your authorizer, the action
connector.update, asked by an
edit with the connector'sidandowner, and by a list once for each
owner on its page with thatownerand noid, to show how many
connections use each of that owner's connectors.connection.create
of a connect to an added connector sendsconnector_owner. The allow
ofconnector.createmay carry the limitvouched: true, which says
someone you trust looked at the server; send it for an administrator's
add alone. Roll your authorizer before this Pons: one built on
latere.ai/x/pkg/authz/serverthat does not knowconnector.update
answers it400, and an edit fails closed with503 authorizer_unavailable. Do not sendvouchedto a Pons before this
one: it does not know the key, and every add fails closed with503. -
Added:
PATCH /connectors/{id}changes an added connector in place,
holding from the next request on every replica with no restart: its
title,description,icon, tool marks,auth.scopes, a
vouched-for connector'sauth.client.secret, anddisabled. Its
name,kind,url,auth.typeand client id are
400 immutable_field. A connector turned off stays listed; a connect
to it is409 connector_disabled, a call through a connection to it
is409 connection_not_connectedwithdetails.reason
connector_disabled, and its connections and their credentials are
kept until it is turned on. A removal is still409 connector_in_use
while a connection uses it. -
Added: an add needs only the address.
authis optional on
POST /connectors: Pons asks the server with no credential, after
the authorizer's question and withinPONS_CREATES_PER_MINUTE, and
storesnone,oauthortokenfrom its answer, with the hint "API
key" for a server that takes a key. Anauththe answer does not
admit is422 auth_mismatch, and a server that does not answer as one
that can be connected is422 server_unreachable, with the status or
the failure and never the address. Every add now makes these
requests, so an address whose server does not answer can no longer be
added. -
Added: a server added by its address signs people in. Pons identifies
itself by a vouched-for connector's own client,auth.clientwith its
idandsecret, sealed and never answered; else by the connector's
client metadata document; else by registering at the server, which the
installation keeps per issuer and reuses for a second connector there.
A server whose authorization server does not say it sendsisssigns
in at/v1/callback/{key}, its issuer's own redirect address, which
refuses an answer meant for another server. An added connector's view
saysauth.client(own,documentorregistered),disabled,
vouched, and, for its own client,auth.redirect_uri, the address to
register that client with. -
Added:
GET /connections/{id}/tools, the tools a connection's server
lists through it, with the effect the connector's marks give each and
whether they hide it, asked each time and recorded as no call. And
connectionson an added connector's view, to a caller your
authorizer lets change it: how many connections of every owner use
it. -
Added:
PONS_MAX_ADDED_CONNECTORS, 50 by default: how many connectors
one owner may add. One more is409 connector_limit, and other
owners' adds go on. -
Changed: the store's schema moves to version 2, which adds columns to
connectors. It runs at start as every migration does; a binary
before this one refuses a schema at version 2.
v0.2.0
-
Added: the MCP address. A connection of kind
mcpis used at its
address,/v1/connections/{id}/mcp, as a Model Context Protocol
server over streamable HTTP: a client sends one JSON-RPC message per
POSTwith its own token, and Pons forwards it to the connector's
urlwith the connection's credential added, streaming the answer
back event by event.GETandDELETEreach a server of a revision
from 2025-03-26 to 2025-11-25, whoseMcp-Session-Idpasses both
ways, so any replica serves a session. Pons reads only the message's
methodand, fortools/call,params.name; a body that is not one
JSON object, a duplicate or differently casedmethod,paramsor
params.name, or anMcp-MethodorMcp-Nameheader that differs
from the body is400 invalid_request.WWW-Authenticate,
Set-CookieandLocationnever pass back, and a redirect is
502 connector_unavailablewith the reasonredirect_refused. -
Added: for your authorizer,
connection.useat the MCP address sends
connection_kindmcp,methodthe protocol method (GETor
DELETEfor an earlier revision's request, none for a reply), and for
tools/callthetooland itseffect,readwhen a
tools.read_onlyglob of the entry matches it.read_onlyand
toolsholdtools/callalone, so a list of tools passes, and a call
of a tool the entry markshiddenis refused with403 forbiddenon
tool. An authorizer that allowsconnection.usetoday without
looking at the kind allows these calls too, every tool included, so
answer them with the limits you want before rolling this Pons. -
Changed: a key for a connector of kind
mcpis tried before it is
kept, by listing the server's tools, and for a server of an earlier
revision by its handshake, a list in its session and the end of that
session; a key the server refuses is422 credential_refused, and a
server that does not answer the list with a2xxis
422 connector_unreachable. Before, such a key was stored untried. -
Changed: the first request of discovery for a connector of kind
mcp
that signs people in is the current revision'stools/listwith no
credential, as the protocol has a client make it, in place of aGET. -
Changed:
PONS_MAX_REQUEST_BYTES, 4 MiB by default, bounds the
message a caller sends to an MCP address; a larger one is
413 request_too_large, whether the connection exists or not. -
Changed: a disconnect, and the sweep of a sign-in that ran out, revoke
a credential at its service only when no other connection holds the
same grant: the same issuer, client id andaccount, of any owner, a
sign-in waiting for its confirm and a reconnecting connection's own
credential included. A service may end every token of a grant at one
revocation, as Google does, so before, disconnecting one of a person's
connections of one account could end the others. A skipped
revocation is logged withreasongrant_heldand thecountof
holders, and never the account. A connection whose account was not
read is revoked at its own disconnect, as before; giveaccountto an
entry whose service ends whole grants. -
Changed: the Google entries, Gmail, Google Calendar and Google Drive,
giverevoke_url: https://oauth2.googleapis.com/revoke. Add it to
yours: the disconnect of a
person's last connection of a Google account then removes the
installation's access in that Google Account, while their other
connections of it keep working until then. Keep the three on one
client: Google ends the grant of the whole project, and Pons compares
the client. -
Changed: protected resource metadata that names an authorization
server at an address that is nothttps, or whose host is an IP
address, is422 connector_unreachablewithdetails.reason
scheme_not_httpsorhost_not_a_name, as an issuer or an endpoint
of the metadata already was. Before, it was422 sign_in_unsupported
with the reasonauthorization_servers.
v0.1.2
-
Added: the limit
requests, with which an authorizer holds a caller
to some of a service's API: each entry is a method and a path pattern,
such asGET /**orPOST /repos/*/*/issues, where*is one path
segment and a last**the rest of the path. A request to a forwarding
address that no entry names is answered403 forbiddenwith the reason
requests, so the caller learns the request is not allowed. Before, an
authorizer could only deny such a request, which a caller reads as a
connection that is not there. In the public packageauthorizer,
LimitshasRequestsandAdmitsRequest. An older Pons refuses an
allow that namesrequestsas limits it cannot read, so roll Pons
before an authorizer that sends it. -
Fixed: the forwarding address carries only the methods an API is
called with,GET,HEAD,OPTIONS,POST,PUT,PATCHand
DELETE. Any other method,TRACEandCONNECTamong them, is
refused with400 invalid_requestbefore the connection is loaded,
as the API documentation already stated. -
Added: a catalog entry's
authorize_urlmay carry a query, for
members a service needs on the authorization request, such as Google's
access_type=offline, which the sign-in sends beside its own. A query
that names one of the sign-in's own members,response_type,
client_id,redirect_uri,code_challenge,code_challenge_method,
state,resourceorscope, is refused when the catalog loads; such
a member was replaced by the sign-in's before. The public package
catalognames them asAuthorizationMembers. Spec 015 gives catalog
entries for Gmail, Google Calendar and Google Drive. -
Changed: the question to the authorizer names a connection's kind,
mcporhttp, asconnection_kind, and a connector's as
connector_kind. Both were sent askind, a name the shared envelope
keeps for the resource itself and drops from the fields, so no
authorizer ever received them. In the public packageauthorizer,
FieldKindis replaced byFieldConnectionKindand
FieldConnectorKind, andFieldIDis removed andidleaves
Fields, since the id is the envelope'sresource.id:SendsID
reports whether an action sends one. Code that named either constant
needs the new names. An authorizer that read the kind of the resource's fields
read nothing before, and reads the new names now. -
Changed: a push that names a ref outside the refs its caller may update
is refused the way a git host refuses one, so git prints the reason.
It was answered403with a JSON body, of which git printed only
RPC failed; HTTP 403. Now git prints, for example,! [remote rejected] HEAD -> main (only branches under refs/heads/agents/ may be pushed by this caller)and exits non-zero. The answer is200with a
report in which every ref of the push is refused, the pack is read to
its end first so git reads the answer of a large push too, and nothing
of the push reaches the connector. The call record staysdenied. -
Fixed: a push larger than git's post buffer, 1 MiB by default, lands
through a git address. git sends such a push after a probe, a request
that names no ref, and Pons answered the probe400 invalid_request,
so git stopped withRPC failed; HTTP 400.
v0.1.1
- Fixed: the release pipeline attests the image's bill of materials and
provenance only while the repository is public, since GitHub keeps
attestations for a private repository only on a higher plan. v0.1.0
published nothing for that reason.