gabriel / musehub public
feat BREAKING #143 feat/143-proposal-comment-delete #1 / 1
AI Agent gabriel · 7 hours ago · Sep 9, 2026 · Diff

feat(#143): wire is_deleted end-to-end for proposal comments

Child of #141 (framework-wide CRUD/delete idiom). MusehubProposalComment already had an is_deleted column with nothing using it -- no delete endpoint, no CLI command. Mirrors the existing, working issue-comment delete pattern (musehub_issues.delete_comment / DELETE /repos/{id}/issues/{n}/comments/{id}), plus the --hard flag and --include-deleted list convention #141 calls for, neither of which existed anywhere in the codebase yet -- this is their first implementation.

Server: - musehub_proposals.delete_comment(session, comment_id, proposal_id, hard=False) -- soft-delete (sets is_deleted) by default; hard=True actually removes the row. - musehub_proposals.list_proposal_comments gained include_deleted (default False, matching existing behavior). - DELETE /repos/{repo_id}/proposals/{proposal_id}/comments/{comment_id} -- soft-delete requires owner or write/admin collaborator (_guard_repo_owner, same guard as comment creation's state-changing actions). ?hard=true requires the stricter owner-or-admin-collaborator check (_guard_admin, imported from repos.py) per #141's 'gated to owner/admin' framework-wide convention. - GET .../comments?include_deleted=true requires the same _guard_repo_owner check (403 for anyone without write access), since showing soft-deleted content is an audit-log capability, not a public read.

6 new tests: soft-delete excludes from list but not include_deleted=true; hard-delete actually removes the row (verified via direct DB query); 404 on a nonexistent comment; 403 for a non-owner/non-collaborator; and the key differential-guard test -- a write (non-admin) collaborator can soft-delete but is correctly rejected from hard-delete. 229 tests across proposals/collaborators/authz-sweep/mcp-write-tools pass with zero regressions.

CLI wiring (muse hub proposal comment delete/--include-deleted) is a companion change in the muse repo, committed separately.

sha256:52ab8032b6bf2313b627a3d858051072dfd3f21f5f2d79bee113928f12510f99 sha
+9 ~2 symbols
sha256:7a4a5998c3c13b571025ce1e9430198afacd7ef434065521abe0eb2e97f6dd08 snapshot
+9
symbols added
~2
symbols modified
0
dead code introduced
Semantic Changes 11 symbols
+ docs/
+ src/
+ tests/
+ tools/
~ musehub/api/routes/musehub/proposals.py .py 2 symbols added, 1 symbol modified
+ delete_proposal_comment function async_function delete_proposal_comment L805–841
+ _guard_admin import import _guard_admin L34–34
~ musehub/services/musehub_proposals.py .py 1 symbol added, 1 symbol modified
+ delete_comment function async_function delete_comment L1267–1297
~ tests/test_musehub_proposals.py .py 6 symbols added
+ _create_comment function async_function _create_comment L1712–1725
+ test_delete_proposal_comment_forbidden_for_non_owner function async_function test_delete_proposal_comment_forbidden_for_non_owner L1808–1835
+ test_delete_proposal_comment_hard_delete_removes_row function async_function test_delete_proposal_comment_hard_delete_removes_row L1760–1789
+ test_delete_proposal_comment_not_found_returns_404 function async_function test_delete_proposal_comment_not_found_returns_404 L1792–1805
+ test_delete_proposal_comment_soft_delete_excludes_from_list function async_function test_delete_proposal_comment_soft_delete_excludes_from_list L1728–1757
+ test_hard_delete_forbidden_for_write_collaborator_but_soft_delete_allowed function async_function test_hard_delete_forbidden_for_write_collaborator_but_soft_delete_allowed L1838–1910
← Older Oldest on feat/143-proposal-comment-delete
All commits
Newer → Latest on feat/143-proposal-comment-delete

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:52ab8032b6bf2313b627a3d858051072dfd3f21f5f2d79bee113928f12510f99 --body "your comment"