You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/03/03 13:53:52 UTC

[isis] 01/01: ISIS-2553: promote ApplicationFeatureId to applib

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch ISIS-2553_rational.id
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 15b79a43ef0d178f879b79a6e509a0f3571cc401
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Mar 3 14:53:32 2021 +0100

    ISIS-2553: promote ApplicationFeatureId to applib
    
    (still needs a lot of cleanup)
---
 .../services/appfeat/ApplicationFeatureId.java     | 172 +++++----------------
 .../appfeat/ApplicationFeatureRepository.java      |   5 +
 .../services/appfeat/ApplicationFeatureType.java   |  17 +-
 .../services/appfeat/ApplicationFeature.java       |   5 +-
 .../ApplicationFeatureRepositoryDefault.java       |  73 ++++-----
 .../core/metamodel/services/appfeat/_Asserts.java  |  50 ++++++
 .../metamodel/services/appfeat/_Predicates.java    |  50 ++++++
 .../metamodel/MetaModelServiceDefault.java         |   4 +-
 .../specloader/SpecificationLoaderDefault.java     |   2 +-
 .../services/appfeat/ApplicationFeatureIdTest.java |  14 +-
 .../ApplicationFeatureRepositoryDefaultTest.java   |   1 +
 .../services/appfeat/ApplicationFeatureTest.java   |   1 +
 .../appfeat/ApplicationFeatureTypeTest.java        |  48 +++---
 .../secman/api/authorizor/AuthorizorSecman.java    |   2 +-
 .../api/permission/ApplicationPermission.java      |   4 +-
 .../ApplicationPermissionRepository.java           |  14 +-
 .../api/permission/ApplicationPermissionValue.java |   2 +-
 .../permission/ApplicationPermissionValueSet.java  |   2 +-
 .../permission/PermissionsEvaluationService.java   |   2 +-
 .../PermissionsEvaluationServiceAbstract.java      |   2 +-
 .../secman/api/role/ApplicationRole.java           |   7 +-
 .../secman/model/app/feature/ApplicationClass.java |   2 +-
 .../model/app/feature/ApplicationClassAction.java  |   2 +-
 .../app/feature/ApplicationClassCollection.java    |   2 +-
 .../model/app/feature/ApplicationClassMember.java  |   2 +-
 .../app/feature/ApplicationClassProperty.java      |   2 +-
 .../app/feature/ApplicationFeatureViewModel.java   |   4 +-
 .../model/app/feature/ApplicationPackage.java      |   4 +-
 .../app/feature/ApplicationPermission_feature.java |   2 +-
 .../user/ApplicationUser_filterPermissions.java    |   6 +-
 .../app/user/ApplicationUser_permissions.java      |   4 +-
 .../model/app/user/UserPermissionViewModel.java    |   4 +-
 .../ApplicationOrphanedPermissionManager.java      |   9 +-
 ...OrphanedPermissionManager_relocateSelected.java |   2 +-
 .../permission/ApplicationPermission_allow.java    |   8 +-
 .../permission/ApplicationPermission_changing.java |   8 +-
 .../permission/ApplicationPermission_delete.java   |  10 +-
 .../ApplicationPermission_updateRole.java          |  12 +-
 .../dom/permission/ApplicationPermission_veto.java |  12 +-
 .../permission/ApplicationPermission_viewing.java  |  12 +-
 .../model/dom/role/ApplicationRole_addAction.java  |   8 +-
 .../model/dom/role/ApplicationRole_addClass.java   |   8 +-
 .../dom/role/ApplicationRole_addCollection.java    |   8 +-
 .../model/dom/role/ApplicationRole_addPackage.java |   8 +-
 ...ion.java => ApplicationRole_addPermission.java} |  89 +++++++----
 .../dom/role/ApplicationRole_addProperty.java      |   8 +-
 .../model/dom/role/ApplicationRole_addUser.java    |   8 +-
 .../dom/role/ApplicationRole_removePermission.java |  12 +-
 .../role/ApplicationRole_removePermissions.java    |   8 +-
 .../model/dom/role/ApplicationRole_removeUser.java |  10 +-
 .../dom/role/ApplicationRole_removeUsers.java      |   8 +-
 .../role/ApplicationRole_updateDescription.java    |  12 +-
 .../model/dom/role/ApplicationRole_updateName.java |  12 +-
 .../dom/tenancy/ApplicationTenancy_addChild.java   |   6 +-
 .../dom/tenancy/ApplicationTenancy_addUser.java    |   8 +-
 .../dom/tenancy/ApplicationTenancy_delete.java     |   4 +-
 .../tenancy/ApplicationTenancy_removeChild.java    |  12 +-
 .../dom/tenancy/ApplicationTenancy_removeUser.java |  12 +-
 .../dom/tenancy/ApplicationTenancy_updateName.java |  14 +-
 .../tenancy/ApplicationTenancy_updateParent.java   |   8 +-
 .../dom/tenancy/ApplicationTenancy_users.java      |   4 +-
 .../ApplicationUserManager_newDelegateUser.java    |   6 +-
 .../user/ApplicationUserManager_newLocalUser.java  |   6 +-
 .../model/dom/user/ApplicationUser_addRole.java    |  12 +-
 .../model/dom/user/ApplicationUser_delete.java     |   6 +-
 .../model/dom/user/ApplicationUser_duplicate.java  |   6 +-
 .../model/dom/user/ApplicationUser_lock.java       |  10 +-
 .../model/dom/user/ApplicationUser_removeRole.java |  12 +-
 .../dom/user/ApplicationUser_removeRoles.java      |   8 +-
 .../dom/user/ApplicationUser_resetPassword.java    |  10 +-
 .../model/dom/user/ApplicationUser_unlock.java     |   8 +-
 .../user/ApplicationUser_updateAccountType.java    |  10 +-
 .../dom/user/ApplicationUser_updateAtPath.java     |   8 +-
 .../user/ApplicationUser_updateEmailAddress.java   |  10 +-
 .../model/dom/user/ApplicationUser_updateName.java |  18 +--
 .../dom/user/ApplicationUser_updatePassword.java   |  18 +--
 .../user/ApplicationUser_updatePhoneNumber.java    |  10 +-
 .../dom/user/ApplicationUser_updateUsername.java   |   8 +-
 .../secman/model/dom/user/HasUsername_open.java    |  10 +-
 .../jdo/dom/permission/ApplicationPermission.java  |   4 +-
 .../ApplicationPermissionRepository.java           |  34 ++--
 .../secman/jdo/dom/user/ApplicationUser.java       |   2 +-
 .../AbstractRoleAndPermissionsFixtureScript.java   |   2 +-
 .../jpa/dom/permission/ApplicationPermission.java  |   4 +-
 .../ApplicationPermissionRepository.java           |  20 ++-
 .../secman/jpa/dom/user/ApplicationUser.java       |   2 +-
 .../AbstractRoleAndPermissionsFixtureScript.java   |   2 +-
 .../secman/shiro/PermissionForMember.java          |   2 +-
 88 files changed, 593 insertions(+), 506 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureId.java b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureId.java
similarity index 78%
rename from core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureId.java
rename to api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureId.java
index f6ce177..f465792 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureId.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureId.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.core.metamodel.services.appfeat;
+package org.apache.isis.applib.services.appfeat;
 
 import java.io.Serializable;
 import java.util.Collections;
@@ -24,7 +24,6 @@ import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.function.Function;
-import java.util.function.Predicate;
 
 import static java.util.Comparator.comparing;
 import static java.util.Comparator.naturalOrder;
@@ -33,7 +32,6 @@ import static java.util.Comparator.nullsFirst;
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Value;
-import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.applib.util.Equality;
 import org.apache.isis.applib.util.Hashing;
 import org.apache.isis.applib.util.ObjectContracts;
@@ -42,7 +40,9 @@ import org.apache.isis.applib.util.ToString;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 
+import lombok.Getter;
 import lombok.NonNull;
+import lombok.Setter;
 import lombok.val;
 
 /**
@@ -118,9 +118,7 @@ implements
     }
 
     public static ApplicationFeatureId newClass(final String classFqn) {
-        final ApplicationFeatureId featureId = new ApplicationFeatureId(ApplicationFeatureType.CLASS);
-        featureId.type.init(featureId, classFqn);
-        return featureId;
+        return new ApplicationFeatureId(ApplicationFeatureType.CLASS, classFqn);
     }
 
     public static ApplicationFeatureId newMember(final String classFqn, final String memberName) {
@@ -132,9 +130,7 @@ implements
     }
 
     public static ApplicationFeatureId newMember(final String fullyQualifiedName) {
-        final ApplicationFeatureId featureId = new ApplicationFeatureId(ApplicationFeatureType.MEMBER);
-        featureId.type.init(featureId, fullyQualifiedName);
-        return featureId;
+        return new ApplicationFeatureId(ApplicationFeatureType.MEMBER, fullyQualifiedName);
     }
 
     /**
@@ -151,10 +147,7 @@ implements
         return new ApplicationFeatureId(_Strings.base64UrlDecode(encodedString));
     }
 
-
-    // //////////////////////////////////////
-
-    // -- constructor
+    // -- CONSTRUCTOR
 
     private ApplicationFeatureId(final String asString) {
         final Iterator<String> iterator = _Strings.splitThenStream(asString, ":").iterator();
@@ -163,8 +156,8 @@ implements
     }
 
     /**
-     * Must be called by {@link ApplicationFeatureType#init(ApplicationFeatureId, String)} immediately afterwards
-     * to fully initialize.
+     * Must be called by {@link ApplicationFeatureType#init(ApplicationFeatureId, String)} 
+     * immediately afterwards to fully initialize.
      */
     ApplicationFeatureId(final ApplicationFeatureType type) {
         this.type = type;
@@ -174,11 +167,8 @@ implements
         type.init(this, fullyQualifiedName);
     }
 
-
-
-    // //////////////////////////////////////
-
-    // -- identification
+    // -- IDENTIFICATION
+    
     /**
      * having a title() method (rather than using @Title annotation) is necessary as a workaround to be able to use
      * wrapperFactory#unwrap(...) method, which is otherwise broken in Isis 1.6.0
@@ -189,10 +179,7 @@ implements
         return buf.toString();
     }
 
-
-    // //////////////////////////////////////
-
-    // -- fullyQualifiedName (property)
+    // -- PROPERTIES
 
     @Programmatic
     public String getFullyQualifiedName() {
@@ -207,10 +194,6 @@ implements
         return buf.toString();
     }
 
-
-
-    // -- objectSpecId (property)
-
     @Programmatic
     public String getLogicalTypeName() {
         if (getTypeSimpleName() == null) {
@@ -226,67 +209,16 @@ implements
         return buf.toString();
     }
 
+    @Getter ApplicationFeatureType type;
 
+    @Programmatic 
+    @Getter @Setter private String namespace;
 
-    // //////////////////////////////////////
-
-    // -- type (property)
-    ApplicationFeatureType type;
-
-    public ApplicationFeatureType getType() {
-        return type;
-    }
-
-
-    // //////////////////////////////////////
-
-    // -- namespace (property)
-    private String namespace;
-
-    @Programmatic
-    public String getNamespace() {
-        return namespace;
-    }
-
-    void setNamespace(final String namespace) {
-        this.namespace = namespace;
-    }
-
-
-    // //////////////////////////////////////
-
-    // -- className (property, optional)
-
-    private String typeSimpleName;
-
-    @Programmatic
-    public String getTypeSimpleName() {
-        return typeSimpleName;
-    }
-
-    void setTypeSimpleName(final String className) {
-        this.typeSimpleName = className;
-    }
-
-
-    // //////////////////////////////////////
-
-    // -- memberName (property, optional)
-    private String memberName;
-
-    @Programmatic
-    public String getMemberName() {
-        return memberName;
-    }
-
-    void setMemberName(final String memberName) {
-        this.memberName = memberName;
-    }
-
-
-    // //////////////////////////////////////
+    @Programmatic 
+    @Getter @Setter private String typeSimpleName;
 
-    // -- Package or Class: getParentPackageId
+    @Programmatic 
+    @Getter @Setter private String memberName;
 
     /**
      * The {@link ApplicationFeatureId id} of the parent package of this
@@ -312,12 +244,6 @@ implements
         }
     }
 
-
-
-    // //////////////////////////////////////
-
-    // -- Member: getParentClassId
-
     /**
      * The {@link ApplicationFeatureId id} of the member's class.
      */
@@ -327,10 +253,7 @@ implements
         return newClass(classFqn);
     }
 
-
-    // //////////////////////////////////////
-
-    // -- asString, asEncodedString
+    // -- ENCODING
 
     @Programmatic
     public String asString() {
@@ -341,7 +264,6 @@ implements
     public String asEncodedString() {
         return _Strings.base64UrlEncode(asString());
     }
-    
 
     // //////////////////////////////////////
 
@@ -362,36 +284,6 @@ implements
 
     // //////////////////////////////////////
 
-    // -- Predicates
-
-    public static class Predicates {
-        private Predicates(){}
-
-        public static Predicate<ApplicationFeatureId> isClassContaining(
-                final ApplicationMemberType memberType, final ApplicationFeatureRepositoryDefault applicationFeatures) {
-            return new Predicate<ApplicationFeatureId>() {
-                @Override
-                public boolean test(final ApplicationFeatureId input) {
-                    if(input.getType() != ApplicationFeatureType.CLASS) {
-                        return false;
-                    }
-                    final ApplicationFeature feature = applicationFeatures.findFeature(input);
-                    if(feature == null) {
-                        return false;
-                    }
-                    return memberType == null || !feature.membersOf(memberType).isEmpty();
-                }
-            };
-        }
-
-        public static Predicate<ApplicationFeatureId> isClassRecursivelyWithin(final ApplicationFeatureId packageId) {
-            return (ApplicationFeatureId input) -> input.getParentIds().contains(packageId);
-        }
-    }
-
-
-    // //////////////////////////////////////
-
     // -- Comparators
     public static final class Comparators {
         private Comparators(){}
@@ -441,10 +333,7 @@ implements
         return parentIds;
     }
 
-
-    // //////////////////////////////////////
-
-    // -- equals, hashCode, compareTo, toString
+    // -- OBJECT CONTRACT
 
     private static final Comparator<ApplicationFeatureId> byType =
             comparing(ApplicationFeatureId::getType, nullsFirst(naturalOrder()));
@@ -510,5 +399,26 @@ implements
         return newFeature(namespace, this.getTypeSimpleName(), this.getMemberName()); 
     }
 
+    @Deprecated // duplicate
+    public static ApplicationFeatureId createPackage(String fqn) {
+        val feat = new ApplicationFeatureId(ApplicationFeatureType.PACKAGE);
+        ApplicationFeatureType.PACKAGE.init(feat, fqn);
+        return feat;
+    }
+    
+    @Deprecated // duplicate
+    public static ApplicationFeatureId createClass(String fqn) {
+        val feat = new ApplicationFeatureId(ApplicationFeatureType.CLASS);
+        ApplicationFeatureType.CLASS.init(feat, fqn);
+        return feat;
+    }
+    
+    @Deprecated // duplicate
+    public static ApplicationFeatureId createMember(String fqn) {
+        val feat = new ApplicationFeatureId(ApplicationFeatureType.MEMBER);
+        ApplicationFeatureType.MEMBER.init(feat, fqn);
+        return feat;
+    }
+
 
 }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java
index fbc1910..558126f 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureRepository.java
@@ -18,8 +18,11 @@
  */
 package org.apache.isis.applib.services.appfeat;
 
+import java.util.Map;
 import java.util.SortedSet;
 
+import org.apache.isis.applib.Identifier;
+
 /**
  * Provides the access to string representations of the packages, classes and
  * class members (collectively: "application features") of the domain classes
@@ -46,4 +49,6 @@ public interface ApplicationFeatureRepository  {
             String className,
             ApplicationMemberType memberType);
 
+    Map<String, ApplicationFeatureId> getFeatureIdentifiersByName();
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureType.java b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureType.java
similarity index 89%
rename from core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureType.java
rename to api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureType.java
index 441b36a..81415a9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureType.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeatureType.java
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.core.metamodel.services.appfeat;
+package org.apache.isis.applib.services.appfeat;
 
-import org.apache.isis.core.metamodel.commons.StringExtensions;
+import org.apache.isis.commons.internal.base._Strings;
 
 public enum ApplicationFeatureType {
     
@@ -76,40 +76,41 @@ public enum ApplicationFeatureType {
     public boolean hideClassName() {
         return this == ApplicationFeatureType.PACKAGE;
     }
+    
     public boolean hideMember() {
         return this == ApplicationFeatureType.PACKAGE || this == ApplicationFeatureType.CLASS;
     }
 
     abstract void init(ApplicationFeatureId applicationFeatureId, String fullyQualifiedName);
 
-    static void ensurePackage(final ApplicationFeatureId feature) {
+    public static void ensurePackage(final ApplicationFeatureId feature) {
         if(feature.type != ApplicationFeatureType.PACKAGE) {
             throw new IllegalStateException("Can only be called for a package; " + feature.toString());
         }
     }
 
-    static void ensurePackageOrClass(final ApplicationFeatureId applicationFeatureId) {
+    public static void ensurePackageOrClass(final ApplicationFeatureId applicationFeatureId) {
         if(applicationFeatureId.type != ApplicationFeatureType.PACKAGE && applicationFeatureId.type != ApplicationFeatureType.CLASS) {
             throw new IllegalStateException("Can only be called for a package or a class; " + applicationFeatureId.toString());
         }
     }
 
-    static void ensureClass(final ApplicationFeatureId feature) {
+    public static void ensureClass(final ApplicationFeatureId feature) {
         if(feature.type != ApplicationFeatureType.CLASS) {
             throw new IllegalStateException("Can only be called for a class; " + feature.toString());
         }
     }
 
-    static void ensureMember(final ApplicationFeatureId feature) {
+    public static void ensureMember(final ApplicationFeatureId feature) {
         if(feature.type != ApplicationFeatureType.MEMBER) {
             throw new IllegalStateException("Can only be called for a member; " + feature.toString());
         }
     }
 
-
     @Override
     public String toString() {
-        return StringExtensions.capitalize(name());
+        return _Strings.capitalize(name());
     }
+    
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeature.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeature.java
index b43ffbf..af36106 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeature.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeature.java
@@ -28,7 +28,9 @@ import javax.enterprise.inject.Vetoed;
 import org.apache.isis.applib.IsisModuleApplib;
 import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.annotation.Value;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.applib.util.Equality;
 import org.apache.isis.applib.util.Hashing;
@@ -193,7 +195,7 @@ public class ApplicationFeature implements Comparable<ApplicationFeature> {
 
             return (final ApplicationFeature input) ->
             input.getContents().stream() // all the classes in this package
-            .anyMatch(ApplicationFeatureId.Predicates.isClassContaining(memberType, applicationFeatures));
+            .anyMatch(_Predicates.isClassContaining(memberType, applicationFeatures));
         }
     }
 
@@ -230,6 +232,7 @@ public class ApplicationFeature implements Comparable<ApplicationFeature> {
     public String toString() {
         return toString.toString(this);
     }
+    
 
 
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
index 8174e00..b718d1d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
@@ -20,10 +20,13 @@ package org.apache.isis.core.metamodel.services.appfeat;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.SortedSet;
+import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
 import javax.inject.Inject;
@@ -34,7 +37,9 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.commons.internal.collections._Sets;
@@ -62,9 +67,11 @@ import lombok.extern.log4j.Log4j2;
 @Service
 @Named("isis.metamodel.ApplicationFeatureRepositoryDefault")
 @Log4j2
-public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRepository {
+public class ApplicationFeatureRepositoryDefault 
+implements ApplicationFeatureRepository {
 
     // -- caches
+    private Map<String, ApplicationFeatureId> featureIdentifiersByName;
     final SortedMap<ApplicationFeatureId, ApplicationFeature> packageFeatures = _Maps.newTreeMap();
     private final SortedMap<ApplicationFeatureId, ApplicationFeature> classFeatures = _Maps.newTreeMap();
     private final SortedMap<ApplicationFeatureId, ApplicationFeature> memberFeatures = _Maps.newTreeMap();
@@ -115,9 +122,22 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
             return;
         }
         initializationState = InitializationState.INITIALIZED;
+        
         for (val spec : specificationLoader.snapshotSpecifications()) {
             createApplicationFeaturesFor(spec);
         }
+        
+        val featuresByName = new HashMap<String, ApplicationFeatureId>();
+        visitFeatureIdentifierByName(packageFeatures, featuresByName::put);
+        visitFeatureIdentifierByName(classFeatures, featuresByName::put);
+        visitFeatureIdentifierByName(memberFeatures, featuresByName::put);
+        this.featureIdentifiersByName = Collections.unmodifiableMap(featuresByName);
+    }
+    
+    private void visitFeatureIdentifierByName(
+            final Map<ApplicationFeatureId, ApplicationFeature> map, 
+            final BiConsumer<String, ApplicationFeatureId> onEntry) {
+        map.forEach((k, v)->onEntry.accept(k.toString(), k));
     }
 
     void createApplicationFeaturesFor(final ObjectSpecification spec) {
@@ -137,8 +157,8 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
             return;
         }
 
-        final String specIdString = spec.getLogicalTypeName();
-        final ApplicationFeatureId classFeatureId = ApplicationFeatureId.newClass(specIdString);
+        final String logicalTypeName = spec.getLogicalTypeName();
+        final ApplicationFeatureId classFeatureId = ApplicationFeatureId.newClass(logicalTypeName);
 
         // add class to our map
         // (later on it may get removed if the class turns out to have no features,
@@ -335,41 +355,6 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
         return excluded;
     }
 
-//XXX[2286] .. replaced by check 'spec.getBeanSort().isUnknown()'
-//    /**
-//     * Ignore the (strict) super-classes of any services.
-//     * <p>
-//     * For example, we want to ignore <code>ExceptionRecognizerComposite</code>
-//     * because there is no service of that type (only of subtypes of that).
-//     * </p>
-//     */
-//    private boolean isSuperClassOfService(final ObjectSpecification spec) {
-//
-//        val specClass = spec.getCorrespondingClass();
-//
-//        // is this class a supertype or the actual type of one of the services?
-//        boolean serviceCls = false;
-//        for (final ManagedBeanAdapter bean : registeredServices.get()) {
-//            final Class<?> serviceClass = bean.getBeanClass();
-//            if (specClass.isAssignableFrom(serviceClass)) {
-//                serviceCls = true;
-//            }
-//        }
-//        if (!serviceCls) {
-//            return false;
-//        }
-//
-//        // yes it is.  In which case, is it the actual concrete class of one of those services?
-//        for (final Object registeredService : registeredServices.get()) {
-//            final Class<?> serviceClass = registeredService.getClass();
-//            if (serviceClass.isAssignableFrom(specClass)) {
-//                return false;
-//            }
-//        }
-//        // couldn't find a service of exactly this type, so ignore the spec.
-//        return true;
-//    }
-
     protected boolean isHidden(final ObjectSpecification spec) {
         final HiddenFacet facet = spec.getFacet(HiddenFacet.class);
         return facet != null &&
@@ -472,6 +457,12 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
         return actionFeatures.values();
     }
 
+    @Override
+    public Map<String, ApplicationFeatureId> getFeatureIdentifiersByName() {
+        initializeIfRequired();
+        return featureIdentifiersByName;
+    }
+    
     // -- packageNames, packageNamesContainingClasses, classNamesContainedIn, memberNamesOf
     
     @Override
@@ -503,7 +494,7 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
         }
         final SortedSet<ApplicationFeatureId> contents = pkg.getContents();
         return contents.stream()
-                .filter(ApplicationFeatureId.Predicates.isClassContaining(memberType, this))
+                .filter(_Predicates.isClassContaining(memberType, this))
                 .map(ApplicationFeatureId.Functions.GET_CLASS_NAME)
                 .collect(_Sets.toUnmodifiableSorted());
     }
@@ -518,7 +509,7 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
         }
         final Set<ApplicationFeatureId> classIds = this.classFeatures.keySet();
         return classIds.stream()
-                .filter(ApplicationFeatureId.Predicates.isClassRecursivelyWithin(packageId))
+                .filter(_Predicates.isClassRecursivelyWithin(packageId))
                 .map(ApplicationFeatureId.Functions.GET_CLASS_NAME)
                 .collect(_Sets.toUnmodifiableSorted());
     }
@@ -539,6 +530,6 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
                 .map(ApplicationFeatureId.Functions.GET_MEMBER_NAME)
                 .collect(_Sets.toUnmodifiableSorted());
     }
-
+    
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Asserts.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Asserts.java
new file mode 100644
index 0000000..369d8f7
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Asserts.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.metamodel.services.appfeat;
+
+import java.util.function.Predicate;
+
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
+import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
+
+final class _Asserts {
+
+    public static Predicate<ApplicationFeatureId> isClassContaining(
+            final ApplicationMemberType memberType, final ApplicationFeatureRepositoryDefault applicationFeatures) {
+        return new Predicate<ApplicationFeatureId>() {
+            @Override
+            public boolean test(final ApplicationFeatureId input) {
+                if(input.getType() != ApplicationFeatureType.CLASS) {
+                    return false;
+                }
+                final ApplicationFeature feature = applicationFeatures.findFeature(input);
+                if(feature == null) {
+                    return false;
+                }
+                return memberType == null || !feature.membersOf(memberType).isEmpty();
+            }
+        };
+    }
+
+    public static Predicate<ApplicationFeatureId> isClassRecursivelyWithin(final ApplicationFeatureId packageId) {
+        return (ApplicationFeatureId input) -> input.getParentIds().contains(packageId);
+    }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Predicates.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Predicates.java
new file mode 100644
index 0000000..93b4fc7
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Predicates.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.metamodel.services.appfeat;
+
+import java.util.function.Predicate;
+
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
+import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
+
+final class _Predicates {
+
+    public static Predicate<ApplicationFeatureId> isClassContaining(
+            final ApplicationMemberType memberType, final ApplicationFeatureRepositoryDefault applicationFeatures) {
+        return new Predicate<ApplicationFeatureId>() {
+            @Override
+            public boolean test(final ApplicationFeatureId input) {
+                if(input.getType() != ApplicationFeatureType.CLASS) {
+                    return false;
+                }
+                final ApplicationFeature feature = applicationFeatures.findFeature(input);
+                if(feature == null) {
+                    return false;
+                }
+                return memberType == null || !feature.membersOf(memberType).isEmpty();
+            }
+        };
+    }
+
+    public static Predicate<ApplicationFeatureId> isClassRecursivelyWithin(final ApplicationFeatureId packageId) {
+        return (ApplicationFeatureId input) -> input.getParentIds().contains(packageId);
+    }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index df26aa9..2969b3a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -31,6 +31,8 @@ import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.commanddto.processor.CommandDtoProcessor;
 import org.apache.isis.applib.services.grid.GridService;
@@ -43,8 +45,6 @@ import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.facets.members.publish.command.CommandPublishingFacet;
 import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.MixedIn;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
index 81d201e..2026089 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
@@ -39,6 +39,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.id.LogicalType;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.metamodel.BeanSort;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
 import org.apache.isis.commons.collections.Can;
@@ -60,7 +61,6 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
 import org.apache.isis.core.metamodel.progmodel.ProgrammingModelService;
 import org.apache.isis.core.metamodel.progmodels.dflt.ProgrammingModelFacetsJava8;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutor;
 import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutor.Substitution;
 import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutorDefault;
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java
index 9f91565..7c319c4 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java
@@ -38,6 +38,8 @@ import static org.hamcrest.Matchers.emptyCollectionOf;
 import static org.hamcrest.Matchers.greaterThan;
 import static org.hamcrest.Matchers.lessThan;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.core.internaltestsupport.contract.ValueTypeContractTestAbstract;
 import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2;
@@ -615,7 +617,7 @@ public class ApplicationFeatureIdTest {
             public void whenNull() throws Exception {
                 expectedException.expect(NullPointerException.class);
 
-                ApplicationFeatureId.Predicates.
+                _Predicates.
                 isClassContaining(ApplicationMemberType.ACTION, mockApplicationFeatureRepository).
                 test(null);
             }
@@ -623,12 +625,12 @@ public class ApplicationFeatureIdTest {
             @Test
             public void whenNotClass() throws Exception {
                 assertThat(
-                        ApplicationFeatureId.Predicates.
+                        _Predicates.
                         isClassContaining(ApplicationMemberType.ACTION, mockApplicationFeatureRepository).
                         test(ApplicationFeatureId.newPackage("com.mycompany")),
                         is(false));
                 assertThat(
-                        ApplicationFeatureId.Predicates.
+                        _Predicates.
                         isClassContaining(ApplicationMemberType.ACTION, mockApplicationFeatureRepository).
                         test(ApplicationFeatureId.newMember("com.mycompany.Bar#foo")),
                         is(false));
@@ -643,7 +645,7 @@ public class ApplicationFeatureIdTest {
                 }});
 
                 assertThat(
-                        ApplicationFeatureId.Predicates.
+                        _Predicates.
                         isClassContaining(ApplicationMemberType.ACTION, mockApplicationFeatureRepository).
                         test(classFeature),
                         is(false));
@@ -660,7 +662,7 @@ public class ApplicationFeatureIdTest {
                 }});
 
                 assertThat(
-                        ApplicationFeatureId.Predicates.
+                        _Predicates.
                         isClassContaining(ApplicationMemberType.ACTION, mockApplicationFeatureRepository).
                         test(classFeature),
                         is(false));
@@ -679,7 +681,7 @@ public class ApplicationFeatureIdTest {
                 }});
 
                 assertThat(
-                        ApplicationFeatureId.Predicates.
+                        _Predicates.
                         isClassContaining(ApplicationMemberType.ACTION, mockApplicationFeatureRepository).
                         test(classFeature),
                         is(true));
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
index 4e2b515..9f0dd47 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
@@ -39,6 +39,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
 
 import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
 import org.apache.isis.commons.collections.Can;
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTest.java
index fe47c9e..34c1f79 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTest.java
@@ -27,6 +27,7 @@ import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 
 public class ApplicationFeatureTest {
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTypeTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTypeTest.java
index 7398248..3ddb220 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTypeTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureTypeTest.java
@@ -26,6 +26,11 @@ import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
+
+import lombok.val;
+
 public class ApplicationFeatureTypeTest {
 
     public static class HideClassName extends ApplicationFeatureTypeTest {
@@ -55,9 +60,7 @@ public class ApplicationFeatureTypeTest {
         @Test
         public void givenPackage() throws Exception {
 
-            final ApplicationFeatureId applicationFeatureId = new ApplicationFeatureId(ApplicationFeatureType.PACKAGE);
-
-            ApplicationFeatureType.PACKAGE.init(applicationFeatureId, "com.mycompany");
+            val applicationFeatureId = ApplicationFeatureId.createPackage("com.mycompany"); 
 
             assertThat(applicationFeatureId.getNamespace(), is("com.mycompany"));
             assertThat(applicationFeatureId.getTypeSimpleName(), is(nullValue()));
@@ -67,9 +70,7 @@ public class ApplicationFeatureTypeTest {
         @Test
         public void givenClass() throws Exception {
 
-            final ApplicationFeatureId applicationFeatureId = new ApplicationFeatureId(ApplicationFeatureType.CLASS);
-
-            ApplicationFeatureType.CLASS.init(applicationFeatureId, "com.mycompany.Bar");
+            val applicationFeatureId = ApplicationFeatureId.createClass("com.mycompany.Bar");
 
             assertThat(applicationFeatureId.getNamespace(), is("com.mycompany"));
             assertThat(applicationFeatureId.getTypeSimpleName(), is("Bar"));
@@ -79,10 +80,8 @@ public class ApplicationFeatureTypeTest {
         @Test
         public void givenMember() throws Exception {
 
-            final ApplicationFeatureId applicationFeatureId = new ApplicationFeatureId(ApplicationFeatureType.MEMBER);
-
-            ApplicationFeatureType.MEMBER.init(applicationFeatureId, "com.mycompany.Bar#foo");
-
+            val applicationFeatureId = ApplicationFeatureId.createMember("com.mycompany.Bar#foo");
+            
             assertThat(applicationFeatureId.getNamespace(), is("com.mycompany"));
             assertThat(applicationFeatureId.getTypeSimpleName(), is("Bar"));
             assertThat(applicationFeatureId.getMemberName(), is("foo"));
@@ -91,9 +90,8 @@ public class ApplicationFeatureTypeTest {
         public void givenMemberMalformed() throws Exception {
 
             expectedException.expect(IllegalArgumentException.class);
-            final ApplicationFeatureId applicationFeatureId = new ApplicationFeatureId(ApplicationFeatureType.MEMBER);
-
-            ApplicationFeatureType.MEMBER.init(applicationFeatureId, "com.mycompany.BarISMISSINGTHEHASHSYMBOL");
+            ApplicationFeatureId
+                    .createMember("com.mycompany.BarISMISSINGTHEHASHSYMBOL");
         }
     }
 
@@ -104,17 +102,17 @@ public class ApplicationFeatureTypeTest {
 
         @Test
         public void whenPackage() throws Exception {
-            ApplicationFeatureType.ensurePackage(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE));
+            ApplicationFeatureType.ensurePackage(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE, "xxx"));
         }
         @Test
         public void whenClass() throws Exception {
             expectedException.expect(IllegalStateException.class);
-            ApplicationFeatureType.ensurePackage(new ApplicationFeatureId(ApplicationFeatureType.CLASS));
+            ApplicationFeatureType.ensurePackage(new ApplicationFeatureId(ApplicationFeatureType.CLASS, "xxx"));
         }
         @Test
         public void whenMember() throws Exception {
             expectedException.expect(IllegalStateException.class);
-            ApplicationFeatureType.ensurePackage(new ApplicationFeatureId(ApplicationFeatureType.MEMBER));
+            ApplicationFeatureType.ensurePackage(new ApplicationFeatureId(ApplicationFeatureType.MEMBER, "xxx#x"));
         }
     }
 
@@ -125,16 +123,16 @@ public class ApplicationFeatureTypeTest {
 
         @Test
         public void whenPackage() throws Exception {
-            ApplicationFeatureType.ensurePackageOrClass(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE));
+            ApplicationFeatureType.ensurePackageOrClass(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE, "xxx"));
         }
         @Test
         public void whenClass() throws Exception {
-            ApplicationFeatureType.ensurePackageOrClass(new ApplicationFeatureId(ApplicationFeatureType.CLASS));
+            ApplicationFeatureType.ensurePackageOrClass(new ApplicationFeatureId(ApplicationFeatureType.CLASS, "xxx"));
         }
         @Test
         public void whenMember() throws Exception {
             expectedException.expect(IllegalStateException.class);
-            ApplicationFeatureType.ensurePackageOrClass(new ApplicationFeatureId(ApplicationFeatureType.MEMBER));
+            ApplicationFeatureType.ensurePackageOrClass(new ApplicationFeatureId(ApplicationFeatureType.MEMBER, "xxx#x"));
         }
 
     }
@@ -146,16 +144,16 @@ public class ApplicationFeatureTypeTest {
         @Test
         public void whenPackage() throws Exception {
             expectedException.expect(IllegalStateException.class);
-            ApplicationFeatureType.ensureClass(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE));
+            ApplicationFeatureType.ensureClass(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE, "xxx"));
         }
         @Test
         public void whenClass() throws Exception {
-            ApplicationFeatureType.ensureClass(new ApplicationFeatureId(ApplicationFeatureType.CLASS));
+            ApplicationFeatureType.ensureClass(new ApplicationFeatureId(ApplicationFeatureType.CLASS, "xxx"));
         }
         @Test
         public void whenMember() throws Exception {
             expectedException.expect(IllegalStateException.class);
-            ApplicationFeatureType.ensureClass(new ApplicationFeatureId(ApplicationFeatureType.MEMBER));
+            ApplicationFeatureType.ensureClass(new ApplicationFeatureId(ApplicationFeatureType.MEMBER, "xxx#x"));
         }
 
     }
@@ -167,16 +165,16 @@ public class ApplicationFeatureTypeTest {
         @Test
         public void whenPackage() throws Exception {
             expectedException.expect(IllegalStateException.class);
-            ApplicationFeatureType.ensureMember(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE));
+            ApplicationFeatureType.ensureMember(new ApplicationFeatureId(ApplicationFeatureType.PACKAGE, "xxx"));
         }
         @Test
         public void whenClass() throws Exception {
             expectedException.expect(IllegalStateException.class);
-            ApplicationFeatureType.ensureMember(new ApplicationFeatureId(ApplicationFeatureType.CLASS));
+            ApplicationFeatureType.ensureMember(new ApplicationFeatureId(ApplicationFeatureType.CLASS, "xxx"));
         }
         @Test
         public void whenMember() throws Exception {
-            ApplicationFeatureType.ensureMember(new ApplicationFeatureId(ApplicationFeatureType.MEMBER));
+            ApplicationFeatureType.ensureMember(new ApplicationFeatureId(ApplicationFeatureType.MEMBER, "xxx#x"));
         }
     }
 
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java
index dc3188a..f49b996 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java
@@ -27,7 +27,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.security.authentication.Authentication;
 import org.apache.isis.core.security.authorization.Authorizor;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java
index 0a7b6d0..1c423aa 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermission.java
@@ -26,10 +26,10 @@ import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionRepository.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionRepository.java
index eb7c476..8af8ea8 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionRepository.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionRepository.java
@@ -21,8 +21,8 @@ package org.apache.isis.extensions.secman.api.permission;
 import java.util.Collection;
 import java.util.Optional;
 
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 
 /**
@@ -62,11 +62,17 @@ public interface ApplicationPermissionRepository<P extends ApplicationPermission
             String memberName);
 
     P newPermission(
-            ApplicationRole holder,
+            ApplicationRole role,
             ApplicationPermissionRule rule,
             ApplicationPermissionMode mode,
             ApplicationFeatureType featureType,
             String featureFqn);
 
-
+    P newPermission(
+            ApplicationRole role,
+            ApplicationPermissionRule rule,
+            ApplicationPermissionMode mode,
+            ApplicationFeatureId featureId);
+    
+    
 }
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValue.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValue.java
index fbd3766..6bd68ab 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValue.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValue.java
@@ -23,9 +23,9 @@ import java.util.Comparator;
 import java.util.List;
 
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ToString;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 
 /**
  * A serializable value object representing an (anonymized)
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValueSet.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValueSet.java
index 5c53ecc..fadcaa1 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValueSet.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/ApplicationPermissionValueSet.java
@@ -24,10 +24,10 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Multimaps;
 import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 
 /**
  * A serializable value object representing a set of (anonymized)
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationService.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationService.java
index dfef149..25cc3da 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationService.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationService.java
@@ -21,7 +21,7 @@ package org.apache.isis.extensions.secman.api.permission;
 import java.io.Serializable;
 import java.util.Collection;
 
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 
 /**
  * Strategy for determining which permission should apply when there are multiple that apply for a particular target
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationServiceAbstract.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationServiceAbstract.java
index 3c041ac..ed76f82 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationServiceAbstract.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/permission/PermissionsEvaluationServiceAbstract.java
@@ -20,8 +20,8 @@ package org.apache.isis.extensions.secman.api.permission;
 
 import java.util.Collection;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 
 /**
  * @since 2.0 {@index}
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/role/ApplicationRole.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/role/ApplicationRole.java
index 1fa9dd0..7a17ceb 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/role/ApplicationRole.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/role/ApplicationRole.java
@@ -37,11 +37,8 @@ public interface ApplicationRole {
 
     public static class AddUserDomainEvent extends ActionDomainEvent {}
     public static class RemoveUserDomainEvent extends ActionDomainEvent {}
-    public static class AddActionDomainEvent extends ActionDomainEvent {}
-    public static class AddClassDomainEvent extends ActionDomainEvent {}
-    public static class AddCollectionDomainEvent extends ActionDomainEvent {}
-    public static class AddPackageDomainEvent extends ActionDomainEvent {}
-    public static class AddPropertyDomainEvent extends ActionDomainEvent {}
+    
+    public static class AddPermissionDomainEvent extends ActionDomainEvent {}
     public static class RemovePermissionDomainEvent extends ActionDomainEvent {}
 
     public static class DeleteDomainEvent extends ActionDomainEvent {}
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClass.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClass.java
index 3025871..6758fd1 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClass.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClass.java
@@ -27,7 +27,7 @@ import org.apache.isis.applib.annotation.CollectionLayout;
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 
 @DomainObject(
         objectType = "isis.ext.secman.ApplicationClass"
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassAction.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassAction.java
index 4e0786c..8240238 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassAction.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassAction.java
@@ -23,7 +23,7 @@ import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 
 @DomainObject(
         objectType = "isis.ext.secman.ApplicationClassAction"
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassCollection.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassCollection.java
index eddfe64..c1a1cad 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassCollection.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassCollection.java
@@ -22,7 +22,7 @@ import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 
 @DomainObject(
         objectType = "isis.ext.secman.ApplicationClassCollection"
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassMember.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassMember.java
index 12294b9..3b3ad36 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassMember.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassMember.java
@@ -23,7 +23,7 @@ import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 
 @DomainObject(
         objectType = "isis.ext.secman.ApplicationClassMember"
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassProperty.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassProperty.java
index e59a407..e4c5bf9 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassProperty.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationClassProperty.java
@@ -23,7 +23,7 @@ import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Optionality;
 import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 
 @DomainObject(
         objectType = "isis.ext.secman.ApplicationClassProperty"
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationFeatureViewModel.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationFeatureViewModel.java
index 463f638..f7991c5 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationFeatureViewModel.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationFeatureViewModel.java
@@ -33,6 +33,8 @@ import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.util.Equality;
 import org.apache.isis.applib.util.Hashing;
@@ -41,9 +43,7 @@ import org.apache.isis.applib.util.ToString;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPackage.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPackage.java
index 7ca2deb..88a6cdd 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPackage.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPackage.java
@@ -26,8 +26,8 @@ import org.apache.isis.applib.annotation.CollectionLayout;
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 
 @DomainObject(
         objectType = "isis.ext.secman.ApplicationPackage"
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPermission_feature.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPermission_feature.java
index 72aae4e..21ae587 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPermission_feature.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/feature/ApplicationPermission_feature.java
@@ -24,9 +24,9 @@ import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
 import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_filterPermissions.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_filterPermissions.java
index 6e07945..b8b1c7b 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_filterPermissions.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_filterPermissions.java
@@ -31,10 +31,10 @@ import org.apache.isis.applib.annotation.Optionality;
 import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.SemanticsOf;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
 
@@ -52,7 +52,7 @@ public class ApplicationUser_filterPermissions {
     @Inject private FactoryService factory;
     @Inject private ApplicationFeatureRepositoryDefault applicationFeatureRepository;
 
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public List<UserPermissionViewModel> act(
@@ -103,7 +103,7 @@ public class ApplicationUser_filterPermissions {
     List<UserPermissionViewModel> asViewModels(final Collection<ApplicationFeature> features) {
         return _Lists.map(
                 features,
-                UserPermissionViewModel.Functions.asViewModel(holder, factory));
+                UserPermissionViewModel.Functions.asViewModel(target, factory));
     }
 
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_permissions.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_permissions.java
index 64c4455..f357af5 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_permissions.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/ApplicationUser_permissions.java
@@ -51,7 +51,7 @@ public class ApplicationUser_permissions {
     @Inject private FactoryService factory;
     @Inject private ApplicationFeatureRepositoryDefault applicationFeatureRepository;
 
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public List<UserPermissionViewModel> coll() {
@@ -62,7 +62,7 @@ public class ApplicationUser_permissions {
     List<UserPermissionViewModel> asViewModels(final java.util.Collection<ApplicationFeature> features) {
         return _Lists.map(
                 features,
-                UserPermissionViewModel.Functions.asViewModel(holder, factory));
+                UserPermissionViewModel.Functions.asViewModel(target, factory));
     }
 
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/UserPermissionViewModel.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/UserPermissionViewModel.java
index 89c4472..38296f8 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/UserPermissionViewModel.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/app/user/UserPermissionViewModel.java
@@ -37,15 +37,15 @@ import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ToString;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager.java
index f3ab4a7..7af6069 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager.java
@@ -22,7 +22,6 @@ import java.util.Collection;
 
 import javax.inject.Inject;
 
-import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.Nature;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
@@ -45,9 +44,9 @@ public class ApplicationOrphanedPermissionManager {
         return applicationPermissionRepository.findOrphaned();
     }
     
-    @Action
-    public Collection<? extends ApplicationPermission> debugOrphanedPermissions() {
-        return applicationPermissionRepository.findOrphaned();
-    }
+//    @Action
+//    public Collection<? extends ApplicationPermission> debugOrphanedPermissions() {
+//        return applicationPermissionRepository.findOrphaned();
+//    }
     
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager_relocateSelected.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager_relocateSelected.java
index 76dc2a5..b168e67 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager_relocateSelected.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationOrphanedPermissionManager_relocateSelected.java
@@ -26,7 +26,7 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.Optionality;
 import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission.RelocateNamespaceDomainEvent;
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_allow.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_allow.java
index 05f7213..c3fb67b 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_allow.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_allow.java
@@ -29,16 +29,16 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationPermission_allow {
 
-    private final ApplicationPermission holder;
+    private final ApplicationPermission target;
 
     //@MemberOrder(name = "Rule", sequence = "1")
     public ApplicationPermission act() {
-        holder.setRule(ApplicationPermissionRule.ALLOW);
-        return holder;
+        target.setRule(ApplicationPermissionRule.ALLOW);
+        return target;
     }
 
     public String disableAct() {
-        return holder.getRule() == ApplicationPermissionRule.ALLOW? "Rule is already set to ALLOW": null;
+        return target.getRule() == ApplicationPermissionRule.ALLOW? "Rule is already set to ALLOW": null;
     }
 
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_changing.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_changing.java
index f4c2f3c..621ee0f 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_changing.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_changing.java
@@ -29,16 +29,16 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationPermission_changing {
 
-    private final ApplicationPermission holder;
+    private final ApplicationPermission target;
 
     //@MemberOrder(name = "Mode", sequence = "2")
     public ApplicationPermission act() {
-        holder.setMode(ApplicationPermissionMode.CHANGING);
-        return holder;
+        target.setMode(ApplicationPermissionMode.CHANGING);
+        return target;
     }
     
     public String disableAct() {
-        return holder.getMode() == ApplicationPermissionMode.CHANGING ? "Mode is already set to CHANGING": null;
+        return target.getMode() == ApplicationPermissionMode.CHANGING ? "Mode is already set to CHANGING": null;
     }
     
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_delete.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_delete.java
index 0f7194c..8ffda8a 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_delete.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_delete.java
@@ -30,17 +30,19 @@ import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
-@Action(domainEvent = DeleteDomainEvent.class, semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE)
+@Action(
+        domainEvent = DeleteDomainEvent.class, 
+        semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE)
 @RequiredArgsConstructor
 public class ApplicationPermission_delete {
     
     @Inject private RepositoryService repository;
 
-    private final ApplicationPermission holder;
+    private final ApplicationPermission target;
 
     public ApplicationRole act() {
-        val owningRole = holder.getRole();
-        repository.remove(holder);
+        val owningRole = target.getRole();
+        repository.remove(target);
         return owningRole;
     }
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_updateRole.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_updateRole.java
index da3c3e1..9e3d4f0 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_updateRole.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_updateRole.java
@@ -31,23 +31,25 @@ import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = UpdateRoleDomainEvent.class, associateWith = "role")
+@Action(
+        domainEvent = UpdateRoleDomainEvent.class, 
+        associateWith = "role")
 @RequiredArgsConstructor
 public class ApplicationPermission_updateRole {
 
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     
-    private final ApplicationPermission holder;
+    private final ApplicationPermission target;
     
     @Model
     public ApplicationPermission act(final ApplicationRole applicationRole) {
-        holder.setRole(applicationRole);
-        return holder;
+        target.setRole(applicationRole);
+        return target;
     }
 
     @Model
     public ApplicationRole default0Act() {
-        return holder.getRole();
+        return target.getRole();
     }
 
     @Model
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_veto.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_veto.java
index 0d5ee2e..1e97cb9 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_veto.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_veto.java
@@ -25,19 +25,21 @@ import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRul
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = VetoDomainEvent.class, associateWith = "rule")
+@Action(
+        domainEvent = VetoDomainEvent.class, 
+        associateWith = "rule")
 @RequiredArgsConstructor
 public class ApplicationPermission_veto {
 
-    private final ApplicationPermission holder;
+    private final ApplicationPermission target;
 
     //@MemberOrder(name = "Rule", sequence = "1")
     public ApplicationPermission act() {
-        holder.setRule(ApplicationPermissionRule.VETO);
-        return holder;
+        target.setRule(ApplicationPermissionRule.VETO);
+        return target;
     }
     public String disableAct() {
-        return holder.getRule() == ApplicationPermissionRule.VETO? "Rule is already set to VETO": null;
+        return target.getRule() == ApplicationPermissionRule.VETO? "Rule is already set to VETO": null;
     }
     
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_viewing.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_viewing.java
index 98e96e3..f3af1e5 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_viewing.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/permission/ApplicationPermission_viewing.java
@@ -25,20 +25,22 @@ import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMod
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = ViewingDomainEvent.class, associateWith = "mode")
+@Action(
+        domainEvent = ViewingDomainEvent.class, 
+        associateWith = "mode")
 @RequiredArgsConstructor
 public class ApplicationPermission_viewing {
 
-    private final ApplicationPermission holder;
+    private final ApplicationPermission target;
     
     //@MemberOrder(name = "Mode", sequence = "1")
     public ApplicationPermission act() {
-        holder.setMode(ApplicationPermissionMode.VIEWING);
-        return holder;
+        target.setMode(ApplicationPermissionMode.VIEWING);
+        return target;
     }
     
     public String disableAct() {
-        return holder.getMode() == ApplicationPermissionMode.VIEWING ? "Mode is already set to VIEWING": null;
+        return target.getMode() == ApplicationPermissionMode.VIEWING ? "Mode is already set to VIEWING": null;
     }
     
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addAction.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addAction.java
index ef977c7..c084589 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addAction.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addAction.java
@@ -25,19 +25,21 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddActionDomainEvent;
+import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPermissionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = AddActionDomainEvent.class, associateWith = "permissions")
+@Action(
+        domainEvent = AddPermissionDomainEvent.class, 
+        associateWith = "permissions")
 @RequiredArgsConstructor
 public class ApplicationRole_addAction {
     
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addClass.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addClass.java
index db47ff7..aa3a2a9 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addClass.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addClass.java
@@ -24,18 +24,20 @@ import javax.inject.Inject;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddClassDomainEvent;
+import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPermissionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = AddClassDomainEvent.class, associateWith = "permissions")
+@Action(
+        domainEvent = AddPermissionDomainEvent.class, 
+        associateWith = "permissions")
 @RequiredArgsConstructor
 public class ApplicationRole_addClass {
     
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addCollection.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addCollection.java
index c64442b..d83db09 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addCollection.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addCollection.java
@@ -27,19 +27,21 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddCollectionDomainEvent;
+import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPermissionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = AddCollectionDomainEvent.class, associateWith = "permissions")
+@Action(
+        domainEvent = AddPermissionDomainEvent.class, 
+        associateWith = "permissions")
 @RequiredArgsConstructor
 public class ApplicationRole_addCollection {
     
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPackage.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPackage.java
index 29c360d..4b2994c 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPackage.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPackage.java
@@ -25,18 +25,20 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPackageDomainEvent;
+import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPermissionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = AddPackageDomainEvent.class, associateWith = "permissions")
+@Action(
+        domainEvent = AddPermissionDomainEvent.class, 
+        associateWith = "permissions")
 @RequiredArgsConstructor
 public class ApplicationRole_addPackage {
     
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addAction.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPermission.java
similarity index 52%
copy from extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addAction.java
copy to extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPermission.java
index ef977c7..d5293ee 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addAction.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPermission.java
@@ -18,87 +18,108 @@
  */
 package org.apache.isis.extensions.secman.model.dom.role;
 
+import java.util.Map;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
 import javax.enterprise.inject.Model;
 import javax.inject.Inject;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.MinLength;
+import org.apache.isis.applib.annotation.Optionality;
+import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.applib.annotation.PromptStyle;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
-import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddActionDomainEvent;
+import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPermissionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
+import lombok.Value;
+import lombok.val;
+import lombok.experimental.Accessors;
 
-@Action(domainEvent = AddActionDomainEvent.class, associateWith = "permissions")
+//TODO[2560] wip
+//@Action(
+//        domainEvent = AddPermissionDomainEvent.class, 
+//        associateWith = "permissions")
+//@ActionLayout(promptStyle = PromptStyle.DIALOG_MODAL)
 @RequiredArgsConstructor
-public class ApplicationRole_addAction {
+public class ApplicationRole_addPermission {
     
     @Inject private ApplicationFeatureRepository applicationFeatureRepository;
     @Inject private ApplicationPermissionRepository<? extends ApplicationPermission> applicationPermissionRepository;
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
+    
+    @Value @Accessors(fluent = true)           
+    public static class Parameters {
+        ApplicationPermissionRule rule; // ALLOW/VETO
+        ApplicationPermissionMode mode; // r/w
+        String feature;
+    }
 
     /**
      * Adds a {@link ApplicationPermission permission} for this role to a
-     * {@link ApplicationMemberType#ACTION action}
-     * {@link ApplicationFeatureType#MEMBER member}
      * {@link ApplicationFeature feature}.
      */
     @MemberOrder(sequence = "3")
     public ApplicationRole act(
+            
+            @Parameter(optionality = Optionality.MANDATORY)
             @ParameterLayout(named="Rule")
             final ApplicationPermissionRule rule,
+            
+            @Parameter(optionality = Optionality.MANDATORY)
             @ParameterLayout(named="Mode")
             final ApplicationPermissionMode mode,
-            @ParameterLayout(named="Package", typicalLength=ApplicationFeature.TYPICAL_LENGTH_PKG_FQN)
-            final String packageFqn,
-            @ParameterLayout(named="Class", typicalLength=ApplicationFeature.TYPICAL_LENGTH_CLS_NAME)
-            final String className,
-            @ParameterLayout(named="Action", typicalLength = ApplicationFeature.TYPICAL_LENGTH_MEMBER_NAME)
-            final String memberName) {
+            
+            @Parameter(optionality = Optionality.MANDATORY)
+            @ParameterLayout(named="Feature")
+            final String featureName) {
+        
+        val featureId = ApplicationFeatureId.parse(featureName);
         
-        applicationPermissionRepository.newPermission(holder, rule, mode, packageFqn, className, memberName);
-        return holder;
+        applicationPermissionRepository.newPermission(target, rule, mode, featureId);
+        return target;
     }
 
     @Model
-    public ApplicationPermissionRule default0Act() {
+    public ApplicationPermissionRule defaultRule(Parameters params) {
         return ApplicationPermissionRule.ALLOW;
     }
 
     @Model
-    public ApplicationPermissionMode default1Act() {
+    public ApplicationPermissionMode defaultMode(Parameters params) {
         return ApplicationPermissionMode.CHANGING;
     }
 
     @Model
-    public java.util.Collection<String> choices2Act() {
-        return applicationFeatureRepository.packageNamesContainingClasses(ApplicationMemberType.ACTION);
+    public java.util.Collection<String> autoComplete2Act(             
+            @MinLength(3) String search) {
+        
+        val idsByName = applicationFeatureRepository.getFeatureIdentifiersByName();
+        
+        return idsByName.entrySet().stream()
+        .filter(entry->matches(entry.getKey(), entry.getValue(), search))
+        .map(Map.Entry::getValue)
+        .map(ApplicationFeatureId::asString)
+        .collect(Collectors.toCollection(TreeSet::new));
     }
 
-    @Model
-    public java.util.Collection<String> choices3Act(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final String packageFqn) {
-        return applicationFeatureRepository.classNamesContainedIn(packageFqn, ApplicationMemberType.ACTION);
+    private boolean matches(String featureName, ApplicationFeatureId featureId, String search) {
+        //TODO yet not very smart
+        return featureName.contains(search);
     }
 
-    @Model
-    public java.util.Collection<String> choices4Act(
-            final ApplicationPermissionRule rule,
-            final ApplicationPermissionMode mode,
-            final String packageFqn,
-            final String className) {
-        return applicationFeatureRepository.memberNamesOf(packageFqn, className, ApplicationMemberType.ACTION);
-    }
     
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addProperty.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addProperty.java
index 131cbbb..7da2f1e 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addProperty.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addProperty.java
@@ -27,19 +27,21 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPropertyDomainEvent;
+import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddPermissionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = AddPropertyDomainEvent.class, associateWith = "permissions")
+@Action(
+        domainEvent = AddPermissionDomainEvent.class, 
+        associateWith = "permissions")
 @RequiredArgsConstructor
 public class ApplicationRole_addProperty {
     
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addUser.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addUser.java
index 4eebbf3..2301c4e 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addUser.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addUser.java
@@ -46,19 +46,19 @@ public class ApplicationRole_addUser {
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
 
     @Model
     public ApplicationRole act(final ApplicationUser applicationUser) {
-        applicationRoleRepository.addRoleToUser(holder, applicationUser);
-        return holder;
+        applicationRoleRepository.addRoleToUser(target, applicationUser);
+        return target;
     }
 
     @Model
     public List<? extends ApplicationUser> autoComplete0Act(final String search) {
         final Collection<? extends ApplicationUser> matchingSearch = applicationUserRepository.find(search);
         final List<? extends ApplicationUser> list = _Lists.newArrayList(matchingSearch);
-        list.removeAll(applicationUserRepository.findByRole(holder));
+        list.removeAll(applicationUserRepository.findByRole(target));
         return list;
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermission.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermission.java
index e5a27b2..a0093b8 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermission.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermission.java
@@ -24,10 +24,10 @@ import javax.enterprise.inject.Model;
 import javax.inject.Inject;
 
 import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository;
@@ -51,7 +51,7 @@ public class ApplicationRole_removePermission {
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationPermissionRepository<? extends ApplicationPermission> applicationPermissionRepository;
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
 
     @Model
     public ApplicationRole act(
@@ -63,12 +63,12 @@ public class ApplicationRole_removePermission {
             final String featureFqn) {
         
         final ApplicationPermission permission = applicationPermissionRepository
-                .findByRoleAndRuleAndFeature(holder, rule, type, featureFqn)
+                .findByRoleAndRuleAndFeature(target, rule, type, featureFqn)
                 .orElse(null);
         if(permission != null) {
             repository.remove(permission);
         }
-        return holder;
+        return target;
     }
 
     @Model
@@ -79,7 +79,7 @@ public class ApplicationRole_removePermission {
             final ApplicationFeatureType type,
             @ParameterLayout(named="Feature", typicalLength=ApplicationFeature.TYPICAL_LENGTH_MEMBER_NAME)
             final String featureFqn) {
-        if(applicationRoleRepository.isAdminRole(holder) 
+        if(applicationRoleRepository.isAdminRole(target) 
                 && configBean.isStickyAdminNamespace(featureFqn)) {
             return "Cannot remove top-level namespace permissions for the admin role.";
         }
@@ -102,7 +102,7 @@ public class ApplicationRole_removePermission {
             final ApplicationFeatureType type) {
         
         final Collection<? extends ApplicationPermission> permissions = applicationPermissionRepository
-                .findByRoleAndRuleAndFeatureTypeCached(holder, rule, type);
+                .findByRoleAndRuleAndFeatureTypeCached(target, rule, type);
         return _Lists.map(
                 permissions,
                 ApplicationPermission::getFeatureFqn);
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermissions.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermissions.java
index 82d3da1..9188f36 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermissions.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removePermissions.java
@@ -51,7 +51,7 @@ public class ApplicationRole_removePermissions {
     @Inject private RepositoryService repository;
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
 
     @Model
     public ApplicationRole act(Collection<ApplicationPermission> permissions) {
@@ -60,14 +60,14 @@ public class ApplicationRole_removePermissions {
         .filter(this::canRemove)
         .forEach(repository::remove);
         
-        return holder;
+        return target;
     }
 
     private boolean canRemove(ApplicationPermission permission) {
-        if(!Objects.equals(permission.getRole(), holder)) {
+        if(!Objects.equals(permission.getRole(), target)) {
             return false;
         }
-        if(applicationRoleRepository.isAdminRole(holder) 
+        if(applicationRoleRepository.isAdminRole(target) 
                 && configBean.isStickyAdminNamespace(permission.getFeatureFqn())) {
             
             messageService.warnUser("Cannot remove top-level namespace permissions for the admin role.");
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUser.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUser.java
index 4720c3c..9d8f9c7 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUser.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUser.java
@@ -42,23 +42,23 @@ public class ApplicationRole_removeUser {
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
 
     @Model
     public ApplicationRole act(final ApplicationUser applicationUser) {
-        applicationRoleRepository.removeRoleFromUser(holder, applicationUser);
-        return holder;
+        applicationRoleRepository.removeRoleFromUser(target, applicationUser);
+        return target;
     }
 
     @Model
     public Collection<? extends ApplicationUser> choices0Act() {
-        return applicationUserRepository.findByRole(holder);
+        return applicationUserRepository.findByRole(target);
     }
 
     @Model
     public String validateAct(final ApplicationUser applicationUser) {
         if(applicationUserRepository.isAdminUser(applicationUser) 
-                && applicationRoleRepository.isAdminRole(holder)) {
+                && applicationRoleRepository.isAdminRole(target)) {
             return "Cannot remove admin user from the admin role.";
         }
         return null;
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUsers.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUsers.java
index 90e991c..4d0773b 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUsers.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_removeUsers.java
@@ -47,21 +47,21 @@ public class ApplicationRole_removeUsers {
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
 
     @Model
     public ApplicationRole act(Collection<ApplicationUser> users) {
         
         _NullSafe.stream(users)
         .filter(this::canRemove)
-        .forEach(user->applicationRoleRepository.removeRoleFromUser(holder, user));
+        .forEach(user->applicationRoleRepository.removeRoleFromUser(target, user));
 
-        return holder;
+        return target;
     }
     
     public boolean canRemove(ApplicationUser applicationUser) {
         if(applicationUserRepository.isAdminUser(applicationUser) 
-                && applicationRoleRepository.isAdminRole(holder)) {
+                && applicationRoleRepository.isAdminRole(target)) {
             messageService.warnUser("Cannot remove admin user from the admin role.");
             return false;
         }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateDescription.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateDescription.java
index d748d1c..4b8fdd6 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateDescription.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateDescription.java
@@ -31,11 +31,13 @@ import org.apache.isis.extensions.secman.api.role.ApplicationRole.UpdateDescript
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = UpdateDescriptionDomainEvent.class, associateWith = "description")
+@Action(
+        domainEvent = UpdateDescriptionDomainEvent.class, 
+        associateWith = "description")
 @RequiredArgsConstructor
 public class ApplicationRole_updateDescription {
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
     
     @MemberOrder(sequence = "1")
     public ApplicationRole act(
@@ -48,13 +50,13 @@ public class ApplicationRole_updateDescription {
                     typicalLength=ApplicationRole.TYPICAL_LENGTH_DESCRIPTION)
             final String description) {
         
-        holder.setDescription(description);
-        return holder;
+        target.setDescription(description);
+        return target;
     }
 
     @Model
     public String default0Act() {
-        return holder.getDescription();
+        return target.getDescription();
     }
 
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateName.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateName.java
index a8e7614..3d72bc6 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateName.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_updateName.java
@@ -27,11 +27,13 @@ import org.apache.isis.extensions.secman.api.role.ApplicationRole.UpdateNameDoma
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = UpdateNameDomainEvent.class, associateWith = "name")
+@Action(
+        domainEvent = UpdateNameDomainEvent.class, 
+        associateWith = "name")
 @RequiredArgsConstructor
 public class ApplicationRole_updateName {
     
-    private final ApplicationRole holder;
+    private final ApplicationRole target;
     
     @MemberOrder(sequence = "1")
     public ApplicationRole updateName(
@@ -39,12 +41,12 @@ public class ApplicationRole_updateName {
             @ParameterLayout(named="Name", typicalLength = ApplicationRole.TYPICAL_LENGTH_NAME)
             final String name) {
         
-        holder.setName(name);
-        return holder;
+        target.setName(name);
+        return target;
     }
 
     public String default0UpdateName() {
-        return holder.getName();
+        return target.getName();
     }
 
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addChild.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addChild.java
index 728e120..b4359b9 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addChild.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addChild.java
@@ -37,11 +37,11 @@ public class ApplicationTenancy_addChild {
     
     @Inject private ApplicationTenancyRepository<? extends ApplicationTenancy> applicationTenancyRepository;
     
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
 
     @Model
     public ApplicationTenancy act(final ApplicationTenancy child) {
-        applicationTenancyRepository.setParentOnTenancy(child, holder);
-        return holder;
+        applicationTenancyRepository.setParentOnTenancy(child, target);
+        return target;
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addUser.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addUser.java
index c0c814d..4e8bf7d 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addUser.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_addUser.java
@@ -46,19 +46,19 @@ public class ApplicationTenancy_addUser {
     @Inject private ApplicationTenancyRepository<? extends ApplicationTenancy> applicationTenancyRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
 
     @Model
     public ApplicationTenancy act(final ApplicationUser applicationUser) {
-        applicationTenancyRepository.setTenancyOnUser(holder, applicationUser);
-        return holder;
+        applicationTenancyRepository.setTenancyOnUser(target, applicationUser);
+        return target;
     }
 
     @Model
     public List<? extends ApplicationUser> autoComplete0Act(final String search) {
         final Collection<? extends ApplicationUser> matchingSearch = applicationUserRepository.find(search);
         final List<? extends ApplicationUser> list = _Lists.newArrayList(matchingSearch);
-        list.removeAll(applicationUserRepository.findByTenancy(holder));
+        list.removeAll(applicationUserRepository.findByTenancy(target));
         return list;
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_delete.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_delete.java
index 9d6edaf..43d7174 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_delete.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_delete.java
@@ -49,12 +49,12 @@ public class ApplicationTenancy_delete {
     @Inject private FactoryService factoryService;
     @Inject private RepositoryService repository;
 
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
 
     
     @Model
     public Collection<? extends ApplicationTenancy> act() {
-        for (val user : applicationUserRepository.findByTenancy(holder)) {
+        for (val user : applicationUserRepository.findByTenancy(target)) {
             val updateAtPathMixin = factoryService.mixin(ApplicationUser_updateAtPath.class, user);
             updateAtPathMixin.act(null);
         }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeChild.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeChild.java
index 02bfc24..0c75ec2 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeChild.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeChild.java
@@ -30,24 +30,26 @@ import org.apache.isis.extensions.secman.api.tenancy.ApplicationTenancyRepositor
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = RemoveChildDomainEvent.class, associateWith = "children", 
-associateWithSequence = "2")
+@Action(
+        domainEvent = RemoveChildDomainEvent.class, 
+        associateWith = "children", 
+        associateWithSequence = "2")
 @RequiredArgsConstructor
 public class ApplicationTenancy_removeChild {
     
     @Inject private ApplicationTenancyRepository<? extends ApplicationTenancy> applicationTenancyRepository;
 
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
 
     @Model
     public ApplicationTenancy act(final ApplicationTenancy child) {
         applicationTenancyRepository.clearParentOnTenancy(child);
-        return holder;
+        return target;
     }
     
     @Model
     public Collection<? extends ApplicationTenancy> choices0Act() {
-        return applicationTenancyRepository.getChildren(holder);
+        return applicationTenancyRepository.getChildren(target);
     }
     
     @Model
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeUser.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeUser.java
index 5707cae..f19cd38 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeUser.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_removeUser.java
@@ -33,8 +33,10 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = RemoveUserDomainEvent.class, associateWith = "users", 
-associateWithSequence = "2")
+@Action(
+        domainEvent = RemoveUserDomainEvent.class, 
+        associateWith = "users", 
+        associateWithSequence = "2")
 @ActionLayout(named="Remove")
 @RequiredArgsConstructor
 public class ApplicationTenancy_removeUser {
@@ -42,17 +44,17 @@ public class ApplicationTenancy_removeUser {
     @Inject private ApplicationTenancyRepository<? extends ApplicationTenancy> applicationTenancyRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
     
     @Model
     public ApplicationTenancy act(final ApplicationUser applicationUser) {
         applicationTenancyRepository.clearTenancyOnUser(applicationUser);
-        return holder;
+        return target;
     }
     
     @Model
     public Collection<? extends ApplicationUser> choices0Act() {
-        return applicationUserRepository.findByTenancy(holder);
+        return applicationUserRepository.findByTenancy(target);
     }
     
     @Model
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateName.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateName.java
index 15338e6..da1755c 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateName.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateName.java
@@ -28,24 +28,26 @@ import org.apache.isis.extensions.secman.api.tenancy.ApplicationTenancy.UpdateNa
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = UpdateNameDomainEvent.class, associateWith = "name", 
-associateWithSequence = "1")
+@Action(
+        domainEvent = UpdateNameDomainEvent.class, 
+        associateWith = "name",
+        associateWithSequence = "1")
 @RequiredArgsConstructor
 public class ApplicationTenancy_updateName {
     
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
 
     @Model
     public ApplicationTenancy act(
             @Parameter(maxLength = ApplicationTenancy.MAX_LENGTH_NAME)
             @ParameterLayout(named="Name", typicalLength=ApplicationTenancy.TYPICAL_LENGTH_NAME)
             final String name) {
-        holder.setName(name);
-        return holder;
+        target.setName(name);
+        return target;
     }
 
     @Model
     public String default0Act() {
-        return holder.getName();
+        return target.getName();
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateParent.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateParent.java
index 011e800..0e17732 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateParent.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_updateParent.java
@@ -39,19 +39,19 @@ public class ApplicationTenancy_updateParent {
     
     @Inject private ApplicationTenancyRepository<? extends ApplicationTenancy> applicationTenancyRepository;
     
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
 
     @Model
     public ApplicationTenancy act(
             @Parameter(optionality = Optionality.OPTIONAL)
             final ApplicationTenancy parent) {
         
-        applicationTenancyRepository.setParentOnTenancy(holder, parent);
-        return holder;
+        applicationTenancyRepository.setParentOnTenancy(target, parent);
+        return target;
     }
 
     @Model
     public ApplicationTenancy default0Act() {
-        return holder.getParent();
+        return target.getParent();
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_users.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_users.java
index e49ef74..f6ee381 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_users.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/tenancy/ApplicationTenancy_users.java
@@ -39,14 +39,14 @@ public class ApplicationTenancy_users {
     
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationTenancy holder;
+    private final ApplicationTenancy target;
 
     // -- users (collection)
 
     public static class UsersDomainEvent extends CollectionDomainEvent<ApplicationUser> {}
 
     public java.util.Collection<? extends ApplicationUser> coll() {
-        return applicationUserRepository.findByAtPath(holder.getPath());
+        return applicationUserRepository.findByAtPath(target.getPath());
     }
 
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newDelegateUser.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newDelegateUser.java
index 2ca0d25..604311d 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newDelegateUser.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newDelegateUser.java
@@ -32,7 +32,9 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUserStatus;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = NewDelegateUserDomainEvent.class, associateWith = "allUsers")
+@Action(
+        domainEvent = NewDelegateUserDomainEvent.class, 
+        associateWith = "allUsers")
 @RequiredArgsConstructor
 public class ApplicationUserManager_newDelegateUser {
     
@@ -41,7 +43,7 @@ public class ApplicationUserManager_newDelegateUser {
     @Inject private RepositoryService repository;
 
     @SuppressWarnings("unused")
-    private final ApplicationUserManager holder;
+    private final ApplicationUserManager target;
     
     @Model
     public ApplicationUser act(
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newLocalUser.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newLocalUser.java
index 995ce0a..de986c7 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newLocalUser.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUserManager_newLocalUser.java
@@ -36,7 +36,9 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUserStatus;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = NewLocalUserDomainEvent.class, associateWith = "allUsers")
+@Action(
+        domainEvent = NewLocalUserDomainEvent.class, 
+        associateWith = "allUsers")
 @RequiredArgsConstructor
 public class ApplicationUserManager_newLocalUser {
     
@@ -46,7 +48,7 @@ public class ApplicationUserManager_newLocalUser {
     @Inject private RepositoryService repository;
     
     @SuppressWarnings("unused")
-    private final ApplicationUserManager holder;
+    private final ApplicationUserManager target;
 
     @Model
     public ApplicationUser act(
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_addRole.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_addRole.java
index cc50625..fbd9217 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_addRole.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_addRole.java
@@ -34,25 +34,27 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUser.AddRoleDomainE
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
-@Action(domainEvent = AddRoleDomainEvent.class, associateWith = "roles")
+@Action(
+        domainEvent = AddRoleDomainEvent.class, 
+        associateWith = "roles")
 @ActionLayout(named="Add")
 @RequiredArgsConstructor
 public class ApplicationUser_addRole {
     
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @MemberOrder(sequence = "1")
     public ApplicationUser act(final ApplicationRole role) {
-        applicationRoleRepository.addRoleToUser(role, holder);
-        return holder;
+        applicationRoleRepository.addRoleToUser(role, target);
+        return target;
     }
 
     public Collection<? extends ApplicationRole> choices0Act() {
         val allRoles = applicationRoleRepository.allRoles();
         val applicationRoles = _Sets.newTreeSet(allRoles);
-        applicationRoles.removeAll(holder.getRoles());
+        applicationRoles.removeAll(target.getRoles());
         return applicationRoles;
     }
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_delete.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_delete.java
index b9d10a9..56ca931 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_delete.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_delete.java
@@ -42,16 +42,16 @@ public class ApplicationUser_delete {
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private RepositoryService repository;
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public Collection<? extends ApplicationUser> act() {
-        repository.removeAndFlush(holder);
+        repository.removeAndFlush(target);
         return applicationUserRepository.allUsers();
     }
 
     @Model
     public String disableAct() {
-        return applicationUserRepository.isAdminUser(holder)? "Cannot delete the admin user": null;
+        return applicationUserRepository.isAdminUser(target)? "Cannot delete the admin user": null;
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_duplicate.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_duplicate.java
index a84659b..841c6f5 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_duplicate.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_duplicate.java
@@ -42,7 +42,7 @@ public class ApplicationUser_duplicate {
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
 
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
@@ -52,12 +52,12 @@ public class ApplicationUser_duplicate {
             final String emailAddress) {
         
         return applicationUserRepository
-                .newUser(username, holder.getAccountType(), user->{
+                .newUser(username, target.getAccountType(), user->{
         
                     user.setStatus(ApplicationUserStatus.DISABLED);
                     user.setEmailAddress(emailAddress);
         
-                    for (ApplicationRole role : holder.getRoles()) {
+                    for (ApplicationRole role : target.getRoles()) {
                         applicationRoleRepository.addRoleToUser(role, user);
                     }
                     
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_lock.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_lock.java
index 55cd9df..2dcca68 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_lock.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_lock.java
@@ -42,19 +42,19 @@ public class ApplicationUser_lock {
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private SecmanConfiguration configBean;
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act() {
-        holder.setStatus(ApplicationUserStatus.DISABLED);
-        return holder;
+        target.setStatus(ApplicationUserStatus.DISABLED);
+        return target;
     }
     
     @Model
     public String disableAct() {
-        if(applicationUserRepository.isAdminUser(holder)) {
+        if(applicationUserRepository.isAdminUser(target)) {
             return "Cannot disable the '" + configBean.getAdminUserName() + "' user.";
         }
-        return holder.getStatus() == ApplicationUserStatus.DISABLED ? "Status is already set to DISABLE": null;
+        return target.getStatus() == ApplicationUserStatus.DISABLED ? "Status is already set to DISABLE": null;
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRole.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRole.java
index ee2d78c..a56745d 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRole.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRole.java
@@ -44,29 +44,29 @@ public class ApplicationUser_removeRole {
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(final ApplicationRole role) {
-        applicationRoleRepository.removeRoleFromUser(role, holder);
-        return holder;
+        applicationRoleRepository.removeRoleFromUser(role, target);
+        return target;
     }
 
     @Model
     public String disableAct() {
-        return holder.getRoles().isEmpty()? "No roles to remove": null;
+        return target.getRoles().isEmpty()? "No roles to remove": null;
     }
 
     @Model
     public Collection<? extends ApplicationRole> choices0Act() {
-        return applicationRoleRepository.getRoles(holder);
+        return applicationRoleRepository.getRoles(target);
     }
 
     @Model
     // duplicated in ApplicationRole_removeUser mixin
     public String validateAct(
             final ApplicationRole applicationRole) {
-        if(applicationUserRepository.isAdminUser(holder) 
+        if(applicationUserRepository.isAdminUser(target) 
                 && applicationRoleRepository.isAdminRole(applicationRole)) {
             return "Cannot remove admin user from the admin role.";
         }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRoles.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRoles.java
index 139ae9c..fb67117 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRoles.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_removeRoles.java
@@ -49,7 +49,7 @@ public class ApplicationUser_removeRoles {
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     
     @Model
@@ -57,9 +57,9 @@ public class ApplicationUser_removeRoles {
         
         _NullSafe.stream(roles)
         .filter(this::canRemove)
-        .forEach(role->applicationRoleRepository.removeRoleFromUser(role, holder));
+        .forEach(role->applicationRoleRepository.removeRoleFromUser(role, target));
         
-        return holder;
+        return target;
     }
 
     @Model
@@ -67,7 +67,7 @@ public class ApplicationUser_removeRoles {
     public boolean canRemove(
             final ApplicationRole applicationRole) {
         
-        if(applicationUserRepository.isAdminUser(holder) 
+        if(applicationUserRepository.isAdminUser(target) 
                 && applicationRoleRepository.isAdminRole(applicationRole)) {
             messageService.warnUser("Cannot remove admin user from the admin role.");
             return false;
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_resetPassword.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_resetPassword.java
index 245d37d..588afa3 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_resetPassword.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_resetPassword.java
@@ -41,7 +41,7 @@ public class ApplicationUser_resetPassword {
     
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
@@ -50,13 +50,13 @@ public class ApplicationUser_resetPassword {
             @ParameterLayout(named="Repeat password")
             final Password newPasswordRepeat) {
         
-        applicationUserRepository.updatePassword(holder, newPassword.getPassword());
-        return holder;
+        applicationUserRepository.updatePassword(target, newPassword.getPassword());
+        return target;
     }
 
     @Model
     public boolean hideAct() {
-        return !applicationUserRepository.isPasswordFeatureEnabled(holder);
+        return !applicationUserRepository.isPasswordFeatureEnabled(target);
     }
 
     @Model
@@ -64,7 +64,7 @@ public class ApplicationUser_resetPassword {
             final Password newPassword,
             final Password newPasswordRepeat) {
         
-        if(!applicationUserRepository.isPasswordFeatureEnabled(holder)) {
+        if(!applicationUserRepository.isPasswordFeatureEnabled(target)) {
             return "Password feature is not available for this User";
         }
         
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_unlock.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_unlock.java
index 6225ad3..8763975 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_unlock.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_unlock.java
@@ -36,16 +36,16 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationUser_unlock {
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act() {
-        holder.setStatus(ApplicationUserStatus.ENABLED);
-        return holder;
+        target.setStatus(ApplicationUserStatus.ENABLED);
+        return target;
     }
     
     @Model
     public String disableAct() {
-        return holder.getStatus() == ApplicationUserStatus.ENABLED ? "Status is already set to ENABLE": null;
+        return target.getStatus() == ApplicationUserStatus.ENABLED ? "Status is already set to ENABLE": null;
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAccountType.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAccountType.java
index 8df97ad..bd4af6a 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAccountType.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAccountType.java
@@ -38,25 +38,25 @@ public class ApplicationUser_updateAccountType {
     
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
             final AccountType accountType) {
-        holder.setAccountType(accountType);
-        return holder;
+        target.setAccountType(accountType);
+        return target;
     }
     
     @Model
     public String disableUpdateAccountType() {
-        return applicationUserRepository.isAdminUser(holder)
+        return applicationUserRepository.isAdminUser(target)
                 ? "Cannot change account type for admin user"
                         : null;
     }
     
     @Model
     public AccountType default0UpdateAccountType() {
-        return holder.getAccountType();
+        return target.getAccountType();
     }
 
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAtPath.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAtPath.java
index 803d604..74549b0 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAtPath.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateAtPath.java
@@ -36,20 +36,20 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationUser_updateAtPath {
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
             @Parameter(optionality = Optionality.OPTIONAL)
             @ParameterLayout(named = "AtPath")
             final String atPath) {
-        holder.setAtPath(atPath);
-        return holder;
+        target.setAtPath(atPath);
+        return target;
     }
 
     @Model
     public String default0Act() {
-        return holder.getAtPath();
+        return target.getAtPath();
     }
 
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateEmailAddress.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateEmailAddress.java
index e894048..f7fc83f 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateEmailAddress.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateEmailAddress.java
@@ -35,25 +35,25 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationUser_updateEmailAddress {
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
             @Parameter(maxLength = ApplicationUser.MAX_LENGTH_EMAIL_ADDRESS)
             @ParameterLayout(named="Email")
             final String emailAddress) {
-        holder.setEmailAddress(emailAddress);
-        return holder;
+        target.setEmailAddress(emailAddress);
+        return target;
     }
 
     @Model
     public String default0Act() {
-        return holder.getEmailAddress();
+        return target.getEmailAddress();
     }
 
     @Model
     public String disableAct() {
-        return holder.isForSelfOrRunAsAdministrator()? null: "Can only update your own user record.";
+        return target.isForSelfOrRunAsAdministrator()? null: "Can only update your own user record.";
     }
 
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateName.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateName.java
index 73e1be6..4a3a8ba 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateName.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateName.java
@@ -36,7 +36,7 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationUser_updateName {
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
@@ -50,30 +50,30 @@ public class ApplicationUser_updateName {
             @ParameterLayout(named="Known As")
             final String knownAs
             ) {
-        holder.setFamilyName(familyName);
-        holder.setGivenName(givenName);
-        holder.setKnownAs(knownAs);
-        return holder;
+        target.setFamilyName(familyName);
+        target.setGivenName(givenName);
+        target.setKnownAs(knownAs);
+        return target;
     }
 
     @Model
     public String default0Act() {
-        return holder.getFamilyName();
+        return target.getFamilyName();
     }
 
     @Model
     public String default1Act() {
-        return holder.getGivenName();
+        return target.getGivenName();
     }
 
     @Model
     public String default2Act() {
-        return holder.getKnownAs();
+        return target.getKnownAs();
     }
 
     @Model
     public String disableAct() {
-        return holder.isForSelfOrRunAsAdministrator()? null: "Can only update your own user record.";
+        return target.isForSelfOrRunAsAdministrator()? null: "Can only update your own user record.";
     }
 
     @Model
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePassword.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePassword.java
index 65fd58b..6f94637 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePassword.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePassword.java
@@ -46,7 +46,7 @@ public class ApplicationUser_updatePassword {
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private Optional<PasswordEncryptionService> passwordEncryptionService; // empty if no candidate is available
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
@@ -57,22 +57,22 @@ public class ApplicationUser_updatePassword {
             @ParameterLayout(named="Re-enter password")
             final Password newPasswordRepeat) {
         
-        applicationUserRepository.updatePassword(holder, newPassword.getPassword());
-        return holder;
+        applicationUserRepository.updatePassword(target, newPassword.getPassword());
+        return target;
     }
 
     @Model
     public boolean hideAct() {
-        return !applicationUserRepository.isPasswordFeatureEnabled(holder);
+        return !applicationUserRepository.isPasswordFeatureEnabled(target);
     }
 
     @Model
     public String disableAct() {
 
-        if(!holder.isForSelfOrRunAsAdministrator()) {
+        if(!target.isForSelfOrRunAsAdministrator()) {
             return "Can only update password for your own user account.";
         }
-        if (!holder.isHasPassword()) {
+        if (!target.isHasPassword()) {
             return "Password must be reset by administrator.";
         }
         return null;
@@ -84,15 +84,15 @@ public class ApplicationUser_updatePassword {
             final Password newPassword,
             final Password newPasswordRepeat) {
 
-        if(!applicationUserRepository.isPasswordFeatureEnabled(holder)) {
+        if(!applicationUserRepository.isPasswordFeatureEnabled(target)) {
             return "Password feature is not available for this User";
         }
 
         val encrypter = passwordEncryptionService.orElseThrow(_Exceptions::unexpectedCodeReach);
         
-        val encryptedPassword = holder.getEncryptedPassword();
+        val encryptedPassword = target.getEncryptedPassword();
         
-        if(holder.getEncryptedPassword() != null) {
+        if(target.getEncryptedPassword() != null) {
             if (!encrypter.matches(existingPassword.getPassword(), encryptedPassword)) {
                 return "Existing password is incorrect";
             }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePhoneNumber.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePhoneNumber.java
index 15ec6ba..8c10425 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePhoneNumber.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updatePhoneNumber.java
@@ -36,24 +36,24 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationUser_updatePhoneNumber {
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
             @ParameterLayout(named="Phone")
             @Parameter(maxLength = ApplicationUser.MAX_LENGTH_PHONE_NUMBER, optionality = Optionality.OPTIONAL)
             final String phoneNumber) {
-        holder.setPhoneNumber(phoneNumber);
-        return holder;
+        target.setPhoneNumber(phoneNumber);
+        return target;
     }
 
     @Model
     public String disableAct() {
-        return holder.isForSelfOrRunAsAdministrator()? null: "Can only update your own user record.";
+        return target.isForSelfOrRunAsAdministrator()? null: "Can only update your own user record.";
     }
     
     @Model
     public String default0Act() {
-        return holder.getPhoneNumber();
+        return target.getPhoneNumber();
     }
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateUsername.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateUsername.java
index aad50c6..afef9be 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateUsername.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateUsername.java
@@ -35,20 +35,20 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationUser_updateUsername {
     
-    private final ApplicationUser holder;
+    private final ApplicationUser target;
 
     @Model
     public ApplicationUser act(
             @Parameter(maxLength = ApplicationUser.MAX_LENGTH_USERNAME)
             @ParameterLayout(named="Username")
             final String username) {
-        holder.setUsername(username);
-        return holder;
+        target.setUsername(username);
+        return target;
     }
 
     @Model
     public String default0Act() {
-        return holder.getUsername();
+        return target.getUsername();
     }
 
 }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/HasUsername_open.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/HasUsername_open.java
index cb282c8..0222e45 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/HasUsername_open.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/HasUsername_open.java
@@ -40,25 +40,25 @@ public class HasUsername_open {
 
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     
-    private final HasUsername holder;
+    private final HasUsername target;
 
     public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<HasUsername_open> {}
 
     
     @MemberOrder(name = "User", sequence = "1") // associate with a 'User' property (if any)
     public ApplicationUser act() {
-        if (holder == null || holder.getUsername() == null) {
+        if (target == null || target.getUsername() == null) {
             return null;
         }
-        return applicationUserRepository.findByUsername(holder.getUsername()).orElse(null);
+        return applicationUserRepository.findByUsername(target.getUsername()).orElse(null);
     }
     
     public boolean hideAct() {
-        return holder instanceof ApplicationUser;
+        return target instanceof ApplicationUser;
     }
 
     public TranslatableString disableAct() {
-        if (holder == null || holder.getUsername() == null) {
+        if (target == null || target.getUsername() == null) {
             return TranslatableString.tr("No username");
         }
         return null;
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java
index b8b6ddf..d622e7f 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermission.java
@@ -37,15 +37,15 @@ import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ObjectContracts.ObjectContract;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValue;
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java
index 67b5827..2fb948a 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/permission/ApplicationPermissionRepository.java
@@ -30,6 +30,8 @@ import javax.inject.Named;
 import org.springframework.stereotype.Repository;
 
 import org.apache.isis.applib.query.Query;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.message.MessageService;
@@ -43,9 +45,7 @@ import org.apache.isis.commons.internal.collections._Multimaps;
 import org.apache.isis.commons.internal.collections._Multimaps.ListMultimap;
 import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValue;
@@ -61,7 +61,7 @@ public class ApplicationPermissionRepository
 implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRepository<ApplicationPermission> {
 
     @Inject private RepositoryService repository;
-    @Inject private ApplicationFeatureRepositoryDefault applicationFeatureRepository;
+    @Inject private ApplicationFeatureRepositoryDefault featureRepository;
     @Inject private FactoryService factory;
     @Inject private MessageService messages;
     
@@ -231,7 +231,7 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
         val role = _Casts.<ApplicationRole>uncheckedCast(genericRole);
 
         final ApplicationFeatureId featureId = ApplicationFeatureId.newFeature(featureType, featureFqn);
-        final ApplicationFeature feature = applicationFeatureRepository.findFeature(featureId);
+        final ApplicationFeature feature = featureRepository.findFeature(featureId);
         if(feature == null) {
             messages.warnUser("No such " + featureType.name().toLowerCase() + ": " + featureFqn);
             return null;
@@ -270,13 +270,22 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
             final String featureClassName,
             final String featureMemberName) {
 
-        val role = _Casts.<ApplicationRole>uncheckedCast(genericRole);
-
         val featureId = ApplicationFeatureId.newFeature(featurePackage, featureClassName, featureMemberName);
+        return newPermission(genericRole, rule, mode, featureId);
+    }
+
+    @Override
+    public ApplicationPermission newPermission(
+            final org.apache.isis.extensions.secman.api.role.ApplicationRole genericRole,
+            final ApplicationPermissionRule rule, 
+            final ApplicationPermissionMode mode, 
+            final ApplicationFeatureId featureId) {
+
+        val role = _Casts.<ApplicationRole>uncheckedCast(genericRole);
         val featureType = featureId.getType();
         val featureFqn = featureId.getFullyQualifiedName();
 
-        val feature = applicationFeatureRepository.findFeature(featureId);
+        val feature = featureRepository.findFeature(featureId);
         if(feature == null) {
             messages.warnUser("No such " + featureType.name().toLowerCase() + ": " + featureFqn);
             return null;
@@ -292,7 +301,7 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
 
         return permission;
     }
-
+    
 
     // -- allPermission (programmatic)
     @Override
@@ -307,7 +316,7 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
     @Override
     public Collection<ApplicationPermission> findOrphaned() {
 
-        final Collection<String> packageNames = applicationFeatureRepository.packageNames();
+        final Collection<String> packageNames = featureRepository.packageNames();
         final Set<String> availableClasses = _Sets.newTreeSet();
         for (String packageName : packageNames) {
             appendClasses(packageName, ApplicationMemberType.PROPERTY, availableClasses);
@@ -317,8 +326,7 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
 
         val orphaned = _Lists.<ApplicationPermission>newArrayList();
 
-        val permissions = allPermissions();
-        for (val permission : permissions) {
+        for (val permission : allPermissions()) {
             final ApplicationFeatureType featureType = permission.getFeatureType();
             final String featureFqn = permission.getFeatureFqn();
 
@@ -360,7 +368,7 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
 
     private void appendClasses(
             final String packageName, final ApplicationMemberType memberType, final Set<String> availableClasses) {
-        final Collection<String> classNames = applicationFeatureRepository.classNamesContainedIn(packageName, memberType);
+        final Collection<String> classNames = featureRepository.classNamesContainedIn(packageName, memberType);
         for (String className : classNames) {
             availableClasses.add(packageName + "." + className);
         }
@@ -380,7 +388,7 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
             final ApplicationMemberType applicationMemberType,
             final List<String> memberNames) {
         final Collection<String> memberNamesOf =
-                applicationFeatureRepository.memberNamesOf(packageName, className, applicationMemberType);
+                featureRepository.memberNamesOf(packageName, className, applicationMemberType);
         memberNames.addAll(memberNamesOf);
     }
 
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.java
index 1d95fec..2abbe37 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.java
@@ -40,6 +40,7 @@ import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.user.RoleMemento;
 import org.apache.isis.applib.services.user.UserMemento;
 import org.apache.isis.applib.services.user.UserService;
@@ -47,7 +48,6 @@ import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ObjectContracts.ObjectContract;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValueSet;
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
index 40ac6e0..3763454 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
@@ -25,8 +25,8 @@ import java.util.stream.Collectors;
 
 import javax.inject.Inject;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java
index 914f41f..ab64170 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermission.java
@@ -45,15 +45,15 @@ import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ObjectContracts.ObjectContract;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValue;
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java
index 8a2665d..52e2e1a 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/permission/ApplicationPermissionRepository.java
@@ -31,6 +31,8 @@ import javax.inject.Named;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.query.Query;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.message.MessageService;
@@ -44,9 +46,7 @@ import org.apache.isis.commons.internal.collections._Multimaps;
 import org.apache.isis.commons.internal.collections._Multimaps.ListMultimap;
 import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeature;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValue;
@@ -278,7 +278,7 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
         repository.persist(permission);
         return permission;
     }
-
+    
     @Override
     public ApplicationPermission newPermission(
             final org.apache.isis.extensions.secman.api.role.ApplicationRole genericRole,
@@ -288,9 +288,19 @@ implements org.apache.isis.extensions.secman.api.permission.ApplicationPermissio
             final String featureClassName,
             final String featureMemberName) {
 
-        val role = _Casts.<ApplicationRole>uncheckedCast(genericRole);
-
         val featureId = ApplicationFeatureId.newFeature(featurePackage, featureClassName, featureMemberName);
+        return newPermission(genericRole, rule, mode, featureId);
+    }
+    
+    @Override
+    public ApplicationPermission newPermission(
+            final org.apache.isis.extensions.secman.api.role.ApplicationRole genericRole,
+            final ApplicationPermissionRule rule, 
+            final ApplicationPermissionMode mode, 
+            final ApplicationFeatureId featureId) {
+        
+        val role = _Casts.<ApplicationRole>uncheckedCast(genericRole);
+        
         val featureType = featureId.getType();
         val featureFqn = featureId.getFullyQualifiedName();
 
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUser.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUser.java
index 2f88229..db9b816 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUser.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUser.java
@@ -51,6 +51,7 @@ import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.user.RoleMemento;
 import org.apache.isis.applib.services.user.UserMemento;
 import org.apache.isis.applib.services.user.UserService;
@@ -58,7 +59,6 @@ import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ObjectContracts.ObjectContract;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValueSet;
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
index fb75029..4dbdb43 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/seed/scripts/AbstractRoleAndPermissionsFixtureScript.java
@@ -24,8 +24,8 @@ import java.util.stream.Collectors;
 
 import javax.inject.Inject;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureType;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
diff --git a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PermissionForMember.java b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PermissionForMember.java
index 6ca9d74..bb8df0e 100644
--- a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PermissionForMember.java
+++ b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PermissionForMember.java
@@ -20,8 +20,8 @@ package org.apache.isis.extensions.secman.shiro;
 
 import org.apache.shiro.authz.Permission;
 
+import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
-import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 
 /**
  * As created by {@link org.apache.isis.extensions.secman.shiro.PermissionResolverForIsisShiroAuthorizor}, interprets the