@rubytech/create-maxy-code 0.1.542 → 0.1.544
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__/public-instruction-seed.test.js +102 -0
- package/dist/index.js +47 -0
- package/dist/public-instruction-seed.js +70 -0
- package/package.json +1 -1
- package/payload/platform/lib/shared-folder/dist/index.d.ts +47 -0
- package/payload/platform/lib/shared-folder/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/shared-folder/dist/index.js +93 -0
- package/payload/platform/lib/shared-folder/dist/index.js.map +1 -0
- package/payload/platform/lib/shared-folder/src/index.ts +92 -0
- package/payload/platform/lib/shared-folder/tsconfig.json +5 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/PLUGIN.md +2 -0
- package/payload/platform/plugins/admin/hooks/__tests__/public-tool-surface.test.sh +173 -0
- package/payload/platform/plugins/admin/hooks/public-tool-surface.sh +123 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js +13 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js.map +1 -1
- package/payload/platform/plugins/admin/skills/channel-instruction/SKILL.md +46 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +18 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +15 -0
- package/payload/platform/plugins/docs/references/access-control.md +14 -0
- package/payload/platform/plugins/docs/references/internals.md +2 -0
- package/payload/platform/plugins/docs/references/platform.md +1 -0
- package/payload/platform/plugins/filesystem/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/filesystem/PLUGIN.md +11 -1
- package/payload/platform/plugins/filesystem/mcp/dist/index.js +23 -7
- package/payload/platform/plugins/filesystem/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js +104 -4
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js +67 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +16 -2
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +54 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js +76 -2
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +81 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +22 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +80 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +13 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/whatsapp/PLUGIN.md +2 -2
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
- package/payload/platform/scripts/__tests__/public-surface-registered.test.sh +102 -0
- package/payload/platform/scripts/check-no-esm-require.mjs +5 -0
- package/payload/platform/scripts/lib/__tests__/account-settings-public-surface.test.sh +109 -0
- package/payload/platform/scripts/lib/account-settings-public-surface.sh +109 -0
- package/payload/platform/scripts/lib/provision-account-dir.sh +6 -3
- package/payload/platform/scripts/setup-account.sh +14 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +8 -4
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +27 -7
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +11 -6
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +8 -4
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +24 -2
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +23 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +35 -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 +286 -25
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +169 -51
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +24 -12
- 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 +194 -28
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +4 -0
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts +24 -3
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js +29 -3
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts +27 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js +32 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/role-census.d.ts +24 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.js +50 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +24 -2
- 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 +21 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts +76 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js +110 -19
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts +60 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js +93 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +31 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +72 -9
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +9 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/types.d.ts +9 -3
- package/payload/platform/services/claude-session-manager/dist/types.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts +0 -1
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.js +0 -46
- package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.d.ts +16 -4
- package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.js +27 -14
- package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/server.js +10 -0
- package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts +0 -1
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.js +0 -60
- package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.d.ts +14 -2
- package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.js +28 -12
- package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.js +10 -0
- package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +97 -33
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +98 -76
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts +18 -0
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +87 -5
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +41 -9
- package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/targets.js +42 -7
- package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -1
- package/payload/platform/templates/agents/admin/INSTRUCTION.md +0 -0
- package/payload/server/{adminuser-self-heal-LC7HZAC6.js → adminuser-self-heal-ZHFNDKJK.js} +1 -1
- package/payload/server/{chunk-HZP7BKBF.js → chunk-CVUSUNXM.js} +128 -4
- package/payload/server/{chunk-CKTHAHL4.js → chunk-DU7GPDJJ.js} +4 -2
- package/payload/server/{chunk-PFF6I7KP.js → chunk-HYQNUVGO.js} +8 -1
- package/payload/server/{chunk-ERIM3EFB.js → chunk-X2RRMHVV.js} +1 -1
- package/payload/server/{manager-CM55K4J2.js → manager-TI2YJQVZ.js} +3 -3
- package/payload/server/maxy-edge.js +3 -3
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js +1 -0
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js +2 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js.gz +0 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js +1 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js.br +0 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js.gz +0 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js +1 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js.br +0 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js.gz +0 -0
- package/payload/server/public/assets/agents-D8phtRX5.js +1 -0
- package/payload/server/public/assets/agents-D8phtRX5.js.br +0 -0
- package/payload/server/public/assets/agents-D8phtRX5.js.gz +0 -0
- package/payload/server/public/assets/browser-DQSTjdom.js +1 -0
- package/payload/server/public/assets/browser-DQSTjdom.js.br +0 -0
- package/payload/server/public/assets/browser-DQSTjdom.js.gz +0 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js +1 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js.br +0 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js.gz +0 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js +1 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js.br +0 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-DFK18xVX.js +1 -0
- package/payload/server/public/assets/chevron-left-DFK18xVX.js.br +0 -0
- package/payload/server/public/assets/chevron-right-DJ4oaHoN.js +1 -0
- package/payload/server/public/assets/chevron-right-DJ4oaHoN.js.br +0 -0
- package/payload/server/public/assets/clock-wHIan2DW.js +1 -0
- package/payload/server/public/assets/clock-wHIan2DW.js.br +0 -0
- package/payload/server/public/assets/{copy-3kj9Oaoc.js → copy-lFFhXRGk.js} +1 -1
- package/payload/server/public/assets/copy-lFFhXRGk.js.br +0 -0
- package/payload/server/public/assets/copy-lFFhXRGk.js.gz +0 -0
- package/payload/server/public/assets/data-Cxv97ARy.js +1 -0
- package/payload/server/public/assets/data-Cxv97ARy.js.br +0 -0
- package/payload/server/public/assets/data-Cxv97ARy.js.gz +0 -0
- package/payload/server/public/assets/{file-text-CBaewT76.js → file-text-D2Y-bkNy.js} +1 -1
- package/payload/server/public/assets/file-text-D2Y-bkNy.js.br +0 -0
- package/payload/server/public/assets/file-text-D2Y-bkNy.js.gz +0 -0
- package/payload/server/public/assets/{graph-B8-e2_Z-.js → graph-C-3yN6JD.js} +3 -3
- package/payload/server/public/assets/graph-C-3yN6JD.js.br +0 -0
- package/payload/server/public/assets/graph-C-3yN6JD.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-Bsc23eZU.js → graph-labels-DiaPLP27.js} +1 -1
- package/payload/server/public/assets/graph-labels-DiaPLP27.js.br +0 -0
- package/payload/server/public/assets/graph-labels-DiaPLP27.js.gz +0 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js +1 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js.br +0 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js.gz +0 -0
- package/payload/server/public/assets/page-BhGeFXWA.js +1 -0
- package/payload/server/public/assets/page-BhGeFXWA.js.br +0 -0
- package/payload/server/public/assets/page-BhGeFXWA.js.gz +0 -0
- package/payload/server/public/assets/page-EnbVC-yM.js +32 -0
- package/payload/server/public/assets/page-EnbVC-yM.js.br +0 -0
- package/payload/server/public/assets/page-EnbVC-yM.js.gz +0 -0
- package/payload/server/public/assets/play-jZFZAG-t.js +1 -0
- package/payload/server/public/assets/play-jZFZAG-t.js.br +0 -0
- package/payload/server/public/assets/play-jZFZAG-t.js.gz +0 -0
- package/payload/server/public/assets/public-CdSgMNC7.js +1 -0
- package/payload/server/public/assets/public-CdSgMNC7.js.br +0 -0
- package/payload/server/public/assets/public-CdSgMNC7.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-FZW7c8p8.js → rotate-ccw-rTRuTqei.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.gz +0 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js +2 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js.br +0 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js.gz +0 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js +1 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js.br +0 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js.gz +0 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js +3 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js.br +0 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-CR-jRJdI.js → triangle-alert-DtWUg6jR.js} +1 -1
- package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js +1 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js +14 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css +1 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js +2 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.gz +0 -0
- package/payload/server/public/assets/{wrench-CpCOYUBc.js → wrench-Ct4kf-uv.js} +1 -1
- package/payload/server/public/assets/wrench-Ct4kf-uv.js.br +0 -0
- package/payload/server/public/assets/wrench-Ct4kf-uv.js.gz +0 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +8 -8
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +6 -6
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +537 -263
- package/payload/server/{src-JN6PIAJN.js → src-MM64CYYZ.js} +1 -1
- package/payload/server/{userprofile-reconcile-QHVLY2AH.js → userprofile-reconcile-TL4JKBPG.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js +0 -1
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js +0 -2
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js.gz +0 -0
- package/payload/server/public/assets/activity-CpMnNr5c.js +0 -1
- package/payload/server/public/assets/activity-CpMnNr5c.js.br +0 -0
- package/payload/server/public/assets/activity-CpMnNr5c.js.gz +0 -0
- package/payload/server/public/assets/admin-CBwKIfaI.js +0 -1
- package/payload/server/public/assets/admin-CBwKIfaI.js.br +0 -0
- package/payload/server/public/assets/admin-CBwKIfaI.js.gz +0 -0
- package/payload/server/public/assets/agents-C4LmSKjb.js +0 -1
- package/payload/server/public/assets/agents-C4LmSKjb.js.br +0 -0
- package/payload/server/public/assets/agents-C4LmSKjb.js.gz +0 -0
- package/payload/server/public/assets/browser-Bm9xm_yc.js +0 -1
- package/payload/server/public/assets/browser-Bm9xm_yc.js.br +0 -0
- package/payload/server/public/assets/browser-Bm9xm_yc.js.gz +0 -0
- package/payload/server/public/assets/calendar-CNY9FTWe.js +0 -1
- package/payload/server/public/assets/calendar-CNY9FTWe.js.br +0 -0
- package/payload/server/public/assets/calendar-CNY9FTWe.js.gz +0 -0
- package/payload/server/public/assets/chat-3WoUGCTd.js +0 -1
- package/payload/server/public/assets/chat-3WoUGCTd.js.br +0 -0
- package/payload/server/public/assets/chat-3WoUGCTd.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-BE16BJnw.js +0 -1
- package/payload/server/public/assets/chevron-left-BE16BJnw.js.br +0 -0
- package/payload/server/public/assets/chevron-right-Bu2VKpeU.js +0 -1
- package/payload/server/public/assets/chevron-right-Bu2VKpeU.js.br +0 -0
- package/payload/server/public/assets/clock-C4Nu2aRV.js +0 -1
- package/payload/server/public/assets/clock-C4Nu2aRV.js.br +0 -0
- package/payload/server/public/assets/copy-3kj9Oaoc.js.br +0 -0
- package/payload/server/public/assets/copy-3kj9Oaoc.js.gz +0 -0
- package/payload/server/public/assets/data-C-x5EHyi.js +0 -1
- package/payload/server/public/assets/data-C-x5EHyi.js.br +0 -1
- package/payload/server/public/assets/data-C-x5EHyi.js.gz +0 -0
- package/payload/server/public/assets/file-text-CBaewT76.js.br +0 -0
- package/payload/server/public/assets/file-text-CBaewT76.js.gz +0 -0
- package/payload/server/public/assets/graph-B8-e2_Z-.js.br +0 -0
- package/payload/server/public/assets/graph-B8-e2_Z-.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-Bsc23eZU.js.br +0 -0
- package/payload/server/public/assets/graph-labels-Bsc23eZU.js.gz +0 -0
- package/payload/server/public/assets/operator-Cve0-qfO.js +0 -1
- package/payload/server/public/assets/operator-Cve0-qfO.js.br +0 -0
- package/payload/server/public/assets/operator-Cve0-qfO.js.gz +0 -0
- package/payload/server/public/assets/page-BgVMs6Vf.js +0 -1
- package/payload/server/public/assets/page-BgVMs6Vf.js.br +0 -0
- package/payload/server/public/assets/page-BgVMs6Vf.js.gz +0 -0
- package/payload/server/public/assets/page-fABub-w8.js +0 -32
- package/payload/server/public/assets/page-fABub-w8.js.br +0 -0
- package/payload/server/public/assets/page-fABub-w8.js.gz +0 -0
- package/payload/server/public/assets/play-B6zXB9K7.js +0 -1
- package/payload/server/public/assets/play-B6zXB9K7.js.br +0 -0
- package/payload/server/public/assets/play-B6zXB9K7.js.gz +0 -0
- package/payload/server/public/assets/public--R2DbdWs.js +0 -1
- package/payload/server/public/assets/public--R2DbdWs.js.br +0 -0
- package/payload/server/public/assets/public--R2DbdWs.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.gz +0 -0
- package/payload/server/public/assets/routines-BpZs2SaT.js +0 -2
- package/payload/server/public/assets/routines-BpZs2SaT.js.br +0 -0
- package/payload/server/public/assets/routines-BpZs2SaT.js.gz +0 -0
- package/payload/server/public/assets/skills-DF7uyEEz.js +0 -1
- package/payload/server/public/assets/skills-DF7uyEEz.js.br +0 -0
- package/payload/server/public/assets/skills-DF7uyEEz.js.gz +0 -0
- package/payload/server/public/assets/tasks-BfJJmoWO.js +0 -3
- package/payload/server/public/assets/tasks-BfJJmoWO.js.br +0 -0
- package/payload/server/public/assets/tasks-BfJJmoWO.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js +0 -14
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css +0 -1
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js +0 -2
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.gz +0 -0
- package/payload/server/public/assets/wrench-CpCOYUBc.js.br +0 -0
- package/payload/server/public/assets/wrench-CpCOYUBc.js.gz +0 -0
|
@@ -22,6 +22,10 @@ const ownAccountId = process.env.ACCOUNT_ID ?? null;
|
|
|
22
22
|
// literal ${HOUSE_ADMIN_SCOPE} placeholder or an empty value as a real scope.
|
|
23
23
|
const houseScope = readPluginHouseScope(process.env);
|
|
24
24
|
const platformRoot = process.env.PLATFORM_ROOT ?? "";
|
|
25
|
+
// Task 2323 — the `sid=` correlation key on every [shared] line. Declared in
|
|
26
|
+
// this plugin's PLUGIN.md env block, so it is present on a real spawn and
|
|
27
|
+
// absent only in the metadata-only boot, where no call reaches a file op.
|
|
28
|
+
const sessionId = process.env.SESSION_ID ?? null;
|
|
25
29
|
process.stderr.write(`[filesystem] boot accountId=${ownAccountId ?? "null"} houseScope=${houseScope ? "set" : "null"}\n`);
|
|
26
30
|
function refuseNoAccount(toolName) {
|
|
27
31
|
process.stderr.write(`[filesystem] tool=${toolName} refuse reason=no-account-context\n`);
|
|
@@ -41,45 +45,57 @@ function refuseNoAccount(toolName) {
|
|
|
41
45
|
function ctx() {
|
|
42
46
|
if (!ownAccountId || !platformRoot)
|
|
43
47
|
return null;
|
|
44
|
-
return {
|
|
48
|
+
return {
|
|
49
|
+
ownAccountId,
|
|
50
|
+
houseScope,
|
|
51
|
+
accountsDir: resolve(platformRoot, "..", "data/accounts"),
|
|
52
|
+
sessionId,
|
|
53
|
+
};
|
|
45
54
|
}
|
|
46
55
|
const targetArg = z
|
|
47
56
|
.string()
|
|
48
57
|
.optional()
|
|
49
58
|
.describe("House admin only: a sub-account ID to operate on. Omit to operate on your own account. A non-house session that passes this is denied (cross-account-denied).");
|
|
50
|
-
|
|
59
|
+
const sharedArg = z
|
|
60
|
+
.boolean()
|
|
61
|
+
.optional()
|
|
62
|
+
.describe("Operate on the install-wide shared folder instead of an account directory. Every account may read it; only the house account may write. Cannot be combined with targetAccountId (shared-and-target-exclusive).");
|
|
63
|
+
eagerTool(server, "file-read", "Read a UTF-8 file under the account directory. Pass a path relative to the account root; pass targetAccountId (house admin only) to read a sub-account's file; pass shared:true to read the install-wide shared folder, which every account may read.", { path: z.string().describe("Path relative to the account directory"), targetAccountId: targetArg, shared: sharedArg }, async (a) => {
|
|
51
64
|
const c = ctx();
|
|
52
65
|
return c ? fileRead(a, c) : refuseNoAccount("file-read");
|
|
53
66
|
});
|
|
54
|
-
eagerTool(server, "file-write", "Write (create or overwrite) a UTF-8 file under the account directory, creating parent directories as needed.", {
|
|
67
|
+
eagerTool(server, "file-write", "Write (create or overwrite) a UTF-8 file under the account directory, creating parent directories as needed. With shared:true the target is the install-wide shared folder, which is read-only unless you are the house account.", {
|
|
55
68
|
path: z.string().describe("Path relative to the account directory"),
|
|
56
69
|
content: z.string().describe("Full file contents to write"),
|
|
57
70
|
targetAccountId: targetArg,
|
|
71
|
+
shared: sharedArg,
|
|
58
72
|
}, async (a) => {
|
|
59
73
|
const c = ctx();
|
|
60
74
|
return c ? fileWrite(a, c) : refuseNoAccount("file-write");
|
|
61
75
|
});
|
|
62
|
-
eagerTool(server, "file-edit", "Replace a single unique occurrence of oldString with newString in a file under the account directory. Fails if oldString is absent or matches more than once.", {
|
|
76
|
+
eagerTool(server, "file-edit", "Replace a single unique occurrence of oldString with newString in a file under the account directory. Fails if oldString is absent or matches more than once. With shared:true the target is the install-wide shared folder, which is read-only unless you are the house account.", {
|
|
63
77
|
path: z.string().describe("Path relative to the account directory"),
|
|
64
78
|
oldString: z.string().describe("Exact text to replace (must occur exactly once)"),
|
|
65
79
|
newString: z.string().describe("Replacement text"),
|
|
66
80
|
targetAccountId: targetArg,
|
|
81
|
+
shared: sharedArg,
|
|
67
82
|
}, async (a) => {
|
|
68
83
|
const c = ctx();
|
|
69
84
|
return c ? fileEdit(a, c) : refuseNoAccount("file-edit");
|
|
70
85
|
});
|
|
71
|
-
eagerTool(server, "file-list", "List the entries of a directory under the account directory (name + type). Omit path to list the account root.", { path: z.string().optional().describe("Directory relative to the account root"), targetAccountId: targetArg }, async (a) => {
|
|
86
|
+
eagerTool(server, "file-list", "List the entries of a directory under the account directory (name + type). Omit path to list the account root; pass shared:true to list the install-wide shared folder.", { path: z.string().optional().describe("Directory relative to the account root"), targetAccountId: targetArg, shared: sharedArg }, async (a) => {
|
|
72
87
|
const c = ctx();
|
|
73
88
|
return c ? fileList(a, c) : refuseNoAccount("file-list");
|
|
74
89
|
});
|
|
75
|
-
eagerTool(server, "file-glob", "List files under the account directory matching a glob (**, *, ?), returned as paths relative to the account root.", { pattern: z.string().describe("Glob pattern, e.g. **/*.md"), targetAccountId: targetArg }, async (a) => {
|
|
90
|
+
eagerTool(server, "file-glob", "List files under the account directory matching a glob (**, *, ?), returned as paths relative to the account root; pass shared:true to glob the install-wide shared folder.", { pattern: z.string().describe("Glob pattern, e.g. **/*.md"), targetAccountId: targetArg, shared: sharedArg }, async (a) => {
|
|
76
91
|
const c = ctx();
|
|
77
92
|
return c ? fileGlob(a, c) : refuseNoAccount("file-glob");
|
|
78
93
|
});
|
|
79
|
-
eagerTool(server, "file-grep", "Search file contents under the account directory for a JavaScript regular expression, returning file:line:preview matches. Omit path to search the whole account.", {
|
|
94
|
+
eagerTool(server, "file-grep", "Search file contents under the account directory for a JavaScript regular expression, returning file:line:preview matches. Omit path to search the whole account; pass shared:true to search the install-wide shared folder.", {
|
|
80
95
|
pattern: z.string().describe("JavaScript regular expression"),
|
|
81
96
|
path: z.string().optional().describe("Subdirectory (relative) to limit the search"),
|
|
82
97
|
targetAccountId: targetArg,
|
|
98
|
+
shared: sharedArg,
|
|
83
99
|
}, async (a) => {
|
|
84
100
|
const c = ctx();
|
|
85
101
|
return c ? fileGrep(a, c) : refuseNoAccount("file-grep");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,wEAAwE;AACxE,8DAA8D;AAC9D,8DAA8D;AAC9D,MAAM,MAAM,GAAQ,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAEjF,4EAA4E;AAC5E,yEAAyE;AACzE,+BAA+B;AAC/B,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC;AACpD,8EAA8E;AAC9E,8EAA8E;AAC9E,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AACrD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;AACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+BAA+B,YAAY,IAAI,MAAM,eAAe,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,IAAI,CACpG,CAAC;AAEF,SAAS,eAAe,CAAC,QAAgB;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,QAAQ,qCAAqC,CAAC,CAAC;IACzF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,GAAG,QAAQ,sHAAsH;aACxI;SACF;QACD,OAAO,EAAE,IAAa;KACvB,CAAC;AACJ,CAAC;AAED;;mFAEmF;AACnF,SAAS,GAAG;IACV,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { mkdtempSync, mkdirSync, writeFileSync, symlinkSync, rmSync, realpathSync } from "node:fs";
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, symlinkSync, rmSync, realpathSync, existsSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
|
-
import { resolveRoot, containedPath, readPluginHouseScope } from "../scope.js";
|
|
5
|
+
import { resolveRoot, containedPath, readPluginHouseScope, SHARED_ROOT_LABEL, } from "../scope.js";
|
|
6
6
|
// enumerateValidAccountIds only counts UUID-named dirs with a parseable
|
|
7
7
|
// account.json, so the fixtures use real UUIDs.
|
|
8
8
|
const HOUSE = "11111111-1111-4111-8111-111111111111";
|
|
@@ -23,8 +23,18 @@ afterEach(() => {
|
|
|
23
23
|
rmSync(accountsDir, { recursive: true, force: true });
|
|
24
24
|
rmSync(outsideDir, { recursive: true, force: true });
|
|
25
25
|
});
|
|
26
|
-
const houseCtx = () => ({
|
|
27
|
-
|
|
26
|
+
const houseCtx = () => ({
|
|
27
|
+
ownAccountId: HOUSE,
|
|
28
|
+
houseScope: HOUSE,
|
|
29
|
+
accountsDir,
|
|
30
|
+
sessionId: null,
|
|
31
|
+
});
|
|
32
|
+
const clientCtx = () => ({
|
|
33
|
+
ownAccountId: CLIENT,
|
|
34
|
+
houseScope: null,
|
|
35
|
+
accountsDir,
|
|
36
|
+
sessionId: null,
|
|
37
|
+
});
|
|
28
38
|
describe("resolveRoot — fail-closed gate", () => {
|
|
29
39
|
it("no target → own account root", () => {
|
|
30
40
|
const r = resolveRoot(houseCtx(), undefined, "file-read");
|
|
@@ -75,6 +85,96 @@ describe("readPluginHouseScope — fail-closed against loader substitution", ()
|
|
|
75
85
|
expect(readPluginHouseScope({ HOUSE_ADMIN_SCOPE: "${HOUSE_ADMIN_SCOPE}" })).toBeNull();
|
|
76
86
|
});
|
|
77
87
|
});
|
|
88
|
+
// Task 2323 — the shared root lives at `<dataRoot>/shared`, a sibling of
|
|
89
|
+
// `<dataRoot>/accounts`. The suite's top-level `accountsDir` is a bare mkdtemp
|
|
90
|
+
// whose parent is the OS tmpdir, so these tests build their own two-level
|
|
91
|
+
// fixture rather than reaching for `<tmpdir>/shared`, which other processes own.
|
|
92
|
+
describe("resolveRoot — shared root", () => {
|
|
93
|
+
let dataRoot;
|
|
94
|
+
let sharedAccountsDir;
|
|
95
|
+
const seed = (id, role) => {
|
|
96
|
+
mkdirSync(join(sharedAccountsDir, id), { recursive: true });
|
|
97
|
+
writeFileSync(join(sharedAccountsDir, id, "account.json"), JSON.stringify({ accountId: id, role }));
|
|
98
|
+
};
|
|
99
|
+
beforeEach(() => {
|
|
100
|
+
dataRoot = mkdtempSync(join(tmpdir(), "xacct-data-"));
|
|
101
|
+
sharedAccountsDir = join(dataRoot, "accounts");
|
|
102
|
+
mkdirSync(sharedAccountsDir, { recursive: true });
|
|
103
|
+
mkdirSync(join(dataRoot, "shared"), { recursive: true });
|
|
104
|
+
seed(HOUSE, "house");
|
|
105
|
+
seed(CLIENT, "client");
|
|
106
|
+
});
|
|
107
|
+
afterEach(() => {
|
|
108
|
+
rmSync(dataRoot, { recursive: true, force: true });
|
|
109
|
+
});
|
|
110
|
+
const ctxFor = (id, scope) => ({
|
|
111
|
+
ownAccountId: id,
|
|
112
|
+
houseScope: scope,
|
|
113
|
+
accountsDir: sharedAccountsDir,
|
|
114
|
+
sessionId: "sid-test",
|
|
115
|
+
});
|
|
116
|
+
it("a sub-account resolves the shared root for a read", () => {
|
|
117
|
+
const r = resolveRoot(ctxFor(CLIENT, null), undefined, "file-read", true);
|
|
118
|
+
expect(r).toEqual({ root: resolve(dataRoot, "shared"), resolved: SHARED_ROOT_LABEL });
|
|
119
|
+
});
|
|
120
|
+
it("the house resolves the shared root for a write", () => {
|
|
121
|
+
const r = resolveRoot(ctxFor(HOUSE, HOUSE), undefined, "file-write", true);
|
|
122
|
+
expect(r).toEqual({ root: resolve(dataRoot, "shared"), resolved: SHARED_ROOT_LABEL });
|
|
123
|
+
});
|
|
124
|
+
it("a sub-account write to the shared root is refused", () => {
|
|
125
|
+
const r = resolveRoot(ctxFor(CLIENT, null), undefined, "file-write", true);
|
|
126
|
+
expect(r).toEqual({ reject: "shared-folder-read-only" });
|
|
127
|
+
});
|
|
128
|
+
it("a sub-account edit of the shared root is refused", () => {
|
|
129
|
+
const r = resolveRoot(ctxFor(CLIENT, null), undefined, "file-edit", true);
|
|
130
|
+
expect(r).toEqual({ reject: "shared-folder-read-only" });
|
|
131
|
+
});
|
|
132
|
+
it("a house SPECIALIST session writes too — the gate is the account, not the role", () => {
|
|
133
|
+
// A specialist carries houseScope=null (Task 1440 stamps HOUSE_ADMIN_SCOPE
|
|
134
|
+
// only for a non-specialist role:admin session), yet it runs on the house
|
|
135
|
+
// account, so the shared write is allowed.
|
|
136
|
+
const r = resolveRoot(ctxFor(HOUSE, null), undefined, "file-write", true);
|
|
137
|
+
expect(r).toEqual({ root: resolve(dataRoot, "shared"), resolved: SHARED_ROOT_LABEL });
|
|
138
|
+
});
|
|
139
|
+
it("shared plus targetAccountId is refused", () => {
|
|
140
|
+
const r = resolveRoot(ctxFor(HOUSE, HOUSE), CLIENT, "file-read", true);
|
|
141
|
+
expect(r).toEqual({ reject: "shared-and-target-exclusive" });
|
|
142
|
+
});
|
|
143
|
+
it("omitting shared still resolves the account root", () => {
|
|
144
|
+
const r = resolveRoot(ctxFor(CLIENT, null), undefined, "file-read");
|
|
145
|
+
expect(r).toEqual({ root: resolve(sharedAccountsDir, CLIENT), resolved: CLIENT });
|
|
146
|
+
});
|
|
147
|
+
it("under house drift (two houses) no account may write", () => {
|
|
148
|
+
seed(GHOST, "house");
|
|
149
|
+
const r = resolveRoot(ctxFor(HOUSE, HOUSE), undefined, "file-write", true);
|
|
150
|
+
expect(r).toEqual({ reject: "shared-folder-read-only" });
|
|
151
|
+
});
|
|
152
|
+
it("an absent shared root is refused, and no plugin call creates it", () => {
|
|
153
|
+
// The installer is the only creator. If a plugin call created it, a folder
|
|
154
|
+
// brought into existence mid-session by a READ would be natively writable
|
|
155
|
+
// for the rest of that session, because pty-spawner resolved its write-deny
|
|
156
|
+
// from existsSync at spawn time.
|
|
157
|
+
rmSync(resolve(dataRoot, "shared"), { recursive: true, force: true });
|
|
158
|
+
expect(resolveRoot(ctxFor(HOUSE, HOUSE), undefined, "file-write", true)).toEqual({
|
|
159
|
+
reject: "shared-folder-absent",
|
|
160
|
+
});
|
|
161
|
+
expect(resolveRoot(ctxFor(CLIENT, null), undefined, "file-read", true)).toEqual({
|
|
162
|
+
reject: "shared-folder-absent",
|
|
163
|
+
});
|
|
164
|
+
expect(existsSync(resolve(dataRoot, "shared"))).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
it("containment rejects ../ escape out of the shared root", () => {
|
|
167
|
+
const root = resolve(dataRoot, "shared");
|
|
168
|
+
mkdirSync(root, { recursive: true });
|
|
169
|
+
expect(() => containedPath(root, `../accounts/${CLIENT}/stolen.txt`)).toThrow("path-escape");
|
|
170
|
+
});
|
|
171
|
+
it("containment rejects a symlink out of the shared root into an account", () => {
|
|
172
|
+
const root = resolve(dataRoot, "shared");
|
|
173
|
+
mkdirSync(root, { recursive: true });
|
|
174
|
+
symlinkSync(resolve(sharedAccountsDir, CLIENT), join(root, "escape"), "dir");
|
|
175
|
+
expect(() => containedPath(root, "escape/account.json")).toThrow("path-escape");
|
|
176
|
+
});
|
|
177
|
+
});
|
|
78
178
|
describe("containedPath — traversal guard", () => {
|
|
79
179
|
it("allows a legitimate file directly under root", () => {
|
|
80
180
|
const root = resolve(accountsDir, HOUSE);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/scope.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"scope.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/scope.test.ts"],"names":[],"mappings":"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"}
|
package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-folder.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/shared-folder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { SHARED_DIR_NAME, sharedRoot, isSharedPath, decideSharedWrite, isHouseAccountDir, } from "../../../../../../lib/shared-folder/dist/index.js";
|
|
6
|
+
describe("shared-folder pure predicates", () => {
|
|
7
|
+
it("names the directory `shared`", () => {
|
|
8
|
+
expect(SHARED_DIR_NAME).toBe("shared");
|
|
9
|
+
});
|
|
10
|
+
it("roots at <dataRoot>/shared", () => {
|
|
11
|
+
expect(sharedRoot("/inst/data")).toBe(resolve("/inst/data", "shared"));
|
|
12
|
+
});
|
|
13
|
+
it("matches the first segment only", () => {
|
|
14
|
+
expect(isSharedPath("shared")).toBe(true);
|
|
15
|
+
expect(isSharedPath("shared/brand/tokens.json")).toBe(true);
|
|
16
|
+
expect(isSharedPath("/shared/x")).toBe(true);
|
|
17
|
+
expect(isSharedPath("accounts/11111111-1111-4111-8111-111111111111/shared")).toBe(false);
|
|
18
|
+
expect(isSharedPath("accounts/x/y/shared/z")).toBe(false);
|
|
19
|
+
expect(isSharedPath("sharedish/x")).toBe(false);
|
|
20
|
+
expect(isSharedPath("")).toBe(false);
|
|
21
|
+
expect(isSharedPath(".")).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
it("allows a house write and refuses every other", () => {
|
|
24
|
+
expect(decideSharedWrite(true)).toEqual({ allow: true });
|
|
25
|
+
expect(decideSharedWrite(false)).toEqual({ reject: "shared-folder-read-only" });
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe("isHouseAccountDir", () => {
|
|
29
|
+
let root;
|
|
30
|
+
const HOUSE = "11111111-1111-4111-8111-111111111111";
|
|
31
|
+
const CLIENT = "22222222-2222-4222-8222-222222222222";
|
|
32
|
+
const seed = (id, role) => {
|
|
33
|
+
mkdirSync(join(root, id), { recursive: true });
|
|
34
|
+
writeFileSync(join(root, id, "account.json"), JSON.stringify({ role }), "utf-8");
|
|
35
|
+
};
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
root = mkdtempSync(join(tmpdir(), "sharedfolder-"));
|
|
38
|
+
});
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
rmSync(root, { recursive: true, force: true });
|
|
41
|
+
});
|
|
42
|
+
it("is true for the single house account", () => {
|
|
43
|
+
seed(HOUSE, "house");
|
|
44
|
+
seed(CLIENT, "client");
|
|
45
|
+
expect(isHouseAccountDir(root, HOUSE)).toBe(true);
|
|
46
|
+
expect(isHouseAccountDir(root, CLIENT)).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it("is false for every account when the census shows two houses (drift)", () => {
|
|
49
|
+
seed(HOUSE, "house");
|
|
50
|
+
seed(CLIENT, "house");
|
|
51
|
+
expect(isHouseAccountDir(root, HOUSE)).toBe(false);
|
|
52
|
+
expect(isHouseAccountDir(root, CLIENT)).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
it("is false when no house is present", () => {
|
|
55
|
+
seed(CLIENT, "client");
|
|
56
|
+
expect(isHouseAccountDir(root, CLIENT)).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
it("is false when the accounts dir does not exist", () => {
|
|
59
|
+
expect(isHouseAccountDir(join(root, "absent"), HOUSE)).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
it("is false when an account.json is unreadable, without throwing", () => {
|
|
62
|
+
seed(HOUSE, "house");
|
|
63
|
+
writeFileSync(join(root, HOUSE, "account.json"), "{ not json", "utf-8");
|
|
64
|
+
expect(isHouseAccountDir(root, HOUSE)).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=shared-folder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-folder.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/shared-folder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolved` value for the shared root, and the discriminator every caller uses
|
|
3
|
+
* to tell a shared resolution from an account one. A provisioned account id is
|
|
4
|
+
* always a UUID, so this literal can never collide with one.
|
|
5
|
+
*
|
|
6
|
+
* A separate `kind` field was considered and rejected: six landed assertions in
|
|
7
|
+
* scope.test.ts compare the success shape with `toEqual`, and widening it would
|
|
8
|
+
* have rewritten passing tests for a distinction this label already carries.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SHARED_ROOT_LABEL = "shared";
|
|
1
11
|
/**
|
|
2
12
|
* Read HOUSE_ADMIN_SCOPE for the plugin, fail-closed. HOUSE_ADMIN_SCOPE is the
|
|
3
13
|
* whole boundary: it is present in the spawn env ONLY for a house role:admin
|
|
@@ -24,12 +34,16 @@ export interface Ctx {
|
|
|
24
34
|
houseScope: string | null;
|
|
25
35
|
/** `<install>/data/accounts` — the root that all account dirs live under. */
|
|
26
36
|
accountsDir: string;
|
|
37
|
+
/** Spawn env SESSION_ID — the `sid=` correlation key that ties one call's
|
|
38
|
+
* `[shared]` lines together. Null in the metadata-only boot, where no call
|
|
39
|
+
* reaches a filesystem operation anyway. */
|
|
40
|
+
sessionId: string | null;
|
|
27
41
|
}
|
|
28
42
|
export type ResolveRootResult = {
|
|
29
43
|
root: string;
|
|
30
44
|
resolved: string;
|
|
31
45
|
} | {
|
|
32
|
-
reject: "cross-account-denied" | "cross-account-invalid-target" | "cross-account-target-not-provisioned";
|
|
46
|
+
reject: "cross-account-denied" | "cross-account-invalid-target" | "cross-account-target-not-provisioned" | "shared-and-target-exclusive" | "shared-folder-read-only" | "shared-folder-absent";
|
|
33
47
|
};
|
|
34
48
|
/**
|
|
35
49
|
* Resolve the account directory a tool call acts on, gated fail-closed. Emits
|
|
@@ -37,7 +51,7 @@ export type ResolveRootResult = {
|
|
|
37
51
|
* `root` is `<accountsDir>/<resolved>` — the strict filesystem root the caller
|
|
38
52
|
* must contain every path within.
|
|
39
53
|
*/
|
|
40
|
-
export declare function resolveRoot(ctx: Ctx, targetAccountId: string | undefined, tool: string): ResolveRootResult;
|
|
54
|
+
export declare function resolveRoot(ctx: Ctx, targetAccountId: string | undefined, tool: string, shared?: boolean): ResolveRootResult;
|
|
41
55
|
/**
|
|
42
56
|
* Resolve `relPath` against the account `root` and prove it stays inside.
|
|
43
57
|
* Lexical containment rejects `../` and absolute-path escapes; a realpath check
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/lib/scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/lib/scope.ts"],"names":[],"mappings":"AA0BA;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAM1C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CAK1E;AAED,MAAM,WAAW,GAAG;IAClB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB;;iDAE6C;IAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClC;IACE,MAAM,EACF,sBAAsB,GACtB,8BAA8B,GAC9B,sCAAsC,GACtC,6BAA6B,GAC7B,yBAAyB,GACzB,sBAAsB,CAAC;CAC5B,CAAC;AAEN;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,GAAG,EACR,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,GACf,iBAAiB,CA0EnB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAenE"}
|
|
@@ -16,7 +16,21 @@ import { resolve, dirname, sep } from "node:path";
|
|
|
16
16
|
import { realpathSync, existsSync } from "node:fs";
|
|
17
17
|
import { resolveEffectiveAccountCore } from "../../../../../lib/account-scope/dist/index.js";
|
|
18
18
|
import { isProvisionedAccount } from "../../../../../lib/account-enumeration/dist/index.js";
|
|
19
|
+
import { sharedRoot, decideSharedWrite, isHouseAccountDir, } from "../../../../../lib/shared-folder/dist/index.js";
|
|
19
20
|
const short = (id) => id.slice(0, 8);
|
|
21
|
+
/**
|
|
22
|
+
* `resolved` value for the shared root, and the discriminator every caller uses
|
|
23
|
+
* to tell a shared resolution from an account one. A provisioned account id is
|
|
24
|
+
* always a UUID, so this literal can never collide with one.
|
|
25
|
+
*
|
|
26
|
+
* A separate `kind` field was considered and rejected: six landed assertions in
|
|
27
|
+
* scope.test.ts compare the success shape with `toEqual`, and widening it would
|
|
28
|
+
* have rewritten passing tests for a distinction this label already carries.
|
|
29
|
+
*/
|
|
30
|
+
export const SHARED_ROOT_LABEL = "shared";
|
|
31
|
+
/** The two tools that mutate. Every other file tool reads, and reads of the
|
|
32
|
+
* shared root are open to every account. */
|
|
33
|
+
const SHARED_WRITE_TOOLS = new Set(["file-write", "file-edit"]);
|
|
20
34
|
/**
|
|
21
35
|
* Read HOUSE_ADMIN_SCOPE for the plugin, fail-closed. HOUSE_ADMIN_SCOPE is the
|
|
22
36
|
* whole boundary: it is present in the spawn env ONLY for a house role:admin
|
|
@@ -49,7 +63,46 @@ export function readPluginHouseScope(env) {
|
|
|
49
63
|
* `root` is `<accountsDir>/<resolved>` — the strict filesystem root the caller
|
|
50
64
|
* must contain every path within.
|
|
51
65
|
*/
|
|
52
|
-
export function resolveRoot(ctx, targetAccountId, tool) {
|
|
66
|
+
export function resolveRoot(ctx, targetAccountId, tool, shared) {
|
|
67
|
+
// Task 2323 — the shared root branch. `<dataRoot>/shared` is a sibling of
|
|
68
|
+
// `<dataRoot>/accounts`, so it is NOT an account and cannot ride the
|
|
69
|
+
// targetAccountId resolver below; it gets its own gate here.
|
|
70
|
+
if (shared) {
|
|
71
|
+
const sid = ctx.sessionId ?? "none";
|
|
72
|
+
// targetAccountId selects an ACCOUNT root. Accepting both would leave the
|
|
73
|
+
// caller's intent ambiguous, so it is refused rather than silently
|
|
74
|
+
// resolved to one of them.
|
|
75
|
+
if (targetAccountId) {
|
|
76
|
+
process.stderr.write(`[shared] op=gate sid=${sid} account=${short(ctx.ownAccountId)} tool=${tool} decision=deny reason=shared-and-target-exclusive\n`);
|
|
77
|
+
return { reject: "shared-and-target-exclusive" };
|
|
78
|
+
}
|
|
79
|
+
const root = sharedRoot(resolve(ctx.accountsDir, ".."));
|
|
80
|
+
// The installer is the ONLY creator of this directory. An earlier revision
|
|
81
|
+
// mkdir'd it here so a first write would not trip `containedPath`'s
|
|
82
|
+
// unconditional realpath, but that made a plugin call — including a
|
|
83
|
+
// sub-account READ — able to create it, and the pty-spawner decides its
|
|
84
|
+
// native write-deny from `existsSync` at spawn time. A folder created
|
|
85
|
+
// mid-session by a read would then be writable natively for the rest of that
|
|
86
|
+
// session, because the deny was resolved before it existed. One creator
|
|
87
|
+
// keeps the spawn-time and call-time answers in agreement.
|
|
88
|
+
if (!existsSync(root)) {
|
|
89
|
+
process.stderr.write(`[shared] op=gate sid=${sid} account=${short(ctx.ownAccountId)} tool=${tool} decision=deny reason=shared-folder-absent\n`);
|
|
90
|
+
return { reject: "shared-folder-absent" };
|
|
91
|
+
}
|
|
92
|
+
const isWrite = SHARED_WRITE_TOOLS.has(tool);
|
|
93
|
+
const isHouse = isHouseAccountDir(ctx.accountsDir, ctx.ownAccountId);
|
|
94
|
+
process.stderr.write(`[shared] op=classify sid=${sid} tool=${tool} isShared=true\n`);
|
|
95
|
+
if (isWrite) {
|
|
96
|
+
const decision = decideSharedWrite(isHouse);
|
|
97
|
+
if ("reject" in decision) {
|
|
98
|
+
process.stderr.write(`[shared] op=gate sid=${sid} account=${short(ctx.ownAccountId)} isHouse=false verb=write decision=deny reason=${decision.reject}\n`);
|
|
99
|
+
return { reject: decision.reject };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
process.stderr.write(`[shared] op=gate sid=${sid} account=${short(ctx.ownAccountId)} isHouse=${isHouse} verb=${isWrite ? "write" : "read"} decision=allow reason=none\n`);
|
|
103
|
+
process.stderr.write(`[shared] op=fs-root root=data/shared/\n`);
|
|
104
|
+
return { root, resolved: SHARED_ROOT_LABEL };
|
|
105
|
+
}
|
|
53
106
|
// Re-scan-on-miss (Task 1471): a sub-account created at runtime after this
|
|
54
107
|
// plugin process booted is absent from the boot-time cached set; the miss
|
|
55
108
|
// re-scans disk once so a live-created target resolves without a restart. A
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/lib/scope.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,mDAAmD;AACnD,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,yEAAyE;AACzE,8EAA8E;AAC9E,2CAA2C;AAC3C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/lib/scope.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,mDAAmD;AACnD,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,yEAAyE;AACzE,8EAA8E;AAC9E,2CAA2C;AAC3C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,gDAAgD,CAAC;AAExD,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAE1C;6CAC6C;AAC7C,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAsB;IACzD,MAAM,GAAG,GAAG,GAAG,CAAC,iBAAiB,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,GAAG,CAAC;AACb,CAAC;AA2BD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,GAAQ,EACR,eAAmC,EACnC,IAAY,EACZ,MAAgB;IAEhB,0EAA0E;IAC1E,qEAAqE;IACrE,6DAA6D;IAC7D,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC;QACpC,0EAA0E;QAC1E,mEAAmE;QACnE,2BAA2B;QAC3B,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wBAAwB,GAAG,YAAY,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,IAAI,qDAAqD,CACjI,CAAC;YACF,OAAO,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAAC;QACnD,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;QACxD,2EAA2E;QAC3E,oEAAoE;QACpE,oEAAoE;QACpE,wEAAwE;QACxE,sEAAsE;QACtE,6EAA6E;QAC7E,wEAAwE;QACxE,2DAA2D;QAC3D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wBAAwB,GAAG,YAAY,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,IAAI,8CAA8C,CAC1H,CAAC;YACF,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QAC5C,CAAC;QACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;QACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,GAAG,SAAS,IAAI,kBAAkB,CAAC,CAAC;QACrF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;gBACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wBAAwB,GAAG,YAAY,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,kDAAkD,QAAQ,CAAC,MAAM,IAAI,CACpI,CAAC;gBACF,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wBAAwB,GAAG,YAAY,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,YAAY,OAAO,SAAS,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,+BAA+B,CACpJ,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAChE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC/C,CAAC;IACD,2EAA2E;IAC3E,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,8DAA8D;IAC9D,MAAM,gBAAgB,GAAG,CAAC,EAAU,EAAE,EAAE,CACtC,oBAAoB,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,2BAA2B,CACrC,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,eAAe,EAAE,EAC/E,gBAAgB,EAChB,sCAAsC,CACvC,CAAC;IACF,MAAM,WAAW,GAAG,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACtE,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACrD,IAAI,QAAQ,IAAI,GAAG,EAAE,CAAC;QACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wBAAwB,IAAI,WAAW,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,WAAW,eAAe,UAAU,yBAAyB,GAAG,CAAC,MAAM,IAAI,CACrJ,CAAC;QACF,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wBAAwB,IAAI,WAAW,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,WAAW,eAAe,UAAU,+BAA+B,CAC7I,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACzF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACzD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,GAAU,EAAE;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sCAAsC,OAAO,aAAa,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,CACrG,CAAC;QACF,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC,CAAC;IACF,IAAI,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC;QAAE,MAAM,EAAE,CAAC;IAClE,IAAI,QAAQ,GAAG,GAAG,CAAC;IACnB,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,YAAY,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC;QAAE,MAAM,EAAE,CAAC;IACpF,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -19,8 +19,18 @@ beforeEach(() => {
|
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
afterEach(() => rmSync(accountsDir, { recursive: true, force: true }));
|
|
22
|
-
const house = () => ({
|
|
23
|
-
|
|
22
|
+
const house = () => ({
|
|
23
|
+
ownAccountId: HOUSE,
|
|
24
|
+
houseScope: HOUSE,
|
|
25
|
+
accountsDir,
|
|
26
|
+
sessionId: null,
|
|
27
|
+
});
|
|
28
|
+
const client = () => ({
|
|
29
|
+
ownAccountId: CLIENT,
|
|
30
|
+
houseScope: null,
|
|
31
|
+
accountsDir,
|
|
32
|
+
sessionId: null,
|
|
33
|
+
});
|
|
24
34
|
const text = (r) => r.content[0].text;
|
|
25
35
|
describe("file handlers — own account round-trip", () => {
|
|
26
36
|
it("write → read → edit → list on the house's own account", () => {
|
|
@@ -91,4 +101,68 @@ describe("file handlers — traversal guard", () => {
|
|
|
91
101
|
expect(text(r)).toContain("escapes the account directory");
|
|
92
102
|
});
|
|
93
103
|
});
|
|
104
|
+
// Task 2323 — the shared folder. Own two-level fixture (`<dataRoot>/accounts`)
|
|
105
|
+
// because the shared root is `<dataRoot>/shared`, and the suite's top-level
|
|
106
|
+
// `accountsDir` is a bare mkdtemp whose parent is the OS tmpdir.
|
|
107
|
+
describe("file handlers — shared folder", () => {
|
|
108
|
+
let dataRoot;
|
|
109
|
+
let sharedAccountsDir;
|
|
110
|
+
const seed = (id, role) => {
|
|
111
|
+
mkdirSync(join(sharedAccountsDir, id), { recursive: true });
|
|
112
|
+
writeFileSync(join(sharedAccountsDir, id, "account.json"), JSON.stringify({ accountId: id, role }));
|
|
113
|
+
};
|
|
114
|
+
const ctxFor = (id, scope) => ({
|
|
115
|
+
ownAccountId: id,
|
|
116
|
+
houseScope: scope,
|
|
117
|
+
accountsDir: sharedAccountsDir,
|
|
118
|
+
sessionId: "sid-shared",
|
|
119
|
+
});
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
dataRoot = mkdtempSync(join(tmpdir(), "xacct-shared-"));
|
|
122
|
+
sharedAccountsDir = join(dataRoot, "accounts");
|
|
123
|
+
mkdirSync(sharedAccountsDir, { recursive: true });
|
|
124
|
+
mkdirSync(join(dataRoot, "shared"), { recursive: true });
|
|
125
|
+
seed(HOUSE, "house");
|
|
126
|
+
seed(CLIENT, "client");
|
|
127
|
+
});
|
|
128
|
+
afterEach(() => rmSync(dataRoot, { recursive: true, force: true }));
|
|
129
|
+
it("the house writes, a sub-account reads, a sub-account cannot write", () => {
|
|
130
|
+
const w = fileWrite({ path: "brand/tokens.json", content: '{"a":1}', shared: true }, ctxFor(HOUSE, HOUSE));
|
|
131
|
+
expect(w.isError).toBeUndefined();
|
|
132
|
+
expect(readFileSync(join(dataRoot, "shared", "brand", "tokens.json"), "utf-8")).toBe('{"a":1}');
|
|
133
|
+
expect(text(fileRead({ path: "brand/tokens.json", shared: true }, ctxFor(CLIENT, null)))).toBe('{"a":1}');
|
|
134
|
+
const denied = fileWrite({ path: "brand/tokens.json", content: "clobbered", shared: true }, ctxFor(CLIENT, null));
|
|
135
|
+
expect(denied.isError).toBe(true);
|
|
136
|
+
expect(text(denied)).toContain("shared-folder-read-only");
|
|
137
|
+
// The refusal is real, not cosmetic: the bytes on disk are untouched.
|
|
138
|
+
expect(readFileSync(join(dataRoot, "shared", "brand", "tokens.json"), "utf-8")).toBe('{"a":1}');
|
|
139
|
+
});
|
|
140
|
+
it("a sub-account cannot edit a shared file", () => {
|
|
141
|
+
fileWrite({ path: "t.json", content: '{"a":1}', shared: true }, ctxFor(HOUSE, HOUSE));
|
|
142
|
+
const r = fileEdit({ path: "t.json", oldString: "1", newString: "2", shared: true }, ctxFor(CLIENT, null));
|
|
143
|
+
expect(r.isError).toBe(true);
|
|
144
|
+
expect(text(r)).toContain("shared-folder-read-only");
|
|
145
|
+
expect(readFileSync(join(dataRoot, "shared", "t.json"), "utf-8")).toBe('{"a":1}');
|
|
146
|
+
});
|
|
147
|
+
it("list, glob and grep of the shared folder are open to a sub-account", () => {
|
|
148
|
+
fileWrite({ path: "brand/tokens.json", content: '{"hue":210}', shared: true }, ctxFor(HOUSE, HOUSE));
|
|
149
|
+
expect(text(fileList({ path: "brand", shared: true }, ctxFor(CLIENT, null)))).toContain("tokens.json");
|
|
150
|
+
expect(text(fileGlob({ pattern: "**/*.json", shared: true }, ctxFor(CLIENT, null)))).toContain("brand/tokens.json");
|
|
151
|
+
expect(text(fileGrep({ pattern: "hue", shared: true }, ctxFor(CLIENT, null)))).toContain("tokens.json");
|
|
152
|
+
});
|
|
153
|
+
it("a shared path that escapes the root names the shared directory, not the account", () => {
|
|
154
|
+
const r = fileRead({ path: "../accounts/" + CLIENT + "/account.json", shared: true }, ctxFor(CLIENT, null));
|
|
155
|
+
expect(r.isError).toBe(true);
|
|
156
|
+
expect(text(r)).toContain("escapes the shared directory");
|
|
157
|
+
});
|
|
158
|
+
it("shared with targetAccountId is refused as exclusive", () => {
|
|
159
|
+
const r = fileRead({ path: "x", shared: true, targetAccountId: CLIENT }, ctxFor(HOUSE, HOUSE));
|
|
160
|
+
expect(r.isError).toBe(true);
|
|
161
|
+
expect(text(r)).toContain("shared-and-target-exclusive");
|
|
162
|
+
});
|
|
163
|
+
it("omitting shared leaves account behaviour untouched", () => {
|
|
164
|
+
expect(fileWrite({ path: "own.txt", content: "mine" }, ctxFor(CLIENT, null)).isError).toBeUndefined();
|
|
165
|
+
expect(readFileSync(join(sharedAccountsDir, CLIENT, "own.txt"), "utf-8")).toBe("mine");
|
|
166
|
+
});
|
|
167
|
+
});
|
|
94
168
|
//# sourceMappingURL=handlers.test.js.map
|