@puddle-code/cli 0.2.7 → 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 (130) hide show
  1. package/CHANGELOG.md +10 -3
  2. package/README.md +1 -1
  3. package/dist/host-control.mjs +64 -61
  4. package/dist/index.js +133 -82
  5. package/dist/install.sh +1 -1
  6. package/dist/public/assets/{App-BkCGcO4p.js → App-BaLJ09-7.js} +2 -2
  7. package/dist/public/assets/{Dashboard-BOK1fw_Q.js → Dashboard-CwqPhujx.js} +1 -1
  8. package/dist/public/assets/{EditorTabClose-CzMQj4jF.js → EditorTabClose-BehvYDm8.js} +1 -1
  9. package/dist/public/assets/{FindWidget-6LifDkeS.js → FindWidget-DkM5Ny1L.js} +1 -1
  10. package/dist/public/assets/{LazyTerminal-Beep0VuJ.js → LazyTerminal-Bx3CSbUu.js} +2 -2
  11. package/dist/public/assets/{ModelRefcount-F2Tf2V5f.js → ModelRefcount-j0XFKXWi.js} +1 -1
  12. package/dist/public/assets/{NewProjectDialog-CoI17sqS.js → NewProjectDialog-CHiC5YY7.js} +1 -1
  13. package/dist/public/assets/{PaneEditorBody-57BHgi2R.js → PaneEditorBody-7n20zvBp.js} +4 -4
  14. package/dist/public/assets/{PdfViewer-T-uYvXEd.js → PdfViewer-CKfdMGYh.js} +2 -2
  15. package/dist/public/assets/SettingsDialog-JzSTfA7-.js +8 -0
  16. package/dist/public/assets/{Terminal-CJMmk0kO.js → Terminal-CW_yt4oG.js} +1 -1
  17. package/dist/public/assets/{Workspace-0P5NTRzC.js → Workspace-BsOrODmq.js} +5 -5
  18. package/dist/public/assets/{abnfDiagram-VCTEODGH-Dl2GTGCZ.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-TLkiib9Z.js → architectureDiagram-5GKGNRK7-BUgo1lsN.js} +1 -1
  21. package/dist/public/assets/{blockDiagram-I7D4REHJ-CFdDK-5H.js → blockDiagram-I7D4REHJ-UglX2bO7.js} +1 -1
  22. package/dist/public/assets/{buffer-store-Pex0dRS2.js → buffer-store-B_VB-G9G.js} +2 -2
  23. package/dist/public/assets/{button-IwQVXqQs.js → button-DlsZoHS1.js} +1 -1
  24. package/dist/public/assets/{c4Diagram-7LVT6UL2-9M5y_7Rr.js → c4Diagram-7LVT6UL2-DVhqTsmi.js} +1 -1
  25. package/dist/public/assets/channel-C5HOkF8K.js +1 -0
  26. package/dist/public/assets/{chunk-2E4U76K2-BEq-rPTx.js → chunk-2E4U76K2-Biysymfb.js} +1 -1
  27. package/dist/public/assets/{chunk-4HAMMTFA-DSsufXZj.js → chunk-4HAMMTFA-CnjG-TUf.js} +1 -1
  28. package/dist/public/assets/{chunk-75Z2AOVW-CUihRphW.js → chunk-75Z2AOVW-BN5baFb9.js} +1 -1
  29. package/dist/public/assets/{chunk-CLGD4ZFX-8FntHoH6.js → chunk-CLGD4ZFX-B0g6JIcT.js} +1 -1
  30. package/dist/public/assets/{chunk-DU6HZSFF-BhI6mdvA.js → chunk-DU6HZSFF-CSc2zx2A.js} +1 -1
  31. package/dist/public/assets/{chunk-F27PBJKO-CflkfzDR.js → chunk-F27PBJKO-CgQY5NLL.js} +1 -1
  32. package/dist/public/assets/{chunk-GMAD6QVW-C6sQnCBM.js → chunk-GMAD6QVW-RUJueMkM.js} +1 -1
  33. package/dist/public/assets/{chunk-GVQU2GXP-BTEA9yBL.js → chunk-GVQU2GXP-fh3FldQM.js} +1 -1
  34. package/dist/public/assets/{chunk-IMKFNOWR-BTN8pZaT.js → chunk-IMKFNOWR-C5sPh7tK.js} +1 -1
  35. package/dist/public/assets/{chunk-L3NEJ4N5-CPMRHY2b.js → chunk-L3NEJ4N5-BHHvLVUm.js} +1 -1
  36. package/dist/public/assets/{chunk-OSK3NFVY-D62Fb29m.js → chunk-OSK3NFVY-DP7Dz8Y0.js} +1 -1
  37. package/dist/public/assets/{chunk-P2QGCYS3-B_AAuki5.js → chunk-P2QGCYS3-FttcQ5j3.js} +1 -1
  38. package/dist/public/assets/{chunk-POPQ4Y6H-C-wGGj3u.js → chunk-POPQ4Y6H-4ZrMU97W.js} +1 -1
  39. package/dist/public/assets/{chunk-PWAF6VOD-DElrnMgG.js → chunk-PWAF6VOD-CihlYgFp.js} +1 -1
  40. package/dist/public/assets/{chunk-SHT3W25Y-D4tV8JU2.js → chunk-SHT3W25Y-FSeRnaXx.js} +1 -1
  41. package/dist/public/assets/{chunk-SVP7TREG-CFj2bSX9.js → chunk-SVP7TREG-Ce-GbVWs.js} +1 -1
  42. package/dist/public/assets/{chunk-TICWLB2K-B-5yvDQM.js → chunk-TICWLB2K-BwNaY0SH.js} +1 -1
  43. package/dist/public/assets/{chunk-TLUHSLCS-CpBFfaGS.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-Bh2z-xpu.js → context-menu-DYqp9bEv.js} +1 -1
  47. package/dist/public/assets/{cssMode-iZ32bnYe.js → cssMode-CuTRdTZz.js} +1 -1
  48. package/dist/public/assets/{cynefin-OW5HDTMX-D5BzXyX_.js → cynefin-OW5HDTMX-Bw6TsxW9.js} +1 -1
  49. package/dist/public/assets/{cynefinDiagram-5FMLGOSQ-CdbgNH0t.js → cynefinDiagram-5FMLGOSQ-BIzNmjbq.js} +1 -1
  50. package/dist/public/assets/{dagre-GXQ25YYZ-B7zDDwyp.js → dagre-GXQ25YYZ-CDytXLeT.js} +1 -1
  51. package/dist/public/assets/{diagram-S7CK7UJ4-WMtT-mtt.js → diagram-S7CK7UJ4-BpamWl9l.js} +1 -1
  52. package/dist/public/assets/{diagram-UQ7AKVKN-DtvvWbC3.js → diagram-UQ7AKVKN-DmgJ3-ND.js} +1 -1
  53. package/dist/public/assets/{diagram-VSXAHHWV-DBLLhbuk.js → diagram-VSXAHHWV-DQZdmIeV.js} +1 -1
  54. package/dist/public/assets/{diagram-VX7I27RA-6sDOwqqU.js → diagram-VX7I27RA-BOjHM12U.js} +1 -1
  55. package/dist/public/assets/{diagram-Z3DM3KII-giEr0RfN.js → diagram-Z3DM3KII-BC_nO99d.js} +1 -1
  56. package/dist/public/assets/{dialog-ClHoWaGa.js → dialog-H68qUfAD.js} +1 -1
  57. package/dist/public/assets/{disclosure-Ch2qCUT3.js → disclosure-wU8K_sQR.js} +1 -1
  58. package/dist/public/assets/{dist-ujnACQRA.js → dist-C5QSPxzH.js} +1 -1
  59. package/dist/public/assets/{dist-C1IA4PaM.js → dist-CgttzJIK.js} +1 -1
  60. package/dist/public/assets/{ebnfDiagram-PWID7BFC-CDfLo0uv.js → ebnfDiagram-PWID7BFC-C9UK3bZX.js} +1 -1
  61. package/dist/public/assets/{erDiagram-RLTQ6QDP-z5xLMSlR.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-C2poetEB.js → ganttDiagram-EL5Y4UJY-CtDwXmwE.js} +1 -1
  65. package/dist/public/assets/{gitGraph-4MIJSDKK-D40KkO3l.js → gitGraph-4MIJSDKK-ChJbe0Zy.js} +1 -1
  66. package/dist/public/assets/{gitGraphDiagram-WWUBYQGX-B4839p8c.js → gitGraphDiagram-WWUBYQGX-DqLFtXkl.js} +1 -1
  67. package/dist/public/assets/{hotkeys-CY98l7MF.js → hotkeys-Cz0t_EHP.js} +1 -1
  68. package/dist/public/assets/{htmlMode-XXBiFVzW.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-R6D6gcdH.js → info-A6RAGUB7-Div0S2Ip.js} +1 -1
  72. package/dist/public/assets/{infoDiagram-27XIBGKW-CQMe7eLM.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-hWJnyGf_.js → ishikawaDiagram-5VMMS53U-DsWVNBtv.js} +1 -1
  75. package/dist/public/assets/{journeyDiagram-3NMN7TZE-DRy7w8VL.js → journeyDiagram-3NMN7TZE-BYYeC34b.js} +1 -1
  76. package/dist/public/assets/{jsonMode-B4KgbobV.js → jsonMode-CziPJMol.js} +1 -1
  77. package/dist/public/assets/{kanban-definition-UXKFOSKX-Dvv0eWiD.js → kanban-definition-UXKFOSKX-BCw3v6NN.js} +1 -1
  78. package/dist/public/assets/{line-K2RkIT6o.js → line-YbGl4cRA.js} +1 -1
  79. package/dist/public/assets/{media-refresh-store-OAgBTFYO.js → media-refresh-store-B2-8HX4O.js} +1 -1
  80. package/dist/public/assets/{mermaid-parser.core-B36v6vc8.js → mermaid-parser.core-Bks1n27y.js} +3 -3
  81. package/dist/public/assets/{mermaid.core-kqdkh9ua.js → mermaid.core-PwPDNHqq.js} +3 -3
  82. package/dist/public/assets/{mindmap-definition-YA3MSWOX-CykDXfif.js → mindmap-definition-YA3MSWOX-BLevROnK.js} +1 -1
  83. package/dist/public/assets/{notification-permission-B9hBLJAo.js → notification-permission-DmY8rjcX.js} +1 -1
  84. package/dist/public/assets/{packet-AYTQ26CC-BDu33u4C.js → packet-AYTQ26CC-CCK4LK_Y.js} +1 -1
  85. package/dist/public/assets/{pdf-BTD1hhPr.js → pdf-CxaY5zdL.js} +1 -1
  86. package/dist/public/assets/{pegDiagram-XKGWAZYB-DWdbGFng.js → pegDiagram-XKGWAZYB-DhkjZiCe.js} +1 -1
  87. package/dist/public/assets/{pie-WAS4IAKB-CeKUt-Xf.js → pie-WAS4IAKB-CHC0k9ep.js} +1 -1
  88. package/dist/public/assets/{pieDiagram-E7YTZNPT-D94ZuRp2.js → pieDiagram-E7YTZNPT-DK2YuIfU.js} +1 -1
  89. package/dist/public/assets/{project-abbrev-E6FngLNw.js → project-abbrev-BYn6QU-q.js} +1 -1
  90. package/dist/public/assets/{quadrantDiagram-AXDQQJYC-DXkTGcPo.js → quadrantDiagram-AXDQQJYC-DI4kRLci.js} +1 -1
  91. package/dist/public/assets/{radar-RG4KPBEZ-C1wtnYrQ.js → radar-RG4KPBEZ-DqqrQ-rz.js} +1 -1
  92. package/dist/public/assets/{railroad-74A4TZTK-Dx_D-zM9.js → railroad-74A4TZTK-CtYFDLom.js} +1 -1
  93. package/dist/public/assets/railroad-abnf-HS5TGJTU-DIXsnxZV.js +1 -0
  94. package/dist/public/assets/railroad-ebnf-LZEXJU2U-B8uF6qy-.js +1 -0
  95. package/dist/public/assets/railroad-peg-WCYAUIDC-Dh5eBaAB.js +1 -0
  96. package/dist/public/assets/{railroadDiagram-O6MQD6OU-DVuwN3bC.js → railroadDiagram-O6MQD6OU-BclO7rZc.js} +1 -1
  97. package/dist/public/assets/{requirementDiagram-BXWQKSXE-nX3JtB1N.js → requirementDiagram-BXWQKSXE-CdtUG7Pb.js} +1 -1
  98. package/dist/public/assets/{sankeyDiagram-P5KCCOFB-DvErANKF.js → sankeyDiagram-P5KCCOFB-BGhtvKxt.js} +1 -1
  99. package/dist/public/assets/{sequenceDiagram-WJ2MYXX4-BruH0Mma.js → sequenceDiagram-WJ2MYXX4-CxFivW0Q.js} +1 -1
  100. package/dist/public/assets/{stateDiagram-D77RDMKH-BMiYrZ8Y.js → stateDiagram-D77RDMKH-BFQhw_cW.js} +1 -1
  101. package/dist/public/assets/stateDiagram-v2-MP3YSRHH-B7cXGe1m.js +1 -0
  102. package/dist/public/assets/{swimlanes-42K2YHIH-CK3jGfyc.js → swimlanes-42K2YHIH-RC1TK3oS.js} +1 -1
  103. package/dist/public/assets/swimlanesDiagram-VR7AAH4N-B1IMbeGf.js +8 -0
  104. package/dist/public/assets/{switch-BrFrNOcn.js → switch-DE8lrtJp.js} +1 -1
  105. package/dist/public/assets/{timeline-definition-24CTP7MA-DHf_pf2_.js → timeline-definition-24CTP7MA-BNpuCp-0.js} +1 -1
  106. package/dist/public/assets/{treeView-Q6P3EWNA-C5uB7_Kg.js → treeView-Q6P3EWNA-BIC2Uin5.js} +1 -1
  107. package/dist/public/assets/{treemap-WGGIJYW6-BGzjaDxJ.js → treemap-WGGIJYW6-DcEgjdWD.js} +1 -1
  108. package/dist/public/assets/{tsMode-C39Hmal5.js → tsMode-D9bCl9c6.js} +1 -1
  109. package/dist/public/assets/{use-ui-state-D5kpevK-.js → use-ui-state-Cqp-5mq9.js} +1 -1
  110. package/dist/public/assets/{vennDiagram-4TSXK5OY-9mb8KINT.js → vennDiagram-4TSXK5OY-CpXtEbyN.js} +1 -1
  111. package/dist/public/assets/{wardley-WFR3VGLG-DW5VvBTA.js → wardley-WFR3VGLG-BzmLqf8a.js} +1 -1
  112. package/dist/public/assets/{wardleyDiagram-VM6X3IG4-DCM5g6RC.js → wardleyDiagram-VM6X3IG4-GlYUe4Pn.js} +1 -1
  113. package/dist/public/assets/{ws-BZ4-LssP.js → ws-DwozYBSn.js} +1 -1
  114. package/dist/public/assets/{xychartDiagram-S5SC5T6Z-Bks8gKZc.js → xychartDiagram-S5SC5T6Z-BYWibIHg.js} +1 -1
  115. package/dist/public/index.html +2 -2
  116. package/package.json +1 -1
  117. package/dist/public/assets/SettingsDialog-CkBdXZyv.js +0 -8
  118. package/dist/public/assets/architecture-7GRP2DOG-UXEF_VQt.js +0 -1
  119. package/dist/public/assets/channel-D3NmDqec.js +0 -1
  120. package/dist/public/assets/classDiagram-ZZMXUADV-8X6mwi75.js +0 -1
  121. package/dist/public/assets/classDiagram-v2-VYDZK3BY-8X6mwi75.js +0 -1
  122. package/dist/public/assets/eventmodeling-NTZA5JFV-CzmQ0jM3.js +0 -1
  123. package/dist/public/assets/flowDiagram-HODETNUW-_tJIQrw7.js +0 -1
  124. package/dist/public/assets/index-D0Lm0Z_9.js +0 -82
  125. package/dist/public/assets/input-BUZTRTzW.js +0 -1
  126. package/dist/public/assets/railroad-abnf-HS5TGJTU-CBfnoAOv.js +0 -1
  127. package/dist/public/assets/railroad-ebnf-LZEXJU2U-0kuF9A11.js +0 -1
  128. package/dist/public/assets/railroad-peg-WCYAUIDC-DCe0oM6p.js +0 -1
  129. package/dist/public/assets/stateDiagram-v2-MP3YSRHH-CF86bnO8.js +0 -1
  130. package/dist/public/assets/swimlanesDiagram-VR7AAH4N-COC62XcR.js +0 -8
package/CHANGELOG.md CHANGED
@@ -4,12 +4,19 @@ Archived release changelog. Governance lives in CLAUDE.md §"Changelog disciplin
4
4
 
5
5
  # Changelog
6
6
 
7
- ## [0.2.7] — 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.
8
13
 
9
14
  ### Changed
10
15
 
11
- - Allow an empty project default base branch to follow the branch currently checked out at the clone location for each new agent or terminal; retain explicit branch choices (daemon/cockpit protocol 21.3; remote protocol remains 2).
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.
12
19
 
13
20
  ### Fixed
14
21
 
15
- - Fix CI deployment validation by creating a private temporary service environment file from the checked-in example before resolving the Compose configuration.
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.
@@ -15775,7 +15775,7 @@ var wsServerMessageSchema = external_exports.discriminatedUnion("t", [
15775
15775
  ]);
15776
15776
 
15777
15777
  // ../shared/src/remote/protocol.ts
15778
- var REMOTE_PROTOCOL_VERSION = 2;
15778
+ var REMOTE_PROTOCOL_VERSION = 3;
15779
15779
  var REMOTE_POLICY = {
15780
15780
  chunkBytes: 32 * 1024,
15781
15781
  frameBytes: 48 * 1024,
@@ -15896,6 +15896,65 @@ var remoteChunkSchema = external_exports.object({
15896
15896
  data: external_exports.string().max(REMOTE_POLICY.chunkBytes)
15897
15897
  }).strict();
15898
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
+
15899
15958
  // ../shared/src/api/cockpit-remote.ts
15900
15959
  var connectorLocalRequestSchema = external_exports.union([
15901
15960
  remoteAdminRequestSchema,
@@ -15923,6 +15982,9 @@ var cockpitRemoteStatusSchema = external_exports.object({
15923
15982
  app: remoteOriginSchema.optional(),
15924
15983
  devices: external_exports.array(remoteDeviceSchema)
15925
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();
15926
15988
 
15927
15989
  // ../shared/src/api/connection-auth.ts
15928
15990
  var CONNECTION_POLICY = {
@@ -15945,7 +16007,7 @@ var authErrorCodeSchema = external_exports.enum([
15945
16007
  "protocol_mismatch"
15946
16008
  ]);
15947
16009
  var controlRequestSchema = external_exports.discriminatedUnion("t", [
15948
- external_exports.object({ t: external_exports.literal("open") }).strict(),
16010
+ external_exports.object({ t: external_exports.literal("open"), profile: profileId.optional() }).strict(),
15949
16011
  external_exports.object({ t: external_exports.literal("renew"), resources: external_exports.array(resourceIdSchema).max(2048) }).strict(),
15950
16012
  external_exports.object({ t: external_exports.literal("close") }).strict()
15951
16013
  ]);
@@ -16034,65 +16096,6 @@ var imageUploadProgressSchema = external_exports.object({
16034
16096
  received: external_exports.number().int().nonnegative().max(IMAGE_UPLOAD_POLICY.imageBytes)
16035
16097
  });
16036
16098
 
16037
- // ../shared/src/remote/service.ts
16038
- var remoteHostSchema = external_exports.object({
16039
- id: remoteIdSchema,
16040
- label: remoteLabelSchema,
16041
- online: external_exports.boolean()
16042
- });
16043
- var remoteHostsSchema = external_exports.array(remoteHostSchema);
16044
- var remoteServiceInfoSchema = external_exports.object({
16045
- providers: external_exports.array(external_exports.enum(["google", "github"])),
16046
- protocol: external_exports.literal(REMOTE_PROTOCOL_VERSION)
16047
- });
16048
- var remoteLoginStateSchema = external_exports.object({
16049
- user: external_exports.object({
16050
- id: remoteAccountSchema,
16051
- name: external_exports.string(),
16052
- email: external_exports.string(),
16053
- emailVerified: external_exports.boolean(),
16054
- twoFactorEnabled: external_exports.boolean()
16055
- }).nullable(),
16056
- mfaRequired: external_exports.boolean()
16057
- });
16058
- var registerHostRequestSchema = external_exports.object({ label: remoteLabelSchema }).strict();
16059
- var registrationResponseSchema = external_exports.object({ host: remoteIdSchema, code: remoteSecretSchema, expires: external_exports.number() }).strict();
16060
- var redeemRegistrationSchema = external_exports.object({ code: remoteSecretSchema }).strict();
16061
- var unregisterHostRequestSchema = external_exports.object({ credential: remoteSecretSchema }).strict();
16062
- var desktopRegistrationSchema = external_exports.object({
16063
- challenge: remoteSecretSchema,
16064
- label: remoteLabelSchema,
16065
- service: remoteOriginSchema,
16066
- app: remoteOriginSchema,
16067
- expires: external_exports.number().int().positive()
16068
- }).strict();
16069
- var registrationStatusSchema = external_exports.object({ ready: external_exports.boolean() }).strict();
16070
- var connectorRegistrationSchema = external_exports.object({
16071
- host: remoteIdSchema,
16072
- account: remoteAccountSchema,
16073
- credential: remoteSecretSchema
16074
- }).strict();
16075
- var connectorConfigSchema = connectorRegistrationSchema.extend({
16076
- service: remoteOriginSchema,
16077
- app: remoteOriginSchema,
16078
- enabled: external_exports.boolean()
16079
- }).strict();
16080
- var connectorSetupSchema = external_exports.object({
16081
- service: remoteOriginSchema.optional(),
16082
- app: remoteOriginSchema.optional(),
16083
- code: remoteSecretSchema.optional(),
16084
- managed: external_exports.boolean().default(true)
16085
- }).strict();
16086
- var remoteIdentitySchema = external_exports.array(external_exports.number().int().min(0).max(255)).min(32).max(256);
16087
- var remoteBrowserHostSchema = external_exports.object({
16088
- host: remoteIdSchema,
16089
- peer: remotePeerSchema,
16090
- account: remoteAccountSchema,
16091
- service: remoteOriginSchema,
16092
- label: external_exports.string(),
16093
- privateKey: remoteIdentitySchema
16094
- }).strict();
16095
-
16096
16099
  // ../shared/src/node/security.ts
16097
16100
  import { createHash, randomBytes } from "node:crypto";
16098
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: 3 };
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 = {};
@@ -19695,7 +19695,7 @@ var wsServerMessageSchema = external_exports.discriminatedUnion("t", [
19695
19695
  ]);
19696
19696
 
19697
19697
  // ../shared/src/remote/protocol.ts
19698
- var REMOTE_PROTOCOL_VERSION = 2;
19698
+ var REMOTE_PROTOCOL_VERSION = 3;
19699
19699
  var REMOTE_POLICY = {
19700
19700
  chunkBytes: 32 * 1024,
19701
19701
  frameBytes: 48 * 1024,
@@ -19816,6 +19816,65 @@ var remoteChunkSchema = external_exports.object({
19816
19816
  data: external_exports.string().max(REMOTE_POLICY.chunkBytes)
19817
19817
  }).strict();
19818
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
+
19819
19878
  // ../shared/src/api/cockpit-remote.ts
19820
19879
  var connectorLocalRequestSchema = external_exports.union([
19821
19880
  remoteAdminRequestSchema,
@@ -19843,6 +19902,9 @@ var cockpitRemoteStatusSchema = external_exports.object({
19843
19902
  app: remoteOriginSchema.optional(),
19844
19903
  devices: external_exports.array(remoteDeviceSchema)
19845
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();
19846
19908
 
19847
19909
  // ../shared/src/api/connection-auth.ts
19848
19910
  var CONNECTION_POLICY = {
@@ -19865,7 +19927,7 @@ var authErrorCodeSchema = external_exports.enum([
19865
19927
  "protocol_mismatch"
19866
19928
  ]);
19867
19929
  var controlRequestSchema = external_exports.discriminatedUnion("t", [
19868
- external_exports.object({ t: external_exports.literal("open") }).strict(),
19930
+ external_exports.object({ t: external_exports.literal("open"), profile: profileId.optional() }).strict(),
19869
19931
  external_exports.object({ t: external_exports.literal("renew"), resources: external_exports.array(resourceIdSchema).max(2048) }).strict(),
19870
19932
  external_exports.object({ t: external_exports.literal("close") }).strict()
19871
19933
  ]);
@@ -19954,65 +20016,6 @@ var imageUploadProgressSchema = external_exports.object({
19954
20016
  received: external_exports.number().int().nonnegative().max(IMAGE_UPLOAD_POLICY.imageBytes)
19955
20017
  });
19956
20018
 
19957
- // ../shared/src/remote/service.ts
19958
- var remoteHostSchema = external_exports.object({
19959
- id: remoteIdSchema,
19960
- label: remoteLabelSchema,
19961
- online: external_exports.boolean()
19962
- });
19963
- var remoteHostsSchema = external_exports.array(remoteHostSchema);
19964
- var remoteServiceInfoSchema = external_exports.object({
19965
- providers: external_exports.array(external_exports.enum(["google", "github"])),
19966
- protocol: external_exports.literal(REMOTE_PROTOCOL_VERSION)
19967
- });
19968
- var remoteLoginStateSchema = external_exports.object({
19969
- user: external_exports.object({
19970
- id: remoteAccountSchema,
19971
- name: external_exports.string(),
19972
- email: external_exports.string(),
19973
- emailVerified: external_exports.boolean(),
19974
- twoFactorEnabled: external_exports.boolean()
19975
- }).nullable(),
19976
- mfaRequired: external_exports.boolean()
19977
- });
19978
- var registerHostRequestSchema = external_exports.object({ label: remoteLabelSchema }).strict();
19979
- var registrationResponseSchema = external_exports.object({ host: remoteIdSchema, code: remoteSecretSchema, expires: external_exports.number() }).strict();
19980
- var redeemRegistrationSchema = external_exports.object({ code: remoteSecretSchema }).strict();
19981
- var unregisterHostRequestSchema = external_exports.object({ credential: remoteSecretSchema }).strict();
19982
- var desktopRegistrationSchema = external_exports.object({
19983
- challenge: remoteSecretSchema,
19984
- label: remoteLabelSchema,
19985
- service: remoteOriginSchema,
19986
- app: remoteOriginSchema,
19987
- expires: external_exports.number().int().positive()
19988
- }).strict();
19989
- var registrationStatusSchema = external_exports.object({ ready: external_exports.boolean() }).strict();
19990
- var connectorRegistrationSchema = external_exports.object({
19991
- host: remoteIdSchema,
19992
- account: remoteAccountSchema,
19993
- credential: remoteSecretSchema
19994
- }).strict();
19995
- var connectorConfigSchema = connectorRegistrationSchema.extend({
19996
- service: remoteOriginSchema,
19997
- app: remoteOriginSchema,
19998
- enabled: external_exports.boolean()
19999
- }).strict();
20000
- var connectorSetupSchema = external_exports.object({
20001
- service: remoteOriginSchema.optional(),
20002
- app: remoteOriginSchema.optional(),
20003
- code: remoteSecretSchema.optional(),
20004
- managed: external_exports.boolean().default(true)
20005
- }).strict();
20006
- var remoteIdentitySchema = external_exports.array(external_exports.number().int().min(0).max(255)).min(32).max(256);
20007
- var remoteBrowserHostSchema = external_exports.object({
20008
- host: remoteIdSchema,
20009
- peer: remotePeerSchema,
20010
- account: remoteAccountSchema,
20011
- service: remoteOriginSchema,
20012
- label: external_exports.string(),
20013
- privateKey: remoteIdentitySchema
20014
- }).strict();
20015
-
20016
20019
  // src/lib/transport/local.ts
20017
20020
  import { spawn } from "node:child_process";
20018
20021
  import { copyFileSync, mkdirSync, readFileSync } from "node:fs";
@@ -20341,7 +20344,12 @@ function parseRemoteArgs(args) {
20341
20344
  for (let i = 0; i < rest.length; i++) {
20342
20345
  const arg = rest[i];
20343
20346
  if (arg === "--foreground") command.foreground = true;
20344
- 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") {
20345
20353
  const value = remoteOriginSchema.safeParse(rest[++i]);
20346
20354
  if (!value.success) throw new CliError("bad_arguments", `${arg} needs an exact HTTPS origin`);
20347
20355
  if (arg === "--service") command.service = value.data;
@@ -20366,6 +20374,10 @@ function parseRemoteArgs(args) {
20366
20374
  throw new CliError("bad_arguments", "Configuration options apply only to remote enable");
20367
20375
  if (!!command.service !== !!command.app)
20368
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");
20369
20381
  return command;
20370
20382
  }
20371
20383
  async function registrationCode() {
@@ -20405,12 +20417,21 @@ async function runRemote(command) {
20405
20417
  "The installed daemon does not include mobile access",
20406
20418
  `puddle upgrade daemon${command.host ? ` ${command.host}` : ""}`
20407
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
+ );
20408
20426
  if (command.action === "run") {
20409
20427
  const result2 = await transport.exec(base, { onStdout: (text) => process.stdout.write(text) });
20410
20428
  return result2.code;
20411
20429
  }
20412
20430
  if (command.action === "reset") {
20413
- 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
+ });
20414
20435
  if (result2.code !== 0)
20415
20436
  throw new CliError("bad_arguments", result2.stderr.trim() || "Reset failed");
20416
20437
  process.stdout.write(
@@ -20427,7 +20448,9 @@ async function runRemote(command) {
20427
20448
  const result = await transport.exec(
20428
20449
  `${base} ${command.action === "enable" ? "--configure" : "--admin"}`,
20429
20450
  {
20430
- 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",
20431
20454
  timeoutMs: 3e4
20432
20455
  }
20433
20456
  );
@@ -20494,14 +20517,15 @@ usage:
20494
20517
  puddle install <daemon|desktop>[@version] [user@host] [--tarball <path>]
20495
20518
  puddle upgrade [cli|daemon|desktop][@version] [user@host] [--tarball <path>]
20496
20519
  puddle remove <cli|daemon|desktop> [user@host] [--yes] [--purge]
20497
- 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>
20498
20521
  [--foreground]
20499
- puddle remote status|pair|devices|disable|reset|run [user@host]
20500
- 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]
20501
20525
  puddle --version | --help
20502
20526
 
20503
20527
  --version lists the installed CLI, daemon, and desktop app with the protocol
20504
- 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.
20505
20529
 
20506
20530
  launch serves the cockpit at http://localhost:7433 against the daemon on this
20507
20531
  machine when no host (or 'local') is given \u2014 installing it under ~/.puddle if
@@ -21108,10 +21132,11 @@ function jsonLines(stream, receive, fail2) {
21108
21132
 
21109
21133
  // ../shared/src/node/host-control.ts
21110
21134
  var HostControlClient = class {
21111
- constructor(openChannel, automatic = true, error51 = (_code, message) => new Error(message)) {
21135
+ constructor(openChannel, automatic = true, error51 = (_code, message) => new Error(message), profile) {
21112
21136
  this.openChannel = openChannel;
21113
21137
  this.automatic = automatic;
21114
21138
  this.error = error51;
21139
+ this.profile = profile;
21115
21140
  this.timer = setInterval(() => {
21116
21141
  if (this.channel && performance.now() >= this.until)
21117
21142
  this.lose(this.channel, "upstream_expired");
@@ -21254,7 +21279,7 @@ var HostControlClient = class {
21254
21279
  channel.once("error", closed);
21255
21280
  channel.once("close", closed);
21256
21281
  channel.once("end", closed);
21257
- send({ t: "open" });
21282
+ send({ t: "open", ...this.profile ? { profile: this.profile } : {} });
21258
21283
  });
21259
21284
  } finally {
21260
21285
  this.connecting = false;
@@ -21528,7 +21553,7 @@ import { readFileSync as readFileSync4 } from "node:fs";
21528
21553
  import { dirname as dirname4, join as join5 } from "node:path";
21529
21554
  import { fileURLToPath as fileURLToPath2 } from "node:url";
21530
21555
  function cliVersion() {
21531
- if (true) return "0.2.7";
21556
+ if (true) return "0.2.8";
21532
21557
  const here = dirname4(fileURLToPath2(import.meta.url));
21533
21558
  for (const candidate of [
21534
21559
  join5(here, "..", "..", "package.json"),
@@ -21908,7 +21933,8 @@ var RELEASE_PROTOCOLS = {
21908
21933
  "0.2.4": { major: 21, minor: 2 },
21909
21934
  "0.2.5": { major: 21, minor: 2 },
21910
21935
  "0.2.6": { major: 21, minor: 2 },
21911
- "0.2.7": { major: 21, minor: 3 }
21936
+ "0.2.7": { major: 21, minor: 3 },
21937
+ "0.2.8": { major: 22, minor: 0 }
21912
21938
  };
21913
21939
  function validProtocol(value) {
21914
21940
  if (typeof value !== "object" || value === null) return false;
@@ -21967,6 +21993,15 @@ function daemonProtocol(home, version2) {
21967
21993
  }
21968
21994
  return releasedProtocol(version2);
21969
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
+ }
21970
22005
  async function installedComponentVersions(opts = {}) {
21971
22006
  const home = opts.home ?? clientHome();
21972
22007
  const cli = {
@@ -21977,10 +22012,12 @@ async function installedComponentVersions(opts = {}) {
21977
22012
  };
21978
22013
  const installedDaemon = daemonVersion(home);
21979
22014
  const installedDaemonProtocol = installedDaemon === void 0 ? void 0 : daemonProtocol(home, installedDaemon);
22015
+ const connectorProtocol = installedDaemon === void 0 ? void 0 : daemonConnectorProtocol(home, installedDaemon);
21980
22016
  const daemon = installedDaemon === void 0 ? { component: "daemon", installed: false } : {
21981
22017
  component: "daemon",
21982
22018
  installed: true,
21983
22019
  version: installedDaemon,
22020
+ ...connectorProtocol !== void 0 ? { connectorProtocol } : {},
21984
22021
  ...installedDaemonProtocol ? { protocol: installedDaemonProtocol } : {}
21985
22022
  };
21986
22023
  const recordedDesktop = readDesktopInstallation(desktopRecordFile(home));
@@ -22012,7 +22049,7 @@ function formatComponentVersions(components) {
22012
22049
  const name = component.component.padEnd(7);
22013
22050
  if (!component.installed) return `${name} not installed`;
22014
22051
  const version2 = component.version ?? "unknown version";
22015
- 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";
22016
22053
  return `${name} ${version2} (${protocol})`;
22017
22054
  }).join("\n");
22018
22055
  }
@@ -23281,13 +23318,18 @@ function remoteAccessHandler(control) {
23281
23318
  return async (req, res, authorised) => {
23282
23319
  if (!control) return fail(res, 404, "remote_controls_unavailable");
23283
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;
23284
23326
  const request = req.method === "POST" ? cockpitRemoteRequestSchema.parse(await readJson(req)) : null;
23285
23327
  if (!authorised()) return fail(res, 401, "browser_rejected");
23286
23328
  if (busy)
23287
23329
  return fail(res, 409, "remote_control_busy", "A host operation is already in progress.");
23288
23330
  busy = true;
23289
23331
  try {
23290
- 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);
23291
23333
  if (!authorised()) return fail(res, 401, "browser_rejected");
23292
23334
  json2(res, 200, response);
23293
23335
  } catch (error51) {
@@ -23540,11 +23582,12 @@ var RemoteAccessControl = class {
23540
23582
  if (result.code !== 0)
23541
23583
  throw new Error("Host control is unavailable. Check the host connection.");
23542
23584
  return {
23543
- availability: result.stdout.includes("cockpit controls 1") ? "ready" : "upgrade_required",
23585
+ availability: result.stdout.includes("cockpit controls 2") ? "ready" : "upgrade_required",
23544
23586
  canDeleteRegistration: result.stdout.includes("delete registration 1")
23545
23587
  };
23546
23588
  }
23547
- async status() {
23589
+ async status(profile) {
23590
+ profileId.parse(profile);
23548
23591
  const capabilities = await this.capabilities();
23549
23592
  if (capabilities.availability !== "ready")
23550
23593
  return {
@@ -23555,12 +23598,16 @@ var RemoteAccessControl = class {
23555
23598
  supervisor: null,
23556
23599
  devices: []
23557
23600
  };
23558
- 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
+ });
23559
23605
  if (result.code !== 0) throw new Error("Could not read remote access status on this host.");
23560
23606
  return cockpitRemoteStatusSchema.parse({ ...JSON.parse(result.stdout), ...capabilities });
23561
23607
  }
23562
- async request(value, authorised) {
23608
+ async request(value, authorised, profile) {
23563
23609
  const request = cockpitRemoteRequestSchema.parse(value);
23610
+ profileId.parse(profile);
23564
23611
  const capabilities = await this.capabilities();
23565
23612
  if (capabilities.availability !== "ready")
23566
23613
  throw new Error("Upgrade the daemon on this host to manage remote access here.");
@@ -23568,7 +23615,7 @@ var RemoteAccessControl = class {
23568
23615
  throw new Error("Upgrade the daemon on this host to delete its remote registration.");
23569
23616
  if (!authorised()) throw new Error("Browser authorisation expired before dispatch.");
23570
23617
  const flag = request.t === "enable" ? "--configure" : request.t === "reset" ? "--reset" : "--admin";
23571
- 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 };
23572
23619
  const result = await this.transport.exec(`${binary} ${flag}`, {
23573
23620
  stdin: JSON.stringify(payload) + "\n",
23574
23621
  timeoutMs: 3e4
@@ -24357,8 +24404,12 @@ HOME_DIR="\${PUDDLE_HOME:-$HOME/.puddle}"
24357
24404
  say() { printf 'puddled remove: %s\\n' "$1"; }
24358
24405
 
24359
24406
  # Persist remote disable before unregistering either supervisor.
24360
- if [ -f "$HOME_DIR/bin/current/daemon/connector.mjs" ] && [ -f "$HOME_DIR/remote/config.json" ]; then
24361
- 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
24362
24413
  fi
24363
24414
 
24364
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