Skip to content

Commit 67d791f

Browse files
feat: consolidate V2 journeys, implement M4 features, fix multiple V2 bugs
- Consolidate Management Fabric Storybook section into Production V2 - Implement My Access page (groups + workspaces tabs with pagination) - Implement Edit User Group with member/service-account filtering - Implement Grant Access to Workspace wizard - Implement bulk role deletion and user status toggles - Add V2 Overview page (shared with V1) - Add organization-wide access drawer with conditional actions - Fix cursor-based pagination (disable next when links.next is null) - Fix V2 audit log route missing rbac:*:read guard - Restore frontend.yaml permission validation (AST-based, lint:permissions) - Add comprehensive Storybook user journey tests with fn() spies - Add Playwright E2E specs for V2 roles, workspaces, and users - Adopt @msw/data for mock database (replaces StatefulCollection, immutable-state) - Centralize seed data in seed.ts with DEFAULT_* constants as single source of truth - Eliminate 9 duplicated fixture files, redirect all consumers to seed.ts/db.ts - Replace hardcoded strings in ~25 story assertions with mock data references - Add ResettableMockCollection.ready promise for async-safe test isolation Made-with: Cursor
1 parent a02227f commit 67d791f

723 files changed

Lines changed: 23654 additions & 23527 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.storybook/contexts/StorybookMockContext.tsx

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,44 @@ export const EMPTY_WORKSPACE_PERMISSIONS: WorkspacePermissionsMap = {
6060
move: [],
6161
};
6262

63+
/**
64+
* Kessel tenant permissions shape (V2 domain hooks).
65+
* Maps tenant-scoped relations to boolean (allowed/denied).
66+
* Used by useRolesAccess, useGroupsAccess, usePrincipalsAccess, useWorkspaceTenantAccess.
67+
*/
68+
export interface TenantPermissionsMap {
69+
rbac_roles_read: boolean;
70+
rbac_roles_write: boolean;
71+
rbac_groups_read: boolean;
72+
rbac_groups_write: boolean;
73+
rbac_principal_read: boolean;
74+
rbac_workspace_view: boolean;
75+
rbac_workspace_edit: boolean;
76+
rbac_workspace_create: boolean;
77+
rbac_workspace_delete: boolean;
78+
rbac_workspace_move: boolean;
79+
}
80+
81+
/** Default tenant permissions (all denied) */
82+
export const EMPTY_TENANT_PERMISSIONS: TenantPermissionsMap = {
83+
rbac_roles_read: false,
84+
rbac_roles_write: false,
85+
rbac_groups_read: false,
86+
rbac_groups_write: false,
87+
rbac_principal_read: false,
88+
rbac_workspace_view: false,
89+
rbac_workspace_edit: false,
90+
rbac_workspace_create: false,
91+
rbac_workspace_delete: false,
92+
rbac_workspace_move: false,
93+
};
94+
6395
export interface MockState {
6496
environment: Environment;
6597
isOrgAdmin: boolean;
6698
permissions: string[];
6799
workspacePermissions: WorkspacePermissionsMap;
100+
tenantPermissions: TenantPermissionsMap;
68101
/** Optional custom user identity for auth.getUser() */
69102
userIdentity?: MockUserIdentity;
70103
}
@@ -98,6 +131,21 @@ export interface StoryParameters {
98131
* ```
99132
*/
100133
workspacePermissions?: Partial<WorkspacePermissionsMap>;
134+
/**
135+
* Tenant permissions for V2 domain hooks (Kessel tenant-scoped checks).
136+
* Maps tenant relations to booleans.
137+
*
138+
* @example
139+
* ```ts
140+
* tenantPermissions: {
141+
* rbac_roles_read: true,
142+
* rbac_roles_write: true,
143+
* rbac_groups_read: true,
144+
* rbac_groups_write: false,
145+
* }
146+
* ```
147+
*/
148+
tenantPermissions?: Partial<TenantPermissionsMap>;
101149
/** User identity for auth.getUser() */
102150
userIdentity?: MockUserIdentity;
103151
/** Feature flags */
@@ -113,6 +161,7 @@ const defaultState: MockState = {
113161
isOrgAdmin: false,
114162
permissions: [],
115163
workspacePermissions: EMPTY_WORKSPACE_PERMISSIONS,
164+
tenantPermissions: EMPTY_TENANT_PERMISSIONS,
116165
};
117166

118167
export const StorybookMockContext = createContext<MockState>(defaultState);
@@ -127,11 +176,19 @@ export const StorybookMockProvider: React.FC<ProviderProps> = ({
127176
isOrgAdmin = false,
128177
permissions = [],
129178
workspacePermissions = EMPTY_WORKSPACE_PERMISSIONS,
179+
tenantPermissions = EMPTY_TENANT_PERMISSIONS,
130180
userIdentity,
131181
}) => {
132-
// Merge partial workspacePermissions with defaults so all 6 keys are always present
133182
const mergedWorkspacePermissions: WorkspacePermissionsMap = { ...EMPTY_WORKSPACE_PERMISSIONS, ...workspacePermissions };
134-
const value: MockState = { environment, isOrgAdmin, permissions, workspacePermissions: mergedWorkspacePermissions, userIdentity };
183+
const mergedTenantPermissions: TenantPermissionsMap = { ...EMPTY_TENANT_PERMISSIONS, ...tenantPermissions };
184+
const value: MockState = {
185+
environment,
186+
isOrgAdmin,
187+
permissions,
188+
workspacePermissions: mergedWorkspacePermissions,
189+
tenantPermissions: mergedTenantPermissions,
190+
userIdentity,
191+
};
135192
return <StorybookMockContext.Provider value={value}>{children}</StorybookMockContext.Provider>;
136193
};
137194

.storybook/fixtures/groups.ts

Lines changed: 0 additions & 66 deletions
This file was deleted.

.storybook/fixtures/roles.ts

Lines changed: 0 additions & 104 deletions
This file was deleted.

.storybook/fixtures/users.ts

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)