@suveren/gateway 0.21.0 → 0.22.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/erp.json +14 -2
- package/dist/control-plane/index.mjs +179 -46
- package/dist/mcp-server/http.mjs +480 -174
- package/dist/ui/assets/{index-D5hgQ_8Z.css → index-BSAkn_Of.css} +1 -1
- package/dist/ui/assets/index-CBoGbefI.js +116 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-BBjT8ue7.js +0 -116
|
@@ -117,7 +117,13 @@
|
|
|
117
117
|
"staticExecution": {
|
|
118
118
|
"action_type": "send"
|
|
119
119
|
},
|
|
120
|
-
"actionLabel": "Quote sent"
|
|
120
|
+
"actionLabel": "Quote sent",
|
|
121
|
+
"preview": {
|
|
122
|
+
"tool": "get_quote",
|
|
123
|
+
"args": { "id": "id", "revision": "revision" },
|
|
124
|
+
"version": { "arg": "revision", "field": "revision" },
|
|
125
|
+
"fields": ["number", "revision", "status", "customer_id", "lines", "net_total", "discount_pct", "valid_until"]
|
|
126
|
+
}
|
|
121
127
|
},
|
|
122
128
|
"convert_quote_to_order": {
|
|
123
129
|
"executionMapping": {
|
|
@@ -128,7 +134,13 @@
|
|
|
128
134
|
"staticExecution": {
|
|
129
135
|
"action_type": "order"
|
|
130
136
|
},
|
|
131
|
-
"actionLabel": "Quote converted to order"
|
|
137
|
+
"actionLabel": "Quote converted to order",
|
|
138
|
+
"preview": {
|
|
139
|
+
"tool": "get_quote",
|
|
140
|
+
"args": { "id": "id", "revision": "revision" },
|
|
141
|
+
"version": { "arg": "revision", "field": "revision" },
|
|
142
|
+
"fields": ["number", "revision", "status", "customer_id", "lines", "net_total", "discount_pct", "valid_until"]
|
|
143
|
+
}
|
|
132
144
|
},
|
|
133
145
|
"load_simulation": {
|
|
134
146
|
"executionMapping": {},
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
7
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
8
|
-
import { existsSync as
|
|
9
|
-
import { dirname as dirname9, join as
|
|
8
|
+
import { existsSync as existsSync12, readFileSync as readFileSync14, renameSync as renameSync2 } from "fs";
|
|
9
|
+
import { dirname as dirname9, join as join14 } from "path";
|
|
10
10
|
import { homedir as homedir7 } from "os";
|
|
11
11
|
import express from "express";
|
|
12
12
|
import { createProxyMiddleware } from "http-proxy-middleware";
|
|
@@ -599,6 +599,25 @@ async function exportReport(gatewayVersion) {
|
|
|
599
599
|
const filename = /filename="([^"]+)"/.exec(res.headers.get("content-disposition") ?? "")?.[1] ?? "suveren-report.html";
|
|
600
600
|
return { html, filename };
|
|
601
601
|
}
|
|
602
|
+
async function getToolPreview(data) {
|
|
603
|
+
const controller = new AbortController();
|
|
604
|
+
const timeout = setTimeout(() => controller.abort(), 12e3);
|
|
605
|
+
try {
|
|
606
|
+
const res = await fetch(`${MCP_BASE}/internal/preview`, {
|
|
607
|
+
method: "POST",
|
|
608
|
+
headers: internalHeaders(),
|
|
609
|
+
body: JSON.stringify(data),
|
|
610
|
+
signal: controller.signal
|
|
611
|
+
});
|
|
612
|
+
if (!res.ok) {
|
|
613
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
614
|
+
throw new Error(`MCP preview failed: ${err.error ?? res.status}`);
|
|
615
|
+
}
|
|
616
|
+
return res.json();
|
|
617
|
+
} finally {
|
|
618
|
+
clearTimeout(timeout);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
602
621
|
async function getAgentContact() {
|
|
603
622
|
const res = await fetch(`${MCP_BASE}/internal/agent-contact`, {
|
|
604
623
|
headers: internalHeaders()
|
|
@@ -3404,8 +3423,121 @@ function createEvidenceExportRouter(spUrl, vault2, dataDir, lockAsTlsMismatch2)
|
|
|
3404
3423
|
return router;
|
|
3405
3424
|
}
|
|
3406
3425
|
|
|
3407
|
-
// src/routes/
|
|
3426
|
+
// src/routes/proposal-preview.ts
|
|
3408
3427
|
import { Router as Router10 } from "express";
|
|
3428
|
+
|
|
3429
|
+
// src/lib/execution-journal-reader.ts
|
|
3430
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
|
|
3431
|
+
import { join as join10 } from "path";
|
|
3432
|
+
function loadJournalEntries(dataDir) {
|
|
3433
|
+
const path = join10(dataDir, "execution-journal.json");
|
|
3434
|
+
if (!existsSync10(path)) return [];
|
|
3435
|
+
try {
|
|
3436
|
+
const parsed = JSON.parse(readFileSync10(path, "utf-8"));
|
|
3437
|
+
return parsed.entries ?? [];
|
|
3438
|
+
} catch {
|
|
3439
|
+
return [];
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
function findLatestByProposal(dataDir, proposalId) {
|
|
3443
|
+
const rows = loadJournalEntries(dataDir).filter((e) => e.proposalId === proposalId);
|
|
3444
|
+
return rows[rows.length - 1];
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
// src/routes/proposal-preview.ts
|
|
3448
|
+
var AS_FETCH_TIMEOUT_MS2 = 1e4;
|
|
3449
|
+
function createProposalStatusRouter(spUrl, vault2, dataDir, lockAsTlsMismatch2) {
|
|
3450
|
+
const router = Router10();
|
|
3451
|
+
router.get("/:id/preview", async (req, res) => {
|
|
3452
|
+
const proposalId = req.params.id;
|
|
3453
|
+
const cookie = vault2.getSpCookie();
|
|
3454
|
+
if (!cookie) {
|
|
3455
|
+
res.status(401).json({ error: "No Authority Server session \u2014 sign in to preview this proposal." });
|
|
3456
|
+
return;
|
|
3457
|
+
}
|
|
3458
|
+
let proposal;
|
|
3459
|
+
try {
|
|
3460
|
+
const controller = new AbortController();
|
|
3461
|
+
const timeout = setTimeout(() => controller.abort(), AS_FETCH_TIMEOUT_MS2);
|
|
3462
|
+
const pin = readPairing(dataDir);
|
|
3463
|
+
let asStatus;
|
|
3464
|
+
let asBody;
|
|
3465
|
+
try {
|
|
3466
|
+
const { res: asRes } = await fetchAs(
|
|
3467
|
+
`${spUrl}/api/proposals/${encodeURIComponent(proposalId)}`,
|
|
3468
|
+
{ headers: { Cookie: cookie }, signal: controller.signal },
|
|
3469
|
+
{
|
|
3470
|
+
enforce: resolvePinTls(dataDir),
|
|
3471
|
+
pinnedSpkiHex: pin && pin.asUrl === spUrl ? pin.tlsSpkiPinHex : void 0
|
|
3472
|
+
}
|
|
3473
|
+
);
|
|
3474
|
+
asStatus = asRes.status;
|
|
3475
|
+
asBody = await asRes.json().catch(() => ({}));
|
|
3476
|
+
} finally {
|
|
3477
|
+
clearTimeout(timeout);
|
|
3478
|
+
}
|
|
3479
|
+
if (asStatus < 200 || asStatus >= 300 || !asBody.proposal) {
|
|
3480
|
+
res.status(asStatus >= 400 ? asStatus : 502).json({
|
|
3481
|
+
error: asBody.error ?? `Could not fetch proposal ${proposalId} (${asStatus})`
|
|
3482
|
+
});
|
|
3483
|
+
return;
|
|
3484
|
+
}
|
|
3485
|
+
proposal = asBody.proposal;
|
|
3486
|
+
} catch (err) {
|
|
3487
|
+
if (err instanceof AsTlsMismatchError) {
|
|
3488
|
+
lockAsTlsMismatch2();
|
|
3489
|
+
res.status(502).json({ error: err.message });
|
|
3490
|
+
return;
|
|
3491
|
+
}
|
|
3492
|
+
res.status(502).json({ error: `Authority Server unreachable: ${err instanceof Error ? err.message : String(err)}` });
|
|
3493
|
+
return;
|
|
3494
|
+
}
|
|
3495
|
+
try {
|
|
3496
|
+
const result = await getToolPreview({ proposalId, tool: proposal.tool, toolArgs: proposal.toolArgs });
|
|
3497
|
+
if (result.status !== "ok") {
|
|
3498
|
+
res.json(result);
|
|
3499
|
+
return;
|
|
3500
|
+
}
|
|
3501
|
+
const response = { ...result, readAt: Date.now() };
|
|
3502
|
+
res.json(response);
|
|
3503
|
+
} catch (err) {
|
|
3504
|
+
res.status(502).json({ error: `MCP server unavailable: ${err instanceof Error ? err.message : String(err)}` });
|
|
3505
|
+
}
|
|
3506
|
+
});
|
|
3507
|
+
router.get("/:id/outcome", (req, res) => {
|
|
3508
|
+
try {
|
|
3509
|
+
const entry = findLatestByProposal(dataDir, req.params.id);
|
|
3510
|
+
if (!entry) {
|
|
3511
|
+
const none = { state: "none" };
|
|
3512
|
+
res.json(none);
|
|
3513
|
+
return;
|
|
3514
|
+
}
|
|
3515
|
+
if (entry.state === "intent") {
|
|
3516
|
+
const intent = { state: "intent", at: entry.startedAt };
|
|
3517
|
+
res.json(intent);
|
|
3518
|
+
return;
|
|
3519
|
+
}
|
|
3520
|
+
if (entry.state === "done") {
|
|
3521
|
+
const done = { state: "done", at: entry.finishedAt ?? entry.startedAt };
|
|
3522
|
+
res.json(done);
|
|
3523
|
+
return;
|
|
3524
|
+
}
|
|
3525
|
+
const failed = {
|
|
3526
|
+
state: "failed",
|
|
3527
|
+
at: entry.finishedAt ?? entry.startedAt,
|
|
3528
|
+
...entry.outcome ? { outcome: entry.outcome } : {},
|
|
3529
|
+
...entry.detail ? { detail: entry.detail } : {}
|
|
3530
|
+
};
|
|
3531
|
+
res.json(failed);
|
|
3532
|
+
} catch (err) {
|
|
3533
|
+
res.status(500).json({ error: `Could not read the execution journal: ${err instanceof Error ? err.message : String(err)}` });
|
|
3534
|
+
}
|
|
3535
|
+
});
|
|
3536
|
+
return router;
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
// src/routes/evidence.ts
|
|
3540
|
+
import { Router as Router11 } from "express";
|
|
3409
3541
|
import { verifyTicketSignature, encodeDidKey } from "@hap/core";
|
|
3410
3542
|
function issuerFromPublicKeyHex(publicKeyHex) {
|
|
3411
3543
|
return encodeDidKey(Buffer.from(publicKeyHex, "hex"));
|
|
@@ -3471,7 +3603,7 @@ function mergeAuthorizations(evidence) {
|
|
|
3471
3603
|
return out;
|
|
3472
3604
|
}
|
|
3473
3605
|
function createEvidenceRouter() {
|
|
3474
|
-
const router =
|
|
3606
|
+
const router = Router11();
|
|
3475
3607
|
router.get("/authorizations", async (_req, res) => {
|
|
3476
3608
|
try {
|
|
3477
3609
|
const evidence = await getLocalEvidence();
|
|
@@ -3514,7 +3646,7 @@ function createEvidenceRouter() {
|
|
|
3514
3646
|
}
|
|
3515
3647
|
|
|
3516
3648
|
// src/routes/report.ts
|
|
3517
|
-
import { Router as
|
|
3649
|
+
import { Router as Router12 } from "express";
|
|
3518
3650
|
function handleError(res, err) {
|
|
3519
3651
|
if (err instanceof McpLockedError) {
|
|
3520
3652
|
res.status(503).json({ error: err.message });
|
|
@@ -3526,7 +3658,7 @@ function handleError(res, err) {
|
|
|
3526
3658
|
});
|
|
3527
3659
|
}
|
|
3528
3660
|
function createReportRouter(getGatewayVersion) {
|
|
3529
|
-
const router =
|
|
3661
|
+
const router = Router12();
|
|
3530
3662
|
router.get("/", async (_req, res) => {
|
|
3531
3663
|
try {
|
|
3532
3664
|
res.json(await getReport());
|
|
@@ -3572,9 +3704,9 @@ function createReportRouter(getGatewayVersion) {
|
|
|
3572
3704
|
}
|
|
3573
3705
|
|
|
3574
3706
|
// src/routes/decrypt-intent.ts
|
|
3575
|
-
import { Router as
|
|
3707
|
+
import { Router as Router13 } from "express";
|
|
3576
3708
|
function createDecryptIntentRouter(vault2) {
|
|
3577
|
-
const router =
|
|
3709
|
+
const router = Router13();
|
|
3578
3710
|
router.post("/", async (req, res) => {
|
|
3579
3711
|
const { intentCiphertext, encryptedKey, approverId } = req.body;
|
|
3580
3712
|
if (typeof intentCiphertext !== "string" || intentCiphertext.length === 0) {
|
|
@@ -3750,22 +3882,22 @@ data: ${data}
|
|
|
3750
3882
|
}
|
|
3751
3883
|
|
|
3752
3884
|
// src/routes/gateway-settings.ts
|
|
3753
|
-
import { Router as
|
|
3885
|
+
import { Router as Router14 } from "express";
|
|
3754
3886
|
|
|
3755
3887
|
// src/lib/gateway-settings.ts
|
|
3756
|
-
import { readFileSync as
|
|
3888
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
3757
3889
|
import { homedir as homedir5 } from "os";
|
|
3758
|
-
import { join as
|
|
3890
|
+
import { join as join11, dirname as dirname7 } from "path";
|
|
3759
3891
|
var DEFAULT_SETTINGS = {
|
|
3760
3892
|
desktopNotifications: true
|
|
3761
3893
|
};
|
|
3762
3894
|
function settingsPath(dataDir) {
|
|
3763
|
-
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ??
|
|
3764
|
-
return
|
|
3895
|
+
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join11(homedir5(), ".suveren");
|
|
3896
|
+
return join11(dir, "settings.json");
|
|
3765
3897
|
}
|
|
3766
3898
|
function readSettings(dataDir) {
|
|
3767
3899
|
try {
|
|
3768
|
-
const raw = JSON.parse(
|
|
3900
|
+
const raw = JSON.parse(readFileSync11(settingsPath(dataDir), "utf8"));
|
|
3769
3901
|
return {
|
|
3770
3902
|
desktopNotifications: typeof raw.desktopNotifications === "boolean" ? raw.desktopNotifications : DEFAULT_SETTINGS.desktopNotifications
|
|
3771
3903
|
};
|
|
@@ -3786,7 +3918,7 @@ function writeSettings(patch, dataDir) {
|
|
|
3786
3918
|
|
|
3787
3919
|
// src/routes/gateway-settings.ts
|
|
3788
3920
|
function createGatewaySettingsRouter() {
|
|
3789
|
-
const router =
|
|
3921
|
+
const router = Router14();
|
|
3790
3922
|
router.get("/", (_req, res) => {
|
|
3791
3923
|
res.json(readSettings());
|
|
3792
3924
|
});
|
|
@@ -3809,23 +3941,23 @@ function createGatewaySettingsRouter() {
|
|
|
3809
3941
|
}
|
|
3810
3942
|
|
|
3811
3943
|
// src/routes/archived-mandates.ts
|
|
3812
|
-
import { Router as
|
|
3944
|
+
import { Router as Router15 } from "express";
|
|
3813
3945
|
|
|
3814
3946
|
// src/lib/archived-mandates-store.ts
|
|
3815
|
-
import { readFileSync as
|
|
3947
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, renameSync } from "fs";
|
|
3816
3948
|
import { homedir as homedir6 } from "os";
|
|
3817
|
-
import { join as
|
|
3949
|
+
import { join as join12, dirname as dirname8 } from "path";
|
|
3818
3950
|
var ID_PATTERN = /^[A-Za-z0-9_.:-]{1,200}$/;
|
|
3819
3951
|
function isValidMandateId(id) {
|
|
3820
3952
|
return typeof id === "string" && ID_PATTERN.test(id);
|
|
3821
3953
|
}
|
|
3822
3954
|
function storePath(dataDir) {
|
|
3823
|
-
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ??
|
|
3824
|
-
return
|
|
3955
|
+
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join12(homedir6(), ".suveren");
|
|
3956
|
+
return join12(dir, "archived-mandates.json");
|
|
3825
3957
|
}
|
|
3826
3958
|
function readArchived(dataDir) {
|
|
3827
3959
|
try {
|
|
3828
|
-
const raw = JSON.parse(
|
|
3960
|
+
const raw = JSON.parse(readFileSync12(storePath(dataDir), "utf8"));
|
|
3829
3961
|
if (!Array.isArray(raw.archived)) return [];
|
|
3830
3962
|
return [...new Set(raw.archived.filter(isValidMandateId))];
|
|
3831
3963
|
} catch {
|
|
@@ -3852,7 +3984,7 @@ function unarchiveMandate(id, dataDir) {
|
|
|
3852
3984
|
|
|
3853
3985
|
// src/routes/archived-mandates.ts
|
|
3854
3986
|
function createArchivedMandatesRouter(dataDir) {
|
|
3855
|
-
const router =
|
|
3987
|
+
const router = Router15();
|
|
3856
3988
|
router.get("/", (_req, res) => {
|
|
3857
3989
|
res.json({ archived: readArchived(dataDir) });
|
|
3858
3990
|
});
|
|
@@ -3874,7 +4006,7 @@ function createArchivedMandatesRouter(dataDir) {
|
|
|
3874
4006
|
}
|
|
3875
4007
|
|
|
3876
4008
|
// src/routes/internal-events.ts
|
|
3877
|
-
import { Router as
|
|
4009
|
+
import { Router as Router16 } from "express";
|
|
3878
4010
|
import { timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
3879
4011
|
var ALLOWED = ["proposal-added", "action-approval-needed"];
|
|
3880
4012
|
var SESSION_EXPIRED = "session-expired";
|
|
@@ -3889,7 +4021,7 @@ function secretMatches(provided, expected) {
|
|
|
3889
4021
|
return timingSafeEqual2(a, b);
|
|
3890
4022
|
}
|
|
3891
4023
|
function createInternalEventsRouter(getSecret, onSessionExpired, onAsKeyMismatch, onAsTlsMismatch) {
|
|
3892
|
-
const router =
|
|
4024
|
+
const router = Router16();
|
|
3893
4025
|
router.post("/event", (req, res) => {
|
|
3894
4026
|
if (!secretMatches(req.headers["x-internal-secret"], getSecret())) {
|
|
3895
4027
|
res.status(401).json({ error: "Unauthorized" });
|
|
@@ -3923,7 +4055,7 @@ function createInternalEventsRouter(getSecret, onSessionExpired, onAsKeyMismatch
|
|
|
3923
4055
|
}
|
|
3924
4056
|
|
|
3925
4057
|
// src/routes/internal-mandate.ts
|
|
3926
|
-
import { Router as
|
|
4058
|
+
import { Router as Router17 } from "express";
|
|
3927
4059
|
import { timingSafeEqual as timingSafeEqual3, randomUUID } from "crypto";
|
|
3928
4060
|
|
|
3929
4061
|
// src/lib/mandate-ceremony.ts
|
|
@@ -4105,7 +4237,7 @@ function secretMatches2(provided, expected) {
|
|
|
4105
4237
|
return a.length === b.length && timingSafeEqual3(a, b);
|
|
4106
4238
|
}
|
|
4107
4239
|
function createInternalMandateRouter(getSecret, deps) {
|
|
4108
|
-
const router =
|
|
4240
|
+
const router = Router17();
|
|
4109
4241
|
router.post("/mandate", async (req, res) => {
|
|
4110
4242
|
if (!secretMatches2(req.header("X-Internal-Secret") ?? void 0, getSecret())) {
|
|
4111
4243
|
res.status(401).json({ error: "unauthorized" });
|
|
@@ -4346,17 +4478,17 @@ function buildSessionHealth(vault2) {
|
|
|
4346
4478
|
}
|
|
4347
4479
|
|
|
4348
4480
|
// src/lib/denials-reader.ts
|
|
4349
|
-
import { existsSync as
|
|
4350
|
-
import { join as
|
|
4481
|
+
import { existsSync as existsSync11, readFileSync as readFileSync13 } from "fs";
|
|
4482
|
+
import { join as join13 } from "path";
|
|
4351
4483
|
function loadDenials(dataDir, decrypt) {
|
|
4352
|
-
const encPath =
|
|
4353
|
-
const plainPath =
|
|
4354
|
-
if (
|
|
4355
|
-
const { blob } = JSON.parse(
|
|
4484
|
+
const encPath = join13(dataDir, "denials.enc.json");
|
|
4485
|
+
const plainPath = join13(dataDir, "denials.json");
|
|
4486
|
+
if (existsSync11(encPath)) {
|
|
4487
|
+
const { blob } = JSON.parse(readFileSync13(encPath, "utf-8"));
|
|
4356
4488
|
return JSON.parse(decrypt(blob)).records ?? [];
|
|
4357
4489
|
}
|
|
4358
|
-
if (
|
|
4359
|
-
return JSON.parse(
|
|
4490
|
+
if (existsSync11(plainPath)) {
|
|
4491
|
+
return JSON.parse(readFileSync13(plainPath, "utf-8")).records ?? [];
|
|
4360
4492
|
}
|
|
4361
4493
|
return [];
|
|
4362
4494
|
}
|
|
@@ -4380,9 +4512,9 @@ function isSimulationMode() {
|
|
|
4380
4512
|
// src/index.ts
|
|
4381
4513
|
(function migrateDataDir() {
|
|
4382
4514
|
if (process.env.SUVEREN_DATA_DIR) return;
|
|
4383
|
-
const oldDir =
|
|
4384
|
-
const newDir =
|
|
4385
|
-
if (!
|
|
4515
|
+
const oldDir = join14(homedir7(), ".hap");
|
|
4516
|
+
const newDir = join14(homedir7(), ".suveren");
|
|
4517
|
+
if (!existsSync12(newDir) && existsSync12(oldDir)) {
|
|
4386
4518
|
try {
|
|
4387
4519
|
renameSync2(oldDir, newDir);
|
|
4388
4520
|
console.error(`[Control Plane] Migrated data directory: ${oldDir} \u2192 ${newDir}`);
|
|
@@ -4392,14 +4524,14 @@ function isSimulationMode() {
|
|
|
4392
4524
|
}
|
|
4393
4525
|
}
|
|
4394
4526
|
})();
|
|
4395
|
-
var DATA_DIR = process.env.SUVEREN_DATA_DIR ??
|
|
4527
|
+
var DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join14(homedir7(), ".suveren");
|
|
4396
4528
|
var SP_URL = resolveAsUrl(DATA_DIR);
|
|
4397
4529
|
validatePinTlsForUrl(resolvePinTls(DATA_DIR), SP_URL);
|
|
4398
4530
|
var POLICY_LOCKED = [...readPolicy().locked];
|
|
4399
4531
|
var POLICY_LOCKED_INSTALL_METHOD = readPolicy().policy.installMethod;
|
|
4400
4532
|
var port = parseInt(process.env.SUVEREN_CP_PORT ?? "3402", 10);
|
|
4401
4533
|
var HAP_MODE = process.env.HAP_MODE ?? "personal";
|
|
4402
|
-
var UI_DIST = process.env.HAP_UI_DIST ??
|
|
4534
|
+
var UI_DIST = process.env.HAP_UI_DIST ?? join14(import.meta.dirname ?? __dirname, "../../ui/dist");
|
|
4403
4535
|
var vault = new Vault(DATA_DIR);
|
|
4404
4536
|
(function repairIfAsUrlChanged() {
|
|
4405
4537
|
const pairing = readPairing(DATA_DIR);
|
|
@@ -4689,6 +4821,7 @@ app.use("/api/gateway-settings", jsonParser, authGuard, createGatewaySettingsRou
|
|
|
4689
4821
|
app.use("/api/archived-mandates", jsonParser, authGuard, createArchivedMandatesRouter());
|
|
4690
4822
|
app.use("/api/encrypt-intent", jsonParser, authGuard, createEncryptIntentRouter());
|
|
4691
4823
|
app.use("/api/evidence-export", authGuard, createEvidenceExportRouter(SP_URL, vault, DATA_DIR, lockAsTlsMismatch));
|
|
4824
|
+
app.use("/proposal-status", authGuard, createProposalStatusRouter(SP_URL, vault, DATA_DIR, lockAsTlsMismatch));
|
|
4692
4825
|
app.use("/api/evidence", authGuard, createEvidenceRouter());
|
|
4693
4826
|
app.use("/api/report", jsonParser, authGuard, createReportRouter(() => RUNNING_VERSION));
|
|
4694
4827
|
app.use("/api/decrypt-intent", jsonParser, authGuard, createDecryptIntentRouter(vault));
|
|
@@ -4851,7 +4984,7 @@ app.get("/as-pairing", authGuard, (_req, res) => {
|
|
|
4851
4984
|
});
|
|
4852
4985
|
app.get("/denials", authGuard, (req, res) => {
|
|
4853
4986
|
try {
|
|
4854
|
-
const dataDir = process.env.SUVEREN_DATA_DIR ??
|
|
4987
|
+
const dataDir = process.env.SUVEREN_DATA_DIR ?? join14(homedir7(), ".suveren");
|
|
4855
4988
|
const all = loadDenials(dataDir, (blob) => vault.decrypt(blob));
|
|
4856
4989
|
const since = Number(req.query.since);
|
|
4857
4990
|
const limit = Number(req.query.limit);
|
|
@@ -4992,7 +5125,7 @@ app.use(
|
|
|
4992
5125
|
function detectInstallMethod2() {
|
|
4993
5126
|
return detectInstallMethod({
|
|
4994
5127
|
dir: import.meta.dirname ?? __dirname,
|
|
4995
|
-
dockerEnv:
|
|
5128
|
+
dockerEnv: existsSync12("/.dockerenv"),
|
|
4996
5129
|
managed: process.env.SUVEREN_INSTALL_METHOD === "managed" || POLICY_LOCKED_INSTALL_METHOD === "managed"
|
|
4997
5130
|
});
|
|
4998
5131
|
}
|
|
@@ -5002,10 +5135,10 @@ function detectRunningVersion() {
|
|
|
5002
5135
|
return process.env.HAP_BUILD_SHA ?? "dev";
|
|
5003
5136
|
}
|
|
5004
5137
|
const dir = import.meta.dirname ?? __dirname;
|
|
5005
|
-
const bundlePkg =
|
|
5006
|
-
if (
|
|
5138
|
+
const bundlePkg = join14(dir, "..", "..", "package.json");
|
|
5139
|
+
if (existsSync12(bundlePkg)) {
|
|
5007
5140
|
try {
|
|
5008
|
-
const pkg = JSON.parse(
|
|
5141
|
+
const pkg = JSON.parse(readFileSync14(bundlePkg, "utf8"));
|
|
5009
5142
|
if (pkg.name === "@suveren/gateway" && typeof pkg.version === "string") {
|
|
5010
5143
|
return pkg.version;
|
|
5011
5144
|
}
|
|
@@ -5047,7 +5180,7 @@ app.get("/health", async (req, res) => {
|
|
|
5047
5180
|
}
|
|
5048
5181
|
});
|
|
5049
5182
|
});
|
|
5050
|
-
if (
|
|
5183
|
+
if (existsSync12(UI_DIST)) {
|
|
5051
5184
|
app.use(express.static(UI_DIST, {
|
|
5052
5185
|
setHeaders: (res, filePath) => {
|
|
5053
5186
|
if (filePath.endsWith("index.html")) {
|
|
@@ -5057,7 +5190,7 @@ if (existsSync11(UI_DIST)) {
|
|
|
5057
5190
|
}));
|
|
5058
5191
|
app.get("*", (_req, res) => {
|
|
5059
5192
|
res.setHeader("Cache-Control", "no-store, must-revalidate");
|
|
5060
|
-
res.sendFile(
|
|
5193
|
+
res.sendFile(join14(UI_DIST, "index.html"));
|
|
5061
5194
|
});
|
|
5062
5195
|
} else {
|
|
5063
5196
|
app.get("/", (_req, res) => {
|