gabriel / musehub public
feat BREAKING task/musehub-117-phase1-schema-hardening #1 / 1
AI Agent gabriel · 19 days ago · Jul 2, 2026 · Diff

feat: schema-harden the domain publish path (musehub#117 Phase 1)

DOM_05: viewer_type is now a real enum (Literal['symbol_graph', 'piano_roll', 'generic']) instead of unvalidated free text. Dropped 'sequence_viewer' from the enum rather than keeping it as a documented- but-never-implemented dead value - the frontend never rendered it distinctly, only symbol_graph/piano_roll get real icon/color treatment today (see Phase 2 for building the real palette).

DOM_06: capabilities is now a real Pydantic model (DomainCapabilities/ DimensionSchema) instead of an unschema'd dict[str, PydanticJson]. merge_semantics is a fixed enum (ot|crdt|three_way); dimensions must be {name, description} objects, not arbitrary shapes. All fields default to safe empty values so the existing capabilities={} minimal-manifest case (used throughout the test suite) stays valid - only genuinely malformed input is rejected, with a specific 422 instead of a silent accept or a generic 500 further down the pipeline.

DOM_07: capabilities capped at 16 KB serialized and 50 dimensions - both generous for a real declarative manifest, both closing the unschema'd-JSON DoS surface that existed with no cap at all.

DOM_08: POST /api/domains rate limited (DOMAIN_REGISTER_LIMIT = 10/minute, mirroring the existing @limiter.limit pattern from wire.py).

10 new tests in test_domains.py covering each rejection case plus sanity checks that legitimate minimal/full manifests still succeed; DOMAIN_REGISTER_LIMIT added to test_rate_limiting.py's constants coverage. 76/76 in test_domains.py, 60/60 in test_rate_limiting.py, no regressions.

sha256:718975d3c370e58f13c9c213beaf5ab3fbb0e6f271af7ce22398d340ef85e55d sha
+26 ~16 −3 symbols
4 changed · 998 in snapshot files
sha256:be2ef0c3e7d86d18bab98e6ed4311494e8d3243f917103b0b762e763b78a9e6f snapshot
+26
symbols added
~16
symbols modified
−3
symbols removed
4
files changed
998
files in snapshot
0
dead code introduced
Semantic Changes 45 symbols
~ musehub/api/routes/musehub/domains.py .py 13 symbols added, 3 symbols removed, 7 symbols modified
_CapabilitiesMap variable variable _CapabilitiesMap L29–29
PydanticJson import import PydanticJson L27–27
unwrap_dict import import unwrap_dict L27–27
+ DimensionSchema class class DimensionSchema L52–56
+ DomainCapabilities class class DomainCapabilities L59–85
+ _check_serialized_size method method _check_serialized_size L79–85
+ MergeSemantics variable variable MergeSemantics L49–49
+ ViewerType variable variable ViewerType L47–47
+ _MAX_CAPABILITIES_BYTES variable variable _MAX_CAPABILITIES_BYTES L40–40
+ _MAX_DIMENSIONS variable variable _MAX_DIMENSIONS L41–41
+ DOMAIN_REGISTER_LIMIT import import DOMAIN_REGISTER_LIMIT L27–27
+ Field import import Field L21–21
+ Literal import import Literal L16–16
+ Request import import Request L18–18
+ limiter import import limiter L27–27
+ model_validator import import model_validator L21–21
~ Query
~ musehub/rate_limits.py .py 1 symbol added
+ DOMAIN_REGISTER_LIMIT variable variable DOMAIN_REGISTER_LIMIT L65–65
~ tests/test_domains.py .py 11 symbols added
+ TestDomainRegistrationRateLimit class class TestDomainRegistrationRateLimit L1172–1207
+ test_register_domain_429_after_limit_exceeded method async_method test_register_domain_429_after_limit_exceeded L1176–1207
+ TestDomainSchemaHardening class class TestDomainSchemaHardening L1009–1169
+ test_empty_capabilities_still_valid method async_method test_empty_capabilities_still_valid L1110–1127
+ test_invalid_merge_semantics_rejected_422 method async_method test_invalid_merge_semantics_rejected_422 L1074–1090
+ test_invalid_viewer_type_rejected_422 method async_method test_invalid_viewer_type_rejected_422 L1014–1031
+ test_malformed_dimensions_rejected_422 method async_method test_malformed_dimensions_rejected_422 L1092–1108
+ test_oversized_capabilities_rejected_422 method async_method test_oversized_capabilities_rejected_422 L1149–1169
+ test_sequence_viewer_rejected_422 method async_method test_sequence_viewer_rejected_422 L1033–1052
+ test_too_many_dimensions_rejected_422 method async_method test_too_many_dimensions_rejected_422 L1129–1147
+ test_valid_viewer_types_accepted method async_method test_valid_viewer_types_accepted L1054–1072
~ tests/test_rate_limiting.py .py 1 symbol added, 9 symbols modified
Files Changed
~4
998 in snapshot
← Older Oldest on task/musehub-117-phase1-schema-hardening
All commits
Newer → Latest on task/musehub-117-phase1-schema-hardening

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