I like the idea of providing callbacks via a naming convention
so have a proc like
callback namespace args
which would invoke all functions in the given namespace passing the given args.
In this case the callback would be something like:
callback ::acs_user::change_state $old_state $new_state
and you would define a function
::acs_user::change_state::dotlrn
to handle this stuff for dotlrn.
alternatively you could just have an nsv of callback name and list of functions to invoke but it makes tracking down the callbacks a little more annoying I think.