@suveren/gateway 0.7.0 → 0.7.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.
- package/dist/control-plane/index.mjs +35 -0
- package/dist/mcp-server/http.mjs +28 -0
- package/package.json +1 -1
|
@@ -2067,6 +2067,37 @@ function createGatewaySettingsRouter() {
|
|
|
2067
2067
|
return router;
|
|
2068
2068
|
}
|
|
2069
2069
|
|
|
2070
|
+
// src/routes/internal-events.ts
|
|
2071
|
+
import { Router as Router11 } from "express";
|
|
2072
|
+
import { timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
2073
|
+
var ALLOWED = ["proposal-added", "action-approval-needed"];
|
|
2074
|
+
function secretMatches(provided, expected) {
|
|
2075
|
+
if (!expected) return false;
|
|
2076
|
+
if (!provided) return false;
|
|
2077
|
+
const a = Buffer.from(provided);
|
|
2078
|
+
const b = Buffer.from(expected);
|
|
2079
|
+
if (a.length !== b.length) return false;
|
|
2080
|
+
return timingSafeEqual2(a, b);
|
|
2081
|
+
}
|
|
2082
|
+
function createInternalEventsRouter(getSecret) {
|
|
2083
|
+
const router = Router11();
|
|
2084
|
+
router.post("/event", (req, res) => {
|
|
2085
|
+
if (!secretMatches(req.headers["x-internal-secret"], getSecret())) {
|
|
2086
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
const type = (req.body ?? {}).type;
|
|
2090
|
+
if (typeof type !== "string" || !ALLOWED.includes(type)) {
|
|
2091
|
+
res.status(400).json({ error: "Unsupported event type" });
|
|
2092
|
+
return;
|
|
2093
|
+
}
|
|
2094
|
+
console.error(`[Control Plane] Internal event received: ${type}`);
|
|
2095
|
+
eventBus.emit(type);
|
|
2096
|
+
res.json({ ok: true });
|
|
2097
|
+
});
|
|
2098
|
+
return router;
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2070
2101
|
// src/lib/notification-dispatcher.ts
|
|
2071
2102
|
var TRIGGER_EVENTS = ["proposal-added", "action-approval-needed"];
|
|
2072
2103
|
var TITLE = "Suveren";
|
|
@@ -2132,6 +2163,9 @@ var NotificationDispatcher = class {
|
|
|
2132
2163
|
} catch {
|
|
2133
2164
|
enabled = true;
|
|
2134
2165
|
}
|
|
2166
|
+
console.error(
|
|
2167
|
+
`[Control Plane] Review pending \u2014 desktop notification ${enabled ? "sent" : "suppressed (turned off)"}`
|
|
2168
|
+
);
|
|
2135
2169
|
if (enabled) {
|
|
2136
2170
|
const message = count >= FLOOD_THRESHOLD ? floodMessage(count) : WAITING_MESSAGE;
|
|
2137
2171
|
this.notifyFn(TITLE, message, process.platform, this.url);
|
|
@@ -2420,6 +2454,7 @@ app.get("/auth/oauth/:integrationId/health", authGuard, async (req, res) => {
|
|
|
2420
2454
|
}
|
|
2421
2455
|
});
|
|
2422
2456
|
app.get("/events", requireAllowedHost, requireAuthQueryOrHeader(vault), createEventsHandler());
|
|
2457
|
+
app.use("/internal", jsonParser, createInternalEventsRouter(() => internalSecret2));
|
|
2423
2458
|
app.use("/vault", jsonParser, authGuard, createVaultRouter(vault));
|
|
2424
2459
|
app.use("/ai", jsonParser, authGuard, createAIRouter(vault));
|
|
2425
2460
|
app.use("/ai-prompts", jsonParser, authGuard, createAIPromptsRouter());
|
package/dist/mcp-server/http.mjs
CHANGED
|
@@ -6,6 +6,33 @@ import express from "express";
|
|
|
6
6
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
7
7
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
8
8
|
|
|
9
|
+
// src/lib/cp-notify.ts
|
|
10
|
+
var CP_PORT = process.env.SUVEREN_CP_PORT ?? "3402";
|
|
11
|
+
var CP_BASE = process.env.SUVEREN_CP_INTERNAL_URL ?? `http://127.0.0.1:${CP_PORT}`;
|
|
12
|
+
var TIMEOUT_MS = 2e3;
|
|
13
|
+
async function notifyControlPlane(type) {
|
|
14
|
+
const secret = process.env.SUVEREN_INTERNAL_SECRET ?? "";
|
|
15
|
+
if (!secret) return;
|
|
16
|
+
try {
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
19
|
+
try {
|
|
20
|
+
await fetch(`${CP_BASE}/internal/event`, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
"X-Internal-Secret": secret
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify({ type }),
|
|
27
|
+
signal: controller.signal
|
|
28
|
+
});
|
|
29
|
+
} finally {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
9
36
|
// src/lib/sp-client.ts
|
|
10
37
|
var SPReceiptError = class extends Error {
|
|
11
38
|
constructor(message, statusCode, body) {
|
|
@@ -167,6 +194,7 @@ var SPClient = class {
|
|
|
167
194
|
const body = await res.json().catch(() => ({}));
|
|
168
195
|
throw new Error(body.error ?? `SP proposal submission failed: ${res.status}`);
|
|
169
196
|
}
|
|
197
|
+
void notifyControlPlane("proposal-added");
|
|
170
198
|
return res.json();
|
|
171
199
|
}
|
|
172
200
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suveren/gateway",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Suveren gateway — local agent gateway built in compliance with the Human Agency Protocol (HAP). Runs the UI, control plane, and MCP server in one Node process.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "server.js",
|