@suveren/gateway 0.4.0 → 0.4.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/ui/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Suveren</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-Cog54HOo.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-JHaCddDE.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the plain-ESM autostart templates.
|
|
3
|
+
*
|
|
4
|
+
* The module is .mjs because the CLI (plain JS, no build step) imports it
|
|
5
|
+
* directly. TypeScript consumers — the tests — need declarations, and without
|
|
6
|
+
* them a typecheck fails with TS7016 rather than checking anything.
|
|
7
|
+
*/
|
|
8
|
+
export declare function escapeXml(value: unknown): string;
|
|
9
|
+
export declare function shellQuote(value: unknown): string;
|
|
10
|
+
|
|
11
|
+
export declare function buildLaunchAgentPlist(opts: {
|
|
12
|
+
launcherPath: string;
|
|
13
|
+
label: string;
|
|
14
|
+
logFile: string;
|
|
15
|
+
dataDir?: string;
|
|
16
|
+
path?: string;
|
|
17
|
+
}): string;
|
|
18
|
+
|
|
19
|
+
export declare function buildMacLauncher(opts: {
|
|
20
|
+
nodePath: string;
|
|
21
|
+
serverEntry: string;
|
|
22
|
+
}): string;
|
|
23
|
+
|
|
24
|
+
export declare function buildSystemdUnit(opts: {
|
|
25
|
+
nodePath: string;
|
|
26
|
+
serverEntry: string;
|
|
27
|
+
logFile: string;
|
|
28
|
+
dataDir?: string;
|
|
29
|
+
path?: string;
|
|
30
|
+
}): string;
|
|
31
|
+
|
|
32
|
+
export declare function buildWindowsTaskXml(opts: {
|
|
33
|
+
nodePath: string;
|
|
34
|
+
serverEntry: string;
|
|
35
|
+
author: string;
|
|
36
|
+
dataDir?: string;
|
|
37
|
+
}): string;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autostart file contents, per platform — pure string builders, no side effects.
|
|
3
|
+
*
|
|
4
|
+
* Separated from the CLI so they can be tested. The macOS plist builder shipped
|
|
5
|
+
* with no tests and interpolated paths straight into XML: a home directory
|
|
6
|
+
* containing `&` or `<` (both legal) produced a malformed plist and an install
|
|
7
|
+
* that failed confusingly. Escaping is applied here, once, for every format
|
|
8
|
+
* that needs it.
|
|
9
|
+
*
|
|
10
|
+
* All three mechanisms are USER-level — no admin, no root:
|
|
11
|
+
* macOS LaunchAgent (~/Library/LaunchAgents)
|
|
12
|
+
* Windows Task Scheduler ONLOGON task, registered from XML
|
|
13
|
+
* Linux systemd user unit (~/.config/systemd/user)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Escape the five XML predefined entities. Used by both plist and Task XML. */
|
|
17
|
+
export function escapeXml(value) {
|
|
18
|
+
return String(value)
|
|
19
|
+
.replace(/&/g, '&')
|
|
20
|
+
.replace(/</g, '<')
|
|
21
|
+
.replace(/>/g, '>')
|
|
22
|
+
.replace(/"/g, '"')
|
|
23
|
+
.replace(/'/g, ''');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* macOS LaunchAgent.
|
|
28
|
+
*
|
|
29
|
+
* RunAtLoad → start at login. KeepAlive → restart on crash. The API key is
|
|
30
|
+
* NEVER placed here: no argument or environment variable carries a secret, so
|
|
31
|
+
* the gateway always boots locked.
|
|
32
|
+
*/
|
|
33
|
+
export function buildLaunchAgentPlist({ launcherPath, label, logFile, dataDir, path }) {
|
|
34
|
+
// launchd hands a process a MINIMAL PATH (/usr/bin:/bin:/usr/sbin:/sbin).
|
|
35
|
+
// The gateway itself still starts — its node path is absolute — but it then
|
|
36
|
+
// cannot find npx or the integration bin shims, so every integration silently
|
|
37
|
+
// fails to launch and the UI shows them all "Not running". Carry the PATH
|
|
38
|
+
// captured at install time, when it is the user's real one.
|
|
39
|
+
const entries = [];
|
|
40
|
+
if (dataDir) entries.push(['SUVEREN_DATA_DIR', dataDir]);
|
|
41
|
+
if (path) entries.push(['PATH', path]);
|
|
42
|
+
|
|
43
|
+
const env = entries.length
|
|
44
|
+
? ' <key>EnvironmentVariables</key>\n <dict>\n' +
|
|
45
|
+
entries.map(([k, v]) => ` <key>${escapeXml(k)}</key>\n <string>${escapeXml(v)}</string>\n`).join('') +
|
|
46
|
+
' </dict>\n'
|
|
47
|
+
: '';
|
|
48
|
+
|
|
49
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
50
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
51
|
+
<plist version="1.0">
|
|
52
|
+
<dict>
|
|
53
|
+
<key>Label</key>
|
|
54
|
+
<string>${escapeXml(label)}</string>
|
|
55
|
+
<key>ProgramArguments</key>
|
|
56
|
+
<array>
|
|
57
|
+
<string>${escapeXml(launcherPath)}</string>
|
|
58
|
+
</array>
|
|
59
|
+
<key>RunAtLoad</key>
|
|
60
|
+
<true/>
|
|
61
|
+
<key>KeepAlive</key>
|
|
62
|
+
<true/>
|
|
63
|
+
<key>StandardOutPath</key>
|
|
64
|
+
<string>${escapeXml(logFile)}</string>
|
|
65
|
+
<key>StandardErrorPath</key>
|
|
66
|
+
<string>${escapeXml(logFile)}</string>
|
|
67
|
+
${env}</dict>
|
|
68
|
+
</plist>
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* A tiny launcher whose FILENAME is what macOS shows in
|
|
75
|
+
* System Settings → Login Items & Extensions.
|
|
76
|
+
*
|
|
77
|
+
* Pointing launchd straight at the node binary made the entry read "node —
|
|
78
|
+
* Item from unidentified developer": the user cannot tell what it is, and it
|
|
79
|
+
* looks like something that wandered in. A file named `Suveren` reads as
|
|
80
|
+
* itself.
|
|
81
|
+
*
|
|
82
|
+
* ("Unidentified developer" persists regardless — it means the node binary is
|
|
83
|
+
* not signed and notarized by a registered Apple developer, which is true of
|
|
84
|
+
* every Homebrew and nvm install. Nothing is bypassed; it is your own node
|
|
85
|
+
* running your own code.)
|
|
86
|
+
*/
|
|
87
|
+
export function buildMacLauncher({ nodePath, serverEntry }) {
|
|
88
|
+
// exec, so the launcher does not linger as an extra process between launchd
|
|
89
|
+
// and the gateway — launchd's KeepAlive and signal delivery then apply to
|
|
90
|
+
// the gateway itself.
|
|
91
|
+
return `#!/bin/sh
|
|
92
|
+
# Generated by \`suveren-gateway service install\`. Safe to delete once the
|
|
93
|
+
# login item is removed.
|
|
94
|
+
exec ${shellQuote(nodePath)} ${shellQuote(serverEntry)} --autostart "$@"
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Single-quote for /bin/sh, escaping embedded quotes. */
|
|
99
|
+
export function shellQuote(value) {
|
|
100
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Linux systemd USER unit.
|
|
105
|
+
*
|
|
106
|
+
* Restart=always is the KeepAlive equivalent. WantedBy=default.target starts it
|
|
107
|
+
* with the user session; `loginctl enable-linger` (offered separately) extends
|
|
108
|
+
* that to boot, before any login.
|
|
109
|
+
*
|
|
110
|
+
* Environment values are quoted because systemd splits unquoted values on
|
|
111
|
+
* whitespace — a data directory with a space would otherwise be truncated.
|
|
112
|
+
*/
|
|
113
|
+
export function buildSystemdUnit({ nodePath, serverEntry, logFile, dataDir, path }) {
|
|
114
|
+
// Same problem as launchd: a systemd user unit does not inherit the shell's
|
|
115
|
+
// PATH, so npx and the integration shims go missing and every integration
|
|
116
|
+
// fails to start.
|
|
117
|
+
const envLines = [];
|
|
118
|
+
if (dataDir) envLines.push(`Environment="SUVEREN_DATA_DIR=${dataDir}"`);
|
|
119
|
+
if (path) envLines.push(`Environment="PATH=${path}"`);
|
|
120
|
+
const envLine = envLines.length ? envLines.join('\n') + '\n' : '';
|
|
121
|
+
return `[Unit]
|
|
122
|
+
Description=Suveren gateway (Human Agency Protocol)
|
|
123
|
+
Documentation=https://www.suveren.ai
|
|
124
|
+
After=network-online.target
|
|
125
|
+
|
|
126
|
+
[Service]
|
|
127
|
+
Type=simple
|
|
128
|
+
ExecStart=${nodePath} ${serverEntry} --autostart
|
|
129
|
+
${envLine}Restart=always
|
|
130
|
+
RestartSec=5
|
|
131
|
+
# The gateway boots LOCKED. Nothing in this unit can unlock the vault, so a
|
|
132
|
+
# restart brings the process back but never the credentials.
|
|
133
|
+
StandardOutput=append:${logFile}
|
|
134
|
+
StandardError=append:${logFile}
|
|
135
|
+
|
|
136
|
+
[Install]
|
|
137
|
+
WantedBy=default.target
|
|
138
|
+
`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Windows Task Scheduler task, as registration XML.
|
|
143
|
+
*
|
|
144
|
+
* Registered with `schtasks /Create /XML`. XML rather than the flag form
|
|
145
|
+
* because the flags cannot express restart-on-failure, and cannot reliably
|
|
146
|
+
* carry paths containing spaces.
|
|
147
|
+
*
|
|
148
|
+
* LogonType=InteractiveToken keeps it in the user's own session with no stored
|
|
149
|
+
* password and no admin rights. Hidden + no execution time limit stop it
|
|
150
|
+
* flashing a console window or being killed after the default 72 hours.
|
|
151
|
+
*/
|
|
152
|
+
export function buildWindowsTaskXml({ nodePath, serverEntry, author, dataDir }) {
|
|
153
|
+
// Task Scheduler requires \Command to be the executable and \Arguments the
|
|
154
|
+
// rest; quoting the script path handles spaces (e.g. under "Program Files").
|
|
155
|
+
// Task Scheduler XML carries no environment block, so the marker that this
|
|
156
|
+
// was a service start has to ride in the arguments.
|
|
157
|
+
const args = `"${serverEntry}" --autostart`;
|
|
158
|
+
const envNote = dataDir ? `Suveren data directory: ${dataDir}` : 'Suveren gateway';
|
|
159
|
+
|
|
160
|
+
return `<?xml version="1.0" encoding="UTF-16"?>
|
|
161
|
+
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
162
|
+
<RegistrationInfo>
|
|
163
|
+
<Description>${escapeXml(envNote)}</Description>
|
|
164
|
+
<Author>${escapeXml(author)}</Author>
|
|
165
|
+
</RegistrationInfo>
|
|
166
|
+
<Triggers>
|
|
167
|
+
<LogonTrigger>
|
|
168
|
+
<Enabled>true</Enabled>
|
|
169
|
+
</LogonTrigger>
|
|
170
|
+
</Triggers>
|
|
171
|
+
<Principals>
|
|
172
|
+
<Principal id="Author">
|
|
173
|
+
<LogonType>InteractiveToken</LogonType>
|
|
174
|
+
<RunLevel>LeastPrivilege</RunLevel>
|
|
175
|
+
</Principal>
|
|
176
|
+
</Principals>
|
|
177
|
+
<Settings>
|
|
178
|
+
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
179
|
+
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
180
|
+
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
181
|
+
<AllowHardTerminate>true</AllowHardTerminate>
|
|
182
|
+
<StartWhenAvailable>true</StartWhenAvailable>
|
|
183
|
+
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
|
184
|
+
<IdleSettings>
|
|
185
|
+
<StopOnIdleEnd>false</StopOnIdleEnd>
|
|
186
|
+
<RestartOnIdle>false</RestartOnIdle>
|
|
187
|
+
</IdleSettings>
|
|
188
|
+
<AllowStartOnDemand>true</AllowStartOnDemand>
|
|
189
|
+
<Enabled>true</Enabled>
|
|
190
|
+
<Hidden>true</Hidden>
|
|
191
|
+
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
|
192
|
+
<WakeToRun>false</WakeToRun>
|
|
193
|
+
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
|
|
194
|
+
<Priority>7</Priority>
|
|
195
|
+
<RestartOnFailure>
|
|
196
|
+
<Interval>PT1M</Interval>
|
|
197
|
+
<Count>3</Count>
|
|
198
|
+
</RestartOnFailure>
|
|
199
|
+
</Settings>
|
|
200
|
+
<Actions Context="Author">
|
|
201
|
+
<Exec>
|
|
202
|
+
<Command>${escapeXml(nodePath)}</Command>
|
|
203
|
+
<Arguments>${escapeXml(args)}</Arguments>
|
|
204
|
+
</Exec>
|
|
205
|
+
</Actions>
|
|
206
|
+
</Task>
|
|
207
|
+
`;
|
|
208
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suveren/gateway",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.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",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"bin",
|
|
15
|
+
"lib",
|
|
15
16
|
"dist",
|
|
16
17
|
"scripts",
|
|
17
18
|
"content",
|