create-metamynd-agent 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +28 -8
  2. package/index.mjs +39 -16
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -135,23 +135,43 @@ npm start
135
135
  ### Separate tool gateway (default)
136
136
 
137
137
  This is the other half of **without MetaMynd, you can be bypassed**: WITH it — specifically, with
138
- `gateway/`, the second process this scaffolds by default — you can't be, the same way the hosted
139
- platform's own MCP counterparty can't be talked around by a compromised agent.
138
+ `gateway/`, the second process this scaffolds by default — calling the tool directly instead of
139
+ through the check no longer works, the same way the hosted platform's own MCP counterparty can't
140
+ be talked around by a compromised agent. See [Not solved by the gateway](#not-solved-by-the-gateway)
141
+ below for the two things this specifically does **not** cover.
140
142
 
141
143
  `guard.guardTool()` in `index.mjs` still runs — it's a fast, local, client-side pre-check that gives
142
144
  good UX (fail fast on an obviously-blocked call, no round trip) — but it is **not** what stops a
143
145
  bypass. It still calls its handler in the SAME process regardless of where the decision came from,
144
146
  so anything able to call that handler directly gets the same result the gate would have given it.
145
147
 
146
- What actually stops a bypass is that `bookFlight()` doesn't exist in the agent's process at all.
148
+ What actually stops that bypass is that `bookFlight()` doesn't exist in the agent's process at all.
147
149
  It exists only in `gateway/server.mjs` — a separate process, started separately, holding any real
148
150
  tool credentials the agent process never sees — which independently re-verifies every request
149
- against the agent's own published policy bundle before running it (same shape as the mutual
150
- counterparty check in [`@metamynd/agentsafe-mcp-guard`](https://www.npmjs.com/package/@metamynd/agentsafe-mcp-guard),
151
- built with [`@metamynd/agentsafe-http-gateway`](https://www.npmjs.com/package/@metamynd/agentsafe-http-gateway)).
152
- It's a minimal slice of the same pattern proven end to end in `demo/duffel-mcp-gateway` in the
151
+ against the agent's own published policy bundle before running it, and **binds that request to the
152
+ actual body being executed** (`@metamynd/agentsafe-http-gateway` ≥ 0.2.0) — closing a confused-deputy
153
+ gap found during testing, where a signed cheap request could be governed while a different, expensive
154
+ body was the one that actually ran. Same shape as the mutual counterparty check in
155
+ [`@metamynd/agentsafe-mcp-guard`](https://www.npmjs.com/package/@metamynd/agentsafe-mcp-guard), built
156
+ with [`@metamynd/agentsafe-http-gateway`](https://www.npmjs.com/package/@metamynd/agentsafe-http-gateway).
157
+ It's a minimal slice of the fuller pattern proven end to end in `demo/duffel-mcp-gateway` in the
153
158
  AgentSafe repo (mutual handshake, x402 payment binding, capability tokens) — this scaffold gives you
154
- just the part that closes the bypass, not the whole protocol.
159
+ just the part that closes the direct-call bypass, not the whole protocol.
160
+
161
+ #### Not solved by the gateway
162
+
163
+ Named precisely, not left implicit:
164
+
165
+ - **Replay.** The gateway checks a signed request is fresh, not that it hasn't been used before —
166
+ a captured valid request can be resent within the freshness window. Single-use nonce consumption
167
+ is the stateful issuer gate's job (`POST /policy/mandate/authorize`); this scaffold never calls it.
168
+ - **Cumulative spend.** Each call is checked against the per-transaction cap correctly, but the
169
+ mandate's TOTAL budget isn't tracked at the gateway — many separately-legal calls can still add
170
+ up past it. The real total is only enforced where a hold is actually reserved: the issuer gate.
171
+
172
+ Both require wiring the full authorize-before-execute flow (agent calls the stateful gate first,
173
+ gateway checks a decision bound to that specific authorization) rather than per-request policy
174
+ re-evaluation alone — see `gateway/README.md`'s own "Beyond this minimal slice" section.
155
175
 
156
176
  Pass `--no-gateway` to opt out and get the old single-process scaffold instead — e.g. if you're
157
177
  already running your own separate gateway and don't need this one. **You are back to being
package/index.mjs CHANGED
@@ -28,7 +28,9 @@ const GUARD_VERSION = '^0.5.0';
28
28
  const MCP_GUARD_PKG = '@metamynd/agentsafe-mcp-guard';
29
29
  const MCP_GUARD_VERSION = '^0.1.0';
30
30
  const GATEWAY_PKG = '@metamynd/agentsafe-http-gateway';
31
- const GATEWAY_VERSION = '^0.1.0';
31
+ // 0.2.0 fixes a confused-deputy gap (payload not bound to the signed request) — the CLI must
32
+ // never scaffold a range that could resolve below it.
33
+ const GATEWAY_VERSION = '^0.2.0';
32
34
  const DEFAULT_API = 'https://metamynd.ai/api/v1';
33
35
  const DEFAULT_GATEWAY_PORT = 4401; // distinct from --harness's dashboard (4400)
34
36
 
@@ -689,15 +691,17 @@ A MetaMynd/AgentSafe-governed agent, scaffolded with \`create-metamynd-agent\`.
689
691
 
690
692
  ${gatewaySection}${
691
693
  withGateway
692
- ? `**With MetaMynd's gateway, you can't be bypassed** that's what this section is about.
693
- This scaffold's default shape (agent + separate gateway process, port ${gatewayPort} by
694
- default) is the actual enforcement boundary: \`guard.guardTool()\` in \`index.mjs\` is a
695
- client-side convenience, not a boundary — it still runs its handler in-process regardless of
696
- where the decision came from. What actually stops a bypass is that \`bookFlight()\` itself only
697
- exists in \`./gateway\`, a process this one cannot reach into, which independently re-verifies
698
- every request against this agent's own policy bundle. Re-scaffold with \`--no-gateway\` for the
699
- old single-process shape it is NOT a separate enforcement boundary; see its own generated
700
- README for why.`
694
+ ? `**With MetaMynd's gateway, calling the tool directly and skipping the check no longer
695
+ works** — that's what this section is about. This scaffold's default shape (agent + separate
696
+ gateway process, port ${gatewayPort} by default) is the actual enforcement boundary for that
697
+ specific bypass: \`guard.guardTool()\` in \`index.mjs\` is a client-side convenience, not a
698
+ boundary it still runs its handler in-process regardless of where the decision came from. What
699
+ actually stops it is that \`bookFlight()\` itself only exists in \`./gateway\`, a process this one
700
+ cannot reach into, which independently re-verifies every request against this agent's own policy
701
+ bundle AND binds it to the actual body being executed. It does NOT track replay or cumulative
702
+ spend across calls — see \`./gateway/README.md\`'s "Beyond this minimal slice" section. Re-scaffold
703
+ with \`--no-gateway\` for the old single-process shape — it is NOT a separate enforcement boundary
704
+ at all; see its own generated README for why.`
701
705
  : `**Without MetaMynd, you can be bypassed** — this is that case. This scaffold has no
702
706
  separate gateway process (either \`--sandbox\`, which never provisions real credentials, or
703
707
  \`--no-gateway\` was passed): \`guard.guardTool()\` wraps a tool in the SAME process as the check
@@ -837,8 +841,11 @@ function gatewayGitignore() {
837
841
  function gatewayReadme(slug, scope, port) {
838
842
  return `# ${slug}-gateway
839
843
 
840
- **With MetaMynd, you can't be bypassed.** This process is why. It is the **real enforcement
841
- boundary** for \`${slug}\`'s tool(s) — not \`../index.mjs\`.
844
+ **With MetaMynd, you can't call the tool directly and skip the check.** This process is why. It
845
+ is the **real enforcement boundary** for \`${slug}\`'s tool(s) — not \`../index.mjs\` — for that
846
+ specific bypass. See [Beyond this minimal slice](#beyond-this-minimal-slice) below for the two
847
+ things it does NOT yet close on its own: replaying a captured request, and spend adding up
848
+ across many separately-legal calls.
842
849
 
843
850
  ## Why this exists
844
851
 
@@ -883,10 +890,26 @@ add another protected route here rather than adding a local function back in \`i
883
890
 
884
891
  ## Beyond this minimal slice
885
892
 
886
- This gateway only re-verifies a signed request (§9.3/§9.6 of the MAGP spec). It does not do the
887
- mutual DID handshake, x402 payment binding, or commitment-bound capability tokens that a
888
- production Service integration would add see \`@metamynd/agentsafe-mcp-guard\`'s own README for
889
- those, and \`demo/duffel-mcp-gateway\` in the AgentSafe repo for a full worked example.
893
+ This gateway independently re-verifies a signed request AND binds it to the actual request body
894
+ (§9.3/§9.6 of the MAGP spec, plus payload binding \`@metamynd/agentsafe-http-gateway\` 0.2.0).
895
+ That closes the specific bypass this scaffold exists to close: an agent (or anything able to call
896
+ its code) presenting one set of values while a different set actually executes.
897
+
898
+ Two things it deliberately does NOT close, named precisely rather than left implicit:
899
+
900
+ - **Replay.** \`verifyRequest()\` checks the signed request is fresh, not that it hasn't been used
901
+ before — a captured valid request can be resent within the freshness window. Single-use nonce
902
+ consumption is the stateful issuer gate's job, not this gateway's; this scaffold never calls it.
903
+ - **Cumulative spend.** Each call is checked against the per-transaction cap correctly, but the
904
+ mandate's TOTAL budget isn't tracked here — many separately-legal calls can still add up past
905
+ it. The real total is only enforced where holds are actually reserved: \`POST
906
+ /policy/mandate/authorize\` on the issuer.
907
+
908
+ Closing both means wiring the full authorize-before-execute flow — the agent calling that
909
+ stateful endpoint first, this gateway checking a decision bound to that specific authorization —
910
+ not just re-evaluating policy per request. See \`@metamynd/agentsafe-mcp-guard\`'s own README
911
+ (mutual DID handshake, x402 payment binding, commitment-bound capability tokens) and
912
+ \`demo/duffel-mcp-gateway\` in the AgentSafe repo for what that full pattern looks like.
890
913
  `;
891
914
  }
892
915
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-metamynd-agent",
3
- "version": "0.7.1",
4
- "description": "Scaffold a MetaMynd/AgentSafe-governed AI agent in one command — logs in, provisions the agent (identity + mandate + SOP + Standards) in a single call, writes agent.metamynd.json plus a runnable agent + separate tool-gateway process (the real enforcement boundary). --harness scaffolds a free, local, zero-network governance harness instead.",
3
+ "version": "0.7.2",
4
+ "description": "Scaffold a MetaMynd/AgentSafe-governed AI agent in one command — logs in, provisions the agent (identity + mandate + SOP + Standards) in a single call, writes agent.metamynd.json plus a runnable agent + separate tool-gateway process that closes the direct-call bypass. --harness scaffolds a free, local, zero-network governance harness instead.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "create-metamynd-agent": "index.mjs"