@suveren/gateway 0.29.1 → 0.31.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.
Files changed (51) hide show
  1. package/content/integrations/calendar.json +3 -0
  2. package/content/integrations/crm.json +10 -0
  3. package/content/integrations/deploy-github.json +1 -0
  4. package/content/integrations/erp.json +4 -0
  5. package/content/integrations/gmail.json +4 -0
  6. package/content/integrations/linkedin.json +4 -0
  7. package/content/integrations/mail.json +1 -0
  8. package/content/integrations/mollie.json +5 -0
  9. package/content/integrations/records.json +4 -0
  10. package/dist/control-plane/index.mjs +151 -32
  11. package/dist/mcp-server/http.mjs +156 -37
  12. package/dist/ui/assets/index-B7qy0B9J.js +123 -0
  13. package/dist/ui/assets/index-DyZY5sLI.css +1 -0
  14. package/dist/ui/index.html +2 -2
  15. package/node_modules/qs/.github/THREAT_MODEL.md +4 -2
  16. package/node_modules/qs/CHANGELOG.md +38 -14
  17. package/node_modules/qs/README.md +31 -3
  18. package/node_modules/qs/dist/qs.js +20 -20
  19. package/node_modules/qs/lib/parse.js +94 -4
  20. package/node_modules/qs/lib/stringify.js +4 -4
  21. package/node_modules/qs/lib/utils.js +130 -6
  22. package/node_modules/qs/package.json +4 -4
  23. package/node_modules/qs/test/parse.js +174 -0
  24. package/node_modules/qs/test/stringify.js +263 -33
  25. package/node_modules/qs/test/utils.js +184 -0
  26. package/node_modules/undici/docs/docs/api/Client.md +2 -0
  27. package/node_modules/undici/lib/core/connect.js +10 -4
  28. package/node_modules/undici/lib/core/symbols.js +1 -0
  29. package/node_modules/undici/lib/dispatcher/agent.js +6 -2
  30. package/node_modules/undici/lib/dispatcher/client-h1.js +0 -2
  31. package/node_modules/undici/lib/dispatcher/client-h2.js +0 -4
  32. package/node_modules/undici/lib/dispatcher/client.js +3 -2
  33. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +12 -0
  34. package/node_modules/undici/lib/handler/cache-handler.js +48 -0
  35. package/node_modules/undici/lib/handler/deduplication-handler.js +57 -13
  36. package/node_modules/undici/lib/handler/redirect-handler.js +8 -1
  37. package/node_modules/undici/lib/interceptor/decompress.js +15 -5
  38. package/node_modules/undici/lib/web/cookies/index.js +3 -1
  39. package/node_modules/undici/lib/web/cookies/parse.js +138 -137
  40. package/node_modules/undici/lib/web/cookies/util.js +21 -2
  41. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +90 -9
  42. package/node_modules/undici/lib/web/eventsource/eventsource.js +4 -1
  43. package/node_modules/undici/lib/web/fetch/index.js +3 -3
  44. package/node_modules/undici/lib/web/infra/index.js +14 -0
  45. package/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +5 -5
  46. package/node_modules/undici/lib/web/websocket/receiver.js +13 -0
  47. package/node_modules/undici/package.json +1 -1
  48. package/node_modules/undici/types/client.d.ts +14 -0
  49. package/package.json +1 -1
  50. package/dist/ui/assets/index-DUIlMVlP.css +0 -1
  51. package/dist/ui/assets/index-wtX8LuiU.js +0 -123
@@ -122,6 +122,7 @@
122
122
  }
123
123
  },
124
124
  "create_event": {
125
+ "summary": "Event: {summary|short}[ on {start.dateTime,start.date|date}]",
125
126
  "executionMapping": {
126
127
  "duration_minutes": "duration",
127
128
  "lookahead_days": "lookahead",
@@ -143,6 +144,7 @@
143
144
  "actionLabel": "Event created"
144
145
  },
145
146
  "update_event": {
147
+ "summary": "Update event[: {summary|short}]",
146
148
  "executionMapping": {
147
149
  "attendees": [
148
150
  {
@@ -164,6 +166,7 @@
164
166
  "actionLabel": "Event updated"
165
167
  },
166
168
  "delete_event": {
169
+ "summary": "Delete an event",
167
170
  "executionMapping": {
168
171
  "calendarId": "allowed_calendars"
169
172
  },
@@ -74,6 +74,7 @@
74
74
  },
75
75
  "overrides": {
76
76
  "create_contact": {
77
+ "summary": "Create contact {name}[ ({company})]",
77
78
  "executionMapping": {
78
79
  "type": "contact_type"
79
80
  },
@@ -94,6 +95,7 @@
94
95
  }
95
96
  },
96
97
  "update_contact": {
98
+ "summary": "Update contact {name,id}",
97
99
  "executionMapping": {
98
100
  "contact_type": "contact_type"
99
101
  },
@@ -123,6 +125,7 @@
123
125
  }
124
126
  },
125
127
  "delete_contact": {
128
+ "summary": "Archive a {contact_type} contact",
126
129
  "executionMapping": {
127
130
  "contact_type": "contact_type"
128
131
  },
@@ -152,6 +155,7 @@
152
155
  }
153
156
  },
154
157
  "restore_contact": {
158
+ "summary": "Restore a {contact_type} contact",
155
159
  "executionMapping": {
156
160
  "contact_type": "contact_type"
157
161
  },
@@ -181,6 +185,7 @@
181
185
  }
182
186
  },
183
187
  "convert_contact": {
188
+ "summary": "Convert a contact to {to_type}",
184
189
  "executionMapping": {
185
190
  "contact_type": "contact_type"
186
191
  },
@@ -210,6 +215,7 @@
210
215
  }
211
216
  },
212
217
  "log_activity": {
218
+ "summary": "Log {type}: {summary|short}",
213
219
  "executionMapping": {
214
220
  "contact_type": "contact_type"
215
221
  },
@@ -229,6 +235,7 @@
229
235
  }
230
236
  },
231
237
  "create_deal": {
238
+ "summary": "Create deal: {title|short}[ — {value|money}]",
232
239
  "executionMapping": {
233
240
  "contact_type": "contact_type"
234
241
  },
@@ -248,6 +255,7 @@
248
255
  }
249
256
  },
250
257
  "update_deal": {
258
+ "summary": "Update deal[: {title|short}][ — {value|money}]",
251
259
  "executionMapping": {
252
260
  "contact_type": "contact_type"
253
261
  },
@@ -276,6 +284,7 @@
276
284
  }
277
285
  },
278
286
  "create_task": {
287
+ "summary": "Create task: {title|short}[ (due {due_date|date})]",
279
288
  "executionMapping": {
280
289
  "contact_type": "contact_type"
281
290
  },
@@ -295,6 +304,7 @@
295
304
  }
296
305
  },
297
306
  "complete_task": {
307
+ "summary": "Complete a task",
298
308
  "executionMapping": {
299
309
  "contact_type": "contact_type"
300
310
  },
@@ -78,6 +78,7 @@
78
78
  }
79
79
  },
80
80
  "release": {
81
+ "summary": "Release {repo} to {environment}",
81
82
  "executionMapping": {
82
83
  "repo": "allowed_repos",
83
84
  "environment": "allowed_environments",
@@ -99,6 +99,7 @@
99
99
  "requiredValue": "unlimited"
100
100
  },
101
101
  "create_quote": {
102
+ "summary": "Quote of {value|money} net[ — {discount_pct|percent} discount]",
102
103
  "executionMapping": {
103
104
  "value": "value",
104
105
  "discount_pct": "discount_pct",
@@ -133,6 +134,7 @@
133
134
  }
134
135
  },
135
136
  "update_quote": {
137
+ "summary": "Update quote to {value|money} net[ — {discount_pct|percent} discount]",
136
138
  "executionMapping": {
137
139
  "value": "value",
138
140
  "discount_pct": "discount_pct",
@@ -161,6 +163,7 @@
161
163
  }
162
164
  },
163
165
  "send_quote": {
166
+ "summary": "Send quote of {value|money} net[ — {discount_pct|percent} discount]",
164
167
  "executionMapping": {
165
168
  "value": "value",
166
169
  "discount_pct": "discount_pct",
@@ -179,6 +182,7 @@
179
182
  }
180
183
  },
181
184
  "convert_quote_to_order": {
185
+ "summary": "Order of {value|money} net from a quote",
182
186
  "executionMapping": {
183
187
  "value": "value",
184
188
  "discount_pct": "discount_pct",
@@ -80,6 +80,7 @@
80
80
  },
81
81
  "overrides": {
82
82
  "send_message": {
83
+ "summary": "Email to {to|list}: {subject|short}",
83
84
  "executionMapping": {
84
85
  "to": [
85
86
  {
@@ -108,6 +109,7 @@
108
109
  "actionLabel": "Email sent"
109
110
  },
110
111
  "create_draft": {
112
+ "summary": "Draft email to {to|list}[: {subject|short}]",
111
113
  "executionMapping": {
112
114
  "to": [
113
115
  {
@@ -136,6 +138,7 @@
136
138
  "actionLabel": "Email drafted"
137
139
  },
138
140
  "send_draft": {
141
+ "summary": "Send a draft email",
139
142
  "executionMapping": {},
140
143
  "staticExecution": {
141
144
  "recipient_count": 1,
@@ -206,6 +209,7 @@
206
209
  }
207
210
  },
208
211
  "delete_draft": {
212
+ "summary": "Delete a draft email",
209
213
  "executionMapping": {},
210
214
  "staticExecution": {
211
215
  "recipient_count": 0,
@@ -62,6 +62,7 @@
62
62
  },
63
63
  "overrides": {
64
64
  "create_post": {
65
+ "summary": "LinkedIn post: {text|short}",
65
66
  "executionMapping": {
66
67
  "visibility": "audience"
67
68
  },
@@ -73,6 +74,7 @@
73
74
  "actionLabel": "Post published"
74
75
  },
75
76
  "create_image_post": {
77
+ "summary": "LinkedIn image post: {text|short}",
76
78
  "executionMapping": {
77
79
  "visibility": "audience"
78
80
  },
@@ -84,6 +86,7 @@
84
86
  "actionLabel": "Image post published"
85
87
  },
86
88
  "create_article_post": {
89
+ "summary": "LinkedIn article: {title,articleUrl|short}",
87
90
  "executionMapping": {
88
91
  "visibility": "audience"
89
92
  },
@@ -95,6 +98,7 @@
95
98
  "actionLabel": "Article published"
96
99
  },
97
100
  "delete_post": {
101
+ "summary": "Delete a LinkedIn post",
98
102
  "executionMapping": {},
99
103
  "staticExecution": {
100
104
  "allowed_platforms": "linkedin",
@@ -79,6 +79,7 @@
79
79
  }
80
80
  },
81
81
  "send_message": {
82
+ "summary": "Email to {to|list}: {subject|short}",
82
83
  "executionMapping": {
83
84
  "to": [
84
85
  {
@@ -38,6 +38,7 @@
38
38
  },
39
39
  "overrides": {
40
40
  "CreatePayment": {
41
+ "summary": "Payment of {amount|money}: {description|short}",
41
42
  "executionMapping": {
42
43
  "amount": "amount",
43
44
  "currency": "currency"
@@ -56,6 +57,7 @@
56
57
  }
57
58
  },
58
59
  "CreatePaymentLink": {
60
+ "summary": "Payment link[ of {amount|money}]: {description|short}",
59
61
  "executionMapping": {
60
62
  "amount": "amount",
61
63
  "currency": "currency"
@@ -89,12 +91,14 @@
89
91
  }
90
92
  },
91
93
  "CancelSubscription": {
94
+ "summary": "Cancel a subscription",
92
95
  "executionMapping": {},
93
96
  "staticExecution": {
94
97
  "action_type": "subscribe"
95
98
  }
96
99
  },
97
100
  "CreateCustomer": {
101
+ "summary": "Create payment customer[ {name}]",
98
102
  "executionMapping": {},
99
103
  "staticExecution": {
100
104
  "action_type": "charge"
@@ -113,6 +117,7 @@
113
117
  }
114
118
  },
115
119
  "RevokeMandate": {
120
+ "summary": "Revoke a payment mandate",
116
121
  "executionMapping": {},
117
122
  "staticExecution": {
118
123
  "action_type": "charge"
@@ -52,6 +52,7 @@
52
52
  "category": "disabled"
53
53
  },
54
54
  "create_record": {
55
+ "summary": "Create {type}: {title|short}",
55
56
  "executionMapping": {},
56
57
  "staticExecution": {
57
58
  "action_type": "write"
@@ -59,6 +60,7 @@
59
60
  "actionLabel": "Record created"
60
61
  },
61
62
  "archive_record": {
63
+ "summary": "Archive a record",
62
64
  "boundField": "archive_access",
63
65
  "requiredValue": "allowed",
64
66
  "executionMapping": {},
@@ -68,10 +70,12 @@
68
70
  "actionLabel": "Record archived"
69
71
  },
70
72
  "update_record": {
73
+ "summary": "Update record[: {title|short}]",
71
74
  "category": "disabled",
72
75
  "actionLabel": "Record updated"
73
76
  },
74
77
  "delete_record": {
78
+ "summary": "Delete a record",
75
79
  "boundField": "delete_access",
76
80
  "requiredValue": "allowed",
77
81
  "executionMapping": {},
@@ -5,9 +5,9 @@ import {
5
5
 
6
6
  // src/index.ts
7
7
  import { randomBytes as randomBytes3 } from "crypto";
8
- import { existsSync as existsSync13, readFileSync as readFileSync15, renameSync as renameSync3 } from "fs";
9
- import { dirname as dirname10, join as join15 } from "path";
10
- import { homedir as homedir8 } from "os";
8
+ import { existsSync as existsSync13, readFileSync as readFileSync17, renameSync as renameSync5 } from "fs";
9
+ import { dirname as dirname12, join as join17 } from "path";
10
+ import { homedir as homedir10 } from "os";
11
11
  import express from "express";
12
12
  import { createProxyMiddleware } from "http-proxy-middleware";
13
13
 
@@ -643,6 +643,13 @@ async function getSkippedCommitments() {
643
643
  if (!res.ok) throw new Error("Failed to fetch skipped commitments");
644
644
  return res.json();
645
645
  }
646
+ async function getMyPendingProposals() {
647
+ const res = await fetch(`${MCP_BASE}/internal/my-pending-proposals`, {
648
+ headers: internalHeaders()
649
+ });
650
+ if (!res.ok) throw new Error("Failed to fetch my pending proposals");
651
+ return res.json();
652
+ }
646
653
  async function getLocalEvidence() {
647
654
  const res = await fetch(`${MCP_BASE}/internal/evidence`, {
648
655
  headers: internalHeaders()
@@ -2258,6 +2265,7 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2, onSessionEstablis
2258
2265
  }
2259
2266
  vault2.wipe();
2260
2267
  await vault2.deriveAndSetKey(apiKey);
2268
+ vault2.setSpCookie(sessionCookie);
2261
2269
  }
2262
2270
  const sessionExpiresAt = typeof data.sessionExpiresAt === "number" ? data.sessionExpiresAt : null;
2263
2271
  vault2.setSessionExpiresAt(sessionExpiresAt);
@@ -3376,15 +3384,15 @@ import { promisify } from "util";
3376
3384
  var run = promisify(execFile);
3377
3385
  var SUPPORTED = /* @__PURE__ */ new Set(["darwin", "win32", "linux"]);
3378
3386
  var MODULE_DIR = pathDirname(fileURLToPath(import.meta.url));
3379
- function findCli(dirname11 = MODULE_DIR) {
3387
+ function findCli(dirname13 = MODULE_DIR) {
3380
3388
  const candidates = [
3381
3389
  // Bundled (the shipped layout): dist/control-plane → dist → root → bin
3382
- resolve(dirname11, "..", "..", "bin", "suveren-gateway.js"),
3390
+ resolve(dirname13, "..", "..", "bin", "suveren-gateway.js"),
3383
3391
  // Bundled, were the routes/ directory ever preserved.
3384
- resolve(dirname11, "..", "..", "..", "bin", "suveren-gateway.js"),
3392
+ resolve(dirname13, "..", "..", "..", "bin", "suveren-gateway.js"),
3385
3393
  // Dev, running from source: the repo's own bundle directory.
3386
- resolve(dirname11, "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js"),
3387
- resolve(dirname11, "..", "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js")
3394
+ resolve(dirname13, "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js"),
3395
+ resolve(dirname13, "..", "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js")
3388
3396
  // Deliberately NO process.cwd() fallback: it makes the result depend on
3389
3397
  // where the process happened to be launched from, so the same install
3390
3398
  // resolves differently between a shell and a login service — and it would
@@ -4622,10 +4630,110 @@ function createArchivedMandatesRouter(dataDir) {
4622
4630
  return router;
4623
4631
  }
4624
4632
 
4625
- // src/routes/internal-events.ts
4633
+ // src/routes/blocked-seen.ts
4626
4634
  import { Router as Router19 } from "express";
4635
+
4636
+ // src/lib/blocked-seen-store.ts
4637
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, renameSync as renameSync3 } from "fs";
4638
+ import { homedir as homedir8 } from "os";
4639
+ import { join as join14, dirname as dirname10 } from "path";
4640
+ function storePath2(dataDir) {
4641
+ const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join14(homedir8(), ".suveren");
4642
+ return join14(dir, "blocked-seen.json");
4643
+ }
4644
+ function readLastSeenBlockedAt(dataDir) {
4645
+ try {
4646
+ const raw = JSON.parse(readFileSync14(storePath2(dataDir), "utf8"));
4647
+ return typeof raw.lastSeenBlockedAt === "number" && Number.isFinite(raw.lastSeenBlockedAt) ? raw.lastSeenBlockedAt : 0;
4648
+ } catch {
4649
+ return 0;
4650
+ }
4651
+ }
4652
+ function markBlockedSeen(ts, dataDir) {
4653
+ const safeTs = typeof ts === "number" && Number.isFinite(ts) ? ts : Date.now();
4654
+ const path = storePath2(dataDir);
4655
+ mkdirSync9(dirname10(path), { recursive: true });
4656
+ const tmp = `${path}.tmp`;
4657
+ writeFileSync9(tmp, JSON.stringify({ lastSeenBlockedAt: safeTs }, null, 2) + "\n", "utf8");
4658
+ renameSync3(tmp, path);
4659
+ return safeTs;
4660
+ }
4661
+
4662
+ // src/routes/blocked-seen.ts
4663
+ function createBlockedSeenRouter(dataDir) {
4664
+ const router = Router19();
4665
+ router.get("/", (_req, res) => {
4666
+ res.json({ lastSeenBlockedAt: readLastSeenBlockedAt(dataDir) });
4667
+ });
4668
+ router.post("/", (req, res) => {
4669
+ const body = req.body;
4670
+ const ts = typeof body?.ts === "number" && Number.isFinite(body.ts) ? body.ts : Date.now();
4671
+ try {
4672
+ res.json({ lastSeenBlockedAt: markBlockedSeen(ts, dataDir) });
4673
+ } catch (err) {
4674
+ res.status(500).json({ error: `Could not save: ${err.message}` });
4675
+ }
4676
+ });
4677
+ return router;
4678
+ }
4679
+
4680
+ // src/routes/tickets-seen.ts
4681
+ import { Router as Router20 } from "express";
4682
+
4683
+ // src/lib/tickets-seen-store.ts
4684
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, renameSync as renameSync4 } from "fs";
4685
+ import { homedir as homedir9 } from "os";
4686
+ import { join as join15, dirname as dirname11 } from "path";
4687
+ function storePath3(dataDir) {
4688
+ const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join15(homedir9(), ".suveren");
4689
+ return join15(dir, "tickets-seen.json");
4690
+ }
4691
+ function readLastSeenTicketsAt(dataDir) {
4692
+ try {
4693
+ const raw = JSON.parse(readFileSync15(storePath3(dataDir), "utf8"));
4694
+ return typeof raw.lastSeenTicketsAt === "number" && Number.isFinite(raw.lastSeenTicketsAt) ? raw.lastSeenTicketsAt : 0;
4695
+ } catch {
4696
+ return 0;
4697
+ }
4698
+ }
4699
+ function markTicketsSeen(ts, dataDir) {
4700
+ const safeTs = typeof ts === "number" && Number.isFinite(ts) ? ts : Date.now();
4701
+ const path = storePath3(dataDir);
4702
+ mkdirSync10(dirname11(path), { recursive: true });
4703
+ const tmp = `${path}.tmp`;
4704
+ writeFileSync10(tmp, JSON.stringify({ lastSeenTicketsAt: safeTs }, null, 2) + "\n", "utf8");
4705
+ renameSync4(tmp, path);
4706
+ return safeTs;
4707
+ }
4708
+
4709
+ // src/routes/tickets-seen.ts
4710
+ function createTicketsSeenRouter(dataDir) {
4711
+ const router = Router20();
4712
+ router.get("/", (_req, res) => {
4713
+ res.json({ lastSeenTicketsAt: readLastSeenTicketsAt(dataDir) });
4714
+ });
4715
+ router.post("/", (req, res) => {
4716
+ const body = req.body;
4717
+ const ts = typeof body?.ts === "number" && Number.isFinite(body.ts) ? body.ts : Date.now();
4718
+ try {
4719
+ res.json({ lastSeenTicketsAt: markTicketsSeen(ts, dataDir) });
4720
+ } catch (err) {
4721
+ res.status(500).json({ error: `Could not save: ${err.message}` });
4722
+ }
4723
+ });
4724
+ return router;
4725
+ }
4726
+
4727
+ // src/routes/internal-events.ts
4728
+ import { Router as Router21 } from "express";
4627
4729
  import { timingSafeEqual as timingSafeEqual3 } from "crypto";
4628
- var ALLOWED = ["proposal-added", "action-approval-needed", "execution-failed"];
4730
+ var ALLOWED = [
4731
+ "proposal-added",
4732
+ "action-approval-needed",
4733
+ "execution-failed",
4734
+ "denial-recorded",
4735
+ "ticket-recorded"
4736
+ ];
4629
4737
  var SESSION_EXPIRED = "session-expired";
4630
4738
  var AS_KEY_MISMATCH = "as-key-mismatch";
4631
4739
  var AS_TLS_MISMATCH = "as-tls-mismatch";
@@ -4638,7 +4746,7 @@ function secretMatches2(provided, expected) {
4638
4746
  return timingSafeEqual3(a, b);
4639
4747
  }
4640
4748
  function createInternalEventsRouter(getSecret, onSessionExpired, onAsKeyMismatch, onAsTlsMismatch) {
4641
- const router = Router19();
4749
+ const router = Router21();
4642
4750
  router.post("/event", (req, res) => {
4643
4751
  if (!secretMatches2(req.headers["x-internal-secret"], getSecret())) {
4644
4752
  res.status(401).json({ error: "Unauthorized" });
@@ -4672,7 +4780,7 @@ function createInternalEventsRouter(getSecret, onSessionExpired, onAsKeyMismatch
4672
4780
  }
4673
4781
 
4674
4782
  // src/routes/internal-mandate.ts
4675
- import { Router as Router20 } from "express";
4783
+ import { Router as Router22 } from "express";
4676
4784
  import { timingSafeEqual as timingSafeEqual4, randomUUID } from "crypto";
4677
4785
 
4678
4786
  // src/lib/mandate-ceremony.ts
@@ -4854,7 +4962,7 @@ function secretMatches3(provided, expected) {
4854
4962
  return a.length === b.length && timingSafeEqual4(a, b);
4855
4963
  }
4856
4964
  function createInternalMandateRouter(getSecret, deps) {
4857
- const router = Router20();
4965
+ const router = Router22();
4858
4966
  router.post("/mandate", async (req, res) => {
4859
4967
  if (!secretMatches3(req.header("X-Internal-Secret") ?? void 0, getSecret())) {
4860
4968
  res.status(401).json({ error: "unauthorized" });
@@ -5057,17 +5165,17 @@ function buildSessionHealth(vault2) {
5057
5165
  }
5058
5166
 
5059
5167
  // src/lib/denials-reader.ts
5060
- import { existsSync as existsSync12, readFileSync as readFileSync14 } from "fs";
5061
- import { join as join14 } from "path";
5168
+ import { existsSync as existsSync12, readFileSync as readFileSync16 } from "fs";
5169
+ import { join as join16 } from "path";
5062
5170
  function loadDenials(dataDir, decrypt) {
5063
- const encPath = join14(dataDir, "denials.enc.json");
5064
- const plainPath = join14(dataDir, "denials.json");
5171
+ const encPath = join16(dataDir, "denials.enc.json");
5172
+ const plainPath = join16(dataDir, "denials.json");
5065
5173
  if (existsSync12(encPath)) {
5066
- const { blob } = JSON.parse(readFileSync14(encPath, "utf-8"));
5174
+ const { blob } = JSON.parse(readFileSync16(encPath, "utf-8"));
5067
5175
  return JSON.parse(decrypt(blob)).records ?? [];
5068
5176
  }
5069
5177
  if (existsSync12(plainPath)) {
5070
- return JSON.parse(readFileSync14(plainPath, "utf-8")).records ?? [];
5178
+ return JSON.parse(readFileSync16(plainPath, "utf-8")).records ?? [];
5071
5179
  }
5072
5180
  return [];
5073
5181
  }
@@ -5091,11 +5199,11 @@ function isSimulationMode() {
5091
5199
  // src/index.ts
5092
5200
  (function migrateDataDir() {
5093
5201
  if (process.env.SUVEREN_DATA_DIR) return;
5094
- const oldDir = join15(homedir8(), ".hap");
5095
- const newDir = join15(homedir8(), ".suveren");
5202
+ const oldDir = join17(homedir10(), ".hap");
5203
+ const newDir = join17(homedir10(), ".suveren");
5096
5204
  if (!existsSync13(newDir) && existsSync13(oldDir)) {
5097
5205
  try {
5098
- renameSync3(oldDir, newDir);
5206
+ renameSync5(oldDir, newDir);
5099
5207
  console.error(`[Control Plane] Migrated data directory: ${oldDir} \u2192 ${newDir}`);
5100
5208
  } catch (err) {
5101
5209
  console.error(`[Control Plane] FATAL: could not migrate data directory ${oldDir} \u2192 ${newDir}:`, err);
@@ -5103,7 +5211,7 @@ function isSimulationMode() {
5103
5211
  }
5104
5212
  }
5105
5213
  })();
5106
- var DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join15(homedir8(), ".suveren");
5214
+ var DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join17(homedir10(), ".suveren");
5107
5215
  var SP_URL = resolveAsUrl(DATA_DIR);
5108
5216
  validatePinTlsForUrl(resolvePinTls(DATA_DIR), SP_URL);
5109
5217
  var POLICY_LOCKED = [...readPolicy().locked];
@@ -5111,7 +5219,7 @@ var POLICY_LOCKED_INSTALL_METHOD = readPolicy().policy.installMethod;
5111
5219
  var POLICY_LOCKED_TEAM = readPolicy().policy.team;
5112
5220
  var port = parseInt(process.env.SUVEREN_CP_PORT ?? "3402", 10);
5113
5221
  var HAP_MODE = process.env.HAP_MODE ?? "personal";
5114
- var UI_DIST = process.env.HAP_UI_DIST ?? join15(import.meta.dirname ?? __dirname, "../../ui/dist");
5222
+ var UI_DIST = process.env.HAP_UI_DIST ?? join17(import.meta.dirname ?? __dirname, "../../ui/dist");
5115
5223
  var vault = new Vault(DATA_DIR);
5116
5224
  var shownSnapshotStore = new ShownSnapshotStore(DATA_DIR);
5117
5225
  (function repairIfAsUrlChanged() {
@@ -5420,6 +5528,8 @@ app.use("/mcp", jsonParser, authGuard, createMCPRouter());
5420
5528
  app.use("/autostart", jsonParser, authGuard, createAutostartRouter());
5421
5529
  app.use("/api/gateway-settings", jsonParser, authGuard, createGatewaySettingsRouter());
5422
5530
  app.use("/api/archived-mandates", jsonParser, authGuard, createArchivedMandatesRouter());
5531
+ app.use("/api/blocked-seen", jsonParser, authGuard, createBlockedSeenRouter());
5532
+ app.use("/api/tickets-seen", jsonParser, authGuard, createTicketsSeenRouter());
5423
5533
  app.use("/api/encrypt-intent", jsonParser, authGuard, createEncryptIntentRouter());
5424
5534
  app.use("/api/evidence-export", authGuard, createEvidenceExportRouter(SP_URL, vault, DATA_DIR, lockAsTlsMismatch));
5425
5535
  app.use("/proposal-status", jsonParser, authGuard, createProposalStatusRouter(SP_URL, vault, DATA_DIR, lockAsTlsMismatch, shownSnapshotStore));
@@ -5564,6 +5674,15 @@ app.get("/skipped-commitments", authGuard, async (_req, res) => {
5564
5674
  res.status(500).json({ error: "Failed to fetch skipped commitments from MCP server" });
5565
5675
  }
5566
5676
  });
5677
+ app.get("/my-pending-proposals", authGuard, async (_req, res) => {
5678
+ try {
5679
+ const data = await getMyPendingProposals();
5680
+ res.json(data);
5681
+ } catch (err) {
5682
+ console.error("[Control Plane] My-pending-proposals retrieval error:", err);
5683
+ res.status(500).json({ error: "Failed to fetch pending proposals from MCP server" });
5684
+ }
5685
+ });
5567
5686
  app.get("/as-pairing", authGuard, (_req, res) => {
5568
5687
  const pairing = readPairing(DATA_DIR);
5569
5688
  const paired = pairing !== null && pairing.asUrl === SP_URL;
@@ -5587,7 +5706,7 @@ app.get("/as-pairing", authGuard, (_req, res) => {
5587
5706
  });
5588
5707
  app.get("/denials", authGuard, (req, res) => {
5589
5708
  try {
5590
- const dataDir = process.env.SUVEREN_DATA_DIR ?? join15(homedir8(), ".suveren");
5709
+ const dataDir = process.env.SUVEREN_DATA_DIR ?? join17(homedir10(), ".suveren");
5591
5710
  const all = loadDenials(dataDir, (blob) => vault.decrypt(blob));
5592
5711
  const since = Number(req.query.since);
5593
5712
  const limit = Number(req.query.limit);
@@ -5646,12 +5765,12 @@ app.put("/agent-brief/context", jsonParser, authGuard, async (req, res) => {
5646
5765
  res.status(413).json({ error: `Context exceeds ${AGENT_CONTEXT_MAX_BYTES}-byte cap` });
5647
5766
  return;
5648
5767
  }
5649
- const { mkdirSync: mkdirSync9, writeFileSync: writeFileSync9, renameSync: renameSync4 } = await import("fs");
5768
+ const { mkdirSync: mkdirSync11, writeFileSync: writeFileSync11, renameSync: renameSync6 } = await import("fs");
5650
5769
  const filePath = agentBriefPath();
5651
- mkdirSync9(dirname10(filePath), { recursive: true });
5770
+ mkdirSync11(dirname12(filePath), { recursive: true });
5652
5771
  const tmpPath = `${filePath}.tmp`;
5653
- writeFileSync9(tmpPath, content, "utf-8");
5654
- renameSync4(tmpPath, filePath);
5772
+ writeFileSync11(tmpPath, content, "utf-8");
5773
+ renameSync6(tmpPath, filePath);
5655
5774
  res.json({ ok: true });
5656
5775
  } catch (err) {
5657
5776
  console.error("[Control Plane] agent-brief/context PUT failed:", err);
@@ -5743,10 +5862,10 @@ function detectRunningVersion() {
5743
5862
  return process.env.HAP_BUILD_SHA ?? "dev";
5744
5863
  }
5745
5864
  const dir = import.meta.dirname ?? __dirname;
5746
- const bundlePkg = join15(dir, "..", "..", "package.json");
5865
+ const bundlePkg = join17(dir, "..", "..", "package.json");
5747
5866
  if (existsSync13(bundlePkg)) {
5748
5867
  try {
5749
- const pkg = JSON.parse(readFileSync15(bundlePkg, "utf8"));
5868
+ const pkg = JSON.parse(readFileSync17(bundlePkg, "utf8"));
5750
5869
  if (pkg.name === "@suveren/gateway" && typeof pkg.version === "string") {
5751
5870
  return pkg.version;
5752
5871
  }
@@ -5798,7 +5917,7 @@ if (existsSync13(UI_DIST)) {
5798
5917
  }));
5799
5918
  app.get("*", (_req, res) => {
5800
5919
  res.setHeader("Cache-Control", "no-store, must-revalidate");
5801
- res.sendFile(join15(UI_DIST, "index.html"));
5920
+ res.sendFile(join17(UI_DIST, "index.html"));
5802
5921
  });
5803
5922
  } else {
5804
5923
  app.get("/", (_req, res) => {