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
|
@@ -8,7 +8,8 @@ import { revertProofSpan } from "@/lib/proof/proof-span";
|
|
|
8
8
|
import { readSidecar, writeSidecar, emptySidecar } from "@/lib/proof/sidecar";
|
|
9
9
|
import { withFileMutex } from "@/lib/proof/mutex";
|
|
10
10
|
import { emitEvents } from "@/lib/proof/event-bus";
|
|
11
|
-
import {
|
|
11
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
12
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
12
13
|
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
13
14
|
|
|
14
15
|
export const runtime = "nodejs";
|
|
@@ -63,22 +64,25 @@ export async function POST(req: Request): Promise<NextResponse> {
|
|
|
63
64
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
const
|
|
67
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
68
|
+
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
69
|
+
const { ws, rootDir } = wsx;
|
|
70
|
+
|
|
71
|
+
const absPath = safeWorkspacePath(rootDir, rel);
|
|
67
72
|
if (!absPath) {
|
|
68
73
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
const scopeCheck = enforceScope(authResult.agent, { filePath: rel, op: "mutate" });
|
|
76
|
+
const scopeCheck = enforceScope(authResult.agent, { filePath: rel, op: "mutate", workspaceId: ws.id });
|
|
72
77
|
if (!scopeCheck.ok) {
|
|
73
78
|
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
const rootDir = getRootDir();
|
|
77
81
|
const actorId = authResult.agent.id;
|
|
78
82
|
|
|
79
83
|
let notFound = false;
|
|
80
84
|
try {
|
|
81
|
-
await withFileMutex(rel
|
|
85
|
+
await withFileMutex(`${rootDir}\u0000${rel}`, async () => {
|
|
82
86
|
let content: string;
|
|
83
87
|
try {
|
|
84
88
|
content = await readFile(absPath, "utf-8");
|
|
@@ -31,7 +31,15 @@ function validateScope(s: Record<string, unknown>): AgentScope | { error: string
|
|
|
31
31
|
return { error: `scope.ops values must be "read", "mutate", or "delete"` };
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
// Optional workspaceId: if present must be a non-empty string ≤ 64 chars.
|
|
35
|
+
let workspaceId: string | undefined;
|
|
36
|
+
if (s.workspaceId !== undefined) {
|
|
37
|
+
if (typeof s.workspaceId !== "string" || s.workspaceId.length < 1 || s.workspaceId.length > 64) {
|
|
38
|
+
return { error: "scope.workspaceId must be a string of 1\u201364 characters" };
|
|
39
|
+
}
|
|
40
|
+
workspaceId = s.workspaceId;
|
|
41
|
+
}
|
|
42
|
+
return { paths: s.paths as string[], ops: s.ops as Array<"read" | "mutate" | "delete">, ...(workspaceId !== undefined ? { workspaceId } : {}) };
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
/** Exported for reuse in approve route. */
|
|
@@ -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 { readRegistry } from "@/lib/proof/registry";
|
|
5
5
|
import { listPendingRegistrations } from "@/lib/proof/pending";
|
|
6
6
|
|
|
@@ -12,7 +12,11 @@ export async function GET(req: Request): Promise<NextResponse> {
|
|
|
12
12
|
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
16
|
+
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
17
|
+
const { ws, rootDir } = wsx;
|
|
18
|
+
|
|
19
|
+
const scopeCheck = enforceScope(auth.agent, { op: "read", workspaceId: ws.id });
|
|
16
20
|
if (!scopeCheck.ok) {
|
|
17
21
|
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
18
22
|
}
|
|
@@ -23,7 +27,7 @@ export async function GET(req: Request): Promise<NextResponse> {
|
|
|
23
27
|
|
|
24
28
|
return NextResponse.json({
|
|
25
29
|
rateLimit: Number(process.env.AGENT_RATE_LIMIT) || 60,
|
|
26
|
-
root:
|
|
30
|
+
root: rootDir,
|
|
27
31
|
registeredAgents,
|
|
28
32
|
pendingRegistrations,
|
|
29
33
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
3
3
|
import { readSidecar, emptySidecar } from "@/lib/proof/sidecar";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
5
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
5
6
|
|
|
6
7
|
export const runtime = "nodejs";
|
|
7
8
|
|
|
@@ -32,17 +33,20 @@ export async function GET(
|
|
|
32
33
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
const
|
|
36
|
+
const wsx = await resolveWorkspaceForAgent(req);
|
|
37
|
+
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
38
|
+
const { ws, rootDir } = wsx;
|
|
39
|
+
|
|
40
|
+
const absPath = safeWorkspacePath(rootDir, rel);
|
|
36
41
|
if (!absPath) {
|
|
37
42
|
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read" });
|
|
45
|
+
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read", workspaceId: ws.id });
|
|
41
46
|
if (!scopeCheck.ok) {
|
|
42
47
|
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
const rootDir = getRootDir();
|
|
46
50
|
const sidecar = (await readSidecar(rootDir, rel)) ?? emptySidecar(rel);
|
|
47
51
|
|
|
48
52
|
return NextResponse.json(sidecar);
|
|
@@ -74,9 +74,25 @@ export async function GET(req: NextRequest): Promise<NextResponse> {
|
|
|
74
74
|
{ method: "GET", path: "/api/agent/fs/ls/<path>", auth: "bearer+agent-id", purpose: "Directory listing. ?recursive&limit&depth. Scope-filtered. Excludes .proof/." },
|
|
75
75
|
{ method: "POST", path: "/api/agent/fs/move", auth: "bearer+agent-id", purpose: "Move/rename. Body: {from, to, ifMatch?}. Moves .md sidecar too." },
|
|
76
76
|
{ method: "POST", path: "/api/agent/fs/search", auth: "bearer+agent-id", purpose: "Server-side grep or glob. Body: {kind:'grep'|'glob', query, path?, glob?, limit?}." },
|
|
77
|
+
// Settings (resolved workspace root, rate limit)
|
|
78
|
+
{ method: "GET", path: "/api/agent/settings", auth: "bearer+agent-id", purpose: "Returns rateLimit + resolved 'root' (the active workspace's directory for the X-Workspace you send)." },
|
|
77
79
|
// Human presence (for editor lease — drives active collab-state)
|
|
78
80
|
{ method: "POST", path: "/api/wiki/presence", auth: "session", purpose: "Human editor lease heartbeat. Body: {path, action:'open'|'heartbeat'|'close'}." },
|
|
79
81
|
],
|
|
82
|
+
workspaces: {
|
|
83
|
+
description:
|
|
84
|
+
"This instance can serve multiple root directories ('workspaces'). Every agent path is relative to ONE workspace root.",
|
|
85
|
+
header: "X-Workspace: <workspaceId>",
|
|
86
|
+
queryParam: "ws=<workspaceId>",
|
|
87
|
+
default:
|
|
88
|
+
"If omitted, the server resolves to the most-recently-opened workspace. Correct for single-workspace instances; be explicit when several exist.",
|
|
89
|
+
discoverId:
|
|
90
|
+
"Ask the human for the workspace id, read it from the ?ws= param of a pasted wiki-viewer URL, or call GET /api/agent/settings (with X-Workspace) to confirm the resolved 'root'.",
|
|
91
|
+
scoped:
|
|
92
|
+
"A token may be pinned to one workspace (scope.workspaceId at approval). Requests resolving to a different workspace return 403 FORBIDDEN. A token with no pin is wildcard (any workspace).",
|
|
93
|
+
isolation:
|
|
94
|
+
"Paths in one workspace never touch another, even with identical relative paths.",
|
|
95
|
+
},
|
|
80
96
|
capabilities: {
|
|
81
97
|
maxFileBytes: MAX_FILE_BYTES,
|
|
82
98
|
supportsRange: true,
|
|
@@ -85,6 +101,8 @@ export async function GET(req: NextRequest): Promise<NextResponse> {
|
|
|
85
101
|
search: ["grep", "glob"],
|
|
86
102
|
globDialect: "**,*,?",
|
|
87
103
|
scopeOps: ["read", "mutate", "delete"],
|
|
104
|
+
scopeWorkspaceId: true,
|
|
105
|
+
workspaceHeader: "X-Workspace",
|
|
88
106
|
collabStates: ["active", "tracked", "untracked", "not-markdown"],
|
|
89
107
|
collabPrecondition: "If-Collab-Match",
|
|
90
108
|
},
|
|
@@ -103,8 +121,8 @@ export async function GET(req: NextRequest): Promise<NextResponse> {
|
|
|
103
121
|
mcpAdapter: {
|
|
104
122
|
package: "wiki-viewer-mcp",
|
|
105
123
|
invoke: "npx wiki-viewer-mcp",
|
|
106
|
-
env: ["WIKI_VIEWER_URL", "WIKI_VIEWER_TOKEN", "WIKI_VIEWER_AGENT_ID"],
|
|
107
|
-
description: "Thin MCP adapter mapping standard MCP filesystem tools onto these endpoints. Reads X-Collab-State and blocks or warns on raw writes to active .md files.",
|
|
124
|
+
env: ["WIKI_VIEWER_URL", "WIKI_VIEWER_TOKEN", "WIKI_VIEWER_AGENT_ID", "WIKI_VIEWER_WORKSPACE"],
|
|
125
|
+
description: "Thin MCP adapter mapping standard MCP filesystem tools onto these endpoints. Set WIKI_VIEWER_WORKSPACE to target a specific workspace (sends X-Workspace on every call). Reads X-Collab-State and blocks or warns on raw writes to active .md files.",
|
|
108
126
|
},
|
|
109
127
|
ops: [
|
|
110
128
|
"block.replace",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { NextResponse } from "next/server";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
5
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
5
6
|
|
|
6
7
|
const MIME_MAP: Record<string, string> = {
|
|
7
8
|
jpg: "image/jpeg",
|
|
@@ -38,15 +39,19 @@ const MIME_MAP: Record<string, string> = {
|
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
export async function GET(
|
|
41
|
-
|
|
42
|
+
request: Request,
|
|
42
43
|
{ params }: { params: Promise<{ path: string[] }> },
|
|
43
44
|
) {
|
|
45
|
+
const wsx = await resolveWorkspaceForAgent(request);
|
|
46
|
+
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
47
|
+
const { rootDir } = wsx;
|
|
48
|
+
|
|
44
49
|
const segments = (await params).path;
|
|
45
50
|
const rel = segments.join("/");
|
|
46
51
|
|
|
47
52
|
// Path traversal guard
|
|
48
|
-
const resolved =
|
|
49
|
-
if (
|
|
53
|
+
const resolved = safeWorkspacePath(rootDir, rel);
|
|
54
|
+
if (!resolved) {
|
|
50
55
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
51
56
|
}
|
|
52
57
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin management API.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/system/admins — any signed-in user (returns isAdmin flag, admin list,
|
|
5
|
+
* and user roster if caller is admin).
|
|
6
|
+
* POST { userId } — admin-only: promote user to admin.
|
|
7
|
+
* DELETE { userId } — admin-only: demote user; refuses to remove last admin.
|
|
8
|
+
*
|
|
9
|
+
* Bootstrap: first authenticated request triggers ensureBootstrapAdmin so the
|
|
10
|
+
* first user to sign in becomes admin when no WIKI_ADMIN_EMAILS is set.
|
|
11
|
+
*/
|
|
12
|
+
import { NextResponse } from "next/server";
|
|
13
|
+
import Database from "better-sqlite3";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import os from "node:os";
|
|
16
|
+
import { mkdirSync } from "node:fs";
|
|
17
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
18
|
+
import { requireUser } from "@/lib/auth/server";
|
|
19
|
+
import {
|
|
20
|
+
isAdmin,
|
|
21
|
+
listAdmins,
|
|
22
|
+
addAdmin,
|
|
23
|
+
removeAdmin,
|
|
24
|
+
requireAdmin,
|
|
25
|
+
ensureBootstrapAdmin,
|
|
26
|
+
} from "@/lib/auth/admin";
|
|
27
|
+
|
|
28
|
+
export const runtime = "nodejs";
|
|
29
|
+
|
|
30
|
+
interface UserRow {
|
|
31
|
+
id: string;
|
|
32
|
+
email: string;
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function queryAllUsers(): UserRow[] {
|
|
37
|
+
try {
|
|
38
|
+
const dir = path.join(process.env.HOME ?? os.homedir(), ".wiki-viewer");
|
|
39
|
+
mkdirSync(dir, { recursive: true });
|
|
40
|
+
const db = new Database(path.join(dir, "auth.db"));
|
|
41
|
+
db.pragma("journal_mode = WAL");
|
|
42
|
+
return db.prepare("SELECT id, email, name FROM user").all() as UserRow[];
|
|
43
|
+
} catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function GET(request: Request) {
|
|
49
|
+
const auth = await requireUser(request);
|
|
50
|
+
if (!auth.ok) return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
51
|
+
|
|
52
|
+
// Bootstrap: first authenticated user becomes admin if no admin set yet.
|
|
53
|
+
await ensureBootstrapAdmin(auth.user.id);
|
|
54
|
+
|
|
55
|
+
const admin = await isAdmin(auth.user.id, auth.user.email);
|
|
56
|
+
const admins = await listAdmins();
|
|
57
|
+
const users = admin ? queryAllUsers() : [];
|
|
58
|
+
|
|
59
|
+
return NextResponse.json({ admins, isAdmin: admin, users });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function POST(request: Request) {
|
|
63
|
+
const csrf = checkOrigin(request);
|
|
64
|
+
if (csrf) return csrf;
|
|
65
|
+
|
|
66
|
+
const authResult = await requireAdmin(request);
|
|
67
|
+
if (!authResult.ok)
|
|
68
|
+
return NextResponse.json({ error: authResult.code }, { status: authResult.status });
|
|
69
|
+
|
|
70
|
+
const body: { userId?: string } = await request.json();
|
|
71
|
+
if (!body.userId?.trim())
|
|
72
|
+
return NextResponse.json({ error: "Missing userId" }, { status: 400 });
|
|
73
|
+
|
|
74
|
+
await addAdmin(body.userId.trim());
|
|
75
|
+
const admins = await listAdmins();
|
|
76
|
+
return NextResponse.json({ ok: true, admins });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function DELETE(request: Request) {
|
|
80
|
+
const csrf = checkOrigin(request);
|
|
81
|
+
if (csrf) return csrf;
|
|
82
|
+
|
|
83
|
+
const authResult = await requireAdmin(request);
|
|
84
|
+
if (!authResult.ok)
|
|
85
|
+
return NextResponse.json({ error: authResult.code }, { status: authResult.status });
|
|
86
|
+
|
|
87
|
+
const body: { userId?: string } = await request.json();
|
|
88
|
+
if (!body.userId?.trim())
|
|
89
|
+
return NextResponse.json({ error: "Missing userId" }, { status: 400 });
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
await removeAdmin(body.userId.trim());
|
|
93
|
+
} catch (e) {
|
|
94
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
95
|
+
if (msg.startsWith("LAST_ADMIN")) {
|
|
96
|
+
return NextResponse.json({ error: "LAST_ADMIN", message: msg }, { status: 409 });
|
|
97
|
+
}
|
|
98
|
+
throw e;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const admins = await listAdmins();
|
|
102
|
+
return NextResponse.json({ ok: true, admins });
|
|
103
|
+
}
|
|
@@ -2,14 +2,15 @@ import { exec } from "node:child_process";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { NextResponse } from "next/server";
|
|
4
4
|
import { checkOrigin } from "@/lib/auth/csrf";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { resolveWorkspaceForUser } from "@/lib/workspace-context";
|
|
6
|
+
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
7
7
|
|
|
8
8
|
export async function POST(request: Request) {
|
|
9
9
|
const csrf = checkOrigin(request);
|
|
10
10
|
if (csrf) return csrf;
|
|
11
|
-
const
|
|
12
|
-
if (!
|
|
11
|
+
const ctx = await resolveWorkspaceForUser(request);
|
|
12
|
+
if (!ctx.ok) return NextResponse.json({ error: ctx.code }, { status: ctx.status });
|
|
13
|
+
const { rootDir } = ctx;
|
|
13
14
|
|
|
14
15
|
const body: { path?: string } = await request.json();
|
|
15
16
|
const rel = body.path;
|
|
@@ -17,8 +18,8 @@ export async function POST(request: Request) {
|
|
|
17
18
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
18
19
|
|
|
19
20
|
// Path traversal guard
|
|
20
|
-
const resolved =
|
|
21
|
-
if (
|
|
21
|
+
const resolved = safeWorkspacePath(rootDir, rel);
|
|
22
|
+
if (!resolved)
|
|
22
23
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
23
24
|
|
|
24
25
|
// Open in system file manager
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy set-root endpoint — back-compat shim for D1.
|
|
3
|
+
*
|
|
4
|
+
* Behaviour:
|
|
5
|
+
* 1. Validate dir (same as before).
|
|
6
|
+
* 2. Create (or find) a workspace for rootDir in the registry.
|
|
7
|
+
* 3. Keep setting the process-global rootDir + writing lastOpenedPath to config
|
|
8
|
+
* so the legacy fallback path still works for the existing client.
|
|
9
|
+
* 4. Return { ok, path, workspaceId } — added workspaceId for D2 migration.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: NOT admin-gated here so the current single-user flow is unaffected.
|
|
12
|
+
* The new POST /api/system/workspaces route is admin-gated; D2 will switch the
|
|
13
|
+
* UI to use that endpoint.
|
|
14
|
+
*/
|
|
1
15
|
import { stat } from "node:fs/promises";
|
|
2
16
|
import { NextResponse } from "next/server";
|
|
3
17
|
import { checkOrigin } from "@/lib/auth/csrf";
|
|
4
18
|
import { requireUser } from "@/lib/auth/server";
|
|
5
19
|
import { writeConfig } from "@/lib/config";
|
|
6
20
|
import { setRootDir } from "@/lib/root-dir";
|
|
21
|
+
import { listWorkspaces, createWorkspace } from "@/lib/workspaces";
|
|
22
|
+
import path from "node:path";
|
|
7
23
|
|
|
8
24
|
export async function POST(request: Request) {
|
|
9
25
|
const csrf = checkOrigin(request);
|
|
@@ -24,7 +40,14 @@ export async function POST(request: Request) {
|
|
|
24
40
|
return NextResponse.json({ error: "Directory not found" }, { status: 404 });
|
|
25
41
|
}
|
|
26
42
|
|
|
43
|
+
// Legacy: keep the global + config in sync for the fallback resolver.
|
|
27
44
|
setRootDir(dir);
|
|
28
45
|
await writeConfig({ lastOpenedPath: dir });
|
|
29
|
-
|
|
46
|
+
|
|
47
|
+
// Find or create a workspace for this rootDir so the registry is populated.
|
|
48
|
+
const resolved = path.resolve(dir);
|
|
49
|
+
const existing = (await listWorkspaces()).find((w) => w.rootDir === resolved);
|
|
50
|
+
const ws = existing ?? (await createWorkspace({ rootDir: dir, createdBy: auth.user.id }));
|
|
51
|
+
|
|
52
|
+
return NextResponse.json({ ok: true, path: dir, workspaceId: ws.id });
|
|
30
53
|
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/system/users (admin only)
|
|
3
|
+
*
|
|
4
|
+
* Admin creates a new account with a generated temporary password, returned
|
|
5
|
+
* once in the response. The new user signs in and changes it. The signup
|
|
6
|
+
* allowlist is bypassed for admin-initiated creation (the admin is the gate).
|
|
7
|
+
*
|
|
8
|
+
* This calls auth.api.signUpEmail server-side; the session it would mint for
|
|
9
|
+
* the new user is discarded (we never forward those Set-Cookie headers), so
|
|
10
|
+
* the admin's own session is untouched.
|
|
11
|
+
*/
|
|
12
|
+
export const runtime = "nodejs";
|
|
13
|
+
|
|
14
|
+
import { NextResponse } from "next/server";
|
|
15
|
+
import { randomBytes } from "node:crypto";
|
|
16
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
17
|
+
import { requireAdmin } from "@/lib/auth/admin";
|
|
18
|
+
import { auth, authReady, withAdminUserCreate, passwordAuthEnabled, db } from "@/lib/auth/server";
|
|
19
|
+
|
|
20
|
+
const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
21
|
+
|
|
22
|
+
/** Readable temp password: 4 groups, mixed case + digits, no ambiguous chars. */
|
|
23
|
+
function generateTempPassword(): string {
|
|
24
|
+
const alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789";
|
|
25
|
+
const bytes = randomBytes(16);
|
|
26
|
+
let out = "";
|
|
27
|
+
for (let i = 0; i < 16; i++) {
|
|
28
|
+
out += alphabet[bytes[i] % alphabet.length];
|
|
29
|
+
if (i % 4 === 3 && i < 15) out += "-";
|
|
30
|
+
}
|
|
31
|
+
return out; // e.g. "k7Pm-9QrT-x2Vn-bL4w"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function POST(req: Request): Promise<NextResponse> {
|
|
35
|
+
const csrf = checkOrigin(req);
|
|
36
|
+
if (csrf) return csrf;
|
|
37
|
+
|
|
38
|
+
const admin = await requireAdmin(req);
|
|
39
|
+
if (!admin.ok) {
|
|
40
|
+
return NextResponse.json({ error: admin.code }, { status: admin.status });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!passwordAuthEnabled) {
|
|
44
|
+
return NextResponse.json(
|
|
45
|
+
{ error: "PASSWORD_AUTH_DISABLED", message: "Email/password sign-in is disabled; cannot create password accounts." },
|
|
46
|
+
{ status: 400 },
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let body: { email?: unknown; name?: unknown };
|
|
51
|
+
try {
|
|
52
|
+
body = (await req.json()) as { email?: unknown; name?: unknown };
|
|
53
|
+
} catch {
|
|
54
|
+
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "Invalid JSON" }, { status: 400 });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const email = typeof body.email === "string" ? body.email.trim().toLowerCase() : "";
|
|
58
|
+
const name = typeof body.name === "string" && body.name.trim() ? body.name.trim() : email.split("@")[0];
|
|
59
|
+
|
|
60
|
+
if (!EMAIL_RE.test(email)) {
|
|
61
|
+
return NextResponse.json({ error: "INVALID_EMAIL", message: "A valid email is required" }, { status: 400 });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const tempPassword = generateTempPassword();
|
|
65
|
+
|
|
66
|
+
await authReady();
|
|
67
|
+
// Reject duplicates up front (signUpEmail may otherwise create a second
|
|
68
|
+
// credential row or silently succeed depending on Better Auth internals).
|
|
69
|
+
try {
|
|
70
|
+
const existing = db
|
|
71
|
+
.prepare("SELECT 1 FROM user WHERE lower(email) = ? LIMIT 1")
|
|
72
|
+
.get(email);
|
|
73
|
+
if (existing) {
|
|
74
|
+
return NextResponse.json(
|
|
75
|
+
{ error: "USER_EXISTS", message: "A user with that email already exists." },
|
|
76
|
+
{ status: 409 },
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
// If the lookup fails, fall through and let signUpEmail decide.
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
// Bypass the signup allowlist for this admin-initiated creation. The
|
|
85
|
+
// returned response (and any session cookie) is intentionally discarded.
|
|
86
|
+
const result = await withAdminUserCreate(() =>
|
|
87
|
+
auth.api.signUpEmail({
|
|
88
|
+
body: { email, password: tempPassword, name },
|
|
89
|
+
asResponse: true,
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
if (!result.ok) {
|
|
93
|
+
const text = await result.text().catch(() => "");
|
|
94
|
+
if (/exist|unique|already/i.test(text)) {
|
|
95
|
+
return NextResponse.json(
|
|
96
|
+
{ error: "USER_EXISTS", message: "A user with that email already exists." },
|
|
97
|
+
{ status: 409 },
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return NextResponse.json(
|
|
101
|
+
{ error: "CREATE_FAILED", message: text || "Failed to create user" },
|
|
102
|
+
{ status: 500 },
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
const msg = e instanceof Error ? e.message : "";
|
|
107
|
+
if (/exist|unique|already/i.test(msg)) {
|
|
108
|
+
return NextResponse.json(
|
|
109
|
+
{ error: "USER_EXISTS", message: "A user with that email already exists." },
|
|
110
|
+
{ status: 409 },
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return NextResponse.json(
|
|
114
|
+
{ error: "CREATE_FAILED", message: msg || "Failed to create user" },
|
|
115
|
+
{ status: 500 },
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return NextResponse.json({ ok: true, email, name, tempPassword });
|
|
120
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/system/workspaces/[id]/open
|
|
3
|
+
*
|
|
4
|
+
* Client calls this when switching to a workspace. Records lastOpenedAt so
|
|
5
|
+
* the most-recently-used workspace can be selected on next load.
|
|
6
|
+
*/
|
|
7
|
+
import { NextResponse } from "next/server";
|
|
8
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
9
|
+
import { requireUser } from "@/lib/auth/server";
|
|
10
|
+
import { isAdmin } from "@/lib/auth/admin";
|
|
11
|
+
import { getWorkspace, touchWorkspace, userCanAccess } from "@/lib/workspaces";
|
|
12
|
+
|
|
13
|
+
export const runtime = "nodejs";
|
|
14
|
+
|
|
15
|
+
type Params = { params: Promise<{ id: string }> };
|
|
16
|
+
|
|
17
|
+
export async function POST(request: Request, { params }: Params) {
|
|
18
|
+
const csrf = checkOrigin(request);
|
|
19
|
+
if (csrf) return csrf;
|
|
20
|
+
|
|
21
|
+
const auth = await requireUser(request);
|
|
22
|
+
if (!auth.ok) return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
23
|
+
|
|
24
|
+
const { id } = await params;
|
|
25
|
+
const ws = await getWorkspace(id);
|
|
26
|
+
if (!ws) return NextResponse.json({ error: "WORKSPACE_NOT_FOUND" }, { status: 404 });
|
|
27
|
+
|
|
28
|
+
const admin = await isAdmin(auth.user.id, auth.user.email);
|
|
29
|
+
if (!userCanAccess(ws, auth.user.id, admin))
|
|
30
|
+
return NextResponse.json({ error: "WORKSPACE_FORBIDDEN" }, { status: 403 });
|
|
31
|
+
|
|
32
|
+
await touchWorkspace(id);
|
|
33
|
+
return NextResponse.json({ ok: true });
|
|
34
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-workspace management API.
|
|
3
|
+
*
|
|
4
|
+
* PATCH /api/system/workspaces/[id] — update name, pinnedPaths (any user with
|
|
5
|
+
* access), or allowedUserIds (admin-only).
|
|
6
|
+
* DELETE /api/system/workspaces/[id] — admin-only: remove workspace from registry
|
|
7
|
+
* (never touches the filesystem directory).
|
|
8
|
+
*/
|
|
9
|
+
import { NextResponse } from "next/server";
|
|
10
|
+
import { checkOrigin } from "@/lib/auth/csrf";
|
|
11
|
+
import { requireUser } from "@/lib/auth/server";
|
|
12
|
+
import { isAdmin, requireAdmin } from "@/lib/auth/admin";
|
|
13
|
+
import {
|
|
14
|
+
getWorkspace,
|
|
15
|
+
renameWorkspace,
|
|
16
|
+
removeWorkspace,
|
|
17
|
+
setWorkspaceAccess,
|
|
18
|
+
setWorkspacePins,
|
|
19
|
+
userCanAccess,
|
|
20
|
+
} from "@/lib/workspaces";
|
|
21
|
+
|
|
22
|
+
export const runtime = "nodejs";
|
|
23
|
+
|
|
24
|
+
type Params = { params: Promise<{ id: string }> };
|
|
25
|
+
|
|
26
|
+
export async function PATCH(request: Request, { params }: Params) {
|
|
27
|
+
const csrf = checkOrigin(request);
|
|
28
|
+
if (csrf) return csrf;
|
|
29
|
+
|
|
30
|
+
const auth = await requireUser(request);
|
|
31
|
+
if (!auth.ok) return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
32
|
+
|
|
33
|
+
const { id } = await params;
|
|
34
|
+
const ws = await getWorkspace(id);
|
|
35
|
+
if (!ws) return NextResponse.json({ error: "WORKSPACE_NOT_FOUND" }, { status: 404 });
|
|
36
|
+
|
|
37
|
+
const admin = await isAdmin(auth.user.id, auth.user.email);
|
|
38
|
+
if (!userCanAccess(ws, auth.user.id, admin))
|
|
39
|
+
return NextResponse.json({ error: "WORKSPACE_FORBIDDEN" }, { status: 403 });
|
|
40
|
+
|
|
41
|
+
const body: {
|
|
42
|
+
name?: string;
|
|
43
|
+
pinnedPaths?: string[];
|
|
44
|
+
allowedUserIds?: string[];
|
|
45
|
+
} = await request.json();
|
|
46
|
+
|
|
47
|
+
// allowedUserIds is admin-only
|
|
48
|
+
if (body.allowedUserIds !== undefined && !admin)
|
|
49
|
+
return NextResponse.json({ error: "ADMIN_REQUIRED" }, { status: 403 });
|
|
50
|
+
|
|
51
|
+
// Apply each field
|
|
52
|
+
if (body.name !== undefined) await renameWorkspace(id, body.name.trim());
|
|
53
|
+
if (body.pinnedPaths !== undefined) await setWorkspacePins(id, body.pinnedPaths);
|
|
54
|
+
if (body.allowedUserIds !== undefined) await setWorkspaceAccess(id, body.allowedUserIds);
|
|
55
|
+
|
|
56
|
+
const updated = await getWorkspace(id);
|
|
57
|
+
return NextResponse.json({ ok: true, workspace: updated });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function DELETE(request: Request, { params }: Params) {
|
|
61
|
+
const csrf = checkOrigin(request);
|
|
62
|
+
if (csrf) return csrf;
|
|
63
|
+
|
|
64
|
+
const authResult = await requireAdmin(request);
|
|
65
|
+
if (!authResult.ok)
|
|
66
|
+
return NextResponse.json({ error: authResult.code }, { status: authResult.status });
|
|
67
|
+
|
|
68
|
+
const { id } = await params;
|
|
69
|
+
const ws = await getWorkspace(id);
|
|
70
|
+
if (!ws) return NextResponse.json({ error: "WORKSPACE_NOT_FOUND" }, { status: 404 });
|
|
71
|
+
|
|
72
|
+
await removeWorkspace(id);
|
|
73
|
+
return NextResponse.json({ ok: true });
|
|
74
|
+
}
|