feat: full CRUD for user/identity -- admin delete, CLI/MCP parity (musehub#224)
Audit: user/identity was an outlier against this workspace's full Rails-style CRUD convention -- DELETE /api/me (GDPR self-delete) existed server-side with zero integration test coverage and no CLI/MCP wrapper; there was no way at all to delete an account that wasn't the caller's own, blocking cleanup of 3 throwaway agent identities from musehub#99 testing.
Investigation found clean precedent for everything this needed: - TokenClaims = MSignContext and require_valid_token = require_signed_request are literal aliases in musehub/auth/dependencies.py -- DELETE /api/me already uses MSign auth, same as every CLI-facing route. No auth-layer fix needed for a CLI wrapper (unlike orgs.py's separate, already-tracked MSign gap). - musehub/api/routes/api/admin.py already establishes the admin pattern: /api/admin/* routes gated by claims.is_admin on the same MSignContext. - POST /api/users (profile creation, distinct from identity/keypair registration via `muse auth register`) already existed server-side with zero CLI wrapper, alongside existing read/update.
Design decisions (confirmed via AskUserQuestion): - Admin delete: DELETE /api/admin/users/{handle}, gated by claims.is_admin, wired into the SAME `muse hub user delete --handle <other>` CLI subcommand rather than a separate admin namespace -- server already enforces admin-only, CLI just routes by whether --handle differs from the caller's own identity. - muse hub user create: added for CRUD symmetry, wrapping the existing POST /api/users endpoint.
Implementation: - New musehub/services/musehub_account.py::delete_identity_account -- shared by both DELETE /api/me (refactored to use it) and the new DELETE /api/admin/users/{handle}, so both paths apply the identical effect (hard-delete auth keys, soft-delete identity) and can never drift. - MCP parity: musehub_create_user_profile and musehub_delete_user_account tools, the latter doing its own is_admin check (MCP calls executor functions directly, bypassing the FastAPI auth dependency layer).
TDD: wrote tests/test_account_deletion.py (self-delete regression coverage that never existed, + 4 new admin-delete tests: success, 403 non-admin, 404 unknown handle, 404 already-deleted handle) and tests/test_mcp_user_account_tools.py (7 tests for the new MCP tools) first. Confirmed genuine RED via muse-dev shelf save/pop isolation on both the HTTP/admin layer and the MCP layer. Also added CLI-side RED tests in muse's tests/test_cli_hub.py (command-construction tests mirroring the existing read/update pattern) before implementing run_user_create/ run_user_delete.
Regression: 188 passed across admin/identity/mcp/compliance/forks test files in musehub; 110 passed in muse's test_cli_hub.py.
Documented both paths in muse/docs/agent-guide.md (Gitism Glossary + Users/topics/forks command reference), per this ticket's own acceptance criteria.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Semantic Changes
77 symbols
Files Changed
+3
~5
1105 in snapshot
0 comments
muse hub commit comment sha256:cb80b9ff286cfe86683166a3a87b9e154cbd890cc4f53071288633672e7df333 --body "your comment"
No comments yet. Be the first to start the discussion.