Skip to content
SecurityAgent-ready

Naming a function by id or name no longer grants access to it

Routing to a specific function checked that it existed and was active, but never that the caller was allowed to reach it, so a workspace could compute against another workspace's private function by naming its id. Every compute path now allows only built-ins, your own functions, and functions listed publicly on the marketplace.

A function you have not listed publicly is now reachable only by you. Explicit routing (a request that carries a function_id, or a routing_preference of explicit) checked three things: that the function existed, that it was active, and that its circuit breaker was closed. It never checked whose function it was. Automatic routing had always filtered to built-ins and your own functions; explicit routing did not, so naming another workspace's function id was enough to have it selected, executed, and its result returned, including the explanation and confidence that are usually the point of a pricing function.

The same rule now applies wherever a caller names a function: POST /api/compute/price, each item of POST /api/compute/batch, POST /api/price-router, and the Test button on the Functions screen. A function is reachable when it is a built-in, when your workspace owns it, or when it is listed publicly on the marketplace. Nothing else is.

This mattered most for functions that call your own endpoint. A function with an execution type of external API is invoked at the address you registered, so an unauthorised caller naming it drove requests, and cost, at infrastructure you pay for, with the calls charged to their workspace and the traffic landing on yours. Batch made that worse: up to a hundred items in a single request, each free to name a function.

Function names were the part that needed no guesswork. POST /api/price-router accepts a friendly function_name in place of an id, which is how built-in models are addressed. That lookup ran across every function on the network, and names are chosen by people rather than generated, so the difference between a hit and a miss reported which names were taken across every workspace. Name resolution is now scoped to the caller, and built-ins and publicly listed functions stay reachable exactly as before.

What you will see if you were relying on the old behaviour. On POST /api/compute/price and the router, a function you cannot reach answers 404, with the same body as an id or name that does not exist anywhere, so the response does not confirm that someone else holds it. A batch still answers 200: one item cannot fail the whole call, so the unreachable item carries that same message as its own error and the rest are priced as usual. The Test button answers 403 for a private function that is not yours, matching what fetching that function's details has always returned. Your own functions, built-ins, and anything listed publicly are unaffected, including testing and routing to a marketplace function you do not own.

Fallback chains follow the same rule. An entry naming a function outside your reach is skipped and the chain moves on, rather than executing it.

If you believe a workspace of yours was named this way, write to support@last-price.ai.

  • Explicit routing by function_id now allows only built-ins, your own functions, and publicly listed ones
  • Each item of a batch request is checked the same way
  • function_name resolution on the router is scoped to the caller, and built-ins stay addressable by name
  • Testing another workspace's private function answers 403, matching the details endpoint. Testing a built-in, or a function listed publicly on the marketplace, still works
  • An unreachable function is answered exactly as a missing one, so the response is not an existence check (a 404 for single requests and the router, the same message as a per-item error inside a batch's 200)
  • Fallback chain entries outside your reach are skipped instead of executed