@puddle-code/cli 0.2.6 → 0.2.8

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +14 -6
  2. package/README.md +1 -1
  3. package/dist/host-control.mjs +69 -63
  4. package/dist/index.js +139 -84
  5. package/dist/install.sh +1 -1
  6. package/dist/public/assets/{App-CzuHShdO.js → App-BaLJ09-7.js} +2 -2
  7. package/dist/public/assets/{Dashboard-B5qWtmwb.js → Dashboard-CwqPhujx.js} +1 -1
  8. package/dist/public/assets/{EditorTabClose-uxuNJdgx.js → EditorTabClose-BehvYDm8.js} +1 -1
  9. package/dist/public/assets/{FindWidget-lUpiYZJG.js → FindWidget-DkM5Ny1L.js} +1 -1
  10. package/dist/public/assets/{LazyTerminal-BYbPpGEI.js → LazyTerminal-Bx3CSbUu.js} +2 -2
  11. package/dist/public/assets/{ModelRefcount-N0Xh_Y-_.js → ModelRefcount-j0XFKXWi.js} +1 -1
  12. package/dist/public/assets/{NewProjectDialog-D3bNK3u_.js → NewProjectDialog-CHiC5YY7.js} +1 -1
  13. package/dist/public/assets/{PaneEditorBody-DrSiMzrp.js → PaneEditorBody-7n20zvBp.js} +4 -4
  14. package/dist/public/assets/{PdfViewer-BhqrWfmb.js → PdfViewer-CKfdMGYh.js} +2 -2
  15. package/dist/public/assets/SettingsDialog-JzSTfA7-.js +8 -0
  16. package/dist/public/assets/{Terminal-Ds17sCF_.js → Terminal-CW_yt4oG.js} +1 -1
  17. package/dist/public/assets/{Workspace-BmtA0kYQ.js → Workspace-BsOrODmq.js} +6 -6
  18. package/dist/public/assets/{abnfDiagram-VCTEODGH-B4ZtDUXi.js → abnfDiagram-VCTEODGH-DuBNM1iE.js} +1 -1
  19. package/dist/public/assets/architecture-7GRP2DOG-251niO5u.js +1 -0
  20. package/dist/public/assets/{architectureDiagram-5GKGNRK7-Cyzuyzwl.js → architectureDiagram-5GKGNRK7-BUgo1lsN.js} +1 -1
  21. package/dist/public/assets/{blockDiagram-I7D4REHJ-BN00JnNl.js → blockDiagram-I7D4REHJ-UglX2bO7.js} +1 -1
  22. package/dist/public/assets/{buffer-store--4yU4YqM.js → buffer-store-B_VB-G9G.js} +2 -2
  23. package/dist/public/assets/{button-DehrlYw7.js → button-DlsZoHS1.js} +1 -1
  24. package/dist/public/assets/{c4Diagram-7LVT6UL2-DpUKodBy.js → c4Diagram-7LVT6UL2-DVhqTsmi.js} +1 -1
  25. package/dist/public/assets/channel-C5HOkF8K.js +1 -0
  26. package/dist/public/assets/{chunk-2E4U76K2-BksaqXZU.js → chunk-2E4U76K2-Biysymfb.js} +1 -1
  27. package/dist/public/assets/{chunk-4HAMMTFA-D01k6w0A.js → chunk-4HAMMTFA-CnjG-TUf.js} +1 -1
  28. package/dist/public/assets/{chunk-75Z2AOVW-DJJjslyX.js → chunk-75Z2AOVW-BN5baFb9.js} +1 -1
  29. package/dist/public/assets/{chunk-CLGD4ZFX-CX1B9i6H.js → chunk-CLGD4ZFX-B0g6JIcT.js} +1 -1
  30. package/dist/public/assets/{chunk-DU6HZSFF-Bx2ELCn-.js → chunk-DU6HZSFF-CSc2zx2A.js} +1 -1
  31. package/dist/public/assets/{chunk-F27PBJKO-CCDhODx8.js → chunk-F27PBJKO-CgQY5NLL.js} +1 -1
  32. package/dist/public/assets/{chunk-GMAD6QVW-C1evXXZi.js → chunk-GMAD6QVW-RUJueMkM.js} +1 -1
  33. package/dist/public/assets/{chunk-GVQU2GXP-C1iphgLK.js → chunk-GVQU2GXP-fh3FldQM.js} +1 -1
  34. package/dist/public/assets/{chunk-IMKFNOWR-5wMdkmsQ.js → chunk-IMKFNOWR-C5sPh7tK.js} +1 -1
  35. package/dist/public/assets/{chunk-L3NEJ4N5-B-aXfMpF.js → chunk-L3NEJ4N5-BHHvLVUm.js} +1 -1
  36. package/dist/public/assets/{chunk-OSK3NFVY-Bm2MaFOc.js → chunk-OSK3NFVY-DP7Dz8Y0.js} +1 -1
  37. package/dist/public/assets/{chunk-P2QGCYS3-H02JaAun.js → chunk-P2QGCYS3-FttcQ5j3.js} +1 -1
  38. package/dist/public/assets/{chunk-POPQ4Y6H-Dmm46Beg.js → chunk-POPQ4Y6H-4ZrMU97W.js} +1 -1
  39. package/dist/public/assets/{chunk-PWAF6VOD-CRt8Ete5.js → chunk-PWAF6VOD-CihlYgFp.js} +1 -1
  40. package/dist/public/assets/{chunk-SHT3W25Y-w4aNK54y.js → chunk-SHT3W25Y-FSeRnaXx.js} +1 -1
  41. package/dist/public/assets/{chunk-SVP7TREG-Cl3QpMDs.js → chunk-SVP7TREG-Ce-GbVWs.js} +1 -1
  42. package/dist/public/assets/{chunk-TICWLB2K-BpBbot9h.js → chunk-TICWLB2K-BwNaY0SH.js} +1 -1
  43. package/dist/public/assets/{chunk-TLUHSLCS-BOnIB6P6.js → chunk-TLUHSLCS-2qFV5yh_.js} +2 -2
  44. package/dist/public/assets/classDiagram-ZZMXUADV-J1XY4rHw.js +1 -0
  45. package/dist/public/assets/classDiagram-v2-VYDZK3BY-J1XY4rHw.js +1 -0
  46. package/dist/public/assets/{context-menu-BT88Vgia.js → context-menu-DYqp9bEv.js} +1 -1
  47. package/dist/public/assets/{cssMode-gXT_K4po.js → cssMode-CuTRdTZz.js} +1 -1
  48. package/dist/public/assets/{cynefin-OW5HDTMX-CJakxaH8.js → cynefin-OW5HDTMX-Bw6TsxW9.js} +1 -1
  49. package/dist/public/assets/{cynefinDiagram-5FMLGOSQ-BJ_fVnC9.js → cynefinDiagram-5FMLGOSQ-BIzNmjbq.js} +1 -1
  50. package/dist/public/assets/{dagre-GXQ25YYZ-CjflcbuS.js → dagre-GXQ25YYZ-CDytXLeT.js} +1 -1
  51. package/dist/public/assets/{diagram-S7CK7UJ4-g8pKIWrY.js → diagram-S7CK7UJ4-BpamWl9l.js} +1 -1
  52. package/dist/public/assets/{diagram-UQ7AKVKN-Dm5Pg4rY.js → diagram-UQ7AKVKN-DmgJ3-ND.js} +1 -1
  53. package/dist/public/assets/{diagram-VSXAHHWV-DV5CVAXg.js → diagram-VSXAHHWV-DQZdmIeV.js} +1 -1
  54. package/dist/public/assets/{diagram-VX7I27RA-Be9qCk-h.js → diagram-VX7I27RA-BOjHM12U.js} +1 -1
  55. package/dist/public/assets/{diagram-Z3DM3KII-C3-xDrxs.js → diagram-Z3DM3KII-BC_nO99d.js} +1 -1
  56. package/dist/public/assets/{dialog-CAMTxigV.js → dialog-H68qUfAD.js} +1 -1
  57. package/dist/public/assets/{disclosure-DvM7-z38.js → disclosure-wU8K_sQR.js} +1 -1
  58. package/dist/public/assets/{dist-3tmIo7Ja.js → dist-C5QSPxzH.js} +1 -1
  59. package/dist/public/assets/{dist-sLs_LTiG.js → dist-CgttzJIK.js} +1 -1
  60. package/dist/public/assets/{ebnfDiagram-PWID7BFC-Bq92n7k-.js → ebnfDiagram-PWID7BFC-C9UK3bZX.js} +1 -1
  61. package/dist/public/assets/{erDiagram-RLTQ6QDP-C5I2bKnS.js → erDiagram-RLTQ6QDP-CXHYIxbP.js} +1 -1
  62. package/dist/public/assets/eventmodeling-NTZA5JFV-C0XlUlJv.js +1 -0
  63. package/dist/public/assets/flowDiagram-HODETNUW-DuvssVqU.js +1 -0
  64. package/dist/public/assets/{ganttDiagram-EL5Y4UJY-qUaBgbbK.js → ganttDiagram-EL5Y4UJY-CtDwXmwE.js} +1 -1
  65. package/dist/public/assets/{gitGraph-4MIJSDKK-CUfoq3Sa.js → gitGraph-4MIJSDKK-ChJbe0Zy.js} +1 -1
  66. package/dist/public/assets/{gitGraphDiagram-WWUBYQGX-kj34Cchu.js → gitGraphDiagram-WWUBYQGX-DqLFtXkl.js} +1 -1
  67. package/dist/public/assets/{hotkeys-DbIEec2f.js → hotkeys-Cz0t_EHP.js} +1 -1
  68. package/dist/public/assets/{htmlMode-C_uC6TDH.js → htmlMode-045YO_ln.js} +1 -1
  69. package/dist/public/assets/{index-uKreLbru.css → index-C4dY_r6p.css} +1 -1
  70. package/dist/public/assets/index-CZuj_0q8.js +82 -0
  71. package/dist/public/assets/{info-A6RAGUB7-C938EzS-.js → info-A6RAGUB7-Div0S2Ip.js} +1 -1
  72. package/dist/public/assets/{infoDiagram-27XIBGKW-BoTxIjdn.js → infoDiagram-27XIBGKW-DJhD-gg1.js} +1 -1
  73. package/dist/public/assets/input-BzZ4Cht7.js +1 -0
  74. package/dist/public/assets/{ishikawaDiagram-5VMMS53U-j98L6THV.js → ishikawaDiagram-5VMMS53U-DsWVNBtv.js} +1 -1
  75. package/dist/public/assets/{journeyDiagram-3NMN7TZE-DI-XCC2F.js → journeyDiagram-3NMN7TZE-BYYeC34b.js} +1 -1
  76. package/dist/public/assets/{jsonMode-BQ3590Ds.js → jsonMode-CziPJMol.js} +1 -1
  77. package/dist/public/assets/{kanban-definition-UXKFOSKX-BCTvFJTJ.js → kanban-definition-UXKFOSKX-BCw3v6NN.js} +1 -1
  78. package/dist/public/assets/{line-hE2Okp1W.js → line-YbGl4cRA.js} +1 -1
  79. package/dist/public/assets/{media-refresh-store-CxqhHl8x.js → media-refresh-store-B2-8HX4O.js} +1 -1
  80. package/dist/public/assets/{mermaid-parser.core-n0Wb6T7Q.js → mermaid-parser.core-Bks1n27y.js} +3 -3
  81. package/dist/public/assets/{mermaid.core-Cb0bw4D8.js → mermaid.core-PwPDNHqq.js} +3 -3
  82. package/dist/public/assets/{mindmap-definition-YA3MSWOX-92LM1OuK.js → mindmap-definition-YA3MSWOX-BLevROnK.js} +1 -1
  83. package/dist/public/assets/{notification-permission-CG2r3Oi8.js → notification-permission-DmY8rjcX.js} +1 -1
  84. package/dist/public/assets/{packet-AYTQ26CC-_HBkwHYp.js → packet-AYTQ26CC-CCK4LK_Y.js} +1 -1
  85. package/dist/public/assets/{pdf-DABk-fGs.js → pdf-CxaY5zdL.js} +1 -1
  86. package/dist/public/assets/{pegDiagram-XKGWAZYB-B-fG_WHS.js → pegDiagram-XKGWAZYB-DhkjZiCe.js} +1 -1
  87. package/dist/public/assets/{pie-WAS4IAKB-ByxJto7v.js → pie-WAS4IAKB-CHC0k9ep.js} +1 -1
  88. package/dist/public/assets/{pieDiagram-E7YTZNPT-Ci8ZSq4L.js → pieDiagram-E7YTZNPT-DK2YuIfU.js} +1 -1
  89. package/dist/public/assets/{project-abbrev-BU2DBpdq.js → project-abbrev-BYn6QU-q.js} +1 -1
  90. package/dist/public/assets/protocol-support-C3qZDXsO.js +1 -0
  91. package/dist/public/assets/{quadrantDiagram-AXDQQJYC-B97Yoxpb.js → quadrantDiagram-AXDQQJYC-DI4kRLci.js} +1 -1
  92. package/dist/public/assets/{radar-RG4KPBEZ-BT2qdAqW.js → radar-RG4KPBEZ-DqqrQ-rz.js} +1 -1
  93. package/dist/public/assets/{railroad-74A4TZTK-Buny6l3B.js → railroad-74A4TZTK-CtYFDLom.js} +1 -1
  94. package/dist/public/assets/railroad-abnf-HS5TGJTU-DIXsnxZV.js +1 -0
  95. package/dist/public/assets/railroad-ebnf-LZEXJU2U-B8uF6qy-.js +1 -0
  96. package/dist/public/assets/railroad-peg-WCYAUIDC-Dh5eBaAB.js +1 -0
  97. package/dist/public/assets/{railroadDiagram-O6MQD6OU-BktpI6J7.js → railroadDiagram-O6MQD6OU-BclO7rZc.js} +1 -1
  98. package/dist/public/assets/{requirementDiagram-BXWQKSXE-DYy_YKmd.js → requirementDiagram-BXWQKSXE-CdtUG7Pb.js} +1 -1
  99. package/dist/public/assets/{sankeyDiagram-P5KCCOFB-BeKH_sFV.js → sankeyDiagram-P5KCCOFB-BGhtvKxt.js} +1 -1
  100. package/dist/public/assets/{sequenceDiagram-WJ2MYXX4-DD8okFGM.js → sequenceDiagram-WJ2MYXX4-CxFivW0Q.js} +1 -1
  101. package/dist/public/assets/{stateDiagram-D77RDMKH-Bfk3E3Oa.js → stateDiagram-D77RDMKH-BFQhw_cW.js} +1 -1
  102. package/dist/public/assets/stateDiagram-v2-MP3YSRHH-B7cXGe1m.js +1 -0
  103. package/dist/public/assets/{swimlanes-42K2YHIH-OVNrzhfn.js → swimlanes-42K2YHIH-RC1TK3oS.js} +1 -1
  104. package/dist/public/assets/swimlanesDiagram-VR7AAH4N-B1IMbeGf.js +8 -0
  105. package/dist/public/assets/{switch-CN9NW-du.js → switch-DE8lrtJp.js} +1 -1
  106. package/dist/public/assets/{timeline-definition-24CTP7MA-C78a8EdU.js → timeline-definition-24CTP7MA-BNpuCp-0.js} +1 -1
  107. package/dist/public/assets/{treeView-Q6P3EWNA-Cl5tCoga.js → treeView-Q6P3EWNA-BIC2Uin5.js} +1 -1
  108. package/dist/public/assets/{treemap-WGGIJYW6-4YVcjSz9.js → treemap-WGGIJYW6-DcEgjdWD.js} +1 -1
  109. package/dist/public/assets/{tsMode-CmGZ7MCT.js → tsMode-D9bCl9c6.js} +1 -1
  110. package/dist/public/assets/{use-ui-state-CzR7YpWb.js → use-ui-state-Cqp-5mq9.js} +1 -1
  111. package/dist/public/assets/{vennDiagram-4TSXK5OY-Lih9MwBs.js → vennDiagram-4TSXK5OY-CpXtEbyN.js} +1 -1
  112. package/dist/public/assets/{wardley-WFR3VGLG-CcU7I6bt.js → wardley-WFR3VGLG-BzmLqf8a.js} +1 -1
  113. package/dist/public/assets/{wardleyDiagram-VM6X3IG4-DxHrszj8.js → wardleyDiagram-VM6X3IG4-GlYUe4Pn.js} +1 -1
  114. package/dist/public/assets/{ws-C-kvwpeD.js → ws-DwozYBSn.js} +1 -1
  115. package/dist/public/assets/{xychartDiagram-S5SC5T6Z-DpLvvdIG.js → xychartDiagram-S5SC5T6Z-BYWibIHg.js} +1 -1
  116. package/dist/public/index.html +2 -2
  117. package/package.json +1 -1
  118. package/dist/public/assets/SettingsDialog-CamnF91I.js +0 -8
  119. package/dist/public/assets/architecture-7GRP2DOG-D0iH6Lxl.js +0 -1
  120. package/dist/public/assets/channel-DT2izo70.js +0 -1
  121. package/dist/public/assets/classDiagram-ZZMXUADV-BSshJUxJ.js +0 -1
  122. package/dist/public/assets/classDiagram-v2-VYDZK3BY-BSshJUxJ.js +0 -1
  123. package/dist/public/assets/eventmodeling-NTZA5JFV-CWxfOZuS.js +0 -1
  124. package/dist/public/assets/flowDiagram-HODETNUW-ddOOBXlS.js +0 -1
  125. package/dist/public/assets/index-BLx1AR0-.js +0 -82
  126. package/dist/public/assets/input-DXYRmAFr.js +0 -1
  127. package/dist/public/assets/protocol-support-C1NCVjbV.js +0 -1
  128. package/dist/public/assets/railroad-abnf-HS5TGJTU-C_aUf3vj.js +0 -1
  129. package/dist/public/assets/railroad-ebnf-LZEXJU2U-BGUVD_Qq.js +0 -1
  130. package/dist/public/assets/railroad-peg-WCYAUIDC-CGdTjBGv.js +0 -1
  131. package/dist/public/assets/stateDiagram-v2-MP3YSRHH-DCg8-XDy.js +0 -1
  132. package/dist/public/assets/swimlanesDiagram-VR7AAH4N-DAqvbP32.js +0 -8
package/CHANGELOG.md CHANGED
@@ -1,14 +1,22 @@
1
1
  <!--
2
- Rolling changelog for the NEXT release. Governance lives in CLAUDE.md §"Changelog discipline".
3
- On publish: retitle [Unreleased] to [X.Y.Z] — date, archive a copy to
4
- docs/changelogs/CHANGELOG-vX.Y.Z.md, then reset this file to this template.
5
- Past releases: see docs/changelogs/.
2
+ Archived release changelog. Governance lives in CLAUDE.md §"Changelog discipline".
6
3
  -->
7
4
 
8
5
  # Changelog
9
6
 
10
- ## [0.2.6] — 2026-09-23
7
+ ## [0.2.8] — 2026-09-24
8
+
9
+ ### Added
10
+
11
+ - Register each host profile independently with a remote account, with separate browser approvals, identities and controls; restrict remote discovery, session operations and terminal events to that profile.
12
+ - Show the bundled connector’s remote protocol as a `-cN` suffix on the daemon line in `puddle --version`, using offline metadata without changing compatibility comparisons.
13
+
14
+ ### Changed
15
+
16
+ - Require `--profile <profile-id>` for remote CLI administration; keep `remote run` as the supervisor for all registrations.
17
+ - Advance daemon/cockpit protocol to 22.0 and remote protocol to 3 for profile-scoped authority; delete legacy host-wide registrations and revoke their approvals on connector startup, retrying relay removal when offline.
18
+ - Switch to Files and reveal the file when clicking a filename in Search; keep per-line results in Search.
11
19
 
12
20
  ### Fixed
13
21
 
14
- - Fix standalone CLI distribution checks on Linux and macOS by retaining gzip on the isolated PATH and invoking system utilities at their original paths.
22
+ - Leave 2.5 rows of blank space below file trees so the directory context menu remains accessible in long lists.
package/README.md CHANGED
@@ -56,7 +56,7 @@ This connects Puddle to the remote host over SSH, bootstrapping the Puddle daemo
56
56
 
57
57
  **To connect from a phone or another browser over the internet:** deploy your own
58
58
  [mobile access service and trusted web application](docs/mobile-access.md), then
59
- use `puddle remote enable` and `puddle remote pair`. The host connects outward;
59
+ use `puddle remote enable --profile <profile-id>` and `puddle remote pair --profile <profile-id>`. Each profile registers independently. The host connects outward;
60
60
  there is no public daemon port or VPN requirement. Each browser needs explicit
61
61
  host approval. The phone view provides live terminals, prompt input and read-only
62
62
  text/diff review over a pinned Noise connection through the relay.
@@ -14834,6 +14834,7 @@ var agentTypeSchema = external_exports.object({
14834
14834
  var repoSchema = external_exports.object({
14835
14835
  id: rowId,
14836
14836
  path: external_exports.string(),
14837
+ /** Empty follows the branch currently checked out at path, resolved for each new session. */
14837
14838
  default_base_branch: external_exports.string(),
14838
14839
  onboarding_notes: external_exports.string().nullable(),
14839
14840
  fetch_enabled: external_exports.boolean(),
@@ -14844,7 +14845,8 @@ var repoWithOrphansSchema = repoSchema.extend({
14844
14845
  });
14845
14846
  var createRepoRequestSchema = external_exports.object({
14846
14847
  path: external_exports.string().min(1),
14847
- default_base_branch: external_exports.string().min(1).optional(),
14848
+ /** Empty follows the clone's current branch; omitted snapshots it at registration. */
14849
+ default_base_branch: external_exports.string().optional(),
14848
14850
  onboarding_notes: external_exports.string().nullable().optional(),
14849
14851
  fetch_enabled: external_exports.boolean().optional()
14850
14852
  });
@@ -14885,7 +14887,8 @@ var repoWorktreesResponseSchema = external_exports.object({
14885
14887
  orphan_branches: external_exports.array(orphanBranchSchema)
14886
14888
  });
14887
14889
  var patchRepoRequestSchema = external_exports.object({
14888
- default_base_branch: external_exports.string().min(1).optional(),
14890
+ /** Empty follows the clone's current branch; omitted leaves the setting unchanged. */
14891
+ default_base_branch: external_exports.string().optional(),
14889
14892
  onboarding_notes: external_exports.string().nullable().optional(),
14890
14893
  fetch_enabled: external_exports.boolean().optional()
14891
14894
  });
@@ -15772,7 +15775,7 @@ var wsServerMessageSchema = external_exports.discriminatedUnion("t", [
15772
15775
  ]);
15773
15776
 
15774
15777
  // ../shared/src/remote/protocol.ts
15775
- var REMOTE_PROTOCOL_VERSION = 2;
15778
+ var REMOTE_PROTOCOL_VERSION = 3;
15776
15779
  var REMOTE_POLICY = {
15777
15780
  chunkBytes: 32 * 1024,
15778
15781
  frameBytes: 48 * 1024,
@@ -15893,6 +15896,65 @@ var remoteChunkSchema = external_exports.object({
15893
15896
  data: external_exports.string().max(REMOTE_POLICY.chunkBytes)
15894
15897
  }).strict();
15895
15898
 
15899
+ // ../shared/src/remote/service.ts
15900
+ var remoteHostSchema = external_exports.object({
15901
+ id: remoteIdSchema,
15902
+ label: remoteLabelSchema,
15903
+ online: external_exports.boolean()
15904
+ });
15905
+ var remoteHostsSchema = external_exports.array(remoteHostSchema);
15906
+ var remoteServiceInfoSchema = external_exports.object({
15907
+ providers: external_exports.array(external_exports.enum(["google", "github"])),
15908
+ protocol: external_exports.literal(REMOTE_PROTOCOL_VERSION)
15909
+ });
15910
+ var remoteLoginStateSchema = external_exports.object({
15911
+ user: external_exports.object({
15912
+ id: remoteAccountSchema,
15913
+ name: external_exports.string(),
15914
+ email: external_exports.string(),
15915
+ emailVerified: external_exports.boolean(),
15916
+ twoFactorEnabled: external_exports.boolean()
15917
+ }).nullable(),
15918
+ mfaRequired: external_exports.boolean()
15919
+ });
15920
+ var registerHostRequestSchema = external_exports.object({ label: remoteLabelSchema }).strict();
15921
+ var registrationResponseSchema = external_exports.object({ host: remoteIdSchema, code: remoteSecretSchema, expires: external_exports.number() }).strict();
15922
+ var redeemRegistrationSchema = external_exports.object({ code: remoteSecretSchema }).strict();
15923
+ var unregisterHostRequestSchema = external_exports.object({ credential: remoteSecretSchema }).strict();
15924
+ var desktopRegistrationSchema = external_exports.object({
15925
+ challenge: remoteSecretSchema,
15926
+ label: remoteLabelSchema,
15927
+ service: remoteOriginSchema,
15928
+ app: remoteOriginSchema,
15929
+ expires: external_exports.number().int().positive()
15930
+ }).strict();
15931
+ var registrationStatusSchema = external_exports.object({ ready: external_exports.boolean() }).strict();
15932
+ var connectorRegistrationSchema = external_exports.object({
15933
+ host: remoteIdSchema,
15934
+ account: remoteAccountSchema,
15935
+ credential: remoteSecretSchema
15936
+ }).strict();
15937
+ var connectorConfigSchema = connectorRegistrationSchema.extend({
15938
+ service: remoteOriginSchema,
15939
+ app: remoteOriginSchema,
15940
+ enabled: external_exports.boolean()
15941
+ }).strict();
15942
+ var connectorSetupSchema = external_exports.object({
15943
+ service: remoteOriginSchema.optional(),
15944
+ app: remoteOriginSchema.optional(),
15945
+ code: remoteSecretSchema.optional(),
15946
+ managed: external_exports.boolean().default(true)
15947
+ }).strict();
15948
+ var remoteIdentitySchema = external_exports.array(external_exports.number().int().min(0).max(255)).min(32).max(256);
15949
+ var remoteBrowserHostSchema = external_exports.object({
15950
+ host: remoteIdSchema,
15951
+ peer: remotePeerSchema,
15952
+ account: remoteAccountSchema,
15953
+ service: remoteOriginSchema,
15954
+ label: external_exports.string(),
15955
+ privateKey: remoteIdentitySchema
15956
+ }).strict();
15957
+
15896
15958
  // ../shared/src/api/cockpit-remote.ts
15897
15959
  var connectorLocalRequestSchema = external_exports.union([
15898
15960
  remoteAdminRequestSchema,
@@ -15920,6 +15982,9 @@ var cockpitRemoteStatusSchema = external_exports.object({
15920
15982
  app: remoteOriginSchema.optional(),
15921
15983
  devices: external_exports.array(remoteDeviceSchema)
15922
15984
  });
15985
+ var connectorProfileSchema = external_exports.object({ profile: profileId }).strict();
15986
+ var connectorAdminSchema = external_exports.object({ profile: profileId, request: connectorLocalRequestSchema }).strict();
15987
+ var connectorConfigureSchema = external_exports.object({ profile: profileId, setup: connectorSetupSchema }).strict();
15923
15988
 
15924
15989
  // ../shared/src/api/connection-auth.ts
15925
15990
  var CONNECTION_POLICY = {
@@ -15942,7 +16007,7 @@ var authErrorCodeSchema = external_exports.enum([
15942
16007
  "protocol_mismatch"
15943
16008
  ]);
15944
16009
  var controlRequestSchema = external_exports.discriminatedUnion("t", [
15945
- external_exports.object({ t: external_exports.literal("open") }).strict(),
16010
+ external_exports.object({ t: external_exports.literal("open"), profile: profileId.optional() }).strict(),
15946
16011
  external_exports.object({ t: external_exports.literal("renew"), resources: external_exports.array(resourceIdSchema).max(2048) }).strict(),
15947
16012
  external_exports.object({ t: external_exports.literal("close") }).strict()
15948
16013
  ]);
@@ -16031,65 +16096,6 @@ var imageUploadProgressSchema = external_exports.object({
16031
16096
  received: external_exports.number().int().nonnegative().max(IMAGE_UPLOAD_POLICY.imageBytes)
16032
16097
  });
16033
16098
 
16034
- // ../shared/src/remote/service.ts
16035
- var remoteHostSchema = external_exports.object({
16036
- id: remoteIdSchema,
16037
- label: remoteLabelSchema,
16038
- online: external_exports.boolean()
16039
- });
16040
- var remoteHostsSchema = external_exports.array(remoteHostSchema);
16041
- var remoteServiceInfoSchema = external_exports.object({
16042
- providers: external_exports.array(external_exports.enum(["google", "github"])),
16043
- protocol: external_exports.literal(REMOTE_PROTOCOL_VERSION)
16044
- });
16045
- var remoteLoginStateSchema = external_exports.object({
16046
- user: external_exports.object({
16047
- id: remoteAccountSchema,
16048
- name: external_exports.string(),
16049
- email: external_exports.string(),
16050
- emailVerified: external_exports.boolean(),
16051
- twoFactorEnabled: external_exports.boolean()
16052
- }).nullable(),
16053
- mfaRequired: external_exports.boolean()
16054
- });
16055
- var registerHostRequestSchema = external_exports.object({ label: remoteLabelSchema }).strict();
16056
- var registrationResponseSchema = external_exports.object({ host: remoteIdSchema, code: remoteSecretSchema, expires: external_exports.number() }).strict();
16057
- var redeemRegistrationSchema = external_exports.object({ code: remoteSecretSchema }).strict();
16058
- var unregisterHostRequestSchema = external_exports.object({ credential: remoteSecretSchema }).strict();
16059
- var desktopRegistrationSchema = external_exports.object({
16060
- challenge: remoteSecretSchema,
16061
- label: remoteLabelSchema,
16062
- service: remoteOriginSchema,
16063
- app: remoteOriginSchema,
16064
- expires: external_exports.number().int().positive()
16065
- }).strict();
16066
- var registrationStatusSchema = external_exports.object({ ready: external_exports.boolean() }).strict();
16067
- var connectorRegistrationSchema = external_exports.object({
16068
- host: remoteIdSchema,
16069
- account: remoteAccountSchema,
16070
- credential: remoteSecretSchema
16071
- }).strict();
16072
- var connectorConfigSchema = connectorRegistrationSchema.extend({
16073
- service: remoteOriginSchema,
16074
- app: remoteOriginSchema,
16075
- enabled: external_exports.boolean()
16076
- }).strict();
16077
- var connectorSetupSchema = external_exports.object({
16078
- service: remoteOriginSchema.optional(),
16079
- app: remoteOriginSchema.optional(),
16080
- code: remoteSecretSchema.optional(),
16081
- managed: external_exports.boolean().default(true)
16082
- }).strict();
16083
- var remoteIdentitySchema = external_exports.array(external_exports.number().int().min(0).max(255)).min(32).max(256);
16084
- var remoteBrowserHostSchema = external_exports.object({
16085
- host: remoteIdSchema,
16086
- peer: remotePeerSchema,
16087
- account: remoteAccountSchema,
16088
- service: remoteOriginSchema,
16089
- label: external_exports.string(),
16090
- privateKey: remoteIdentitySchema
16091
- }).strict();
16092
-
16093
16099
  // ../shared/src/node/security.ts
16094
16100
  import { createHash, randomBytes } from "node:crypto";
16095
16101
  import {
package/dist/index.js CHANGED
@@ -3925,7 +3925,7 @@ import { createInterface } from "node:readline";
3925
3925
  import { Writable } from "node:stream";
3926
3926
 
3927
3927
  // ../shared/src/protocol.ts
3928
- var PROTOCOL_VERSION = { major: 21, minor: 2 };
3928
+ var PROTOCOL_VERSION = { major: 22, minor: 0 };
3929
3929
 
3930
3930
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
3931
3931
  var external_exports = {};
@@ -18754,6 +18754,7 @@ var agentTypeSchema = external_exports.object({
18754
18754
  var repoSchema = external_exports.object({
18755
18755
  id: rowId,
18756
18756
  path: external_exports.string(),
18757
+ /** Empty follows the branch currently checked out at path, resolved for each new session. */
18757
18758
  default_base_branch: external_exports.string(),
18758
18759
  onboarding_notes: external_exports.string().nullable(),
18759
18760
  fetch_enabled: external_exports.boolean(),
@@ -18764,7 +18765,8 @@ var repoWithOrphansSchema = repoSchema.extend({
18764
18765
  });
18765
18766
  var createRepoRequestSchema = external_exports.object({
18766
18767
  path: external_exports.string().min(1),
18767
- default_base_branch: external_exports.string().min(1).optional(),
18768
+ /** Empty follows the clone's current branch; omitted snapshots it at registration. */
18769
+ default_base_branch: external_exports.string().optional(),
18768
18770
  onboarding_notes: external_exports.string().nullable().optional(),
18769
18771
  fetch_enabled: external_exports.boolean().optional()
18770
18772
  });
@@ -18805,7 +18807,8 @@ var repoWorktreesResponseSchema = external_exports.object({
18805
18807
  orphan_branches: external_exports.array(orphanBranchSchema)
18806
18808
  });
18807
18809
  var patchRepoRequestSchema = external_exports.object({
18808
- default_base_branch: external_exports.string().min(1).optional(),
18810
+ /** Empty follows the clone's current branch; omitted leaves the setting unchanged. */
18811
+ default_base_branch: external_exports.string().optional(),
18809
18812
  onboarding_notes: external_exports.string().nullable().optional(),
18810
18813
  fetch_enabled: external_exports.boolean().optional()
18811
18814
  });
@@ -19692,7 +19695,7 @@ var wsServerMessageSchema = external_exports.discriminatedUnion("t", [
19692
19695
  ]);
19693
19696
 
19694
19697
  // ../shared/src/remote/protocol.ts
19695
- var REMOTE_PROTOCOL_VERSION = 2;
19698
+ var REMOTE_PROTOCOL_VERSION = 3;
19696
19699
  var REMOTE_POLICY = {
19697
19700
  chunkBytes: 32 * 1024,
19698
19701
  frameBytes: 48 * 1024,
@@ -19813,6 +19816,65 @@ var remoteChunkSchema = external_exports.object({
19813
19816
  data: external_exports.string().max(REMOTE_POLICY.chunkBytes)
19814
19817
  }).strict();
19815
19818
 
19819
+ // ../shared/src/remote/service.ts
19820
+ var remoteHostSchema = external_exports.object({
19821
+ id: remoteIdSchema,
19822
+ label: remoteLabelSchema,
19823
+ online: external_exports.boolean()
19824
+ });
19825
+ var remoteHostsSchema = external_exports.array(remoteHostSchema);
19826
+ var remoteServiceInfoSchema = external_exports.object({
19827
+ providers: external_exports.array(external_exports.enum(["google", "github"])),
19828
+ protocol: external_exports.literal(REMOTE_PROTOCOL_VERSION)
19829
+ });
19830
+ var remoteLoginStateSchema = external_exports.object({
19831
+ user: external_exports.object({
19832
+ id: remoteAccountSchema,
19833
+ name: external_exports.string(),
19834
+ email: external_exports.string(),
19835
+ emailVerified: external_exports.boolean(),
19836
+ twoFactorEnabled: external_exports.boolean()
19837
+ }).nullable(),
19838
+ mfaRequired: external_exports.boolean()
19839
+ });
19840
+ var registerHostRequestSchema = external_exports.object({ label: remoteLabelSchema }).strict();
19841
+ var registrationResponseSchema = external_exports.object({ host: remoteIdSchema, code: remoteSecretSchema, expires: external_exports.number() }).strict();
19842
+ var redeemRegistrationSchema = external_exports.object({ code: remoteSecretSchema }).strict();
19843
+ var unregisterHostRequestSchema = external_exports.object({ credential: remoteSecretSchema }).strict();
19844
+ var desktopRegistrationSchema = external_exports.object({
19845
+ challenge: remoteSecretSchema,
19846
+ label: remoteLabelSchema,
19847
+ service: remoteOriginSchema,
19848
+ app: remoteOriginSchema,
19849
+ expires: external_exports.number().int().positive()
19850
+ }).strict();
19851
+ var registrationStatusSchema = external_exports.object({ ready: external_exports.boolean() }).strict();
19852
+ var connectorRegistrationSchema = external_exports.object({
19853
+ host: remoteIdSchema,
19854
+ account: remoteAccountSchema,
19855
+ credential: remoteSecretSchema
19856
+ }).strict();
19857
+ var connectorConfigSchema = connectorRegistrationSchema.extend({
19858
+ service: remoteOriginSchema,
19859
+ app: remoteOriginSchema,
19860
+ enabled: external_exports.boolean()
19861
+ }).strict();
19862
+ var connectorSetupSchema = external_exports.object({
19863
+ service: remoteOriginSchema.optional(),
19864
+ app: remoteOriginSchema.optional(),
19865
+ code: remoteSecretSchema.optional(),
19866
+ managed: external_exports.boolean().default(true)
19867
+ }).strict();
19868
+ var remoteIdentitySchema = external_exports.array(external_exports.number().int().min(0).max(255)).min(32).max(256);
19869
+ var remoteBrowserHostSchema = external_exports.object({
19870
+ host: remoteIdSchema,
19871
+ peer: remotePeerSchema,
19872
+ account: remoteAccountSchema,
19873
+ service: remoteOriginSchema,
19874
+ label: external_exports.string(),
19875
+ privateKey: remoteIdentitySchema
19876
+ }).strict();
19877
+
19816
19878
  // ../shared/src/api/cockpit-remote.ts
19817
19879
  var connectorLocalRequestSchema = external_exports.union([
19818
19880
  remoteAdminRequestSchema,
@@ -19840,6 +19902,9 @@ var cockpitRemoteStatusSchema = external_exports.object({
19840
19902
  app: remoteOriginSchema.optional(),
19841
19903
  devices: external_exports.array(remoteDeviceSchema)
19842
19904
  });
19905
+ var connectorProfileSchema = external_exports.object({ profile: profileId }).strict();
19906
+ var connectorAdminSchema = external_exports.object({ profile: profileId, request: connectorLocalRequestSchema }).strict();
19907
+ var connectorConfigureSchema = external_exports.object({ profile: profileId, setup: connectorSetupSchema }).strict();
19843
19908
 
19844
19909
  // ../shared/src/api/connection-auth.ts
19845
19910
  var CONNECTION_POLICY = {
@@ -19862,7 +19927,7 @@ var authErrorCodeSchema = external_exports.enum([
19862
19927
  "protocol_mismatch"
19863
19928
  ]);
19864
19929
  var controlRequestSchema = external_exports.discriminatedUnion("t", [
19865
- external_exports.object({ t: external_exports.literal("open") }).strict(),
19930
+ external_exports.object({ t: external_exports.literal("open"), profile: profileId.optional() }).strict(),
19866
19931
  external_exports.object({ t: external_exports.literal("renew"), resources: external_exports.array(resourceIdSchema).max(2048) }).strict(),
19867
19932
  external_exports.object({ t: external_exports.literal("close") }).strict()
19868
19933
  ]);
@@ -19951,65 +20016,6 @@ var imageUploadProgressSchema = external_exports.object({
19951
20016
  received: external_exports.number().int().nonnegative().max(IMAGE_UPLOAD_POLICY.imageBytes)
19952
20017
  });
19953
20018
 
19954
- // ../shared/src/remote/service.ts
19955
- var remoteHostSchema = external_exports.object({
19956
- id: remoteIdSchema,
19957
- label: remoteLabelSchema,
19958
- online: external_exports.boolean()
19959
- });
19960
- var remoteHostsSchema = external_exports.array(remoteHostSchema);
19961
- var remoteServiceInfoSchema = external_exports.object({
19962
- providers: external_exports.array(external_exports.enum(["google", "github"])),
19963
- protocol: external_exports.literal(REMOTE_PROTOCOL_VERSION)
19964
- });
19965
- var remoteLoginStateSchema = external_exports.object({
19966
- user: external_exports.object({
19967
- id: remoteAccountSchema,
19968
- name: external_exports.string(),
19969
- email: external_exports.string(),
19970
- emailVerified: external_exports.boolean(),
19971
- twoFactorEnabled: external_exports.boolean()
19972
- }).nullable(),
19973
- mfaRequired: external_exports.boolean()
19974
- });
19975
- var registerHostRequestSchema = external_exports.object({ label: remoteLabelSchema }).strict();
19976
- var registrationResponseSchema = external_exports.object({ host: remoteIdSchema, code: remoteSecretSchema, expires: external_exports.number() }).strict();
19977
- var redeemRegistrationSchema = external_exports.object({ code: remoteSecretSchema }).strict();
19978
- var unregisterHostRequestSchema = external_exports.object({ credential: remoteSecretSchema }).strict();
19979
- var desktopRegistrationSchema = external_exports.object({
19980
- challenge: remoteSecretSchema,
19981
- label: remoteLabelSchema,
19982
- service: remoteOriginSchema,
19983
- app: remoteOriginSchema,
19984
- expires: external_exports.number().int().positive()
19985
- }).strict();
19986
- var registrationStatusSchema = external_exports.object({ ready: external_exports.boolean() }).strict();
19987
- var connectorRegistrationSchema = external_exports.object({
19988
- host: remoteIdSchema,
19989
- account: remoteAccountSchema,
19990
- credential: remoteSecretSchema
19991
- }).strict();
19992
- var connectorConfigSchema = connectorRegistrationSchema.extend({
19993
- service: remoteOriginSchema,
19994
- app: remoteOriginSchema,
19995
- enabled: external_exports.boolean()
19996
- }).strict();
19997
- var connectorSetupSchema = external_exports.object({
19998
- service: remoteOriginSchema.optional(),
19999
- app: remoteOriginSchema.optional(),
20000
- code: remoteSecretSchema.optional(),
20001
- managed: external_exports.boolean().default(true)
20002
- }).strict();
20003
- var remoteIdentitySchema = external_exports.array(external_exports.number().int().min(0).max(255)).min(32).max(256);
20004
- var remoteBrowserHostSchema = external_exports.object({
20005
- host: remoteIdSchema,
20006
- peer: remotePeerSchema,
20007
- account: remoteAccountSchema,
20008
- service: remoteOriginSchema,
20009
- label: external_exports.string(),
20010
- privateKey: remoteIdentitySchema
20011
- }).strict();
20012
-
20013
20019
  // src/lib/transport/local.ts
20014
20020
  import { spawn } from "node:child_process";
20015
20021
  import { copyFileSync, mkdirSync, readFileSync } from "node:fs";
@@ -20338,7 +20344,12 @@ function parseRemoteArgs(args) {
20338
20344
  for (let i = 0; i < rest.length; i++) {
20339
20345
  const arg = rest[i];
20340
20346
  if (arg === "--foreground") command.foreground = true;
20341
- else if (arg === "--service" || arg === "--app-origin") {
20347
+ else if (arg === "--profile") {
20348
+ const parsed = profileId.safeParse(rest[++i]);
20349
+ if (!parsed.success)
20350
+ throw new CliError("bad_arguments", "--profile requires an exact profile id");
20351
+ command.profile = parsed.data;
20352
+ } else if (arg === "--service" || arg === "--app-origin") {
20342
20353
  const value = remoteOriginSchema.safeParse(rest[++i]);
20343
20354
  if (!value.success) throw new CliError("bad_arguments", `${arg} needs an exact HTTPS origin`);
20344
20355
  if (arg === "--service") command.service = value.data;
@@ -20363,6 +20374,10 @@ function parseRemoteArgs(args) {
20363
20374
  throw new CliError("bad_arguments", "Configuration options apply only to remote enable");
20364
20375
  if (!!command.service !== !!command.app)
20365
20376
  throw new CliError("bad_arguments", "Specify both --service and --app-origin");
20377
+ if (action !== "run" && !command.profile)
20378
+ throw new CliError("bad_arguments", "Select a profile with --profile <profile-id>");
20379
+ if (action === "run" && command.profile)
20380
+ throw new CliError("bad_arguments", "remote run supervises all registered profiles");
20366
20381
  return command;
20367
20382
  }
20368
20383
  async function registrationCode() {
@@ -20402,12 +20417,21 @@ async function runRemote(command) {
20402
20417
  "The installed daemon does not include mobile access",
20403
20418
  `puddle upgrade daemon${command.host ? ` ${command.host}` : ""}`
20404
20419
  );
20420
+ const capabilities = await transport.exec(`${base} --version`, { timeoutMs: 1e4 });
20421
+ if (capabilities.code !== 0 || !capabilities.stdout.includes("cockpit controls 2"))
20422
+ throw new CliError(
20423
+ "protocol_mismatch",
20424
+ "Upgrade the host daemon before managing profile registrations."
20425
+ );
20405
20426
  if (command.action === "run") {
20406
20427
  const result2 = await transport.exec(base, { onStdout: (text) => process.stdout.write(text) });
20407
20428
  return result2.code;
20408
20429
  }
20409
20430
  if (command.action === "reset") {
20410
- const result2 = await transport.exec(`${base} --reset`, { timeoutMs: 3e4 });
20431
+ const result2 = await transport.exec(`${base} --reset`, {
20432
+ timeoutMs: 3e4,
20433
+ stdin: JSON.stringify({ profile: command.profile }) + "\n"
20434
+ });
20411
20435
  if (result2.code !== 0)
20412
20436
  throw new CliError("bad_arguments", result2.stderr.trim() || "Reset failed");
20413
20437
  process.stdout.write(
@@ -20424,7 +20448,9 @@ async function runRemote(command) {
20424
20448
  const result = await transport.exec(
20425
20449
  `${base} ${command.action === "enable" ? "--configure" : "--admin"}`,
20426
20450
  {
20427
- stdin: JSON.stringify(payload) + "\n",
20451
+ stdin: JSON.stringify(
20452
+ command.action === "enable" ? { profile: command.profile, setup: payload } : { profile: command.profile, request: payload }
20453
+ ) + "\n",
20428
20454
  timeoutMs: 3e4
20429
20455
  }
20430
20456
  );
@@ -20491,14 +20517,15 @@ usage:
20491
20517
  puddle install <daemon|desktop>[@version] [user@host] [--tarball <path>]
20492
20518
  puddle upgrade [cli|daemon|desktop][@version] [user@host] [--tarball <path>]
20493
20519
  puddle remove <cli|daemon|desktop> [user@host] [--yes] [--purge]
20494
- puddle remote enable [user@host] --service <https-origin> --app-origin <https-origin>
20520
+ puddle remote enable --profile <profile-id> [user@host] --service <https-origin> --app-origin <https-origin>
20495
20521
  [--foreground]
20496
- puddle remote status|pair|devices|disable|reset|run [user@host]
20497
- puddle remote approve|revoke <device-id> [user@host]
20522
+ puddle remote status|pair|devices|disable|reset --profile <profile-id> [user@host]
20523
+ puddle remote run [user@host]
20524
+ puddle remote approve|revoke <device-id> --profile <profile-id> [user@host]
20498
20525
  puddle --version | --help
20499
20526
 
20500
20527
  --version lists the installed CLI, daemon, and desktop app with the protocol
20501
- each speaks; absent local components are reported as not installed.
20528
+ each speaks (daemon -cN reports the connector\u2019s remote protocol); absent local components are reported as not installed.
20502
20529
 
20503
20530
  launch serves the cockpit at http://localhost:7433 against the daemon on this
20504
20531
  machine when no host (or 'local') is given \u2014 installing it under ~/.puddle if
@@ -21105,10 +21132,11 @@ function jsonLines(stream, receive, fail2) {
21105
21132
 
21106
21133
  // ../shared/src/node/host-control.ts
21107
21134
  var HostControlClient = class {
21108
- constructor(openChannel, automatic = true, error51 = (_code, message) => new Error(message)) {
21135
+ constructor(openChannel, automatic = true, error51 = (_code, message) => new Error(message), profile) {
21109
21136
  this.openChannel = openChannel;
21110
21137
  this.automatic = automatic;
21111
21138
  this.error = error51;
21139
+ this.profile = profile;
21112
21140
  this.timer = setInterval(() => {
21113
21141
  if (this.channel && performance.now() >= this.until)
21114
21142
  this.lose(this.channel, "upstream_expired");
@@ -21251,7 +21279,7 @@ var HostControlClient = class {
21251
21279
  channel.once("error", closed);
21252
21280
  channel.once("close", closed);
21253
21281
  channel.once("end", closed);
21254
- send({ t: "open" });
21282
+ send({ t: "open", ...this.profile ? { profile: this.profile } : {} });
21255
21283
  });
21256
21284
  } finally {
21257
21285
  this.connecting = false;
@@ -21525,7 +21553,7 @@ import { readFileSync as readFileSync4 } from "node:fs";
21525
21553
  import { dirname as dirname4, join as join5 } from "node:path";
21526
21554
  import { fileURLToPath as fileURLToPath2 } from "node:url";
21527
21555
  function cliVersion() {
21528
- if (true) return "0.2.6";
21556
+ if (true) return "0.2.8";
21529
21557
  const here = dirname4(fileURLToPath2(import.meta.url));
21530
21558
  for (const candidate of [
21531
21559
  join5(here, "..", "..", "package.json"),
@@ -21904,7 +21932,9 @@ var RELEASE_PROTOCOLS = {
21904
21932
  "0.2.3": { major: 20, minor: 0 },
21905
21933
  "0.2.4": { major: 21, minor: 2 },
21906
21934
  "0.2.5": { major: 21, minor: 2 },
21907
- "0.2.6": { major: 21, minor: 2 }
21935
+ "0.2.6": { major: 21, minor: 2 },
21936
+ "0.2.7": { major: 21, minor: 3 },
21937
+ "0.2.8": { major: 22, minor: 0 }
21908
21938
  };
21909
21939
  function validProtocol(value) {
21910
21940
  if (typeof value !== "object" || value === null) return false;
@@ -21963,6 +21993,15 @@ function daemonProtocol(home, version2) {
21963
21993
  }
21964
21994
  return releasedProtocol(version2);
21965
21995
  }
21996
+ function daemonConnectorProtocol(home, version2) {
21997
+ try {
21998
+ const raw = readFileSync5(join7(home, "bin", "current", "CONNECTOR_PROTOCOL"), "utf8").trim();
21999
+ if (/^[1-9][0-9]*$/.test(raw) && Number.isSafeInteger(Number(raw))) return Number(raw);
22000
+ return void 0;
22001
+ } catch {
22002
+ return /^0\.2\.[0-7]$/.test(version2) ? 2 : void 0;
22003
+ }
22004
+ }
21966
22005
  async function installedComponentVersions(opts = {}) {
21967
22006
  const home = opts.home ?? clientHome();
21968
22007
  const cli = {
@@ -21973,10 +22012,12 @@ async function installedComponentVersions(opts = {}) {
21973
22012
  };
21974
22013
  const installedDaemon = daemonVersion(home);
21975
22014
  const installedDaemonProtocol = installedDaemon === void 0 ? void 0 : daemonProtocol(home, installedDaemon);
22015
+ const connectorProtocol = installedDaemon === void 0 ? void 0 : daemonConnectorProtocol(home, installedDaemon);
21976
22016
  const daemon = installedDaemon === void 0 ? { component: "daemon", installed: false } : {
21977
22017
  component: "daemon",
21978
22018
  installed: true,
21979
22019
  version: installedDaemon,
22020
+ ...connectorProtocol !== void 0 ? { connectorProtocol } : {},
21980
22021
  ...installedDaemonProtocol ? { protocol: installedDaemonProtocol } : {}
21981
22022
  };
21982
22023
  const recordedDesktop = readDesktopInstallation(desktopRecordFile(home));
@@ -22008,7 +22049,7 @@ function formatComponentVersions(components) {
22008
22049
  const name = component.component.padEnd(7);
22009
22050
  if (!component.installed) return `${name} not installed`;
22010
22051
  const version2 = component.version ?? "unknown version";
22011
- const protocol = component.protocol ? `protocol ${component.protocol.major}.${component.protocol.minor}` : "protocol unknown";
22052
+ const protocol = component.protocol ? `protocol ${component.protocol.major}.${component.protocol.minor}${component.component === "daemon" && component.connectorProtocol !== void 0 ? `-c${component.connectorProtocol}` : ""}` : "protocol unknown";
22012
22053
  return `${name} ${version2} (${protocol})`;
22013
22054
  }).join("\n");
22014
22055
  }
@@ -23277,13 +23318,18 @@ function remoteAccessHandler(control) {
23277
23318
  return async (req, res, authorised) => {
23278
23319
  if (!control) return fail(res, 404, "remote_controls_unavailable");
23279
23320
  if (req.method !== "GET" && req.method !== "POST") return fail(res, 405, "method_not_allowed");
23321
+ const url2 = new URL(req.url, "http://localhost");
23322
+ const scope = connectorProfileSchema.safeParse(Object.fromEntries(url2.searchParams));
23323
+ if (!scope.success || url2.searchParams.getAll("profile").length !== 1)
23324
+ return fail(res, 400, "invalid_profile", "Select the profile to manage remote access.");
23325
+ const { profile } = scope.data;
23280
23326
  const request = req.method === "POST" ? cockpitRemoteRequestSchema.parse(await readJson(req)) : null;
23281
23327
  if (!authorised()) return fail(res, 401, "browser_rejected");
23282
23328
  if (busy)
23283
23329
  return fail(res, 409, "remote_control_busy", "A host operation is already in progress.");
23284
23330
  busy = true;
23285
23331
  try {
23286
- const response = request ? await control.request(request, authorised) : await control.status();
23332
+ const response = request ? await control.request(request, authorised, profile) : await control.status(profile);
23287
23333
  if (!authorised()) return fail(res, 401, "browser_rejected");
23288
23334
  json2(res, 200, response);
23289
23335
  } catch (error51) {
@@ -23536,11 +23582,12 @@ var RemoteAccessControl = class {
23536
23582
  if (result.code !== 0)
23537
23583
  throw new Error("Host control is unavailable. Check the host connection.");
23538
23584
  return {
23539
- availability: result.stdout.includes("cockpit controls 1") ? "ready" : "upgrade_required",
23585
+ availability: result.stdout.includes("cockpit controls 2") ? "ready" : "upgrade_required",
23540
23586
  canDeleteRegistration: result.stdout.includes("delete registration 1")
23541
23587
  };
23542
23588
  }
23543
- async status() {
23589
+ async status(profile) {
23590
+ profileId.parse(profile);
23544
23591
  const capabilities = await this.capabilities();
23545
23592
  if (capabilities.availability !== "ready")
23546
23593
  return {
@@ -23551,12 +23598,16 @@ var RemoteAccessControl = class {
23551
23598
  supervisor: null,
23552
23599
  devices: []
23553
23600
  };
23554
- const result = await this.transport.exec(`${binary} --inspect`, { timeoutMs: 1e4 });
23601
+ const result = await this.transport.exec(`${binary} --inspect`, {
23602
+ timeoutMs: 1e4,
23603
+ stdin: JSON.stringify({ profile }) + "\n"
23604
+ });
23555
23605
  if (result.code !== 0) throw new Error("Could not read remote access status on this host.");
23556
23606
  return cockpitRemoteStatusSchema.parse({ ...JSON.parse(result.stdout), ...capabilities });
23557
23607
  }
23558
- async request(value, authorised) {
23608
+ async request(value, authorised, profile) {
23559
23609
  const request = cockpitRemoteRequestSchema.parse(value);
23610
+ profileId.parse(profile);
23560
23611
  const capabilities = await this.capabilities();
23561
23612
  if (capabilities.availability !== "ready")
23562
23613
  throw new Error("Upgrade the daemon on this host to manage remote access here.");
@@ -23564,7 +23615,7 @@ var RemoteAccessControl = class {
23564
23615
  throw new Error("Upgrade the daemon on this host to delete its remote registration.");
23565
23616
  if (!authorised()) throw new Error("Browser authorisation expired before dispatch.");
23566
23617
  const flag = request.t === "enable" ? "--configure" : request.t === "reset" ? "--reset" : "--admin";
23567
- const payload = request.t === "enable" ? { ...request.registration, managed: true } : request;
23618
+ const payload = request.t === "enable" ? { profile, setup: { ...request.registration, managed: true } } : request.t === "reset" ? { profile } : { profile, request };
23568
23619
  const result = await this.transport.exec(`${binary} ${flag}`, {
23569
23620
  stdin: JSON.stringify(payload) + "\n",
23570
23621
  timeoutMs: 3e4
@@ -24353,8 +24404,12 @@ HOME_DIR="\${PUDDLE_HOME:-$HOME/.puddle}"
24353
24404
  say() { printf 'puddled remove: %s\\n' "$1"; }
24354
24405
 
24355
24406
  # Persist remote disable before unregistering either supervisor.
24356
- if [ -f "$HOME_DIR/bin/current/daemon/connector.mjs" ] && [ -f "$HOME_DIR/remote/config.json" ]; then
24357
- printf '%s\\n' '{"t":"disable"}' | "$HOME_DIR/bin/current/bin/node" "$HOME_DIR/bin/current/daemon/connector.mjs" --admin >/dev/null 2>&1 || exit 1
24407
+ if [ -f "$HOME_DIR/bin/current/daemon/connector.mjs" ] && [ -d "$HOME_DIR/remote" ]; then
24408
+ if [ -f "$HOME_DIR/bin/current/CONNECTOR_PROTOCOL" ]; then
24409
+ "$HOME_DIR/bin/current/bin/node" "$HOME_DIR/bin/current/daemon/connector.mjs" --disable-all >/dev/null 2>&1 || exit 1
24410
+ elif [ -f "$HOME_DIR/remote/config.json" ]; then
24411
+ printf '%s\\n' '{"t":"disable"}' | "$HOME_DIR/bin/current/bin/node" "$HOME_DIR/bin/current/daemon/connector.mjs" --admin >/dev/null 2>&1 || exit 1
24412
+ fi
24358
24413
  fi
24359
24414
 
24360
24415
  # systemd user unit
package/dist/install.sh CHANGED
@@ -254,7 +254,7 @@ fi
254
254
 
255
255
  printf '%s\n' "$KIND" > "$HOME_DIR/supervisor"
256
256
  # An upgrade replaces the supervised connector too. Never opt a new host in.
257
- if [ "$START" = 1 ] && [ -f "$HOME_DIR/remote/config.json" ]; then
257
+ if [ "$START" = 1 ] && [ -d "$HOME_DIR/remote" ]; then
258
258
  if [ "$KIND" = systemd ] && [ -f "$HOME/.config/systemd/user/puddle-connector.service" ]; then
259
259
  systemctl --user restart puddle-connector || die "connector restart failed"
260
260
  elif [ "$KIND" = launchd ] && [ -f "$HOME/Library/LaunchAgents/dev.puddle.connector.plist" ]; then