gabriel / musehub public
feat BREAKING feat/repo-crud-security #2 / 2
gabriel · 166 days ago · Apr 13, 2026 · Diff

feat: musehub_get_repo + musehub_list_repos with security, tests, timeout harness

- Add execute_get_repo with visibility enforcement (no existence oracle for private repos) - Add execute_list_repos with correlated subquery (fixes scalar_subquery IN-clause bug) - Add default_branch, updated_at, pushed_at to RepoResponse + _to_repo_response - Add TestGetRepoVisibilityEnforcement (8 tests) + TestListReposComprehensive (8 tests) - Fix test_repository_service + test_musehub_ui_jsonld: add required updated_at to RepoResponse fixtures - Fix test_mcp_read_tools: test_get_repo_private_accessible_by_owner passes actor=owner - Add pytest-timeout (60s) to prevent frozen test sessions - Expand test_canary: schema completeness, TRUNCATE coverage, session wiring - Add muse hub repo delete <OWNER/SLUG|UUID> positional arg (ergonomics fix)

sha256:a08918df78ac2599513bb0ea60061f27db66f97130d0523b834386f9620bb1bd sha
+38 ~30 symbols
sha256:8833263085930a7c210c1eb86cd54512321acc57fefb7ce5ee9bc82e7aa54f9e snapshot
+38
symbols added
~30
symbols modified
0
dead code introduced
Semantic Changes 68 symbols
~ musehub/mcp/dispatcher.py .py 1 symbol modified
~ musehub/models/musehub.py .py 1 symbol modified
~ pyproject.toml .toml 7 symbols modified
~ requirements.txt .txt 1 symbol modified
~ tests/test_canary.py .py 20 symbols added, 1 symbol modified
+ TestDBReachable class class TestDBReachable L23–34
+ test_connection method async_method test_connection L26–28
+ test_postgres_version method async_method test_postgres_version L30–34
+ TestSchemaComplete class class TestSchemaComplete L37–68
+ test_all_orm_tables_exist method async_method test_all_orm_tables_exist L40–52
+ test_no_orphan_db_tables method async_method test_no_orphan_db_tables L54–68
+ TestSessionWiring class class TestSessionWiring L128–151
+ test_asyncsessionlocal_uses_test_engine method async_method test_asyncsessionlocal_uses_test_engine L139–151
+ test_connected_to_test_database method async_method test_connected_to_test_database L131–137
+ TestTruncateCoverage class class TestTruncateCoverage L95–125
+ test_truncate_sql_covers_all_orm_tables method method test_truncate_sql_covers_all_orm_tables L108–125
+ TestTruncateIsolation class class TestTruncateIsolation L71–92
+ test_insert_is_visible_within_test method async_method test_insert_is_visible_within_test L74–83
+ test_previous_test_data_is_gone method async_method test_previous_test_data_is_gone L85–92
+ AsyncSession import import AsyncSession L14–14
+ Base import import Base L16–16
+ annotations import import annotations L9–9
+ pytest import import pytest L11–11
+ pytest_asyncio import import pytest_asyncio L12–12
+ text import import text L13–13
~ tests/test_mcp_read_tools.py .py 18 symbols added, 2 symbols modified
+ TestGetRepoVisibilityEnforcement class class TestGetRepoVisibilityEnforcement L1141–1245
+ test_private_repo_accessible_by_collaborator method async_method test_private_repo_accessible_by_collaborator L1174–1192
+ test_private_repo_accessible_by_owner method async_method test_private_repo_accessible_by_owner L1144–1152
+ test_private_repo_by_owner_slug_denied_to_non_owner method async_method test_private_repo_by_owner_slug_denied_to_non_owner L1223–1231
+ test_private_repo_denied_to_non_owner method async_method test_private_repo_denied_to_non_owner L1154–1162
+ test_private_repo_denied_to_pending_collaborator method async_method test_private_repo_denied_to_pending_collaborator L1194–1211
+ test_private_repo_denied_to_unauthenticated method async_method test_private_repo_denied_to_unauthenticated L1164–1172
+ test_public_repo_accessible_without_auth method async_method test_public_repo_accessible_without_auth L1213–1221
+ test_visibility_error_message_does_not_reveal_existence method async_method test_visibility_error_message_does_not_reveal_existence L1233–1245
+ TestListReposComprehensive class class TestListReposComprehensive L1248–1394
+ test_list_repos_cursor_is_stable_across_requests method async_method test_list_repos_cursor_is_stable_across_requests L1354–1369
+ test_list_repos_excludes_pending_collab method async_method test_list_repos_excludes_pending_collab L1272–1290
+ test_list_repos_excludes_soft_deleted method async_method test_list_repos_excludes_soft_deleted L1292–1307
+ test_list_repos_includes_collaboration_repos method async_method test_list_repos_includes_collaboration_repos L1251–1270
+ test_list_repos_limit_clamped_at_100 method async_method test_list_repos_limit_clamped_at_100 L1383–1394
+ test_list_repos_malformed_cursor_returns_first_page method async_method test_list_repos_malformed_cursor_returns_first_page L1371–1381
+ test_list_repos_pagination_stress method async_method test_list_repos_pagination_stress L1325–1352
+ test_list_repos_total_excludes_soft_deleted method async_method test_list_repos_total_excludes_soft_deleted L1309–1323
~ tests/test_musehub_ui_jsonld.py .py 1 symbol modified

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:a08918df78ac2599513bb0ea60061f27db66f97130d0523b834386f9620bb1bd --body "your comment"