feat(directory): Phase 2 — Roles + Entitlements + Comments#412
Open
larsgeorge-db wants to merge 1 commit into
Open
feat(directory): Phase 2 — Roles + Entitlements + Comments#412larsgeorge-db wants to merge 1 commit into
larsgeorge-db wants to merge 1 commit into
Conversation
Stacks on Phase 1 frontend (#407). Migrates the multi-principal RBAC surfaces to PrincipalPicker per plan #375. UI changes: - settings/role-form-dialog.tsx — assigned_groups text-with-commas Input replaced with PrincipalPicker(multi, groups). Legacy comma-separated strings still rehydrate via the new normaliseAssignedGroups helper. - views/entitlements.tsx — Persona group-assignment "add" Select with hard-coded demo list replaced with PrincipalPicker(multi, groups). The picker renders the current selection as its own badges, so the separate Badge row is gone. Backend PUT /api/entitlements/personas/{id}/groups accepts the same List[str] payload. - comments/comment-sidebar.tsx — Audience field gains a PrincipalPicker(multi, users+groups) alongside (not replacing) the existing Teams / App Roles checkbox lists. Picked users emit as plain emails, picked groups as plain group names; existing team:* / role:* tokens flow through unchanged. parseAudienceTokens + buildAudienceTokens helpers extracted for round-trip clarity. Helpers (pure functions, fully tested): - lib/audience.ts — parseAudienceTokens / buildAudienceTokens. - lib/assigned-groups.ts — normaliseAssignedGroups. Tests (12 new, 562 total passing): - lib/audience.test.ts (6): mixed audience round-trip, defensive guards (null / empty / non-string), empty-id passthrough for prefix-only tokens. - lib/assigned-groups.test.ts (6): array passthrough, comma-string split + trim, empty / nullish / non-string-non-array → [] fallback. Per-page form tests with the picker rendered inside Radix dialogs remain deferred to Playwright E2E (matches the existing convention in this repo: role-form-dialog.test, team-form-dialog.test, and project-form-dialog.test are all skipped for the same Radix-in-jsdom reason). The new helpers cover the load-bearing data transforms. No backend changes -- existing PUT/POST endpoints accept the same payload shapes they already did.
This was referenced May 21, 2026
larsgeorge-db
added a commit
that referenced
this pull request
May 21, 2026
…r scope Documents what shipped under PRs #406 / #407 / #412 / #413 / #416 / #417: - Renames the integration's manager / routes / settings keys in the PRD to match the implementation (Directory layer, /api/directory/*, DIRECTORY_* settings, Settings → Directory tab). - Documents the DirectoryProvider interface and the (DirectoryProviderContext, DirectoryProviderConfig) factory signature so future provider plug-ins know what to implement. - Documents the v1 provider set, which expanded during planning from Entra-only to entra + lakebase + file. The Lakebase table schema and CSV format are included so operators have a single reference. - Preserves story content, the disambiguation rule, both picker modes, storage-compatibility guarantees, and graceful-degradation rules from the PRD body unchanged. - Re-confirms the out-of-scope list (Okta/Ping, service principals, OBO, profile photos, manager hierarchy, role/team Select replacement, CSV bulk import) which the abstraction makes cheap to revisit.
larsgeorge-db
added a commit
that referenced
this pull request
May 21, 2026
…r scope Documents what shipped under PRs #406 / #407 / #412 / #413 / #416 / #417: - Renames the integration's manager / routes / settings keys in the PRD to match the implementation (Directory layer, /api/directory/*, DIRECTORY_* settings, Settings → Directory tab). - Documents the DirectoryProvider interface and the (DirectoryProviderContext, DirectoryProviderConfig) factory signature so future provider plug-ins know what to implement. - Documents the v1 provider set, which expanded during planning from Entra-only to entra + lakebase + file. The Lakebase table schema and CSV format are included so operators have a single reference. - Preserves story content, the disambiguation rule, both picker modes, storage-compatibility guarantees, and graceful-degradation rules from the PRD body unchanged. - Re-confirms the out-of-scope list (Okta/Ping, service principals, OBO, profile photos, manager hierarchy, role/team Select replacement, CSV bulk import) which the abstraction makes cheap to revisit.
398400c to
23fd4f7
Compare
6778b9a to
58eaf6b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2 of the directory-lookup-and-principal-picker plan (#375). Stacked on #407 — base is
feat/directory-frontendso the diff here is Phase-2 only. Will rebase ontomainonce #406 and #407 land.Plan: #375
Backend: #406
Phase 1 frontend: #407
Summary
Three multi-principal RBAC surfaces migrated to
PrincipalPicker. No backend changes — every existing endpoint accepts the same payload shape it already did.role-form-dialog.tsx):assigned_groupscomma-separated Input →PrincipalPicker(multi, groups). Legacy comma-string records still rehydrate via the newnormaliseAssignedGroupshelper.entitlements.tsx): persona-group "add"Selectwith a hard-coded 14-name demo list →PrincipalPicker(multi, groups). The picker renders its own selected-badges so the separate Badge row was dropped.PUT /api/entitlements/personas/{id}/groupspayload unchanged.comment-sidebar.tsx): audience gainsPrincipalPicker(multi, users+groups)alongside (not replacing) the existing Teams + App Roles checkbox lists. Picked users emit as plain emails, picked groups as plain group names;team:*/role:*tokens flow through unchanged. The round-trip is extracted intobuildAudienceTokens/parseAudienceTokens.Helpers added
lib/audience.ts—parseAudienceTokens(audience)/buildAudienceTokens(parsed)for the mixed-token round-trip.lib/assigned-groups.ts—normaliseAssignedGroups(raw)tolerates bothstring[]and legacy comma-string shapes.Test plan
yarn type-check).lib/audience.test.ts(6): split team:/role:/principal mix, defensive guards for null/empty/non-string, prefix-only tokens preserve their empty id, round-trip identity.lib/assigned-groups.test.ts(6): array passthrough, empty-string drop, comma-split + trim, trailing/repeated commas, nullish / non-string-non-array → [], empty string → [].role-form-dialog.test,team-form-dialog.test,project-form-dialog.test,tag-selector.testall skipped for the same Radix-in-jsdom reason). The new helpers cover the load-bearing data transforms.Acceptance criteria from the plan
assigned_groupsvia the picker; group-membership-based authorization unchanged (no backend changes).assigned_groupsrecords render and save without breakage (covered bynormaliseAssignedGroups).PUTbody shape.team:*+role:*) round-trips correctly; existing notification fan-out for team/role tokens unaffected (no backend changes; existing parsing in comment renderer preserved).