pairling 0.2.3 → 0.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pairling",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
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",
@@ -15,10 +15,6 @@
15
15
  "bugs": {
16
16
  "url": "https://pairling.dev/support"
17
17
  },
18
- "repository": {
19
- "type": "git",
20
- "url": "https://pairling.dev"
21
- },
22
18
  "license": "UNLICENSED",
23
19
  "author": "Pairling (https://pairling.dev)",
24
20
  "type": "module",
@@ -39,8 +35,12 @@
39
35
  "publishConfig": {
40
36
  "access": "public"
41
37
  },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/mergimg0/pairling-helper"
41
+ },
42
42
  "optionalDependencies": {
43
- "@pairling/runtime-darwin-arm64": "0.2.3",
44
- "@pairling/runtime-darwin-x64": "0.2.3"
43
+ "@pairling/runtime-darwin-arm64": "0.2.5",
44
+ "@pairling/runtime-darwin-x64": "0.2.5"
45
45
  }
46
46
  }
@@ -1 +1 @@
1
- feat/onestream-pairling-integration
1
+ HEAD
@@ -1 +1 @@
1
- 6d905a33
1
+ 2f094bd
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.2.5
@@ -165,7 +165,7 @@ def build_manifest_payload(
165
165
  },
166
166
  },
167
167
  "endpoints": {
168
- "public": ["/health", "/manifest", "/pair/start", "/pair/claim"],
168
+ "public": ["/health", "/manifest", "/pair/start", "/pair/claim", "/pair/psk-claim"],
169
169
  "authenticated": [
170
170
  "/manifest",
171
171
  "/sessions",
@@ -235,7 +235,7 @@ func (h *Handler) allowedForAnyMethod(path string, header http.Header) bool {
235
235
  }
236
236
 
237
237
  func (h *Handler) requestBodyLimit(method, path string) int64 {
238
- if method == http.MethodPost && path == "/pair/claim" && (h.mode == ExposureModePrePair || h.mode == ExposureModePairlingConnect) {
238
+ if method == http.MethodPost && isPrePairClaimPath(path) && (h.mode == ExposureModePrePair || h.mode == ExposureModePairlingConnect) {
239
239
  if h.maxBodyBytes <= 0 || prePairMaxBodyBytes < h.maxBodyBytes {
240
240
  return prePairMaxBodyBytes
241
241
  }
@@ -259,7 +259,7 @@ func (h *Handler) requestBodyLimit(method, path string) int64 {
259
259
  }
260
260
 
261
261
  func (h *Handler) rateLimitPath(method, path string) bool {
262
- return method == http.MethodPost && path == "/pair/claim" && (h.mode == ExposureModePrePair || h.mode == ExposureModePairlingConnect)
262
+ return method == http.MethodPost && isPrePairClaimPath(path) && (h.mode == ExposureModePrePair || h.mode == ExposureModePairlingConnect)
263
263
  }
264
264
 
265
265
  func prePairAllowed(method, path string) bool {
@@ -273,6 +273,10 @@ func prePairAllowed(method, path string) bool {
273
273
  }
274
274
  }
275
275
 
276
+ func isPrePairClaimPath(path string) bool {
277
+ return path == "/pair/claim" || path == "/pair/psk-claim"
278
+ }
279
+
276
280
  func hasBearer(header http.Header) bool {
277
281
  return strings.HasPrefix(header.Get("Authorization"), "Bearer ")
278
282
  }
@@ -491,6 +495,7 @@ var postPaths = map[string]bool{
491
495
  "/open": true,
492
496
  "/orchestrations": true,
493
497
  "/pair/claim": true,
498
+ "/pair/psk-claim": true,
494
499
  "/pair/revoke": true,
495
500
  "/pair/rotate-token": true,
496
501
  "/pair/start": true,
@@ -524,11 +529,13 @@ var prePairGetPaths = map[string]bool{
524
529
  "/health": true,
525
530
  "/healthz": true,
526
531
  "/readyz": true,
532
+ "/routez": true,
527
533
  "/manifest": true,
528
534
  }
529
535
 
530
536
  var prePairPostPaths = map[string]bool{
531
- "/pair/claim": true,
537
+ "/pair/claim": true,
538
+ "/pair/psk-claim": true,
532
539
  }
533
540
 
534
541
  type MemoryRateLimiter struct {
@@ -308,7 +308,7 @@ func TestNewHandlerAcceptsLoopbackUpstream(t *testing.T) {
308
308
  }
309
309
  }
310
310
 
311
- func TestPrePairModeOnlyAllowsHealthManifestAndClaim(t *testing.T) {
311
+ func TestPrePairModeOnlyAllowsHealthManifestRoutezAndClaims(t *testing.T) {
312
312
  var forwarded []string
313
313
  upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
314
314
  forwarded = append(forwarded, r.Method+" "+r.URL.Path)
@@ -324,8 +324,10 @@ func TestPrePairModeOnlyAllowsHealthManifestAndClaim(t *testing.T) {
324
324
  }{
325
325
  {http.MethodGet, "/health"},
326
326
  {http.MethodGet, "/healthz"},
327
+ {http.MethodGet, "/routez"},
327
328
  {http.MethodGet, "/manifest"},
328
329
  {http.MethodPost, "/pair/claim"},
330
+ {http.MethodPost, "/pair/psk-claim"},
329
331
  }
330
332
  for _, tc := range allowed {
331
333
  t.Run("allows "+tc.method+" "+tc.path, func(t *testing.T) {
@@ -407,7 +409,13 @@ func TestPairlingConnectModeRequiresBearerForPostPairEndpointsAndRejectsRemotePa
407
409
  t.Fatalf("pre-pair claim status = %d body = %s", rec.Code, rec.Body.String())
408
410
  }
409
411
 
410
- if fmt.Sprintf("%+v", forwarded) != "[POST /send-text POST /pair/claim]" {
412
+ rec = httptest.NewRecorder()
413
+ handler.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "http://pairling-connect.local/pair/psk-claim", strings.NewReader(`{}`)))
414
+ if rec.Code != http.StatusOK {
415
+ t.Fatalf("pre-pair PSK claim status = %d body = %s", rec.Code, rec.Body.String())
416
+ }
417
+
418
+ if fmt.Sprintf("%+v", forwarded) != "[POST /send-text POST /pair/claim POST /pair/psk-claim]" {
411
419
  t.Fatalf("forwarded = %+v", forwarded)
412
420
  }
413
421
  }
@@ -442,44 +450,48 @@ func TestPairlingConnectModeMatchesEndpointContract(t *testing.T) {
442
450
  }
443
451
  }
444
452
 
445
- func TestPrePairClaimIsRateLimitedAndBodyLimited(t *testing.T) {
446
- var upstreamCalls int
447
- upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
448
- upstreamCalls++
449
- w.WriteHeader(http.StatusOK)
450
- }))
451
- defer upstream.Close()
452
- limiter := NewMemoryRateLimiter(1, time.Minute)
453
- handler := newTestHandlerWithMode(t, upstream.URL, defaultMaxBodyBytes, nil, ExposureModePrePair, limiter)
454
-
455
- req := httptest.NewRequest(http.MethodPost, "http://pairling-connect.local/pair/claim", strings.NewReader(`{}`))
456
- req.RemoteAddr = "100.64.0.8:12345"
457
- rec := httptest.NewRecorder()
458
- handler.ServeHTTP(rec, req)
459
- if rec.Code != http.StatusOK {
460
- t.Fatalf("first claim status = %d body = %s", rec.Code, rec.Body.String())
461
- }
453
+ func TestPrePairClaimsAreRateLimitedAndBodyLimited(t *testing.T) {
454
+ for _, path := range []string{"/pair/claim", "/pair/psk-claim"} {
455
+ t.Run(path, func(t *testing.T) {
456
+ var upstreamCalls int
457
+ upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
458
+ upstreamCalls++
459
+ w.WriteHeader(http.StatusOK)
460
+ }))
461
+ defer upstream.Close()
462
+ limiter := NewMemoryRateLimiter(1, time.Minute)
463
+ handler := newTestHandlerWithMode(t, upstream.URL, defaultMaxBodyBytes, nil, ExposureModePrePair, limiter)
464
+
465
+ req := httptest.NewRequest(http.MethodPost, "http://pairling-connect.local"+path, strings.NewReader(`{}`))
466
+ req.RemoteAddr = "100.64.0.8:12345"
467
+ rec := httptest.NewRecorder()
468
+ handler.ServeHTTP(rec, req)
469
+ if rec.Code != http.StatusOK {
470
+ t.Fatalf("first claim status = %d body = %s", rec.Code, rec.Body.String())
471
+ }
462
472
 
463
- req = httptest.NewRequest(http.MethodPost, "http://pairling-connect.local/pair/claim", strings.NewReader(`{}`))
464
- req.RemoteAddr = "100.64.0.8:12345"
465
- rec = httptest.NewRecorder()
466
- handler.ServeHTTP(rec, req)
467
- if rec.Code != http.StatusTooManyRequests {
468
- t.Fatalf("second claim status = %d body = %s", rec.Code, rec.Body.String())
469
- }
473
+ req = httptest.NewRequest(http.MethodPost, "http://pairling-connect.local"+path, strings.NewReader(`{}`))
474
+ req.RemoteAddr = "100.64.0.8:12345"
475
+ rec = httptest.NewRecorder()
476
+ handler.ServeHTTP(rec, req)
477
+ if rec.Code != http.StatusTooManyRequests {
478
+ t.Fatalf("second claim status = %d body = %s", rec.Code, rec.Body.String())
479
+ }
470
480
 
471
- largeBody := strings.NewReader(strings.Repeat("x", int(prePairMaxBodyBytes)+1))
472
- req = httptest.NewRequest(http.MethodPost, "http://pairling-connect.local/pair/claim", largeBody)
473
- req.RemoteAddr = "100.64.0.9:12345"
474
- req.ContentLength = prePairMaxBodyBytes + 1
475
- rec = httptest.NewRecorder()
476
- handler.ServeHTTP(rec, req)
477
- if rec.Code != http.StatusRequestEntityTooLarge {
478
- t.Fatalf("large claim status = %d body = %s", rec.Code, rec.Body.String())
479
- }
481
+ largeBody := strings.NewReader(strings.Repeat("x", int(prePairMaxBodyBytes)+1))
482
+ req = httptest.NewRequest(http.MethodPost, "http://pairling-connect.local"+path, largeBody)
483
+ req.RemoteAddr = "100.64.0.9:12345"
484
+ req.ContentLength = prePairMaxBodyBytes + 1
485
+ rec = httptest.NewRecorder()
486
+ handler.ServeHTTP(rec, req)
487
+ if rec.Code != http.StatusRequestEntityTooLarge {
488
+ t.Fatalf("large claim status = %d body = %s", rec.Code, rec.Body.String())
489
+ }
480
490
 
481
- if upstreamCalls != 1 {
482
- t.Fatalf("upstream calls = %d, want 1", upstreamCalls)
491
+ if upstreamCalls != 1 {
492
+ t.Fatalf("upstream calls = %d, want 1", upstreamCalls)
493
+ }
494
+ })
483
495
  }
484
496
  }
485
497
 
@@ -747,7 +747,20 @@ ptybroker_live_session_count() {
747
747
  import json
748
748
  import sys
749
749
 
750
- payload = json.loads(sys.argv[1])
750
+ def load_json_arg(raw):
751
+ text = str(raw or "").strip()
752
+ decoder = json.JSONDecoder()
753
+ for index, char in enumerate(text):
754
+ if char not in "{[":
755
+ continue
756
+ try:
757
+ value, _ = decoder.raw_decode(text[index:])
758
+ return value
759
+ except json.JSONDecodeError:
760
+ continue
761
+ return {}
762
+
763
+ payload = load_json_arg(sys.argv[1])
751
764
  status = payload.get("status") if isinstance(payload.get("status"), dict) else {}
752
765
  print(status.get("live_session_count", "unknown"))
753
766
  PY
@@ -799,7 +812,20 @@ ptybroker_live_revision() {
799
812
  import json
800
813
  import sys
801
814
 
802
- payload = json.loads(sys.argv[1])
815
+ def load_json_arg(raw):
816
+ text = str(raw or "").strip()
817
+ decoder = json.JSONDecoder()
818
+ for index, char in enumerate(text):
819
+ if char not in "{[":
820
+ continue
821
+ try:
822
+ value, _ = decoder.raw_decode(text[index:])
823
+ return value
824
+ except json.JSONDecodeError:
825
+ continue
826
+ return {}
827
+
828
+ payload = load_json_arg(sys.argv[1])
803
829
  status = payload.get("status") if isinstance(payload.get("status"), dict) else payload
804
830
  print(status.get("source_revision") or "")
805
831
  PY
@@ -813,7 +839,20 @@ import sys
813
839
  from pathlib import Path
814
840
 
815
841
  current = Path(sys.argv[1])
816
- payload = json.loads(sys.argv[2])
842
+ def load_json_arg(raw):
843
+ text = str(raw or "").strip()
844
+ decoder = json.JSONDecoder()
845
+ for index, char in enumerate(text):
846
+ if char not in "{[":
847
+ continue
848
+ try:
849
+ value, _ = decoder.raw_decode(text[index:])
850
+ return value
851
+ except json.JSONDecodeError:
852
+ continue
853
+ return {}
854
+
855
+ payload = load_json_arg(sys.argv[2])
817
856
  live = payload.get("status") if isinstance(payload.get("status"), dict) else payload
818
857
 
819
858
  def read_revision(root: Path):
@@ -881,7 +920,20 @@ ptybroker_report_deferred_restart() {
881
920
  import json
882
921
  import sys
883
922
 
884
- state = json.loads(sys.argv[1])
923
+ def load_json_arg(raw):
924
+ text = str(raw or "").strip()
925
+ decoder = json.JSONDecoder()
926
+ for index, char in enumerate(text):
927
+ if char not in "{[":
928
+ continue
929
+ try:
930
+ value, _ = decoder.raw_decode(text[index:])
931
+ return value
932
+ except json.JSONDecodeError:
933
+ continue
934
+ return {}
935
+
936
+ state = load_json_arg(sys.argv[1])
885
937
  if state.get("state") != "stale_deferred":
886
938
  raise SystemExit(0)
887
939
  live = state.get("live") if isinstance(state.get("live"), dict) else {}
@@ -902,7 +954,20 @@ ptybroker_state_field() {
902
954
  import json
903
955
  import sys
904
956
 
905
- payload = json.loads(sys.argv[1])
957
+ def load_json_arg(raw):
958
+ text = str(raw or "").strip()
959
+ decoder = json.JSONDecoder()
960
+ for index, char in enumerate(text):
961
+ if char not in "{[":
962
+ continue
963
+ try:
964
+ value, _ = decoder.raw_decode(text[index:])
965
+ return value
966
+ except json.JSONDecodeError:
967
+ continue
968
+ return {}
969
+
970
+ payload = load_json_arg(sys.argv[1])
906
971
  value = payload
907
972
  for part in sys.argv[2].split("."):
908
973
  if isinstance(value, dict):
@@ -1089,7 +1154,7 @@ install_runtime() {
1089
1154
  log "Installed Pairling runtime $RELEASE_NAME"
1090
1155
  if ! is_dry_run; then
1091
1156
  log ""
1092
- if ! pair_runtime --qr; then
1157
+ if ! PAIRLING_CONNECTD_ROUTE_WAIT_SECONDS="${PAIRLING_CONNECTD_ROUTE_WAIT_SECONDS:-35}" pair_runtime --qr; then
1093
1158
  log "Pairling installed, but setup could not generate a pairing invitation. Run: pairling doctor --json; pairling pair --qr" >&2
1094
1159
  exit 1
1095
1160
  fi
@@ -1151,10 +1216,12 @@ pair_runtime() {
1151
1216
  payload_file="$(mktemp)"
1152
1217
  if python3 - "$PAIRLING_RUNTIME_PORT" "$ttl" "$REPO_ROOT" >"$payload_file" <<'PY'
1153
1218
  import json
1219
+ import ipaddress
1154
1220
  import os
1155
1221
  import socket
1156
1222
  import subprocess
1157
1223
  import sys
1224
+ import time
1158
1225
  import urllib.parse
1159
1226
  import urllib.error
1160
1227
  import urllib.request
@@ -1219,6 +1286,37 @@ mac_name = str(((payload.get("pair_service") or {}).get("txt") or {}).get("mac_n
1219
1286
  # plaintext claim, so this field is the bridge that actually makes WS3 engage.
1220
1287
  mac_ake_pub = str(payload.get("mac_ake_pub") or (payload.get("claim") or {}).get("mac_ake_pub") or "")
1221
1288
 
1289
+ def is_ats_local_ipv4(value: str) -> bool:
1290
+ try:
1291
+ addr = ipaddress.ip_address(value)
1292
+ except ValueError:
1293
+ return False
1294
+ if addr.version != 4 or addr.is_loopback or addr.is_link_local:
1295
+ return False
1296
+ return (
1297
+ value.startswith("10.")
1298
+ or value.startswith("192.168.")
1299
+ or any(value.startswith(f"172.{i}.") for i in range(16, 32))
1300
+ )
1301
+
1302
+ def detected_lan_ip() -> str:
1303
+ override = os.environ.get("PAIRLING_TEST_LAN_IP")
1304
+ if override is not None:
1305
+ value = override.strip()
1306
+ return value if is_ats_local_ipv4(value) else ""
1307
+ if os.environ.get("PAIRLING_DISABLE_LAN") == "1" or os.environ.get("PAIRLING_TEST_DISABLE_LAN") == "1":
1308
+ return ""
1309
+ try:
1310
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1311
+ try:
1312
+ sock.connect(("8.8.8.8", 80))
1313
+ ip = sock.getsockname()[0]
1314
+ finally:
1315
+ sock.close()
1316
+ return ip if is_ats_local_ipv4(ip) else ""
1317
+ except Exception:
1318
+ return ""
1319
+
1222
1320
  def detected_tailnet_ip() -> str:
1223
1321
  override = os.environ.get("PAIRLING_TEST_TAILSCALE_IP")
1224
1322
  if override is not None:
@@ -1236,35 +1334,64 @@ def detected_tailnet_ip() -> str:
1236
1334
  return ip
1237
1335
  return ""
1238
1336
 
1337
+ def connectd_route_wait_seconds() -> float:
1338
+ try:
1339
+ return min(max(float(os.environ.get("PAIRLING_CONNECTD_ROUTE_WAIT_SECONDS") or "0"), 0.0), 60.0)
1340
+ except ValueError:
1341
+ return 0.0
1342
+
1343
+ def connectd_route_poll_seconds() -> float:
1344
+ try:
1345
+ return min(max(float(os.environ.get("PAIRLING_CONNECTD_ROUTE_POLL_SECONDS") or "0.5"), 0.1), 2.0)
1346
+ except ValueError:
1347
+ return 0.5
1348
+
1349
+ def status_could_be_ready_soon(status: dict) -> bool:
1350
+ if not status:
1351
+ return True
1352
+ if status.get("auth_url_present"):
1353
+ return False
1354
+ return True
1355
+
1356
+ def ready_connectd_route():
1357
+ wait_seconds = connectd_route_wait_seconds()
1358
+ poll_seconds = connectd_route_poll_seconds()
1359
+ deadline = time.monotonic() + wait_seconds
1360
+ while True:
1361
+ status = fetch_connectd_status(timeout_seconds=0.7)
1362
+ connect_routes = advertised_pairling_connect_routes(status)
1363
+ if connect_routes:
1364
+ return connect_routes[0]
1365
+ if wait_seconds <= 0 or time.monotonic() >= deadline or not status_could_be_ready_soon(status):
1366
+ return None
1367
+ time.sleep(min(poll_seconds, max(0.0, deadline - time.monotonic())))
1368
+
1239
1369
  def default_pair_route(port_number: int) -> dict:
1240
1370
  for key in ("PAIRLING_PAIR_BASE_URL", "PAIRLING_PUBLIC_BASE_URL"):
1241
1371
  value = os.environ.get(key)
1242
1372
  if value:
1243
1373
  return {"base_url": value, "source": "explicit_override", "status": "override"}
1244
- connect_routes = advertised_pairling_connect_routes(fetch_connectd_status(timeout_seconds=0.7))
1245
- if connect_routes:
1246
- route = connect_routes[0]
1374
+ # Remote-first pairing: if connectd reports a ready Pairling Connect route,
1375
+ # the QR advertises that route and the iOS app claims it through the
1376
+ # embedded pre-pair transport. LAN/Bonjour are explicit degraded fallbacks
1377
+ # when Pairling Connect is not ready.
1378
+ route = ready_connectd_route()
1379
+ if route:
1247
1380
  return {
1248
1381
  "base_url": route["base_url"],
1249
1382
  "source": route["source"],
1250
1383
  "status": route["status"],
1251
1384
  "kind": route["kind"],
1252
1385
  }
1386
+ lan_ip = detected_lan_ip()
1387
+ if lan_ip:
1388
+ return {"base_url": f"http://{lan_ip}:{port_number}", "source": "lan", "status": "fallback", "kind": "lan"}
1389
+ if os.environ.get("PAIRLING_DISABLE_BONJOUR") != "1" and os.environ.get("PAIRLING_TEST_DISABLE_BONJOUR") != "1":
1390
+ return {"base_url": f"http://{socket.gethostname()}.local:{port_number}", "source": "bonjour", "status": "fallback", "kind": "bonjour"}
1253
1391
  tailnet_ip = detected_tailnet_ip()
1254
1392
  if tailnet_ip:
1255
- return {"base_url": f"http://{tailnet_ip}:{port_number}", "source": "standalone_tailnet", "status": "fallback"}
1256
- try:
1257
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1258
- try:
1259
- sock.connect(("8.8.8.8", 80))
1260
- ip = sock.getsockname()[0]
1261
- finally:
1262
- sock.close()
1263
- if ip and not ip.startswith(("127.", "169.254.")):
1264
- return {"base_url": f"http://{ip}:{port_number}", "source": "lan", "status": "fallback"}
1265
- except Exception:
1266
- pass
1267
- return {"base_url": f"http://{socket.gethostname()}.local:{port_number}", "source": "bonjour", "status": "fallback"}
1393
+ return {"base_url": f"http://{tailnet_ip}:{port_number}", "source": "standalone_tailnet", "status": "fallback", "kind": "standalone_tailnet"}
1394
+ return {"base_url": f"http://{socket.gethostname()}.local:{port_number}", "source": "bonjour", "status": "fallback", "kind": "bonjour"}
1268
1395
 
1269
1396
  pair_route = default_pair_route(int(port))
1270
1397
  base_url = str(pair_route.get("base_url") or "")
@@ -1285,6 +1412,11 @@ if pair_id and secret:
1285
1412
  pair_params["route_status"] = "ready"
1286
1413
  pair_params["route_kind"] = str(pair_route.get("kind") or "tailnet")
1287
1414
  pair_params["route_contract"] = "pairling-runtime-v1"
1415
+ elif pair_route.get("status") == "fallback":
1416
+ pair_params["route_source"] = "local_fallback"
1417
+ pair_params["route_status"] = "degraded"
1418
+ pair_params["route_kind"] = str(pair_route.get("kind") or pair_route.get("source") or "local")
1419
+ pair_params["route_contract"] = "pairling-runtime-v1"
1288
1420
  manual = {
1289
1421
  "base_url": base_url,
1290
1422
  "pair_id": pair_id,
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "connectd": {
3
3
  "darwin-arm64": {
4
- "sha256": "4a1ec43865486a1958c11a253f9955542354da58ab81dedfc1828727ff691050",
4
+ "sha256": "96400014bc7d32bd1b976216eb6dc76a6621d9da34a2ef02da87c72957dea170",
5
5
  "team_id": "965AVD34A3"
6
6
  },
7
7
  "darwin-x64": {
8
- "sha256": "05da872d33362df876e3fbca2d527f8acd33225917a774068bd3894fe2cbec84",
8
+ "sha256": "bb4df01a72f6c2032c8d7341f5d243fa3e6c99295c033dbf3f99a7d7eed650b7",
9
9
  "team_id": "965AVD34A3"
10
10
  }
11
11
  },
12
12
  "files": [
13
13
  {
14
14
  "path": "payload/mac/SOURCE_BRANCH",
15
- "sha256": "b7cda4715ebe6bb92ec69b85df0e99668564bde99f03d6e04109b399538000b2"
15
+ "sha256": "34d6a94dacb895403529caac12a19aed745c6caca7a8d0f4ed631999044f76e8"
16
16
  },
17
17
  {
18
18
  "path": "payload/mac/SOURCE_DIRTY",
@@ -20,11 +20,11 @@
20
20
  },
21
21
  {
22
22
  "path": "payload/mac/SOURCE_REVISION",
23
- "sha256": "fbe59df8b5637ce46090bf962b4c7be19a18596f93dc3963f228836be332e593"
23
+ "sha256": "6fba526ba8b27c395d71b9d6067bb09fe9458c5d650a92af80541ad7971a3ba3"
24
24
  },
25
25
  {
26
26
  "path": "payload/mac/VERSION",
27
- "sha256": "3ab94c04d24986f3af288ba1cda2c0bbddbc5a89dff097182805f54578e1ea75"
27
+ "sha256": "e959f750e92dbb7614ae28ac96f0a37272caed81d8bbb758791af7bfbb6106a0"
28
28
  },
29
29
  {
30
30
  "path": "payload/mac/companiond/app_attest_lan.py",
@@ -152,7 +152,7 @@
152
152
  },
153
153
  {
154
154
  "path": "payload/mac/companiond/runtime_manifest.py",
155
- "sha256": "92c8c04def5e166a41926cf97de5dbb285a586f67e0f15eeef873c9f0337cb46"
155
+ "sha256": "72d61833a74e8171157784bee252f3e0f0bb15d77b740c2ffb2d82214d3b4933"
156
156
  },
157
157
  {
158
158
  "path": "payload/mac/companiond/runtime_paths.py",
@@ -212,11 +212,11 @@
212
212
  },
213
213
  {
214
214
  "path": "payload/mac/connectd/internal/gateway/proxy.go",
215
- "sha256": "ce827d08826492193b025738322ae72e3d806604968f4e7d19e3d37c78dce313"
215
+ "sha256": "5da0f96ec8c364d90a7c07e4e968df6e9bd7bfeadf6cbe25d0bb743cdba3a91a"
216
216
  },
217
217
  {
218
218
  "path": "payload/mac/connectd/internal/gateway/proxy_test.go",
219
- "sha256": "f45c74df51939f688bc3b3bb326d9fa103c2b39f81eb589b1e6be06731de9f3a"
219
+ "sha256": "1eefdfc331e97033d124cd627dd6e456f6de71e3a28b8d05aa6ede9faa3ff663"
220
220
  },
221
221
  {
222
222
  "path": "payload/mac/connectd/internal/runtime/config.go",
@@ -252,7 +252,7 @@
252
252
  },
253
253
  {
254
254
  "path": "payload/mac/install/install-runtime.sh",
255
- "sha256": "45c0295ad0f6e610c0cbf10057fd341754967ffaa5eee403ad1aaa1ea1954a5c"
255
+ "sha256": "87c1db89b281b78d0809b4360c54c5c57b8e4f25a473496373315236ffeb6117"
256
256
  },
257
257
  {
258
258
  "path": "payload/mac/install/psk_dependency_check.py",
@@ -276,8 +276,8 @@
276
276
  }
277
277
  ],
278
278
  "package": "pairling",
279
- "package_version": "0.2.3",
279
+ "package_version": "0.2.5",
280
280
  "schema_version": 1,
281
281
  "source_dirty": false,
282
- "source_revision": "6d905a33"
282
+ "source_revision": "2f094bd"
283
283
  }