@hellolynk-ai/codex-plugin 0.2.100 → 0.2.102-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 +79 -11
- package/hellolynk-client-pack-manifest.json +111 -71
- 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-client-profile.mjs +25 -2
- package/plugins/hellolynk-codex/runtime/bootstrap/core/hellolynk-darwin-host.mjs +256 -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 +3 -7
- 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-profile.mjs +25 -2
- package/plugins/hellolynk-codex/runtime/core/hellolynk-client-update-entry.mjs +7 -3
- package/plugins/hellolynk-codex/runtime/core/hellolynk-client-update-runtime.mjs +24 -8
- package/plugins/hellolynk-codex/runtime/core/hellolynk-client-update.mjs +23 -9
- package/plugins/hellolynk-codex/runtime/core/hellolynk-darwin-host.mjs +256 -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-addressing-tools.cjs +1 -1
- 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 +3 -7
- 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 +116 -19
- 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 +59 -27
- 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/server/codex-neutral-production.mjs +17 -9
- package/plugins/hellolynk-codex/server/mcp-server.mjs +1193 -1193
- package/plugins/hellolynk-codex/server/native-conversation-directory.mjs +33 -33
- package/plugins/hellolynk-codex/server/workbench-runtime.mjs +42 -42
- package/tools/hellolynk-activate-neutral-host-clients.mjs +5 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"files": [
|
|
5
5
|
{
|
|
6
6
|
"path": "release/package.json",
|
|
7
|
-
"sha256": "
|
|
7
|
+
"sha256": "befbca064334e8ff7f9d192f095ac1bd786a3882385a450fc2c2d2a5c9b2b7dd"
|
|
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",
|
|
@@ -36,23 +36,23 @@
|
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
"path": "core/hellolynk-client-profile.mjs",
|
|
39
|
-
"sha256": "
|
|
39
|
+
"sha256": "8be37831c96610e3d0a64848ada86488970cc6079e49764b47d8a8b2ba852269"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"path": "core/hellolynk-client-update-entry.mjs",
|
|
43
|
-
"sha256": "
|
|
43
|
+
"sha256": "1e513a4a98437dc60b49f9f39fc3958808c3acfaeb6c5bb638efea2e61d4b1ee"
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"path": "core/hellolynk-client-update-runtime.mjs",
|
|
47
|
-
"sha256": "
|
|
47
|
+
"sha256": "96aa12ba21619a0cd78ef61c63be6f43fdb61f892201ce923ee35e0912ae2e52"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"path": "core/hellolynk-client-update.mjs",
|
|
51
|
-
"sha256": "
|
|
51
|
+
"sha256": "93bf5f2ecc72731d70367306989fa18c82fa7bf9e4b5f785a1376f0d55239428"
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"path": "core/hellolynk-release-retention.mjs",
|
|
55
|
-
"sha256": "
|
|
55
|
+
"sha256": "7cfd7e20c37ac1479f2472cc5fba8e830dcd1b83b91a86c340749cf145f0d661"
|
|
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": "0772d7a23280b18d5bc59383a6a14fd2ecfd9de1ec53b351be0250770e3e2e70"
|
|
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",
|
|
@@ -168,11 +176,11 @@
|
|
|
168
176
|
},
|
|
169
177
|
{
|
|
170
178
|
"path": "core/hellolynk-native-addressing-tools.cjs",
|
|
171
|
-
"sha256": "
|
|
179
|
+
"sha256": "f4bd81b3d03277e28955a62409383a0c4072c6212567f71425df4e18ece75d63"
|
|
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": "e744bacf65f7b86cbcf7d654189c0e07e09401083e2b6f9053b17c1c3bacd1b4"
|
|
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",
|
|
@@ -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": "0772d7a23280b18d5bc59383a6a14fd2ecfd9de1ec53b351be0250770e3e2e70"
|
|
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",
|
|
@@ -312,7 +328,7 @@
|
|
|
312
328
|
},
|
|
313
329
|
{
|
|
314
330
|
"path": "bootstrap/core/hellolynk-client-profile.mjs",
|
|
315
|
-
"sha256": "
|
|
331
|
+
"sha256": "8be37831c96610e3d0a64848ada86488970cc6079e49764b47d8a8b2ba852269"
|
|
316
332
|
},
|
|
317
333
|
{
|
|
318
334
|
"path": "bootstrap/core/hellolynk-host-auth.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": "2e09f95b8c15ac307d3be0e5b29fecd00e5eae95fd816e885c51484990e703cb"
|
|
348
380
|
},
|
|
349
381
|
{
|
|
350
382
|
"path": "release/server/neutral-host-adapter.mjs",
|
|
@@ -352,7 +384,7 @@
|
|
|
352
384
|
},
|
|
353
385
|
{
|
|
354
386
|
"path": "release/server/workbench-runtime.mjs",
|
|
355
|
-
"sha256": "
|
|
387
|
+
"sha256": "99e069a72a0be3e73a993b2092d55470fcb481eb381841a156b2756415a0a0a9"
|
|
356
388
|
}
|
|
357
389
|
]
|
|
358
390
|
}
|
|
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") }
|
|
@@ -7,6 +7,8 @@ import { discoverNeutralHost } from "./neutral-host-adapter.mjs";
|
|
|
7
7
|
import { launchPinnedNeutralHostBootstrap, verifyPinnedNeutralHostRuntime } from "../runtime/core/hellolynk-neutral-host-launcher.mjs";
|
|
8
8
|
import { resolveClientAccountRoot } from "../runtime/core/hellolynk-client-account.mjs";
|
|
9
9
|
import { startInstalledClientUpdate } from "../runtime/core/hellolynk-client-update-entry.mjs";
|
|
10
|
+
import { recordCodexReleaseProcess } from "../runtime/core/hellolynk-release-retention.mjs";
|
|
11
|
+
import { DARWIN_VAULT_FILE } from "../runtime/core/hellolynk-darwin-vault.mjs";
|
|
10
12
|
|
|
11
13
|
const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
12
14
|
const PLUGIN_ROOT = path.dirname(MODULE_DIR);
|
|
@@ -18,17 +20,22 @@ const MAX_DISCOVERY_WAIT_MS = 120_000;
|
|
|
18
20
|
let installedPrepare = null;
|
|
19
21
|
const TRUSTED_BOOTSTRAP_FILES = Object.freeze(new Map([
|
|
20
22
|
["runtime/bootstrap/core/hellolynk-local-process-lock.mjs", "5212990a98b9ad2eb83fa2d5fb8a123d687c5ef6daf6cba49a4b6d04a7fe251e"],
|
|
21
|
-
["runtime/bootstrap/core/hellolynk-client-account.mjs", "
|
|
22
|
-
["runtime/neutral-host-release-loader.mjs", "
|
|
23
|
+
["runtime/bootstrap/core/hellolynk-client-account.mjs", "6e03a05127d4dc86be6391567b51a956d1a987acf4e23f5699ce0e00c3187b7e"],
|
|
24
|
+
["runtime/neutral-host-release-loader.mjs", "283a20c6a9b90481bc03c143ab51d5289abf7b7a86fbe51fba7ea2ae1e6d2c60"],
|
|
23
25
|
["runtime/neutral-host-bootstrap.mjs", "53513deed7f0155a6603a1489d1609fae37776442358181ff7650d0cd9351f0a"],
|
|
24
26
|
["runtime/bootstrap/core/hellolynk-runtime-safety.cjs", "43d576d9f774409f4a735793c1503a6f397e787b10c59a4ac9cc9257299f5efe"],
|
|
25
|
-
["runtime/bootstrap/core/hellolynk-host
|
|
26
|
-
["runtime/bootstrap/core/hellolynk-
|
|
27
|
+
["runtime/bootstrap/core/hellolynk-darwin-host.mjs", "0772d7a23280b18d5bc59383a6a14fd2ecfd9de1ec53b351be0250770e3e2e70"],
|
|
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"],
|
|
27
31
|
["runtime/bootstrap/core/hellolynk-host-auth.mjs", "db1ec56f4e60e6450fba50188eecf89748f39f5d7a75c2456c30a6053233555d"],
|
|
28
|
-
["runtime/bootstrap/core/hellolynk-client-profile.mjs", "
|
|
29
|
-
["runtime/bootstrap/core/hellolynk-platform-credential-store.mjs", "
|
|
32
|
+
["runtime/bootstrap/core/hellolynk-client-profile.mjs", "8be37831c96610e3d0a64848ada86488970cc6079e49764b47d8a8b2ba852269"],
|
|
33
|
+
["runtime/bootstrap/core/hellolynk-platform-credential-store.mjs", "3969708bafefc3b267bb34a9dcc115804c874ad14f4a036426d727c02ff70d42"],
|
|
30
34
|
["runtime/bootstrap/core/hellolynk-client-core.mjs", "94bbad1d0ccee969bbffed176449e427188f1b892512a64167ab31f63d258e2b"],
|
|
31
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
|
+
] : []),
|
|
32
39
|
]));
|
|
33
40
|
|
|
34
41
|
// A still-open cache may load a different installed release during an update.
|
|
@@ -149,7 +156,7 @@ export async function prepareCodexNeutralRelease(options = {}, finalBindingDefer
|
|
|
149
156
|
releaseRoot: bootstrapReleaseRoot,
|
|
150
157
|
});
|
|
151
158
|
const storeRoot = resolveClientAccountRoot("codex", absolutePath(
|
|
152
|
-
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || bootstrapTrusted.defaultStoreRoot(
|
|
159
|
+
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || bootstrapTrusted.defaultStoreRoot(process.platform, env),
|
|
153
160
|
"neutral_codex_binding_configuration_required",
|
|
154
161
|
));
|
|
155
162
|
const bootstrapInstallationStore = bootstrapTrusted.createInstallationStore({ root: storeRoot });
|
|
@@ -197,7 +204,7 @@ async function prepareSelectedRelease(options, verifiedInitial = null) {
|
|
|
197
204
|
const releaseRoot = path.dirname(path.dirname(loaderPath));
|
|
198
205
|
const trusted = await loadTrustedBootstrap({ loaderPath, releaseRoot });
|
|
199
206
|
const storeRoot = resolveClientAccountRoot("codex", absolutePath(
|
|
200
|
-
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || trusted.defaultStoreRoot(
|
|
207
|
+
options.storeRoot || env.HELLOLYNK_NEUTRAL_STORE_ROOT || trusted.defaultStoreRoot(process.platform, env),
|
|
201
208
|
"neutral_codex_binding_configuration_required",
|
|
202
209
|
));
|
|
203
210
|
const installationStore = trusted.createInstallationStore({ root: storeRoot });
|
|
@@ -216,6 +223,7 @@ async function prepareSelectedRelease(options, verifiedInitial = null) {
|
|
|
216
223
|
assertReleaseBinding(binding, inspection);
|
|
217
224
|
const release = await loader.activateNeutralHostRelease(inspection);
|
|
218
225
|
if (!release || typeof release.run !== "function") throw codeError("neutral_codex_runner_integrity_invalid");
|
|
226
|
+
await recordCodexReleaseProcess(path.resolve(releaseRoot, "../.."));
|
|
219
227
|
return Object.freeze({ release, inspection, binding, initialBindingFingerprint,
|
|
220
228
|
releaseRoot, storeRoot, installationStore, protectedStore,
|
|
221
229
|
runnerBinding: (root) => currentRunnerBinding(storeRoot, root, binding, initialBindingFingerprint) });
|
|
@@ -266,7 +274,7 @@ async function initializationFingerprint(storeRoot, binding = null) {
|
|
|
266
274
|
if (parent === path.dirname(parent)) break;
|
|
267
275
|
}
|
|
268
276
|
};
|
|
269
|
-
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);
|
|
270
278
|
await stat(path.join(storeRoot, "installations-v1.json"), false);
|
|
271
279
|
const state = JSON.stringify([...seen]);
|
|
272
280
|
if (binding) {
|