@hellolynk-ai/codex-plugin 0.2.102 → 0.2.103-macos.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 +17 -17
- package/bin/hellolynk-client-setup.mjs +70 -10
- package/hellolynk-client-pack-manifest.json +101 -61
- package/hellolynk-client-pack-pin.json +1 -1
- package/package.json +8 -4
- package/plugins/hellolynk-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/hellolynk-codex/.mcp.json +20 -19
- package/plugins/hellolynk-codex/package.json +1 -1
- package/plugins/hellolynk-codex/runtime/bootstrap/core/hellolynk-client-account.mjs +1 -1
- package/plugins/hellolynk-codex/runtime/bootstrap/core/hellolynk-darwin-host.mjs +269 -0
- package/plugins/hellolynk-codex/runtime/bootstrap/core/hellolynk-darwin-vault.mjs +153 -0
- package/plugins/hellolynk-codex/runtime/bootstrap/core/hellolynk-host-protected-store.mjs +20 -8
- package/plugins/hellolynk-codex/runtime/bootstrap/core/hellolynk-neutral-host-installation-store.mjs +1 -1
- package/plugins/hellolynk-codex/runtime/bootstrap/core/hellolynk-platform-credential-store.mjs +68 -14
- package/plugins/hellolynk-codex/runtime/bootstrap/platform/darwin/hellolynk-keychain-helper.bin +0 -0
- package/plugins/hellolynk-codex/runtime/bootstrap/platform/darwin/hellolynk-keychain-helper.swift +149 -0
- package/plugins/hellolynk-codex/runtime/connect-activate.mjs +5 -1
- package/plugins/hellolynk-codex/runtime/core/hellolynk-client-account.mjs +1 -1
- package/plugins/hellolynk-codex/runtime/core/hellolynk-client-update-entry.mjs +7 -3
- package/plugins/hellolynk-codex/runtime/core/hellolynk-client-update-runtime.mjs +62 -33
- package/plugins/hellolynk-codex/runtime/core/hellolynk-client-update.mjs +62 -18
- package/plugins/hellolynk-codex/runtime/core/hellolynk-darwin-host.mjs +269 -0
- package/plugins/hellolynk-codex/runtime/core/hellolynk-darwin-vault.mjs +153 -0
- package/plugins/hellolynk-codex/runtime/core/hellolynk-host-protected-store.mjs +20 -8
- package/plugins/hellolynk-codex/runtime/core/hellolynk-human-confirmation-ledger.mjs +53 -6
- package/plugins/hellolynk-codex/runtime/core/hellolynk-local-data-protection.mjs +22 -7
- package/plugins/hellolynk-codex/runtime/core/hellolynk-native-human-confirmation-broker.mjs +7 -5
- package/plugins/hellolynk-codex/runtime/core/hellolynk-neutral-host-installation-store.mjs +1 -1
- package/plugins/hellolynk-codex/runtime/core/hellolynk-neutral-host-launcher.mjs +9 -3
- package/plugins/hellolynk-codex/runtime/core/hellolynk-neutral-host-process.mjs +1 -1
- package/plugins/hellolynk-codex/runtime/core/hellolynk-platform-credential-store.mjs +68 -14
- package/plugins/hellolynk-codex/runtime/core/hellolynk-release-retention.mjs +101 -2
- package/plugins/hellolynk-codex/runtime/core/hellolynk-workbench-connection.mjs +5 -3
- package/plugins/hellolynk-codex/runtime/neutral-host-release-entry.mjs +1 -1
- package/plugins/hellolynk-codex/runtime/neutral-host-release-loader.mjs +1 -1
- package/plugins/hellolynk-codex/runtime/neutral-host-release-manifest.json +56 -24
- package/plugins/hellolynk-codex/runtime/neutral-host-release-pin.json +1 -1
- package/plugins/hellolynk-codex/runtime/platform/darwin/hellolynk-keychain-helper.bin +0 -0
- package/plugins/hellolynk-codex/runtime/platform/darwin/hellolynk-keychain-helper.swift +149 -0
- package/plugins/hellolynk-codex/runtime/platform/windows/credential-store.ps1 +46 -10
- package/plugins/hellolynk-codex/server/codex-neutral-production.mjs +14 -8
- package/tools/hellolynk-activate-neutral-host-clients.mjs +5 -1
|
@@ -6,7 +6,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
6
6
|
const ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
const PIN_PATH = path.join(ROOT, "neutral-host-release-pin.json");
|
|
8
8
|
const MANIFEST_PATH = path.join(ROOT, "neutral-host-release-manifest.json");
|
|
9
|
-
const SAFE_RUNTIME_RELATIVE = /^(?:[A-Za-z0-9][A-Za-z0-9._-]*\/)*[A-Za-z0-9][A-Za-z0-9._-]*\.(?:cjs|mjs|ps1)$/;
|
|
9
|
+
const SAFE_RUNTIME_RELATIVE = /^(?:[A-Za-z0-9][A-Za-z0-9._-]*\/)*[A-Za-z0-9][A-Za-z0-9._-]*\.(?:cjs|mjs|ps1|swift|bin)$/;
|
|
10
10
|
const SAFE_RELEASE_RELATIVE = /^release\/(?:[A-Za-z0-9][A-Za-z0-9._-]*\/)*[A-Za-z0-9][A-Za-z0-9._-]*\.(?:mjs|ps1|md|html|js|css|json)$/;
|
|
11
11
|
|
|
12
12
|
export async function inspectNeutralHostRelease() {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"files": [
|
|
5
5
|
{
|
|
6
6
|
"path": "release/package.json",
|
|
7
|
-
"sha256": "
|
|
7
|
+
"sha256": "f786baab2e9f35836813c6b77e1cbc0fb8c0a3c0a2055b2e6ea777f2428cd232"
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
"path": "neutral-host-bootstrap.mjs",
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"path": "connect-activate.mjs",
|
|
15
|
-
"sha256": "
|
|
15
|
+
"sha256": "93c68c23ed2d18e87766ecd8dae6c3d8e757eca6ad7569477c8ec994402a8b0e"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"path": "neutral-host-release-loader.mjs",
|
|
19
|
-
"sha256": "
|
|
19
|
+
"sha256": "283a20c6a9b90481bc03c143ab51d5289abf7b7a86fbe51fba7ea2ae1e6d2c60"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"path": "neutral-host-release-entry.mjs",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "698d7e80d38353d56c7f1c337fbc676e8649d08afc726ffcb31215dc11fc8455"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"path": "core/hellolynk-agent-configurator.mjs",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"path": "core/hellolynk-client-account.mjs",
|
|
31
|
-
"sha256": "
|
|
31
|
+
"sha256": "6e03a05127d4dc86be6391567b51a956d1a987acf4e23f5699ce0e00c3187b7e"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"path": "core/hellolynk-client-core.mjs",
|
|
@@ -40,19 +40,19 @@
|
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"path": "core/hellolynk-client-update-entry.mjs",
|
|
43
|
-
"sha256": "
|
|
43
|
+
"sha256": "d9548eacda8632976e42aafc65f0cef2ec9c5233d2d53b31b02aec0a1702b5eb"
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"path": "core/hellolynk-client-update-runtime.mjs",
|
|
47
|
-
"sha256": "
|
|
47
|
+
"sha256": "aa233e2cdbdfadb7da6aa489591bc12c4121101b94696f93f6e6cb5d3e7c7870"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"path": "core/hellolynk-client-update.mjs",
|
|
51
|
-
"sha256": "
|
|
51
|
+
"sha256": "e57f7cc5e98519a014cef7cef68a97bb7e2beb33eb381c38d1751a3967904aaa"
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"path": "core/hellolynk-release-retention.mjs",
|
|
55
|
-
"sha256": "
|
|
55
|
+
"sha256": "0ee150af5a9bcc1f636e3ff980ee90ce7d073ab5ed4a991920cd3472bc65529c"
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"path": "core/hellolynk-contact-request-e2ee.mjs",
|
|
@@ -62,6 +62,14 @@
|
|
|
62
62
|
"path": "core/hellolynk-device-enrollment.mjs",
|
|
63
63
|
"sha256": "f3e99ff2bdfa76e5a830a518792a1b9e5e705d7a8a01eca725dd7c5c8391d4ef"
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
"path": "core/hellolynk-darwin-host.mjs",
|
|
67
|
+
"sha256": "ded97c3bc3dd65ca75305f5199a1340dffb987a5f283454d60586df8b6b55c09"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"path": "core/hellolynk-darwin-vault.mjs",
|
|
71
|
+
"sha256": "b6094d856af016e674e4a0183a4e474397bbe92e66638743fa62fe085b554d30"
|
|
72
|
+
},
|
|
65
73
|
{
|
|
66
74
|
"path": "core/hellolynk-direct-text-e2ee-client.mjs",
|
|
67
75
|
"sha256": "4007bf5e6c91df00adf10384cc1f0d0d28491b8ded518365dddbac717f3ac5be"
|
|
@@ -76,7 +84,7 @@
|
|
|
76
84
|
},
|
|
77
85
|
{
|
|
78
86
|
"path": "core/hellolynk-host-protected-store.mjs",
|
|
79
|
-
"sha256": "
|
|
87
|
+
"sha256": "10f81f4f6a5dd2fe9a742e847b2eb47dbf20f802f4414f46a05ccbc3505148e2"
|
|
80
88
|
},
|
|
81
89
|
{
|
|
82
90
|
"path": "core/hellolynk-host-transport-client.mjs",
|
|
@@ -108,7 +116,7 @@
|
|
|
108
116
|
},
|
|
109
117
|
{
|
|
110
118
|
"path": "core/hellolynk-human-confirmation-ledger.mjs",
|
|
111
|
-
"sha256": "
|
|
119
|
+
"sha256": "43b6b6baea422eb226c850f15966c907d834bc2f5aadbab6ee0c9e05445f182f"
|
|
112
120
|
},
|
|
113
121
|
{
|
|
114
122
|
"path": "core/hellolynk-human-relationship-controller.mjs",
|
|
@@ -140,7 +148,7 @@
|
|
|
140
148
|
},
|
|
141
149
|
{
|
|
142
150
|
"path": "core/hellolynk-local-data-protection.mjs",
|
|
143
|
-
"sha256": "
|
|
151
|
+
"sha256": "cea4f73ec5a31918c48bd8234e28d38ff1bb8028d2591f542b15ee12b2238e1f"
|
|
144
152
|
},
|
|
145
153
|
{
|
|
146
154
|
"path": "core/hellolynk-local-identity-trust.mjs",
|
|
@@ -172,7 +180,7 @@
|
|
|
172
180
|
},
|
|
173
181
|
{
|
|
174
182
|
"path": "core/hellolynk-native-human-confirmation-broker.mjs",
|
|
175
|
-
"sha256": "
|
|
183
|
+
"sha256": "f190c28af2703b58a685a57213b2789df7eda35d7699d718f9420cd1dddd1b65"
|
|
176
184
|
},
|
|
177
185
|
{
|
|
178
186
|
"path": "core/hellolynk-neutral-host-assembly.mjs",
|
|
@@ -180,15 +188,15 @@
|
|
|
180
188
|
},
|
|
181
189
|
{
|
|
182
190
|
"path": "core/hellolynk-neutral-host-installation-store.mjs",
|
|
183
|
-
"sha256": "
|
|
191
|
+
"sha256": "42ae1e7deb876a8308b7bfed6a7b891d1834117b62504fc5befe3f91a0b4c740"
|
|
184
192
|
},
|
|
185
193
|
{
|
|
186
194
|
"path": "core/hellolynk-neutral-host-launcher.mjs",
|
|
187
|
-
"sha256": "
|
|
195
|
+
"sha256": "d94b853a7ed1ebc9c7e9bd7c37e2405e39849fb6d4ddf3d697e17ba169eda6d2"
|
|
188
196
|
},
|
|
189
197
|
{
|
|
190
198
|
"path": "core/hellolynk-neutral-host-process.mjs",
|
|
191
|
-
"sha256": "
|
|
199
|
+
"sha256": "7b237a1400c604da5decbb29ab3ce556fd1b744d0cfd7d28b5560b217da120b1"
|
|
192
200
|
},
|
|
193
201
|
{
|
|
194
202
|
"path": "core/hellolynk-neutral-host-store-adapters.mjs",
|
|
@@ -200,7 +208,7 @@
|
|
|
200
208
|
},
|
|
201
209
|
{
|
|
202
210
|
"path": "core/hellolynk-platform-credential-store.mjs",
|
|
203
|
-
"sha256": "
|
|
211
|
+
"sha256": "3969708bafefc3b267bb34a9dcc115804c874ad14f4a036426d727c02ff70d42"
|
|
204
212
|
},
|
|
205
213
|
{
|
|
206
214
|
"path": "core/hellolynk-relay-client-cli.mjs",
|
|
@@ -216,7 +224,7 @@
|
|
|
216
224
|
},
|
|
217
225
|
{
|
|
218
226
|
"path": "core/hellolynk-workbench-connection.mjs",
|
|
219
|
-
"sha256": "
|
|
227
|
+
"sha256": "6ce8e75025d31ed81c39150df2766231fc871ef18c234de986dc910bab79d639"
|
|
220
228
|
},
|
|
221
229
|
{
|
|
222
230
|
"path": "workbench/candidate-bootstrap.mjs",
|
|
@@ -284,7 +292,7 @@
|
|
|
284
292
|
},
|
|
285
293
|
{
|
|
286
294
|
"path": "platform/windows/credential-store.ps1",
|
|
287
|
-
"sha256": "
|
|
295
|
+
"sha256": "8f288c91a1f6ecaf2651baab9bdfc55014c11ea9e165f203ca7a69f4d47d7917"
|
|
288
296
|
},
|
|
289
297
|
{
|
|
290
298
|
"path": "platform/windows/hellolynk-host-protected-store.ps1",
|
|
@@ -302,9 +310,17 @@
|
|
|
302
310
|
"path": "platform/windows/hellolynk-native-human-confirmation-broker.ps1",
|
|
303
311
|
"sha256": "757a731a3e8761d5d473db19ecfc330783f2826663a0057c4d6896e679d7a388"
|
|
304
312
|
},
|
|
313
|
+
{
|
|
314
|
+
"path": "bootstrap/core/hellolynk-darwin-host.mjs",
|
|
315
|
+
"sha256": "ded97c3bc3dd65ca75305f5199a1340dffb987a5f283454d60586df8b6b55c09"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"path": "bootstrap/core/hellolynk-darwin-vault.mjs",
|
|
319
|
+
"sha256": "b6094d856af016e674e4a0183a4e474397bbe92e66638743fa62fe085b554d30"
|
|
320
|
+
},
|
|
305
321
|
{
|
|
306
322
|
"path": "bootstrap/core/hellolynk-client-account.mjs",
|
|
307
|
-
"sha256": "
|
|
323
|
+
"sha256": "6e03a05127d4dc86be6391567b51a956d1a987acf4e23f5699ce0e00c3187b7e"
|
|
308
324
|
},
|
|
309
325
|
{
|
|
310
326
|
"path": "bootstrap/core/hellolynk-client-core.mjs",
|
|
@@ -320,7 +336,7 @@
|
|
|
320
336
|
},
|
|
321
337
|
{
|
|
322
338
|
"path": "bootstrap/core/hellolynk-host-protected-store.mjs",
|
|
323
|
-
"sha256": "
|
|
339
|
+
"sha256": "10f81f4f6a5dd2fe9a742e847b2eb47dbf20f802f4414f46a05ccbc3505148e2"
|
|
324
340
|
},
|
|
325
341
|
{
|
|
326
342
|
"path": "bootstrap/core/hellolynk-local-process-lock.mjs",
|
|
@@ -328,11 +344,11 @@
|
|
|
328
344
|
},
|
|
329
345
|
{
|
|
330
346
|
"path": "bootstrap/core/hellolynk-neutral-host-installation-store.mjs",
|
|
331
|
-
"sha256": "
|
|
347
|
+
"sha256": "42ae1e7deb876a8308b7bfed6a7b891d1834117b62504fc5befe3f91a0b4c740"
|
|
332
348
|
},
|
|
333
349
|
{
|
|
334
350
|
"path": "bootstrap/core/hellolynk-platform-credential-store.mjs",
|
|
335
|
-
"sha256": "
|
|
351
|
+
"sha256": "3969708bafefc3b267bb34a9dcc115804c874ad14f4a036426d727c02ff70d42"
|
|
336
352
|
},
|
|
337
353
|
{
|
|
338
354
|
"path": "bootstrap/core/hellolynk-runtime-safety.cjs",
|
|
@@ -342,9 +358,25 @@
|
|
|
342
358
|
"path": "bootstrap/platform/windows/hellolynk-host-protected-store.ps1",
|
|
343
359
|
"sha256": "24357e8ce54090b4ec68e457f02c9e834a80f3273ef3c03a8c0fa7258797fb49"
|
|
344
360
|
},
|
|
361
|
+
{
|
|
362
|
+
"path": "platform/darwin/hellolynk-keychain-helper.swift",
|
|
363
|
+
"sha256": "5d933589a1d739217bc164f73ab9afadc9e27cc512e1c00c0be4b38975fb6d5b"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"path": "platform/darwin/hellolynk-keychain-helper.bin",
|
|
367
|
+
"sha256": "f1a782c08229ebc0e8d1704b6390e91c5695e084b4df0a1a6dc043f6b23700ab"
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"path": "bootstrap/platform/darwin/hellolynk-keychain-helper.swift",
|
|
371
|
+
"sha256": "5d933589a1d739217bc164f73ab9afadc9e27cc512e1c00c0be4b38975fb6d5b"
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"path": "bootstrap/platform/darwin/hellolynk-keychain-helper.bin",
|
|
375
|
+
"sha256": "f1a782c08229ebc0e8d1704b6390e91c5695e084b4df0a1a6dc043f6b23700ab"
|
|
376
|
+
},
|
|
345
377
|
{
|
|
346
378
|
"path": "release/server/codex-neutral-production.mjs",
|
|
347
|
-
"sha256": "
|
|
379
|
+
"sha256": "2c2f209339385cc14f27fe985f4deb75f4bd48e689035311847cc3b08e36ac52"
|
|
348
380
|
},
|
|
349
381
|
{
|
|
350
382
|
"path": "release/server/neutral-host-adapter.mjs",
|
|
Binary file
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Rebuild in this directory: xcrun swiftc -O -target arm64-apple-macos13.0 -module-name HelloLynkKeychain hellolynk-keychain-helper.swift -o hellolynk-keychain-helper.bin
|
|
2
|
+
import AppKit
|
|
3
|
+
import CryptoKit
|
|
4
|
+
import Foundation
|
|
5
|
+
import Security
|
|
6
|
+
|
|
7
|
+
func fail(_ code: String) -> Never {
|
|
8
|
+
FileHandle.standardError.write(Data((code + "\n").utf8))
|
|
9
|
+
exit(1)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
func requireNoGrantACL(_ path: String) {
|
|
13
|
+
guard let acl = acl_get_file(path, ACL_TYPE_EXTENDED) else {
|
|
14
|
+
if errno == ENOENT { return } // A first write creates the file with mode 0600.
|
|
15
|
+
fail("macos_vault_acl_unavailable")
|
|
16
|
+
}
|
|
17
|
+
defer { acl_free(UnsafeMutableRawPointer(acl)) }
|
|
18
|
+
var entry: acl_entry_t?
|
|
19
|
+
var selector = ACL_FIRST_ENTRY
|
|
20
|
+
while acl_get_entry(acl, Int32(selector.rawValue), &entry) == 0 {
|
|
21
|
+
var tag = ACL_UNDEFINED_TAG
|
|
22
|
+
guard acl_get_tag_type(entry, &tag) == 0, tag == ACL_EXTENDED_DENY else {
|
|
23
|
+
fail("macos_vault_acl_invalid")
|
|
24
|
+
}
|
|
25
|
+
selector = ACL_NEXT_ENTRY
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// The caller verifies the release path's ancestors and package hashes. Walk
|
|
30
|
+
// with lstat so a symlink or hard link cannot redirect a permission change.
|
|
31
|
+
func secureRelease(_ path: String, verifyOnly: Bool) {
|
|
32
|
+
var pending = [path]
|
|
33
|
+
while let entry = pending.popLast() {
|
|
34
|
+
var st = stat()
|
|
35
|
+
guard lstat(entry, &st) == 0, st.st_uid == getuid() else { fail("macos_vault_release_invalid") }
|
|
36
|
+
let type = st.st_mode & S_IFMT
|
|
37
|
+
guard type == S_IFDIR || (type == S_IFREG && st.st_nlink == 1) else { fail("macos_vault_release_invalid") }
|
|
38
|
+
let mode: mode_t = type == S_IFDIR || entry.hasSuffix(".bin") ? 0o700 : 0o600
|
|
39
|
+
if (st.st_mode & 0o7777) != mode {
|
|
40
|
+
guard !verifyOnly, chmod(entry, mode) == 0 else { fail("macos_vault_release_permissions_invalid") }
|
|
41
|
+
}
|
|
42
|
+
requireNoGrantACL(entry)
|
|
43
|
+
if type == S_IFDIR {
|
|
44
|
+
guard let names = try? FileManager.default.contentsOfDirectory(atPath: entry) else { fail("macos_vault_release_invalid") }
|
|
45
|
+
pending.append(contentsOf: names.map { entry + "/" + $0 })
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func masterKey(_ root: String, create: Bool) -> Data {
|
|
51
|
+
let account = SHA256.hash(data: Data(root.utf8)).map { String(format: "%02x", $0) }.joined()
|
|
52
|
+
let base: [String: Any] = [
|
|
53
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
54
|
+
kSecAttrService as String: "com.hellolynk.codex.macos-vault.v1",
|
|
55
|
+
kSecAttrAccount as String: account
|
|
56
|
+
]
|
|
57
|
+
var lookup = base
|
|
58
|
+
lookup[kSecReturnData as String] = true
|
|
59
|
+
lookup[kSecMatchLimit as String] = kSecMatchLimitOne
|
|
60
|
+
var result: CFTypeRef?
|
|
61
|
+
let status = SecItemCopyMatching(lookup as CFDictionary, &result)
|
|
62
|
+
if status == errSecSuccess {
|
|
63
|
+
guard let key = result as? Data, key.count == 32 else { fail("macos_vault_key_invalid") }
|
|
64
|
+
return key
|
|
65
|
+
}
|
|
66
|
+
guard status == errSecItemNotFound else { fail("macos_keychain_access_\(abs(Int(status)))") }
|
|
67
|
+
guard create else { fail("macos_vault_key_missing") }
|
|
68
|
+
let key = SymmetricKey(size: .bits256).withUnsafeBytes { Data($0) }
|
|
69
|
+
var add = base
|
|
70
|
+
add[kSecValueData as String] = key
|
|
71
|
+
add[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
|
72
|
+
let inserted = SecItemAdd(add as CFDictionary, nil)
|
|
73
|
+
if inserted == errSecDuplicateItem { return masterKey(root, create: false) }
|
|
74
|
+
guard inserted == errSecSuccess else { fail("macos_keychain_access_\(abs(Int(inserted)))") }
|
|
75
|
+
return key
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
func nativeConfirmation() {
|
|
79
|
+
let raw = FileHandle.standardInput.readDataToEndOfFile()
|
|
80
|
+
guard raw.count <= 20480 * 6 + 8192,
|
|
81
|
+
var v = (try? JSONSerialization.jsonObject(with: raw)) as? [String: Any],
|
|
82
|
+
let body = v["displayText"] as? String, !body.isEmpty, body.utf8.count <= 20480,
|
|
83
|
+
let encoded = v["hmacKey"] as? String, encoded.count == 43,
|
|
84
|
+
let key = Data(base64Encoded: encoded.replacingOccurrences(of: "-", with: "+")
|
|
85
|
+
.replacingOccurrences(of: "_", with: "/") + "="), key.count == 32,
|
|
86
|
+
let recipient = v["recipientHelloLynkId"] as? String,
|
|
87
|
+
v["contract"] as? String == "hellolynk-native-human-confirmation-v1",
|
|
88
|
+
v["textDigest"] as? String == SHA256.hash(data: Data(body.utf8)).map({ String(format: "%02x", $0) }).joined()
|
|
89
|
+
else { fail("human_confirmation_request_invalid") }
|
|
90
|
+
|
|
91
|
+
var fields = ["contract", "actionId", "decision", "principalId", "delegateId", "hostInstallationId",
|
|
92
|
+
"adapterId", "adapterInstanceId", "hostGeneration", "recipientHelloLynkId"]
|
|
93
|
+
var label = "收件人:" + recipient
|
|
94
|
+
if v["recipientDelegateId"] != nil || v["recipientInstanceDisplayName"] != nil {
|
|
95
|
+
guard let name = v["recipientInstanceDisplayName"] as? String, !name.isEmpty, name.utf8.count <= 512,
|
|
96
|
+
name.range(of: #"[\x00-\x1F\x7F-\x9F\u2028\u2029\u202A-\u202E\u2066-\u2069]"#, options: .regularExpression) == nil,
|
|
97
|
+
v["recipientDelegateId"] is String else { fail("human_confirmation_request_invalid") }
|
|
98
|
+
fields += ["recipientDelegateId", "recipientInstanceDisplayName"]
|
|
99
|
+
label += "\n目标 AI:" + name
|
|
100
|
+
}
|
|
101
|
+
fields += ["clientMessageId", "textDigest", "createdAtMs", "expiresAtMs", "challenge"]
|
|
102
|
+
var expected = Set(fields)
|
|
103
|
+
expected.remove("decision")
|
|
104
|
+
expected.formUnion(["displayText", "hmacKey"])
|
|
105
|
+
guard expected == Set(v.keys) else { fail("human_confirmation_request_invalid") }
|
|
106
|
+
let app = NSApplication.shared
|
|
107
|
+
app.setActivationPolicy(.accessory)
|
|
108
|
+
app.activate(ignoringOtherApps: true)
|
|
109
|
+
let dialog = NSAlert()
|
|
110
|
+
dialog.messageText = "是否允许 HelloLynk 发送以下文本?"
|
|
111
|
+
dialog.informativeText = label
|
|
112
|
+
dialog.addButton(withTitle: "取消")
|
|
113
|
+
dialog.addButton(withTitle: "批准发送")
|
|
114
|
+
let scroll = NSScrollView(frame: NSRect(x: 0, y: 0, width: 500, height: 230))
|
|
115
|
+
scroll.hasVerticalScroller = true
|
|
116
|
+
let view = NSTextView(frame: scroll.contentView.bounds)
|
|
117
|
+
view.isEditable = false
|
|
118
|
+
view.isRichText = false
|
|
119
|
+
view.isVerticallyResizable = true
|
|
120
|
+
view.autoresizingMask = [.width]
|
|
121
|
+
view.textContainer?.widthTracksTextView = true
|
|
122
|
+
view.string = body
|
|
123
|
+
scroll.documentView = view
|
|
124
|
+
dialog.accessoryView = scroll
|
|
125
|
+
v["decision"] = dialog.runModal() == .alertSecondButtonReturn ? "approve" : "cancel"
|
|
126
|
+
let message = fields.map { field -> String in
|
|
127
|
+
if let text = v[field] as? String { return text }
|
|
128
|
+
if ["createdAtMs","expiresAtMs"].contains(field), let n = v[field] as? NSNumber { return n.stringValue }
|
|
129
|
+
fail("human_confirmation_request_invalid")
|
|
130
|
+
}.joined(separator: "\n")
|
|
131
|
+
let proof = HMAC<SHA256>.authenticationCode(for: Data(message.utf8), using: SymmetricKey(data: key))
|
|
132
|
+
v["proof"] = proof.map { String(format: "%02x", $0) }.joined()
|
|
133
|
+
for field in ["hmacKey", "challenge", "displayText"] { v.removeValue(forKey: field) }
|
|
134
|
+
guard let output = try? JSONSerialization.data(withJSONObject: v) else { fail("human_confirmation_response_invalid") }
|
|
135
|
+
FileHandle.standardOutput.write(output)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let args = Array(CommandLine.arguments.dropFirst())
|
|
139
|
+
if args == ["confirm"] { nativeConfirmation() }
|
|
140
|
+
else if args.count == 3, args[0] == "key", args[1].hasPrefix("/"), ["load","create"].contains(args[2]) {
|
|
141
|
+
requireNoGrantACL(args[1])
|
|
142
|
+
requireNoGrantACL(args[1] + "/protected-v1.sqlite")
|
|
143
|
+
let key = masterKey(args[1], create: args[2] == "create")
|
|
144
|
+
FileHandle(fileDescriptor: 3, closeOnDealloc: false).write(key)
|
|
145
|
+
} else if args.count == 2, ["verify-tree", "secure-tree"].contains(args[0]), args[1].hasPrefix("/") {
|
|
146
|
+
secureRelease(args[1], verifyOnly: args[0] == "verify-tree")
|
|
147
|
+
} else if args.count == 2, args[0] == "verify-acl", args[1].hasPrefix("/") {
|
|
148
|
+
requireNoGrantACL(args[1])
|
|
149
|
+
} else { fail("macos_vault_helper_arguments_invalid") }
|
|
@@ -85,8 +85,27 @@ public static class HelloLynkWindowsFileNative {
|
|
|
85
85
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
86
86
|
public static extern bool MoveFileExW(string existingName, string newName, uint flags);
|
|
87
87
|
|
|
88
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
89
|
+
private struct SECURITY_ATTRIBUTES {
|
|
90
|
+
public int Length;
|
|
91
|
+
public IntPtr SecurityDescriptor;
|
|
92
|
+
public int InheritHandle;
|
|
93
|
+
}
|
|
94
|
+
|
|
88
95
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
89
|
-
|
|
96
|
+
private static extern bool CreateDirectoryW(string path, ref SECURITY_ATTRIBUTES attributes);
|
|
97
|
+
|
|
98
|
+
public static bool CreateProtectedDirectory(string path, byte[] descriptor) {
|
|
99
|
+
var pinned = GCHandle.Alloc(descriptor, GCHandleType.Pinned);
|
|
100
|
+
try {
|
|
101
|
+
var attributes = new SECURITY_ATTRIBUTES {
|
|
102
|
+
Length = Marshal.SizeOf<SECURITY_ATTRIBUTES>(),
|
|
103
|
+
SecurityDescriptor = pinned.AddrOfPinnedObject(),
|
|
104
|
+
InheritHandle = 0
|
|
105
|
+
};
|
|
106
|
+
return CreateDirectoryW(path, ref attributes);
|
|
107
|
+
} finally { pinned.Free(); }
|
|
108
|
+
}
|
|
90
109
|
}
|
|
91
110
|
'@
|
|
92
111
|
|
|
@@ -162,7 +181,7 @@ function Get-HelloLynkExistingAncestorDirectories([string]$RootPath) {
|
|
|
162
181
|
return $ordered
|
|
163
182
|
}
|
|
164
183
|
|
|
165
|
-
function Assert-HelloLynkTrustedAncestorAcl([string]$RootPath) {
|
|
184
|
+
function Assert-HelloLynkTrustedAncestorAcl([string]$RootPath, [bool]$Create = $false) {
|
|
166
185
|
$rootParent = [IO.Path]::GetDirectoryName($RootPath.TrimEnd([char[]]@('\', '/')))
|
|
167
186
|
$directories = @(Get-HelloLynkExistingAncestorDirectories $RootPath)
|
|
168
187
|
$dangerousRights = (
|
|
@@ -175,6 +194,8 @@ function Assert-HelloLynkTrustedAncestorAcl([string]$RootPath) {
|
|
|
175
194
|
[Security.AccessControl.FileSystemRights]::ChangePermissions -bor
|
|
176
195
|
[Security.AccessControl.FileSystemRights]::TakeOwnership
|
|
177
196
|
)
|
|
197
|
+
$createRights = [Security.AccessControl.FileSystemRights]::CreateFiles -bor
|
|
198
|
+
[Security.AccessControl.FileSystemRights]::CreateDirectories
|
|
178
199
|
foreach ($directory in $directories) {
|
|
179
200
|
Assert-HelloLynkNoReparseAncestors $directory
|
|
180
201
|
$identity = Open-HelloLynkIdentity $directory $true
|
|
@@ -204,6 +225,7 @@ function Assert-HelloLynkTrustedAncestorAcl([string]$RootPath) {
|
|
|
204
225
|
)
|
|
205
226
|
$isRootParent = $directory.Equals($rootParent, [StringComparison]::OrdinalIgnoreCase)
|
|
206
227
|
$directoryIndex = [Array]::IndexOf($directories, $directory)
|
|
228
|
+
$willCreateProtectedChild = $Create -and -not $isRootParent -and $directoryIndex -eq $directories.Count - 1
|
|
207
229
|
$nextDirectoryProtected = $false
|
|
208
230
|
if ($directoryIndex -ge 0 -and $directoryIndex + 1 -lt $directories.Count) {
|
|
209
231
|
try {
|
|
@@ -220,15 +242,20 @@ function Assert-HelloLynkTrustedAncestorAcl([string]$RootPath) {
|
|
|
220
242
|
) { continue }
|
|
221
243
|
$rights = $rule.FileSystemRights
|
|
222
244
|
$hasDangerousRights = (($rights -band $dangerousRights) -ne 0)
|
|
245
|
+
# A competing child created by a different user fails our owner check.
|
|
246
|
+
# A grant to alter the ancestor itself still prevents first creation.
|
|
247
|
+
$canCreateProtectedChild = $willCreateProtectedChild -and
|
|
248
|
+
(($rights -band $dangerousRights -band (-bnot $createRights)) -eq 0)
|
|
223
249
|
$hasDeleteChild = (
|
|
224
250
|
($rights -band [Security.AccessControl.FileSystemRights]::DeleteSubdirectoriesAndFiles) -ne 0
|
|
225
251
|
)
|
|
226
252
|
if (
|
|
227
253
|
$hasDeleteChild -or
|
|
228
|
-
($hasDangerousRights -and ($isRootParent -or -not $nextDirectoryProtected))
|
|
254
|
+
($hasDangerousRights -and ($isRootParent -or (-not $nextDirectoryProtected -and -not $canCreateProtectedChild)))
|
|
229
255
|
) { Fail "client_root_ancestor_dacl_untrusted" }
|
|
230
256
|
}
|
|
231
257
|
}
|
|
258
|
+
return $directories[-1]
|
|
232
259
|
}
|
|
233
260
|
|
|
234
261
|
function New-HelloLynkAcl([bool]$Directory) {
|
|
@@ -361,7 +388,7 @@ function Exit-HelloLynkRootMutex($Mutex) {
|
|
|
361
388
|
try { $Mutex.ReleaseMutex() } finally { $Mutex.Dispose() }
|
|
362
389
|
}
|
|
363
390
|
|
|
364
|
-
function Ensure-HelloLynkSecureDirectory([string]$PathValue) {
|
|
391
|
+
function Ensure-HelloLynkSecureDirectory([string]$PathValue, [string]$ExistingAncestor = "") {
|
|
365
392
|
if ([IO.Directory]::Exists($PathValue)) {
|
|
366
393
|
Assert-HelloLynkNoReparseAncestors $PathValue
|
|
367
394
|
Assert-HelloLynkSecureAcl $PathValue $true
|
|
@@ -370,12 +397,21 @@ function Ensure-HelloLynkSecureDirectory([string]$PathValue) {
|
|
|
370
397
|
return
|
|
371
398
|
}
|
|
372
399
|
$parent = [IO.Path]::GetDirectoryName($PathValue)
|
|
373
|
-
if (
|
|
374
|
-
|
|
400
|
+
if ($ExistingAncestor) {
|
|
401
|
+
if (-not $parent.Equals($ExistingAncestor, [StringComparison]::OrdinalIgnoreCase)) {
|
|
402
|
+
Ensure-HelloLynkSecureDirectory $parent $ExistingAncestor
|
|
403
|
+
}
|
|
404
|
+
} elseif (-not [IO.Directory]::Exists($parent)) {
|
|
405
|
+
Ensure-HelloLynkSecureDirectory $parent
|
|
406
|
+
}
|
|
407
|
+
Assert-HelloLynkNoReparseAncestors $PathValue
|
|
408
|
+
$descriptor = (New-HelloLynkAcl $true).GetSecurityDescriptorBinaryForm()
|
|
409
|
+
if (-not [HelloLynkWindowsFileNative]::CreateProtectedDirectory($PathValue, $descriptor)) {
|
|
375
410
|
Fail "client_root_create_race"
|
|
376
411
|
}
|
|
377
|
-
Set-HelloLynkSecureAcl $PathValue $true
|
|
378
412
|
Assert-HelloLynkNoReparseAncestors $PathValue
|
|
413
|
+
# Keep the Windows auto-inheritance marker used by child file ACL checks.
|
|
414
|
+
Set-HelloLynkSecureAcl $PathValue $true
|
|
379
415
|
Assert-HelloLynkSecureAcl $PathValue $true
|
|
380
416
|
$identity = Open-HelloLynkIdentity $PathValue $true
|
|
381
417
|
$identity.Handle.Dispose()
|
|
@@ -386,14 +422,14 @@ function Resolve-HelloLynkClientRoot([string]$RootValue, [bool]$Create) {
|
|
|
386
422
|
Assert-HelloLynkNoReparseAncestors $root
|
|
387
423
|
$mutex = Enter-HelloLynkRootMutex $root
|
|
388
424
|
try {
|
|
389
|
-
Assert-HelloLynkTrustedAncestorAcl $root
|
|
390
|
-
if ($Create) { Ensure-HelloLynkSecureDirectory $root }
|
|
425
|
+
$existingAncestor = Assert-HelloLynkTrustedAncestorAcl $root $Create
|
|
426
|
+
if ($Create) { Ensure-HelloLynkSecureDirectory $root $existingAncestor }
|
|
391
427
|
if (-not [IO.Directory]::Exists($root)) { Fail "client_root_missing" }
|
|
392
428
|
Assert-HelloLynkNoReparseAncestors $root
|
|
393
429
|
Assert-HelloLynkSecureAcl $root $true
|
|
394
430
|
$identity = Open-HelloLynkIdentity $root $true
|
|
395
431
|
try {
|
|
396
|
-
Assert-HelloLynkTrustedAncestorAcl $root
|
|
432
|
+
$null = Assert-HelloLynkTrustedAncestorAcl $root
|
|
397
433
|
$canonical = $root
|
|
398
434
|
} finally { $identity.Handle.Dispose() }
|
|
399
435
|
return [pscustomobject]@{ Root = $canonical; Mutex = $mutex }
|
|
@@ -8,6 +8,7 @@ import { launchPinnedNeutralHostBootstrap, verifyPinnedNeutralHostRuntime } from
|
|
|
8
8
|
import { resolveClientAccountRoot } from "../runtime/core/hellolynk-client-account.mjs";
|
|
9
9
|
import { startInstalledClientUpdate } from "../runtime/core/hellolynk-client-update-entry.mjs";
|
|
10
10
|
import { recordCodexReleaseProcess } from "../runtime/core/hellolynk-release-retention.mjs";
|
|
11
|
+
import { DARWIN_VAULT_FILE } from "../runtime/core/hellolynk-darwin-vault.mjs";
|
|
11
12
|
|
|
12
13
|
const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
13
14
|
const PLUGIN_ROOT = path.dirname(MODULE_DIR);
|
|
@@ -19,17 +20,22 @@ const MAX_DISCOVERY_WAIT_MS = 120_000;
|
|
|
19
20
|
let installedPrepare = null;
|
|
20
21
|
const TRUSTED_BOOTSTRAP_FILES = Object.freeze(new Map([
|
|
21
22
|
["runtime/bootstrap/core/hellolynk-local-process-lock.mjs", "5212990a98b9ad2eb83fa2d5fb8a123d687c5ef6daf6cba49a4b6d04a7fe251e"],
|
|
22
|
-
["runtime/bootstrap/core/hellolynk-client-account.mjs", "
|
|
23
|
-
["runtime/neutral-host-release-loader.mjs", "
|
|
23
|
+
["runtime/bootstrap/core/hellolynk-client-account.mjs", "6e03a05127d4dc86be6391567b51a956d1a987acf4e23f5699ce0e00c3187b7e"],
|
|
24
|
+
["runtime/neutral-host-release-loader.mjs", "283a20c6a9b90481bc03c143ab51d5289abf7b7a86fbe51fba7ea2ae1e6d2c60"],
|
|
24
25
|
["runtime/neutral-host-bootstrap.mjs", "53513deed7f0155a6603a1489d1609fae37776442358181ff7650d0cd9351f0a"],
|
|
25
26
|
["runtime/bootstrap/core/hellolynk-runtime-safety.cjs", "43d576d9f774409f4a735793c1503a6f397e787b10c59a4ac9cc9257299f5efe"],
|
|
26
|
-
["runtime/bootstrap/core/hellolynk-host
|
|
27
|
-
["runtime/bootstrap/core/hellolynk-
|
|
27
|
+
["runtime/bootstrap/core/hellolynk-darwin-host.mjs", "ded97c3bc3dd65ca75305f5199a1340dffb987a5f283454d60586df8b6b55c09"],
|
|
28
|
+
["runtime/bootstrap/core/hellolynk-darwin-vault.mjs", "b6094d856af016e674e4a0183a4e474397bbe92e66638743fa62fe085b554d30"],
|
|
29
|
+
["runtime/bootstrap/core/hellolynk-host-protected-store.mjs", "10f81f4f6a5dd2fe9a742e847b2eb47dbf20f802f4414f46a05ccbc3505148e2"],
|
|
30
|
+
["runtime/bootstrap/core/hellolynk-neutral-host-installation-store.mjs", "42ae1e7deb876a8308b7bfed6a7b891d1834117b62504fc5befe3f91a0b4c740"],
|
|
28
31
|
["runtime/bootstrap/core/hellolynk-host-auth.mjs", "db1ec56f4e60e6450fba50188eecf89748f39f5d7a75c2456c30a6053233555d"],
|
|
29
32
|
["runtime/bootstrap/core/hellolynk-client-profile.mjs", "8be37831c96610e3d0a64848ada86488970cc6079e49764b47d8a8b2ba852269"],
|
|
30
|
-
["runtime/bootstrap/core/hellolynk-platform-credential-store.mjs", "
|
|
33
|
+
["runtime/bootstrap/core/hellolynk-platform-credential-store.mjs", "3969708bafefc3b267bb34a9dcc115804c874ad14f4a036426d727c02ff70d42"],
|
|
31
34
|
["runtime/bootstrap/core/hellolynk-client-core.mjs", "94bbad1d0ccee969bbffed176449e427188f1b892512a64167ab31f63d258e2b"],
|
|
32
35
|
["runtime/bootstrap/platform/windows/hellolynk-host-protected-store.ps1", "24357e8ce54090b4ec68e457f02c9e834a80f3273ef3c03a8c0fa7258797fb49"],
|
|
36
|
+
...(process.platform === "darwin" ? [
|
|
37
|
+
["runtime/bootstrap/platform/darwin/hellolynk-keychain-helper.bin", "f1a782c08229ebc0e8d1704b6390e91c5695e084b4df0a1a6dc043f6b23700ab"],
|
|
38
|
+
] : []),
|
|
33
39
|
]));
|
|
34
40
|
|
|
35
41
|
// A still-open cache may load a different installed release during an update.
|
|
@@ -150,7 +156,7 @@ export async function prepareCodexNeutralRelease(options = {}, finalBindingDefer
|
|
|
150
156
|
releaseRoot: bootstrapReleaseRoot,
|
|
151
157
|
});
|
|
152
158
|
const storeRoot = resolveClientAccountRoot("codex", absolutePath(
|
|
153
|
-
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || bootstrapTrusted.defaultStoreRoot(
|
|
159
|
+
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || bootstrapTrusted.defaultStoreRoot(process.platform, env),
|
|
154
160
|
"neutral_codex_binding_configuration_required",
|
|
155
161
|
));
|
|
156
162
|
const bootstrapInstallationStore = bootstrapTrusted.createInstallationStore({ root: storeRoot });
|
|
@@ -198,7 +204,7 @@ async function prepareSelectedRelease(options, verifiedInitial = null) {
|
|
|
198
204
|
const releaseRoot = path.dirname(path.dirname(loaderPath));
|
|
199
205
|
const trusted = await loadTrustedBootstrap({ loaderPath, releaseRoot });
|
|
200
206
|
const storeRoot = resolveClientAccountRoot("codex", absolutePath(
|
|
201
|
-
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || trusted.defaultStoreRoot(
|
|
207
|
+
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || trusted.defaultStoreRoot(process.platform, env),
|
|
202
208
|
"neutral_codex_binding_configuration_required",
|
|
203
209
|
));
|
|
204
210
|
const installationStore = trusted.createInstallationStore({ root: storeRoot });
|
|
@@ -268,7 +274,7 @@ async function initializationFingerprint(storeRoot, binding = null) {
|
|
|
268
274
|
if (parent === path.dirname(parent)) break;
|
|
269
275
|
}
|
|
270
276
|
};
|
|
271
|
-
await stat(path.join(storeRoot, "capabilities-v1.dpapi.clixml"), false);
|
|
277
|
+
await stat(path.join(storeRoot, process.platform === "darwin" ? DARWIN_VAULT_FILE : "capabilities-v1.dpapi.clixml"), false);
|
|
272
278
|
await stat(path.join(storeRoot, "installations-v1.json"), false);
|
|
273
279
|
const state = JSON.stringify([...seen]);
|
|
274
280
|
if (binding) {
|
|
@@ -5,6 +5,7 @@ import crypto from "node:crypto";
|
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
|
|
8
|
+
import { verifyDarwinUnclaimedAuthorization } from "../plugins/hellolynk-codex/runtime/core/hellolynk-darwin-host.mjs";
|
|
8
9
|
import { readClientProfile } from "../plugins/hellolynk-codex/runtime/core/hellolynk-client-profile.mjs";
|
|
9
10
|
import { createNeutralHostInstallationStore } from "../plugins/hellolynk-codex/runtime/core/hellolynk-neutral-host-installation-store.mjs";
|
|
10
11
|
import { clientAccountBaseRoot } from "../plugins/hellolynk-codex/runtime/core/hellolynk-client-account.mjs";
|
|
@@ -164,7 +165,7 @@ assert.equal(releaseVerification.verifiedFileCount >= 8, true);
|
|
|
164
165
|
let transport = null;
|
|
165
166
|
let bootstrapTransportRequired = false;
|
|
166
167
|
let protectedStorePresent = true;
|
|
167
|
-
try { await fs.lstat(path.join(root, "capabilities-v1.dpapi.clixml")); }
|
|
168
|
+
try { await fs.lstat(path.join(root, process.platform === "darwin" ? "protected-v1.sqlite" : "capabilities-v1.dpapi.clixml")); }
|
|
168
169
|
catch (error) {
|
|
169
170
|
if (error?.code !== "ENOENT") throw error;
|
|
170
171
|
protectedStorePresent = false;
|
|
@@ -173,6 +174,9 @@ if (!protectedStorePresent) {
|
|
|
173
174
|
if (!(freshPreBind || recoveryPreBind)) await store.status();
|
|
174
175
|
await verifyHostProtectedStorePath({ root, path: root, directory: true });
|
|
175
176
|
bootstrapTransportRequired = true;
|
|
177
|
+
} else if (process.platform === "darwin" && freshPreBind) {
|
|
178
|
+
await verifyDarwinUnclaimedAuthorization(root);
|
|
179
|
+
bootstrapTransportRequired = true;
|
|
176
180
|
} else {
|
|
177
181
|
assert.equal((await store.status()).protected, true);
|
|
178
182
|
try { transport = preflightOnly ? await store.verifyTransport() : await store.resolveTransport(); }
|