MILAB-6761: add pl-cli admin delete-user - #1795
Draft
blackcat wants to merge 1 commit into
Draft
Conversation
Multi-provider auth can hand one person two accounts. The spare showed up in
the sharing user picker and its projects kept taking part in deduplication,
and no shipped tool removed one — the migration guide said as much.
`admin delete-user <user>` now does, over the new AuthAPI.DeleteUser RPC.
When the account still owns projects it requires an explicit decision rather
than picking a default, because both defaults are wrong to assume — one
silently destroys data, the other silently hands it to someone:
--move-projects-to <user> re-attach every project to another user's root,
then delete the account
--delete-projects delete the projects with the account
The move is a move, not a copy: the same project resources are re-homed, so
nothing is duplicated and nothing needs re-verifying. This works across roots
because the backend allows a reference between differently coloured resources
when the caller holds write access to both. A name the target already uses is
suffixed rather than overwritten, and the target's project list is created if
they never had one. The whole batch is one transaction.
Both forms prompt with the affected project list first; --force skips it.
pl-client gains PlClient.deleteUser (gRPC-only, like listUsers), and
pl-middle-layer exports ProjectsResourceType, which a caller writing into
another user's root needs.
🦋 Changeset detectedLatest commit: fd0ae2c The changes in this PR will be included in the next version bump. This PR includes changesets to release 10 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
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.
Ticket: MILAB-6761
Backend PR: milaboratory/pl#2157 (needs to land first — the RPC this drives is new)
Why
Multi-provider auth can hand one person two accounts. The spare showed up in the sharing user picker and its projects kept taking part in deduplication, and no shipped tool removed one.
What
pl-cli admin delete-user <user>, over the newAuthAPI.DeleteUserRPC. When the account still owns projects the command requires an explicit decision instead of picking a default, because both defaults are wrong to assume — one silently destroys data, the other silently hands it to someone:--move-projects-to <user>--delete-projectsPassing neither (with projects present) or both is an error. An account that owns nothing has no decision to make and deletes straight through.
The move is a move, not a copy: the same project resources are re-homed, so nothing is duplicated and nothing needs re-verifying — unlike the existing
admin copy-project+project deletepattern. This works across roots because the backend permits a reference between differently coloured resources when the caller holds write access to both, which admin credentials do. Details:X→X (Copy)) rather than overwritten, and two source projects sharing a name do not both keep it;Both forms prompt with the affected project list first;
--forceskips it for scripted runs.--format jsonemits a machine-readable report (moved/deleted projects, root id, grants revoked, index entries removed).Supporting changes
pl-client:PlClient.deleteUser(login)→UserDeletionReport, gRPC-only likelistUsers. The report carries the root id as a rawbigintrather than aSignedResourceId— the resource is gone, so it is for the audit line, not for further calls.pl-middle-layer: exportsProjectsResourceType, which a caller writing into another user's root needs (ensureProjectListRidonly works ontx.clientRoot).project_ops.ts:moveProjects,listProjectIdentities(listProjectsomits the field name a re-home needs),openUserRoot(a missing project list is a legitimate state for a whole-account operation, not an error) andensureUserProjectList.User "x" not found on this server.instead of surfacing the backend'suser root not found, which reads as a missing resource rather than a missing user.Proto sync
The
DeleteUsermessages were applied surgically tolib/node/pl-client/proto/, not viasync-proto.sh. A full resync would have pulled unrelated in-flight backend proto changes (tree since-token work) into this PR. The local copy therefore stays behindpl@mainon those messages until someone runs a proper resync — worth doing once the backend PR lands.Testing
Verified end-to-end against a backend built from the companion branch, with three htpasswd users and an admin:
NG:0x8f,NG:0x90), the colliding name deduped toShared Name (Copy), alice gone fromadmin user-list, bob's own project untouched;RG:0x93vs the oldRG:0x89— a fresh identity, which is the point of the ticket;types:check,linter:check,formatter:checkandbuildclean on all three touched packages.pl-client's 100 integration tests pass against a live backend.