@openagt/install 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +9 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +15 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +181 -0
- package/dist/install.js.map +1 -0
- package/dist/mac.d.ts +76 -0
- package/dist/mac.d.ts.map +1 -0
- package/dist/mac.js +144 -0
- package/dist/mac.js.map +1 -0
- package/package.json +41 -3
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Suleiman Shahbari
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,OAAO,EAAE;KACN,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;KAChC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAkB,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Where the commands write. */
|
|
2
|
+
export interface InstallIO {
|
|
3
|
+
out: (line: string) => void;
|
|
4
|
+
err: (line: string) => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* `npx @openagt/install`: the dashboard starts at login, at `https://openagent.build`. Asks
|
|
8
|
+
* for the person's password twice: macOS's own window, to trust the certificate made here, and
|
|
9
|
+
* once in this terminal, as the administrator, for the name and its port. Typed again, it does
|
|
10
|
+
* the same, and asks nothing it needs no more.
|
|
11
|
+
*/
|
|
12
|
+
export declare function install(io?: InstallIO, env?: NodeJS.ProcessEnv): Promise<number>;
|
|
13
|
+
/** `npx @openagt/uninstall`: everything {@link install} put on this Mac, taken off. Each part is taken off even when another fails. */
|
|
14
|
+
export declare function uninstall(io?: InstallIO, env?: NodeJS.ProcessEnv): Promise<number>;
|
|
15
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAWA,gCAAgC;AAChC,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5B;AAuGD;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,EAAE,GAAE,SAAqB,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6C9G;AAED,uIAAuI;AACvI,wBAAsB,SAAS,CAAC,EAAE,GAAE,SAAqB,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkChH"}
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { execFile, spawn } from 'node:child_process';
|
|
2
|
+
import { X509Certificate } from 'node:crypto';
|
|
3
|
+
import { mkdir, readFile, realpath, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { request } from 'node:https';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import { connect } from 'node:net';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import { CERTIFICATE_FILE, KEY_FILE, readSecureAddress, secureAddressDir } from '@openagt/dashboard/secure-address';
|
|
10
|
+
import { ADDRESS, CERTIFICATE_DAYS, DASHBOARD_LABEL, LOOPBACK_ADDRESS, adminInstallScript, adminUninstallScript, certificateConfig, dashboardPlist } from './mac.js';
|
|
11
|
+
const defaultIO = {
|
|
12
|
+
out: line => process.stdout.write(line + '\n'),
|
|
13
|
+
err: line => process.stderr.write(line + '\n'),
|
|
14
|
+
};
|
|
15
|
+
/** The port the dashboard's plain address is on, which the install's dashboard takes. */
|
|
16
|
+
const DASHBOARD_PORT = 4200;
|
|
17
|
+
/** Where the install keeps what it puts on this Mac, outside the secure address's own folder. */
|
|
18
|
+
function places(env) {
|
|
19
|
+
const home = env.HOME || homedir();
|
|
20
|
+
return {
|
|
21
|
+
home,
|
|
22
|
+
agent: join(home, 'Library', 'LaunchAgents', `${DASHBOARD_LABEL}.plist`),
|
|
23
|
+
logs: join(home, 'Library', 'Logs', 'OpenAgent'),
|
|
24
|
+
app: join(home, 'Library', 'Application Support', 'OpenAgent'),
|
|
25
|
+
keychain: join(home, 'Library', 'Keychains', 'login.keychain-db'),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Run a command to its end; rejects with what it said when it fails. `interactive` gives it this terminal, for a password. */
|
|
29
|
+
function run(command, args, opts = {}) {
|
|
30
|
+
if (opts.interactive) {
|
|
31
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
32
|
+
spawn(command, args, { stdio: 'inherit' })
|
|
33
|
+
.on('error', rejectPromise)
|
|
34
|
+
.on('exit', code => (code === 0 ? resolvePromise() : rejectPromise(new Error(`${command} ended with ${code}`))));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
38
|
+
execFile(command, args, (error, _stdout, stderr) => (error ? rejectPromise(new Error(String(stderr).trim() || error.message)) : resolvePromise()));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** Whether something answers on this computer's `port`. */
|
|
42
|
+
function taken(port) {
|
|
43
|
+
return new Promise(resolvePromise => {
|
|
44
|
+
const socket = connect(port, '127.0.0.1');
|
|
45
|
+
socket.once('connect', () => (socket.destroy(), resolvePromise(true)));
|
|
46
|
+
socket.once('error', () => resolvePromise(false));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The dashboard the launch agent runs. Run from a checkout, or from a folder of its own, it is
|
|
51
|
+
* the one this command came with. Run by `npx`, that one is in npm's cache, which npm empties
|
|
52
|
+
* when it likes: the same version is installed to a folder of OpenAgent's own.
|
|
53
|
+
*/
|
|
54
|
+
async function lastingDashboard(app, io) {
|
|
55
|
+
const manifest = await realpath(createRequire(import.meta.url).resolve('@openagt/dashboard/package.json'));
|
|
56
|
+
if (!manifest.includes('/_npx/'))
|
|
57
|
+
return join(dirname(manifest), 'dist', 'cli', 'bin.js');
|
|
58
|
+
const { version } = JSON.parse(await readFile(manifest, 'utf8'));
|
|
59
|
+
io.out(`◆ installing OpenAgent v${version} in ${app}`);
|
|
60
|
+
await mkdir(app, { recursive: true });
|
|
61
|
+
await run('npm', ['install', '--prefix', app, '--no-fund', '--no-audit', `@openagt/dashboard@${version}`]);
|
|
62
|
+
return join(app, 'node_modules', '@openagt', 'dashboard', 'dist', 'cli', 'bin.js');
|
|
63
|
+
}
|
|
64
|
+
/** The certificate for {@link ADDRESS}, made on this computer when there is none for it. */
|
|
65
|
+
async function ensureCertificate(env) {
|
|
66
|
+
const kept = await readSecureAddress(env).catch(() => undefined);
|
|
67
|
+
if (kept?.name === ADDRESS)
|
|
68
|
+
return kept.cert;
|
|
69
|
+
const dir = secureAddressDir(env);
|
|
70
|
+
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
71
|
+
const config = join(dir, 'openssl.cnf');
|
|
72
|
+
await writeFile(config, certificateConfig(ADDRESS));
|
|
73
|
+
await run('openssl', ['req', '-x509', '-newkey', 'rsa:2048', '-nodes', '-keyout', join(dir, KEY_FILE), '-out', join(dir, CERTIFICATE_FILE), '-days', String(CERTIFICATE_DAYS), '-config', config, '-extensions', 'ext']);
|
|
74
|
+
await rm(config);
|
|
75
|
+
return readFile(join(dir, CERTIFICATE_FILE), 'utf8');
|
|
76
|
+
}
|
|
77
|
+
/** Whether this Mac trusts the certificate for {@link ADDRESS} already, so a second install asks nothing. */
|
|
78
|
+
function trusted(certFile) {
|
|
79
|
+
return run('security', ['verify-cert', '-c', certFile, '-p', 'ssl', '-s', ADDRESS, '-q']).then(() => true, () => false);
|
|
80
|
+
}
|
|
81
|
+
/** Whether the secure address answers with the dashboard, as a browser reaches it. */
|
|
82
|
+
function answers(cert) {
|
|
83
|
+
return new Promise(resolvePromise => {
|
|
84
|
+
const req = request({ host: LOOPBACK_ADDRESS, port: 443, path: '/', servername: ADDRESS, ca: cert, headers: { host: ADDRESS }, timeout: 2000 }, res => {
|
|
85
|
+
res.resume();
|
|
86
|
+
resolvePromise(res.statusCode === 200);
|
|
87
|
+
});
|
|
88
|
+
req.on('error', () => resolvePromise(false));
|
|
89
|
+
req.on('timeout', () => req.destroy());
|
|
90
|
+
req.end();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async function waitUntilAnswers(cert, ms) {
|
|
94
|
+
const until = Date.now() + ms;
|
|
95
|
+
while (Date.now() < until) {
|
|
96
|
+
if (await answers(cert))
|
|
97
|
+
return true;
|
|
98
|
+
await new Promise(resolvePromise => setTimeout(resolvePromise, 500));
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* `npx @openagt/install`: the dashboard starts at login, at `https://openagent.build`. Asks
|
|
104
|
+
* for the person's password twice: macOS's own window, to trust the certificate made here, and
|
|
105
|
+
* once in this terminal, as the administrator, for the name and its port. Typed again, it does
|
|
106
|
+
* the same, and asks nothing it needs no more.
|
|
107
|
+
*/
|
|
108
|
+
export async function install(io = defaultIO, env = process.env) {
|
|
109
|
+
if (process.platform !== 'darwin') {
|
|
110
|
+
io.err('For now OpenAgent installs on a Mac only. On this computer, run `npx @openagt/dashboard`.');
|
|
111
|
+
return 1;
|
|
112
|
+
}
|
|
113
|
+
const place = places(env);
|
|
114
|
+
const uid = process.getuid?.() ?? 0;
|
|
115
|
+
// One installed already stops first, so what holds the port below is someone else's.
|
|
116
|
+
await run('launchctl', ['bootout', `gui/${uid}/${DASHBOARD_LABEL}`]).catch(() => { });
|
|
117
|
+
if (await taken(DASHBOARD_PORT)) {
|
|
118
|
+
io.err(`A dashboard runs on port ${DASHBOARD_PORT} already. Stop it (Ctrl+C in its terminal), then run this again.`);
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const dashboard = await lastingDashboard(place.app, io);
|
|
123
|
+
const cert = await ensureCertificate(env);
|
|
124
|
+
const certFile = join(secureAddressDir(env), CERTIFICATE_FILE);
|
|
125
|
+
if (!(await trusted(certFile))) {
|
|
126
|
+
io.out(`◆ a certificate for ${ADDRESS} was made on this Mac. macOS asks for your password to trust it.`);
|
|
127
|
+
await run('security', ['add-trusted-cert', '-r', 'trustRoot', '-p', 'ssl', '-k', place.keychain, certFile]);
|
|
128
|
+
}
|
|
129
|
+
io.out(`◆ your password as the administrator, once: ${ADDRESS} is pointed at this Mac (/etc/hosts), and its port 443 at the dashboard (a packet filter rule).`);
|
|
130
|
+
await run('sudo', ['/bin/sh', '-c', adminInstallScript(ADDRESS)], { interactive: true });
|
|
131
|
+
await mkdir(place.logs, { recursive: true });
|
|
132
|
+
await mkdir(dirname(place.agent), { recursive: true });
|
|
133
|
+
const log = join(place.logs, 'dashboard.log');
|
|
134
|
+
const agentEnv = { PATH: env.PATH ?? '/usr/bin:/bin:/usr/sbin:/sbin', ...(env.XDG_CONFIG_HOME ? { XDG_CONFIG_HOME: env.XDG_CONFIG_HOME } : {}) };
|
|
135
|
+
await writeFile(place.agent, dashboardPlist({ node: process.execPath, dashboard, home: place.home, env: agentEnv, log }));
|
|
136
|
+
await run('launchctl', ['bootstrap', `gui/${uid}`, place.agent]);
|
|
137
|
+
if (!(await waitUntilAnswers(cert, 30_000))) {
|
|
138
|
+
io.err(`The dashboard does not answer at https://${ADDRESS} yet. What it says is in ${log}.`);
|
|
139
|
+
return 1;
|
|
140
|
+
}
|
|
141
|
+
io.out(`◆ OpenAgent is installed: https://${ADDRESS}`);
|
|
142
|
+
io.out(' It starts when you log in. `npx @openagt/uninstall` takes it off again.');
|
|
143
|
+
spawn('open', [`https://${ADDRESS}`], { stdio: 'ignore', detached: true }).on('error', () => { }).unref();
|
|
144
|
+
return 0;
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
io.err(`OpenAgent could not be installed: ${err instanceof Error ? err.message : String(err)}`);
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** `npx @openagt/uninstall`: everything {@link install} put on this Mac, taken off. Each part is taken off even when another fails. */
|
|
152
|
+
export async function uninstall(io = defaultIO, env = process.env) {
|
|
153
|
+
if (process.platform !== 'darwin') {
|
|
154
|
+
io.err('OpenAgent installs on a Mac only, so there is nothing to take off here.');
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
const place = places(env);
|
|
158
|
+
const uid = process.getuid?.() ?? 0;
|
|
159
|
+
await run('launchctl', ['bootout', `gui/${uid}/${DASHBOARD_LABEL}`]).catch(() => { });
|
|
160
|
+
await rm(place.agent, { force: true });
|
|
161
|
+
const dir = secureAddressDir(env);
|
|
162
|
+
const pem = await readFile(join(dir, CERTIFICATE_FILE), 'utf8').catch(() => undefined);
|
|
163
|
+
if (pem !== undefined) {
|
|
164
|
+
io.out('◆ macOS asks for your password to stop trusting the certificate.');
|
|
165
|
+
await run('security', ['remove-trusted-cert', join(dir, CERTIFICATE_FILE)]).catch(() => { });
|
|
166
|
+
const sha1 = new X509Certificate(pem).fingerprint.replaceAll(':', '');
|
|
167
|
+
await run('security', ['delete-certificate', '-Z', sha1, place.keychain]).catch(() => { });
|
|
168
|
+
}
|
|
169
|
+
io.out(`◆ your password as the administrator, once: the hosts line for ${ADDRESS} and its port rule are taken off.`);
|
|
170
|
+
const admin = await run('sudo', ['/bin/sh', '-c', adminUninstallScript()], { interactive: true }).then(() => true, () => false);
|
|
171
|
+
await rm(dir, { recursive: true, force: true });
|
|
172
|
+
await rm(place.app, { recursive: true, force: true });
|
|
173
|
+
await rm(place.logs, { recursive: true, force: true });
|
|
174
|
+
if (!admin) {
|
|
175
|
+
io.err(`The hosts line and the port rule are still there: run this again to take them off.`);
|
|
176
|
+
return 1;
|
|
177
|
+
}
|
|
178
|
+
io.out('◆ OpenAgent is off this Mac. Your projects and their agents’ records are left as they were.');
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
|
package/dist/mac.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the install puts on a Mac, as text: the files it writes and the one script it runs as the
|
|
3
|
+
* administrator. Pure, so a test reads each one; {@link install} and {@link uninstall} write and run them.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The dashboard's secure address: the website's own name, which this computer then answers
|
|
7
|
+
* itself, the dashboard with the website's copy beside it (#1919).
|
|
8
|
+
*/
|
|
9
|
+
export declare const ADDRESS = "openagent.build";
|
|
10
|
+
/**
|
|
11
|
+
* The address the name points at: one of this computer's own, the address's alone. The port rule
|
|
12
|
+
* then touches nothing else this computer sends itself on port 443 (a container a developer
|
|
13
|
+
* publishes there, say), as a rule for `127.0.0.1` would.
|
|
14
|
+
*/
|
|
15
|
+
export declare const LOOPBACK_ADDRESS = "127.0.0.42";
|
|
16
|
+
/** What starts the dashboard at login: a launch agent of the person's own. */
|
|
17
|
+
export declare const DASHBOARD_LABEL = "build.openagent.dashboard";
|
|
18
|
+
/** What sends the address's port 443 to the dashboard at every start of the Mac: a launch daemon, the system's. */
|
|
19
|
+
export declare const PORT_LABEL = "build.openagent.port";
|
|
20
|
+
export declare const PORT_PLIST = "/Library/LaunchDaemons/build.openagent.port.plist";
|
|
21
|
+
/**
|
|
22
|
+
* The port rule's place: a part of Apple's own `com.apple` rules, which `/etc/pf.conf` reads
|
|
23
|
+
* whatever is in them, so the file itself is never changed.
|
|
24
|
+
*/
|
|
25
|
+
export declare const PORT_ANCHOR = "com.apple/openagent";
|
|
26
|
+
export declare const PORT_RULE_FILE = "/etc/pf.anchors/build.openagent";
|
|
27
|
+
/** The end of the hosts line the install adds, which is how the uninstall finds it again. */
|
|
28
|
+
export declare const HOSTS_MARK = "# OpenAgent";
|
|
29
|
+
/** One value in a launchd property list. */
|
|
30
|
+
type PlistValue = string | boolean | PlistValue[] | {
|
|
31
|
+
[key: string]: PlistValue;
|
|
32
|
+
};
|
|
33
|
+
/** A launchd property list holding `dict`. */
|
|
34
|
+
export declare function plist(dict: {
|
|
35
|
+
[key: string]: PlistValue;
|
|
36
|
+
}): string;
|
|
37
|
+
/**
|
|
38
|
+
* The launch agent that runs the dashboard from login on, as the person, in their home folder.
|
|
39
|
+
* It runs with the variables of the install's terminal it needs (`env`): a launch agent's own
|
|
40
|
+
* `PATH` finds no `git`, `gh` or coding agent the person installed, and a moved config folder
|
|
41
|
+
* holds the registry and the certificate. Started again only when it fails: a dashboard that
|
|
42
|
+
* ends well (one ran on its port already, and it handed over) stays ended.
|
|
43
|
+
*/
|
|
44
|
+
export declare function dashboardPlist(opts: {
|
|
45
|
+
node: string;
|
|
46
|
+
dashboard: string;
|
|
47
|
+
home: string;
|
|
48
|
+
env: {
|
|
49
|
+
[name: string]: string;
|
|
50
|
+
};
|
|
51
|
+
log: string;
|
|
52
|
+
}): string;
|
|
53
|
+
/** The rule that sends the address's port 443 to the dashboard's secure port. */
|
|
54
|
+
export declare function portRule(port?: number): string;
|
|
55
|
+
/**
|
|
56
|
+
* The launch daemon that, at each start of the Mac, gives this computer the address's own
|
|
57
|
+
* address, loads the port rule and switches the packet filter on. A Mac has only `127.0.0.1` of
|
|
58
|
+
* its own until told more.
|
|
59
|
+
*/
|
|
60
|
+
export declare function portPlist(): string;
|
|
61
|
+
/** `value` as one word of a shell script, whatever it holds. */
|
|
62
|
+
export declare function quoted(value: string): string;
|
|
63
|
+
/** Shell lines that take the install's line out of the hosts file `file`, and leave the rest as it was. */
|
|
64
|
+
export declare function removeHostsLine(file: string): string;
|
|
65
|
+
/** Shell lines that point `name` at this computer in the hosts file `file`, once, however often they run. */
|
|
66
|
+
export declare function addHostsLine(file: string, name: string): string;
|
|
67
|
+
/** The install's one script as the administrator: the hosts line, and the port rule with its launch daemon, started now. */
|
|
68
|
+
export declare function adminInstallScript(name?: string): string;
|
|
69
|
+
/** The uninstall's one script as the administrator: everything {@link adminInstallScript} put there, taken off. */
|
|
70
|
+
export declare function adminUninstallScript(): string;
|
|
71
|
+
/** The certificate's openssl settings: for `name` alone, for a server, and no authority over any other. */
|
|
72
|
+
export declare function certificateConfig(name: string): string;
|
|
73
|
+
/** The longest a certificate may last for Safari and macOS: 825 days. */
|
|
74
|
+
export declare const CERTIFICATE_DAYS = 825;
|
|
75
|
+
export {};
|
|
76
|
+
//# sourceMappingURL=mac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mac.d.ts","sourceRoot":"","sources":["../src/mac.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH;;;GAGG;AACH,eAAO,MAAM,OAAO,oBAAoB,CAAA;AACxC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,eAAe,CAAA;AAE5C,8EAA8E;AAC9E,eAAO,MAAM,eAAe,8BAA8B,CAAA;AAC1D,mHAAmH;AACnH,eAAO,MAAM,UAAU,yBAAyB,CAAA;AAChD,eAAO,MAAM,UAAU,sDAA+C,CAAA;AACtE;;;GAGG;AACH,eAAO,MAAM,WAAW,wBAAwB,CAAA;AAChD,eAAO,MAAM,cAAc,oCAAoC,CAAA;AAE/D,6FAA6F;AAC7F,eAAO,MAAM,UAAU,gBAAgB,CAAA;AAEvC,4CAA4C;AAC5C,KAAK,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,CAAA;AAajF,8CAA8C;AAC9C,wBAAgB,KAAK,CAAC,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,GAAG,MAAM,CAOjE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAW5I;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,IAAI,GAAE,MAAoB,GAAG,MAAM,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAMlC;AAED,gEAAgE;AAChE,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,6GAA6G;AAC7G,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/D;AAKD,4HAA4H;AAC5H,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAgB,GAAG,MAAM,CAWjE;AAED,mHAAmH;AACnH,wBAAgB,oBAAoB,IAAI,MAAM,CAQ7C;AAED,2GAA2G;AAC3G,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYtD;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,MAAM,CAAA"}
|
package/dist/mac.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { SECURE_PORT } from '@openagt/dashboard/secure-address';
|
|
2
|
+
/**
|
|
3
|
+
* What the install puts on a Mac, as text: the files it writes and the one script it runs as the
|
|
4
|
+
* administrator. Pure, so a test reads each one; {@link install} and {@link uninstall} write and run them.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The dashboard's secure address: the website's own name, which this computer then answers
|
|
8
|
+
* itself, the dashboard with the website's copy beside it (#1919).
|
|
9
|
+
*/
|
|
10
|
+
export const ADDRESS = 'openagent.build';
|
|
11
|
+
/**
|
|
12
|
+
* The address the name points at: one of this computer's own, the address's alone. The port rule
|
|
13
|
+
* then touches nothing else this computer sends itself on port 443 (a container a developer
|
|
14
|
+
* publishes there, say), as a rule for `127.0.0.1` would.
|
|
15
|
+
*/
|
|
16
|
+
export const LOOPBACK_ADDRESS = '127.0.0.42';
|
|
17
|
+
/** What starts the dashboard at login: a launch agent of the person's own. */
|
|
18
|
+
export const DASHBOARD_LABEL = 'build.openagent.dashboard';
|
|
19
|
+
/** What sends the address's port 443 to the dashboard at every start of the Mac: a launch daemon, the system's. */
|
|
20
|
+
export const PORT_LABEL = 'build.openagent.port';
|
|
21
|
+
export const PORT_PLIST = `/Library/LaunchDaemons/${PORT_LABEL}.plist`;
|
|
22
|
+
/**
|
|
23
|
+
* The port rule's place: a part of Apple's own `com.apple` rules, which `/etc/pf.conf` reads
|
|
24
|
+
* whatever is in them, so the file itself is never changed.
|
|
25
|
+
*/
|
|
26
|
+
export const PORT_ANCHOR = 'com.apple/openagent';
|
|
27
|
+
export const PORT_RULE_FILE = '/etc/pf.anchors/build.openagent';
|
|
28
|
+
/** The end of the hosts line the install adds, which is how the uninstall finds it again. */
|
|
29
|
+
export const HOSTS_MARK = '# OpenAgent';
|
|
30
|
+
function escapeXml(text) {
|
|
31
|
+
return text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');
|
|
32
|
+
}
|
|
33
|
+
function plistValue(value, indent) {
|
|
34
|
+
if (typeof value === 'string')
|
|
35
|
+
return `${indent}<string>${escapeXml(value)}</string>`;
|
|
36
|
+
if (typeof value === 'boolean')
|
|
37
|
+
return `${indent}<${value}/>`;
|
|
38
|
+
if (Array.isArray(value))
|
|
39
|
+
return [`${indent}<array>`, ...value.map(item => plistValue(item, indent + ' ')), `${indent}</array>`].join('\n');
|
|
40
|
+
return [`${indent}<dict>`, ...Object.entries(value).flatMap(([key, item]) => [`${indent} <key>${escapeXml(key)}</key>`, plistValue(item, indent + ' ')]), `${indent}</dict>`].join('\n');
|
|
41
|
+
}
|
|
42
|
+
/** A launchd property list holding `dict`. */
|
|
43
|
+
export function plist(dict) {
|
|
44
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
45
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
46
|
+
<plist version="1.0">
|
|
47
|
+
${plistValue(dict, '')}
|
|
48
|
+
</plist>
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The launch agent that runs the dashboard from login on, as the person, in their home folder.
|
|
53
|
+
* It runs with the variables of the install's terminal it needs (`env`): a launch agent's own
|
|
54
|
+
* `PATH` finds no `git`, `gh` or coding agent the person installed, and a moved config folder
|
|
55
|
+
* holds the registry and the certificate. Started again only when it fails: a dashboard that
|
|
56
|
+
* ends well (one ran on its port already, and it handed over) stays ended.
|
|
57
|
+
*/
|
|
58
|
+
export function dashboardPlist(opts) {
|
|
59
|
+
return plist({
|
|
60
|
+
Label: DASHBOARD_LABEL,
|
|
61
|
+
ProgramArguments: [opts.node, opts.dashboard],
|
|
62
|
+
WorkingDirectory: opts.home,
|
|
63
|
+
EnvironmentVariables: opts.env,
|
|
64
|
+
RunAtLoad: true,
|
|
65
|
+
KeepAlive: { SuccessfulExit: false },
|
|
66
|
+
StandardOutPath: opts.log,
|
|
67
|
+
StandardErrorPath: opts.log,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** The rule that sends the address's port 443 to the dashboard's secure port. */
|
|
71
|
+
export function portRule(port = SECURE_PORT) {
|
|
72
|
+
return `rdr pass on lo0 inet proto tcp from any to ${LOOPBACK_ADDRESS} port 443 -> 127.0.0.1 port ${port}\n`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The launch daemon that, at each start of the Mac, gives this computer the address's own
|
|
76
|
+
* address, loads the port rule and switches the packet filter on. A Mac has only `127.0.0.1` of
|
|
77
|
+
* its own until told more.
|
|
78
|
+
*/
|
|
79
|
+
export function portPlist() {
|
|
80
|
+
return plist({
|
|
81
|
+
Label: PORT_LABEL,
|
|
82
|
+
ProgramArguments: ['/bin/sh', '-c', `/sbin/ifconfig lo0 alias ${LOOPBACK_ADDRESS} up && /sbin/pfctl -a ${PORT_ANCHOR} -f ${PORT_RULE_FILE} && /sbin/pfctl -E`],
|
|
83
|
+
RunAtLoad: true,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** `value` as one word of a shell script, whatever it holds. */
|
|
87
|
+
export function quoted(value) {
|
|
88
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
89
|
+
}
|
|
90
|
+
/** Shell lines that take the install's line out of the hosts file `file`, and leave the rest as it was. */
|
|
91
|
+
export function removeHostsLine(file) {
|
|
92
|
+
return `if grep -q ${quoted(` ${HOSTS_MARK}$`)} ${quoted(file)}; then sed -i '' ${quoted(`/ ${HOSTS_MARK}$/d`)} ${quoted(file)}; fi`;
|
|
93
|
+
}
|
|
94
|
+
/** Shell lines that point `name` at this computer in the hosts file `file`, once, however often they run. */
|
|
95
|
+
export function addHostsLine(file, name) {
|
|
96
|
+
return [
|
|
97
|
+
removeHostsLine(file),
|
|
98
|
+
// A file that does not end its last line would have this one joined to it.
|
|
99
|
+
`if [ -s ${quoted(file)} ] && [ -n "$(tail -c 1 ${quoted(file)})" ]; then echo >> ${quoted(file)}; fi`,
|
|
100
|
+
`printf '%s\\n' ${quoted(`${LOOPBACK_ADDRESS} ${name} ${HOSTS_MARK}`)} >> ${quoted(file)}`,
|
|
101
|
+
].join('\n');
|
|
102
|
+
}
|
|
103
|
+
/** Forget what the Mac remembers of names, so the hosts line counts at once. */
|
|
104
|
+
const FORGET_NAMES = 'dscacheutil -flushcache; killall -HUP mDNSResponder 2>/dev/null || true';
|
|
105
|
+
/** The install's one script as the administrator: the hosts line, and the port rule with its launch daemon, started now. */
|
|
106
|
+
export function adminInstallScript(name = ADDRESS) {
|
|
107
|
+
return `set -e
|
|
108
|
+
${addHostsLine('/etc/hosts', name)}
|
|
109
|
+
printf '%s' ${quoted(portRule())} > ${PORT_RULE_FILE}
|
|
110
|
+
printf '%s' ${quoted(portPlist())} > ${PORT_PLIST}
|
|
111
|
+
chown root:wheel ${PORT_RULE_FILE} ${PORT_PLIST}
|
|
112
|
+
chmod 644 ${PORT_RULE_FILE} ${PORT_PLIST}
|
|
113
|
+
launchctl bootout system/${PORT_LABEL} 2>/dev/null || true
|
|
114
|
+
launchctl bootstrap system ${PORT_PLIST}
|
|
115
|
+
${FORGET_NAMES}
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
/** The uninstall's one script as the administrator: everything {@link adminInstallScript} put there, taken off. */
|
|
119
|
+
export function adminUninstallScript() {
|
|
120
|
+
return `${removeHostsLine('/etc/hosts')}
|
|
121
|
+
launchctl bootout system/${PORT_LABEL} 2>/dev/null || true
|
|
122
|
+
/sbin/pfctl -a ${PORT_ANCHOR} -F all 2>/dev/null || true
|
|
123
|
+
/sbin/ifconfig lo0 -alias ${LOOPBACK_ADDRESS} 2>/dev/null || true
|
|
124
|
+
rm -f ${PORT_RULE_FILE} ${PORT_PLIST}
|
|
125
|
+
${FORGET_NAMES}
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
/** The certificate's openssl settings: for `name` alone, for a server, and no authority over any other. */
|
|
129
|
+
export function certificateConfig(name) {
|
|
130
|
+
return `[req]
|
|
131
|
+
distinguished_name = dn
|
|
132
|
+
prompt = no
|
|
133
|
+
[dn]
|
|
134
|
+
CN = ${name}
|
|
135
|
+
[ext]
|
|
136
|
+
subjectAltName = DNS:${name}
|
|
137
|
+
basicConstraints = critical, CA:FALSE
|
|
138
|
+
keyUsage = critical, digitalSignature, keyEncipherment
|
|
139
|
+
extendedKeyUsage = serverAuth
|
|
140
|
+
`;
|
|
141
|
+
}
|
|
142
|
+
/** The longest a certificate may last for Safari and macOS: 825 days. */
|
|
143
|
+
export const CERTIFICATE_DAYS = 825;
|
|
144
|
+
//# sourceMappingURL=mac.js.map
|
package/dist/mac.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mac.js","sourceRoot":"","sources":["../src/mac.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openagt/install",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Install OpenAgent on this computer: the dashboard starts when you log in, at https://openagent.build, which this computer then answers itself. `npx @openagt/uninstall` takes it all off again.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/openagt/openagent.git",
|
|
9
|
+
"directory": "packages/install"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=22.12.0"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"openagent-install": "dist/bin.js"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@openagt/dashboard": "0.55.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "^7.0.2"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc -p tsconfig.build.json",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "tsc -p tsconfig.test.json && node --test --test-timeout=60000 'dist-test/**/*.test.js'",
|
|
42
|
+
"clean": "rm -rf dist dist-test"
|
|
43
|
+
}
|
|
6
44
|
}
|
package/README.md
DELETED