@rubytech/create-maxy-code 0.1.307 → 0.1.309
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/claude-ptys-slice.test.js +1 -1
- package/dist/__tests__/cloudflared-slice.test.js +1 -1
- package/dist/__tests__/macos-darwin-branch.test.js +4 -6
- package/package.json +1 -1
- package/payload/platform/lib/admin-access-password/__tests__/index.test.ts +142 -0
- package/payload/platform/lib/admin-access-password/dist/index.d.ts +49 -0
- package/payload/platform/lib/admin-access-password/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/admin-access-password/dist/index.js +198 -0
- package/payload/platform/lib/admin-access-password/dist/index.js.map +1 -0
- package/payload/platform/lib/admin-access-password/src/index.ts +176 -0
- package/payload/platform/lib/admin-access-password/tsconfig.json +8 -0
- package/payload/platform/lib/models/dist/index.d.ts +13 -0
- package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/models/dist/index.js +20 -1
- package/payload/platform/lib/models/dist/index.js.map +1 -1
- package/payload/platform/lib/models/src/index.ts +19 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/PLUGIN.md +1 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js +63 -19
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/admin-user-management/SKILL.md +8 -2
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +23 -3
- package/payload/platform/plugins/docs/references/admin-ui.md +21 -1
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/scripts/check-no-esm-require.mjs +4 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +4 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +193 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +12 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +52 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +9 -3
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.d.ts +8 -0
- package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.js +7 -0
- package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts +8 -0
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -0
- package/payload/platform/services/webchat-channel/dist/instructions.js +44 -0
- package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -0
- package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.js +11 -18
- package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
- package/payload/server/{chunk-4QFPGAUZ.js → chunk-J6WDAWFJ.js} +190 -82
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/AccessGate-CU4Qw6M6.js +1 -0
- package/payload/server/public/assets/AdminLoginScreens-DUpRIM1h.js +1 -0
- package/payload/server/public/assets/AdminShell-DkoQSsqo.js +1 -0
- package/payload/server/public/assets/{Checkbox-DoPOlZTV.js → Checkbox-DMA1hVhn.js} +1 -1
- package/payload/server/public/assets/OperatorConversations-BIHiyyxU.js +1 -0
- package/payload/server/public/assets/admin-BHvOMcCh.js +1 -0
- package/payload/server/public/assets/{arc-DxSm8tli.js → arc-Dl9QFDgW.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-Crq5RSDG.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-7JSAh0vL.js → architectureDiagram-Q4EWVU46-CNLQUVi9.js} +1 -1
- package/payload/server/public/assets/{audio-attachment-mime-BA10IzqQ.js → audio-attachment-mime-DOBET-W1.js} +3 -3
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DLoVmHKD.js → blockDiagram-DXYQGD6D-B-QxfVjk.js} +1 -1
- package/payload/server/public/assets/brand-4F9ZXBF8.css +1 -0
- package/payload/server/public/assets/{brand-BaRMO3mZ.js → brand-C7kj0USi.js} +1 -1
- package/payload/server/public/assets/browser-eLSiC7_b.js +1 -0
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Nv1G0o9P.js → c4Diagram-AHTNJAMY-NuYFvPDU.js} +1 -1
- package/payload/server/public/assets/channel-KT66MFN2.js +1 -0
- package/payload/server/public/assets/chat-DedpVKUl.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-BpqPMhoA.js → chunk-2KRD3SAO-l5VL1KQm.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-DgXHlVU_.js → chunk-336JU56O-C5gVznC2.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-CWMiOm8Y.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-nwyZSZH8.js → chunk-4BX2VUAB-BtMVz_Sq.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-Tfxz9LHX.js → chunk-4TB4RGXK-C8-dmCuT.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-6FMJQGXG.js → chunk-55IACEB6-C5gWvEJW.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-g2FgZF3D.js → chunk-5FUZZQ4R-BZ7VZoAC.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-DtLwXsPH.js → chunk-5PVQY5BW-C_ajQOGC.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-K91CP5ZU.js → chunk-67CJDMHE-BJOR2dwK.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-BGpCQhqK.js → chunk-7N4EOEYR-DvZLpquX.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-jkDbInck.js → chunk-AA7GKIK3-h5tVsPlW.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-mDosdzGs.js → chunk-BSJP7CBP-DLOF2-m3.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-DhBxewpQ.js → chunk-CIAEETIT-CQRQMPCf.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-B7c-9Emg.js → chunk-EDXVE4YY-K9-EfuM2.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-Cqhhncox.js → chunk-ENJZ2VHE-DVoy6NvU.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-BpDq6wj1.js → chunk-FMBD7UC4-CQn_2o2b.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-Ds02-ktu.js → chunk-FOC6F5B3-CuN73goS.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-BTX5POFr.js → chunk-ICPOFSXX-CKhl9J-H.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-Du1PXXBU.js → chunk-K5T4RW27-CBskuQmq.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-siasOAf8.js → chunk-KGLVRYIC-Chtjt8xK.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-xf1rbZtf.js → chunk-LIHQZDEY-EOBiBNSH.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-DeTLQ_LD.js → chunk-ORNJ4GCN-uPPq-5MN.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-DQ7_oVJn.js → chunk-OYMX7WX6-BRzbxJOT.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-DCzpF46A.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-CXmFUKgn.js → chunk-U2HBQHQK-Bndyn5nF.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-Bj8-8Wkz.js → chunk-X2U36JSP-BspGBHXW.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-Con3TXqt.js → chunk-XPW4576I-HgXQ2k9h.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-Dx8BHGWf.js → chunk-YZCP3GAM-C7oTyCnw.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-Dp4Q5Y-f.js → chunk-ZZ45TVLE-CufWa7QL.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-QOU4HzJJ.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DcOUai3Z.js +1 -0
- package/payload/server/public/assets/clone-CHh05KN-.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-pZiCv69E.js → cose-bilkent-S5V4N54A-BM3yEbF-.js} +1 -1
- package/payload/server/public/assets/{dagre-CLqhEgbL.js → dagre-C7WHNZO8.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-BCxE8iyk.js → dagre-KV5264BT-bcZx3l06.js} +1 -1
- package/payload/server/public/assets/data-BcoBY39U.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-slUEdZzz.js → diagram-5BDNPKRD-B7VotaMF.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-DPcraMfu.js → diagram-G4DWMVQ6-CWWvEsFx.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DR6luhGK.js → diagram-MMDJMWI5-DYHVkTYJ.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-Jap1B4wA.js → diagram-TYMM5635-CHeB6Ama.js} +1 -1
- package/payload/server/public/assets/{dist-Dbh7HrZX.js → dist-CjjtmoWL.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-DJKUs2hO.js → erDiagram-SMLLAGMA-C9gog8QP.js} +1 -1
- package/payload/server/public/assets/{flatten-Cl1Bc3dR.js → flatten-QcJDm7yK.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-C8W-ZZ9W.js → flowDiagram-DWJPFMVM-B2O9lKTh.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DYCX4Xu2.js → ganttDiagram-T4ZO3ILL-DEa4AwbR.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-BC-u4jgy.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-CZu_fpgS.js → gitGraphDiagram-UUTBAWPF-BjXPQpBL.js} +1 -1
- package/payload/server/public/assets/{graph-D29p1FJH.js → graph-C7Hye_vp.js} +2 -2
- package/payload/server/public/assets/{graph-labels-DF3QVHkH.js → graph-labels-YYgGsEVd.js} +1 -1
- package/payload/server/public/assets/{graphlib-Bdp7TA4y.js → graphlib-CBevn2DP.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-DPUetTz-.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-q2dl09-M.js +2 -0
- package/payload/server/public/assets/{isEmpty-D1pGOD1J.js → isEmpty-BO6BAEn7.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-B7KfIX6z.js → ishikawaDiagram-UXIWVN3A-CPLfpvqv.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CSDwBfhF.js → journeyDiagram-VCZTEJTY-CTHe8MiD.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CWzcEKTr.js → kanban-definition-6JOO6SKY-Bm9h1O3Y.js} +1 -1
- package/payload/server/public/assets/{line-BNQSlbYn.js → line-C31b0rtY.js} +1 -1
- package/payload/server/public/assets/{linear-BN6kGN93.js → linear-Cfm_8_pU.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-CcFhkElq.js → mermaid-parser.core-B3tGwOcE.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-BsIeJ7Cc.js → mermaid.core-BM3s85ZW.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CQVzj6D_.js → mindmap-definition-QFDTVHPH-CaGv_mIB.js} +1 -1
- package/payload/server/public/assets/operator-WsXhcbBF.js +1 -0
- package/payload/server/public/assets/{ordinal-CBZeH4Yp.js → ordinal-jLCwuvYg.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-BcfR-ZwA.js +1 -0
- package/payload/server/public/assets/page-BhHTnqv4.js +1 -0
- package/payload/server/public/assets/pie-ZZUOXDRM-BiKgZdNB.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-DnrQ9fyn.js → pieDiagram-DEJITSTG-BhAXps4u.js} +1 -1
- package/payload/server/public/assets/public-ViXjC_dA.js +6 -0
- package/payload/server/public/assets/public-next-BKECyMz2.js +1 -0
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BQWlCyWi.js → quadrantDiagram-34T5L4WZ-BWtTdNs8.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-nvCjiW_J.js +1 -0
- package/payload/server/public/assets/{reduce-PuPlFPRX.js → reduce-Dmi_NdVH.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-Du_vZhU1.js → requirementDiagram-MS252O5E-CWU0qCcP.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Cf6Z8GPQ.js → sankeyDiagram-XADWPNL6-DYvutQld.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-CS8GVol8.js → sequenceDiagram-FGHM5R23-Cir0hBWS.js} +1 -1
- package/payload/server/public/assets/{src-BoaldmnP.js → src-CwB968DO.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-Bv1NW2F1.js → stateDiagram-FHFEXIEX-Be-h8YSS.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CAnmjSj7.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-ClGYAsr0.js → timeline-definition-GMOUNBTQ-C3C4Wuyk.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BinXCVyM.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-CSmh20Ze.js +1 -0
- package/payload/server/public/assets/{useSelectionMode-ghXuZicl.js → useSelectionMode-CG_Iel5F.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-C2wTcxQT.js → vennDiagram-DHZGUBPP-mDclw0Sa.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-BiCmRKWx.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-D86-ivEx.js → wardleyDiagram-NUSXRM2D-mvk-YA9g.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-Ba5WAN8P.js → xychartDiagram-5P7HB3ND-9M7k1hmD.js} +1 -1
- package/payload/server/public/browser.html +8 -8
- package/payload/server/public/chat.html +11 -11
- package/payload/server/public/data.html +7 -7
- package/payload/server/public/graph.html +10 -10
- package/payload/server/public/index.html +10 -10
- package/payload/server/public/operator.html +13 -13
- package/payload/server/public/public-next.html +24 -0
- package/payload/server/public/public.html +9 -8
- package/payload/server/server.js +4450 -3781
- package/dist/__tests__/onboarding-state-readback.test.js +0 -61
- package/dist/__tests__/rss-sampler-installer.test.js +0 -27
- package/dist/onboarding-readback.js +0 -27
- package/payload/server/public/assets/AdminLoginScreens-BsC-EwAn.js +0 -1
- package/payload/server/public/assets/AdminShell-CiKKN22G.js +0 -1
- package/payload/server/public/assets/admin-DSwmdCKp.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-6g9jRVgc.js +0 -1
- package/payload/server/public/assets/brand-C001cin3.css +0 -1
- package/payload/server/public/assets/browser-BKR1eJJb.js +0 -1
- package/payload/server/public/assets/channel-BgQLJanG.js +0 -1
- package/payload/server/public/assets/chat-DZXNRiy-.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-Dr_XVuUq.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-DF4o9HRJ.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-DAbPKU6u.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BKuFQLcv.js +0 -1
- package/payload/server/public/assets/clone-DnNHGhNe.js +0 -1
- package/payload/server/public/assets/data-CuVmW1WN.js +0 -1
- package/payload/server/public/assets/file-download-4_hQmMwU.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-g7mvu6IY.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-DZqJuIkB.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-cGfGccHz.js +0 -2
- package/payload/server/public/assets/operator-CQRaBNN7.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Hn8rlHpy.js +0 -1
- package/payload/server/public/assets/page-Dz2F3QtB.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-BPGWVqBm.js +0 -1
- package/payload/server/public/assets/public-B7BQwWpP.js +0 -6
- package/payload/server/public/assets/radar-PYXPWWZC-DMdLrj3E.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BGUCxPmp.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CWxofUbI.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-Cfgb_ZG0.js +0 -1
- package/payload/server/public/assets/wardley-RL74JXVD-B45olYjj.js +0 -1
- /package/payload/server/public/assets/{file-download-qc_xy7Az.css → OperatorConversations-qc_xy7Az.css} +0 -0
- /package/payload/server/public/assets/{_baseFor-brRjpUOX.js → _baseFor-D8P3gUw3.js} +0 -0
- /package/payload/server/public/assets/{array-BGFCBI0e.js → array-CLwNaqU1.js} +0 -0
- /package/payload/server/public/assets/{chunk-Pqm5yXtL.js → chunk-CAM3fms7.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-TvRJ2tGX.js → cytoscape.esm-mZ4wTuB7.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-CRZydyG6.js → defaultLocale-D_VMtRaY.js} +0 -0
- /package/payload/server/public/assets/{init-B8gtcn7T.js → init-vVpfz1D6.js} +0 -0
- /package/payload/server/public/assets/{katex-RxgSu_dy.js → katex-DaHGEgm7.js} +0 -0
- /package/payload/server/public/assets/{path-DZF-JdEe.js → path-CuyvWNAH.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-CQ36nxok.js → preload-helper-TKOBYGYD.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-6CnTHTkH.js → rough.esm-JX0wREDd.js} +0 -0
|
@@ -2756,23 +2756,9 @@ function websockifyLog(event, fields = {}) {
|
|
|
2756
2756
|
console.error(`[websockify] ${formatKv({ event, ...fields })}`);
|
|
2757
2757
|
}
|
|
2758
2758
|
|
|
2759
|
-
//
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
{ key: "length", label: "At least 8 characters", met: password.length >= 8 },
|
|
2763
|
-
{ key: "number", label: "Contains a number", met: /\d/.test(password) },
|
|
2764
|
-
{ key: "special", label: "Contains a special character", met: /[^A-Za-z0-9]/.test(password) },
|
|
2765
|
-
{ key: "whitespace", label: "No spaces", met: password.length > 0 && !/\s/.test(password) }
|
|
2766
|
-
];
|
|
2767
|
-
}
|
|
2768
|
-
function isPasswordValid(password) {
|
|
2769
|
-
return validatePasswordStrength(password).every((r) => r.met);
|
|
2770
|
-
}
|
|
2771
|
-
|
|
2772
|
-
// app/lib/remote-auth.ts
|
|
2773
|
-
import { scrypt, randomBytes, timingSafeEqual, createHmac } from "crypto";
|
|
2774
|
-
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
2775
|
-
import { dirname } from "path";
|
|
2759
|
+
// ../lib/admin-access-password/src/index.ts
|
|
2760
|
+
import { scrypt, randomBytes, timingSafeEqual } from "crypto";
|
|
2761
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, renameSync, unlinkSync } from "fs";
|
|
2776
2762
|
var SCRYPT_N = 16384;
|
|
2777
2763
|
var SCRYPT_R = 8;
|
|
2778
2764
|
var SCRYPT_P = 1;
|
|
@@ -2785,56 +2771,170 @@ function scryptAsync(password, salt) {
|
|
|
2785
2771
|
});
|
|
2786
2772
|
});
|
|
2787
2773
|
}
|
|
2788
|
-
async function
|
|
2774
|
+
async function hashAccessPassword(password) {
|
|
2789
2775
|
const salt = randomBytes(32);
|
|
2790
2776
|
const hash = await scryptAsync(password, salt);
|
|
2791
2777
|
return `${salt.toString("hex")}:${hash.toString("hex")}`;
|
|
2792
2778
|
}
|
|
2793
|
-
async function
|
|
2794
|
-
const
|
|
2795
|
-
if (
|
|
2796
|
-
const
|
|
2797
|
-
const
|
|
2798
|
-
if (
|
|
2799
|
-
const salt = Buffer.from(saltHex, "hex");
|
|
2800
|
-
const storedHash = Buffer.from(hashHex, "hex");
|
|
2801
|
-
if (storedHash.length !== SCRYPT_KEYLEN) {
|
|
2802
|
-
return { ok: false, why: "hash-length", hashBytes: storedHash.length };
|
|
2803
|
-
}
|
|
2779
|
+
async function matchesHash(password, stored) {
|
|
2780
|
+
const colon = stored.indexOf(":");
|
|
2781
|
+
if (colon === -1) return false;
|
|
2782
|
+
const salt = Buffer.from(stored.slice(0, colon), "hex");
|
|
2783
|
+
const storedHash = Buffer.from(stored.slice(colon + 1), "hex");
|
|
2784
|
+
if (storedHash.length !== SCRYPT_KEYLEN) return false;
|
|
2804
2785
|
let computed;
|
|
2805
2786
|
try {
|
|
2806
2787
|
computed = await scryptAsync(password, salt);
|
|
2807
2788
|
} catch {
|
|
2808
|
-
return
|
|
2809
|
-
}
|
|
2810
|
-
if (timingSafeEqual(computed, storedHash)) {
|
|
2811
|
-
return { ok: true, hashBytes: storedHash.length };
|
|
2789
|
+
return false;
|
|
2812
2790
|
}
|
|
2813
|
-
return
|
|
2791
|
+
return timingSafeEqual(computed, storedHash);
|
|
2814
2792
|
}
|
|
2815
|
-
function
|
|
2816
|
-
if (!existsSync2(
|
|
2817
|
-
const
|
|
2818
|
-
|
|
2793
|
+
function readUsers(usersFile) {
|
|
2794
|
+
if (!existsSync2(usersFile)) return [];
|
|
2795
|
+
const raw2 = readFileSync2(usersFile, "utf-8").trim();
|
|
2796
|
+
if (!raw2) return [];
|
|
2797
|
+
const parsed = JSON.parse(raw2);
|
|
2798
|
+
if (!Array.isArray(parsed)) throw new Error("users.json is not an array");
|
|
2799
|
+
return parsed;
|
|
2800
|
+
}
|
|
2801
|
+
function writeUsersAtomic(usersFile, users) {
|
|
2802
|
+
const tmp = `${usersFile}.tmp-${process.pid}`;
|
|
2803
|
+
writeFileSync(tmp, JSON.stringify(users, null, 2) + "\n", { mode: 384 });
|
|
2804
|
+
renameSync(tmp, usersFile);
|
|
2805
|
+
}
|
|
2806
|
+
async function setAccessPassword(userId, password, usersFile) {
|
|
2807
|
+
const users = readUsers(usersFile);
|
|
2808
|
+
const idx = users.findIndex((u) => u.userId === userId);
|
|
2809
|
+
if (idx === -1) throw new Error(`no users.json record for userId=${userId}`);
|
|
2810
|
+
users[idx] = { ...users[idx], accessHash: await hashAccessPassword(password) };
|
|
2811
|
+
writeUsersAtomic(usersFile, users);
|
|
2819
2812
|
}
|
|
2820
|
-
function
|
|
2813
|
+
async function verifyAccessPassword(password, usersFile) {
|
|
2814
|
+
let users;
|
|
2821
2815
|
try {
|
|
2822
|
-
|
|
2823
|
-
const content = readFileSync2(REMOTE_PASSWORD_FILE, "utf-8").trim();
|
|
2824
|
-
if (!content || !content.includes(":")) return null;
|
|
2825
|
-
return content;
|
|
2816
|
+
users = readUsers(usersFile);
|
|
2826
2817
|
} catch {
|
|
2827
2818
|
return null;
|
|
2828
2819
|
}
|
|
2820
|
+
for (const u of users) {
|
|
2821
|
+
if (typeof u.accessHash === "string" && await matchesHash(password, u.accessHash)) {
|
|
2822
|
+
return u.userId;
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
return null;
|
|
2826
|
+
}
|
|
2827
|
+
async function accessPasswordCollides(password, usersFile, excludeUserId) {
|
|
2828
|
+
let users;
|
|
2829
|
+
try {
|
|
2830
|
+
users = readUsers(usersFile);
|
|
2831
|
+
} catch {
|
|
2832
|
+
return false;
|
|
2833
|
+
}
|
|
2834
|
+
for (const u of users) {
|
|
2835
|
+
if (u.userId === excludeUserId) continue;
|
|
2836
|
+
if (typeof u.accessHash === "string" && await matchesHash(password, u.accessHash)) {
|
|
2837
|
+
return true;
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
return false;
|
|
2841
|
+
}
|
|
2842
|
+
function anyAccessPasswordConfigured(usersFile) {
|
|
2843
|
+
let users;
|
|
2844
|
+
try {
|
|
2845
|
+
users = readUsers(usersFile);
|
|
2846
|
+
} catch {
|
|
2847
|
+
return false;
|
|
2848
|
+
}
|
|
2849
|
+
return users.some((u) => typeof u.accessHash === "string" && u.accessHash.length > 0);
|
|
2850
|
+
}
|
|
2851
|
+
function accessStoreUnreadable(usersFile) {
|
|
2852
|
+
if (!existsSync2(usersFile)) return false;
|
|
2853
|
+
try {
|
|
2854
|
+
readUsers(usersFile);
|
|
2855
|
+
return false;
|
|
2856
|
+
} catch {
|
|
2857
|
+
return true;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
function migrateLegacyRemotePassword(usersFile, legacyFile, ownerUserId) {
|
|
2861
|
+
if (!existsSync2(legacyFile)) return "noop-no-legacy";
|
|
2862
|
+
const legacy = readFileSync2(legacyFile, "utf-8").trim();
|
|
2863
|
+
const users = readUsers(usersFile);
|
|
2864
|
+
const idx = users.findIndex((u) => u.userId === ownerUserId);
|
|
2865
|
+
if (idx === -1) return "noop-no-owner";
|
|
2866
|
+
const existing = users[idx].accessHash;
|
|
2867
|
+
if (typeof existing === "string" && existing.length > 0) {
|
|
2868
|
+
unlinkSync(legacyFile);
|
|
2869
|
+
return "noop-owner-has-hash";
|
|
2870
|
+
}
|
|
2871
|
+
if (!legacy.includes(":")) {
|
|
2872
|
+
unlinkSync(legacyFile);
|
|
2873
|
+
return "noop-no-legacy";
|
|
2874
|
+
}
|
|
2875
|
+
users[idx] = { ...users[idx], accessHash: legacy };
|
|
2876
|
+
writeUsersAtomic(usersFile, users);
|
|
2877
|
+
unlinkSync(legacyFile);
|
|
2878
|
+
return "migrated";
|
|
2879
|
+
}
|
|
2880
|
+
function readLegacyRemoteHash(legacyFile) {
|
|
2881
|
+
if (!existsSync2(legacyFile)) return null;
|
|
2882
|
+
const raw2 = readFileSync2(legacyFile, "utf-8").trim();
|
|
2883
|
+
return raw2.includes(":") ? raw2 : null;
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
// app/lib/password-strength.ts
|
|
2887
|
+
function validatePasswordStrength(password) {
|
|
2888
|
+
return [
|
|
2889
|
+
{ key: "length", label: "At least 8 characters", met: password.length >= 8 },
|
|
2890
|
+
{ key: "number", label: "Contains a number", met: /\d/.test(password) },
|
|
2891
|
+
{ key: "special", label: "Contains a special character", met: /[^A-Za-z0-9]/.test(password) },
|
|
2892
|
+
{ key: "whitespace", label: "No spaces", met: password.length > 0 && !/\s/.test(password) }
|
|
2893
|
+
];
|
|
2894
|
+
}
|
|
2895
|
+
function isPasswordValid(password) {
|
|
2896
|
+
return validatePasswordStrength(password).every((r) => r.met);
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
// app/lib/remote-auth.ts
|
|
2900
|
+
import { scrypt as scrypt2, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2, createHmac } from "crypto";
|
|
2901
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
2902
|
+
import { dirname } from "path";
|
|
2903
|
+
var SCRYPT_N2 = 16384;
|
|
2904
|
+
var SCRYPT_R2 = 8;
|
|
2905
|
+
var SCRYPT_P2 = 1;
|
|
2906
|
+
var SCRYPT_KEYLEN2 = 64;
|
|
2907
|
+
function scryptAsync2(password, salt) {
|
|
2908
|
+
return new Promise((resolve7, reject) => {
|
|
2909
|
+
scrypt2(password, salt, SCRYPT_KEYLEN2, { N: SCRYPT_N2, r: SCRYPT_R2, p: SCRYPT_P2 }, (err, key) => {
|
|
2910
|
+
if (err) reject(err);
|
|
2911
|
+
else resolve7(key);
|
|
2912
|
+
});
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
async function hashPassword(password) {
|
|
2916
|
+
const salt = randomBytes2(32);
|
|
2917
|
+
const hash = await scryptAsync2(password, salt);
|
|
2918
|
+
return `${salt.toString("hex")}:${hash.toString("hex")}`;
|
|
2919
|
+
}
|
|
2920
|
+
function isRemoteAuthConfigured() {
|
|
2921
|
+
if (anyAccessPasswordConfigured(USERS_FILE)) return true;
|
|
2922
|
+
if (accessStoreUnreadable(USERS_FILE)) return true;
|
|
2923
|
+
return readLegacyRemoteHash(REMOTE_PASSWORD_FILE) !== null;
|
|
2829
2924
|
}
|
|
2830
2925
|
async function setRemotePassword(password) {
|
|
2831
2926
|
const hash = await hashPassword(password);
|
|
2832
|
-
|
|
2927
|
+
writeFileSync2(REMOTE_PASSWORD_FILE, hash, "utf-8");
|
|
2833
2928
|
}
|
|
2834
2929
|
async function verifyRemotePassword(password) {
|
|
2835
|
-
const
|
|
2836
|
-
if (
|
|
2837
|
-
|
|
2930
|
+
const matchedUserId = await verifyAccessPassword(password, USERS_FILE);
|
|
2931
|
+
if (matchedUserId) return { ok: true, hashBytes: SCRYPT_KEYLEN2, userId: matchedUserId };
|
|
2932
|
+
const legacy = readLegacyRemoteHash(REMOTE_PASSWORD_FILE);
|
|
2933
|
+
if (legacy && await matchesHash(password, legacy)) {
|
|
2934
|
+
return { ok: true, hashBytes: SCRYPT_KEYLEN2, userId: null };
|
|
2935
|
+
}
|
|
2936
|
+
const configured = anyAccessPasswordConfigured(USERS_FILE) || legacy !== null;
|
|
2937
|
+
return { ok: false, why: configured ? "password-mismatch" : "no-password-file", hashBytes: 0 };
|
|
2838
2938
|
}
|
|
2839
2939
|
var SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2840
2940
|
var TOKEN_PREFIX = "v1.";
|
|
@@ -2844,20 +2944,20 @@ var cachedSecret = null;
|
|
|
2844
2944
|
function getSecret() {
|
|
2845
2945
|
if (cachedSecret) return cachedSecret;
|
|
2846
2946
|
try {
|
|
2847
|
-
const hex2 =
|
|
2947
|
+
const hex2 = readFileSync3(REMOTE_SESSION_SECRET_FILE, "utf-8").trim();
|
|
2848
2948
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
2849
2949
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
2850
2950
|
return cachedSecret;
|
|
2851
2951
|
}
|
|
2852
2952
|
} catch {
|
|
2853
2953
|
}
|
|
2854
|
-
const fresh =
|
|
2954
|
+
const fresh = randomBytes2(SECRET_BYTES).toString("hex");
|
|
2855
2955
|
try {
|
|
2856
2956
|
mkdirSync2(dirname(REMOTE_SESSION_SECRET_FILE), { recursive: true, mode: 448 });
|
|
2857
|
-
|
|
2957
|
+
writeFileSync2(REMOTE_SESSION_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
|
|
2858
2958
|
} catch {
|
|
2859
2959
|
}
|
|
2860
|
-
const hex =
|
|
2960
|
+
const hex = readFileSync3(REMOTE_SESSION_SECRET_FILE, "utf-8").trim();
|
|
2861
2961
|
cachedSecret = Buffer.from(hex, "hex");
|
|
2862
2962
|
return cachedSecret;
|
|
2863
2963
|
}
|
|
@@ -2872,7 +2972,7 @@ function signPayload(payloadJson, secret) {
|
|
|
2872
2972
|
return base64urlEncode(createHmac("sha256", secret).update(payloadJson).digest());
|
|
2873
2973
|
}
|
|
2874
2974
|
function createRemoteSession(opts = {}) {
|
|
2875
|
-
const payload = { c: opts.now ?? Date.now(), n:
|
|
2975
|
+
const payload = { c: opts.now ?? Date.now(), n: randomBytes2(NONCE_BYTES).toString("hex") };
|
|
2876
2976
|
const payloadJson = JSON.stringify(payload);
|
|
2877
2977
|
const payloadB64 = base64urlEncode(Buffer.from(payloadJson, "utf-8"));
|
|
2878
2978
|
const sig = signPayload(payloadJson, getSecret());
|
|
@@ -2895,7 +2995,7 @@ function parseToken(token) {
|
|
|
2895
2995
|
const expected = signPayload(payloadJson, getSecret());
|
|
2896
2996
|
const expectedBuf = Buffer.from(expected, "utf-8");
|
|
2897
2997
|
const provBuf = Buffer.from(sigB64, "utf-8");
|
|
2898
|
-
const signatureValid = expectedBuf.length === provBuf.length &&
|
|
2998
|
+
const signatureValid = expectedBuf.length === provBuf.length && timingSafeEqual2(expectedBuf, provBuf);
|
|
2899
2999
|
let payload;
|
|
2900
3000
|
try {
|
|
2901
3001
|
payload = JSON.parse(payloadJson);
|
|
@@ -3442,6 +3542,10 @@ var SYSTEM_PATH_SLUGS = ["public", "public-chat", "chat", "graph", "data", "brow
|
|
|
3442
3542
|
var PUBLIC_ALLOWED_PREFIXES = [
|
|
3443
3543
|
"/api/session",
|
|
3444
3544
|
"/api/chat",
|
|
3545
|
+
// Task 873 — the detooled public surface's visitor-authed reader (pointer +
|
|
3546
|
+
// server-filtered SSE stream). Reached by the visitor browser on the public
|
|
3547
|
+
// host; authenticated by the __access_session grant inside the route.
|
|
3548
|
+
"/api/public-reader/",
|
|
3445
3549
|
"/api/access/",
|
|
3446
3550
|
"/api/health",
|
|
3447
3551
|
"/api/group/",
|
|
@@ -3473,13 +3577,13 @@ function classifyHost(host, operatorDomains2, isPublicHost) {
|
|
|
3473
3577
|
import { watchFile } from "fs";
|
|
3474
3578
|
|
|
3475
3579
|
// app/lib/operator-domains.ts
|
|
3476
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as
|
|
3580
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3477
3581
|
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
3478
3582
|
var OPERATOR_DOMAINS_PATH = resolve3(MAXY_DIR, "operator-domains.json");
|
|
3479
3583
|
function loadOperatorDomains() {
|
|
3480
3584
|
if (!existsSync3(OPERATOR_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
|
|
3481
3585
|
try {
|
|
3482
|
-
const parsed = JSON.parse(
|
|
3586
|
+
const parsed = JSON.parse(readFileSync4(OPERATOR_DOMAINS_PATH, "utf-8"));
|
|
3483
3587
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
3484
3588
|
return new Set(parsed.filter((h) => typeof h === "string"));
|
|
3485
3589
|
} catch {
|
|
@@ -3506,11 +3610,11 @@ function getOperatorDomains() {
|
|
|
3506
3610
|
|
|
3507
3611
|
// app/lib/claude-agent/account.ts
|
|
3508
3612
|
import { resolve as resolve4 } from "path";
|
|
3509
|
-
import { readFileSync as
|
|
3613
|
+
import { readFileSync as readFileSync6, readdirSync, existsSync as existsSync5, statSync } from "fs";
|
|
3510
3614
|
|
|
3511
3615
|
// ../lib/brand-templating/src/index.ts
|
|
3512
3616
|
import { join as join2 } from "path";
|
|
3513
|
-
import { existsSync as existsSync4, readFileSync as
|
|
3617
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5 } from "fs";
|
|
3514
3618
|
var PLACEHOLDER = "{{productName}}";
|
|
3515
3619
|
var cachedProductName = null;
|
|
3516
3620
|
function brandJsonPath() {
|
|
@@ -3530,7 +3634,7 @@ function getBrandProductName() {
|
|
|
3530
3634
|
}
|
|
3531
3635
|
let parsed;
|
|
3532
3636
|
try {
|
|
3533
|
-
parsed = JSON.parse(
|
|
3637
|
+
parsed = JSON.parse(readFileSync5(path, "utf-8"));
|
|
3534
3638
|
} catch (err) {
|
|
3535
3639
|
throw new Error(
|
|
3536
3640
|
`[skill-loader] brand.json unreadable at ${path}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -3594,7 +3698,7 @@ function listValidAccounts() {
|
|
|
3594
3698
|
}
|
|
3595
3699
|
let config;
|
|
3596
3700
|
try {
|
|
3597
|
-
config = JSON.parse(
|
|
3701
|
+
config = JSON.parse(readFileSync6(configPath, "utf-8"));
|
|
3598
3702
|
} catch {
|
|
3599
3703
|
console.error(
|
|
3600
3704
|
`[platform] accounts-state CORRUPT-JSON id=${entry.name} \u2014 account.json failed to parse; treating as stub`
|
|
@@ -3610,7 +3714,7 @@ function resolveAccount() {
|
|
|
3610
3714
|
let usersJsonUserId = null;
|
|
3611
3715
|
if (existsSync5(USERS_FILE)) {
|
|
3612
3716
|
try {
|
|
3613
|
-
const raw2 =
|
|
3717
|
+
const raw2 = readFileSync6(USERS_FILE, "utf-8").trim();
|
|
3614
3718
|
if (raw2) {
|
|
3615
3719
|
const users = JSON.parse(raw2);
|
|
3616
3720
|
if (users.length > 0) {
|
|
@@ -3626,7 +3730,7 @@ function resolveAccount() {
|
|
|
3626
3730
|
if (!entry.isDirectory()) continue;
|
|
3627
3731
|
const configPath = resolve4(ACCOUNTS_DIR, entry.name, "account.json");
|
|
3628
3732
|
if (!existsSync5(configPath)) continue;
|
|
3629
|
-
const raw2 =
|
|
3733
|
+
const raw2 = readFileSync6(configPath, "utf-8");
|
|
3630
3734
|
let config;
|
|
3631
3735
|
try {
|
|
3632
3736
|
config = JSON.parse(raw2);
|
|
@@ -3661,7 +3765,7 @@ function resolveAccount() {
|
|
|
3661
3765
|
function readAgentFile(accountDir, agentName, filename) {
|
|
3662
3766
|
const filePath = resolve4(accountDir, "agents", agentName, filename);
|
|
3663
3767
|
if (!existsSync5(filePath)) return null;
|
|
3664
|
-
const raw2 =
|
|
3768
|
+
const raw2 = readFileSync6(filePath, "utf-8");
|
|
3665
3769
|
if (filename.endsWith(".md")) {
|
|
3666
3770
|
return substituteBrandPlaceholders(raw2, filePath);
|
|
3667
3771
|
}
|
|
@@ -3690,7 +3794,7 @@ function resolveDefaultAgentSlug(accountDir) {
|
|
|
3690
3794
|
}
|
|
3691
3795
|
let config;
|
|
3692
3796
|
try {
|
|
3693
|
-
config = JSON.parse(
|
|
3797
|
+
config = JSON.parse(readFileSync6(configPath, "utf-8"));
|
|
3694
3798
|
} catch (err) {
|
|
3695
3799
|
console.error("[agent-resolve] failed to read account.json:", err);
|
|
3696
3800
|
return null;
|
|
@@ -3765,14 +3869,14 @@ function resolveAgentConfig(accountDir, agentName) {
|
|
|
3765
3869
|
const knowledgeMtime = statSync(knowledgePath).mtimeMs;
|
|
3766
3870
|
const summaryMtime = statSync(summaryPath).mtimeMs;
|
|
3767
3871
|
if (summaryMtime >= knowledgeMtime) {
|
|
3768
|
-
knowledge =
|
|
3872
|
+
knowledge = readFileSync6(summaryPath, "utf-8");
|
|
3769
3873
|
} else {
|
|
3770
3874
|
console.warn(`[agent-config] ${agentName}: KNOWLEDGE-SUMMARY.md is stale (KNOWLEDGE.md is newer) \u2014 using full knowledge`);
|
|
3771
|
-
knowledge =
|
|
3875
|
+
knowledge = readFileSync6(knowledgePath, "utf-8");
|
|
3772
3876
|
}
|
|
3773
3877
|
knowledgeBaked = true;
|
|
3774
3878
|
} else if (hasKnowledge) {
|
|
3775
|
-
knowledge =
|
|
3879
|
+
knowledge = readFileSync6(knowledgePath, "utf-8");
|
|
3776
3880
|
knowledgeBaked = true;
|
|
3777
3881
|
}
|
|
3778
3882
|
let budget = null;
|
|
@@ -3808,7 +3912,7 @@ function resolveUserAccounts(userId) {
|
|
|
3808
3912
|
if (!existsSync5(configPath)) continue;
|
|
3809
3913
|
let config;
|
|
3810
3914
|
try {
|
|
3811
|
-
config = JSON.parse(
|
|
3915
|
+
config = JSON.parse(readFileSync6(configPath, "utf-8"));
|
|
3812
3916
|
} catch {
|
|
3813
3917
|
console.error(`[session] account.json corrupt at ${configPath} \u2014 skipping`);
|
|
3814
3918
|
continue;
|
|
@@ -3893,8 +3997,8 @@ function getSessionKeyBySessionId(_sessionId) {
|
|
|
3893
3997
|
// app/lib/claude-agent/plugin-manifest.ts
|
|
3894
3998
|
import { resolve as resolve5, join as join3 } from "path";
|
|
3895
3999
|
import {
|
|
3896
|
-
readFileSync as
|
|
3897
|
-
writeFileSync as
|
|
4000
|
+
readFileSync as readFileSync7,
|
|
4001
|
+
writeFileSync as writeFileSync4,
|
|
3898
4002
|
readdirSync as readdirSync2,
|
|
3899
4003
|
existsSync as existsSync6,
|
|
3900
4004
|
statSync as statSync2,
|
|
@@ -3915,7 +4019,7 @@ function readBundleSubPlugins(bundlePath) {
|
|
|
3915
4019
|
if (!existsSync6(bundlePath)) return [];
|
|
3916
4020
|
let raw2;
|
|
3917
4021
|
try {
|
|
3918
|
-
raw2 =
|
|
4022
|
+
raw2 = readFileSync7(bundlePath, "utf-8");
|
|
3919
4023
|
} catch {
|
|
3920
4024
|
return [];
|
|
3921
4025
|
}
|
|
@@ -3988,8 +4092,8 @@ function reapDuplicateFlatPremiumSubs(bundles, stagingRoot, pluginsDir) {
|
|
|
3988
4092
|
const flatDir = resolve5(pluginsDir, sub);
|
|
3989
4093
|
const flatManifest = resolve5(flatDir, "PLUGIN.md");
|
|
3990
4094
|
if (!existsSync6(premiumManifest) || !existsSync6(flatManifest)) continue;
|
|
3991
|
-
const premiumSha = createHash2("sha256").update(
|
|
3992
|
-
const flatSha = createHash2("sha256").update(
|
|
4095
|
+
const premiumSha = createHash2("sha256").update(readFileSync7(premiumManifest)).digest("hex");
|
|
4096
|
+
const flatSha = createHash2("sha256").update(readFileSync7(flatManifest)).digest("hex");
|
|
3993
4097
|
if (isBundle) {
|
|
3994
4098
|
if (premiumSha === flatSha) {
|
|
3995
4099
|
try {
|
|
@@ -4051,10 +4155,10 @@ function reconcileEnabledPlugins(accountDir, config, accountId) {
|
|
|
4051
4155
|
const merged = [...currentSet];
|
|
4052
4156
|
const configPath = resolve5(accountDir, "account.json");
|
|
4053
4157
|
try {
|
|
4054
|
-
const raw2 =
|
|
4158
|
+
const raw2 = readFileSync7(configPath, "utf-8");
|
|
4055
4159
|
const parsed = JSON.parse(raw2);
|
|
4056
4160
|
parsed.enabledPlugins = merged;
|
|
4057
|
-
|
|
4161
|
+
writeFileSync4(configPath, JSON.stringify(parsed, null, 2) + "\n");
|
|
4058
4162
|
config.enabledPlugins = merged;
|
|
4059
4163
|
} catch (err) {
|
|
4060
4164
|
console.error(`${TAG} enabled-stamp write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -4082,10 +4186,10 @@ function cleanupLeakedPremiumSubs(accountDir, config, accountId) {
|
|
|
4082
4186
|
if (removed.length === 0) return;
|
|
4083
4187
|
const configPath = resolve5(accountDir, "account.json");
|
|
4084
4188
|
try {
|
|
4085
|
-
const raw2 =
|
|
4189
|
+
const raw2 = readFileSync7(configPath, "utf-8");
|
|
4086
4190
|
const parsed = JSON.parse(raw2);
|
|
4087
4191
|
parsed.enabledPlugins = kept;
|
|
4088
|
-
|
|
4192
|
+
writeFileSync4(configPath, JSON.stringify(parsed, null, 2) + "\n");
|
|
4089
4193
|
config.enabledPlugins = kept;
|
|
4090
4194
|
console.log(`${TAG} cleanup accountId=${accountId ?? "unknown"} removed=[${removed.join(",")}]`);
|
|
4091
4195
|
} catch (err) {
|
|
@@ -4133,7 +4237,7 @@ function requirePortEnv(envName, options = {}) {
|
|
|
4133
4237
|
// app/lib/neo4j-store.ts
|
|
4134
4238
|
import neo4j from "neo4j-driver";
|
|
4135
4239
|
import { randomUUID } from "crypto";
|
|
4136
|
-
import { readFileSync as
|
|
4240
|
+
import { readFileSync as readFileSync8, readdirSync as readdirSync3, existsSync as existsSync7, openSync, readSync, closeSync, statSync as statSync3 } from "fs";
|
|
4137
4241
|
import { resolve as resolve6 } from "path";
|
|
4138
4242
|
var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve6(process.cwd(), "..");
|
|
4139
4243
|
var driver = null;
|
|
@@ -4141,7 +4245,7 @@ function readPassword() {
|
|
|
4141
4245
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
4142
4246
|
const passwordFile = resolve6(PLATFORM_ROOT3, "config/.neo4j-password");
|
|
4143
4247
|
try {
|
|
4144
|
-
return
|
|
4248
|
+
return readFileSync8(passwordFile, "utf-8").trim();
|
|
4145
4249
|
} catch {
|
|
4146
4250
|
throw new Error(
|
|
4147
4251
|
`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
|
|
@@ -5190,7 +5294,7 @@ function loadEnabledPluginProfileKeys(accountId) {
|
|
|
5190
5294
|
if (!existsSync7(accountFile)) return {};
|
|
5191
5295
|
let enabled;
|
|
5192
5296
|
try {
|
|
5193
|
-
const raw2 =
|
|
5297
|
+
const raw2 = readFileSync8(accountFile, "utf-8");
|
|
5194
5298
|
const parsed = JSON.parse(raw2);
|
|
5195
5299
|
enabled = Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : [];
|
|
5196
5300
|
} catch (err) {
|
|
@@ -5205,7 +5309,7 @@ function loadEnabledPluginProfileKeys(accountId) {
|
|
|
5205
5309
|
if (!existsSync7(manifestPath)) continue;
|
|
5206
5310
|
let manifest;
|
|
5207
5311
|
try {
|
|
5208
|
-
manifest =
|
|
5312
|
+
manifest = readFileSync8(manifestPath, "utf-8");
|
|
5209
5313
|
} catch {
|
|
5210
5314
|
continue;
|
|
5211
5315
|
}
|
|
@@ -5461,11 +5565,11 @@ async function projectAgent(accountId, accountDir, slug) {
|
|
|
5461
5565
|
);
|
|
5462
5566
|
return;
|
|
5463
5567
|
}
|
|
5464
|
-
config = JSON.parse(
|
|
5568
|
+
config = JSON.parse(readFileSync8(configPath, "utf-8"));
|
|
5465
5569
|
for (const { filename, role } of AGENT_FILE_ROLES) {
|
|
5466
5570
|
const filePath = resolve6(agentDir, filename);
|
|
5467
5571
|
if (!existsSync7(filePath)) continue;
|
|
5468
|
-
const body =
|
|
5572
|
+
const body = readFileSync8(filePath, "utf-8");
|
|
5469
5573
|
presentRoles.push({ role, body, edge: ROLE_TO_EDGE[role] });
|
|
5470
5574
|
}
|
|
5471
5575
|
} catch (err) {
|
|
@@ -5726,6 +5830,7 @@ export {
|
|
|
5726
5830
|
LID_MAP_FILE,
|
|
5727
5831
|
LOG_DIR,
|
|
5728
5832
|
BIN_DIR,
|
|
5833
|
+
REMOTE_PASSWORD_FILE,
|
|
5729
5834
|
INSTALL_OWNER_FILE,
|
|
5730
5835
|
VISITOR_TOKEN_SECRET_FILE,
|
|
5731
5836
|
CLAUDE_CREDENTIALS_FILE,
|
|
@@ -5734,6 +5839,9 @@ export {
|
|
|
5734
5839
|
sanitizeClientCorrId,
|
|
5735
5840
|
httpLog,
|
|
5736
5841
|
websockifyLog,
|
|
5842
|
+
setAccessPassword,
|
|
5843
|
+
accessPasswordCollides,
|
|
5844
|
+
migrateLegacyRemotePassword,
|
|
5737
5845
|
validatePasswordStrength,
|
|
5738
5846
|
isPasswordValid,
|
|
5739
5847
|
isRemoteAuthConfigured,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e}from"./chunk-CAM3fms7.js";import{o as t,u as n}from"./brand-C7kj0USi.js";import{c as r,d as i,l as a,u as o}from"./audio-attachment-mime-DOBET-W1.js";import{r as s}from"./useSelectionMode-CG_Iel5F.js";var c=e(n(),1);function l(){let[e,t]=(0,c.useState)(null),[n,s]=(0,c.useState)(null),[l,u]=(0,c.useState)(`loading`),[d,f]=(0,c.useState)(``),[p,m]=(0,c.useState)(null),[h,g]=(0,c.useState)(null),[_,v]=(0,c.useState)(!1),[y,b]=(0,c.useState)(null),x=(0,c.useMemo)(()=>r(),[]),S=(0,c.useMemo)(()=>a(),[]),[C,w]=(0,c.useState)(null),T=(0,c.useRef)(x||``),E=(0,c.useRef)(null),D=(0,c.useRef)(null),O=(0,c.useRef)(!1),k=(0,c.useRef)(null),[A,j]=(0,c.useState)(`request-link`),[M,N]=(0,c.useState)(null),P=(0,c.useRef)(null),F=(0,c.useRef)(null);(0,c.useEffect)(()=>{try{let e=sessionStorage.getItem(`maxy_session`);e&&(F.current=e)}catch{}},[]);let I=(0,c.useCallback)(e=>{E.current=e,t(e);try{sessionStorage.setItem(`maxy_session`,e)}catch{}u(`chat`)},[]),L=(0,c.useCallback)(()=>{E.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}t(null),u(`auth-required`),j(`request-link`)},[]),R=(0,c.useCallback)(async e=>{j(`verifying`);try{let t=T.current,n=await fetch(`/api/access/verify-token`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({token:e,agentSlug:t})});if(window.history.replaceState({},``,window.location.pathname),n.ok){let e=await n.json().catch(()=>({}));return e?.displayName&&N({displayName:e.displayName,contactValue:``,expiresAt:null,status:`active`}),!0}return j(`verify-failed`),!1}catch{return j(`verify-failed`),!1}},[]),z=(0,c.useCallback)(async()=>{if(E.current)return E.current;if(D.current)return D.current;let e=(async()=>{try{let e=F.current,n=await fetch(`/api/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({session_id:o(),...x?{agent:x}:{},...S?{group_slug:S}:{},...e?{session_key:e}:{}})});if(!n.ok){let e=await n.json().catch(()=>({error:``}));return i&&console.error(`[session] POST /api/session failed: ${n.status} ${n.statusText}`,e),n.status===404?s(e.error||`Agent not found`):n.status===503&&s(e.error||`Service unavailable`),null}let r=await n.json();if(r.auth_required){r.agent_id&&(T.current=r.agent_id),f(r.displayName||``),r.agentImage&&m(r.agentImage),r.agentImageShape&&g(r.agentImageShape),r.showAgentName&&v(r.showAgentName),r.branding&&b(r.branding),u(`auth-required`);let e=new URLSearchParams(window.location.search).get(`token`);return e?await R(e)&&window.location.reload():j(`request-link`),null}E.current=r.session_key,t(r.session_key),r.displayName&&f(r.displayName),r.agentImage&&m(r.agentImage),r.agentImageShape&&g(r.agentImageShape),r.showAgentName&&v(r.showAgentName),r.branding&&b(r.branding),u(`chat`),r.resumed&&r.messages&&(O.current=!0,k.current=r.messages),r.group&&w({groupSlug:r.groupSlug,groupName:r.groupName,participants:r.participants??[]});try{sessionStorage.setItem(`maxy_session`,r.session_key)}catch{}return r.session_key}catch(e){return i&&console.error(`[session] fetch /api/session threw:`,e),s(`Unable to connect. Please check your connection and try again.`),null}finally{D.current=null}})();return D.current=e,e},[x,S,R]);return{sessionId:e,cacheKeyRef:E,sessionError:n,pageState:l,setPageState:u,agentDisplayName:d,agentImage:p,agentImageShape:h,showAgentName:_,agentSlug:x,branding:y,resolvedSlugRef:T,ensureSession:z,startNewSession:(0,c.useCallback)(async()=>{E.current=null,D.current=null,F.current=null,O.current=!1,k.current=null,t(null),s(null);try{sessionStorage.removeItem(`maxy_session`)}catch{}await z()},[z]),enterChat:I,enterGate:L,resumedRef:O,resumeMessagesRef:k,gateState:A,setGateState:j,grantInfo:M,setGrantInfo:N,gateCacheKeyRef:P,groupContext:C,groupSlug:S}}var u=t();function d({gateState:e,setGateState:t,grantInfo:n,resolvedSlugRef:r}){let[i,a]=(0,c.useState)(``),[o,l]=(0,c.useState)(!1),[d,f]=(0,c.useState)(null);async function p(e){e.preventDefault();let n=i.trim().toLowerCase();if(!n){f(`Enter the email you were invited on.`);return}l(!0),f(null);try{let e=await fetch(`/api/access/request-magic-link`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({contactValue:n,agentSlug:r.current})});if(e.status===429){f((await e.json().catch(()=>({})))?.error||`Too many requests. Try again later.`);return}t(`request-sent`)}catch{f(`Could not reach the server. Check your connection and try again.`)}finally{l(!1)}}return(0,u.jsxs)(`div`,{className:`access-gate`,children:[e===`verifying`&&(0,u.jsxs)(`div`,{className:`access-gate-message`,children:[(0,u.jsx)(`h2`,{children:`Verifying your link…`}),(0,u.jsx)(`p`,{children:`This takes a moment.`})]}),e===`verify-failed`&&(0,u.jsxs)(`div`,{className:`access-gate-message`,children:[(0,u.jsx)(`h2`,{children:`That link did not work`}),(0,u.jsx)(`p`,{children:`It may have expired, already been used, or been for a different agent. You can request a fresh one below.`}),(0,u.jsx)(s,{onClick:()=>{t(`request-link`),f(null)},children:`Request a new link`})]}),e===`request-link`&&(0,u.jsxs)(`form`,{className:`access-gate-form`,onSubmit:p,children:[(0,u.jsx)(`h2`,{children:n?.displayName?`Welcome back, ${n.displayName}`:`Sign in`}),(0,u.jsx)(`p`,{children:`Enter the email you were invited on and we will send you a fresh link.`}),(0,u.jsx)(`label`,{htmlFor:`access-email`,children:`Email`}),(0,u.jsx)(`input`,{id:`access-email`,type:`email`,inputMode:`email`,autoComplete:`email`,value:i,onChange:e=>a(e.target.value),disabled:o}),d&&(0,u.jsx)(`p`,{className:`access-gate-error`,children:d}),(0,u.jsx)(s,{type:`submit`,disabled:o||!i.trim(),children:o?`Sending…`:`Send me a link`})]}),e===`request-sent`&&(0,u.jsxs)(`div`,{className:`access-gate-message`,children:[(0,u.jsx)(`h2`,{children:`Check your email`}),(0,u.jsx)(`p`,{children:`If that address is on the invite list, a fresh link is on the way. It expires in 15 minutes.`}),(0,u.jsx)(s,{onClick:()=>{t(`request-link`),a(``),f(null)},children:`Try a different email`})]})]})}export{l as n,d as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e}from"./chunk-CAM3fms7.js";import{a as t,o as n,t as r,u as i}from"./brand-C7kj0USi.js";import{S as a,g as o}from"./OperatorConversations-BIHiyyxU.js";import{s}from"./AdminShell-DkoQSsqo.js";import{r as c}from"./useSelectionMode-CG_Iel5F.js";import{t as l}from"./Checkbox-DMA1hVhn.js";new Set(`image/jpeg,image/png,image/gif,image/webp,application/pdf,text/plain,text/markdown,text/csv,text/html,text/calendar,application/zip,application/x-zip-compressed,audio/ogg,audio/opus,audio/mp4,audio/mpeg,audio/webm,audio/wav,.opus,.ogg,.m4a,.mp3,.wav,.webm`.split(`,`).filter(e=>!e.startsWith(`.`)));function u(e){switch(e){case`expanded`:return!0;case`collapsed`:return!1;default:return}}var d=`admin-landing-redirected`,f=`/graph`;function p(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var m=e(i(),1);function h(e=`admin`){let[t,n]=(0,m.useState)(`loading`),[r,i]=(0,m.useState)(``),[o,c]=(0,m.useState)(``),[l,h]=(0,m.useState)(``),[g,_]=(0,m.useState)(!1),[v,y]=(0,m.useState)(!1),[b,x]=(0,m.useState)(!1),[S,C]=(0,m.useState)(!1),[w,T]=(0,m.useState)(!1),[E,D]=(0,m.useState)(null),[O,k]=(0,m.useState)(null),[A,j]=(0,m.useState)(void 0),[M,N]=(0,m.useState)(null),[P,F]=(0,m.useState)(void 0),[I,L]=(0,m.useState)(null),[ee,R]=(0,m.useState)(null),[z,B]=(0,m.useState)([]),[V,H]=(0,m.useState)(!1),[U,W]=(0,m.useState)(void 0),G=(0,m.useRef)(void 0),[K,q]=(0,m.useState)(!1);(0,m.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&q(!0)}).catch(()=>{})},[]);let J=(0,m.useRef)(null),Y=(0,m.useRef)(null);(0,m.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let r=await t.json();D(r.session_key),R(r.sessionId??null),j(r.businessName),N(r.role??null),F(r.userName===void 0?null:r.userName),L(r.avatar??null);let i=u(r.thinkingView);return G.current=i,W(i),n(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(r=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check returned ${i.status} after retries`),n(`set-pin`);return}let a=await i.json();if(!a.pin_configured){n(`set-pin`);return}if(!a.claude_authenticated){n(`connect-claude`);return}if(await e())return;n(`enter-pin`)}catch(e){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check failed:`,e),n(`set-pin`)}}t()},[]),(0,m.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,m.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(d)===`1`}catch{}if(p({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(d,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${f}`),window.location.replace(f)}},[t,e]);let X=(0,m.useRef)(null);(0,m.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();if(t.auth_status===`dead`||t.auth_status===`missing`){n(`connect-claude`);return}}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){a(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),X.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,m.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&n(`enter-pin`)}).catch(()=>{})},[t]);async function Z(e,t){y(!0);try{let r=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!r.ok){h((await r.json().catch(()=>({}))).error||`Invalid PIN`);return}let a=await r.json();if(a.accounts&&!a.session_key){console.log(`[admin] account picker shown: userId=${a.userId} accountCount=${a.accounts.length}`),B(a.accounts),n(`account-picker`);return}D(a.session_key),R(a.sessionId??null),j(a.businessName),N(a.role??null),F(a.userName===void 0?null:a.userName),L(a.avatar??null);let o=u(a.thinkingView);if(G.current=o,W(o),t)try{sessionStorage.setItem(`maxy-account-id`,t)}catch{}try{sessionStorage.setItem(`maxy-admin-session-key`,a.session_key)}catch{}i(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1),H(!1)}}let Q=(0,m.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=o.trim();if(!t){h(`Please enter your name.`);return}if(r.length<4){h(`PIN must be at least 4 characters.`);return}let a=r;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:a,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let r=await e.json();r.pin_configured&&r.claude_authenticated?n(`enter-pin`):r.pin_configured?n(`connect-claude`):h(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await Z(a);return}i(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[r,v,o]),te=(0,m.useCallback)(async e=>{e.preventDefault(),h(``),await Z(r)},[r]),ne=(0,m.useCallback)(async()=>{T(!0);try{if(!await s())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}return n(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,m.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}i(``),h(``),n(`enter-pin`)},[]);return(0,m.useEffect)(()=>{X.current=$},[$]),{appState:t,setAppState:n,pin:r,setPin:i,operatorName:o,setOperatorName:c,pinError:l,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:ee,setSessionId:R,accounts:z,accountPickerLoading:V,expandAll:U,setExpandAll:W,expandAllDefaultRef:G,remoteAuthEnabled:K,pinInputRef:J,setPinFormRef:Y,handleSetPin:Q,handleLogin:te,handleAccountSelect:(0,m.useCallback)(async e=>{H(!0),h(``),await Z(r,e)},[r]),handleDisconnect:ne,handleLogout:$,handleChangePin:(0,m.useCallback)(async()=>{if(!r){h(`Enter your current PIN first.`);return}y(!0),h(``);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({currentPin:r})});if(!e.ok){h((await e.json().catch(()=>({error:`Incorrect PIN.`}))).error||`Incorrect PIN.`);return}i(``),h(``),n(`set-pin`)}catch(e){console.error(`[admin-auth] change pin failed:`,e),h(e instanceof Error?e.message:String(e))}finally{y(!1)}},[r])}}var g=n();function _({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,m.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,g.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,g.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function v(e){let{pin:n,setPin:i,showPin:a,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:h}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,r.productName]}),(0,g.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,r.productName,` who you are, then choose a PIN.`]}),(0,g.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>h(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,g.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:n,onChange:i,onComplete:()=>{},showPin:a}),(0,g.jsx)(c,{variant:`send`,type:`submit`,disabled:!n||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsx)(l,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function y(e){let{pin:n,setPin:i,showPin:a,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,onChangePin:p,remoteAuthEnabled:m,onSignOutRemote:h}=e;return(0,g.jsxs)(`div`,{className:`connect-page`,children:[m&&h&&(0,g.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:h,children:`Sign out`}),(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:r.productName}),(0,g.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:n,onChange:i,onComplete:()=>{},showPin:a,autoFocus:!0}),(0,g.jsx)(c,{variant:`send`,type:`submit`,disabled:!n,loading:s,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsxs)(`div`,{className:`pin-options`,children:[(0,g.jsx)(l,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`}),(0,g.jsx)(c,{type:`button`,variant:`ghost`,onClick:p,children:`Change PIN`})]})]}),u&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function b(e){let{accounts:n,loading:i,error:a,onSelect:s}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:r.productName}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Select an account`}),(0,g.jsx)(`div`,{className:`account-picker-list`,children:n.map(e=>(0,g.jsxs)(`button`,{className:`account-picker-card`,onClick:()=>s(e.accountId),disabled:i,type:`button`,children:[(0,g.jsx)(`span`,{className:`account-picker-name`,children:e.businessName||e.accountId}),(0,g.jsx)(`span`,{className:`account-picker-role`,children:e.role}),i&&(0,g.jsx)(o,{className:`account-picker-spinner`,size:16})]},e.accountId))}),a&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:a})]})})}function x(e){let{authPolling:n,setAuthPolling:i,authLoading:a,setAuthLoading:o,pinError:s,setPinError:l,setAppState:u}=e,[d,f]=(0,m.useState)(!1),[p,h]=(0,m.useState)(!1);async function _(){h(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}h(!1)}async function v(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){i(!0),f(!0),o(!1);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),i(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function y(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),i(!1),l(``)}return n||d?(0,g.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,g.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[n?(0,g.jsx)(`button`,{onClick:y,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,g.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,g.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,g.jsx)(`p`,{className:`chat-intro`,children:n?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!n&&(0,g.jsx)(`div`,{style:{marginTop:`12px`},children:(0,g.jsx)(c,{variant:`primary`,onClick:v,disabled:a,children:a?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})})]}),(0,g.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,g.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,g.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsxs)(`div`,{className:`connect-logos`,children:[(0,g.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,g.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,g.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,g.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,g.jsx)(`img`,{src:t,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,g.jsx)(`span`,{className:`connect-logo-label`,children:r.productName})]})]}),(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,r.productName]}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,g.jsx)(c,{variant:`primary`,onClick:v,disabled:a,children:a?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,g.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,g.jsx)(`button`,{onClick:_,disabled:p,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:p?`Launching…`:`Open browser first`}),s&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function S({auth:e}){return e.appState===`loading`?(0,g.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,g.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,g.jsx)(x,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,g.jsx)(y,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,onChangePin:e.handleChangePin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):e.appState===`account-picker`?(0,g.jsx)(b,{accounts:e.accounts,loading:e.accountPickerLoading,error:e.pinError,onSelect:e.handleAccountSelect}):null}export{h as n,S as t};
|