@suveren/gateway 0.22.0 → 0.23.1

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.
@@ -6,7 +6,7 @@
6
6
  "icon": "users",
7
7
  "profile": "customers",
8
8
  "npmPackage": "@humanagencyp/crm-mcp",
9
- "npmVersion": "1.3.0",
9
+ "npmVersion": "1.4.1",
10
10
  "mcp": {
11
11
  "command": "crm-mcp",
12
12
  "args": []
@@ -41,10 +41,10 @@
41
41
  "oauth": null,
42
42
  "toolGating": {
43
43
  "default": {
44
- "executionMapping": {},
45
- "staticExecution": {
46
- "contact_type": "customer"
47
- }
44
+ "executionMapping": {
45
+ "contact_type": "contact_type"
46
+ },
47
+ "staticExecution": {}
48
48
  },
49
49
  "overrides": {
50
50
  "create_contact": {
@@ -57,54 +57,230 @@
57
57
  "actionLabel": "Contact created"
58
58
  },
59
59
  "update_contact": {
60
- "executionMapping": {},
60
+ "executionMapping": {
61
+ "contact_type": "contact_type"
62
+ },
61
63
  "staticExecution": {
62
- "contact_type": "customer",
63
64
  "action_type": "write"
64
65
  },
65
- "actionLabel": "Contact updated"
66
+ "actionLabel": "Contact updated",
67
+ "preview": {
68
+ "tool": "get_contact",
69
+ "args": {
70
+ "id": "id",
71
+ "revision": "revision"
72
+ },
73
+ "version": {
74
+ "arg": "revision",
75
+ "field": "revision"
76
+ },
77
+ "fields": [
78
+ "name",
79
+ "company",
80
+ "type",
81
+ "stage",
82
+ "email",
83
+ "archived",
84
+ "revision"
85
+ ]
86
+ }
66
87
  },
67
88
  "delete_contact": {
68
- "executionMapping": {},
89
+ "executionMapping": {
90
+ "contact_type": "contact_type"
91
+ },
92
+ "staticExecution": {
93
+ "action_type": "delete"
94
+ },
95
+ "actionLabel": "Contact archived",
96
+ "preview": {
97
+ "tool": "get_contact",
98
+ "args": {
99
+ "id": "id",
100
+ "revision": "revision"
101
+ },
102
+ "version": {
103
+ "arg": "revision",
104
+ "field": "revision"
105
+ },
106
+ "fields": [
107
+ "name",
108
+ "company",
109
+ "type",
110
+ "stage",
111
+ "email",
112
+ "archived",
113
+ "revision"
114
+ ]
115
+ }
116
+ },
117
+ "restore_contact": {
118
+ "executionMapping": {
119
+ "contact_type": "contact_type"
120
+ },
69
121
  "staticExecution": {
70
- "contact_type": "customer",
71
122
  "action_type": "delete"
72
123
  },
73
- "actionLabel": "Contact deleted"
124
+ "actionLabel": "Contact restored",
125
+ "preview": {
126
+ "tool": "get_contact",
127
+ "args": {
128
+ "id": "id",
129
+ "revision": "revision"
130
+ },
131
+ "version": {
132
+ "arg": "revision",
133
+ "field": "revision"
134
+ },
135
+ "fields": [
136
+ "name",
137
+ "company",
138
+ "type",
139
+ "stage",
140
+ "email",
141
+ "archived",
142
+ "revision"
143
+ ]
144
+ }
145
+ },
146
+ "convert_contact": {
147
+ "executionMapping": {
148
+ "contact_type": "contact_type"
149
+ },
150
+ "staticExecution": {
151
+ "action_type": "write"
152
+ },
153
+ "actionLabel": "Contact type changed",
154
+ "preview": {
155
+ "tool": "get_contact",
156
+ "args": {
157
+ "id": "id",
158
+ "revision": "revision"
159
+ },
160
+ "version": {
161
+ "arg": "revision",
162
+ "field": "revision"
163
+ },
164
+ "fields": [
165
+ "name",
166
+ "company",
167
+ "type",
168
+ "stage",
169
+ "email",
170
+ "archived",
171
+ "revision"
172
+ ]
173
+ }
74
174
  },
75
175
  "log_activity": {
76
- "executionMapping": {},
176
+ "executionMapping": {
177
+ "contact_type": "contact_type"
178
+ },
77
179
  "staticExecution": {
78
- "contact_type": "customer",
79
180
  "action_type": "write"
181
+ },
182
+ "preview": {
183
+ "tool": "get_contact",
184
+ "args": {
185
+ "id": "contact_id"
186
+ },
187
+ "fields": [
188
+ "name",
189
+ "company",
190
+ "type"
191
+ ]
80
192
  }
81
193
  },
82
194
  "create_deal": {
83
- "executionMapping": {},
195
+ "executionMapping": {
196
+ "contact_type": "contact_type"
197
+ },
84
198
  "staticExecution": {
85
- "contact_type": "customer",
86
199
  "action_type": "write"
200
+ },
201
+ "preview": {
202
+ "tool": "get_contact",
203
+ "args": {
204
+ "id": "contact_id"
205
+ },
206
+ "fields": [
207
+ "name",
208
+ "company",
209
+ "type"
210
+ ]
87
211
  }
88
212
  },
89
213
  "update_deal": {
90
- "executionMapping": {},
214
+ "executionMapping": {
215
+ "contact_type": "contact_type"
216
+ },
91
217
  "staticExecution": {
92
- "contact_type": "customer",
93
218
  "action_type": "write"
219
+ },
220
+ "preview": {
221
+ "tool": "get_deal",
222
+ "args": {
223
+ "id": "id",
224
+ "revision": "revision"
225
+ },
226
+ "version": {
227
+ "arg": "revision",
228
+ "field": "revision"
229
+ },
230
+ "fields": [
231
+ "title",
232
+ "value",
233
+ "currency",
234
+ "stage",
235
+ "expected_close",
236
+ "contact_id",
237
+ "revision"
238
+ ]
94
239
  }
95
240
  },
96
241
  "create_task": {
97
- "executionMapping": {},
242
+ "executionMapping": {
243
+ "contact_type": "contact_type"
244
+ },
98
245
  "staticExecution": {
99
- "contact_type": "customer",
100
246
  "action_type": "write"
247
+ },
248
+ "preview": {
249
+ "tool": "get_contact",
250
+ "args": {
251
+ "id": "contact_id"
252
+ },
253
+ "fields": [
254
+ "name",
255
+ "company",
256
+ "type"
257
+ ]
101
258
  }
102
259
  },
103
260
  "complete_task": {
104
- "executionMapping": {},
261
+ "executionMapping": {
262
+ "contact_type": "contact_type"
263
+ },
105
264
  "staticExecution": {
106
- "contact_type": "customer",
107
265
  "action_type": "write"
266
+ },
267
+ "preview": {
268
+ "tool": "get_task",
269
+ "args": {
270
+ "id": "id",
271
+ "revision": "revision"
272
+ },
273
+ "version": {
274
+ "arg": "revision",
275
+ "field": "revision"
276
+ },
277
+ "fields": [
278
+ "title",
279
+ "status",
280
+ "due_date",
281
+ "contact_id",
282
+ "revision"
283
+ ]
108
284
  }
109
285
  },
110
286
  "find_contacts": {
@@ -112,6 +288,11 @@
112
288
  "boundField": "read_access",
113
289
  "requiredValue": "unlimited"
114
290
  },
291
+ "get_contact": {
292
+ "category": "read",
293
+ "boundField": "read_access",
294
+ "requiredValue": "unlimited"
295
+ },
115
296
  "get_timeline": {
116
297
  "category": "read",
117
298
  "boundField": "read_access",
@@ -122,11 +303,21 @@
122
303
  "boundField": "read_access",
123
304
  "requiredValue": "unlimited"
124
305
  },
306
+ "get_deal": {
307
+ "category": "read",
308
+ "boundField": "read_access",
309
+ "requiredValue": "unlimited"
310
+ },
125
311
  "list_tasks": {
126
312
  "category": "read",
127
313
  "boundField": "read_access",
128
314
  "requiredValue": "unlimited"
129
315
  },
316
+ "get_task": {
317
+ "category": "read",
318
+ "boundField": "read_access",
319
+ "requiredValue": "unlimited"
320
+ },
130
321
  "export_crm": {
131
322
  "category": "read",
132
323
  "boundField": "export_access",
@@ -3538,10 +3538,31 @@ function createProposalStatusRouter(spUrl, vault2, dataDir, lockAsTlsMismatch2)
3538
3538
 
3539
3539
  // src/routes/evidence.ts
3540
3540
  import { Router as Router11 } from "express";
3541
- import { verifyTicketSignature, encodeDidKey } from "@hap/core";
3541
+ import { createPublicKey as createPublicKey2, verify as verifyEd25519 } from "crypto";
3542
+ import { verifyTicketSignature, encodeDidKey, canonicalize as canonicalize2 } from "@hap/core";
3542
3543
  function issuerFromPublicKeyHex(publicKeyHex) {
3543
3544
  return encodeDidKey(Buffer.from(publicKeyHex, "hex"));
3544
3545
  }
3546
+ var ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
3547
+ function isPreV07Ticket(receipt) {
3548
+ return receipt.issuer === void 0 || receipt.issuer === null;
3549
+ }
3550
+ function verifyPreV07TicketSignature(receipt, asPublicKeyHex) {
3551
+ const { signature, ...signed } = receipt;
3552
+ if (typeof signature !== "string" || !/^[0-9a-f]{64}$/i.test(asPublicKeyHex)) return false;
3553
+ try {
3554
+ const key = createPublicKey2({
3555
+ key: Buffer.concat([ED25519_SPKI_PREFIX, Buffer.from(asPublicKeyHex, "hex")]),
3556
+ format: "der",
3557
+ type: "spki"
3558
+ });
3559
+ const sig = Buffer.from(signature, "base64");
3560
+ if (sig.length !== 64) return false;
3561
+ return verifyEd25519(null, Buffer.from(canonicalize2(signed), "utf8"), key, sig);
3562
+ } catch {
3563
+ return false;
3564
+ }
3565
+ }
3545
3566
  async function verifyAll(receipts) {
3546
3567
  const out = {};
3547
3568
  for (const raw of receipts) {
@@ -3552,6 +3573,11 @@ async function verifyAll(receipts) {
3552
3573
  out[id] = "unverifiable";
3553
3574
  continue;
3554
3575
  }
3576
+ const receipt = e.receipt;
3577
+ if (isPreV07Ticket(receipt)) {
3578
+ out[id] = verifyPreV07TicketSignature(receipt, e.asPublicKey) ? "valid-legacy" : "invalid";
3579
+ continue;
3580
+ }
3555
3581
  try {
3556
3582
  await verifyTicketSignature(e.receipt, { trustedIssuers: [issuerFromPublicKeyHex(e.asPublicKey)] });
3557
3583
  out[id] = "valid";
@@ -4131,7 +4157,7 @@ async function planMandate(req, deps) {
4131
4157
  if (!isPersonal) {
4132
4158
  const cfg = await deps.as("GET", `/api/groups/${encodeURIComponent(group.id)}/profile-config/${encodeURIComponent(profile.id)}`);
4133
4159
  approvers = (cfg.status === 200 ? cfg.body?.config?.approvers : void 0) ?? [];
4134
- if (approvers.length === 0) refuse(`${name} is not enabled in "${group.name}": a team admin must name who may give ${name} mandates.`);
4160
+ if (approvers.length === 0) refuse(`${name} ${versionOf(profile.id)} is not enabled in "${group.name}". Ask an admin of "${group.name}" to enable ${name} ${versionOf(profile.id)} and name who may give its mandates.`);
4135
4161
  if (!approvers.includes(user.id)) refuse(`Only ${name}'s approvers in "${group.name}" can give this mandate, and the signed-in person is not one of them.`);
4136
4162
  }
4137
4163
  const bounds = { ...scalarRecord("limits", req.limits), profile: profile.id };
@@ -3270,6 +3270,9 @@ function mapPreviewArgs(preview, actionArgs) {
3270
3270
  }
3271
3271
  return mapped;
3272
3272
  }
3273
+ function previewHasNoTarget(preview, mapped) {
3274
+ return Object.keys(preview.args).length > 0 && Object.keys(mapped).length === 0;
3275
+ }
3273
3276
  var PreviewTimeoutError = class extends Error {
3274
3277
  };
3275
3278
  function withTimeout(p, ms) {
@@ -3322,6 +3325,7 @@ async function computeSubmissionPreviewHash(integrationManager2, integrationId,
3322
3325
  const preview = getToolPreviewConfig(integrationId, toolName);
3323
3326
  if (!preview || preview.version) return void 0;
3324
3327
  const mapped = mapPreviewArgs(preview, actionArgs);
3328
+ if (previewHasNoTarget(preview, mapped)) return void 0;
3325
3329
  const read = await readPreview(integrationManager2, integrationId, preview.tool, mapped);
3326
3330
  if (read.status !== "ok") return void 0;
3327
3331
  return hashPreviewBody(read.body);
@@ -3338,6 +3342,7 @@ async function buildInternalPreview(integrationManager2, integrationId, toolName
3338
3342
  const preview = getToolPreviewConfig(integrationId, toolName);
3339
3343
  if (!preview) return { status: "none" };
3340
3344
  const mappedArgs = mapPreviewArgs(preview, actionArgs);
3345
+ if (previewHasNoTarget(preview, mappedArgs)) return { status: "none", reason: "no_target" };
3341
3346
  const read1 = await readPreview(integrationManager2, integrationId, preview.tool, mappedArgs);
3342
3347
  if (read1.status !== "ok") return read1;
3343
3348
  const ok = (extra = {}) => ({