Two problems, one idea
The first problem is the record. Parmana’s signed Execution Trust Record contains the result of the action, so it can only be built after the action is released. If building or storing it fails, an action has run and nothing signed describes it. Before 21 September that was possible in Parmana. The context needed to rebuild the record existed only in the memory of the request that failed. The second problem is language. “Failed” and “we don’t know” are different facts, and they call for opposite actions. The idea for both is old and simple: write down what you are about to do, before you do it. If you cannot write it down, do not do it. And when you do not know the outcome, say so.How Parmana does it
An Execution Intent is signed and stored before release. After the policy approves, the authorization is signed and a signing readiness check passes, the runtime signs an intent and writes it to the database. Only then is the action released to the connector. If the intent cannot be signed or stored, the caller gets a 503 and nothing is released. This is enforced everywhere except test and development, there is no switch to turn it off in production, and the readiness endpoint reports a missing intents table before the first real request hits it. The intent holds only what exists before release: the ids, the policy reference, the hashes of the policy content, the facts and the executable content copied from the signed authorization, the action and target, the caller, and when it was created. It never holds the result and never the raw parameters; the content hash binds it to them. It is signed with the same key as the Trust Record, so anyone with the public key can verify it, through an API route that needs no credential or offline from a clone of the repository. The Python SDK has an offline verifier, and the TypeScript SDK has one from version 1.3.0. Each intent has a state. It is kept next to the intent, and it is not signed:- Prepared: signed and stored; the action may or may not have been released.
- Released: the connector answered and the execution context was saved; no Trust Record yet.
- Finalized: a signed Trust Record exists. The normal outcome.
- Errored: the release stage raised an error. The action may still have run.
- Resolved: a verified human checked the target system and closed it.
What it does not do
- An intent does not prove the action ran, or what happened. It proves what was about to be released. A crash between storing the intent and releasing leaves an intent for an action that never ran.
- Not every released action gets a signed Trust Record. If the context save after release also failed, finalize refuses with a 409, and the outcome has to be established at the target system by hand.
- Closing an intent by hand is not signed. It is an attributed, timestamped statement by a person. It is not tamper evident and does not create a Trust Record. If an operator closes one as executed, the signed evidence is still only the intent.
- Not verified on Vercel: the failure paths (finalize, resolve) and a real Paytm refund. The extra signing cost (about 35 ms) was measured once from a developer machine, not from production.
- An action refused at release stays errored until a person closes it; there is no “not released” state yet.
- Approved requests are slow today. One took 24 to 32 seconds in production, so clients are told to use a 120 second timeout and to read the record before sending anything again.
- Transactions from before 21 September have no intent.