gabriel / musehub public
feat patch mists task/mist-phase3-db-models-service #1 / 1
gabriel · 163 days ago · Apr 15, 2026 · Diff

feat(mists): Phase 3 — DB model, Pydantic wire models, service layer, migration, and 81-test suite

- MusehubMist ORM class appended to musehub_models.py (25 columns, 4 composite indices, self-referential fork FK with SET NULL) - 7 Pydantic wire models in musehub/models/mists.py (MistResponse, MistListEntry, MistListResponse, MistCreateRequest, MistUpdateRequest, MistForkResponse, MistEmbedResponse) with validators for visibility, tags (XSS/null/length), and filename - 9 async service functions in musehub/services/musehub_mists.py: create, get, list (keyset pagination), fork (depth-limited to 5), update, delete, increment_view, increment_embed, get_forks - Alembic migration 0048 (down_revision=0047) - 81-test suite across 8 tiers: unit, integration, edge cases, stress, data integrity, performance, security, docstrings — all green

sha256:bf218c635e12eb3f5b298df0d3bac3026c510d6d21269fc2fbc8ebeb0d5d82c7 sha
+186 symbols
sha256:b9692d655419969ec3385210c76e436c5634ae1fa56af3e8a5e538bdbd24876b snapshot
+186
symbols added
0
dead code introduced
Semantic Changes 186 symbols
+ branch_labels variable variable branch_labels L28–28
+ depends_on variable variable depends_on L29–29
+ down_revision variable variable down_revision L27–27
+ downgrade function function downgrade L119–124
+ annotations import import annotations L21–21
+ op import import op L24–24
+ sa import import sa L23–23
+ revision variable variable revision L26–26
+ upgrade function function upgrade L32–116
~ musehub/models/mists.py .py 21 symbols added
+ MistCreateRequest class class MistCreateRequest L238–342
+ validate_filename method method validate_filename L321–342
+ validate_tags method method validate_tags L294–317
+ validate_visibility method method validate_visibility L276–290
+ MistEmbedResponse class class MistEmbedResponse L431–450
+ MistForkResponse class class MistForkResponse L397–423
+ MistListEntry class class MistListEntry L152–205
+ MistListResponse class class MistListResponse L213–230
+ MistResponse class class MistResponse L60–144
+ MistUpdateRequest class class MistUpdateRequest L350–389
+ validate_visibility method method validate_visibility L375–389
+ _MAX_CONTENT_BYTES variable variable _MAX_CONTENT_BYTES L52–52
+ _MAX_TAGS variable variable _MAX_TAGS L50–50
+ _MAX_TAG_LENGTH variable variable _MAX_TAG_LENGTH L51–51
+ _VALID_ARTIFACT_TYPES variable variable _VALID_ARTIFACT_TYPES L46–48
+ _VALID_VISIBILITY variable variable _VALID_VISIBILITY L49–49
+ CamelModel import import CamelModel L40–40
+ Field import import Field L38–38
+ annotations import import annotations L34–34
+ datetime import import datetime L36–36
+ field_validator import import field_validator L38–38
~ musehub/services/musehub_mists.py .py 28 symbols added
+ _FORK_DEPTH_LIMIT variable variable _FORK_DEPTH_LIMIT L57–57
+ _count_mists function async_function _count_mists L150–164
+ _to_mist_list_entry function function _to_mist_list_entry L112–147
+ _to_mist_response function function _to_mist_response L69–109
+ _utc_now function function _utc_now L60–66
+ create_mist function async_function create_mist L172–267
+ delete_mist function async_function delete_mist L533–563
+ fork_mist function async_function fork_mist L371–471
+ get_mist function async_function get_mist L270–289
+ get_mist_forks function async_function get_mist_forks L607–633
+ AsyncSession import import AsyncSession L41–41
+ MistForkResponse import import MistForkResponse L44–44
+ MistListEntry import import MistListEntry L44–44
+ MistListResponse import import MistListResponse L44–44
+ MistResponse import import MistResponse L44–44
+ annotations import import annotations L35–35
+ datetime import import datetime L38–38
+ db import import db L43–43
+ func function import func L40–40
+ logging import import logging L37–37
+ select import import select L40–40
+ timezone import import timezone L38–38
+ update import import update L40–40
+ increment_mist_embed function async_function increment_mist_embed L587–604
+ increment_mist_view function async_function increment_mist_view L566–584
+ list_mists function async_function list_mists L292–368
+ logger variable variable logger L51–51
+ update_mist function async_function update_mist L474–530
~ tests/test_mist_models_service.py .py 127 symbols added
+ TestDataIntegrity class class TestDataIntegrity L993–1070
+ test_counters_independent_per_mist method async_method test_counters_independent_per_mist L1008–1021
+ test_fork_count_multi method async_method test_fork_count_multi L1043–1061
+ test_fork_inherits_parent_visibility method async_method test_fork_inherits_parent_visibility L1024–1040
+ test_total_decrements_after_delete method async_method test_total_decrements_after_delete L997–1005
+ test_update_tags_replaces_list method async_method test_update_tags_replaces_list L1064–1070
+ TestDocstrings class class TestDocstrings L1196–1248
+ test_fork_depth_limit_constant method method test_fork_depth_limit_constant L1246–1248
+ test_orm_model_has_expected_columns method method test_orm_model_has_expected_columns L1234–1244
+ test_orm_model_has_tablename method method test_orm_model_has_tablename L1231–1232
+ test_pydantic_models_have_docstrings method method test_pydantic_models_have_docstrings L1216–1229
+ test_service_functions_have_docstrings method method test_service_functions_have_docstrings L1199–1214
+ TestEdgeCases class class TestEdgeCases L816–925
+ test_create_empty_tags_stored_as_list method async_method test_create_empty_tags_stored_as_list L901–904
+ test_create_with_secret_visibility method async_method test_create_with_secret_visibility L907–913
+ test_duplicate_mist_id_raises_integrity_error method async_method test_duplicate_mist_id_raises_integrity_error L820–841
+ test_fork_depth_limit_enforced method async_method test_fork_depth_limit_enforced L844–873
+ test_list_bad_cursor_ignored method async_method test_list_bad_cursor_ignored L891–898
+ test_mist_list_entry_primary_symbol_from_anchors method async_method test_mist_list_entry_primary_symbol_from_anchors L916–925
+ test_update_content_twice_increments_version_twice method async_method test_update_content_twice_increments_version_twice L876–888
+ TestIntegrationCounters class class TestIntegrationCounters L745–777
+ test_increment_embed_count method async_method test_increment_embed_count L762–771
+ test_increment_nonexistent_noop method async_method test_increment_nonexistent_noop L774–777
+ test_increment_view_count method async_method test_increment_view_count L749–759
+ TestIntegrationCreate class class TestIntegrationCreate L342–433
+ test_create_defaults method async_method test_create_defaults L383–399
+ test_create_returns_mist_response method async_method test_create_returns_mist_response L402–407
+ test_create_stores_all_fields method async_method test_create_stores_all_fields L346–380
+ test_create_symbol_anchors_stored method async_method test_create_symbol_anchors_stored L425–433
+ test_create_with_base_url method async_method test_create_with_base_url L410–422
+ TestIntegrationDelete class class TestIntegrationDelete L715–742
+ test_delete_non_owner_fails method async_method test_delete_non_owner_fails L730–737
+ test_delete_not_found_returns_false method async_method test_delete_not_found_returns_false L740–742
+ test_delete_own_mist method async_method test_delete_own_mist L719–727
+ TestIntegrationFork class class TestIntegrationFork L547–642
+ test_fork_creates_linked_copy method async_method test_fork_creates_linked_copy L551–567
+ test_fork_increments_depth method async_method test_fork_increments_depth L614–630
+ test_fork_increments_source_fork_count method async_method test_fork_increments_source_fork_count L570–586
+ test_fork_inherits_content method async_method test_fork_inherits_content L589–611
+ test_fork_nonexistent_returns_none method async_method test_fork_nonexistent_returns_none L633–642
+ TestIntegrationForkList class class TestIntegrationForkList L780–808
+ test_forks_of_original method async_method test_forks_of_original L784–801
+ test_no_forks_returns_empty method async_method test_no_forks_returns_empty L804–808
+ TestIntegrationGet class class TestIntegrationGet L436–459
+ test_get_existing method async_method test_get_existing L440–446
+ test_get_not_found method async_method test_get_not_found L449–451
+ test_get_with_base_url method async_method test_get_with_base_url L454–459
+ TestIntegrationList class class TestIntegrationList L462–544
+ test_list_artifact_type_filter method async_method test_list_artifact_type_filter L498–506
+ test_list_by_owner method async_method test_list_by_owner L466–476
+ test_list_global_explore method async_method test_list_global_explore L523–531
+ test_list_newest_first method async_method test_list_newest_first L534–544
+ test_list_pagination_next_cursor method async_method test_list_pagination_next_cursor L509–520
+ test_list_secret_hidden_by_default method async_method test_list_secret_hidden_by_default L479–486
+ test_list_secret_visible_when_owner method async_method test_list_secret_visible_when_owner L489–495
+ TestIntegrationUpdate class class TestIntegrationUpdate L645–712
+ test_update_content_increments_version method async_method test_update_content_increments_version L671–680
+ test_update_non_owner_returns_none method async_method test_update_non_owner_returns_none L683–690
+ test_update_none_fields_unchanged method async_method test_update_none_fields_unchanged L700–712
+ test_update_not_found_returns_none method async_method test_update_not_found_returns_none L693–697
+ test_update_title method async_method test_update_title L649–657
+ test_update_visibility method async_method test_update_visibility L660–668
+ TestPerformance class class TestPerformance L1078–1104
+ test_get_100_times_under_500ms method async_method test_get_100_times_under_500ms L1095–1104
+ test_list_50_mists_under_500ms method async_method test_list_50_mists_under_500ms L1082–1092
+ TestSecurity class class TestSecurity L1112–1188
+ test_delete_by_non_owner_rejected method async_method test_delete_by_non_owner_rejected L1129–1135
+ test_fork_depth_limit_prevents_deep_chain method async_method test_fork_depth_limit_prevents_deep_chain L1146–1175
+ test_secret_mist_hidden_from_explore method async_method test_secret_mist_hidden_from_explore L1138–1143
+ test_secret_visible_only_with_include_secret method async_method test_secret_visible_only_with_include_secret L1178–1188
+ test_update_by_non_owner_rejected method async_method test_update_by_non_owner_rejected L1116–1126
+ TestStress class class TestStress L933–985
+ test_create_50_mists method async_method test_create_50_mists L937–944
+ test_five_level_fork_chain method async_method test_five_level_fork_chain L947–967
+ test_list_pagination_covers_all_pages method async_method test_list_pagination_covers_all_pages L970–985
+ TestUnitPydanticModels class class TestUnitPydanticModels L159–261
+ test_mist_create_request_minimal method method test_mist_create_request_minimal L206–211
+ test_mist_embed_response_fields method method test_mist_embed_response_fields L234–242
+ test_mist_fork_response_fields method method test_mist_fork_response_fields L219–232
+ test_mist_list_entry_primary_symbol_none method method test_mist_list_entry_primary_symbol_none L184–198
+ test_mist_list_response_defaults method method test_mist_list_response_defaults L200–204
+ test_mist_response_camel_alias method method test_mist_response_camel_alias L244–261
+ test_mist_response_required_fields method method test_mist_response_required_fields L162–182
+ test_mist_update_request_all_none method method test_mist_update_request_all_none L213–217
+ TestUnitValidators class class TestUnitValidators L264–334
+ test_filename_null_byte_rejected method method test_filename_null_byte_rejected L324–326
+ test_filename_path_separator_rejected method method test_filename_path_separator_rejected L320–322
+ test_filename_traversal_rejected method method test_filename_traversal_rejected L316–318
+ test_tag_html_special method method test_tag_html_special L299–306
+ test_tag_null_byte method method test_tag_null_byte L291–297
+ test_tag_too_long method method test_tag_too_long L283–289
+ test_tag_valid method method test_tag_valid L308–314
+ test_too_many_tags method method test_too_many_tags L275–281
+ test_update_visibility_invalid method method test_update_visibility_invalid L328–330
+ test_update_visibility_none_allowed method method test_update_visibility_none_allowed L332–334
+ test_visibility_invalid method method test_visibility_invalid L267–269
+ test_visibility_valid_values method method test_visibility_valid_values L271–273
+ _OTHER variable variable _OTHER L88–88
+ _OWNER variable variable _OWNER L87–87
+ _mist function async_function _mist L120–151
+ _mist_id function function _mist_id L95–97
+ _repo function async_function _repo L100–117
+ _uid function function _uid L91–92
+ AsyncSession import import AsyncSession L59–59
+ IntegrityError import import IntegrityError L58–58
+ MistCreateRequest import import MistCreateRequest L62–62
+ MistEmbedResponse import import MistEmbedResponse L62–62
+ MistForkResponse import import MistForkResponse L62–62
+ MistListEntry import import MistListEntry L62–62
+ MistListResponse import import MistListResponse L62–62
+ MistResponse import import MistResponse L62–62
+ MistUpdateRequest import import MistUpdateRequest L62–62
+ MusehubMist import import MusehubMist L61–61
+ MusehubRepo import import MusehubRepo L61–61
+ annotations import import annotations L52–52
+ create_mist import import create_mist L71–71
+ delete_mist import import delete_mist L71–71
+ fork_mist import import fork_mist L71–71
+ get_mist import import get_mist L71–71
+ get_mist_forks import import get_mist_forks L71–71
+ increment_mist_embed import import increment_mist_embed L71–71
+ increment_mist_view import import increment_mist_view L71–71
+ list_mists import import list_mists L71–71
+ pytest import import pytest L57–57
+ time import import time L54–54
+ update_mist import import update_mist L71–71
+ uuid import import uuid L55–55
~ musehub/db/musehub_models.py .py 1 symbol added
+ MusehubMist class class MusehubMist L1130–1277
← Older Oldest on task/mist-phase3-db-models-service
All commits
Newer → Latest on task/mist-phase3-db-models-service

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