wiki-viewer 1.7.2 → 1.8.1
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/.next/standalone/.github/workflows/publish.yml +1 -1
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +6 -0
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/routes-manifest.json +40 -0
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/agent/activity/route.js +6 -6
- package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js +6 -6
- package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js +6 -6
- package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js +7 -7
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js +5 -5
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js +5 -5
- package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js +8 -7
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js +9 -8
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js +8 -7
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js +7 -7
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js +6 -5
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js +7 -6
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/internal/span/route.js +6 -5
- package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/settings/route.js +7 -7
- package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js +8 -7
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js +8 -2
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/[...all]/route.js +5 -5
- package/.next/standalone/.next/server/app/api/auth/[...all]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/admins/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/admins/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/admins/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/admins/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/admins/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/admins/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/admins/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/auth-config/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/auth-config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/auth-settings/route.js +4 -4
- package/.next/standalone/.next/server/app/api/system/auth-settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/browse/route.js +4 -4
- package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/clear-root/route.js +5 -5
- package/.next/standalone/.next/server/app/api/system/clear-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/config/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/pins/route.js +4 -4
- package/.next/standalone/.next/server/app/api/system/pins/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/reveal/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/root-status/route.js +5 -5
- package/.next/standalone/.next/server/app/api/system/root-status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/set-root/route.js +6 -6
- package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/users/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/users/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/users/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/users/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/users/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/users/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/users/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js +14 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/system/workspaces/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js +8 -2
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/app/route.js +5 -5
- package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/content/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/download/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/file/route.js +8 -2
- package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/move/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/page/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/search/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route.js +15 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/wiki/search/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js +6 -6
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js +7 -7
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js +7 -9
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/signin/page.js +1 -1
- package/.next/standalone/.next/server/app/signin/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/signin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +6 -0
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0d2jbo5.js +1 -1
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0ytral2.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-244bv._.js +16 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0xz-_0v._.js → [root-of-the-server]__0-inabx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-ao6a_._.js → [root-of-the-server]__0.-9jt0._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0~-r-8f._.js → [root-of-the-server]__00c1-dr._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00lep-u._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00mtevo._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00qu86p._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__012753j._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__01hp8ax._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0269d2e._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0jhr.ex._.js → [root-of-the-server]__02n6z97._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__036mhjp._.js +5 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__03p0ob1._.js +16 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05t~v6l._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__068ni_k._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__082nhm6._.js → [root-of-the-server]__07vphbd._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0pg6dn-._.js → [root-of-the-server]__08lkuwa._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__09cqzem._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0p_ox-k._.js → [root-of-the-server]__09k4q9e._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0_601._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ae3dk6._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0s28.4-._.js → [root-of-the-server]__0af-x45._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cqu-wm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d75a5q._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d7x3e1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d7zxm_._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e7vs98._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fxzg4v._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0gda_iu._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hu~q20._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jk1uf4._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-8clq._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lhka0x._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0kdn1le._.js → [root-of-the-server]__0na11h0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0nd.b_c._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0otb8ra._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0p0-p__._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0piofm3._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rrf-jr._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s6_lzw._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0sh13v5._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ta~flu._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0v4im4p._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0qn8e~s._.js → [root-of-the-server]__0v_kyp-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vatqe-._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vdb2nr._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wdh63w._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0z3wg9x._.js +12 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0mzo03s._.js → [root-of-the-server]__0~.-3yk._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__123._fe._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__12800b1._.js → [root-of-the-server]__12ee_s6._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12onytt._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__04udrya._.js → [root-of-the-server]__12q8ch8._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1377.79._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1378-ox._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13aid91._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13hp4tw._.js +12 -0
- package/.next/standalone/.next/server/chunks/_079xuln._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0dr1r1g._.js +452 -0
- package/.next/standalone/.next/server/chunks/_101exke._.js +452 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_admins_route_actions_0dsm7cx.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_users_route_actions_0whj5cy.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_open_route_actions_1087xu7.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_route_actions_0~h7-8s.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_route_actions_0mkalc3.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_wiki_search_route_actions_0inxu93.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules__pnpm_0aj5g-w._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_lib_search_0d-_j3u._.js +46 -0
- package/.next/standalone/.next/server/chunks/src_lib_search_0ymmp0c._.js +46 -0
- package/.next/standalone/.next/server/chunks/ssr/{0~w0_katex_dist_katex_mjs_0b8ra51._.js → 0~w0_katex_dist_katex_mjs_04mhawr._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_erDiagram-TEJ5UH35_mjs_0v6rnqy._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_mermaid_core_mjs_0hj_n-~._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0btcd4o._.js → [root-of-the-server]__02twzph._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ytvlzs._.js → [root-of-the-server]__09~x2v~._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0pqaawz._.js +18 -18
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0c71i8a._.js → node_modules__pnpm_0.96tmo._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0lm8e2c._.js → node_modules__pnpm_011vy_q._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ezm2us._.js → node_modules__pnpm_01o_5qt._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j3mvgg._.js → node_modules__pnpm_04n0h6.._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0~ln0by._.js → node_modules__pnpm_093dp2q._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_11e~j49._.js → node_modules__pnpm_09ej62_._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0de8xt-._.js → node_modules__pnpm_09ljbdz._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-x6zex._.js → node_modules__pnpm_09~_ob2._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0yq5z.h._.js → node_modules__pnpm_0a01ng7._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0kwc-vs._.js → node_modules__pnpm_0b8qx0g._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hrbz84._.js → node_modules__pnpm_0bbc---._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hobcbs._.js → node_modules__pnpm_0c.309.._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0rw91-f._.js → node_modules__pnpm_0c8aunj._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0o.c1z8._.js → node_modules__pnpm_0hk6xys._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0dboa_e._.js → node_modules__pnpm_0hlzy8f._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j53hti._.js → node_modules__pnpm_0nw5ou2._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0xrmzh1._.js → node_modules__pnpm_0o.dn8o._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0cxwhfd._.js → node_modules__pnpm_0s0ur~d._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_07rxv2x._.js → node_modules__pnpm_0shlang._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0i.pw_m._.js → node_modules__pnpm_0sq3c2r._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ajzar9._.js → node_modules__pnpm_0t9jb7d._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_012nt.s._.js → node_modules__pnpm_0wmx9kq._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0z~h2ow._.js → node_modules__pnpm_0xfx0sf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0cbsnwf._.js → node_modules__pnpm_0yiz.-t._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0bum3-3._.js → node_modules__pnpm_11sut1u._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0mdo4i3._.js → node_modules__pnpm_124u4o2._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0il8j.j._.js → node_modules__pnpm_13tajgx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/src_app_signin_00yk0vm._.js +2 -2
- package/.next/standalone/.next/server/edge/chunks/{08yl_next_dist_esm_build_templates_edge-wrapper_0o9h3w_.js → 08yl_next_dist_esm_build_templates_edge-wrapper_0xbpts6.js} +2 -2
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0.pmgt2._.js +3 -0
- package/.next/standalone/.next/server/functions-config-manifest.json +6 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +8 -8
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/0c_~zevf2n0r4.css +2 -0
- package/.next/standalone/.next/static/chunks/0l4842ez-0_66.js +129 -0
- package/.next/standalone/README.md +46 -2
- package/.next/standalone/agents/bootstrap-prompt.md +3 -1
- package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +38 -11
- package/.next/standalone/docs/workspacing-plan.md +364 -0
- package/.next/standalone/package.json +2 -2
- package/.next/standalone/packages/wiki-viewer-mcp/README.md +6 -5
- package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +4 -0
- package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +4 -0
- package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +6 -0
- package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +5 -0
- package/.next/standalone/src/app/api/agent/activity/route.ts +9 -8
- package/.next/standalone/src/app/api/agent/events/[...path]/route.ts +20 -8
- package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +16 -9
- package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +28 -18
- package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +12 -7
- package/.next/standalone/src/app/api/agent/fs/move/route.ts +16 -11
- package/.next/standalone/src/app/api/agent/fs/search/route.ts +49 -13
- package/.next/standalone/src/app/api/agent/internal/span/route.ts +9 -5
- package/.next/standalone/src/app/api/agent/register/route.ts +9 -1
- package/.next/standalone/src/app/api/agent/settings/route.ts +7 -3
- package/.next/standalone/src/app/api/agent/sidecar/[...path]/route.ts +8 -4
- package/.next/standalone/src/app/api/agents/install/route.ts +20 -2
- package/.next/standalone/src/app/api/assets/[...path]/route.ts +9 -4
- package/.next/standalone/src/app/api/system/admins/route.ts +103 -0
- package/.next/standalone/src/app/api/system/reveal/route.ts +7 -6
- package/.next/standalone/src/app/api/system/set-root/route.ts +24 -1
- package/.next/standalone/src/app/api/system/users/route.ts +120 -0
- package/.next/standalone/src/app/api/system/workspaces/[id]/open/route.ts +34 -0
- package/.next/standalone/src/app/api/system/workspaces/[id]/route.ts +74 -0
- package/.next/standalone/src/app/api/system/workspaces/route.ts +67 -0
- package/.next/standalone/src/app/api/upload/[...path]/route.ts +10 -5
- package/.next/standalone/src/app/api/wiki/app/route.ts +10 -9
- package/.next/standalone/src/app/api/wiki/content/route.ts +14 -14
- package/.next/standalone/src/app/api/wiki/download/route.ts +7 -6
- package/.next/standalone/src/app/api/wiki/file/route.ts +7 -2
- package/.next/standalone/src/app/api/wiki/folder/route.ts +6 -5
- package/.next/standalone/src/app/api/wiki/move/route.ts +7 -7
- package/.next/standalone/src/app/api/wiki/new-file/route.ts +7 -6
- package/.next/standalone/src/app/api/wiki/page/route.ts +6 -5
- package/.next/standalone/src/app/api/wiki/presence/route.ts +8 -7
- package/.next/standalone/src/app/api/wiki/route.ts +13 -11
- package/.next/standalone/src/app/api/wiki/search/route.ts +44 -0
- package/.next/standalone/src/app/api/wiki/slugs/route.ts +8 -8
- package/.next/standalone/src/app/api/wiki/upload/route.ts +6 -5
- package/.next/standalone/src/app/api/wiki/watch/route.ts +16 -40
- package/.next/standalone/src/app/globals.css +484 -484
- package/.next/standalone/src/app/page.tsx +163 -49
- package/.next/standalone/src/components/auth-settings-sheet.tsx +171 -2
- package/.next/standalone/src/components/dir-picker.tsx +8 -6
- package/.next/standalone/src/components/editor/comment-thread.tsx +2 -1
- package/.next/standalone/src/components/editor/csv-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/editor-toolbar.tsx +2 -2
- package/.next/standalone/src/components/editor/editor.tsx +6 -5
- package/.next/standalone/src/components/editor/file-fallback-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/folder-index.tsx +2 -1
- package/.next/standalone/src/components/editor/image-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/media-popover.tsx +2 -1
- package/.next/standalone/src/components/editor/media-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/mermaid-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/node-app-viewer.tsx +4 -3
- package/.next/standalone/src/components/editor/notebook-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/office/docx-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/office/office-chrome.tsx +3 -2
- package/.next/standalone/src/components/editor/office/pptx-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/office/xlsx-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/pdf-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/proof-span-popover.tsx +2 -1
- package/.next/standalone/src/components/editor/source-viewer.tsx +3 -2
- package/.next/standalone/src/components/editor/suggest-edit-popover.tsx +2 -1
- package/.next/standalone/src/components/editor/suggestion-card.tsx +2 -1
- package/.next/standalone/src/components/editor/website-viewer.tsx +2 -1
- package/.next/standalone/src/components/editor/wiki-link-create-dialog.tsx +2 -1
- package/.next/standalone/src/components/search/search-command-dialog.tsx +109 -0
- package/.next/standalone/src/components/search/sidebar-search-box.tsx +121 -0
- package/.next/standalone/src/components/search/snippet-text.tsx +48 -0
- package/.next/standalone/src/components/ui/command.tsx +3 -2
- package/.next/standalone/src/lib/auth/admin.ts +112 -0
- package/.next/standalone/src/lib/auth/server.ts +13 -2
- package/.next/standalone/src/lib/config.ts +56 -4
- package/.next/standalone/src/lib/proof/audit.ts +19 -10
- package/.next/standalone/src/lib/proof/auth.ts +11 -0
- package/.next/standalone/src/lib/proof/collab-state.ts +4 -2
- package/.next/standalone/src/lib/proof/file-lock.ts +5 -0
- package/.next/standalone/src/lib/proof/idempotency.ts +5 -0
- package/.next/standalone/src/lib/proof/lease.ts +40 -27
- package/.next/standalone/src/lib/proof/mutex.ts +4 -0
- package/.next/standalone/src/lib/proof/raw-fs.ts +2 -3
- package/.next/standalone/src/lib/proof/registry.ts +5 -0
- package/.next/standalone/src/lib/search/indexable-exts.ts +25 -0
- package/.next/standalone/src/lib/search/indexer.ts +567 -0
- package/.next/standalone/src/lib/search/sanitize.ts +35 -0
- package/.next/standalone/src/lib/search/search-db.ts +57 -0
- package/.next/standalone/src/lib/search/watcher-pool.ts +79 -0
- package/.next/standalone/src/lib/workspace-client.ts +82 -0
- package/.next/standalone/src/lib/workspace-context.ts +142 -0
- package/.next/standalone/src/lib/workspaces.ts +196 -0
- package/.next/standalone/src/stores/ai-panel-store.ts +3 -2
- package/.next/standalone/src/stores/editor-store.ts +4 -3
- package/.next/standalone/src/stores/proof-store.ts +4 -3
- package/.next/standalone/src/stores/search-store.ts +86 -0
- package/.next/standalone/src/stores/wiki-slugs-store.ts +2 -1
- package/.next/standalone/src/tests/proof/admin-create-user.test.ts +43 -0
- package/.next/standalone/src/tests/proof/agent-workspace-scope.test.ts +134 -0
- package/.next/standalone/src/tests/proof/collab-state.test.ts +43 -41
- package/.next/standalone/src/tests/proof/preload.ts +21 -0
- package/.next/standalone/src/tests/proof/search-index.test.ts +339 -0
- package/.next/standalone/src/tests/proof/workspace-isolation.test.ts +87 -0
- package/.next/standalone/src/tests/proof/workspaces-api.test.ts +227 -0
- package/.next/standalone/tsconfig.tsbuildinfo +1 -1
- package/README.md +46 -2
- package/package.json +2 -2
- package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0o~h4zq.js +0 -5
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.hb9q2._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.uux34._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0092hkp._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05f6x0i._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05idwm9._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06-dtd0._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06sek6_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07fpqks._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__094q5bj._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0awzyon._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d_da6q._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hhhvm7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kk26wc._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0km8suj._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kur4ro._.js +0 -15
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0mkwoul._.js +0 -12
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qc2~6l._.js +0 -15
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qyd-o8._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rkve~v._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rzo40z._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0sjocwy._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ssj9~d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s~i040._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t220d-._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t5mg.n._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0trsqf4._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xq124z._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__106uw_c._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__10w2q~o._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13w-0iy._.js +0 -3
- package/.next/standalone/.next/server/chunks/src_lib_auth_server_ts_00f4e0h._.js +0 -452
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0ug2rvl._.js +0 -3
- package/.next/standalone/.next/static/chunks/0vwkqw_rofm-c.js +0 -129
- package/.next/standalone/.next/static/chunks/0zay6349~v_wc.css +0 -2
- /package/.next/standalone/.next/static/{0XvNCOSEq7cbARTLtAolL → 17VWCQ9_AhwJBT4yjkvWG}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{0XvNCOSEq7cbARTLtAolL → 17VWCQ9_AhwJBT4yjkvWG}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{0XvNCOSEq7cbARTLtAolL → 17VWCQ9_AhwJBT4yjkvWG}/_ssgManifest.js +0 -0
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* WIKI_VIEWER_URL Base URL of wiki-viewer instance (required)
|
|
10
10
|
* WIKI_VIEWER_TOKEN Bearer token from TOFU registration (required)
|
|
11
11
|
* WIKI_VIEWER_AGENT_ID X-Agent-Id header value (required)
|
|
12
|
+
* WIKI_VIEWER_WORKSPACE Workspace id for X-Workspace header (optional; targets one workspace)
|
|
12
13
|
*
|
|
13
14
|
* Mode-awareness:
|
|
14
15
|
* Before any raw write to a .md file, the shim checks the cached
|
|
@@ -76,12 +77,14 @@ export function createClient(overrides?: {
|
|
|
76
77
|
baseUrl?: string;
|
|
77
78
|
token?: string;
|
|
78
79
|
agentId?: string;
|
|
80
|
+
workspace?: string;
|
|
79
81
|
fetch?: typeof fetch;
|
|
80
82
|
}): WikiViewerClient {
|
|
81
83
|
return new WikiViewerClient({
|
|
82
84
|
baseUrl: overrides?.baseUrl ?? requireEnv("WIKI_VIEWER_URL"),
|
|
83
85
|
token: overrides?.token ?? requireEnv("WIKI_VIEWER_TOKEN"),
|
|
84
86
|
agentId: overrides?.agentId ?? requireEnv("WIKI_VIEWER_AGENT_ID"),
|
|
87
|
+
workspace: overrides?.workspace ?? process.env.WIKI_VIEWER_WORKSPACE,
|
|
85
88
|
fetch: overrides?.fetch,
|
|
86
89
|
});
|
|
87
90
|
}
|
|
@@ -524,6 +527,7 @@ async function runRegister() {
|
|
|
524
527
|
"scope-paths": { type: "string", default: "**/*" },
|
|
525
528
|
ops: { type: "string", default: "read,mutate" },
|
|
526
529
|
timeout: { type: "string", default: "300" },
|
|
530
|
+
workspace: { type: "string" },
|
|
527
531
|
},
|
|
528
532
|
allowPositionals: true,
|
|
529
533
|
});
|
|
@@ -595,6 +599,7 @@ async function runRegister() {
|
|
|
595
599
|
WIKI_VIEWER_URL: values.url,
|
|
596
600
|
WIKI_VIEWER_TOKEN: result.token,
|
|
597
601
|
WIKI_VIEWER_AGENT_ID: result.agentId,
|
|
602
|
+
...(values.workspace ? { WIKI_VIEWER_WORKSPACE: values.workspace } : {}),
|
|
598
603
|
},
|
|
599
604
|
},
|
|
600
605
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
3
|
-
import {
|
|
3
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
4
4
|
import {
|
|
5
5
|
aggregateActivity,
|
|
6
6
|
ACTIVITY_DEFAULT_LIMIT,
|
|
@@ -16,14 +16,15 @@ export async function GET(req: Request): Promise<NextResponse> {
|
|
|
16
16
|
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
if (!
|
|
21
|
-
return NextResponse.json({ error:
|
|
19
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
20
|
+
if (!wsx.ok) {
|
|
21
|
+
return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
22
22
|
}
|
|
23
|
+
const { ws, rootDir } = wsx;
|
|
23
24
|
|
|
24
|
-
const
|
|
25
|
-
if (!
|
|
26
|
-
return NextResponse.json({ error:
|
|
25
|
+
const scopeCheck = enforceScope(auth.agent, { op: "read", workspaceId: ws.id });
|
|
26
|
+
if (!scopeCheck.ok) {
|
|
27
|
+
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const url = new URL(req.url);
|
|
@@ -32,7 +33,7 @@ export async function GET(req: Request): Promise<NextResponse> {
|
|
|
32
33
|
|
|
33
34
|
// Enforce scope on explicit file query parameter
|
|
34
35
|
if (fileFilter) {
|
|
35
|
-
const fileScope = enforceScope(auth.agent, { filePath: fileFilter, op: "read" });
|
|
36
|
+
const fileScope = enforceScope(auth.agent, { filePath: fileFilter, op: "read", workspaceId: ws.id });
|
|
36
37
|
if (!fileScope.ok) {
|
|
37
38
|
return NextResponse.json({ error: fileScope.code, message: fileScope.message }, { status: 403 });
|
|
38
39
|
}
|
|
@@ -3,7 +3,8 @@ import { checkAuth, enforceScope, verifyBy } from "@/lib/proof/auth";
|
|
|
3
3
|
import { readSidecar, writeSidecar, emptySidecar } from "@/lib/proof/sidecar";
|
|
4
4
|
import { pollEvents } from "@/lib/proof/event-bus";
|
|
5
5
|
import { withFileMutex } from "@/lib/proof/mutex";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
7
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
7
8
|
|
|
8
9
|
export const runtime = "nodejs";
|
|
9
10
|
|
|
@@ -28,6 +29,12 @@ export async function GET(
|
|
|
28
29
|
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
33
|
+
if (!wsx.ok) {
|
|
34
|
+
return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
35
|
+
}
|
|
36
|
+
const { ws, rootDir } = wsx;
|
|
37
|
+
|
|
31
38
|
const { path: segments } = await params;
|
|
32
39
|
const rel = mdPath(segments);
|
|
33
40
|
|
|
@@ -38,12 +45,12 @@ export async function GET(
|
|
|
38
45
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
39
46
|
}
|
|
40
47
|
|
|
41
|
-
const absPath =
|
|
48
|
+
const absPath = safeWorkspacePath(rootDir, rel);
|
|
42
49
|
if (!absPath) {
|
|
43
50
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read" });
|
|
53
|
+
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read", workspaceId: ws.id });
|
|
47
54
|
if (!scopeCheck.ok) {
|
|
48
55
|
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
49
56
|
}
|
|
@@ -65,7 +72,6 @@ export async function GET(
|
|
|
65
72
|
limit = MAX_LIMIT;
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
const rootDir = getRootDir();
|
|
69
75
|
const sidecar = (await readSidecar(rootDir, rel)) ?? emptySidecar(rel);
|
|
70
76
|
const events = pollEvents(sidecar, after, limit);
|
|
71
77
|
const lastEventId = sidecar.nextEventId - 1;
|
|
@@ -83,6 +89,12 @@ export async function POST(
|
|
|
83
89
|
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
84
90
|
}
|
|
85
91
|
|
|
92
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
93
|
+
if (!wsx.ok) {
|
|
94
|
+
return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
95
|
+
}
|
|
96
|
+
const { ws, rootDir } = wsx;
|
|
97
|
+
|
|
86
98
|
const { path: segments } = await params;
|
|
87
99
|
const rel = mdPath(segments);
|
|
88
100
|
|
|
@@ -93,12 +105,12 @@ export async function POST(
|
|
|
93
105
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
94
106
|
}
|
|
95
107
|
|
|
96
|
-
const absPath =
|
|
108
|
+
const absPath = safeWorkspacePath(rootDir, rel);
|
|
97
109
|
if (!absPath) {
|
|
98
110
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
99
111
|
}
|
|
100
112
|
|
|
101
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "mutate" });
|
|
113
|
+
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "mutate", workspaceId: ws.id });
|
|
102
114
|
if (!scopeCheck.ok) {
|
|
103
115
|
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
104
116
|
}
|
|
@@ -122,11 +134,11 @@ export async function POST(
|
|
|
122
134
|
return NextResponse.json({ error: byCheck.code, message: byCheck.message }, { status: 403 });
|
|
123
135
|
}
|
|
124
136
|
|
|
125
|
-
const rootDir = getRootDir();
|
|
126
137
|
const upToId = body.upToId as number;
|
|
127
138
|
const by = body.by as string;
|
|
128
139
|
|
|
129
|
-
|
|
140
|
+
// Namespace mutex key with rootDir to prevent cross-workspace lock contention.
|
|
141
|
+
await withFileMutex(`${rootDir}\0${rel}`, async () => {
|
|
130
142
|
const sidecar = (await readSidecar(rootDir, rel)) ?? emptySidecar(rel);
|
|
131
143
|
sidecar.lastAck[by] = upToId;
|
|
132
144
|
await writeSidecar(rootDir, rel, sidecar);
|
|
@@ -18,7 +18,8 @@ import { NextResponse } from "next/server";
|
|
|
18
18
|
import { checkAuth, enforceScope, verifyBy } from "@/lib/proof/auth";
|
|
19
19
|
import { applyOps, readSnapshot } from "@/lib/proof/ops-applier";
|
|
20
20
|
import { idempotency } from "@/lib/proof/idempotency";
|
|
21
|
-
import {
|
|
21
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
22
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
22
23
|
import type { Op } from "@/lib/proof/types";
|
|
23
24
|
import { checkAndConsume } from "@/lib/proof/rate-limit";
|
|
24
25
|
import { computeCollabState } from "@/lib/proof/collab-state";
|
|
@@ -52,17 +53,20 @@ export async function GET(
|
|
|
52
53
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
const
|
|
56
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
57
|
+
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
58
|
+
const { ws, rootDir } = wsx;
|
|
59
|
+
|
|
60
|
+
const absPath = safeWorkspacePath(rootDir, rel);
|
|
56
61
|
if (!absPath) {
|
|
57
62
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read" });
|
|
65
|
+
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read", workspaceId: ws.id });
|
|
61
66
|
if (!scopeCheck.ok) {
|
|
62
67
|
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
const rootDir = getRootDir();
|
|
66
70
|
const snapshot = await readSnapshot(rootDir, rel);
|
|
67
71
|
if (!snapshot) {
|
|
68
72
|
return NextResponse.json({ error: "NOT_FOUND", message: "File not found" }, { status: 404 });
|
|
@@ -107,7 +111,11 @@ export async function POST(
|
|
|
107
111
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
108
112
|
}
|
|
109
113
|
|
|
110
|
-
const
|
|
114
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
115
|
+
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
116
|
+
const { ws, rootDir } = wsx;
|
|
117
|
+
|
|
118
|
+
const absPath = safeWorkspacePath(rootDir, rel);
|
|
111
119
|
if (!absPath) {
|
|
112
120
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
113
121
|
}
|
|
@@ -123,7 +131,7 @@ export async function POST(
|
|
|
123
131
|
const payloadHash = createHash("sha256").update(rawBody, "utf8").digest("hex");
|
|
124
132
|
|
|
125
133
|
// Check idempotency cache
|
|
126
|
-
const cached = idempotency.get(idempotencyKey);
|
|
134
|
+
const cached = idempotency.get(`${rootDir}\u0000${idempotencyKey}`);
|
|
127
135
|
if (cached) {
|
|
128
136
|
if (cached.payloadHash !== payloadHash) {
|
|
129
137
|
return NextResponse.json(
|
|
@@ -154,7 +162,7 @@ export async function POST(
|
|
|
154
162
|
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "ops (array) required" }, { status: 400 });
|
|
155
163
|
}
|
|
156
164
|
|
|
157
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "mutate" });
|
|
165
|
+
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "mutate", workspaceId: ws.id });
|
|
158
166
|
if (!scopeCheck.ok) {
|
|
159
167
|
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
160
168
|
}
|
|
@@ -181,7 +189,6 @@ export async function POST(
|
|
|
181
189
|
);
|
|
182
190
|
}
|
|
183
191
|
|
|
184
|
-
const rootDir = getRootDir();
|
|
185
192
|
const result = await applyOps({
|
|
186
193
|
rootDir,
|
|
187
194
|
mdPath: rel,
|
|
@@ -203,7 +210,7 @@ export async function POST(
|
|
|
203
210
|
responseBody = JSON.stringify(payload);
|
|
204
211
|
}
|
|
205
212
|
|
|
206
|
-
idempotency.set(idempotencyKey
|
|
213
|
+
idempotency.set(`${rootDir}\u0000${idempotencyKey}`, { payloadHash, status, body: responseBody });
|
|
207
214
|
|
|
208
215
|
return new NextResponse(responseBody, {
|
|
209
216
|
status,
|
|
@@ -11,7 +11,8 @@ import { readFile, stat, unlink, rm } from "node:fs/promises";
|
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import { NextResponse } from "next/server";
|
|
13
13
|
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
14
|
-
import {
|
|
14
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
15
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
15
16
|
import { withFileMutex } from "@/lib/proof/mutex";
|
|
16
17
|
import { readSidecar, emptySidecar, deleteSidecar } from "@/lib/proof/sidecar";
|
|
17
18
|
import { reconcileSidecar } from "@/lib/proof/ops-applier";
|
|
@@ -50,13 +51,17 @@ export async function GET(
|
|
|
50
51
|
const { path: segments } = await params;
|
|
51
52
|
const relPath = rel(segments);
|
|
52
53
|
|
|
53
|
-
const
|
|
54
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
55
|
+
if (!wsx.ok) return errJson(wsx.code, wsx.code, wsx.status);
|
|
56
|
+
const { ws, rootDir } = wsx;
|
|
57
|
+
|
|
58
|
+
const basic = safeWorkspacePath(rootDir, relPath);
|
|
54
59
|
if (!basic) return errJson("INVALID_PATH", "Path traversal rejected", 400);
|
|
55
60
|
|
|
56
|
-
const absPath = await safeAbsPath(relPath);
|
|
61
|
+
const absPath = await safeAbsPath(rootDir, relPath);
|
|
57
62
|
if (!absPath) return errJson("INVALID_PATH", "Path rejected (symlink escape or denied)", 400);
|
|
58
63
|
|
|
59
|
-
const scope = enforceScope(auth.agent, { filePath: relPath, op: "read" });
|
|
64
|
+
const scope = enforceScope(auth.agent, { filePath: relPath, op: "read", workspaceId: ws.id });
|
|
60
65
|
if (!scope.ok) return errJson(scope.code, scope.message, 403);
|
|
61
66
|
|
|
62
67
|
let data: Buffer;
|
|
@@ -84,7 +89,6 @@ export async function GET(
|
|
|
84
89
|
};
|
|
85
90
|
|
|
86
91
|
// X-Collab-* headers (§3.5 mode signal)
|
|
87
|
-
const rootDir = getRootDir();
|
|
88
92
|
const collab = await computeCollabState(rootDir, relPath);
|
|
89
93
|
if (collab.state !== "not-markdown") {
|
|
90
94
|
baseHeaders["X-Collab-State"] = collab.state;
|
|
@@ -148,23 +152,26 @@ async function applyMutation(
|
|
|
148
152
|
const auth = await checkAuth(req);
|
|
149
153
|
if (!auth.ok) return errJson("UNAUTHORIZED", auth.message ?? "Unauthorized", 401);
|
|
150
154
|
|
|
155
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
156
|
+
if (!wsx.ok) return errJson(wsx.code, wsx.code, wsx.status);
|
|
157
|
+
const { ws, rootDir } = wsx;
|
|
158
|
+
|
|
151
159
|
const relPath = rel(segments);
|
|
152
160
|
const url = new URL(req.url);
|
|
153
161
|
const mkdirs = url.searchParams.get("mkdirs") === "true";
|
|
154
162
|
const force = url.searchParams.get("force") === "true";
|
|
155
163
|
|
|
156
|
-
const basic =
|
|
164
|
+
const basic = safeWorkspacePath(rootDir, relPath);
|
|
157
165
|
if (!basic) return errJson("INVALID_PATH", "Path traversal rejected", 400);
|
|
158
166
|
|
|
159
|
-
const absPath = await safeAbsPath(relPath);
|
|
167
|
+
const absPath = await safeAbsPath(rootDir, relPath);
|
|
160
168
|
if (!absPath) return errJson("INVALID_PATH", "Path rejected (symlink escape or denied)", 400);
|
|
161
169
|
|
|
162
|
-
const scope = enforceScope(auth.agent, { filePath: relPath, op: "mutate" });
|
|
170
|
+
const scope = enforceScope(auth.agent, { filePath: relPath, op: "mutate", workspaceId: ws.id });
|
|
163
171
|
if (!scope.ok) return errJson(scope.code, scope.message, 403);
|
|
164
172
|
|
|
165
173
|
const ifMatch = req.headers.get("if-match");
|
|
166
174
|
const ifCollabMatch = req.headers.get("if-collab-match");
|
|
167
|
-
const rootDir = getRootDir();
|
|
168
175
|
|
|
169
176
|
// The whole read-existing → precondition → compute → write → reconcile → audit
|
|
170
177
|
// sequence runs inside the mutex for .md (so R6 and reconcile are atomic with
|
|
@@ -256,6 +263,7 @@ async function applyMutation(
|
|
|
256
263
|
oldSha: existingSha,
|
|
257
264
|
newSha,
|
|
258
265
|
forced: force,
|
|
266
|
+
workspaceId: ws.id,
|
|
259
267
|
});
|
|
260
268
|
|
|
261
269
|
const st = await stat(absPath);
|
|
@@ -268,7 +276,7 @@ async function applyMutation(
|
|
|
268
276
|
});
|
|
269
277
|
};
|
|
270
278
|
|
|
271
|
-
return isMarkdown(relPath) ? withFileMutex(relPath
|
|
279
|
+
return isMarkdown(relPath) ? withFileMutex(`${rootDir}\u0000${relPath}`, doMutation) : doMutation();
|
|
272
280
|
}
|
|
273
281
|
|
|
274
282
|
// ── PUT ──────────────────────────────────────────────────────────────────────
|
|
@@ -377,14 +385,18 @@ export async function DELETE(
|
|
|
377
385
|
const url = new URL(req.url);
|
|
378
386
|
const recursive = url.searchParams.get("recursive") === "true";
|
|
379
387
|
|
|
380
|
-
const
|
|
388
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
389
|
+
if (!wsx.ok) return errJson(wsx.code, wsx.code, wsx.status);
|
|
390
|
+
const { ws, rootDir } = wsx;
|
|
391
|
+
|
|
392
|
+
const basic = safeWorkspacePath(rootDir, relPath);
|
|
381
393
|
if (!basic) return errJson("INVALID_PATH", "Path traversal rejected", 400);
|
|
382
394
|
|
|
383
|
-
const absPath = await safeAbsPath(relPath);
|
|
395
|
+
const absPath = await safeAbsPath(rootDir, relPath);
|
|
384
396
|
if (!absPath) return errJson("INVALID_PATH", "Path rejected (symlink escape or denied)", 400);
|
|
385
397
|
|
|
386
398
|
// Requires "delete" scope op
|
|
387
|
-
const scope = enforceScope(auth.agent, { filePath: relPath, op: "delete" });
|
|
399
|
+
const scope = enforceScope(auth.agent, { filePath: relPath, op: "delete", workspaceId: ws.id });
|
|
388
400
|
if (!scope.ok) return errJson(scope.code, scope.message, 403);
|
|
389
401
|
|
|
390
402
|
const ifMatch = req.headers.get("if-match");
|
|
@@ -405,7 +417,7 @@ export async function DELETE(
|
|
|
405
417
|
}
|
|
406
418
|
// Directory delete — no single sha, skip If-Match; require recursive flag as confirmation
|
|
407
419
|
await rm(absPath, { recursive: true, force: true });
|
|
408
|
-
writeAuditRow({ agentId: auth.agent.id, op: "delete", path: relPath, forced: false });
|
|
420
|
+
writeAuditRow({ agentId: auth.agent.id, op: "delete", path: relPath, forced: false, workspaceId: ws.id });
|
|
409
421
|
return NextResponse.json({ deleted: relPath });
|
|
410
422
|
}
|
|
411
423
|
|
|
@@ -420,10 +432,8 @@ export async function DELETE(
|
|
|
420
432
|
return errJson("PRECONDITION_FAILED", "If-Match sha256 mismatch", 412);
|
|
421
433
|
}
|
|
422
434
|
|
|
423
|
-
const rootDir = getRootDir();
|
|
424
|
-
|
|
425
435
|
if (isMarkdown(relPath)) {
|
|
426
|
-
await withFileMutex(relPath
|
|
436
|
+
await withFileMutex(`${rootDir}\u0000${relPath}`, async () => {
|
|
427
437
|
await unlink(absPath);
|
|
428
438
|
await deleteSidecar(rootDir, relPath);
|
|
429
439
|
});
|
|
@@ -431,6 +441,6 @@ export async function DELETE(
|
|
|
431
441
|
await unlink(absPath);
|
|
432
442
|
}
|
|
433
443
|
|
|
434
|
-
writeAuditRow({ agentId: auth.agent.id, op: "delete", path: relPath, oldSha: existingSha, forced: false });
|
|
444
|
+
writeAuditRow({ agentId: auth.agent.id, op: "delete", path: relPath, oldSha: existingSha, forced: false, workspaceId: ws.id });
|
|
435
445
|
return NextResponse.json({ deleted: relPath });
|
|
436
446
|
}
|
|
@@ -13,7 +13,8 @@ import { readdir, stat } from "node:fs/promises";
|
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
import { NextResponse } from "next/server";
|
|
15
15
|
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
16
|
-
import {
|
|
16
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
17
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
17
18
|
import { safeAbsPath } from "@/lib/proof/raw-fs";
|
|
18
19
|
import type { Agent } from "@/lib/proof/registry";
|
|
19
20
|
|
|
@@ -44,6 +45,7 @@ async function walkDir(
|
|
|
44
45
|
maxDepth: number,
|
|
45
46
|
limit: number,
|
|
46
47
|
results: LsEntry[],
|
|
48
|
+
workspaceId?: string,
|
|
47
49
|
): Promise<void> {
|
|
48
50
|
if (depth > maxDepth || results.length >= limit) return;
|
|
49
51
|
|
|
@@ -63,7 +65,7 @@ async function walkDir(
|
|
|
63
65
|
const childRel = relDir ? `${relDir}/${item.name}` : item.name;
|
|
64
66
|
|
|
65
67
|
// Scope check per entry
|
|
66
|
-
const sc = enforceScope(agent, { filePath: childRel, op: "read" });
|
|
68
|
+
const sc = enforceScope(agent, { filePath: childRel, op: "read", workspaceId });
|
|
67
69
|
if (!sc.ok) continue;
|
|
68
70
|
|
|
69
71
|
let type: LsEntry["type"];
|
|
@@ -88,7 +90,7 @@ async function walkDir(
|
|
|
88
90
|
results.push({ name: item.name, path: childRel, type, size, mtime });
|
|
89
91
|
|
|
90
92
|
if (recursive && type === "dir") {
|
|
91
|
-
await walkDir(rootDir, childRel, agent, recursive, depth + 1, maxDepth, limit, results);
|
|
93
|
+
await walkDir(rootDir, childRel, agent, recursive, depth + 1, maxDepth, limit, results, workspaceId);
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
}
|
|
@@ -103,10 +105,14 @@ export async function GET(
|
|
|
103
105
|
const { path: segments } = await params;
|
|
104
106
|
const relPath = segments ? segments.join("/") : "";
|
|
105
107
|
|
|
108
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
109
|
+
if (!wsx.ok) return errJson(wsx.code, wsx.code, wsx.status);
|
|
110
|
+
const { ws, rootDir } = wsx;
|
|
111
|
+
|
|
106
112
|
if (relPath) {
|
|
107
|
-
const basic =
|
|
113
|
+
const basic = safeWorkspacePath(rootDir, relPath);
|
|
108
114
|
if (!basic) return errJson("INVALID_PATH", "Path traversal rejected", 400);
|
|
109
|
-
const safe = await safeAbsPath(relPath);
|
|
115
|
+
const safe = await safeAbsPath(rootDir, relPath);
|
|
110
116
|
if (!safe) return errJson("INVALID_PATH", "Path rejected (symlink escape or denied)", 400);
|
|
111
117
|
}
|
|
112
118
|
|
|
@@ -122,7 +128,6 @@ export async function GET(
|
|
|
122
128
|
);
|
|
123
129
|
|
|
124
130
|
// Verify the dir actually exists
|
|
125
|
-
const rootDir = getRootDir();
|
|
126
131
|
const absDir = relPath ? path.join(rootDir, relPath) : rootDir;
|
|
127
132
|
try {
|
|
128
133
|
const st = await stat(absDir);
|
|
@@ -137,7 +142,7 @@ export async function GET(
|
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
const entries: LsEntry[] = [];
|
|
140
|
-
await walkDir(rootDir, relPath, auth.agent, recursive, 0, depth, limit, entries);
|
|
145
|
+
await walkDir(rootDir, relPath, auth.agent, recursive, 0, depth, limit, entries, ws.id);
|
|
141
146
|
|
|
142
147
|
return NextResponse.json({
|
|
143
148
|
path: relPath,
|
|
@@ -14,7 +14,8 @@ import { rename, stat } from "node:fs/promises";
|
|
|
14
14
|
import path from "node:path";
|
|
15
15
|
import { NextResponse } from "next/server";
|
|
16
16
|
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
17
|
-
import {
|
|
17
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
18
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
18
19
|
import { withFileMutex } from "@/lib/proof/mutex";
|
|
19
20
|
import { moveSidecar } from "@/lib/proof/sidecar";
|
|
20
21
|
import { writeAuditRow } from "@/lib/proof/audit";
|
|
@@ -47,13 +48,17 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
47
48
|
const toRel = body.to;
|
|
48
49
|
const ifMatch = typeof body.ifMatch === "string" ? body.ifMatch : undefined;
|
|
49
50
|
|
|
51
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
52
|
+
if (!wsx.ok) return errJson(wsx.code, wsx.code, wsx.status);
|
|
53
|
+
const { ws, rootDir } = wsx;
|
|
54
|
+
|
|
50
55
|
// Basic traversal
|
|
51
|
-
if (!
|
|
52
|
-
if (!
|
|
56
|
+
if (!safeWorkspacePath(rootDir, fromRel)) return errJson("INVALID_PATH", "from: path traversal rejected", 400);
|
|
57
|
+
if (!safeWorkspacePath(rootDir, toRel)) return errJson("INVALID_PATH", "to: path traversal rejected", 400);
|
|
53
58
|
|
|
54
|
-
const fromAbs = await safeAbsPath(fromRel);
|
|
59
|
+
const fromAbs = await safeAbsPath(rootDir, fromRel);
|
|
55
60
|
if (!fromAbs) return errJson("INVALID_PATH", "from: path rejected (symlink escape or denied)", 400);
|
|
56
|
-
const toAbs = await safeAbsPath(toRel);
|
|
61
|
+
const toAbs = await safeAbsPath(rootDir, toRel);
|
|
57
62
|
if (!toAbs) return errJson("INVALID_PATH", "to: path rejected (symlink escape or denied)", 400);
|
|
58
63
|
|
|
59
64
|
// Self-move guard
|
|
@@ -63,11 +68,11 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
// Scope: source requires read+mutate; dest requires mutate
|
|
66
|
-
const sc1 = enforceScope(auth.agent, { filePath: fromRel, op: "read" });
|
|
71
|
+
const sc1 = enforceScope(auth.agent, { filePath: fromRel, op: "read", workspaceId: ws.id });
|
|
67
72
|
if (!sc1.ok) return errJson(sc1.code, sc1.message, 403);
|
|
68
|
-
const sc2 = enforceScope(auth.agent, { filePath: fromRel, op: "mutate" });
|
|
73
|
+
const sc2 = enforceScope(auth.agent, { filePath: fromRel, op: "mutate", workspaceId: ws.id });
|
|
69
74
|
if (!sc2.ok) return errJson(sc2.code, sc2.message, 403);
|
|
70
|
-
const sc3 = enforceScope(auth.agent, { filePath: toRel, op: "mutate" });
|
|
75
|
+
const sc3 = enforceScope(auth.agent, { filePath: toRel, op: "mutate", workspaceId: ws.id });
|
|
71
76
|
if (!sc3.ok) return errJson(sc3.code, sc3.message, 403);
|
|
72
77
|
|
|
73
78
|
// Verify source exists
|
|
@@ -95,7 +100,6 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
95
100
|
}
|
|
96
101
|
}
|
|
97
102
|
|
|
98
|
-
const rootDir = getRootDir();
|
|
99
103
|
const isMd = isMarkdown(fromRel);
|
|
100
104
|
|
|
101
105
|
// Lock source + dest in sorted order to avoid deadlock
|
|
@@ -112,13 +116,14 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
112
116
|
path: fromRel,
|
|
113
117
|
newSha: toRel, // store destination in newSha field for audit trail
|
|
114
118
|
forced: false,
|
|
119
|
+
workspaceId: ws.id,
|
|
115
120
|
});
|
|
116
121
|
};
|
|
117
122
|
|
|
118
123
|
if (first === fromRel) {
|
|
119
|
-
await withFileMutex(first
|
|
124
|
+
await withFileMutex(`${rootDir}\u0000${first}`, () => withFileMutex(`${rootDir}\u0000${second}`, doMove));
|
|
120
125
|
} else {
|
|
121
|
-
await withFileMutex(first
|
|
126
|
+
await withFileMutex(`${rootDir}\u0000${first}`, () => withFileMutex(`${rootDir}\u0000${second}`, doMove));
|
|
122
127
|
}
|
|
123
128
|
|
|
124
129
|
return NextResponse.json({ from: fromRel, to: toRel });
|
|
@@ -19,10 +19,12 @@
|
|
|
19
19
|
export const runtime = "nodejs";
|
|
20
20
|
|
|
21
21
|
import { readdir, readFile, stat } from "node:fs/promises";
|
|
22
|
+
import { ensureIndexer, ftsSearch } from "@/lib/search/indexer";
|
|
22
23
|
import path from "node:path";
|
|
23
24
|
import { NextResponse } from "next/server";
|
|
24
25
|
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
25
|
-
import {
|
|
26
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
27
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
26
28
|
import { safeAbsPath, looksLikeBinary } from "@/lib/proof/raw-fs";
|
|
27
29
|
import { matchGlob } from "@/lib/proof/glob";
|
|
28
30
|
import type { Agent } from "@/lib/proof/registry";
|
|
@@ -36,6 +38,8 @@ export interface SearchMatch {
|
|
|
36
38
|
line?: number;
|
|
37
39
|
col?: number;
|
|
38
40
|
text?: string;
|
|
41
|
+
score?: number;
|
|
42
|
+
snippet?: string;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
function errJson(code: string, message: string, status: number): NextResponse {
|
|
@@ -74,6 +78,7 @@ async function grepSearch(
|
|
|
74
78
|
limit: number,
|
|
75
79
|
agent: Agent,
|
|
76
80
|
deadline: number,
|
|
81
|
+
workspaceId?: string,
|
|
77
82
|
): Promise<{ matches: SearchMatch[]; truncated: boolean }> {
|
|
78
83
|
let regex: RegExp;
|
|
79
84
|
try {
|
|
@@ -94,7 +99,7 @@ async function grepSearch(
|
|
|
94
99
|
if (matches.length >= limit) return { matches, truncated: true };
|
|
95
100
|
if (Date.now() > deadline) return { matches, truncated: true };
|
|
96
101
|
|
|
97
|
-
const sc = enforceScope(agent, { filePath: fileRel, op: "read" });
|
|
102
|
+
const sc = enforceScope(agent, { filePath: fileRel, op: "read", workspaceId });
|
|
98
103
|
if (!sc.ok) continue;
|
|
99
104
|
|
|
100
105
|
let buf: Buffer;
|
|
@@ -140,6 +145,7 @@ async function globSearch(
|
|
|
140
145
|
limit: number,
|
|
141
146
|
agent: Agent,
|
|
142
147
|
deadline: number,
|
|
148
|
+
workspaceId?: string,
|
|
143
149
|
): Promise<{ matches: SearchMatch[]; truncated: boolean }> {
|
|
144
150
|
const matches: SearchMatch[] = [];
|
|
145
151
|
|
|
@@ -151,7 +157,7 @@ async function globSearch(
|
|
|
151
157
|
const baseName = path.basename(fileRel);
|
|
152
158
|
if (!matchGlob(pattern, fileRel) && !matchGlob(pattern, baseName)) continue;
|
|
153
159
|
|
|
154
|
-
const sc = enforceScope(agent, { filePath: fileRel, op: "read" });
|
|
160
|
+
const sc = enforceScope(agent, { filePath: fileRel, op: "read", workspaceId });
|
|
155
161
|
if (!sc.ok) continue;
|
|
156
162
|
|
|
157
163
|
matches.push({ path: fileRel });
|
|
@@ -173,14 +179,17 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
173
179
|
return errJson("INVALID_PAYLOAD", "Invalid JSON body", 400);
|
|
174
180
|
}
|
|
175
181
|
|
|
176
|
-
if (body.kind !== "grep" && body.kind !== "glob") {
|
|
177
|
-
return errJson("INVALID_PAYLOAD", 'kind must be "grep" or "
|
|
182
|
+
if (body.kind !== "grep" && body.kind !== "glob" && body.kind !== "fts") {
|
|
183
|
+
return errJson("INVALID_PAYLOAD", 'kind must be "grep", "glob", or "fts"', 400);
|
|
178
184
|
}
|
|
179
|
-
if (typeof body.query !== "string"
|
|
185
|
+
if (typeof body.query !== "string") {
|
|
186
|
+
return errJson("INVALID_PAYLOAD", "query (string) required", 400);
|
|
187
|
+
}
|
|
188
|
+
if (body.kind !== "fts" && !body.query) {
|
|
180
189
|
return errJson("INVALID_PAYLOAD", "query (string) required", 400);
|
|
181
190
|
}
|
|
182
191
|
|
|
183
|
-
const kind = body.kind as "grep" | "glob";
|
|
192
|
+
const kind = body.kind as "grep" | "glob" | "fts";
|
|
184
193
|
const query = body.query as string;
|
|
185
194
|
const startRelRaw = typeof body.path === "string" ? body.path : "";
|
|
186
195
|
const limit = Math.min(
|
|
@@ -188,17 +197,19 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
188
197
|
HARD_MAX_MATCHES,
|
|
189
198
|
);
|
|
190
199
|
|
|
200
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
201
|
+
if (!wsx.ok) return errJson(wsx.code, wsx.code, wsx.status);
|
|
202
|
+
const { ws, rootDir } = wsx;
|
|
203
|
+
|
|
191
204
|
// Validate start path
|
|
192
205
|
if (startRelRaw) {
|
|
193
|
-
if (!
|
|
206
|
+
if (!safeWorkspacePath(rootDir, startRelRaw)) {
|
|
194
207
|
return errJson("INVALID_PATH", "path: traversal rejected", 400);
|
|
195
208
|
}
|
|
196
|
-
const safe = await safeAbsPath(startRelRaw);
|
|
209
|
+
const safe = await safeAbsPath(rootDir, startRelRaw);
|
|
197
210
|
if (!safe) return errJson("INVALID_PATH", "path: rejected (symlink escape or denied)", 400);
|
|
198
211
|
}
|
|
199
212
|
|
|
200
|
-
const rootDir = getRootDir();
|
|
201
|
-
|
|
202
213
|
// Verify start path is a directory
|
|
203
214
|
if (startRelRaw) {
|
|
204
215
|
try {
|
|
@@ -214,14 +225,39 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
214
225
|
}
|
|
215
226
|
}
|
|
216
227
|
|
|
228
|
+
// FTS branch -- handled before the grep/glob path validation below.
|
|
229
|
+
if (kind === "fts") {
|
|
230
|
+
const sc = enforceScope(auth.agent, { op: "read", workspaceId: ws.id });
|
|
231
|
+
if (!sc.ok) return errJson("FORBIDDEN", sc.message ?? "Forbidden", 403);
|
|
232
|
+
|
|
233
|
+
ensureIndexer(ws.id, rootDir).catch((e) =>
|
|
234
|
+
console.error("[search] ensureIndexer failed", e),
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
// Over-fetch so the post-filter (path scope + start-path restriction) can
|
|
238
|
+
// still return up to `limit` results when some top-ranked hits are denied.
|
|
239
|
+
const startPrefix = startRelRaw ? `${startRelRaw.replace(/\/+$/, "")}/` : "";
|
|
240
|
+
const fts = ftsSearch(ws.id, query, Math.min(limit * 4, HARD_MAX_MATCHES));
|
|
241
|
+
const filtered = fts.matches.filter((m) => {
|
|
242
|
+
if (startPrefix && !m.path.startsWith(startPrefix)) return false;
|
|
243
|
+
return enforceScope(auth.agent, { filePath: m.path, op: "read", workspaceId: ws.id }).ok;
|
|
244
|
+
});
|
|
245
|
+
const matches = filtered
|
|
246
|
+
.slice(0, limit)
|
|
247
|
+
.map((m) => ({ path: m.path, score: m.score, snippet: m.snippet }));
|
|
248
|
+
// truncated if the DB itself capped, or the scoped set still exceeds limit.
|
|
249
|
+
const truncated = fts.truncated || filtered.length > limit;
|
|
250
|
+
return NextResponse.json({ kind, query, matches, truncated });
|
|
251
|
+
}
|
|
252
|
+
|
|
217
253
|
const deadline = Date.now() + SEARCH_TIMEOUT_MS;
|
|
218
254
|
let result: { matches: SearchMatch[]; truncated: boolean };
|
|
219
255
|
|
|
220
256
|
try {
|
|
221
257
|
if (kind === "grep") {
|
|
222
|
-
result = await grepSearch(rootDir, startRelRaw, query, limit, auth.agent, deadline);
|
|
258
|
+
result = await grepSearch(rootDir, startRelRaw, query, limit, auth.agent, deadline, ws.id);
|
|
223
259
|
} else {
|
|
224
|
-
result = await globSearch(rootDir, startRelRaw, query, limit, auth.agent, deadline);
|
|
260
|
+
result = await globSearch(rootDir, startRelRaw, query, limit, auth.agent, deadline, ws.id);
|
|
225
261
|
}
|
|
226
262
|
} catch (e) {
|
|
227
263
|
return errJson("SEARCH_ERROR", (e as Error).message, 400);
|