You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/05/04 06:21:11 UTC

[isis] branch ISIS-2619 updated: ISIS-2614 and ISIS-2609: removes Application.getName ; moves mixin domain events down from API to model

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

danhaywood pushed a commit to branch ISIS-2619
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/ISIS-2619 by this push:
     new fb301fb  ISIS-2614 and ISIS-2609: removes Application.getName ; moves mixin domain events down from API to model
fb301fb is described below

commit fb301fb3ffeed88fd91dfe812dedfdbb73d54e93
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue May 4 07:20:08 2021 +0100

    ISIS-2614 and ISIS-2609: removes Application.getName ; moves mixin domain events down from API to model
    
    Instead of getName, we use getUsername.
---
 .../isis/applib/services/user/ImpersonateMenu.java |   3 +-
 .../api/permission/ApplicationPermission.java      |  14 +-
 .../secman/api/role/ApplicationRole.java           |  11 -
 .../secman/api/tenancy/ApplicationTenancy.java     |  14 +-
 .../secman/api/user/ApplicationUser.java           | 289 +++++++++++++++++----
 .../secman/model/IsisModuleExtSecmanModel.java     |   5 +-
 ...OrphanedPermissionManager_relocateSelected.java |  28 +-
 .../permission/ApplicationPermission_allow.java    |  16 +-
 .../permission/ApplicationPermission_changing.java |  19 +-
 .../permission/ApplicationPermission_delete.java   |  10 +-
 .../ApplicationPermission_updateRole.java          |  17 +-
 .../dom/permission/ApplicationPermission_veto.java |  14 +-
 .../permission/ApplicationPermission_viewing.java  |  19 +-
 .../dom/role/ApplicationRole_addPermission.java    |  26 +-
 .../model/dom/role/ApplicationRole_addUser.java    |  12 +-
 .../model/dom/role/ApplicationRole_delete.java     |  14 +-
 .../role/ApplicationRole_removePermissions.java    |  18 +-
 .../dom/role/ApplicationRole_removeUsers.java      |  20 +-
 .../role/ApplicationRole_updateDescription.java    |  20 +-
 .../model/dom/role/ApplicationRole_updateName.java |  16 +-
 .../ApplicationUserManager_newDelegateUser.java    |  26 +-
 .../user/ApplicationUserManager_newLocalUser.java  |  24 +-
 .../model/dom/user/ApplicationUser_addRole.java    |  11 +-
 .../model/dom/user/ApplicationUser_delete.java     |  16 +-
 .../model/dom/user/ApplicationUser_duplicate.java  |  21 +-
 .../model/dom/user/ApplicationUser_lock.java       |  13 +-
 .../dom/user/ApplicationUser_removeRoles.java      |  24 +-
 .../dom/user/ApplicationUser_resetPassword.java    |  18 +-
 .../model/dom/user/ApplicationUser_unlock.java     |  12 +-
 .../user/ApplicationUser_updateAccountType.java    |  17 +-
 .../dom/user/ApplicationUser_updateAtPath.java     |  10 +-
 .../user/ApplicationUser_updateEmailAddress.java   |  12 +-
 .../dom/user/ApplicationUser_updateFaxNumber.java  |  12 +-
 .../model/dom/user/ApplicationUser_updateName.java |  13 +-
 .../dom/user/ApplicationUser_updatePassword.java   |  21 +-
 .../user/ApplicationUser_updatePhoneNumber.java    |  15 +-
 .../dom/user/ApplicationUser_updateUsername.java   |  11 +-
 .../menu/ImpersonateMenuAdvisorForSecman.java      |   7 +-
 .../secman/jdo/dom/user/ApplicationUser.java       | 157 ++++-------
 .../dom/user/ApplicationUser.layout.fallback.xml   | 109 +++++---
 .../ApplicationUserManager_newDelegateUser.java    |  22 +-
 .../user/ApplicationUserManager_newLocalUser.java  |  30 +--
 .../jdo/dom/user/ApplicationUserRepository.java    |  46 ++--
 .../secman/jpa/dom/user/ApplicationUser.java       | 170 ++++--------
 .../ApplicationUserManager_newDelegateUser.java    |  20 +-
 .../user/ApplicationUserManager_newLocalUser.java  |  26 +-
 .../jpa/dom/user/ApplicationUserRepository.java    |  46 ++--
 .../secman/shiro/PrincipalForApplicationUser.java  |  30 +--
 48 files changed, 861 insertions(+), 663 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java b/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java
index 87ea661..395034f 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/user/ImpersonateMenu.java
@@ -3,6 +3,7 @@ package org.apache.isis.applib.services.user;
 import java.util.Collections;
 import java.util.List;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import org.apache.isis.applib.IsisModuleApplib;
@@ -114,7 +115,7 @@ public class ImpersonateMenu {
             final String userName,
             final List<String> roleNames) {
 
-        this.userService.impersonateUser(userName, roleNames);
+        this.userService.impersonateUser(userName, roleNames != null ? roleNames : Collections.emptyList());
         this.messageService.informUser("Now impersonating " + userName);
     }
     public boolean hideImpersonateWithRoles() {
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 823ae5c..2baae35 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
@@ -40,7 +40,7 @@ import lombok.val;
  *
  * <p>
  *     Each permission has a {@link #getRule() rule} and a {@link #getMode() mode}.  The
- *     {@link ApplicationPermissionRule rule} determines whether the permission 
+ *     {@link ApplicationPermissionRule rule} determines whether the permission
  *     {@link ApplicationPermissionRule#ALLOW grants}
  *     access to the feature or {@link ApplicationPermissionRule#VETO veto}es access
  *     to it.  The {@link ApplicationPermissionMode mode} indicates whether
@@ -72,16 +72,6 @@ public interface ApplicationPermission {
 
     public static abstract class PropertyDomainEvent<T> extends IsisModuleExtSecmanApi.PropertyDomainEvent<ApplicationPermission, T> {}
     public static abstract class CollectionDomainEvent<T> extends IsisModuleExtSecmanApi.CollectionDomainEvent<ApplicationPermission, T> {}
-    public static abstract class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationPermission> {}
-
-    public static class AllowDomainEvent extends ActionDomainEvent {}
-    public static class UpdateRoleDomainEvent extends ActionDomainEvent {}
-    public static class VetoDomainEvent extends ActionDomainEvent {}
-    public static class DeleteDomainEvent extends ActionDomainEvent {}
-    public static class ChangingDomainEvent extends ActionDomainEvent {}
-    public static class ViewingDomainEvent extends ActionDomainEvent {}
-
-    public static class RelocateNamespaceDomainEvent extends ActionDomainEvent {}
 
     // -- MODEL
 
@@ -130,7 +120,7 @@ public interface ApplicationPermission {
     @Property
     @PropertyLayout(
             hidden=Where.REFERENCES_PARENT,
-            fieldSetId="Role", 
+            fieldSetId="Role",
             sequence = "1")
     default ApplicationRole getRole() {
         throw _Exceptions.unsupportedOperation("please implement me");
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 6c30ef0..988bb28 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
@@ -35,17 +35,6 @@ public interface ApplicationRole {
     public static abstract class CollectionDomainEvent<T> extends IsisModuleExtSecmanApi.CollectionDomainEvent<ApplicationRole, T> {}
     public static abstract class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole> {}
 
-    public static class AddUserDomainEvent extends ActionDomainEvent {}
-    public static class RemoveUserDomainEvent extends ActionDomainEvent {}
-    
-    public static class AddPermissionDomainEvent extends ActionDomainEvent {}
-    public static class RemovePermissionDomainEvent extends ActionDomainEvent {}
-
-    public static class DeleteDomainEvent extends ActionDomainEvent {}
-
-    public static class UpdateDescriptionDomainEvent extends ActionDomainEvent {}
-    public static class UpdateNameDomainEvent extends ActionDomainEvent {}
-
     // -- MODEL
 
     /**
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancy.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancy.java
index c39f3f5..ed209ea 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancy.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancy.java
@@ -35,13 +35,13 @@ public interface ApplicationTenancy {
     public static abstract class CollectionDomainEvent<T> extends IsisModuleExtSecmanApi.CollectionDomainEvent<ApplicationTenancy, T> {}
     public static abstract class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
 
-    public static class AddUserDomainEvent extends ActionDomainEvent {}
-    public static class RemoveUserDomainEvent extends ActionDomainEvent {}
-    public static class AddChildDomainEvent extends ActionDomainEvent {}
-    public static class DeleteDomainEvent extends ActionDomainEvent {}
-    public static class RemoveChildDomainEvent extends ActionDomainEvent {}
-    public static class UpdateNameDomainEvent extends ActionDomainEvent {}
-    public static class UpdateParentDomainEvent extends ActionDomainEvent {}
+    public static class AddUserDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
+    public static class RemoveUserDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
+    public static class AddChildDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
+    public static class DeleteDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
+    public static class RemoveChildDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
+    public static class UpdateNameDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
+    public static class UpdateParentDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationTenancy> {}
 
     // -- MODEL
 
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java
index f4d227d..3e95d2c 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java
@@ -20,12 +20,27 @@ package org.apache.isis.extensions.secman.api.user;
 
 import java.util.Set;
 
+import javax.inject.Inject;
+
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.applib.annotation.Collection;
+import org.apache.isis.applib.annotation.CollectionLayout;
+import org.apache.isis.applib.annotation.Editing;
+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.mixins.security.HasUsername;
+import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValueSet;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 import org.apache.isis.extensions.secman.api.tenancy.HasAtPath;
 
+import lombok.RequiredArgsConstructor;
+
 /**
  * @since 2.0 {@index}
  */
@@ -33,93 +48,267 @@ public interface ApplicationUser extends HasUsername, HasAtPath {
 
     // -- CONSTANTS
 
-    public static final int MAX_LENGTH_USERNAME = 120;
-    public static final int MAX_LENGTH_FAMILY_NAME = 120;
-    public static final int MAX_LENGTH_GIVEN_NAME = 120;
-    public static final int MAX_LENGTH_KNOWN_AS = 120;
-    public static final int MAX_LENGTH_EMAIL_ADDRESS = 120;
-    public static final int MAX_LENGTH_PHONE_NUMBER = 120;
+    int MAX_LENGTH_USERNAME = 120;
+    int MAX_LENGTH_FAMILY_NAME = 120;
+    int MAX_LENGTH_GIVEN_NAME = 120;
+    int MAX_LENGTH_KNOWN_AS = 120;
+    int MAX_LENGTH_EMAIL_ADDRESS = 120;
+    int MAX_LENGTH_PHONE_NUMBER = 120;
+    int MAX_LENGTH_AT_PATH = 254;
 
     // -- DOMAIN EVENTS
 
-    public static abstract class PropertyDomainEvent<T> extends IsisModuleExtSecmanApi.PropertyDomainEvent<ApplicationUser, T> {}
-    public static abstract class CollectionDomainEvent<T> extends IsisModuleExtSecmanApi.CollectionDomainEvent<ApplicationUser, T> {}
-    public static abstract class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser> {}
-
-    public static class AddRoleDomainEvent extends ActionDomainEvent {}
-    public static class UpdateAtPathDomainEvent extends ActionDomainEvent {}
-    public static class UpdateUsernameDomainEvent extends ActionDomainEvent {}
-    public static class UpdateNameDomainEvent extends ActionDomainEvent {}
-    public static class UpdateEmailAddressDomainEvent extends ActionDomainEvent {}
-    public static class UpdatePhoneNumberDomainEvent extends ActionDomainEvent {}
-    public static class UpdateFaxNumberDomainEvent extends ActionDomainEvent {}
-    public static class UpdateAccountTypeDomainEvent extends ActionDomainEvent {}
-    public static class UnlockDomainEvent extends ActionDomainEvent {}
-    public static class LockDomainEvent extends ActionDomainEvent {}
-    public static class UpdatePasswordDomainEvent extends ActionDomainEvent {}
-    public static class ResetPasswordDomainEvent extends ActionDomainEvent {}
-    public static class RemoveRoleDomainEvent extends ActionDomainEvent {}
-    public static class DeleteDomainEvent extends ActionDomainEvent {}
-    public static class NewDelegateUserDomainEvent extends ActionDomainEvent {}
-    public static class NewLocalUserDomainEvent extends ActionDomainEvent {}
-    public static class UserDuplicateDomainEvent extends ActionDomainEvent {}
+    abstract class PropertyDomainEvent<T> extends IsisModuleExtSecmanApi.PropertyDomainEvent<ApplicationUser, T> {}
+    abstract class CollectionDomainEvent<T> extends IsisModuleExtSecmanApi.CollectionDomainEvent<ApplicationUser, T> {}
 
     // -- MODEL
 
-    /**
-     * 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
-     */
     default String title() {
-        return getName();
+        final StringBuilder buf = new StringBuilder();
+        if(getFamilyName() != null) {
+            if(getKnownAs() != null) {
+                buf.append(getKnownAs());
+            } else {
+                buf.append(getGivenName());
+            }
+            buf.append(' ')
+                    .append(getFamilyName())
+                    .append(" (").append(getUsername()).append(')');
+        } else {
+            buf.append(getUsername());
+        }
+        return buf.toString();
     }
 
     default String iconName() {
         return getStatus().isEnabled() ? "enabled" : "disabled";
     }
 
-    String getName();
 
-    String getEncryptedPassword();
-
-    AccountType getAccountType();
-    void setAccountType(AccountType accountType);
-
-    ApplicationPermissionValueSet getPermissionSet();
+    // -- username (property)
 
-    Set<? extends ApplicationRole> getRoles();
+    class UsernameDomainEvent extends PropertyDomainEvent<String> {}
 
-    ApplicationUserStatus getStatus();
-    void setStatus(ApplicationUserStatus disabled);
+    @Property(
+            domainEvent = UsernameDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_USERNAME
+    )
+    @PropertyLayout(
+            hidden=Where.PARENTED_TABLES,
+            fieldSetId="identity",
+            sequence = "1")
+    @Override
+    String getUsername();
+    void setUsername(String username);
 
-    void setAtPath(String atPath);
 
-    String getEmailAddress();
-    void setEmailAddress(String emailAddress);
+    // -- familyName (property)
 
-    String getFaxNumber();
-    void setFaxNumber(String faxNumber);
+    class FamilyNameDomainEvent extends PropertyDomainEvent<String> {}
 
+    @Property(
+            domainEvent = FamilyNameDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_FAMILY_NAME
+    )
+    @PropertyLayout(
+            hidden=Where.ALL_TABLES,
+            fieldSetId="Name",
+            sequence = "2.1")
     String getFamilyName();
     void setFamilyName(String familyName);
 
+
+    // -- givenName (property)
+
+    class GivenNameDomainEvent extends PropertyDomainEvent<String> {}
+
+    @Property(
+            domainEvent = GivenNameDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_KNOWN_AS
+    )
+    @PropertyLayout(
+            hidden=Where.ALL_TABLES,
+            fieldSetId="Name",
+            sequence = "2.2")
     String getGivenName();
     void setGivenName(String givenName);
 
+
+    // -- knownAs (property)
+
+    class KnownAsDomainEvent extends PropertyDomainEvent<String> {}
+
+    @Property(
+            domainEvent = KnownAsDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_KNOWN_AS
+    )
+    @PropertyLayout(
+            hidden=Where.ALL_TABLES,
+            fieldSetId="Name",
+            sequence = "2.3")
     String getKnownAs();
     void setKnownAs(String knownAs);
 
+
+    // -- emailAddress (property)
+
+    class EmailAddressDomainEvent extends PropertyDomainEvent<String> {}
+
+    @Property(
+            domainEvent = EmailAddressDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_EMAIL_ADDRESS
+    )
+    @PropertyLayout(fieldSetId="Contact Details", sequence = "3.1")
+    String getEmailAddress();
+    void setEmailAddress(String emailAddress);
+
+
+    // -- phoneNumber (property)
+
+    class PhoneNumberDomainEvent extends PropertyDomainEvent<String> {}
+
+    @Property(
+            domainEvent = PhoneNumberDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_PHONE_NUMBER
+    )
+    @PropertyLayout(fieldSetId="Contact Details", sequence = "3.2")
     String getPhoneNumber();
     void setPhoneNumber(String phoneNumber);
 
-    void setUsername(String username);
 
+    // -- faxNumber (property)
+
+    class FaxNumberDomainEvent extends PropertyDomainEvent<String> {}
+
+    @Property(
+            domainEvent = FaxNumberDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_PHONE_NUMBER
+    )
+    @PropertyLayout(
+            hidden=Where.PARENTED_TABLES,
+            fieldSetId="Contact Details",
+            sequence = "3.3")
+    String getFaxNumber();
+    void setFaxNumber(String faxNumber);
+
+
+    // -- atPath (property)
+
+    class AtPathDomainEvent extends PropertyDomainEvent<String> {}
+
+    @Property(
+            domainEvent = AtPathDomainEvent.class,
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_AT_PATH
+    )
+    @PropertyLayout(fieldSetId="atPath", sequence = "3.4")
+    @Override
+    String getAtPath();
+    void setAtPath(String atPath);
+
+    // -- accountType (property)
+
+    class AccountTypeDomainEvent extends PropertyDomainEvent<AccountType> {}
+
+    @Property(
+            domainEvent = AccountTypeDomainEvent.class,
+            editing = Editing.DISABLED
+    )
+    @PropertyLayout(fieldSetId="Status", sequence = "3")
+    AccountType getAccountType();
+    void setAccountType(AccountType accountType);
+
+
+    // -- status (property)
+
+    class StatusDomainEvent extends PropertyDomainEvent<ApplicationUserStatus> {}
+
+    @Property(
+            domainEvent = StatusDomainEvent.class,
+            editing = Editing.DISABLED
+    )
+    @PropertyLayout(fieldSetId="Status", sequence = "4")
+    ApplicationUserStatus getStatus();
+    void setStatus(ApplicationUserStatus disabled);
+
+
+    // -- encryptedPassword (hidden property)
+
+    @PropertyLayout(hidden=Where.EVERYWHERE)
+    String getEncryptedPassword();
     void setEncryptedPassword(String encryptedPassword);
 
-    boolean isForSelfOrRunAsAdministrator();
 
-    boolean isHasPassword();
 
+    // -- hasPassword (derived property)
+
+    class HasPasswordDomainEvent extends PropertyDomainEvent<Boolean> {}
+
+    @Property(
+            domainEvent = HasPasswordDomainEvent.class,
+            editing = Editing.DISABLED
+    )
+    @PropertyLayout(fieldSetId="Status", sequence = "4")
+    default boolean isHasPassword() {
+        return _Strings.isNotEmpty(getEncryptedPassword());
+    }
+
+    @Component
+    @RequiredArgsConstructor(onConstructor_ = {@Inject})
+    class HasPasswordAdvisor {
+
+        final org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<?> applicationUserRepository;
+
+        @EventListener(org.apache.isis.extensions.secman.api.user.ApplicationUser.HasPasswordDomainEvent.class)
+        public void advise(org.apache.isis.extensions.secman.api.user.ApplicationUser.HasPasswordDomainEvent ev) {
+            switch(ev.getEventPhase()) {
+                case HIDE:
+                    if(! applicationUserRepository.isPasswordFeatureEnabled(ev.getSource())) {
+                        ev.hide();
+                    }
+                    break;
+            }
+        }
+    }
+
+
+
+
+
+    // -- roles (collection)
+
+
+    class RolesDomainEvent extends CollectionDomainEvent<ApplicationRole> {}
+
+    @Collection(
+            domainEvent = RolesDomainEvent.class
+    )
+    @CollectionLayout(
+            defaultView="table",
+            sequence = "20")
+    Set<? extends ApplicationRole> getRoles();
+
+
+
+
+    /**
+     * Short-term (request-scoped) caching.
+     * @return
+     */
+    @Programmatic
+    ApplicationPermissionValueSet getPermissionSet();
+
+    @Programmatic
+    boolean isForSelfOrRunAsAdministrator();
+
+    @Programmatic
     default boolean isLocalAccount() {
         return getAccountType() == AccountType.LOCAL;
     }
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java
index 362f968..1b92eaa 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java
@@ -22,6 +22,7 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
+import org.apache.isis.extensions.secman.api.user.ApplicationUser;
 import org.apache.isis.extensions.secman.model.dom.feature.ApplicationFeatureViewModels;
 import org.apache.isis.extensions.secman.model.dom.feature.ApplicationNamespace;
 import org.apache.isis.extensions.secman.model.dom.feature.ApplicationType;
@@ -98,7 +99,9 @@ import org.apache.isis.extensions.secman.model.spiimpl.TableColumnHidingService;
         ApplicationTenancyMenu.class,
         ApplicationUserMenu.class,
 
-        //ImpersonateMenuAdvisorForSecman.class, //not activated by default yet
+        ApplicationUser.HasPasswordAdvisor.class,
+
+        ImpersonateMenuAdvisorForSecman.class, //not activated by default yet
         MeService.class,
 
         // @Component
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 bf86949..dca9c58 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
@@ -32,30 +32,33 @@ import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.services.appfeat.ApplicationFeature;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+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.ApplicationPermission.RelocateNamespaceDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.permission.ApplicationOrphanedPermissionManager_relocateSelected.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @Action(
         associateWith = "orphanedPermissions",
-        domainEvent = RelocateNamespaceDomainEvent.class, 
+        domainEvent = ActionDomainEvent.class,
         semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE)
 @ActionLayout(describedAs = "for the selected permissions renames the namespace")
 @RequiredArgsConstructor
 public class ApplicationOrphanedPermissionManager_relocateSelected {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationOrphanedPermissionManager_relocateSelected> {}
+
     @Inject private ApplicationFeatureRepository featureRepository;
-    
+
     private final ApplicationOrphanedPermissionManager target;
-    
+
     public ApplicationOrphanedPermissionManager act(
             final Collection<ApplicationPermission> permissions,
-            
+
             @Parameter(optionality = Optionality.MANDATORY)
             final String targetNamespace) {
-        
+
         permissions.forEach(perm->relocate(perm, targetNamespace));
         return target;
     }
@@ -65,20 +68,19 @@ public class ApplicationOrphanedPermissionManager_relocateSelected {
                     .map(ApplicationFeature::getFullyQualifiedName)
                     .collect(Collectors.toCollection(TreeSet::new));
     }
-    
+
     private void relocate(
-            final ApplicationPermission permission, 
+            final ApplicationPermission permission,
             final String targetNamespace) {
-        
+
         val appFeatureId = ApplicationFeatureId.newFeature(
-                permission.getFeatureSort(), 
+                permission.getFeatureSort(),
                 permission.getFeatureFqn());
-        
+
         val relocatedFqn = appFeatureId
                 .withNamespace(targetNamespace)
                 .getFullyQualifiedName();
-        
+
         permission.setFeatureFqn(relocatedFqn);
     }
-    
 }
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 8dbe48b..79e6882 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
@@ -19,19 +19,28 @@
 package org.apache.isis.extensions.secman.model.dom.permission;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
+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.ApplicationPermission.AllowDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.permission.ApplicationPermission_allow.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = AllowDomainEvent.class, associateWith = "rule")
+@Action(
+        domainEvent = ApplicationPermission_allow.ActionDomainEvent.class,
+        associateWith = "rule"
+)
+@ActionLayout(
+        sequence = "1"
+)
 @RequiredArgsConstructor
 public class ApplicationPermission_allow {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationPermission_allow> {}
+
     private final ApplicationPermission target;
 
-    //@PropertyLayout(group = "Rule", sequence = "1")
     public ApplicationPermission act() {
         target.setRule(ApplicationPermissionRule.ALLOW);
         return target;
@@ -40,5 +49,4 @@ public class ApplicationPermission_allow {
     public String disableAct() {
         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 b5e27f0..7f2e611 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
@@ -19,27 +19,34 @@
 package org.apache.isis.extensions.secman.model.dom.permission;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.PromptStyle;
+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.ApplicationPermission.ChangingDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.permission.ApplicationPermission_changing.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 
 import lombok.RequiredArgsConstructor;
 
-@Action(domainEvent = ChangingDomainEvent.class, associateWith = "mode")
+@Action(
+        domainEvent = ApplicationPermission_changing.ActionDomainEvent.class,
+        associateWith = "mode")
+@ActionLayout(
+        sequence = "2", promptStyle = PromptStyle.INLINE
+)
 @RequiredArgsConstructor
 public class ApplicationPermission_changing {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationPermission_changing> {}
+
     private final ApplicationPermission target;
 
-    //@PropertyLayout(group = "Mode", sequence = "2")
     public ApplicationPermission act() {
         target.setMode(ApplicationPermissionMode.CHANGING);
         return target;
     }
-    
+
     public String disableAct() {
         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 8ffda8a..b56f729 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
@@ -23,19 +23,22 @@ import javax.inject.Inject;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.services.repository.RepositoryService;
+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.ApplicationPermission.DeleteDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.permission.ApplicationPermission_delete.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @Action(
-        domainEvent = DeleteDomainEvent.class, 
+        domainEvent = ApplicationPermission_delete.ActionDomainEvent.class,
         semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE)
 @RequiredArgsConstructor
 public class ApplicationPermission_delete {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationPermission_delete> {}
+
     @Inject private RepositoryService repository;
 
     private final ApplicationPermission target;
@@ -45,5 +48,4 @@ public class ApplicationPermission_delete {
         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 ab24095..20653a3 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
@@ -23,24 +23,32 @@ import java.util.Collection;
 import javax.inject.Inject;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.applib.annotation.PromptStyle;
+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.ApplicationPermission.UpdateRoleDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.permission.ApplicationPermission_updateRole.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateRoleDomainEvent.class, 
+        domainEvent = ActionDomainEvent.class,
         associateWith = "role")
+@ActionLayout(
+        sequence = "1",
+        promptStyle = PromptStyle.INLINE_AS_IF_EDIT)
 @RequiredArgsConstructor
 public class ApplicationPermission_updateRole {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationPermission_updateRole> {}
+
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
-    
+
     private final ApplicationPermission target;
-    
+
     @MemberSupport
     public ApplicationPermission act(final ApplicationRole applicationRole) {
         target.setRole(applicationRole);
@@ -56,5 +64,4 @@ public class ApplicationPermission_updateRole {
     public Collection<? extends ApplicationRole> choices0Act() {
         return applicationRoleRepository.allRoles();
     }
-    
 }
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 fd404a0..4ce7ffe 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
@@ -19,21 +19,27 @@
 package org.apache.isis.extensions.secman.model.dom.permission;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
+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.ApplicationPermission.VetoDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.permission.ApplicationPermission_veto.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionRule;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = VetoDomainEvent.class, 
+        domainEvent = ApplicationPermission_veto.ActionDomainEvent.class,
         associateWith = "rule")
+@ActionLayout(
+        sequence = "2"
+)
 @RequiredArgsConstructor
 public class ApplicationPermission_veto {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationPermission_veto> {}
+
     private final ApplicationPermission target;
 
-    //@PropertyLayout(group = "Rule", sequence = "1")
     public ApplicationPermission act() {
         target.setRule(ApplicationPermissionRule.VETO);
         return target;
@@ -41,6 +47,4 @@ public class ApplicationPermission_veto {
     public String disableAct() {
         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 83bbbba..458638c 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
@@ -19,29 +19,34 @@
 package org.apache.isis.extensions.secman.model.dom.permission;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.PromptStyle;
+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.ApplicationPermission.ViewingDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.permission.ApplicationPermission_viewing.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = ViewingDomainEvent.class, 
+        domainEvent = ApplicationPermission_viewing.ActionDomainEvent.class,
         associateWith = "mode")
+@ActionLayout(
+        sequence = "1", promptStyle = PromptStyle.INLINE
+)
 @RequiredArgsConstructor
 public class ApplicationPermission_viewing {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationPermission_viewing> {}
+
     private final ApplicationPermission target;
-    
-    //@PropertyLayout(group = "Mode", sequence = "1")
+
     public ApplicationPermission act() {
         target.setMode(ApplicationPermissionMode.VIEWING);
         return target;
     }
-    
+
     public String disableAct() {
         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_addPermission.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPermission.java
index 9ab3053..51cee50 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPermission.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_addPermission.java
@@ -30,12 +30,13 @@ import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.PromptStyle;
 import org.apache.isis.applib.services.appfeat.ApplicationFeature;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
+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;
 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.AddPermissionDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.role.ApplicationRole_addPermission.ActionDomainEvent;
 import org.apache.isis.extensions.secman.model.dom.feature.ApplicationFeatureChoices;
 
 import lombok.RequiredArgsConstructor;
@@ -43,7 +44,7 @@ import lombok.Value;
 import lombok.experimental.Accessors;
 
 @Action(
-        domainEvent = AddPermissionDomainEvent.class, 
+        domainEvent = ApplicationRole_addPermission.ActionDomainEvent.class,
         associateWith = "permissions")
 @ActionLayout(
 		named="Add",
@@ -51,13 +52,15 @@ import lombok.experimental.Accessors;
 		promptStyle = PromptStyle.DIALOG_MODAL)
 @RequiredArgsConstructor
 public class ApplicationRole_addPermission {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole_addPermission> {}
+
     @Inject private ApplicationFeatureRepository featureRepository;
     @Inject private ApplicationPermissionRepository<? extends ApplicationPermission> applicationPermissionRepository;
-    
+
     private final ApplicationRole target;
-    
-    @Value @Accessors(fluent = true)           
+
+    @Value @Accessors(fluent = true)
     public static class Parameters {
         ApplicationPermissionRule rule; // ALLOW/VETO
         ApplicationPermissionMode mode; // r/w
@@ -69,21 +72,19 @@ public class ApplicationRole_addPermission {
      * {@link ApplicationFeature feature}.
      */
     public ApplicationRole act(
-            
+
             @Parameter(optionality = Optionality.MANDATORY)
-            @ParameterLayout(named="Rule")
             final ApplicationPermissionRule rule,
-            
+
             @Parameter(optionality = Optionality.MANDATORY)
-            @ParameterLayout(named="Mode")
             final ApplicationPermissionMode mode,
-            
+
             @Parameter(optionality = Optionality.MANDATORY)
             @ParameterLayout(
                     named = "Feature",
                     describedAs = ApplicationFeatureChoices.DESCRIBED_AS)
             final ApplicationFeatureChoices.AppFeat feature) {
-        
+
         applicationPermissionRepository.newPermission(target, rule, mode, feature.getFeatureId());
         return target;
     }
@@ -104,5 +105,4 @@ public class ApplicationRole_addPermission {
             final @MinLength(3) String search) {
         return ApplicationFeatureChoices.autoCompleteFeature(featureRepository, search);
     }
-    
 }
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 6e98cd7..608fa07 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
@@ -27,8 +27,9 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.commons.internal.collections._Lists;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.AddUserDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.role.ApplicationRole_addUser.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
@@ -36,15 +37,17 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = AddUserDomainEvent.class, 
+        domainEvent = ApplicationRole_addUser.ActionDomainEvent.class,
         associateWith = "users")
 @ActionLayout(named="Add", sequence = "1")
 @RequiredArgsConstructor
 public class ApplicationRole_addUser {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole_addUser> {}
+
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
-    
+
     private final ApplicationRole target;
 
     @MemberSupport
@@ -60,4 +63,5 @@ public class ApplicationRole_addUser {
         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_delete.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_delete.java
index 98818d5..57933e8 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_delete.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/role/ApplicationRole_delete.java
@@ -26,23 +26,27 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.SemanticsOf;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
+import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.DeleteDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.role.ApplicationRole_delete.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = DeleteDomainEvent.class, 
+        domainEvent = ApplicationRole_delete.ActionDomainEvent.class,
         semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE)
 @ActionLayout(sequence = "1")
 @RequiredArgsConstructor
 public class ApplicationRole_delete {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole_delete> {}
+
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
-    
+
     private final ApplicationRole holder;
-    
+
     @MemberSupport
     public Collection<? extends ApplicationRole> act() {
         applicationRoleRepository.deleteRole(holder);
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 921641d..f60f353 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
@@ -30,16 +30,17 @@ import org.apache.isis.applib.annotation.PromptStyle;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermission;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.RemovePermissionDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.role.ApplicationRole_removePermissions.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = RemovePermissionDomainEvent.class, 
+        domainEvent = ApplicationRole_removePermissions.ActionDomainEvent.class,
         associateWith = "permissions")
 @ActionLayout(
 		named="Remove",
@@ -48,20 +49,22 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class ApplicationRole_removePermissions {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole_removePermissions> {}
+
     @Inject private MessageService messageService;
     @Inject private SecmanConfiguration configBean;
     @Inject private RepositoryService repository;
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
-    
+
     private final ApplicationRole target;
 
     @MemberSupport
     public ApplicationRole act(Collection<ApplicationPermission> permissions) {
-        
+
         _NullSafe.stream(permissions)
         .filter(this::canRemove)
         .forEach(repository::remove);
-        
+
         return target;
     }
 
@@ -69,13 +72,12 @@ public class ApplicationRole_removePermissions {
         if(!Objects.equals(permission.getRole(), target)) {
             return false;
         }
-        if(applicationRoleRepository.isAdminRole(target) 
+        if(applicationRoleRepository.isAdminRole(target)
                 && configBean.isStickyAdminNamespace(permission.getFeatureFqn())) {
-            
+
             messageService.warnUser("Cannot remove top-level namespace permissions for the admin role.");
             return false;
         }
         return true;
     }
-
 }
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 7e62b13..4045256 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
@@ -27,8 +27,9 @@ import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.RemoveUserDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.role.ApplicationRole_removeUsers.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
@@ -36,37 +37,36 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = RemoveUserDomainEvent.class,
+        domainEvent = ApplicationRole_removeUsers.ActionDomainEvent.class,
         associateWith = "users")
 @ActionLayout(named="Remove", sequence = "2")
 @RequiredArgsConstructor
 public class ApplicationRole_removeUsers {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole_removeUsers> {}
+
     @Inject private MessageService messageService;
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
-    
+
     private final ApplicationRole target;
 
     @MemberSupport
     public ApplicationRole act(Collection<ApplicationUser> users) {
-        
+
         _NullSafe.stream(users)
         .filter(this::canRemove)
         .forEach(user->applicationRoleRepository.removeRoleFromUser(target, user));
 
         return target;
     }
-    
+
     public boolean canRemove(ApplicationUser applicationUser) {
-        if(applicationUserRepository.isAdminUser(applicationUser) 
+        if(applicationUserRepository.isAdminUser(applicationUser)
                 && applicationRoleRepository.isAdminRole(target)) {
             messageService.warnUser("Cannot remove admin user from the admin role.");
             return false;
         }
         return true;
     }
-    
-    
-    
 }
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 0ba4db7..5f815ad 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
@@ -24,21 +24,25 @@ import org.apache.isis.applib.annotation.MemberSupport;
 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.types.DescriptionType;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.UpdateDescriptionDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.role.ApplicationRole_updateDescription.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateDescriptionDomainEvent.class, 
+        domainEvent = ApplicationRole_updateDescription.ActionDomainEvent.class,
         associateWith = "description")
-@ActionLayout(sequence = "1")
+@ActionLayout(sequence = "1", promptStyle = PromptStyle.INLINE_AS_IF_EDIT)
 @RequiredArgsConstructor
 public class ApplicationRole_updateDescription {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole_updateDescription> {}
+
     private final ApplicationRole target;
-    
+
     @MemberSupport
     public ApplicationRole act(
             @Parameter(
@@ -46,10 +50,10 @@ public class ApplicationRole_updateDescription {
                     optionality = Optionality.OPTIONAL
                     )
             @ParameterLayout(
-                    named="Description", 
+                    named="Description",
                     typicalLength=ApplicationRole.TYPICAL_LENGTH_DESCRIPTION)
             final String description) {
-        
+
         target.setDescription(description);
         return target;
     }
@@ -58,6 +62,4 @@ public class ApplicationRole_updateDescription {
     public String default0Act() {
         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 3b805b9..941c9cc 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
@@ -22,25 +22,28 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
-import org.apache.isis.extensions.secman.api.role.ApplicationRole.UpdateNameDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.role.ApplicationRole_updateName.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateNameDomainEvent.class, 
+        domainEvent = ApplicationRole_updateName.ActionDomainEvent.class,
         associateWith = "name")
 @ActionLayout(sequence = "1")
 @RequiredArgsConstructor
 public class ApplicationRole_updateName {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationRole_updateName> {}
+
     private final ApplicationRole target;
-    
+
     public ApplicationRole act(
-            @Parameter(maxLength = ApplicationRole.MAX_LENGTH_NAME) 
+            @Parameter(maxLength = ApplicationRole.MAX_LENGTH_NAME)
             @ParameterLayout(named="Name", typicalLength = ApplicationRole.TYPICAL_LENGTH_NAME)
             final String name) {
-        
+
         target.setName(name);
         return target;
     }
@@ -48,5 +51,4 @@ public class ApplicationRole_updateName {
     public String default0Act() {
         return target.getName();
     }
-
 }
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 30395b2..f5991ad 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
@@ -21,6 +21,7 @@ package org.apache.isis.extensions.secman.model.dom.user;
 import javax.inject.Inject;
 
 import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.SecurityRealmCharacteristic;
 import org.apache.isis.extensions.secman.api.SecurityRealmService;
@@ -34,16 +35,19 @@ import lombok.val;
 
 /**
  * @apiNote This mixin requires concrete implementations associated with JPA and JDO,
- * since action's type parameters are inspected for their compile time types 
- * and the ApplicationRole here is just an interface that the framework has not much 
+ * since action's type parameters are inspected for their compile time types
+ * and the ApplicationRole here is just an interface that the framework has not much
  * meta-model information to derive UI behavior from.
- * 
+ *
  * @implNote due to current limitations, both the main and its supporting methods have to be
- * overridden with the concrete subclasses. 
- * 
+ * overridden with the concrete subclasses.
+ *
  */
 public abstract class ApplicationUserManager_newDelegateUser<R extends ApplicationRole> {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUserManager_newDelegateUser> {}
+
+    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
     @Inject private ApplicationRoleRepository<R> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private SecmanConfiguration configBean;
@@ -54,7 +58,7 @@ public abstract class ApplicationUserManager_newDelegateUser<R extends Applicati
           final String username,
           final R initialRole,
           final Boolean enabled) {
-        
+
         final ApplicationUser user = applicationUserRepository
                 .newDelegateUser(username, ApplicationUserStatus.parse(enabled));
 
@@ -64,7 +68,7 @@ public abstract class ApplicationUserManager_newDelegateUser<R extends Applicati
         repository.persist(user);
         return user;
     }
-    
+
     protected boolean doHide() {
         return hasNoDelegateAuthenticationRealm();
     }
@@ -74,12 +78,12 @@ public abstract class ApplicationUserManager_newDelegateUser<R extends Applicati
                 .findByNameCached(configBean.getRegularUserRoleName())
                 .orElse(null);
     }
-    
+
     // -- HELPER
-    
+
     private boolean hasNoDelegateAuthenticationRealm() {
         val realm = securityRealmService.getCurrentRealm();
-        return realm == null 
+        return realm == null
                 || !realm.getCharacteristics()
                     .contains(SecurityRealmCharacteristic.DELEGATING);
     }
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 b440c60..05281b0 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
@@ -25,6 +25,7 @@ import javax.inject.Inject;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.value.Password;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
@@ -34,22 +35,24 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUserStatus;
 
 /**
  * @apiNote This mixin requires concrete implementations associated with JPA and JDO,
- * since action's type parameters are inspected for their compile time types 
- * and the ApplicationRole here is just an interface that the framework has not much 
+ * since action's type parameters are inspected for their compile time types
+ * and the ApplicationRole here is just an interface that the framework has not much
  * meta-model information to derive UI behavior from.
- * 
+ *
  * @implNote due to current limitations, both the main and its supporting methods have to be
- * overridden with the concrete subclasses. 
- * 
+ * overridden with the concrete subclasses.
+ *
  */
 public abstract class ApplicationUserManager_newLocalUser<R extends ApplicationRole> {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUserManager_newLocalUser> {}
+
     @Inject private ApplicationRoleRepository<R> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private SecmanConfiguration configBean;
     @Inject private FactoryService factory;
     @Inject private RepositoryService repository;
-    
+
     protected ApplicationUser doAct(
             final String username,
             final Password password,
@@ -57,7 +60,7 @@ public abstract class ApplicationUserManager_newLocalUser<R extends ApplicationR
             final R initialRole,
             final Boolean enabled,
             final String emailAddress) {
-        
+
         ApplicationUser user = applicationUserRepository.findByUsername(username).orElse(null);
         if (user == null) {
             user = applicationUserRepository
@@ -81,19 +84,18 @@ public abstract class ApplicationUserManager_newLocalUser<R extends ApplicationR
             final R initialRole,
             final Boolean enabled,
             final String emailAddress) {
-        
+
         if (!Objects.equals(newPassword, newPasswordRepeat)) {
             return "Passwords do not match";
         }
 
         return null;
     }
-    
+
     protected R doDefault3() {
         return applicationRoleRepository
                 .findByNameCached(configBean.getRegularUserRoleName())
                 .orElse(null);
     }
-   
 
 }
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 f99b494..d5ff1dc 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
@@ -25,23 +25,26 @@ import javax.inject.Inject;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.commons.internal.collections._Sets;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.AddRoleDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_addRole.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @Action(
-        domainEvent = AddRoleDomainEvent.class, 
+        domainEvent = ApplicationUser_addRole.ActionDomainEvent.class,
         associateWith = "roles")
 @ActionLayout(named="Add", sequence = "1")
 @RequiredArgsConstructor
 public class ApplicationUser_addRole {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_addRole> {}
+
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
-    
+
     private final ApplicationUser target;
 
     public ApplicationUser act(final ApplicationRole role) {
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 4868fce..0954621 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
@@ -27,22 +27,26 @@ import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.DeleteDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_delete.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = DeleteDomainEvent.class,
-        semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE)
-@ActionLayout(sequence = "1")
+        domainEvent = ApplicationUser_delete.ActionDomainEvent.class,
+        semantics = SemanticsOf.IDEMPOTENT_ARE_YOU_SURE,
+        associateWith = "username")
+@ActionLayout(sequence = "2", position = ActionLayout.Position.PANEL)
 @RequiredArgsConstructor
 public class ApplicationUser_delete {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_delete> {}
+
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private RepositoryService repository;
-    
+
     private final ApplicationUser target;
 
     @MemberSupport
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 a9226f9..2cd40c9 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
@@ -21,24 +21,30 @@ package org.apache.isis.extensions.secman.model.dom.user;
 import javax.inject.Inject;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.Optionality;
 import org.apache.isis.applib.annotation.Parameter;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UserDuplicateDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_duplicate.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserStatus;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UserDuplicateDomainEvent.class 
+        domainEvent = ApplicationUser_duplicate.ActionDomainEvent.class,
+        associateWith = "username"
         )
+@ActionLayout(sequence = "1", position = ActionLayout.Position.PANEL)
 @RequiredArgsConstructor
 public class ApplicationUser_duplicate {
 
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_duplicate> {}
+
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
 
@@ -50,19 +56,18 @@ public class ApplicationUser_duplicate {
             final String username,
             @Parameter(optionality = Optionality.OPTIONAL)
             final String emailAddress) {
-        
+
         return applicationUserRepository
                 .newUser(username, target.getAccountType(), user->{
-        
+
                     user.setStatus(ApplicationUserStatus.DISABLED);
                     user.setEmailAddress(emailAddress);
-        
+
                     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 3b0b2c2..3ecd459 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
@@ -23,24 +23,27 @@ import javax.inject.Inject;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.LockDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_lock.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserStatus;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = LockDomainEvent.class, 
+        domainEvent = ApplicationUser_lock.ActionDomainEvent.class,
         associateWith = "status")
 @ActionLayout(named="Disable", sequence = "2")
 @RequiredArgsConstructor
 public class ApplicationUser_lock {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_lock> {}
+
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private SecmanConfiguration configBean;
-    
+
     private final ApplicationUser target;
 
     @MemberSupport
@@ -48,7 +51,7 @@ public class ApplicationUser_lock {
         target.setStatus(ApplicationUserStatus.DISABLED);
         return target;
     }
-    
+
     @MemberSupport
     public String disableAct() {
         if(applicationUserRepository.isAdminUser(target)) {
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 d009da1..dd13f3f 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
@@ -27,49 +27,51 @@ import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.role.ApplicationRole;
 import org.apache.isis.extensions.secman.api.role.ApplicationRoleRepository;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.RemoveRoleDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_removeRoles.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = RemoveRoleDomainEvent.class, 
+        domainEvent = ApplicationUser_removeRoles.ActionDomainEvent.class,
         associateWith = "roles")
 @ActionLayout(named="Remove", sequence = "2")
 @RequiredArgsConstructor
 public class ApplicationUser_removeRoles {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_removeRoles> {}
+
     @Inject private MessageService messageService;
     @Inject private ApplicationRoleRepository<? extends ApplicationRole> applicationRoleRepository;
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
-    
+
     private final ApplicationUser target;
 
-    
+
     @MemberSupport
     public ApplicationUser act(Collection<ApplicationRole> roles) {
-        
+
         _NullSafe.stream(roles)
         .filter(this::canRemove)
         .forEach(role->applicationRoleRepository.removeRoleFromUser(role, target));
-        
+
         return target;
     }
 
     // same logic in ApplicationRole_removeUsers
     public boolean canRemove(
             final ApplicationRole applicationRole) {
-        
-        if(applicationUserRepository.isAdminUser(target) 
+
+        if(applicationUserRepository.isAdminUser(target)
                 && applicationRoleRepository.isAdminRole(applicationRole)) {
             messageService.warnUser("Cannot remove admin user from the admin role.");
             return false;
         }
         return true;
     }
-     
-    
+
 }
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 ae13650..728ec1b 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
@@ -27,21 +27,24 @@ import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.value.Password;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.ResetPasswordDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_resetPassword.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = ResetPasswordDomainEvent.class, 
+        domainEvent = ApplicationUser_resetPassword.ActionDomainEvent.class,
         associateWith = "hasPassword")
 @ActionLayout(sequence = "20")
 @RequiredArgsConstructor
 public class ApplicationUser_resetPassword {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_resetPassword> {}
+
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
-    
+
     private final ApplicationUser target;
 
     @MemberSupport
@@ -50,7 +53,7 @@ public class ApplicationUser_resetPassword {
             final Password newPassword,
             @ParameterLayout(named="Repeat password")
             final Password newPasswordRepeat) {
-        
+
         applicationUserRepository.updatePassword(target, newPassword.getPassword());
         return target;
     }
@@ -64,11 +67,11 @@ public class ApplicationUser_resetPassword {
     public String validateAct(
             final Password newPassword,
             final Password newPasswordRepeat) {
-        
+
         if(!applicationUserRepository.isPasswordFeatureEnabled(target)) {
             return "Password feature is not available for this User";
         }
-        
+
         if (!Objects.equals(newPassword, newPasswordRepeat)) {
             return "Passwords do not match";
         }
@@ -76,5 +79,4 @@ public class ApplicationUser_resetPassword {
         return null;
     }
 
-
 }
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 4e9563e..19389c9 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
@@ -21,21 +21,24 @@ package org.apache.isis.extensions.secman.model.dom.user;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UnlockDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_unlock.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserStatus;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UnlockDomainEvent.class, 
+        domainEvent = ApplicationUser_unlock.ActionDomainEvent.class,
         associateWith = "status")
 @ActionLayout(
         named="Enable", // symmetry with lock (disable)
         sequence = "1")
 @RequiredArgsConstructor
 public class ApplicationUser_unlock {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_unlock> {}
+
     private final ApplicationUser target;
 
     @MemberSupport
@@ -43,9 +46,10 @@ public class ApplicationUser_unlock {
         target.setStatus(ApplicationUserStatus.ENABLED);
         return target;
     }
-    
+
     @MemberSupport
     public String disableAct() {
         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 b6ff677..233b104 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
@@ -23,22 +23,25 @@ import javax.inject.Inject;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.AccountType;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdateAccountTypeDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updateAccountType.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateAccountTypeDomainEvent.class, 
+        domainEvent = ApplicationUser_updateAccountType.ActionDomainEvent.class,
         associateWith = "accountType")
-@ActionLayout(sequence = "1")
+@ActionLayout(sequence = "1", position = ActionLayout.Position.RIGHT)
 @RequiredArgsConstructor
 public class ApplicationUser_updateAccountType {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updateAccountType> {}
+
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
-    
+
     private final ApplicationUser target;
 
     @MemberSupport
@@ -47,14 +50,14 @@ public class ApplicationUser_updateAccountType {
         target.setAccountType(accountType);
         return target;
     }
-    
+
     @MemberSupport
     public String disableAct() {
         return applicationUserRepository.isAdminUser(target)
                 ? "Cannot change account type for admin user"
                         : null;
     }
-    
+
     @MemberSupport
     public AccountType default0Act() {
         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 c012fc8..a45146f 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
@@ -24,18 +24,21 @@ import org.apache.isis.applib.annotation.MemberSupport;
 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.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdateAtPathDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updateAtPath.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateAtPathDomainEvent.class, 
+        domainEvent = ApplicationUser_updateAtPath.ActionDomainEvent.class,
         associateWith = "atPath")
 @ActionLayout(sequence = "1")
 @RequiredArgsConstructor
 public class ApplicationUser_updateAtPath {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updateAtPath> {}
+
     private final ApplicationUser target;
 
     @MemberSupport
@@ -52,5 +55,4 @@ public class ApplicationUser_updateAtPath {
         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 8790355..ddc6272 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
@@ -23,18 +23,22 @@ import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 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.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdateEmailAddressDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updateEmailAddress.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateEmailAddressDomainEvent.class, 
+        domainEvent = ApplicationUser_updateEmailAddress.ActionDomainEvent.class,
         associateWith = "emailAddress")
-@ActionLayout(sequence = "1")
+@ActionLayout(sequence = "1", promptStyle = PromptStyle.INLINE_AS_IF_EDIT)
 @RequiredArgsConstructor
 public class ApplicationUser_updateEmailAddress {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updateEmailAddress> {}
+
     private final ApplicationUser target;
 
     @MemberSupport
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateFaxNumber.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateFaxNumber.java
index 9add764..a6963f5 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateFaxNumber.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/user/ApplicationUser_updateFaxNumber.java
@@ -24,18 +24,22 @@ import org.apache.isis.applib.annotation.MemberSupport;
 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.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdateFaxNumberDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updateFaxNumber.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateFaxNumberDomainEvent.class, 
+        domainEvent = ApplicationUser_updateFaxNumber.ActionDomainEvent.class,
         associateWith = "faxNumber")
-@ActionLayout(sequence = "1")
+@ActionLayout(sequence = "1", promptStyle = PromptStyle.INLINE_AS_IF_EDIT)
 @RequiredArgsConstructor
 public class ApplicationUser_updateFaxNumber {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updateFaxNumber> {}
+
     private final ApplicationUser holder;
 
     @MemberSupport
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 28c1bcb..ffb51c9 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
@@ -24,18 +24,21 @@ import org.apache.isis.applib.annotation.MemberSupport;
 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.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdateNameDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updateName.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateNameDomainEvent.class, 
-        associateWith = "knownAs")
+        domainEvent = ApplicationUser_updateName.ActionDomainEvent.class,
+        associateWith = "familyName")
 @ActionLayout(sequence = "1")
 @RequiredArgsConstructor
 public class ApplicationUser_updateName {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updateName> {}
+
     private final ApplicationUser target;
 
     @MemberSupport
@@ -53,6 +56,7 @@ public class ApplicationUser_updateName {
         target.setFamilyName(familyName);
         target.setGivenName(givenName);
         target.setKnownAs(knownAs);
+
         return target;
     }
 
@@ -86,4 +90,5 @@ public class ApplicationUser_updateName {
         }
         return null;
     }
+
 }
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 6fe21e5..0ab1835 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
@@ -29,35 +29,36 @@ import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.value.Password;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.encryption.PasswordEncryptionService;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdatePasswordDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updatePassword.ActionDomainEvent;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @Action(
-        domainEvent = UpdatePasswordDomainEvent.class, 
+        domainEvent = ApplicationUser_updatePassword.ActionDomainEvent.class,
         associateWith = "hasPassword")
 @ActionLayout(sequence = "10")
 @RequiredArgsConstructor
 public class ApplicationUser_updatePassword {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updatePassword> {}
+
     @Inject private ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
     @Inject private Optional<PasswordEncryptionService> passwordEncryptionService; // empty if no candidate is available
-    
+
     private final ApplicationUser target;
 
     @MemberSupport
     public ApplicationUser act(
-            @ParameterLayout(named="Existing password")
             final Password existingPassword,
-            @ParameterLayout(named="New password")
             final Password newPassword,
             @ParameterLayout(named="Re-enter password")
             final Password newPasswordRepeat) {
-        
+
         applicationUserRepository.updatePassword(target, newPassword.getPassword());
         return target;
     }
@@ -90,9 +91,9 @@ public class ApplicationUser_updatePassword {
         }
 
         val encrypter = passwordEncryptionService.orElseThrow(_Exceptions::unexpectedCodeReach);
-        
+
         val encryptedPassword = target.getEncryptedPassword();
-        
+
         if(target.getEncryptedPassword() != null) {
             if (!encrypter.matches(existingPassword.getPassword(), encryptedPassword)) {
                 return "Existing password is incorrect";
@@ -105,6 +106,6 @@ public class ApplicationUser_updatePassword {
 
         return null;
     }
-    
+
 
 }
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 c72c105..48e49f1 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
@@ -24,18 +24,22 @@ import org.apache.isis.applib.annotation.MemberSupport;
 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.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdatePhoneNumberDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updatePhoneNumber.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdatePhoneNumberDomainEvent.class, 
+        domainEvent = ApplicationUser_updatePhoneNumber.ActionDomainEvent.class,
         associateWith = "phoneNumber")
-@ActionLayout(sequence = "1")
+@ActionLayout(sequence = "1", promptStyle = PromptStyle.INLINE_AS_IF_EDIT)
 @RequiredArgsConstructor
 public class ApplicationUser_updatePhoneNumber {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updatePhoneNumber> {}
+
     private final ApplicationUser target;
 
     @MemberSupport
@@ -51,9 +55,10 @@ public class ApplicationUser_updatePhoneNumber {
     public String disableAct() {
         return target.isForSelfOrRunAsAdministrator()? null: "Can only update your own user record.";
     }
-    
+
     @MemberSupport
     public String default0Act() {
         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 1ca0f12..11ae78f 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
@@ -23,18 +23,21 @@ import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.extensions.secman.api.IsisModuleExtSecmanApi;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.UpdateUsernameDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUser_updateUsername.ActionDomainEvent;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = UpdateUsernameDomainEvent.class, 
+        domainEvent = ApplicationUser_updateUsername.ActionDomainEvent.class,
         associateWith = "username")
-@ActionLayout(sequence = "1")
+@ActionLayout(sequence = "1", position = ActionLayout.Position.RIGHT)
 @RequiredArgsConstructor
 public class ApplicationUser_updateUsername {
-    
+
+    public static class ActionDomainEvent extends IsisModuleExtSecmanApi.ActionDomainEvent<ApplicationUser_updateUsername> {}
+
     private final ApplicationUser target;
 
     @MemberSupport
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/menu/ImpersonateMenuAdvisorForSecman.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/menu/ImpersonateMenuAdvisorForSecman.java
index f7c6d22..55f61a3 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/menu/ImpersonateMenuAdvisorForSecman.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/menu/ImpersonateMenuAdvisorForSecman.java
@@ -1,6 +1,8 @@
 package org.apache.isis.extensions.secman.model.menu;
 
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import javax.inject.Inject;
@@ -41,7 +43,7 @@ public class ImpersonateMenuAdvisorForSecman implements ImpersonateMenuAdvisor {
         return this.applicationUserRepository.allUsers()
                 .stream()
                 .filter(x -> x.getStatus() == ApplicationUserStatus.ENABLED)
-                .map(ApplicationUser::getName)
+                .map(ApplicationUser::getUsername)
                 .collect(Collectors.toList());
     }
 
@@ -56,6 +58,9 @@ public class ImpersonateMenuAdvisorForSecman implements ImpersonateMenuAdvisor {
     @Override
     public List<String> roleNamesFor(
             final String username) {
+        if(username == null) {
+            return null;
+        }
         val applicationUser =
                 applicationUserRepository.findByUsername(username)
                         .orElseThrow(RuntimeException::new);
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 3b56664..4ea2885 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
@@ -121,255 +121,194 @@ import lombok.val;
 public class ApplicationUser implements Comparable<ApplicationUser>,
 org.apache.isis.extensions.secman.api.user.ApplicationUser {
 
-    @Inject private ApplicationUserRepository applicationUserRepository;
     @Inject private ApplicationPermissionRepository applicationPermissionRepository;
     @Inject private UserService userService;
     /**
      * Optional service, if configured then is used to evaluate permissions within
      * {@link org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValueSet#evaluate(ApplicationFeatureId, ApplicationPermissionMode)}
-     * else will fallback to a {@link org.apache.isis.extensions.secman.api.permission.PermissionsEvaluationService#DEFAULT default}
+     * else will fallback to a default.
      * implementation.
      */
     @Inject private PermissionsEvaluationService permissionsEvaluationService;
     @Inject private SecmanConfiguration configBean;
 
-    // -- name (derived property)
-
-    public static class NameDomainEvent extends PropertyDomainEvent<String> {}
-
-    @Override
-    @javax.jdo.annotations.NotPersistent
-    @Property(
-            domainEvent = NameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
-    @PropertyLayout(
-            hidden=Where.OBJECT_FORMS,
-            fieldSetId="Id", 
-            sequence = "1")
-    public String getName() {
-        final StringBuilder buf = new StringBuilder();
-        if(getFamilyName() != null) {
-            if(getKnownAs() != null) {
-                buf.append(getKnownAs());
-            } else {
-                buf.append(getGivenName());
-            }
-            buf.append(' ')
-            .append(getFamilyName())
-            .append(" (").append(getUsername()).append(')');
-        } else {
-            buf.append(getUsername());
-        }
-        return buf.toString();
-    }
 
 
     // -- username (property)
 
-    public static class UsernameDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @javax.jdo.annotations.Column(allowsNull="false", length = MAX_LENGTH_USERNAME)
     @Property(
             domainEvent = UsernameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_USERNAME
+    )
     @PropertyLayout(
             hidden=Where.PARENTED_TABLES,
-            fieldSetId="Id", 
+            fieldSetId="Id",
             sequence = "1")
+    @javax.jdo.annotations.Column(allowsNull="false", length = MAX_LENGTH_USERNAME)
     @Getter @Setter
     private String username;
 
 
     // -- familyName (property)
 
-    public static class FamilyNameDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_FAMILY_NAME)
     @Property(
             domainEvent = FamilyNameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_FAMILY_NAME
+    )
     @PropertyLayout(
             hidden=Where.ALL_TABLES,
             fieldSetId="Name",
             sequence = "2.1")
+    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_FAMILY_NAME)
     @Getter @Setter
     private String familyName;
 
 
     // -- givenName (property)
 
-    public static class GivenNameDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_GIVEN_NAME)
     @Property(
             domainEvent = GivenNameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_KNOWN_AS
+    )
     @PropertyLayout(
             hidden=Where.ALL_TABLES,
-            fieldSetId="Name", 
+            fieldSetId="Name",
             sequence = "2.2")
+    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_GIVEN_NAME)
     @Getter @Setter
     private String givenName;
 
 
     // -- knownAs (property)
 
-    public static class KnownAsDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_KNOWN_AS)
     @Property(
             domainEvent = KnownAsDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_KNOWN_AS
+    )
     @PropertyLayout(
             hidden=Where.ALL_TABLES,
             fieldSetId="Name",
             sequence = "2.3")
+    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_KNOWN_AS)
     @Getter @Setter
     private String knownAs;
 
 
     // -- emailAddress (property)
 
-    public static class EmailAddressDomainEvent extends PropertyDomainEvent<String> {}
-
-    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_EMAIL_ADDRESS)
     @Property(
             domainEvent = EmailAddressDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_EMAIL_ADDRESS
+    )
     @PropertyLayout(fieldSetId="Contact Details", sequence = "3.1")
+    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_EMAIL_ADDRESS)
     @Getter @Setter
     private String emailAddress;
 
 
     // -- phoneNumber (property)
 
-    public static class PhoneNumberDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_PHONE_NUMBER)
     @Property(
             domainEvent = PhoneNumberDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_PHONE_NUMBER
+    )
     @PropertyLayout(fieldSetId="Contact Details", sequence = "3.2")
+    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_PHONE_NUMBER)
     @Getter @Setter
     private String phoneNumber;
 
 
     // -- faxNumber (property)
 
-    public static class FaxNumberDomainEvent extends PropertyDomainEvent<String> {}
-
-    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_PHONE_NUMBER)
     @Property(
             domainEvent = FaxNumberDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_PHONE_NUMBER
+    )
     @PropertyLayout(
             hidden=Where.PARENTED_TABLES,
-            fieldSetId="Contact Details", 
+            fieldSetId="Contact Details",
             sequence = "3.3")
+    @javax.jdo.annotations.Column(allowsNull="true", length = MAX_LENGTH_PHONE_NUMBER)
     @Getter @Setter
     private String faxNumber;
 
 
     // -- atPath (property)
 
-    public static class AtPathDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @javax.jdo.annotations.Column(name = "atPath", allowsNull="true")
     @Property(
             domainEvent = AtPathDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_AT_PATH
+    )
     @PropertyLayout(fieldSetId="atPath", sequence = "3.4")
+    @javax.jdo.annotations.Column(name = "atPath", allowsNull="true", length = MAX_LENGTH_AT_PATH)
     @Getter @Setter
     private String atPath;
 
     // -- accountType (property)
 
-    public static class AccountTypeDomainEvent extends PropertyDomainEvent<AccountType> {}
-
-
-    @javax.jdo.annotations.Column(allowsNull="false")
     @Property(
             domainEvent = AccountTypeDomainEvent.class,
             editing = Editing.DISABLED
-            )
+    )
     @PropertyLayout(fieldSetId="Status", sequence = "3")
+    @javax.jdo.annotations.Column(allowsNull="false")
     @Getter @Setter
     private AccountType accountType;
 
 
-    // -- status (property), visible (action), usable (action)
+    // -- status (property)
 
-    public static class StatusDomainEvent extends PropertyDomainEvent<ApplicationUserStatus> {}
-
-
-    @javax.jdo.annotations.Column(allowsNull="false")
     @Property(
             domainEvent = StatusDomainEvent.class,
             editing = Editing.DISABLED
-            )
+    )
     @PropertyLayout(fieldSetId="Status", sequence = "4")
+    @javax.jdo.annotations.Column(allowsNull="false")
     @Getter @Setter
     private ApplicationUserStatus status;
 
 
     // -- encryptedPassword (hidden property)
 
-
-    @javax.jdo.annotations.Column(allowsNull="true")
     @PropertyLayout(hidden=Where.EVERYWHERE)
+    @javax.jdo.annotations.Column(allowsNull="true")
     @Getter @Setter
     private String encryptedPassword;
 
-    public boolean hideEncryptedPassword() {
-        return !applicationUserRepository.isPasswordFeatureEnabled(this);
-    }
 
 
     // -- hasPassword (derived property)
 
-    public static class HasPasswordDomainEvent extends PropertyDomainEvent<Boolean> {}
-
     @Property(
             domainEvent = HasPasswordDomainEvent.class,
             editing = Editing.DISABLED
-            )
+    )
     @PropertyLayout(fieldSetId="Status", sequence = "4")
     @Override
     public boolean isHasPassword() {
-        return _Strings.isNotEmpty(getEncryptedPassword());
+        return org.apache.isis.extensions.secman.api.user.ApplicationUser.super.isHasPassword();
     }
 
-    public boolean hideHasPassword() {
-        return !applicationUserRepository.isPasswordFeatureEnabled(this);
-    }
 
     // -- roles (collection)
-    public static class RolesDomainEvent extends CollectionDomainEvent<ApplicationRole> {}
 
-    @javax.jdo.annotations.Persistent(table="ApplicationUserRoles")
-    @javax.jdo.annotations.Join(column="userId")
-    @javax.jdo.annotations.Element(column="roleId")
     @Collection(
             domainEvent = RolesDomainEvent.class
-            )
+    )
     @CollectionLayout(
             defaultView="table",
             sequence = "20")
+    @javax.jdo.annotations.Persistent(table="ApplicationUserRoles")
+    @javax.jdo.annotations.Join(column="userId")
+    @javax.jdo.annotations.Element(column="roleId")
     @Getter @Setter
     private Set<ApplicationRole> roles = new TreeSet<>();
 
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.layout.fallback.xml b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.layout.fallback.xml
index 4b43b4c..0d84208 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.layout.fallback.xml
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUser.layout.fallback.xml
@@ -26,46 +26,81 @@ under the License.
         </bs3:col>
     </bs3:row>
     <bs3:row>
-        <bs3:col span="4">
-            <cpt:fieldSet name="Id" id="id" unreferencedProperties="true">
-                <cpt:property id="name"/>
-                <cpt:property id="username"/>
-                <cpt:property id="encryptedPassword"/>
-            </cpt:fieldSet>
+        <bs3:col span="3">
+			<bs3:row>
+				<bs3:col span="12">
+					<bs3:tabGroup>
+						<bs3:tab name="Identity">
+							<bs3:row>
+								<bs3:col span="12">
+									<cpt:fieldSet name="Identity" id="identity"/>
+								</bs3:col>
+							</bs3:row>
+						</bs3:tab>
+						<bs3:tab name="Other">
+							<bs3:row>
+								<bs3:col span="12">
+									<cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/>
+								</bs3:col>
+							</bs3:row>
+						</bs3:tab>
+						<bs3:tab name="Metadata">
+							<bs3:row>
+								<bs3:col span="12">
+									<cpt:fieldSet name="Metadata" id="metadata">
+										<cpt:property id="objectType"/>
+										<cpt:property id="objectIdentifier"/>
+										<cpt:property id="datanucleusIdLong" hidden="EVERYWHERE"/>
+										<cpt:property id="datanucleusVersionLong"/>
+										<cpt:property id="datanucleusVersionTimestamp"/>
+									</cpt:fieldSet>
+								</bs3:col>
+							</bs3:row>
+						</bs3:tab>
+					</bs3:tabGroup>
+				</bs3:col>
+			</bs3:row>
             <cpt:fieldSet name="Status" id="status">
                 <cpt:property id="accountType"/>
-                <cpt:property id="hasPassword"/>
                 <cpt:property id="status"/>
                 <cpt:property id="atPath"/>
             </cpt:fieldSet>
-            <cpt:fieldSet name="Metadata" id="metadata">
-                <cpt:property id="datanucleusIdLong"/>
-                <cpt:property id="datanucleusVersionLong"/>
-                <cpt:property id="datanucleusVersionTimestamp"/>
-            </cpt:fieldSet>
         </bs3:col>
-        <bs3:col span="8">
+		<bs3:col span="3">
+			<bs3:tabGroup>
+				<bs3:tab name="Name">
+					<bs3:row>
+						<bs3:col span="12">
+							<cpt:fieldSet name="Name" id="name">
+								<cpt:property id="familyName">
+									<cpt:action id="updateName"/>
+								</cpt:property>
+								<cpt:property id="givenName"/>
+								<cpt:property id="knownAs"/>
+							</cpt:fieldSet>
+						</bs3:col>
+					</bs3:row>
+				</bs3:tab>
+				<bs3:tab name="Contact Details">
+					<bs3:row>
+						<bs3:col span="12">
+							<cpt:fieldSet name="Contact Details" id="contactDetails">
+								<cpt:property id="emailAddress"/>
+								<cpt:property id="phoneNumber"/>
+								<cpt:property id="faxNumber"/>
+							</cpt:fieldSet>
+						</bs3:col>
+					</bs3:row>
+				</bs3:tab>
+			</bs3:tabGroup>
+			<cpt:fieldSet name="Password" id="password">
+                <cpt:property id="hasPassword"/>
+			</cpt:fieldSet>
+		</bs3:col>
+        <bs3:col span="6">
         	<bs3:row>
         		<bs3:col span="12">
         			<bs3:tabGroup>
-        				<bs3:tab name="Name and Contact Details">
-        					<bs3:row>
-        						<bs3:col span="6">
-						            <cpt:fieldSet name="Contact Details" id="contactDetails">
-						                <cpt:property id="emailAddress"/>
-						                <cpt:property id="phoneNumber"/>
-						                <cpt:property id="faxNumber"/>
-						            </cpt:fieldSet>
-        						</bs3:col>
-        						<bs3:col span="6">
-						            <cpt:fieldSet name="Name" id="name">
-						                <cpt:property id="familyName"/>
-						                <cpt:property id="givenName"/>
-						                <cpt:property id="knownAs"/>
-						            </cpt:fieldSet>						            
-        						</bs3:col>
-        					</bs3:row>
-        				</bs3:tab>
 		        		<bs3:tab name="Roles">
 		        			<bs3:row>
 		        				<bs3:col span="12">
@@ -80,14 +115,14 @@ under the License.
 		        				</bs3:col>
 		        			</bs3:row>
 		        		</bs3:tab>
-		        		<bs3:tab name="Other">
-		        			<bs3:row>
-		        				<bs3:col span="12" unreferencedCollections="true" />
-		        			</bs3:row>
-		        		</bs3:tab>
         			</bs3:tabGroup>
         		</bs3:col>
         	</bs3:row>
         </bs3:col>
     </bs3:row>
-</bs3:grid>
\ No newline at end of file
+	<bs3:row>
+		<bs3:col span="12">
+			<bs3:tabGroup unreferencedCollections="true"/>
+		</bs3:col>
+	</bs3:row>
+</bs3:grid>
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newDelegateUser.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newDelegateUser.java
index 09cd8f1..55a5b44 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newDelegateUser.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newDelegateUser.java
@@ -24,42 +24,42 @@ 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.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.NewDelegateUserDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newDelegateUser.ActionDomainEvent;
 import org.apache.isis.extensions.secman.jdo.dom.role.ApplicationRole;
 import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = NewDelegateUserDomainEvent.class, 
+        domainEvent = ActionDomainEvent.class,
         associateWith = "allUsers")
 @RequiredArgsConstructor
 public class ApplicationUserManager_newDelegateUser
 extends org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newDelegateUser<ApplicationRole>{
-    
+
     private final ApplicationUserManager target;
-    
+
     @MemberSupport
     public ApplicationUserManager act(
-            
+
           @Parameter(maxLength = ApplicationUser.MAX_LENGTH_USERNAME)
           @ParameterLayout(named = "Name")
           final String username,
-            
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Initial role")
           final ApplicationRole initialRole,
-            
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Enabled?")
           final Boolean enabled
-            
+
             ) {
-        
+
         super.doAct(username, initialRole, enabled);
-        return target; 
+        return target;
     }
-    
+
     @MemberSupport
     public boolean hideAct() {
         return super.doHide();
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newLocalUser.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newLocalUser.java
index 3aa1286..97dc218 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newLocalUser.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserManager_newLocalUser.java
@@ -25,51 +25,51 @@ import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.value.Password;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.NewLocalUserDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newLocalUser.ActionDomainEvent;
 import org.apache.isis.extensions.secman.jdo.dom.role.ApplicationRole;
 import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = NewLocalUserDomainEvent.class, 
+        domainEvent = ActionDomainEvent.class,
         associateWith = "allUsers")
 @RequiredArgsConstructor
 public class ApplicationUserManager_newLocalUser
 extends org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newLocalUser<ApplicationRole> {
-    
+
     private final ApplicationUserManager target;
-    
+
     @MemberSupport
     public ApplicationUserManager act(
           @Parameter(maxLength = ApplicationUser.MAX_LENGTH_USERNAME)
           @ParameterLayout(named = "Name")
           final String username,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Password")
           final Password password,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Repeat password")
           final Password passwordRepeat,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Initial role")
           final ApplicationRole initialRole,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Enabled?")
           final Boolean enabled,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Email Address")
           final String emailAddress) {
-        
+
         super.doAct(username, password, passwordRepeat, initialRole, enabled, emailAddress);
-        return target; 
+        return target;
     }
-    
+
     @MemberSupport
     public String validateAct(
             final String username,
@@ -78,14 +78,14 @@ extends org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_
             final ApplicationRole initialRole,
             final Boolean enabled,
             final String emailAddress) {
-        
+
         return super.doValidate(username, newPassword, newPasswordRepeat, initialRole, enabled, emailAddress);
     }
-    
+
     @MemberSupport
     public ApplicationRole default3Act() {
         return super.doDefault3();
     }
-  
+
 
 }
diff --git a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserRepository.java b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserRepository.java
index 9b60dc3..acd476a 100644
--- a/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserRepository.java
+++ b/extensions/security/secman/persistence-jdo/src/main/java/org/apache/isis/extensions/secman/jdo/dom/user/ApplicationUserRepository.java
@@ -61,15 +61,15 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
     @Inject private SecmanConfiguration configBean;
     @Inject private Optional<PasswordEncryptionService> passwordEncryptionService; // empty if no candidate is available
 	@Inject protected IsisConfiguration isisConfiguration;
-    @Inject private EventBusService eventBusService;  
- 
+    @Inject private EventBusService eventBusService;
+
     @Inject private javax.inject.Provider<QueryResultsCache> queryResultsCacheProvider;
-    
+
     @Override
     public ApplicationUser newApplicationUser() {
         return factoryService.detachedEntity(new ApplicationUser());
     }
-    
+
     // -- findOrCreateUserByUsername (programmatic)
 
     /**
@@ -85,14 +85,14 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
             final String username) {
         // slightly unusual to cache a function that modifies state, but safe because this is idempotent
         return queryResultsCacheProvider.get().execute(()->
-            findByUsername(username).orElseGet(()->newDelegateUser(username, null)), 
+            findByUsername(username).orElseGet(()->newDelegateUser(username, null)),
             ApplicationUserRepository.class, "findOrCreateUserByUsername", username);
     }
 
     // -- findByUsername
 
     public Optional<ApplicationUser> findByUsernameCached(final String username) {
-        return queryResultsCacheProvider.get().execute(this::findByUsername, 
+        return queryResultsCacheProvider.get().execute(this::findByUsername,
                 ApplicationUserRepository.class, "findByUsernameCached", username);
     }
 
@@ -105,7 +105,7 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
     // -- findByEmailAddress (programmatic)
 
     public Optional<ApplicationUser> findByEmailAddressCached(final String emailAddress) {
-        return queryResultsCacheProvider.get().execute(this::findByEmailAddress, 
+        return queryResultsCacheProvider.get().execute(this::findByEmailAddress,
                 ApplicationUserRepository.class, "findByEmailAddressCached", emailAddress);
     }
 
@@ -134,20 +134,20 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
                 .stream()
                 .collect(_Sets.toUnmodifiableSorted());
     }
-    
+
     @Override
     public Collection<ApplicationUser> findByRole(
             org.apache.isis.extensions.secman.api.role.ApplicationRole genericRole) {
-        
+
         val role = _Casts.<ApplicationRole>uncheckedCast(genericRole);
         return _NullSafe.stream(role.getUsers())
                 .collect(_Sets.toUnmodifiableSorted());
     }
-    
+
     @Override
     public Collection<ApplicationUser> findByTenancy(
             @NonNull final org.apache.isis.extensions.secman.api.tenancy.ApplicationTenancy genericTenancy) {
-        return findByAtPath(genericTenancy.getPath()) 
+        return findByAtPath(genericTenancy.getPath())
                 .stream()
                 .collect(_Sets.toUnmodifiableSorted());
     }
@@ -168,9 +168,9 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
         }
         return Collections.emptySortedSet();
     }
-    
+
     // -- UPDATE USER STATE
-    
+
     @Override
     public void enable(org.apache.isis.extensions.secman.api.user.ApplicationUser user) {
         if(user.getStatus() != ApplicationUserStatus.ENABLED) {
@@ -189,15 +189,15 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
 
     @Override
     public boolean isAdminUser(org.apache.isis.extensions.secman.api.user.ApplicationUser user) {
-        return configBean.getAdminUserName().equals(user.getName());
+        return configBean.getAdminUserName().equals(user.getUsername());
     }
 
     @Override
     public ApplicationUser newUser(
-            @NonNull String username, 
+            @NonNull String username,
             @Nullable AccountType accountType,
             Consumer<ApplicationUser> beforePersist) {
-        
+
         val user = newApplicationUser();
         user.setUsername(username);
         user.setAccountType(accountType);
@@ -205,18 +205,18 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
         if(user.getAccountType().equals(AccountType.LOCAL)) {
         	// keep null when is set for status in accept() call above
         } else {
-			user.setStatus(configBean.isAutoEnableIfDelegatedAndAuthenticated() 
-			        ?  ApplicationUserStatus.ENABLED 
+			user.setStatus(configBean.isAutoEnableIfDelegatedAndAuthenticated()
+			        ?  ApplicationUserStatus.ENABLED
 	                :  ApplicationUserStatus.DISABLED);
         }
         repository.persistAndFlush(user);
         eventBusService.post(UserCreatedEvent.of(user));
         return user;
     }
-    
+
     @Override
     public boolean updatePassword(
-            final org.apache.isis.extensions.secman.api.user.ApplicationUser user, 
+            final org.apache.isis.extensions.secman.api.user.ApplicationUser user,
             final String password) {
         // in case called programmatically
         if(!isPasswordFeatureEnabled(user)) {
@@ -227,15 +227,15 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
         repository.persistAndFlush(user);
         return true;
     }
-    
+
     @Override
     public boolean isPasswordFeatureEnabled(org.apache.isis.extensions.secman.api.user.ApplicationUser user) {
-        return user.isLocalAccount() 
+        return user.isLocalAccount()
                 /*sonar-ignore-on*/
                 && passwordEncryptionService!=null // if for any reason injection fails
                 /*sonar-ignore-off*/
                 && passwordEncryptionService.isPresent();
     }
 
-    
+
 }
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 ca82ce2..b14455d 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
@@ -39,6 +39,7 @@ import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import javax.persistence.UniqueConstraint;
+import javax.persistence.Version;
 
 import org.apache.isis.applib.annotation.BookmarkPolicy;
 import org.apache.isis.applib.annotation.Collection;
@@ -121,13 +122,12 @@ import lombok.val;
 public class ApplicationUser implements Comparable<ApplicationUser>,
 org.apache.isis.extensions.secman.api.user.ApplicationUser {
 
-    @Inject private transient ApplicationUserRepository applicationUserRepository;
     @Inject private transient ApplicationPermissionRepository applicationPermissionRepository;
     @Inject private transient UserService userService;
     /**
      * Optional service, if configured then is used to evaluate permissions within
      * {@link org.apache.isis.extensions.secman.api.permission.ApplicationPermissionValueSet#evaluate(ApplicationFeatureId, ApplicationPermissionMode)}
-     * else will fallback to a {@link org.apache.isis.extensions.secman.api.permission.PermissionsEvaluationService#DEFAULT default}
+     * else will fallback to a default.
      * implementation.
      */
     @Inject private transient PermissionsEvaluationService permissionsEvaluationService;
@@ -137,247 +137,189 @@ org.apache.isis.extensions.secman.api.user.ApplicationUser {
     @GeneratedValue
     private Long id;
 
-    // -- name (derived property)
-
-    public static class NameDomainEvent extends PropertyDomainEvent<String> {}
-
-    @Override
-    @javax.persistence.Transient
-    @Property(
-            domainEvent = NameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
-    @PropertyLayout(
-            hidden=Where.OBJECT_FORMS,
-            fieldSetId="Id", 
-            sequence = "1")
-    public String getName() {
-        final StringBuilder buf = new StringBuilder();
-        if(getFamilyName() != null) {
-            if(getKnownAs() != null) {
-                buf.append(getKnownAs());
-            } else {
-                buf.append(getGivenName());
-            }
-            buf.append(' ')
-            .append(getFamilyName())
-            .append(" (").append(getUsername()).append(')');
-        } else {
-            buf.append(getUsername());
-        }
-        return buf.toString();
-    }
+    @Version
+    private Long version;
 
 
     // -- username (property)
 
-    public static class UsernameDomainEvent extends PropertyDomainEvent<String> {}
-
-    @Column(nullable=false, length=MAX_LENGTH_USERNAME)
     @Property(
             domainEvent = UsernameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_USERNAME
+    )
     @PropertyLayout(
             hidden=Where.PARENTED_TABLES,
-            fieldSetId="Id", 
+            fieldSetId="Id",
             sequence = "1")
+    @Column(nullable=false, length=MAX_LENGTH_USERNAME)
     @Getter @Setter
     private String username;
 
 
     // -- familyName (property)
 
-    public static class FamilyNameDomainEvent extends PropertyDomainEvent<String> {}
-
-    @Column(nullable=true, length=MAX_LENGTH_FAMILY_NAME)
     @Property(
             domainEvent = FamilyNameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_FAMILY_NAME
+    )
     @PropertyLayout(
             hidden=Where.ALL_TABLES,
             fieldSetId="Name",
             sequence = "2.1")
+    @Column(nullable=true, length=MAX_LENGTH_FAMILY_NAME)
     @Getter @Setter
     private String familyName;
 
 
     // -- givenName (property)
 
-    public static class GivenNameDomainEvent extends PropertyDomainEvent<String> {}
-
-    @Column(nullable=true, length=MAX_LENGTH_GIVEN_NAME)
     @Property(
             domainEvent = GivenNameDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_KNOWN_AS
+    )
     @PropertyLayout(
-            hidden=Where.ALL_TABLES, 
-            fieldSetId="Name", 
+            hidden=Where.ALL_TABLES,
+            fieldSetId="Name",
             sequence = "2.2")
+    @Column(nullable=true, length=MAX_LENGTH_GIVEN_NAME)
     @Getter @Setter
     private String givenName;
 
 
     // -- knownAs (property)
 
-    public static class KnownAsDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @Column(nullable=true, length=MAX_LENGTH_KNOWN_AS)
     @Property(
             domainEvent = KnownAsDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_KNOWN_AS
+    )
     @PropertyLayout(
             hidden=Where.ALL_TABLES,
             fieldSetId="Name",
             sequence = "2.3")
+    @Column(nullable=true, length=MAX_LENGTH_KNOWN_AS)
     @Getter @Setter
     private String knownAs;
 
 
     // -- emailAddress (property)
 
-    public static class EmailAddressDomainEvent extends PropertyDomainEvent<String> {}
-
-    @Column(nullable=true, length=MAX_LENGTH_EMAIL_ADDRESS)
     @Property(
             domainEvent = EmailAddressDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_EMAIL_ADDRESS
+    )
     @PropertyLayout(fieldSetId="Contact Details", sequence = "3.1")
+    @Column(nullable=true, length=MAX_LENGTH_EMAIL_ADDRESS)
     @Getter @Setter
     private String emailAddress;
 
 
     // -- phoneNumber (property)
 
-    public static class PhoneNumberDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @Column(nullable=true, length=MAX_LENGTH_PHONE_NUMBER)
     @Property(
             domainEvent = PhoneNumberDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_PHONE_NUMBER
+    )
     @PropertyLayout(fieldSetId="Contact Details", sequence = "3.2")
+    @Column(nullable=true, length=MAX_LENGTH_PHONE_NUMBER)
     @Getter @Setter
     private String phoneNumber;
 
 
     // -- faxNumber (property)
 
-    public static class FaxNumberDomainEvent extends PropertyDomainEvent<String> {}
-
-    @Column(nullable=true, length=MAX_LENGTH_PHONE_NUMBER)
     @Property(
             domainEvent = FaxNumberDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_PHONE_NUMBER
+    )
     @PropertyLayout(
             hidden=Where.PARENTED_TABLES,
-            fieldSetId="Contact Details", 
+            fieldSetId="Contact Details",
             sequence = "3.3")
+    @Column(nullable=true, length=MAX_LENGTH_PHONE_NUMBER)
     @Getter @Setter
     private String faxNumber;
 
 
     // -- atPath (property)
 
-    public static class AtPathDomainEvent extends PropertyDomainEvent<String> {}
-
-
-    @Column(name="atPath", nullable=true)
     @Property(
             domainEvent = AtPathDomainEvent.class,
-            editing = Editing.DISABLED
-            )
+            editing = Editing.DISABLED,
+            maxLength = MAX_LENGTH_AT_PATH
+    )
     @PropertyLayout(fieldSetId="atPath", sequence = "3.4")
+    @Column(name="atPath", nullable=true, length = MAX_LENGTH_AT_PATH)
     @Getter @Setter
     private String atPath;
 
     // -- accountType (property)
 
-    public static class AccountTypeDomainEvent extends PropertyDomainEvent<AccountType> {}
-
-
-    @Column(nullable=false)
-    @Enumerated(EnumType.STRING)
     @Property(
             domainEvent = AccountTypeDomainEvent.class,
             editing = Editing.DISABLED
-            )
+    )
     @PropertyLayout(fieldSetId="Status", sequence = "3")
+    @Column(nullable=false)
+    @Enumerated(EnumType.STRING)
     @Getter @Setter
     private AccountType accountType;
 
 
-    // -- status (property), visible (action), usable (action)
+    // -- status (property)
 
-    public static class StatusDomainEvent extends PropertyDomainEvent<ApplicationUserStatus> {}
-
-
-    @Column(nullable=false)
-    @Enumerated(EnumType.STRING)
     @Property(
             domainEvent = StatusDomainEvent.class,
             editing = Editing.DISABLED
-            )
+    )
     @PropertyLayout(fieldSetId="Status", sequence = "4")
+    @Column(nullable=false)
+    @Enumerated(EnumType.STRING)
     @Getter @Setter
     private ApplicationUserStatus status;
 
 
     // -- encryptedPassword (hidden property)
 
-
-    @Column(nullable=true)
     @PropertyLayout(hidden=Where.EVERYWHERE)
+    @Column(nullable=true)
     @Getter @Setter
     private String encryptedPassword;
 
-    public boolean hideEncryptedPassword() {
-        return !applicationUserRepository.isPasswordFeatureEnabled(this);
-    }
 
 
     // -- hasPassword (derived property)
 
-    public static class HasPasswordDomainEvent extends PropertyDomainEvent<Boolean> {}
-
     @Property(
             domainEvent = HasPasswordDomainEvent.class,
             editing = Editing.DISABLED
-            )
+    )
     @PropertyLayout(fieldSetId="Status", sequence = "4")
     @Override
     public boolean isHasPassword() {
-        return _Strings.isNotEmpty(getEncryptedPassword());
+        return org.apache.isis.extensions.secman.api.user.ApplicationUser.super.isHasPassword();
     }
 
-    public boolean hideHasPassword() {
-        return !applicationUserRepository.isPasswordFeatureEnabled(this);
-    }
 
     // -- roles (collection)
-    public static class RolesDomainEvent extends CollectionDomainEvent<ApplicationRole> {}
 
-//    @javax.jdo.annotations.Persistent(table="ApplicationUserRoles")
-//    @javax.jdo.annotations.Join(column="userId")
-//    @javax.jdo.annotations.Element(column="roleId")
-    @ManyToMany(mappedBy = "users", cascade = CascadeType.ALL)
-    @JoinTable(
-            name = "ApplicationUserRoles",
-            joinColumns = {@JoinColumn(name = "userId")},
-            inverseJoinColumns = {@JoinColumn(name = "roleId")})
     @Collection(
             domainEvent = RolesDomainEvent.class
-            )
+    )
     @CollectionLayout(
             defaultView="table",
             sequence = "20")
+    @ManyToMany(mappedBy = "users", cascade = CascadeType.ALL)
+    @JoinTable(
+            name = "ApplicationUserRoles",
+            joinColumns = {@JoinColumn(name = "userId")},
+            inverseJoinColumns = {@JoinColumn(name = "roleId")})
     @Getter @Setter
     private Set<ApplicationRole> roles = new TreeSet<>();
 
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newDelegateUser.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newDelegateUser.java
index c5039d7..9cc2d74 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newDelegateUser.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newDelegateUser.java
@@ -24,42 +24,42 @@ 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.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.NewDelegateUserDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newDelegateUser.ActionDomainEvent;
 import org.apache.isis.extensions.secman.jpa.dom.role.ApplicationRole;
 import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = NewDelegateUserDomainEvent.class, 
+        domainEvent = ActionDomainEvent.class,
         associateWith = "allUsers")
 @RequiredArgsConstructor
 public class ApplicationUserManager_newDelegateUser
 extends org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newDelegateUser<ApplicationRole>{
-    
+
     private final ApplicationUserManager target;
-    
+
     @MemberSupport
     public ApplicationUserManager act(
-            
+
           @Parameter(maxLength = ApplicationUser.MAX_LENGTH_USERNAME)
           @ParameterLayout(named = "Name")
           final String username,
-            
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Initial role")
           final ApplicationRole initialRole,
-            
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Enabled?")
           final Boolean enabled
-            
+
             ) {
-        
+
         super.doAct(username, initialRole, enabled);
         return target;
     }
-    
+
     @MemberSupport
     public boolean hideAct() {
         return super.doHide();
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newLocalUser.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newLocalUser.java
index 53b8bb0..ab9365a 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newLocalUser.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserManager_newLocalUser.java
@@ -25,50 +25,50 @@ import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.value.Password;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
-import org.apache.isis.extensions.secman.api.user.ApplicationUser.NewLocalUserDomainEvent;
+import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newLocalUser.ActionDomainEvent;
 import org.apache.isis.extensions.secman.jpa.dom.role.ApplicationRole;
 import org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager;
 
 import lombok.RequiredArgsConstructor;
 
 @Action(
-        domainEvent = NewLocalUserDomainEvent.class, 
+        domainEvent = ActionDomainEvent.class,
         associateWith = "allUsers")
 @RequiredArgsConstructor
-public class ApplicationUserManager_newLocalUser 
+public class ApplicationUserManager_newLocalUser
 extends org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_newLocalUser<ApplicationRole> {
-    
+
     private final ApplicationUserManager target;
-    
+
     @MemberSupport
     public ApplicationUserManager act(
           @Parameter(maxLength = ApplicationUser.MAX_LENGTH_USERNAME)
           @ParameterLayout(named = "Name")
           final String username,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Password")
           final Password password,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Repeat password")
           final Password passwordRepeat,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Initial role")
           final ApplicationRole initialRole,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Enabled?")
           final Boolean enabled,
-          
+
           @Parameter(optionality = Optionality.OPTIONAL)
           @ParameterLayout(named = "Email Address")
           final String emailAddress) {
         super.doAct(username, password, passwordRepeat, initialRole, enabled, emailAddress);
         return target;
     }
-    
+
     @MemberSupport
     public String validateAct(
             final String username,
@@ -77,10 +77,10 @@ extends org.apache.isis.extensions.secman.model.dom.user.ApplicationUserManager_
             final ApplicationRole initialRole,
             final Boolean enabled,
             final String emailAddress) {
-        
+
         return super.doValidate(username, newPassword, newPasswordRepeat, initialRole, enabled, emailAddress);
     }
-    
+
     @MemberSupport
     public ApplicationRole default3Act() {
         return super.doDefault3();
diff --git a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserRepository.java b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserRepository.java
index be9f2ba..f39cff0 100644
--- a/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserRepository.java
+++ b/extensions/security/secman/persistence-jpa/src/main/java/org/apache/isis/extensions/secman/jpa/dom/user/ApplicationUserRepository.java
@@ -63,15 +63,15 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
     @Inject private SecmanConfiguration configBean;
     @Inject private Optional<PasswordEncryptionService> passwordEncryptionService; // empty if no candidate is available
 	@Inject protected IsisConfiguration isisConfiguration;
-    @Inject private EventBusService eventBusService;  
- 
+    @Inject private EventBusService eventBusService;
+
     @Inject private javax.inject.Provider<QueryResultsCache> queryResultsCacheProvider;
-    
+
     @Override
     public ApplicationUser newApplicationUser() {
         return factoryService.detachedEntity(new ApplicationUser());
     }
-    
+
     // -- findOrCreateUserByUsername (programmatic)
 
     /**
@@ -87,14 +87,14 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
             final String username) {
         // slightly unusual to cache a function that modifies state, but safe because this is idempotent
         return queryResultsCacheProvider.get().execute(()->
-            findByUsername(username).orElseGet(()->newDelegateUser(username, null)), 
+            findByUsername(username).orElseGet(()->newDelegateUser(username, null)),
             ApplicationUserRepository.class, "findOrCreateUserByUsername", username);
     }
 
     // -- findByUsername
 
     public Optional<ApplicationUser> findByUsernameCached(final String username) {
-        return queryResultsCacheProvider.get().execute(this::findByUsername, 
+        return queryResultsCacheProvider.get().execute(this::findByUsername,
                 ApplicationUserRepository.class, "findByUsernameCached", username);
     }
 
@@ -107,7 +107,7 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
     // -- findByEmailAddress (programmatic)
 
     public Optional<ApplicationUser> findByEmailAddressCached(final String emailAddress) {
-        return queryResultsCacheProvider.get().execute(this::findByEmailAddress, 
+        return queryResultsCacheProvider.get().execute(this::findByEmailAddress,
                 ApplicationUserRepository.class, "findByEmailAddressCached", emailAddress);
     }
 
@@ -137,20 +137,20 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
                 .stream()
                 .collect(_Sets.toUnmodifiableSorted());
     }
-    
+
     @Override
     public Collection<ApplicationUser> findByRole(
             org.apache.isis.extensions.secman.api.role.ApplicationRole genericRole) {
-        
+
         val role = _Casts.<ApplicationRole>uncheckedCast(genericRole);
         return _NullSafe.stream(role.getUsers())
                 .collect(_Sets.toUnmodifiableSorted());
     }
-    
+
     @Override
     public Collection<ApplicationUser> findByTenancy(
             @NonNull final org.apache.isis.extensions.secman.api.tenancy.ApplicationTenancy genericTenancy) {
-        return findByAtPath(genericTenancy.getPath()) 
+        return findByAtPath(genericTenancy.getPath())
                 .stream()
                 .collect(_Sets.toUnmodifiableSorted());
     }
@@ -171,9 +171,9 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
         }
         return Collections.emptySortedSet();
     }
-    
+
     // -- UPDATE USER STATE
-    
+
     @Override
     public void enable(org.apache.isis.extensions.secman.api.user.ApplicationUser user) {
         if(user.getStatus() != ApplicationUserStatus.ENABLED) {
@@ -192,15 +192,15 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
 
     @Override
     public boolean isAdminUser(org.apache.isis.extensions.secman.api.user.ApplicationUser user) {
-        return configBean.getAdminUserName().equals(user.getName());
+        return configBean.getAdminUserName().equals(user.getUsername());
     }
 
     @Override
     public ApplicationUser newUser(
-            @NonNull String username, 
+            @NonNull String username,
             @Nullable AccountType accountType,
             Consumer<ApplicationUser> beforePersist) {
-        
+
         val user = newApplicationUser();
         user.setUsername(username);
         user.setAccountType(accountType);
@@ -208,18 +208,18 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
         if(user.getAccountType().equals(AccountType.LOCAL)) {
         	// keep null when is set for status in accept() call above
         } else {
-			user.setStatus(configBean.isAutoEnableIfDelegatedAndAuthenticated() 
-			        ?  ApplicationUserStatus.ENABLED 
+			user.setStatus(configBean.isAutoEnableIfDelegatedAndAuthenticated()
+			        ?  ApplicationUserStatus.ENABLED
 	                :  ApplicationUserStatus.DISABLED);
         }
         repository.persistAndFlush(user);
         eventBusService.post(UserCreatedEvent.of(user));
         return user;
     }
-    
+
     @Override
     public boolean updatePassword(
-            final org.apache.isis.extensions.secman.api.user.ApplicationUser user, 
+            final org.apache.isis.extensions.secman.api.user.ApplicationUser user,
             final String password) {
         // in case called programmatically
         if(!isPasswordFeatureEnabled(user)) {
@@ -230,15 +230,15 @@ implements org.apache.isis.extensions.secman.api.user.ApplicationUserRepository<
         repository.persistAndFlush(user);
         return true;
     }
-    
+
     @Override
     public boolean isPasswordFeatureEnabled(org.apache.isis.extensions.secman.api.user.ApplicationUser user) {
-        return user.isLocalAccount() 
+        return user.isLocalAccount()
                 /*sonar-ignore-on*/
                 && passwordEncryptionService!=null // if for any reason injection fails
                 /*sonar-ignore-off*/
                 && passwordEncryptionService.isPresent();
     }
 
-    
+
 }
diff --git a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java
index 2cd62a9..985f153 100644
--- a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java
+++ b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java
@@ -55,7 +55,7 @@ import lombok.val;
  * </p>
  *
  * TODO: this should probably implement java.security.Principal so that it doesn't get wrapped in a
- * ShiroHttpServletRequest.ObjectPrincipal. 
+ * ShiroHttpServletRequest.ObjectPrincipal.
  * Such a change would need some testing to avoid regressions, though.
  */
 @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@@ -67,7 +67,7 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
         if(applicationUser == null) {
             return null;
         }
-        val username = applicationUser.getName();
+        val username = applicationUser.getUsername();
         val encryptedPassword = applicationUser.getEncryptedPassword();
         val accountType = applicationUser.getAccountType();
         val roles = applicationUser.getRoles()
@@ -75,8 +75,8 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
                 .map(ApplicationRole::getName)
                 .collect(Collectors.toCollection(TreeSet::new));
         val permissionSet = applicationUser.getPermissionSet();
-        
-        return new PrincipalForApplicationUser(username, encryptedPassword, accountType, 
+
+        return new PrincipalForApplicationUser(username, encryptedPassword, accountType,
                 applicationUser.getStatus(), roles, permissionSet);
     }
 
@@ -86,7 +86,7 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
     @Getter(value = AccessLevel.PACKAGE) private final ApplicationUserStatus status;
     @Getter(value = AccessLevel.PUBLIC)  private final Set<String> roles;
     @Getter(value = AccessLevel.PACKAGE) private final ApplicationPermissionValueSet permissionSet;
-    
+
     public boolean isDisabled() {
         return getStatus() == ApplicationUserStatus.DISABLED;
     }
@@ -95,7 +95,7 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
     public Collection<String> getStringPermissions() {
         return Collections.emptyList();
     }
-    
+
     @Override
     public Collection<Permission> getObjectPermissions() {
         return objectPermissions.get();
@@ -112,22 +112,22 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
     public String toString() {
         return getUsername();
     }
-    
+
     // -- HELPER
-    
-    private final transient _Lazy<Collection<Permission>> objectPermissions = 
+
+    private final transient _Lazy<Collection<Permission>> objectPermissions =
             _Lazy.threadSafe(this::createObjectPermissions);
-    
+
     private Collection<Permission> createObjectPermissions() {
         val permission = Permission_backedByPermissionSet.of(getPermissionSet());
         return Collections.singleton(permission);
     }
-    
+
     @RequiredArgsConstructor(staticName = "of")
     private static class Permission_backedByPermissionSet implements Permission {
-        
+
         @NonNull private final ApplicationPermissionValueSet permissionSet;
-        
+
         @Override
         public boolean implies(Permission p) {
             if (!(p instanceof PermissionForMember)) {
@@ -135,9 +135,9 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
             }
             val permissionForMember = (PermissionForMember) p;
             return permissionSet.grants(
-                    permissionForMember.getFeatureId(), 
+                    permissionForMember.getFeatureId(),
                     permissionForMember.getMode());
         }
     }
-    
+
 }