HorarioByIDQuery acota HorarioQuery a una sola matrícula; HorarioReader gana FetchByID reutilizando el scan de FetchAll, y rowReaderFor lo expone como /api/v1/sync/horario/upsert (mismo patrón que users). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>