Repository navigation
Closed
Feature
Copy link
Labels
peoplePeople: Group Admins, Capo Admins, Teams, Soci and census (see the People roadmap)People: Group Admins, Capo Admins, Teams, Soci and census (see the People roadmap)
Description
Context
#73 has the right core for Phase 1:
- the dashboard binds a role to a People meaning (
role.people_binding); - the backend reads who holds bound roles;
- the backend applies People role commands, and Auth checks every assignment against the actor's own access.
After #73 was approved, #75 was merged into #73's branch (not into main). It added:
- preliminary people, stored as
userrows with no credentials (migration0024_people_registration); - link proposals based on email, Telegram and name;
- Master Admin approval to link a preliminary person to an account, and to undo the link.
We're dropping #75. People who haven't linked an account live only in the backend. Why:
- We often don't know how someone will sign in: with Entra ID if they're a socio, otherwise with any Google account. The email and name we have may not match that account, so matching identities inside the IdP isn't reliable.
- Placeholder users have to be excluded everywhere else in the IdP (directory, signing picker, deletion, counts), and linking or unlinking has to move roles between subjects. That's a lot of security-sensitive IdP code for no benefit.
- It broke both ways of linking. In feat(people)!: manage Auth-backed people before and after their first login backend#99, invite acceptance and manual linking both send
link-personwith the invitee or the board member as the actor. Auth refuses unless the actor is Master Admin (src/auth/people-registration.ts:106on the branch), so both paths fail with 403.
The roadmap is PoliNetworkOrg/admin#146; Phase 1 is PoliNetworkOrg/admin#143.
Work
- Reset
feat/people-role-apitod698d3c. This dropsb57a858(feat(people): register people before login and expose role assignment dates #75) and the four commits after it:1d08a15,ce9dbc3,f48b750,b4360ef.- Migration
0024_people_registrationgoes away;0023_role_people_bindingstays. - Check the numbering against
mainbefore merging. feat(rbac): support inherited permission overrides #68 also wants a0022, andmainalready has0022_idp_mcp.
- Migration
- Remove Soci from
GET /api/internal/people-roles. Return only the bound roles and the people who hold them: name, directory email, Telegram ID and username.- Remove the list of "every PoliNetwork Microsoft 365 account, bound role or not" and the
azureIdfield. Soci isn't People's concern; Phase 2 will read Entra ID directly. - Optional: bring back the earliest assignment date per held bound role (
since, from feat(people): register people before login and expose role assignment dates #75) if the dashboard shows "admin since". Re-implement it on its own.
- Remove the list of "every PoliNetwork Microsoft 365 account, bound role or not" and the
- Add a
capobinding kind for Capo Admins. It needs the pattern, therole_people_binding_checkconstraint,parsePeopleBinding/describePeopleBindingsupport and the command planner.- Appointing or ending a Capo Admin needs
admin:access+people:appoint, like a Lead. capo-admininheritsadmin, so the existing inherited-binding check will also requirepeople:write. That's intended.
- Appointing or ending a Capo Admin needs
- Turn the Master Admin check on binding into a permission. Today only Master Admin can bind a role (
people-binding.ts, the People binding card and the MCP tool).- Add a managed permission, e.g.
idp:people:bind(impliesidp:roles:read), so the capability can be delegated like every other IdP admin right. - Master Admin keeps it implicitly.
- The Master Admin exception to bounded delegation in
peopleRoleChangeProblemcan stay, since Master Admin holds every permission anyway.
- Add a managed permission, e.g.
- Make the delegation rules easy to extend. Today they're an inline ternary in
peopleRoleChangeProblem. Restructure them as one rule per binding kind, saying who may assign and unassignadmin,capo,team:*:memberandteam:*:lead.- The goal: "a Capo Admin may add or remove the admins under them" should later be a small, local change. We are not building it now.
- Such a rule needs a scope Auth can verify (which admins are under which Capo). Don't design that now; just don't close the door. For example, keep the command format open to an optional context field.
- MCP:
set_role_people_bindingstays. Gate it with the new permission instead of Master Admin, and supportcapo. - README: update the deployment steps to match [People · Phase 1] Configure People role bindings in the production IdP #79.
Contract the backend relies on (unchanged from #73)
POST /api/internal/people-roles, internal scopeidp:people:roles.- Body:
{ id, actor, sub, reason, changes }. - Idempotent by
id, and applied all-or-nothing. - 409 when the mapping is ambiguous, or when the requested state would still be held through another role.
- Body:
- Auth works out the actor's access itself. It refuses:
- unbound roles;
- giving yourself a role;
- missing
people:write/people:appoint/ Lead of the team; - a role granting permissions the actor doesn't hold (bounded delegation).
subis always a real login account. There are no preliminary subjects.- When an invite is accepted, the backend sends the person who made the assignment as the actor, not the invitee, because Auth refuses self-grants. Auth needs no special case for this, but the tests should cover it. See [People · Phase 1] Link records to accounts by email invite or manually backend#102.
Notes
trusted-admininheritsadmin. People assignsadminandcapo;trusted-adminstays hand-assigned in Auth for now. Don't also bind it asadmin, or the planner answers 409 (ambiguous).- Roles that carry any
idp:*permission can't be bound. In production that rules outit-coreandit-lead. See [People · Phase 1] Configure People role bindings in the production IdP #79 for what to do about the IT team.
Done when
- feat(people)!: let People manage bound roles through the backend #73 contains only the above and is reviewed again. The current approval predates feat(people): register people before login and expose role assignment dates #75 being merged into the branch.
- Check, unit tests, the People PostgreSQL integration tests and the build pass.
Reacted by coderabbitai
Metadata
Metadata
Assignees
Labels
peoplePeople: Group Admins, Capo Admins, Teams, Soci and census (see the People roadmap)People: Group Admins, Capo Admins, Teams, Soci and census (see the People roadmap)
Activity
coderabbitai commentedon Oct 29, 2026
🔗 Related PRs
#73 - feat(rbac): let People manage bound roles through the backend [open]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
feat(people)!: bind Capo Admins, delegate binding with idp:people:bin…