- Add StringNormalizer.normalize() (trim + toLowerCase ROOT) for username normalization
- Migrate SystemAdministratorService private normalize() to use StringNormalizer.normalize()
- Remove now-unused Locale import from SystemAdministratorService
- Add StringNormalizerTest coverage for new normalize() method
- Add SystemAdministratorServiceTest with 10 unit tests covering all public methods
- Replace JsonSupport inner class (AtomicReference lazy singleton) with simple static final ObjectMapper field
- Replace TODO code-smell comments in TwitchEmoteService, SevenTvEmoteService, and MarketplaceScriptSeedLoader with descriptive Javadoc
- Use normalize() consistently in ChannelDirectoryService.topicFor()
- Extract admin endpoint group (add/remove/list admins, suggestions) into dedicated ChannelAdminApiController
- ChannelApiController reduced from 665 to 520 lines; removes 3 dependency injections
- ChannelDirectoryService: extract resolveOrderForSort() helper from bulk-reorder comparator lambda
- Remove TODO comment from ChannelApiController (partially addressed by this split)
- Add AssetPatch.forOrder() and simplify AssetPatch.fromVisibility() factory
- Replace null-chain AssetPatch constructors in ChannelDirectoryService with forOrder()
- Extract OAuthTokenCipher.buildFromKeys() to deduplicate two fromEnvironment() overloads
- Replace inline upload-size guards in createAsset/createScriptAttachment with enforceUploadLimit()
- Make script attachment content endpoint public for all channels (not just hard-coded 'gasolinebased')
- Extract StringNormalizer.toLowerCaseRoot() utility and use it in ChannelDirectoryService/ChannelSettingsService