Fix: don't expose internal logic