Skip to main content
Sponson’s adapters (packages/adapters/src/) and the fake cloud (packages/sim/src/routes/) were written without real provider accounts. This page records what was checked, without an account, against each provider’s published API specification: every HTTP call an adapter makes, and every numbered assumption at the top of a sim routes file. What a specification cannot settle still needs a live run of pnpm test:live (scenarios/contract.test.ts). Legend: ✅ matches the spec · ⚠️ differed from the spec (fixed in adapter and sim unless noted) · ❓ the spec is silent; needs a live account.

Sources

All fetched on 2026-10-10 (LaunchDarkly, PlanetScale, Supabase, Netlify: 2026-10-11) and treated as data; none is vendored into the repository. Vercel, Neon and Clerk use bearer authentication (securitySchemes), which is what the shared HTTP client sends by default: ✅. LaunchDarkly takes the access token as the whole Authorization value, without Bearer; the adapter sends it that way (authHeader: "header:authorization"): ✅. PlanetScale service tokens are not bearer tokens either; see below. Supabase’s Management API and Netlify’s API use bearer tokens: ✅. Cloudflare’s API token is a bearer token too (“The preferred authorization scheme”): ✅.

Vercel

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/vercel.ts)

Neon

Calls the adapter makes

The spec also says a 503 is always safe to retry; the shared HTTP client retries 5xx only for idempotent methods, which is more cautious than needed but not wrong.

Sim assumptions (packages/sim/src/routes/neon.ts)

Clerk

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/clerk.ts)

LaunchDarkly

Calls the adapter makes

The PATCH is sent as idempotent (a 502/503/504 or dropped connection is retried): adding and removing an individual target are set operations, so repeating one changes nothing more.

Sim assumptions (packages/sim/src/routes/launchdarkly.ts)

PlanetScale

Paths are relative to https://api.planetscale.com/v1 (the spec’s servers) and, below the first row, to /organizations/{organization}/databases/{database}.

Calls the adapter makes

Not used: PATCH …/passwords/{id} takes only name and cidrs (✅), so a role cannot change in place (PS10), and the adapter never calls …/passwords/{id}/renew, which would rotate the plaintext.

Sim assumptions (packages/sim/src/routes/planetscale.ts)

The generic http adapter

The http adapter makes the calls a plan line declares, so there is no provider to verify it against: a line is checked by running sponson plan (it only reads) against the real API before the first apply. The plans in examples/ that use it are illustrative and say so. Recipes are the exception: each is verified against the provider pages it cites, its assumptions are numbered and marked verified or not in its file (and listed in docs/recipes.md), and pnpm test:live runs it against the real API when its credential and SPONSON_LIVE_* variables are set (ADR 0020).

Sim assumptions (packages/sim/src/routes/rest.ts)

They describe a conventional JSON REST API, not one provider; the adapter’s tests and scenarios run against them.

Authentication forms (packages/adapters/src/http-adapter-auth.ts)

Checked on 2026-10-11 against the providers’ docs and official clients; the sims and scenarios encode them.

Sim assumptions (packages/sim/src/routes/aws.ts)

Sim assumptions (packages/sim/src/routes/railway.ts, packages/sim/src/routes/fly.ts)

Supabase

Written against the spec from the start (the adapter is newer than this page), so there is no ⚠️ column history: every call below was checked before the first commit. Base URL https://api.supabase.com/v1; the spec’s paths carry the /v1 prefix.

Calls the adapter makes

Derived outputs: api_url is https://<ref>.supabase.co (the project URL format in the API docs) and connection_string is postgresql://<db_user>:<db_pass>@<db_host>:<db_port>/postgres, matching the documented direct connection string (postgres database; the password percent-encoded). The direct host resolves over IPv6 unless the project has the IPv4 add-on.

Sim assumptions (packages/sim/src/routes/supabase.ts)

Netlify

Written against the specification and docs from the start (no earlier version to correct), so the table records what each call relies on rather than fixes.

Calls the adapter makes

Deploy Previews cannot be rebuilt through any documented call (the docs describe “Retry deploy” in the UI only), so a context: deploy-preview line reports the stale deploy (notes.stale_deploy) and waits for a newer one.

Sim assumptions (packages/sim/src/routes/netlify.ts)

Cloudflare

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/cloudflare.ts)

Not built, and why

  • Preview URL output. Preview deployments documents the branch alias <alias>.<project>.pages.dev and that “Branch name aliases are lowercased and non-alphanumeric characters are replaced with a hyphen”, but not the shortening of long names (a 28-character limit appears only in community answers) or what happens on collisions, and the host is the project’s subdomain, which may differ from its name. Computing it from the branch would sometimes be wrong, so pages_env has no outputs. The deployment object’s documented aliases list is the reliable source, for a later deployment op.

Algolia

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/algolia.ts)

Xata

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/xata.ts)

Contentful

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/contentful.ts)

DigitalOcean

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/digitalocean.ts)

Google Cloud Run

Calls the adapter makes

Sim assumptions (packages/sim/src/routes/cloud_run.ts)

Secret sources

What each built-in secret source sends and reads (packages/adapters/src/secrets.ts). The CLI-backed ones are tested with injected output and fake executables shaped like the documented output; the HTTP ones against a local server and the generic REST sim (assumption R7’s exact headers and fixed tokens) serving the documented answers.

What still needs a live account

  • Vercel: V1 for a deployment (the list was checked), the deployment list’s order, how overlapping target sets are refused, whether the env list pages with until, branch auto-cancel, and that a gitSource deployment from the project’s link builds.
  • Neon: N2 (whether any request answers 423 in practice, endpoint readiness).
  • Clerk: C1 (status and wording of a duplicate), C2 (the envelope, confirmed only through the SDKs).
  • LaunchDarkly: LD5 (re-adding a target the variation already serves; the status of a two-variation refusal), LD7 (read-after-write), LD2 (an unknown environment), LD3 (the user placeholders in contextTargets).
  • PlanetScale: PS4 (a new branch is not ready at first; how long provisioning takes), PS5 (status of a duplicate branch name), PS7 (deletion timing), PS9 (duplicate password names), PS12 (a password on a branch still provisioning), and PS1 and PS8 end to end.
  • Supabase: S1 and S3 (a branch’s ref is usable at once; the detail’s status while it comes up), S4 (db_pass for a personal access token), S5 (status of a duplicate name), S6 (404 for an unknown ref, list visibility after delete), S8 (verbatim storage of the list), S9 (a branch’s own Auth config through the same endpoint). The Supabase block of the contract suite is optional in a live run (branching needs a paid plan).
  • Netlify: NL2 (name is the subdomain), NL3 (PATCH leaves other values and keeps ids), NL5 (status of a duplicate key), NL6 (an emptied variable), NL7 (deploy order, context values, review_id), NL10 (updated_at on PATCH), NL11 (a build of a branch whose branch deploys are off).
  • Cloudflare: CF3 (what a secret’s value looks like in GET), CF4 (that PATCH merges the map), CF6 (status of an unknown project), CF7 (a write is readable at once).
  • Algolia: AL5 (whether a copy’s destination is visible before its task is published), AL6 (status of deleting a missing index), AL8 (how long a copy takes).
  • Xata: XA3 (whether branch names are unique), XA5 (the spelling of statusType), XA6 (credentials of a branch still coming up), XA7 (how long a branch takes).
  • DigitalOcean: DO3 (status of a duplicate name), DO6 (that the stored spec keeps every sent field in order), DO7 (what a secret reads back as).
  • Google Cloud Run: CR4 (status of a taken revision name), CR7 (short or full revision names), CR8 (whether a stale etag is refused, and how), CR9 (when a template change’s operation ends), CR13 (tag rules beyond lowercase).
  • Secret sources: Vault’s answer for a soft-deleted latest version; the exact failure texts of az, bws and infisical for a missing secret.
  • The generic adapter’s authentication forms and GraphQL examples: every ❓ above, and each provider end to end (the examples run against sims, not the live APIs).
Run them with pnpm test:live; see the header of scenarios/contract.test.ts.

Live runs

Runs of pnpm test:live (or a part of it) against real accounts. Every other check in this document is against published specifications and documentation only.