Skip to main content
Selo sends real requests and real payments. A release test pays your endpoint, then replays the identical signed payment against it. Pointed at someone else’s API, that would be unwanted traffic with money attached. So Selo tests a route only while a verified, unexpired authorization covers its exact origin, path and method. Consent is never inferred.

Scope

An authorization covers one route and one method. Selo compares all three parts exactly. To test GET and POST on the same path, or two paths on the same origin, create one authorization for each. The target URL must also pass Selo’s address rules: HTTPS only, no user name or password in the URL, no explicit port, a hostname rather than an IP address, at least two labels, and not a local name such as .local or .internal. See the security model.

Two ways to authorize

The standard method, available to anyone through the API or the CLI. You prove control of the origin by serving a token Selo gave you. The authorization’s type is well_known_file.

The well-known file method

1

Create the authorization

Send the target URL, the method, a project name (1 to 80 characters) and a contact (3 to 200 characters).
Terminal
Selo answers 201 with a pending authorization and the line to publish:
201 Created
The token is 32 random bytes, encoded as 43 base64url characters. This response is the only time Selo returns it.
2

Publish the line

Serve the expectedContent line at verificationUrl, on the same origin as the route. The file may hold other lines, so one file can carry the tokens for several authorizations on the same origin.
.well-known/selo-verification.txt
3

Verify

Ask Selo to read the file:
Terminal
200 OK
The CLI does the same with selo auth create, selo auth verify and selo auth status. See Authorize your endpoint for the full walkthrough and selo auth for the flags.

How Selo reads the file

  • One GET to <origin>/.well-known/selo-verification.txt with accept: text/plain, through the SSRF-safe fetch, with a 10-second timeout.
  • Up to 3 redirects are followed, and every hop must stay on the same origin and pass the address checks again.
  • The response must be 2xx and at most 4 KiB.
  • Selo trims each line, takes the lines that start with selo-verification=, hashes the value after the prefix with SHA-256, and compares it with the stored hash in constant time. One matching line is enough.
Verifying an authorization that is already verified and unexpired returns it unchanged. The operator records consent with a command run against Selo’s own database:
Terminal
  • Every flag is required. --note (1 to 1,000 characters) must say how the owner consented, and it is stored with the authorization.
  • The target URL passes the same address rules as the well-known method.
  • The command writes a VERIFIED authorization of type manual_owner_consent, prints its id, and the authorization expires after the same 24 hours.
Consent is explicit and recorded. Selo never treats a public listing, a price in a 402 or a Bazaar entry as permission to test a route.

Statuses

Selo reads the file only when you call verify. Removing the file afterwards does not end the authorization; it stays valid until it expires 24 hours after verification. The public API has no route that revokes an authorization.

Where Selo checks it

Selo checks the authorization at every point where a request or a payment could follow.

When it lapses mid-job

An authorization can expire between your payment and the end of the run. Selo does not let a lapsed authorization through to save the job:
  • At the start of the run, a lapse ends the job before any request reaches your endpoint.
  • Before the downstream payment, the spend guard refuses to reserve, so nothing is signed.
  • After the paid call, the replay is skipped and retry_safety reports NOT_RUN, so the verdict cannot be PASS. Results already measured keep their evidence, so a FAIL that was already proven stays a FAIL.
Selo has already been paid at the start of the run, so start release tests well inside the authorization’s 24 hours. The CLI and the GitHub Action check the authorization through the free preflight before they pay. Each check at the start of the run and before the replay is recorded as an authorization_snapshot evidence record: the authorization’s id, type, status, origin, route, method, verification and expiry times, the requested target, whether it was covered and whether it was valid.

The hashed nonce

Selo stores only the SHA-256 of the verification token, never the token itself. The token appears once, in the 201 response that created the authorization, and no later response returns the token or its hash. During verification Selo hashes each candidate line and compares hashes in constant time. Once you publish the line, the token is public. Its purpose is to show that whoever requested the authorization controls the origin, not to act as a secret.

Authorize your endpoint

Step-by-step, with the CLI and the API.

Run a preflight

The free check that confirms the authorization and reads your price.

Security model

Address rules, DNS pinning and redirect handling.

Errors and reason codes

Every error the authorization routes return.