Version history for envless-sdk, the Ruby client for the Envless API, published on RubyGems. Pin it for the latest coverage, security patches and type fixes. When a newer version is out, the client says so once on a terminal, with a link to this page.
The TypeScript SDK, @goenvless/sdk, has its own changelog, and so does the Python SDK. They cover the same API, and a change to one lands in the others.
Next release
Each list method takes only the options its route reads. An option the API ignored is now an ArgumentError for an unknown keyword instead of a silent no-op, so drop it from the call.
workspaces.listandproducts.access.listtakelimit:andoffset:;products.list,products.list_projects,keys.listandwebhooks.listaddsearch:andorder:;projects.listandenvironments.listaddproduct:as wellvariables.list,variables.list_history,versions.listandversions.list_entriestakelimit:,offset:andproduct:;invites.listtakessearch:;webhooks.list_deliveriestakesstatus:. Thelist_allanditerateforms follow theirlist- New:
members.list(role_id:)keeps only the members holding one role, androles.list(sort_by:)orders byname,updatedorcreated variables.get_by_id,variables.update_by_id,variables.delete_by_id,versions.getandversions.rollbackno longer takeproduct:, which their routes never readvariables.create,create_many,updateandupdate_by_idacceptisSecret:, and anupdatesentry passed tovariables.applymay carryname:to rename the variable in the same transaction
v0.0.1
Initial release. The Ruby twin of the TypeScript SDK, covering 100% of the public HTTP API: all 113 methods across 13 namespaces, under their TypeScript names in snake_case. A parity check replays every method against the requests the TypeScript SDK records, with no options, with every option set and with the body passed as keywords, and fails the build on any difference in the request, the retries, the errors or the result.
Client
Envless::Client.newwith a reader for every namespace:me,workspace(withworkspace.domain),workspaces,products(withproducts.access),projects,environments,variables,versions,members,invites,roles,keys,webhooksEnvless.variablesand every other namespace reach a shared client built fromENVLESS_TOKENandENVLESS_API_ENDPOINTthe first time one is touched, andEnvless.init(...)configures it once at startup.Envless.clientreturns it andEnvless.reset_clientdrops it- A request body goes in as keyword arguments or as one Hash, keyed by the API's own field names, and every result is a Hash with Symbol keys. Options are snake_case keywords:
product:,limit:,offset:,search:,order:,status:,reattempt:, andtimeout:on every method client.raw.request(path, method:, query:, body:)reaches an endpoint no method wraps yet, with the client's key, base URL, timeout and retries- Bring your own
adapter:, anything that responds tocall(request), for a different HTTP library or for tests. Redirects, retries and the deadline stay in the client - A client is frozen once built, safe to share between threads, and keeps a pool of kept-alive connections that it rebuilds after a fork
Pagination
- Every collection has
listfor one page as anEnvless::Page,list_allfor everything as an Array, anditerate, which yields to a block or returns a lazyEnumerator - Secondary collections get their own trio:
products.list_projects,products.access.list,variables.list_history,versions.list_entries,webhooks.list_deliveries, each withlist_all_*anditerate_*forms - The walk ends on
hasMorebeing false or an empty page, and advances by the items actually received
Errors
Envless::ApiErrorcarries the stablecodeplusstatus,message,resource,field,request_idandretry_after_seconds, with predicates for the common branches:auth?,scope_missing?,validation?,needs_upgrade?,not_found?,conflict?,rate_limited?Envless::NetworkErrorfor transport failures, withtimeout?when the deadline passed.Envless::DecryptionErrorandEnvless::WebhookVerificationErrorfor the crypto and webhook helpers. All of them inheritEnvless::Error, and a mistake in the call itself raisesArgumentErrorbefore anything is sentGET,HEAD,PUTandDELETEare retried on408,429,500,502,503and504with exponential backoff capped at 30 seconds, honouringRetry-After.POSTandPATCHare never retriedtimeoutis a hard deadline for each attempt, redirects and the response body included.0turns it off- A variable name is checked before anything is sent, and an unusable one raises the same
Envless::ApiErrorthe API would, withrequest_idset tonil
Encryption
encrypt_valueanddecrypt_value, byte-for-byte compatible with the TypeScript and Python SDKs, the CLI, the dashboard and@goenvless/env: AES-256-GCM under a PBKDF2-SHA-256 key with 200,000 iterations and the workspace salt.v1:andv2:<iterations>:envelopes both decryptderive_workspace_keyandimport_workspace_keyreturn anEnvless::WorkspaceKeythat never prints its bytes, forencrypt_with_keyanddecrypt_with_keyacross a batchciphertext?,passphrase_strength,variable_name_validationandENCRYPTION_PARAMETERSrotate_workspace_passphrase(client:, ...)re-encrypts an environment's live variables and its version history, and lists infailuresany version entry whose encrypted default cannot be rewritten because the entry's own value is not ciphertext- Plaintext, passphrases and workspace ids must be valid UTF-8, and a raw key goes in only as 32 binary bytes, so binary data or a passphrase passed by mistake raises
ArgumentErrorinstead of producing ciphertext nothing else can read
Webhooks
verify_webhook_signature(payload:, headers:, secret:)checks the HMAC-SHA256 signature in constant time and the timestamp drift, then returns the parsed event. It takes the raw body and headers from a Hash in any case, a Rack env or Rails'request.headers
Runtime
- Ruby 3.2 or newer, with no runtime dependencies:
Net::HTTPandOpenSSLfrom the standard library - RBS signatures for every method, body and response, with a manifest that declares the standard libraries they use, so
library "envless-sdk"in a Steepfile is all a project needs - Every request carries
User-Agent: envless-sdk-ruby/0.0.1