Before you begin
- Node.js 22 or later, and Git.
- About ten minutes.
npm ciand the first build take most of it.
1. Set up a fresh clone
If a later step fails with a missing file under
keys/, one of the two key commands was skipped.
2. Watch a person decide
Tutorial 119 runs the realcustomer-refund 1.2.0 policy and the components the server runs, in one process.
- The agent’s own claims (eligible, fraud check passed) never approve a refund (steps 1 and 2).
- Saying
managerApproved: trueis worth nothing without a signed approval (step 3). - A signed approval covers one action, one resource, up to one amount, once (steps 5 to 7).
- The policy still applies to an approved request (step 8).
3. Release an action to a system Parmana has no code for
Tutorial 123 registers an external connector through maker checker, runs an example endpoint from the SDK on your machine, and releases an approved request to it.4. Run the server and call it from the SDK
The tutorials run Parmana in one process. Now run the server and talk to it over HTTP, as an agent does.Make a caller key for your agent
Key : ...) and the entry to configure ({"callerId":"local-agent","keyHash":...}).
Only the hash is ever stored. Keep the raw key for the agent; put the entry in PARMANA_API_KEYS.
Make an approver key and sign an approval
You play the approver here. On a real deployment the approver is a different person (Chapter 5).--ttl-seconds, and it can be used once.
Start the server
NODE_ENV=test with PARMANA_STORAGE=memory runs with no database. It also registers test:fixture-execute, a
connector that needs no credential, and trusts the approver key in PARMANA_TEST_APPROVER_PUBLIC_KEY_FILE. The server
refuses to start if that variable is set with any other NODE_ENV.
/health, /ready and the API description routes needs a key.
Send a request, refused, then approved
Save asfirst-action.ts in typescript/examples/ (so @parmana/sdk resolves to the SDK you built) and run it with
PARMANA_API_KEY set to the raw key:
allowedPrincipalIds defaults to the caller id when the key entry names none. That is why the request acts as
me.callerId.