@burdenoff/microfe-organization 2026.517.1 → 2026.518.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/dist/organization-management/UserOrganizationRoot.d.ts +11 -4
- package/dist/organization-management/UserOrganizationRoot.d.ts.map +1 -1
- package/dist/organization-management/UserOrganizationRoot.js +23 -16
- package/dist/organization-management/UserOrganizationRoot.js.map +1 -1
- package/dist/organization-management/UserOrganizationRoutes.d.ts +27 -5
- package/dist/organization-management/UserOrganizationRoutes.d.ts.map +1 -1
- package/dist/organization-management/UserOrganizationRoutes.js +61 -20
- package/dist/organization-management/UserOrganizationRoutes.js.map +1 -1
- package/dist/organization-management/modules/workspaces/schemas/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -7,11 +7,18 @@ import { OrganizationRootProps } from './types';
|
|
|
7
7
|
* User-facing root for the organization management MFE, intended to be
|
|
8
8
|
* mounted inside product shells (workspaces, botlit, fluidgrids, etc.).
|
|
9
9
|
*
|
|
10
|
-
* Exposes
|
|
11
|
-
*
|
|
10
|
+
* Exposes the membership-scoped organization surface:
|
|
11
|
+
* - Organizations list (`mode="my"` → `myOrganizations`)
|
|
12
|
+
* - Organization detail / edit (per-action `hasPermission` gates;
|
|
13
|
+
* backend enforces membership on `organization(id)` resolver)
|
|
14
|
+
* - Members list / detail / invite (backend enforces membership on
|
|
15
|
+
* `organizationMembers` resolver)
|
|
16
|
+
* - My pending invites
|
|
12
17
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
18
|
+
* Registers "Organizations" + "My Invites" nav items.
|
|
19
|
+
*
|
|
20
|
+
* Takes the same props as `OrganizationRootProps` so hosts can swap
|
|
21
|
+
* between the user and admin roots without adapter code.
|
|
15
22
|
*/
|
|
16
23
|
export declare const UserOrganizationRoot: FC<OrganizationRootProps>;
|
|
17
24
|
//# sourceMappingURL=UserOrganizationRoot.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserOrganizationRoot.d.ts","sourceRoot":"","sources":["../../src/organization-management/UserOrganizationRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,OAAO,KAAK,EAAW,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAG9D
|
|
1
|
+
{"version":3,"file":"UserOrganizationRoot.d.ts","sourceRoot":"","sources":["../../src/organization-management/UserOrganizationRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,OAAO,KAAK,EAAW,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAG9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,qBAAqB,CA4D1D,CAAC"}
|
|
@@ -1,37 +1,44 @@
|
|
|
1
1
|
import { OrgConsoleProvider as e } from "./providers/OrgConsoleProvider.js";
|
|
2
2
|
import { UserOrganizationRoutes as t } from "./UserOrganizationRoutes.js";
|
|
3
3
|
import { useEffect as n } from "react";
|
|
4
|
-
import {
|
|
5
|
-
import { Toaster as
|
|
6
|
-
import { FeatureFlagProvider as
|
|
7
|
-
import { jsx as
|
|
4
|
+
import { Building2 as r, Mail as i } from "lucide-react";
|
|
5
|
+
import { Toaster as a } from "@burdenoff/fe-libs/ui";
|
|
6
|
+
import { FeatureFlagProvider as o } from "@burdenoff/fe-libs/shared/feature-flags";
|
|
7
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
8
|
//#region src/organization-management/UserOrganizationRoot.tsx
|
|
9
|
-
var
|
|
10
|
-
let { registerNavItems:
|
|
9
|
+
var l = (l) => {
|
|
10
|
+
let { registerNavItems: u, registerFooterItems: d, basePath: f = "/organizations" } = l, p = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
|
|
11
11
|
return n(() => {
|
|
12
|
-
if (
|
|
12
|
+
if (u) return u([{
|
|
13
|
+
id: "user-org-organizations",
|
|
14
|
+
label: "Organizations",
|
|
15
|
+
path: f,
|
|
16
|
+
icon: /* @__PURE__ */ s(r, { size: 20 }),
|
|
17
|
+
order: 20,
|
|
18
|
+
group: "user"
|
|
19
|
+
}, {
|
|
13
20
|
id: "user-org-invites",
|
|
14
21
|
label: "My Invites",
|
|
15
|
-
path: f
|
|
16
|
-
icon: /* @__PURE__ */
|
|
22
|
+
path: p(f, "/invites"),
|
|
23
|
+
icon: /* @__PURE__ */ s(i, { size: 20 }),
|
|
17
24
|
order: 30,
|
|
18
25
|
group: "user"
|
|
19
26
|
}]);
|
|
20
|
-
}, [
|
|
21
|
-
if (
|
|
27
|
+
}, [u, f]), n(() => {
|
|
28
|
+
if (d) return d([{
|
|
22
29
|
id: "user-organization-version",
|
|
23
30
|
label: "Organization (User) v0.1.0",
|
|
24
31
|
type: "status",
|
|
25
32
|
order: 30,
|
|
26
33
|
section: "left"
|
|
27
34
|
}]);
|
|
28
|
-
}, [
|
|
35
|
+
}, [d]), /* @__PURE__ */ s(o, {
|
|
29
36
|
workspaceId: null,
|
|
30
37
|
gateway: "global",
|
|
31
38
|
defaultEnabled: !0,
|
|
32
|
-
children: /* @__PURE__ */
|
|
33
|
-
...
|
|
34
|
-
children: [/* @__PURE__ */
|
|
39
|
+
children: /* @__PURE__ */ c(e, {
|
|
40
|
+
...l,
|
|
41
|
+
children: [/* @__PURE__ */ s(t, {}), /* @__PURE__ */ s(a, {
|
|
35
42
|
position: "top-right",
|
|
36
43
|
richColors: !0,
|
|
37
44
|
closeButton: !0
|
|
@@ -40,6 +47,6 @@ var c = (c) => {
|
|
|
40
47
|
});
|
|
41
48
|
};
|
|
42
49
|
//#endregion
|
|
43
|
-
export {
|
|
50
|
+
export { l as UserOrganizationRoot };
|
|
44
51
|
|
|
45
52
|
//# sourceMappingURL=UserOrganizationRoot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserOrganizationRoot.js","names":[],"sources":["../../src/organization-management/UserOrganizationRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport { Mail } from 'lucide-react';\nimport { Toaster } from '@burdenoff/fe-libs/ui';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { OrgConsoleProvider } from './providers/OrgConsoleProvider';\nimport type { NavItem, OrganizationRootProps } from './types';\nimport { UserOrganizationRoutes } from './UserOrganizationRoutes';\n\n/**\n * UserOrganizationRoot\n *\n * User-facing root for the organization management MFE, intended to be\n * mounted inside product shells (workspaces, botlit, fluidgrids, etc.).\n *\n * Exposes
|
|
1
|
+
{"version":3,"file":"UserOrganizationRoot.js","names":[],"sources":["../../src/organization-management/UserOrganizationRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport { Building2, Mail } from 'lucide-react';\nimport { Toaster } from '@burdenoff/fe-libs/ui';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { OrgConsoleProvider } from './providers/OrgConsoleProvider';\nimport type { NavItem, OrganizationRootProps } from './types';\nimport { UserOrganizationRoutes } from './UserOrganizationRoutes';\n\n/**\n * UserOrganizationRoot\n *\n * User-facing root for the organization management MFE, intended to be\n * mounted inside product shells (workspaces, botlit, fluidgrids, etc.).\n *\n * Exposes the membership-scoped organization surface:\n * - Organizations list (`mode=\"my\"` → `myOrganizations`)\n * - Organization detail / edit (per-action `hasPermission` gates;\n * backend enforces membership on `organization(id)` resolver)\n * - Members list / detail / invite (backend enforces membership on\n * `organizationMembers` resolver)\n * - My pending invites\n *\n * Registers \"Organizations\" + \"My Invites\" nav items.\n *\n * Takes the same props as `OrganizationRootProps` so hosts can swap\n * between the user and admin roots without adapter code.\n */\nexport const UserOrganizationRoot: FC<OrganizationRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/organizations' } = props;\n\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'user-org-organizations',\n label: 'Organizations',\n path: basePath,\n icon: <Building2 size={20} />,\n order: 20,\n group: 'user',\n },\n {\n id: 'user-org-invites',\n label: 'My Invites',\n path: joinPath(basePath, '/invites'),\n icon: <Mail size={20} />,\n order: 30,\n group: 'user',\n },\n ];\n\n const cleanup = registerNavItems(navItems);\n return cleanup;\n }, [registerNavItems, basePath]);\n\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'user-organization-version',\n label: 'Organization (User) v0.1.0',\n type: 'status' as const,\n order: 30,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems]);\n\n return (\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <OrgConsoleProvider {...props}>\n <UserOrganizationRoutes />\n <Toaster position=\"top-right\" richColors closeButton />\n </OrgConsoleProvider>\n </FeatureFlagProvider>\n );\n};\n"],"mappings":";;;;;;;;AA4BA,IAAa,KAAmD,MAAU;CACxE,IAAM,EAAE,qBAAkB,wBAAqB,cAAW,qBAAqB,GAEzE,KAAY,GAAc,OACZ,EAAK,SAAS,IAAI,GAAG,EAAK,MAAM,GAAG,GAAG,GAAG,MACzC,EAAK,WAAW,IAAI,GAAG,IAAO,IAAI;AA+CtD,QA3CA,QAAgB;AACT,QAsBL,QADgB,EAnBY,CAC1B;GACE,IAAI;GACJ,OAAO;GACP,MAAM;GACN,MAAM,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;GAC7B,OAAO;GACP,OAAO;GACR,EACD;GACE,IAAI;GACJ,OAAO;GACP,MAAM,EAAS,GAAU,WAAW;GACpC,MAAM,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;GACxB,OAAO;GACP,OAAO;GACR,CACF,CAEyC;IAEzC,CAAC,GAAkB,EAAS,CAAC,EAEhC,QAAgB;AACT,QAaL,QADgB,EAVI,CAClB;GACE,IAAI;GACJ,OAAO;GACP,MAAM;GACN,OAAO;GACP,SAAS;GACV,CACF,CAE+C;IAE/C,CAAC,EAAoB,CAAC,EAGvB,kBAAC,GAAD;EAAqB,aAAa;EAAM,SAAQ;EAAS,gBAAgB;YACvE,kBAAC,GAAD;GAAoB,GAAI;aAAxB,CACE,kBAAC,GAAD,EAA0B,CAAA,EAC1B,kBAAC,GAAD;IAAS,UAAS;IAAY,YAAA;IAAW,aAAA;IAAc,CAAA,CACpC;;EACD,CAAA"}
|
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* UserOrganizationRoutes
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* User-facing routing surface for the organization MFE, mounted by product
|
|
5
|
+
* application shells (vibecontrols, etc.). Exposes the same shape as the
|
|
6
|
+
* admin routing surface but the list page renders membership-scoped via
|
|
7
|
+
* `mode="my"` (calls `myOrganizations` with `@rbac(scopeType: "self")`).
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
9
|
+
* Per-action authorisation lives inside each page (`hasPermission` checks
|
|
10
|
+
* for create / update / delete), so users with elevated permissions on an
|
|
11
|
+
* org still see those controls; users without them only see view actions.
|
|
12
|
+
*
|
|
13
|
+
* All routes are unconditionally mounted. Feature flags
|
|
14
|
+
* (`organization.create`, `organization.workspaces`, `organization.members`,
|
|
15
|
+
* `organization.invite`) are applied at the call site — buttons, nav
|
|
16
|
+
* items, section headers inside the pages — not on the route graph. This
|
|
17
|
+
* avoids a class of route/nav mismatches where a page unconditionally
|
|
18
|
+
* navigates to a URL that has been gated off (the previous flag-gated
|
|
19
|
+
* routes produced dead URLs from `OrganizationDetailPage`'s workspace
|
|
20
|
+
* cards, "Create Workspace" CTA, "Manage Members" button, etc.).
|
|
21
|
+
*
|
|
22
|
+
* Access control:
|
|
23
|
+
* - Per-action `hasPermission` checks inside each page hide controls the
|
|
24
|
+
* user can't use.
|
|
25
|
+
* - Backend resolvers (`organization`, `organizationMembers`, etc.)
|
|
26
|
+
* enforce membership server-side via `userHasAccessToOrganization`, so
|
|
27
|
+
* deep-linking to a URL the user has no access to 403s at the resolver.
|
|
28
|
+
*
|
|
29
|
+
* Lazy loading strategy:
|
|
30
|
+
* - OrganizationsListPage: Eager loaded (main entry point)
|
|
31
|
+
* - All other pages: Lazy loaded for better initial bundle size
|
|
10
32
|
*/
|
|
11
33
|
export declare function UserOrganizationRoutes(): import("react/jsx-runtime").JSX.Element;
|
|
12
34
|
//# sourceMappingURL=UserOrganizationRoutes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserOrganizationRoutes.d.ts","sourceRoot":"","sources":["../../src/organization-management/UserOrganizationRoutes.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UserOrganizationRoutes.d.ts","sourceRoot":"","sources":["../../src/organization-management/UserOrganizationRoutes.tsx"],"names":[],"mappings":"AAqEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,sBAAsB,4CA4BrC"}
|
|
@@ -1,30 +1,71 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { OrganizationsListPage as e } from "./modules/organizations/pages/OrganizationsListPage.js";
|
|
2
|
+
import { Suspense as t, lazy as n } from "react";
|
|
3
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
|
+
import { Route as a, Routes as o } from "react-router-dom";
|
|
4
5
|
//#region src/organization-management/UserOrganizationRoutes.tsx
|
|
5
|
-
var s =
|
|
6
|
-
function
|
|
7
|
-
return /* @__PURE__ */
|
|
6
|
+
var s = n(() => import("./modules/organizations/pages/OrganizationCreatePage.js").then((e) => ({ default: e.OrganizationCreatePage }))), c = n(() => import("./modules/organizations/pages/OrganizationDetailPage.js").then((e) => ({ default: e.OrganizationDetailPage }))), l = n(() => import("./modules/organizations/pages/OrganizationEditPage.js").then((e) => ({ default: e.OrganizationEditPage }))), u = n(() => import("./modules/workspaces/pages/WorkspacesListPage.js").then((e) => ({ default: e.WorkspacesListPage }))), d = n(() => import("./modules/workspaces/pages/WorkspaceCreatePage.js").then((e) => ({ default: e.WorkspaceCreatePage }))), f = n(() => import("./modules/workspaces/pages/WorkspaceDetailPage.js").then((e) => ({ default: e.WorkspaceDetailPage }))), p = n(() => import("./modules/workspaces/pages/WorkspaceEditPage.js").then((e) => ({ default: e.WorkspaceEditPage }))), m = n(() => import("./modules/members/pages/MembersListPage.js").then((e) => ({ default: e.MembersListPage }))), h = n(() => import("./modules/members/pages/MemberDetailPage.js").then((e) => ({ default: e.MemberDetailPage }))), g = n(() => import("./modules/members/pages/InviteMemberPage.js").then((e) => ({ default: e.InviteMemberPage }))), _ = n(() => import("./modules/members/pages/MyInvitesPage.js").then((e) => ({ default: e.MyInvitesPage })));
|
|
7
|
+
function v() {
|
|
8
|
+
return /* @__PURE__ */ r("div", {
|
|
8
9
|
className: "flex items-center justify-center min-h-[200px]",
|
|
9
|
-
children: /* @__PURE__ */
|
|
10
|
+
children: /* @__PURE__ */ r("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-[var(--color-border-default)] border-t-[var(--color-action-primary-bg)]" })
|
|
10
11
|
});
|
|
11
12
|
}
|
|
12
|
-
function
|
|
13
|
-
return /* @__PURE__ */
|
|
14
|
-
fallback: /* @__PURE__ */
|
|
15
|
-
children: /* @__PURE__ */
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
function y() {
|
|
14
|
+
return /* @__PURE__ */ r(t, {
|
|
15
|
+
fallback: /* @__PURE__ */ r(v, {}),
|
|
16
|
+
children: /* @__PURE__ */ i(o, { children: [
|
|
17
|
+
/* @__PURE__ */ r(a, {
|
|
18
|
+
index: !0,
|
|
19
|
+
element: /* @__PURE__ */ r(e, { mode: "my" })
|
|
20
|
+
}),
|
|
21
|
+
/* @__PURE__ */ r(a, {
|
|
22
|
+
path: "new",
|
|
23
|
+
element: /* @__PURE__ */ r(s, {})
|
|
24
|
+
}),
|
|
25
|
+
/* @__PURE__ */ r(a, {
|
|
26
|
+
path: ":id",
|
|
27
|
+
element: /* @__PURE__ */ r(c, {})
|
|
28
|
+
}),
|
|
29
|
+
/* @__PURE__ */ r(a, {
|
|
30
|
+
path: ":id/edit",
|
|
31
|
+
element: /* @__PURE__ */ r(l, {})
|
|
32
|
+
}),
|
|
33
|
+
/* @__PURE__ */ r(a, {
|
|
34
|
+
path: "invites",
|
|
35
|
+
element: /* @__PURE__ */ r(_, {})
|
|
36
|
+
}),
|
|
37
|
+
/* @__PURE__ */ r(a, {
|
|
38
|
+
path: "workspaces",
|
|
39
|
+
element: /* @__PURE__ */ r(u, {})
|
|
40
|
+
}),
|
|
41
|
+
/* @__PURE__ */ r(a, {
|
|
42
|
+
path: "workspaces/new",
|
|
43
|
+
element: /* @__PURE__ */ r(d, {})
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ r(a, {
|
|
46
|
+
path: "workspaces/:id",
|
|
47
|
+
element: /* @__PURE__ */ r(f, {})
|
|
48
|
+
}),
|
|
49
|
+
/* @__PURE__ */ r(a, {
|
|
50
|
+
path: "workspaces/:id/edit",
|
|
51
|
+
element: /* @__PURE__ */ r(p, {})
|
|
52
|
+
}),
|
|
53
|
+
/* @__PURE__ */ r(a, {
|
|
54
|
+
path: ":organizationId/members/invite",
|
|
55
|
+
element: /* @__PURE__ */ r(g, {})
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ r(a, {
|
|
58
|
+
path: ":organizationId/members",
|
|
59
|
+
element: /* @__PURE__ */ r(m, {})
|
|
60
|
+
}),
|
|
61
|
+
/* @__PURE__ */ r(a, {
|
|
62
|
+
path: ":organizationId/members/:userId",
|
|
63
|
+
element: /* @__PURE__ */ r(h, {})
|
|
20
64
|
})
|
|
21
|
-
})
|
|
22
|
-
path: "invites",
|
|
23
|
-
element: /* @__PURE__ */ n(s, {})
|
|
24
|
-
})] })
|
|
65
|
+
] })
|
|
25
66
|
});
|
|
26
67
|
}
|
|
27
68
|
//#endregion
|
|
28
|
-
export {
|
|
69
|
+
export { y as UserOrganizationRoutes };
|
|
29
70
|
|
|
30
71
|
//# sourceMappingURL=UserOrganizationRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserOrganizationRoutes.js","names":[],"sources":["../../src/organization-management/UserOrganizationRoutes.tsx"],"sourcesContent":["import { lazy, Suspense } from 'react';\nimport {
|
|
1
|
+
{"version":3,"file":"UserOrganizationRoutes.js","names":[],"sources":["../../src/organization-management/UserOrganizationRoutes.tsx"],"sourcesContent":["import { lazy, Suspense } from 'react';\nimport { Route, Routes } from 'react-router-dom';\n\n// Eager load — main entry point page\nimport { OrganizationsListPage } from './modules/organizations/pages/OrganizationsListPage';\n\n// Lazy load — secondary pages. Same set as the admin surface but the list\n// page below renders in `mode=\"my\"` (membership-scoped), and per-action\n// permission gates inside each page (hasPermission(PERMISSIONS.ORG_*))\n// already hide buttons the user can't use.\nconst OrganizationCreatePage = lazy(() =>\n import('./modules/organizations/pages/OrganizationCreatePage').then((m) => ({\n default: m.OrganizationCreatePage,\n }))\n);\nconst OrganizationDetailPage = lazy(() =>\n import('./modules/organizations/pages/OrganizationDetailPage').then((m) => ({\n default: m.OrganizationDetailPage,\n }))\n);\nconst OrganizationEditPage = lazy(() =>\n import('./modules/organizations/pages/OrganizationEditPage').then((m) => ({\n default: m.OrganizationEditPage,\n }))\n);\nconst WorkspacesListPage = lazy(() =>\n import('./modules/workspaces/pages/WorkspacesListPage').then((m) => ({\n default: m.WorkspacesListPage,\n }))\n);\nconst WorkspaceCreatePage = lazy(() =>\n import('./modules/workspaces/pages/WorkspaceCreatePage').then((m) => ({\n default: m.WorkspaceCreatePage,\n }))\n);\nconst WorkspaceDetailPage = lazy(() =>\n import('./modules/workspaces/pages/WorkspaceDetailPage').then((m) => ({\n default: m.WorkspaceDetailPage,\n }))\n);\nconst WorkspaceEditPage = lazy(() =>\n import('./modules/workspaces/pages/WorkspaceEditPage').then((m) => ({\n default: m.WorkspaceEditPage,\n }))\n);\nconst MembersListPage = lazy(() =>\n import('./modules/members/pages/MembersListPage').then((m) => ({ default: m.MembersListPage }))\n);\nconst MemberDetailPage = lazy(() =>\n import('./modules/members/pages/MemberDetailPage').then((m) => ({ default: m.MemberDetailPage }))\n);\nconst InviteMemberPage = lazy(() =>\n import('./modules/members/pages/InviteMemberPage').then((m) => ({ default: m.InviteMemberPage }))\n);\nconst MyInvitesPage = lazy(() =>\n import('./modules/members/pages/MyInvitesPage').then((m) => ({ default: m.MyInvitesPage }))\n);\n\n/**\n * Loading fallback for lazy-loaded pages\n */\nfunction PageLoadingFallback() {\n return (\n <div className=\"flex items-center justify-center min-h-[200px]\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-[var(--color-border-default)] border-t-[var(--color-action-primary-bg)]\" />\n </div>\n );\n}\n\n/**\n * UserOrganizationRoutes\n *\n * User-facing routing surface for the organization MFE, mounted by product\n * application shells (vibecontrols, etc.). Exposes the same shape as the\n * admin routing surface but the list page renders membership-scoped via\n * `mode=\"my\"` (calls `myOrganizations` with `@rbac(scopeType: \"self\")`).\n *\n * Per-action authorisation lives inside each page (`hasPermission` checks\n * for create / update / delete), so users with elevated permissions on an\n * org still see those controls; users without them only see view actions.\n *\n * All routes are unconditionally mounted. Feature flags\n * (`organization.create`, `organization.workspaces`, `organization.members`,\n * `organization.invite`) are applied at the call site — buttons, nav\n * items, section headers inside the pages — not on the route graph. This\n * avoids a class of route/nav mismatches where a page unconditionally\n * navigates to a URL that has been gated off (the previous flag-gated\n * routes produced dead URLs from `OrganizationDetailPage`'s workspace\n * cards, \"Create Workspace\" CTA, \"Manage Members\" button, etc.).\n *\n * Access control:\n * - Per-action `hasPermission` checks inside each page hide controls the\n * user can't use.\n * - Backend resolvers (`organization`, `organizationMembers`, etc.)\n * enforce membership server-side via `userHasAccessToOrganization`, so\n * deep-linking to a URL the user has no access to 403s at the resolver.\n *\n * Lazy loading strategy:\n * - OrganizationsListPage: Eager loaded (main entry point)\n * - All other pages: Lazy loaded for better initial bundle size\n */\nexport function UserOrganizationRoutes() {\n return (\n <Suspense fallback={<PageLoadingFallback />}>\n <Routes>\n {/* Organizations — index is the membership-scoped list (eager loaded) */}\n <Route index element={<OrganizationsListPage mode=\"my\" />} />\n <Route path=\"new\" element={<OrganizationCreatePage />} />\n <Route path=\":id\" element={<OrganizationDetailPage />} />\n <Route path=\":id/edit\" element={<OrganizationEditPage />} />\n\n {/* My Invites — user-level, not org-scoped */}\n <Route path=\"invites\" element={<MyInvitesPage />} />\n\n {/* Workspaces — `OrganizationDetailPage` navigates here on workspace\n card click and the \"Create Workspace\" CTA. */}\n <Route path=\"workspaces\" element={<WorkspacesListPage />} />\n <Route path=\"workspaces/new\" element={<WorkspaceCreatePage />} />\n <Route path=\"workspaces/:id\" element={<WorkspaceDetailPage />} />\n <Route path=\"workspaces/:id/edit\" element={<WorkspaceEditPage />} />\n\n {/* Members — scoped under organization ID. `OrganizationDetailPage`\n unconditionally renders the \"Manage Members\" button. */}\n <Route path=\":organizationId/members/invite\" element={<InviteMemberPage />} />\n <Route path=\":organizationId/members\" element={<MembersListPage />} />\n <Route path=\":organizationId/members/:userId\" element={<MemberDetailPage />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":";;;;;AAUA,IAAM,IAAyB,QAC7B,OAAO,2DAAwD,MAAM,OAAO,EAC1E,SAAS,EAAE,wBACZ,EAAE,CACJ,EACK,IAAyB,QAC7B,OAAO,2DAAwD,MAAM,OAAO,EAC1E,SAAS,EAAE,wBACZ,EAAE,CACJ,EACK,IAAuB,QAC3B,OAAO,yDAAsD,MAAM,OAAO,EACxE,SAAS,EAAE,sBACZ,EAAE,CACJ,EACK,IAAqB,QACzB,OAAO,oDAAiD,MAAM,OAAO,EACnE,SAAS,EAAE,oBACZ,EAAE,CACJ,EACK,IAAsB,QAC1B,OAAO,qDAAkD,MAAM,OAAO,EACpE,SAAS,EAAE,qBACZ,EAAE,CACJ,EACK,IAAsB,QAC1B,OAAO,qDAAkD,MAAM,OAAO,EACpE,SAAS,EAAE,qBACZ,EAAE,CACJ,EACK,IAAoB,QACxB,OAAO,mDAAgD,MAAM,OAAO,EAClE,SAAS,EAAE,mBACZ,EAAE,CACJ,EACK,IAAkB,QACtB,OAAO,8CAA2C,MAAM,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAChG,EACK,IAAmB,QACvB,OAAO,+CAA4C,MAAM,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAClG,EACK,IAAmB,QACvB,OAAO,+CAA4C,MAAM,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAClG,EACK,IAAgB,QACpB,OAAO,4CAAyC,MAAM,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAC5F;AAKD,SAAS,IAAsB;AAC7B,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,6HAA8H,CAAA;EACzI,CAAA;;AAoCV,SAAgB,IAAyB;AACvC,QACE,kBAAC,GAAD;EAAU,UAAU,kBAAC,GAAD,EAAuB,CAAA;YACzC,kBAAC,GAAD,EAAA,UAAA;GAEE,kBAAC,GAAD;IAAO,OAAA;IAAM,SAAS,kBAAC,GAAD,EAAuB,MAAK,MAAO,CAAA;IAAI,CAAA;GAC7D,kBAAC,GAAD;IAAO,MAAK;IAAM,SAAS,kBAAC,GAAD,EAA0B,CAAA;IAAI,CAAA;GACzD,kBAAC,GAAD;IAAO,MAAK;IAAM,SAAS,kBAAC,GAAD,EAA0B,CAAA;IAAI,CAAA;GACzD,kBAAC,GAAD;IAAO,MAAK;IAAW,SAAS,kBAAC,GAAD,EAAwB,CAAA;IAAI,CAAA;GAG5D,kBAAC,GAAD;IAAO,MAAK;IAAU,SAAS,kBAAC,GAAD,EAAiB,CAAA;IAAI,CAAA;GAIpD,kBAAC,GAAD;IAAO,MAAK;IAAa,SAAS,kBAAC,GAAD,EAAsB,CAAA;IAAI,CAAA;GAC5D,kBAAC,GAAD;IAAO,MAAK;IAAiB,SAAS,kBAAC,GAAD,EAAuB,CAAA;IAAI,CAAA;GACjE,kBAAC,GAAD;IAAO,MAAK;IAAiB,SAAS,kBAAC,GAAD,EAAuB,CAAA;IAAI,CAAA;GACjE,kBAAC,GAAD;IAAO,MAAK;IAAsB,SAAS,kBAAC,GAAD,EAAqB,CAAA;IAAI,CAAA;GAIpE,kBAAC,GAAD;IAAO,MAAK;IAAiC,SAAS,kBAAC,GAAD,EAAoB,CAAA;IAAI,CAAA;GAC9E,kBAAC,GAAD;IAAO,MAAK;IAA0B,SAAS,kBAAC,GAAD,EAAmB,CAAA;IAAI,CAAA;GACtE,kBAAC,GAAD;IAAO,MAAK;IAAkC,SAAS,kBAAC,GAAD,EAAoB,CAAA;IAAI,CAAA;GACxE,EAAA,CAAA;EACA,CAAA"}
|
|
@@ -14,16 +14,16 @@ export declare const createWorkspaceSchema: z.ZodObject<{
|
|
|
14
14
|
organizationId: string;
|
|
15
15
|
name: string;
|
|
16
16
|
slug: string;
|
|
17
|
-
type?: string | undefined;
|
|
18
17
|
status?: WorkspaceStatus | undefined;
|
|
18
|
+
type?: string | undefined;
|
|
19
19
|
metadata?: Record<string, unknown> | undefined;
|
|
20
20
|
}, {
|
|
21
21
|
tenantId: string;
|
|
22
22
|
organizationId: string;
|
|
23
23
|
name: string;
|
|
24
24
|
slug: string;
|
|
25
|
-
type?: string | undefined;
|
|
26
25
|
status?: WorkspaceStatus | undefined;
|
|
26
|
+
type?: string | undefined;
|
|
27
27
|
metadata?: Record<string, unknown> | undefined;
|
|
28
28
|
}>;
|
|
29
29
|
export declare const updateWorkspaceSchema: z.ZodObject<{
|