private void propagateRequirements(final @NonNull CommandNode<C> leafNode) {
        final Permission commandPermission = leafNode.command().commandPermission();
        Type senderType = leafNode.command().senderType().map(TypeToken::getType).orElse(null);
        if (senderType == null) {
            senderType = Object.class;
        }
        // Get chain and order it tail->head
        List<CommandNode<C>> chain = this.getChain(leafNode);
        Collections.reverse(chain);
        for (final CommandNode<C> commandArgumentNode : chain) {
            final Set<Type> senderTypes = commandArgumentNode.nodeMeta()
                    .computeIfAbsent(CommandNode.META_KEY_SENDER_TYPES, $ -> new HashSet<>());
            updateSenderRequirements(senderTypes, senderType);

            final Map<Type, Permission> accessMap = commandArgumentNode.nodeMeta()
                    .computeIfAbsent(CommandNode.META_KEY_ACCESS, $ -> new HashMap<>());
            updateAccess(accessMap, senderType, commandPermission);
        }
    }
Propagates permission and sender type requirements from the {@link Command} owning the {@code leafNode}'s component down
the tree, merging as is appropriate for nodes shared by multiple chains.

@param leafNode leafNode
cloud-core/src/main/java/org/incendo/cloud/CommandTree.java