Repository navigation
feat(people): register people before login and expose role assignment dates - #75
Conversation
People reads who holds its bound roles from GET /api/internal/people-roles on every operation instead of keeping a copy, so it needs this IdP to say when each role started: since maps every held bound role to the date (YYYY-MM-DD, UTC) of the earliest assignment that confers it, directly or through a parent role.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
Keep preliminary identities and declared contacts in Auth without credentials or provider accounts. Offer verified identity and name-only review proposals; require Master Admin approval to transfer current bound roles to a real login account while preserving provider accounts and existing roles. Add the preliminary-person migration and idempotent creation, contact editing and linking commands, with PostgreSQL and matching coverage.
|
For the record: we're not going ahead with the preliminary-person model from this PR. It will be removed from #73's branch by resetting it to Why:
Instead, people without a linked account stay in the backend with their pending assignments. Linking happens only through an email invite (any account can accept it) or by hand with a new If you want to keep anything from here, the per-role assignment date ( |
…d and drop Soci Rework of #73 for #78, after dropping #75's preliminary people. - Add the `capo` binding for Capo Admins: pattern, check constraint, parser and `{ kind: "capo", active }` commands. Appointing or ending one needs `admin:access` + `people:appoint`; `capo-admin` inherits `admin`, so `people:write` is required too. - Binding a role to People needs the new managed permission `idp:people:bind` (always implies `idp:roles:read`) instead of Master Admin, bounded like role edits: only Master Admin binds a role granting permissions they don't hold. The role page card and the MCP tool follow it. - Restructure delegation as one rule per binding kind (`PEOPLE_RULES`), so a later "Capo Admins manage their admins" rule is a local change. - `GET /api/internal/people-roles` lists only holders of bound roles: no Microsoft 365 accounts or `azureId`. It reports `since` per held role. - README: People roles and the deployment steps from #79. Folded into the unreleased migration 0023. Closes #78
* feat(rbac): let People manage bound roles through the backend
Master Admin can bind a hand-made role to the admin dashboard's People
register (admin, team:<key>:member, team:<key>:lead) on its page. Roles
carrying idp:* permissions can't be bound, and role or permission saves
that would give a bound role one are refused.
- GET /api/internal/people-roles (backend client, idp:access:read) lists
the bound roles and their holders with name, directory email and
Telegram, including roles that grant no permission.
- POST /api/internal/people-roles (backend client, new scope
idp:people:roles) gives or takes back a bound role on behalf of the
dashboard user the backend authenticated. This IdP resolves the actor's
own access: no self-grants, people:write (or leading the team) for
admin and member roles, people:appoint for Leads, admin:access, and
bounded delegation unless Master Admin. Audited with via: "people".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(mcp): bind roles to People from an agent
Master Admin can call set_role_people_binding, so an agent connected to
the MCP server can set up People roles end to end alongside
create_permission, create_role and assign_role.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(rbac): refuse unknown People actors and skip audits for no-op changes
- An unknown actor got a 500 from the membership refresh; it is now the
intended 403.
- A People change that alters nothing (already held, or held only
through a parent role) no longer writes an audit row claiming it did.
- The directory says which bound roles each holder was given directly,
the only ones a change can take back.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(rbac)!: apply People role commands atomically and idempotently
People now sends one command per person with the desired state of each
changed concept. Auth plans the concrete assignments against its own graph,
checks the actor for every one of them before writing, and applies all or
none. A command that would leave the requested state held through another
role is refused with 409 instead of reporting a revocation that never
happened. The command is stored as a `people.roles` audit receipt, so a
retry after a lost response applies nothing again and returns the current
roles.
The actor check now covers every bound role a role inherits, so a member
role wrapping a Lead role needs people:appoint.
The People directory also lists accounts with a PoliNetwork Microsoft 365
login and their object ID, so People can match Microsoft 365 members to
linked accounts without relying on an address.
BREAKING CHANGE: POST /api/internal/people-roles takes
`{ id, actor, sub, reason, changes }` and answers with the person's bound
roles, instead of `{ actor, sub, role, action, reason }` and 204. Deploy
before the backend.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(people)!: bind Capo Admins, delegate binding with idp:people:bind and drop Soci
Rework of #73 for #78, after dropping #75's preliminary people.
- Add the `capo` binding for Capo Admins: pattern, check constraint, parser and
`{ kind: "capo", active }` commands. Appointing or ending one needs
`admin:access` + `people:appoint`; `capo-admin` inherits `admin`, so
`people:write` is required too.
- Binding a role to People needs the new managed permission `idp:people:bind`
(always implies `idp:roles:read`) instead of Master Admin, bounded like role
edits: only Master Admin binds a role granting permissions they don't hold.
The role page card and the MCP tool follow it.
- Restructure delegation as one rule per binding kind (`PEOPLE_RULES`), so a
later "Capo Admins manage their admins" rule is a local change.
- `GET /api/internal/people-roles` lists only holders of bound roles: no
Microsoft 365 accounts or `azureId`. It reports `since` per held role.
- README: People roles and the deployment steps from #79.
Folded into the unreleased migration 0023.
Closes #78
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Tommaso Morganti <tommaso.morganti01@gmail.com>
People can register a person in Auth before their first login, using only first and last name, optional contacts, and initial bound admin/team roles. Auth remains the authority for identity details and role assignments. This extends #73 and supports PoliNetworkOrg/backend#99 and PoliNetworkOrg/admin#136.
0024_people_registration.sqlstores declared contacts separately from verified provider evidence. The preliminary Auth subject has no credentials, provider accounts or sessions, and is excluded from the login-account/signing picker.create-person,update-personandlink-personcommands. Creation/contact editing requireadmin:accessandpeople:write; every role assignment still passes the original delegation checks. Reused IDs with changed input are refused.users[].since, the earliest assignment date conferring each held bound role, including inheritance.Validation: check, typecheck, all tests and production build/bundle validation passed. 352 tests passed and 117 were skipped, with the People role PostgreSQL suite enabled on a disposable migrated database. New coverage checks contact matching, ambiguity, no pre-login provider account, idempotent creation, rejected non-Master linking, Master approval and canonical directory identity.
Merge into #73 first. Deploy Auth and apply migration 0024 before the matching backend/dashboard feature. Keep the People role bindings and backend
idp:people:rolesscope configured. Other integration suites requiring their own external configuration remain skipped; no production mutation or real-provider sign-in was performed.