@two7722/sentinel-guard 1.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/dist/__tests__/rules-engine.test.d.ts +1 -0
- package/dist/__tests__/rules-engine.test.js +69 -0
- package/dist/__tests__/rules-engine.test.js.map +1 -0
- package/dist/__tests__/transport-encryption.test.d.ts +1 -0
- package/dist/__tests__/transport-encryption.test.js +95 -0
- package/dist/__tests__/transport-encryption.test.js.map +1 -0
- package/dist/api/client.d.ts +27 -0
- package/dist/api/client.js +91 -0
- package/dist/api/client.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +12 -0
- package/dist/cli/bootstrap.js +132 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +534 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/crypto/keys.d.ts +40 -0
- package/dist/crypto/keys.js +125 -0
- package/dist/crypto/keys.js.map +1 -0
- package/dist/crypto/transport-encryption.d.ts +13 -0
- package/dist/crypto/transport-encryption.js +62 -0
- package/dist/crypto/transport-encryption.js.map +1 -0
- package/dist/install/setup.d.ts +2 -0
- package/dist/install/setup.js +80 -0
- package/dist/install/setup.js.map +1 -0
- package/dist/lib/budget.d.ts +14 -0
- package/dist/lib/budget.js +93 -0
- package/dist/lib/budget.js.map +1 -0
- package/dist/lib/claude-process.d.ts +16 -0
- package/dist/lib/claude-process.js +98 -0
- package/dist/lib/claude-process.js.map +1 -0
- package/dist/lib/daemon.d.ts +6 -0
- package/dist/lib/daemon.js +218 -0
- package/dist/lib/daemon.js.map +1 -0
- package/dist/lib/diff.d.ts +5 -0
- package/dist/lib/diff.js +85 -0
- package/dist/lib/diff.js.map +1 -0
- package/dist/lib/doctor.d.ts +1 -0
- package/dist/lib/doctor.js +108 -0
- package/dist/lib/doctor.js.map +1 -0
- package/dist/lib/history.d.ts +22 -0
- package/dist/lib/history.js +62 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/logger.d.ts +11 -0
- package/dist/lib/logger.js +62 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/modes.d.ts +22 -0
- package/dist/lib/modes.js +58 -0
- package/dist/lib/modes.js.map +1 -0
- package/dist/lib/overrides.d.ts +13 -0
- package/dist/lib/overrides.js +74 -0
- package/dist/lib/overrides.js.map +1 -0
- package/dist/lib/session.d.ts +32 -0
- package/dist/lib/session.js +68 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/summarizer.d.ts +5 -0
- package/dist/lib/summarizer.js +46 -0
- package/dist/lib/summarizer.js.map +1 -0
- package/dist/lib/tunnel.d.ts +2 -0
- package/dist/lib/tunnel.js +48 -0
- package/dist/lib/tunnel.js.map +1 -0
- package/dist/relay/pending.d.ts +27 -0
- package/dist/relay/pending.js +65 -0
- package/dist/relay/pending.js.map +1 -0
- package/dist/rules/engine.d.ts +31 -0
- package/dist/rules/engine.js +203 -0
- package/dist/rules/engine.js.map +1 -0
- package/dist/server/http.d.ts +8 -0
- package/dist/server/http.js +359 -0
- package/dist/server/http.js.map +1 -0
- package/dist/socket/client.d.ts +16 -0
- package/dist/socket/client.js +81 -0
- package/dist/socket/client.js.map +1 -0
- package/dist/transport/cloudkit.d.ts +30 -0
- package/dist/transport/cloudkit.js +162 -0
- package/dist/transport/cloudkit.js.map +1 -0
- package/dist/transport/factory.d.ts +6 -0
- package/dist/transport/factory.js +20 -0
- package/dist/transport/factory.js.map +1 -0
- package/dist/transport/interface.d.ts +25 -0
- package/dist/transport/interface.js +13 -0
- package/dist/transport/interface.js.map +1 -0
- package/dist/transport/local.d.ts +46 -0
- package/dist/transport/local.js +320 -0
- package/dist/transport/local.js.map +1 -0
- package/dist/transport/remote.d.ts +17 -0
- package/dist/transport/remote.js +83 -0
- package/dist/transport/remote.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
|
+
/**
|
|
9
|
+
* Unit tests for the rules engine glob matching and rule matching logic.
|
|
10
|
+
* Uses Node.js built-in test runner (no extra dependencies).
|
|
11
|
+
*
|
|
12
|
+
* Run: npx tsx --test src/__tests__/rules-engine.test.ts
|
|
13
|
+
*/
|
|
14
|
+
// Inline the globMatch function to test independently
|
|
15
|
+
function globMatch(pattern, value) {
|
|
16
|
+
const regex = pattern
|
|
17
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
18
|
+
.replace(/\*\*/g, '{{DOUBLESTAR}}')
|
|
19
|
+
.replace(/\*/g, '[^/]*')
|
|
20
|
+
.replace(/{{DOUBLESTAR}}/g, '.*');
|
|
21
|
+
return new RegExp(`^${regex}$`).test(value);
|
|
22
|
+
}
|
|
23
|
+
(0, node_test_1.describe)('globMatch', () => {
|
|
24
|
+
(0, node_test_1.test)('exact match', () => {
|
|
25
|
+
node_assert_1.default.strictEqual(globMatch('Bash', 'Bash'), true);
|
|
26
|
+
node_assert_1.default.strictEqual(globMatch('Bash', 'Write'), false);
|
|
27
|
+
});
|
|
28
|
+
(0, node_test_1.test)('single wildcard (*)', () => {
|
|
29
|
+
node_assert_1.default.strictEqual(globMatch('Edit*', 'Edit'), true);
|
|
30
|
+
node_assert_1.default.strictEqual(globMatch('Edit*', 'EditFile'), true);
|
|
31
|
+
node_assert_1.default.strictEqual(globMatch('*.ts', 'foo.ts'), true);
|
|
32
|
+
node_assert_1.default.strictEqual(globMatch('*.ts', 'foo/bar.ts'), false); // * doesn't cross /
|
|
33
|
+
});
|
|
34
|
+
(0, node_test_1.test)('double wildcard (**)', () => {
|
|
35
|
+
node_assert_1.default.strictEqual(globMatch('**/.env*', '/home/user/.env'), true);
|
|
36
|
+
node_assert_1.default.strictEqual(globMatch('**/.env*', '/home/user/.env.local'), true);
|
|
37
|
+
node_assert_1.default.strictEqual(globMatch('**/.env*', '.env'), true);
|
|
38
|
+
node_assert_1.default.strictEqual(globMatch('src/**/*.ts', 'src/foo/bar.ts'), true);
|
|
39
|
+
node_assert_1.default.strictEqual(globMatch('src/**/*.ts', 'src/a/b/c.ts'), true);
|
|
40
|
+
});
|
|
41
|
+
(0, node_test_1.test)('/tmp/** pattern', () => {
|
|
42
|
+
node_assert_1.default.strictEqual(globMatch('/tmp/**', '/tmp/foo.txt'), true);
|
|
43
|
+
node_assert_1.default.strictEqual(globMatch('/tmp/**', '/tmp/a/b/c'), true);
|
|
44
|
+
node_assert_1.default.strictEqual(globMatch('/tmp/**', '/home/tmp/foo'), false);
|
|
45
|
+
});
|
|
46
|
+
(0, node_test_1.test)('**/secrets/** pattern', () => {
|
|
47
|
+
node_assert_1.default.strictEqual(globMatch('**/secrets/**', '/app/secrets/key.pem'), true);
|
|
48
|
+
node_assert_1.default.strictEqual(globMatch('**/secrets/**', 'secrets/a'), true);
|
|
49
|
+
node_assert_1.default.strictEqual(globMatch('**/secrets/**', '/x/secrets/a/b'), true);
|
|
50
|
+
});
|
|
51
|
+
(0, node_test_1.test)('special regex characters in pattern', () => {
|
|
52
|
+
node_assert_1.default.strictEqual(globMatch('file.name.ts', 'file.name.ts'), true);
|
|
53
|
+
node_assert_1.default.strictEqual(globMatch('file.name.ts', 'filexnamexts'), false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
(0, node_test_1.describe)('rule priority sorting', () => {
|
|
57
|
+
(0, node_test_1.test)('lower priority number wins', () => {
|
|
58
|
+
const rules = [
|
|
59
|
+
{ id: 'a', priority: 20 },
|
|
60
|
+
{ id: 'b', priority: 1 },
|
|
61
|
+
{ id: 'c', priority: 10 },
|
|
62
|
+
];
|
|
63
|
+
const sorted = [...rules].sort((a, b) => a.priority - b.priority);
|
|
64
|
+
node_assert_1.default.strictEqual(sorted[0].id, 'b');
|
|
65
|
+
node_assert_1.default.strictEqual(sorted[1].id, 'c');
|
|
66
|
+
node_assert_1.default.strictEqual(sorted[2].id, 'a');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=rules-engine.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules-engine.test.js","sourceRoot":"","sources":["../../src/__tests__/rules-engine.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
|
+
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
9
|
+
const tweetnacl_util_1 = require("tweetnacl-util");
|
|
10
|
+
/**
|
|
11
|
+
* Unit tests for transport encryption (NaCl secretbox).
|
|
12
|
+
*
|
|
13
|
+
* Run: npx tsx --test src/__tests__/transport-encryption.test.ts
|
|
14
|
+
*/
|
|
15
|
+
// Inline encrypt/decrypt to avoid module init side effects
|
|
16
|
+
function encryptMessage(plaintext, key) {
|
|
17
|
+
const nonce = tweetnacl_1.default.randomBytes(24);
|
|
18
|
+
const msgBytes = new TextEncoder().encode(plaintext);
|
|
19
|
+
const encrypted = tweetnacl_1.default.secretbox(msgBytes, nonce, key);
|
|
20
|
+
const combined = new Uint8Array(24 + encrypted.length);
|
|
21
|
+
combined.set(nonce, 0);
|
|
22
|
+
combined.set(encrypted, 24);
|
|
23
|
+
return (0, tweetnacl_util_1.encodeBase64)(combined);
|
|
24
|
+
}
|
|
25
|
+
function decryptMessage(encoded, key) {
|
|
26
|
+
try {
|
|
27
|
+
const combined = (0, tweetnacl_util_1.decodeBase64)(encoded);
|
|
28
|
+
if (combined.length < 25)
|
|
29
|
+
return null;
|
|
30
|
+
const nonce = combined.slice(0, 24);
|
|
31
|
+
const ciphertext = combined.slice(24);
|
|
32
|
+
const decrypted = tweetnacl_1.default.secretbox.open(ciphertext, nonce, key);
|
|
33
|
+
if (!decrypted)
|
|
34
|
+
return null;
|
|
35
|
+
return new TextDecoder().decode(decrypted);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
(0, node_test_1.describe)('transport encryption', () => {
|
|
42
|
+
const key = tweetnacl_1.default.randomBytes(32);
|
|
43
|
+
(0, node_test_1.test)('encrypt then decrypt roundtrip', () => {
|
|
44
|
+
const message = '{"event":"approval_request","data":{"id":"abc123"}}';
|
|
45
|
+
const encrypted = encryptMessage(message, key);
|
|
46
|
+
const decrypted = decryptMessage(encrypted, key);
|
|
47
|
+
node_assert_1.default.strictEqual(decrypted, message);
|
|
48
|
+
});
|
|
49
|
+
(0, node_test_1.test)('decrypt with wrong key fails', () => {
|
|
50
|
+
const wrongKey = tweetnacl_1.default.randomBytes(32);
|
|
51
|
+
const encrypted = encryptMessage('secret data', key);
|
|
52
|
+
const result = decryptMessage(encrypted, wrongKey);
|
|
53
|
+
node_assert_1.default.strictEqual(result, null);
|
|
54
|
+
});
|
|
55
|
+
(0, node_test_1.test)('decrypt garbage returns null', () => {
|
|
56
|
+
node_assert_1.default.strictEqual(decryptMessage('not-valid-base64!!!', key), null);
|
|
57
|
+
node_assert_1.default.strictEqual(decryptMessage((0, tweetnacl_util_1.encodeBase64)(new Uint8Array(10)), key), null);
|
|
58
|
+
});
|
|
59
|
+
(0, node_test_1.test)('handles empty message', () => {
|
|
60
|
+
const encrypted = encryptMessage('', key);
|
|
61
|
+
const decrypted = decryptMessage(encrypted, key);
|
|
62
|
+
node_assert_1.default.strictEqual(decrypted, '');
|
|
63
|
+
});
|
|
64
|
+
(0, node_test_1.test)('handles unicode', () => {
|
|
65
|
+
const msg = '审批请求:工具 Write → /tmp/文件.txt';
|
|
66
|
+
const encrypted = encryptMessage(msg, key);
|
|
67
|
+
const decrypted = decryptMessage(encrypted, key);
|
|
68
|
+
node_assert_1.default.strictEqual(decrypted, msg);
|
|
69
|
+
});
|
|
70
|
+
(0, node_test_1.test)('encrypted output is base64', () => {
|
|
71
|
+
const encrypted = encryptMessage('test', key);
|
|
72
|
+
// Should be valid base64
|
|
73
|
+
node_assert_1.default.doesNotThrow(() => (0, tweetnacl_util_1.decodeBase64)(encrypted));
|
|
74
|
+
// Should not be plain text
|
|
75
|
+
node_assert_1.default.notStrictEqual(encrypted, 'test');
|
|
76
|
+
});
|
|
77
|
+
(0, node_test_1.test)('nonce is unique per encryption', () => {
|
|
78
|
+
const e1 = encryptMessage('same', key);
|
|
79
|
+
const e2 = encryptMessage('same', key);
|
|
80
|
+
// Same plaintext, different nonces → different ciphertext
|
|
81
|
+
node_assert_1.default.notStrictEqual(e1, e2);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
(0, node_test_1.describe)('pending request store', () => {
|
|
85
|
+
(0, node_test_1.test)('resolve resolves the promise', async () => {
|
|
86
|
+
// Simple simulation of the pending store behavior
|
|
87
|
+
let resolvedAction = null;
|
|
88
|
+
const promise = new Promise((resolve) => {
|
|
89
|
+
setTimeout(() => resolve('allowed'), 10);
|
|
90
|
+
});
|
|
91
|
+
resolvedAction = await promise;
|
|
92
|
+
node_assert_1.default.strictEqual(resolvedAction, 'allowed');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=transport-encryption.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport-encryption.test.js","sourceRoot":"","sources":["../../src/__tests__/transport-encryption.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
interface TokenFile {
|
|
2
|
+
serverURL: string;
|
|
3
|
+
token: string;
|
|
4
|
+
deviceId: string;
|
|
5
|
+
expiresAt: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* POST /v1/auth — 用 Ed25519 challenge-response 换 JWT
|
|
9
|
+
*/
|
|
10
|
+
export declare function authGetToken(serverURL: string): Promise<TokenFile>;
|
|
11
|
+
/**
|
|
12
|
+
* 读取已保存的 JWT — 如果过期或不存在返回 null
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadToken(): TokenFile | null;
|
|
15
|
+
/**
|
|
16
|
+
* 确保有有效 token — 没有则走 auth 流程
|
|
17
|
+
*/
|
|
18
|
+
export declare function ensureToken(serverURL: string): Promise<TokenFile>;
|
|
19
|
+
/**
|
|
20
|
+
* 获取已存 serverURL(如果有)
|
|
21
|
+
*/
|
|
22
|
+
export declare function getStoredServerURL(): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* 清除 token
|
|
25
|
+
*/
|
|
26
|
+
export declare function clearToken(): void;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authGetToken = authGetToken;
|
|
4
|
+
exports.loadToken = loadToken;
|
|
5
|
+
exports.ensureToken = ensureToken;
|
|
6
|
+
exports.getStoredServerURL = getStoredServerURL;
|
|
7
|
+
exports.clearToken = clearToken;
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const keys_1 = require("../crypto/keys");
|
|
11
|
+
const logger_1 = require("../lib/logger");
|
|
12
|
+
const TOKEN_PATH = (0, path_1.join)((0, keys_1.getSentinelDir)(), 'token.json');
|
|
13
|
+
// ==================== Auth ====================
|
|
14
|
+
/**
|
|
15
|
+
* POST /v1/auth — 用 Ed25519 challenge-response 换 JWT
|
|
16
|
+
*/
|
|
17
|
+
async function authGetToken(serverURL) {
|
|
18
|
+
const challenge = (0, keys_1.authChallenge)();
|
|
19
|
+
const url = `${serverURL.replace(/\/$/, '')}/v1/auth`;
|
|
20
|
+
const res = await fetch(url, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: { 'Content-Type': 'application/json' },
|
|
23
|
+
body: JSON.stringify({
|
|
24
|
+
...challenge,
|
|
25
|
+
deviceName: `${process.env.USER ?? 'unknown'}@${require('os').hostname()}`,
|
|
26
|
+
deviceType: 'mac',
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
const body = await res.text();
|
|
31
|
+
throw new Error(`Auth failed (${res.status}): ${body}`);
|
|
32
|
+
}
|
|
33
|
+
const json = (await res.json());
|
|
34
|
+
if (!json.success) {
|
|
35
|
+
throw new Error('Auth response: success=false');
|
|
36
|
+
}
|
|
37
|
+
const tokenFile = {
|
|
38
|
+
serverURL: serverURL.replace(/\/$/, ''),
|
|
39
|
+
token: json.data.token,
|
|
40
|
+
deviceId: json.data.deviceId,
|
|
41
|
+
expiresAt: new Date(Date.now() + json.data.expiresIn * 1000).toISOString(),
|
|
42
|
+
};
|
|
43
|
+
(0, fs_1.writeFileSync)(TOKEN_PATH, JSON.stringify(tokenFile, null, 2), { mode: 0o600 });
|
|
44
|
+
logger_1.log.info(`Authenticated. Device ID: ${tokenFile.deviceId}`);
|
|
45
|
+
return tokenFile;
|
|
46
|
+
}
|
|
47
|
+
// ==================== Token Storage ====================
|
|
48
|
+
/**
|
|
49
|
+
* 读取已保存的 JWT — 如果过期或不存在返回 null
|
|
50
|
+
*/
|
|
51
|
+
function loadToken() {
|
|
52
|
+
if (!(0, fs_1.existsSync)(TOKEN_PATH))
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
const raw = JSON.parse((0, fs_1.readFileSync)(TOKEN_PATH, 'utf-8'));
|
|
56
|
+
if (new Date(raw.expiresAt) < new Date()) {
|
|
57
|
+
logger_1.log.warn('Token expired, re-auth needed');
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return raw;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 确保有有效 token — 没有则走 auth 流程
|
|
68
|
+
*/
|
|
69
|
+
async function ensureToken(serverURL) {
|
|
70
|
+
const existing = loadToken();
|
|
71
|
+
if (existing && existing.serverURL === serverURL.replace(/\/$/, '')) {
|
|
72
|
+
return existing;
|
|
73
|
+
}
|
|
74
|
+
return authGetToken(serverURL);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 获取已存 serverURL(如果有)
|
|
78
|
+
*/
|
|
79
|
+
function getStoredServerURL() {
|
|
80
|
+
return loadToken()?.serverURL ?? null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 清除 token
|
|
84
|
+
*/
|
|
85
|
+
function clearToken() {
|
|
86
|
+
const { unlinkSync } = require('fs');
|
|
87
|
+
if ((0, fs_1.existsSync)(TOKEN_PATH)) {
|
|
88
|
+
unlinkSync(TOKEN_PATH);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type TransportMode } from '../transport/interface';
|
|
2
|
+
export interface BootstrapOpts {
|
|
3
|
+
mode: TransportMode;
|
|
4
|
+
port: number;
|
|
5
|
+
server?: string;
|
|
6
|
+
remote?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Start transport + HTTP hook server. Used by both `sentinel start` and `sentinel run`.
|
|
10
|
+
* Returns a shutdown callback.
|
|
11
|
+
*/
|
|
12
|
+
export declare function bootstrapSentinel(opts: BootstrapOpts): Promise<() => void>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.bootstrapSentinel = bootstrapSentinel;
|
|
37
|
+
// packages/sentinel-cli/src/cli/bootstrap.ts
|
|
38
|
+
const factory_1 = require("../transport/factory");
|
|
39
|
+
const local_1 = require("../transport/local");
|
|
40
|
+
const interface_1 = require("../transport/interface");
|
|
41
|
+
const http_1 = require("../server/http");
|
|
42
|
+
const engine_1 = require("../rules/engine");
|
|
43
|
+
const pending_1 = require("../relay/pending");
|
|
44
|
+
const logger_1 = require("../lib/logger");
|
|
45
|
+
const child_process_1 = require("child_process");
|
|
46
|
+
/** Kill any stale process holding the given port (best-effort, silent). */
|
|
47
|
+
function freePort(port) {
|
|
48
|
+
try {
|
|
49
|
+
(0, child_process_1.execSync)(`lsof -ti :${port} | xargs kill -9`, { stdio: 'ignore' });
|
|
50
|
+
}
|
|
51
|
+
catch { }
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Start transport + HTTP hook server. Used by both `sentinel start` and `sentinel run`.
|
|
55
|
+
* Returns a shutdown callback.
|
|
56
|
+
*/
|
|
57
|
+
async function bootstrapSentinel(opts) {
|
|
58
|
+
const { mode, port, remote } = opts;
|
|
59
|
+
// Free stale processes on both ports before binding
|
|
60
|
+
freePort(port); // hook server port (7749)
|
|
61
|
+
freePort(7750); // TCP transport port
|
|
62
|
+
if (mode === 'server') {
|
|
63
|
+
const { ensureToken, getStoredServerURL } = await Promise.resolve().then(() => __importStar(require('../api/client')));
|
|
64
|
+
const serverURL = opts.server ?? getStoredServerURL();
|
|
65
|
+
if (!serverURL) {
|
|
66
|
+
logger_1.log.error('Server mode requires -s URL.');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
logger_1.log.info('Authenticating...');
|
|
70
|
+
const tokenData = await ensureToken(serverURL);
|
|
71
|
+
const transport = (0, factory_1.createTransport)('server', { serverUrl: serverURL, token: tokenData.token });
|
|
72
|
+
(0, interface_1.setTransport)(transport);
|
|
73
|
+
logger_1.log.info(`Connecting to ${serverURL}...`);
|
|
74
|
+
await transport.start();
|
|
75
|
+
}
|
|
76
|
+
else if (mode === 'cloudkit') {
|
|
77
|
+
const transport = (0, factory_1.createTransport)('cloudkit');
|
|
78
|
+
(0, interface_1.setTransport)(transport);
|
|
79
|
+
await transport.start();
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// local
|
|
83
|
+
const transport = (0, factory_1.createTransport)('local');
|
|
84
|
+
(0, interface_1.setTransport)(transport);
|
|
85
|
+
await transport.start();
|
|
86
|
+
if (transport instanceof local_1.LocalTransport) {
|
|
87
|
+
const info = transport.getConnectionInfo();
|
|
88
|
+
logger_1.log.info(`iOS can connect to: ${info.ip}:${info.port}`);
|
|
89
|
+
try {
|
|
90
|
+
const qrcode = require('qrcode-terminal');
|
|
91
|
+
const qrData = `sentinel://${info.ip}:${info.port}`;
|
|
92
|
+
console.log('');
|
|
93
|
+
logger_1.log.info('Scan QR code with Sentinel iOS app:');
|
|
94
|
+
qrcode.generate(qrData, { small: true }, (code) => { console.log(code); });
|
|
95
|
+
}
|
|
96
|
+
catch { }
|
|
97
|
+
transport.onRulesUpdate((rules) => (0, engine_1.setCustomRules)(rules));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
(0, engine_1.watchRules)();
|
|
101
|
+
await (0, http_1.startHttpServer)(port);
|
|
102
|
+
(0, http_1.setupUserMessageHandler)();
|
|
103
|
+
const cleanupFns = [];
|
|
104
|
+
if (remote) {
|
|
105
|
+
try {
|
|
106
|
+
const { startTunnel, stopTunnel } = require('../lib/tunnel');
|
|
107
|
+
logger_1.log.info('Starting Cloudflare Tunnel...');
|
|
108
|
+
const tunnelUrl = await startTunnel(7750);
|
|
109
|
+
const remoteAddr = tunnelUrl.replace(/https?:\/\//, '');
|
|
110
|
+
logger_1.log.success(`Remote: ${tunnelUrl}`);
|
|
111
|
+
try {
|
|
112
|
+
const qrcode = require('qrcode-terminal');
|
|
113
|
+
const qrData = `sentinel-remote://${remoteAddr}`;
|
|
114
|
+
console.log('');
|
|
115
|
+
logger_1.log.info('Scan QR code for remote access:');
|
|
116
|
+
qrcode.generate(qrData, { small: true }, (code) => { console.log(code); });
|
|
117
|
+
}
|
|
118
|
+
catch { }
|
|
119
|
+
cleanupFns.push(stopTunnel);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
logger_1.log.error(`Tunnel failed: ${err.message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return () => {
|
|
126
|
+
for (const fn of cleanupFns)
|
|
127
|
+
fn();
|
|
128
|
+
pending_1.pending.clear();
|
|
129
|
+
(0, interface_1.getTransport)()?.stop();
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"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"}
|