@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.
- package/content/integrations/calendar.json +3 -0
- package/content/integrations/crm.json +10 -0
- package/content/integrations/deploy-github.json +1 -0
- package/content/integrations/erp.json +4 -0
- package/content/integrations/gmail.json +4 -0
- package/content/integrations/linkedin.json +4 -0
- package/content/integrations/mail.json +1 -0
- package/content/integrations/mollie.json +5 -0
- package/content/integrations/records.json +4 -0
- package/dist/control-plane/index.mjs +151 -32
- package/dist/mcp-server/http.mjs +156 -37
- package/dist/ui/assets/index-B7qy0B9J.js +123 -0
- package/dist/ui/assets/index-DyZY5sLI.css +1 -0
- package/dist/ui/index.html +2 -2
- package/node_modules/qs/.github/THREAT_MODEL.md +4 -2
- package/node_modules/qs/CHANGELOG.md +38 -14
- package/node_modules/qs/README.md +31 -3
- package/node_modules/qs/dist/qs.js +20 -20
- package/node_modules/qs/lib/parse.js +94 -4
- package/node_modules/qs/lib/stringify.js +4 -4
- package/node_modules/qs/lib/utils.js +130 -6
- package/node_modules/qs/package.json +4 -4
- package/node_modules/qs/test/parse.js +174 -0
- package/node_modules/qs/test/stringify.js +263 -33
- package/node_modules/qs/test/utils.js +184 -0
- package/node_modules/undici/docs/docs/api/Client.md +2 -0
- package/node_modules/undici/lib/core/connect.js +10 -4
- package/node_modules/undici/lib/core/symbols.js +1 -0
- package/node_modules/undici/lib/dispatcher/agent.js +6 -2
- package/node_modules/undici/lib/dispatcher/client-h1.js +0 -2
- package/node_modules/undici/lib/dispatcher/client-h2.js +0 -4
- package/node_modules/undici/lib/dispatcher/client.js +3 -2
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +12 -0
- package/node_modules/undici/lib/handler/cache-handler.js +48 -0
- package/node_modules/undici/lib/handler/deduplication-handler.js +57 -13
- package/node_modules/undici/lib/handler/redirect-handler.js +8 -1
- package/node_modules/undici/lib/interceptor/decompress.js +15 -5
- package/node_modules/undici/lib/web/cookies/index.js +3 -1
- package/node_modules/undici/lib/web/cookies/parse.js +138 -137
- package/node_modules/undici/lib/web/cookies/util.js +21 -2
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +90 -9
- package/node_modules/undici/lib/web/eventsource/eventsource.js +4 -1
- package/node_modules/undici/lib/web/fetch/index.js +3 -3
- package/node_modules/undici/lib/web/infra/index.js +14 -0
- package/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +5 -5
- package/node_modules/undici/lib/web/websocket/receiver.js +13 -0
- package/node_modules/undici/package.json +1 -1
- package/node_modules/undici/types/client.d.ts +14 -0
- package/package.json +1 -1
- package/dist/ui/assets/index-DUIlMVlP.css +0 -1
- 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
|
},
|
|
@@ -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",
|
|
@@ -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
|
|
9
|
-
import { dirname as
|
|
10
|
-
import { homedir as
|
|
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(
|
|
3387
|
+
function findCli(dirname13 = MODULE_DIR) {
|
|
3380
3388
|
const candidates = [
|
|
3381
3389
|
// Bundled (the shipped layout): dist/control-plane → dist → root → bin
|
|
3382
|
-
resolve(
|
|
3390
|
+
resolve(dirname13, "..", "..", "bin", "suveren-gateway.js"),
|
|
3383
3391
|
// Bundled, were the routes/ directory ever preserved.
|
|
3384
|
-
resolve(
|
|
3392
|
+
resolve(dirname13, "..", "..", "..", "bin", "suveren-gateway.js"),
|
|
3385
3393
|
// Dev, running from source: the repo's own bundle directory.
|
|
3386
|
-
resolve(
|
|
3387
|
-
resolve(
|
|
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/
|
|
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 = [
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
5061
|
-
import { join as
|
|
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 =
|
|
5064
|
-
const plainPath =
|
|
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(
|
|
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(
|
|
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 =
|
|
5095
|
-
const newDir =
|
|
5202
|
+
const oldDir = join17(homedir10(), ".hap");
|
|
5203
|
+
const newDir = join17(homedir10(), ".suveren");
|
|
5096
5204
|
if (!existsSync13(newDir) && existsSync13(oldDir)) {
|
|
5097
5205
|
try {
|
|
5098
|
-
|
|
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 ??
|
|
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 ??
|
|
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 ??
|
|
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:
|
|
5768
|
+
const { mkdirSync: mkdirSync11, writeFileSync: writeFileSync11, renameSync: renameSync6 } = await import("fs");
|
|
5650
5769
|
const filePath = agentBriefPath();
|
|
5651
|
-
|
|
5770
|
+
mkdirSync11(dirname12(filePath), { recursive: true });
|
|
5652
5771
|
const tmpPath = `${filePath}.tmp`;
|
|
5653
|
-
|
|
5654
|
-
|
|
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 =
|
|
5865
|
+
const bundlePkg = join17(dir, "..", "..", "package.json");
|
|
5747
5866
|
if (existsSync13(bundlePkg)) {
|
|
5748
5867
|
try {
|
|
5749
|
-
const pkg = JSON.parse(
|
|
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(
|
|
5920
|
+
res.sendFile(join17(UI_DIST, "index.html"));
|
|
5802
5921
|
});
|
|
5803
5922
|
} else {
|
|
5804
5923
|
app.get("/", (_req, res) => {
|