pairling 0.2.10 → 0.2.12
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 +6 -7
- package/package.json +3 -3
- package/payload/mac/SOURCE_REVISION +1 -1
- package/payload/mac/VERSION +1 -1
- package/payload/mac/companiond/pairling_pairing.py +13 -7
- package/payload/mac/companiond/pairlingd.py +586 -410
- package/payload/mac/companiond/runtime_contract.py +0 -3
- package/payload/mac/companiond/runtime_manifest.py +2 -1
- package/payload/mac/companiond/runtime_paths.py +2 -6
- package/payload/mac/companiond/safety_monitor.py +56 -1
- package/payload/mac/connectd/internal/gateway/proxy.go +14 -1
- package/payload/mac/connectd/internal/gateway/proxy_test.go +24 -0
- package/payload/mac/install/bootstrap-first-run.sh +32 -1
- package/payload/mac/install/doctor.sh +43 -14
- package/payload/mac/install/install-runtime.sh +817 -57
- package/payload/mac/install/render-launchd.py +1 -28
- package/payload/mac/install/uninstall-runtime.sh +0 -3
- package/payload/mac/install/verify-payload-manifest.py +71 -0
- package/payload-manifest.json +23 -27
- package/payload/mac/guardian/companion-power-guardian.py +0 -613
- package/payload/mac/guardian/guardian_contract.py +0 -67
|
@@ -8,7 +8,6 @@ import plistlib
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
10
|
PAIRLING_DAEMON_LABEL = "dev.pairling.companiond"
|
|
11
|
-
PAIRLING_GUARDIAN_LABEL = "dev.pairling.power-guardian"
|
|
12
11
|
PAIRLING_CONNECTD_LABEL = "dev.pairling.connectd"
|
|
13
12
|
PAIRLING_PTYBROKER_LABEL = "dev.pairling.ptybroker"
|
|
14
13
|
PAIRLING_RUNTIME_PORT = "7773"
|
|
@@ -24,7 +23,7 @@ def daemon_plist(current: Path, logs: Path, python_bin: str) -> dict:
|
|
|
24
23
|
env = {
|
|
25
24
|
"PAIRLING_RUNTIME_PORT": PAIRLING_RUNTIME_PORT,
|
|
26
25
|
"COMPANION_DAEMON_PORT": PAIRLING_RUNTIME_PORT,
|
|
27
|
-
"PAIRLING_BIND_MODE": "
|
|
26
|
+
"PAIRLING_BIND_MODE": "loopback",
|
|
28
27
|
"PAIRLING_APP_SUPPORT_ROOT": str(current.parent.parent),
|
|
29
28
|
"PAIRLING_LOGS_ROOT": str(logs),
|
|
30
29
|
"PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin",
|
|
@@ -44,30 +43,6 @@ def daemon_plist(current: Path, logs: Path, python_bin: str) -> dict:
|
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
|
|
47
|
-
def guardian_plist(current: Path, logs: Path, python_bin: str) -> dict:
|
|
48
|
-
return {
|
|
49
|
-
"Label": PAIRLING_GUARDIAN_LABEL,
|
|
50
|
-
"ProgramArguments": [
|
|
51
|
-
python_bin,
|
|
52
|
-
str(current / "guardian" / "companion-power-guardian.py"),
|
|
53
|
-
],
|
|
54
|
-
"EnvironmentVariables": {
|
|
55
|
-
"PAIRLING_RUNTIME_PORT": PAIRLING_RUNTIME_PORT,
|
|
56
|
-
"COMPANION_DAEMON_PORT": PAIRLING_RUNTIME_PORT,
|
|
57
|
-
"COMPANION_COORDINATOR_HOST": "pairling-mac",
|
|
58
|
-
"COMPANION_GUARDIAN_ENFORCE": "0",
|
|
59
|
-
"COMPANION_LOW_POWER_MODE_POLICY": "preserve",
|
|
60
|
-
"COMPANION_POWER_INTERVAL_SECONDS": "20",
|
|
61
|
-
"COMPANION_POWER_STATE_PATH": "/var/run/pairling-power-state.json",
|
|
62
|
-
"PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin",
|
|
63
|
-
},
|
|
64
|
-
"RunAtLoad": True,
|
|
65
|
-
"KeepAlive": True,
|
|
66
|
-
"StandardOutPath": str(logs / "power-guardian.log"),
|
|
67
|
-
"StandardErrorPath": str(logs / "power-guardian.err"),
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
46
|
def connectd_plist(current: Path, logs: Path) -> dict:
|
|
72
47
|
app_support = current.parent.parent
|
|
73
48
|
return {
|
|
@@ -124,7 +99,6 @@ def main() -> int:
|
|
|
124
99
|
parser.add_argument("--logs-root", required=True)
|
|
125
100
|
parser.add_argument("--output-dir", required=True)
|
|
126
101
|
parser.add_argument("--daemon-python", default="/usr/local/bin/python3")
|
|
127
|
-
parser.add_argument("--guardian-python", default="/usr/bin/python3")
|
|
128
102
|
parser.add_argument("--mirror-python", default="/usr/local/bin/python3", help=argparse.SUPPRESS)
|
|
129
103
|
args = parser.parse_args()
|
|
130
104
|
|
|
@@ -134,7 +108,6 @@ def main() -> int:
|
|
|
134
108
|
|
|
135
109
|
write_plist(out / f"{PAIRLING_DAEMON_LABEL}.plist", daemon_plist(current, logs, args.daemon_python))
|
|
136
110
|
write_plist(out / f"{PAIRLING_PTYBROKER_LABEL}.plist", ptybroker_plist(current, logs, args.daemon_python))
|
|
137
|
-
write_plist(out / f"{PAIRLING_GUARDIAN_LABEL}.plist", guardian_plist(current, logs, args.guardian_python))
|
|
138
111
|
write_plist(out / f"{PAIRLING_CONNECTD_LABEL}.plist", connectd_plist(current, logs))
|
|
139
112
|
return 0
|
|
140
113
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
PAIRLING_DAEMON_LABEL="dev.pairling.companiond"
|
|
5
|
-
PAIRLING_GUARDIAN_LABEL="dev.pairling.power-guardian"
|
|
6
5
|
PAIRLING_CONNECTD_LABEL="dev.pairling.connectd"
|
|
7
6
|
PAIRLING_PTYBROKER_LABEL="dev.pairling.ptybroker"
|
|
8
7
|
APP_SUPPORT="${PAIRLING_APP_SUPPORT_ROOT:-${COMPANION_APP_SUPPORT_ROOT:-$HOME/Library/Application Support/Pairling}}"
|
|
@@ -10,7 +9,6 @@ LOGS_ROOT="${PAIRLING_LOGS_ROOT:-${COMPANION_LOGS_ROOT:-$HOME/Library/Logs/Pairl
|
|
|
10
9
|
USER_PLIST="$HOME/Library/LaunchAgents/$PAIRLING_DAEMON_LABEL.plist"
|
|
11
10
|
CONNECTD_USER_PLIST="$HOME/Library/LaunchAgents/$PAIRLING_CONNECTD_LABEL.plist"
|
|
12
11
|
PTYBROKER_USER_PLIST="$HOME/Library/LaunchAgents/$PAIRLING_PTYBROKER_LABEL.plist"
|
|
13
|
-
SYSTEM_PLIST="/Library/LaunchDaemons/$PAIRLING_GUARDIAN_LABEL.plist"
|
|
14
12
|
# Legacy: the silent-join mint broker, removed from the product. Torn down below.
|
|
15
13
|
MINTD_SYSTEM_LABEL="dev.pairling.mintd"
|
|
16
14
|
MINTD_SYSTEM_PLIST="/Library/LaunchDaemons/$MINTD_SYSTEM_LABEL.plist"
|
|
@@ -137,7 +135,6 @@ bootout_user "$PAIRLING_PTYBROKER_LABEL" "$PTYBROKER_USER_PLIST"
|
|
|
137
135
|
rm -f "$USER_PLIST"
|
|
138
136
|
rm -f "$CONNECTD_USER_PLIST"
|
|
139
137
|
rm -f "$PTYBROKER_USER_PLIST"
|
|
140
|
-
bootout_system "$PAIRLING_GUARDIAN_LABEL" "$SYSTEM_PLIST"
|
|
141
138
|
teardown_legacy_mintd
|
|
142
139
|
|
|
143
140
|
rm -rf "$APP_SUPPORT/pair" 2>/dev/null || true
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import hashlib
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def fail(message: str) -> int:
|
|
11
|
+
print(f"payload manifest verification failed: {message}", file=sys.stderr)
|
|
12
|
+
return 1
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def sha256(path: Path) -> str:
|
|
16
|
+
digest = hashlib.sha256()
|
|
17
|
+
with path.open("rb") as fh:
|
|
18
|
+
for chunk in iter(lambda: fh.read(1024 * 1024), b""):
|
|
19
|
+
digest.update(chunk)
|
|
20
|
+
return digest.hexdigest()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def payload_file(payload_root: Path, rel: str) -> Path | None:
|
|
24
|
+
path = Path(rel)
|
|
25
|
+
if path.is_absolute() or ".." in path.parts:
|
|
26
|
+
return None
|
|
27
|
+
parts = path.parts
|
|
28
|
+
if not parts or parts[0] != "payload":
|
|
29
|
+
return None
|
|
30
|
+
return payload_root.joinpath(*parts[1:])
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main() -> int:
|
|
34
|
+
if len(sys.argv) != 3:
|
|
35
|
+
return fail("usage: verify-payload-manifest.py <payload-root> <payload-manifest.json>")
|
|
36
|
+
payload_root = Path(sys.argv[1]).resolve()
|
|
37
|
+
manifest_path = Path(sys.argv[2]).resolve()
|
|
38
|
+
try:
|
|
39
|
+
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
40
|
+
except (OSError, json.JSONDecodeError) as exc:
|
|
41
|
+
return fail(f"cannot read manifest: {exc}")
|
|
42
|
+
if not isinstance(manifest, dict) or manifest.get("schema_version") != 1:
|
|
43
|
+
return fail("unsupported manifest schema")
|
|
44
|
+
files = manifest.get("files")
|
|
45
|
+
if not isinstance(files, list) or not files:
|
|
46
|
+
return fail("manifest has no files")
|
|
47
|
+
for item in files:
|
|
48
|
+
if not isinstance(item, dict):
|
|
49
|
+
return fail("manifest file entry is not an object")
|
|
50
|
+
rel = str(item.get("path") or "")
|
|
51
|
+
expected = str(item.get("sha256") or "")
|
|
52
|
+
if len(expected) != 64 or any(c not in "0123456789abcdef" for c in expected.lower()):
|
|
53
|
+
return fail(f"bad sha256 for {rel or '<missing path>'}")
|
|
54
|
+
target = payload_file(payload_root, rel)
|
|
55
|
+
if target is None:
|
|
56
|
+
return fail(f"bad payload path {rel!r}")
|
|
57
|
+
try:
|
|
58
|
+
resolved = target.resolve(strict=True)
|
|
59
|
+
except OSError:
|
|
60
|
+
return fail(f"missing payload file {rel}")
|
|
61
|
+
if payload_root not in (resolved, *resolved.parents):
|
|
62
|
+
return fail(f"payload path escapes root {rel!r}")
|
|
63
|
+
actual = sha256(resolved)
|
|
64
|
+
if actual.lower() != expected.lower():
|
|
65
|
+
return fail(f"sha256 mismatch for {rel}")
|
|
66
|
+
print(f"payload manifest verified: {len(files)} files")
|
|
67
|
+
return 0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
raise SystemExit(main())
|
package/payload-manifest.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"connectd": {
|
|
3
3
|
"darwin-arm64": {
|
|
4
|
-
"sha256": "
|
|
4
|
+
"sha256": "29af8f7c4d4291e487804bf84e918ae58d35e258ee542c70884ab107e94b63fa",
|
|
5
5
|
"team_id": "965AVD34A3"
|
|
6
6
|
},
|
|
7
7
|
"darwin-x64": {
|
|
8
|
-
"sha256": "
|
|
8
|
+
"sha256": "6df440f47c58dc520396ed4bf8b437545b27c87d6e3787c20ce212b6a3a58f6d",
|
|
9
9
|
"team_id": "965AVD34A3"
|
|
10
10
|
}
|
|
11
11
|
},
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"path": "payload/mac/SOURCE_REVISION",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "2828a4f7792a6e97ac014e5205bdcf361ced85eff86009de975b92da14959e2b"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"path": "payload/mac/VERSION",
|
|
27
|
-
"sha256": "
|
|
27
|
+
"sha256": "b1d246bf58dfe9d621c372fbca4fdda71a56ddd79c641b9e3b7dde08ca4d7512"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"path": "payload/mac/companiond/app_attest_lan.py",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"path": "payload/mac/companiond/pairling_pairing.py",
|
|
83
|
-
"sha256": "
|
|
83
|
+
"sha256": "9b1046d54b7b1c026186e9d1f1dae4ff33de3c66f36f37b8842b2be7fcaeb36c"
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
"path": "payload/mac/companiond/pairling_psk.py",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
"path": "payload/mac/companiond/pairlingd.py",
|
|
99
|
-
"sha256": "
|
|
99
|
+
"sha256": "0377e193d6ac49bfb55979bb4c17635caa1f2cbcb8c85c0d51447cf07939f908"
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
102
|
"path": "payload/mac/companiond/providers/__init__.py",
|
|
@@ -148,19 +148,19 @@
|
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
"path": "payload/mac/companiond/runtime_contract.py",
|
|
151
|
-
"sha256": "
|
|
151
|
+
"sha256": "903c4bef29b17454c8dde50ebaa9b7107e8d5a113f25b2a0861b18e544b7b9ee"
|
|
152
152
|
},
|
|
153
153
|
{
|
|
154
154
|
"path": "payload/mac/companiond/runtime_manifest.py",
|
|
155
|
-
"sha256": "
|
|
155
|
+
"sha256": "c38f2bca253b9364263593ad8443bdf4ebbb80f823a11f8a66cc0a142e944f3d"
|
|
156
156
|
},
|
|
157
157
|
{
|
|
158
158
|
"path": "payload/mac/companiond/runtime_paths.py",
|
|
159
|
-
"sha256": "
|
|
159
|
+
"sha256": "d5f0c2546e50c1fa30e9e2c043c0ef97e924cb0c92626c2885c577b9b4e613ad"
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
162
|
"path": "payload/mac/companiond/safety_monitor.py",
|
|
163
|
-
"sha256": "
|
|
163
|
+
"sha256": "eb2aebe73214d8cafa810295f0b1a63933b5f850d3e45533108b55d2b9c4b08e"
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
166
|
"path": "payload/mac/companiond/sentinel_notifications.py",
|
|
@@ -232,11 +232,11 @@
|
|
|
232
232
|
},
|
|
233
233
|
{
|
|
234
234
|
"path": "payload/mac/connectd/internal/gateway/proxy.go",
|
|
235
|
-
"sha256": "
|
|
235
|
+
"sha256": "39d736dc16ccd2e7118605d36014d63f0bedf0b6c08fbb64ee5cf7b795869119"
|
|
236
236
|
},
|
|
237
237
|
{
|
|
238
238
|
"path": "payload/mac/connectd/internal/gateway/proxy_test.go",
|
|
239
|
-
"sha256": "
|
|
239
|
+
"sha256": "678025830386e2175fcf84adc18537bb673a97db1d29cbd7c79ef5cc1721d6f2"
|
|
240
240
|
},
|
|
241
241
|
{
|
|
242
242
|
"path": "payload/mac/connectd/internal/runtime/config.go",
|
|
@@ -254,25 +254,17 @@
|
|
|
254
254
|
"path": "payload/mac/connectd/internal/status/status_test.go",
|
|
255
255
|
"sha256": "5d2c9601c5edf6afc0abc7d4737cc06fd4e3a53cb83c0fce4b51750c1e194366"
|
|
256
256
|
},
|
|
257
|
-
{
|
|
258
|
-
"path": "payload/mac/guardian/companion-power-guardian.py",
|
|
259
|
-
"sha256": "b613f57b886a88a047b9f226ae0d9c160932b114f6957b1721988363f80eeca9"
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
"path": "payload/mac/guardian/guardian_contract.py",
|
|
263
|
-
"sha256": "18f08827a61b165b21f47616bfc7a6aacf1d309672ddd83dee411415d9af10dd"
|
|
264
|
-
},
|
|
265
257
|
{
|
|
266
258
|
"path": "payload/mac/install/bootstrap-first-run.sh",
|
|
267
|
-
"sha256": "
|
|
259
|
+
"sha256": "294c74c9cd07af6d738dfbad5f125f9a142c358d659506466a4e8c3df62243c5"
|
|
268
260
|
},
|
|
269
261
|
{
|
|
270
262
|
"path": "payload/mac/install/doctor.sh",
|
|
271
|
-
"sha256": "
|
|
263
|
+
"sha256": "87f817965611e59cb84b1547dd59352f0f637d66084e3d4d7a84cea299ad82e2"
|
|
272
264
|
},
|
|
273
265
|
{
|
|
274
266
|
"path": "payload/mac/install/install-runtime.sh",
|
|
275
|
-
"sha256": "
|
|
267
|
+
"sha256": "2cba0b8bc3731c5725aae2229fe4b2069f71c4f269e1cc212c03197152561daf"
|
|
276
268
|
},
|
|
277
269
|
{
|
|
278
270
|
"path": "payload/mac/install/psk_dependency_check.py",
|
|
@@ -280,11 +272,15 @@
|
|
|
280
272
|
},
|
|
281
273
|
{
|
|
282
274
|
"path": "payload/mac/install/render-launchd.py",
|
|
283
|
-
"sha256": "
|
|
275
|
+
"sha256": "454b8ed22c801fce9c557cfcd09928cd01caf9c37a517ece0ec424a5532b95c4"
|
|
284
276
|
},
|
|
285
277
|
{
|
|
286
278
|
"path": "payload/mac/install/uninstall-runtime.sh",
|
|
287
|
-
"sha256": "
|
|
279
|
+
"sha256": "10cd5eb9ea5424a7a71b6c92a0eba97d2d524807d49e7e0035c51ad4f1fce546"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"path": "payload/mac/install/verify-payload-manifest.py",
|
|
283
|
+
"sha256": "131788b553d88077ba7f0592579b3c702fb91a328b7cd81d596358051df1ba48"
|
|
288
284
|
},
|
|
289
285
|
{
|
|
290
286
|
"path": "payload/mac/mcp/phone_tools.py",
|
|
@@ -296,8 +292,8 @@
|
|
|
296
292
|
}
|
|
297
293
|
],
|
|
298
294
|
"package": "pairling",
|
|
299
|
-
"package_version": "0.2.
|
|
295
|
+
"package_version": "0.2.12",
|
|
300
296
|
"schema_version": 1,
|
|
301
297
|
"source_dirty": false,
|
|
302
|
-
"source_revision": "
|
|
298
|
+
"source_revision": "71ea638dd7f9fe82a505448f437113380eec83aa"
|
|
303
299
|
}
|