0050: Calls live in the app, or in the project

On this page

Status: accepted

Context

Calls is Short Leash's HTTP client: requests you save per site, send, and check, each coming back with what it caused on the site (0051). Saved requests have to survive restarts and be easy to share, the secrets they use (tokens, passwords) must stay out of anything shared, and sending one shouldn't depend on DNS or certificates working the same on every computer. People who use HTTP clients expect their requests to be plain files they can commit, and to never be locked in: export always works.

Decision

  • Short Leash's database by default. A site's calls, folders, environments and the responses kept as examples are in Short Leash's database (0029), like scratchpads (0030): nothing is written into the project unless you ask. A site keeps at most 500 calls, 200 folders and 20 environments, and each call its last 5 examples. Examples are the only responses written to disk, because you keep them on purpose. What each send got back (History) and the cookies sends collect stay in memory, like captured requests (invariant 11).
  • Keep in project folder, per site. Turned on, Short Leash writes the site's calls to a folder of the project you pick (calls/ unless you choose another), as Short Leash's own YAML: collection.yml, a folder.yml per folder, one file per call, and environments/*.yml with the names of secret variables only. While it's on, the files are what counts: Short Leash reads them the first time the site's calls are used after it starts and when the app comes back to the front, and writes them after each change, atomically, as ordinary files (0644). Turned on over a folder that already holds calls, it keeps both: Short Leash's are added beside the folder's. It never deletes a file it didn't write, and when a file changed on disk and in Short Leash since its last write it asks which to keep. This is the one place Short Leash writes into a project on its own, and only after you turn it on (an exception to invariant 3 that you choose). The folder must be inside the site's folder.
  • Secrets in a file only you can read. Values of secret variables and the OAuth 2 tokens calls get live in secrets/calls.json (0600), never in the database, the files or the API (invariant 9); the app sees whether each has a value and its last four characters. They're hidden as •••••• in History, in what AI tools get back, and in the CLI's output (values of 4 characters or more; shorter ones would hide ordinary text).
  • Sends go through the proxy for Short Leash's sites. A call to a Short Leash site is handed to the proxy in process, as a local HTTPS request: no DNS, no TLS, the same on macOS and Windows, and recorded on Requests like any other request. Anything else, the share URL included, goes over the network with reqwest, following redirects one hop at a time (at most 10) and dropping Authorization, Cookie and the XSRF header when a redirect goes to another host.
  • Checks are data, not code. Checks (status, a header, a JSONPath value, the body, the duration) and the values a call keeps for the next ones are rules Short Leash evaluates; Short Leash doesn't run scripts from calls, so a collection from a repository can't run code on your computer. Scripts in imported collections are left out, with a warning.
  • AI tools reach less. Calls sent through leash mcp reach the site and its share URL. Other hosts need the site's setting "Let AI tools call other hosts" and the tool asking for it; this computer's and the local network's addresses are refused even then, checked on every hop and after the name is looked up.
  • Open formats out and in. Calls export as curl, an .http file or a Short Leash folder; they import from curl, Postman, OpenAPI, Insomnia, Bruno and OpenCollection files, .http files, HAR and the site's own routes (route:list, debug:router). Imports are previews until you add them.

Alternatives

  • Files in the project, always would make every site's folder hold Short Leash's files, show up in git status for people who don't want it, and need a watcher for every project.
  • An existing collection format as Short Leash's own (Bruno's YAML) would tie Short Leash to a format another product changes, with no license on its specification; Short Leash imports it instead.
  • Real HTTPS to 127.0.0.1 for .test sites would test Short Leash talking to itself and depend on the CA being trusted, which differs by platform; the proxy already measures what the site took.
  • JavaScript in a sandbox for checks gives more power but makes every cloned collection a way to run code; the rules cover what people use most, and scripts can come later if they're asked for.

Consequences

  • A site's calls are private to your computer unless you turn on the project folder; teammates get them by committing that folder.
  • With the project folder on, two people editing the same call in Git get an ordinary merge conflict in a small YAML file.
  • In-process sends show the site's time, not DNS or TLS; sends to the share URL and other hosts show those.
  • Queued jobs run in another process, so a call's "What it caused" doesn't include what its jobs did.