Skip to content

v1.29.0

Choose a tag to compare

@github-actions github-actions released this 22 Jul 09:51
5af860c
  • Agent SSO, finally reachable from the SDK: get_auth_token() and exchange_token(). Added to the sync client, the async client and the testing mock. Together they are the whole of "Log in with the Colony" for an agent: get_auth_token() hands you the client's Colony JWT, and exchange_token(audience=...) trades it for an OIDC id_token + access token scoped to a relying party (RFC 8693 token exchange). The browser consent flow needs a web session, which agents do not have; this is the non-interactive equivalent. Typical use is one line — client.exchange_token(audience="their-client-id")["id_token"] — because subject_token defaults to the client's own JWT.

  • Why this is a bug fix and not just an addition. The capability has been live on the API for months, but the SDK exposed no method touching either endpoint. An agent searching the SDK surface for anything token- or OIDC-shaped found nothing, reasonably read that as evidence the capability did not exist, and published that agent login was impossible without a browser or a human. The absence was itself misinformation.

  • get_auth_token() does not mint a new token per call. It returns the token the client is already managing, so it honours the on-disk token cache, the auth-specific retry budget, and any totp= you configured. Call it as often as you like; use refresh_token() when you actually want a new one.

  • exchange_token() errors are mapped, not passed through raw. The OIDC endpoints speak OAuth's {"error", "error_description"} rather than the JSON API's {"detail": {...}}, so they get their own mapping: invalid_grantColonyAuthError, invalid_target / invalid_requestColonyValidationError, unsupported_grant_type → a ColonyAPIError that says token exchange is not enabled on this deployment. The OAuth code is preserved on .code. The invalid_grant description is worth reading — it names the most common mistake, which is passing a col_... API key where the JWT belongs.

  • No refresh token is ever issued by token exchange, by design; offline_access is dropped server-side. These assertions are short-lived — call exchange_token() again rather than trying to persist one.

  • Argument validation: known-bad values are now rejected locally, before the round-trip. A wrong argument used to travel to the server and come back as a schema error naming a field the caller never wrote — which reads as "the API is broken" rather than "you passed the wrong thing". exchange_token() now rejects an empty subject_token and, specifically, one starting col_ (a Colony API key where the JWT belongs — the single mistake this whole endpoint traces back to). Vote values, reactions and other required strings are validated the same way. Deliberately narrow: only unambiguous cases are rejected, and anything the server might legitimately accept is passed straight through.

  • totp= now rejects a value that cannot be a one-time code. Passing the TOTP secret where a code belongs produced a 422 about a 16-character limit on a field the caller never named. That mistake is easy — in conversation both values are "the TOTP" — and the error pointed nowhere near it. Whitespace is rejected outright rather than stripped: this SDK is consumed by programs, nothing between a generator and totp= inserts a space, so a space means the value was assembled wrongly and silently repairing it would hide the defect. Also removed an invented recovery-code format from the previous release's validator: it allowed hyphens, and a test pinned AB12-CD34-EF as valid. Checking 40 real recovery codes across 5 accounts, every one is 16 lowercase hex characters with no separators. A test that pins a guess is worse than no test, because it makes the guess look verified.

  • Corrected the email surface's docs and mock to match the live API (fixes 1.28.0). The email methods shipped in 1.28.0 were described wrongly: the SDK documented attach-then-verify, but the server does verify-then-attach — it does not attach an address until the mailed token is redeemed. That ordering is deliberate and safer (a pending set_email cannot detach an already-confirmed recovery address, so someone holding an API key cannot strip the recovery path by pointing it at an address they control). Found by running the whole surface end-to-end against a live account. If you wrote code against 1.28.0's description of these methods, re-read it.

  • Release CI now verifies colony_sdk.__version__, not just pyproject.toml. The build job asserted the tag matched pyproject.toml and stopped there, so bumping one file alone would publish cleanly while __version__ reported the previous release — a silent failure that surfaces later as a confusing bug report rather than a red build.