pairling 0.2.7 → 0.2.9

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.
@@ -11,6 +11,11 @@ USER_PLIST="$HOME/Library/LaunchAgents/$PAIRLING_DAEMON_LABEL.plist"
11
11
  CONNECTD_USER_PLIST="$HOME/Library/LaunchAgents/$PAIRLING_CONNECTD_LABEL.plist"
12
12
  PTYBROKER_USER_PLIST="$HOME/Library/LaunchAgents/$PAIRLING_PTYBROKER_LABEL.plist"
13
13
  SYSTEM_PLIST="/Library/LaunchDaemons/$PAIRLING_GUARDIAN_LABEL.plist"
14
+ # Legacy: the silent-join mint broker, removed from the product. Torn down below.
15
+ MINTD_SYSTEM_LABEL="dev.pairling.mintd"
16
+ MINTD_SYSTEM_PLIST="/Library/LaunchDaemons/$MINTD_SYSTEM_LABEL.plist"
17
+ MINTD_SYSTEM_DIR="/Library/Application Support/Pairling/mint"
18
+ MINTD_SERVICE_ACCOUNT="_pairling_mint"
14
19
  YES="false"
15
20
  DELETE_STATE="false"
16
21
  DELETE_LOGS="false"
@@ -98,6 +103,32 @@ bootout_system() {
98
103
  fi
99
104
  }
100
105
 
106
+ # Legacy teardown: the silent-join mint broker (dev.pairling.mintd) was removed
107
+ # from the product. Machines that ran the old `enable-silent-join` still carry a
108
+ # root LaunchDaemon, a stored Tailscale OAuth secret under the system mint dir,
109
+ # and the _pairling_mint role account. Remove all three. Best-effort, sudo-gated.
110
+ teardown_legacy_mintd() {
111
+ if [[ ! -f "$MINTD_SYSTEM_PLIST" && ! -d "$MINTD_SYSTEM_DIR" ]] \
112
+ && ! id -u "$MINTD_SERVICE_ACCOUNT" >/dev/null 2>&1; then
113
+ return
114
+ fi
115
+ if is_dry_run; then
116
+ printf 'dry-run: would remove the legacy silent-join mint broker (%s, %s, user %s)\n' \
117
+ "$MINTD_SYSTEM_PLIST" "$MINTD_SYSTEM_DIR" "$MINTD_SERVICE_ACCOUNT"
118
+ return
119
+ fi
120
+ if sudo -n true >/dev/null 2>&1; then
121
+ sudo launchctl bootout "system/$MINTD_SYSTEM_LABEL" >/dev/null 2>&1 || true
122
+ sudo launchctl bootout system "$MINTD_SYSTEM_PLIST" >/dev/null 2>&1 || true
123
+ sudo rm -f "$MINTD_SYSTEM_PLIST"
124
+ sudo rm -rf "$MINTD_SYSTEM_DIR"
125
+ sudo /usr/sbin/sysadminctl -deleteUser "$MINTD_SERVICE_ACCOUNT" >/dev/null 2>&1 || true
126
+ printf 'Removed the legacy silent-join mint broker.\n'
127
+ else
128
+ printf 'Skipping legacy mint-broker removal: passwordless sudo is unavailable.\n' >&2
129
+ fi
130
+ }
131
+
101
132
  confirm
102
133
 
103
134
  bootout_user "$PAIRLING_DAEMON_LABEL" "$USER_PLIST"
@@ -107,6 +138,7 @@ rm -f "$USER_PLIST"
107
138
  rm -f "$CONNECTD_USER_PLIST"
108
139
  rm -f "$PTYBROKER_USER_PLIST"
109
140
  bootout_system "$PAIRLING_GUARDIAN_LABEL" "$SYSTEM_PLIST"
141
+ teardown_legacy_mintd
110
142
 
111
143
  rm -rf "$APP_SUPPORT/pair" 2>/dev/null || true
112
144
 
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "connectd": {
3
3
  "darwin-arm64": {
4
- "sha256": "9941dbf0462cd6140c24d3c37f3351aa6dbe093183740fd042ddaa6f44cb1c65",
4
+ "sha256": "3ee070f12619390609a8c76e0ae4803ab1bc48c9f77361b8f27a4125846f38e3",
5
5
  "team_id": "965AVD34A3"
6
6
  },
7
7
  "darwin-x64": {
8
- "sha256": "66f6f18d836e43389d6efd70b0bd59200daaf668220907a6f1bfde17983ae7fe",
8
+ "sha256": "c1ee211c3da71200d7855c9246ea04cd25fda702f7fb33a366b4d51bdaf9e230",
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": "15d265ea54cc0e8147c8f5e60a9f83297966a1f7c059888a09d97d3e5b7a6d0c"
23
+ "sha256": "29c2c816c529155cc86f26d44a8e8d79fc170fc26ade74fac3780554b5c864ff"
24
24
  },
25
25
  {
26
26
  "path": "payload/mac/VERSION",
27
- "sha256": "5b57e3b8c153d1d33b0c0f1ee29d3de1bf93232ed95aa78b80fe885e99faa915"
27
+ "sha256": "2f2b333be8858cb384114251b668bb1c9e45a0bb8393600b7ad4093d0e8e72f6"
28
28
  },
29
29
  {
30
30
  "path": "payload/mac/companiond/app_attest_lan.py",
@@ -96,7 +96,7 @@
96
96
  },
97
97
  {
98
98
  "path": "payload/mac/companiond/pairlingd.py",
99
- "sha256": "ee2a9115531a15f9cc3aff0680be3bb7ab7b42c7cf001eac05b33cbf36755842"
99
+ "sha256": "ca1c5551dd235990d4ff8d8b9c3c3f25e912ca9c22c7003f50c9fe1ccb6bf02e"
100
100
  },
101
101
  {
102
102
  "path": "payload/mac/companiond/providers/__init__.py",
@@ -200,28 +200,16 @@
200
200
  },
201
201
  {
202
202
  "path": "payload/mac/connectd/cmd/pairling-connectd/main.go",
203
- "sha256": "4582664c189db3c13fef81328172d69fa0bcd6b064396c0a811a154da98f7f21"
203
+ "sha256": "019288bd16c6e900c60206ee4739f9ae5ed640ea73cd57db6a1f0d618c9bf00c"
204
204
  },
205
205
  {
206
206
  "path": "payload/mac/connectd/cmd/pairling-connectd/peer_identity_test.go",
207
- "sha256": "044c1260387b990de073d4f09fa516c3ce15ded7c255b5e1ac3d57f3f5810c27"
207
+ "sha256": "eb1f44e588c2d70e2660f805ee6b7fe09aa793365c0ae442164785a8241c35d8"
208
208
  },
209
209
  {
210
210
  "path": "payload/mac/connectd/cmd/pairling-connectd/upstream_health_test.go",
211
211
  "sha256": "dc5b6d3a8d11f38bcc198287bdbc95f058d35792ca6cf34bc49ca0bed22bfacf"
212
212
  },
213
- {
214
- "path": "payload/mac/connectd/cmd/pairling-tailnet-mintd/main.go",
215
- "sha256": "64fd4527c97397fce10793001af8d59ac3154c75c7ed9e1b532f8f2e4bf88bd4"
216
- },
217
- {
218
- "path": "payload/mac/connectd/cmd/pairling-tailnet-mintd/mintd.go",
219
- "sha256": "ca49b8ab8216eeec770ad6e9e8111aca819a9a88b050d7eefbdf69c0fad20376"
220
- },
221
- {
222
- "path": "payload/mac/connectd/cmd/pairling-tailnet-mintd/mintd_test.go",
223
- "sha256": "14a9af6b9575ba89314ce05f2fe465844fea3bb40b3eba5e0d33d059608bfb1f"
224
- },
225
213
  {
226
214
  "path": "payload/mac/connectd/go.mod",
227
215
  "sha256": "c96748d396598b0952b4c0d43f7f85ca3a56f4019761088267421b22518d5905"
@@ -244,11 +232,11 @@
244
232
  },
245
233
  {
246
234
  "path": "payload/mac/connectd/internal/gateway/proxy.go",
247
- "sha256": "ad7de08a59819fcbdd81f62d707738af128064cc24cea576674aee2f0960c267"
235
+ "sha256": "b852408a35b71a0b62554cc93f413c3352034432f14529ab3ddbe85fa5ee49c8"
248
236
  },
249
237
  {
250
238
  "path": "payload/mac/connectd/internal/gateway/proxy_test.go",
251
- "sha256": "b02cd354dcd3292079f35ee86a1ce75e3ed8286550f064fdae7914e661464910"
239
+ "sha256": "f3a6b1974c1ccba8e5e380d18c31a5aca61458b6d4a1075865b8978e86e54209"
252
240
  },
253
241
  {
254
242
  "path": "payload/mac/connectd/internal/runtime/config.go",
@@ -284,7 +272,7 @@
284
272
  },
285
273
  {
286
274
  "path": "payload/mac/install/install-runtime.sh",
287
- "sha256": "152eed164fd4edfd42874f20e8476d8e42415d5e93e090b716fef2ea7ed6424e"
275
+ "sha256": "40ffa67a3833ce4342c241ca4f1e7dec471a86b0c80359746cd75a8df2e33f60"
288
276
  },
289
277
  {
290
278
  "path": "payload/mac/install/psk_dependency_check.py",
@@ -292,11 +280,11 @@
292
280
  },
293
281
  {
294
282
  "path": "payload/mac/install/render-launchd.py",
295
- "sha256": "5c4c06b578e24726731650ff39d688248ba1bd412b9e21fc368b13d07e8ee0df"
283
+ "sha256": "29db1aa46d62cd23ba27ab283bb990d168bfc08fb82cfc681046dc7b887d85fe"
296
284
  },
297
285
  {
298
286
  "path": "payload/mac/install/uninstall-runtime.sh",
299
- "sha256": "8af7b3bb4de4b053888fe44a9fdb576144d6cb154bafc9b3d02edac90a7055ec"
287
+ "sha256": "0edeb5336a71c235d8796a8e59072c6d8983d196de5aae0cfcb4b0c3560fa33f"
300
288
  },
301
289
  {
302
290
  "path": "payload/mac/mcp/phone_tools.py",
@@ -307,19 +295,9 @@
307
295
  "sha256": "5ebcd63fc53114ace518807c2221e562e65237e57945a76c457f5931a5791cc1"
308
296
  }
309
297
  ],
310
- "mintd": {
311
- "darwin-arm64": {
312
- "sha256": "326d1d42a0b40bdb60687f7b7d190c12c520106e47542054b1b807d397e41fe9",
313
- "team_id": "965AVD34A3"
314
- },
315
- "darwin-x64": {
316
- "sha256": "477cf4d9b88f1e8303e5545eb3c03460e0c75b284f9d628641cb80e2be14af38",
317
- "team_id": "965AVD34A3"
318
- }
319
- },
320
298
  "package": "pairling",
321
- "package_version": "0.2.7",
299
+ "package_version": "0.2.9",
322
300
  "schema_version": 1,
323
301
  "source_dirty": false,
324
- "source_revision": "102b7cf"
302
+ "source_revision": "c97bbab"
325
303
  }
@@ -1,121 +0,0 @@
1
- package main
2
-
3
- import (
4
- "context"
5
- "encoding/json"
6
- "errors"
7
- "flag"
8
- "fmt"
9
- "log"
10
- "net/http"
11
- "os"
12
- "os/exec"
13
- "os/signal"
14
- "strconv"
15
- "strings"
16
- "syscall"
17
- "time"
18
- )
19
-
20
- func main() {
21
- var (
22
- secretPath = flag.String("secret-path", "/Library/Application Support/Pairling/mint/client_secret.json", "OAuth client credential JSON")
23
- socketPath = flag.String("socket-path", "/Library/Application Support/Pairling/run/mintd/mintd.sock", "Unix socket path")
24
- statePath = flag.String("state-path", "/Library/Application Support/Pairling/mint/state.json", "persistent rate-limit state JSON")
25
- auditPath = flag.String("audit-path", "/Library/Application Support/Pairling/mint/audit.jsonl", "audit JSONL path")
26
- alertPath = flag.String("alert-path", "/Library/Application Support/Pairling/run/mintd/alerts.jsonl", "health-readable alert JSONL path")
27
- apiBaseURL = flag.String("api-base-url", "https://api.tailscale.com/api/v2", "Tailscale API base URL")
28
- oauthURL = flag.String("oauth-url", "https://api.tailscale.com/api/v2/oauth/token", "Tailscale OAuth token URL")
29
- authorizedUID = flag.Int("authorized-uid", -1, "only this peer uid may request mints")
30
- )
31
- flag.Parse()
32
-
33
- b, err := NewBroker(BrokerConfig{
34
- SecretPath: *secretPath,
35
- StatePath: *statePath,
36
- AuditPath: *auditPath,
37
- AlertPath: *alertPath,
38
- OAuthURL: *oauthURL,
39
- APIBaseURL: *apiBaseURL,
40
- LockStatus: defaultLockStatus,
41
- })
42
- if err != nil {
43
- log.Fatal(err)
44
- }
45
- ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
46
- defer stop()
47
- if err := b.ServeUnix(ctx, *socketPath, *authorizedUID); err != nil {
48
- log.Fatal(err)
49
- }
50
- }
51
-
52
- func defaultLockStatus(ctx context.Context) (bool, error) {
53
- if locked, err := lockStatusFromConnectdStatus(ctx, "http://127.0.0.1:7774/status"); err == nil {
54
- return locked, nil
55
- }
56
- return lockStatusFromCandidates(ctx, []string{
57
- "/opt/homebrew/bin/tailscale",
58
- "/Applications/Tailscale.app/Contents/MacOS/Tailscale",
59
- "tailscale",
60
- })
61
- }
62
-
63
- func lockStatusFromConnectdStatus(ctx context.Context, statusURL string) (bool, error) {
64
- req, err := http.NewRequestWithContext(ctx, http.MethodGet, statusURL, nil)
65
- if err != nil {
66
- return false, err
67
- }
68
- resp, err := (&http.Client{Timeout: 2 * time.Second}).Do(req)
69
- if err != nil {
70
- return false, err
71
- }
72
- defer resp.Body.Close()
73
- if resp.StatusCode != http.StatusOK {
74
- return false, fmt.Errorf("connectd status returned %s", resp.Status)
75
- }
76
- var body struct {
77
- TailnetLockEnabled *bool `json:"tailnet_lock_enabled"`
78
- }
79
- if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
80
- return false, err
81
- }
82
- if body.TailnetLockEnabled == nil {
83
- return false, errors.New("connectd status omitted tailnet_lock_enabled")
84
- }
85
- return *body.TailnetLockEnabled, nil
86
- }
87
-
88
- func lockStatusFromCandidates(ctx context.Context, candidates []string) (bool, error) {
89
- var errs []error
90
- for _, bin := range candidates {
91
- out, err := exec.CommandContext(ctx, bin, "lock", "status").CombinedOutput()
92
- if err != nil {
93
- errs = append(errs, fmt.Errorf("%s: %w", bin, err))
94
- continue
95
- }
96
- text := strings.ToLower(string(out))
97
- if strings.Contains(text, "tailscale gui failed to start") {
98
- errs = append(errs, fmt.Errorf("%s: gui unavailable", bin))
99
- continue
100
- }
101
- if strings.Contains(text, "not enabled") || strings.Contains(text, "disabled") {
102
- return false, nil
103
- }
104
- if strings.Contains(text, "enabled") {
105
- return true, nil
106
- }
107
- return false, fmt.Errorf("unrecognized tailscale lock status: %q", strings.TrimSpace(string(out)))
108
- }
109
- return false, errors.New("tailscale lock status unavailable: " + joinErrors(errs))
110
- }
111
-
112
- func joinErrors(errs []error) string {
113
- parts := make([]string, 0, len(errs))
114
- for _, err := range errs {
115
- parts = append(parts, err.Error())
116
- }
117
- if len(parts) == 0 {
118
- return "no candidates"
119
- }
120
- return strconv.Quote(strings.Join(parts, "; "))
121
- }