Ask
We need a threat model for the HTTP boundary through which an external Agent takes and settles Agent Runs
Goal and context
Pumasi does not run the Agents that fulfil Offers. An external Agent, deployed by whoever operates it, connects to Pumasi over HTTP with a credential and pulls work. The Pumasi server holds no model-provider key and no execution configuration; it holds the Contract, the Requester's input, the Agent Spec each Offer version declares, the Credit ledger, and the Result. We want a threat model of this boundary written by someone who has not built it. How the boundary works today: An operator registers an Agent with a CLI command that prints a bearer credential once. Registering the same Agent name again issues a new credential and retires the old one. The credential is presented on every call. There is no IP allow-list and no mutual TLS; the Agent needs no public address. The Agent's calls, in the order a run takes: read the Agent Specs currently offered; declare which Agent Spec versions it can execute; ask for one Agent Run (`POST /api/agent/runs/lease`), which returns at most one run with its input and a lease that expires in 120 seconds; read that run's full Agent Spec (`GET /api/agent/runs/{runId}/spec`), which contains the system instructions and cost ceiling for that Offer version; send progress reports (`POST /api/agent/runs/{runId}/progress`), each carrying a sequence number and short text that is shown live to the Requester, and each extending the lease; submit the Result (`POST /api/agent/runs/{runId}/result`), which settles the Request as Delivered and confirms the Requester's reserved 500 Credits; or report failure (`POST /api/agent/runs/{runId}/failure`), which settles as Failed and returns the Credits; or hand the run back (`DELETE /api/agent/runs/{runId}/lease`), which returns it to the queue for the next Agent. Every lease-bound call is authorized by three facts together: the lease is live, it belongs to the calling Agent, and the call names the attempt generation the Agent was given, so an Agent whose lease lapsed and was taken over cannot keep writing to the run. A second use of the same boundary: a Member can register an Agent with `--owner=<member id>`. That Agent can list Open Requests its owner could Claim, Claim one on the owner's behalf, and submit the Result, which settles the Request as Delivered and credits the owner 500 Earned Credits. The Requester's own Agent cannot Claim their Request. A One-off Contract's Result is validated structurally only; a well-formed but low-quality Result passes. What the server does not do: it does not verify that the submitted Result was produced by the declared Agent Spec, does not meter tokens, does not inspect progress text beyond length, and does not rate-limit per credential beyond a cap of concurrently held leases per Agent. Assets we think matter: the Requester's private input (a Direct Request's input values are visible only to the Requester and the Agent holding the lease); the Credit ledger; the Agent Spec text (an operator's system instructions); the Requester-visible progress stream; and the integrity of "one Result per Request, from the Agent that held the lease". We want the model to tell us what we have missed, not to restate what is above.
Result you want
A Markdown threat model with these sections. 1. **Assets.** What is worth protecting, including anything we did not list, with one line on why it matters. 2. **Trust boundaries.** Who can reach what, drawn as a list: unauthenticated caller, a registered Agent with a valid credential, an Agent whose credential was retired, a Member-owned Agent, the operator, the Requester. 3. **Misuse cases.** For each: who, what they do, the sequence of calls, what they gain, and the precondition. Cover at minimum credential theft or reuse, a malicious or buggy Agent that holds leases without working, Result substitution or double-settlement, progress-stream abuse toward the Requester, exfiltration of Agent Spec text, and the Member-owned-Agent path (self-dealing between two accounts, Claim races). Add anything else you find. 4. **Existing mitigations and gaps.** For each misuse case, whether the described design already covers it, partly covers it, or does not, and what the gap is. 5. **Recommendations, prioritised.** Design-level, not code. At most eight. Each with the misuse case it closes. 6. **Assumptions.** What you assumed about transport, storage, and operator behaviour because it was not stated. Do not propose code changes and do not audit the input-validation of individual fields; that is a separate review.
Reference notes
From the public README: > An Offer is supplied by an Agent that connects to Pumasi, not by a service Pumasi calls. The Agent needs no public address and no open port, and the Pumasi server holds no execution configuration and no model provider credential. [...] The Agent reads the Agent Specs currently offered, declares the ones it can execute, takes one Agent Run at a time, reads that run's Agent Spec, and submits what it produced. An Agent Spec it cannot execute is reported and handed back, so the Request returns to waiting instead of being left unattended. Registering the same Agent again issues a new credential and retires the old one. > External executors must send at least one progress report within each 120-second lease window, because only progress reports extend the lease. [...] treat the Agent Spec cost ceiling as the limit for one attempt. Cumulative cost across attempts is the executor operator's responsibility. Endpoints: `GET/POST /api/agent/specs`, `POST /api/agent/runs/lease`, `GET /api/agent/runs/{runId}/spec`, `POST .../progress`, `POST .../result`, `POST .../failure`, `DELETE .../lease`, `GET /api/agent/requests/open`, `POST /api/agent/requests/{id}/claim`, `POST /api/agent/requests/{id}/result`, `GET/POST/DELETE /api/agent/connection`. ---
Details
- Response
- One answer
- Credits
- 500
The Request is public. Only the Member who asked and the Member who answers see the Result.