@suveren/gateway 0.18.2 → 0.19.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/README.md +16 -1
- package/bin/suveren-gateway.js +204 -13
- package/dist/control-plane/index.mjs +22 -0
- package/dist/mcp-server/chunk-ZRRZFGRL.mjs +2412 -0
- package/dist/mcp-server/http.mjs +385 -674
- package/dist/mcp-server/report-verify-cli.mjs +64 -7
- package/dist/ui/assets/index-DF3kB2R3.js +111 -0
- package/dist/ui/assets/index-kObsFuwK.css +1 -0
- package/dist/ui/index.html +2 -2
- package/lib/install-settings.d.mts +41 -0
- package/lib/install-settings.mjs +318 -0
- package/lib/policy.d.mts +6 -1
- package/lib/policy.mjs +48 -4
- package/node_modules/@hap/core/dist/index.d.mts +13 -0
- package/node_modules/@hap/core/dist/index.d.ts +13 -0
- package/node_modules/@hap/core/package.json +1 -1
- package/node_modules/@hap/core/src/types.ts +13 -0
- package/package.json +1 -1
- package/profiles/index.json +2 -1
- package/profiles/reporting/0.2.profile.json +98 -0
- package/server.js +20 -4
- package/dist/mcp-server/chunk-QOKPECVY.mjs +0 -751
- package/dist/ui/assets/index-Bfi-G4qJ.css +0 -1
- package/dist/ui/assets/index-D0uXCqQB.js +0 -111
|
@@ -315,6 +315,19 @@ interface ProfileBoundsField {
|
|
|
315
315
|
* kinds, and the same boundType can carry different units.
|
|
316
316
|
*/
|
|
317
317
|
unit?: FieldUnit;
|
|
318
|
+
/**
|
|
319
|
+
* The largest value a mandate may set for this (numeric) bound — a ceiling
|
|
320
|
+
* on what the owner can grant, declared by the profile. E.g. reporting@0.2
|
|
321
|
+
* `read_max_age_days: { maximum: 366 }`: no reporting mandate may read back
|
|
322
|
+
* further than a year.
|
|
323
|
+
*
|
|
324
|
+
* Distinct from the bound itself: the bound limits each ACTION; `maximum`
|
|
325
|
+
* limits the MANDATE. A value above it is not a valid mandate for this
|
|
326
|
+
* profile — the mandate editor caps its input, the issuing Authority Server
|
|
327
|
+
* should refuse it, and an enforcement point that reads the bound applies
|
|
328
|
+
* min(value, maximum). Absent → no ceiling.
|
|
329
|
+
*/
|
|
330
|
+
maximum?: number;
|
|
318
331
|
/** @deprecated v0.4: use boundType instead. */
|
|
319
332
|
constraint?: FieldConstraint;
|
|
320
333
|
/** @deprecated v0.4: use boundType: { kind: 'enum', values: [...] }. */
|
|
@@ -320,6 +320,19 @@ export interface ProfileBoundsField {
|
|
|
320
320
|
* kinds, and the same boundType can carry different units.
|
|
321
321
|
*/
|
|
322
322
|
unit?: FieldUnit;
|
|
323
|
+
/**
|
|
324
|
+
* The largest value a mandate may set for this (numeric) bound — a ceiling
|
|
325
|
+
* on what the owner can grant, declared by the profile. E.g. reporting@0.2
|
|
326
|
+
* `read_max_age_days: { maximum: 366 }`: no reporting mandate may read back
|
|
327
|
+
* further than a year.
|
|
328
|
+
*
|
|
329
|
+
* Distinct from the bound itself: the bound limits each ACTION; `maximum`
|
|
330
|
+
* limits the MANDATE. A value above it is not a valid mandate for this
|
|
331
|
+
* profile — the mandate editor caps its input, the issuing Authority Server
|
|
332
|
+
* should refuse it, and an enforcement point that reads the bound applies
|
|
333
|
+
* min(value, maximum). Absent → no ceiling.
|
|
334
|
+
*/
|
|
335
|
+
maximum?: number;
|
|
323
336
|
/** @deprecated v0.4: use boundType instead. */
|
|
324
337
|
constraint?: FieldConstraint;
|
|
325
338
|
/** @deprecated v0.4: use boundType: { kind: 'enum', values: [...] }. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suveren/gateway",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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",
|
package/profiles/index.json
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"github.com/humanagencyprotocol/hap-profiles/sales@0.3": "sales/0.3.profile.json",
|
|
31
31
|
"github.com/humanagencyprotocol/hap-profiles/purchase@0.6": "purchase/0.6.profile.json",
|
|
32
32
|
"github.com/humanagencyprotocol/hap-profiles/reporting@0.1": "reporting/0.1.profile.json",
|
|
33
|
-
"github.com/humanagencyprotocol/hap-profiles/delegation@0.1": "delegation/0.1.profile.json"
|
|
33
|
+
"github.com/humanagencyprotocol/hap-profiles/delegation@0.1": "delegation/0.1.profile.json",
|
|
34
|
+
"github.com/humanagencyprotocol/hap-profiles/reporting@0.2": "reporting/0.2.profile.json"
|
|
34
35
|
}
|
|
35
36
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "github.com/humanagencyprotocol/hap-profiles/reporting@0.2",
|
|
3
|
+
"name": "Reporting",
|
|
4
|
+
"version": "0.2",
|
|
5
|
+
"description": "Reporting authority — lets an agent read the evidence a gateway holds (tickets, approvals, mandates, records in the systems it connects) and write one report stored on that machine. Changes no system.",
|
|
6
|
+
"whatsNew": "Adds a reporting window: the agent only sees, opens and exports evidence from the last N days (read_max_age_days). Anything older is invisible to it and cannot enter a report or an export.",
|
|
7
|
+
"boundsSchema": {
|
|
8
|
+
"actionTypes": [
|
|
9
|
+
"report"
|
|
10
|
+
],
|
|
11
|
+
"keyOrder": [
|
|
12
|
+
"profile",
|
|
13
|
+
"read_access",
|
|
14
|
+
"read_max_age_days",
|
|
15
|
+
"report_daily_max"
|
|
16
|
+
],
|
|
17
|
+
"fields": {
|
|
18
|
+
"profile": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"required": true
|
|
21
|
+
},
|
|
22
|
+
"read_access": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"required": true,
|
|
25
|
+
"displayName": "Read evidence",
|
|
26
|
+
"description": "Allow the agent to read tickets, approvals, mandates and the records in connected systems, to build a report",
|
|
27
|
+
"boundType": {
|
|
28
|
+
"kind": "enum",
|
|
29
|
+
"values": [
|
|
30
|
+
"unlimited",
|
|
31
|
+
"none"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"toolsDescription": "tickets, approvals, mandates, system records",
|
|
35
|
+
"default": "unlimited"
|
|
36
|
+
},
|
|
37
|
+
"read_max_age_days": {
|
|
38
|
+
"type": "number",
|
|
39
|
+
"required": true,
|
|
40
|
+
"displayName": "Reporting window (days)",
|
|
41
|
+
"description": "How far back the agent may read evidence for a report: tickets, approvals, mandates and records from the last N days, at most 366. Anything older is invisible to the agent and cannot enter a report or an export. Enforced locally by the gateway (reads carry no ticket); signed here so the window the owner approved is part of the mandate.",
|
|
42
|
+
"unit": "days",
|
|
43
|
+
"boundType": {
|
|
44
|
+
"kind": "per_transaction",
|
|
45
|
+
"of": "read_age_days"
|
|
46
|
+
},
|
|
47
|
+
"maximum": 366,
|
|
48
|
+
"default": 30
|
|
49
|
+
},
|
|
50
|
+
"report_daily_max": {
|
|
51
|
+
"type": "number",
|
|
52
|
+
"required": true,
|
|
53
|
+
"displayName": "Report updates per day",
|
|
54
|
+
"description": "Maximum times per day the agent may write or replace the report",
|
|
55
|
+
"unit": "count",
|
|
56
|
+
"boundType": {
|
|
57
|
+
"kind": "cumulative_count",
|
|
58
|
+
"window": "daily"
|
|
59
|
+
},
|
|
60
|
+
"appliesTo": [
|
|
61
|
+
"report"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"executionContextSchema": {
|
|
67
|
+
"fields": {
|
|
68
|
+
"report_count_daily": {
|
|
69
|
+
"source": "cumulative",
|
|
70
|
+
"cumulativeField": "_count",
|
|
71
|
+
"window": "daily",
|
|
72
|
+
"description": "Running daily count of report writes",
|
|
73
|
+
"required": true,
|
|
74
|
+
"constraint": {
|
|
75
|
+
"type": "number",
|
|
76
|
+
"enforceable": [
|
|
77
|
+
"max"
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"requiredGates": [
|
|
84
|
+
"bounds",
|
|
85
|
+
"intent",
|
|
86
|
+
"commitment",
|
|
87
|
+
"decision_owner"
|
|
88
|
+
],
|
|
89
|
+
"ttl": {
|
|
90
|
+
"default": 86400,
|
|
91
|
+
"max": 2592000
|
|
92
|
+
},
|
|
93
|
+
"retention_minimum": 7776000,
|
|
94
|
+
"content_binding": {
|
|
95
|
+
"version": "1",
|
|
96
|
+
"kind": "jcs"
|
|
97
|
+
}
|
|
98
|
+
}
|
package/server.js
CHANGED
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
import { spawn } from 'node:child_process';
|
|
11
11
|
import { dirname, join } from 'node:path';
|
|
12
12
|
import { fileURLToPath } from 'node:url';
|
|
13
|
-
import {
|
|
13
|
+
import { tmpdir, constants as osConstants } from 'node:os';
|
|
14
14
|
import { existsSync, mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
|
|
15
15
|
import { resolveCaFile, resolveProxyUrl, resolveSimulation } from './lib/config.mjs';
|
|
16
16
|
import { readPolicy, isPolicyLocked } from './lib/policy.mjs';
|
|
17
17
|
import { unsupportedNodeReason } from './lib/node-version.mjs';
|
|
18
|
+
import { resolveInstallSettings } from './lib/install-settings.mjs';
|
|
18
19
|
|
|
19
20
|
// Docker and the login service start this file directly, not through the CLI,
|
|
20
21
|
// so it checks the Node version too (see lib/node-version.mjs).
|
|
@@ -63,7 +64,19 @@ function exitLikeChild(code, signal) {
|
|
|
63
64
|
// MERGED into one combined PEM file instead. Comparing against that combined
|
|
64
65
|
// path would never match the saved path alone, so the guard has to be a
|
|
65
66
|
// dedicated marker, not a value comparison (which would also re-exec forever).
|
|
66
|
-
|
|
67
|
+
// Ports + data folder: IT policy > env > saved install setting > default
|
|
68
|
+
// (see lib/install-settings.mjs). Resolved here, not just in the CLI,
|
|
69
|
+
// because the login service starts this file directly. Refuses to start on
|
|
70
|
+
// an invalid value rather than guessing a port or a folder.
|
|
71
|
+
let INSTALL;
|
|
72
|
+
try {
|
|
73
|
+
INSTALL = resolveInstallSettings();
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error(`[suveren-gateway] ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
console.error('[suveren-gateway] Fix it with `suveren-gateway config set …` (see `suveren-gateway config help`).');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
const DATA_DIR = INSTALL.dataDir;
|
|
67
80
|
const savedCaFile = resolveCaFile(DATA_DIR);
|
|
68
81
|
if (savedCaFile && !process.env.SUVEREN_CA_REEXEC_DONE) {
|
|
69
82
|
let effectiveCaFile = savedCaFile;
|
|
@@ -159,8 +172,8 @@ if (policyNoProxy) {
|
|
|
159
172
|
process.env.NO_PROXY = policyNoProxy;
|
|
160
173
|
}
|
|
161
174
|
|
|
162
|
-
const CP_PORT =
|
|
163
|
-
const MCP_PORT =
|
|
175
|
+
const CP_PORT = String(INSTALL.cpPort);
|
|
176
|
+
const MCP_PORT = String(INSTALL.mcpPort);
|
|
164
177
|
const UI_DIST = process.env.HAP_UI_DIST ?? join(__dirname, 'dist', 'ui');
|
|
165
178
|
// Integration manifests + profile catalog ship inside the bundle so a
|
|
166
179
|
// fresh `npm install -g` install has working integrations and profiles
|
|
@@ -176,6 +189,9 @@ const env = {
|
|
|
176
189
|
NODE_ENV: 'production',
|
|
177
190
|
SUVEREN_CP_PORT: CP_PORT,
|
|
178
191
|
SUVEREN_MCP_PORT: MCP_PORT,
|
|
192
|
+
// Only when not the default: the control plane's one-time ~/.hap →
|
|
193
|
+
// ~/.suveren migration runs only while SUVEREN_DATA_DIR is unset.
|
|
194
|
+
...(INSTALL.source.dataDir !== 'default' ? { SUVEREN_DATA_DIR: DATA_DIR } : {}),
|
|
179
195
|
// The control plane talks to the MCP server over this URL. It defaults to
|
|
180
196
|
// 127.0.0.1:3430 in mcp-bridge.ts, so if the user overrode SUVEREN_MCP_PORT
|
|
181
197
|
// without also setting this, every CP→MCP internal call hit the wrong port
|