Layering-rule violation found in a sweep against the "command → service → mapper" rule (CLAUDE.md). Not a functional bug — behaviour is correct; this is maintainability/tech-debt.
Two command handlers inject ApiKeyMapper directly instead of going through ApiKeyService for their read paths:
treasury-api-plugin/.../commands/PersonalKeyHandler.java (mapper injected at line 24) — apiKeyMapper.findByOwnerAndType() / findById() called directly in doList (49), doExport (68), doReissue (84), doRevoke (100).
treasury-api-plugin/.../commands/BusinessKeyHandler.java (mapper injected at line 24) — direct mapper calls in doList (60), doListAccess (79), doExport (98), doReissue (114), doRevoke (130), including findBusinessAccessibleByEmployee().
Fix: route these reads through ApiKeyService (add the missing query methods to the interface/impl) so the command handlers only depend on the service. Bind in the plugin's Guice module as usual.
Discovered alongside the CLAUDE.md layering-rules addition; filing for a later pass.