docs: private boolean hasUnblockedPathToGrant(
              IAuthorizationService service,
              IAuthorizationPrincipal principal,
              IPermissionOwner owner,
              IPermissionActivity activity,
              IPermissionTarget target,
              Set<IGroupMember> seenGroups)
              throws GroupsException {
  
          if (log.isTraceEnabled()) {
              log.trace(
                      "Searching for unblocked path to GRANT for principal '{}' to "
                              + "'{}' on target '{}' having already checked:  {}",
                      principal.getKey(),
                      activity.getFname(),
                      target.getKey(),
                      seenGroups);
          }
  
          /*
           * Step #1:  Specific GRANT/DENY attached to this principal
           */
          final IPermission[] permissions =
                  service.getPermissionsForPrincipal(
                          principal, owner.getFname(), activity.getFname(), target.getKey());
  
          final Set<IPermission> activePermissions = removeInactivePermissions(permissions);
          final boolean denyExists =
                  containsType(activePermissions, IPermission.PERMISSION_TYPE_DENY);
          if (denyExists) {
              // We need go no further;  DENY trumps both GRANT & inherited permissions
              return false;
          }
          final boolean grantExists =
                  containsType(activePermissions, IPermission.PERMISSION_TYPE_GRANT);
          if (grantExists) {
              // We need go no further;  explicit GRANT at this level of the hierarchy
              if (log.isTraceEnabled()) {
                  log.trace(
                          "Found unblocked path to this permission set including a GRANT:  {}",
                          activePermissions);
              }
              return true;
          }
  
          /*
           * Step #2:  Seek an answer from affiliated groups
           */
          IGroupMember principalAsGroupMember = service.getGroupMember(principal);
          if (seenGroups.contains(principalAsGroupMember)) {
              if (log.isTraceEnabled()) {
                  log.trace(
                          "Declining to re-examine principal '{}' for permission to '{}' "
                                  + "on '{}' because this group is among already checked groups:  {}",
                          principal.getKey(),
                          activity.getFname(),
                          target.getKey(),
                          seenGroups);
              }
              return false;
          }
          seenGroups.add(principalAsGroupMember);
          Set<IEntityGroup> immediatelyContainingGroups = principalAsGroupMember.getParentGroups();
          for (IGroupMember parentGroup : immediatelyContainingGroups) {
              try {
                  if (parentGroup != null) {
                      IAuthorizationPrincipal parentPrincipal = service.newPrincipal(parentGroup);
                      boolean parentHasUnblockedPathToGrant =
                              hasUnblockedPathToGrantWithCache(
                                      service, parentPrincipal, owner, activity, target, seenGroups);
                      if (parentHasUnblockedPathToGrant) {
                          return true;
                      }
                      // Parent didn't have a path to grant, fall through and try another parent (if
                      // any)
                  }
              } catch (Exception e) {
                  // problem evaluating this path, but let's not let it stop
                  // us from exploring other paths.  Though a portion of the
                  // group structure is broken, permission may be granted by
                  // an unbroken portion
                  log.error("Error evaluating permissions of parent group [" + parentGroup + "]", e);
              }
          }
  
          /*
           * Step #3:  No explicit GRANT means no permission
           */
          return false;
      }