I'm not sure, but I think you're not going about this entirely the right way.
The domain is the field your client works in, but what is most important is how they view that domain. There are a gazillion schools out there, but they don't all work the same. They don't all have the same rules, procedures or lingo.
So you have to find out how your client works: map out the behaviours. E.g. a student enrolls: what effect does this have across the entire school and all of its departments?
You also have to mark out where the same words start to have different meanings, because that's usually a sign you've found another bounded context. E.g. a student is something different to a teacher, than to the accounting department.
It's completely normal to have for example 2 student classes, with different or even the same properties in 2 bounded contexts. Focus on the behaviour, not the data; don't normalize prematurely.
If you have multiple bounded contexts, you generally want to be able to communicate between them. Most of the time, this is accomplished by sending domain events (e.g. StudentEnrolledInCourseEvent) over a message bus like RabbitMQ. You can then process these events on the other side however you wish.
If you have a map of the behaviours and marked different bounded contexts, you can start to look at what needs to be transactionally consistent; those groups will be your aggregates.
I can't think of a school related example right now, but consider a car with weels. You can control the wheels of the car through the api of the car, but not directly, because you want to avoid having one wheel pointing left and another weel pointing right.
Keep in mind that plenty of entities are aggregates on their own; not all aggregates are "nested" entities.
I hope this was of some help.