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
package/README.md
CHANGED
|
@@ -27,11 +27,9 @@ Then open Pairling on your iPhone and scan the QR code that `setup` prints.
|
|
|
27
27
|
- Stages the runtime under `~/Library/Application Support/Pairling/runtime/`
|
|
28
28
|
(versioned releases, atomic `current` symlink flip, `pairling rollback`).
|
|
29
29
|
- Installs user-domain LaunchAgents (`dev.pairling.companiond`,
|
|
30
|
-
`dev.pairling.connectd`). No root
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
the Developer ID signature of the bundled `pairling-connectd` binary before
|
|
34
|
-
staging — fail closed.
|
|
30
|
+
`dev.pairling.connectd`, `dev.pairling.ptybroker`). No root helper is installed.
|
|
31
|
+
- Verifies the package payload manifest and the Developer ID signature of the
|
|
32
|
+
bundled `pairling-connectd` binary before staging — fail closed.
|
|
35
33
|
|
|
36
34
|
## Commands
|
|
37
35
|
|
|
@@ -54,8 +52,9 @@ pairling uninstall [--yes]
|
|
|
54
52
|
- **Readable payload:** the runtime is Python/bash source plus one signed Go
|
|
55
53
|
binary (`pairling-connectd`); inspect it with `npm pack pairling --dry-run`.
|
|
56
54
|
- **Integrity chain:** CI records SHA-256 of every payload file in
|
|
57
|
-
`payload-manifest.json`; `pairling setup`
|
|
58
|
-
`pairling doctor` re-verifies the staged
|
|
55
|
+
`payload-manifest.json`; `pairling setup` verifies that manifest and the
|
|
56
|
+
binary signature before staging; `pairling doctor` re-verifies the staged
|
|
57
|
+
runtime and the binary signature.
|
|
59
58
|
- **Local-first:** the daemon serves your devices with per-device scoped bearer
|
|
60
59
|
tokens. npm being down can never affect an installed Mac.
|
|
61
60
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pairling",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "Pair your iPhone with the AI coding agents running on your Mac. CLI and local runtime installer for the Pairling iOS app.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pairling",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"url": "https://github.com/mergimg0/pairling-helper"
|
|
41
41
|
},
|
|
42
42
|
"optionalDependencies": {
|
|
43
|
-
"@pairling/runtime-darwin-arm64": "0.2.
|
|
44
|
-
"@pairling/runtime-darwin-x64": "0.2.
|
|
43
|
+
"@pairling/runtime-darwin-arm64": "0.2.12",
|
|
44
|
+
"@pairling/runtime-darwin-x64": "0.2.12"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
71ea638dd7f9fe82a505448f437113380eec83aa
|
package/payload/mac/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.2.
|
|
1
|
+
0.2.12
|
|
@@ -358,6 +358,7 @@ class PairingStore:
|
|
|
358
358
|
relay_device_id: str | None = None,
|
|
359
359
|
relay_required: bool = False,
|
|
360
360
|
relay_claim_verifier=None,
|
|
361
|
+
require_direct_attest: bool = False,
|
|
361
362
|
) -> PairClaim:
|
|
362
363
|
with self._claim_lock:
|
|
363
364
|
record, path, now = self._precheck_claim(pair_id)
|
|
@@ -384,6 +385,7 @@ class PairingStore:
|
|
|
384
385
|
attested_claim_ticket=attested_claim_ticket,
|
|
385
386
|
relay_device_id=relay_device_id, relay_required=relay_required,
|
|
386
387
|
relay_claim_verifier=relay_claim_verifier,
|
|
388
|
+
require_direct_attest=require_direct_attest,
|
|
387
389
|
)
|
|
388
390
|
|
|
389
391
|
def _precheck_claim(self, pair_id: str) -> tuple[dict, Path, float]:
|
|
@@ -460,6 +462,7 @@ class PairingStore:
|
|
|
460
462
|
relay_required: bool,
|
|
461
463
|
relay_claim_verifier,
|
|
462
464
|
funnel_origin: bool = False,
|
|
465
|
+
require_direct_attest: bool = False,
|
|
463
466
|
attestation_verified: bool | None = None,
|
|
464
467
|
) -> PairClaim:
|
|
465
468
|
"""Post-authentication finalize, shared by legacy and PSK claims. The
|
|
@@ -475,7 +478,8 @@ class PairingStore:
|
|
|
475
478
|
attestation_verified = self._verify_claim_attestation(
|
|
476
479
|
pair_id=pair_id, record=record, attest_object=attest_object,
|
|
477
480
|
attest_key_id=attest_key_id, attest_environment=attest_environment,
|
|
478
|
-
require=funnel_origin
|
|
481
|
+
require=funnel_origin or require_direct_attest,
|
|
482
|
+
force_production=funnel_origin or require_direct_attest,
|
|
479
483
|
)
|
|
480
484
|
relay_status = "none"
|
|
481
485
|
verified_relay_device_id = relay_device_id
|
|
@@ -569,6 +573,7 @@ class PairingStore:
|
|
|
569
573
|
relay_required: bool = False,
|
|
570
574
|
relay_claim_verifier=None,
|
|
571
575
|
funnel_origin: bool = False,
|
|
576
|
+
require_direct_attest: bool = False,
|
|
572
577
|
) -> tuple[PairClaim, bytes, bytes, bytes]:
|
|
573
578
|
"""WS3 PSK-authenticated ECDH claim. The secret is NEVER received; the
|
|
574
579
|
caller proves knowledge of it by completing the authenticated key
|
|
@@ -584,14 +589,14 @@ class PairingStore:
|
|
|
584
589
|
raise PairingError("psk_bad_key", 400, "invalid psk material")
|
|
585
590
|
with self._claim_lock:
|
|
586
591
|
attestation_verified = None
|
|
587
|
-
if funnel_origin:
|
|
588
|
-
#
|
|
592
|
+
if funnel_origin or require_direct_attest:
|
|
593
|
+
# Public network claims prove a genuine device BEFORE the attempt counter
|
|
589
594
|
# and the ECDH derive, so an un-attested spray cannot lock out a
|
|
590
|
-
# live invitation or force crypto work. Fail
|
|
595
|
+
# live invitation or force crypto work. Fail closed regardless of
|
|
591
596
|
# the env default, with the environment pinned to production.
|
|
592
|
-
|
|
597
|
+
hard_attest_record, _ = self._load_record(pair_id)
|
|
593
598
|
attestation_verified = self._verify_claim_attestation(
|
|
594
|
-
pair_id=pair_id, record=
|
|
599
|
+
pair_id=pair_id, record=hard_attest_record, attest_object=attest_object,
|
|
595
600
|
attest_key_id=attest_key_id, attest_environment=attest_environment,
|
|
596
601
|
require=True, force_production=True,
|
|
597
602
|
)
|
|
@@ -624,7 +629,8 @@ class PairingStore:
|
|
|
624
629
|
attested_claim_ticket=attested_claim_ticket,
|
|
625
630
|
relay_device_id=relay_device_id, relay_required=relay_required,
|
|
626
631
|
relay_claim_verifier=relay_claim_verifier,
|
|
627
|
-
funnel_origin=funnel_origin,
|
|
632
|
+
funnel_origin=funnel_origin, require_direct_attest=require_direct_attest,
|
|
633
|
+
attestation_verified=attestation_verified,
|
|
628
634
|
)
|
|
629
635
|
aad = _psk.transcript(pair_id, a_pub, b_pub)
|
|
630
636
|
mac_confirm = _psk.confirm_tag(k_confirm, _psk.CONFIRM_MAC, pair_id, a_pub, b_pub)
|