render_api 0.1.7
render_api: ^0.1.7 copied to clipboard
Unofficial Dart client for the whole Render REST API: services, Postgres, cron jobs, disks, env groups, metrics and more. 208 typed operations.
0.1.7 #
Findings from a security audit of this package.
- Path parameters are percent-encoded. They were interpolated raw into the
URL across all 208 operations, so
retrieveService(serviceId: '../owners')built/v1/services/../owners, whichUrinormalises to/v1/ownersbefore it is sent — an authenticated request to an endpoint the caller never named. A?in an id smuggled query parameters, and on adelete*operation the same trick reached a different resource entirely. This matters because a caller may be passing an id that arrived in a request. - The API key is no longer sent over plain
httpto a real host. The base URL is not always chosen by whoever writes the call:RENDER_USE_LOCAL_DEVplusRENDER_LOCAL_DEV_URLredirects every authenticated request from the environment.httpsis required, except on loopback, which is what local development actually is. - The example no longer writes secrets to disk. Its response cache
persisted every successful body to
SharedPreferences, including/env-vars, whose values on a real service are database URLs and API keys — while the token itself sat correctly in the keychain. Those responses are cached in memory only now.
Checked and found sound, so recorded rather than changed: Authorization is
not forwarded across a redirect to another host (verified against a live
redirect, not assumed); no exception carries the token; the package has two
dependencies.
0.1.6 #
- Every model type is now documented. 232 of them carried no
documentation at all, including
Service— the specification describes 26% of its own schemas, and the generator emitted a doc comment only where one existed. What operations do with a type is a fact the spec states; it just does not state it anywhere the type can see. Each model now says what returns it, what accepts it, and which types it appears inside. - Properties carry what the spec knows about them — format, default, range, length, pattern, and the wire name where it differs from the Dart one. Only a fifth have a description, but most have facts worth stating.
- Constructors,
fromJsonandtoJsonare documented, including whytoJsonmergesunknownFieldsback in. - No API change. Documentation only.
0.1.5 #
-
A long
Retry-Afterno longer looks like a hang. Rate limits were honoured without a ceiling: Render answersRetry-After: 51on the Postgres introspection endpoints, and retrying three times meant sleeping two and a half minutes in silence before surfacing anything. Measured, not guessed — the second call totop-queriesin a row is refused.RenderApiClient.maxRetryDelay(5 seconds by default) caps how long the client will wait. Past it the call fails immediately withRenderRateLimitException, whoseretryAftersays when it is worth trying again — a judgement the caller can make and a library cannot. Short waits are still retried as before. Raise it to wait longer, or setDuration.zeronever to sleep.
0.1.4 #
-
Every model keeps the JSON it was decoded from.
rawJsonis the very map the response decoded to — kept by reference, nothing copied, walked or re-encoded — andunknownFieldsderives from it the keys the specification does not declare. This is not hypothetical:GET /servicessendsautoDeployTriggeron every service and the spec never mentions it, so until now it was dropped on the floor with no way to reach it.toJson()merges those keys back, so fetching an object and sending it again no longer silently discards what Render sent but never documented. A model built in Dart rather than decoded has an emptyrawJsonand is unaffected. -
A response that does not match the spec no longer costs you the payload.
RenderDecodeExceptioncarries what actually arrived, decoded but untyped, along with the method and path. Previously a specification error meant the caller got nothing at all. -
getBandwidthSourcesworks. It never has. The spec declares an object wrapping adataarray, labels as an object and epoch-integer timestamps; the API returns the same array-of-series every other metric returns, keyed by atrafficSourcelabel oftotalorhttp. The correction lives intool/generate.dart, so the vendored spec stays a faithful copy of Render's and regeneration cannot undo it. -
A 429 now says which limit was hit. Postgres introspection —
listPostgresProcesses,listPostgresSizes,listPostgresTableScans,listPostgresTopQueries— is rate limited far more tightly than the metrics endpoints: two calls in a row were enough to trip it against a live database. The hint says so, and points atretryAfter. -
A 400 on a metric now says why. HTTP request and latency metrics are gated by the resource's instance plan: on the free tier Render answers
400 {"message":"query is not allowed for plan: Hobby"}, which reads like a malformed request and is not. CPU, memory and bandwidth are returned on every plan. Found against a live free service, not inferred from the spec — the parameter is optional there and nothing marks the endpoint as paid-only. -
hintFornow receives the response body, so a hint can key on what Render actually said rather than on the status code alone. Internal; no public API change. -
The library doc comment still described the package 0.1.0 was. It opened with "Covers the workflows surface", showed
render.taskRuns.run('my-workflow/sumSquares', …)— a facade removed before 0.1.0 shipped, so the snippet did not compile — andrawpointed at[workflows],[tasks]and[taskRuns]as though they existed. 0.1.1 fixed exactly this in the README and 0.1.2 fixed the description; the library comment pub.dev renders on the API page was missed both times.It now says what the package covers, and both snippets compile. Verified the way the last one should have been: by compiling them.
-
example/is now a Flutter app — a read-only dashboard over the workspace hierarchy, services, databases, workflows and metrics. The three command-line scripts moved todart_examples/unchanged; if you referencedexample/raw_smoke.dart, it isdart_examples/raw_smoke.dartnow.Documents three things every caller meets: the
<Thing>WithCursorwrappers, the hints on typed errors, and thatState,RouteandImagecollide with Flutter's own names. -
The README now says how to use this package from Flutter. Import it with a prefix —
as render, thenrender.Service— rather than hiding the colliding names: a prefix never needs revisiting when Render adds a schema, and it keepsrender.Statereachable instead of throwing it away. The snippet compiles; it was checked by compiling it.
0.1.3 #
- The
RenderApi()example said// reads RENDER_API_KEYwithout saying from where. Now// token from the RENDER_API_KEY env var, in the README and in the library doc comment pub.dev renders on the API page.
0.1.2 #
- Clean up README
- Corrected what this package is. Both the description and the README's
opening said it covered "workflows, tasks and task runs" — the description
duplicated
render_workflows, and neither conveyed that this is the whole REST API: 208 operations across 26 resource groups, of which workflows are three. Services, Postgres, cron jobs, disks, env groups, metrics, logs and the rest were invisible to anyone reading either. - The opening now points at
render_workflowsfor actually running tasks, so the two packages read as complementary rather than overlapping.
0.1.1 #
Documentation and packaging; no API changes.
- The README's usage example did not compile. It described an earlier
hand-written facade —
render.taskRuns.run(...),render.workflows.list(),waitFor— none of which exist on the generated API. Rewritten around what the package actually exposes, and every snippet now verified by compiling it. - Adds
example/example.dart, and formats the package. Those were the two things costing pub.dev points; the score is now 160/160. tool/generate.dartrunsdart formatas its last step, so regenerating cannot undo the formatting.- The README now points at the two companion packages:
render_workflowsfor running tasks, andrender-darton npm for writing the task bodies in Dart. pub.dev serves the README from the published archive, so this needed a release to become visible.
0.1.0 #
Initial release.
- The whole Render REST API: 208 operations and 164 models, generated from Render's OpenAPI specification.
- Two spellings of every call — flat (
render.listWorkflows(...), matching Render's own Node examples) and grouped (render.raw.workflows.listWorkflows(...)). - Method names taken from the spec's
operationId, so they correspond one for one with Render's official@api/render-apibindings. - Typed exceptions carrying hints for Render's less obvious responses —
500rather than404for an unknown task run id, and500for a workflow whose repository cannot be read. - Unknown enum values decode to
.unknownrather than throwing, so a new region or status cannot break a working client. - Cursor pagination, retries with backoff, and a configurable timeout.
- Runs on the Dart VM and under dart2js. On the web there is no environment, so the API token must be passed explicitly.