create-metamynd-agent 0.12.2 → 0.13.0
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.
- package/README.md +24 -6
- package/index.mjs +75 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,11 +10,14 @@ default, a second `gateway/` process** built on
|
|
|
10
10
|
The agent's own `guardTool()` call is a fast, local, client-side check; the gateway is the real
|
|
11
11
|
enforcement boundary — see [Separate tool gateway](#separate-tool-gateway-default) below.
|
|
12
12
|
|
|
13
|
-
> **Prerequisite:** an agent is always owned by a person/org with a **MetaMynd account**.
|
|
14
|
-
>
|
|
15
|
-
>
|
|
16
|
-
>
|
|
17
|
-
>
|
|
13
|
+
> **Prerequisite:** an agent is always owned by a person/org with a **MetaMynd account**. The hosted
|
|
14
|
+
> flow provisions under your account's **verified principal** (KYC/KYB; on a beta deployment the
|
|
15
|
+
> platform can auto-approve one on first use) — if there is none, provisioning stops with "complete
|
|
16
|
+
> KYC/KYB first". That is all it needs: this CLI always provisions **Testnet** agents, so mainnet
|
|
17
|
+
> eligibility is not required. A mainnet agent is launched from the dashboard's **Launchpad**
|
|
18
|
+
> (`/dashboard/launchpad`) and needs a **mainnet-eligible** principal (verified by the identity
|
|
19
|
+
> provider, or reviewed by a person on the platform's team). `--harness` and `--sandbox` need no
|
|
20
|
+
> account or verification at all.
|
|
18
21
|
|
|
19
22
|
## Free local harness (no account, no network, `--harness`)
|
|
20
23
|
|
|
@@ -322,7 +325,8 @@ with the default hosted flow (login + provision):
|
|
|
322
325
|
never faked, still enforced.
|
|
323
326
|
- **The generated README lists the request fields your rules read** (`consent`, `piiPresent`,
|
|
324
327
|
`jurisdiction`, …). An allow-list, consent or PII rule does not fire when its field is absent, so
|
|
325
|
-
your application must supply it. These fields are asserted by the calling agent
|
|
328
|
+
your application must supply it. These fields are asserted by the calling agent — except
|
|
329
|
+
`jurisdiction`, which is signed (see [Jurisdiction](#jurisdiction-signed-since-0130)).
|
|
326
330
|
|
|
327
331
|
**Hosted specifics.** The default shape is still agent + `gateway/`. The gateway runs with
|
|
328
332
|
`requireAuthorization: false` and a route with no value fields: the guard only seals a single-use
|
|
@@ -399,6 +403,20 @@ polls until the owner approves, then scaffolds the project (the same default two
|
|
|
399
403
|
the full flow above — `--no-gateway`/`--gateway-port` work here too). With `--byok` the keypair is
|
|
400
404
|
generated locally and control is proven on claim — MetaMynd never sees the private key.
|
|
401
405
|
|
|
406
|
+
## Jurisdiction (signed, since 0.13.0)
|
|
407
|
+
|
|
408
|
+
The scaffolded agents pass a request's `jurisdiction` (ISO 3166-1 alpha-2) as the guard's **signed** top-level field
|
|
409
|
+
(MAGP §8.3.12), not as context: the generated `mapArgs` is `({ jurisdiction, ...context }) => ({ jurisdiction, context })`,
|
|
410
|
+
and the gateway call signs it the same way. The gate (and the harness's local check) judges jurisdiction rules on the
|
|
411
|
+
signed value only and ignores one in the context. Scaffolds pin `@metamynd/agentsafe-guard` ^0.16.0,
|
|
412
|
+
`@metamynd/agentsafe-mcp-guard` ^0.16.0 and `@metamynd/agentsafe-http-gateway` ^0.14.0, which sign and verify it.
|
|
413
|
+
|
|
414
|
+
- A value that is not two ASCII letters is refused before anything is sent (`MALFORMED_REQUEST`).
|
|
415
|
+
- **A registered payee's country wins**: a signed value that differs is refused `JURISDICTION_MISMATCH`.
|
|
416
|
+
- A jurisdiction rule with none signed is refused `JURISDICTION_REQUIRED`; a value off the mandate's list is
|
|
417
|
+
`JURISDICTION_NOT_ALLOWED`. The demo stages a jurisdiction rule with a user-assigned code (`ZZ`) off the list, and
|
|
418
|
+
stages nothing when no two-letter code is on every jurisdiction allow-list (no passing request can exist).
|
|
419
|
+
|
|
402
420
|
## Risk: say it, or have your owner set it
|
|
403
421
|
|
|
404
422
|
The starter rules include a high-risk review. A request that sends **no** `riskLevel` (or an unrecognised one)
|
package/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// create-metamynd-agent — scaffold a MetaMynd/AgentSafe-governed agent in one command.
|
|
3
3
|
//
|
|
4
|
-
// Logs
|
|
4
|
+
// Logs the owner in (provisioning uses the owner's verified principal; the agent is always
|
|
5
|
+
// Testnet — mainnet goes through the dashboard Launchpad), provisions the agent in ONE call
|
|
5
6
|
// (POST /onboarding/agent → identity + mandate + starter SOP + enforced Standards),
|
|
6
7
|
// writes the portable `agent.metamynd.json` and a runnable agent example, PLUS (by default)
|
|
7
8
|
// a separate `gateway/` process — a second, independent guard that re-verifies every request
|
|
@@ -53,7 +54,9 @@ const GUARD_PKG = '@metamynd/agentsafe-guard';
|
|
|
53
54
|
// requires request inputs blocks a bare baseline request).
|
|
54
55
|
// 0.12.4 makes `verify` probe in the currency the mandate's caps name (it assumed USD), which a scaffolded
|
|
55
56
|
// non-USD agent's `npm test` needs.
|
|
56
|
-
|
|
57
|
+
// 0.16.0 signs an optional top-level `jurisdiction` (MAGP 8.3.12, the v2 message) — the scaffolded non-financial agent
|
|
58
|
+
// passes a request's jurisdiction that way, since the gate no longer reads one from the unsigned context.
|
|
59
|
+
const GUARD_VERSION = '^0.16.0';
|
|
57
60
|
/** The harness entry point's config load, shared by both harness templates: a fresh clone has no
|
|
58
61
|
* agent.metamynd.json (it is gitignored), so say what to do instead of a bare ENOENT (BR-004). */
|
|
59
62
|
function harnessConfigLoad() {
|
|
@@ -102,7 +105,15 @@ const MCP_GUARD_PKG = '@metamynd/agentsafe-mcp-guard';
|
|
|
102
105
|
// 0.6.0 brings buildAuthMessage's `resource` field and buildLocalDecisionMessage into this
|
|
103
106
|
// package's own bundled policy-core.mjs (alongside the guard's own 0.10.0) — no scaffolded
|
|
104
107
|
// template code changes, but the floor must still cover the real current version.
|
|
105
|
-
|
|
108
|
+
// 0.13.0: a daemon-held service key (keyProvider: 'daemon') now signs claims and settlements as the gateway's
|
|
109
|
+
// DID instead of claiming anonymously — refused on every mainnet hold before. No template change.
|
|
110
|
+
// 0.14.0: the claim can declare an x402 payment (x402: true) so the issuer observes lowered settlements. No template
|
|
111
|
+
// change (the scaffolded gateways don't pay by x402), but the floor must cover the real current version.
|
|
112
|
+
// 0.15.0: payloadDigestOf/toWireJson exported and refundAuthorization (its own signed `refund` action). No template
|
|
113
|
+
// change (the scaffolded gateways don't refund), but the floor must cover the real current version.
|
|
114
|
+
// 0.16.0: verifies a v2 (signed-jurisdiction) request and judges jurisdiction rules on the signed value only. Required:
|
|
115
|
+
// the scaffolded agent now signs jurisdiction, which an older gateway would refuse SIGNATURE_INVALID.
|
|
116
|
+
const MCP_GUARD_VERSION = '^0.16.0';
|
|
106
117
|
const GATEWAY_PKG = '@metamynd/agentsafe-http-gateway';
|
|
107
118
|
// 0.2.0 fixes a confused-deputy gap (payload not bound to the signed request) — the CLI must
|
|
108
119
|
// never scaffold a range that could resolve below it.
|
|
@@ -114,7 +125,11 @@ const GATEWAY_PKG = '@metamynd/agentsafe-http-gateway';
|
|
|
114
125
|
// 0.5.0 adds the OPTIONAL Credential Vault `resolveCredential` hook on createHttpGateway (Module
|
|
115
126
|
// G) — additive and backward-compatible (every existing consumer sees zero behavior change), but
|
|
116
127
|
// the floor must still cover the real current version per this repo's own package-version check.
|
|
117
|
-
|
|
128
|
+
// 0.12.0: per-route `x402: true` declares an x402 payment on the claim. No template change.
|
|
129
|
+
// 0.13.0: a configured resolveCredential that refuses now FAILS CLOSED (502 CREDENTIAL_UNAVAILABLE) instead of forwarding
|
|
130
|
+
// without a credential. No template change (the scaffolded gateway does not use the Credential Vault).
|
|
131
|
+
// 0.14.0: depends on agentsafe-mcp-guard ^0.16.0 (verifies a signed-jurisdiction request). No template change.
|
|
132
|
+
const GATEWAY_VERSION = '^0.14.0';
|
|
118
133
|
const DEFAULT_API = 'https://metamynd.ai/api/v1';
|
|
119
134
|
const DEFAULT_GATEWAY_PORT = 4401; // distinct from --harness's dashboard (4400)
|
|
120
135
|
|
|
@@ -219,11 +234,13 @@ ${c.b('Environment')}
|
|
|
219
234
|
${c.b('Network')}
|
|
220
235
|
Every hosted agent this CLI provisions is a ${c.b('Testnet')} agent, whatever your verification status —
|
|
221
236
|
there is deliberately no mainnet flag. To launch a ${c.b('Mainnet')} agent, use the Launchpad in the
|
|
222
|
-
dashboard (https://metamynd.ai/dashboard/launchpad): its Mainnet option
|
|
223
|
-
|
|
237
|
+
dashboard (https://metamynd.ai/dashboard/launchpad): its Mainnet option needs a mainnet-eligible
|
|
238
|
+
principal (verified by the identity provider, or reviewed by a person on the platform's team).
|
|
224
239
|
|
|
225
240
|
${c.b('What it does')}
|
|
226
|
-
1. Logs in as
|
|
241
|
+
1. Logs in as the owner → owner access token
|
|
242
|
+
(provisioning uses your account's verified principal — KYC/KYB, or one the platform
|
|
243
|
+
auto-approves on a beta deployment; mainnet eligibility is NOT needed for Testnet)
|
|
227
244
|
2. POST /onboarding/agent (one call) → identity + mandate + SOP + Standards
|
|
228
245
|
3. Writes agent.metamynd.json + index.mjs, PLUS (by default) a separate gateway/ process —
|
|
229
246
|
the real enforcement boundary, not index.mjs's own guard.guardTool() call. --no-gateway
|
|
@@ -483,7 +500,16 @@ const ATOM_DEMO = {
|
|
|
483
500
|
fire: (cfg) => ({ riskLevel: cfg?.level ?? 'high' }),
|
|
484
501
|
says: (cfg) => 'the risk level is ' + (cfg?.level ?? 'high') + ' or above',
|
|
485
502
|
},
|
|
486
|
-
|
|
503
|
+
// The jurisdiction is SIGNED, so it must be a real two-letter code (MAGP 8.3.12): a user-assigned ISO code the list omits.
|
|
504
|
+
'jurisdiction-not-allowed': {
|
|
505
|
+
field: 'jurisdiction',
|
|
506
|
+
fire: (cfg) => {
|
|
507
|
+
const allowed = new Set((Array.isArray(cfg?.allowed) ? cfg.allowed : []).map((c) => String(c).toUpperCase()));
|
|
508
|
+
const code = ['ZZ', 'XX', 'QZ', 'XZ'].find((c) => !allowed.has(c));
|
|
509
|
+
return code ? { jurisdiction: code } : null;
|
|
510
|
+
},
|
|
511
|
+
says: () => 'the jurisdiction is not on the allowed list',
|
|
512
|
+
},
|
|
487
513
|
'data-residency-violation': { field: 'dataResidency', fire: () => ({ dataResidency: 'zz-not-allowed' }), says: () => 'the data would be stored outside the allowed regions' },
|
|
488
514
|
'model-not-allowed': { field: 'model', fire: () => ({ model: 'unlisted-model' }), says: () => 'the model is not on the allowed list' },
|
|
489
515
|
'tool-not-allowed': { field: 'tool', fire: () => ({ tool: 'unlisted-tool' }), says: () => 'the tool is not on the allowed list' },
|
|
@@ -505,6 +531,8 @@ const ATOM_DEMO = {
|
|
|
505
531
|
},
|
|
506
532
|
};
|
|
507
533
|
|
|
534
|
+
const TWO_LETTERS = /^[A-Za-z]{2}$/;
|
|
535
|
+
|
|
508
536
|
// [predicate, request field, config key holding the allow-list, exact (case-sensitive) match?]
|
|
509
537
|
// data-source-not-approved compares exactly; the other allow-list atoms compare case-insensitively.
|
|
510
538
|
const ALLOW_LISTS = [
|
|
@@ -603,8 +631,23 @@ function buildPolicyCases(molecules, { maxCases = 8 } = {}) {
|
|
|
603
631
|
const lists = configsOf(pred).map((cfg) => (Array.isArray(cfg[key]) ? cfg[key].map(String) : []));
|
|
604
632
|
if (!lists.length || lists.some((l) => l.length === 0)) continue;
|
|
605
633
|
const norm = (v) => (exact ? v : v.toLowerCase().trim());
|
|
606
|
-
|
|
607
|
-
|
|
634
|
+
// The jurisdiction is SIGNED (MAGP 8.3.12), so only a real two-letter code can be sent at all.
|
|
635
|
+
const sendable = (v) => field !== 'jurisdiction' || TWO_LETTERS.test(v.trim());
|
|
636
|
+
const common = lists[0].find((v) => sendable(v) && lists.every((l) => l.some((x) => norm(x) === norm(v))));
|
|
637
|
+
if (common !== undefined) base[field] = field === 'jurisdiction' ? common.trim().toUpperCase() : common;
|
|
638
|
+
}
|
|
639
|
+
// A jurisdiction rule that can refuse makes the field REQUIRED: the gate (and the guard's local check) refuses a request
|
|
640
|
+
// that signs none with JURISDICTION_REQUIRED. With no code on every list, no request can pass — stage nothing, truthfully.
|
|
641
|
+
const jurisdictionEnforced = live.some((m) => m.decision !== 'observe' && m.atoms.some((a) => a.predicate === 'jurisdiction-not-allowed'));
|
|
642
|
+
if (jurisdictionEnforced && base.jurisdiction === undefined) {
|
|
643
|
+
return {
|
|
644
|
+
cases: [],
|
|
645
|
+
inputs,
|
|
646
|
+
notDemonstrated: molecules.map((m) => ({
|
|
647
|
+
rule: label(m),
|
|
648
|
+
why: 'no two-letter jurisdiction is on every jurisdiction allow-list, and a request that signs none is refused JURISDICTION_REQUIRED, so the demo cannot stage a passing request',
|
|
649
|
+
})),
|
|
650
|
+
};
|
|
608
651
|
}
|
|
609
652
|
const evidenceCfgs = configsOf('evidence-requirement');
|
|
610
653
|
if (evidenceCfgs.length) base.evidenceTypes = [...new Set(evidenceCfgs.flatMap((cfg) => (Array.isArray(cfg.required) ? cfg.required.map(String) : [])))];
|
|
@@ -1240,7 +1283,8 @@ ${withGateway ? `const GATEWAY = process.env.GATEWAY_URL || 'http://localhost:${
|
|
|
1240
1283
|
// --- this file to call directly — the tool, and any real credentials it needs, live only in
|
|
1241
1284
|
// --- ./gateway, which independently re-verifies this signed request itself.
|
|
1242
1285
|
async function performViaGateway(args, decision) {
|
|
1243
|
-
const
|
|
1286
|
+
const { jurisdiction, ...context } = args; // the jurisdiction is SIGNED (a top-level field), never context
|
|
1287
|
+
const signed = await guard.buildSignedRequest({ action: '${scope}', merchant: MERCHANT, jurisdiction, context });
|
|
1244
1288
|
signed.authorizationId = decision?.authorizationId; // none for a value-less action — see ./gateway/README.md
|
|
1245
1289
|
const res = await fetch(GATEWAY + '/perform', {
|
|
1246
1290
|
method: 'POST',
|
|
@@ -1266,11 +1310,12 @@ async function performAction(args) {
|
|
|
1266
1310
|
}
|
|
1267
1311
|
`}
|
|
1268
1312
|
// --- The GATED version. Register THIS with your agent instead of the raw handler. ---
|
|
1269
|
-
// The request's own fields (consent, piiPresent,
|
|
1313
|
+
// The request's own fields (consent, piiPresent, ...) travel as the gate's \`context\`. \`jurisdiction\` is the
|
|
1314
|
+
// exception: it is SIGNED (a top-level field, ISO 3166-1 alpha-2) — the gate ignores one in the unsigned context.
|
|
1270
1315
|
const gatedAction = guard.guardTool(
|
|
1271
1316
|
'${scope}', // = your mandate scope
|
|
1272
1317
|
${withGateway ? 'performViaGateway' : 'performAction'},
|
|
1273
|
-
(
|
|
1318
|
+
({ jurisdiction, ...context }) => ({ merchant: MERCHANT, jurisdiction, context }), // map tool args → gate inputs
|
|
1274
1319
|
);
|
|
1275
1320
|
|
|
1276
1321
|
// --- An action the agent was NEVER granted. Wrapping it is the demonstration: no rule anywhere
|
|
@@ -1500,8 +1545,9 @@ a forged bundle with a higher cap or no rules; \`server.mjs\` refuses an unsigne
|
|
|
1500
1545
|
|
|
1501
1546
|
**NOT closed — be precise about this:**
|
|
1502
1547
|
|
|
1503
|
-
- **Rule inputs are not signed
|
|
1504
|
-
|
|
1548
|
+
- **Rule inputs are not signed** — except \`jurisdiction\`, which this agent signs (MAGP 8.3.12; a
|
|
1549
|
+
registered payee's country overrides it at the gate). The other fields your rules read (\`consent\`,
|
|
1550
|
+
\`piiPresent\`, …) travel in the request's \`itinerary\`, which the signature does not cover, and
|
|
1505
1551
|
the body the tool executes is not bound to it (\`valueFields: []\`). An agent that CAN sign — a
|
|
1506
1552
|
dishonest one, or a compromised one — can omit a field or send a different one, and the rule that
|
|
1507
1553
|
reads it will not fire: an allow-list, consent or PII rule treats an absent field as "nothing to
|
|
@@ -1589,8 +1635,9 @@ these (the demo in \`index.mjs\` does):
|
|
|
1589
1635
|
${demo.inputs.map((i) => `- \`${i.field}\` — ${i.rules.join(', ')}`).join('\n') || '- (none — your rules read no request fields)'}
|
|
1590
1636
|
|
|
1591
1637
|
**A missing field is not a violation** for an allow-list, consent or PII rule: if your application
|
|
1592
|
-
forgets to send \`
|
|
1593
|
-
|
|
1638
|
+
forgets to send \`consent\`, that rule simply does not fire. Make sure the field is always present.
|
|
1639
|
+
(\`jurisdiction\` is different: it is signed, and a jurisdiction rule with none signed is refused
|
|
1640
|
+
\`JURISDICTION_REQUIRED\`.) These fields are asserted by the calling agent and are not covered by its signature —
|
|
1594
1641
|
an agent that can sign could omit or forge one, and the rule would not fire. Source them from a system you
|
|
1595
1642
|
control, not from model output.${demo.notDemonstrated.length ? `
|
|
1596
1643
|
|
|
@@ -3088,7 +3135,8 @@ ${withGateway ? `console.log(dim(' gateway : http://localhost:${gatewayPort} (
|
|
|
3088
3135
|
// takes effect on the next decision, no restart. The gateway process (when scaffolded) reads the SAME file.
|
|
3089
3136
|
const getBundle = () => JSON.parse(readFileSync('./metamynd-rules.json', 'utf8'));
|
|
3090
3137
|
|
|
3091
|
-
// The request's own fields (consent, piiPresent,
|
|
3138
|
+
// The request's own fields (consent, piiPresent, ...) travel as the gate's \`context\`. \`jurisdiction\` is the exception:
|
|
3139
|
+
// it is SIGNED (a top-level field, ISO 3166-1 alpha-2) and rules judge only that one, never a context value.
|
|
3092
3140
|
const MERCHANT = ${merchant ? JSON.stringify(merchant) : 'undefined'};
|
|
3093
3141
|
${withGateway ? `const GATEWAY = process.env.HARNESS_GATEWAY_URL || 'http://localhost:${gatewayPort}';
|
|
3094
3142
|
// Calls the gateway process instead of a local function — there is no raw performAction() in THIS
|
|
@@ -3097,7 +3145,8 @@ ${withGateway ? `const GATEWAY = process.env.HARNESS_GATEWAY_URL || 'http://loca
|
|
|
3097
3145
|
async function callGateway(path, action, args) {
|
|
3098
3146
|
// The body is empty on purpose (this tool reads nothing from it), and it is signed as the payload so the gateway can
|
|
3099
3147
|
// require binding on every route: a body with anything in it is not the one signed (MAGP 8.3.9).
|
|
3100
|
-
const
|
|
3148
|
+
const { jurisdiction, ...context } = args;
|
|
3149
|
+
const signed = await guard.buildSignedRequest({ action, merchant: MERCHANT, jurisdiction, context, payload: {} });
|
|
3101
3150
|
const res = await fetch(GATEWAY + path, { method: 'POST', headers: { 'content-type': 'application/json', 'x-magp-request': JSON.stringify(signed) }, body: '{}' });
|
|
3102
3151
|
const body = await res.json().catch(() => null);
|
|
3103
3152
|
if (!res.ok) {
|
|
@@ -3117,7 +3166,7 @@ async function performAction(args) {
|
|
|
3117
3166
|
const gatedAction = guard.guardToolLocal(
|
|
3118
3167
|
'${scope}', // = your mandate scope
|
|
3119
3168
|
${withGateway ? `(args) => callGateway('/perform', '${scope}', args)` : 'performAction'},
|
|
3120
|
-
(
|
|
3169
|
+
({ jurisdiction, ...context }) => ({ merchant: MERCHANT, jurisdiction, context }), // map tool args → gate inputs
|
|
3121
3170
|
getBundle,
|
|
3122
3171
|
);
|
|
3123
3172
|
|
|
@@ -3297,8 +3346,9 @@ of these (the demo in \`index.mjs\` does):
|
|
|
3297
3346
|
${demo.inputs.map((i) => `- \`${i.field}\` — ${i.rules.join(', ')}`).join('\n') || '- (none — your rules read no request fields)'}
|
|
3298
3347
|
|
|
3299
3348
|
**A missing field is not a violation** for an allow-list, consent or PII rule: if your application
|
|
3300
|
-
forgets to send \`
|
|
3301
|
-
|
|
3349
|
+
forgets to send \`consent\`, that rule simply does not fire. Make sure the field is always present.
|
|
3350
|
+
(\`jurisdiction\` is different: it is signed, and a jurisdiction rule with none signed is refused
|
|
3351
|
+
\`JURISDICTION_REQUIRED\`.)${demo.notDemonstrated.length ? `
|
|
3302
3352
|
|
|
3303
3353
|
Rules the demo does not stage (they are still enforced):
|
|
3304
3354
|
|
|
@@ -3323,9 +3373,9 @@ runs, and so is any top-level body key you did not list in that route's \`allowe
|
|
|
3323
3373
|
(\`PAYLOAD_UNBINDABLE\`) — nothing signed covers it. When your real tool reads more body fields, list exactly
|
|
3324
3374
|
those keys; the gateway refuses the rest.${neutral ? `
|
|
3325
3375
|
|
|
3326
|
-
**Also NOT closed — rule inputs are not signed
|
|
3327
|
-
\`
|
|
3328
|
-
not cover. An agent that can sign could omit a field or send a different one, and the rule that reads
|
|
3376
|
+
**Also NOT closed — rule inputs are not signed** (except \`jurisdiction\`, a signed top-level field).
|
|
3377
|
+
The other request fields your rules read (\`consent\`, \`piiPresent\`, …) travel in the signed request's
|
|
3378
|
+
context, which the signature does not cover. An agent that can sign could omit a field or send a different one, and the rule that reads
|
|
3329
3379
|
it would not fire. The gateway enforces scope and identity firmly; an input-dependent rule is only as
|
|
3330
3380
|
strong as whatever supplies its input.` : ''}
|
|
3331
3381
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-metamynd-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
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 direct-call, confused-deputy, replay, and cumulative-spend bypasses. --harness scaffolds a free, local, zero-network governance harness instead.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|