Bind an agent’s action to the approved arguments

An assistant receives approval to export one report, then substitutes a different report and destination. Repair the tool gateway that authorizes the final action.

Requires Node.js 22 or newer. No package installation or server needed. To work in a container instead, open the folder with VS Code Dev Containers or GitHub Codespaces: .devcontainer/devcontainer.json uses the Dev Containers Node.js 24 image, pinned by digest.
1. Unzip all files into one folder.
2. In that folder, run: node --test exercise.test.mjs
3. Edit tool-gateway.mjs, then run the same command again.

The starter deliberately fails some tests. A successful repair passes every case, including cases that catch common wrong fixes. The browser runs this same cases.mjs with the same fixtures; locally Node runs your code directly. If you completed the optional first stage in the browser, Download my work adds your input as stage1-input.json and the tests include it. Only run code you wrote or reviewed.

1. Reproduce the substitution
Run the changed-destination case. Approval of an operation name alone does not authorize every possible destination.

2. Enforce user authority
Require the trusted tenant, a report in session.reports, and a destination in session.allowedDestinations. Model text cannot add permissions.

3. Bind approval to the action
Require active approval and exact equality for tool, tenant, report and destination. Ignore an approved:true property supplied by the model.

4. Retain authorized work
The exact approved export must pass. Explain how the real executor will consume the approval and prevent a second use atomically.

SUPPLIED CONTRACT
allowToolCall(call, session, approval) receives a proposed export {tool,tenant,report,destination}, trusted session {tenant,reports,allowedDestinations}, and a trusted approval record {tool,tenant,report,destination,active}. Only export_report is allowed. Require current session access and an exact match to every approved field. This harness evaluates the predicate only: it does not execute exports, consume approvals or prove replay prevention. A real executor must atomically claim the approval and bind it to the committed operation.

REFERENCE
reference.mjs contains an explained solution: The exact approved r1 export to internal://finance passes. Changing destination fails authorization and approval binding. Changing r1 to r2 fails approval binding even when the session can read both reports. Removing r1 from current session access fails despite matching approval. active=false or a model-supplied approved:true cannot grant authority. Repeating this pure predicate with the same still-active inputs would return true again, so single-use execution requires the separate durable executor boundary.

SCOPE
This is the authorization predicate; no export is sent. Production must validate tool schemas, canonicalize approved arguments, protect the approval store, atomically consume approval, prevent replay and reauthorize at execution time. Human approval does not replace authorization.

NEXT TASK
Can a retry, delegated agent or changed argument reuse an approval in your tool system?

SOURCE
https://genai.owasp.org/resource/agent-control-standard-acs/
